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::check_coeffs(casadi_int n, casadi_int m,
91  const std::vector<casadi_int>& offset, const std::vector<casadi_int>& degree) {
92  casadi_int expected = get_coeff_size(m, offset, degree);
93  casadi_assert(n==expected,
94  "Expected " + str(expected) + " coefficients, but got " + str(n) + ".");
95  }
96 
97  void BSplineCommon::prepare(casadi_int m, const std::vector<casadi_int>& offset,
98  const std::vector<casadi_int>& degree, casadi_int &coeffs_size,
99  std::vector<casadi_int>& coeffs_dims, std::vector<casadi_int>& strides) {
100 
101  casadi_int n_dims = degree.size();
102  coeffs_size = get_coeff_size(m, offset, degree);
103  coeffs_dims.resize(n_dims+1);
104  coeffs_dims[0] = m;
105  for (casadi_int i=0;i<n_dims;++i) coeffs_dims[i+1] = offset[i+1]-offset[i]-degree[i]-1;
106 
107  // Prepare strides
108  strides.resize(n_dims);
109  strides[0] = m;
110  for (casadi_int i=0;i<n_dims-1;++i) {
111  strides[i+1] = strides[i]*coeffs_dims[i+1];
112  }
113  }
114 
117  s.pack("BSpline::type", 'n');
118  }
119 
122  s.pack("BSpline::type", 'p');
123  }
124 
127  s.pack("BSplineCommon::knots", knots_);
128  s.pack("BSplineCommon::offset", offset_);
129  s.pack("BSplineCommon::degree", degree_);
130  s.pack("BSplineCommon::m", m_);
131  s.pack("BSplineCommon::lookup_mode", lookup_mode_);
132  s.pack("BSplineCommon::strides", strides_);
133  s.pack("BSplineCommon::coeffs_dims", coeffs_dims_);
134  s.pack("BSplineCommon::coeffs_size", coeffs_size_);
135  s.pack("BSplineCommon::jac_cache_", jac_cache_);
136  }
137 
139  s.unpack("BSplineCommon::knots", knots_);
140  s.unpack("BSplineCommon::offset", offset_);
141  s.unpack("BSplineCommon::degree", degree_);
142  s.unpack("BSplineCommon::m", m_);
143  s.unpack("BSplineCommon::lookup_mode", lookup_mode_);
144  s.unpack("BSplineCommon::strides", strides_);
145  s.unpack("BSplineCommon::coeffs_dims", coeffs_dims_);
146  s.unpack("BSplineCommon::coeffs_size", coeffs_size_);
147  s.unpack("BSplineCommon::jac_cache_", jac_cache_);
148  }
149 
152  s.pack("BSpline::coeffs", coeffs_);
153  }
154 
156  s.unpack("BSpline::coeffs", coeffs_);
157  }
158 
159  BSpline::BSpline(const MX& x, const std::vector<double>& knots,
160  const std::vector<casadi_int>& offset,
161  const std::vector<double>& coeffs,
162  const std::vector<casadi_int>& degree,
163  casadi_int m,
164  const std::vector<casadi_int>& lookup_mode) :
165  BSplineCommon(knots, offset, degree, m, lookup_mode), coeffs_(coeffs) {
166  casadi_assert_dev(x.numel()==degree.size());
167  set_dep(x);
169  }
170 
172  const MX& coeffs,
173  const std::vector<double>& knots,
174  const std::vector<casadi_int>& offset,
175  const std::vector<casadi_int>& degree,
176  casadi_int m,
177  const std::vector<casadi_int>& lookup_mode) :
178  BSplineCommon(knots, offset, degree, m, lookup_mode) {
179  casadi_assert_dev(x.size1()==degree.size());
180  set_dep(x, coeffs);
182  }
183 
184  void get_boor(const MX& x, const MX& knots, casadi_int degree, casadi_int lookup_mode,
185  MX& start, MX& boor) {
186  MX knots_clipped = knots(range(degree, knots.size1()-degree));
187 
188  Dict low_opts;
189  low_opts["lookup_mode"] = Low::lookup_mode_from_enum(lookup_mode);
190  MX L = low(knots_clipped, x, low_opts);
191  start = fmin(L, knots.size1()-2*degree-2);
192 
193  DM boor_init = DM::zeros(x.size2(), 2*degree+1);
194  boor_init(Slice(), degree) = 1;
195  std::vector<MX> boor_full = horzsplit(MX(boor_init));
196  casadi_int n_knots = 2*degree+2;
197 
198  MX kn;
199  MX(knots).get_nz(kn, false, start, MX(range(n_knots)));
200 
201  std::vector<MX> knv = horzsplit(kn);
202 
203  MX xt = x.T();
204 
205  for (casadi_int d=1;d<degree+1;++d) {
206  for (casadi_int i=0;i<n_knots-d-1;++i) {
207  MX bottom = knv[i+d]-knv[i];
208  MX b = if_else_zero(bottom, (xt-knv[i])*boor_full[i]/(bottom+1e-100));
209  bottom = knv[i+d+1]-knv[i + 1];
210  b += if_else_zero(bottom, (knv[i+d+1]-xt)*boor_full[i+1]/(bottom+1e-100));
211  boor_full[i] = b;
212  }
213  }
214 
215  boor = horzcat(std::vector<MX>(boor_full.begin(), boor_full.begin()+degree+1));
216  }
217 
218  // Helper: get number of knots from either std::vector<double> or MX
219  static casadi_int knot_size(const std::vector<double>& k) { return k.size(); }
220  static casadi_int knot_size(const MX& k) { return k.size1(); }
221 
222  template<typename K>
223  MX do_inline(const MX& x,
224  const std::vector<K>& knots,
225  const MX& coeffs,
226  casadi_int m,
227  const std::vector<casadi_int>& degree,
228  const std::vector<casadi_int>& lookup_mode) {
229 
230  casadi_int batch_x = x.size2();
231 
232  // Number of grid points
233  casadi_int N = knots.size();
234  std::vector<MX> xs = vertsplit(x);
235 
236  // Compute De Boor vector in each direction
237  std::vector<MX> starts(N);
238  std::vector< std::vector<MX> > boors(N);
239  for (casadi_int i=0;i<N;++i) {
240  MX boor;
241  get_boor(xs[i], knots[i], degree[i], lookup_mode[i], starts[i], boor);
242  boors[i] = horzsplit(boor.T());
243  }
244 
245  // Compute strides
246  std::vector<casadi_int> strides = {m};
247  for (casadi_int i=0;i<N-1;++i) {
248  strides.push_back(strides.back()*(knot_size(knots[i])-degree[i]-1));
249  }
250 
251  // Start index of subtensor: row vector
252  MX start = mtimes(DM(strides).T(), vertcat(starts));
253 
254  // Elements of subtensor
255  DM core = DM(range(m));
256  for (casadi_int i=0;i<N;++i) {
257  casadi_int n = degree[i]+1;
258  core = vec(repmat(core, 1, n)+repmat(strides[i]*DM(range(n)).T(), core.size1(), 1));
259  }
260 
261  std::vector<MX> res;
262 
263  for (casadi_int k=0;k<batch_x;++k) {
264 
265  // Flattened subtensor of coefficients
266  MX c = reshape(coeffs(start(k)+core), m, -1);
267 
268  // Compute outer product of De Boor vectors
269  MX boor = 1;
270  for (casadi_int i=0;i<N;++i) {
271  boor = vec(mtimes(boor, boors[i][k].T()));
272  }
273 
274  res.push_back(mtimes(c, boor));
275  }
276 
277  return horzcat(res);
278  }
279 
280  MX BSpline::create(const MX& x, const std::vector< std::vector<double> >& knots,
281  const std::vector<double>& coeffs,
282  const std::vector<casadi_int>& degree,
283  casadi_int m,
284  const Dict& opts) {
285 
286  casadi_assert(x.is_vector(), "x argument must be a vector, got " + x.dim() + " instead.");
287  casadi_assert(x.numel()==knots.size(), "x argument length (" + str(x.numel()) + ") must match "
288  "number knot list length (" + str(knots.size()) + ").");
289  casadi_assert(degree.size()==knots.size(), "Degree list length (" + str(degree.size()) + ") "
290  "must match knot list length (" + str(knots.size()) + ").");
291 
292  bool do_inline_flag = false;
293  std::vector<std::string> lookup_mode;
294 
295  for (auto&& op : opts) {
296  if (op.first=="inline") {
297  do_inline_flag = op.second;
298  } else if (op.first=="lookup_mode") {
299  lookup_mode = op.second;
300  } else {
301  casadi_error("Unknown option '" + op.first + "'.");
302  }
303  }
304 
305  std::vector<casadi_int> offset;
306  std::vector<double> stacked;
307  Interpolant::stack_grid(knots, offset, stacked);
308  check_coeffs(coeffs.size(), m, offset, degree);
309 
310  std::vector<casadi_int> mode =
311  Interpolant::interpret_lookup_mode(lookup_mode, stacked, offset, degree, degree);
312 
313  if (do_inline_flag) {
314  return do_inline(x, knots, coeffs, m, degree, mode);
315  } else {
316  return x->get_bspline(stacked, offset, coeffs, degree, m, mode);
317  }
318  }
319 
321  const MX& coeffs,
322  const std::vector< std::vector<double> >& knots,
323  const std::vector<casadi_int>& degree,
324  casadi_int m,
325  const Dict& opts) {
326 
327  casadi_assert(x.is_vector(), "x argument must be a vector, got " + x.dim() + " instead.");
328  casadi_assert(x.numel()==knots.size(), "x argument length (" + str(x.numel()) + ") must match "
329  "knot list length (" + str(knots.size()) + ").");
330  casadi_assert(degree.size()==knots.size(), "Degree list length (" + str(degree.size()) + ") "
331  "must match knot list length (" + str(knots.size()) + ").");
332  bool do_inline_flag = false;
333  std::vector<std::string> lookup_mode;
334 
335  for (auto&& op : opts) {
336  if (op.first=="inline") {
337  do_inline_flag = op.second;
338  } else if (op.first=="lookup_mode") {
339  lookup_mode = op.second;
340  } else {
341  casadi_error("Unknown option '" + op.first + "'.");
342  }
343  }
344 
345  std::vector<casadi_int> offset;
346  std::vector<double> stacked;
347  Interpolant::stack_grid(knots, offset, stacked);
348  check_coeffs(coeffs.numel(), m, offset, degree);
349  std::vector<casadi_int> mode =
350  Interpolant::interpret_lookup_mode(lookup_mode, stacked, offset, degree, degree);
351 
352  if (do_inline_flag) {
353  return do_inline(x, knots, coeffs, m, degree, mode);
354  } else {
355  return x->get_bspline(coeffs, stacked, offset, degree, m, mode);
356  }
357  }
358 
360  const MX& coeffs,
361  const std::vector<MX>& knots,
362  const std::vector<casadi_int>& degree,
363  casadi_int m,
364  const Dict& opts) {
365 
366  casadi_assert(x.is_vector(), "x argument must be a vector, got " + x.dim() + " instead.");
367  casadi_assert(x.numel()==knots.size(), "x argument length (" + str(x.numel()) + ") must match "
368  "knot list length (" + str(knots.size()) + ").");
369  casadi_assert(degree.size()==knots.size(), "Degree list length (" + str(degree.size()) + ") "
370  "must match knot list length (" + str(knots.size()) + ").");
371 
372  // Parametric knots: always inline (non-inline path requires numeric knots)
373  std::vector<std::string> lookup_mode;
374  for (auto&& op : opts) {
375  if (op.first=="lookup_mode") {
376  lookup_mode = op.second;
377  } else if (op.first!="inline") {
378  casadi_error("Unknown option '" + op.first + "'.");
379  }
380  }
381 
382  // Build offset from MX knot sizes
383  std::vector<casadi_int> offset(knots.size()+1);
384  offset[0] = 0;
385  for (casadi_int i=0; i<knots.size(); ++i) {
386  offset[i+1] = offset[i] + knots[i].size1();
387  }
388  check_coeffs(coeffs.numel(), m, offset, degree);
389 
390  std::vector<casadi_int> mode =
391  Interpolant::interpret_lookup_mode(lookup_mode, std::vector<double>(),
392  offset, degree, degree);
393 
394  return do_inline(x, knots, coeffs, m, degree, mode);
395  }
396 
397  std::string BSpline::disp(const std::vector<std::string>& arg) const {
398  return "BSpline(" + arg.at(0) + ")";
399  }
400 
401  std::string BSplineParametric::disp(const std::vector<std::string>& arg) const {
402  return "BSplineParametric(" + arg.at(0) + ", " + arg.at(1) + ")";
403  }
404 
405  void BSpline::eval_mx(const std::vector<MX>& arg, std::vector<MX>& res,
406  const std::vector<bool>& unique) const {
407  res[0] = arg[0]->get_bspline(knots_, offset_, coeffs_, degree_, m_, lookup_mode_);
408  }
409 
410  void BSplineParametric::eval_mx(const std::vector<MX>& arg, std::vector<MX>& res,
411  const std::vector<bool>& unique) const {
412  res[0] = arg[0]->get_bspline(arg[1], knots_, offset_, degree_, m_, lookup_mode_);
413  }
414 
416 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
417  // Safe access to jac_cache_
418  std::lock_guard<std::mutex> lock(jac_cache_mtx_);
419 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
420  if (jac_cache_.is_empty()) {
421  jac_cache_ = jac(dep(0), DM(coeffs_));
422  }
423  return jac_cache_;
424  }
425 
427 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
428  std::lock_guard<std::mutex> lock(jac_cache_mtx_);
429 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
430  if (jac_cache_.is_empty()) {
431  jac_cache_ = jac(dep(0), dep(1));
432  }
433  return jac_cache_;
434  }
435 
436  void BSplineCommon::ad_forward(const std::vector<std::vector<MX> >& fseed,
437  std::vector<std::vector<MX> >& fsens) const {
438  MX J = jac_cached();
439 
440  for (casadi_int d=0; d<fsens.size(); ++d) {
441  fsens[d][0] = mtimes(J, fseed[d][0]);
442  }
443  }
444 
445  void BSplineCommon::ad_reverse(const std::vector<std::vector<MX> >& aseed,
446  std::vector<std::vector<MX> >& asens) const {
447  MX JT = jac_cached().T();
448  for (casadi_int d=0; d<aseed.size(); ++d) {
449  asens[d][0] += mtimes(JT, aseed[d][0]);
450  }
451  }
452 
453  int BSpline::eval(const double** arg, double** res, casadi_int* iw, double* w) const {
454  if (!res[0]) return 0;
455 
456  casadi_clear(res[0], m_);
459  iw, w);
460  return 0;
461  }
462 
463  int BSplineParametric::eval(const double** arg, double** res, casadi_int* iw, double* w) const {
464  if (!res[0]) return 0;
465 
466  casadi_clear(res[0], m_);
468  get_ptr(degree_), get_ptr(strides_), arg[1], m_, arg[0], get_ptr(lookup_mode_),
469  iw, w);
470  return 0;
471  }
472 
474  const std::vector<casadi_int>& arg,
475  const std::vector<casadi_int>& res,
476  const std::vector<bool>& arg_is_ref,
477  std::vector<bool>& res_is_ref) const {
478  casadi_int n_dims = offset_.size()-1;
479 
482  g << g.clear(g.work(res[0], m_, false), m_) << "\n";
483 
484  // Input and output buffers
485  g << "CASADI_PREFIX(nd_boor_eval)(" << g.work(res[0], m_, false) << "," << n_dims << ","
486  << g.constant(knots_) << "," << g.constant(offset_) << "," << g.constant(degree_)
487  << "," << g.constant(strides_) << "," << generate(g, arg, arg_is_ref) << "," << m_ << ","
488  << g.work(arg[0], n_dims, arg_is_ref[0]) << "," << g.constant(lookup_mode_) << ", iw, w);\n";
489  }
490 
492  const std::vector<casadi_int>& arg,
493  const std::vector<bool>& arg_is_ref) const {
494  return g.constant(coeffs_);
495  }
496 
498  const std::vector<casadi_int>& arg,
499  const std::vector<bool>& arg_is_ref) const {
500  return g.work(arg[1], dep(1).nnz(), arg_is_ref[1]);
501  }
502 
503  DM BSpline::dual(const std::vector<double>& x,
504  const std::vector< std::vector<double> >& knots,
505  const std::vector<casadi_int>& degree,
506  const Dict& opts) {
507 
508  std::vector<casadi_int> offset;
509  std::vector<double> stacked;
510  Interpolant::stack_grid(knots, offset, stacked);
511 
512  std::vector<std::string> lookup_mode;
513  auto it = opts.find("lookup_mode");
514  if (it!=opts.end()) lookup_mode = it->second;
515  std::vector<casadi_int> lookup_mode_int =
516  Interpolant::interpret_lookup_mode(lookup_mode, stacked, offset, degree, degree);
517 
518  casadi_int n_dims = degree.size();
519  casadi_int N = x.size()/n_dims;
520  casadi_assert(N*n_dims==x.size(), "Number of point coordinates (" + str(x.size()) + ") "
521  "must be a multiple of the number of dimensions (" + str(n_dims) + ").");
522 
523  casadi_int coeffs_size;
524  std::vector<casadi_int> coeffs_dims, strides;
525  prepare(1, offset, degree, coeffs_size, coeffs_dims, strides);
526 
527  // Size of coefficients
528  std::vector<double> contribution(coeffs_size);
529  std::vector<casadi_int> nz(coeffs_size);
530 
531  std::vector<double> data;
532  std::vector<casadi_int> row, col;
533 
534  std::vector<double> w(n_w(degree));
535  std::vector<casadi_int> iw(n_iw(degree));
536 
537  for (casadi_int i=0;i<N;++i) {
538  std::fill(contribution.begin(), contribution.end(), 0.0);
539  casadi_int nnz = casadi_nd_boor_dual_eval(get_ptr(contribution), get_ptr(nz),
540  degree.size(), get_ptr(stacked), get_ptr(offset),
541  get_ptr(degree), get_ptr(strides), get_ptr(x)+i*n_dims, get_ptr(lookup_mode_int),
542  get_ptr(iw), get_ptr(w));
543  data.insert(data.end(), contribution.begin(), contribution.begin()+nnz);
544  col.insert(col.end(), nz.begin(), nz.begin()+nnz);
545  row.insert(row.end(), nnz, i);
546  }
547 
548  return DM(Sparsity::triplet(coeffs_size, N, col, row), data).T();
549  }
550 
551 } // namespace casadi
BSpline Node.
Definition: bspline.hpp:42
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
Definition: bspline.cpp:125
std::vector< casadi_int > lookup_mode_
Definition: bspline.hpp:78
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:436
std::vector< double > knots_
Definition: bspline.hpp:74
MX jac_cache_
Jacobian.
Definition: bspline.hpp:91
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:76
size_t sz_w() const override
Get required length of w field.
Definition: bspline.cpp:58
std::vector< casadi_int > offset_
Definition: bspline.hpp:75
casadi_int coeffs_size_
Definition: bspline.hpp:83
std::vector< casadi_int > coeffs_dims_
Definition: bspline.hpp:82
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:473
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:97
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:445
std::vector< casadi_int > strides_
Definition: bspline.hpp:81
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
static void check_coeffs(casadi_int n, casadi_int m, const std::vector< casadi_int > &offset, const std::vector< casadi_int > &degree)
Definition: bspline.cpp:90
virtual MX jac_cached() const =0
casadi_int op() const override
Get the operation.
Definition: bspline.hpp:123
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:120
std::string disp(const std::vector< std::string > &arg) const override
Print expression.
Definition: bspline.cpp:401
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:171
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:497
MX jac_cached() const override
Definition: bspline.cpp:426
int eval(const double **arg, double **res, casadi_int *iw, double *w) const override
Evaluate the function numerically.
Definition: bspline.cpp:463
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:410
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:320
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:491
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:280
std::vector< double > coeffs_
Definition: bspline.hpp:225
MX jac_cached() const override
Definition: bspline.cpp:415
int eval(const double **arg, double **res, casadi_int *iw, double *w) const override
Evaluate the function numerically.
Definition: bspline.cpp:453
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:503
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:159
std::string disp(const std::vector< std::string > &arg) const override
Print expression.
Definition: bspline.cpp:397
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:405
void serialize_type(SerializingStream &s) const override
Serialize type information.
Definition: bspline.cpp:115
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
Definition: bspline.cpp:150
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, size1()*size2()
bool is_empty(bool both=false) const
Check if the matrix 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:536
virtual casadi_int offset() const
Definition: mx_node.cpp:221
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:1061
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:531
void set_sparsity(const Sparsity &sparsity)
Set the sparsity.
Definition: mx_node.cpp:225
void set_dep(const MX &dep)
Set unary dependency.
Definition: mx_node.cpp:229
MX - Matrix expression.
Definition: mx.hpp:145
MX T() const
Transpose the matrix.
Definition: mx.cpp:1098
void get_nz(MX &m, bool ind1, const Slice &kk) const
Get a set of nonzeros (what x.nz[k] does)
Definition: mx.cpp:406
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:1041
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 from the (row, col) index of every nonzero.
Definition: sparsity.cpp:1157
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:219
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:223
void get_boor(const MX &x, const MX &knots, casadi_int degree, casadi_int lookup_mode, MX &start, MX &boor)
Definition: bspline.cpp:184
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)