9 #include "boost/format.hpp" 19 static int search_array(
double z,
double const *
x,
int n,
int i);
24 for (
unsigned int i = 0; i !=
_coeffs.
size(); ++i) {
31 int const n = x.
size();
42 for (
int i = 0; i != n; ++i) {
43 ind = search_array(x[i], &
_knots[0], nknot, ind);
47 }
else if (ind >= nknot) {
51 double const dx = x[i] -
_knots[ind];
59 int const n = x.
size();
72 for (
int i = 0; i != n; ++i) {
73 ind = search_array(x[i], &
_knots[0], nknot, ind);
77 }
else if (ind >= nknot) {
81 double const dx = x[i] -
_knots[ind];
90 (
boost::format(
"TautSpline: x and y must have the same size; saw %d %d\n") %
95 int const ntau = x.
size();
103 calculateTautSpline(x, y, gamma0);
107 calculateTautSplineEvenOdd(x, y, gamma0, type == Even);
113 double const gamma0) {
114 const double *tau = &x[0];
115 const double *gtau = &y[0];
116 int const ntau = x.
size();
119 int const nknot = ntau;
124 for (
int i = 1; i < nknot; i++) {
126 if (tau[i - 1] >= tau[i]) {
128 (
boost::format(
"point %d and the next, %f %f, are out of order") % (i - 1) %
136 _coeffs[1][0] = (gtau[1] - gtau[0]) / (tau[1] - tau[0]);
140 _coeffs[1][1] = (gtau[1] - gtau[0]) / (tau[1] - tau[0]);
143 double tmp = (tau[2] - tau[0]) * (tau[2] - tau[1]) * (tau[1] - tau[0]);
145 _coeffs[1][0] = ((gtau[1] - gtau[0]) * pow(tau[2] - tau[0], 2) -
146 (gtau[2] - gtau[0]) * pow(tau[1] - tau[0], 2)) /
149 -2 * ((gtau[1] - gtau[0]) * (tau[2] - tau[0]) - (gtau[2] - gtau[0]) * (tau[1] - tau[0])) /
158 _coeffs[0][2] = gtau[2];
159 _coeffs[1][2] = _coeffs[1][0] + (tau[2] - tau[0]) * _coeffs[2][0];
160 _coeffs[2][2] = _coeffs[2][0];
179 for (
int i = 0; i != 6; i++) {
186 for (
int i = 0; i < ntau - 1; i++) {
187 s[0][i] = tau[i + 1] - tau[i];
190 (
boost::format(
"point %d and the next, %f %f, are out of order") % i % tau[i] %
194 s[3][i + 1] = (gtau[i + 1] - gtau[i]) / s[0][i];
196 for (
int i = 1; i < ntau - 1; ++i) {
197 s[3][i] = s[3][i + 1] - s[3][i];
205 s[1][1] = s[0][0] / 3;
208 double gamma = gamma0;
211 }
else if (gamma > 3) {
217 double const onemg3 = 1 - gamma / 3;
238 for (
int i = 1; i < ntau - 2; ++i) {
243 if ((method == 2 && s[3][i] * s[3][i + 1] >= 0) || method == 3) {
244 double const temp = fabs(s[3][i + 1]);
245 double const denom = fabs(s[3][i]) + temp;
248 if (fabs(z - 0.5) <= 1.0 / 6.0) {
263 double temp = onemg3 / onemzt;
264 alpha = (temp < 1 ? temp : 1);
265 factor = zeta / (alpha * (zt2 - 1) + 1);
266 s[5][i] = zeta * factor / 6;
267 s[1][i] += s[0][i] * ((1 - alpha * onemzt) * factor / 2 - s[5][i]);
276 s[2][i] = s[0][i] / 6;
281 }
else if (z_half == 0) {
282 s[1][i] += s[0][i] / 3;
283 s[2][i] = s[0][i] / 6;
285 onemzt = gamma * (1 -
z);
287 double const temp = onemg3 / zeta;
288 alpha = (temp < 1 ? temp : 1);
289 factor = onemzt / (1 - alpha * zeta * (onemzt + 1));
290 s[5][i] = onemzt * factor / 6;
291 s[1][i] += s[0][i] / 3;
292 s[2][i] = s[5][i] * s[0][i];
304 s[1][0] = s[0][0] / 6;
308 const double factr2 = zeta * (alpha * (zt2 - 1.) + 1.) / (alpha * (zeta * zt2 - 1.) + 1.);
309 ratio = factr2 * s[0][1] / s[1][0];
310 s[1][1] = factr2 * s[0][1] + s[0][0];
311 s[2][1] = -factr2 * s[0][0];
312 }
else if (z_half == 0) {
313 ratio = s[0][1] / s[1][0];
314 s[1][1] = s[0][1] + s[0][0];
317 ratio = s[0][1] / s[1][0];
318 s[1][1] = s[0][1] + s[0][0];
319 s[2][1] = -s[0][0] * 6 * alpha * s[5][1];
329 s[1][1] += ratio * s[2][0];
330 s[2][1] += ratio * entry3;
331 s[3][1] = ratio * s[3][1];
339 s[1][i] += ratio * s[2][i - 1];
340 s[3][i] += ratio * s[3][i - 1];
346 ratio = -s[5][i] * s[0][i] / s[1][i];
347 s[1][i + 1] = s[0][i] / 3;
348 }
else if (z_half == 0) {
349 ratio = -(s[0][i] / 6) / s[1][i];
350 s[1][i + 1] = s[0][i] / 3;
352 ratio = -(s[0][i] / 6) / s[1][i];
353 s[1][i + 1] = s[0][i] * ((1 - zeta * alpha) * factor / 2 - s[5][i]);
357 s[4][ntau - 2] = 0.5;
362 double const entry_ = ratio * s[2][ntau - 3] + s[1][ntau - 2] + s[0][ntau - 2] / 3;
363 s[1][ntau - 1] = s[0][ntau - 2] / 6;
364 s[3][ntau - 1] = ratio * s[3][ntau - 3] + s[3][ntau - 2];
366 ratio = s[0][ntau - 2] * 6 * s[5][ntau - 3] * alpha / s[1][ntau - 3];
367 s[1][ntau - 2] = ratio * s[2][ntau - 3] + s[0][ntau - 2] + s[0][ntau - 3];
368 s[2][ntau - 2] = -s[0][ntau - 3];
369 }
else if (z_half == 0) {
370 ratio = s[0][ntau - 2] / s[1][ntau - 3];
371 s[1][ntau - 2] = ratio * s[2][ntau - 3] + s[0][ntau - 2] + s[0][ntau - 3];
372 s[2][ntau - 2] = -s[0][ntau - 3];
374 const double factr2 =
375 onemzt * (alpha * (onemzt * onemzt - 1) + 1) / (alpha * (onemzt * onemzt * onemzt - 1) + 1);
376 ratio = factr2 * s[0][ntau - 2] / s[1][ntau - 3];
377 s[1][ntau - 2] = ratio * s[2][ntau - 3] + factr2 * s[0][ntau - 3] + s[0][ntau - 2];
378 s[2][ntau - 2] = -factr2 * s[0][ntau - 3];
386 s[3][ntau - 2] = ratio * s[3][ntau - 3];
387 ratio = -entry_ / s[1][ntau - 2];
388 s[1][ntau - 1] += ratio * s[2][ntau - 2];
389 s[3][ntau - 1] += ratio * s[3][ntau - 2];
394 s[3][ntau - 1] /= s[1][ntau - 1];
395 for (
int i = ntau - 2; i > 0; --i) {
396 s[3][i] = (s[3][i] - s[2][i] * s[3][i + 1]) / s[1][i];
399 s[3][0] = (s[3][0] - s[2][0] * s[3][1] - entry3 * s[3][2]) / s[1][0];
408 int const nknot0 = nknot;
411 for (
int i = 0; i < ntau - 1; ++i) {
412 double const z = s[4][i];
413 if ((z < 0.5 && z != 0.0) || (z > 0.5 && (1 -
z) != 0.0)) {
417 assert(nknot == nknot0);
424 for (
int i = 0; i < ntau - 1; ++i) {
427 double const divdif = (gtau[i + 1] - gtau[i]) / s[0][i];
429 double const z_half = z - 0.5;
438 double const c = s[3][i + 1] / 6;
439 double const d = s[3][i] * s[5][i];
442 double const del = zeta * s[0][i];
445 double temp = onemg3 / onemzt;
446 alpha = (temp < 1 ? temp : 1);
447 factor = onemzt * onemzt * alpha;
449 _coeffs[0][j] = gtau[i] + divdif * del +
450 temp * temp * (d * onemzt * (factor - 1) + c * zeta * (zt2 - 1));
451 _coeffs[1][j] = divdif + s[0][i] * (d * (1 - 3 * factor) + c * (3 * zt2 - 1));
452 _coeffs[2][j] = (d * alpha * onemzt + c * zeta) * 6;
453 _coeffs[3][j] = (c - d * alpha) * 6 / s[0][i];
454 if (del * zt2 == 0) {
455 _coeffs[1][j - 1] = 0;
456 _coeffs[3][j - 1] = 0;
458 _coeffs[3][j - 1] = _coeffs[3][j] - d * 6 * (1 - alpha) / (del * zt2);
459 _coeffs[1][j - 1] = _coeffs[1][j] - del * (_coeffs[2][j] - del / 2 * _coeffs[3][j - 1]);
462 }
else if (z_half == 0) {
463 _coeffs[1][j] = divdif - s[0][i] * (s[3][i] * 2 + s[3][i + 1]) / 6;
464 _coeffs[3][j] = (s[3][i + 1] - s[3][i]) / s[0][i];
466 onemzt = gamma * (1 -
z);
473 double const temp = onemg3 / zeta;
474 alpha = (temp < 1 ? temp : 1);
475 double const c = s[3][i + 1] * s[5][i];
476 double const d = s[3][i] / 6;
477 double const del = zeta * s[0][i];
478 _knots[j + 1] = tau[i] + del;
479 _coeffs[1][j] = divdif - s[0][i] * (2 * d + c);
480 _coeffs[3][j] = (c * alpha - d) * 6 / s[0][i];
484 _coeffs[3][j - 1] + (1 - alpha) * 6 * c / (s[0][i] * (onemzt * onemzt * onemzt));
485 _coeffs[2][j] = _coeffs[2][j - 1] + del * _coeffs[3][j - 1];
486 _coeffs[1][j] = _coeffs[1][j - 1] + del * (_coeffs[2][j - 1] + del / 2 * _coeffs[3][j - 1]);
487 _coeffs[0][j] = _coeffs[0][j - 1] +
488 del * (_coeffs[1][j - 1] +
489 del / 2 * (_coeffs[2][j - 1] + del / 3 * _coeffs[3][j - 1]));
505 double const del = tau[ntau - 1] -
_knots[nknot - 2];
509 del * (
_coeffs[2][nknot - 2] / 2 + del *
_coeffs[3][nknot - 2] / 6));
512 _coeffs[2][nknot - 1] = _coeffs[2][nknot - 2] + del * _coeffs[3][nknot - 2];
513 _coeffs[3][nknot - 1] = _coeffs[3][nknot - 2];
515 assert(j + 1 == nknot);
521 static void spcof1(
const double x[],
double avh,
const double y[],
const double dy[],
int n,
double p,
522 double q,
double a[],
double *c[3],
double u[],
const double v[]);
524 static void sperr1(
const double x[],
double avh,
const double dy[],
int n,
double *r[3],
double p,
double var,
527 static double spfit1(
const double x[],
double avh,
const double dy[],
int n,
double rho,
double *p,
double *q,
528 double var,
double stat[],
const double a[],
double *c[3],
double *r[3],
double *t[2],
529 double u[],
double v[]);
531 static double spint1(
const double x[],
double *avh,
const double y[],
double dy[],
int n,
double a[],
532 double *c[3],
double *r[3],
double *t[2]);
538 int const n = x.
size();
539 double const ratio = 2.0;
540 double const tau = 1.618033989;
541 double avdf, avar, stat[6];
542 double p, q, delta, r1, r2, r3, r4;
543 double gf1, gf2, gf3, gf4, avh, err;
558 r[0] = &scratch[0] + 1;
559 r[1] = r[0] + (n + 2);
560 r[2] = r[1] + (n + 2);
562 t[0] = r[2] + (n + 2);
563 t[1] = t[0] + (n + 2);
564 double *u = t[1] + (n + 2);
565 double *v = u + (n + 2);
571 avdf = spint1(&x[0], &avh, &f[0], &sdf[0], n, y, c, r, t);
580 gf1 = spfit1(&x[0], avh, &sdf[0], n, r1, &p, &q, avar, stat, y, c, r, t, u, v);
585 gf2 = spfit1(&x[0], avh, &sdf[0], n, r2, &p, &q, avar, stat, y, c, r, t, u, v);
588 gf1 = spfit1(&x[0], avh, &sdf[0], n, r1, &p, &q, avar, stat, y, c, r, t, u, v);
609 gf3 = spfit1(&x[0], avh, &sdf[0], n, r3, &p, &q, avar, stat, y, c, r, t, u, v);
623 if (p > 0 && q > 0) {
627 delta = (r2 - r1) / tau;
630 gf3 = spfit1(&x[0], avh, &sdf[0], n, r3, &p, &q, avar, stat, y, c, r, t, u, v);
631 gf4 = spfit1(&x[0], avh, &sdf[0], n, r4, &p, &q, avar, stat, y, c, r, t, u, v);
643 gf3 = spfit1(&x[0], avh, &sdf[0], n, r3, &p, &q, avar, stat, y, c, r, t, u, v);
651 gf4 = spfit1(&x[0], avh, &sdf[0], n, r4, &p, &q, avar, stat, y, c, r, t, u, v);
654 err = (r2 - r1) / (r1 + r2);
655 }
while (err * err + 1 > 1 && err > 1e-6);
658 gf1 = spfit1(&x[0], avh, &sdf[0], n, r1, &p, &q, avar, stat, y, c, r, t, u, v);
664 spcof1(&x[0], avh, &f[0], &sdf[0], n, p, q, y, c, u, v);
666 stat[2] /= avdf * avdf;
667 stat[3] /= avdf * avdf;
668 stat[4] /= avdf * avdf;
673 sperr1(&x[0], avh, &sdf[0], n, r, p, avar, errs);
679 *chisq = n * stat[4];
692 static double spint1(
const double x[],
double *avh,
const double f[],
double df[],
int n,
double a[],
693 double *c[3],
double *r[3],
double *t[2]) {
703 for (i = 0; i < n - 1; ++i) {
714 for (
int i = 0; i < n; ++i) {
721 for (i = 0; i < n; ++i) {
727 h = (x[1] - x[0]) / (*avh);
728 ff = (f[1] - f[0]) / h;
732 for (i = 1; i < n - 1; ++i) {
734 h = (x[i + 1] - x[i]) / (*avh);
736 ff = (f[i + 1] - f[i]) / h;
738 t[0][i] = (g + h) * 2. / 3.;
740 r[2][i] = df[i - 1] / g;
741 r[0][i] = df[i + 1] / h;
742 r[1][i] = -df[i] / g - df[i] / h;
751 for (i = 1; i < n - 1; i++) {
752 c[0][i] = r[0][i] * r[0][i] + r[1][i] * r[1][i] + r[2][i] * r[2][i];
753 c[1][i] = r[0][i] * r[1][i + 1] + r[1][i] * r[2][i + 1];
754 c[2][i] = r[0][i] * r[2][i + 2];
785 static double spfit1(
const double x[],
double avh,
const double dy[],
int n,
double rho,
double *pp,
786 double *pq,
double var,
double stat[],
const double a[],
double *c[3],
double *r[3],
787 double *t[2],
double u[],
double v[]) {
796 if (fabs(rho) < eps) {
799 }
else if (fabs(1 / rho) < eps) {
812 r[0][-1] = r[0][0] = 0;
814 for (
int i = 1; i < n - 1; ++i) {
815 r[2][i - 2] = g * r[0][i - 2];
816 r[1][i - 1] = f * r[0][i - 1];
818 double tmp = p * c[0][i] + q * t[0][i] - f * r[1][i - 1] - g * r[2][i - 2];
825 f = p * c[1][i] + q * t[1][i] - h * r[1][i - 1];
833 for (
int i = 1; i < n - 1; i++) {
834 u[i] = a[i] - r[1][i - 1] * u[i - 1] - r[2][i - 2] * u[i - 2];
837 for (
int i = n - 2; i > 0; i--) {
838 u[i] = r[0][i] * u[i] - r[1][i] * u[i + 1] - r[2][i] * u[i + 2];
844 for (
int i = 0; i < n - 1; i++) {
846 h = (u[i + 1] - u[i]) / ((x[i + 1] - x[i]) / avh);
847 v[i] = dy[i] * (h - g);
850 v[n - 1] = -h * dy[n - 1];
851 e += v[n - 1] * v[n - 1];
855 r[0][n - 1] = r[1][n - 1] = r[0][n] = 0;
856 for (i = n - 2; i > 0; i--) {
859 r[1][i] = -g * r[0][i + 1] - h * r[1][i + 1];
860 r[2][i] = -g * r[1][i + 1] - h * r[0][i + 2];
861 r[0][i] = r[0][i] - g * r[1][i] - h * r[2][i];
867 for (i = 1; i < n - 1; ++i) {
868 f += r[0][i] * c[0][i];
869 g += r[1][i] * c[1][i];
870 h += r[2][i] * c[2][i];
878 stat[2] = n * e / (f * f + 1e-20);
879 stat[3] = e * p * p / n;
880 stat[5] = e * p / ((f < 0) ? f - 1e-10 : f + 1e-10);
882 fun = stat[3] - 2 * var * stat[1] / n + var;
886 stat[4] = stat[5] - stat[3];
900 static void spcof1(
const double x[],
double avh,
const double y[],
const double dy[],
int n,
double p,
901 double q,
double a[],
double *c[3],
double u[],
const double v[]) {
906 qh = q / (avh * avh);
908 for (i = 0; i < n; ++i) {
909 a[i] = y[i] - p * dy[i] * v[i];
915 for (i = 0; i < n - 1; ++i) {
917 c[2][i] = (u[i + 1] - u[i]) / (3 * h);
918 c[0][i] = (a[i + 1] - a[i]) / h - (h * c[2][i] + u[i]) * h;
928 static void sperr1(
const double x[],
double avh,
const double dy[],
int n,
double *r[3],
double p,
double var,
936 h = avh / (x[1] - x[0]);
937 (*se)[0] = 1 - p * dy[0] * dy[0] * h * h * r[0][1];
938 r[0][0] = r[1][0] = r[2][0] = 0;
942 for (i = 1; i < n - 1; ++i) {
944 h = avh / (x[i + 1] - x[i]);
946 f1 = f * r[0][i - 1] + g * r[1][i - 1] + h * r[2][i - 1];
947 g1 = f * r[1][i - 1] + g * r[0][i] + h * r[1][i];
948 h1 = f * r[2][i - 1] + g * r[1][i] + h * r[0][i + 1];
949 (*se)[i] = 1 - p * dy[i] * dy[i] * (f * f1 + g * g1 + h * h1);
951 (*se)[n - 1] = 1 - p * dy[n - 1] * dy[n - 1] * h * h * r[0][n - 2];
955 for (
int i = 0; i < n; ++i) {
956 double const tmp = (*se)[i] * var;
957 (*se)[i] = (tmp >= 0) ? sqrt(tmp) * dy[i] : 0;
965 const double *tau = &_tau[0];
966 const double *gtau = &_gtau[0];
967 int const ntau = _tau.
size();
970 if (tau[0] == 0.0f) {
971 int const np = 2 * ntau - 1;
975 x[ntau - 1] = tau[0];
976 y[ntau - 1] = gtau[0];
977 for (
int i = 1; i != ntau; ++i) {
979 x[ntau - 1 + i] = tau[i];
980 y[ntau - 1 + i] = gtau[i];
981 x[ntau - 1 - i] = -tau[i];
982 y[ntau - 1 - i] = gtau[i];
984 x[ntau - 1 + i] = tau[i];
985 y[ntau - 1 + i] = gtau[i];
986 x[ntau - 1 - i] = -tau[i];
987 y[ntau - 1 - i] = -gtau[i];
991 int const np = 2 * ntau;
995 for (
int i = 0; i != ntau; ++i) {
997 x[ntau + i] = tau[i];
998 y[ntau + i] = gtau[i];
999 x[ntau - 1 - i] = -tau[i];
1000 y[ntau - 1 - i] = gtau[i];
1002 x[ntau + i] = tau[i];
1003 y[ntau + i] = gtau[i];
1004 x[ntau - 1 - i] = -tau[i];
1005 y[ntau - 1 - i] = -gtau[i];
1015 for (ii = sp.
_knots.
size() - 1; ii >= 0; --ii) {
1016 if (sp.
_knots[ii] < 0.0f) {
1020 int const i0 = ii + 1;
1025 for (
int i = i0; i !=
static_cast<int>(sp.
_knots.
size()); ++i) {
1027 for (
int j = 0; j != 4; ++j) {
1038 static int search_array(
double z,
double const *x,
int n,
int i) {
1042 if (i < 0 || i >= n) {
1046 unsigned int step = 1;
1055 while (z >= x[hi]) {
1085 while (hi - lo > 1) {
1086 mid = (lo + hi) / 2;
1103 while (lo < n - 1 && x[lo + 1] == xm) lo++;
1113 for (
unsigned int i = 0; i != newRoots.
size(); ++i) {
1114 if (newRoots[i] >= x0 && newRoots[i] < x1) {
1132 double const tmp = b * b - 4 * a * c;
1136 roots.
push_back((-b - sqrt(tmp)) / (2 * a));
1138 roots.
push_back((-b + sqrt(tmp)) / (2 * a));
1144 if (roots[0] > roots[1]) {
1145 double const tmp2 = roots[0];
1146 roots[0] = roots[1];
1158 do_quadratic(b, c, d, roots);
1165 double const q = (b * b - 3 * c) / 9;
1166 double const r = (2 * b * b * b - 9 * b * c + 27 * d) / 54;
1172 double const sq = (q >= 0) ? sqrt(q) : -sqrt(-q);
1173 double const sq3 = sq * sq * sq;
1174 if (::fabs(r) < sq3) {
1175 double const theta = ::acos(r / sq3);
1183 if (roots[0] > roots[1]) {
1186 if (roots[1] > roots[2]) {
1189 if (roots[0] > roots[1]) {
1194 }
else if (::fabs(r) == sq3) {
1195 double const aa = -((r < 0) ? -::pow(-r, 1.0 / 3.0) : ::pow(r, 1.0 / 3.0));
1204 if (roots[0] > roots[1]) {
1211 double tmp = ::sqrt(r * r - (q > 0 ? sq3 * sq3 : -sq3 * sq3));
1212 tmp = r + (r < 0 ? -tmp : tmp);
1213 double const aa = -((tmp < 0) ? -::pow(-tmp, 1.0 / 3.0) : ::pow(tmp, 1.0 / 3.0));
1236 double const x1 =
b;
1239 int i0 = search_array(x0, &
_knots[0], nknot, -1);
1240 int const i1 = search_array(x1, &
_knots[0], nknot, i0);
1241 assert(i1 >= i0 && i1 <= nknot - 1);
1257 for (
unsigned int j = 0; j != newRoots.
size(); ++j) {
1258 newRoots[j] +=
_knots[i0];
1260 keep_valid_roots(roots, newRoots, x0,
_knots[i0]);
1263 }
else if (i0 >= nknot) {
1268 for (
unsigned int j = 0; j != newRoots.
size(); ++j) {
1269 newRoots[j] +=
_knots[i0];
1271 keep_valid_roots(roots, newRoots, x0, x1);
1279 for (
int i = i0; i <= i1; i++) {
1282 for (
unsigned int j = 0; j != newRoots.
size(); ++j) {
1283 newRoots[j] +=
_knots[i];
1285 keep_valid_roots(roots, newRoots, ((i == i0) ? x0 :
_knots[i]), ((i == i1) ? x1 :
_knots[i + 1]));
std::vector< std::vector< double > > _coeffs
std::vector< double > _knots
std::vector< double > roots(double const value, double const x0, double const x1) const
Find the roots of Spline - val = 0 in the range [x0, x1).
SmoothedSpline(std::vector< double > const &x, std::vector< double > const &y, std::vector< double > const &dy, double s, double *chisq=NULL, std::vector< double > *errs=NULL)
Cubic spline data smoother.
double cos(Angle const &a)
void derivative(std::vector< double > const &x, std::vector< double > &dydx) const
Find the derivative of a Spline.
A base class for image defects.
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
void interpolate(std::vector< double > const &x, std::vector< double > &y) const
Interpolate a Spline.
void _allocateSpline(int const nknot)
Allocate the storage a Spline needs.
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Reports invalid arguments.
TautSpline(std::vector< double > const &x, std::vector< double > const &y, double const gamma=0, Symmetry type=Unknown)
Construct cubic spline interpolant to given data.