Geant4  10.03.p01
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4JTPolynomialSolver Class Reference

#include <G4JTPolynomialSolver.hh>

Public Member Functions

 G4JTPolynomialSolver ()
 
 ~G4JTPolynomialSolver ()
 
G4int FindRoots (G4double *op, G4int degree, G4double *zeror, G4double *zeroi)
 

Detailed Description

Definition at line 70 of file G4JTPolynomialSolver.hh.

Constructor & Destructor Documentation

G4JTPolynomialSolver::G4JTPolynomialSolver ( )

Definition at line 48 of file G4JTPolynomialSolver.cc.

49  : sr(0.), si(0.), u(0.),v(0.),
50  a(0.), b(0.), c(0.), d(0.),
51  a1(0.), a3(0.), a7(0.),
52  e(0.), f(0.), g(0.), h(0.),
53  szr(0.), szi(0.), lzr(0.), lzi(0.),
54  n(0)
55 {
56 }
G4JTPolynomialSolver::~G4JTPolynomialSolver ( )

Definition at line 58 of file G4JTPolynomialSolver.cc.

59 {
60 }

Member Function Documentation

G4int G4JTPolynomialSolver::FindRoots ( G4double op,
G4int  degree,
G4double zeror,
G4double zeroi 
)

Definition at line 62 of file G4JTPolynomialSolver.cc.

