void BaseShadowRenderImage::getTerrPolys( SimTerrain * terr) { float rad = shadow.getShadowRadius(); GridFile *terrFile = terr->getGridFile(); const TMat3F & terrInv = terr->getInvTransform(); // get the light direction in terrain space Point3F lightInTerr; m_mul(lastLight,(RMat3F&)terr->getInvTransform(),&lightInTerr); if (IsZero(lightInTerr.z,0.01f)) return; // light parallel to x-y plane // center of shape in world coords Point3F shapeInWorld,preC; m_mul(shape->getShape().fCenter,shape->fRootDeltaTransform,&preC); m_mul(preC,transform,&shapeInWorld); // feet of shape in world coords Point3F feetInTerr; m_mul(transform.p,terrInv,&feetInTerr); // first task is to find plane on ground where light hits // this plane will be used to decide how big to make box // to grab terrain polys from Point3F n,p; float dot; bool gotIt = false; // first, are we standing on the terrain...if so, use this plane CollisionSurface cs; if (terrFile->getSurfaceInfo(feetInTerr,&cs)) { if (IsZero(feetInTerr.z-cs.position.z,rad)) { n = cs.normal; p = cs.position; dot = m_dot(n,lightInTerr); if (dot < -0.2f) gotIt = true; } } // now project in direction of light down from top of shape Point3F ta, a = shapeInWorld; a.z += rad; m_mul(a,terrInv,&ta); Point3F tb = lightInTerr; tb *= ShadowFeelerLength; tb += ta; GridCollision coll(terrFile,NULL); if (coll.collide(ta,tb) && terrFile->getSurfaceInfo(coll.surface.position,&cs)) { float thisDot = m_dot(lightInTerr,coll.surface.normal); if (!gotIt || (thisDot > dot && thisDot < -0.2f)) { n = coll.surface.normal; p = coll.surface.position; dot = thisDot; gotIt = true; } } if (!gotIt) return; // no terrain polys // shape center in terrain space Point3F shapeInTerr; m_mul(shapeInWorld,terrInv,&shapeInTerr); // we now have light, shape center, and a plane all in terrain space // build a box around projection of shape center onto plane Point3F shapeOnGround; float k = 1.0f / dot; float t = m_dot(n,p-shapeInTerr) * k; shapeOnGround = lightInTerr; shapeOnGround *= t; shapeOnGround += shapeInTerr; // make the box Box2F shadowBox; shadowBox.fMin = shadowBox.fMax = shapeOnGround; float tx = -rad * n.x * k; float ty = -rad * n.y * k; float tz = -rad * n.z * k; shadowBox.fMin.x -= rad + tx*lightInTerr.x + fabs(ty*lightInTerr.x) + fabs(tz*lightInTerr.x); shadowBox.fMax.x += rad - tx*lightInTerr.x + fabs(ty*lightInTerr.x) + fabs(tz*lightInTerr.x); shadowBox.fMin.y -= rad + ty*lightInTerr.y + fabs(tx*lightInTerr.y) + fabs(tz*lightInTerr.y); shadowBox.fMax.y += rad - ty*lightInTerr.y + fabs(tx*lightInTerr.y) + fabs(tz*lightInTerr.y); int maxPolys = min(shadow.projectionList.size() + BaseShadowRenderImage::maxTerrainPolys, BaseShadowRenderImage::maxProjectionPolys); // now get polys from terrain to project shadow onto terrFile->getPolys(shadowBox,terr->getTransform(),shadow.projectionList,maxPolys); }
void inv(zz_pE& d, mat_zz_pE& X, const mat_zz_pE& A) { long n = A.NumRows(); if (A.NumCols() != n) Error("inv: nonsquare matrix"); if (n == 0) { set(d); X.SetDims(0, 0); return; } long i, j, k, pos; zz_pX t1, t2; zz_pX *x, *y; const zz_pXModulus& p = zz_pE::modulus(); vec_zz_pX *M = newNTL_NEW_OP vec_zz_pX[n]; for (i = 0; i < n; i++) { M[i].SetLength(2*n); for (j = 0; j < n; j++) { M[i][j].rep.SetMaxLength(2*deg(p)-1); M[i][j] = rep(A[i][j]); M[i][n+j].rep.SetMaxLength(2*deg(p)-1); clear(M[i][n+j]); } set(M[i][n+i]); } zz_pX det; set(det); for (k = 0; k < n; k++) { pos = -1; for (i = k; i < n; i++) { rem(t1, M[i][k], p); M[i][k] = t1; if (pos == -1 && !IsZero(t1)) { pos = i; } } if (pos != -1) { if (k != pos) { swap(M[pos], M[k]); negate(det, det); } MulMod(det, det, M[k][k], p); // make M[k, k] == -1 mod p, and make row k reduced InvMod(t1, M[k][k], p); negate(t1, t1); for (j = k+1; j < 2*n; j++) { rem(t2, M[k][j], p); MulMod(M[k][j], t2, t1, p); } for (i = k+1; i < n; i++) { // M[i] = M[i] + M[k]*M[i,k] t1 = M[i][k]; // this is already reduced x = M[i].elts() + (k+1); y = M[k].elts() + (k+1); for (j = k+1; j < 2*n; j++, x++, y++) { // *x = *x + (*y)*t1 mul(t2, *y, t1); add(*x, *x, t2); } } } else { clear(d); goto done; } } X.SetDims(n, n); for (k = 0; k < n; k++) { for (i = n-1; i >= 0; i--) { clear(t1); for (j = i+1; j < n; j++) { mul(t2, rep(X[j][k]), M[i][j]); add(t1, t1, t2); } sub(t1, t1, M[i][n+k]); conv(X[i][k], t1); } } conv(d, det); done: delete[] M; }
void kernel(mat_zz_pE& X, const mat_zz_pE& A) { long m = A.NumRows(); long n = A.NumCols(); mat_zz_pE M; long r; transpose(M, A); r = gauss(M); X.SetDims(m-r, m); long i, j, k, s; zz_pX t1, t2; zz_pE T3; vec_long D; D.SetLength(m); for (j = 0; j < m; j++) D[j] = -1; vec_zz_pE inverses; inverses.SetLength(m); j = -1; for (i = 0; i < r; i++) { do { j++; } while (IsZero(M[i][j])); D[j] = i; inv(inverses[j], M[i][j]); } for (k = 0; k < m-r; k++) { vec_zz_pE& v = X[k]; long pos = 0; for (j = m-1; j >= 0; j--) { if (D[j] == -1) { if (pos == k) set(v[j]); else clear(v[j]); pos++; } else { i = D[j]; clear(t1); for (s = j+1; s < m; s++) { mul(t2, rep(v[s]), rep(M[i][s])); add(t1, t1, t2); } conv(T3, t1); mul(T3, T3, inverses[j]); negate(v[j], T3); } } } }
AUR_BOOL IsEqual( AUR_FLOAT32 p_Left, AUR_FLOAT32 p_Right ) { return IsZero( p_Left - p_Right ); }
bool NotZero() const { return !IsZero(); }
static void NullSpace(long& r, vec_long& D, vec_ZZVec& M, long verbose) { long k, l, n; long i, j; long pos; ZZ t1, t2; ZZ *x, *y; const ZZ& p = ZZ_p::modulus(); n = M.length(); D.SetLength(n); for (j = 0; j < n; j++) D[j] = -1; r = 0; l = 0; for (k = 0; k < n; k++) { if (verbose && k % 10 == 0) cerr << "+"; pos = -1; for (i = l; i < n; i++) { rem(t1, M[i][k], p); M[i][k] = t1; if (pos == -1 && !IsZero(t1)) pos = i; } if (pos != -1) { swap(M[pos], M[l]); // make M[l, k] == -1 mod p, and make row l reduced InvMod(t1, M[l][k], p); NegateMod(t1, t1, p); for (j = k+1; j < n; j++) { rem(t2, M[l][j], p); MulMod(M[l][j], t2, t1, p); } for (i = l+1; i < n; i++) { // M[i] = M[i] + M[l]*M[i,k] t1 = M[i][k]; // this is already reduced x = M[i].elts() + (k+1); y = M[l].elts() + (k+1); for (j = k+1; j < n; j++, x++, y++) { // *x = *x + (*y)*t1 mul(t2, *y, t1); add(*x, *x, t2); } } D[k] = l; // variable k is defined by row l l++; } else { r++; } } }
/* item[n] = start + n * delta */ static Array MakeLinearList(Array start, Array end, int *n, Array delta) { int i, j; Array a_start = NULL, a_end = NULL, a_delta = NULL; int delstart = 0, delend = 0, deldelta = 0; Array alist[3]; Array output = NULL; int count = 1; int bytes; Type t; Category c; int rank; int shape[MAXSHAPE]; int nitems; int i_start, i_end, i_delta; float f_start, f_end, f_delta, f_count; Pointer dp; int *ip; Object in[MAXCOMPINPUTS]; /* hardcoded in compute */ Object out; String compstr = NULL; char cbuf[64]; Error rc; /* do this or die in compute */ for (i=0; i<MAXCOMPINPUTS; i++) in[i] = NULL; /* find common format of start, end, delta and check for 4 parms */ i = 0; if (start) alist[i++] = start; if (end) alist[i++] = end; if (delta) alist[i++] = delta; if (n) { count = *n; if (i == 3) { DXWarning("too many inputs specified; ignoring delta"); i--; delta = NULL; } } else if (i == 2) count = 2; if (i < 2) { DXSetError(ERROR_BAD_PARAMETER, "not enough inputs specified to generate a list"); return NULL; } if (!DXQueryArrayCommonV(&t, &c, &rank, shape, i, alist)) { DXAddMessage("start, end and/or delta"); return NULL; } /* shortcut the process here if the data is scalar integer or * scalar float. otherwise, if the data is vector or ubyte * or whatever, fall through and use Compute so we can increment * by irregular values. */ if (t != TYPE_INT && t != TYPE_FLOAT) goto complicated; if (c != CATEGORY_REAL || rank != 0) goto complicated; /* compute missing value(s): * start = end - ((count - 1) * delta) * end = start + ((count - 1) * delta) * count = ((end - start) / delta) + 1 * delta = (end - start) / (count - 1) */ /* convert to the common format */ if (start) a_start = DXArrayConvertV(start, t, c, rank, shape); if (end) a_end = DXArrayConvertV(end, t, c, rank, shape); if (delta) a_delta = DXArrayConvertV(delta, t, c, rank, shape); /* for integer, scalar lists */ if (t == TYPE_INT) { if (!start) { i_end = *(int *)DXGetArrayData(a_end); i_delta = *(int *)DXGetArrayData(a_delta); i_start = i_end - ((count - 1) * i_delta); } if (!end) { i_start = *(int *)DXGetArrayData(a_start); i_delta = *(int *)DXGetArrayData(a_delta); i_end = i_start + ((count - 1) * i_delta); } if (!delta) { /* if count == 1, generate a zero of the right type. otherwise * divide to figure out the right delta to make count-1 steps * between start and end. it's count-1 because if you want * N numbers between start and end, you have N-1 increments. */ i_start = *(int *)DXGetArrayData(a_start); i_end = *(int *)DXGetArrayData(a_end); if (count == 1) i_delta = 0; else i_delta = (i_end - i_start) / (count - 1); /* try to catch the case where delta ends up being 0 (like * because the inputs are int and the count is larger than * the difference between start and end). allow it to be zero * only if start == end; i suppose if you ask for 10 things * where start == end you should be able to get them. */ if (i_delta == 0 && i_start != i_end) { DXSetError(ERROR_BAD_PARAMETER, "count too large to generate list between start and end"); goto error; } } /* if all three arrays are there, count must be missing */ if (i == 3) { i_start = *(int *)DXGetArrayData(a_start); i_end = *(int *)DXGetArrayData(a_end); i_delta = *(int *)DXGetArrayData(a_delta); if (i_delta == 0) count = 1; else { if ((i_end >= i_start && i_delta > 0) || (i_end < i_start && i_delta < 0)) count = (int)(((double)i_end-i_start) / (double)i_delta) +1; else { if (i_delta < 0) DXSetError(ERROR_BAD_PARAMETER, "delta must be positive if start is less than end"); else DXSetError(ERROR_BAD_PARAMETER, "delta must be negative if end is less than start"); goto error; } } } output = (Array)DXNewRegularArray(TYPE_INT, 1, count, (Pointer)&i_start, (Pointer)&i_delta); } /* for float, scalar lists */ if (t == TYPE_FLOAT) { if (!start) { f_end = *(float *)DXGetArrayData(a_end); f_delta = *(float *)DXGetArrayData(a_delta); f_start = f_end - ((count - 1.0) * f_delta); } if (!end) { f_start = *(float *)DXGetArrayData(a_start); f_delta = *(float *)DXGetArrayData(a_delta); f_end = f_start + ((count - 1.0) * f_delta); } if (!delta) { /* if count == 1, generate a zero of the right type. otherwise * divide to figure out the right delta to make count-1 steps * between start and end. it's count-1 because if you want * N numbers between start and end, you have N-1 increments. */ f_start = *(float *)DXGetArrayData(a_start); f_end = *(float *)DXGetArrayData(a_end); if (count == 1) f_delta = 0.0; else f_delta = (f_end - f_start) / (count - 1.0); /* try to catch the case where delta ends up being 0 (like * because the inputs are int and the count is larger than * the difference between start and end). allow it to be zero * only if start == end; i suppose if you ask for 10 things * where start == end you should be able to get them. */ if (f_delta == 0.0 && f_start != f_end) { DXSetError(ERROR_BAD_PARAMETER, "count too large to generate list between start and end"); goto error; } } /* if all three arrays are there, count must be missing */ if (i == 3) { f_start = *(float *)DXGetArrayData(a_start); f_end = *(float *)DXGetArrayData(a_end); f_delta = *(float *)DXGetArrayData(a_delta); if (f_delta == 0.0) count = 1; else { if ((f_end >= f_start && f_delta > 0) || (f_end < f_start && f_delta < 0)) { /* the intermediate float variable below is to minimize * float round-off error. if delta is 0.1 and you * ask for a list between 0 and 1, it does the math in * double, the delta used is actually 0.10000001, and * you get counts = 10.9999999 instead of 11. when * converted directly to int it becomes just 10 and your * list ends at 0.9 instead of 1. * math in base 2 has some problems. */ f_count = ((f_end - f_start) / f_delta) +1; count = (int)f_count; } else { if (f_delta < 0) DXSetError(ERROR_BAD_PARAMETER, "delta must be positive if start is less than end"); else DXSetError(ERROR_BAD_PARAMETER, "delta must be negative if end is less than start"); goto error; } } } output = (Array)DXNewRegularArray(TYPE_FLOAT, 1, count, (Pointer)&f_start, (Pointer)&f_delta); } DXDelete((Object)a_start); DXDelete((Object)a_end); DXDelete((Object)a_delta); /* return Array */ return output; /* input is a vector, or a data type different from int or float. * use compute so this code doesn't have to be replicated for each * different shape and type. */ complicated: nitems = 1; for (j=0; j<rank; j++) nitems *= shape[j]; /* compute missing value(s): * start = end - ((count - 1) * delta) * end = start + ((count - 1) * delta) * count = ((end - start) / delta) + 1 * delta = (end - start) / (count - 1) */ if (!start) { compstr = DXNewString("$0 - (($1 - 1) * $2)"); if (!compstr) goto error; in[0] = (Object)compstr; in[1] = (Object)end; in[3] = (Object)delta; in[2] = (Object)DXNewArray(TYPE_INT, CATEGORY_REAL, 0); if (!in[2]) goto error; if (!DXAddArrayData((Array)in[2], 0, 1, (Pointer)&count)) goto error; /* i need to explain this - it's basically so if compute was * going to try to cache this, it could add a reference and * then later when i call delete the object won't get deleted * out from underneath compute. (i know compute doesn't cache * things, but a different module might.) */ DXReference((Object)compstr); DXReference(in[2]); rc = m_Compute(in, &out); DXDelete((Object)compstr); compstr = NULL; DXDelete(in[2]); in[2] = NULL; if (rc == ERROR) goto error; start = (Array)out; delstart++; } if (!end) { compstr = DXNewString("$0 + (($1 - 1) * $2)"); if (!compstr) goto error; in[0] = (Object)compstr; in[1] = (Object)start; in[3] = (Object)delta; in[2] = (Object)DXNewArray(TYPE_INT, CATEGORY_REAL, 0); if (!in[2]) goto error; if (!DXAddArrayData((Array)in[2], 0, 1, (Pointer)&count)) goto error; DXReference((Object)compstr); DXReference(in[2]); rc = m_Compute(in, &out); DXDelete((Object)compstr); compstr = NULL; DXDelete(in[2]); in[2] = NULL; if (rc == ERROR) goto error; end = (Array)out; delend++; } if (!delta) { /* if count == 1, generate a zero of the right type. otherwise * divide to figure out the right delta to make count-1 steps * between start and end. it's count-1 because if you want * N numbers between start and end, you have N-1 increments. */ if (count == 1) compstr = DXNewString("$1 - $1"); else compstr = DXNewString("($2 - $0) / ($1 - 1)"); if (!compstr) goto error; in[0] = (Object)compstr; in[1] = (Object)start; in[3] = (Object)end; in[2] = (Object)DXNewArray(TYPE_INT, CATEGORY_REAL, 0); if (!in[2]) goto error; if (!DXAddArrayData((Array)in[2], 0, 1, (Pointer)&count)) goto error; DXReference((Object)compstr); DXReference(in[2]); rc = m_Compute(in, &out); DXDelete((Object)compstr); compstr = NULL; DXDelete(in[2]); in[2] = NULL; if (rc == ERROR) goto error; delta = (Array)out; deldelta++; /* try to catch the case where delta ends up being 0 (like * because the inputs are int and the count is larger than * the difference between start and end). allow it to be zero * only if start == end; i suppose if you ask for 10 things * where start == end you should be able to get them. */ if (IsZero(delta) && !IsEqual(start, end)) { DXSetError(ERROR_BAD_PARAMETER, "count too large to generate list between start and end"); goto error; } } /* if all three arrays are there, count must be missing */ if (i == 3) { char tbuf[512]; int firsttime = 1; int lastcount = 0; /* this loop allows us to to handle vectors or matricies as * well as scalars. it requires that the deltas compute to * a consistent count. like start=[0 2 4], end=[4 8 16], * would work if delta=[1 2 4] but not if delta was [1 2 2]. */ for (j=0; j < nitems; j++) { /* i think this code only works for vectors - i'm not sure * what it will do with rank=2 data. */ /* this point of this next compute expression: * if the delta is 0, don't divide by zero - the count is 1. * if the end is smaller than the start, the delta has to be * negative. if it's not, return -1. you can't generate a * negative count from the equations, so this is a safe signal. */ sprintf(tbuf, "float($2.%d) == 0.0 ? " " 1 : " " ( (($1.%d >= $0.%d) && ($2.%d > 0) || " " ($1.%d < $0.%d) && ($2.%d < 0)) ? " " int(float($1.%d - $0.%d) / float($2.%d)) + 1 : " " -1 ) ", j, j, j, j, j, j, j, j, j, j); compstr = DXNewString(tbuf); if (!compstr) goto error; in[0] = (Object)compstr; in[1] = (Object)start; in[2] = (Object)end; in[3] = (Object)delta; DXReference((Object)compstr); rc = m_Compute(in, &out); DXDelete((Object)compstr); compstr = NULL; if (rc == ERROR) goto error; if (!DXExtractInteger(out, &count)) { DXSetError(ERROR_BAD_PARAMETER, "can't compute number of items"); goto error; } DXDelete((Object)out); if (count == 0) continue; if (count < 0) { if (IsNegative(delta)) DXSetError(ERROR_BAD_PARAMETER, "delta must be positive if start is less than end"); else DXSetError(ERROR_BAD_PARAMETER, "delta must be negative if end is less than start"); goto error; } if (firsttime) { lastcount = count; firsttime = 0; } else { if (count != lastcount) { DXSetError(ERROR_BAD_PARAMETER, "inconsistent number of items required by inputs"); goto error; } } } } /* now have 4 consistant values - once again make sure they are * converted into an identical format. */ a_start = DXArrayConvertV(start, t, c, rank, shape); a_end = DXArrayConvertV(end, t, c, rank, shape); a_delta = DXArrayConvertV(delta, t, c, rank, shape); /* make empty array with n items */ output = DXNewArrayV(t, c, rank, shape); if (!output) goto error; if (!DXAddArrayData(output, 0, count, NULL)) goto error; dp = DXGetArrayData(output); if (!dp) goto error; /* foreach n */ /* call compute to add delta */ /* memcpy to right offset in array */ /* end */ bytes = DXGetItemSize(output); sprintf(cbuf, "%s($0 + ($1 * $2))", TypeName(t)); compstr = DXNewString(cbuf); if (!compstr) goto error; in[0] = (Object)compstr; in[1] = (Object)a_start; in[3] = (Object)a_delta; in[2] = (Object)DXNewArray(TYPE_INT, CATEGORY_REAL, 0); if (!in[2]) goto error; if (!DXAddArrayData((Array)in[2], 0, 1, NULL)) goto error; ip = (int *)DXGetArrayData((Array)in[2]); DXReference((Object)compstr); DXReference(in[2]); for (i=0; i<count; i++) { *ip = i; rc = m_Compute(in, &out); if (rc == ERROR) goto error; memcpy(INCVOID(dp, bytes*i), DXGetArrayData((Array)out), bytes); DXDelete((Object)out); } DXDelete((Object)compstr); DXDelete(in[2]); DXDelete((Object)a_start); DXDelete((Object)a_end); DXDelete((Object)a_delta); if (delstart) DXDelete((Object)start); if (delend) DXDelete((Object)end); if (deldelta) DXDelete((Object)delta); /* return Array */ return output; error: DXDelete((Object)output); DXDelete((Object)compstr); DXDelete((Object)a_start); DXDelete((Object)a_end); DXDelete((Object)a_delta); if (delstart) DXDelete((Object)start); if (delend) DXDelete((Object)end); if (deldelta) DXDelete((Object)delta); return NULL; }
void resultant(ZZ_p& rres, const ZZ_pX& u, const ZZ_pX& v) { if (deg(u) <= NTL_ZZ_pX_GCD_CROSSOVER || deg(v) <= NTL_ZZ_pX_GCD_CROSSOVER) { PlainResultant(rres, u, v); return; } ZZ_pX u1, v1; u1 = u; v1 = v; ZZ_p res, t; set(res); if (deg(u1) == deg(v1)) { rem(u1, u1, v1); swap(u1, v1); if (IsZero(v1)) { clear(rres); return; } power(t, LeadCoeff(u1), deg(u1) - deg(v1)); mul(res, res, t); if (deg(u1) & 1) negate(res, res); } else if (deg(u1) < deg(v1)) { swap(u1, v1); if (deg(u1) & deg(v1) & 1) negate(res, res); } // deg(u1) > deg(v1) && v1 != 0 vec_ZZ_p cvec; vec_long dvec; cvec.SetMaxLength(deg(v1)+2); dvec.SetMaxLength(deg(v1)+2); append(cvec, LeadCoeff(u1)); append(dvec, deg(u1)); while (deg(u1) > NTL_ZZ_pX_GCD_CROSSOVER && !IsZero(v1)) { ResHalfGCD(u1, v1, cvec, dvec); if (!IsZero(v1)) { append(cvec, LeadCoeff(v1)); append(dvec, deg(v1)); rem(u1, u1, v1); swap(u1, v1); } } if (IsZero(v1) && deg(u1) > 0) { clear(rres); return; } long i, l; l = dvec.length(); if (deg(u1) == 0) { // we went all the way... for (i = 0; i <= l-3; i++) { power(t, cvec[i+1], dvec[i]-dvec[i+2]); mul(res, res, t); if (dvec[i] & dvec[i+1] & 1) negate(res, res); } power(t, cvec[l-1], dvec[l-2]); mul(res, res, t); } else { for (i = 0; i <= l-3; i++) { power(t, cvec[i+1], dvec[i]-dvec[i+2]); mul(res, res, t); if (dvec[i] & dvec[i+1] & 1) negate(res, res); } power(t, cvec[l-1], dvec[l-2]-deg(v1)); mul(res, res, t); if (dvec[l-2] & dvec[l-1] & 1) negate(res, res); PlainResultant(t, u1, v1); mul(res, res, t); } rres = res; }
void HalfGCD(ZZ_pXMatrix& M_out, const ZZ_pX& U, const ZZ_pX& V, long d_red) { if (IsZero(V) || deg(V) <= deg(U) - d_red) { set(M_out(0,0)); clear(M_out(0,1)); clear(M_out(1,0)); set(M_out(1,1)); return; } long n = deg(U) - 2*d_red + 2; if (n < 0) n = 0; ZZ_pX U1, V1; RightShift(U1, U, n); RightShift(V1, V, n); if (d_red <= NTL_ZZ_pX_HalfGCD_CROSSOVER) { IterHalfGCD(M_out, U1, V1, d_red); return; } long d1 = (d_red + 1)/2; if (d1 < 1) d1 = 1; if (d1 >= d_red) d1 = d_red - 1; ZZ_pXMatrix M1; HalfGCD(M1, U1, V1, d1); mul(U1, V1, M1); long d2 = deg(V1) - deg(U) + n + d_red; if (IsZero(V1) || d2 <= 0) { M_out = M1; return; } ZZ_pX Q; ZZ_pXMatrix M2; DivRem(Q, U1, U1, V1); swap(U1, V1); HalfGCD(M2, U1, V1, d2); ZZ_pX t(INIT_SIZE, deg(M1(1,1))+deg(Q)+1); mul(t, Q, M1(1,0)); sub(t, M1(0,0), t); swap(M1(0,0), M1(1,0)); swap(M1(1,0), t); t.kill(); t.SetMaxLength(deg(M1(1,1))+deg(Q)+1); mul(t, Q, M1(1,1)); sub(t, M1(0,1), t); swap(M1(0,1), M1(1,1)); swap(M1(1,1), t); t.kill(); mul(M_out, M2, M1); }
void KarMul(ZZX& c, const ZZX& a, const ZZX& b) { if (IsZero(a) || IsZero(b)) { clear(c); return; } if (&a == &b) { KarSqr(c, a); return; } vec_ZZ mem; const ZZ *ap, *bp; ZZ *cp; long sa = a.rep.length(); long sb = b.rep.length(); if (&a == &c) { mem = a.rep; ap = mem.elts(); } else ap = a.rep.elts(); if (&b == &c) { mem = b.rep; bp = mem.elts(); } else bp = b.rep.elts(); c.rep.SetLength(sa+sb-1); cp = c.rep.elts(); long maxa, maxb, xover; maxa = MaxBits(a); maxb = MaxBits(b); xover = 2; if (sa < xover || sb < xover) PlainMul(cp, ap, sa, bp, sb); else { /* karatsuba */ long n, hn, sp, depth; n = max(sa, sb); sp = 0; depth = 0; do { hn = (n+1) >> 1; sp += (hn << 2) - 1; n = hn; depth++; } while (n >= xover); ZZVec stk; stk.SetSize(sp, ((maxa + maxb + NumBits(min(sa, sb)) + 2*depth + 10) + NTL_ZZ_NBITS-1)/NTL_ZZ_NBITS); KarMul(cp, ap, sa, bp, sb, stk.elts()); } c.normalize(); }
void BerlekampMassey(ZZ_pX& h, const vec_ZZ_p& a, long m) { ZZ_pX Lambda, Sigma, Temp; long L; ZZ_p Delta, Delta1, t1; long shamt; // cerr << "*** " << m << "\n"; Lambda.SetMaxLength(m+1); Sigma.SetMaxLength(m+1); Temp.SetMaxLength(m+1); L = 0; set(Lambda); clear(Sigma); set(Delta); shamt = 0; long i, r, dl; for (r = 1; r <= 2*m; r++) { // cerr << r << "--"; clear(Delta1); dl = deg(Lambda); for (i = 0; i <= dl; i++) { mul(t1, Lambda.rep[i], a[r-i-1]); add(Delta1, Delta1, t1); } if (IsZero(Delta1)) { shamt++; // cerr << "case 1: " << deg(Lambda) << " " << deg(Sigma) << " " << shamt << "\n"; } else if (2*L < r) { div(t1, Delta1, Delta); mul(Temp, Sigma, t1); Sigma = Lambda; ShiftSub(Lambda, Temp, shamt+1); shamt = 0; L = r-L; Delta = Delta1; // cerr << "case 2: " << deg(Lambda) << " " << deg(Sigma) << " " << shamt << "\n"; } else { shamt++; div(t1, Delta1, Delta); mul(Temp, Sigma, t1); ShiftSub(Lambda, Temp, shamt); // cerr << "case 3: " << deg(Lambda) << " " << deg(Sigma) << " " << shamt << "\n"; } } // cerr << "finished: " << L << " " << deg(Lambda) << "\n"; dl = deg(Lambda); h.rep.SetLength(L + 1); for (i = 0; i < L - dl; i++) clear(h.rep[i]); for (i = L - dl; i <= L; i++) h.rep[i] = Lambda.rep[L - i]; }
long IsX(const ZZX& a) { return deg(a) == 1 && IsOne(LeadCoeff(a)) && IsZero(ConstTerm(a)); }
// Create new local-bridge BRIDGE *BrNewBridge(HUB *h, char *name, POLICY *p, bool local, bool monitor, bool tapmode, char *tapaddr, bool limit_broadcast, LOCALBRIDGE *parent_local_bridge) { BRIDGE *b; POLICY *policy; THREAD *t; // Validate arguments if (h == NULL || name == NULL || parent_local_bridge == NULL) { return NULL; } if (p == NULL) { policy = ClonePolicy(GetDefaultPolicy()); } else { policy = ClonePolicy(p); } b = ZeroMalloc(sizeof(BRIDGE)); b->Cedar = h->Cedar; b->Hub = h; StrCpy(b->Name, sizeof(b->Name), name); b->Policy = policy; b->Local = local; b->Monitor = monitor; b->TapMode = tapmode; b->LimitBroadcast = limit_broadcast; b->ParentLocalBridge = parent_local_bridge; if (b->TapMode) { if (tapaddr != NULL && IsZero(tapaddr, 6) == false) { Copy(b->TapMacAddress, tapaddr, 6); } else { GenMacAddress(b->TapMacAddress); } } if (monitor) { // Enabling monitoring mode policy->MonitorPort = true; } if (b->LimitBroadcast == false) { // Disable broadcast limiter policy->NoBroadcastLimiter = true; } // Start thread t = NewThread(BrBridgeThread, b); WaitThreadInit(t); ReleaseThread(t); return b; }
// Add a local-bridge void AddLocalBridge(CEDAR *c, char *hubname, char *devicename, bool local, bool monitor, bool tapmode, char *tapaddr, bool limit_broadcast) { UINT i; HUB *h = NULL; LOCALBRIDGE *br = NULL; // Validate arguments if (c == NULL || hubname == NULL || devicename == NULL) { return; } if (OS_IS_UNIX(GetOsInfo()->OsType) == false) { tapmode = false; } LockList(c->HubList); { LockList(c->LocalBridgeList); { bool exists = false; // Ensure that the same configuration local-bridge doesn't exist already for (i = 0;i < LIST_NUM(c->LocalBridgeList);i++) { LOCALBRIDGE *br = LIST_DATA(c->LocalBridgeList, i); if (StrCmpi(br->DeviceName, devicename) == 0) { if (StrCmpi(br->HubName, hubname) == 0) { if (br->TapMode == tapmode) { exists = true; } } } } if (exists == false) { // Add configuration br = ZeroMalloc(sizeof(LOCALBRIDGE)); StrCpy(br->HubName, sizeof(br->HubName), hubname); StrCpy(br->DeviceName, sizeof(br->DeviceName), devicename); br->Bridge = NULL; br->Local = local; br->TapMode = tapmode; br->LimitBroadcast = limit_broadcast; br->Monitor = monitor; if (br->TapMode) { if (tapaddr != NULL && IsZero(tapaddr, 6) == false) { Copy(br->TapMacAddress, tapaddr, 6); } else { GenMacAddress(br->TapMacAddress); } } Add(c->LocalBridgeList, br); // Find the hub for (i = 0;i < LIST_NUM(c->HubList);i++) { HUB *hub = LIST_DATA(c->HubList, i); if (StrCmpi(hub->Name, br->HubName) == 0) { h = hub; AddRef(h->ref); break; } } } } UnlockList(c->LocalBridgeList); } UnlockList(c->HubList); // Start the local-bridge immediately if (h != NULL && br != NULL && h->Type != HUB_TYPE_FARM_DYNAMIC) { Lock(h->lock_online); { if (h->Offline == false) { LockList(c->LocalBridgeList); { if (IsInList(c->LocalBridgeList, br)) { if (br->Bridge == NULL) { br->Bridge = BrNewBridge(h, br->DeviceName, NULL, br->Local, br->Monitor, br->TapMode, br->TapMacAddress, br->LimitBroadcast, br); } } } UnlockList(c->LocalBridgeList); } } Unlock(h->lock_online); } ReleaseHub(h); }
/** * Advances a fling by an interpolated amount based on the Android OverScroller. * This should be called whenever sampling the content transform for this * frame. Returns true if the fling animation should be advanced by one frame, * or false if there is no fling or the fling has ended. */ bool AndroidFlingAnimation::DoSample(FrameMetrics& aFrameMetrics, const TimeDuration& aDelta) { bool shouldContinueFling = true; mOverScroller->ComputeScrollOffset(&shouldContinueFling); // OverScroller::GetCurrVelocity will sometimes return NaN. So need to externally // calculate current velocity and not rely on what the OverScroller calculates. // mOverScroller->GetCurrVelocity(&speed); int32_t currentX = 0; int32_t currentY = 0; mOverScroller->GetCurrX(¤tX); mOverScroller->GetCurrY(¤tY); ParentLayerPoint offset((float)currentX, (float)currentY); bool hitBoundX = CheckBounds(mApzc.mX, offset.x, mFlingDirection.x, &(offset.x)); bool hitBoundY = CheckBounds(mApzc.mY, offset.y, mFlingDirection.y, &(offset.y)); ParentLayerPoint velocity = mPreviousVelocity; // Sometimes the OverScroller fails to update the offset for a frame. // If the frame can still scroll we just use the velocity from the previous // frame. However, if the frame can no longer scroll in the direction // of the fling, then end the animation. if (offset != mPreviousOffset) { if (aDelta.ToMilliseconds() > 0) { velocity = (offset - mPreviousOffset) / (float)aDelta.ToMilliseconds(); mPreviousVelocity = velocity; } } else if (hitBoundX || hitBoundY) { // We have reached the end of the scroll in one of the directions being scrolled and the offset has not // changed so end animation. shouldContinueFling = false; } float speed = velocity.Length(); // gfxPrefs::APZFlingStoppedThreshold is only used in tests. if (!shouldContinueFling || (speed < gfxPrefs::APZFlingStoppedThreshold())) { if (shouldContinueFling) { // The OverScroller thinks it should continue but the speed is below // the stopping threshold so abort the animation. mOverScroller->AbortAnimation(); } // This animation is going to end. If DeferHandleFlingOverscroll // has not been called and there is still some velocity left, // call it so that fling hand off may occur if applicable. if (!mSentBounceX && !mSentBounceY && (speed > 0.0f)) { DeferHandleFlingOverscroll(velocity); } return false; } mPreviousOffset = offset; mApzc.SetVelocityVector(velocity); aFrameMetrics.SetScrollOffset(offset / aFrameMetrics.GetZoom()); // If we hit a bounds while flinging, send the velocity so that the bounce // animation can play. if (hitBoundX || hitBoundY) { ParentLayerPoint bounceVelocity = velocity; if (!mSentBounceX && hitBoundX && fabsf(offset.x - mStartOffset.x) > BOUNDS_EPSILON) { mSentBounceX = true; } else { bounceVelocity.x = 0.0f; } if (!mSentBounceY && hitBoundY && fabsf(offset.y - mStartOffset.y) > BOUNDS_EPSILON) { mSentBounceY = true; } else { bounceVelocity.y = 0.0f; } if (!IsZero(bounceVelocity)) { DeferHandleFlingOverscroll(bounceVelocity); } } return true; }
void XHalfGCD(ZZ_pXMatrix& M_out, ZZ_pX& U, ZZ_pX& V, long d_red) { if (IsZero(V) || deg(V) <= deg(U) - d_red) { set(M_out(0,0)); clear(M_out(0,1)); clear(M_out(1,0)); set(M_out(1,1)); return; } long du = deg(U); if (d_red <= NTL_ZZ_pX_HalfGCD_CROSSOVER) { IterHalfGCD(M_out, U, V, d_red); return; } long d1 = (d_red + 1)/2; if (d1 < 1) d1 = 1; if (d1 >= d_red) d1 = d_red - 1; ZZ_pXMatrix M1; HalfGCD(M1, U, V, d1); mul(U, V, M1); long d2 = deg(V) - du + d_red; if (IsZero(V) || d2 <= 0) { M_out = M1; return; } ZZ_pX Q; ZZ_pXMatrix M2; DivRem(Q, U, U, V); swap(U, V); XHalfGCD(M2, U, V, d2); ZZ_pX t(INIT_SIZE, deg(M1(1,1))+deg(Q)+1); mul(t, Q, M1(1,0)); sub(t, M1(0,0), t); swap(M1(0,0), M1(1,0)); swap(M1(1,0), t); t.kill(); t.SetMaxLength(deg(M1(1,1))+deg(Q)+1); mul(t, Q, M1(1,1)); sub(t, M1(0,1), t); swap(M1(0,1), M1(1,1)); swap(M1(1,1), t); t.kill(); mul(M_out, M2, M1); }
/* Both ellipses are assumed to have non-zero radii */ int Int2Elip(Point *IntPts,Ellipse *E1,Ellipse *E2) { TMat ElpCirMat1,ElpCirMat2,InvMat,TempMat; Conic Conic1,Conic2,Conic3,TempConic; double Roots[3],qRoots[2]; static Circle TestCir = {{0.0,0.0},1.0}; Line TestLine[2]; Point TestPoint; double PolyCoef[4]; /* coefficients of the polynomial */ double D; /* discriminant: B^2 - AC */ double Phi; /* ellipse rotation */ double m,n; /* ellipse translation */ double Scl; /* scaling factor */ int NumRoots,NumLines; int CircleInts; /* intersections between line and circle */ int IntCount = 0; /* number of intersections found */ int i,j,k; /* compute the transformations which turn E1 and E2 into circles */ Elp2Cir(E1,&ElpCirMat1); Elp2Cir(E2,&ElpCirMat2); /* compute the inverse transformation of ElpCirMat1 */ InvElp2Cir(E1,&InvMat); /* Compute the characteristic matrices */ GenEllipseCoefs(E1,&Conic1); GenEllipseCoefs(E2,&Conic2); /* Find x such that Det(Conic1 + x Conic2) = 0 */ PolyCoef[0] = -Conic1.C*Conic1.D*Conic1.D + 2.0*Conic1.B*Conic1.D*Conic1.E - Conic1.A*Conic1.E*Conic1.E - Conic1.B*Conic1.B*Conic1.F + Conic1.A*Conic1.C*Conic1.F; PolyCoef[1] = -(Conic2.C*Conic1.D*Conic1.D) - 2.0*Conic1.C*Conic1.D*Conic2.D + 2.0*Conic2.B*Conic1.D*Conic1.E + 2.0*Conic1.B*Conic2.D*Conic1.E - Conic2.A*Conic1.E*Conic1.E + 2.0*Conic1.B*Conic1.D*Conic2.E - 2.0*Conic1.A*Conic1.E*Conic2.E - 2.0*Conic1.B*Conic2.B*Conic1.F + Conic2.A*Conic1.C*Conic1.F + Conic1.A*Conic2.C*Conic1.F - Conic1.B*Conic1.B*Conic2.F + Conic1.A*Conic1.C*Conic2.F; PolyCoef[2] = -2.0*Conic2.C*Conic1.D*Conic2.D - Conic1.C*Conic2.D*Conic2.D + 2.0*Conic2.B*Conic2.D*Conic1.E + 2.0*Conic2.B*Conic1.D*Conic2.E + 2.0*Conic1.B*Conic2.D*Conic2.E - 2.0*Conic2.A*Conic1.E*Conic2.E - Conic1.A*Conic2.E*Conic2.E - Conic2.B*Conic2.B*Conic1.F + Conic2.A*Conic2.C*Conic1.F - 2.0*Conic1.B*Conic2.B*Conic2.F + Conic2.A*Conic1.C*Conic2.F + Conic1.A*Conic2.C*Conic2.F; PolyCoef[3] = -Conic2.C*Conic2.D*Conic2.D + 2.0*Conic2.B*Conic2.D*Conic2.E - Conic2.A*Conic2.E*Conic2.E - Conic2.B*Conic2.B*Conic2.F + Conic2.A*Conic2.C*Conic2.F; NumRoots = SolveCubic(PolyCoef,Roots); if (NumRoots == 0) return 0; /* we try all the roots, even though it's redundant, so that we avoid some pathological situations */ for (i=0;i<NumRoots;i++) { NumLines = 0; /* Conic3 = Conic1 + mu Conic2 */ Conic3.A = Conic1.A + Roots[i]*Conic2.A; Conic3.B = Conic1.B + Roots[i]*Conic2.B; Conic3.C = Conic1.C + Roots[i]*Conic2.C; Conic3.D = Conic1.D + Roots[i]*Conic2.D; Conic3.E = Conic1.E + Roots[i]*Conic2.E; Conic3.F = Conic1.F + Roots[i]*Conic2.F; D = Conic3.B*Conic3.B - Conic3.A*Conic3.C; if (IsZero(Conic3.A) && IsZero(Conic3.B) && IsZero(Conic3.C)) { /* Case 1 - Single line */ NumLines = 1; /* compute endpoints of the line, avoiding division by zero */ if (fabs(Conic3.D) > fabs(Conic3.E)) { TestLine[0].P1.Y = 0.0; TestLine[0].P1.X = -Conic3.F/(Conic3.D + Conic3.D); TestLine[0].P2.Y = 1.0; TestLine[0].P2.X = -(Conic3.E + Conic3.E + Conic3.F)/ (Conic3.D + Conic3.D); } else { TestLine[0].P1.X = 0.0; TestLine[0].P1.Y = -Conic3.F/(Conic3.E + Conic3.E); TestLine[0].P2.X = 1.0; TestLine[0].P2.Y = -(Conic3.D + Conic3.D + Conic3.F)/ (Conic3.E + Conic3.E); } } else { /* use the espresion for Phi that takes atan of the smallest argument */ Phi = (fabs(Conic3.B + Conic3.B) < fabs(Conic3.A-Conic3.C)? atan((Conic3.B + Conic3.B)/(Conic3.A - Conic3.C)): M_PI_2 - atan((Conic3.A - Conic3.C)/(Conic3.B + Conic3.B)))/2.0; if (IsZero(D)) { /* Case 2 - Parallel lines */ TempConic = Conic3; TempMat = IdentMat; RotateMat(&TempMat,-Phi); TransformConic(&TempConic,&TempMat); if (IsZero(TempConic.C)) /* vertical */ { PolyCoef[0] = TempConic.F; PolyCoef[1] = 2*TempConic.D; PolyCoef[2] = TempConic.A; if ((NumLines=SolveQuadic(PolyCoef,qRoots))!=0) { TestLine[0].P1.X = qRoots[0]; TestLine[0].P1.Y = -1.0; TestLine[0].P2.X = qRoots[0]; TestLine[0].P2.Y = 1.0; if (NumLines==2) { TestLine[1].P1.X = qRoots[1]; TestLine[1].P1.Y = -1.0; TestLine[1].P2.X = qRoots[1]; TestLine[1].P2.Y = 1.0; } } } else /* horizontal */ { PolyCoef[0] = TempConic.F; PolyCoef[1] = 2*TempConic.E; PolyCoef[2] = TempConic.C; if ((NumLines=SolveQuadic(PolyCoef,qRoots))!=0) { TestLine[0].P1.X = -1.0; TestLine[0].P1.Y = qRoots[0]; TestLine[0].P2.X = 1.0; TestLine[0].P2.Y = qRoots[0]; if (NumLines==2) { TestLine[1].P1.X = -1.0; TestLine[1].P1.Y = qRoots[1]; TestLine[1].P2.X = 1.0; TestLine[1].P2.Y = qRoots[1]; } } } TempMat = IdentMat; RotateMat(&TempMat,Phi); TransformPoint(&TestLine[0].P1,&TempMat); TransformPoint(&TestLine[0].P2,&TempMat); if (NumLines==2) { TransformPoint(&TestLine[1].P1,&TempMat); TransformPoint(&TestLine[1].P2,&TempMat); } } else { /* Case 3 - Crossing lines */ NumLines = 2; /* translate the system so that the intersection of the lines is at the origin */ TempConic = Conic3; m = (Conic3.C*Conic3.D - Conic3.B*Conic3.E)/D; n = (Conic3.A*Conic3.E - Conic3.B*Conic3.D)/D; TempMat = IdentMat; TranslateMat(&TempMat,-m,-n); RotateMat(&TempMat,-Phi); TransformConic(&TempConic,&TempMat); /* Compute the line endpoints */ TestLine[0].P1.X = sqrt(fabs(1.0/TempConic.A)); TestLine[0].P1.Y = sqrt(fabs(1.0/TempConic.C)); Scl = max(TestLine[0].P1.X,TestLine[0].P1.Y); /* adjust range */ TestLine[0].P1.X /= Scl; TestLine[0].P1.Y /= Scl; TestLine[0].P2.X = - TestLine[0].P1.X; TestLine[0].P2.Y = - TestLine[0].P1.Y; TestLine[1].P1.X = TestLine[0].P1.X; TestLine[1].P1.Y = - TestLine[0].P1.Y; TestLine[1].P2.X = - TestLine[1].P1.X; TestLine[1].P2.Y = - TestLine[1].P1.Y; /* translate the lines back */ TempMat = IdentMat; RotateMat(&TempMat,Phi); TranslateMat(&TempMat,m,n); TransformPoint(&TestLine[0].P1,&TempMat); TransformPoint(&TestLine[0].P2,&TempMat); TransformPoint(&TestLine[1].P1,&TempMat); TransformPoint(&TestLine[1].P2,&TempMat); } } /* find the ellipse line intersections */ for (j = 0;j < NumLines;j++) { /* transform the line endpts into the circle space of the ellipse */ TransformPoint(&TestLine[j].P1,&ElpCirMat1); TransformPoint(&TestLine[j].P2,&ElpCirMat1); /* compute the number of intersections of the transformed line and test circle */ CircleInts = IntCirLine(&IntPts[IntCount],&TestCir,&TestLine[j]); if (CircleInts>0) { /* transform the intersection points back into ellipse space */ for (k = 0;k < CircleInts;k++) TransformPoint(&IntPts[IntCount+k],&InvMat); /* update the number of intersections found */ IntCount += CircleInts; } } } /* validate the points */ j = IntCount; IntCount = 0; for (i = 0;i < j;i++) { TestPoint = IntPts[i]; TransformPoint(&TestPoint,&ElpCirMat2); if (TestPoint.X < 2.0 && TestPoint.Y < 2.0 && IsZero(1.0 - sqrt(TestPoint.X*TestPoint.X + TestPoint.Y*TestPoint.Y))) IntPts[IntCount++]=IntPts[i]; } return IntCount; }
void interpolate(ZZ_pX& f, const vec_ZZ_p& a, const vec_ZZ_p& b) { long m = a.length(); if (b.length() != m) LogicError("interpolate: vector length mismatch"); if (m == 0) { clear(f); return; } vec_ZZ_p prod; prod = a; ZZ_p t1, t2; long k, i; vec_ZZ_p res; res.SetLength(m); for (k = 0; k < m; k++) { const ZZ_p& aa = a[k]; set(t1); for (i = k-1; i >= 0; i--) { mul(t1, t1, aa); add(t1, t1, prod[i]); } clear(t2); for (i = k-1; i >= 0; i--) { mul(t2, t2, aa); add(t2, t2, res[i]); } inv(t1, t1); sub(t2, b[k], t2); mul(t1, t1, t2); for (i = 0; i < k; i++) { mul(t2, prod[i], t1); add(res[i], res[i], t2); } res[k] = t1; if (k < m-1) { if (k == 0) negate(prod[0], prod[0]); else { negate(t1, a[k]); add(prod[k], t1, prod[k-1]); for (i = k-1; i >= 1; i--) { mul(t2, prod[i], t1); add(prod[i], t2, prod[i-1]); } mul(prod[0], prod[0], t1); } } } while (m > 0 && IsZero(res[m-1])) m--; res.SetLength(m); f.rep = res; }
void inv(ZZ& d_out, mat_ZZ& x_out, const mat_ZZ& A, long deterministic) { long n = A.NumRows(); if (A.NumCols() != n) Error("solve: nonsquare matrix"); if (n == 0) { set(d_out); x_out.SetDims(0, 0); return; } zz_pBak zbak; zbak.save(); ZZ_pBak Zbak; Zbak.save(); mat_ZZ x(INIT_SIZE, n, n); ZZ d, d1; ZZ d_prod, x_prod; set(d_prod); set(x_prod); long d_instable = 1; long x_instable = 1; long gp_cnt = 0; long check = 0; mat_ZZ y; long i; long bound = 2+DetBound(A); for (i = 0; ; i++) { if ((check || IsZero(d)) && !d_instable) { if (NumBits(d_prod) > bound) { break; } else if (!deterministic && bound > 1000 && NumBits(d_prod) < 0.25*bound) { ZZ P; long plen = 90 + NumBits(max(bound, NumBits(d))); GenPrime(P, plen, 90 + 2*NumBits(gp_cnt++)); ZZ_p::init(P); mat_ZZ_p AA; conv(AA, A); ZZ_p dd; determinant(dd, AA); if (CRT(d, d_prod, rep(dd), P)) d_instable = 1; else break; } } zz_p::FFTInit(i); long p = zz_p::modulus(); mat_zz_p AA; conv(AA, A); if (!check) { mat_zz_p xx; zz_p dd; inv(dd, xx, AA); d_instable = CRT(d, d_prod, rep(dd), p); if (!IsZero(dd)) { mul(xx, xx, dd); x_instable = CRT(x, x_prod, xx); } else x_instable = 1; if (!d_instable && !x_instable) { mul(y, x, A); if (IsDiag(y, n, d)) { d1 = d; check = 1; } } } else { zz_p dd; determinant(dd, AA); d_instable = CRT(d, d_prod, rep(dd), p); } } if (check && d1 != d) { mul(x, x, d); ExactDiv(x, d1); } d_out = d; if (check) x_out = x; zbak.restore(); Zbak.restore(); }
void Q_SetKer(QMatrix *Q, Vector *RightKer, Vector *LeftKer) /* defines the null space in the case of a singular matrix */ { double Sum, Mean, Cmp, Norm; size_t Dim, Ind; Real *KerCmp; V_Lock(RightKer); V_Lock(LeftKer); if (LASResult() == LASOK) { if (Q->Dim == RightKer->Dim && (Q->Symmetry || Q->Dim == LeftKer->Dim)) { Dim = Q->Dim; /* release array for old null space components when it exists */ if (Q->RightKerCmp != NULL) { free(Q->RightKerCmp); Q->RightKerCmp = NULL; } if (Q->LeftKerCmp != NULL) { free(Q->LeftKerCmp); Q->LeftKerCmp = NULL; } Q->UnitRightKer = False; Q->UnitLeftKer = False; /* right null space */ KerCmp = RightKer->Cmp; /* test whether the matrix Q has a unit right null space */ Sum = 0.0; for(Ind = 1; Ind <= Dim; Ind++) Sum += KerCmp[Ind]; Mean = Sum / (double)Dim; Q->UnitRightKer = True; if (!IsZero(Mean)) { for(Ind = 1; Ind <= Dim; Ind++) if (!IsOne(KerCmp[Ind] / Mean)) Q->UnitRightKer = False; } else { Q->UnitRightKer = False; } if (!Q->UnitRightKer) { Sum = 0.0; for(Ind = 1; Ind <= Dim; Ind++) { Cmp = KerCmp[Ind]; Sum += Cmp * Cmp; } Norm = sqrt(Sum); if (!IsZero(Norm)) { Q->RightKerCmp = (Real *)malloc((Dim + 1) * sizeof(Real)); if (Q->RightKerCmp != NULL) { for(Ind = 1; Ind <= Dim; Ind++) Q->RightKerCmp[Ind] = KerCmp[Ind] / Norm; } else { LASError(LASMemAllocErr, "Q_SetKer", Q->Name, RightKer->Name, LeftKer->Name); } } } if (!Q->Symmetry) { /* left null space */ KerCmp = LeftKer->Cmp; /* test whether the matrix Q has a unit left null space */ Sum = 0.0; for(Ind = 1; Ind <= Dim; Ind++) Sum += KerCmp[Ind]; Mean = Sum / (double)Dim; Q->UnitLeftKer = True; if (!IsZero(Mean)) { for(Ind = 1; Ind <= Dim; Ind++) if (!IsOne(KerCmp[Ind] / Mean)) Q->UnitLeftKer = False; } else { Q->UnitLeftKer = False; } if (!Q->UnitLeftKer) { Sum = 0.0; for(Ind = 1; Ind <= Dim; Ind++) { Cmp = KerCmp[Ind]; Sum += Cmp * Cmp; } Norm = sqrt(Sum); if (!IsZero(Norm)) { Q->LeftKerCmp = (Real *)malloc((Dim + 1) * sizeof(Real)); if (Q->LeftKerCmp != NULL) { for(Ind = 1; Ind <= Dim; Ind++) Q->LeftKerCmp[Ind] = KerCmp[Ind] / Norm; } else { LASError(LASMemAllocErr, "Q_SetKer", Q->Name, RightKer->Name, LeftKer->Name); } } } } else { } } else { LASError(LASDimErr, "Q_SetKer", Q->Name, RightKer->Name, LeftKer->Name); } } V_Unlock(RightKer); V_Unlock(LeftKer); }
NTL_START_IMPL void CharPolyMod(ZZX& gg, const ZZX& a, const ZZX& f, long deterministic) { if (!IsOne(LeadCoeff(f)) || deg(f) < 1 || deg(a) >= deg(f)) Error("CharPolyMod: bad args"); if (IsZero(a)) { clear(gg); SetCoeff(gg, deg(f)); return; } long bound = 2 + CharPolyBound(a, f); long gp_cnt = 0; zz_pBak bak; bak.save(); ZZ_pBak bak1; bak1.save(); ZZX g; ZZ prod; clear(g); set(prod); long i; long instable = 1; for (i = 0; ; i++) { if (NumBits(prod) > bound) break; if (!deterministic && !instable && bound > 1000 && NumBits(prod) < 0.25*bound) { long plen = 90 + NumBits(max(bound, MaxBits(g))); ZZ P; GenPrime(P, plen, 90 + 2*NumBits(gp_cnt++)); ZZ_p::init(P); ZZ_pX G, A, F; conv(A, a); conv(F, f); CharPolyMod(G, A, F); if (CRT(g, prod, G)) instable = 1; else break; } zz_p::FFTInit(i); zz_pX G, A, F; conv(A, a); conv(F, f); CharPolyMod(G, A, F); instable = CRT(g, prod, G); } gg = g; bak.restore(); bak1.restore(); }
bool Vector::operator == (const Vector& v) const { if(IsZero(x - v.x) && IsZero(y - v.y) && IsZero(z - v.z)) return(true); return(false); }
LD_BOOL IsEqual( LD_FLOAT32 p_Left, LD_FLOAT32 p_Right ) { return ( IsZero( p_Left - p_Right ) ); }
float Ray::GetDistanceFrom(Ray& r) { float t = (d | r.d); if(IsZero(t)) return(-BIGNUMBER); // plane is paralell to the ray, return -infinite return(((r.p - p) | r.d) / t); }
void determinant(zz_pE& d, const mat_zz_pE& M_in) { long k, n; long i, j; long pos; zz_pX t1, t2; zz_pX *x, *y; const zz_pXModulus& p = zz_pE::modulus(); n = M_in.NumRows(); if (M_in.NumCols() != n) Error("determinant: nonsquare matrix"); if (n == 0) { set(d); return; } vec_zz_pX *M = newNTL_NEW_OP vec_zz_pX[n]; for (i = 0; i < n; i++) { M[i].SetLength(n); for (j = 0; j < n; j++) { M[i][j].rep.SetMaxLength(2*deg(p)-1); M[i][j] = rep(M_in[i][j]); } } zz_pX det; set(det); for (k = 0; k < n; k++) { pos = -1; for (i = k; i < n; i++) { rem(t1, M[i][k], p); M[i][k] = t1; if (pos == -1 && !IsZero(t1)) pos = i; } if (pos != -1) { if (k != pos) { swap(M[pos], M[k]); negate(det, det); } MulMod(det, det, M[k][k], p); // make M[k, k] == -1 mod p, and make row k reduced InvMod(t1, M[k][k], p); negate(t1, t1); for (j = k+1; j < n; j++) { rem(t2, M[k][j], p); MulMod(M[k][j], t2, t1, p); } for (i = k+1; i < n; i++) { // M[i] = M[i] + M[k]*M[i,k] t1 = M[i][k]; // this is already reduced x = M[i].elts() + (k+1); y = M[k].elts() + (k+1); for (j = k+1; j < n; j++, x++, y++) { // *x = *x + (*y)*t1 mul(t2, *y, t1); add(*x, *x, t2); } } } else { clear(d); goto done; } } conv(d, det); done: delete[] M; }
void Slice::ConnectSegmentNeighbors() { unsigned int s; unsigned int potential; unsigned int s2; double potentialangle; double potentialDist; double minDist = 10000.0; Segment* thisSeg = NULL; Segment* thatSeg = NULL; QVector2D* thisPoint = NULL; QVector2D* thatPoint = NULL; std::vector<Segment*> sameXStripSegs; std::vector<Segment*> potentialLeadSegs; Segment* finalLeadSeg = NULL; for(s = 0; s < segmentList.size(); s++)//compare from every segment { thisSeg = segmentList[s]; thisPoint = &thisSeg->p2;//compare from the 2nd point on "this" segment if(thisSeg->leadingSeg)//no need to add a connection if there already is one! continue; potentialLeadSegs.clear();//clear out the potentials list GetSegmentsAroundX(sameXStripSegs, thisPoint->x()); ////////////////////////////////////// for(s2 = 0; s2 < sameXStripSegs.size(); s2++)//to every other segment in ring { //make sure its not the same segment if(s == s2) {continue;} thatSeg = sameXStripSegs[s2]; if(thatSeg->trailingSeg)//already connected to a trailing segment... continue; thatPoint = &thatSeg->p1;//to the first point of "that" segment if(IsZero(Distance2D(*thisPoint, *thatPoint),0.03))//they are close enough to each other { potentialLeadSegs.push_back(thatSeg); } } ////////////////////////////////////// //sort through and pick from the potential pile //we want to pick a segment with the sharpest change in direction! // // //1>>>>>>>>>A>>>>>>>>2 1>>>>>>>>B>>>>>>>>>2 // ^ // large delta angle/ Right Wieghted minDist = 100000.0; finalLeadSeg = NULL; potentialangle = 0.0; for(potential = 0; potential < potentialLeadSegs.size(); potential++) { thatSeg = potentialLeadSegs[potential]; //potentialDot = (thisSeg->normal.x() * thatSeg->normal.x()) + (thisSeg->normal.y() * thatSeg->normal.y()); //gives a number indicating how sharp the angle is, -1 is the sharpest (-1,1) //potentialCross = (thisSeg->normal.x() * thatSeg->normal.y()) - (thisSeg->normal.y() * thatSeg->normal.x());//gives a number indicating a right or left turn. (uphill is positive), (downhill is negative) (-1,1) potentialDist = Distance2D(thisSeg->p2, thatSeg->p1); if(potentialDist < minDist) { minDist = potentialDist; finalLeadSeg = potentialLeadSegs[potential]; } } if(finalLeadSeg) { thisSeg->leadingSeg = finalLeadSeg; finalLeadSeg->trailingSeg = thisSeg; thisSeg->p2 = finalLeadSeg->p1; thisSeg->FormNormal(); } } }
long gauss(mat_zz_pE& M_in, long w) { long k, l; long i, j; long pos; zz_pX t1, t2, t3; zz_pX *x, *y; long n = M_in.NumRows(); long m = M_in.NumCols(); if (w < 0 || w > m) Error("gauss: bad args"); const zz_pXModulus& p = zz_pE::modulus(); vec_zz_pX *M = newNTL_NEW_OP vec_zz_pX[n]; for (i = 0; i < n; i++) { M[i].SetLength(m); for (j = 0; j < m; j++) { M[i][j].rep.SetMaxLength(2*deg(p)-1); M[i][j] = rep(M_in[i][j]); } } l = 0; for (k = 0; k < w && l < n; k++) { pos = -1; for (i = l; i < n; i++) { rem(t1, M[i][k], p); M[i][k] = t1; if (pos == -1 && !IsZero(t1)) { pos = i; } } if (pos != -1) { swap(M[pos], M[l]); InvMod(t3, M[l][k], p); negate(t3, t3); for (j = k+1; j < m; j++) { rem(M[l][j], M[l][j], p); } for (i = l+1; i < n; i++) { // M[i] = M[i] + M[l]*M[i,k]*t3 MulMod(t1, M[i][k], t3, p); clear(M[i][k]); x = M[i].elts() + (k+1); y = M[l].elts() + (k+1); for (j = k+1; j < m; j++, x++, y++) { // *x = *x + (*y)*t1 mul(t2, *y, t1); add(t2, t2, *x); *x = t2; } } l++; } } for (i = 0; i < n; i++) for (j = 0; j < m; j++) conv(M_in[i][j], M[i][j]); delete [] M; return l; }
int MathUtils::solveCubic(double c[4], double s[3]) { int i, num; double sub; double A, B, C; double sq_A, p, q; double cb_p, D; /* normal form: x^3 + Ax^2 + Bx + C = 0 */ A = c[ 2 ] / c[ 3 ]; B = c[ 1 ] / c[ 3 ]; C = c[ 0 ] / c[ 3 ]; /* substitute x = y - A/3 to eliminate quadric term: x^3 +px + q = 0 */ sq_A = A * A; p = 1.0/3 * (- 1.0/3 * sq_A + B); q = 1.0/2 * (2.0/27 * A * sq_A - 1.0/3 * A * B + C); /* use Cardano's formula */ cb_p = p * p * p; D = q * q + cb_p; if (IsZero(D)) { if (IsZero(q)) { /* one triple solution */ s[ 0 ] = 0; num = 1; } else { /* one single and one double solution */ double u = cbrt(-q); s[ 0 ] = 2 * u; s[ 1 ] = - u; num = 2; } } else if (D < 0) { /* Casus irreducibilis: three real solutions */ double phi = 1.0/3 * acos(-q / sqrt(-cb_p)); double t = 2 * sqrt(-p); s[ 0 ] = t * cos(phi); s[ 1 ] = - t * cos(phi + M_PI / 3); s[ 2 ] = - t * cos(phi - M_PI / 3); num = 3; } else { /* one real solution */ double sqrt_D = sqrt(D); double u = cbrt(sqrt_D - q); double v = - cbrt(sqrt_D + q); s[ 0 ] = u + v; num = 1; } /* resubstitute */ sub = 1.0/3 * A; for (i = 0; i < num; ++i) s[ i ] -= sub; return num; }
int SolveQuartic(double *c, double *s) { double coeffs[ 4 ]; double z, u, v, sub; double A, B, C, D; double sq_A, p, q, r; int i, num; /* normal form: x^4 + Ax^3 + Bx^2 + Cx + D = 0 */ A = c[ 3 ] / c[ 4 ]; B = c[ 2 ] / c[ 4 ]; C = c[ 1 ] / c[ 4 ]; D = c[ 0 ] / c[ 4 ]; /* substitute x = y - A/4 to eliminate cubic term: x^4 + px^2 + qx + r = 0 */ sq_A = A * A; p = - 3.0/8 * sq_A + B; q = 1.0/8 * sq_A * A - 1.0/2 * A * B + C; r = - 3.0/256*sq_A*sq_A + 1.0/16*sq_A*B - 1.0/4*A*C + D; if (IsZero(r)) { /* no absolute term: y(y^3 + py + q) = 0 */ coeffs[ 0 ] = q; coeffs[ 1 ] = p; coeffs[ 2 ] = 0; coeffs[ 3 ] = 1; num = SolveCubic(coeffs, s); s[ num++ ] = 0; } else { /* solve the resolvent cubic ... */ coeffs[ 0 ] = 1.0/2 * r * p - 1.0/8 * q * q; coeffs[ 1 ] = - r; coeffs[ 2 ] = - 1.0/2 * p; coeffs[ 3 ] = 1; (void) SolveCubic(coeffs, s); /* ... and take the one real solution ... */ z = s[ 0 ]; /* ... to build two quadric equations */ u = z * z - r; v = 2 * z - p; if (IsZero(u)) u = 0; else if (u > 0) u = sqrt(u); else return 0; if (IsZero(v)) v = 0; else if (v > 0) v = sqrt(v); else return 0; coeffs[ 0 ] = z - u; coeffs[ 1 ] = q < 0 ? -v : v; coeffs[ 2 ] = 1; num = SolveQuadric(coeffs, s); coeffs[ 0 ]= z + u; coeffs[ 1 ] = q < 0 ? v : -v; coeffs[ 2 ] = 1; num += SolveQuadric(coeffs, s + num); } /* resubstitute */ sub = 1.0/4 * A; for (i = 0; i < num; ++i) s[ i ] -= sub; return num; }
static FeatureData Combine_Line_Line_Constraints(FeaturePtr c1, FeaturePtr c2) { Vector cross; double param1; Vector temp_v1, temp_v2, temp_v3, temp_v4; Vector point1; FeatureData result; /* The result is inconsistent if the lines don't intersect, a point ** otherwise (their point of intersection. */ VCross(c1->f_vector, c2->f_vector, cross); if ( VZero(cross) ) { /* The lines are parallel. */ if ( Point_On_Line( c1->f_vector, c1->f_point, c2->f_point) ) return *c1; else { result.f_type = inconsistent_feature; return result; } } /* They still may or may not intersect. */ VSub(c1->f_point, c2->f_point, temp_v1); VCross(c2->f_vector, temp_v1, temp_v2); VCross(c1->f_vector, temp_v1, temp_v3); /* temp_v3 and temp_v2 are both perp to temp_v1. */ /* If temp_v2 is 0, then the lines intersect at c1->f_point1. */ /* If temp_v3 is 0, then the lines intersect at c1->f_point2. */ /* If temp_v2 and temp_v3 are parallel, the lines intersect somewhere. */ /* Otherwise they don't. */ if ( VZero(temp_v2) ) { result.f_type = point_feature; result.f_point = c1->f_point; return result; } else if ( VZero(temp_v2) ) { result.f_type = point_feature; result.f_point = c2->f_point; return result; } VCross(temp_v2, temp_v3, temp_v4); if ( ! VZero(temp_v4) ) { result.f_type = inconsistent_feature; return result; } /* Get the parameter for the point of intersection. */ if ( ! IsZero(cross.z) ) param1 = temp_v2.z / cross.z; else if ( ! IsZero(cross.y) ) param1 = temp_v2.y / cross.y; else param1 = temp_v2.x / cross.x; VScalarMul(c1->f_vector, param1, temp_v1); VAdd(temp_v1, c1->f_point, point1); result.f_type = point_feature; result.f_point = point1; return result; }