muMECH  1.0
polynomialRootSolution.cpp
Go to the documentation of this file.
1 //********************************************************************************************************
2 // code: ### ### ##### #### ## ##
3 // ## ## ######## ## ## ## ## ##
4 // ## ## ## ## ## ### ## ######
5 // ## ## ## ## ## ## ## ## ##
6 // ##### ## ## ##### #### ## ##
7 // ##
8 //
9 // name: polynomialRootSolution.cpp
10 // author(s): Jan Novak
11 // language: C, C++
12 // license: This program is free software; you can redistribute it and/or modify
13 // it under the terms of the GNU Lesser General Public License as published by
14 // the Free Software Foundation; either version 2 of the License, or
15 // (at your option) any later version.
16 //
17 // This program is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU Lesser General Public License for more details.
21 //
22 // You should have received a copy of the GNU Lesser General Public License
23 // along with this program; if not, write to the Free Software
24 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 //********************************************************************************************************
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <math.h>
30 #include <cmath>
31 
32 #include "macros.h"
33 #include "polynomialRootSolution.h"
34 #include "mathlib.h"
35 #include "elementaryFunctions.h"
36 
37 
38 namespace mumech {
39 
40 //********************************************************************************************************
41 // PUBLIC FUNCTIONS
42 //********************************************************************************************************
43 
44 
45 //********************************************************************************************************
46 // description: Function gives the analitical solution of cubic
47 // furmula of the real coefficients a, b, c
48 // x^3 + ax^2 + bx + c = 0
49 // last edit: 30. 11. 2008
50 //-------------------------------------------------------------------------------------------------------
51 // Solution adopted from Numerical Recepies book
52 //********************************************************************************************************
53 
54 std::complex<double> * polynomialRootSolution::GetCubicPolyRoots( double a, double b, double c, std::complex<double> * roots )
55 {
56  double Q = ( SQR( a ) - 3. * b )/9. , R = ( 2. * CUB( a ) - 9. * a * b + 27. * c )/54., Theta = 0.;
57 
58  if( SQR( R ) < CUB( Q ) ){ //all roots real
59  Theta = acos( R/ sqrt( CUB( Q ) ) );
60  roots[0].real(-2. * sqrt( Q ) * cos( Theta/3. ) - a/3.);
61  roots[1].real(-2. * sqrt( Q ) * cos( ( Theta + 2 * PI )/3. ) - a/3.);
62  roots[2].real(-2. * sqrt( Q ) * cos( ( Theta - 2 * PI )/3. ) - a/3.);
63  roots[0].imag(0.);
64  roots[1].imag(0.);
65  roots[2].imag(0.);
66  }
67  else{
68  // double A = -pow( ( R + sqrt( SQR( R ) - CUB( Q ) ) ), 1./3. );
69  double A = -sgn( R ) * pow( ( ABS( R ) + sqrt( SQR( R ) - CUB( Q ) ) ), 1./3. ), B = ( A == 0 )? 0 : Q/A;
70  //the only real root
71  roots[0].real(( A + B ) - a/3.); roots[0].imag(0.);
72  //complex roots
73  roots[1].real(-.5 * ( A + B ) - a/3.); roots[2].real(-.5 * ( A + B ) - a/3.);
74  roots[1].imag(sqrt( 3.)/2. * ( A - B ));
75  roots[2].imag(-sqrt( 3.)/2. * ( A - B ));
76  }
77  return( roots );
78 }//end of function: GetCubicFormSolu()
79 
80 //********************************************************************************************************
81 // description: Function gives the analitical solution of cubic furmula of generally
82 // complex coefficients a, b, c; i.e. solution to: x^3 + ax^2 + bx + c = 0
83 // last edit: 02. 08. 2010
84 //-------------------------------------------------------------------------------------------------------
85 // note : Solution adopted from Numerical Recepies book
86 //********************************************************************************************************
87 std::complex<double> * polynomialRootSolution::GetCubicPolyRoots( std::complex<double> a, std::complex<double> b,
88  std::complex<double> c, std::complex<double>* roots )
89 {
90  std::complex<double> Q = ( SQR( a ) - 3. * b )/9. , R = ( 2. * CUB( a ) - 9. * a * b + 27. * c )/54.;
91 
92  //initial cleansing
93  roots[0] = roots[1] = roots[2] = (0. , 0.);
94 
95  //all roots real
96  if( ABS( imag( Q ) ) <= _MACHINE_EPS_ &&
97  ABS( imag( R ) ) <= _MACHINE_EPS_ &&
98  ( SQR( real( R ) ) < CUB( real( Q ) ) ) )
99  {
100  double Theta = acos( real( R )/ sqrt( CUB( real( Q ) ) ) ),
101  aux_mlt1 = -2. * sqrt( real( Q ) );
102  std::complex<double> aux_mlt2 = (real( a )/3. , 0.);
103 
104  roots[0] = aux_mlt1 * cos( Theta/3. ) - aux_mlt2;
105  roots[1] = aux_mlt1 * cos( ( Theta + 2 * PI )/3. ) - aux_mlt2;
106  roots[2] = aux_mlt1 * cos( ( Theta - 2 * PI )/3. ) - aux_mlt2;
107  }
108  else{//generally complex roots
109  std::complex<double> aux_mlt1 = sqrt( SQR( R ) - CUB( Q ) );
110  int signum = ( real( aux_mlt1 ) < 0. )? -1 : 1;
111  std::complex<double> A = -1. * pow( ( R + (double)signum * aux_mlt1 ), 1./3. ),
112  B = ( ABS( real( A ) ) <= _MACHINE_EPS_ &&
113  ABS( imag( A ) ) <= _MACHINE_EPS_ ) ? (0. , 0.) : Q/A,
114  AplusB = A + B, AminusB = A - B, a_div_3 = a/3.,
115  auxConjPart = (0. , AminusB * _sgrt3div2_);
116 
117  //generally complex roots
118  roots[0] = AplusB - a_div_3;
119  roots[1] = roots[2] = -.5 * AplusB - a/3.;
120  roots[1] += auxConjPart;
121  roots[2] -= auxConjPart;
122  }
123 
124  return roots;
125 }//end of function: GetCubicFormSolu()
126 
127 
128 void
129 polynomialRootSolution::GauLegF(double *x, double *w, const int nPoints, const double minLim, const double maxLim)
130 {
131  /* compute x(i) and w(i) i=1,n Legendre ordinates and weights */
132  /* on interval -1.0 to 1.0 (length is 2.0) and scaled to given interval */
133  /* nPoints = number of base points */
134  /* use ordinates and weights for Gauss Legendre integration */
135 
136  if( x == NULL ) _errorr( "Field for point positions must be allocated" );
137  if( w == NULL ) _errorr( "Field for weights must be allocated" );
138 
139  int i, j, m;
140  double jj, nn;
141  double p1, p2, p3, pp, xl, xm, z, z1;
142 
143  // zero vectors
144  CleanVector(x,nPoints);
145  CleanVector(w,nPoints);
146 
147  m = (nPoints+1) / 2;
148  xm = 0.5 * (maxLim + minLim);
149  xl = 0.5 * (maxLim - minLim);
150 
151  nn = (double)nPoints;
152  for(i = 0; i < m; i++)
153  {
154  z = cos(PI * ((double)i + 0.75) / ((double)nPoints + 0.5));
155  do{
156  p1 = 1.0;
157  p2 = 0.0;
158  for(j = 0; j < nPoints; j++)
159  {
160  jj = double(j);
161  p3 = p2;
162  p2 = p1;
163  p1 = ((2.*jj + 1.)*z*p2 - jj*p3) / (jj + 1.);
164  }
165  pp = nn * (z*p1 - p2) / (z*z - 1.);
166  z1 = z;
167  z = z1 - p1 / pp;
168  } while( fabs(z - z1) >= 1.e-12);
169 
170  x[i] = xm - xl * z;
171  x[nPoints-1-i] = xm + xl * z;
172  w[i] = 2. * xl / ((1. - z*z) * pp*pp);
173  w[nPoints-1-i] = w[i];
174  }
175 }
176 
177 void
178 polynomialRootSolution::GauHerQ(double *x, double *w, const int nPoints) //-+ infinity
179 {
180  /* nPoints = number of base points */
181 
182  if( x == NULL ) _errorr( "Field for point positions must be allocated" );
183  if( w == NULL ) _errorr( "Field for weights must be allocated" );
184 
185  int i, j, m;
186  double p1, p2, p3, pp, z, z1;
187  double nn, jj, PIM4;
188 
189  PIM4 = pow(PI, -0.25);
190  z = 0.;
191  m = (nPoints+1) / 2;
192 
193  nn = (double)nPoints;
194  for( i = 1; i <= m; i++ )
195  {
196  if( i==1) {
197  z = sqrt(2.*nn + 1.) - 1.85575 * pow(2.*nn + 1., -0.16667);
198 
199  } else if( i==2 ) {
200  z -= 1.14*pow(nn, 0.426) / z;
201 
202  } else if( i==3 ) {
203  z = 1.86*z - 0.86 * x[1];
204 
205  } else if( i==4 ) {
206  z = 1.91*z - 0.91 * x[2];
207 
208  } else {
209  z = 2.0*z - x[i-2];
210  }
211 
212  do
213  {
214  p1 = PIM4;
215  p2 = 0.0;
216  for( j = 1; j <= nPoints; j++ )
217  {
218  jj = double(j);
219  p3 = p2;
220  p2 = p1;
221  p1 = z*sqrt(2./jj)*p2 - sqrt((jj-1.)/jj)*p3;
222  }
223  pp = sqrt(2.*nn) * p2;
224  z1 = z;
225  z = z1 - p1/pp;
226  } while (fabs(z-z1) >= 1.e-12);
227 
228  x[i-1] = z;
229  x[nPoints-i] = -z;
230  w[i-1] = 2.0 / (pp * pp);
231  w[nPoints-i] = w[i-1];
232  }
233 }
234 
235 } // end of namespace mumech
236 
237 /*end of file*/
double sgn(double i)
Returns the signum of given value (if value is < 0 returns -1, otherwise returns 1) ...
Definition: mathlib.h:42
Class polynomialRootSolution collects functions calculating the roots of polynomial functions...
#define PI
Definition: macros.h:71
std::complex< double > * GetCubicPolyRoots(double a, double b, double c, std::complex< double > *roots)
Function gives the analitical solution of cubic furmula of the real coefficients a, b, c x^3 + ax^2 + bx + c = 0.
#define CUB(a)
Definition: macros.h:98
The header file of usefull macros.
Collection of the functions of basic manipulations, some of them can be used instead of their counter...
#define _sgrt3div2_
#define ABS(a)
Definition: macros.h:118
static void GauLegF(double *x, double *w, const int nPoints, const double minLim, const double maxLim)
#define _MACHINE_EPS_
#define SQR(a)
Definition: macros.h:97
#define _errorr(_1)
Definition: gelib.h:160
Mathematic functions.
void CleanVector(double *a, long n)
Functin cleans a &#39;double&#39; vector, initialize each value being 0-zero.
static void GauHerQ(double *x, double *w, const int nPoints)
void e(int i)