Polynomial.cxx

Go to the documentation of this file.
00001 // @(#)root/mathmore:$Id: Polynomial.cxx 24403 2008-06-20 08:31:10Z moneta $
00002 // Authors: L. Moneta, A. Zsenei   08/2005 
00003 
00004  /**********************************************************************
00005   *                                                                    *
00006   * Copyright (c) 2004 ROOT Foundation,  CERN/PH-SFT                   *
00007   *                                                                    *
00008   * This library is free software; you can redistribute it and/or      *
00009   * modify it under the terms of the GNU General Public License        *
00010   * as published by the Free Software Foundation; either version 2     *
00011   * of the License, or (at your option) any later version.             *
00012   *                                                                    *
00013   * This library is distributed in the hope that it will be useful,    *
00014   * but WITHOUT ANY WARRANTY; without even the implied warranty of     *
00015   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   *
00016   * General Public License for more details.                           *
00017   *                                                                    *
00018   * You should have received a copy of the GNU General Public License  *
00019   * along with this library (see file COPYING); if not, write          *
00020   * to the Free Software Foundation, Inc., 59 Temple Place, Suite      *
00021   * 330, Boston, MA 02111-1307 USA, or contact the author.             *
00022   *                                                                    *
00023   **********************************************************************/
00024 
00025 // Implementation file for class Polynomial
00026 // 
00027 // Created by: Lorenzo Moneta  at Wed Nov 10 17:46:19 2004
00028 // 
00029 // Last update: Wed Nov 10 17:46:19 2004
00030 // 
00031 
00032 #include "Math/Polynomial.h"
00033 
00034 
00035 #include "gsl/gsl_math.h"
00036 #include "gsl/gsl_errno.h"
00037 #include "gsl/gsl_poly.h"
00038 #include "gsl/gsl_poly.h"
00039 #include "complex_quartic.h"
00040 
00041 #define DEBUG
00042 #ifdef DEBUG
00043 #include <iostream>
00044 #endif
00045 
00046 namespace ROOT {
00047 namespace Math {
00048 
00049 
00050 Polynomial::Polynomial(unsigned int n) : 
00051   // number of par is order + 1
00052   ParFunc( n+1 ), 
00053   fOrder(n), 
00054   fDerived_params(std::vector<double>(n) )
00055 {
00056 }
00057 
00058   //order 1
00059 Polynomial::Polynomial(double a, double b) : 
00060   ParFunc( 2 ), 
00061   fOrder(1), 
00062   fDerived_params(std::vector<double>(1) )
00063 {
00064   fParams[0] = b; 
00065   fParams[1] = a; 
00066 }
00067 
00068 // order 2
00069 Polynomial::Polynomial(double a, double b, double c) : 
00070   ParFunc( 3 ), 
00071   fOrder(2), 
00072   fDerived_params(std::vector<double>(2) )
00073 {
00074   fParams[0] = c; 
00075   fParams[1] = b; 
00076   fParams[2] = a; 
00077 }
00078 
00079 // order 3 (cubic)
00080 Polynomial::Polynomial(double a, double b, double c, double d) : 
00081   // number of par is order + 1
00082   ParFunc( 4 ), 
00083   fOrder(3), 
00084   fDerived_params(std::vector<double>(3) )
00085 {
00086   fParams[0] = d; 
00087   fParams[1] = c; 
00088   fParams[2] = b; 
00089   fParams[3] = a; 
00090 }
00091 
00092 // order 3 (quartic)
00093 Polynomial::Polynomial(double a, double b, double c, double d, double e) : 
00094   // number of par is order + 1
00095   ParFunc( 5 ), 
00096   fOrder(4), 
00097   fDerived_params(std::vector<double>(4) )
00098 {
00099   fParams[0] = e; 
00100   fParams[1] = d; 
00101   fParams[2] = c; 
00102   fParams[3] = b; 
00103   fParams[4] = a; 
00104 }
00105 
00106 
00107 
00108 // Polynomial::Polynomial(const Polynomial &) 
00109 // {
00110 // }
00111 
00112 // Polynomial & Polynomial::operator = (const Polynomial &rhs) 
00113 // {
00114 //    if (this == &rhs) return *this;  // time saving self-test
00115 
00116 //    return *this;
00117 // }
00118 
00119 
00120 double  Polynomial::DoEvalPar (double x, const double * p) const { 
00121   
00122     return gsl_poly_eval( p, fOrder + 1, x); 
00123 
00124 }
00125 
00126 
00127 
00128 double  Polynomial::DoDerivative(double x) const{ 
00129 
00130    for ( unsigned int i = 0; i < fOrder; ++i ) 
00131     fDerived_params[i] =  (i + 1) * Parameters()[i+1]; 
00132 
00133    return gsl_poly_eval( &fDerived_params.front(), fOrder, x); 
00134 
00135 }
00136 
00137 double Polynomial::DoParameterDerivative (double x, const double *, unsigned int ipar) const { 
00138 
00139       return gsl_pow_int(x, ipar); 
00140 }
00141 
00142 
00143 
00144 IGenFunction * Polynomial::Clone() const { 
00145     Polynomial * f =  new Polynomial(fOrder);
00146     f->fDerived_params = fDerived_params; 
00147     f->SetParameters( Parameters() ); 
00148     return f; 
00149 }
00150         
00151 
00152 const std::vector< std::complex <double> > &  Polynomial::FindRoots(){
00153 
00154 
00155     // check if order is correct
00156     unsigned int n = fOrder;
00157     while ( Parameters()[n] == 0 ) { 
00158       n--;
00159     } 
00160 
00161     fRoots.clear();  
00162     fRoots.reserve(n);  
00163 
00164 
00165     if (n == 0) {   
00166       return fRoots;
00167     } 
00168     else if (n == 1 ) { 
00169       if ( Parameters()[1] == 0) return fRoots;
00170       double r = - Parameters()[0]/ Parameters()[1]; 
00171       fRoots.push_back( std::complex<double> ( r, 0.0) ); 
00172     }
00173     // quadratic equations
00174     else if (n == 2 ) { 
00175       gsl_complex z1, z2;
00176       int nr = gsl_poly_complex_solve_quadratic(Parameters()[2], Parameters()[1], Parameters()[0], &z1, &z2); 
00177       if ( nr != 2) { 
00178 #ifdef DEBUG
00179         std::cout << "Polynomial quadratic ::-  FAILED to find roots" << std::endl; 
00180 #endif
00181         return fRoots;
00182       } 
00183       fRoots.push_back(std::complex<double>(z1.dat[0],z1.dat[1]) ); 
00184       fRoots.push_back(std::complex<double>(z2.dat[0],z2.dat[1]) );       
00185     }
00186     // cubic equations
00187     else if (n == 3 ) { 
00188       gsl_complex  z1, z2, z3;   
00189       // renormmalize params in this case
00190       double w = Parameters()[3]; 
00191       double a = Parameters()[2]/w;
00192       double b = Parameters()[1]/w;
00193       double c = Parameters()[0]/w;
00194       int nr = gsl_poly_complex_solve_cubic(a, b, c, &z1, &z2, &z3); 
00195       if (nr != 3) { 
00196 #ifdef DEBUG
00197         std::cout << "Polynomial  cubic::-  FAILED to find roots" << std::endl; 
00198 #endif
00199         return fRoots; 
00200 
00201       }
00202       fRoots.push_back(std::complex<double> (z1.dat[0],z1.dat[1]) ); 
00203       fRoots.push_back(std::complex<double> (z2.dat[0],z2.dat[1]) ); 
00204       fRoots.push_back(std::complex<double> (z3.dat[0],z3.dat[1]) );       
00205     }
00206     // quartic equations
00207     else if (n == 4 ) { 
00208       // quartic eq.  
00209       gsl_complex  z1, z2, z3, z4;   
00210       // renormalize params in this case
00211       double w = Parameters()[4]; 
00212       double a = Parameters()[3]/w;
00213       double b = Parameters()[2]/w;
00214       double c = Parameters()[1]/w;
00215       double d = Parameters()[0]/w;
00216       int nr = gsl_poly_complex_solve_quartic(a, b, c, d, &z1, &z2, &z3, & z4); 
00217       if (nr != 4) { 
00218 #ifdef DEBUG
00219         std::cout << "Polynomial quartic ::-  FAILED to find roots" << std::endl; 
00220 #endif
00221         return fRoots;
00222       } 
00223       fRoots.push_back(std::complex<double> (z1.dat[0],z1.dat[1]) ); 
00224       fRoots.push_back(std::complex<double> (z2.dat[0],z2.dat[1]) ); 
00225       fRoots.push_back(std::complex<double> (z3.dat[0],z3.dat[1]) );       
00226       fRoots.push_back(std::complex<double> (z4.dat[0],z4.dat[1]) );       
00227     }
00228     else { 
00229     // for higher order polynomial use numerical fRoots
00230       FindNumRoots();
00231     }      
00232 
00233     return fRoots; 
00234 
00235   }
00236 
00237 
00238 std::vector< double >  Polynomial::FindRealRoots(){
00239   FindRoots(); 
00240   std::vector<double> roots; 
00241   roots.reserve(fOrder); 
00242   for (unsigned int i = 0; i < fOrder; ++i) { 
00243     if (fRoots[i].imag() == 0) 
00244       roots.push_back( fRoots[i].real() ); 
00245   }
00246   return roots; 
00247 }
00248 const std::vector< std::complex <double> > &  Polynomial::FindNumRoots(){
00249 
00250 
00251     // check if order is correct
00252     unsigned int n = fOrder;
00253     while ( Parameters()[n] == 0 ) { 
00254       n--;
00255     } 
00256     fRoots.clear();
00257     fRoots.reserve(n);  
00258 
00259 
00260     if (n == 0) {   
00261       return fRoots;
00262     } 
00263 
00264     gsl_poly_complex_workspace * w = gsl_poly_complex_workspace_alloc( n + 1); 
00265     std::vector<double> z(2*n);
00266     int status = gsl_poly_complex_solve ( Parameters(), n+1, w, &z.front() );  
00267     gsl_poly_complex_workspace_free(w);
00268     if (status != GSL_SUCCESS) return fRoots; 
00269     for (unsigned int i = 0; i < n; ++i) 
00270       fRoots.push_back(std::complex<double> (z[2*i],z[2*i+1] ) );      
00271 
00272     return fRoots; 
00273 }
00274 
00275 
00276 } // namespace Math
00277 } // namespace ROOT

Generated on Tue Jul 5 14:34:57 2011 for ROOT_528-00b_version by  doxygen 1.5.1