Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
G4JTPolynomialSolver.cc
Go to the documentation of this file.
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// $Id$
27//
28// --------------------------------------------------------------------
29// GEANT 4 class source file
30//
31// G4JTPolynomialSolver
32//
33// Implementation based on Jenkins-Traub algorithm.
34// --------------------------------------------------------------------
35
37#include "G4SystemOfUnits.hh"
38
39const G4double G4JTPolynomialSolver::base = 2;
40const G4double G4JTPolynomialSolver::eta = DBL_EPSILON;
41const G4double G4JTPolynomialSolver::infin = DBL_MAX;
42const G4double G4JTPolynomialSolver::smalno = DBL_MIN;
43const G4double G4JTPolynomialSolver::are = DBL_EPSILON;
44const G4double G4JTPolynomialSolver::mre = DBL_EPSILON;
45const G4double G4JTPolynomialSolver::lo = DBL_MIN/DBL_EPSILON ;
46
48 : sr(0.), si(0.), u(0.),v(0.),
49 a(0.), b(0.), c(0.), d(0.),
50 a1(0.), a2(0.), a3(0.), a6(0.), a7(0.),
51 e(0.), f(0.), g(0.), h(0.),
52 szr(0.), szi(0.), lzr(0.), lzi(0.),
53 n(0), nmi(0)
54{
55}
56
58{
59}
60
62 G4double *zeror, G4double *zeroi)
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}
308
309void G4JTPolynomialSolver::ComputeFixedShiftPolynomial(G4int l2, G4int *nz)
310{
311 // Computes up to L2 fixed shift k-polynomials, testing for convergence
312 // in the linear or quadratic case. Initiates one of the variable shift
313 // iterations and returns with the number of zeros found.
314
315 G4double svu=0.0, svv=0.0, ui=0.0, vi=0.0, xs=0.0;
316 G4double betas=0.25, betav=0.25, oss=sr, ovv=v,
317 ss=0.0, vv=0.0, ts=1.0, tv=1.0;
318 G4double ots=0.0, otv=0.0;
319 G4double tvv=1.0, tss=1.0;
320 G4int type=0, i=0, j=0, iflag=0, vpass=0, spass=0, vtry=0, stry=0;
321
322 *nz = 0;
323
324 // Evaluate polynomial by synthetic division.
325 //
326 QuadraticSyntheticDivision(n,&u,&v,p,qp,&a,&b);
327 ComputeScalarFactors(&type);
328 for (j=0;j<l2;j++)
329 {
330 // Calculate next k polynomial and estimate v.
331 //
332 ComputeNextPolynomial(&type);
333 ComputeScalarFactors(&type);
334 ComputeNewEstimate(type,&ui,&vi);
335 vv = vi;
336
337 // Estimate xs.
338 //
339 ss = 0.0;
340 if (k[n-1] != 0.0) { ss = -p[n]/k[n-1]; }
341 tv = 1.0;
342 ts = 1.0;
343 if (j == 0 || type == 3)
344 {
345 ovv = vv;
346 oss = ss;
347 otv = tv;
348 ots = ts;
349 continue;
350 }
351
352 // Compute relative measures of convergence of xs and v sequences.
353 //
354 if (vv != 0.0) { tv = std::fabs((vv-ovv)/vv); }
355 if (ss != 0.0) { ts = std::fabs((ss-oss)/ss); }
356
357 // If decreasing, multiply two most recent convergence measures.
358 tvv = 1.0;
359 if (tv < otv) { tvv = tv*otv; }
360 tss = 1.0;
361 if (ts < ots) { tss = ts*ots; }
362
363 // Compare with convergence criteria.
364 vpass = (tvv < betav);
365 spass = (tss < betas);
366 if (!(spass || vpass))
367 {
368 ovv = vv;
369 oss = ss;
370 otv = tv;
371 ots = ts;
372 continue;
373 }
374
375 // At least one sequence has passed the convergence test.
376 // Store variables before iterating.
377 //
378 svu = u;
379 svv = v;
380 for (i=0;i<n;i++)
381 {
382 svk[i] = k[i];
383 }
384 xs = ss;
385
386 // Choose iteration according to the fastest converging sequence.
387 //
388 vtry = 0;
389 stry = 0;
390 if ((spass && (!vpass)) || (tss < tvv))
391 {
392 RealPolynomialIteration(&xs,nz,&iflag);
393 if (*nz > 0) { return; }
394
395 // Linear iteration has failed. Flag that it has been
396 // tried and decrease the convergence criterion.
397 //
398 stry = 1;
399 betas *=0.25;
400 if (iflag == 0) { goto _restore_variables; }
401
402 // If linear iteration signals an almost double real
403 // zero attempt quadratic iteration.
404 //
405 ui = -(xs+xs);
406 vi = xs*xs;
407 }
408
409_quadratic_iteration:
410
411 do
412 {
413 QuadraticPolynomialIteration(&ui,&vi,nz);
414 if (*nz > 0) { return; }
415
416 // Quadratic iteration has failed. Flag that it has
417 // been tried and decrease the convergence criterion.
418 //
419 vtry = 1;
420 betav *= 0.25;
421
422 // Try linear iteration if it has not been tried and
423 // the S sequence is converging.
424 //
425 if (stry || !spass) { break; }
426 for (i=0;i<n;i++)
427 {
428 k[i] = svk[i];
429 }
430 RealPolynomialIteration(&xs,nz,&iflag);
431 if (*nz > 0) { return; }
432
433 // Linear iteration has failed. Flag that it has been
434 // tried and decrease the convergence criterion.
435 //
436 stry = 1;
437 betas *=0.25;
438 if (iflag == 0) { break; }
439
440 // If linear iteration signals an almost double real
441 // zero attempt quadratic iteration.
442 //
443 ui = -(xs+xs);
444 vi = xs*xs;
445 }
446 while (iflag != 0);
447
448 // Restore variables.
449
450_restore_variables:
451
452 u = svu;
453 v = svv;
454 for (i=0;i<n;i++)
455 {
456 k[i] = svk[i];
457 }
458
459 // Try quadratic iteration if it has not been tried
460 // and the V sequence is converging.
461 //
462 if (vpass && !vtry) { goto _quadratic_iteration; }
463
464 // Recompute QP and scalar values to continue the
465 // second stage.
466 //
467 QuadraticSyntheticDivision(n,&u,&v,p,qp,&a,&b);
468 ComputeScalarFactors(&type);
469
470 ovv = vv;
471 oss = ss;
472 otv = tv;
473 ots = ts;
474 }
475}
476
477void G4JTPolynomialSolver::
478QuadraticPolynomialIteration(G4double *uu, G4double *vv, G4int *nz)
479{
480 // Variable-shift k-polynomial iteration for a
481 // quadratic factor converges only if the zeros are
482 // equimodular or nearly so.
483 // uu, vv - coefficients of starting quadratic.
484 // nz - number of zeros found.
485 //
486 G4double ui=0.0, vi=0.0;
487 G4double omp=0.0;
488 G4double relstp=0.0;
489 G4double mp=0.0, ee=0.0, t=0.0, zm=0.0;
490 G4int type=0, i=1, j=0, tried=0;
491
492 *nz = 0;
493 tried = 0;
494 u = *uu;
495 v = *vv;
496
497 // Main loop.
498
499 while (1)
500 {
501 Quadratic(1.0,u,v,&szr,&szi,&lzr,&lzi);
502
503 // Return if roots of the quadratic are real and not
504 // close to multiple or nearly equal and of opposite
505 // sign.
506 //
507 if (std::fabs(std::fabs(szr)-std::fabs(lzr)) > 0.01 * std::fabs(lzr))
508 { return; }
509
510 // Evaluate polynomial by quadratic synthetic division.
511 //
512 QuadraticSyntheticDivision(n,&u,&v,p,qp,&a,&b);
513 mp = std::fabs(a-szr*b) + std::fabs(szi*b);
514
515 // Compute a rigorous bound on the rounding error in evaluating p.
516 //
517 zm = std::sqrt(std::fabs(v));
518 ee = 2.0*std::fabs(qp[0]);
519 t = -szr*b;
520 for (i=1;i<n;i++)
521 {
522 ee = ee*zm + std::fabs(qp[i]);
523 }
524 ee = ee*zm + std::fabs(a+t);
525 ee *= (5.0 *mre + 4.0*are);
526 ee = ee - (5.0*mre+2.0*are)*(std::fabs(a+t)+std::fabs(b)*zm)
527 + 2.0*are*std::fabs(t);
528
529 // Iteration has converged sufficiently if the
530 // polynomial value is less than 20 times this bound.
531 //
532 if (mp <= 20.0*ee)
533 {
534 *nz = 2;
535 return;
536 }
537 j++;
538
539 // Stop iteration after 20 steps.
540 //
541 if (j > 20) { return; }
542 if (j >= 2)
543 {
544 if (!(relstp > 0.01 || mp < omp || tried))
545 {
546 // A cluster appears to be stalling the convergence.
547 // Five fixed shift steps are taken with a u,v close to the cluster.
548 //
549 if (relstp < eta) { relstp = eta; }
550 relstp = std::sqrt(relstp);
551 u = u - u*relstp;
552 v = v + v*relstp;
553 QuadraticSyntheticDivision(n,&u,&v,p,qp,&a,&b);
554 for (i=0;i<5;i++)
555 {
556 ComputeScalarFactors(&type);
557 ComputeNextPolynomial(&type);
558 }
559 tried = 1;
560 j = 0;
561 }
562 }
563 omp = mp;
564
565 // Calculate next k polynomial and new u and v.
566 //
567 ComputeScalarFactors(&type);
568 ComputeNextPolynomial(&type);
569 ComputeScalarFactors(&type);
570 ComputeNewEstimate(type,&ui,&vi);
571
572 // If vi is zero the iteration is not converging.
573 //
574 if (!(vi != 0.0)) { return; }
575 relstp = std::fabs((vi-v)/vi);
576 u = ui;
577 v = vi;
578 }
579}
580
581void G4JTPolynomialSolver::
582RealPolynomialIteration(G4double *sss, G4int *nz, G4int *iflag)
583{
584 // Variable-shift H polynomial iteration for a real zero.
585 // sss - starting iterate
586 // nz - number of zeros found
587 // iflag - flag to indicate a pair of zeros near real axis.
588
589 G4double t=0.;
590 G4double omp=0.;
591 G4double pv=0.0, kv=0.0, xs= *sss;
592 G4double mx=0.0, mp=0.0, ee=0.0;
593 G4int i=1, j=0;
594
595 *nz = 0;
596 *iflag = 0;
597
598 // Main loop
599 //
600 while (1)
601 {
602 pv = p[0];
603
604 // Evaluate p at xs.
605 //
606 qp[0] = pv;
607 for (i=1;i<=n;i++)
608 {
609 pv = pv*xs + p[i];
610 qp[i] = pv;
611 }
612 mp = std::fabs(pv);
613
614 // Compute a rigorous bound on the error in evaluating p.
615 //
616 mx = std::fabs(xs);
617 ee = (mre/(are+mre))*std::fabs(qp[0]);
618 for (i=1;i<=n;i++)
619 {
620 ee = ee*mx + std::fabs(qp[i]);
621 }
622
623 // Iteration has converged sufficiently if the polynomial
624 // value is less than 20 times this bound.
625 //
626 if (mp <= 20.0*((are+mre)*ee-mre*mp))
627 {
628 *nz = 1;
629 szr = xs;
630 szi = 0.0;
631 return;
632 }
633 j++;
634
635 // Stop iteration after 10 steps.
636 //
637 if (j > 10) { return; }
638 if (j >= 2)
639 {
640 if (!(std::fabs(t) > 0.001*std::fabs(xs-t) || mp < omp))
641 {
642 // A cluster of zeros near the real axis has been encountered.
643 // Return with iflag set to initiate a quadratic iteration.
644 //
645 *iflag = 1;
646 *sss = xs;
647 return;
648 } // Return if the polynomial value has increased significantly.
649 }
650
651 omp = mp;
652
653 // Compute t, the next polynomial, and the new iterate.
654 //
655 kv = k[0];
656 qk[0] = kv;
657 for (i=1;i<n;i++)
658 {
659 kv = kv*xs + k[i];
660 qk[i] = kv;
661 }
662 if (std::fabs(kv) <= std::fabs(k[n-1])*10.0*eta) // Use unscaled form.
663 {
664 k[0] = 0.0;
665 for (i=1;i<n;i++)
666 {
667 k[i] = qk[i-1];
668 }
669 }
670 else // Use the scaled form of the recurrence if k at xs is nonzero.
671 {
672 t = -pv/kv;
673 k[0] = qp[0];
674 for (i=1;i<n;i++)
675 {
676 k[i] = t*qk[i-1] + qp[i];
677 }
678 }
679 kv = k[0];
680 for (i=1;i<n;i++)
681 {
682 kv = kv*xs + k[i];
683 }
684 t = 0.0;
685 if (std::fabs(kv) > std::fabs(k[n-1]*10.0*eta)) { t = -pv/kv; }
686 xs += t;
687 }
688}
689
690void G4JTPolynomialSolver::ComputeScalarFactors(G4int *type)
691{
692 // This function calculates scalar quantities used to
693 // compute the next k polynomial and new estimates of
694 // the quadratic coefficients.
695 // type - integer variable set here indicating how the
696 // calculations are normalized to avoid overflow.
697
698 // Synthetic division of k by the quadratic 1,u,v
699 //
700 QuadraticSyntheticDivision(n-1,&u,&v,k,qk,&c,&d);
701 if (std::fabs(c) <= std::fabs(k[n-1]*100.0*eta))
702 {
703 if (std::fabs(d) <= std::fabs(k[n-2]*100.0*eta))
704 {
705 *type = 3; // Type=3 indicates the quadratic is almost a factor of k.
706 return;
707 }
708 }
709
710 if (std::fabs(d) < std::fabs(c))
711 {
712 *type = 1; // Type=1 indicates that all formulas are divided by c.
713 e = a/c;
714 f = d/c;
715 g = u*e;
716 h = v*b;
717 a3 = a*e + (h/c+g)*b;
718 a1 = b - a*(d/c);
719 a7 = a + g*d + h*f;
720 return;
721 }
722 *type = 2; // Type=2 indicates that all formulas are divided by d.
723 e = a/d;
724 f = c/d;
725 g = u*b;
726 h = v*b;
727 a3 = (a+g)*e + h*(b/d);
728 a1 = b*f-a;
729 a7 = (f+u)*a + h;
730}
731
732void G4JTPolynomialSolver::ComputeNextPolynomial(G4int *type)
733{
734 // Computes the next k polynomials using scalars
735 // computed in ComputeScalarFactors.
736
737 G4int i=2;
738
739 if (*type == 3) // Use unscaled form of the recurrence if type is 3.
740 {
741 k[0] = 0.0;
742 k[1] = 0.0;
743 for (i=2;i<n;i++)
744 {
745 k[i] = qk[i-2];
746 }
747 return;
748 }
749 G4double temp = a;
750 if (*type == 1) { temp = b; }
751 if (std::fabs(a1) <= std::fabs(temp)*eta*10.0)
752 {
753 // If a1 is nearly zero then use a special form of the recurrence.
754 //
755 k[0] = 0.0;
756 k[1] = -a7*qp[0];
757 for(i=2;i<n;i++)
758 {
759 k[i] = a3*qk[i-2] - a7*qp[i-1];
760 }
761 return;
762 }
763
764 // Use scaled form of the recurrence.
765 //
766 a7 /= a1;
767 a3 /= a1;
768 k[0] = qp[0];
769 k[1] = qp[1] - a7*qp[0];
770 for (i=2;i<n;i++)
771 {
772 k[i] = a3*qk[i-2] - a7*qp[i-1] + qp[i];
773 }
774}
775
776void G4JTPolynomialSolver::
777ComputeNewEstimate(G4int type, G4double *uu, G4double *vv)
778{
779 // Compute new estimates of the quadratic coefficients
780 // using the scalars computed in calcsc.
781
782 G4double a4=0.0, a5=0.0, b1=0.0, b2=0.0,
783 c1=0.0, c2=0.0, c3=0.0, c4=0.0, temp=0.0;
784
785 // Use formulas appropriate to setting of type.
786 //
787 if (type == 3) // If type=3 the quadratic is zeroed.
788 {
789 *uu = 0.0;
790 *vv = 0.0;
791 return;
792 }
793 if (type == 2)
794 {
795 a4 = (a+g)*f + h;
796 a5 = (f+u)*c + v*d;
797 }
798 else
799 {
800 a4 = a + u*b +h*f;
801 a5 = c + (u+v*f)*d;
802 }
803
804 // Evaluate new quadratic coefficients.
805 //
806 b1 = -k[n-1]/p[n];
807 b2 = -(k[n-2]+b1*p[n-1])/p[n];
808 c1 = v*b2*a1;
809 c2 = b1*a7;
810 c3 = b1*b1*a3;
811 c4 = c1 - c2 - c3;
812 temp = a5 + b1*a4 - c4;
813 if (!(temp != 0.0))
814 {
815 *uu = 0.0;
816 *vv = 0.0;
817 return;
818 }
819 *uu = u - (u*(c3+c2)+v*(b1*a1+b2*a7))/temp;
820 *vv = v*(1.0+c4/temp);
821 return;
822}
823
824void G4JTPolynomialSolver::
825QuadraticSyntheticDivision(G4int nn, G4double *uu, G4double *vv,
826 std::vector<G4double> &pp, std::vector<G4double> &qq,
827 G4double *aa, G4double *bb)
828{
829 // Divides pp by the quadratic 1,uu,vv placing the quotient
830 // in qq and the remainder in aa,bb.
831
832 G4double cc=0.0;
833 *bb = pp[0];
834 qq[0] = *bb;
835 *aa = pp[1] - (*bb)*(*uu);
836 qq[1] = *aa;
837 for (G4int i=2;i<=nn;i++)
838 {
839 cc = pp[i] - (*aa)*(*uu) - (*bb)*(*vv);
840 qq[i] = cc;
841 *bb = *aa;
842 *aa = cc;
843 }
844}
845
846void G4JTPolynomialSolver::Quadratic(G4double aa,G4double b1,
847 G4double cc,G4double *ssr,G4double *ssi,
848 G4double *lr,G4double *li)
849{
850
851 // Calculate the zeros of the quadratic aa*z^2 + b1*z + cc.
852 // The quadratic formula, modified to avoid overflow, is used
853 // to find the larger zero if the zeros are real and both
854 // are complex. The smaller real zero is found directly from
855 // the product of the zeros c/a.
856
857 G4double bb=0.0, dd=0.0, ee=0.0;
858
859 if (!(aa != 0.0)) // less than two roots
860 {
861 if (b1 != 0.0)
862 { *ssr = -cc/b1; }
863 else
864 { *ssr = 0.0; }
865 *lr = 0.0;
866 *ssi = 0.0;
867 *li = 0.0;
868 return;
869 }
870 if (!(cc != 0.0)) // one real root, one zero root
871 {
872 *ssr = 0.0;
873 *lr = -b1/aa;
874 *ssi = 0.0;
875 *li = 0.0;
876 return;
877 }
878
879 // Compute discriminant avoiding overflow.
880 //
881 bb = b1/2.0;
882 if (std::fabs(bb) < std::fabs(cc))
883 {
884 if (cc < 0.0)
885 { ee = -aa; }
886 else
887 { ee = aa; }
888 ee = bb*(bb/std::fabs(cc)) - ee;
889 dd = std::sqrt(std::fabs(ee))*std::sqrt(std::fabs(cc));
890 }
891 else
892 {
893 ee = 1.0 - (aa/bb)*(cc/bb);
894 dd = std::sqrt(std::fabs(ee))*std::fabs(bb);
895 }
896 if (ee < 0.0) // complex conjugate zeros
897 {
898 *ssr = -bb/aa;
899 *lr = *ssr;
900 *ssi = std::fabs(dd/aa);
901 *li = -(*ssi);
902 }
903 else
904 {
905 if (bb >= 0.0) // real zeros.
906 { dd = -dd; }
907 *lr = (-bb+dd)/aa;
908 *ssr = 0.0;
909 if (*lr != 0.0)
910 { *ssr = (cc/ *lr)/aa; }
911 *ssi = 0.0;
912 *li = 0.0;
913 }
914}
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
G4int FindRoots(G4double *op, G4int degree, G4double *zeror, G4double *zeroi)
#define DBL_MIN
Definition: templates.hh:75
#define DBL_EPSILON
Definition: templates.hh:87
#define DBL_MAX
Definition: templates.hh:83