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