bspline.cpp
1 /*
2  * This file is part of CasADi.
3  *
4  * CasADi -- A symbolic framework for dynamic optimization.
5  * Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl,
6  * KU Leuven. All rights reserved.
7  * Copyright (C) 2011-2014 Greg Horn
8  *
9  * CasADi is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 3 of the License, or (at your option) any later version.
13  *
14  * CasADi is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with CasADi; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 
26 #include "bspline_impl.hpp"
27 
28 namespace casadi {
29 
31  char t;
32  s.unpack("BSpline::type", t);
33  switch (t) {
34  case 'n':
35  return new BSpline(s);
36  case 'p':
37  return new BSplineParametric(s);
38  default:
39  casadi_error("Unknown BSpline type");
40  }
41  }
42 
44  BSplineCommon::BSplineCommon(const std::vector<double>& knots,
45  const std::vector<casadi_int>& offset,
46  const std::vector<casadi_int>& degree,
47  casadi_int m,
48  const std::vector<casadi_int>& lookup_mode) :
49  knots_(knots), offset_(offset), degree_(degree),
50  m_(m), lookup_mode_(lookup_mode) {
52  }
53 
54  size_t BSplineCommon::sz_iw() const {
55  return n_iw(degree_);
56  }
57 
58  size_t BSplineCommon::sz_w() const {
59  return n_w(degree_);
60  }
61 
62  size_t BSplineCommon::n_iw(const std::vector<casadi_int>& degree) {
63  casadi_int n_dims = degree.size();
64  casadi_int sz = 0;
65  sz += n_dims+1; // boor_offset
66  sz += n_dims; // starts
67  sz += n_dims; // index
68  sz += n_dims+1; // coeff_offset
69  return sz;
70  }
71 
72  size_t BSplineCommon::n_w(const std::vector<casadi_int>& degree) {
73  casadi_int n_dims = degree.size();
74  casadi_int sz = 0;
75  for (casadi_int k=0;k<n_dims-1;++k) {
76  sz += degree[k]+1; // boor
77  }
78  sz += 2*degree[n_dims-1]+1;
79  sz += n_dims+1;
80  return sz;
81  }
82 
83  casadi_int BSplineCommon::get_coeff_size(casadi_int m, const std::vector<casadi_int>& offset,
84  const std::vector<casadi_int>& degree) {
85  casadi_int ret = m;
86  for (casadi_int i=0;i<degree.size();++i) ret*= offset[i+1]-offset[i]-degree[i]-1;
87  return ret;
88  }
89 
90  void BSplineCommon::prepare(casadi_int m, const std::vector<casadi_int>& offset,
91  const std::vector<casadi_int>& degree, casadi_int &coeffs_size,
92  std::vector<casadi_int>& coeffs_dims, std::vector<casadi_int>& strides) {
93 
94  casadi_int n_dims = degree.size();
95  coeffs_size = get_coeff_size(m, offset, degree);
96  coeffs_dims.resize(n_dims+1);
97  coeffs_dims[0] = m;
98  for (casadi_int i=0;i<n_dims;++i) coeffs_dims[i+1] = offset[i+1]-offset[i]-degree[i]-1;
99 
100  // Prepare strides
101  strides.resize(n_dims);
102  strides[0] = m;
103  for (casadi_int i=0;i<n_dims-1;++i) {
104  strides[i+1] = strides[i]*coeffs_dims[i+1];
105  }
106  }
107 
110  s.pack("BSpline::type", 'n');
111  }
112 
115  s.pack("BSpline::type", 'p');
116  }
117 
120  s.pack("BSplineCommon::knots", knots_);
121  s.pack("BSplineCommon::offset", offset_);
122  s.pack("BSplineCommon::degree", degree_);
123  s.pack("BSplineCommon::m", m_);
124  s.pack("BSplineCommon::lookup_mode", lookup_mode_);
125  s.pack("BSplineCommon::strides", strides_);
126  s.pack("BSplineCommon::coeffs_dims", coeffs_dims_);
127  s.pack("BSplineCommon::coeffs_size", coeffs_size_);
128  s.pack("BSplineCommon::jac_cache_", jac_cache_);
129  }
130 
132  s.unpack("BSplineCommon::knots", knots_);
133  s.unpack("BSplineCommon::offset", offset_);
134  s.unpack("BSplineCommon::degree", degree_);
135  s.unpack("BSplineCommon::m", m_);
136  s.unpack("BSplineCommon::lookup_mode", lookup_mode_);
137  s.unpack("BSplineCommon::strides", strides_);
138  s.unpack("BSplineCommon::coeffs_dims", coeffs_dims_);
139  s.unpack("BSplineCommon::coeffs_size", coeffs_size_);
140  s.unpack("BSplineCommon::jac_cache_", jac_cache_);
141  }
142 
145  s.pack("BSpline::coeffs", coeffs_);
146  }
147 
149  s.unpack("BSpline::coeffs", coeffs_);
150  }
151 
152  BSpline::BSpline(const MX& x, const std::vector<double>& knots,
153  const std::vector<casadi_int>& offset,
154  const std::vector<double>& coeffs,
155  const std::vector<casadi_int>& degree,
156  casadi_int m,
157  const std::vector<casadi_int>& lookup_mode) :
158  BSplineCommon(knots, offset, degree, m, lookup_mode), coeffs_(coeffs) {
159  casadi_assert_dev(x.numel()==degree.size());
160  set_dep(x);
162  }
163 
165  const MX& coeffs,
166  const std::vector<double>& knots,
167  const std::vector<casadi_int>& offset,
168  const std::vector<casadi_int>& degree,
169  casadi_int m,
170  const std::vector<casadi_int>& lookup_mode) :
171  BSplineCommon(knots, offset, degree, m, lookup_mode) {
172  casadi_assert_dev(x.size1()==degree.size());
173  set_dep(x, coeffs);
175  }
176 
177  void get_boor(const MX& x, const MX& knots, casadi_int degree, casadi_int lookup_mode,
178  MX& start, MX& boor) {
179  MX knots_clipped = knots(range(degree, knots.size1()-degree));
180 
181  Dict low_opts;
182  low_opts["lookup_mode"] = Low::lookup_mode_from_enum(lookup_mode);
183  MX L = low(knots_clipped, x, low_opts);
184  start = fmin(L, knots.size1()-2*degree-2);
185 
186  DM boor_init = DM::zeros(x.size2(), 2*degree+1);
187  boor_init(Slice(), degree) = 1;
188  std::vector<MX> boor_full = horzsplit(MX(boor_init));
189  casadi_int n_knots = 2*degree+2;
190 
191  MX kn;
192  MX(knots).get_nz(kn, false, start, MX(range(n_knots)));
193 
194  std::vector<MX> knv = horzsplit(kn);
195 
196  MX xt = x.T();
197 
198  for (casadi_int d=1;d<degree+1;++d) {
199  for (casadi_int i=0;i<n_knots-d-1;++i) {
200  MX bottom = knv[i+d]-knv[i];
201  MX b = if_else_zero(bottom, (xt-knv[i])*boor_full[i]/(bottom+1e-100));
202  bottom = knv[i+d+1]-knv[i + 1];
203  b += if_else_zero(bottom, (knv[i+d+1]-xt)*boor_full[i+1]/(bottom+1e-100));
204  boor_full[i] = b;
205  }
206  }
207 
208  boor = horzcat(std::vector<MX>(boor_full.begin(), boor_full.begin()+degree+1));
209  }
210 
211  // Helper: get number of knots from either std::vector<double> or MX
212  static casadi_int knot_size(const std::vector<double>& k) { return k.size(); }
213  static casadi_int knot_size(const MX& k) { return k.size1(); }
214 
215  template<typename K>
216  MX do_inline(const MX& x,
217  const std::vector<K>& knots,
218  const MX& coeffs,
219  casadi_int m,
220  const std::vector<casadi_int>& degree,
221  const std::vector<casadi_int>& lookup_mode) {
222 
223  casadi_int batch_x = x.size2();
224 
225  // Number of grid points
226  casadi_int N = knots.size();
227  std::vector<MX> xs = vertsplit(x);
228 
229  // Compute De Boor vector in each direction
230  std::vector<MX> starts(N);
231  std::vector< std::vector<MX> > boors(N);
232  for (casadi_int i=0;i<N;++i) {
233  MX boor;
234  get_boor(xs[i], knots[i], degree[i], lookup_mode[i], starts[i], boor);
235  boors[i] = horzsplit(boor.T());
236  }
237 
238  // Compute strides
239  std::vector<casadi_int> strides = {m};
240  for (casadi_int i=0;i<N-1;++i) {
241  strides.push_back(strides.back()*(knot_size(knots[i])-degree[i]-1));
242  }
243 
244  // Start index of subtensor: row vector
245  MX start = mtimes(DM(strides).T(), vertcat(starts));
246 
247  // Elements of subtensor
248  DM core = DM(range(m));
249  for (casadi_int i=0;i<N;++i) {
250  casadi_int n = degree[i]+1;
251  core = vec(repmat(core, 1, n)+repmat(strides[i]*DM(range(n)).T(), core.size1(), 1));
252  }
253 
254  std::vector<MX> res;
255 
256  for (casadi_int k=0;k<batch_x;++k) {
257 
258  // Flattened subtensor of coefficients
259  MX c = reshape(coeffs(start(k)+core), m, -1);
260 
261  // Compute outer product of De Boor vectors
262  MX boor = 1;
263  for (casadi_int i=0;i<N;++i) {
264  boor = vec(mtimes(boor, boors[i][k].T()));
265  }
266 
267  res.push_back(mtimes(c, boor));
268  }
269 
270  return horzcat(res);
271  }
272 
273  MX BSpline::create(const MX& x, const std::vector< std::vector<double> >& knots,
274  const std::vector<double>& coeffs,
275  const std::vector<casadi_int>& degree,
276  casadi_int m,
277  const Dict& opts) {
278 
279  casadi_assert(x.is_vector(), "x argument must be a vector, got " + x.dim() + " instead.");
280  casadi_assert(x.numel()==knots.size(), "x argument length (" + str(x.numel()) + ") must match "
281  "number knot list length (" + str(knots.size()) + ").");
282  casadi_assert(degree.size()==knots.size(), "Degree list length (" + str(degree.size()) + ") "
283  "must match knot list length (" + str(knots.size()) + ").");
284 
285  bool do_inline_flag = false;
286  std::vector<std::string> lookup_mode;
287 
288  for (auto&& op : opts) {
289  if (op.first=="inline") {
290  do_inline_flag = op.second;
291  } else if (op.first=="lookup_mode") {
292  lookup_mode = op.second;
293  }
294  }
295 
296  std::vector<casadi_int> offset;
297  std::vector<double> stacked;
298  Interpolant::stack_grid(knots, offset, stacked);
299 
300  std::vector<casadi_int> mode =
301  Interpolant::interpret_lookup_mode(lookup_mode, stacked, offset, degree, degree);
302 
303  if (do_inline_flag) {
304  return do_inline(x, knots, coeffs, m, degree, mode);
305  } else {
306  return x->get_bspline(stacked, offset, coeffs, degree, m, mode);
307  }
308  }
309 
311  const MX& coeffs,
312  const std::vector< std::vector<double> >& knots,
313  const std::vector<casadi_int>& degree,
314  casadi_int m,
315  const Dict& opts) {
316 
317  casadi_assert(x.is_vector(), "x argument must be a vector, got " + x.dim() + " instead.");
318  casadi_assert(x.numel()==knots.size(), "x argument length (" + str(x.numel()) + ") must match "
319  "knot list length (" + str(knots.size()) + ").");
320  casadi_assert(degree.size()==knots.size(), "Degree list length (" + str(degree.size()) + ") "
321  "must match knot list length (" + str(knots.size()) + ").");
322  bool do_inline_flag = false;
323  std::vector<std::string> lookup_mode;
324 
325  for (auto&& op : opts) {
326  if (op.first=="inline") {
327  do_inline_flag = op.second;
328  } else if (op.first=="lookup_mode") {
329  lookup_mode = op.second;
330  }
331  }
332 
333  std::vector<casadi_int> offset;
334  std::vector<double> stacked;
335  Interpolant::stack_grid(knots, offset, stacked);
336  std::vector<casadi_int> mode =
337  Interpolant::interpret_lookup_mode(lookup_mode, stacked, offset, degree, degree);
338 
339  if (do_inline_flag) {
340  return do_inline(x, knots, coeffs, m, degree, mode);
341  } else {
342  return x->get_bspline(coeffs, stacked, offset, degree, m, mode);
343  }
344  }
345 
347  const MX& coeffs,
348  const std::vector<MX>& knots,
349  const std::vector<casadi_int>& degree,
350  casadi_int m,
351  const Dict& opts) {
352 
353  casadi_assert(x.is_vector(), "x argument must be a vector, got " + x.dim() + " instead.");
354  casadi_assert(x.numel()==knots.size(), "x argument length (" + str(x.numel()) + ") must match "
355  "knot list length (" + str(knots.size()) + ").");
356  casadi_assert(degree.size()==knots.size(), "Degree list length (" + str(degree.size()) + ") "
357  "must match knot list length (" + str(knots.size()) + ").");
358 
359  // Parametric knots: always inline (non-inline path requires numeric knots)
360  std::vector<std::string> lookup_mode;
361  for (auto&& op : opts) {
362  if (op.first=="lookup_mode") {
363  lookup_mode = op.second;
364  }
365  }
366 
367  // Build offset from MX knot sizes
368  std::vector<casadi_int> offset(knots.size()+1);
369  offset[0] = 0;
370  for (casadi_int i=0; i<knots.size(); ++i) {
371  offset[i+1] = offset[i] + knots[i].size1();
372  }
373 
374  std::vector<casadi_int> mode =
375  Interpolant::interpret_lookup_mode(lookup_mode, std::vector<double>(),
376  offset, degree, degree);
377 
378  return do_inline(x, knots, coeffs, m, degree, mode);
379  }
380 
381  std::string BSpline::disp(const std::vector<std::string>& arg) const {
382  return "BSpline(" + arg.at(0) + ")";
383  }
384 
385  std::string BSplineParametric::disp(const std::vector<std::string>& arg) const {
386  return "BSplineParametric(" + arg.at(0) + ", " + arg.at(1) + ")";
387  }
388 
389  void BSpline::eval_mx(const std::vector<MX>& arg, std::vector<MX>& res,
390  const std::vector<bool>& unique) const {
391  res[0] = arg[0]->get_bspline(knots_, offset_, coeffs_, degree_, m_, lookup_mode_);
392  }
393 
394  void BSplineParametric::eval_mx(const std::vector<MX>& arg, std::vector<MX>& res,
395  const std::vector<bool>& unique) const {
396  res[0] = arg[0]->get_bspline(arg[1], knots_, offset_, degree_, m_, lookup_mode_);
397  }
398 
400 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
401  // Safe access to jac_cache_
402  std::lock_guard<std::mutex> lock(jac_cache_mtx_);
403 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
404  if (jac_cache_.is_empty()) {
405  jac_cache_ = jac(dep(0), DM(coeffs_));
406  }
407  return jac_cache_;
408  }
409 
411 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
412  std::lock_guard<std::mutex> lock(jac_cache_mtx_);
413 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
414  if (jac_cache_.is_empty()) {
415  jac_cache_ = jac(dep(0), dep(1));
416  }
417  return jac_cache_;
418  }
419 
420  void BSplineCommon::ad_forward(const std::vector<std::vector<MX> >& fseed,
421  std::vector<std::vector<MX> >& fsens) const {
422  MX J = jac_cached();
423 
424  for (casadi_int d=0; d<fsens.size(); ++d) {
425  fsens[d][0] = mtimes(J, fseed[d][0]);
426  }
427  }
428 
429  void BSplineCommon::ad_reverse(const std::vector<std::vector<MX> >& aseed,
430  std::vector<std::vector<MX> >& asens) const {
431  MX JT = jac_cached().T();
432  for (casadi_int d=0; d<aseed.size(); ++d) {
433  asens[d][0] += mtimes(JT, aseed[d][0]);
434  }
435  }
436 
437  int BSpline::eval(const double** arg, double** res, casadi_int* iw, double* w) const {
438  if (!res[0]) return 0;
439 
440  casadi_clear(res[0], m_);
443  iw, w);
444  return 0;
445  }
446 
447  int BSplineParametric::eval(const double** arg, double** res, casadi_int* iw, double* w) const {
448  if (!res[0]) return 0;
449 
450  casadi_clear(res[0], m_);
452  get_ptr(degree_), get_ptr(strides_), arg[1], m_, arg[0], get_ptr(lookup_mode_),
453  iw, w);
454  return 0;
455  }
456 
458  const std::vector<casadi_int>& arg,
459  const std::vector<casadi_int>& res,
460  const std::vector<bool>& arg_is_ref,
461  std::vector<bool>& res_is_ref) const {
462  casadi_int n_dims = offset_.size()-1;
463 
466  g << g.clear(g.work(res[0], m_, false), m_) << "\n";
467 
468  // Input and output buffers
469  g << "CASADI_PREFIX(nd_boor_eval)(" << g.work(res[0], m_, false) << "," << n_dims << ","
470  << g.constant(knots_) << "," << g.constant(offset_) << "," << g.constant(degree_)
471  << "," << g.constant(strides_) << "," << generate(g, arg, arg_is_ref) << "," << m_ << ","
472  << g.work(arg[0], n_dims, arg_is_ref[0]) << "," << g.constant(lookup_mode_) << ", iw, w);\n";
473  }
474 
476  const std::vector<casadi_int>& arg,
477  const std::vector<bool>& arg_is_ref) const {
478  return g.constant(coeffs_);
479  }
480 
482  const std::vector<casadi_int>& arg,
483  const std::vector<bool>& arg_is_ref) const {
484  return g.work(arg[1], dep(1).nnz(), arg_is_ref[1]);
485  }
486 
487  DM BSpline::dual(const std::vector<double>& x,
488  const std::vector< std::vector<double> >& knots,
489  const std::vector<casadi_int>& degree,
490  const Dict& opts) {
491 
492  std::vector<casadi_int> offset;
493  std::vector<double> stacked;
494  Interpolant::stack_grid(knots, offset, stacked);
495 
496  std::vector<std::string> lookup_mode;
497  auto it = opts.find("lookup_mode");
498  if (it!=opts.end()) lookup_mode = it->second;
499  std::vector<casadi_int> lookup_mode_int =
500  Interpolant::interpret_lookup_mode(lookup_mode, stacked, offset, degree, degree);
501 
502  casadi_int n_dims = degree.size();
503  casadi_int N = x.size()/n_dims;
504  casadi_assert_dev(N*n_dims==x.size());
505 
506  casadi_int coeffs_size;
507  std::vector<casadi_int> coeffs_dims, strides;
508  prepare(1, offset, degree, coeffs_size, coeffs_dims, strides);
509 
510  // Size of coefficients
511  std::vector<double> contribution(coeffs_size);
512  std::vector<casadi_int> nz(coeffs_size);
513 
514  std::vector<double> data;
515  std::vector<casadi_int> row, col;
516 
517  std::vector<double> w(n_w(degree));
518  std::vector<casadi_int> iw(n_iw(degree));
519 
520  for (casadi_int i=0;i<N;++i) {
521  std::fill(contribution.begin(), contribution.end(), 0.0);
522  casadi_int nnz = casadi_nd_boor_dual_eval(get_ptr(contribution), get_ptr(nz),
523  degree.size(), get_ptr(stacked), get_ptr(offset),
524  get_ptr(degree), get_ptr(strides), get_ptr(x)+i*n_dims, get_ptr(lookup_mode_int),
525  get_ptr(iw), get_ptr(w));
526  data.insert(data.end(), contribution.begin(), contribution.begin()+nnz);
527  col.insert(col.end(), nz.begin(), nz.begin()+nnz);
528  row.insert(row.end(), nnz, i);
529  }
530 
531  return DM(Sparsity::triplet(coeffs_size, N, col, row), data).T();
532  }
533 
534 } // namespace casadi
BSpline Node.
Definition: bspline.hpp:42
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
Definition: bspline.cpp:118
std::vector< casadi_int > lookup_mode_
Definition: bspline.hpp:75
void ad_forward(const std::vector< std::vector< MX > > &fseed, std::vector< std::vector< MX > > &fsens) const override
Calculate forward mode directional derivatives.
Definition: bspline.cpp:420
std::vector< double > knots_
Definition: bspline.hpp:71
MX jac_cache_
Jacobian.
Definition: bspline.hpp:88
static casadi_int get_coeff_size(casadi_int m, const std::vector< casadi_int > &offset, const std::vector< casadi_int > &degree)
Definition: bspline.cpp:83
static size_t n_w(const std::vector< casadi_int > &degree)
Get required length of w field.
Definition: bspline.cpp:72
BSplineCommon(const std::vector< double > &knots, const std::vector< casadi_int > &offset, const std::vector< casadi_int > &degree, casadi_int m, const std::vector< casadi_int > &lookup_mode)
Constructor.
Definition: bspline.cpp:44
std::vector< casadi_int > degree_
Definition: bspline.hpp:73
size_t sz_w() const override
Get required length of w field.
Definition: bspline.cpp:58
std::vector< casadi_int > offset_
Definition: bspline.hpp:72
casadi_int coeffs_size_
Definition: bspline.hpp:80
std::vector< casadi_int > coeffs_dims_
Definition: bspline.hpp:79
void generate(CodeGenerator &g, const std::vector< casadi_int > &arg, const std::vector< casadi_int > &res, const std::vector< bool > &arg_is_ref, std::vector< bool > &res_is_ref) const override
Generate code for the operation.
Definition: bspline.cpp:457
static void prepare(casadi_int m, const std::vector< casadi_int > &offset, const std::vector< casadi_int > &degree, casadi_int &coeffs_size, std::vector< casadi_int > &coeffs_dims, std::vector< casadi_int > &strides)
Definition: bspline.cpp:90
void ad_reverse(const std::vector< std::vector< MX > > &aseed, std::vector< std::vector< MX > > &asens) const override
Calculate reverse mode directional derivatives.
Definition: bspline.cpp:429
std::vector< casadi_int > strides_
Definition: bspline.hpp:78
size_t sz_iw() const override
Get required length of iw field.
Definition: bspline.cpp:54
static size_t n_iw(const std::vector< casadi_int > &degree)
Get required length of iw field.
Definition: bspline.cpp:62
virtual MX jac_cached() const =0
casadi_int op() const override
Get the operation.
Definition: bspline.hpp:120
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: bspline.cpp:30
MX jac(const MX &x, const T &coeffs) const
void serialize_type(SerializingStream &s) const override
Serialize type information.
Definition: bspline.cpp:113
std::string disp(const std::vector< std::string > &arg) const override
Print expression.
Definition: bspline.cpp:385
BSplineParametric(const MX &x, const MX &coeffs, const std::vector< double > &knots, const std::vector< casadi_int > &offset, const std::vector< casadi_int > &degree, casadi_int m, const std::vector< casadi_int > &lookup_mode)
Constructor.
Definition: bspline.cpp:164
std::string generate(CodeGenerator &g, const std::vector< casadi_int > &arg, const std::vector< bool > &arg_is_ref) const override
Generate code for the operation.
Definition: bspline.cpp:481
MX jac_cached() const override
Definition: bspline.cpp:410
int eval(const double **arg, double **res, casadi_int *iw, double *w) const override
Evaluate the function numerically.
Definition: bspline.cpp:447
void eval_mx(const std::vector< MX > &arg, std::vector< MX > &res, const std::vector< bool > &unique={}) const override
Evaluate symbolically (MX)
Definition: bspline.cpp:394
static MX create(const MX &x, const MX &coeffs, const std::vector< std::vector< double > > &knots, const std::vector< casadi_int > &degree, casadi_int m, const Dict &opts)
Definition: bspline.cpp:310
std::string generate(CodeGenerator &g, const std::vector< casadi_int > &arg, const std::vector< bool > &arg_is_ref) const override
Generate code for the operation.
Definition: bspline.cpp:475
static MX create(const MX &x, const std::vector< std::vector< double > > &knots, const std::vector< double > &coeffs, const std::vector< casadi_int > &degree, casadi_int m, const Dict &opts)
Definition: bspline.cpp:273
std::vector< double > coeffs_
Definition: bspline.hpp:222
MX jac_cached() const override
Definition: bspline.cpp:399
int eval(const double **arg, double **res, casadi_int *iw, double *w) const override
Evaluate the function numerically.
Definition: bspline.cpp:437
static DM dual(const std::vector< double > &x, const std::vector< std::vector< double > > &knots, const std::vector< casadi_int > &degree, const Dict &opts)
Definition: bspline.cpp:487
BSpline(const MX &x, const std::vector< double > &knots, const std::vector< casadi_int > &offset, const std::vector< double > &coeffs, const std::vector< casadi_int > &degree, casadi_int m, const std::vector< casadi_int > &lookup_mode)
Constructor.
Definition: bspline.cpp:152
std::string disp(const std::vector< std::string > &arg) const override
Print expression.
Definition: bspline.cpp:381
void eval_mx(const std::vector< MX > &arg, std::vector< MX > &res, const std::vector< bool > &unique={}) const override
Evaluate symbolically (MX)
Definition: bspline.cpp:389
void serialize_type(SerializingStream &s) const override
Serialize type information.
Definition: bspline.cpp:108
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
Definition: bspline.cpp:143
Helper class for C code generation.
std::string work(casadi_int n, casadi_int sz, bool is_ref) const
std::string constant(const std::vector< casadi_int > &v)
Represent an array constant; adding it when new.
std::string clear(const std::string &res, std::size_t n)
Create a fill operation.
void add_auxiliary(Auxiliary f, const std::vector< std::string > &inst={"casadi_real"})
Add a built-in auxiliary function.
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
casadi_int numel() const
Get the number of elements.
bool is_empty(bool both=false) const
Check if the sparsity is empty, i.e. if one of the dimensions is zero.
bool is_vector() const
Check if the matrix is a row or column vector.
casadi_int size2() const
Get the second dimension (i.e. number of columns)
casadi_int size1() const
Get the first dimension (i.e. number of rows)
std::string dim(bool with_nz=false) const
Get string representation of dimensions.
static MatType zeros(casadi_int nrow=1, casadi_int ncol=1)
Create a dense matrix or a matrix with specified sparsity with all entries zero.
static void stack_grid(const std::vector< std::vector< double > > &grid, std::vector< casadi_int > &offset, std::vector< double > &stacked)
Definition: interpolant.cpp:46
static std::vector< casadi_int > interpret_lookup_mode(const std::vector< std::string > &modes, const std::vector< double > &grid, const std::vector< casadi_int > &offset, const std::vector< casadi_int > &margin_left=std::vector< casadi_int >(), const std::vector< casadi_int > &margin_right=std::vector< casadi_int >())
Convert from (optional) lookup modes labels to enum.
static std::string lookup_mode_from_enum(casadi_int lookup_mode)
Definition: casadi_low.cpp:48
Node class for MX objects.
Definition: mx_node.hpp:51
virtual void serialize_type(SerializingStream &s) const
Serialize type information.
Definition: mx_node.cpp:535
virtual casadi_int offset() const
Definition: mx_node.cpp:220
MX get_bspline(const std::vector< double > &knots, const std::vector< casadi_int > &offset, const std::vector< double > &coeffs, const std::vector< casadi_int > &degree, casadi_int m, const std::vector< casadi_int > &lookup_mode) const
BSpline.
Definition: mx_node.cpp:1060
casadi_int nnz(casadi_int i=0) const
Definition: mx_node.hpp:427
const MX & dep(casadi_int ind=0) const
dependencies - functions that have to be evaluated before this one
Definition: mx_node.hpp:392
virtual void serialize_body(SerializingStream &s) const
Serialize an object without type information.
Definition: mx_node.cpp:530
void set_sparsity(const Sparsity &sparsity)
Set the sparsity.
Definition: mx_node.cpp:224
void set_dep(const MX &dep)
Set unary dependency.
Definition: mx_node.cpp:228
MX - Matrix expression.
Definition: mx.hpp:92
MX T() const
Transpose the matrix.
Definition: mx.cpp:1095
void get_nz(MX &m, bool ind1, const Slice &kk) const
Definition: mx.cpp:405
Matrix< Scalar > T() const
Transpose the matrix.
Helper class for Serialization.
void pack(const Sparsity &e)
Serializes an object to the output stream.
Class representing a Slice.
Definition: slice.hpp:48
static Sparsity dense(casadi_int nrow, casadi_int ncol=1)
Create a dense rectangular sparsity pattern *.
Definition: sparsity.cpp:1028
static Sparsity triplet(casadi_int nrow, casadi_int ncol, const std::vector< casadi_int > &row, const std::vector< casadi_int > &col, std::vector< casadi_int > &mapping, bool invert_mapping)
Create a sparsity pattern given the nonzeros in sparse triplet form *.
Definition: sparsity.cpp:1143
The casadi namespace.
Definition: archiver.cpp:28
std::vector< casadi_int > range(casadi_int start, casadi_int stop, casadi_int step, casadi_int len)
Range function.
double if_else_zero(double x, double y)
Conditional assignment.
Definition: calculus.hpp:295
static casadi_int knot_size(const std::vector< double > &k)
Definition: bspline.cpp:212
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
T * get_ptr(std::vector< T > &v)
Get a pointer to the data contained in the vector.
Matrix< double > DM
Definition: dm_fwd.hpp:33
MX do_inline(const MX &x, const std::vector< K > &knots, const MX &coeffs, casadi_int m, const std::vector< casadi_int > &degree, const std::vector< casadi_int > &lookup_mode)
Definition: bspline.cpp:216
void get_boor(const MX &x, const MX &knots, casadi_int degree, casadi_int lookup_mode, MX &start, MX &boor)
Definition: bspline.cpp:177
void casadi_clear(T1 *x, casadi_int n)
CLEAR: x <- 0.
void casadi_nd_boor_eval(T1 *ret, casadi_int n_dims, const T1 *knots, const casadi_int *offset, const casadi_int *degree, const casadi_int *strides, const T1 *c, casadi_int m, const T1 *x, const casadi_int *lookup_mode, casadi_int *iw, T1 *w)