Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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// G4JTPolynomialSolver class implementation.
27//
28// Author: Oliver Link, 15.02.2005
29// Translated to C++ and adapted to use STL vectors.
30// --------------------------------------------------------------------
31
33#include "G4Pow.hh"
34#include "G4SystemOfUnits.hh"
35
36const G4double G4JTPolynomialSolver::base = 2;
37const G4double G4JTPolynomialSolver::eta = DBL_EPSILON;
38const G4double G4JTPolynomialSolver::infin = DBL_MAX;
39const G4double G4JTPolynomialSolver::smalno = DBL_MIN;
40const G4double G4JTPolynomialSolver::are = DBL_EPSILON;
41const G4double G4JTPolynomialSolver::mre = DBL_EPSILON;
42const G4double G4JTPolynomialSolver::lo = DBL_MIN / DBL_EPSILON;
43
45 G4double* zeroi)
46{
47 G4double t = 0.0, aa = 0.0, bb = 0.0, cc = 0.0, factor = 1.0;
48 G4double max = 0.0, min = infin, xxx = 0.0, x = 0.0, sc = 0.0, bnd = 0.0;
49 G4double xm = 0.0, ff = 0.0, df = 0.0, dx = 0.0;
50 G4int cnt = 0, nz = 0, i = 0, j = 0, jj = 0, l = 0, nm1 = 0, zerok = 0;
51 G4Pow* power = G4Pow::GetInstance();
52
53 // Initialization of constants for shift rotation.
54 //
55 static const G4double xx = std::sqrt(0.5);
56 static const G4double rot = 94.0 * deg;
57 static const G4double cosr = std::cos(rot), sinr = std::sin(rot);
58 G4double xo = xx, yo = -xx;
59 n = degr;
60
61 // Algorithm fails if the leading coefficient is zero.
62 //
63 if(!(op[0] != 0.0))
64 {
65 return -1;
66 }
67
68 // Remove the zeros at the origin, if any.
69 //
70 while(!(op[n] != 0.0))
71 {
72 j = degr - n;
73 zeror[j] = 0.0;
74 zeroi[j] = 0.0;
75 n--;
76 }
77 if(n < 1)
78 {
79 return -1;
80 }
81
82 // Allocate buffers here
83 //
84 std::vector<G4double> temp(degr + 1);
85 std::vector<G4double> pt(degr + 1);
86
87 p.assign(degr + 1, 0);
88 qp.assign(degr + 1, 0);
89 k.assign(degr + 1, 0);
90 qk.assign(degr + 1, 0);
91 svk.assign(degr + 1, 0);
92
93 // Make a copy of the coefficients.
94 //
95 for(i = 0; i <= n; ++i)
96 {
97 p[i] = op[i];
98 }
99
100 do
101 {
102 if(n == 1) // Start the algorithm for one zero.
103 {
104 zeror[degr - 1] = -p[1] / p[0];
105 zeroi[degr - 1] = 0.0;
106 n -= 1;
107 return degr - n;
108 }
109 if(n == 2) // Calculate the final zero or pair of zeros.
110 {
111 Quadratic(p[0], p[1], p[2], &zeror[degr - 2], &zeroi[degr - 2],
112 &zeror[degr - 1], &zeroi[degr - 1]);
113 n -= 2;
114 return degr - n;
115 }
116
117 // Find largest and smallest moduli of coefficients.
118 //
119 max = 0.0;
120 min = infin;
121 for(i = 0; i <= n; ++i)
122 {
123 x = std::fabs(p[i]);
124 if(x > max)
125 {
126 max = x;
127 }
128 if(x != 0.0 && x < min)
129 {
130 min = x;
131 }
132 }
133
134 // Scale if there are large or very small coefficients.
135 // Computes a scale factor to multiply the coefficients of the
136 // polynomial. The scaling is done to avoid overflow and to
137 // avoid undetected underflow interfering with the convergence
138 // criterion. The factor is a power of the base.
139 //
140 sc = lo / min;
141
142 if(((sc <= 1.0) && (max >= 10.0)) || ((sc > 1.0) && (infin / sc >= max)) ||
143 ((infin / sc >= max) && (max >= 10)))
144 {
145 if(!(sc != 0.0))
146 {
147 sc = smalno;
148 }
149 l = (G4int)(G4Log(sc) / G4Log(base) + 0.5);
150 factor = power->powN(base, l);
151 if(factor != 1.0)
152 {
153 for(i = 0; i <= n; ++i)
154 {
155 p[i] = factor * p[i];
156 } // 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 = G4Exp((G4Log(-pt[n]) - G4Log(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)
178 {
179 x = xm;
180 }
181 }
182
183 // Chop the interval (0,x) until ff <= 0
184 //
185 while(true)
186 {
187 xm = x * 0.1;
188 ff = pt[0];
189 for(i = 1; i <= n; ++i)
190 {
191 ff = ff * xm + pt[i];
192 }
193 if(ff <= 0.0)
194 {
195 break;
196 }
197 x = xm;
198 }
199 dx = x;
200
201 // Do Newton interation until x converges to two decimal places.
202 //
203 while(std::fabs(dx / x) > 0.005)
204 {
205 ff = pt[0];
206 df = ff;
207 for(i = 1; i < n; ++i)
208 {
209 ff = ff * x + pt[i];
210 df = df * x + ff;
211 }
212 ff = ff * x + pt[n];
213 dx = ff / df;
214 x -= dx;
215 }
216 bnd = x;
217
218 // Compute the derivative as the initial k polynomial
219 // and do 5 steps with no shift.
220 //
221 nm1 = n - 1;
222 for(i = 1; i < n; ++i)
223 {
224 k[i] = (G4double)(n - i) * p[i] / (G4double) n;
225 }
226 k[0] = p[0];
227 aa = p[n];
228 bb = p[n - 1];
229 zerok = static_cast<G4int>(k[n - 1] == 0);
230 for(jj = 0; jj < 5; ++jj)
231 {
232 cc = k[n - 1];
233 if(zerok == 0) // Use a scaled form of recurrence if k at 0 is nonzero.
234 {
235 // Use a scaled form of recurrence if value of k at 0 is nonzero.
236 //
237 t = -aa / cc;
238 for(i = 0; i < nm1; ++i)
239 {
240 j = n - i - 1;
241 k[j] = t * k[j - 1] + p[j];
242 }
243 k[0] = p[0];
244 zerok =
245 static_cast<G4int>(std::fabs(k[n - 1]) <= std::fabs(bb) * eta * 10.0);
246 }
247 else // Use unscaled form of recurrence.
248 {
249 for(i = 0; i < nm1; ++i)
250 {
251 j = n - i - 1;
252 k[j] = k[j - 1];
253 }
254 k[0] = 0.0;
255 zerok = static_cast<G4int>(!(k[n - 1] != 0.0));
256 }
257 }
258
259 // Save k for restarts with new shifts.
260 //
261 for(i = 0; i < n; ++i)
262 {
263 temp[i] = k[i];
264 }
265
266 // Loop to select the quadratic corresponding to each new shift.
267 //
268 for(cnt = 0; cnt < 20; ++cnt)
269 {
270 // Quadratic corresponds to a double shift to a
271 // non-real point and its complex conjugate. The point
272 // has modulus bnd and amplitude rotated by 94 degrees
273 // from the previous shift.
274 //
275 xxx = cosr * xo - sinr * yo;
276 yo = sinr * xo + cosr * yo;
277 xo = xxx;
278 sr = bnd * xo;
279 si = bnd * yo;
280 u = -2.0 * sr;
281 v = bnd;
282 ComputeFixedShiftPolynomial(20 * (cnt + 1), &nz);
283 if(nz != 0)
284 {
285 // The second stage jumps directly to one of the third
286 // stage iterations and returns here if successful.
287 // Deflate the polynomial, store the zero or zeros and
288 // return to the main algorithm.
289 //
290 j = degr - n;
291 zeror[j] = szr;
292 zeroi[j] = szi;
293 n -= nz;
294 for(i = 0; i <= n; ++i)
295 {
296 p[i] = qp[i];
297 }
298 if(nz != 1)
299 {
300 zeror[j + 1] = lzr;
301 zeroi[j + 1] = lzi;
302 }
303 break;
304 }
305
306 // If the iteration is unsuccessful another quadratic
307 // is chosen after restoring k.
308 //
309 for(i = 0; i < n; ++i)
310 {
311 k[i] = temp[i];
312 }
313
314 }
315 } while(nz != 0); // End of initial DO loop
316
317 // Return with failure if no convergence with 20 shifts.
318 //
319 return degr - n;
320}
321
322void G4JTPolynomialSolver::ComputeFixedShiftPolynomial(G4int l2, G4int* nz)
323{
324 // Computes up to L2 fixed shift k-polynomials, testing for convergence
325 // in the linear or quadratic case. Initiates one of the variable shift
326 // iterations and returns with the number of zeros found.
327
328 G4double svu = 0.0, svv = 0.0, ui = 0.0, vi = 0.0, xs = 0.0;
329 G4double betas = 0.25, betav = 0.25, oss = sr, ovv = v, ss = 0.0, vv = 0.0,
330 ts = 1.0, tv = 1.0;
331 G4double ots = 0.0, otv = 0.0;
332 G4double tvv = 1.0, tss = 1.0;
333 G4int type = 0, i = 0, j = 0, iflag = 0, vpass = 0, spass = 0, vtry = 0,
334 stry = 0;
335
336 *nz = 0;
337
338 // Evaluate polynomial by synthetic division.
339 //
340 QuadraticSyntheticDivision(n, &u, &v, p, qp, &a, &b);
341 ComputeScalarFactors(&type);
342 for(j = 0; j < l2; ++j)
343 {
344 // Calculate next k polynomial and estimate v.
345 //
346 ComputeNextPolynomial(&type);
347 ComputeScalarFactors(&type);
348 ComputeNewEstimate(type, &ui, &vi);
349 vv = vi;
350
351 // Estimate xs.
352 //
353 ss = 0.0;
354 if(k[n - 1] != 0.0)
355 {
356 ss = -p[n] / k[n - 1];
357 }
358 tv = 1.0;
359 ts = 1.0;
360 if(j == 0 || type == 3)
361 {
362 ovv = vv;
363 oss = ss;
364 otv = tv;
365 ots = ts;
366 continue;
367 }
368
369 // Compute relative measures of convergence of xs and v sequences.
370 //
371 if(vv != 0.0)
372 {
373 tv = std::fabs((vv - ovv) / vv);
374 }
375 if(ss != 0.0)
376 {
377 ts = std::fabs((ss - oss) / ss);
378 }
379
380 // If decreasing, multiply two most recent convergence measures.
381 tvv = 1.0;
382 if(tv < otv)
383 {
384 tvv = tv * otv;
385 }
386 tss = 1.0;
387 if(ts < ots)
388 {
389 tss = ts * ots;
390 }
391
392 // Compare with convergence criteria.
393 vpass = static_cast<G4int>(tvv < betav);
394 spass = static_cast<G4int>(tss < betas);
395 if(!((spass != 0) || (vpass != 0)))
396 {
397 ovv = vv;
398 oss = ss;
399 otv = tv;
400 ots = ts;
401 continue;
402 }
403
404 // At least one sequence has passed the convergence test.
405 // Store variables before iterating.
406 //
407 svu = u;
408 svv = v;
409 for(i = 0; i < n; ++i)
410 {
411 svk[i] = k[i];
412 }
413 xs = ss;
414
415 // Choose iteration according to the fastest converging sequence.
416 //
417 vtry = 0;
418 stry = 0;
419 if(((spass != 0) && (vpass == 0)) || (tss < tvv))
420 {
421 RealPolynomialIteration(&xs, nz, &iflag);
422 if(*nz > 0)
423 {
424 return;
425 }
426
427 // Linear iteration has failed. Flag that it has been
428 // tried and decrease the convergence criterion.
429 //
430 stry = 1;
431 betas *= 0.25;
432 if(iflag == 0)
433 {
434 goto _restore_variables;
435 }
436
437 // If linear iteration signals an almost double real
438 // zero attempt quadratic iteration.
439 //
440 ui = -(xs + xs);
441 vi = xs * xs;
442 }
443
444 _quadratic_iteration:
445
446 do
447 {
448 QuadraticPolynomialIteration(&ui, &vi, nz);
449 if(*nz > 0)
450 {
451 return;
452 }
453
454 // Quadratic iteration has failed. Flag that it has
455 // been tried and decrease the convergence criterion.
456 //
457 vtry = 1;
458 betav *= 0.25;
459
460 // Try linear iteration if it has not been tried and
461 // the S sequence is converging.
462 //
463 if((stry != 0) || (spass == 0))
464 {
465 break;
466 }
467 for(i = 0; i < n; ++i)
468 {
469 k[i] = svk[i];
470 }
471 RealPolynomialIteration(&xs, nz, &iflag);
472 if(*nz > 0)
473 {
474 return;
475 }
476
477 // Linear iteration has failed. Flag that it has been
478 // tried and decrease the convergence criterion.
479 //
480 stry = 1;
481 betas *= 0.25;
482 if(iflag == 0)
483 {
484 break;
485 }
486
487 // If linear iteration signals an almost double real
488 // zero attempt quadratic iteration.
489 //
490 ui = -(xs + xs);
491 vi = xs * xs;
492 } while(iflag != 0);
493
494 // Restore variables.
495
496 _restore_variables:
497
498 u = svu;
499 v = svv;
500 for(i = 0; i < n; ++i)
501 {
502 k[i] = svk[i];
503 }
504
505 // Try quadratic iteration if it has not been tried
506 // and the V sequence is converging.
507 //
508 if((vpass != 0) && (vtry == 0))
509 {
510 goto _quadratic_iteration;
511 }
512
513 // Recompute QP and scalar values to continue the
514 // second stage.
515 //
516 QuadraticSyntheticDivision(n, &u, &v, p, qp, &a, &b);
517 ComputeScalarFactors(&type);
518
519 ovv = vv;
520 oss = ss;
521 otv = tv;
522 ots = ts;
523 }
524}
525
526void G4JTPolynomialSolver::QuadraticPolynomialIteration(G4double* uu,
527 G4double* vv, G4int* nz)
528{
529 // Variable-shift k-polynomial iteration for a
530 // quadratic factor converges only if the zeros are
531 // equimodular or nearly so.
532 // uu, vv - coefficients of starting quadratic.
533 // nz - number of zeros found.
534 //
535 G4double ui = 0.0, vi = 0.0;
536 G4double omp = 0.0;
537 G4double relstp = 0.0;
538 G4double mp = 0.0, ee = 0.0, t = 0.0, zm = 0.0;
539 G4int type = 0, i = 1, j = 0, tried = 0;
540
541 *nz = 0;
542 tried = 0;
543 u = *uu;
544 v = *vv;
545
546 // Main loop.
547
548 while(true)
549 {
550 Quadratic(1.0, u, v, &szr, &szi, &lzr, &lzi);
551
552 // Return if roots of the quadratic are real and not
553 // close to multiple or nearly equal and of opposite
554 // sign.
555 //
556 if(std::fabs(std::fabs(szr) - std::fabs(lzr)) > 0.01 * std::fabs(lzr))
557 {
558 return;
559 }
560
561 // Evaluate polynomial by quadratic synthetic division.
562 //
563 QuadraticSyntheticDivision(n, &u, &v, p, qp, &a, &b);
564 mp = std::fabs(a - szr * b) + std::fabs(szi * b);
565
566 // Compute a rigorous bound on the rounding error in evaluating p.
567 //
568 zm = std::sqrt(std::fabs(v));
569 ee = 2.0 * std::fabs(qp[0]);
570 t = -szr * b;
571 for(i = 1; i < n; ++i)
572 {
573 ee = ee * zm + std::fabs(qp[i]);
574 }
575 ee = ee * zm + std::fabs(a + t);
576 ee *= (5.0 * mre + 4.0 * are);
577 ee = ee - (5.0 * mre + 2.0 * are) * (std::fabs(a + t) + std::fabs(b) * zm) +
578 2.0 * are * std::fabs(t);
579
580 // Iteration has converged sufficiently if the
581 // polynomial value is less than 20 times this bound.
582 //
583 if(mp <= 20.0 * ee)
584 {
585 *nz = 2;
586 return;
587 }
588 j++;
589
590 // Stop iteration after 20 steps.
591 //
592 if(j > 20)
593 {
594 return;
595 }
596 if(j >= 2)
597 {
598 if(!(relstp > 0.01 || mp < omp || (tried != 0)))
599 {
600 // A cluster appears to be stalling the convergence.
601 // Five fixed shift steps are taken with a u,v close to the cluster.
602 //
603 if(relstp < eta)
604 {
605 relstp = eta;
606 }
607 relstp = std::sqrt(relstp);
608 u = u - u * relstp;
609 v = v + v * relstp;
610 QuadraticSyntheticDivision(n, &u, &v, p, qp, &a, &b);
611 for(i = 0; i < 5; ++i)
612 {
613 ComputeScalarFactors(&type);
614 ComputeNextPolynomial(&type);
615 }
616 tried = 1;
617 j = 0;
618 }
619 }
620 omp = mp;
621
622 // Calculate next k polynomial and new u and v.
623 //
624 ComputeScalarFactors(&type);
625 ComputeNextPolynomial(&type);
626 ComputeScalarFactors(&type);
627 ComputeNewEstimate(type, &ui, &vi);
628
629 // If vi is zero the iteration is not converging.
630 //
631 if(!(vi != 0.0))
632 {
633 return;
634 }
635 relstp = std::fabs((vi - v) / vi);
636 u = ui;
637 v = vi;
638 }
639}
640
641void G4JTPolynomialSolver::RealPolynomialIteration(G4double* sss, G4int* nz,
642 G4int* iflag)
643{
644 // Variable-shift H polynomial iteration for a real zero.
645 // sss - starting iterate
646 // nz - number of zeros found
647 // iflag - flag to indicate a pair of zeros near real axis.
648
649 G4double t = 0.;
650 G4double omp = 0.;
651 G4double pv = 0.0, kv = 0.0, xs = *sss;
652 G4double mx = 0.0, mp = 0.0, ee = 0.0;
653 G4int i = 1, j = 0;
654
655 *nz = 0;
656 *iflag = 0;
657
658 // Main loop
659 //
660 while(true)
661 {
662 pv = p[0];
663
664 // Evaluate p at xs.
665 //
666 qp[0] = pv;
667 for(i = 1; i <= n; ++i)
668 {
669 pv = pv * xs + p[i];
670 qp[i] = pv;
671 }
672 mp = std::fabs(pv);
673
674 // Compute a rigorous bound on the error in evaluating p.
675 //
676 mx = std::fabs(xs);
677 ee = (mre / (are + mre)) * std::fabs(qp[0]);
678 for(i = 1; i <= n; ++i)
679 {
680 ee = ee * mx + std::fabs(qp[i]);
681 }
682
683 // Iteration has converged sufficiently if the polynomial
684 // value is less than 20 times this bound.
685 //
686 if(mp <= 20.0 * ((are + mre) * ee - mre * mp))
687 {
688 *nz = 1;
689 szr = xs;
690 szi = 0.0;
691 return;
692 }
693 j++;
694
695 // Stop iteration after 10 steps.
696 //
697 if(j > 10)
698 {
699 return;
700 }
701 if(j >= 2)
702 {
703 if(!(std::fabs(t) > 0.001 * std::fabs(xs - t) || mp < omp))
704 {
705 // A cluster of zeros near the real axis has been encountered.
706 // Return with iflag set to initiate a quadratic iteration.
707 //
708 *iflag = 1;
709 *sss = xs;
710 return;
711 } // Return if the polynomial value has increased significantly.
712 }
713
714 omp = mp;
715
716 // Compute t, the next polynomial, and the new iterate.
717 //
718 kv = k[0];
719 qk[0] = kv;
720 for(i = 1; i < n; ++i)
721 {
722 kv = kv * xs + k[i];
723 qk[i] = kv;
724 }
725 if(std::fabs(kv) <= std::fabs(k[n - 1]) * 10.0 * eta) // Use unscaled form.
726 {
727 k[0] = 0.0;
728 for(i = 1; i < n; ++i)
729 {
730 k[i] = qk[i - 1];
731 }
732 }
733 else // Use the scaled form of the recurrence if k at xs is nonzero.
734 {
735 t = -pv / kv;
736 k[0] = qp[0];
737 for(i = 1; i < n; ++i)
738 {
739 k[i] = t * qk[i - 1] + qp[i];
740 }
741 }
742 kv = k[0];
743 for(i = 1; i < n; ++i)
744 {
745 kv = kv * xs + k[i];
746 }
747 t = 0.0;
748 if(std::fabs(kv) > std::fabs(k[n - 1] * 10.0 * eta))
749 {
750 t = -pv / kv;
751 }
752 xs += t;
753 }
754}
755
756void G4JTPolynomialSolver::ComputeScalarFactors(G4int* type)
757{
758 // This function calculates scalar quantities used to
759 // compute the next k polynomial and new estimates of
760 // the quadratic coefficients.
761 // type - integer variable set here indicating how the
762 // calculations are normalized to avoid overflow.
763
764 // Synthetic division of k by the quadratic 1,u,v
765 //
766 QuadraticSyntheticDivision(n - 1, &u, &v, k, qk, &c, &d);
767 if(std::fabs(c) <= std::fabs(k[n - 1] * 100.0 * eta))
768 {
769 if(std::fabs(d) <= std::fabs(k[n - 2] * 100.0 * eta))
770 {
771 *type = 3; // Type=3 indicates the quadratic is almost a factor of k.
772 return;
773 }
774 }
775
776 if(std::fabs(d) < std::fabs(c))
777 {
778 *type = 1; // Type=1 indicates that all formulas are divided by c.
779 e = a / c;
780 f = d / c;
781 g = u * e;
782 h = v * b;
783 a3 = a * e + (h / c + g) * b;
784 a1 = b - a * (d / c);
785 a7 = a + g * d + h * f;
786 return;
787 }
788 *type = 2; // Type=2 indicates that all formulas are divided by d.
789 e = a / d;
790 f = c / d;
791 g = u * b;
792 h = v * b;
793 a3 = (a + g) * e + h * (b / d);
794 a1 = b * f - a;
795 a7 = (f + u) * a + h;
796}
797
798void G4JTPolynomialSolver::ComputeNextPolynomial(G4int* type)
799{
800 // Computes the next k polynomials using scalars
801 // computed in ComputeScalarFactors.
802
803 G4int i = 2;
804
805 if(*type == 3) // Use unscaled form of the recurrence if type is 3.
806 {
807 k[0] = 0.0;
808 k[1] = 0.0;
809 for(i = 2; i < n; ++i)
810 {
811 k[i] = qk[i - 2];
812 }
813 return;
814 }
815 G4double temp = a;
816 if(*type == 1)
817 {
818 temp = b;
819 }
820 if(std::fabs(a1) <= std::fabs(temp) * eta * 10.0)
821 {
822 // If a1 is nearly zero then use a special form of the recurrence.
823 //
824 k[0] = 0.0;
825 k[1] = -a7 * qp[0];
826 for(i = 2; i < n; ++i)
827 {
828 k[i] = a3 * qk[i - 2] - a7 * qp[i - 1];
829 }
830 return;
831 }
832
833 // Use scaled form of the recurrence.
834 //
835 a7 /= a1;
836 a3 /= a1;
837 k[0] = qp[0];
838 k[1] = qp[1] - a7 * qp[0];
839 for(i = 2; i < n; ++i)
840 {
841 k[i] = a3 * qk[i - 2] - a7 * qp[i - 1] + qp[i];
842 }
843}
844
845void G4JTPolynomialSolver::ComputeNewEstimate(G4int type, G4double* uu,
846 G4double* vv)
847{
848 // Compute new estimates of the quadratic coefficients
849 // using the scalars computed in calcsc.
850
851 G4double a4 = 0.0, a5 = 0.0, b1 = 0.0, b2 = 0.0, c1 = 0.0, c2 = 0.0, c3 = 0.0,
852 c4 = 0.0, temp = 0.0;
853
854 // Use formulas appropriate to setting of type.
855 //
856 if(type == 3) // If type=3 the quadratic is zeroed.
857 {
858 *uu = 0.0;
859 *vv = 0.0;
860 return;
861 }
862 if(type == 2)
863 {
864 a4 = (a + g) * f + h;
865 a5 = (f + u) * c + v * d;
866 }
867 else
868 {
869 a4 = a + u * b + h * f;
870 a5 = c + (u + v * f) * d;
871 }
872
873 // Evaluate new quadratic coefficients.
874 //
875 b1 = -k[n - 1] / p[n];
876 b2 = -(k[n - 2] + b1 * p[n - 1]) / p[n];
877 c1 = v * b2 * a1;
878 c2 = b1 * a7;
879 c3 = b1 * b1 * a3;
880 c4 = c1 - c2 - c3;
881 temp = a5 + b1 * a4 - c4;
882 if(!(temp != 0.0))
883 {
884 *uu = 0.0;
885 *vv = 0.0;
886 return;
887 }
888 *uu = u - (u * (c3 + c2) + v * (b1 * a1 + b2 * a7)) / temp;
889 *vv = v * (1.0 + c4 / temp);
890 return;
891}
892
893void G4JTPolynomialSolver::QuadraticSyntheticDivision(
894 G4int nn, G4double* uu, G4double* vv, std::vector<G4double>& pp,
895 std::vector<G4double>& qq, G4double* aa, G4double* bb)
896{
897 // Divides pp by the quadratic 1,uu,vv placing the quotient
898 // in qq and the remainder in aa,bb.
899
900 G4double cc = 0.0;
901 *bb = pp[0];
902 qq[0] = *bb;
903 *aa = pp[1] - (*bb) * (*uu);
904 qq[1] = *aa;
905 for(G4int i = 2; i <= nn; ++i)
906 {
907 cc = pp[i] - (*aa) * (*uu) - (*bb) * (*vv);
908 qq[i] = cc;
909 *bb = *aa;
910 *aa = cc;
911 }
912}
913
914void G4JTPolynomialSolver::Quadratic(G4double aa, G4double b1, G4double cc,
915 G4double* ssr, G4double* ssi, G4double* lr,
916 G4double* li)
917{
918 // Calculate the zeros of the quadratic aa*z^2 + b1*z + cc.
919 // The quadratic formula, modified to avoid overflow, is used
920 // to find the larger zero if the zeros are real and both
921 // are complex. The smaller real zero is found directly from
922 // the product of the zeros c/a.
923
924 G4double bb = 0.0, dd = 0.0, ee = 0.0;
925
926 if(!(aa != 0.0)) // less than two roots
927 {
928 if(b1 != 0.0)
929 {
930 *ssr = -cc / b1;
931 }
932 else
933 {
934 *ssr = 0.0;
935 }
936 *lr = 0.0;
937 *ssi = 0.0;
938 *li = 0.0;
939 return;
940 }
941 if(!(cc != 0.0)) // one real root, one zero root
942 {
943 *ssr = 0.0;
944 *lr = -b1 / aa;
945 *ssi = 0.0;
946 *li = 0.0;
947 return;
948 }
949
950 // Compute discriminant avoiding overflow.
951 //
952 bb = b1 / 2.0;
953 if(std::fabs(bb) < std::fabs(cc))
954 {
955 if(cc < 0.0)
956 {
957 ee = -aa;
958 }
959 else
960 {
961 ee = aa;
962 }
963 ee = bb * (bb / std::fabs(cc)) - ee;
964 dd = std::sqrt(std::fabs(ee)) * std::sqrt(std::fabs(cc));
965 }
966 else
967 {
968 ee = 1.0 - (aa / bb) * (cc / bb);
969 dd = std::sqrt(std::fabs(ee)) * std::fabs(bb);
970 }
971 if(ee < 0.0) // complex conjugate zeros
972 {
973 *ssr = -bb / aa;
974 *lr = *ssr;
975 *ssi = std::fabs(dd / aa);
976 *li = -(*ssi);
977 }
978 else
979 {
980 if(bb >= 0.0) // real zeros.
981 {
982 dd = -dd;
983 }
984 *lr = (-bb + dd) / aa;
985 *ssr = 0.0;
986 if(*lr != 0.0)
987 {
988 *ssr = (cc / *lr) / aa;
989 }
990 *ssi = 0.0;
991 *li = 0.0;
992 }
993}
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition: G4Exp.hh:180
G4double G4Log(G4double x)
Definition: G4Log.hh:227
double G4double
Definition: G4Types.hh:83
int G4int
Definition: G4Types.hh:85
G4int FindRoots(G4double *op, G4int degree, G4double *zeror, G4double *zeroi)
Definition: G4Pow.hh:49
static G4Pow * GetInstance()
Definition: G4Pow.cc:41
G4double powN(G4double x, G4int n) const
Definition: G4Pow.cc:162
#define DBL_MIN
Definition: templates.hh:54
#define DBL_EPSILON
Definition: templates.hh:66
#define DBL_MAX
Definition: templates.hh:62