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