mirror of
https://github.com/boostorg/math.git
synced 2026-01-19 04:22:09 +00:00
Second derivative for septic Hermite spline.
This commit is contained in:
@@ -336,9 +336,57 @@ public:
|
||||
return dydx;
|
||||
}
|
||||
|
||||
inline Real double_prime(Real x) const
|
||||
inline Real double_prime(Real x) constq
|
||||
{
|
||||
return std::numeric_limits<Real>::quiet_NaN();
|
||||
Real xf = x0_ + (y_.size()-1)/inv_dx_;
|
||||
if (x < x0_ || x > xf)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss.precision(std::numeric_limits<Real>::digits10+3);
|
||||
oss << "Requested abscissa x = " << x << ", which is outside of allowed range ["
|
||||
<< x0_ << ", " << xf << "]";
|
||||
throw std::domain_error(oss.str());
|
||||
}
|
||||
if (x == xf)
|
||||
{
|
||||
return d2y_.back()*2*inv_dx_*inv_dx_;
|
||||
}
|
||||
|
||||
return this->unchecked_double_prime(x);
|
||||
}
|
||||
|
||||
inline Real unchecked_double_prime(Real x) const
|
||||
{
|
||||
using std::floor;
|
||||
Real s3 = (x-x0_)*inv_dx_;
|
||||
Real ii = floor(s3);
|
||||
auto i = static_cast<decltype(y_.size())>(ii);
|
||||
Real t = s3 - ii;
|
||||
|
||||
Real y0 = y_[i];
|
||||
Real y1 = y_[i+1];
|
||||
Real dy0 = dy_[i];
|
||||
Real dy1 = dy_[i+1];
|
||||
Real a0 = d2y_[i];
|
||||
Real a1 = d2y_[i+1];
|
||||
Real j0 = d3y_[i];
|
||||
Real j1 = d3y_[i+1];
|
||||
Real t2 = t*t;
|
||||
|
||||
Real z0 = 420*t2*(1 + t*(-4 + t*(5 - 2*t)));
|
||||
Real z1 = 60*t2*(-4 + t*(15 + t*(-18 + 7*t)));
|
||||
Real z2 = 60*t2*(-3 + t*(13 + t*(-17 + 7*t)));
|
||||
Real z3 = (1 + t2*(-60 + t*(200 + t*(-225 + 84*t))));
|
||||
Real z4 = t2*(30 + t*(-140 + t*(195 - 84*t)));
|
||||
Real z5 = t*(1 + t*(-8 + t*(20 + t*(-20 + 7*t))));
|
||||
Real z6 = t2*(-2 + t*(10 + t*(-15 + 7*t)));
|
||||
|
||||
Real d2ydx2 = z0*(y1-y0)*inv_dx_*inv_dx_;
|
||||
d2ydx2 += (z1*dy0 + z2*dy1)*inv_dx_*inv_dx_;
|
||||
d2ydx2 += (z3*a0 + z4*a1)*2*inv_dx_*inv_dx_;
|
||||
d2ydx2 += 6*(z5*j0 + z6*j1)/(inv_dx_*inv_dx_);
|
||||
|
||||
return d2ydx2;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -437,7 +485,7 @@ public:
|
||||
}
|
||||
if (x == xf)
|
||||
{
|
||||
return data_.back()[1];
|
||||
return data_.back()[1]*inv_dx_;
|
||||
}
|
||||
|
||||
return this->unchecked_prime(x);
|
||||
@@ -449,7 +497,7 @@ public:
|
||||
Real ii = floor(s3);
|
||||
auto i = static_cast<decltype(data_.size())>(ii);
|
||||
Real t = s3 - ii;
|
||||
|
||||
|
||||
Real y0 = data_[i][0];
|
||||
Real y1 = data_[i+1][0];
|
||||
Real dy0 = data_[i][1];
|
||||
@@ -475,9 +523,57 @@ public:
|
||||
return dydx;
|
||||
}
|
||||
|
||||
inline Real double_prime(Real x) const
|
||||
inline Real double_prime(Real x) const
|
||||
{
|
||||
return std::numeric_limits<Real>::quiet_NaN();
|
||||
Real xf = x0_ + (data_.size()-1)/inv_dx_;
|
||||
if (x < x0_ || x > xf)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss.precision(std::numeric_limits<Real>::digits10+3);
|
||||
oss << "Requested abscissa x = " << x << ", which is outside of allowed range ["
|
||||
<< x0_ << ", " << xf << "]";
|
||||
throw std::domain_error(oss.str());
|
||||
}
|
||||
if (x == xf)
|
||||
{
|
||||
return data_.back()[2]*2*inv_dx_*inv_dx_;
|
||||
}q
|
||||
|
||||
return this->unchecked_double_prime(x);
|
||||
}
|
||||
|
||||
inline Real unchecked_double_prime(Real x) const
|
||||
{
|
||||
using std::floor;
|
||||
Real s3 = (x-x0_)*inv_dx_;
|
||||
Real ii = floor(s3);
|
||||
auto i = static_cast<decltype(data_.size())>(ii);
|
||||
Real t = s3 - ii;
|
||||
|
||||
Real y0 = data_[i][0];
|
||||
Real y1 = data_[i+1][0];
|
||||
Real dy0 = data_[i][1];
|
||||
Real dy1 = data_[i+1][1];
|
||||
Real a0 = data_[i][2];
|
||||
Real a1 = data_[i+1][2];
|
||||
Real j0 = data_[i][3];
|
||||
Real j1 = data_[i+1][3];
|
||||
Real t2 = t*t;
|
||||
|
||||
Real z0 = 420*t2*(1 + t*(-4 + t*(5 - 2*t)));
|
||||
Real z1 = 60*t2*(-4 + t*(15 + t*(-18 + 7*t)));
|
||||
Real z2 = 60*t2*(-3 + t*(13 + t*(-17 + 7*t)));
|
||||
Real z3 = (1 + t2*(-60 + t*(200 + t*(-225 + 84*t))));
|
||||
Real z4 = t2*(30 + t*(-140 + t*(195 - 84*t)));
|
||||
Real z5 = t*(1 + t*(-8 + t*(20 + t*(-20 + 7*t))));
|
||||
Real z6 = t2*(-2 + t*(10 + t*(-15 + 7*t)));
|
||||
|
||||
Real d2ydx2 = z0*(y1-y0)*inv_dx_*inv_dx_;
|
||||
d2ydx2 += (z1*dy0 + z2*dy1)*inv_dx_*inv_dx_;
|
||||
d2ydx2 += (z3*a0 + z4*a1)*2*inv_dx_*inv_dx_;
|
||||
d2ydx2 += 6*(z5*j0 + z6*j1)/(inv_dx_*inv_dx_);
|
||||
|
||||
return d2ydx2;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -491,6 +491,10 @@ public:
|
||||
{
|
||||
return m_qh->unchecked_double_prime(x);
|
||||
}
|
||||
if constexpr (p >= 10)
|
||||
{
|
||||
return m_sh->unchecked_double_prime(x);
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<Real, Real> support() const
|
||||
|
||||
@@ -51,9 +51,11 @@ void test_constant()
|
||||
d2ydx2.resize(128, 0);
|
||||
d3ydx3.resize(128, 0);
|
||||
auto csh = cardinal_septic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3), x0, dx);
|
||||
for (Real t = x0; t <= 127; t += 0.25) {
|
||||
for (Real t = x0; t <= 127; t += 0.25)
|
||||
{
|
||||
CHECK_ULP_CLOSE(Real(7), csh(t), 24);
|
||||
CHECK_ULP_CLOSE(Real(0), csh.prime(t), 24);
|
||||
CHECK_ULP_CLOSE(Real(0), csh.double_prime(t), 24);
|
||||
}
|
||||
|
||||
std::vector<std::array<Real, 4>> data(128);
|
||||
@@ -69,6 +71,7 @@ void test_constant()
|
||||
{
|
||||
CHECK_ULP_CLOSE(Real(7), csh_aos(t), 24);
|
||||
CHECK_ULP_CLOSE(Real(0), csh_aos.prime(t), 24);
|
||||
CHECK_ULP_CLOSE(Real(0), csh_aos.double_prime(t), 24);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -130,6 +133,7 @@ void test_linear()
|
||||
{
|
||||
CHECK_ULP_CLOSE(t, csh(t), 15);
|
||||
CHECK_ULP_CLOSE(Real(1), csh.prime(t), 15);
|
||||
CHECK_ULP_CLOSE(Real(0), csh.double_prime(t), 15);
|
||||
}
|
||||
|
||||
std::vector<std::array<Real, 4>> data(10);
|
||||
@@ -145,6 +149,7 @@ void test_linear()
|
||||
{
|
||||
CHECK_ULP_CLOSE(t, csh_aos(t), 15);
|
||||
CHECK_ULP_CLOSE(Real(1), csh_aos.prime(t), 15);
|
||||
CHECK_ULP_CLOSE(Real(0), csh_aos.double_prime(t), 15);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,6 +236,7 @@ void test_quadratic()
|
||||
{
|
||||
CHECK_ULP_CLOSE(t*t/2, csh(t), 24);
|
||||
CHECK_ULP_CLOSE(t, csh.prime(t), 24);
|
||||
CHECK_ULP_CLOSE(Real(1), csh.double_prime(t), 24);
|
||||
}
|
||||
|
||||
std::vector<std::array<Real, 4>> data(10);
|
||||
@@ -246,6 +252,7 @@ void test_quadratic()
|
||||
{
|
||||
CHECK_ULP_CLOSE(t*t/2, csh_aos(t), 24);
|
||||
CHECK_ULP_CLOSE(t, csh_aos.prime(t), 24);
|
||||
CHECK_ULP_CLOSE(Real(1), csh_aos.double_prime(t), 24);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,6 +310,7 @@ void test_cubic()
|
||||
{
|
||||
CHECK_ULP_CLOSE(t*t*t, csh(t), 151);
|
||||
CHECK_ULP_CLOSE(3*t*t, csh.prime(t), 151);
|
||||
CHECK_ULP_CLOSE(6*t, csh.double_prime(t), 151);
|
||||
}
|
||||
|
||||
std::vector<std::array<Real, 4>> data(8);
|
||||
@@ -319,6 +327,7 @@ void test_cubic()
|
||||
{
|
||||
CHECK_ULP_CLOSE(t*t*t, csh_aos(t), 151);
|
||||
CHECK_ULP_CLOSE(3*t*t, csh_aos.prime(t), 151);
|
||||
CHECK_ULP_CLOSE(6*t, csh_aos.double_prime(t), 151);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,6 +386,7 @@ void test_quartic()
|
||||
{
|
||||
CHECK_ULP_CLOSE(t*t*t*t, csh(t), 117);
|
||||
CHECK_ULP_CLOSE(4*t*t*t, csh.prime(t), 117);
|
||||
CHECK_ULP_CLOSE(12*t*t, csh.double_prime(t), 117);
|
||||
}
|
||||
|
||||
std::vector<std::array<Real, 4>> data(10);
|
||||
@@ -393,6 +403,7 @@ void test_quartic()
|
||||
{
|
||||
CHECK_ULP_CLOSE(t*t*t*t, csh_aos(t), 117);
|
||||
CHECK_ULP_CLOSE(4*t*t*t, csh_aos.prime(t), 117);
|
||||
CHECK_ULP_CLOSE(12*t*t, csh_aos.double_prime(t), 117);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user