Garfield++ 5.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
Numerics.cc
Go to the documentation of this file.
1#include <algorithm>
2#include <array>
3#include <cmath>
4#include <iostream>
5#include <limits>
6#include <numeric>
7
9
10namespace {
11
12int deqnGen(const int n, std::vector<std::vector<double > >& a,
13 std::vector<double>& b) {
14
15 std::vector<int> ir(n, 0);
16 double det = 0.;
17 int ifail = 0, jfail = 0;
18 Garfield::Numerics::CERNLIB::dfact(n, a, ir, ifail, det, jfail);
19 if (ifail != 0) return ifail;
21 return 0;
22}
23
24/// Epsilon algorithm.
25/// Determines the limit of a given sequence of approximations,
26/// by means of the epsilon algorithm of P. Wynn.
27/// An estimate of the absolute error is also given.
28/// The condensed epsilon table is computed. Only those elements needed
29/// for the computation of the next diagonal are preserved.
30/// \param epstab elements of the two lower diagonals of the triangular
31/// epsilon table. The elements are numbered starting at the
32/// right-hand corner of the triangle.
33/// \param n size of the epsilon table.
34/// \param result resulting approximation to the integral.
35/// \param abserr estimate of the absolute error computed from
36/// result and the three previous results.
37/// \param lastRes last three results.
38/// \param nres number of calls to the function.
39void qelg(unsigned int& n, std::array<double, 52>& epstab,
40 double& result, double& abserr,
41 std::array<double, 3>& lastRes, unsigned int& nres) {
42
43 constexpr double eps = std::numeric_limits<double>::epsilon();
44
45 ++nres;
46 abserr = std::numeric_limits<double>::max();
47 result = epstab[n - 1];
48 if (n < 3) {
49 abserr = std::max(abserr, 50. * eps * std::abs(result));
50 return;
51 }
52 epstab[n + 1] = epstab[n - 1];
53 epstab[n - 1] = std::numeric_limits<double>::max();
54 // Number of elements to be computed in the new diagonal.
55 const unsigned int nnew = (n - 1) / 2;
56 const unsigned int nold = n;
57 unsigned int k = n;
58 for (unsigned int i = 1; i <= nnew; ++i) {
59 double res = epstab[k + 1];
60 // e0 - e3 are the four elements on which the computation of a new
61 // element in the epsilon table is based.
62 // e0
63 // e3 e1 new
64 // e2
65 const double e0 = epstab[k - 3];
66 const double e1 = epstab[k - 2];
67 const double e2 = res;
68 const double delta2 = e2 - e1;
69 const double err2 = std::abs(delta2);
70 const double tol2 = std::max(std::abs(e2), std::abs(e1)) * eps;
71 const double delta3 = e1 - e0;
72 const double err3 = std::abs(delta3);
73 const double tol3 = std::max(std::abs(e1), std::abs(e0)) * eps;
74 if (err2 <= tol2 && err3 <= tol3) {
75 // If e0, e1 and e2 are equal to within machine accuracy,
76 // convergence is assumed.
77 result = res;
78 abserr = std::max(err2 + err3, 50. * eps * std::abs(result));
79 return;
80 }
81 const double e3 = epstab[k - 1];
82 epstab[k - 1] = e1;
83 const double delta1 = e1 - e3;
84 const double err1 = std::abs(delta1);
85 const double tol1 = std::max(std::abs(e1), std::abs(e3)) * eps;
86 // If two elements are very close to each other, omit
87 // a part of the table by adjusting the value of n
88 if (err1 <= tol1 || err2 <= tol2 || err3 <= tol3) {
89 n = i + i - 1;
90 break;
91 }
92 const double ss = 1. / delta1 + 1. / delta2 - 1./ delta3;
93 // Test to detect irregular behaviour in the table, and
94 // eventually omit a part of the table adjusting the value of n.
95 if (std::abs(ss * e1) <= 1.e-4) {
96 n = i + i - 1;
97 break;
98 }
99 // Compute a new element and eventually adjust the value of result.
100 res = e1 + 1. / ss;
101 epstab[k - 1] = res;
102 k -= 2;
103 const double error = err2 + std::abs(res - e2) + err3;
104 if (error <= abserr) {
105 abserr = error;
106 result = res;
107 }
108 }
109 // Shift the table.
110 constexpr unsigned int limexp = 50;
111 if (n == limexp) n = 2 * (limexp / 2) - 1;
112 unsigned int ib = (nold % 2 == 0) ? 1 : 0;
113 for (unsigned int i = 0; i <= nnew; ++i) {
114 epstab[ib] = epstab[ib + 2];
115 ib += 2;
116 }
117 if (nold != n) {
118 for (unsigned int i = 0; i < n; ++i) {
119 epstab[i] = epstab[nold - n + i];
120 }
121 }
122 if (nres >= 4) {
123 // Compute error estimate.
124 abserr = std::abs(result - lastRes[2]) +
125 std::abs(result - lastRes[1]) +
126 std::abs(result - lastRes[0]);
127 lastRes[0] = lastRes[1];
128 lastRes[1] = lastRes[2];
129 lastRes[2] = result;
130 } else {
131 lastRes[nres - 1] = result;
132 abserr = std::numeric_limits<double>::max();
133 }
134 abserr = std::max(abserr, 50. * eps * std::abs(result));
135}
136
137}
138
139namespace Garfield {
140
141namespace Numerics {
142
143namespace QUADPACK {
144
145void qagi(std::function<double(double)> f, double bound, const int inf,
146 const double epsabs, const double epsrel,
147 double& result, double& abserr, unsigned int& status) {
148
149 status = 0;
150 result = 0.;
151 abserr = 0.;
152
153 // Test on validity of parameters.
154 constexpr double eps = std::numeric_limits<double>::epsilon();
155 if (epsabs <= 0. && epsrel < std::max(50. * eps, 0.5e-28)) {
156 status = 6;
157 return;
158 }
159 // First approximation to the integral
160 if (inf == 2) bound = 0.;
161 double resabs0 = 0., resasc0 = 0.;
162 qk15i(f, bound, inf, 0., 1., result, abserr, resabs0, resasc0);
163
164 // Calculate the requested accuracy.
165 double tol = std::max(epsabs, epsrel * std::abs(result));
166 // Test on accuracy.
167 if (abserr <= 100. * eps * resabs0 && abserr > tol) {
168 // Roundoff error at the first attempt.
169 status = 2;
170 return;
171 }
172 // Test if the first approximation was good enough.
173 if ((abserr <= tol && abserr != resasc0) || abserr == 0.) return;
174
175 struct Interval {
176 double a; ///< Left end point.
177 double b; ///< Right end point.
178 double r; ///< Approximation to the integral over this interval.
179 double e; ///< Error estimate.
180 };
181 std::vector<Interval> intervals(1);
182 intervals[0].a = 0.;
183 intervals[0].b = 1.;
184 intervals[0].r = result;
185 intervals[0].e = abserr;
186 constexpr unsigned int nMaxIntervals = 500;
187 unsigned int nIntervals = 1;
188 // Interval to be bisected.
189 auto it = intervals.begin();
190 size_t nrmax = 0;
191
192 // Initialize the epsilon table.
193 std::array<double, 52> epstab;
194 epstab[0] = result;
195 // Count the number of elements currently in the epsilon table.
196 unsigned int nEps = 2;
197 // Keep track of the last three results.
198 std::array<double, 3> lastRes = {0., 0., 0.};
199 // Count the number of calls to the epsilon extrapolation function.
200 unsigned int nRes = 0;
201 // Flag denoting that we are attempting to perform extrapolation.
202 bool extrap = false;
203 // Flag indicating that extrapolation is no longer allowed.
204 bool noext = false;
205 unsigned int ktmin = 0;
206
207 // Initialize the sum of the integrals over the subintervals.
208 double area = result;
209 // Initialize the sum of the errors over the subintervals.
210 double errSum = abserr;
211 // Length of the smallest interval considered up now, multiplied by 1.5.
212 double small = 0.375;
213 // Sum of the errors over the intervals larger than the smallest interval
214 // considered up to now.
215 double errLarge = 0.;
216 double errTest = 0.;
217 // Error estimate of the interval with the largest error estimate.
218 double errMax = abserr;
219 abserr = std::numeric_limits<double>::max();
220
221 // Count roundoff errors.
222 std::array<unsigned int, 3> nRoundOff = {0, 0, 0};
223 bool roundOffErrors = false;
224 double correc = 0.;
225
226 // Set flag whether the integrand is positive.
227 const bool pos = (std::abs(result) >= (1. - 50. * eps) * resabs0);
228
229 // Main loop.
230 bool dosum = false;
231 for (nIntervals = 2; nIntervals <= nMaxIntervals; ++nIntervals) {
232 // Bisect the subinterval.
233 const double a1 = (*it).a;
234 const double b2 = (*it).b;
235 const double b1 = 0.5 * (a1 + b2);
236 const double a2 = b1;
237 // Save the error on the interval before doing the subdivision.
238 const double errLast = (*it).e;
239 double area1 = 0., err1 = 0., resabs1 = 0., resasc1 = 0.;
240 qk15i(f, bound, inf, a1, b1, area1, err1, resabs1, resasc1);
241 double area2 = 0., err2 = 0., resabs2 = 0., resasc2 = 0.;
242 qk15i(f, bound, inf, a2, b2, area2, err2, resabs2, resasc2);
243 // Improve previous approximations to integral and error
244 // and test for accuracy.
245 const double area12 = area1 + area2;
246 const double err12 = err1 + err2;
247 errSum += err12 - errMax;
248 area += area12 - (*it).r;
249 if (resasc1 != err1 && resasc2 != err2) {
250 if (std::abs((*it).r - area12) <= 1.e-5 * std::abs(area12) &&
251 err12 >= 0.99 * errMax) {
252 if (extrap) {
253 ++nRoundOff[1];
254 } else {
255 ++nRoundOff[0];
256 }
257 }
258 if (nIntervals > 10 && err12 > errMax) ++nRoundOff[2];
259 }
260 tol = std::max(epsabs, epsrel * std::abs(area));
261 // Test for roundoff error and eventually set error flag.
262 if (nRoundOff[0] + nRoundOff[1] >= 10 || nRoundOff[2] >= 20) status = 2;
263 if (nRoundOff[1] >= 5) roundOffErrors = true;
264 // Set error flag in the case that the number of subintervals equals limit.
265 if (nIntervals == nMaxIntervals) status = 1;
266 // Set error flag in the case of bad integrand behaviour
267 // at some points of the integration range.
268 constexpr double tol1 = 1. + 100. * eps;
269 constexpr double tol2 = 1000. * std::numeric_limits<double>::min();
270 if (std::max(std::abs(a1), std::abs(b2)) <= tol1 * (std::abs(a2) + tol2)) {
271 status = 4;
272 }
273 // Append the newly-created intervals to the list.
274 if (err2 > err1) {
275 (*it).a = a2;
276 (*it).r = area2;
277 (*it).e = err2;
278 Interval interval;
279 interval.a = a1;
280 interval.b = b1;
281 interval.r = area1;
282 interval.e = err1;
283 intervals.push_back(std::move(interval));
284 } else {
285 (*it).b = b1;
286 (*it).r = area1;
287 (*it).e = err1;
288 Interval interval;
289 interval.a = a2;
290 interval.b = b2;
291 interval.r = area2;
292 interval.e = err2;
293 intervals.push_back(std::move(interval));
294 }
295 // Sort the intervals in descending order by error estimate.
296 std::sort(intervals.begin(), intervals.end(),
297 [](const Interval& lhs, const Interval& rhs) {
298 return (lhs.e > rhs.e);
299 });
300 // Select the subinterval to be bisected next.
301 it = intervals.begin() + nrmax;
302 errMax = (*it).e;
303 if (errSum <= tol) {
304 dosum = true;
305 break;
306 }
307 if (status != 0) break;
308 if (nIntervals == 2) {
309 errLarge = errSum;
310 errTest = tol;
311 epstab[1] = area;
312 continue;
313 }
314 if (noext) continue;
315 errLarge -= errLast;
316 if (std::abs(b1 - a1) > small) errLarge += err12;
317 if (!extrap) {
318 // Test whether the interval to be bisected next is the smallest one.
319 if (std::abs((*it).b - (*it).a) > small) continue;
320 extrap = true;
321 nrmax = 1;
322 }
323 // The smallest interval has the largest error.
324 // Before bisecting decrease the sum of the errors over the
325 // larger intervals (errLarge) and perform extrapolation.
326 if (!roundOffErrors && errLarge > errTest) {
327 const size_t k0 = nrmax;
328 size_t k1 = nIntervals;
329 if (nIntervals > (2 + nMaxIntervals / 2)) {
330 k1 = nMaxIntervals + 3 - nIntervals;
331 }
332 bool found = false;
333 for (unsigned int k = k0; k < k1; ++k) {
334 it = intervals.begin() + nrmax;
335 errMax = (*it).e;
336 if (std::abs((*it).b - (*it).a) > small) {
337 found = true;
338 break;
339 }
340 ++nrmax;
341 }
342 if (found) continue;
343 }
344 // Perform extrapolation.
345 epstab[nEps] = area;
346 ++nEps;
347 double resExtr = 0., errExtr = 0.;
348 qelg(nEps, epstab, resExtr, errExtr, lastRes, nRes);
349 ++ktmin;
350 if (ktmin > 5 && abserr < 1.e-3 * errSum) status = 5;
351 if (errExtr < abserr) {
352 ktmin = 0;
353 abserr = errExtr;
354 result = resExtr;
355 correc = errLarge;
356 errTest = std::max(epsabs, epsrel * std::abs(resExtr));
357 if (abserr <= errTest) break;
358 }
359 // Prepare bisection of the smallest interval.
360 if (nEps == 1) noext = true;
361 if (status == 5) break;
362 it = intervals.begin();
363 errMax = (*it).e;
364 nrmax = 0;
365 extrap = false;
366 small *= 0.5;
367 errLarge = errSum;
368 }
369 // Set final result and error estimate.
370 if (abserr == std::numeric_limits<double>::max()) dosum = true;
371 if (!dosum) {
372 if ((status != 0 || roundOffErrors)) {
373 if (roundOffErrors) {
374 abserr += correc;
375 if (status == 0) status = 3;
376 }
377 if (result != 0. && area != 0.) {
378 if (abserr / std::abs(result) > errSum / std::abs(area)) dosum = true;
379 } else {
380 if (abserr > errSum) {
381 dosum = true;
382 } else if (area == 0.) {
383 if (status > 2) --status;
384 return;
385 }
386 }
387 }
388 // Test on divergence
389 if (!dosum) {
390 if (!pos && std::max(std::abs(result), std::abs(area)) <= resabs0 * 0.01) {
391 if (status > 2) --status;
392 return;
393 }
394 const double r = result / area;
395 if (r < 0.01 || r > 100. || errSum > std::abs(area)) {
396 status = 5;
397 return;
398 }
399 }
400 } else {
401 // Compute global integral sum.
402 result = 0.;
403 for (const auto& interval : intervals) result += interval.r;
404 abserr = errSum;
405 if (status > 2) --status;
406 }
407}
408
409void qk15i(std::function<double(double)> f, double bound, const int inf,
410 const double a, const double b, double& result, double& abserr,
411 double& resabs, double& resasc) {
412
413 // The abscissae and weights are supplied for the interval (-1, 1).
414 // Because of symmetry only the positive abscissae and
415 // their corresponding weights are given.
416
417 // Weights of the 7-point Gauss rule.
418 constexpr double wg[8] = {0., 0.129484966168869693270611432679082,
419 0., 0.279705391489276667901467771423780,
420 0., 0.381830050505118944950369775488975,
421 0., 0.417959183673469387755102040816327};
422 // Abscissae of the 15-point Kronrod rule.
423 constexpr double xgk[8] = {
424 0.991455371120812639206854697526329,
425 0.949107912342758524526189684047851,
426 0.864864423359769072789712788640926,
427 0.741531185599394439863864773280788,
428 0.586087235467691130294144838258730,
429 0.405845151377397166906606412076961,
430 0.207784955007898467600689403773245,
431 0.};
432 // Weights of the 15-point Kronrod rule.
433 constexpr double wgk[8] = {
434 0.022935322010529224963732008058970,
435 0.063092092629978553290700663189204,
436 0.104790010322250183839876322541518,
437 0.140653259715525918745189590510238,
438 0.169004726639267902826583426598550,
439 0.190350578064785409913256402421014,
440 0.204432940075298892414161999234649,
441 0.209482141084727828012999174891714};
442
443 const int dinf = std::min(1, inf);
444
445 // Mid point of the interval.
446 const double xc = 0.5 * (a + b);
447 // Half-length of the interval.
448 const double h = 0.5 * (b - a);
449 // Transformed abscissa.
450 const double tc = bound + dinf * (1. - xc) / xc;
451 double fc = f(tc);
452 if (inf == 2) fc += f(-tc);
453 fc = (fc / xc) / xc;
454 // Result of the 7-point Gauss formula.
455 double resg = wg[7] * fc;
456 // Result of the 15-point Kronrod formula.
457 double resk = wgk[7] * fc;
458 resabs = std::abs(resk);
459 std::array<double, 7> fv1, fv2;
460 for (unsigned int j = 0; j < 7; ++j) {
461 const double x = h * xgk[j];
462 const double x1 = xc - x;
463 const double x2 = xc + x;
464 const double t1 = bound + dinf * (1. - x1) / x1;
465 const double t2 = bound + dinf * (1. - x2) / x2;
466 double y1 = f(t1);
467 double y2 = f(t2);
468 if (inf == 2) {
469 y1 += f(-t1);
470 y2 += f(-t2);
471 }
472 y1 = (y1 / x1) / x1;
473 y2 = (y2 / x2) / x2;
474 fv1[j] = y1;
475 fv2[j] = y2;
476 const double fsum = y1 + y2;
477 resg += wg[j] * fsum;
478 resk += wgk[j] * fsum;
479 resabs += wgk[j] * (std::abs(y1) + std::abs(y2));
480 }
481 // Approximation to the mean value of the transformed integrand over (a,b).
482 const double reskh = resk * 0.5;
483 resasc = wgk[7] * std::abs(fc - reskh);
484 for (unsigned int j = 0; j < 7; ++j) {
485 resasc += wgk[j] * (std::abs(fv1[j] - reskh) + std::abs(fv2[j] - reskh));
486 }
487 result = resk * h;
488 resasc *= h;
489 resabs *= h;
490 abserr = std::abs((resk - resg) * h);
491 if (resasc != 0. && abserr != 0.) {
492 abserr = resasc * std::min(1., pow(200. * abserr / resasc, 1.5));
493 }
494 constexpr double eps = 50. * std::numeric_limits<double>::epsilon();
495 if (resabs > std::numeric_limits<double>::min() / eps) {
496 abserr = std::max(eps * resabs, abserr);
497 }
498}
499
500void qk15(std::function<double(double)> f, const double a, const double b,
501 double& result, double& abserr, double& resabs, double& resasc) {
502
503 // Gauss quadrature weights and Kronron quadrature abscissae and weights
504 // as evaluated with 80 decimal digit arithmetic by L. W. Fullerton,
505 // Bell labs, Nov. 1981.
506
507 // Weights of the 7-point Gauss rule.
508 constexpr double wg[4] = {
509 0.129484966168869693270611432679082,
510 0.279705391489276667901467771423780,
511 0.381830050505118944950369775488975,
512 0.417959183673469387755102040816327};
513 // Abscissae of the 15-point Kronrod rule.
514 constexpr double xgk[8] = {
515 0.991455371120812639206854697526329,
516 0.949107912342758524526189684047851,
517 0.864864423359769072789712788640926,
518 0.741531185599394439863864773280788,
519 0.586087235467691130294144838258730,
520 0.405845151377397166906606412076961,
521 0.207784955007898467600689403773245,
522 0.};
523 // Weights of the 15-point Kronrod rule.
524 constexpr double wgk[8] = {
525 0.022935322010529224963732008058970,
526 0.063092092629978553290700663189204,
527 0.104790010322250183839876322541518,
528 0.140653259715525918745189590510238,
529 0.169004726639267902826583426598550,
530 0.190350578064785409913256402421014,
531 0.204432940075298892414161999234649,
532 0.209482141084727828012999174891714};
533
534 // Mid point of the interval.
535 const double xc = 0.5 * (a + b);
536 // Half-length of the interval.
537 const double h = 0.5 * (b - a);
538 const double dh = std::abs(h);
539 // Compute the 15-point Kronrod approximation to the integral,
540 // and estimate the absolute error.
541 const double fc = f(xc);
542 // Result of the 7-point Gauss formula.
543 double resg = fc * wg[3];
544 // Result of the 15-point Kronrod formula.
545 double resk = fc * wgk[7];
546 resabs = std::abs(resk);
547 std::array<double, 7> fv1, fv2;
548 for (unsigned int j = 0; j < 3; ++j) {
549 const unsigned int k = j * 2 + 1;
550 const double x = h * xgk[k];
551 double y1 = f(xc - x);
552 double y2 = f(xc + x);
553 fv1[k] = y1;
554 fv2[k] = y2;
555 const double fsum = y1 + y2;
556 resg += wg[j] * fsum;
557 resk += wgk[k] * fsum;
558 resabs += wgk[k] * (std::abs(y1) + std::abs(y2));
559 }
560 for (unsigned int j = 0; j < 4; ++j) {
561 const unsigned int k = j * 2;
562 const double x = h * xgk[k];
563 const double y1 = f(xc - x);
564 const double y2 = f(xc + x);
565 fv1[k] = y1;
566 fv2[k] = y2;
567 const double fsum = y1 + y2;
568 resk += wgk[k] * fsum;
569 resabs += wgk[k] * (std::abs(y1) + std::abs(y2));
570 }
571 // Approximation to the mean value of f over (a,b), i.e. to i/(b-a).
572 const double reskh = resk * 0.5;
573 resasc = wgk[7] * std::abs(fc - reskh);
574 for (unsigned int j = 0; j < 7; ++j) {
575 resasc += wgk[j] * (std::abs(fv1[j] - reskh) + std::abs(fv2[j] - reskh));
576 }
577 result = resk * h;
578 resabs *= dh;
579 resasc *= dh;
580 abserr = std::abs((resk - resg) * h);
581 if (resasc != 0. && abserr != 0.) {
582 abserr = resasc * std::min(1., pow(200. * abserr / resasc, 1.5));
583 }
584 constexpr double eps = 50. * std::numeric_limits<double>::epsilon();
585 if (resabs > std::numeric_limits<double>::min() / eps) {
586 abserr = std::max(eps * resabs, abserr);
587 }
588}
589
590}
591
592namespace CERNLIB {
593
594int deqn(const int n, std::vector<std::vector<double> >& a,
595 std::vector<double>& b) {
596
597 // REPLACES B BY THE SOLUTION X OF A*X=B, AFTER WHICH A IS UNDEFINED.
598
599 if (n < 1) return 1;
600 if (n == 1) {
601 if (a[0][0] == 0.) return -1;
602 const double s = 1. / a[0][0];
603 b[0] *= s;
604 } else if (n == 2) {
605 // Cramer's rule.
606 const double det = a[0][0] * a[1][1] - a[0][1] * a[1][0];
607 if (det == 0.) return -1;
608 const double s = 1. / det;
609 const double b1 = b[0];
610 b[0] = s * ( a[1][1] * b1 - a[0][1] * b[1]);
611 b[1] = s * (-a[1][0] * b1 + a[0][0] * b[1]);
612 } else if (n == 3) {
613 // Factorize matrix A=L*U.
614 // First pivot search.
615 const double t1 = std::abs(a[0][0]);
616 const double t2 = std::abs(a[1][0]);
617 const double t3 = std::abs(a[2][0]);
618 unsigned int m1 = 0, m2 = 0, m3 = 0;
619 if (t1 < t2 && t3 < t2) {
620 // Pivot is A21
621 m1 = 1;
622 m2 = 0;
623 m3 = 2;
624 } else if (t2 < t1 && t3 < t1) {
625 // Pivot is A11
626 m1 = 0;
627 m2 = 1;
628 m3 = 2;
629 } else {
630 // Pivot is A31
631 m1 = 2;
632 m2 = 1;
633 m3 = 0;
634 }
635 double temp = a[m1][0];
636 if (temp == 0.) return deqnGen(n, a, b);
637 const double l11 = 1. / temp;
638 const double u12 = l11 * a[m1][1];
639 const double u13 = l11 * a[m1][2];
640 double l22 = a[m2][1] - a[m2][0] * u12;
641 double l32 = a[m3][1] - a[m3][0] * u12;
642 // Second pivot search.
643 if (std::abs(l22) < std::abs(l32)) {
644 std::swap(m2, m3);
645 std::swap(l22, l32);
646 }
647 double l21 = a[m2][0];
648 double l31 = a[m3][0];
649 if (l22 == 0.) return deqnGen(n, a, b);
650 l22 = 1. / l22;
651 const double u23 = l22 * (a[m2][2] - l21 * u13);
652 temp = a[m3][2] - l31 * u13 - l32 * u23;
653 if (temp == 0.) return deqnGen(n, a, b);
654 const double l33 = 1. / temp;
655
656 // Solve L*Y=B and U*X=Y.
657 const double y1 = l11 * b[m1];
658 const double y2 = l22 * (b[m2] - l21 * y1);
659 b[2] = l33 * (b[m3] - l31 * y1 - l32 * y2);
660 b[1] = y2 - u23 * b[2];
661 b[0] = y1 - u12 * b[1] - u13 * b[2];
662 } else {
663 // N > 3 cases. Factorize matrix and solve system.
664 return deqnGen(n, a, b);
665 }
666 return 0;
667}
668
669void dfact(const int n, std::vector<std::vector<double> >& a,
670 std::vector<int>& ir, int& ifail, double& det, int& jfail) {
671 constexpr double g1 = 1.e-19;
672 constexpr double g2 = 1.e-19;
673
674 double t;
675 int k;
676
677 ifail = jfail = 0;
678
679 int nxch = 0;
680 det = 1.;
681
682 for (int j = 1; j <= n; ++j) {
683 k = j;
684 double p = fabs(a[j - 1][j - 1]);
685 if (j == n) {
686 if (p <= 0.) {
687 det = 0.;
688 ifail = -1;
689 jfail = 0;
690 return;
691 }
692 det *= a[j - 1][j - 1];
693 a[j - 1][j - 1] = 1. / a[j - 1][j - 1];
694 t = fabs(det);
695 if (t < g1) {
696 det = 0.;
697 if (jfail == 0) jfail = -1;
698 } else if (t > g2) {
699 det = 1.;
700 if (jfail == 0) jfail = +1;
701 }
702 continue;
703 }
704 for (int i = j + 1; i <= n; ++i) {
705 double q = std::abs(a[i - 1][j - 1]);
706 if (q <= p) continue;
707 k = i;
708 p = q;
709 }
710 if (k != j) {
711 for (int l = 1; l <= n; ++l) {
712 std::swap(a[j - 1][l - 1], a[k - 1][l - 1]);
713 }
714 ++nxch;
715 ir[nxch - 1] = j * 4096 + k;
716 } else if (p <= 0.) {
717 det = 0.;
718 ifail = -1;
719 jfail = 0;
720 return;
721 }
722 det *= a[j - 1][j - 1];
723 a[j - 1][j - 1] = 1. / a[j - 1][j - 1];
724 t = fabs(det);
725 if (t < g1) {
726 det = 0.;
727 if (jfail == 0) jfail = -1;
728 } else if (t > g2) {
729 det = 1.;
730 if (jfail == 0) jfail = +1;
731 }
732 for (k = j + 1; k <= n; ++k) {
733 double s11 = -a[j - 1][k - 1];
734 double s12 = -a[k - 1][j];
735 if (j == 1) {
736 a[j - 1][k - 1] = -s11 * a[j - 1][j - 1];
737 a[k - 1][j] = -(s12 + a[j - 1][j] * a[k - 1][j - 1]);
738 continue;
739 }
740 for (int i = 1; i <= j - 1; ++i) {
741 s11 += a[i - 1][k - 1] * a[j - 1][i - 1];
742 s12 += a[i - 1][j] * a[k - 1][i - 1];
743 }
744 a[j - 1][k - 1] = -s11 * a[j - 1][j - 1];
745 a[k - 1][j] = -a[j - 1][j] * a[k - 1][j - 1] - s12;
746 }
747 }
748
749 if (nxch % 2 != 0) det = -det;
750 if (jfail != 0) det = 0.;
751 ir[n - 1] = nxch;
752}
753
754void dfeqn(const int n, std::vector<std::vector<double> >& a,
755 std::vector<int>& ir, std::vector<double>& b) {
756 if (n <= 0) return;
757
758 int nxch = ir[n - 1];
759 if (nxch != 0) {
760 for (int m = 1; m <= nxch; ++m) {
761 const int ij = ir[m - 1];
762 const int i = ij / 4096;
763 const int j = ij % 4096;
764 std::swap(b[i - 1], b[j - 1]);
765 }
766 }
767
768 b[0] *= a[0][0];
769 if (n == 1) return;
770
771 for (int i = 2; i <= n; ++i) {
772 double s21 = -b[i - 1];
773 for (int j = 1; j <= i - 1; ++j) {
774 s21 += a[i - 1][j - 1] * b[j - 1];
775 }
776 b[i - 1] = -a[i - 1][i - 1] * s21;
777 }
778
779 for (int i = 1; i <= n - 1; ++i) {
780 double s22 = -b[n - i - 1];
781 for (int j = 1; j <= i; ++j) {
782 s22 += a[n - i - 1][n - j] * b[n - j];
783 }
784 b[n - i - 1] = -s22;
785 }
786}
787
788int dinv(const int n, std::vector<std::vector<double> >& a) {
789
790 if (n < 1) return 1;
791 if (n > 3) {
792 // Factorize matrix and invert.
793 double det = 0.;
794 int ifail = 0;
795 int jfail = 0;
796 std::vector<int> ir(n, 0);
797 dfact(n, a, ir, ifail, det, jfail);
798 if (ifail != 0) return ifail;
799 dfinv(n, a, ir);
800 } else if (n == 3) {
801 // Compute cofactors.
802 const double c11 = a[1][1] * a[2][2] - a[1][2] * a[2][1];
803 const double c12 = a[1][2] * a[2][0] - a[1][0] * a[2][2];
804 const double c13 = a[1][0] * a[2][1] - a[1][1] * a[2][0];
805 const double c21 = a[2][1] * a[0][2] - a[2][2] * a[0][1];
806 const double c22 = a[2][2] * a[0][0] - a[2][0] * a[0][2];
807 const double c23 = a[2][0] * a[0][1] - a[2][1] * a[0][0];
808 const double c31 = a[0][1] * a[1][2] - a[0][2] * a[1][1];
809 const double c32 = a[0][2] * a[1][0] - a[0][0] * a[1][2];
810 const double c33 = a[0][0] * a[1][1] - a[0][1] * a[1][0];
811 const double t1 = fabs(a[0][0]);
812 const double t2 = fabs(a[1][0]);
813 const double t3 = fabs(a[2][0]);
814 double det = 0.;
815 double pivot = 0.;
816 if (t2 < t1 && t3 < t1) {
817 pivot = a[0][0];
818 det = c22 * c33 - c23 * c32;
819 } else if (t1 < t2 && t3 < t2) {
820 pivot = a[1][0];
821 det = c13 * c32 - c12 * c33;
822 } else {
823 pivot = a[2][0];
824 det = c23 * c12 - c22 * c13;
825 }
826 // Set elements of inverse in A.
827 if (det == 0.) return -1;
828 double s = pivot / det;
829 a[0][0] = s * c11;
830 a[0][1] = s * c21;
831 a[0][2] = s * c31;
832 a[1][0] = s * c12;
833 a[1][1] = s * c22;
834 a[1][2] = s * c32;
835 a[2][0] = s * c13;
836 a[2][1] = s * c23;
837 a[2][2] = s * c33;
838 } else if (n == 2) {
839 // Cramer's rule.
840 const double det = a[0][0] * a[1][1] - a[0][1] * a[1][0];
841 if (det == 0.) return -1;
842 const double s = 1. / det;
843 const double c11 = s * a[1][1];
844 a[0][1] = -s * a[0][1];
845 a[1][0] = -s * a[1][0];
846 a[1][1] = s * a[0][0];
847 a[0][0] = c11;
848 } else if (n == 1) {
849 if (a[0][0] == 0.) return -1;
850 a[0][0] = 1. / a[0][0];
851 }
852 return 0;
853}
854
855void dfinv(const int n, std::vector<std::vector<double> >& a,
856 std::vector<int>& ir) {
857
858 if (n <= 1) return;
859 a[1][0] = -a[1][1] * a[0][0] * a[1][0];
860 a[0][1] = -a[0][1];
861 if (n > 2) {
862 for (int i = 3; i <= n; ++i) {
863 for (int j = 1; j <= i - 2; ++j) {
864 double s31 = 0.;
865 double s32 = a[j - 1][i - 1];
866 for (int k = j; k <= i - 2; ++k) {
867 s31 += a[k - 1][j - 1] * a[i - 1][k - 1];
868 s32 += a[j - 1][k] * a[k][i - 1];
869 }
870 a[i - 1][j - 1] =
871 -a[i - 1][i - 1] * (s31 + a[i - 2][j - 1] * a[i - 1][i - 2]);
872 a[j - 1][i - 1] = -s32;
873 }
874 a[i - 1][i - 2] = -a[i - 1][i - 1] * a[i - 2][i - 2] * a[i - 1][i - 2];
875 a[i - 2][i - 1] = -a[i - 2][i - 1];
876 }
877 }
878
879 for (int i = 1; i <= n - 1; ++i) {
880 for (int j = 1; j <= i; ++j) {
881 double s33 = a[i - 1][j - 1];
882 for (int k = 1; k <= n - i; ++k) {
883 s33 += a[i + k - 1][j - 1] * a[i - 1][i + k - 1];
884 }
885 a[i - 1][j - 1] = s33;
886 }
887 for (int j = 1; j <= n - i; ++j) {
888 double s34 = 0.;
889 for (int k = j; k <= n - i; ++k) {
890 s34 += a[i + k - 1][i + j - 1] * a[i - 1][i + k - 1];
891 }
892 a[i - 1][i + j - 1] = s34;
893 }
894 }
895
896 int nxch = ir[n - 1];
897 if (nxch == 0) return;
898
899 for (int m = 1; m <= nxch; ++m) {
900 int k = nxch - m + 1;
901 int ij = ir[k - 1];
902 int i = ij / 4096;
903 int j = ij % 4096;
904 for (k = 1; k <= n; ++k) {
905 std::swap(a[k - 1][i - 1], a[k - 1][j - 1]);
906 }
907 }
908}
909
910int deqinv(const int n, std::vector<std::vector<double> >& a,
911 std::vector<double>& b) {
912
913 // Test for parameter errors.
914 if (n < 1) return 1;
915
916 double det = 0.;
917 if (n > 3) {
918 // n > 3 cases. Factorize matrix, invert and solve system.
919 std::vector<int> ir(n, 0);
920 int ifail = 0, jfail = 0;
921 dfact(n, a, ir, ifail, det, jfail);
922 if (ifail != 0) return ifail;
923 dfeqn(n, a, ir, b);
924 dfinv(n, a, ir);
925 } else if (n == 3) {
926 // n = 3 case. Compute cofactors.
927 const double c11 = a[1][1] * a[2][2] - a[1][2] * a[2][1];
928 const double c12 = a[1][2] * a[2][0] - a[1][0] * a[2][2];
929 const double c13 = a[1][0] * a[2][1] - a[1][1] * a[2][0];
930 const double c21 = a[2][1] * a[0][2] - a[2][2] * a[0][1];
931 const double c22 = a[2][2] * a[0][0] - a[2][0] * a[0][2];
932 const double c23 = a[2][0] * a[0][1] - a[2][1] * a[0][0];
933 const double c31 = a[0][1] * a[1][2] - a[0][2] * a[1][1];
934 const double c32 = a[0][2] * a[1][0] - a[0][0] * a[1][2];
935 const double c33 = a[0][0] * a[1][1] - a[0][1] * a[1][0];
936 const double t1 = fabs(a[0][0]);
937 const double t2 = fabs(a[1][0]);
938 const double t3 = fabs(a[2][0]);
939
940 // Set temp = pivot and det = pivot * det.
941 double temp = 0.;
942 if (t2 < t1 && t3 < t1) {
943 temp = a[0][0];
944 det = c22 * c33 - c23 * c32;
945 } else if (t1 < t2 && t3 < t2) {
946 temp = a[1][0];
947 det = c13 * c32 - c12 * c33;
948 } else {
949 temp = a[2][0];
950 det = c23 * c12 - c22 * c13;
951 }
952
953 // Set elements of inverse in A.
954 if (det == 0.) return -1;
955 const double s = temp / det;
956 a[0][0] = s * c11;
957 a[0][1] = s * c21;
958 a[0][2] = s * c31;
959 a[1][0] = s * c12;
960 a[1][1] = s * c22;
961 a[1][2] = s * c32;
962 a[2][0] = s * c13;
963 a[2][1] = s * c23;
964 a[2][2] = s * c33;
965
966 // Replace b by Ainv * b.
967 const double b1 = b[0];
968 const double b2 = b[1];
969 b[0] = a[0][0] * b1 + a[0][1] * b2 + a[0][2] * b[2];
970 b[1] = a[1][0] * b1 + a[1][1] * b2 + a[1][2] * b[2];
971 b[2] = a[2][0] * b1 + a[2][1] * b2 + a[2][2] * b[2];
972 } else if (n == 2) {
973 // n = 2 case by Cramer's rule.
974 det = a[0][0] * a[1][1] - a[0][1] * a[1][0];
975 if (det == 0.) return -1;
976 const double s = 1. / det;
977 const double c11 = s * a[1][1];
978 a[0][1] = -s * a[0][1];
979 a[1][0] = -s * a[1][0];
980 a[1][1] = s * a[0][0];
981 a[0][0] = c11;
982
983 const double b1 = b[0];
984 b[0] = c11 * b1 + a[0][1] * b[1];
985 b[1] = a[1][0] * b1 + a[1][1] * b[1];
986 } else {
987 // n = 1 case.
988 if (a[0][0] == 0.) return -1;
989 a[0][0] = 1. / a[0][0];
990 b[0] = a[0][0] * b[0];
991 }
992 return 0;
993}
994
995void cfact(const int n, std::vector<std::vector<std::complex<double> > >& a,
996 std::vector<int>& ir, int& ifail, std::complex<double>& det,
997 int& jfail) {
998 constexpr double g1 = 1.e-19;
999 constexpr double g2 = 1.e-19;
1000
1001 ifail = jfail = 0;
1002
1003 int nxch = 0;
1004 det = std::complex<double>(1., 0.);
1005
1006 for (int j = 1; j <= n; ++j) {
1007 int k = j;
1008 double p = std::max(fabs(real(a[j - 1][j - 1])), fabs(imag(a[j - 1][j - 1])));
1009 if (j == n) {
1010 if (p <= 0.) {
1011 det = std::complex<double>(0., 0.);
1012 ifail = -1;
1013 jfail = 0;
1014 return;
1015 }
1016 det *= a[j - 1][j - 1];
1017 a[j - 1][j - 1] = std::complex<double>(1., 0.) / a[j - 1][j - 1];
1018 const double t = std::max(fabs(real(det)), fabs(imag(det)));
1019 if (t < g1) {
1020 det = std::complex<double>(0., 0.);
1021 if (jfail == 0) jfail = -1;
1022 } else if (t > g2) {
1023 det = std::complex<double>(1., 0.);
1024 if (jfail == 0) jfail = +1;
1025 }
1026 continue;
1027 }
1028 for (int i = j + 1; i <= n; ++i) {
1029 double q = std::max(fabs(real(a[i - 1][j - 1])), fabs(imag(a[i - 1][j - 1])));
1030 if (q <= p) continue;
1031 k = i;
1032 p = q;
1033 }
1034 if (k != j) {
1035 for (int l = 1; l <= n; ++l) {
1036 const auto tf = a[j - 1][l - 1];
1037 a[j - 1][l - 1] = a[k - 1][l - 1];
1038 a[k - 1][l - 1] = tf;
1039 }
1040 ++nxch;
1041 ir[nxch - 1] = j * 4096 + k;
1042 } else if (p <= 0.) {
1043 det = std::complex<double>(0., 0.);
1044 ifail = -1;
1045 jfail = 0;
1046 return;
1047 }
1048 det *= a[j - 1][j - 1];
1049 a[j - 1][j - 1] = 1. / a[j - 1][j - 1];
1050 const double t = std::max(fabs(real(det)), fabs(imag(det)));
1051 if (t < g1) {
1052 det = std::complex<double>(0., 0.);
1053 if (jfail == 0) jfail = -1;
1054 } else if (t > g2) {
1055 det = std::complex<double>(1., 0.);
1056 if (jfail == 0) jfail = +1;
1057 }
1058 for (k = j + 1; k <= n; ++k) {
1059 auto s11 = -a[j - 1][k - 1];
1060 auto s12 = -a[k - 1][j];
1061 if (j == 1) {
1062 a[j - 1][k - 1] = -s11 * a[j - 1][j - 1];
1063 a[k - 1][j] = -(s12 + a[j - 1][j] * a[k - 1][j - 1]);
1064 continue;
1065 }
1066 for (int i = 1; i <= j - 1; ++i) {
1067 s11 += a[i - 1][k - 1] * a[j - 1][i - 1];
1068 s12 += a[i - 1][j] * a[k - 1][i - 1];
1069 }
1070 a[j - 1][k - 1] = -s11 * a[j - 1][j - 1];
1071 a[k - 1][j] = -a[j - 1][j] * a[k - 1][j - 1] - s12;
1072 }
1073 }
1074
1075 if (nxch % 2 != 0) det = -det;
1076 if (jfail != 0) det = std::complex<double>(0., 0.);
1077 ir[n - 1] = nxch;
1078}
1079
1080void cfinv(const int n, std::vector<std::vector<std::complex<double> > >& a,
1081 std::vector<int>& ir) {
1082
1083 if (n <= 1) return;
1084 a[1][0] = -a[1][1] * a[0][0] * a[1][0];
1085 a[0][1] = -a[0][1];
1086 if (n > 2) {
1087 for (int i = 3; i <= n; ++i) {
1088 for (int j = 1; j <= i - 2; ++j) {
1089 auto s31 = std::complex<double>(0., 0.);
1090 auto s32 = a[j - 1][i - 1];
1091 for (int k = j; k <= i - 2; ++k) {
1092 s31 += a[k - 1][j - 1] * a[i - 1][k - 1];
1093 s32 += a[j - 1][k] * a[k][i - 1];
1094 }
1095 a[i - 1][j - 1] =
1096 -a[i - 1][i - 1] * (s31 + a[i - 2][j - 1] * a[i - 1][i - 2]);
1097 a[j - 1][i - 1] = -s32;
1098 }
1099 a[i - 1][i - 2] = -a[i - 1][i - 1] * a[i - 2][i - 2] * a[i - 1][i - 2];
1100 a[i - 2][i - 1] = -a[i - 2][i - 1];
1101 }
1102 }
1103
1104 for (int i = 1; i <= n - 1; ++i) {
1105 for (int j = 1; j <= i; ++j) {
1106 auto s33 = a[i - 1][j - 1];
1107 for (int k = 1; k <= n - i; ++k) {
1108 s33 += a[i + k - 1][j - 1] * a[i - 1][i + k - 1];
1109 }
1110 a[i - 1][j - 1] = s33;
1111 }
1112 for (int j = 1; j <= n - i; ++j) {
1113 std::complex<double> s34(0., 0.);
1114 for (int k = j; k <= n - i; ++k) {
1115 s34 += a[i + k - 1][i + j - 1] * a[i - 1][i + k - 1];
1116 }
1117 a[i - 1][i + j - 1] = s34;
1118 }
1119 }
1120
1121 int nxch = ir[n - 1];
1122 if (nxch == 0) return;
1123
1124 for (int m = 1; m <= nxch; ++m) {
1125 int k = nxch - m + 1;
1126 const int ij = ir[k - 1];
1127 const int i = ij / 4096;
1128 const int j = ij % 4096;
1129 for (k = 1; k <= n; ++k) {
1130 std::swap(a[k - 1][i - 1], a[k - 1][j - 1]);
1131 }
1132 }
1133}
1134
1135int cinv(const int n, std::vector<std::vector<std::complex<double> > >& a) {
1136
1137 // Test for parameter errors.
1138 if (n < 1) return 1;
1139
1140 std::complex<double> det(0., 0.);
1141 if (n > 3) {
1142 // n > 3 cases. Factorize matrix and invert.
1143 std::vector<int> ir(n, 0);
1144 int ifail = 0, jfail = 0;
1145 cfact(n, a, ir, ifail, det, jfail);
1146 if (ifail != 0) return ifail;
1147 cfinv(n, a, ir);
1148 } else if (n == 3) {
1149 // n = 3 case. Compute cofactors.
1150 const auto c11 = a[1][1] * a[2][2] - a[1][2] * a[2][1];
1151 const auto c12 = a[1][2] * a[2][0] - a[1][0] * a[2][2];
1152 const auto c13 = a[1][0] * a[2][1] - a[1][1] * a[2][0];
1153 const auto c21 = a[2][1] * a[0][2] - a[2][2] * a[0][1];
1154 const auto c22 = a[2][2] * a[0][0] - a[2][0] * a[0][2];
1155 const auto c23 = a[2][0] * a[0][1] - a[2][1] * a[0][0];
1156 const auto c31 = a[0][1] * a[1][2] - a[0][2] * a[1][1];
1157 const auto c32 = a[0][2] * a[1][0] - a[0][0] * a[1][2];
1158 const auto c33 = a[0][0] * a[1][1] - a[0][1] * a[1][0];
1159 const double t1 = fabs(real(a[0][0])) + fabs(imag(a[0][0]));
1160 const double t2 = fabs(real(a[1][0])) + fabs(imag(a[1][0]));
1161 const double t3 = fabs(real(a[2][0])) + fabs(imag(a[2][0]));
1162
1163 // Set temp = pivot and det = pivot * det.
1164 std::complex<double> temp(0., 0.);
1165 if (t2 < t1 && t3 < t1) {
1166 temp = a[0][0];
1167 det = c22 * c33 - c23 * c32;
1168 } else if (t1 < t2 && t3 < t2) {
1169 temp = a[1][0];
1170 det = c13 * c32 - c12 * c33;
1171 } else {
1172 temp = a[2][0];
1173 det = c23 * c12 - c22 * c13;
1174 }
1175 // Set elements of inverse in A.
1176 if (real(det) == 0. && imag(det) == 0.) return -1;
1177 const auto s = temp / det;
1178 a[0][0] = s * c11;
1179 a[0][1] = s * c21;
1180 a[0][2] = s * c31;
1181 a[1][0] = s * c12;
1182 a[1][1] = s * c22;
1183 a[1][2] = s * c32;
1184 a[2][0] = s * c13;
1185 a[2][1] = s * c23;
1186 a[2][2] = s * c33;
1187 } else if (n == 2) {
1188 // n=2 case by Cramer's rule.
1189 det = a[0][0] * a[1][1] - a[0][1] * a[1][0];
1190 if (real(det) == 0. && imag(det) == 0.) return -1;
1191 const auto s = std::complex<double>(1., 0.) / det;
1192 const auto c11 = s * a[1][1];
1193 a[0][1] = -s * a[0][1];
1194 a[1][0] = -s * a[1][0];
1195 a[1][1] = s * a[0][0];
1196 a[0][0] = c11;
1197 } else {
1198 // n = 1 case.
1199 if (real(a[0][0]) == 0. && imag(a[0][0]) == 0.) return -1;
1200 a[0][0] = std::complex<double>(1., 0.) / a[0][0];
1201 }
1202 return 0;
1203}
1204
1205void cfft(std::vector<std::complex<double> >& a, const int msign) {
1206
1207 if (msign == 0) return;
1208 const int m = std::abs(msign);
1209 const int n = pow(2, m);
1210 // Bit reversal.
1211 int j = 1;
1212 for (int i = 1; i <= n - 1; ++i) {
1213 if (i < j) std::swap(a[j - 1], a[i - 1]);
1214 int k = n / 2;
1215 while (k < j) {
1216 j -= k;
1217 k /= 2;
1218 }
1219 j += k;
1220 }
1221 for (int i = 1; i <= n; i += 2) {
1222 const auto t = a[i];
1223 a[i] = a[i - 1] - t;
1224 a[i - 1] += t;
1225 }
1226 if (m == 1) return;
1227 double c = 0.;
1228 double s = msign >= 0 ? 1. : -1.;
1229 int le = 2;
1230 for (int l = 2; l <= m; ++l) {
1231 std::complex<double> w(c, s);
1232 std::complex<double> u = w;
1233 c = sqrt(0.5 * c + 0.5);
1234 s = imag(w) / (c + c);
1235 int le1 = le;
1236 le = le1 + le1;
1237 for (int i = 1; i <= n; i += le) {
1238 const auto t = a[i + le1 - 1];
1239 a[i + le1 - 1] = a[i - 1] - t;
1240 a[i - 1] += t;
1241 }
1242 for (j = 2; j <= le1; ++j) {
1243 for (int i = j; i <= n; i += le) {
1244 const auto t = a[i + le1 - 1] * u;
1245 a[i + le1 - 1] = a[i - 1] - t;
1246 a[i - 1] += t;
1247 }
1248 u *= w;
1249 }
1250 }
1251}
1252
1253}
1254
1255double Divdif(const std::vector<double>& f, const std::vector<double>& a,
1256 const int nn, const double x, const int mm) {
1257
1258 double t[20], d[20];
1259
1260 // Check the arguments.
1261 if (nn < 2) {
1262 std::cerr << "Divdif: Array length < 2.\n";
1263 return 0.;
1264 }
1265 if (mm < 1) {
1266 std::cerr << "Divdif: Interpolation order < 1.\n";
1267 return 0.;
1268 }
1269
1270 // Deal with the case that X is located at first or last point.
1271 const double tol1 = 1.e-6 * fabs(fabs(a[1]) - fabs(a[0]));
1272 const double tol2 = 1.e-6 * fabs(fabs(a[nn-1]) - fabs(a[nn-2]));
1273 if (fabs(x - a[0]) < tol1) return f[0];
1274 if (fabs(x - a[nn - 1]) < tol2) return f[nn - 1];
1275
1276 // Find subscript IX of X in array A.
1277 constexpr int mmax = 10;
1278 const int m = std::min({mm, mmax, nn - 1});
1279 const int mplus = m + 1;
1280 int ix = 0;
1281 int iy = nn + 1;
1282 if (a[0] > a[nn - 1]) {
1283 // Search decreasing arguments.
1284 do {
1285 const int mid = (ix + iy) / 2;
1286 if (x > a[mid - 1]) {
1287 iy = mid;
1288 } else {
1289 ix = mid;
1290 }
1291 } while (iy - ix > 1);
1292 } else {
1293 // Search increasing arguments.
1294 do {
1295 const int mid = (ix + iy) / 2;
1296 if (x < a[mid - 1]) {
1297 iy = mid;
1298 } else {
1299 ix = mid;
1300 }
1301 } while (iy - ix > 1);
1302 }
1303 // Copy reordered interpolation points into (T[I],D[I]), setting
1304 // EXTRA to True if M+2 points to be used.
1305 int npts = m + 2 - (m % 2);
1306 int ip = 0;
1307 int l = 0;
1308 do {
1309 const int isub = ix + l;
1310 if ((1 > isub) || (isub > nn)) {
1311 // Skip point.
1312 npts = mplus;
1313 } else {
1314 // Insert point.
1315 ip++;
1316 t[ip - 1] = a[isub - 1];
1317 d[ip - 1] = f[isub - 1];
1318 }
1319 if (ip < npts) {
1320 l = -l;
1321 if (l >= 0) ++l;
1322 }
1323 } while (ip < npts);
1324
1325 const bool extra = npts != mplus;
1326 // Replace d by the leading diagonal of a divided-difference table,
1327 // supplemented by an extra line if EXTRA is True.
1328 for (l = 1; l <= m; l++) {
1329 if (extra) {
1330 const int isub = mplus - l;
1331 d[m + 1] = (d[m + 1] - d[m - 1]) / (t[m + 1] - t[isub - 1]);
1332 }
1333 int i = mplus;
1334 for (int j = l; j <= m; j++) {
1335 const int isub = i - l;
1336 d[i - 1] = (d[i - 1] - d[i - 2]) / (t[i - 1] - t[isub - 1]);
1337 i--;
1338 }
1339 }
1340 // Evaluate the Newton interpolation formula at X, averaging two values
1341 // of last difference if EXTRA is True.
1342 double sum = d[mplus - 1];
1343 if (extra) {
1344 sum = 0.5 * (sum + d[m + 1]);
1345 }
1346 int j = m;
1347 for (l = 1; l <= m; l++) {
1348 sum = d[j - 1] + (x - t[j - 1]) * sum;
1349 j--;
1350 }
1351 return sum;
1352}
1353
1354bool Boxin2(const std::vector<std::vector<double> >& value,
1355 const std::vector<double>& xAxis, const std::vector<double>& yAxis,
1356 const int nx, const int ny, const double x, const double y,
1357 double& f, const int iOrder) {
1358 //-----------------------------------------------------------------------
1359 // BOXIN2 - Interpolation of order 1 and 2 in an irregular rectangular
1360 // 2-dimensional grid.
1361 //-----------------------------------------------------------------------
1362 int iX0 = 0, iX1 = 0;
1363 int iY0 = 0, iY1 = 0;
1364 std::array<double, 3> fX;
1365 std::array<double, 3> fY;
1366 f = 0.;
1367 // Ensure we are in the grid.
1368 if ((xAxis[nx - 1] - x) * (x - xAxis[0]) < 0 ||
1369 (yAxis[ny - 1] - y) * (y - yAxis[0]) < 0) {
1370 std::cerr << "Boxin2: Point not in the grid; no interpolation.\n";
1371 return false;
1372 }
1373 // Make sure we have enough points.
1374 if (iOrder < 0 || iOrder > 2) {
1375 std::cerr << "Boxin2: Incorrect order; no interpolation.\n";
1376 return false;
1377 } else if (nx < 1 || ny < 1) {
1378 std::cerr << "Boxin2: Incorrect number of points; no interpolation.\n";
1379 return false;
1380 }
1381 if (iOrder == 0 || nx <= 1) {
1382 // Zeroth order interpolation in x.
1383 // Find the nearest node.
1384 double dist = fabs(x - xAxis[0]);
1385 int iNode = 0;
1386 for (int i = 1; i < nx; i++) {
1387 if (fabs(x - xAxis[i]) < dist) {
1388 dist = fabs(x - xAxis[i]);
1389 iNode = i;
1390 }
1391 }
1392 // Set the summing range.
1393 iX0 = iNode;
1394 iX1 = iNode;
1395 // Establish the shape functions.
1396 fX = {1., 0., 0.};
1397 } else if (iOrder == 1 || nx <= 2) {
1398 // First order interpolation in x.
1399 // Find the grid segment containing this point.
1400 int iGrid = 0;
1401 for (int i = 1; i < nx; i++) {
1402 if ((xAxis[i - 1] - x) * (x - xAxis[i]) >= 0.) {
1403 iGrid = i;
1404 }
1405 }
1406 const double x0 = xAxis[iGrid - 1];
1407 const double x1 = xAxis[iGrid];
1408 // Ensure there won't be divisions by zero.
1409 if (x1 == x0) {
1410 std::cerr << "Boxin2: Incorrect grid; no interpolation.\n";
1411 return false;
1412 }
1413 // Compute local coordinates.
1414 const double xL = (x - x0) / (x1 - x0);
1415 // Set the summing range.
1416 iX0 = iGrid - 1;
1417 iX1 = iGrid;
1418 // Set the shape functions.
1419 fX = {1. - xL, xL, 0.};
1420 } else if (iOrder == 2) {
1421 // Second order interpolation in x.
1422 // Find the nearest node and the grid segment.
1423 double dist = fabs(x - xAxis[0]);
1424 int iNode = 0;
1425 for (int i = 1; i < nx; ++i) {
1426 if (fabs(x - xAxis[i]) < dist) {
1427 dist = fabs(x - xAxis[i]);
1428 iNode = i;
1429 }
1430 }
1431 // Find the nearest fitting 2x2 matrix.
1432 int iGrid = std::max(1, std::min(nx - 2, iNode));
1433 const double x0 = xAxis[iGrid - 1];
1434 const double x1 = xAxis[iGrid];
1435 const double x2 = xAxis[iGrid + 1];
1436 // Ensure there won't be divisions by zero.
1437 if (x2 == x0) {
1438 std::cerr << "Boxin2: Incorrect grid; no interpolation.\n";
1439 return false;
1440 }
1441 // Compute the alpha and local coordinate for this grid segment.
1442 const double xAlpha = (x1 - x0) / (x2 - x0);
1443 const double xL = (x - x0) / (x2 - x0);
1444 // Ensure there won't be divisions by zero.
1445 if (xAlpha <= 0 || xAlpha >= 1) {
1446 std::cerr << "Boxin2: Incorrect grid; no interpolation.\n";
1447 return false;
1448 }
1449 // Set the summing range.
1450 iX0 = iGrid - 1;
1451 iX1 = iGrid + 1;
1452 // Set the shape functions.
1453 const double xL2 = xL * xL;
1454 fX[0] = xL2 / xAlpha - xL * (1. + xAlpha) / xAlpha + 1.;
1455 fX[1] = (xL2 - xL) / (xAlpha * xAlpha - xAlpha);
1456 fX[2] = (xL2 - xL * xAlpha) / (1. - xAlpha);
1457 }
1458 if (iOrder == 0 || ny <= 1) {
1459 // Zeroth order interpolation in y.
1460 // Find the nearest node.
1461 double dist = fabs(y - yAxis[0]);
1462 int iNode = 0;
1463 for (int i = 1; i < ny; i++) {
1464 if (fabs(y - yAxis[i]) < dist) {
1465 dist = fabs(y - yAxis[i]);
1466 iNode = i;
1467 }
1468 }
1469 // Set the summing range.
1470 iY0 = iNode;
1471 iY1 = iNode;
1472 // Establish the shape functions.
1473 fY = {1., 0., 0.};
1474 } else if (iOrder == 1 || ny <= 2) {
1475 // First order interpolation in y.
1476 // Find the grid segment containing this point.
1477 int iGrid = 0;
1478 for (int i = 1; i < ny; ++i) {
1479 if ((yAxis[i - 1] - y) * (y - yAxis[i]) >= 0) {
1480 iGrid = i;
1481 }
1482 }
1483 const double y0 = yAxis[iGrid - 1];
1484 const double y1 = yAxis[iGrid];
1485 // Ensure there won't be divisions by zero.
1486 if (y1 == y0) {
1487 std::cerr << "Boxin2: Incorrect grid; no interpolation.\n";
1488 return false;
1489 }
1490 // Compute local coordinates.
1491 const double yL = (y - y0) / (y1 - y0);
1492 // Set the summing range.
1493 iY0 = iGrid - 1;
1494 iY1 = iGrid;
1495 // Set the shape functions.
1496 fY = {1. - yL, yL, 0.};
1497 } else if (iOrder == 2) {
1498 // Second order interpolation in y.
1499 // Find the nearest node and the grid segment.
1500 double dist = fabs(y - yAxis[0]);
1501 int iNode = 0;
1502 for (int i = 1; i < ny; ++i) {
1503 if (fabs(y - yAxis[i]) < dist) {
1504 dist = fabs(y - yAxis[i]);
1505 iNode = i;
1506 }
1507 }
1508 // Find the nearest fitting 2x2 matrix.
1509 int iGrid = std::max(1, std::min(ny - 2, iNode));
1510 const double y0 = yAxis[iGrid - 1];
1511 const double y1 = yAxis[iGrid];
1512 const double y2 = yAxis[iGrid + 1];
1513 // Ensure there won't be divisions by zero.
1514 if (y2 == y0) {
1515 std::cerr << "Boxin2: Incorrect grid; no interpolation.\n";
1516 return false;
1517 }
1518 // Compute the alpha and local coordinate for this grid segment.
1519 const double yAlpha = (y1 - y0) / (y2 - y0);
1520 const double yL = (y - y0) / (y2 - y0);
1521 // Ensure there won't be divisions by zero.
1522 if (yAlpha <= 0 || yAlpha >= 1) {
1523 std::cerr << "Boxin2: Incorrect grid; no interpolation.\n";
1524 return false;
1525 }
1526 // Set the summing range.
1527 iY0 = iGrid - 1;
1528 iY1 = iGrid + 1;
1529 // Set the shape functions.
1530 const double yL2 = yL * yL;
1531 fY[0] = yL2 / yAlpha - yL * (1. + yAlpha) / yAlpha + 1.;
1532 fY[1] = (yL2 - yL) / (yAlpha * yAlpha - yAlpha);
1533 fY[2] = (yL2 - yL * yAlpha) / (1. - yAlpha);
1534 }
1535
1536 // Sum the shape functions.
1537 for (int i = iX0; i <= iX1; ++i) {
1538 for (int j = iY0; j <= iY1; ++j) {
1539 f += value[i][j] * fX[i - iX0] * fY[j - iY0];
1540 }
1541 }
1542 return true;
1543}
1544
1545bool Boxin3(const std::vector<std::vector<std::vector<double> > >& value,
1546 const std::vector<double>& xAxis, const std::vector<double>& yAxis,
1547 const std::vector<double>& zAxis, const int nx, const int ny,
1548 const int nz, const double xx, const double yy, const double zz,
1549 double& f, const int iOrder) {
1550 //-----------------------------------------------------------------------
1551 // BOXIN3 - interpolation of order 1 and 2 in an irregular rectangular
1552 // 3-dimensional grid.
1553 //-----------------------------------------------------------------------
1554 int iX0 = 0, iX1 = 0;
1555 int iY0 = 0, iY1 = 0;
1556 int iZ0 = 0, iZ1 = 0;
1557 std::array<double, 4> fX;
1558 std::array<double, 4> fY;
1559 std::array<double, 4> fZ;
1560
1561 f = 0.;
1562 // Ensure we are in the grid.
1563 const double x = std::min(std::max(xx, std::min(xAxis[0], xAxis[nx - 1])),
1564 std::max(xAxis[0], xAxis[nx - 1]));
1565 const double y = std::min(std::max(yy, std::min(yAxis[0], yAxis[ny - 1])),
1566 std::max(yAxis[0], yAxis[ny - 1]));
1567 const double z = std::min(std::max(zz, std::min(zAxis[0], zAxis[nz - 1])),
1568 std::max(zAxis[0], zAxis[nz - 1]));
1569
1570 // Make sure we have enough points.
1571 if (iOrder < 0 || iOrder > 2) {
1572 std::cerr << "Boxin3: Incorrect order; no interpolation.\n";
1573 return false;
1574 } else if (nx < 1 || ny < 1 || nz < 1) {
1575 std::cerr << "Boxin3: Incorrect number of points; no interpolation.\n";
1576 return false;
1577 }
1578 if (iOrder == 0 || nx == 1) {
1579 // Zeroth order interpolation in x.
1580 // Find the nearest node.
1581 double dist = fabs(x - xAxis[0]);
1582 int iNode = 0;
1583 for (int i = 1; i < nx; i++) {
1584 if (fabs(x - xAxis[i]) < dist) {
1585 dist = fabs(x - xAxis[i]);
1586 iNode = i;
1587 }
1588 }
1589 // Set the summing range.
1590 iX0 = iNode;
1591 iX1 = iNode;
1592 // Establish the shape functions.
1593 fX = {1., 0., 0., 0.};
1594 } else if (iOrder == 1 || nx == 2) {
1595 // First order interpolation in x.
1596 // Find the grid segment containing this point.
1597 int iGrid = 0;
1598 for (int i = 1; i < nx; i++) {
1599 if ((xAxis[i - 1] - x) * (x - xAxis[i]) >= 0.) {
1600 iGrid = i;
1601 }
1602 }
1603 const double x0 = xAxis[iGrid - 1];
1604 const double x1 = xAxis[iGrid];
1605 // Ensure there won't be divisions by zero.
1606 if (x1 == x0) {
1607 std::cerr << "Boxin3: Incorrect grid; no interpolation.\n";
1608 return false;
1609 }
1610 // Compute local coordinates.
1611 const double xL = (x - x0) / (x1 - x0);
1612 // Set the summing range.
1613 iX0 = iGrid - 1;
1614 iX1 = iGrid;
1615 // Set the shape functions.
1616 fX = {1. - xL, xL, 0., 0.};
1617 } else if (iOrder == 2) {
1618 // Second order interpolation in x.
1619 // Find the grid segment containing this point.
1620 int iGrid = 0;
1621 for (int i = 1; i < nx; i++) {
1622 if ((xAxis[i - 1] - x) * (x - xAxis[i]) >= 0.) {
1623 iGrid = i;
1624 }
1625 }
1626 if (iGrid == 1) {
1627 iX0 = iGrid - 1;
1628 iX1 = iGrid + 1;
1629 const double x0 = xAxis[iX0];
1630 const double x1 = xAxis[iX0 + 1];
1631 const double x2 = xAxis[iX0 + 2];
1632 if (x0 == x1 || x0 == x2 || x1 == x2) {
1633 std::cerr << "Boxin3: One or more grid points in x coincide.\n"
1634 << " No interpolation.\n";
1635 return false;
1636 }
1637 fX[0] = (x - x1) * (x - x2) / ((x0 - x1) * (x0 - x2));
1638 fX[1] = (x - x0) * (x - x2) / ((x1 - x0) * (x1 - x2));
1639 fX[2] = (x - x0) * (x - x1) / ((x2 - x0) * (x2 - x1));
1640 } else if (iGrid == nx - 1) {
1641 iX0 = iGrid - 2;
1642 iX1 = iGrid;
1643 const double x0 = xAxis[iX0];
1644 const double x1 = xAxis[iX0 + 1];
1645 const double x2 = xAxis[iX0 + 2];
1646 if (x0 == x1 || x0 == x2 || x1 == x2) {
1647 std::cerr << "Boxin3: One or more grid points in x coincide.\n"
1648 << " No interpolation.\n";
1649 return false;
1650 }
1651 fX[0] = (x - x1) * (x - x2) / ((x0 - x1) * (x0 - x2));
1652 fX[1] = (x - x0) * (x - x2) / ((x1 - x0) * (x1 - x2));
1653 fX[2] = (x - x0) * (x - x1) / ((x2 - x0) * (x2 - x1));
1654 } else {
1655 iX0 = iGrid - 2;
1656 iX1 = iGrid + 1;
1657 const double x0 = xAxis[iX0];
1658 const double x1 = xAxis[iX0 + 1];
1659 const double x2 = xAxis[iX0 + 2];
1660 const double x3 = xAxis[iX0 + 3];
1661 if (x0 == x1 || x0 == x2 || x0 == x3 ||
1662 x1 == x2 || x1 == x3 || x2 == x3) {
1663 std::cerr << "Boxin3: One or more grid points in x coincide.\n"
1664 << " No interpolation.\n";
1665 return false;
1666 }
1667 // Compute the local coordinate for this grid segment.
1668 const double xL = (x - x1) / (x2 - x1);
1669 fX[0] = ((x - x1) * (x - x2) / ((x0 - x1) * (x0 - x2))) * (1. - xL);
1670 fX[1] = ((x - x0) * (x - x2) / ((x1 - x0) * (x1 - x2))) * (1. - xL) +
1671 ((x - x2) * (x - x3) / ((x1 - x2) * (x1 - x3))) * xL;
1672 fX[2] = ((x - x0) * (x - x1) / ((x2 - x0) * (x2 - x1))) * (1. - xL) +
1673 ((x - x1) * (x - x3) / ((x2 - x1) * (x2 - x3))) * xL;
1674 fX[3] = ((x - x1) * (x - x2) / ((x3 - x1) * (x3 - x2))) * xL;
1675 }
1676 }
1677
1678 if (iOrder == 0 || ny == 1) {
1679 // Zeroth order interpolation in y.
1680 // Find the nearest node.
1681 double dist = fabs(y - yAxis[0]);
1682 int iNode = 0;
1683 for (int i = 1; i < ny; i++) {
1684 if (fabs(y - yAxis[i]) < dist) {
1685 dist = fabs(y - yAxis[i]);
1686 iNode = i;
1687 }
1688 }
1689 // Set the summing range.
1690 iY0 = iNode;
1691 iY1 = iNode;
1692 // Establish the shape functions.
1693 fY = {1., 0., 0., 0.};
1694 } else if (iOrder == 1 || ny == 2) {
1695 // First order interpolation in y.
1696 // Find the grid segment containing this point.
1697 int iGrid = 0;
1698 for (int i = 1; i < ny; i++) {
1699 if ((yAxis[i - 1] - y) * (y - yAxis[i]) >= 0.) {
1700 iGrid = i;
1701 }
1702 }
1703 // Ensure there won't be divisions by zero.
1704 const double y0 = yAxis[iGrid - 1];
1705 const double y1 = yAxis[iGrid];
1706 if (y1 == y0) {
1707 std::cerr << "Boxin3: Incorrect grid; no interpolation.\n";
1708 return false;
1709 }
1710 // Compute local coordinates.
1711 const double yL = (y - y0) / (y1 - y0);
1712 // Set the summing range.
1713 iY0 = iGrid - 1;
1714 iY1 = iGrid;
1715 // Set the shape functions.
1716 fY = {1. - yL, yL, 0., 0.};
1717 } else if (iOrder == 2) {
1718 // Second order interpolation in y.
1719 // Find the grid segment containing this point.
1720 int iGrid = 0;
1721 for (int i = 1; i < ny; i++) {
1722 if ((yAxis[i - 1] - y) * (y - yAxis[i]) >= 0.) {
1723 iGrid = i;
1724 }
1725 }
1726 if (iGrid == 1) {
1727 iY0 = iGrid - 1;
1728 iY1 = iGrid + 1;
1729 const double y0 = yAxis[iY0];
1730 const double y1 = yAxis[iY0 + 1];
1731 const double y2 = yAxis[iY0 + 2];
1732 if (y0 == y1 || y0 == y2 || y1 == y2) {
1733 std::cerr << "Boxin3: One or more grid points in y coincide.\n"
1734 << " No interpolation.\n";
1735 return false;
1736 }
1737 fY[0] = (y - y1) * (y - y2) / ((y0 - y1) * (y0 - y2));
1738 fY[1] = (y - y0) * (y - y2) / ((y1 - y0) * (y1 - y2));
1739 fY[2] = (y - y0) * (y - y1) / ((y2 - y0) * (y2 - y1));
1740 } else if (iGrid == ny - 1) {
1741 iY0 = iGrid - 2;
1742 iY1 = iGrid;
1743 const double y0 = yAxis[iY0];
1744 const double y1 = yAxis[iY0 + 1];
1745 const double y2 = yAxis[iY0 + 2];
1746 if (y0 == y1 || y0 == y2 || y1 == y2) {
1747 std::cerr << "Boxin3: One or more grid points in y coincide.\n"
1748 << " No interpolation.\n";
1749 return false;
1750 }
1751 fY[0] = (y - y1) * (y - y2) / ((y0 - y1) * (y0 - y2));
1752 fY[1] = (y - y0) * (y - y2) / ((y1 - y0) * (y1 - y2));
1753 fY[2] = (y - y0) * (y - y1) / ((y2 - y0) * (y2 - y1));
1754 } else {
1755 iY0 = iGrid - 2;
1756 iY1 = iGrid + 1;
1757 const double y0 = yAxis[iY0];
1758 const double y1 = yAxis[iY0 + 1];
1759 const double y2 = yAxis[iY0 + 2];
1760 const double y3 = yAxis[iY0 + 3];
1761 if (y0 == y1 || y0 == y2 || y0 == y3 ||
1762 y1 == y2 || y1 == y3 || y2 == y3) {
1763 std::cerr << "Boxin3: One or more grid points in y coincide.\n"
1764 << " No interpolation.\n";
1765 return false;
1766 }
1767 // Compute the local coordinate for this grid segment.
1768 const double yL = (y - y1) / (y2 - y1);
1769 fY[0] = ((y - y1) * (y - y2) / ((y0 - y1) * (y0 - y2))) * (1. - yL);
1770 fY[1] = ((y - y0) * (y - y2) / ((y1 - y0) * (y1 - y2))) * (1. - yL) +
1771 ((y - y2) * (y - y3) / ((y1 - y2) * (y1 - y3))) * yL;
1772 fY[2] = ((y - y0) * (y - y1) / ((y2 - y0) * (y2 - y1))) * (1. - yL) +
1773 ((y - y1) * (y - y3) / ((y2 - y1) * (y2 - y3))) * yL;
1774 fY[3] = ((y - y1) * (y - y2) / ((y3 - y1) * (y3 - y2))) * yL;
1775 }
1776 }
1777
1778 if (iOrder == 0 || nz == 1) {
1779 // Zeroth order interpolation in z.
1780 // Find the nearest node.
1781 double dist = fabs(z - zAxis[0]);
1782 int iNode = 0;
1783 for (int i = 1; i < nz; i++) {
1784 if (fabs(z - zAxis[i]) < dist) {
1785 dist = fabs(z - zAxis[i]);
1786 iNode = i;
1787 }
1788 }
1789 // Set the summing range.
1790 iZ0 = iNode;
1791 iZ1 = iNode;
1792 // Establish the shape functions.
1793 fZ = {1., 0., 0., 0.};
1794 } else if (iOrder == 1 || nz == 2) {
1795 // First order interpolation in z.
1796 // Find the grid segment containing this point.
1797 int iGrid = 0;
1798 for (int i = 1; i < nz; i++) {
1799 if ((zAxis[i - 1] - z) * (z - zAxis[i]) >= 0.) {
1800 iGrid = i;
1801 }
1802 }
1803 const double z0 = zAxis[iGrid - 1];
1804 const double z1 = zAxis[iGrid];
1805 // Ensure there won't be divisions by zero.
1806 if (z1 == z0) {
1807 std::cerr << "Boxin3: Incorrect grid; no interpolation.\n";
1808 return false;
1809 }
1810 // Compute local coordinates.
1811 const double zL = (z - z0) / (z1 - z0);
1812 // Set the summing range.
1813 iZ0 = iGrid - 1;
1814 iZ1 = iGrid;
1815 // Set the shape functions.
1816 fZ = {1. - zL, zL, 0., 0.};
1817 } else if (iOrder == 2) {
1818 // Second order interpolation in z.
1819 // Find the grid segment containing this point.
1820 int iGrid = 0;
1821 for (int i = 1; i < nz; i++) {
1822 if ((zAxis[i - 1] - z) * (z - zAxis[i]) >= 0.) {
1823 iGrid = i;
1824 }
1825 }
1826 if (iGrid == 1) {
1827 iZ0 = iGrid - 1;
1828 iZ1 = iGrid + 1;
1829 const double z0 = zAxis[iZ0];
1830 const double z1 = zAxis[iZ0 + 1];
1831 const double z2 = zAxis[iZ0 + 2];
1832 if (z0 == z1 || z0 == z2 || z1 == z2) {
1833 std::cerr << "Boxin3: One or more grid points in z coincide.\n"
1834 << " No interpolation.\n";
1835 return false;
1836 }
1837 fZ[0] = (z - z1) * (z - z2) / ((z0 - z1) * (z0 - z2));
1838 fZ[1] = (z - z0) * (z - z2) / ((z1 - z0) * (z1 - z2));
1839 fZ[2] = (z - z0) * (z - z1) / ((z2 - z0) * (z2 - z1));
1840 } else if (iGrid == nz - 1) {
1841 iZ0 = iGrid - 2;
1842 iZ1 = iGrid;
1843 const double z0 = zAxis[iZ0];
1844 const double z1 = zAxis[iZ0 + 1];
1845 const double z2 = zAxis[iZ0 + 2];
1846 if (z0 == z1 || z0 == z2 || z1 == z2) {
1847 std::cerr << "Boxin3: One or more grid points in z coincide.\n"
1848 << " No interpolation.\n";
1849 return false;
1850 }
1851 fZ[0] = (z - z1) * (z - z2) / ((z0 - z1) * (z0 - z2));
1852 fZ[1] = (z - z0) * (z - z2) / ((z1 - z0) * (z1 - z2));
1853 fZ[2] = (z - z0) * (z - z1) / ((z2 - z0) * (z2 - z1));
1854 } else {
1855 iZ0 = iGrid - 2;
1856 iZ1 = iGrid + 1;
1857 const double z0 = zAxis[iZ0];
1858 const double z1 = zAxis[iZ0 + 1];
1859 const double z2 = zAxis[iZ0 + 2];
1860 const double z3 = zAxis[iZ0 + 3];
1861 if (z0 == z1 || z0 == z2 || z0 == z3 ||
1862 z1 == z2 || z1 == z3 || z2 == z3) {
1863 std::cerr << "Boxin3: One or more grid points in z coincide.\n"
1864 << " No interpolation.\n";
1865 return false;
1866 }
1867 // Compute the local coordinate for this grid segment.
1868 const double zL = (z - z1) / (z2 - z1);
1869 fZ[0] = ((z - z1) * (z - z2) / ((z0 - z1) * (z0 - z2))) * (1. - zL);
1870 fZ[1] = ((z - z0) * (z - z2) / ((z1 - z0) * (z1 - z2))) * (1. - zL) +
1871 ((z - z2) * (z - z3) / ((z1 - z2) * (z1 - z3))) * zL;
1872 fZ[2] = ((z - z0) * (z - z1) / ((z2 - z0) * (z2 - z1))) * (1. - zL) +
1873 ((z - z1) * (z - z3) / ((z2 - z1) * (z2 - z3))) * zL;
1874 fZ[3] = ((z - z1) * (z - z2) / ((z3 - z1) * (z3 - z2))) * zL;
1875 }
1876 }
1877
1878 for (int i = iX0; i <= iX1; ++i) {
1879 for (int j = iY0; j <= iY1; ++j) {
1880 for (int k = iZ0; k <= iZ1; ++k) {
1881 f += value[i][j][k] * fX[i - iX0] * fY[j - iY0] * fZ[k - iZ0];
1882 }
1883 }
1884 }
1885 return true;
1886}
1887
1889 std::function<double(double, const std::vector<double>&)> f,
1890 std::vector<double>& par, std::vector<double>& epar,
1891 const std::vector<double>& x, const std::vector<double>& y,
1892 const std::vector<double>& ey, const unsigned int nMaxIter,
1893 const double diff, double& chi2, const double eps,
1894 const bool debug, const bool verbose) {
1895
1896 //-----------------------------------------------------------------------
1897 // LSQFIT - Subroutine fitting the parameters A in the routine F to
1898 // the data points (X,Y) using a least squares method.
1899 // Translated from an Algol routine written by Geert Jan van
1900 // Oldenborgh and Rob Veenhof, based on Stoer + Bulirsch.
1901 // VARIABLES : F( . ,A,VAL) : Subroutine to be fitted.
1902 // (X,Y) : Input data.
1903 // D : Derivative matrix.
1904 // R : Difference vector between Y and F(X,A).
1905 // S : Correction vector for A.
1906 // EPSDIF : Used for differentiating.
1907 // EPS : Numerical resolution.
1908 // (Last updated on 23/ 5/11.)
1909 //-----------------------------------------------------------------------
1910
1911 const unsigned int n = par.size();
1912 const unsigned int m = x.size();
1913 // Make sure that the # degrees of freedom < the number of data points.
1914 if (n > m) {
1915 std::cerr << "LeastSquaresFit: Number of parameters to be varied\n"
1916 << " exceeds the number of data points.\n";
1917 return false;
1918 }
1919
1920 // Check the errors.
1921 if (*std::min_element(ey.cbegin(), ey.cend()) <= 0.) {
1922 std::cerr << "LeastSquaresFit: Not all errors are > 0; no fit done.\n";
1923 return false;
1924 }
1925 chi2 = 0.;
1926 // Largest difference.
1927 double diffc = -1.;
1928 // Initialise the difference vector R.
1929 std::vector<double> r(m, 0.);
1930 for (unsigned int i = 0; i < m; ++i) {
1931 // Compute initial residuals.
1932 r[i] = (y[i] - f(x[i], par)) / ey[i];
1933 // Compute initial maximum difference.
1934 diffc = std::max(std::abs(r[i]), diffc);
1935 // And compute initial chi2.
1936 chi2 += r[i] * r[i];
1937 }
1938 if (debug) {
1939 std::cout << " Input data points:\n"
1940 << " X Y Y - F(X)\n";
1941 for (unsigned int i = 0; i < m; ++i) {
1942 std::printf(" %9u %15.8e %15.8e %15.8e\n", i, x[i], y[i], r[i]);
1943 }
1944 std::cout << " Initial values of the fit parameters:\n"
1945 << " Parameter Value\n";
1946 for (unsigned int i = 0; i < n; ++i) {
1947 std::printf(" %9u %15.8e\n", i, par[i]);
1948 }
1949 }
1950 if (verbose) {
1951 std::cout << " MINIMISATION SUMMARY\n"
1952 << " Initial situation:\n";
1953 std::printf(" Largest difference between fit and target: %15.8e\n",
1954 diffc);
1955 std::printf(" Sum of squares of these differences: %15.8e\n",
1956 chi2);
1957 }
1958 // Start optimising loop.
1959 bool converged = false;
1960 double chi2L = 0.;
1961 for (unsigned int iter = 1; iter <= nMaxIter; ++iter) {
1962 // Check the stopping criteria: (1) max norm, (2) change in chi-squared.
1963 if ((diffc < diff) || (iter > 1 && std::abs(chi2L - chi2) < eps * chi2)) {
1964 if (debug || verbose) {
1965 if (diffc < diff) {
1966 std::cout << " The maximum difference stopping criterion "
1967 << "is satisfied.\n";
1968 } else {
1969 std::cout << " The relative change in chi-squared has dropped "
1970 << "below the threshold.\n";
1971 }
1972 }
1973 converged = true;
1974 break;
1975 }
1976 // Calculate the derivative matrix.
1977 std::vector<std::vector<double> > d(n, std::vector<double>(m, 0.));
1978 for (unsigned int i = 0; i < n; ++i) {
1979 const double epsdif = eps * (1. + std::abs(par[i]));
1980 par[i] += 0.5 * epsdif;
1981 for (unsigned int j = 0; j < m; ++j) d[i][j] = f(x[j], par);
1982 par[i] -= epsdif;
1983 for (unsigned int j = 0; j < m; ++j) {
1984 d[i][j] = (d[i][j] - f(x[j], par)) / (epsdif * ey[j]);
1985 }
1986 par[i] += 0.5 * epsdif;
1987 }
1988 // Invert the matrix in Householder style.
1989 std::vector<double> colsum(n, 0.);
1990 std::vector<int> pivot(n, 0);
1991 for (unsigned int i = 0; i < n; ++i) {
1992 colsum[i] = std::inner_product(d[i].cbegin(), d[i].cend(),
1993 d[i].cbegin(), 0.);
1994 pivot[i] = i;
1995 }
1996 // Decomposition.
1997 std::vector<double> alpha(n, 0.);
1998 bool singular = false;
1999 for (unsigned int k = 0; k < n; ++k) {
2000 double sigma = colsum[k];
2001 unsigned int jbar = k;
2002 for (unsigned int j = k + 1; j < n; ++j) {
2003 if (sigma < colsum[j]) {
2004 sigma = colsum[j];
2005 jbar = j;
2006 }
2007 }
2008 if (jbar != k) {
2009 // Interchange columns.
2010 std::swap(pivot[k], pivot[jbar]);
2011 std::swap(colsum[k], colsum[jbar]);
2012 std::swap(d[k], d[jbar]);
2013 }
2014 sigma = 0.;
2015 for (unsigned int i = k; i < m; ++i) sigma += d[k][i] * d[k][i];
2016 if (sigma == 0. || sqrt(sigma) < 1.e-8 * std::abs(d[k][k])) {
2017 singular = true;
2018 break;
2019 }
2020 alpha[k] = d[k][k] < 0. ? sqrt(sigma) : -sqrt(sigma);
2021 const double beta = 1. / (sigma - d[k][k] * alpha[k]);
2022 d[k][k] -= alpha[k];
2023 std::vector<double> b(n, 0.);
2024 for (unsigned int j = k + 1; j < n; ++j) {
2025 for (unsigned int i = k; i < n; ++i) b[j] += d[k][i] * d[j][i];
2026 b[j] *= beta;
2027 }
2028 for (unsigned int j = k + 1; j < n; ++j) {
2029 for (unsigned int i = k; i < m; ++i) {
2030 d[j][i] -= d[k][i] * b[j];
2031 colsum[j] -= d[j][k] * d[j][k];
2032 }
2033 }
2034 }
2035 if (singular) {
2036 std::cerr << "LeastSquaresFit: Householder matrix (nearly) singular;\n"
2037 << " no further optimisation.\n"
2038 << " Ensure the function depends on the parameters\n"
2039 << " and try to supply reasonable starting values.\n";
2040 break;
2041 }
2042 // Solve.
2043 for (unsigned int j = 0; j < n; ++j) {
2044 double gamma = 0.;
2045 for (unsigned int i = j; i < m; ++i) gamma += d[j][i] * r[i];
2046 gamma *= 1. / (alpha[j] * d[j][j]);
2047 for (unsigned int i = j; i < m; ++i) r[i] += gamma * d[j][i];
2048 }
2049 std::vector<double> z(n, 0.);
2050 z[n - 1] = r[n - 1] / alpha[n - 1];
2051 for (int i = n - 1; i >= 1; --i) {
2052 double sum = 0.;
2053 for (unsigned int j = i + 1; j <= n; ++j) {
2054 sum += d[j - 1][i - 1] * z[j - 1];
2055 }
2056 z[i - 1] = (r[i - 1] - sum) / alpha[i - 1];
2057 }
2058 // Correction vector.
2059 std::vector<double> s(n, 0.);
2060 for (unsigned int i = 0; i < n; ++i) s[pivot[i]] = z[i];
2061 // Generate some debugging output.
2062 if (debug) {
2063 std::cout << " Correction vector in iteration " << iter << ":\n";
2064 for (unsigned int i = 0; i < n; ++i) {
2065 std::printf(" %5u %15.8e\n", i, s[i]);
2066 }
2067 }
2068 // Add part of the correction vector to the estimate to improve chi2.
2069 chi2L = chi2;
2070 chi2 *= 2;
2071 for (unsigned int i = 0; i < n; ++i) par[i] += s[i] * 2;
2072 for (unsigned int i = 0; i <= 10; ++i) {
2073 if (chi2 <= chi2L) break;
2074 if (std::abs(chi2L - chi2) < eps * chi2) {
2075 if (debug) {
2076 std::cout << " Too little improvement; reduction loop halted.\n";
2077 }
2078 break;
2079 }
2080 chi2 = 0.;
2081 const double scale = 1. / pow(2, i);
2082 for (unsigned int j = 0; j < n; ++j) par[j] -= s[j] * scale;
2083 for (unsigned int j = 0; j < m; ++j) {
2084 r[j] = (y[j] - f(x[j], par)) / ey[j];
2085 chi2 += r[j] * r[j];
2086 }
2087 if (debug) {
2088 std::printf(" Reduction loop %3i: chi2 = %15.8e\n", i, chi2);
2089 }
2090 }
2091 // Calculate the max. norm.
2092 diffc = std::abs(r[0]);
2093 for (unsigned int i = 1; i < m; ++i) {
2094 diffc = std::max(std::abs(r[i]), diffc);
2095 }
2096 // Print some debugging output.
2097 if (debug) {
2098 std::cout << " Values of the fit parameters after iteration "
2099 << iter << "\n Parameter Value\n";
2100 for (unsigned int i = 0; i < n; ++i) {
2101 std::printf(" %9u %15.8e\n", i, par[i]);
2102 }
2103 std::printf(" for which chi2 = %15.8e and diff = %15.8e\n",
2104 chi2, diffc);
2105 } else if (verbose) {
2106 std::printf(" Step %3u: largest deviation = %15.8e, chi2 = %15.8e\n",
2107 iter, diffc, chi2);
2108 }
2109 }
2110 // End of fit, perform error calculation.
2111 if (!converged) {
2112 std::cerr << "LeastSquaresFit: Maximum number of iterations reached.\n";
2113 }
2114 // Calculate the derivative matrix for the final settings.
2115 std::vector<std::vector<double> > d(n, std::vector<double>(m, 0.));
2116 for (unsigned int i = 0; i < n; ++i) {
2117 const double epsdif = eps * (1. + std::abs(par[i]));
2118 par[i] += 0.5 * epsdif;
2119 for (unsigned int j = 0; j < m; ++j) d[i][j] = f(x[j], par);
2120 par[i] -= epsdif;
2121 for (unsigned int j = 0; j < m; ++j) {
2122 d[i][j] = (d[i][j] - f(x[j], par)) / (epsdif * ey[j]);
2123 }
2124 par[i] += 0.5 * epsdif;
2125 }
2126 // Calculate the error matrix.
2127 std::vector<std::vector<double> > cov(n, std::vector<double>(n, 0.));
2128 for (unsigned int i = 0; i < n; ++i) {
2129 for (unsigned int j = 0; j < n; ++j) {
2130 cov[i][j] = std::inner_product(d[i].cbegin(), d[i].cend(),
2131 d[j].cbegin(), 0.);
2132 }
2133 }
2134 // Compute the scaling factor for the errors.
2135 double scale = m > n ? chi2 / (m - n) : 1.;
2136 // Invert it to get the covariance matrix.
2137 epar.assign(n, 0.);
2138 if (Garfield::Numerics::CERNLIB::dinv(n, cov) != 0) {
2139 std::cerr << "LeastSquaresFit: Singular covariance matrix; "
2140 << "no error calculation.\n";
2141 } else {
2142 for (unsigned int i = 0; i < n; ++i) {
2143 for (unsigned int j = 0; j < n; ++j) cov[i][j] *= scale;
2144 epar[i] = sqrt(std::max(0., cov[i][i]));
2145 }
2146 }
2147 // Print results.
2148 if (debug) {
2149 std::cout << " Comparison between input and fit:\n"
2150 << " X Y F(X)\n";
2151 for (unsigned int i = 0; i < m; ++i) {
2152 const double fit = f(x[i], par);
2153 std::printf(" %5u %15.8e %15.8e %15.8e\n", i, x[i], y[i], fit);
2154 }
2155 }
2156 if (verbose) {
2157 std::cout << " Final values of the fit parameters:\n"
2158 << " Parameter Value Error\n";
2159 for (unsigned int i = 0; i < n; ++i) {
2160 std::printf(" %9u %15.8e %15.8e\n", i, par[i], epar[i]);
2161 }
2162 std::cout << " The errors have been scaled by a factor of "
2163 << sqrt(scale) << ".\n";
2164 std::cout << " Covariance matrix:\n";
2165 for (unsigned int i = 0; i < n; ++i) {
2166 for (unsigned int j = 0; j < n; ++j) {
2167 std::printf(" %15.8e", cov[i][j]);
2168 }
2169 std::cout << "\n";
2170 }
2171 std::cout << " Correlation matrix:\n";
2172 for (unsigned int i = 0; i < n; ++i) {
2173 for (unsigned int j = 0; j < n; ++j) {
2174 double cor = 0.;
2175 if (cov[i][i] > 0. && cov[j][j] > 0.) {
2176 cor = cov[i][j] / sqrt(cov[i][i] * cov[j][j]);
2177 }
2178 std::printf(" %15.8e", cor);
2179 }
2180 std::cout << "\n";
2181 }
2182 std::cout << " Minimisation finished.\n";
2183 }
2184 return converged;
2185}
2186
2187}
2188}
void dfinv(const int n, std::vector< std::vector< double > > &a, std::vector< int > &ir)
Definition Numerics.cc:855
void cfact(const int n, std::vector< std::vector< std::complex< double > > > &a, std::vector< int > &ir, int &ifail, std::complex< double > &det, int &jfail)
Definition Numerics.cc:995
int deqn(const int n, std::vector< std::vector< double > > &a, std::vector< double > &b)
Definition Numerics.cc:594
void dfact(const int n, std::vector< std::vector< double > > &a, std::vector< int > &ir, int &ifail, double &det, int &jfail)
Definition Numerics.cc:669
void cfinv(const int n, std::vector< std::vector< std::complex< double > > > &a, std::vector< int > &ir)
Definition Numerics.cc:1080
int dinv(const int n, std::vector< std::vector< double > > &a)
Replace square matrix A by its inverse.
Definition Numerics.cc:788
void dfeqn(const int n, std::vector< std::vector< double > > &a, std::vector< int > &ir, std::vector< double > &b)
Definition Numerics.cc:754
int cinv(const int n, std::vector< std::vector< std::complex< double > > > &a)
Replace square matrix A by its inverse.
Definition Numerics.cc:1135
int deqinv(const int n, std::vector< std::vector< double > > &a, std::vector< double > &b)
Replaces b by the solution x of Ax = b, and replace A by its inverse.
Definition Numerics.cc:910
void cfft(std::vector< std::complex< double > > &a, const int msign)
Definition Numerics.cc:1205
void qk15(std::function< double(double)> f, const double a, const double b, double &result, double &abserr, double &resabs, double &resasc)
15-point Gauss-Kronrod integration with finite integration range.
Definition Numerics.cc:500
void qagi(std::function< double(double)> f, double bound, const int inf, const double epsabs, const double epsrel, double &result, double &abserr, unsigned int &status)
Definition Numerics.cc:145
void qk15i(std::function< double(double)> f, double bound, const int inf, const double a, const double b, double &result, double &abserr, double &resabs, double &resasc)
Definition Numerics.cc:409
Collection of numerical routines.
Definition Numerics.hh:14
bool Boxin3(const std::vector< std::vector< std::vector< double > > > &value, const std::vector< double > &xAxis, const std::vector< double > &yAxis, const std::vector< double > &zAxis, const int nx, const int ny, const int nz, const double xx, const double yy, const double zz, double &f, const int iOrder)
Definition Numerics.cc:1545
bool LeastSquaresFit(std::function< double(double, const std::vector< double > &)> f, std::vector< double > &par, std::vector< double > &epar, const std::vector< double > &x, const std::vector< double > &y, const std::vector< double > &ey, const unsigned int nMaxIter, const double diff, double &chi2, const double eps, const bool debug, const bool verbose)
Least-squares minimisation.
Definition Numerics.cc:1888
bool Boxin2(const std::vector< std::vector< double > > &value, const std::vector< double > &xAxis, const std::vector< double > &yAxis, const int nx, const int ny, const double xx, const double yy, double &f, const int iOrder)
Definition Numerics.cc:1354
double Divdif(const std::vector< double > &f, const std::vector< double > &a, int nn, double x, int mm)
Definition Numerics.cc:1255