/*
poly.cc -- routines for manipulation of polynomials in one var
- (c) 1993--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+ (c) 1993--2003 Han-Wen Nienhuys <hanwen@cs.uu.nl>
*/
#include <math.h>
Polynomial
-Polynomial::multiply(const Polynomial & p1, const Polynomial & p2)
+Polynomial::multiply (const Polynomial & p1, const Polynomial & p2)
{
Polynomial dest;
}
void
-Polynomial::differentiate()
+Polynomial::differentiate ()
{
for (int i = 1; i<= degree (); i++)
{
}
Polynomial
-Polynomial::power(int exponent, const Polynomial & src)
+Polynomial::power (int exponent, const Polynomial & src)
{
int e = exponent;
- Polynomial dest(1), base(src);
+ Polynomial dest (1), base (src);
- // classicint power. invariant: src^exponent = dest * src ^ e
- // greetings go out to Lex Bijlsma & Jaap vd Woude
+ /*
+ classic int power. invariant: src^exponent = dest * src ^ e
+ greetings go out to Lex Bijlsma & Jaap vd Woude */
while (e > 0)
{
if (e % 2)
{
- dest = multiply(dest, base);
+ dest = multiply (dest, base);
e--;
} else
{
- base = multiply(base, base);
+ base = multiply (base, base);
e /= 2;
}
}
static Real const FUDGE = 1e-8;
void
-Polynomial::clean()
+Polynomial::clean ()
{
- int i;
- for (i = 0; i <= degree (); i++)
- {
- if (abs(coefs_[i]) < FUDGE)
- coefs_[i] = 0.0;
- }
-
- while (degree () > 0 && fabs (coefs_.top ()) < FUDGE * fabs (coefs_.top (1)))
+/*
+ We only do relative comparisons. Absolute comparisons break down in
+ degenerate cases. */
+ while (degree () > 0 &&
+ (fabs (coefs_.top ()) < FUDGE * fabs (coefs_.top (1))
+ || !coefs_.top ()))
coefs_.pop ();
}
-Polynomial
-Polynomial::add(const Polynomial & p1, const Polynomial & p2)
+
+void
+Polynomial::operator += (Polynomial const &p)
{
- Polynomial dest;
- int tempord = p2.degree () >? p1.degree ();
- for (int i = 0; i <= tempord; i++)
- {
- Real temp = 0.0;
- if (i <= p1.degree ())
- temp += p1.coefs_[i];
- if (i <= p2.degree ())
- temp += p2.coefs_[i];
- dest.coefs_.push (temp);
- }
- return dest;
+ while (degree () < p.degree())
+ coefs_.push (0.0);
+
+ for (int i = 0; i <= p.degree(); i++)
+ coefs_[i] += p.coefs_[i];
}
+
void
-Polynomial::scalarmultiply(Real fact)
+Polynomial::operator -= (Polynomial const &p)
{
- for (int i = 0; i <= degree (); i++)
- coefs_[i] *= fact;
+ while (degree () < p.degree())
+ coefs_.push (0.0);
+
+ for (int i = 0; i <= p.degree(); i++)
+ coefs_[i] -= p.coefs_[i];
}
-Polynomial
-Polynomial::subtract(const Polynomial & p1, const Polynomial & p2)
+
+void
+Polynomial::scalarmultiply (Real fact)
{
- Polynomial dest;
- int tempord = p2.degree () >? p1.degree ();
-
- for (int i = 0; i <= tempord; i++)
- {
- Real temp = 0.0; // can't store result directly.. a=a-b
- if (i <= p1.degree ())
- temp += p1.coefs_[i];
- if (i <= p2.degree ())
- temp -= p2.coefs_[i];
- dest.coefs_.push (temp);
- }
- return dest;
-
+ for (int i = 0; i <= degree (); i++)
+ coefs_[i] *= fact;
}
+
+
void
-Polynomial::set_negate(const Polynomial & src)
+Polynomial::set_negate (const Polynomial & src)
{
- for (int i = 0; i <= src.degree(); i++)
+ for (int i = 0; i <= src.degree (); i++)
coefs_[i] = -src.coefs_[i];
}
/// mod of #u/v#
int
-Polynomial::set_mod(const Polynomial &u, const Polynomial &v)
+Polynomial::set_mod (const Polynomial &u, const Polynomial &v)
{
- (*this) = u;
+ (*this) = u;
- if (v.lc() < 0.0) {
+ if (v.lc () < 0.0) {
for (int k = u.degree () - v.degree () - 1; k >= 0; k -= 2)
coefs_[k] = -coefs_[k];
while (k >= 0 && coefs_[k] == 0.0)
k--;
- coefs_.set_size(1+ ( (k < 0) ? 0 : k));
- return degree();
+ coefs_.set_size (1+ ((k < 0) ? 0 : k));
+ return degree ();
}
void
-Polynomial::check_sol(Real x) const
+Polynomial::check_sol (Real x) const
{
- Real f=eval(x);
- Polynomial p(*this);
- p.differentiate();
- Real d = p.eval(x);
+ Real f=eval (x);
+ Polynomial p (*this);
+ p.differentiate ();
+ Real d = p.eval (x);
- if( abs(f) > abs(d) * FUDGE)
+ if ( abs (f) > abs (d) * FUDGE)
;
/*
- warning("x=%f is not a root of polynomial\n"
- "f(x)=%f, f'(x)=%f \n", x, f, d); */
+ warning ("x=%f is not a root of polynomial\n"
+ "f (x)=%f, f' (x)=%f \n", x, f, d); */
}
void
-Polynomial::check_sols(Array<Real> roots) const
+Polynomial::check_sols (Array<Real> roots) const
{
for (int i=0; i< roots.size (); i++)
- check_sol(roots[i]);
+ check_sol (roots[i]);
}
Polynomial::Polynomial (Real a, Real b)
}
/* cubic root. */
-inline Real cubic_root(Real x)
+inline Real cubic_root (Real x)
{
if (x > 0.0)
- return pow(x, 1.0/3.0) ;
+ return pow (x, 1.0/3.0) ;
else if (x < 0.0)
- return -pow(-x, 1.0/3.0);
+ return -pow (-x, 1.0/3.0);
else
return 0.0;
}
}
Array<Real>
-Polynomial::solve_cubic()const
+Polynomial::solve_cubic ()const
{
Array<Real> sol;
/* use Cardano's formula */
- Real cb_p = p * p * p;
- Real D = q * q + cb_p;
+ Real cb = p * p * p;
+ Real D = q * q + cb;
- if (iszero(D)) {
- if (iszero(q)) { /* one triple solution */
+ if (iszero (D)) {
+ if (iszero (q)) { /* one triple solution */
sol.push (0);
sol.push (0);
sol.push (0);
} else { /* one single and one double solution */
- Real u = cubic_root(-q);
+ Real u = cubic_root (-q);
sol.push (2 * u);
sol.push (-u);
}
} else if (D < 0) { /* Casus irreducibilis: three real solutions */
- Real phi = 1.0 / 3 * acos(-q / sqrt(-cb_p));
- Real t = 2 * sqrt(-p);
+ Real phi = 1.0 / 3 * acos (-q / sqrt (-cb));
+ Real t = 2 * sqrt (-p);
- sol.push (t * cos(phi));
- sol.push (-t * cos(phi + M_PI / 3));
- sol.push ( -t * cos(phi - M_PI / 3));
+ sol.push (t * cos (phi));
+ sol.push (-t * cos (phi + M_PI / 3));
+ sol.push ( -t * cos (phi - M_PI / 3));
} else { /* one real solution */
- Real sqrt_D = sqrt(D);
- Real u = cubic_root(sqrt_D - q);
- Real v = -cubic_root(sqrt_D + q);
+ Real sqrt_D = sqrt (D);
+ Real u = cubic_root (sqrt_D - q);
+ Real v = -cubic_root (sqrt_D + q);
sol.push ( u + v);
}
{
sol[i] -= sub;
+#ifdef PARANOID
assert (fabs (eval (sol[i]) ) < 1e-8);
+#endif
}
return sol;
Real
Polynomial::lc () const
{
- return coefs_.top();
+ return coefs_.top ();
}
Real&
all roots of quadratic eqn.
*/
Array<Real>
-Polynomial::solve_quadric()const
+Polynomial::solve_quadric ()const
{
Array<Real> sol;
/* normal form: x^2 + px + q = 0 */
Real D = p * p - q;
if (D>0) {
- D = sqrt(D);
+ D = sqrt (D);
sol.push ( D - p);
sol.push ( -D - p);
/* solve linear equation */
Array<Real>
-Polynomial::solve_linear()const
+Polynomial::solve_linear ()const
{
Array<Real> s;
if (coefs_[1])
case 3:
return solve_cubic ();
}
- assert (false);
Array<Real> s;
return s;
}
*this = multiply (*this,p2);
}
-void
-Polynomial::operator += (Polynomial const &p)
-{
- *this = add( *this, p);
-}
-void
-Polynomial::operator -= (Polynomial const &p)
-{
- *this = subtract(*this, p);
-}