]> git.donarmstrong.com Git - lilypond.git/blobdiff - flower/polynomial.cc
* Another grand 2003 update.
[lilypond.git] / flower / polynomial.cc
index d3c353891539c44870635dcb10afeea9dd64ef99..b9f93092d5996605b2c47edb665cc1723d8f48c9 100644 (file)
@@ -1,9 +1,10 @@
 /*
    poly.cc -- routines for manipulation of polynomials in one var
 
-   (c) 1993--1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+  (c)  1993--2003 Han-Wen Nienhuys <hanwen@cs.uu.nl>
  */
 
+#include <math.h>
 
 #include "polynomial.hh"
 
@@ -28,7 +29,7 @@ Polynomial::eval (Real x)const
 
 
 Polynomial
-Polynomial::multiply(const Polynomial & p1, const Polynomial & p2)
+Polynomial::multiply (const Polynomial & p1, const Polynomial & p2)
 {
   Polynomial dest;
 
@@ -45,7 +46,7 @@ Polynomial::multiply(const Polynomial & p1, const Polynomial & p2)
 }
 
 void
-Polynomial::differentiate()
+Polynomial::differentiate ()
 {
   for (int i = 1; i<= degree (); i++)
     {
@@ -55,22 +56,23 @@ Polynomial::differentiate()
 }
 
 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;
          }
     }
@@ -80,77 +82,64 @@ Polynomial::power(int exponent, const Polynomial & src)
 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];
 
@@ -167,30 +156,30 @@ Polynomial::set_mod(const Polynomial &u, const Polynomial &v)
   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)
@@ -201,12 +190,12 @@ 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;
 }
@@ -218,7 +207,7 @@ iszero (Real r)
 }
 
 Array<Real>
-Polynomial::solve_cubic()const
+Polynomial::solve_cubic ()const
 {
   Array<Real> sol;
   
@@ -237,31 +226,31 @@ Polynomial::solve_cubic()const
 
   /* 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);
   }
@@ -273,7 +262,9 @@ Polynomial::solve_cubic()const
     {
       sol[i] -= sub;
 
+#ifdef PARANOID
       assert (fabs (eval (sol[i]) ) < 1e-8);
+#endif
     }
   
   return sol;
@@ -282,7 +273,7 @@ Polynomial::solve_cubic()const
 Real
 Polynomial::lc () const
 {
-  return coefs_.top();
+  return coefs_.top ();
 }
 
 Real&
@@ -300,7 +291,7 @@ Polynomial::degree ()const
    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 */
@@ -310,7 +301,7 @@ Polynomial::solve_quadric()const
   Real D = p * p - q;
 
   if (D>0) {
-    D = sqrt(D);
+    D = sqrt (D);
 
     sol.push ( D - p);
     sol.push ( -D - p);
@@ -320,7 +311,7 @@ Polynomial::solve_quadric()const
 
 /* solve linear equation */
 Array<Real>
-Polynomial::solve_linear()const
+Polynomial::solve_linear ()const
 {
   Array<Real> s;
   if (coefs_[1])
@@ -344,7 +335,6 @@ Polynomial::solve () const
     case 3:
       return solve_cubic ();
     }
-  assert (false);
   Array<Real> s;
   return s;
 }
@@ -355,14 +345,4 @@ Polynomial:: operator *= (Polynomial const &p2)
   *this = multiply (*this,p2);
 }  
 
-void
-Polynomial::operator += (Polynomial const &p)
-{
-  *this = add( *this, p);
-}
 
-void
-Polynomial::operator -= (Polynomial const &p)
-{
-  *this = subtract(*this, p);
-}