source: trunk/source/global/HEPNumerics/src/G4AnalyticalPolSolver.cc @ 1202

Last change on this file since 1202 was 1058, checked in by garnier, 15 years ago

file release beta

File size: 10.3 KB
Line 
1//
2// ********************************************************************
3// * License and Disclaimer                                           *
4// *                                                                  *
5// * The  Geant4 software  is  copyright of the Copyright Holders  of *
6// * the Geant4 Collaboration.  It is provided  under  the terms  and *
7// * conditions of the Geant4 Software License,  included in the file *
8// * LICENSE and available at  http://cern.ch/geant4/license .  These *
9// * include a list of copyright holders.                             *
10// *                                                                  *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work  make  any representation or  warranty, express or implied, *
14// * regarding  this  software system or assume any liability for its *
15// * use.  Please see the license in the file  LICENSE  and URL above *
16// * for the full disclaimer and the limitation of liability.         *
17// *                                                                  *
18// * This  code  implementation is the result of  the  scientific and *
19// * technical work of the GEANT4 collaboration.                      *
20// * By using,  copying,  modifying or  distributing the software (or *
21// * any work based  on the software)  you  agree  to acknowledge its *
22// * use  in  resulting  scientific  publications,  and indicate your *
23// * acceptance of all terms of the Geant4 Software license.          *
24// ********************************************************************
25//
26//
27// $Id: G4AnalyticalPolSolver.cc,v 1.7 2007/11/13 17:35:06 gcosmo Exp $
28// GEANT4 tag $Name: geant4-09-02-ref-02 $
29//
30
31#include  "globals.hh"
32#include  <complex>
33
34#include "G4AnalyticalPolSolver.hh"
35
36//////////////////////////////////////////////////////////////////////////////
37
38G4AnalyticalPolSolver::G4AnalyticalPolSolver() {;}
39
40//////////////////////////////////////////////////////////////////////////////
41
42G4AnalyticalPolSolver::~G4AnalyticalPolSolver() {;}
43
44//////////////////////////////////////////////////////////////////////////////
45//
46// Array r[3][5]  p[5]
47// Roots of poly p[0] x^2 + p[1] x+p[2]=0
48//
49// x = r[1][k] + i r[2][k];  k = 1, 2
50
51G4int G4AnalyticalPolSolver::QuadRoots( G4double p[5], G4double r[3][5] )
52{
53  G4double b, c, d2, d;
54
55  b  = -p[1]/p[0]/2.;
56  c  =  p[2]/p[0];
57  d2 =  b*b - c;
58 
59  if( d2 >= 0. )
60  {
61    d       = std::sqrt(d2);
62    r[1][1] = b - d;   
63    r[1][2] = b + d;   
64    r[2][1] = 0.; 
65    r[2][2] = 0.;
66  }
67  else
68  {
69    d       = std::sqrt(-d2);
70    r[2][1] =  d; 
71    r[2][2] = -d;
72    r[1][1] =  b; 
73    r[1][2] =  b;
74  }
75
76  return 2;
77}
78
79//////////////////////////////////////////////////////////////////////////////
80//
81// Array r[3][5]  p[5]
82// Roots of poly p[0] x^3 + p[1] x^2...+p[3]=0
83// x=r[1][k] + i r[2][k]  k=1,...,3
84// Assumes 0<arctan(x)<pi/2 for x>0
85
86G4int G4AnalyticalPolSolver::CubicRoots( G4double p[5], G4double r[3][5] )
87{
88  G4double x,t,b,c,d;
89  G4int k;
90
91  if( p[0] != 1. )
92  {
93    for(k = 1; k < 4; k++ ) { p[k] = p[k]/p[0]; }
94    p[0] = 1.;
95  }
96  x = p[1]/3.0; 
97  t = x*p[1];
98  b = 0.5*( x*( t/1.5 - p[2] ) + p[3] ); 
99  t = ( t - p[2] )/3.0;
100  c = t*t*t; 
101  d = b*b - c;
102
103  if( d >= 0. )
104  {
105    d = std::pow( (std::sqrt(d) + std::fabs(b) ), 1.0/3.0 );
106   
107    if( d != 0. )
108    {
109       if( b > 0. ) { b = -d; }
110       else         { b =  d; }
111       c =  t/b;
112    }
113    d       =  std::sqrt(0.75)*(b - c); 
114    r[2][2] =  d; 
115    b       =  b + c;
116    c       = -0.5*b-x;
117    r[1][2] =  c;
118
119    if( ( b > 0. &&  x <= 0. ) || ( b < 0. && x > 0. ) )
120    {
121       r[1][1] =  c; 
122       r[2][1] = -d; 
123       r[1][3] =  b - x;
124       r[2][3] =  0;
125    }
126    else
127    {
128       r[1][1] =  b - x; 
129       r[2][1] =  0.; 
130       r[1][3] =  c;
131       r[2][3] = -d;
132    }
133  }              // end of 2 equal or complex roots
134  else
135  {
136    if( b == 0. ) { d =  std::atan(1.0)/1.5; }
137    else          { d =  std::atan( std::sqrt(-d)/std::fabs(b) )/3.0; }
138
139    if( b < 0. )  { b =  std::sqrt(t)*2.0; }
140    else          { b = -2.0*std::sqrt(t); }
141
142    c =  std::cos(d)*b; 
143    t = -std::sqrt(0.75)*std::sin(d)*b - 0.5*c;
144    d = -t - c - x; 
145    c =  c - x; 
146    t =  t - x;
147
148    if( std::fabs(c) > std::fabs(t) ) { r[1][3] = c; }
149    else
150    {
151      r[1][3] = t; 
152      t       = c;
153    }
154    if( std::fabs(d) > std::fabs(t) ) { r[1][2] = d; }
155    else
156    {
157      r[1][2] = t; 
158      t       = d;
159    }
160    r[1][1] = t;
161
162    for(k = 1; k < 4; k++ ) { r[2][k] = 0.; }
163  }
164  return 0;
165}
166
167//////////////////////////////////////////////////////////////////////////////
168//
169// Array r[3][5]  p[5]
170// Roots of poly p[0] x^4 + p[1] x^3...+p[4]=0
171// x=r[1][k] + i r[2][k]  k=1,...,4
172
173G4int G4AnalyticalPolSolver::BiquadRoots( G4double p[5], G4double r[3][5] )
174{
175  G4double a, b, c, d, e;
176  G4int i, k, j, noRoots;
177
178  if(p[0] != 1.0)
179  {
180    for( k = 1; k < 5; k++) { p[k] = p[k]/p[0]; }
181    p[0] = 1.;
182  }
183  e = 0.25*p[1];
184  b = 2*e;
185  c = b*b;
186  d = 0.75*c;
187  b = p[3] + b*( c - p[2] );
188  a = p[2] - d;
189  c = p[4] + e*( e*a - p[3] );
190  a = a - d;
191
192  p[1] = 0.5*a;
193  p[2] = (p[1]*p[1]-c)*0.25;
194  p[3] = b*b/(-64.0);
195
196  if( p[3] < 0. )
197  {
198    noRoots = CubicRoots(p,r);
199
200    for( k = 1; k < 4; k++ )
201    {
202      if( r[2][k] == 0. && r[1][k] > 0 )
203      {
204        d = r[1][k]*4; 
205        a = a + d;
206
207        if     ( a >= 0. && b >= 0.) { p[1] =  std::sqrt(d); }
208        else if( a <= 0. && b <= 0.) { p[1] =  std::sqrt(d); }
209        else                         { p[1] = -std::sqrt(d); }
210
211        b = 0.5*( a + b/p[1] );
212
213        p[2]    = c/b; 
214        noRoots = QuadRoots(p,r);
215
216        for( i = 1; i < 3; i++ )
217        {
218          for( j = 1; j < 3; j++ ) { r[j][i+2] = r[j][i]; }
219        }
220        p[1]    = -p[1]; 
221        p[2]    =  b; 
222        noRoots = QuadRoots(p,r);
223
224        for( i = 1; i < 5; i++ ) { r[1][i] = r[1][i] - e; }
225
226        return 4;
227      }
228    }
229  }
230  if( p[2] < 0. )
231  {
232    b    = std::sqrt(c); 
233    d    = b + b - a;
234    p[1] = 0.; 
235   
236    if( d > 0. ) { p[1] = std::sqrt(d); }
237  }
238  else
239  {
240    if( p[1] > 0.) { b =  std::sqrt(p[2])*2.0 + p[1]; }
241    else           { b = -std::sqrt(p[2])*2.0 + p[1]; }
242
243    if( b != 0.) { p[1] = 0; }
244    else
245    {
246      for(k = 1; k < 5; k++ )
247      {
248          r[1][k] = -e;
249          r[2][k] =  0;
250      }
251      return 0;
252    }
253  }
254
255  p[2]    = c/b; 
256  noRoots = QuadRoots(p,r);
257
258  for( k = 1; k < 3; k++ )
259  {
260    for( j = 1; j < 3; j++ ) { r[j][k+2] = r[j][k]; }
261  }
262  p[1]    = -p[1]; 
263  p[2]    =  b; 
264  noRoots = QuadRoots(p,r);
265
266  for( k = 1; k < 5; k++ ) { r[1][k] = r[1][k] - e; }
267
268  return 4;
269}
270
271//////////////////////////////////////////////////////////////////////////////
272
273G4int G4AnalyticalPolSolver::QuarticRoots( G4double p[5], G4double r[3][5])
274{
275  G4double a0, a1, a2, a3, y1;
276  G4double R2, D2, E2, D, E, R = 0.;
277  G4double a, b, c, d, ds;
278
279  G4double reRoot[4];
280  G4int k, noRoots, noReRoots = 0;
281 
282  for( k = 0; k < 4; k++ ) { reRoot[k] = DBL_MAX; }
283
284  if( p[0] != 1.0 )
285  {
286    for( k = 1; k < 5; k++) { p[k] = p[k]/p[0]; }
287    p[0] = 1.;
288  }
289  a3 = p[1];
290  a2 = p[2];
291  a1 = p[3];
292  a0 = p[4];
293
294  // resolvent cubic equation cofs:
295
296  p[1] = -a2;
297  p[2] = a1*a3 - 4*a0;
298  p[3] = 4*a2*a0 - a1*a1 - a3*a3*a0;
299
300  noRoots = CubicRoots(p,r);
301
302  for( k = 1; k < 4; k++ )
303  {
304    if( r[2][k] == 0. ) // find a real root
305    {
306      noReRoots++;
307      reRoot[k] = r[1][k];
308    }
309    else reRoot[k] = DBL_MAX; // kInfinity;
310  }
311  y1 = DBL_MAX; // kInfinity; 
312  for( k = 1; k < 4; k++ )
313  {
314    if ( reRoot[k] < y1 ) { y1 = reRoot[k]; }
315  }
316
317  R2 = 0.25*a3*a3 - a2 + y1;
318  b  = 0.25*(4*a3*a2 - 8*a1 - a3*a3*a3);
319  c  = 0.75*a3*a3 - 2*a2;
320  a  = c - R2;
321  d  = 4*y1*y1 - 16*a0;
322
323  if( R2 > 0.)
324  {
325    R = std::sqrt(R2);
326    D2 = a + b/R;
327    E2 = a - b/R;
328
329    if( D2 >= 0. )
330    {
331      D       = std::sqrt(D2);
332      r[1][1] = -0.25*a3 + 0.5*R + 0.5*D;
333      r[1][2] = -0.25*a3 + 0.5*R - 0.5*D;
334      r[2][1] = 0.;
335      r[2][2] = 0.;
336    }
337    else
338    {
339      D       = std::sqrt(-D2);
340      r[1][1] = -0.25*a3 + 0.5*R;
341      r[1][2] = -0.25*a3 + 0.5*R;
342      r[2][1] =  0.5*D;
343      r[2][2] = -0.5*D;
344    }
345    if( E2 >= 0. )
346    {
347      E       = std::sqrt(E2);
348      r[1][3] = -0.25*a3 - 0.5*R + 0.5*E;
349      r[1][4] = -0.25*a3 - 0.5*R - 0.5*E;
350      r[2][3] = 0.;
351      r[2][4] = 0.;
352    }
353    else
354    {
355      E       = std::sqrt(-E2);
356      r[1][3] = -0.25*a3 - 0.5*R;
357      r[1][4] = -0.25*a3 - 0.5*R;
358      r[2][3] =  0.5*E;
359      r[2][4] = -0.5*E;
360    }
361  }
362  else if( R2 < 0.)
363  {
364    R = std::sqrt(-R2);
365    G4complex CD2(a,-b/R);
366    G4complex CD = std::sqrt(CD2);
367
368    r[1][1] = -0.25*a3 + 0.5*real(CD);
369    r[1][2] = -0.25*a3 - 0.5*real(CD);
370    r[2][1] =  0.5*R + 0.5*imag(CD);
371    r[2][2] =  0.5*R - 0.5*imag(CD);
372    G4complex CE2(a,b/R);
373    G4complex CE = std::sqrt(CE2);
374
375    r[1][3] = -0.25*a3 + 0.5*real(CE);
376    r[1][4] = -0.25*a3 - 0.5*real(CE);
377    r[2][3] =  -0.5*R + 0.5*imag(CE);
378    r[2][4] =  -0.5*R - 0.5*imag(CE);
379  }
380  else // R2=0 case
381  {
382    if(d >= 0.)
383    {
384      D2 = c + std::sqrt(d);
385      E2 = c - std::sqrt(d);
386
387      if( D2 >= 0. )
388      {
389        D       = std::sqrt(D2);
390        r[1][1] = -0.25*a3 + 0.5*R + 0.5*D;
391        r[1][2] = -0.25*a3 + 0.5*R - 0.5*D;
392        r[2][1] = 0.;
393        r[2][2] = 0.;
394      }
395      else
396      {
397        D       = std::sqrt(-D2);
398        r[1][1] = -0.25*a3 + 0.5*R;
399        r[1][2] = -0.25*a3 + 0.5*R;
400        r[2][1] =  0.5*D;
401        r[2][2] = -0.5*D;
402      }
403      if( E2 >= 0. )
404      {
405        E       = std::sqrt(E2);
406        r[1][3] = -0.25*a3 - 0.5*R + 0.5*E;
407        r[1][4] = -0.25*a3 - 0.5*R - 0.5*E;
408        r[2][3] = 0.;
409        r[2][4] = 0.;
410      }
411      else
412      {
413        E       = std::sqrt(-E2);
414        r[1][3] = -0.25*a3 - 0.5*R;
415        r[1][4] = -0.25*a3 - 0.5*R;
416        r[2][3] =  0.5*E;
417        r[2][4] = -0.5*E;
418      }
419    }
420    else
421    {
422      ds = std::sqrt(-d);
423      G4complex CD2(c,ds);
424      G4complex CD = std::sqrt(CD2);
425
426      r[1][1] = -0.25*a3 + 0.5*real(CD);
427      r[1][2] = -0.25*a3 - 0.5*real(CD);
428      r[2][1] =  0.5*R + 0.5*imag(CD);
429      r[2][2] =  0.5*R - 0.5*imag(CD);
430
431      G4complex CE2(c,-ds);
432      G4complex CE = std::sqrt(CE2);
433
434      r[1][3] = -0.25*a3 + 0.5*real(CE);
435      r[1][4] = -0.25*a3 - 0.5*real(CE);
436      r[2][3] =  -0.5*R + 0.5*imag(CE);
437      r[2][4] =  -0.5*R - 0.5*imag(CE);
438    } 
439  }
440  return 4;
441}
442
443//
444//
445//////////////////////////////////////////////////////////////////////////////
Note: See TracBrowser for help on using the repository browser.