/* * FindRoots : * Given a 5th-degree equation in Bernstein-Bezier form, find * all of the roots in the interval [0, 1]. Return the number * of roots found. */ static int FindRoots( Geom::Point *w, /* The control points */ int degree, /* The degree of the polynomial */ double *t, /* RETURN candidate t-values */ int depth) /* The depth of the recursion */ { int i; Geom::Point Left[W_DEGREE+1], /* New left and right */ Right[W_DEGREE+1]; /* control polygons */ int left_count, /* Solution count from */ right_count; /* children */ double left_t[W_DEGREE+1], /* Solutions from kids */ right_t[W_DEGREE+1]; switch (CrossingCount(w, degree)) { case 0 : { /* No solutions here */ return 0; break; } case 1 : { /* Unique solution */ /* Stop recursion when the tree is deep enough */ /* if deep enough, return 1 solution at midpoint */ if (depth >= MAXDEPTH) { t[0] = (w[0][Geom::X] + w[W_DEGREE][Geom::X]) / 2.0; return 1; } if (ControlPolygonFlatEnough(w, degree)) { t[0] = ComputeXIntercept(w, degree); return 1; } break; } } /* Otherwise, solve recursively after */ /* subdividing control polygon */ Bez(w, degree, 0.5, Left, Right); left_count = FindRoots(Left, degree, left_t, depth+1); right_count = FindRoots(Right, degree, right_t, depth+1); /* Gather solutions together */ for (i = 0; i < left_count; i++) { t[i] = left_t[i]; } for (i = 0; i < right_count; i++) { t[i+left_count] = right_t[i]; } /* Send back total number of solutions */ return (left_count+right_count); }
Maybe<Real> NewtonPolySolve::FindSmallestPositiveRoot(const RPolynomial& p, const Real /*lastSmallestPositive*/) { if (NumberOfSignChanges(p) == 0) return Maybe<Real>(); const CPolynomial q(p); //{ // bool converged; // RPolynomial t = RPolynomial::MakeT(); // Scalar x = NextRoot(q, Scalar(lastSmallestPositive), &converged); // if (converged && IsReal(x) && x.real() > 0 && NumberOfSignChanges(p.EvaluateAt(t + x.real() + .1)) == 0) // return x.real(); // /*if (converged && ) // return x;*/ //} const ScalarList roots = FindRoots(q); Maybe<Real> result; for (int i = 0 ; i < (int)roots.size() ; i++) { if (IsReal(roots[i]) && roots[i].real() > 0) { if (result.IsValid()) { result = std::min(result.Get(), roots[i].real()); } else { result = roots[i].real(); } } } return result; }
ScalarList NewtonPolySolve::FindRoots(const CPolynomial& poly, const ScalarList& guessListIn) { if (poly.Degree() == 0) { if (poly[0] == Scalar(0)) return ScalarList(1,0); else throw Exception("No solution"); } Scalar x(0); ScalarList guessList = guessListIn; if (!guessList.empty()) { x = guessList.back(); guessList.pop_back(); } bool converged; x = NextRoot(poly, x, &converged); ScalarList answers; if (poly.Degree() > 1) ScalarList answers = FindRoots(poly.RemoveRoot(x), guessList); answers.push_back(x); return answers; }
/* * NearestPointOnCurve : * Compute the parameter value of the point on a Bezier * curve segment closest to some arbtitrary, user-input point. * Return the point on the curve at that parameter value. * Geom::Point P; The user-supplied point Geom::Point *V; Control points of cubic Bezier */ double NearestPointOnCurve(Geom::Point P, Geom::Point *V) { double t_candidate[W_DEGREE]; /* Possible roots */ /* Convert problem to 5th-degree Bezier form */ Geom::Point *w = ConvertToBezierForm(P, V); /* Find all possible roots of 5th-degree equation */ int n_solutions = FindRoots(w, W_DEGREE, t_candidate, 0); std::free((char *)w); /* Check distance to end of the curve, where t = 1 */ double dist = SquaredLength(P - V[DEGREE]); double t = 1.0; /* Find distances for candidate points */ for (int i = 0; i < n_solutions; i++) { Geom::Point p = Bez(V, DEGREE, t_candidate[i], NULL, NULL); double new_dist = SquaredLength(P - p); if (new_dist < dist) { dist = new_dist; t = t_candidate[i]; } } /* Return the parameter value t */ return t; }
/* * FindRoots : * Given a 5th-degree equation in Bernstein-Bezier form, find * all of the roots in the interval [0, 1]. Return the number * of roots found. */ int Measurement::FindRoots(QPointF* w, int degree,double *t,int depth) { int i; QPointF Left[W_DEGREE+1], /* New left and right */ Right[W_DEGREE+1]; /* control polygons */ int left_count, /* Solution count from */ right_count; /* children */ double left_t[W_DEGREE+1], /* Solutions from kids */ right_t[W_DEGREE+1]; switch (CrossingCount(w, degree)) { case 0 : { /* No solutions here */ return 0; } case 1 : { /* Unique solution */ /* Stop recursion when the tree is deep enough */ /* if deep enough, return 1 solution at midpoint */ if (depth >= MAXDEPTH) { t[0] = (w[0].rx() + w[W_DEGREE].rx()) / 2.0; return 1; } if (ControlPolygonFlatEnough(w, degree)) { t[0] = ComputeXIntercept(w, degree); return 1; } break; } } /* Otherwise, solve recursively after */ /* subdividing control polygon */ Bezier(w, degree, 0.5, Left, Right); left_count = FindRoots(Left, degree, left_t, depth+1); right_count = FindRoots(Right, degree, right_t, depth+1); /* Gather solutions together */ for (i = 0; i < left_count; i++) { t[i] = left_t[i]; } for (i = 0; i < right_count; i++) { t[i+left_count] = right_t[i]; } /* Send back total number of solutions */ return (left_count+right_count); }
void PAlgebraModDerived<type>::mapToFt(RX& w, const RX& G,unsigned long t,const RX* rF1) const { if (isDryRun()) { w = RX::zero(); return; } long i = zMStar.indexOfRep(t); if (i < 0) { clear(w); return; } if (rF1==NULL) { // Compute the representation "from scratch" // special case if (G == factors[i]) { SetX(w); return; } //special case if (deg(G) == 1) { w = -ConstTerm(G); return; } // the general case: currently only works when r == 1 assert(r == 1); REBak bak; bak.save(); RE::init(factors[i]); // work with the extension field GF_p[X]/Ft(X) REX Ga; conv(Ga, G); // G as a polynomial over the extension field vec_RE roots; FindRoots(roots, Ga); // Find roots of G in this field RE* first = &roots[0]; RE* last = first + roots.length(); RE* smallest = min_element(first, last); // make a canonical choice w=rep(*smallest); return; } // if rF1 is set, then use it instead, setting w = rF1(X^t) mod Ft(X) RXModulus Ft(factors[i]); // long tInv = InvMod(t,m); RX X2t = PowerXMod(t,Ft); // X2t = X^t mod Ft w = CompMod(*rF1,X2t,Ft); // w = F1(X2t) mod Ft /* Debugging sanity-check: G(w)=0 in the extension field (Z/2Z)[X]/Ft(X) RE::init(factors[i]); REX Ga; conv(Ga, G); // G as a polynomial over the extension field RE ra; conv(ra, w); // w is an element in the extension field eval(ra,Ga,ra); // ra = Ga(ra) if (!IsZero(ra)) {// check that Ga(w)=0 in this extension field cout << "rF1(X^t) mod Ft(X) != root of G mod Ft, t=" << t << endl; exit(0); }*******************************************************************/ }
// FindRoots : // Given a 5th-degree equation in Bernstein-Bezier form, find // all of the roots in the interval [0, 1]. Return the number // of roots found. // Parameters : // w: The control points // degree: The degree of the polynomial // t: output candidate t-values // depth: The depth of the recursion // static int FindRoots(const Point2d* w, int degree, float* t, int depth) { int i; Point2d Left[W_DEGREE+1]; // New left and right Point2d Right[W_DEGREE+1]; // control polygons int left_count; // Solution count from children int right_count; float left_t[W_DEGREE+1]; // Solutions from kids float right_t[W_DEGREE+1]; switch (CrossingCount(w, degree)) { case 0 : // No solutions here return 0; case 1 : // Unique solution // Stop recursion when the tree is deep enough // if deep enough, return 1 solution at midpoint if (depth >= MAXDEPTH) { t[0] = (w[0].x + w[W_DEGREE].x) / 2; return 1; } if (ControlPolygonFlatEnough(w, degree)) { t[0] = ComputeXIntercept(w, degree); return 1; } break; } // Otherwise, solve recursively after subdividing control polygon BezierPoint(w, degree, 0.5f, Left, Right); left_count = FindRoots(Left, degree, left_t, depth+1); right_count = FindRoots(Right, degree, right_t, depth+1); // Gather solutions together for (i = 0; i < left_count; i++) { t[i] = left_t[i]; } for (i = 0; i < right_count; i++) { t[i+left_count] = right_t[i]; } // Send back total number of solutions return (left_count+right_count); }
double Measurement::NearestPointOnCurve(QPointF P, vector<QPointF> V) { QPointF *w; /* Ctl pts for 5th-degree eqn */ double t_candidate[W_DEGREE]; /* Possible roots */ int n_solutions; /* Number of roots found */ double t; /* Parameter value of closest pt*/ QPointF v_arr[4]; for(int i=0; i<4; i++) v_arr[i]=V[i]; /* Convert problem to 5th-degree Bezier form */ w = ConvertToBezierForm(P, v_arr); /* Find all possible roots of 5th-degree equation */ n_solutions = FindRoots(w, W_DEGREE, t_candidate, 0); free((char *)w); /* Compare distances of P to all candidates, and to t=0, and t=1 */ { double dist, new_dist; QPointF p; QPointF v; int i; /* Check distance to beginning of curve, where t = 0 */ dist = V2SquaredLength(V2Sub(&P, &v_arr[0], &v)); t = 0.0; /* Find distances for candidate points */ for (i = 0; i < n_solutions; i++) { p = Bezier(v_arr, DEGREE, t_candidate[i], (QPointF *)NULL, (QPointF *)NULL); new_dist = V2SquaredLength(V2Sub(&P, &p, &v)); if (new_dist < dist) { dist = new_dist; t = t_candidate[i]; } } /* Finally, look at distance to end point, where t = 1.0 */ new_dist = V2SquaredLength(V2Sub(&P, &V[DEGREE], &v)); if (new_dist < dist) { dist = new_dist; t = 1.0; } } /* Return the point on the curve at parameter value t */ // printf("t : %4.12f\n", t); QPointF b=Bezier(v_arr, DEGREE, t, (QPointF *)NULL, (QPointF *)NULL); return V2DistanceBetween2Points(&P,&b); }
static void ZZ_pX_linear_roots(struct ZZ_p*** v, long* n, struct ZZ_pX* f) { long i; vec_ZZ_p w; FindRoots(w, *f); *n = w.length(); (*v) = (ZZ_p**) malloc(sizeof(ZZ_p*)*(*n)); for (i=0; i<(*n); i++) { (*v)[i] = new ZZ_p(w[i]); } }
void EDFSplit(vec_ZZ_pEX& v, const ZZ_pEX& f, const ZZ_pEX& b, long d) { ZZ_pEX a, g, h; ZZ_pEXModulus F; vec_ZZ_pE roots; build(F, f); long n = F.n; long r = n/d; random(a, n); TraceMap(g, a, d, F, b); MinPolyMod(h, g, F, r); FindRoots(roots, h); FindFactors(v, f, g, roots); }
// 计算一点到三次贝塞尔曲线段上的最近点 // Parameters : // pt: The user-supplied point // pts: Control points of cubic Bezier // nearpt: output the point on the curve at that parameter value // GEOMAPI void mgNearestOnBezier( const Point2d& pt, const Point2d* pts, Point2d& nearpt) { Point2d w[W_DEGREE+1]; // Ctl pts for 5th-degree eqn float t_candidate[W_DEGREE]; // Possible roots int n_solutions; // Number of roots found float t; // Parameter value of closest pt // Convert problem to 5th-degree Bezier form ConvertToBezierForm(pt, pts, w); // Find all possible roots of 5th-degree equation n_solutions = FindRoots(w, W_DEGREE, t_candidate, 0); // Compare distances of pt to all candidates, and to t=0, and t=1 { float dist, new_dist; Point2d p; int i; // Check distance to beginning of curve, where t = 0 dist = (pt - pts[0]).lengthSqrd(); t = 0.0; // Find distances for candidate points for (i = 0; i < n_solutions; i++) { p = BezierPoint(pts, DEGREE, t_candidate[i], (Point2d *)NULL, (Point2d *)NULL); new_dist = (pt - p).lengthSqrd(); if (new_dist < dist) { dist = new_dist; t = t_candidate[i]; } } // Finally, look at distance to end point, where t = 1.0 new_dist = (pt - pts[DEGREE]).lengthSqrd(); if (new_dist < dist) { dist = new_dist; t = 1.0; } } // Return the point on the curve at parameter value t // printf("t : %4.12f\n", t); nearpt = (BezierPoint(pts, DEGREE, t, (Point2d *)NULL, (Point2d *)NULL)); }
void RootEDF(vec_ZZ_pEX& factors, const ZZ_pEX& f, long verbose) { vec_ZZ_pE roots; double t; if (verbose) { cerr << "finding roots..."; t = GetTime(); } FindRoots(roots, f); if (verbose) { cerr << (GetTime()-t) << "\n"; } long r = roots.length(); factors.SetLength(r); for (long j = 0; j < r; j++) { SetX(factors[j]); sub(factors[j], factors[j], roots[j]); } }
bool RaySphereIntersection(const NVector& C, float r, const NVector& O, const NVector& D, float tmin, float tmax, float& t) { float t0, t1; NVector H = (O - C); float a = (D * D); float b = (H * D) * 2.0f; float c = (H * H) - r*r; if (!FindRoots(a, b, c, t0, t1)) return false; if (t0 > tmax || t1 < tmin) return false; t = t0; if (t0 < tmin) t = t1; return true; }
ScalarList NewtonPolySolve::FindRoots(const RPolynomial& poly, const ScalarList& guessList) { return FindRoots(CPolynomial(poly), guessList); }
void SFBerlekamp(vec_ZZ_pX& factors, const ZZ_pX& ff, long verbose) { ZZ_pX f = ff; if (!IsOne(LeadCoeff(f))) Error("SFBerlekamp: bad args"); if (deg(f) == 0) { factors.SetLength(0); return; } if (deg(f) == 1) { factors.SetLength(1); factors[0] = f; return; } double t; const ZZ& p = ZZ_p::modulus(); long n = deg(f); ZZ_pXModulus F; build(F, f); ZZ_pX g, h; if (verbose) { cerr << "computing X^p..."; t = GetTime(); } PowerXMod(g, p, F); if (verbose) { cerr << (GetTime()-t) << "\n"; } vec_long D; long r; vec_ZZVec M; if (verbose) { cerr << "building matrix..."; t = GetTime(); } BuildMatrix(M, n, g, F, verbose); if (verbose) { cerr << (GetTime()-t) << "\n"; } if (verbose) { cerr << "diagonalizing..."; t = GetTime(); } NullSpace(r, D, M, verbose); if (verbose) { cerr << (GetTime()-t) << "\n"; } if (verbose) cerr << "number of factors = " << r << "\n"; if (r == 1) { factors.SetLength(1); factors[0] = f; return; } if (verbose) { cerr << "factor extraction..."; t = GetTime(); } vec_ZZ_p roots; RandomBasisElt(g, D, M); MinPolyMod(h, g, F, r); if (deg(h) == r) M.kill(); FindRoots(roots, h); FindFactors(factors, f, g, roots); ZZ_pX g1; vec_ZZ_pX S, S1; long i; while (factors.length() < r) { if (verbose) cerr << "+"; RandomBasisElt(g, D, M); S.kill(); for (i = 0; i < factors.length(); i++) { const ZZ_pX& f = factors[i]; if (deg(f) == 1) { append(S, f); continue; } build(F, f); rem(g1, g, F); if (deg(g1) <= 0) { append(S, f); continue; } MinPolyMod(h, g1, F, min(deg(f), r-factors.length()+1)); FindRoots(roots, h); S1.kill(); FindFactors(S1, f, g1, roots); append(S, S1); } swap(factors, S); } if (verbose) { cerr << (GetTime()-t) << "\n"; } if (verbose) { cerr << "degrees:"; long i; for (i = 0; i < factors.length(); i++) cerr << " " << deg(factors[i]); cerr << "\n"; } }
/////////////////////////////////////////////////////////////////////////// // PURPOSE: // Given syndrome ssWithoutEvens of BCH code with design distance d, // finds sparse vector (with no more than // (d-1)/2 ones) with that syndrome // (note that syndrome as well sparse vector // representation are defined at BCHSyndromeCompute above). // 'answer' returns positions of ones in the resulting vector. // These positions are elements of GF2E (i.e., we view the vector // as a vector whose positions are indexed by elements of GF2E). // Returns false if no such vector exists, true otherwise // The input syndrome is assumed to not have even powers, i.e., // has (d-1)/2 elements, such as the syndrome computed by BCHSyndromeCompute. // // ASSUMPTIONS: // Let m=GF2E::degree() (i.e., the field is GF(2^m)). // This algorithm assumes that d is odd, greater than 1, and less than 2^m. // (else BCH codes don't make sense). // Assumes input is of length (d-1)/2. // // ALGORITHM USED: // Implements BCH decoding based on Euclidean algorithm; // For the explanation of the algorithm, see // Syndrome Encoding and Decoding of BCH Codes in Sublinear Time // (Excerpted from Fuzzy Extractors: // How to Generate Strong Keys from Biometrics and Other Noisy Data) // by Yevgeniy Dodis, Rafail Ostrovsky, Leonid Reyzin and Adam Smith // or Theorem 18.7 of Victor Shoup's "A Computational Introduction to // Number Theory and Algebra" (first edition, 2005), or // pp. 170-173 of "Introduction to Coding Theory" by Jurgen Bierbrauer. // // // RUNNING TIME: // If the output has e elements (i.e., the length of the output vector // is e; note that e <= (d-1)/2), then // the running time is O(d^2 + e^2 + e^{\log_2 3} m) operations in GF(2^m), // each of which takes time O(m^{\log_2 3}) in NTL. Note that // \log_2 3 is approximately 1.585. // bool BCHSyndromeDecode(vec_GF2E &answer, const vec_GF2E & ssWithoutEvens, long d) { long i; vec_GF2E ss; // This takes O(d) operation in GF(2^m) InterpolateEvens(ss, ssWithoutEvens); GF2EX r1, r2, r3, v1, v2, v3, q, temp; GF2EX *Rold, *Rcur, *Rnew, *Vold, *Vcur, *Vnew, *tempPointer; // Use pointers to avoid moving polynomials around // An assignment of polynomials requires copying the coefficient vector; // we will not assign polynomials, but will swap pointers instead Rold = &r1; Rcur = &r2; Rnew = &r3; Vold = &v1; Vcur = &v2; Vnew = &v3; SetCoeff(*Rold, d-1, 1); // Rold holds z^{d-1} // Rcur=S(z)/z where S is the syndrome poly, Rcur = \sum S_j z^{j-1} // Note that because we index arrays from 0, S_j is stored in ss[j-1] for (i=0; i<d-1; i++) SetCoeff (*Rcur, i, ss[i]); // Vold is already 0 -- no need to initialize // Initialize Vcur to 1 SetCoeff(*Vcur, 0, 1); // Vcur = 1 // Now run Euclid, but stop as soon as degree of Rcur drops below // (d-1)/2 // This will take O(d^2) operations in GF(2^m) long t = (d-1)/2; while (deg(*Rcur) >= t) { // Rold = Rcur*q + Rnew DivRem(q, *Rnew, *Rold, *Rcur); // Vnew = Vold - qVcur) mul(temp, q, *Vcur); sub (*Vnew, *Vold, temp); // swap everything tempPointer = Rold; Rold = Rcur; Rcur = Rnew; Rnew = tempPointer; tempPointer = Vold; Vold = Vcur; Vcur = Vnew; Vnew = tempPointer; } // At the end of the loop, sigma(z) is Vcur // (up to a constant factor, which doesn't matter, // since we care about roots of sigma). // The roots of sigma(z) are inverses of the points we // are interested in. // We will check that 0 is not // a root of Vcur (else its inverse won't exist, and hence // the right polynomial doesn't exist). if (IsZero(ConstTerm(*Vcur))) return false; // Need sigma to be monic for FindRoots MakeMonic(*Vcur); // check if sigma(z) has distinct roots if not, return false // this will take O(e^{\log_2 3} m) operations in GF(2^m), // where e is the degree of sigma(z) if (CheckIfDistinctRoots(*Vcur) == false) return false; // find roots of sigma(z) // this will take O(e^2 + e^{\log_2 3} m) operations in GF(2^m), // where e is the degree of sigma(z) answer = FindRoots(*Vcur); // take inverses of roots of sigma(z) for (i = 0; i < answer.length(); ++i) answer[i] = inv(answer[i]); // It is now necessary to verify if the resulting vector // has the correct syndrome: it is possible that it does // not even though the polynomial sigma(z) factors // completely // This takes O(de) operations in GF(2^m) vec_GF2E test; BCHSyndromeCompute (test, answer, d); return (test==ssWithoutEvens); }