// Add b to a or Subs b from a. void sub(Poly& a, const Poly& b) { if(a.size() < b.size()) a.resize(b.size(), 0); for(int i = 0; i < b.size(); ++i) a[i] ^= b[i]; tidy(a); }
Poly divide(Poly const &a, Poly const &b, Poly &r) { Poly c; r = a; // remainder assert(!b.empty()); const unsigned k = a.degree(); const unsigned l = b.degree(); c.resize(k, 0.); for(unsigned i = k; i >= l; i--) { assert(i >= 0); double ci = r.back()/b.back(); c[i-l] += ci; Poly bb = ci*b; //std::cout << ci <<"*(" << b.shifted(i-l) << ") = " // << bb.shifted(i-l) << " r= " << r << std::endl; r -= bb.shifted(i-l); r.pop_back(); } //std::cout << "r= " << r << std::endl; r.normalize(); c.normalize(); return c; }
bool get(Poly& p) { int N; if(!(cin >> N)) return false; p.resize(N + 1); for(int i = 0; i <= N; ++i) cin >> p[N - i]; return true; }
Poly Poly::operator*(const Poly& p) const { Poly result; result.resize(degree() + p.degree()+1); for(unsigned i = 0; i < size(); i++) { for(unsigned j = 0; j < p.size(); j++) { result[i+j] += (*this)[i] * p[j]; } } return result; }
// Slow deconvolution, polynomial dividing. // q returns the quotient, r returns the remainder. void deconv(const Poly& u, const Poly& v, Poly& q, Poly& r) { int n = u.size() - 1; int nv = v.size() - 1; q.assign(n+1, 0.0); r = u; for(int k = n-nv; k >= 0; k--) { q[k] = r[nv+k] / v[nv]; for(int j = nv+k-1; j >= k; j--) r[j] -= q[k] * v[j-k]; } r.resize(nv); }
// Slow deconvolution, polynomial dividing. // q returns the quotient, r returns the remainder. void deconv(const Poly& u, const Poly& v, Poly& q, Poly& r) { int n = u.size() - 1; int nv = v.size() - 1; q.assign(n + 1, 0); r = u; for(int k = n-nv; k >= 0; k--) { q[k] = r[nv+k]; for(int j = nv+k-1; j >= k; j--) r[j] ^= (q[k] & v[j-k]); } r.resize(nv); tidy(q); tidy(r); }
Poly convexHull( Poly p ){ sort( p.begin(), p.end() ); int n = p.size(), k = 0; Poly h ( 2 * n ); for( int i = 0; i < n; i++ ){ while( k >= 2 && ccw( h[k-2], h[k-1], p[i] ) <= 0 ) k--; h[k++] = p[i]; } int t = k + 1; for( int i = n - 2; i >= 0; i-- ){ while( k >= t && ccw( h[k-2], h[k-1], p[i] ) <= 0 ) k--; h[k++] = p[i]; } h.resize( k - 1 ); return h; }
/** Set the number of loops for one particular poly. An \c EIndexError exception is thrown if \a poly is out of range. */ void PolyhedronGeom::setNumLoops(int poly, int num) { if ((poly<0) || (poly>=getNumPolys())) throw EIndexError("Poly index out of range."); if (num<0) num=0; Poly* polygon = polys[poly]; // Number of loops before the modification int prevsize = polygon->size(); // Number of vertices removed (this number is used to adjust the constraint // size for facevarying variables) int lostverts = 0; int i; // Delete loops if the number of loops was decreased if (num<prevsize) { for(i=num; i<prevsize; i++) { // Add the number of verts in the loop lostverts += (*polygon)[i]->size(); // Delete the loop delete (*polygon)[i]; } } // Resize loop list polygon->resize(num); // Allocate new loops... // (the new loops have no verts, so lostverts doesn't have to be modified) for(i=prevsize; i<num; i++) { (*polygon)[i] = new VertexLoop(); } // Update the size constraint for facevarying variables... // Todo: This probably shouldn't be done for every single modification // again and again... UserSizeConstraint* usc = dynamic_cast<UserSizeConstraint*>(faceVaryingSizeConstraint.get()); // std::cout<<"LOSTVERTS: "<<lostverts<<std::endl; if (usc!=0) usc->setSize(usc->getSize()-lostverts); }
Poly convexHull( Poly p ){ sort( p.begin(), p.end() ); int n = p.size(), k = 0; Poly h ( 2 * n ); for( int i = 0; i < n; i++ ){ while( k >= 2 && ccw( h[k-2], h[k-1], p[i] ) <= 0 ) k--; h[k++] = p[i]; } int t = k + 1; for( int i = n - 2; i >= 0; i-- ){ while( k >= t && ccw( h[k-2], h[k-1], p[i] ) <= 0 ) k--; h[k++] = p[i]; } // devuelve el primero y el ultimo punto iguales, por eso se le resta 1 h.resize( k - 1 ); return h; }
int main() { init(); Poly now; int N; double left, right, ans; while(cin >> N) { now.resize(N+1); for(int i = N; i >= 0; --i) cin >> now[i]; cin >> left >> right; for(int i = 0; i <= N; ++i) { if(right > 0 || i % 2 == 0) ans += now[i] * polyval(S[i], fabs(right)+1); else ans -= now[i] * polyval(S[i], fabs(right)+1); if(left > 0 || i % 2) ans -= now[i] * polyval(S[i], fabs(left - 1.0)+1); else ans += now[i] * polyval(S[i], fabs(left - 1.0)+1); } if(fabs(ans) < 1e-5) ans = 0; printf("%.6le\n", ans); } }
// Polynomial addition a(x) += k * b(x). void add(Poly& a, const Poly& b, double k = 1.0) { if(a.size() < b.size()) a.resize(b.size(), 0); for(int i = 0; i < b.size(); ++i) a[i] += k * b[i]; }
std::vector<double> EllipticalArc::allNearestPoints( Point const& p, double from, double to ) const { std::vector<double> result; if ( from > to ) std::swap(from, to); if ( from < 0 || to > 1 ) { THROW_RANGEERROR("[from,to] interval out of range"); } if ( ( are_near(ray(X), 0) && are_near(ray(Y), 0) ) || are_near(from, to) ) { result.push_back(from); return result; } else if ( are_near(ray(X), 0) || are_near(ray(Y), 0) ) { LineSegment seg(pointAt(from), pointAt(to)); Point np = seg.pointAt( seg.nearestPoint(p) ); if ( are_near(ray(Y), 0) ) { if ( are_near(_rot_angle, M_PI/2) || are_near(_rot_angle, 3*M_PI/2) ) { result = roots(np[Y], Y); } else { result = roots(np[X], X); } } else { if ( are_near(_rot_angle, M_PI/2) || are_near(_rot_angle, 3*M_PI/2) ) { result = roots(np[X], X); } else { result = roots(np[Y], Y); } } return result; } else if ( are_near(ray(X), ray(Y)) ) { Point r = p - center(); if ( are_near(r, Point(0,0)) ) { THROW_INFINITESOLUTIONS(0); } // TODO: implement case r != 0 // Point np = ray(X) * unit_vector(r); // std::vector<double> solX = roots(np[X],X); // std::vector<double> solY = roots(np[Y],Y); // double t; // if ( are_near(solX[0], solY[0]) || are_near(solX[0], solY[1])) // { // t = solX[0]; // } // else // { // t = solX[1]; // } // if ( !(t < from || t > to) ) // { // result.push_back(t); // } // else // { // // } } // solve the equation <D(E(t),t)|E(t)-p> == 0 // that provides min and max distance points // on the ellipse E wrt the point p // after the substitutions: // cos(t) = (1 - s^2) / (1 + s^2) // sin(t) = 2t / (1 + s^2) // where s = tan(t/2) // we get a 4th degree equation in s /* * ry s^4 ((-cy + py) Cos[Phi] + (cx - px) Sin[Phi]) + * ry ((cy - py) Cos[Phi] + (-cx + px) Sin[Phi]) + * 2 s^3 (rx^2 - ry^2 + (-cx + px) rx Cos[Phi] + (-cy + py) rx Sin[Phi]) + * 2 s (-rx^2 + ry^2 + (-cx + px) rx Cos[Phi] + (-cy + py) rx Sin[Phi]) */ Point p_c = p - center(); double rx2_ry2 = (ray(X) - ray(Y)) * (ray(X) + ray(Y)); double sinrot, cosrot; sincos(_rot_angle, sinrot, cosrot); double expr1 = ray(X) * (p_c[X] * cosrot + p_c[Y] * sinrot); Poly coeff; coeff.resize(5); coeff[4] = ray(Y) * ( p_c[Y] * cosrot - p_c[X] * sinrot ); coeff[3] = 2 * ( rx2_ry2 + expr1 ); coeff[2] = 0; coeff[1] = 2 * ( -rx2_ry2 + expr1 ); coeff[0] = -coeff[4]; // for ( unsigned int i = 0; i < 5; ++i ) // std::cerr << "c[" << i << "] = " << coeff[i] << std::endl; std::vector<double> real_sol; // gsl_poly_complex_solve raises an error // if the leading coefficient is zero if ( are_near(coeff[4], 0) ) { real_sol.push_back(0); if ( !are_near(coeff[3], 0) ) { double sq = -coeff[1] / coeff[3]; if ( sq > 0 ) { double s = std::sqrt(sq); real_sol.push_back(s); real_sol.push_back(-s); } } } else { real_sol = solve_reals(coeff); } for ( unsigned int i = 0; i < real_sol.size(); ++i ) { real_sol[i] = 2 * std::atan(real_sol[i]); if ( real_sol[i] < 0 ) real_sol[i] += 2*M_PI; } // when s -> Infinity then <D(E)|E-p> -> 0 iff coeff[4] == 0 // so we add M_PI to the solutions being lim arctan(s) = PI when s->Infinity if ( (real_sol.size() % 2) != 0 ) { real_sol.push_back(M_PI); } double mindistsq1 = std::numeric_limits<double>::max(); double mindistsq2 = std::numeric_limits<double>::max(); double dsq; unsigned int mi1, mi2; for ( unsigned int i = 0; i < real_sol.size(); ++i ) { dsq = distanceSq(p, pointAtAngle(real_sol[i])); if ( mindistsq1 > dsq ) { mindistsq2 = mindistsq1; mi2 = mi1; mindistsq1 = dsq; mi1 = i; } else if ( mindistsq2 > dsq ) { mindistsq2 = dsq; mi2 = i; } } double t = map_to_01( real_sol[mi1] ); if ( !(t < from || t > to) ) { result.push_back(t); } bool second_sol = false; t = map_to_01( real_sol[mi2] ); if ( real_sol.size() == 4 && !(t < from || t > to) ) { if ( result.empty() || are_near(mindistsq1, mindistsq2) ) { result.push_back(t); second_sol = true; } } // we need to test extreme points too double dsq1 = distanceSq(p, pointAt(from)); double dsq2 = distanceSq(p, pointAt(to)); if ( second_sol ) { if ( mindistsq2 > dsq1 ) { result.clear(); result.push_back(from); mindistsq2 = dsq1; } else if ( are_near(mindistsq2, dsq) ) { result.push_back(from); } if ( mindistsq2 > dsq2 ) { result.clear(); result.push_back(to); } else if ( are_near(mindistsq2, dsq2) ) { result.push_back(to); } } else { if ( result.empty() ) { if ( are_near(dsq1, dsq2) ) { result.push_back(from); result.push_back(to); } else if ( dsq2 > dsq1 ) { result.push_back(from); } else { result.push_back(to); } } } return result; }