mx_node.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 "mx_node.hpp"
27 #include "casadi_misc.hpp"
28 #include "transpose.hpp"
29 #include "reshape.hpp"
30 #include "sparsity_cast.hpp"
31 #include "multiplication.hpp"
32 #include "bilin.hpp"
33 #include "rank1.hpp"
34 #include "subref.hpp"
35 #include "subassign.hpp"
36 #include "getnonzeros.hpp"
37 #include "getnonzeros_param.hpp"
38 #include "setnonzeros.hpp"
39 #include "setnonzeros_param.hpp"
40 #include "project.hpp"
41 #include "solve.hpp"
42 #include "unary_mx.hpp"
43 #include "binary_mx.hpp"
44 #include "determinant.hpp"
45 #include "inverse.hpp"
46 #include "dot.hpp"
47 #include "norm.hpp"
48 #include "mmin.hpp"
49 #include "concat.hpp"
50 #include "split.hpp"
51 #include "assertion.hpp"
52 #include "monitor.hpp"
53 #include "repmat.hpp"
54 #include "casadi_find.hpp"
55 #include "casadi_low.hpp"
56 #include "einstein.hpp"
57 #include "io_instruction.hpp"
58 #include "symbolic_mx.hpp"
59 #include "constant_mx.hpp"
60 #include "map.hpp"
61 #include "bspline.hpp"
62 #include "convexify.hpp"
63 #include "logsumexp.hpp"
64 
65 // Template implementations
66 #include "setnonzeros_impl.hpp"
67 #include "setnonzeros_param_impl.hpp"
68 #include "solve_impl.hpp"
69 #include "binary_mx_impl.hpp"
70 
71 #include "serializing_stream.hpp"
72 
73 #include <typeinfo>
74 
75 namespace casadi {
76 
78  temp = 0;
79  }
80 
81 
83 
84  // Start destruction method if any of the dependencies has dependencies
85  for (std::vector<MX>::iterator cc=dep_.begin(); cc!=dep_.end(); ++cc) {
86  // Skip if constant
87  if (cc->is_constant()) continue;
88 
89  // Check if there are other "owners" of the node
90  if (cc->getCount()!= 1) {
91 
92  // Replace with a 0-by-0 matrix
93  *cc = MX();
94 
95  } else {
96  // Stack of expressions to be deleted
97  std::stack<MX> deletion_stack;
98 
99  // Move the child to the deletion stack
100  deletion_stack.push(*cc);
101  *cc = MX();
102 
103  // Process stack
104  while (!deletion_stack.empty()) {
105 
106  // Top element
107  MX t = deletion_stack.top();
108 
109  // Check if the top element has dependencies with dependencies
110  bool found_dep = false;
111 
112  // Start destruction method if any of the dependencies has dependencies
113  while (!t->dep_.empty()) {
114  const MX& ii = t->dep_.back();
115 
116  // Skip if constant
117  if (ii.is_constant()) {
118  t->dep_.pop_back();
119  continue;
120  }
121  // Check if this is the only reference to the element
122  if (ii.getCount()==1) {
123  // Remove and add to stack
124  deletion_stack.push(ii);
125  t->dep_.pop_back();
126  found_dep = true;
127  break;
128  } else {
129  t->dep_.pop_back();
130  }
131  }
132 
133  // Pop from stack if no dependencies found
134  if (!found_dep) {
135  deletion_stack.pop();
136  }
137  }
138  }
139  }
140  }
141 
142  casadi_int MXNode::n_primitives() const {
143  return 1;
144  }
145 
146  bool MXNode::has_duplicates() const {
147  casadi_error("'has_duplicates' not defined for class " + class_name());
148  }
149 
150  void MXNode::reset_input() const {
151  casadi_error("'reset_input' not defined for class " + class_name());
152  }
153 
154  void MXNode::primitives(std::vector<MX>::iterator& it) const {
155  *it++ = shared_from_this<MX>();
156  }
157 
158  void MXNode::split_primitives(const MX& x, std::vector<MX>::iterator& it) const {
159  *it++ = x;
160  }
161 
162  void MXNode::split_primitives(const SX& x, std::vector<SX>::iterator& it) const {
163  *it++ = x;
164  }
165 
166  void MXNode::split_primitives(const DM& x, std::vector<DM>::iterator& it) const {
167  *it++ = x;
168  }
169 
170  template<typename T>
171  T MXNode::join_primitives_gen(typename std::vector<T>::const_iterator& it) const {
172  T ret = *it++;
173  if (ret.size()==size()) {
174  return ret;
175  } else {
176  casadi_assert_dev(ret.is_empty(true));
177  return T(size());
178  }
179  }
180 
181  MX MXNode::join_primitives(std::vector<MX>::const_iterator& it) const {
182  return join_primitives_gen<MX>(it);
183  }
184 
185  DM MXNode::join_primitives(std::vector<DM>::const_iterator& it) const {
186  return join_primitives_gen<DM>(it);
187  }
188 
189  SX MXNode::join_primitives(std::vector<SX>::const_iterator& it) const {
190  return join_primitives_gen<SX>(it);
191  }
192 
193  const std::string& MXNode::name() const {
194  casadi_error("'name' not defined for class " + class_name());
195  }
196 
197  std::string MXNode::class_name() const {
198  // Lazy solution
199  return typeid(*this).name();
200  }
201 
202  bool MXNode::__nonzero__() const {
203  casadi_error("Can only determine truth value of a numeric MX.");
204  }
205 
206  casadi_int MXNode::n_dep() const {
207  return dep_.size();
208  }
209 
210  casadi_int MXNode::ind() const {
211  casadi_error("'ind' not defined for class " + class_name());
212  }
213 
214  casadi_int MXNode::segment() const {
215  casadi_error("'segment' not defined for class " + class_name());
216  }
217 
218  casadi_int MXNode::offset() const {
219  casadi_error("'offset' not defined for class " + class_name());
220  }
221 
222  void MXNode::set_sparsity(const Sparsity& sparsity) {
224  }
225 
226  void MXNode::set_dep(const MX& dep) {
227  dep_.resize(1);
228  dep_[0] = dep;
229  check_dep();
230  }
231 
232  void MXNode::set_dep(const MX& dep1, const MX& dep2) {
233  dep_.resize(2);
234  dep_[0] = dep1;
235  dep_[1] = dep2;
236  check_dep();
237  }
238 
239  void MXNode::set_dep(const MX& dep1, const MX& dep2, const MX& dep3) {
240  dep_.resize(3);
241  dep_[0] = dep1;
242  dep_[1] = dep2;
243  dep_[2] = dep3;
244  check_dep();
245  }
246 
247  void MXNode::set_dep(const std::vector<MX>& dep) {
248  dep_ = dep;
249  check_dep();
250  }
251 
252  void MXNode::check_dep() const {
253  for (const MX& e : dep_) {
254  if (e->has_output()) {
255  casadi_assert(is_output(),
256  "You cannot build an expression out of a MultipleOutput node. "
257  "You must select a concrete output by making a get_output() call.");
258  }
259  }
260  }
261 
262  const Sparsity& MXNode::sparsity(casadi_int oind) const {
263  casadi_assert(oind==0, "Index out of bounds");
264  return sparsity_;
265  }
266 
267  void MXNode::disp(std::ostream& stream, bool more) const {
268  // Find out which noded can be inlined
269  std::map<const MXNode*, casadi_int> nodeind;
270  can_inline(nodeind);
271 
272  // Print expression
273  std::vector<std::string> intermed;
274  std::string s = print_compact(nodeind, intermed);
275 
276  // Print intermediate expressions
277  for (casadi_int i=0; i<intermed.size(); ++i)
278  stream << "@" << (i+1) << "=" << intermed[i] << ", ";
279 
280  // Print this
281  stream << s;
282  }
283 
284  void MXNode::can_inline(std::map<const MXNode*, casadi_int>& nodeind) const {
285  // Add or mark node in map
286  std::map<const MXNode*, casadi_int>::iterator it=nodeind.find(this);
287  if (it==nodeind.end()) {
288  // First time encountered, mark inlined
289  nodeind.insert(it, std::make_pair(this, 0));
290 
291  // Handle dependencies with recursion
292  for (casadi_int i=0; i<n_dep(); ++i) {
293  dep(i)->can_inline(nodeind);
294  }
295  } else if (it->second==0 && op()!=OP_PARAMETER) {
296  // Node encountered before, do not inline (except if symbolic primitive)
297  it->second = -1;
298  }
299  }
300 
301  std::string MXNode::print_compact(std::map<const MXNode*, casadi_int>& nodeind,
302  std::vector<std::string>& intermed) const {
303  // Get reference to node index
304  casadi_int& ind = nodeind[this];
305 
306  // If positive, already in intermediate expressions
307  if (ind>0) return "@" + str(ind);
308 
309  // Get expressions for dependencies
310  std::vector<std::string> arg(n_dep());
311  for (casadi_int i=0; i<arg.size(); ++i) {
312  arg[i] = dep(i)->print_compact(nodeind, intermed);
313  }
314 
315  // Get expression for this
316  std::string s = disp(arg);
317 
318  // Decide what to do with the expression
319  if (ind==0) {
320  // Inline expression
321  return s;
322  } else {
323  // Add to list of intermediate expressions and return reference
324  intermed.push_back(s);
325  ind = intermed.size(); // For subsequent references
326  return "@" + str(ind);
327  }
328  }
329 
331  casadi_error("'which_function' not defined for class " + class_name());
332  }
333 
334  casadi_int MXNode::which_output() const {
335  casadi_error("'which_output' not defined for class " + class_name());
336  }
337 
338  int MXNode::eval(const double** arg, double** res, casadi_int* iw, double* w) const {
339  casadi_error("'eval' not defined for class " + class_name());
340  return 1;
341  }
342 
343  int MXNode::eval_sx(const SXElem** arg, SXElem** res, casadi_int* iw, SXElem* w) const {
344  casadi_error("'eval_sx' not defined for class " + class_name());
345  return 1;
346  }
347 
348  void MXNode::eval_mx(const std::vector<MX>& arg, std::vector<MX>& res) const {
349  casadi_error("'eval_mx' not defined for class " + class_name());
350  }
351 
352  void MXNode::eval_linear(const std::vector<std::array<MX, 3> >& arg,
353  std::vector<std::array<MX, 3> >& res) const {
354  std::vector<MX> arg_sum(arg.size());
355  for (casadi_int i=0; i<arg.size(); ++i) {
356  arg_sum[i] = arg[i][0] + arg[i][1] + arg[i][2];
357  }
358  std::vector<MX> res_nonlin(res.size());
359  eval_mx(arg_sum, res_nonlin);
360  for (casadi_int i=0; i<res.size(); ++i) {
361  res[i][0] = MX::zeros(sparsity());
362  res[i][1] = MX::zeros(sparsity());
363  res[i][2] = res_nonlin[i];
364  }
365  }
366 
367  void MXNode::eval_linear_rearrange(const std::vector<std::array<MX, 3> >& arg,
368  std::vector<std::array<MX, 3> >& res) const {
369  // Treat each category separately
370  for (casadi_int i=0; i<3; ++i) {
371  // Read arguments for categiry i
372  std::vector<MX> eval_arg(n_dep());
373  for (casadi_int j=0; j<n_dep(); ++j) {
374  eval_arg[j] = arg[j][i];
375  }
376  std::vector<MX> eval_res(nout());
377  // Normal symbolic evaluation
378  eval_mx(eval_arg, eval_res);
379  // Assign results
380  for (casadi_int j=0; j<nout(); ++j) {
381  res[j][i] = eval_res[j];
382  }
383  }
384  }
385 
386  void MXNode::ad_forward(const std::vector<std::vector<MX> >& fseed,
387  std::vector<std::vector<MX> >& fsens) const {
388  casadi_error("'ad_forward' not defined for class " + class_name());
389  }
390 
391  void MXNode::ad_reverse(const std::vector<std::vector<MX> >& aseed,
392  std::vector<std::vector<MX> >& asens) const {
393  casadi_error("'ad_reverse' not defined for class " + class_name());
394  }
395 
396  int MXNode::sp_forward(const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const {
397  // By default, everything depends on everything
398  bvec_t all_depend(0);
399 
400  // Get dependencies of all inputs
401  for (casadi_int k=0; k<n_dep(); ++k) {
402  const bvec_t* v = arg[k];
403  for (casadi_int i=0; i<dep(k).nnz(); ++i) {
404  all_depend |= v[i];
405  }
406  }
407 
408  // Propagate to all outputs
409  for (casadi_int k=0; k<nout(); ++k) {
410  bvec_t* v = res[k];
411  for (casadi_int i=0; i<sparsity(k).nnz(); ++i) {
412  v[i] = all_depend;
413  }
414  }
415  return 0;
416  }
417 
418  int MXNode::sp_reverse(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const {
419  // By default, everything depends on everything
420  bvec_t all_depend(0);
421 
422  // Get dependencies of all outputs
423  for (casadi_int k=0; k<nout(); ++k) {
424  bvec_t* v = res[k];
425  for (casadi_int i=0; i<sparsity(k).nnz(); ++i) {
426  all_depend |= v[i];
427  v[i] = 0;
428  }
429  }
430 
431  // Propagate to all inputs
432  for (casadi_int k=0; k<n_dep(); ++k) {
433  bvec_t* v = arg[k];
434  for (casadi_int i=0; i<dep(k).nnz(); ++i) {
435  v[i] |= all_depend;
436  }
437  }
438  return 0;
439  }
440 
441  MX MXNode::get_output(casadi_int oind) const {
442  casadi_assert(oind==0, "Output index out of bounds");
443  return shared_from_this<MX>();
444  }
445 
447  const std::vector<casadi_int>& arg,
448  const std::vector<casadi_int>& res,
449  const std::vector<bool>& arg_is_ref,
450  std::vector<bool>& res_is_ref) const {
451  casadi_warning("Cannot code generate MX nodes of type " + class_name() +
452  "The generation will proceed, but compilation of the code will "
453  "not be possible.");
454  g << "#error " << class_name() << ": " << arg << " => " << res << '\n';
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,
462  casadi_int i) const {
463  res_is_ref[i] = arg_is_ref[i];
464  if (arg[i]==res[i]) return;
465  if (nnz()==1) {
466  g << g.workel(res[i]) << " = " << g.workel(arg[i]) << ";\n";
467  } else if (arg_is_ref[i]) {
468  g << g.work(res[i], nnz(), true) << " = " << g.work(arg[i], nnz(), true) << ";\n";
469  } else {
470  g << g.copy(g.work(arg[i], nnz(), false), nnz(), g.work(res[i], nnz(), false)) << "\n";
471  }
472  }
473 
474 
475 
476  double MXNode::to_double() const {
477  casadi_error("'to_double' not defined for class " + class_name());
478  }
479 
480  DM MXNode::get_DM() const {
481  casadi_error("'get_DM' not defined for class " + class_name());
482  }
483 
485  if (sparsity().is_scalar()) {
486  return shared_from_this<MX>();
487  } else if (sparsity().is_vector()) {
488  return get_reshape(sparsity().T());
489  } else if (sparsity().is_dense()) {
490  return MX::create(new DenseTranspose(shared_from_this<MX>()));
491  } else {
492  return MX::create(new Transpose(shared_from_this<MX>()));
493  }
494  }
495 
496  MX MXNode::get_reshape(const Sparsity& sp) const {
497  casadi_assert_dev(sp.is_reshape(sparsity()));
498  if (sp==sparsity()) {
499  return shared_from_this<MX>();
500  } else {
501  return MX::create(new Reshape(shared_from_this<MX>(), sp));
502  }
503  }
504 
506  casadi_assert_dev(sp.nnz()==nnz());
507  if (sp==sparsity()) {
508  return shared_from_this<MX>();
509  } else {
510  return MX::create(new SparsityCast(shared_from_this<MX>(), sp));
511  }
512  }
513 
514  Dict MXNode::info() const {
515  return Dict();
516  }
517 
519  serialize_type(s);
520  serialize_body(s);
521  }
522 
524  s.pack("MXNode::deps", dep_);
525  s.pack("MXNode::sp", sparsity_);
526  }
527 
529  s.pack("MXNode::op", static_cast<int>(op()));
530  }
531 
533  temp = 0;
534 
535  s.unpack("MXNode::deps", dep_);
536  s.unpack("MXNode::sp", sparsity_);
537  }
538 
539 
541  int op;
542  s.unpack("MXNode::op", op);
543 
546  } else if (casadi_math<MX>::is_unary(op)) {
547  return UnaryMX::deserialize(s);
548  }
549 
550  auto it = MXNode::deserialize_map.find(op);
551  if (it==MXNode::deserialize_map.end()) {
552  casadi_error("Not implemented op " + str(casadi_int(op)) + ":" + str(OP_GETNONZEROS));
553  } else {
554  return it->second(s);
555  }
556  }
557 
558 
559  MX MXNode::get_mac(const MX& y, const MX& z) const {
560  if (sparsity().is_orthonormal() && y.is_column() && y.is_dense()
561  && y.sparsity()==z.sparsity() && z.is_zero()) {
562  std::vector<casadi_int> perm = sparsity().permutation_vector();
563  MX nz = sparsity_cast(shared_from_this<MX>(), Sparsity::dense(nnz()));
564  return (nz*y)(perm);
565  }
566  // Get reference to transposed first argument
567  MX x = shared_from_this<MX>();
568 
569  casadi_assert(y.size2()==z.size2(),
570  "Dimension error x.mac(z). Got y=" + str(y.size2()) + " and z=" + z.dim() + ".");
571  casadi_assert(x.size1()==z.size1(),
572  "Dimension error x.mac(z). Got x=" + x.dim() + " and z=" + z.dim() + ".");
573  casadi_assert(y.size1()==x.size2(),
574  "Dimension error x.mac(z). Got y=" + str(y.size1()) + " and x" + x.dim() + ".");
575  if (x.is_dense() && y.is_dense() && z.is_dense()) {
576  return MX::create(new DenseMultiplication(z, x, y));
577  } else {
578  return MX::create(new Multiplication(z, x, y));
579  }
580  }
581 
582  MX MXNode::get_einstein(const MX& A, const MX& B,
583  const std::vector<casadi_int>& dim_c, const std::vector<casadi_int>& dim_a,
584  const std::vector<casadi_int>& dim_b,
585  const std::vector<casadi_int>& c, const std::vector<casadi_int>& a,
586  const std::vector<casadi_int>& b) const {
587 
588  if (A.is_zero() || B.is_zero())
589  return shared_from_this<MX>();
590 
591  MX C = densify(shared_from_this<MX>());
592 
593  if (A.is_constant() && B.is_constant() && C.is_constant()) {
594  // Constant folding
595  DM Ac = A->get_DM();
596  DM Bc = B->get_DM();
597  DM Cc = C->get_DM();
598  return einstein(vec(densify(Ac)), vec(densify(Bc)), vec(densify(Cc)),
599  dim_a, dim_b, dim_c, a, b, c);
600  }
601 
602  return MX::create(new Einstein(C, densify(A), densify(B), dim_c, dim_a, dim_b, c, a, b));
603  }
604 
605  MX MXNode::get_bilin(const MX& x, const MX& y) const {
606  return MX::create(new Bilin(shared_from_this<MX>(), x, y));
607  }
608 
609  MX MXNode::get_rank1(const MX& alpha, const MX& x, const MX& y) const {
610  return MX::create(new Rank1(shared_from_this<MX>(), alpha, x, y));
611  }
612 
614  return MX::create(new LogSumExp(shared_from_this<MX>()));
615  }
616 
617  MX MXNode::get_solve_triu(const MX& r, bool tr) const {
618  if (tr) {
619  return MX::create(new TriuSolve<true>(densify(r), shared_from_this<MX>()));
620  } else {
621  return MX::create(new TriuSolve<false>(densify(r), shared_from_this<MX>()));
622  }
623  }
624 
625  MX MXNode::get_solve_tril(const MX& r, bool tr) const {
626  if (tr) {
627  return MX::create(new TrilSolve<true>(densify(r), shared_from_this<MX>()));
628  } else {
629  return MX::create(new TrilSolve<false>(densify(r), shared_from_this<MX>()));
630  }
631  }
632 
633  MX MXNode::get_solve_triu_unity(const MX& r, bool tr) const {
634  if (tr) {
635  return MX::create(new TriuSolveUnity<true>(densify(r), shared_from_this<MX>()));
636  } else {
637  return MX::create(new TriuSolveUnity<false>(densify(r), shared_from_this<MX>()));
638  }
639  }
640 
641  MX MXNode::get_solve_tril_unity(const MX& r, bool tr) const {
642  if (tr) {
643  return MX::create(new TrilSolveUnity<true>(densify(r), shared_from_this<MX>()));
644  } else {
645  return MX::create(new TrilSolveUnity<false>(densify(r), shared_from_this<MX>()));
646  }
647  }
648 
649  MX MXNode::get_solve(const MX& r, bool tr, const Linsol& linear_solver) const {
650  if (tr) {
651  return MX::create(new LinsolCall<true>(densify(r), shared_from_this<MX>(), linear_solver));
652  } else {
653  return MX::create(new LinsolCall<false>(densify(r), shared_from_this<MX>(), linear_solver));
654  }
655  }
656 
657  MX MXNode::get_nzref(const Sparsity& sp, const std::vector<casadi_int>& nz) const {
658  if (sparsity().is_dense() && is_range(nz, 0, nnz())) {
659  return sparsity_cast(shared_from_this<MX>(), sp);
660  }
661  return GetNonzeros::create(sp, shared_from_this<MX>(), nz);
662  }
663 
664  MX MXNode::get_nz_ref(const MX& nz) const {
665  return GetNonzerosParam::create(shared_from_this<MX>(), nz);
666  }
667 
668  MX MXNode::get_nz_ref(const MX& inner, const Slice& outer) const {
669  if (outer.all()==std::vector<casadi_int>{0}) {
670  return get_nz_ref(inner);
671  } else {
672  return GetNonzerosParam::create(shared_from_this<MX>(), inner, outer);
673  }
674  }
675 
676  MX MXNode::get_nz_ref(const Slice& inner, const MX& outer) const {
677  if (inner.all()==std::vector<casadi_int>{0}) {
678  return get_nz_ref(outer);
679  } else {
680  return GetNonzerosParam::create(shared_from_this<MX>(), inner, outer);
681  }
682  }
683 
684  MX MXNode::get_nz_ref(const MX& inner, const MX& outer) const {
685  return GetNonzerosParam::create(shared_from_this<MX>(), inner, outer);
686  }
687 
688  MX MXNode::get_nzassign(const MX& y, const std::vector<casadi_int>& nz) const {
689  // Check if any element needs to be set at all
690  bool set_any = false;
691  for (auto i=nz.begin(); i!=nz.end() && !set_any; ++i) {
692  set_any = *i >= 0;
693  }
694  if (!set_any) return y;
695 
696  return SetNonzeros<false>::create(y, shared_from_this<MX>(), nz);
697  }
698 
699 
700  MX MXNode::get_nzadd(const MX& y, const std::vector<casadi_int>& nz) const {
701  if (nz.empty() || is_zero()) {
702  return y;
703  } else {
704  return SetNonzeros<true>::create(y, shared_from_this<MX>(), nz);
705  }
706  }
707 
708  MX MXNode::get_nzassign(const MX& y, const MX& nz) const {
709  return SetNonzerosParam<false>::create(y, shared_from_this<MX>(), nz);
710  }
711 
712  MX MXNode::get_nzassign(const MX& y, const MX& inner, const Slice& outer) const {
713  return SetNonzerosParam<false>::create(y, shared_from_this<MX>(), inner, outer);
714  }
715 
716  MX MXNode::get_nzassign(const MX& y, const Slice& inner, const MX& outer) const {
717  return SetNonzerosParam<false>::create(y, shared_from_this<MX>(), inner, outer);
718  }
719 
720  MX MXNode::get_nzassign(const MX& y, const MX& inner, const MX& outer) const {
721  return SetNonzerosParam<false>::create(y, shared_from_this<MX>(), inner, outer);
722  }
723 
724  MX MXNode::get_nzadd(const MX& y, const MX& nz) const {
725  if (nz.is_empty() || is_zero()) {
726  return y;
727  } else {
728  return SetNonzerosParam<true>::create(y, shared_from_this<MX>(), nz);
729  }
730  }
731 
732  MX MXNode::get_nzadd(const MX& y, const MX& inner, const Slice& outer) const {
733  if (inner.is_empty() || outer.is_empty() || is_zero()) {
734  return y;
735  } else {
736  return SetNonzerosParam<true>::create(y, shared_from_this<MX>(), inner, outer);
737  }
738  }
739 
740  MX MXNode::get_nzadd(const MX& y, const Slice& inner, const MX& outer) const {
741  if (outer.is_empty() || outer.is_empty() || is_zero()) {
742  return y;
743  } else {
744  return SetNonzerosParam<true>::create(y, shared_from_this<MX>(), inner, outer);
745  }
746  }
747 
748  MX MXNode::get_nzadd(const MX& y, const MX& inner, const MX& outer) const {
749  if (inner.is_empty() || outer.is_empty() || is_zero()) {
750  return y;
751  } else {
752  return SetNonzerosParam<true>::create(y, shared_from_this<MX>(), inner, outer);
753  }
754  }
755 
756  MX MXNode::get_project(const Sparsity& sp) const {
757  if (sp==sparsity()) {
758  return shared_from_this<MX>();
759  } else if (sp.nnz()==0) {
760  return MX::zeros(sp);
761  } else if (sp.is_dense()) {
762  return MX::create(new Densify(shared_from_this<MX>(), sp));
763  } else if (sparsity().is_dense()) {
764  return MX::create(new Sparsify(shared_from_this<MX>(), sp));
765  } else {
766  return MX::create(new Project(shared_from_this<MX>(), sp));
767  }
768  }
769 
770  MX MXNode::get_subref(const Slice& i, const Slice& j) const {
771  return MX::create(new SubRef(shared_from_this<MX>(), i, j));
772  }
773 
774  MX MXNode::get_subassign(const MX& y, const Slice& i, const Slice& j) const {
775  return MX::create(new SubAssign(shared_from_this<MX>(), y, i, j));
776  }
777 
778  MX MXNode::get_unary(casadi_int op) const {
779  if (operation_checker<F0XChecker>(op) && is_zero()) {
780  // If identically zero
781  return MX::zeros(sparsity());
782  } else {
783  // Create a new node
784  return MX::create(new UnaryMX(Operation(op), shared_from_this<MX>()));
785  }
786  }
787 
788  MX MXNode::get_binary(casadi_int op, const MX& y) const {
789  // If-else-zero nodes are always simplified at top level to avoid NaN propagation
790  if (y.op() == OP_IF_ELSE_ZERO) {
791  if (op == OP_MUL) {
792  // (Rule 1.) x * if_else_zero(c, y), simplified to if_else_zero(c, x * y)
793  // Background: x is often a partial derivative and may evaluate to INF or NAN.
794  // The simplification ensures that the zero seed corresponding to an inactive branch does
795  // not give rise to any NaN contribution to the derivative due to NaN * 0 == NaN.
796  return if_else_zero(y.dep(0), shared_from_this<MX>() * y.dep(1));
797  } else if (op == OP_ADD && this->op() == OP_IF_ELSE_ZERO && MX::is_equal(dep(0), y.dep(0))) {
798  // (Rule 2.) if_else_zero(c, x) + if_else_zero(c, y) is simplified to if_else_zero(c, x + y)
799  // Background: During the backward propagation, seeds are added together. Without this rule,
800  // the addition node can prevent rule (1.) from working in subsequent steps.
801  return if_else_zero(y.dep(0), dep(1) + y.dep(1));
802  }
803  } else if (this->op() == OP_IF_ELSE_ZERO && op == OP_MUL) {
804  // Same as Rule 1. above, but with factors swapped. For symmetry.
805  return if_else_zero(dep(0), dep(1) * y);
806  }
807  // Create binary node
808  if (sparsity().is_scalar(false)) {
809  if (nnz()==0) {
810  if (operation_checker<F0XChecker>(op)) return MX::zeros(Sparsity(y.size()));
811  return to_matrix(MX(0)->_get_binary(op, y, true, false), y.sparsity());
812  } else {
813  return to_matrix(_get_binary(op, y, true, false), y.sparsity());
814  }
815  } else if (y.is_scalar()) {
816  if (y.nnz()==0) {
817  if (operation_checker<FX0Checker>(op)) return MX::zeros(Sparsity(size()));
818  return to_matrix(_get_binary(op, MX(0), false, true), sparsity());
819  } else {
820  return to_matrix(_get_binary(op, y, false, true), sparsity());
821  }
822  } else {
823  casadi_assert(sparsity().size() == y.sparsity().size(), "Dimension mismatch.");
824  if (sparsity()==y.sparsity()) {
825  // Matching sparsities
826  return _get_binary(op, y, false, false);
827  } else {
828  // Get the sparsity pattern of the result
829  // (ignoring structural zeros giving rise to nonzero result)
830  const Sparsity& x_sp = sparsity();
831  const Sparsity& y_sp = y.sparsity();
832  Sparsity r_sp = x_sp.combine(y_sp, operation_checker<F0XChecker>(op),
833  operation_checker<FX0Checker>(op));
834 
835  // Project the arguments to this sparsity
836  MX xx = project(shared_from_this<MX>(), r_sp);
837  MX yy = project(y, r_sp);
838  return xx->_get_binary(op, yy, false, false);
839  }
840  }
841  }
842 
843  MX MXNode::_get_binary(casadi_int op, const MX& y, bool scX, bool scY) const {
844  casadi_assert_dev(sparsity()==y.sparsity() || scX || scY);
845 
847 
848  // If identically zero due to one argument being zero
849  if ((operation_checker<F0XChecker>(op) && nnz()==0) ||
850  (operation_checker<FX0Checker>(op) && y->nnz()==0)) {
851  return MX::zeros(Sparsity(size()));
852  }
853 
854  if ((operation_checker<F0XChecker>(op) && is_zero()) ||
855  (operation_checker<FX0Checker>(op) && y->is_zero())) {
856  return MX::zeros(sparsity());
857  }
858 
859  // Handle special operations (independent of type)
860  switch (op) {
861  case OP_ADD:
862  if (MXNode::is_equal(y.get(), this, maxDepth())) return get_unary(OP_TWICE);
863  break;
864  case OP_SUB:
865  case OP_NE:
866  case OP_LT:
867  if (MXNode::is_equal(y.get(), this, maxDepth())) return MX::zeros(sparsity());
868  break;
869  case OP_DIV:
870  if (y->is_zero()) return MX::nan(sparsity());
871  // fall-through
872  case OP_EQ:
873  case OP_LE:
874  if (MXNode::is_equal(y.get(), this, maxDepth())) return MX::ones(sparsity());
875  break;
876  case OP_MUL:
877  if (MXNode::is_equal(y.get(), this, maxDepth())) return get_unary(OP_SQ);
878  break;
879  default: break; // no rule
880  }
881 
882  // Handle special cases for the second argument
883  switch (y->op()) {
884  case OP_CONST:
885  // Make the constant the first argument, if possible
886  if (this->op()!=OP_CONST && operation_checker<CommChecker>(op)) {
887  return y->_get_binary(op, shared_from_this<MX>(), scY, scX);
888  } else {
889  switch (op) {
890  case OP_POW:
891  return _get_binary(OP_CONSTPOW, y, scX, scY);
892  case OP_CONSTPOW:
893  if (y->is_value(-1)) return get_unary(OP_INV);
894  else if (y->is_value(0)) return MX::ones(size());
895  else if (y->is_value(1)) return shared_from_this<MX>();
896  else if (y->is_value(2)) return get_unary(OP_SQ);
897  break;
898  case OP_ADD:
899  case OP_SUB:
900  if (y->is_zero())
901  return scX ? repmat(shared_from_this<MX>(), y.size()) : shared_from_this<MX>();
902  break;
903  case OP_MUL:
904  if (y->is_value(1)) return shared_from_this<MX>();
905  break;
906  case OP_DIV:
907  if (y->is_value(1)) return shared_from_this<MX>();
908  else if (y->is_value(0.5)) return get_unary(OP_TWICE);
909  break;
910  default: break; // no rule
911  }
912  }
913  break;
914  case OP_NEG:
915  if (op==OP_ADD) {
916  return _get_binary(OP_SUB, y->dep(), scX, scY);
917  } else if (op==OP_SUB) {
918  return _get_binary(OP_ADD, y->dep(), scX, scY);
919  } else if (op==OP_MUL) {
920  return -_get_binary(OP_MUL, y->dep(), scX, scY);
921  } else if (op==OP_DIV) {
922  return -_get_binary(OP_DIV, y->dep(), scX, scY);
923  }
924  break;
925  case OP_INV:
926  if (op==OP_MUL) {
927  return _get_binary(OP_DIV, y->dep(), scX, scY);
928  } else if (op==OP_DIV) {
929  return _get_binary(OP_MUL, y->dep(), scX, scY);
930  }
931  break;
932  default: break; // no rule
933  }
934 
935  }
936 
937  if (scX) {
938  // Check if it is ok to loop over nonzeros only
939  if (y.is_dense() || operation_checker<FX0Checker>(op) ||
940  (is_zero() && operation_checker<F00Checker>(op))) {
941  // Loop over nonzeros
942  return MX::create(new BinaryMX<true, false>(Operation(op), shared_from_this<MX>(), y));
943  } else {
944  // Put a densification node in between
945  return _get_binary(op, densify(y), true, false);
946  }
947  } else if (scY) {
948  // Check if it is ok to loop over nonzeros only
949  if (sparsity().is_dense() || operation_checker<F0XChecker>(op) ||
950  (y.is_zero() && operation_checker<F00Checker>(op)) ||
951  (y.is_constant() && static_cast<double>(y)>0 && (op==OP_CONSTPOW || op==OP_POW))) {
952  // Loop over nonzeros
953  return MX::create(new BinaryMX<false, true>(Operation(op), shared_from_this<MX>(), y));
954  } else {
955  // Put a densification node in between
956  return densify(shared_from_this<MX>())->_get_binary(op, y, false, true);
957  }
958  } else {
959  // Loop over nonzeros only
960  MX rr = MX::create(new BinaryMX<false, false>(Operation(op), shared_from_this<MX>(), y));
961 
962  // Handle structural zeros giving rise to nonzero result, e.g. cos(0) == 1
963  if (!rr.is_dense() && !operation_checker<F00Checker>(op)) {
964  // Get the value for the structural zeros
965  double fcn_0(0);
966  casadi_math<double>::fun(op, 0, 0, fcn_0);
967  rr = densify(rr, fcn_0);
968  }
969  return rr;
970  }
971  }
972 
974  casadi_error("'mapping' not defined for class " + class_name());
975  }
976 
977  bool MXNode::sameOpAndDeps(const MXNode* node, casadi_int depth) const {
978  if (op()!=node->op() || n_dep()!=node->n_dep())
979  return false;
980  for (casadi_int i=0; i<n_dep(); ++i) {
981  if (!MX::is_equal(dep(i), node->dep(i), depth-1))
982  return false;
983  }
984  return true;
985  }
986 
987  MX MXNode::get_assert(const MX& y, const std::string& fail_message) const {
988  return MX::create(new Assertion(shared_from_this<MX>(), y, fail_message));
989  }
990 
991  MX MXNode::get_monitor(const std::string& comment) const {
992  if (nnz()==0) {
993  return shared_from_this<MX>();
994  } else {
995  return MX::create(new Monitor(shared_from_this<MX>(), comment));
996  }
997  }
998 
1000  MX x = shared_from_this<MX>();
1001  casadi_assert(x.is_vector(), "Argument must be vector, got " + x.dim() + ".");
1002  if (x.is_column()) {
1003  return MX::create(new Find(shared_from_this<MX>()));
1004  } else {
1005  return find(x.T());
1006  }
1007  }
1008 
1009  MX MXNode::get_low(const MX& v, const Dict& options) const {
1010  return MX::create(new Low(v, shared_from_this<MX>(), options));
1011  }
1012 
1013  MX MXNode::get_bspline(const std::vector<double>& knots,
1014  const std::vector<casadi_int>& offset,
1015  const std::vector<double>& coeffs,
1016  const std::vector<casadi_int>& degree,
1017  casadi_int m,
1018  const std::vector<casadi_int>& lookup_mode) const {
1019  MX x = shared_from_this<MX>();
1020  return MX::create(new BSpline(x, knots, offset, coeffs, degree, m, lookup_mode));
1021  }
1022 
1023  MX MXNode::get_bspline(const MX& coeffs,
1024  const std::vector<double>& knots,
1025  const std::vector<casadi_int>& offset,
1026  const std::vector<casadi_int>& degree,
1027  casadi_int m,
1028  const std::vector<casadi_int>& lookup_mode) const {
1029  MX x = shared_from_this<MX>();
1030  return MX::create(new BSplineParametric(x, coeffs, knots, offset, degree, m, lookup_mode));
1031  }
1032 
1033  MX MXNode::get_convexify(const Dict& opts) const {
1034  return MX::create(new Convexify(shared_from_this<MX>(), opts));
1035  }
1036 
1038  return MX::create(new Determinant(shared_from_this<MX>()));
1039  }
1040 
1042  return MX::create(new Inverse(shared_from_this<MX>()));
1043  }
1044 
1045 
1046  MX MXNode::get_dot(const MX& y) const {
1047  casadi_assert(
1048  size2()==y.size2() && size1()==y.size1(),
1049  "MXNode::dot: Dimension mismatch. dot requires its "
1050  "two arguments to have equal shapes, but got ("
1051  + str(size2()) + ", " + str(size1()) + ") and ("
1052  + str(y.size2()) + ", " + str(y.size1()) + ").");
1053  if (sparsity()==y.sparsity()) {
1054  if (sparsity().nnz()==0) {
1055  return 0;
1056  } else if (sparsity().is_scalar()) {
1057  return get_binary(OP_MUL, y);
1058  } else {
1059  if (shared_from_this<MX>().is_zero() || y.is_zero()) return 0;
1060  return MX::create(new Dot(shared_from_this<MX>(), y));
1061  }
1062  } else {
1063  // Project to pattern intersection
1064  Sparsity sp = sparsity().intersect(y.sparsity());
1065  MX xx = project(shared_from_this<MX>(), sp);
1066  MX yy = project(y, sp);
1067  return xx->get_dot(yy);
1068  }
1069  }
1070 
1072  return MX::create(new NormF(shared_from_this<MX>()));
1073  }
1074 
1076  return MX::create(new Norm2(shared_from_this<MX>()));
1077  }
1078 
1080  return MX::create(new NormInf(shared_from_this<MX>()));
1081  }
1082 
1084  return MX::create(new Norm1(shared_from_this<MX>()));
1085  }
1086 
1088  if (sparsity_.is_empty()) return MX();
1089  return MX::create(new MMin(shared_from_this<MX>()));
1090  }
1091 
1093  if (sparsity_.is_empty()) return MX();
1094  return MX::create(new MMax(shared_from_this<MX>()));
1095  }
1096 
1097  MX MXNode::get_horzcat(const std::vector<MX>& x) const {
1098  // Check if there is any existing horzcat operation
1099  for (auto i=x.begin(); i!=x.end(); ++i) {
1100  if (i->op()==OP_HORZCAT) {
1101  // Split up
1102  std::vector<MX> x_split(x.begin(), i);
1103  for (; i!=x.end(); ++i) {
1104  if (i->op()==OP_HORZCAT) {
1105  x_split.insert(x_split.end(), (*i)->dep_.begin(), (*i)->dep_.end());
1106  } else {
1107  x_split.push_back(*i);
1108  }
1109  }
1110  return horzcat(x_split);
1111  }
1112  }
1113 
1114  // Create a Horzcat node
1115  return MX::create(new Horzcat(x));
1116  }
1117 
1118  MX MXNode::get_diagcat(const std::vector<MX>& x) const {
1119  // Create a Horzcat node
1120  return MX::create(new Diagcat(x));
1121  }
1122 
1123  MX MXNode::get_vertcat(const std::vector<MX>& x) const {
1124  // Check if there is any existing vertcat operation
1125  for (auto i=x.begin(); i!=x.end(); ++i) {
1126  if (i->op()==OP_VERTCAT) {
1127  // Split up
1128  std::vector<MX> x_split(x.begin(), i);
1129  for (; i!=x.end(); ++i) {
1130  if (i->op()==OP_VERTCAT) {
1131  x_split.insert(x_split.end(), (*i)->dep_.begin(), (*i)->dep_.end());
1132  } else {
1133  x_split.push_back(*i);
1134  }
1135  }
1136  return vertcat(x_split);
1137  }
1138  }
1139 
1140  return MX::create(new Vertcat(x));
1141  }
1142 
1143  std::vector<MX> MXNode::get_horzsplit(const std::vector<casadi_int>& output_offset) const {
1144  if (is_zero()) {
1145  std::vector<MX> ret =
1146  MX::createMultipleOutput(new Horzsplit(shared_from_this<MX>(), output_offset));
1147  for (casadi_int i=0;i<ret.size();++i) {
1148  ret[i]=MX::zeros(ret[i].sparsity());
1149  }
1150  return ret;
1151  }
1152  std::vector<MX> ret =
1153  MX::createMultipleOutput(new Horzsplit(shared_from_this<MX>(), output_offset));
1154 
1156  // Simplify horzsplit(horzcat)
1157  if (op()==OP_HORZCAT) {
1158  casadi_int offset_deps = 0;
1159  casadi_int j = 0;
1160  for (casadi_int i=0;i<output_offset.size();++i) {
1161  while (offset_deps<output_offset[i]) { offset_deps+=dep(j).size2();++j; }
1162  if (j>=n_dep()) j = n_dep()-1;
1163  if (output_offset[i]==offset_deps &&
1164  (i+1<output_offset.size()?output_offset[i+1]:size2()) ==
1165  offset_deps +dep(j).size2()) {
1166  // Aligned with vertcat dependency
1167  ret[i] = dep(j);
1168  }
1169  }
1170  }
1171  }
1172  return ret;
1173  }
1174 
1175  MX MXNode::get_repmat(casadi_int n, casadi_int m) const {
1176  if (n==1) {
1177  return MX::create(new HorzRepmat(shared_from_this<MX>(), m));
1178  } else {
1179  // Fallback to generic_matrix impl
1180  return GenericMatrix<MX>::repmat(shared_from_this<MX>(), n, m);
1181  }
1182  }
1183 
1184  MX MXNode::get_repsum(casadi_int n, casadi_int m) const {
1185  if (n==1) {
1186  return MX::create(new HorzRepsum(shared_from_this<MX>(), m));
1187  } else {
1188  // Fallback to generic_matrix impl
1189  return GenericMatrix<MX>::repsum(shared_from_this<MX>(), n, m);
1190  }
1191  }
1192 
1193  std::vector<MX> MXNode::get_diagsplit(const std::vector<casadi_int>& offset1,
1194  const std::vector<casadi_int>& offset2) const {
1195  if (is_zero()) {
1196  std::vector<MX> ret =
1197  MX::createMultipleOutput(new Diagsplit(shared_from_this<MX>(), offset1, offset2));
1198  for (casadi_int i=0;i<ret.size();++i) {
1199  ret[i]=MX::zeros(ret[i].sparsity());
1200  }
1201  return ret;
1202  }
1203  std::vector<MX> ret =
1204  MX::createMultipleOutput(new Diagsplit(shared_from_this<MX>(), offset1, offset2));
1205 
1206  return ret;
1207  }
1208 
1209  std::vector<MX> MXNode::get_vertsplit(const std::vector<casadi_int>& output_offset) const {
1210  if (is_zero()) {
1211  std::vector<MX> ret =
1212  MX::createMultipleOutput(new Vertsplit(shared_from_this<MX>(), output_offset));
1213  for (casadi_int i=0;i<ret.size();++i) {
1214  ret[i]=MX::zeros(ret[i].sparsity());
1215  }
1216  return ret;
1217  }
1218  std::vector<MX> ret =
1219  MX::createMultipleOutput(new Vertsplit(shared_from_this<MX>(), output_offset));
1220 
1222  // Simplify vertsplit(vertcat)
1223  if (op()==OP_VERTCAT) {
1224  casadi_int offset_deps = 0;
1225  casadi_int j = 0;
1226  for (casadi_int i=0;i<output_offset.size();++i) {
1227  while (offset_deps<output_offset[i]) { offset_deps+=dep(j).size1();++j; }
1228  if (j>=n_dep()) j = n_dep()-1;
1229  if (output_offset[i]==offset_deps &&
1230  (i+1<output_offset.size()?output_offset[i+1]:size1()) ==
1231  offset_deps +dep(j).size1()) {
1232  // Aligned with vertcat dependency
1233  ret[i] = dep(j);
1234  }
1235  }
1236  }
1237  }
1238  return ret;
1239  }
1240 
1241  void MXNode::copy_fwd(const bvec_t* arg, bvec_t* res, casadi_int len) {
1242  if (arg!=res) {
1243  std::copy(arg, arg+len, res);
1244  }
1245  }
1246 
1247  void MXNode::copy_rev(bvec_t* arg, bvec_t* res, casadi_int len) {
1248  if (arg!=res) {
1249  for (casadi_int k=0; k<len; ++k) {
1250  *arg++ |= *res;
1251  *res++ = 0;
1252  }
1253  }
1254  }
1255 
1256  bool MXNode::is_equal(const MXNode* x, const MXNode* y, casadi_int depth) {
1257  if (x==y) {
1258  return true;
1259  } else if (depth>0) {
1260  return x->is_equal(y, depth);
1261  } else {
1262  return false;
1263  }
1264  }
1265 
1266 
1267  // Note: binary/unary operations are omitted here
1268  std::map<casadi_int, MXNode* (*)(DeserializingStream&)> MXNode::deserialize_map = {
1276  //{OP_MAP, Map::deserialize}, Map is a function
1293  // OP_SUBREF
1294  // OP_SUBASSIGN,
1312  //OP_ERFINV,
1313  //OP_PRINTME,
1314  //OP_LIFT,
1315  //OP_EINSTEIN
1320  };
1321 
1322 
1323 } // namespace casadi
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: bspline.cpp:30
Calculate quadratic form.
Definition: bilin.hpp:42
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: bilin.hpp:110
Represents any binary operation that involves two matrices.
Definition: binary_mx.hpp:41
static MXNode * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Helper class for C code generation.
std::string work(casadi_int n, casadi_int sz, bool is_ref) const
std::string copy(const std::string &arg, std::size_t n, const std::string &res)
Create a copy operation.
std::string workel(casadi_int n) const
static MXNode * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
Convexify a symmetric matrix.
Definition: convexify.hpp:46
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: convexify.hpp:104
An MX atomic for matrix-matrix product,.
Matrix transpose (dense)
Definition: transpose.hpp:177
Densify.
Definition: project.hpp:146
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
Matrix determinant.
Definition: determinant.hpp:42
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: determinant.hpp:81
Diagonal concatenation of matrices.
Definition: concat.hpp:306
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: concat.hpp:376
Diag split, x -> x0, x1, ...
Definition: split.hpp:180
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: split.hpp:223
Matrix dot.
Definition: dot.hpp:42
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: dot.hpp:116
An MX atomic for an Einstein product,.
Definition: einstein.hpp:40
Finds the first nonzero element in a vector.
Definition: casadi_find.hpp:39
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Function object.
Definition: function.hpp:60
bool is_dense() const
Check if the matrix expression is dense.
bool is_column() const
Check if the matrix is a column vector (i.e. size2()==1)
bool is_empty(bool both=false) const
Check if the sparsity is empty, i.e. if one of the dimensions is zero.
std::pair< casadi_int, casadi_int > size() const
Get the shape.
bool is_vector() const
Check if the matrix is a row or column vector.
casadi_int nnz() const
Get the number of (structural) non-zero elements.
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 MX ones(casadi_int nrow=1, casadi_int ncol=1)
Create a dense matrix or a matrix with specified sparsity with all entries one.
static MatType repsum(const MatType &x, casadi_int n, casadi_int m=1)
Functions called by friend functions defined here.
static MX zeros(casadi_int nrow=1, casadi_int ncol=1)
Create a dense matrix or a matrix with specified sparsity with all entries zero.
bool is_scalar(bool scalar_and_dense=false) const
Check if the matrix expression is scalar.
casadi_int getCount() const
Get the reference count.
static MX create(const MX &x, const MX &nz)
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
static MX create(const Sparsity &sp, const MX &x, const std::vector< casadi_int > &nz)
Definition: getnonzeros.cpp:32
static bool simplification_on_the_fly
Indicates whether simplifications should be made on the fly.
Horizontal repmat.
Definition: repmat.hpp:43
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: repmat.hpp:126
Horizontal repsum.
Definition: repmat.hpp:141
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: repmat.hpp:216
Horizontal concatenation.
Definition: concat.hpp:137
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: concat.hpp:207
Horizontal split, x -> x0, x1, ...
Definition: split.hpp:123
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: split.hpp:165
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Matrix inverse.
Definition: inverse.hpp:42
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: inverse.hpp:81
Linear solve operation with a linear solver instance.
Definition: solve.hpp:148
static MXNode * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
Definition: solve_impl.hpp:324
Linear solver.
Definition: linsol.hpp:55
Calculate logsumexp update.
Definition: logsumexp.hpp:42
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: logsumexp.hpp:100
Lows the first nonzero element in a vector.
Definition: casadi_low.hpp:39
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: casadi_low.hpp:108
Matrix maximum.
Definition: mmin.hpp:116
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: mmin.hpp:178
Matrix minimum.
Definition: mmin.hpp:40
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: mmin.hpp:102
Node class for MX objects.
Definition: mx_node.hpp:51
virtual void serialize_type(SerializingStream &s) const
Serialize type information.
Definition: mx_node.cpp:528
virtual MX get_logsumexp() const
Logsumexp.
Definition: mx_node.cpp:613
virtual void reset_input() const
Reset the marker for an input expression.
Definition: mx_node.cpp:150
std::string class_name() const override
Get name of public class.
Definition: mx_node.cpp:197
virtual MX get_nzassign(const MX &y, const std::vector< casadi_int > &nz) const
Assign the nonzeros of a matrix to another matrix.
Definition: mx_node.cpp:688
virtual const std::string & name() const
Get the name.
Definition: mx_node.cpp:193
virtual casadi_int n_primitives() const
Get the number of symbolic primitives.
Definition: mx_node.cpp:142
virtual MX get_norm_2() const
Spectral norm.
Definition: mx_node.cpp:1075
~MXNode() override=0
Destructor.
Definition: mx_node.cpp:82
virtual MX get_output(casadi_int oind) const
Get an output.
Definition: mx_node.cpp:441
virtual casadi_int offset() const
Definition: mx_node.cpp:218
virtual bool is_zero() const
Check if identically zero.
Definition: mx_node.hpp:71
virtual MX get_sparsity_cast(const Sparsity &sp) const
Sparsity cast.
Definition: mx_node.cpp:505
virtual MX get_mmax() const
Max.
Definition: mx_node.cpp:1092
static bool is_equal(const MXNode *x, const MXNode *y, casadi_int depth)
Check if two nodes are equivalent up to a given depth.
Definition: mx_node.cpp:1256
static void copy_fwd(const bvec_t *arg, bvec_t *res, casadi_int len)
Propagate sparsities forward through a copy operation.
Definition: mx_node.cpp:1241
virtual int eval_sx(const SXElem **arg, SXElem **res, casadi_int *iw, SXElem *w) const
Evaluate symbolically (SX)
Definition: mx_node.cpp:343
virtual int sp_forward(const bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const
Propagate sparsity forward.
Definition: mx_node.cpp:396
virtual Matrix< casadi_int > mapping() const
Get an IM representation of a GetNonzeros or SetNonzeros node.
Definition: mx_node.cpp:973
virtual MX get_einstein(const MX &A, const MX &B, const std::vector< casadi_int > &dim_c, const std::vector< casadi_int > &dim_a, const std::vector< casadi_int > &dim_b, const std::vector< casadi_int > &c, const std::vector< casadi_int > &a, const std::vector< casadi_int > &b) const
Einstein product and addition.
Definition: mx_node.cpp:582
virtual DM get_DM() const
Get the value (only for constant nodes)
Definition: mx_node.cpp:480
virtual void ad_reverse(const std::vector< std::vector< MX > > &aseed, std::vector< std::vector< MX > > &asens) const
Calculate reverse mode directional derivatives.
Definition: mx_node.cpp:391
virtual bool has_duplicates() const
Detect duplicate symbolic expressions.
Definition: mx_node.cpp:146
virtual 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
Generate code for the operation.
Definition: mx_node.cpp:446
virtual casadi_int ind() const
Definition: mx_node.cpp:210
virtual MX get_solve(const MX &r, bool tr, const Linsol &linear_solver) const
Solve a system of linear equations.
Definition: mx_node.cpp:649
virtual MX get_solve_triu(const MX &r, bool tr) const
Solve a system of linear equations, upper triangular A.
Definition: mx_node.cpp:617
void can_inline(std::map< const MXNode *, casadi_int > &nodeind) const
Find out which nodes can be inlined.
Definition: mx_node.cpp:284
virtual MX get_mac(const MX &y, const MX &z) const
Matrix multiplication and addition.
Definition: mx_node.cpp:559
friend class MX
Definition: mx_node.hpp:52
MX get_find() const
Find.
Definition: mx_node.cpp:999
virtual MX get_solve_tril_unity(const MX &r, bool tr) const
Solve a system of linear equations, lower triangular A, unity diagnal.
Definition: mx_node.cpp:641
virtual Dict info() const
Definition: mx_node.cpp:514
static bool maxDepth()
Get equality checking depth.
Definition: mx_node.hpp:342
virtual MX join_primitives(std::vector< MX >::const_iterator &it) const
Join an expression along symbolic primitives.
Definition: mx_node.cpp:181
virtual MX get_dot(const MX &y) const
Inner product.
Definition: mx_node.cpp:1046
virtual MX get_repmat(casadi_int m, casadi_int n) const
Create a repeated matrix node.
Definition: mx_node.cpp:1175
virtual int sp_reverse(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const
Propagate sparsity backwards.
Definition: mx_node.cpp:418
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:1013
static void copy_rev(bvec_t *arg, bvec_t *res, casadi_int len)
Propagate sparsities backwards through a copy operation.
Definition: mx_node.cpp:1247
virtual MX get_diagcat(const std::vector< MX > &x) const
Create a diagonal concatenation node.
Definition: mx_node.cpp:1118
MX get_binary(casadi_int op, const MX &y) const
Get a binary operation operation.
Definition: mx_node.cpp:788
virtual MX get_det() const
Determinant.
Definition: mx_node.cpp:1037
std::pair< casadi_int, casadi_int > size() const
Definition: mx_node.hpp:392
Sparsity sparsity_
The sparsity pattern.
Definition: mx_node.hpp:767
virtual void ad_forward(const std::vector< std::vector< MX > > &fseed, std::vector< std::vector< MX > > &fsens) const
Calculate forward mode directional derivatives.
Definition: mx_node.cpp:386
MXNode()
Constructor.
Definition: mx_node.cpp:77
virtual MX get_solve_tril(const MX &r, bool tr) const
Solve a system of linear equations, lower triangular A.
Definition: mx_node.cpp:625
void generate_copy(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, casadi_int i) const
Definition: mx_node.cpp:457
casadi_int temp
Definition: mx_node.hpp:757
void check_dep() const
Check validatity of dependencies.
Definition: mx_node.cpp:252
virtual MX get_unary(casadi_int op) const
Get a unary operation.
Definition: mx_node.cpp:778
static std::map< casadi_int, MXNode *(*)(DeserializingStream &)> deserialize_map
Definition: mx_node.hpp:779
const Sparsity & sparsity() const
Get the sparsity.
Definition: mx_node.hpp:372
virtual MX get_project(const Sparsity &sp) const
Create set sparse.
Definition: mx_node.cpp:756
casadi_int size2() const
Definition: mx_node.hpp:391
casadi_int nnz(casadi_int i=0) const
Definition: mx_node.hpp:389
static MXNode * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
Definition: mx_node.cpp:540
virtual void eval_mx(const std::vector< MX > &arg, std::vector< MX > &res) const
Evaluate symbolically (MX)
Definition: mx_node.cpp:348
virtual MX get_solve_triu_unity(const MX &r, bool tr) const
Solve a system of linear equations, upper triangular A, unity diagonal.
Definition: mx_node.cpp:633
virtual const Function & which_function() const
Get called function.
Definition: mx_node.cpp:330
virtual casadi_int nout() const
Number of outputs.
Definition: mx_node.hpp:364
virtual bool is_value(double val) const
Check if a certain value.
Definition: mx_node.hpp:86
virtual casadi_int which_output() const
Get function output.
Definition: mx_node.cpp:334
virtual MX get_subref(const Slice &i, const Slice &j) const
Get submatrix reference.
Definition: mx_node.cpp:770
const MX & dep(casadi_int ind=0) const
dependencies - functions that have to be evaluated before this one
Definition: mx_node.hpp:354
std::vector< MX > dep_
dependencies - functions that have to be evaluated before this one
Definition: mx_node.hpp:762
virtual MX get_norm_1() const
1-norm
Definition: mx_node.cpp:1083
virtual MX get_nz_ref(const MX &nz) const
Get the nonzeros of matrix, parametrically.
Definition: mx_node.cpp:664
virtual MX get_subassign(const MX &y, const Slice &i, const Slice &j) const
Get submatrix assignment.
Definition: mx_node.cpp:774
MX get_monitor(const std::string &comment) const
Monitor.
Definition: mx_node.cpp:991
casadi_int n_dep() const
Number of dependencies.
Definition: mx_node.cpp:206
virtual MX get_reshape(const Sparsity &sp) const
Reshape.
Definition: mx_node.cpp:496
virtual void serialize_body(SerializingStream &s) const
Serialize an object without type information.
Definition: mx_node.cpp:523
virtual casadi_int segment() const
Definition: mx_node.cpp:214
virtual void primitives(std::vector< MX >::iterator &it) const
Get symbolic primitives.
Definition: mx_node.cpp:154
MX get_convexify(const Dict &opts) const
Convexify.
Definition: mx_node.cpp:1033
void set_sparsity(const Sparsity &sparsity)
Set the sparsity.
Definition: mx_node.cpp:222
virtual MX get_horzcat(const std::vector< MX > &x) const
Create a horizontal concatenation node.
Definition: mx_node.cpp:1097
virtual casadi_int op() const =0
Get the operation.
virtual MX get_transpose() const
Transpose.
Definition: mx_node.cpp:484
virtual MX get_norm_fro() const
Frobenius norm.
Definition: mx_node.cpp:1071
virtual std::vector< MX > get_diagsplit(const std::vector< casadi_int > &offset1, const std::vector< casadi_int > &offset2) const
Create a diagonal split node.
Definition: mx_node.cpp:1193
virtual std::vector< MX > get_horzsplit(const std::vector< casadi_int > &output_offset) const
Create a horizontal split node.
Definition: mx_node.cpp:1143
virtual MX get_vertcat(const std::vector< MX > &x) const
Create a vertical concatenation node (vectors only)
Definition: mx_node.cpp:1123
casadi_int size1() const
Definition: mx_node.hpp:390
virtual MX get_repsum(casadi_int m, casadi_int n) const
Create a repeated sum node.
Definition: mx_node.cpp:1184
virtual MX get_mmin() const
Min.
Definition: mx_node.cpp:1087
virtual MX get_nzref(const Sparsity &sp, const std::vector< casadi_int > &nz) const
Get the nonzeros of matrix.
Definition: mx_node.cpp:657
virtual MX get_nzadd(const MX &y, const std::vector< casadi_int > &nz) const
Add the nonzeros of a matrix to another matrix.
Definition: mx_node.cpp:700
virtual int eval(const double **arg, double **res, casadi_int *iw, double *w) const
Evaluate numerically.
Definition: mx_node.cpp:338
virtual MX get_norm_inf() const
Infinity norm.
Definition: mx_node.cpp:1079
MX get_low(const MX &v, const Dict &options) const
Find.
Definition: mx_node.cpp:1009
virtual MX get_inv() const
Inverse.
Definition: mx_node.cpp:1041
bool sameOpAndDeps(const MXNode *node, casadi_int depth) const
Checks if two nodes have the same operation and have.
Definition: mx_node.cpp:977
virtual std::vector< MX > get_vertsplit(const std::vector< casadi_int > &output_offset) const
Create a vertical split node (vectors only)
Definition: mx_node.cpp:1209
virtual bool __nonzero__() const
Check the truth value of this node.
Definition: mx_node.cpp:202
virtual MX get_bilin(const MX &x, const MX &y) const
Bilinear form.
Definition: mx_node.cpp:605
void set_dep(const MX &dep)
Set unary dependency.
Definition: mx_node.cpp:226
MX get_assert(const MX &y, const std::string &fail_message) const
Assertion.
Definition: mx_node.cpp:987
virtual MX _get_binary(casadi_int op, const MX &y, bool scX, bool scY) const
Get a binary operation operation (matrix-matrix)
Definition: mx_node.cpp:843
virtual std::string disp(const std::vector< std::string > &arg) const =0
Print expression.
virtual MX get_rank1(const MX &alpha, const MX &x, const MX &y) const
Bilinear form.
Definition: mx_node.cpp:609
virtual bool is_output() const
Check if evaluation output.
Definition: mx_node.hpp:282
virtual void split_primitives(const MX &x, std::vector< MX >::iterator &it) const
Split up an expression along symbolic primitives.
Definition: mx_node.cpp:158
static MX to_matrix(const MX &x, const Sparsity &sp)
Convert scalar to matrix.
Definition: mx_node.hpp:442
void eval_linear_rearrange(const std::vector< std::array< MX, 3 > > &arg, std::vector< std::array< MX, 3 > > &res) const
Evaluate the MX node on a const/linear/nonlinear partition.
Definition: mx_node.cpp:367
T join_primitives_gen(typename std::vector< T >::const_iterator &it) const
Join an expression along symbolic primitives (template)
Definition: mx_node.cpp:171
void serialize(SerializingStream &s) const
Serialize an object.
Definition: mx_node.cpp:518
virtual double to_double() const
Get the value (only for scalar constant nodes)
Definition: mx_node.cpp:476
virtual void eval_linear(const std::vector< std::array< MX, 3 > > &arg, std::vector< std::array< MX, 3 > > &res) const
Evaluate the MX node on a const/linear/nonlinear partition.
Definition: mx_node.cpp:352
std::string print_compact(std::map< const MXNode *, casadi_int > &nodeind, std::vector< std::string > &intermed) const
Print compact.
Definition: mx_node.cpp:301
MX - Matrix expression.
Definition: mx.hpp:92
static MX create(MXNode *node)
Create from node.
Definition: mx.cpp:67
const Sparsity & sparsity() const
Get the sparsity pattern.
Definition: mx.cpp:592
bool is_constant() const
Check if constant.
Definition: mx.cpp:770
MXNode * get() const
Get a const pointer to the node.
Definition: mx.cpp:544
static bool is_equal(const MX &x, const MX &y, casadi_int depth=0)
Definition: mx.cpp:838
MX T() const
Transpose the matrix.
Definition: mx.cpp:1029
static std::vector< MX > createMultipleOutput(MXNode *node)
Create from node (multiple-outputs)
Definition: mx.cpp:128
static MX nan(const Sparsity &sp)
create a matrix with all nan
Definition: mx.cpp:576
MX dep(casadi_int ch=0) const
Get the nth dependency as MX.
Definition: mx.cpp:754
bool is_zero() const
check if zero (note that false negative answers are possible)
Definition: mx.cpp:1001
casadi_int op() const
Get operation type.
Definition: mx.cpp:822
Sparse matrix class. SX and DM are specializations.
Definition: matrix_decl.hpp:99
Monitor.
Definition: monitor.hpp:41
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: monitor.hpp:121
An MX atomic for matrix-matrix product,.
static MXNode * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
1-norm
Definition: norm.hpp:189
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: norm.hpp:251
Represents a 2-norm (spectral norm)
Definition: norm.hpp:143
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: norm.hpp:174
Represents a Frobenius norm.
Definition: norm.hpp:66
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: norm.hpp:128
Represents an infinity-norm operation on a MX.
Definition: norm.hpp:266
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: norm.hpp:328
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Change the sparsity of an expression.
Definition: project.hpp:39
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: project.cpp:115
Calculate rank1 update.
Definition: rank1.hpp:42
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: rank1.hpp:113
Reshape an expression.
Definition: reshape.hpp:42
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: reshape.hpp:184
The basic scalar symbolic class of CasADi.
Definition: sx_elem.hpp:75
Helper class for Serialization.
void pack(const Sparsity &e)
Serializes an object to the output stream.
static MXNode * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
static MX create(const MX &y, const MX &x, const MX &nz)
Create functions.
static MX create(const MX &y, const MX &x, const std::vector< casadi_int > &nz)
Create functions.
static MXNode * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
Class representing a Slice.
Definition: slice.hpp:48
bool is_empty() const
Check if slice is empty.
Definition: slice.cpp:111
std::vector< casadi_int > all() const
Get a vector of indices.
Definition: slice.cpp:90
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
static MatType repmat(const MatType &x, casadi_int n, casadi_int m=1)
General sparsity class.
Definition: sparsity.hpp:106
Sparsity intersect(const Sparsity &y, std::vector< unsigned char > &mapping) const
Intersection of two sparsity patterns.
Definition: sparsity.cpp:417
const std::vector< casadi_int > permutation_vector(bool invert=false) const
Construct permutation vector from permutation matrix.
Definition: sparsity.cpp:1375
static Sparsity dense(casadi_int nrow, casadi_int ncol=1)
Create a dense rectangular sparsity pattern *.
Definition: sparsity.cpp:1012
bool is_reshape(const Sparsity &y) const
Check if the sparsity is a reshape of another.
Definition: sparsity.cpp:791
Sparsity combine(const Sparsity &y, bool f0x_is_zero, bool function0_is_zero, std::vector< unsigned char > &mapping) const
Combine two sparsity patterns.
Definition: sparsity.cpp:398
casadi_int nnz() const
Get the number of (structural) non-zeros.
Definition: sparsity.cpp:148
std::pair< casadi_int, casadi_int > size() const
Get the shape.
Definition: sparsity.cpp:152
bool is_empty(bool both=false) const
Check if the sparsity is empty.
Definition: sparsity.cpp:144
bool is_dense() const
Is dense?
Definition: sparsity.cpp:273
Reference to a submatrix.
Definition: subassign.hpp:41
Reference to a submatrix.
Definition: subref.hpp:42
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Matrix transpose.
Definition: transpose.hpp:42
static MXNode * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
Definition: transpose.cpp:46
Linear solve with an upper triangular matrix.
Definition: solve.hpp:382
Linear solve with an upper triangular matrix.
Definition: solve.hpp:258
Linear solve with an upper triangular matrix, unity diagonal.
Definition: solve.hpp:341
Linear solve with an upper triangular matrix.
Definition: solve.hpp:217
Represents a general unary operation on an MX.
Definition: unary_mx.hpp:39
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: unary_mx.hpp:139
Vertical concatenation of vectors.
Definition: concat.hpp:221
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: concat.hpp:291
Vertical split of vectors, x -> x0, x1, ...
Definition: split.hpp:238
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: split.hpp:280
The casadi namespace.
Definition: archiver.cpp:28
double if_else_zero(double x, double y)
Conditional assignment.
Definition: calculus.hpp:289
unsigned long long bvec_t
bool is_range(const std::vector< casadi_int > &v, casadi_int start, casadi_int stop, casadi_int step)
Check if a vector matches a range.
Definition: casadi_misc.cpp:91
std::vector< casadi_int > find(const std::vector< T > &v)
find nonzeros
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
Operation
Enum for quick access to any node.
Definition: calculus.hpp:60
@ OP_DIAGCAT
Definition: calculus.hpp:130
@ OP_NE
Definition: calculus.hpp:70
@ OP_HORZCAT
Definition: calculus.hpp:124
@ OP_VERTCAT
Definition: calculus.hpp:127
@ OP_SPARSITY_CAST
Definition: calculus.hpp:200
@ OP_LOW
Definition: calculus.hpp:94
@ OP_HORZREPSUM
Definition: calculus.hpp:187
@ OP_ADDNONZEROS_PARAM
Definition: calculus.hpp:160
@ OP_IF_ELSE_ZERO
Definition: calculus.hpp:71
@ OP_MMAX
Definition: calculus.hpp:181
@ OP_BSPLINE
Definition: calculus.hpp:195
@ OP_DIAGSPLIT
Definition: calculus.hpp:139
@ OP_INV
Definition: calculus.hpp:73
@ OP_INVERSE
Definition: calculus.hpp:112
@ OP_OUTPUT
Definition: calculus.hpp:82
@ OP_MMIN
Definition: calculus.hpp:181
@ OP_SETNONZEROS
Definition: calculus.hpp:163
@ OP_FIND
Definition: calculus.hpp:91
@ OP_VERTSPLIT
Definition: calculus.hpp:136
@ OP_LT
Definition: calculus.hpp:70
@ OP_EQ
Definition: calculus.hpp:70
@ OP_CONST
Definition: calculus.hpp:79
@ OP_TWICE
Definition: calculus.hpp:67
@ OP_INPUT
Definition: calculus.hpp:82
@ OP_SUB
Definition: calculus.hpp:65
@ OP_DETERMINANT
Definition: calculus.hpp:109
@ OP_DOT
Definition: calculus.hpp:115
@ OP_POW
Definition: calculus.hpp:66
@ OP_PROJECT
Definition: calculus.hpp:169
@ OP_ADDNONZEROS
Definition: calculus.hpp:157
@ OP_PARAMETER
Definition: calculus.hpp:85
@ OP_SETNONZEROS_PARAM
Definition: calculus.hpp:166
@ OP_BILIN
Definition: calculus.hpp:118
@ OP_MTIMES
Definition: calculus.hpp:100
@ OP_CONVEXIFY
Definition: calculus.hpp:197
@ OP_LOGSUMEXP
Definition: calculus.hpp:208
@ OP_NORM1
Definition: calculus.hpp:178
@ OP_CALL
Definition: calculus.hpp:88
@ OP_ADD
Definition: calculus.hpp:65
@ OP_NORM2
Definition: calculus.hpp:178
@ OP_LE
Definition: calculus.hpp:70
@ OP_RESHAPE
Definition: calculus.hpp:142
@ OP_DIV
Definition: calculus.hpp:65
@ OP_TRANSPOSE
Definition: calculus.hpp:106
@ OP_SOLVE
Definition: calculus.hpp:103
@ OP_ASSERTION
Definition: calculus.hpp:172
@ OP_NEG
Definition: calculus.hpp:66
@ OP_RANK1
Definition: calculus.hpp:121
@ OP_CONSTPOW
Definition: calculus.hpp:66
@ OP_MUL
Definition: calculus.hpp:65
@ OP_HORZREPMAT
Definition: calculus.hpp:184
@ OP_HORZSPLIT
Definition: calculus.hpp:133
@ OP_GETNONZEROS_PARAM
Definition: calculus.hpp:154
@ OP_SQ
Definition: calculus.hpp:67
@ OP_NORMF
Definition: calculus.hpp:178
@ OP_MONITOR
Definition: calculus.hpp:175
@ OP_GETNONZEROS
Definition: calculus.hpp:151
@ OP_NORMINF
Definition: calculus.hpp:178
Easy access to all the functions for a particular type.
Definition: calculus.hpp:1125
static void fun(unsigned char op, const T &x, const T &y, T &f)
Evaluate a built in function (scalar-scalar)
Definition: calculus.hpp:1289