void* dcPool_getItem(doeE env, dcPool pool) { dcPoolItem item; item = pool->freeItems; if (item == NULL) { item = doeMem_malloc(env, pool->itemSize); if (item == NULL) { doeError_setNoMemory(env); return NULL; } item->origin = pool; item->next = NULL; pool->freeItems = item; pool->itemsInPool++; #ifdef DEBUG_MEMSTATS pool->totalMem_malloc++; #endif } pool->freeItems = item->next; pool->itemsInUse++; if (pool->itemsInUse > pool->itemsMaxInUse) pool->itemsMaxInUse = pool->itemsInUse; return (void*)((void**)item + 1); }
dcPool dcPool_create(doeE env, char* poolname, ixx itembytes, ixx initialitems, f32 xsigma) { dcPool pool = doeMem_malloc(env, sizeof(dcPoolData)); if (pool == NULL) { doeError_setNoMemory(env); return NULL; } dcPool_init(env, pool, poolname, itembytes, initialitems, xsigma); if (doeError_occurred(env)) { dcPool_cleanup(env, pool); doeMem_free(env, pool); return NULL; } return pool; }
static dcPathConsumer RunsBuilder_create(doeE env, dcPathFillerData* pfp) { dcPathConsumer p = doeMem_malloc(env, (i32)sizeof(RunsBuilderData)); if (p == NULL) { doeError_setNoMemory(env); return NULL; } RunsBuilder_init(env, p, pfp); if (doeError_occurred(env)) { doeMem_free(env, p); p = NULL; } return p; }
static dcPathConsumer FastOutputPC_create(doeE env) { dcPathConsumer p = doeMem_malloc(env, (i32)sizeof(FastOutputPCData)); if (p == NULL) { doeError_setNoMemory(env); return NULL; } FastOutputPC_init(env, p); if (doeError_occurred(env)) { doeMem_free(env, p); p = NULL; } return p; }
dcPathFiller dcPathFiller_create(doeE env) { dcPathFiller p = (dcPathFiller)doeMem_malloc(env, (i32)sizeof(dcPathFillerData)); if (p == NULL) { doeError_setNoMemory(env); return NULL; } dcPathFiller_init(env, p); if (doeError_occurred(env)) { _cleanup(env, (doeObject)p); doeMem_free(env, p); p = NULL; } return p; }
void dcPathFiller_staticInitialize(doeE env) { if (clients++ > 0) return; dcPool_staticInitialize(env); dcPathStore_staticInitialize(env); dcLLFiller_staticInitialize(env); FastOutputPC_staticInitialize(env); if (doeError_occurred(env)) { doeError_setNoMemory(env); return; } dcPathFiller_tileSizeL2S = dcLLFiller_tileSizeL2S; dcPathFiller_tileSize = 1 << dcPathFiller_tileSizeL2S; dcPathFiller_tileSizeF = (f32)dcPathFiller_tileSize; runCheckCost = 77.0F; KArc2 = 158.0F; LArc2 = runCheckCost + 46.0F; MArc2 = (f32)dcLLFiller_ticsSetupArc2; NArc2 = (f32)dcLLFiller_ticsStepArc2; DIV2Arc2 = 2.00 * (2 * KArc2 + LArc2 + MArc2) / (2 * NArc2 * dcPathFiller_tileSizeF); DIV4Arc2 = 0.67 * (2 * KArc2 + .5F * LArc2 + .5F * MArc2) / (2 * NArc2 * dcPathFiller_tileSizeF); KArc3 = 206.0F; LArc3 = runCheckCost + 67.0F; MArc3 = (f32)dcLLFiller_ticsSetupArc3; NArc3 = (f32)dcLLFiller_ticsStepArc3; DIV2Arc3 = 2.00 * (2 * KArc3 + LArc3 + MArc3) / (2 * NArc3 * dcPathFiller_tileSizeF); DIV4Arc3 = 0.67 * (2 * KArc3 + .5F * LArc3 + .5F * MArc3) / (2 * NArc3 * dcPathFiller_tileSizeF); }
void dcPathFiller_init(doeE env, dcPathFiller pf) { dcPathFillerData* p = (dcPathFillerData*)pf; dcPathStore ps = (dcPathStore) pf; p->redundantReset = FALSE; p->tileRuns = NULL; p->lsEffects = NULL; p->runsBuilder = NULL; p->fastOutputPC = NULL; BASE_init(env, pf); *pf = &dcPathFillerClass; p->poolRun = dcPool_create(env, "Run's pool", sizeof(RunData), 0, 1.0); p->poolLeftSide = dcPool_create(env, "LeftSide's pool", sizeof(LeftSideData), 0, 1.0); p->xtsize = 40; p->xt = doeMem_malloc(env, sizeof(f32)*p->xtsize); p->ytsize = 40; p->yt = doeMem_malloc(env, sizeof(f32)*p->ytsize); if (p->xt == NULL || p->yt == NULL) { doeError_setNoMemory(env); } p->thisFPP = (*ps)->getFastPathProducer(env, ps); p->runsBuilder = RunsBuilder_create(env, p); p->fastOutputPC = (FastOutputPC)FastOutputPC_create(env); if (doeError_occurred(env)) return; reset(env, pf); }
CJPathConsumer CJPathConsumer_create(doeE env, jobject obj) { CJPCData* p; JNIEnv* jenv = doeE_getPCtxt(env); p = (CJPCData*)doeMem_malloc(env, sizeof(CJPCData)); if (p == NULL) { doeError_setNoMemory(env); return NULL; } CJPathConsumer_init(env, (CJPathConsumer)p); if (doeError_occurred(env)) { doeMem_free(env, p); return NULL; } /* _________________________________ * the Java PathConsumer counterpart */ p->jpc = (*jenv)->NewGlobalRef(jenv, obj); return (CJPathConsumer)p; }
static void processToRunsArc1(doeE env, dcPathFillerData* p, f32 x0, f32 y0, f32 x1, f32 y1) /* OA-relative, tileSize-scaled coordinates */ { /* NOTE: lines affecting multiple tiles are divided into segments affecting exactly one; in that sense, this method is rather different from its ...Arc2 and ...Arc3 cousins */ { f32 arclox, arcloy, archix, archiy; if (x0 < x1) { arclox = x0; archix = x1; } else { arclox = x1; archix = x0; } if (y0 < y1) { arcloy = y0; archiy = y1; } else { arcloy = y1; archiy = y0; } /* if the arc cannot possibly affect OA, skip it */ if (arclox >= p->outWTiF || archiy <= 0.0F || arcloy >= p->outHTiF) { return; } /* unless the line is partially outside OA (not the most common case), skip further testing and prunning */ if (arclox < 0.0F || archix > p->outWTiF || arcloy < 0.0F || archiy > p->outHTiF) { /* prune the parts of the line above, below and to the right of OA */ f32 r = 0, outhtif, outwtif; outhtif = p->outHTiF; outwtif = p->outWTiF; if (y1 != y0) { r = (x1 - x0) / (y1 - y0); if (y0 < 0.0F) { x0 -= y0 * r; y0 = 0.0F; } if (y1 < 0.0F) { x1 -= y1 * r; y1 = 0.0F; } if (y0 > outhtif) { x0 += (outhtif - y0) * r; y0 = outhtif; } if (y1 > outhtif) { x1 += (outhtif - y1) * r; y1 = outhtif; } } if (x1 != x0) { r = (y1 - y0) / (x1 - x0); if (x0 > outwtif) { y0 += (outwtif - x0) * r; x0 = outwtif; } if (x1 > outwtif) { y1 += (outwtif - x1) * r; x1 = outwtif; } } /* recompute arclox, archix */ if (x0 < x1) { arclox = x0; archix = x1; } else { arclox = x1; archix = x0; } /* if the clipped line cannot possibly affect OA, skip it */ if (arclox >= outwtif) { return; } /* if the line is partly or completely W of OA... */ if (arclox < 0.0F) { /* if the line is completely W of OA, use its projection; if it is just partially W of OA, break it at x=0 and process the parts recursively: one will be completly inside OA, the other completely W (this may not be the fastest way to do it, but the case seems sufficiently rare to merit this simpler treatment) */ if (archix <= 0.0F) { x0 = x1 = arclox = archix = 0.0F; } else { f32 ym = (x0 < 0.0F)? y0 - x0 * r : y1 - x1 * r; processToRunsArc1(env, p, x0, y0, 0.0F, ym); processToRunsArc1(env, p, 0.0F, ym, x1, y1); return; } } } } { /* the line is now inside OA (0<=x<=outW, 0<=y<=outH); divide it in segments affecting exactly one tile */ f32 dx = x1 - x0; f32 dy = y1 - y0; f32 *xt, *yt; i32 maxcoords; f32 t = 0; f32 xprev = x0; f32 yprev = y0; i32 xi = 1; /* xt[0] = yt[0] = 0.0F <-> x0,y0 */ i32 yi = 1; maxcoords = ABS(dx); maxcoords += 3; if (p->xtsize < maxcoords) { p->xt = doeMem_malloc(env, sizeof(f32)*maxcoords); if (p->xt == NULL) { doeError_setNoMemory(env); return; } p->xtsize = maxcoords; } xt = p->xt; integralCoordTs(xt, x0, x1); maxcoords = ABS(dy); maxcoords += 3; if (p->ytsize < maxcoords) { p->yt = doeMem_malloc(env, sizeof(f32)*maxcoords); if (p->yt == NULL) { doeError_setNoMemory(env); return; } p->ytsize = maxcoords; } yt = p->yt; integralCoordTs(yt, y0, y1); do { f32 xtt = xt[xi]; f32 ytt = yt[yi]; bool xley = xtt <= ytt; bool ylex = ytt <= xtt; i32 tileloxi, tileloyi; if (xley) { t = xtt; xi++; } if (ylex) { t = ytt; yi++; } if (t != 1.0F) { x1 = x0 + dx * t; if (xley) x1 = ROUND(x1); y1 = y0 + dy * t; if (ylex) y1 = ROUND(y1); } else { x1 = x0 + dx; y1 = y0 + dy; } tileloxi = (i32)floor((dx > 0)? xprev : x1) + 1; /* tileRuns[0][0] is west of OA */ tileloyi = (i32)floor((dy > 0)? yprev : y1); appendToRunArc1(env, p, xprev, yprev, x1, y1, tileloxi, tileloyi); xprev = x1; yprev = y1; } while (t != 1.0F); } }
static void setOutputArea(doeE env, dcPathFiller pf, f32 outlox, f32 outloy, i32 w, i32 h) { dcPathFillerData* p = (dcPathFillerData*)pf; dcFastPathProducer fpp = p->thisFPP; i32 xi, yi; /* check state, parameters */ if (!((dcPathStoreData*)p)->pathDefined) { doeError_set(env, dcPRError, dcPRError_UNEX_setOutputArea); return; } if (w <= 0 || h <= 0) { doeError_set(env, dcPRError, dcPRError_BAD_outputarea); return; } if (!( dcPathFiller_validLoCoord(outlox) && dcPathFiller_validLoCoord(outloy) && dcPathFiller_validHiCoord(outlox + w) && dcPathFiller_validHiCoord(outloy + h))) { doeError_set(env, dcPRException, dcPRException_BAD_COORD_setOutputArea); return; } stateSet(p, setOutputAreaDone); p->outLoX = outlox; p->outLoY = outloy; p->outW = w; p->outH = h; p->outWTiF = w / dcPathFiller_tileSizeF; p->outHTiF = h / dcPathFiller_tileSizeF; if (p->tileRuns != NULL) doeMem_free(env, p->tileRuns); p->fastOutput = w <= dcPathFiller_tileSize && h <= dcPathFiller_tileSize && p->pathBox[0] >= outlox && p->pathBox[1] >= outloy && p->pathBox[2] <= outlox + w && p->pathBox[3] <= outloy + h; if (p->fastOutput) return; /* allocate [tileRuns], indexed [xindex][yindex]; (here we reuse [w] and [h] as width and height in tiles) */ p->outWTi = w = (p->outW + dcPathFiller_tileSize - 1) >> dcPathFiller_tileSizeL2S; p->outHTi = h = (p->outH + dcPathFiller_tileSize - 1) >> dcPathFiller_tileSizeL2S; p->tileRuns = doeMem_malloc(env, sizeof(Run*)*(w + 1) /* array of (Run*), indexed by X */ + sizeof(Run )*(w + 1)*h/* arrays of (Run), indexed by Y */ ); if (p->tileRuns == NULL) { doeError_setNoMemory(env); return; } for (xi = 0; xi <= w; xi++) { p->tileRuns[xi] = (Run*)(p->tileRuns + w + 1) + xi * h; } for (yi = 0; yi < h; yi++) { for (xi = 0; xi <= w; xi++) { p->tileRuns[xi][yi] = NULL; } } (*fpp)->sendTo(env, fpp, p->runsBuilder); if (doeError_occurred(env)) { doeError_setNoMemory(env); return; } /* set things so [nextTile] will advance to the 1st tile */ p->tileXI = w; p->tileYI = -1; (*pf)->nextTile(env, pf); }
static void dcPool_init(doeE env, dcPool pool, char* poolname, ixx itembytes, ixx initialitems, f32 xsigma) { ixx i; dcPoolItem item; for (i = 0; poolname[i] != 0; i++); pool->poolName = doeMem_malloc(env, i + 1); if (pool->poolName == NULL) { doeError_setNoMemory(env); return; } while (i >= 0) { pool->poolName[i] = poolname[i]; i--; } pool->itemSize = itembytes = sizeof(void*)*(((itembytes + sizeof(void*) - 1) / sizeof(void*)) + 1); pool->itemMinInPool = initialitems; pool->xSigma = xsigma; for (i = 0; i < dcPool_samples; i++) pool->U[i] = initialitems; pool->sumU = dcPool_samples * initialitems; pool->sumUU = dcPool_samples * initialitems * initialitems; pool->ui = 0; #ifdef DEBUG_MEMSTATS #ifdef DEBUG_MEMSTATS_PER_CYCLE pool->aux = doeMem_malloc(env, 102); for (i = 0; i <= 100; i++) { pool->aux[i] = ' '; if (0 == i % 10) pool->aux[i] = '|'; if (i == initialitems) pool->aux[i] = 'A'; } pool->aux[101] = 0; #endif pool->totalPool = 0; pool->totalUsed = 0; pool->totalMem_malloc = 0; pool->totalMem_free = 0; pool->totalCycles = 0; #endif item = NULL; for (i = 0; i < initialitems; i++) { dcPoolItem newitem = doeMem_malloc(env, itembytes); if (newitem == NULL) { doeError_setNoMemory(env); return; } #ifdef DEBUG_MEMSTATS pool->totalMem_malloc++; #endif newitem->origin = pool; newitem->next = item; item = newitem; } pool->freeItems = item; pool->itemsInUse = pool->itemsMaxInUse = 0; pool->itemsInPool = initialitems; }