00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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
00052 ParFunc( n+1 ),
00053 fOrder(n),
00054 fDerived_params(std::vector<double>(n) )
00055 {
00056 }
00057
00058
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
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
00080 Polynomial::Polynomial(double a, double b, double c, double d) :
00081
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
00093 Polynomial::Polynomial(double a, double b, double c, double d, double e) :
00094
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
00109
00110
00111
00112
00113
00114
00115
00116
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
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
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
00187 else if (n == 3 ) {
00188 gsl_complex z1, z2, z3;
00189
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
00207 else if (n == 4 ) {
00208
00209 gsl_complex z1, z2, z3, z4;
00210
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
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
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 }
00277 }