Geant4.10
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Public Member Functions
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 47 of file G4JTPolynomialSolver.cc.

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

Definition at line 57 of file G4JTPolynomialSolver.cc.

58 {
59 }

Member Function Documentation

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

Definition at line 61 of file G4JTPolynomialSolver.cc.

References python.hepunit::deg, G4INCL::Math::max(), G4INCL::Math::min(), and test::x.

Referenced by G4TwistBoxSide::DistanceToSurface(), G4TwistTrapParallelSide::DistanceToSurface(), and G4TwistTrapAlphaSide::DistanceToSurface().

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

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