2 #include "LinAlg/LinAlg.hpp"
3 #include "qip/Vector.hpp"
4 #include <gsl/gsl_bspline.h>
5 #include <gsl/gsl_version.h>
12 #ifdef GSL_MAJOR_VERSION
13 #if GSL_MAJOR_VERSION == 1
17 #if GSL_MAJOR_VERSION <= 2 && GSL_MINOR_VERSION < 8
18 #define GSL_VERSION_PRIOR_2_8
44 gsl_bspline_workspace *gsl_bspl_work{
nullptr};
48 gsl_bspline_deriv_workspace *gsl_bspl_deriv_work{
nullptr};
52 enum class KnotDistro { logarithmic, linear, loglinear };
56 BSpline(std::size_t n, std::size_t k,
double x0,
double xmax,
57 KnotDistro kd = KnotDistro::logarithmic)
58 : m_K(k), m_N(n), m_xmax(xmax) {
59 assert(m_N > m_K &&
"Require N>K for B-splines");
60 assert(xmax > x0 && x0 > 0.0 && xmax > 0.0 &&
"xmax>x0 and both positive");
63 const std::size_t n_break = m_N - m_K + 2;
64 gsl_bspl_work = gsl_bspline_alloc(m_K, n_break);
68 gsl_bspl_deriv_work = gsl_bspline_deriv_alloc(m_K);
71 set_knots(x0, xmax, n_break, kd);
74 #ifdef GSL_VERSION_PRIOR_2_8
76 assert(gsl_bspline_ncoeffs(gsl_bspl_work) == m_N);
78 assert(gsl_bspline_ncontrol(gsl_bspl_work) == m_N);
80 assert(gsl_bspline_order(gsl_bspl_work) == m_K);
81 assert(gsl_bspline_nbreak(gsl_bspl_work) == n_break);
91 gsl_bspline_free(gsl_bspl_work);
93 gsl_bspline_deriv_free(gsl_bspl_deriv_work);
99 std::size_t
K() {
return m_K; }
101 std::size_t
d() {
return m_K - 1; }
103 std::size_t
N() {
return m_N; }
109 for (std::size_t i = 0; i < m_N; ++i) {
110 if (gsl_vector_get(gsl_bspl_work->knots, i + m_K) > x) {
119 std::vector<double>
get(
double x) {
120 std::vector<double> b(m_N);
121 gsl_vector_view b_gsl = gsl_vector_view_array(b.data(), b.size());
122 if (x >= 0.0 && x <= m_xmax) {
124 #ifdef GSL_VERSION_PRIOR_2_8
126 gsl_bspline_eval(x, &b_gsl.vector, gsl_bspl_work);
128 gsl_bspline_eval_basis(x, &b_gsl.vector, gsl_bspl_work);
145 std::pair<std::size_t, LinAlg::Matrix<double>>
147 std::pair<std::size_t, LinAlg::Matrix<double>> out{0, {m_K, n_deriv + 1}};
149 if (x >= 0.0 && x <= m_xmax) {
153 auto &i0 = out.first;
154 auto &bij = out.second;
155 gsl_matrix_view b_gsl = bij.as_gsl_view();
159 gsl_bspline_deriv_eval_nonzero(x, n_deriv, &b_gsl.matrix, &i0, &i_end,
160 gsl_bspl_work, gsl_bspl_deriv_work);
161 #elif defined GSL_VERSION_PRIOR_2_8
163 gsl_bspline_deriv_eval_nonzero(x, n_deriv, &b_gsl.matrix, &i0, &i_end,
166 gsl_bspline_basis_deriv(x, n_deriv, &b_gsl.matrix, &i0, gsl_bspl_work);
174 void print_knots()
const {
176 std::size_t n_cols_to_print = 4;
177 std::cout <<
"Knots:\n ";
178 std::size_t count = 0;
179 while (count < m_N + m_K) {
180 auto t = gsl_bspl_work->knots->data[count];
183 if (count % n_cols_to_print == 0)
186 if (count % n_cols_to_print != 0)
192 void set_knots(
double x0,
double xmax, std::size_t n_break, KnotDistro kd) {
201 auto breaks = (kd == KnotDistro::logarithmic) ?
203 (kd == KnotDistro::linear) ?
205 (kd == KnotDistro::loglinear) ?
207 std::vector<double>{};
209 breaks.insert(breaks.begin(), 0.0);
211 auto gsl_break_vec = gsl_vector_view_array(breaks.data(), breaks.size());
213 #ifdef GSL_VERSION_PRIOR_2_8
215 gsl_bspline_knots(&gsl_break_vec.vector, gsl_bspl_work);
217 gsl_bspline_init_augment(&gsl_break_vec.vector, gsl_bspl_work);
Definition: BSpline.hpp:35
std::size_t d()
Degree of the splines, d:=K-1.
Definition: BSpline.hpp:101
std::vector< double > get(double x)
Returns a std::vector of all splines {b0, b1, ..., b_N-1} evaluated at x.
Definition: BSpline.hpp:119
BSpline(std::size_t n, std::size_t k, double x0, double xmax, KnotDistro kd=KnotDistro::logarithmic)
Constructs basis of n splines of order k, defined over [0,xmax]. x0 is first non-zero knot....
Definition: BSpline.hpp:56
std::size_t find_i0(double x)
Returns the first nonzero spline index i0; Note that i runs [0,N). The last non-zero index is min(i0+...
Definition: BSpline.hpp:108
std::pair< std::size_t, LinAlg::Matrix< double > > get_nonzero(double x, std::size_t n_deriv)
Returns a pair {i0, M}, where i0 is spline index of first non-zero spline, and M is a matrix of non-z...
Definition: BSpline.hpp:146
std::size_t K()
Order of the splines, K.
Definition: BSpline.hpp:99
std::size_t N()
Number of splines, N.
Definition: BSpline.hpp:103
std::vector< T > uniform_range(T first, T last, N number)
Produces a uniformly*(see below) distributed range of values between [first,last] with number steps....
Definition: Vector.hpp:232
std::vector< T > loglinear_range(T first, T last, T b, N number)
Produces a Log-Linear distributed range of values between [first,last] with number steps....
Definition: Vector.hpp:291
std::vector< T > logarithmic_range(T first, T last, N number)
Produces a logarithmicly*(see below) distributed range of values between [first,last] with number ste...
Definition: Vector.hpp:261