kma_page_t* kma_get_page() { void* ptr = master->ptr; unsigned int num = GET(ptr); //read the page count currently in master page kma_page_t* newpage = get_page(); //request a new page void* temp = ptr + WSIZE_11 + num*sizeof(kma_page_t*); *(kma_page_t**)temp = newpage; //place the new kma_page_t* in master page PUT(ptr, ++num); //update page count PUT(newpage->ptr, PACK(PAGESIZE,0)); // place block header in the newly allocated page /* record in the freelist */ fl_add(newpage->ptr); return newpage; }
void* kma_split(void* ptr, kma_size_t size) { unsigned int blk_size= GETSIZE(ptr); unsigned int half = blk_size >> 1; if (((half - BLKHDR) < size) || (blk_size == MINSIZE)) { // cannot split any more and need to allocate the block; PUT(ptr, PACK(blk_size,1)); return ptr; } // split! PUT(ptr, PACK(half,0)); //update header void* next_half = ptr+half; PUT(next_half, PACK(half,0)); //insert the second header //insert next_half to free list fl_add(next_half); return kma_split(ptr, size); //recurse }
void* kma_coalesce(void* ptr) { unsigned int size = GETSIZE(ptr); /* for debugging use void* base_addr = BASEADDR(ptr); unsigned int offset = (ptr - base_addr)/size; printf("%d", offset); */ int bud = WHERE_BUD(ptr, size); //0 if bud on the right, 1 if bud on the left /* corner condition: size == PAGESIZE */ if (size == PAGESIZE) return ptr; /* find bud location */ void* bud_addr; if (bud) bud_addr = ptr - size; //bud on the left else bud_addr = ptr + size; //bud on the right bool can_coalesce; can_coalesce = (!IF_ALLOC(bud_addr)) && (GETSIZE(ptr) == GETSIZE(bud_addr)); if (!can_coalesce) { //bud allocated - do nothing,simply return, this is great! fl_add(ptr); return ptr; } //we need to coalesce! if (bud) { fl_remove(bud_addr); PUT(bud_addr, PACK(size<<1,0)); //bud on the left, update bud header return kma_coalesce(bud_addr); } fl_remove(bud_addr); PUT(ptr, PACK(size<<1,0)); //bud on the right, update our header return kma_coalesce(ptr); }
static sCmdArg eval_binOpExp(const sASTNode *node,octa offset,bool *finished) { sCmdArg res = {ARGVAL_INT,ORG_EXPR,0,{0}}; sCmdArg left = eval_get(node->d.binOpExp.left,offset,finished); sCmdArg right = eval_get(node->d.binOpExp.right,offset,finished); if(left.type == ARGVAL_STR || right.type == ARGVAL_STR) cmds_throwEx("Unsupported operation!\n"); if(left.type == ARGVAL_FLOAT || right.type == ARGVAL_FLOAT) { unsigned ex; if(left.type != ARGVAL_FLOAT) { left.d.integer = fl_floatit(left.d.integer,0,true,false,&ex); left.type = ARGVAL_FLOAT; } if(right.type != ARGVAL_FLOAT) { right.d.integer = fl_floatit(right.d.integer,0,true,false,&ex); right.type = ARGVAL_FLOAT; } res.type = ARGVAL_FLOAT; switch(node->d.binOpExp.op) { case BINOP_ADD: res.d.integer = fl_add(left.d.integer,right.d.integer,&ex); break; case BINOP_SUB: res.d.integer = fl_sub(left.d.integer,right.d.integer,&ex); break; case BINOP_MULU: case BINOP_MUL: res.d.integer = fl_mult(left.d.integer,right.d.integer,&ex); break; case BINOP_DIVU: case BINOP_DIV: res.d.integer = fl_divide(left.d.integer,right.d.integer,&ex); break; case BINOP_MODU: case BINOP_MOD: // 2500 makes sure that the remainder can be calculated in one step res.d.integer = fl_remstep(left.d.integer,right.d.integer,2500,&ex); break; case BINOP_AND: case BINOP_OR: case BINOP_XOR: case BINOP_SL: case BINOP_SAR: case BINOP_SR: cmds_throwEx("Unsupported operation!\n"); break; default: assert(false); break; } } else { // note: some of the operations are the same on x86 and mmix. but some of them aren't. // therefore, we use the mmix-integer-arithmetic-functions if they are different. octa aux; switch(node->d.binOpExp.op) { case BINOP_ADD: res.d.integer = left.d.integer + right.d.integer; break; case BINOP_SUB: res.d.integer = left.d.integer - right.d.integer; break; case BINOP_MUL: res.d.integer = int_smult(left.d.integer,right.d.integer,&aux); break; case BINOP_MULU: res.d.integer = int_umult(left.d.integer,right.d.integer,&aux); break; case BINOP_DIV: res.d.integer = int_sdiv(left.d.integer,right.d.integer,&aux); break; case BINOP_DIVU: res.d.integer = int_udiv(0,left.d.integer,right.d.integer,&aux); break; case BINOP_MOD: int_sdiv(left.d.integer,right.d.integer,&aux); res.d.integer = aux; break; case BINOP_MODU: int_udiv(0,left.d.integer,right.d.integer,&aux); res.d.integer = aux; break; case BINOP_AND: res.d.integer = left.d.integer & right.d.integer; break; case BINOP_OR: res.d.integer = left.d.integer | right.d.integer; break; case BINOP_XOR: res.d.integer = left.d.integer ^ right.d.integer; break; case BINOP_SL: res.d.integer = int_shiftLeft(left.d.integer,right.d.integer); break; case BINOP_SAR: res.d.integer = int_shiftRightArith(left.d.integer,right.d.integer); break; case BINOP_SR: res.d.integer = int_shiftRightLog(left.d.integer,right.d.integer); break; default: assert(false); break; } } if(offset == 0) *finished = false; return res; }
/* Allocates the rel_t object, and adds it to the list in the polygroup if it factored or was a partial. * It determines the factors by trial division, and it also adds the factors to the linked list in the * rel_t. If it didn't factor and wasn't a partial, the relation is freed. */ void construct_relation (mpz_t qx, int32_t x, poly_t *p, nsieve_t *ns){ ns->tdiv_ct ++; rel_t *rel = (rel_t *)(malloc(sizeof(rel_t))); if (rel == NULL){ printf ("Malloc failed\n"); exit(1); } rel->poly = p; rel->x = x; rel->cofactor = 1; rel->factors = NULL; if (mpz_cmp_ui (qx, 0) < 0){ fl_add (rel, 0); } mpz_abs(qx, qx); uint64_t q = 0; int i; while (mpz_divisible_ui_p(qx, 2)){ // handle 2 separately mpz_divexact_ui(qx, qx, 2); fl_add (rel, 1); } for (i=1; i < ns->fb_len; i++){ // instead of doing a multi-precision divisiblilty test, we can use the get_offset method to // detect if 'x' is in the arithmetic progression of sieve values divisible by ns->fb[i]. if (get_offset (ns->fb[i], i, x, 0, p, p->group, ns) == 0 || get_offset (ns->fb[i], i, x, 1, p, p->group, ns) == 0){ mpz_divexact_ui(qx, qx, ns->fb[i]); fl_add (rel, i+1); // add to the factor list // If the result of the division fits in 64 bits, ditch the arbitrary precision. if (mpz_fits_64 (qx)) goto fixedprec_tdiv; while (mpz_divisible_ui_p (qx, ns->fb[i])){ // the sieve doesn't tell us mpz_divexact_ui(qx, qx, ns->fb[i]); // how many times the factor divided fl_add (rel, i+1); if (mpz_fits_64 (qx)){ goto fixedprec_tdiv; } } } } fixedprec_tdiv: q = mpz_get_64 (qx); if (q < ns->fb[i] * ns->fb[i]){ // q must be prime if (q < ns->fb_bound){ // if it's less than the factor base bound, it had better be in the FB. fl_add (rel, fb_lookup (q, ns)); // look it up and add it to the list. goto add_rel; } if (q < ns->lp_bound) { // in this case we have a partial relation. rel->cofactor = q; goto add_rel; } } while (i < ns->fb_len){ // continue the trial division while (q % ns->fb[i] == 0){ // it is no longer efficient to compute offsets here (that q /= ns->fb[i]; // calculation involved mods!) fl_add (rel, i+1); if (q < ns->fb[i] * ns->fb[i]){ if (q < ns->fb_bound){ fl_add (rel, fb_lookup (q, ns)); goto add_rel; } if (q < ns->lp_bound) { rel->cofactor = q; goto add_rel; } } } i++; } // if we're here, we weren't able to do anything with this relation. // rel_free (rel); return; add_rel: // add the relation to the list in the poly_group_t we're working with. if (p->group->nrels < PG_REL_STORAGE){ p->group->relns[ p->group->nrels ] = rel; p->group->nrels ++; return; } else { // if we ran out of space, just let it go. // rel_free(rel); return; } }