2 poly.cc -- routines for manipulation of polynomials in one var
4 (c) 1993--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 #include "polynomial.hh"
17 Een beter milieu begint bij uzelf. Hergebruik!
20 This was ripped from Rayce, a raytracer I once wrote.
24 Polynomial::eval (Real x) const
29 for (vsize i = coefs_.size (); i--;)
30 p = x * p + coefs_[i];
36 Polynomial::multiply (const Polynomial &p1, const Polynomial &p2)
40 int deg = p1.degree () + p2.degree ();
41 for (int i = 0; i <= deg; i++)
43 dest.coefs_.push_back (0);
44 for (int j = 0; j <= i; j++)
45 if (i - j <= p2.degree () && j <= p1.degree ())
46 dest.coefs_.back () += p1.coefs_[j] * p2.coefs_[i - j];
53 Polynomial::differentiate ()
55 for (int i = 1; i <= degree (); i++)
56 coefs_[i - 1] = coefs_[i] * i;
61 Polynomial::power (int exponent, const Polynomial &src)
64 Polynomial dest (1), base (src);
67 classic int power. invariant: src^exponent = dest * src ^ e
68 greetings go out to Lex Bijlsma & Jaap vd Woude */
73 dest = multiply (dest, base);
79 base = multiply (base, base);
86 static Real const FUDGE = 1e-8;
92 We only do relative comparisons. Absolute comparisons break down in
95 && (fabs (coefs_.back ()) < FUDGE * fabs (back (coefs_, 1))
101 Polynomial::operator += (Polynomial const &p)
103 while (degree () < p.degree ())
104 coefs_.push_back (0.0);
106 for (int i = 0; i <= p.degree (); i++)
107 coefs_[i] += p.coefs_[i];
111 Polynomial::operator -= (Polynomial const &p)
113 while (degree () < p.degree ())
114 coefs_.push_back (0.0);
116 for (int i = 0; i <= p.degree (); i++)
117 coefs_[i] -= p.coefs_[i];
121 Polynomial::scalarmultiply (Real fact)
123 for (int i = 0; i <= degree (); i++)
128 Polynomial::set_negate (const Polynomial &src)
130 for (int i = 0; i <= src.degree (); i++)
131 coefs_[i] = -src.coefs_[i];
136 Polynomial::set_mod (const Polynomial &u, const Polynomial &v)
142 for (int k = u.degree () - v.degree () - 1; k >= 0; k -= 2)
143 coefs_[k] = -coefs_[k];
145 for (int k = u.degree () - v.degree (); k >= 0; k--)
146 for (int j = v.degree () + k - 1; j >= k; j--)
147 coefs_[j] = -coefs_[j] - coefs_[v.degree () + k] * v.coefs_[j - k];
152 for (int k = u.degree () - v.degree (); k >= 0; k--)
153 for (int j = v.degree () + k - 1; j >= k; j--)
154 coefs_[j] -= coefs_[v.degree () + k] * v.coefs_[j - k];
157 int k = v.degree () - 1;
158 while (k >= 0 && coefs_[k] == 0.0)
161 coefs_.resize (1+ ((k < 0) ? 0 : k));
166 Polynomial::check_sol (Real x) const
169 Polynomial p (*this);
173 if (abs (f) > abs (d) * FUDGE)
174 programming_error ("not a root of polynomial\n");
178 Polynomial::check_sols (vector<Real> roots) const
180 for (vsize i = 0; i < roots.size (); i++)
181 check_sol (roots[i]);
184 Polynomial::Polynomial (Real a, Real b)
186 coefs_.push_back (a);
188 coefs_.push_back (b);
192 inline Real cubic_root (Real x)
195 return pow (x, 1.0 / 3.0);
197 return -pow (-x, 1.0 / 3.0);
208 Polynomial::solve_cubic ()const
212 /* normal form: x^3 + Ax^2 + Bx + C = 0 */
213 Real A = coefs_[2] / coefs_[3];
214 Real B = coefs_[1] / coefs_[3];
215 Real C = coefs_[0] / coefs_[3];
218 * substitute x = y - A/3 to eliminate quadric term: x^3 +px + q = 0
222 Real p = 1.0 / 3 * (-1.0 / 3 * sq_A + B);
223 Real q = 1.0 / 2 * (2.0 / 27 * A *sq_A - 1.0 / 3 * A *B + C);
225 /* use Cardano's formula */
232 if (iszero (q)) { /* one triple solution */
237 else { /* one single and one double solution */
238 Real u = cubic_root (-q);
240 sol.push_back (2 * u);
246 /* Casus irreducibilis: three real solutions */
247 Real phi = 1.0 / 3 * acos (-q / sqrt (-cb));
248 Real t = 2 * sqrt (-p);
250 sol.push_back (t * cos (phi));
251 sol.push_back (-t * cos (phi + M_PI / 3));
252 sol.push_back (-t * cos (phi - M_PI / 3));
256 /* one real solution */
257 Real sqrt_D = sqrt (D);
258 Real u = cubic_root (sqrt_D - q);
259 Real v = -cubic_root (sqrt_D + q);
261 sol.push_back (u + v);
265 Real sub = 1.0 / 3 * A;
267 for (vsize i = sol.size (); i--;)
272 assert (fabs (eval (sol[i])) < 1e-8);
280 Polynomial::lc () const
282 return coefs_.back ();
288 return coefs_.back ();
292 Polynomial::degree ()const
294 return coefs_.size () -1;
297 all roots of quadratic eqn.
300 Polynomial::solve_quadric ()const
303 /* normal form: x^2 + px + q = 0 */
304 Real p = coefs_[1] / (2 * coefs_[2]);
305 Real q = coefs_[0] / coefs_[2];
313 sol.push_back (D - p);
314 sol.push_back (-D - p);
319 /* solve linear equation */
321 Polynomial::solve_linear ()const
325 s.push_back (-coefs_[0] / coefs_[1]);
330 Polynomial::solve () const
332 Polynomial *me = (Polynomial *) this;
338 return solve_linear ();
340 return solve_quadric ();
342 return solve_cubic ();
349 Polynomial::operator *= (Polynomial const &p2)
351 *this = multiply (*this, p2);