Warning, file /include/boost/math/special_functions/cardinal_b_spline.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006 #ifndef BOOST_MATH_SPECIAL_CARDINAL_B_SPLINE_HPP
0007 #define BOOST_MATH_SPECIAL_CARDINAL_B_SPLINE_HPP
0008
0009 #include <array>
0010 #include <cmath>
0011 #include <limits>
0012 #include <type_traits>
0013
0014 namespace boost { namespace math {
0015
0016 namespace detail {
0017
0018 template<class Real>
0019 inline Real B1(Real x)
0020 {
0021 if (x < 0)
0022 {
0023 return B1(-x);
0024 }
0025 if (x < Real(1))
0026 {
0027 return 1 - x;
0028 }
0029 return Real(0);
0030 }
0031 }
0032
0033 template<unsigned n, typename Real>
0034 Real cardinal_b_spline(Real x) {
0035 static_assert(!std::is_integral<Real>::value, "Does not work with integral types.");
0036
0037 if (x < 0) {
0038
0039 return cardinal_b_spline<n, Real>(-x);
0040 }
0041
0042 if (n==0)
0043 {
0044 if (x < Real(1)/Real(2)) {
0045 return Real(1);
0046 }
0047 else if (x == Real(1)/Real(2)) {
0048 return Real(1)/Real(2);
0049 }
0050 else {
0051 return Real(0);
0052 }
0053 }
0054
0055 if (n==1)
0056 {
0057 return detail::B1(x);
0058 }
0059
0060 Real supp_max = (n+1)/Real(2);
0061 if (x >= supp_max)
0062 {
0063 return Real(0);
0064 }
0065
0066
0067
0068
0069 std::array<Real, n> v;
0070 Real z = x + 1 - supp_max;
0071 for (unsigned i = 0; i < n; ++i)
0072 {
0073 v[i] = detail::B1(z);
0074 z += 1;
0075 }
0076
0077 Real smx = supp_max - x;
0078 for (unsigned j = 2; j <= n; ++j)
0079 {
0080 Real a = (j + 1 - smx);
0081 Real b = smx;
0082 for(unsigned k = 0; k <= n - j; ++k)
0083 {
0084 v[k] = (a*v[k+1] + b*v[k])/Real(j);
0085 a += 1;
0086 b -= 1;
0087 }
0088 }
0089
0090 return v[0];
0091 }
0092
0093
0094 template<unsigned n, typename Real>
0095 Real cardinal_b_spline_prime(Real x)
0096 {
0097 static_assert(!std::is_integral<Real>::value, "Cardinal B-splines do not work with integer types.");
0098
0099 if (x < 0)
0100 {
0101
0102 return -cardinal_b_spline_prime<n, Real>(-x);
0103 }
0104
0105
0106 if (n==0)
0107 {
0108
0109 if (x == Real(1)/Real(2))
0110 {
0111 return std::numeric_limits<Real>::infinity();
0112 }
0113 else
0114 {
0115 return Real(0);
0116 }
0117 }
0118
0119 if (n==1)
0120 {
0121 if (x==0)
0122 {
0123 return Real(0);
0124 }
0125 if (x==1)
0126 {
0127 return -Real(1)/Real(2);
0128 }
0129 return Real(-1);
0130 }
0131
0132
0133 Real supp_max = (n+1)/Real(2);
0134 if (x >= supp_max)
0135 {
0136 return Real(0);
0137 }
0138
0139
0140 std::array<Real, n> v;
0141 Real z = x + 1 - supp_max;
0142 for (unsigned i = 0; i < n; ++i)
0143 {
0144 v[i] = detail::B1(z);
0145 z += 1;
0146 }
0147
0148 Real smx = supp_max - x;
0149 for (unsigned j = 2; j <= n - 1; ++j)
0150 {
0151 Real a = (j + 1 - smx);
0152 Real b = smx;
0153 for(unsigned k = 0; k <= n - j; ++k)
0154 {
0155 v[k] = (a*v[k+1] + b*v[k])/Real(j);
0156 a += 1;
0157 b -= 1;
0158 }
0159 }
0160
0161 return v[1] - v[0];
0162 }
0163
0164
0165 template<unsigned n, typename Real>
0166 Real cardinal_b_spline_double_prime(Real x)
0167 {
0168 static_assert(!std::is_integral<Real>::value, "Cardinal B-splines do not work with integer types.");
0169 static_assert(n >= 3, "n>=3 for second derivatives of cardinal B-splines is required.");
0170
0171 if (x < 0)
0172 {
0173
0174 return cardinal_b_spline_double_prime<n, Real>(-x);
0175 }
0176
0177
0178 Real supp_max = (n+1)/Real(2);
0179 if (x >= supp_max)
0180 {
0181 return Real(0);
0182 }
0183
0184
0185 std::array<Real, n> v;
0186 Real z = x + 1 - supp_max;
0187 for (unsigned i = 0; i < n; ++i)
0188 {
0189 v[i] = detail::B1(z);
0190 z += 1;
0191 }
0192
0193 Real smx = supp_max - x;
0194 for (unsigned j = 2; j <= n - 2; ++j)
0195 {
0196 Real a = (j + 1 - smx);
0197 Real b = smx;
0198 for(unsigned k = 0; k <= n - j; ++k)
0199 {
0200 v[k] = (a*v[k+1] + b*v[k])/Real(j);
0201 a += 1;
0202 b -= 1;
0203 }
0204 }
0205
0206 return v[2] - 2*v[1] + v[0];
0207 }
0208
0209
0210 template<unsigned n, class Real>
0211 Real forward_cardinal_b_spline(Real x)
0212 {
0213 static_assert(!std::is_integral<Real>::value, "Cardinal B-splines do not work with integral types.");
0214 return cardinal_b_spline<n>(x - (n+1)/Real(2));
0215 }
0216
0217 }}
0218 #endif