31 fltp08 m_right_value = 0.0;
32 bool m_made_monotonic =
false;
44 ,
fltp08 right_value = 0.0)
48 , m_left_value(left_value)
49 , m_right_value(right_value)
53 for (
uint04 i = 0; i < Y.size(); i++)
55 setPoints(X, Y, m_type);
60 ,
bool make_monotonic =
false
64 ,
fltp08 right_value = 0.0)
68 , m_left_value(left_value)
69 , m_right_value(right_value)
71 setPoints(X, Y, m_type);
78 lib_assert(x.size() == y.size(),
"Y size must be = X size");
79 lib_assert(x.size() >= 3,
"X size must be greater");
81 lib_assert(x.size() >= 4,
"not-a-knot with 3 points has multiple solutions");
83 m_made_monotonic =
false;
87 for (
uint04 i = 0; i < n - 1; i++)
88 lib_assert(m_x[i] < m_x[i + 1],
"x must have monotonicity");
97 for (
uint04 i = 0; i < n - 1; i++)
101 m_b[i] = (m_y[i + 1] - m_y[i]) / (m_x[i + 1] - m_x[i]);
104 m_b[n - 1] = m_b[n - 2];
120 for (
uint04 i = 1; i < n - 1; i++)
122 A(i, i - 1) = 1.0 / 3.0 * (x[i] - x[i - 1]);
123 A(i, i) = 2.0 / 3.0 * (x[i + 1] - x[i - 1]);
124 A(i, i + 1) = 1.0 / 3.0 * (x[i + 1] - x[i]);
125 rhs[i] = (y[i + 1] - y[i]) / (x[i + 1] - x[i]) - (y[i] - y[i - 1]) / (x[i] - x[i - 1]);
133 rhs[0] = m_left_value;
139 A(0, 0) = 2.0 * (x[1] - x[0]);
140 A(0, 1) = 1.0 * (x[1] - x[0]);
141 rhs[0] = 3.0 * ((y[1] - y[0]) / (x[1] - x[0]) - m_left_value);
147 A(0, 0) = -(x[2] - x[1]);
148 A(0, 1) = x[2] - x[0];
149 A(0, 2) = -(x[1] - x[0]);
154 lib_assert(
false,
"unknown state");
159 A(n - 1, n - 1) = 2.0;
160 A(n - 1, n - 2) = 0.0;
161 rhs[n - 1] = m_right_value;
168 A(n - 1, n - 1) = 2.0 * (x[n - 1] - x[n - 2]);
169 A(n - 1, n - 2) = 1.0 * (x[n - 1] - x[n - 2]);
170 rhs[n - 1] = 3.0 * (m_right_value - (y[n - 1] - y[n - 2]) / (x[n - 1] - x[n - 2]));
176 A(n - 1, n - 3) = -(x[n - 1] - x[n - 2]);
177 A(n - 1, n - 2) = x[n - 1] - x[n - 3];
178 A(n - 1, n - 1) = -(x[n - 2] - x[n - 3]);
183 lib_assert(
false,
"unknown state");
187 m_c = A.luSolve(rhs);
192 for (
uint04 i = 0; i < n - 1; i++)
194 m_d[i] = 1.0 / 3.0 * (m_c[i + 1] - m_c[i]) / (x[i + 1] - x[i]);
195 m_b[i] = (y[i + 1] - y[i]) / (x[i + 1] - x[i])
196 - 1.0 / 3.0 * (2.0 * m_c[i] + m_c[i + 1]) * (x[i + 1] - x[i]);
200 fltp08 h = x[n - 1] - x[n - 2];
203 m_b[n - 1] = 3.0 * m_d[n - 2] * h * h + 2.0 * m_c[n - 2] * h + m_b[n - 2];
217 for (
uint04 i = 1; i < n - 1; i++)
219 const fltp08 h = m_x[i + 1] - m_x[i];
220 const fltp08 hl = m_x[i] - m_x[i - 1];
221 m_b[i] = -h / (hl * (hl + h)) * m_y[i - 1] + (h - hl) / (hl * h) * m_y[i]
222 + hl / (h * (hl + h)) * m_y[i + 1];
227 m_b[0] = m_left_value;
231 const fltp08 h = m_x[1] - m_x[0];
232 m_b[0] = 0.5 * (-m_b[1] - 0.5 * m_left_value * h + 3.0 * (m_y[1] - m_y[0]) / h);
237 const fltp08 h0 = m_x[1] - m_x[0];
238 const fltp08 h1 = m_x[2] - m_x[1];
239 m_b[0] = -m_b[1] + 2.0 * (m_y[1] - m_y[0]) / h0
240 + h0 * h0 / (h1 * h1) * (m_b[1] + m_b[2] - 2.0 * (m_y[2] - m_y[1]) / h1);
244 lib_assert(
false,
"unknown state");
248 m_b[n - 1] = m_right_value;
253 const fltp08 h = m_x[n - 1] - m_x[n - 2];
254 m_b[n - 1] = 0.5 * (-m_b[n - 2] + 0.5 * m_right_value * h + 3.0 * (m_y[n - 1] - m_y[n - 2]) / h);
255 m_c[n - 1] = 0.5 * m_right_value;
260 const fltp08 h0 = m_x[n - 2] - m_x[n - 3];
261 const fltp08 h1 = m_x[n - 1] - m_x[n - 2];
262 m_b[n - 1] = -m_b[n - 2] + 2.0 * (m_y[n - 1] - m_y[n - 2]) / h1 + h1 * h1 / (h0 * h0)
263 * (m_b[n - 3] + m_b[n - 2] - 2.0 * (m_y[n - 2] - m_y[n - 3]) / h0);
265 m_c[n - 1] = (m_b[n - 2] + 2.0 * m_b[n - 1]) / h1 - 3.0 * (m_y[n - 1] - m_y[n - 2]) / (h1 * h1);
269 lib_assert(
false,
"unknown state");
279 lib_assert(
false,
"unknown state");
288 lib_assert(m_x.size() == m_y.size(),
"unknown state");
289 lib_assert(m_x.size() == m_b.size(),
"unknown state");
290 lib_assert(m_x.size() > 2,
"unknown state");
291 bool modified =
false;
292 const uint04 n = m_x.size();
295 for (
uint04 i = 0; i < n; i++)
299 if (((m_y[im1] <= m_y[i]) && (m_y[i] <= m_y[ip1]) && m_b[i] < 0.0) ||
300 ((m_y[im1] >= m_y[i]) && (m_y[i] >= m_y[ip1]) && m_b[i] > 0.0)) {
308 for (
uint04 i = 0; i < n - 1; i++)
310 fltp08 h = m_x[i + 1] - m_x[i];
311 for (
uint01 n = 0; n < t_point_type::NumberOfDimensions(); n++)
313 fltp08 avg = (m_y[i + 1][n] - m_y[i][n]) / h;
314 if (avg == 0.0 && (m_b[i][n] != 0.0 || m_b[i + 1][n] != 0.0)) {
319 else if ((m_b[i][n] >= 0.0 && m_b[i + 1][n] >= 0.0 && avg > 0.0) ||
320 (m_b[i][n] <= 0.0 && m_b[i + 1][n] <= 0.0 && avg < 0.0))
324 fltp08 r =
sqrt(m_b[i][n] * m_b[i][n] + m_b[i + 1][n] * m_b[i + 1][n]) /
abs(avg);
329 m_b[i][n] *= (3.0 / r);
330 m_b[i + 1][n] *= (3.0 / r);
339 m_made_monotonic =
true;
347 auto it = std::upper_bound(m_x.begin(), m_x.end(), x);
351 t_point_type operator() (
fltp08 x)
const
359 uint04 idx = find_closest(x);
362 t_point_type interpol;
366 interpol = (m_c0 * h + m_b[0]) * h + m_y[0];
368 else if (x > m_x[n - 1])
371 interpol = (m_c[n - 1] * h + m_b[n - 1]) * h + m_y[n - 1];
376 interpol = ((m_d[idx] * h + m_c[idx]) * h + m_b[idx]) * h + m_y[idx];
383 lib_assert(order > 0,
"unknown state");
385 uint04 idx = find_closest(x);
388 t_point_type interpol;
395 interpol = 2.0 * m_c0 * h + m_b[0];
398 interpol = 2.0 * m_c0;
405 else if (x > m_x[n - 1])
411 interpol = 2.0 * m_c[n - 1] * h + m_b[n - 1];
414 interpol = 2.0 * m_c[n - 1];
427 interpol = (3.0 * m_d[idx] * h + 2.0 * m_c[idx]) * h + m_b[idx];
430 interpol = 6.0 * m_d[idx] * h + 2.0 * m_c[idx];
433 interpol = 6.0 * m_d[idx];
447 const uint04 n = m_x.size();
450 if (ignore_extrapolation ==
false)
452 root = solveCubic(m_y[0] - y, m_b[0], m_c0, t_point_type(0.0), 1);
453 for (
uint04 j = 0; j < root.size(); j++)
456 x.
add(m_x[0] + root[j]);
462 for (
uint04 i = 0; i < n - 1; i++)
464 root = solveCubic(m_y[i] - y, m_b[i], m_c[i], m_d[i], 1);
465 for (
uint04 j = 0; j < root.size(); j++)
467 fltp08 h = (i > 0) ? (m_x[i] - m_x[i - 1]) : 0.0;
469 if ((-eps <= root[j]) && (root[j] < m_x[i + 1] - m_x[i]))
471 t_point_type new_root = m_x[i] + root[j];
472 if (x.size() > 0 && x.last() + eps > new_root)
485 if (!ignore_extrapolation)
487 root = solveCubic(m_y[n - 1] - y, m_b[n - 1], m_c[n - 1], t_point_type(0.0), 1);
488 for (
uint04 j = 0; j < root.size(); j++)
491 x.
add(m_x[n - 1] + root[j]);
502 return 2.2204460492503131e-16;
535 , t_point_type b, t_point_type c
536 ,
int newton_iter = 0)
539 return solveLinear(a, b);
541 const t_point_type p = 0.5 * b / c;
542 const t_point_type q = a / c;
543 const t_point_type discr = p * p - q;
544 const fltp08 eps = 0.5 * getEPS();
545 const t_point_type discr_err = (6.0 * (p * p) + 3.0 *
abs(q) +
abs(discr)) * eps;
548 if (
abs(discr) <= discr_err)
554 else if (discr < 0.0) {
560 for (
uint01 n = 0; n < t_point_type::NumberOfDimensions(); n++)
562 x[0][n] = -p[n] -
sqrt(discr[n]);
563 x[1][n] = -p[n] +
sqrt(discr[n]);
568 for (
uint04 i = 0; i < x.size(); i++)
570 for (
int k = 0; k < newton_iter; k++)
572 t_point_type f = (c * x[i] + b) * x[i] + a;
573 t_point_type f1 = 2.0 * c * x[i] + b;
591 , t_point_type b, t_point_type c
592 , t_point_type d,
int newton_iter)
const
595 return solveQuadratic(a, b, c, newton_iter);
606 const t_point_type p = -(1.0 / 3.0) * b + (1.0 / 9.0) * (c * c);
607 const t_point_type r = 2.0 * (c * c) - 9.0 * b;
608 const t_point_type q = -0.5 * a - (1.0 / 54.0) * (c * r);
609 const t_point_type discr = p * p * p - q * q;
610 const fltp08 eps = getEPS();
611 t_point_type p_err = eps * ((3.0 / 3.0) *
abs(b)
612 + (4.0 / 9.0) * (c * c)
614 t_point_type r_err = eps * (6.0 * (c * c)
617 t_point_type q_err = 0.5 *
abs(a) * eps
618 + (1.0 / 54.0) *
abs(c) * (r_err +
abs(r) * 3.0 * eps)
620 t_point_type discr_err = (p * p) * (3.0 * p_err
621 +
abs(p) * 2.0 * eps)
622 +
abs(q) * (2.0 * q_err
628 if (
abs(discr) <= discr_err)
644 else if (discr > Vertex < 3, fltp08>(0))
648 for (
uint01 n = 0; n < t_point_type::NumberOfDimensions(); n++)
650 fltp08 ac = (1.0 / 3.0) * acos(q[n] / (p[n] *
sqrt(p[n])));
652 z[0][n] = sq *
cos(ac);
657 else if (discr < 0.0)
661 for (
uint01 n = 0; n < t_point_type::NumberOfDimensions(); n++)
663 fltp08 sgnq = (q[n] >= 0 ? 1 : -1);
665 fltp08 C = sgnq * pow(basis, 1.0 / 3.0);
666 z[0][n] = C + p[n] / C;
669 for (
uint04 i = 0; i < z.size(); i++)
672 z[i] -= (1.0 / 3.0) * c;
674 for (
int k = 0; k < newton_iter; k++)
676 t_point_type f = ((z[i] + c) * z[i] + b) * z[i] + a;
677 t_point_type f1 = (3.0 * z[i] + 2.0 * c) * z[i] + b;
687 lib_assert(z.size() > 0,
"cubic should always have at least one root");
688 t_point_type xmin =
abs(z[0]);
690 for (
uint04 i = 1; i < z.size(); i++)
692 if (xmin >
abs(z[i]))
700 std::sort(z.begin(), z.end());
705 lib_assert(m_x.size() == 0,
"setPoints() must not have happened yet");
708 m_left_value = left_value;
709 m_right_value = right_value;
712 void setCoeffsFromB()
714 lib_assert(m_x.size() == m_y.size(),
"m_y size");
715 lib_assert(m_x.size() == m_b.size(),
"m_b size");
716 lib_assert(m_x.size() > 2,
"size bust be > 2");
723 for (
uint04 i = 0; i < n - 1; i++)
725 const fltp08 h = m_x[i + 1] - m_x[i];
727 m_c[i] = (3.0 * (m_y[i + 1] - m_y[i]) / h - (2.0 * m_b[i] + m_b[i + 1])) / h;
729 m_d[i] = ((m_b[i + 1] - m_b[i]) / (3.0 * h) - 2.0 / 3.0 * m_c[i]) / h;