64 {
65  G4double t=0.0, aa=0.0, bb=0.0, cc=0.0, factor=1.0;
66  G4double max=0.0, min=infin, xxx=0.0, x=0.0, sc=0.0, bnd=0.0;
67  G4double xm=0.0, ff=0.0, df=0.0, dx=0.0;
68  G4int cnt=0, nz=0, i=0, j=0, jj=0, l=0, nm1=0, zerok=0;
69  G4Pow* power = G4Pow::GetInstance();
70 
71  // Initialization of constants for shift rotation.
72  //
73  static const G4double xx = std::sqrt(0.5);
74  static const G4double rot = 94.0*deg;
75  static const G4double cosr = std::cos(rot),
76  sinr = std::sin(rot);
77  G4double xo = xx, yo = -xx;
78  n = degr;
79 
80  // Algorithm fails if the leading coefficient is zero.
81  //
82  if (!(op[0] != 0.0)) { return -1; }
83 
84  // Remove the zeros at the origin, if any.
85  //
86  while (!(op[n] != 0.0))
87  {
88  j = degr - n;
89  zeror[j] = 0.0;
90  zeroi[j] = 0.0;
91  n--;
92  }
93  if (n < 1) { return -1; }
94 
95  // Allocate buffers here
96  //
97  std::vector<G4double> temp(degr+1) ;
98  std::vector<G4double> pt(degr+1) ;
99 
100  p.assign(degr+1,0) ;
101  qp.assign(degr+1,0) ;
102  k.assign(degr+1,0) ;
103  qk.assign(degr+1,0) ;
104  svk.assign(degr+1,0) ;
105 
106  // Make a copy of the coefficients.
107  //
108  for (i=0;i<=n;i++)
109  { p[i] = op[i]; }
110 
111  do
112  {
113  if (n == 1) // Start the algorithm for one zero.
114  {
115  zeror[degr-1] = -p[1]/p[0];
116  zeroi[degr-1] = 0.0;
117  n -= 1;
118  return degr - n ;
119  }
120  if (n == 2) // Calculate the final zero or pair of zeros.
121  {
122  Quadratic(p[0],p[1],p[2],&zeror[degr-2],&zeroi[degr-2],
123  &zeror[degr-1],&zeroi[degr-1]);
124  n -= 2;
125  return degr - n ;
126  }
127 
128  // Find largest and smallest moduli of coefficients.
129  //
130  max = 0.0;
131  min = infin;
132  for (i=0;i<=n;i++)
133  {
134  x = std::fabs(p[i]);
135  if (x > max) { max = x; }
136  if (x != 0.0 && x < min) { min = x; }
137  }
138 
139  // Scale if there are large or very small coefficients.
140  // Computes a scale factor to multiply the coefficients of the
141  // polynomial. The scaling is done to avoid overflow and to
142  // avoid undetected underflow interfering with the convergence
143  // criterion. The factor is a power of the base.
144  //
145  sc = lo/min;
146 
147  if ( ((sc <= 1.0) && (max >= 10.0))
148  || ((sc > 1.0) && (infin/sc >= max))
149  || ((infin/sc >= max) && (max >= 10)) )
150  {
151  if (!( sc != 0.0 ))
152  { sc = smalno ; }
153  l = (G4int)(G4Log(sc)/G4Log(base) + 0.5);
154  factor = power->powN(base,l);
155  if (factor != 1.0)
156  {
157  for (i=0;i<=n;i++)
158  { p[i] = factor*p[i]; } // Scale polynomial.
159  }
160  }
161 
162  // Compute lower bound on moduli of roots.
163  //
164  for (i=0;i<=n;i++)
165  {
166  pt[i] = (std::fabs(p[i]));
167  }
168  pt[n] = - pt[n];
169 
170  // Compute upper estimate of bound.
171  //
172  x = G4Exp((G4Log(-pt[n])-G4Log(pt[0])) / (G4double)n);
173 
174  // If Newton step at the origin is better, use it.
175  //
176  if (pt[n-1] != 0.0)
177  {
178  xm = -pt[n]/pt[n-1];
179  if (xm < x) { x = xm; }
180  }
181 
182  // Chop the interval (0,x) until ff <= 0
183  //
184  while (1)
185  {
186  xm = x*0.1;
187  ff = pt[0];
188  for (i=1;i<=n;i++)
189  { ff = ff*xm + pt[i]; }
190  if (ff <= 0.0) { break; }
191  x = xm;
192  }
193  dx = x;
194 
195  // Do Newton interation until x converges to two decimal places.
196  //
197  while (std::fabs(dx/x) > 0.005)
198  {
199  ff = pt[0];
200  df = ff;
201  for (i=1;i<n;i++)
202  {
203  ff = ff*x + pt[i];
204  df = df*x + ff;
205  }
206  ff = ff*x + pt[n];
207  dx = ff/df;
208  x -= dx;
209  }
210  bnd = x;
211 
212  // Compute the derivative as the initial k polynomial
213  // and do 5 steps with no shift.
214  //
215  nm1 = n - 1;
216  for (i=1;i<n;i++)
217  { k[i] = (G4double)(n-i)*p[i]/(G4double)n; }
218  k[0] = p[0];
219  aa = p[n];
220  bb = p[n-1];
221  zerok = (k[n-1] == 0);
222  for(jj=0;jj<5;jj++)
223  {
224  cc = k[n-1];
225  if (!zerok) // Use a scaled form of recurrence if k at 0 is nonzero.
226  {
227  // Use a scaled form of recurrence if value of k at 0 is nonzero.
228  //
229  t = -aa/cc;
230  for (i=0;i<nm1;i++)
231  {
232  j = n-i-1;
233  k[j] = t*k[j-1]+p[j];
234  }
235  k[0] = p[0];
236  zerok = (std::fabs(k[n-1]) <= std::fabs(bb)*eta*10.0);
237  }
238  else // Use unscaled form of recurrence.
239  {
240  for (i=0;i<nm1;i++)
241  {
242  j = n-i-1;
243  k[j] = k[j-1];
244  }
245  k[0] = 0.0;
246  zerok = (!(k[n-1] != 0.0));
247  }
248  }
249 
250  // Save k for restarts with new shifts.
251  //
252  for (i=0;i<n;i++)
253  { temp[i] = k[i]; }
254 
255  // Loop to select the quadratic corresponding to each new shift.
256  //
257  for (cnt = 0;cnt < 20;cnt++)
258  {
259  // Quadratic corresponds to a double shift to a
260  // non-real point and its complex conjugate. The point
261  // has modulus bnd and amplitude rotated by 94 degrees
262  // from the previous shift.
263  //
264  xxx = cosr*xo - sinr*yo;
265  yo = sinr*xo + cosr*yo;
266  xo = xxx;
267  sr = bnd*xo;
268  si = bnd*yo;
269  u = -2.0 * sr;
270  v = bnd;
271  ComputeFixedShiftPolynomial(20*(cnt+1),&nz);
272  if (nz != 0)
273  {
274  // The second stage jumps directly to one of the third
275  // stage iterations and returns here if successful.
276  // Deflate the polynomial, store the zero or zeros and
277  // return to the main algorithm.
278  //
279  j = degr - n;
280  zeror[j] = szr;
281  zeroi[j] = szi;
282  n -= nz;
283  for (i=0;i<=n;i++)
284  { p[i] = qp[i]; }
285  if (nz != 1)
286  {
287  zeror[j+1] = lzr;
288  zeroi[j+1] = lzi;
289  }
290  break;
291  }
292  else
293  {
294  // If the iteration is unsuccessful another quadratic
295  // is chosen after restoring k.
296  //
297  for (i=0;i<n;i++)
298  {
299  k[i] = temp[i];
300  }
301  }
302  }
303  }
304  while (nz != 0); // End of initial DO loop
305 
306  // Return with failure if no convergence with 20 shifts.
307  //
308  return degr - n;
309 }
static G4Pow * GetInstance()
Definition: G4Pow.cc:55
G4double powN(G4double x, G4int n) const
Definition: G4Pow.cc:128
Definition: G4Pow.hh:56
const char * p
Definition: xmltok.h:285
const XML_Char int const XML_Char int const XML_Char * base
Definition: expat.h:331
int G4int
Definition: G4Types.hh:78
static ulg bb
Definition: csz_inflate.cc:344
G4double G4Log(G4double x)
Definition: G4Log.hh:230
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition: G4Exp.hh:183
T max(const T t1, const T t2)
brief Return the largest of the two arguments
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
double G4double
Definition: G4Types.hh:76
static constexpr double deg
Definition: G4SIunits.hh:152

Here is the call graph for this function:

Here is the caller graph for this function:


The documentation for this class was generated from the following files: