calculus.hpp
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 #ifndef CASADI_CALCULUS_HPP
27 #define CASADI_CALCULUS_HPP
28 
29 #include <iostream>
30 #include <string>
31 #include <cmath>
32 #include <limits>
33 #include <algorithm>
34 #include "casadi_common.hpp"
35 
36 // Define pi if the compiler fails to do so
37 
39 
40 namespace casadi {
41 #ifndef SWIG
43 #ifdef M_PI
44  const double pi = M_PI;
45 #else
46  const double pi = 3.14159265358979323846;
47 #endif
48 
50  const double inf = std::numeric_limits<double>::infinity();
51 
53  const double nan = std::numeric_limits<double>::quiet_NaN();
54 
56  const double eps = std::numeric_limits<double>::epsilon();
57 #endif // SWIG
58 
60  enum Operation {
61  // Simple assignment
62  OP_ASSIGN,
63 
64  // Standard unary and binary functions
65  OP_ADD, OP_SUB, OP_MUL, OP_DIV,
66  OP_NEG, OP_EXP, OP_LOG, OP_POW, OP_CONSTPOW,
67  OP_SQRT, OP_SQ, OP_TWICE,
68  OP_SIN, OP_COS, OP_TAN,
69  OP_ASIN, OP_ACOS, OP_ATAN,
70  OP_LT, OP_LE, OP_EQ, OP_NE, OP_NOT, OP_AND, OP_OR,
71  OP_FLOOR, OP_CEIL, OP_FMOD, OP_FABS, OP_SIGN, OP_COPYSIGN, OP_IF_ELSE_ZERO,
72  OP_ERF, OP_FMIN, OP_FMAX,
73  OP_INV,
74  OP_SINH, OP_COSH, OP_TANH,
75  OP_ASINH, OP_ACOSH, OP_ATANH,
76  OP_ATAN2,
77 
78  // Double constant
79  OP_CONST,
80 
81  // Function input and output
82  OP_INPUT, OP_OUTPUT,
83 
84  // Free parameter
85  OP_PARAMETER,
86 
87  // Embedded function call
88  OP_CALL,
89 
90  // Find first nonzero in a vector
91  OP_FIND,
92 
93  // Find first nonzero in a vector
94  OP_LOW,
95 
96  // Embedded function call in parallel
97  OP_MAP,
98 
99  // Matrix multiplication
100  OP_MTIMES,
101 
102  // Solve linear system of equations
103  OP_SOLVE,
104 
105  // Matrix transpose
106  OP_TRANSPOSE,
107 
108  // Matrix determinant
109  OP_DETERMINANT,
110 
111  // Matrix inverse
112  OP_INVERSE,
113 
114  // Inner product
115  OP_DOT,
116 
117  // Bilinear form
118  OP_BILIN,
119 
120  // Rank-1 update
121  OP_RANK1,
122 
123  // Horizontal concatenation
124  OP_HORZCAT,
125 
126  // Vertical concatenation of vectors
127  OP_VERTCAT,
128 
129  // Diagonal concatenation
130  OP_DIAGCAT,
131 
132  // Horizontal split
133  OP_HORZSPLIT,
134 
135  // Vertical split of vectors
136  OP_VERTSPLIT,
137 
138  // Diagonal split
139  OP_DIAGSPLIT,
140 
141  // Reshape an expression
142  OP_RESHAPE,
143 
144  // Submatrix reference
145  OP_SUBREF,
146 
147  // Submatrix assignment
148  OP_SUBASSIGN,
149 
150  // Nonzero reference
151  OP_GETNONZEROS,
152 
153  // Parametric nonzero reference
154  OP_GETNONZEROS_PARAM,
155 
156  // Nonzero addition
157  OP_ADDNONZEROS,
158 
159  // parametric nonzero addition
160  OP_ADDNONZEROS_PARAM,
161 
162  // Nonzero assignment
163  OP_SETNONZEROS,
164 
165  // Parametric nonzero assignment
166  OP_SETNONZEROS_PARAM,
167 
168  // Set sparse
169  OP_PROJECT,
170 
171  // Assertion
172  OP_ASSERTION,
173 
174  // Monitor
175  OP_MONITOR,
176 
177  // Norms
178  OP_NORM2, OP_NORM1, OP_NORMINF, OP_NORMF,
179 
180  // min/max
181  OP_MMIN, OP_MMAX,
182 
183  // Horizontal repeat
184  OP_HORZREPMAT,
185 
186  // Horizontal repeat sum
187  OP_HORZREPSUM,
188 
189  OP_ERFINV,
190  OP_PRINTME,
191  OP_LIFT,
192 
193  OP_EINSTEIN,
194 
195  OP_BSPLINE,
196 
197  OP_CONVEXIFY,
198 
199  // Sparsity cast
200  OP_SPARSITY_CAST,
201 
202  OP_LOG1P,
203 
204  OP_EXPM1,
205 
206  OP_HYPOT,
207 
208  OP_LOGSUMEXP,
209 
210  OP_REMAINDER
211 
212  };
213  #define NUM_BUILT_IN_OPS (OP_REMAINDER+1)
214 
215  #define OP_
216 
217 #ifndef SWIG
218 
220 
223  using std::isfinite;
224  using std::sqrt;
225  using std::sin;
226  using std::cos;
227  using std::tan;
228  using std::atan;
229  using std::asin;
230  using std::acos;
231  using std::sinh;
232  using std::cosh;
233  using std::tanh;
234  using std::exp;
235  using std::log;
236  using std::log10;
237  using std::abs;
238  using std::fabs;
239  using std::floor;
240  using std::ceil;
241  using std::pow;
242  using std::fmod;
243  using std::remainder;
244  using std::atan2;
245  using std::erf;
246  using std::fmin;
247  using std::fmax;
248  using std::fabs;
249  using std::atanh;
250  using std::asinh;
251  using std::acosh;
252  using std::isnan;
253  using std::isinf;
254  using std::log1p;
255  using std::expm1;
256  using std::hypot;
257  using std::copysign;
259 
261  // Implement "missing" operations
262 
264  inline double sign(double x) { return x<0 ? -1 : x>0 ? 1 : x;}
266 
268 
270 
271  inline double simplify(double x) { return x;}
272  inline double constpow(double x, double y) { return pow(x, y);}
273  inline double printme(double x, double y) {
274  std::ios::fmtflags f(uout().flags());
275  uout() << "|> " << y << " : ";
276  uout() << std::setprecision(std::numeric_limits<double>::digits10 + 1) << std::scientific;
277  uout() << x << std::endl;
278  uout().flags(f);
279  return x;
280  }
281  inline bool is_equal(double x, double y, casadi_int depth=0) { return x==y;}
282 
283 
284  // Integer maximum and minimum
285  inline casadi_int casadi_max(casadi_int x, casadi_int y) { return std::max(x, y);}
286  inline casadi_int casadi_min(casadi_int x, casadi_int y) { return std::min(x, y);}
287 
289  inline double if_else_zero(double x, double y) { return x==0 ? 0 : y;}
290  inline double if_else(double x, double y, double z) { return x==0 ? z : y;}
291 #ifdef HAS_ERFINV
292  using ::erfinv;
293 #else // HAS ERFINV
294  inline double erfinv(double x) throw() {
295  // Approximation found in Sourceforge and modified: Not very efficient
296  if (x>=1) {
297  return x==1 ? inf : nan;
298  } else if (x<=-1) {
299  return x==-1 ? -inf : nan;
300  } else if (x<-0.7) {
301  double z = sqrt(-log((1.0+x)/2.0));
302  return -(((1.641345311*z+3.429567803)*z-1.624906493)*z-1.970840454)/
303  ((1.637067800*z+3.543889200)*z+1.0);
304  } else {
305  double y;
306  if (x<0.7) {
307  double z = x*x;
308  y = x*(((-0.140543331*z+0.914624893)*z-1.645349621)*z+0.886226899)/
309  ((((-0.329097515*z+0.012229801)*z+1.442710462)*z-2.118377725)*z+1.0);
310  } else {
311  double z = sqrt(-log((1.0-x)/2.0));
312  y = (((1.641345311*z+3.429567803)*z-1.624906493)*z-1.970840454)/
313  ((1.637067800*z+3.543889200)*z+1.0);
314  }
315 
316  //polish x to full accuracy
317  y = y - (erf(y) - x) / (2.0/sqrt(pi) * exp(-y*y));
318  y = y - (erf(y) - x) / (2.0/sqrt(pi) * exp(-y*y));
319  return y;
320  }
321  }
322 #endif // HAS_ERFINV
324 
325  template<typename T>
326  T twice(const T& x) {
327  return x+x;
328  }
329 
330  template<typename T>
331  T sq(const T& x) {
332  return x*x;
333  }
334 
335  template<casadi_int I>
336  struct UnaryOperation {
338  template<typename T> static inline void fcn(const T& x, T& f);
339 
341  template<typename T> static inline void der(const T& x, const T& f, T* d);
342  };
343 
344  template<casadi_int I>
345  struct BinaryOperation {
347  template<typename T> static inline void fcn(const T& x, const T& y, T& f) {
348  UnaryOperation<I>::fcn(x, f);}
349 
351  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d) {
352  UnaryOperation<I>::der(x, f, d); d[1]=0; }
353  };
354 
355  template<casadi_int I>
356  struct BinaryOperationE {
358  template<typename T> static inline T fcn(const T& x, const T& y) {
359  T ret;
360  BinaryOperation<I>::fcn(x, y, ret);
361  return ret;
362  }
363  };
364 
366  template<casadi_int I>
367  struct DerBinaryOperation {
369  template<typename T> static inline void derf(const T& x, const T& y, T& f, T* d) {
370 
374  T tmp;
375 
377  BinaryOperation<I>::fcn(x, y, tmp);
378 
380  BinaryOperation<I>::der(x, y, tmp, d);
381 
383  f = tmp;
384  }
385  };
386 
388  template<casadi_int I>
389  struct BinaryOperationSS {
391  template<typename T> static inline void fcn(const T& x, const T& y, T& f, casadi_int n) {
392  BinaryOperation<I>::fcn(x, y, f);
393  }
394 
396  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d,
397  casadi_int n) {
398  BinaryOperation<I>::der(x, y, f, d);
399  }
400  };
401 
402 
404  template<casadi_int I>
405  struct BinaryOperationVV {
407  template<typename T> static inline void fcn(const T* x, const T* y, T* f, casadi_int n) {
408  for (casadi_int i=0; i<n; ++i) {
409  BinaryOperation<I>::fcn(*x++, *y++, *f++);
410  }
411  }
412 
414  template<typename T> static inline void der(const T* x, const T* y,
415  const T* f, T* d, casadi_int n) {
416  for (casadi_int i=0; i<n; ++i, d+=2) {
417  BinaryOperation<I>::der(*x++, *y++, *f++, d);
418  }
419  }
420  };
421 
423  template<casadi_int I>
424  struct BinaryOperationVS {
426  template<typename T> static inline void fcn(const T* x, const T& y, T* f, casadi_int n) {
427  for (casadi_int i=0; i<n; ++i) {
428  BinaryOperation<I>::fcn(*x++, y, *f++);
429  }
430  }
431 
433  template<typename T> static inline void der(const T* x, const T& y,
434  const T* f, T* d, casadi_int n) {
435  for (casadi_int i=0; i<n; ++i, d+=2) {
436  BinaryOperation<I>::der(*x++, y, *f++, d);
437  }
438  }
439  };
440 
442  template<casadi_int I>
443  struct BinaryOperationSV {
445  template<typename T> static inline void fcn(const T& x, const T* y, T* f, casadi_int n) {
446  for (casadi_int i=0; i<n; ++i) {
447  BinaryOperation<I>::fcn(x, *y++, *f++);
448  }
449  }
450 
452  template<typename T> static inline void der(const T& x, const T* y,
453  const T* f, T* d, casadi_int n) {
454  for (casadi_int i=0; i<n; ++i, d+=2) {
455  BinaryOperation<I>::der(x, *y++, *f++, d);
456  }
457  }
458  };
459 
462  template<casadi_int I> struct SmoothChecker { static const bool check=true;};
463  template<> struct SmoothChecker<OP_LT>{ static const bool check=false;};
464  template<> struct SmoothChecker<OP_LE>{ static const bool check=false;};
465  template<> struct SmoothChecker<OP_FLOOR>{ static const bool check=false;};
466  template<> struct SmoothChecker<OP_CEIL>{ static const bool check=false;};
467  template<> struct SmoothChecker<OP_FMOD>{ static const bool check=false;};
468  template<> struct SmoothChecker<OP_REMAINDER>{ static const bool check=false;};
469  template<> struct SmoothChecker<OP_EQ>{ static const bool check=false;};
470  template<> struct SmoothChecker<OP_NE>{ static const bool check=false;};
471  template<> struct SmoothChecker<OP_SIGN>{ static const bool check=false;};
472  template<> struct SmoothChecker<OP_COPYSIGN>{ static const bool check=false;};
473  template<> struct SmoothChecker<OP_NOT>{ static const bool check=false;};
474  template<> struct SmoothChecker<OP_AND>{ static const bool check=false;};
475  template<> struct SmoothChecker<OP_OR>{ static const bool check=false;};
476  template<> struct SmoothChecker<OP_IF_ELSE_ZERO>{ static const bool check=false;};
478 
481  template<casadi_int I> struct F0XChecker { static const bool check=false;};
482  template<> struct F0XChecker<OP_ASSIGN>{ static const bool check=true;};
483  template<> struct F0XChecker<OP_MUL>{ static const bool check=true;};
484  template<> struct F0XChecker<OP_DIV>{ static const bool check=true;};
485  template<> struct F0XChecker<OP_NEG>{ static const bool check=true;};
486  template<> struct F0XChecker<OP_POW>{ static const bool check=true;};
487  template<> struct F0XChecker<OP_CONSTPOW>{ static const bool check=true;};
488  template<> struct F0XChecker<OP_SQRT>{ static const bool check=true;};
489  template<> struct F0XChecker<OP_SQ>{ static const bool check=true;};
490  template<> struct F0XChecker<OP_TWICE>{ static const bool check=true;};
491  template<> struct F0XChecker<OP_SIN>{ static const bool check=true;};
492  template<> struct F0XChecker<OP_TAN>{ static const bool check=true;};
493  template<> struct F0XChecker<OP_ATAN>{ static const bool check=true;};
494  template<> struct F0XChecker<OP_ASIN>{ static const bool check=true;};
495  template<> struct F0XChecker<OP_FLOOR>{ static const bool check=true;};
496  template<> struct F0XChecker<OP_CEIL>{ static const bool check=true;};
497  template<> struct F0XChecker<OP_FMOD>{ static const bool check=true;};
498  template<> struct F0XChecker<OP_REMAINDER>{ static const bool check=true;};
499  template<> struct F0XChecker<OP_FABS>{ static const bool check=true;};
500  template<> struct F0XChecker<OP_SIGN>{ static const bool check=true;};
501  template<> struct F0XChecker<OP_COPYSIGN>{ static const bool check=true;};
502  template<> struct F0XChecker<OP_ERF>{ static const bool check=true;};
503  template<> struct F0XChecker<OP_SINH>{ static const bool check=true;};
504  template<> struct F0XChecker<OP_TANH>{ static const bool check=true;};
505  template<> struct F0XChecker<OP_ASINH>{ static const bool check=true;};
506  template<> struct F0XChecker<OP_ATANH>{ static const bool check=true;};
507  template<> struct F0XChecker<OP_ERFINV>{ static const bool check=true;};
508  template<> struct F0XChecker<OP_AND>{ static const bool check=true;};
509  template<> struct F0XChecker<OP_IF_ELSE_ZERO>{ static const bool check=true;};
510  template<> struct F0XChecker<OP_LOG1P>{ static const bool check=true;};
511  template<> struct F0XChecker<OP_EXPM1>{ static const bool check=true;};
513 
516  template<casadi_int I> struct FX0Checker { static const bool check=false;};
517  template<> struct FX0Checker<OP_MUL>{ static const bool check=true;};
518  template<> struct FX0Checker<OP_AND>{ static const bool check=true;};
519  template<> struct FX0Checker<OP_IF_ELSE_ZERO>{ static const bool check=true;};
521 
524  template<casadi_int I> struct F00Checker {
525  static const bool check=F0XChecker<I>::check || FX0Checker<I>::check;
526  };
527  template<> struct F00Checker<OP_ADD>{ static const bool check=true;};
528  template<> struct F00Checker<OP_SUB>{ static const bool check=true;};
529  template<> struct F00Checker<OP_FMIN>{ static const bool check=true;};
530  template<> struct F00Checker<OP_FMAX>{ static const bool check=true;};
531  template<> struct F00Checker<OP_AND>{ static const bool check=true;};
532  template<> struct F00Checker<OP_OR>{ static const bool check=true;};
533  template<> struct F00Checker<OP_COPYSIGN>{ static const bool check=true;};
534  template<> struct F00Checker<OP_LT>{ static const bool check=true;};
535  template<> struct F00Checker<OP_HYPOT>{ static const bool check=true;};
537 
540  template<casadi_int I> struct CommChecker { static const bool check=false;};
541  template<> struct CommChecker<OP_ADD>{ static const bool check=true;};
542  template<> struct CommChecker<OP_MUL>{ static const bool check=true;};
543  template<> struct CommChecker<OP_EQ>{ static const bool check=true;};
544  template<> struct CommChecker<OP_NE>{ static const bool check=true;};
545  template<> struct CommChecker<OP_AND>{ static const bool check=true;};
546  template<> struct CommChecker<OP_OR>{ static const bool check=true;};
547  template<> struct CommChecker<OP_HYPOT>{ static const bool check=true;};
549 
552  template<casadi_int I> struct NonnegativeChecker { static const bool check=false;};
553  template<> struct NonnegativeChecker<OP_SQRT>{ static const bool check=true;};
554  template<> struct NonnegativeChecker<OP_SQ>{ static const bool check=true;};
555  template<> struct NonnegativeChecker<OP_EXP>{ static const bool check=true;};
556  template<> struct NonnegativeChecker<OP_LT>{ static const bool check=true;};
557  template<> struct NonnegativeChecker<OP_LE>{ static const bool check=true;};
558  template<> struct NonnegativeChecker<OP_EQ>{ static const bool check=true;};
559  template<> struct NonnegativeChecker<OP_NE>{ static const bool check=true;};
560  template<> struct NonnegativeChecker<OP_NOT>{ static const bool check=true;};
561  template<> struct NonnegativeChecker<OP_AND>{ static const bool check=true;};
562  template<> struct NonnegativeChecker<OP_OR>{ static const bool check=true;};
563  template<> struct NonnegativeChecker<OP_HYPOT>{ static const bool check=true;};
565 
568  template<casadi_int I> struct NargChecker { static const casadi_int check=1;};
569  template<> struct NargChecker<OP_ADD>{ static const casadi_int check=2;};
570  template<> struct NargChecker<OP_SUB>{ static const casadi_int check=2;};
571  template<> struct NargChecker<OP_MUL>{ static const casadi_int check=2;};
572  template<> struct NargChecker<OP_DIV>{ static const casadi_int check=2;};
573  template<> struct NargChecker<OP_POW>{ static const casadi_int check=2;};
574  template<> struct NargChecker<OP_CONSTPOW>{ static const casadi_int check=2;};
575  template<> struct NargChecker<OP_EQ>{ static const casadi_int check=2;};
576  template<> struct NargChecker<OP_NE>{ static const casadi_int check=2;};
577  template<> struct NargChecker<OP_AND>{ static const casadi_int check=2;};
578  template<> struct NargChecker<OP_OR>{ static const casadi_int check=2;};
579  template<> struct NargChecker<OP_FMIN>{ static const casadi_int check=2;};
580  template<> struct NargChecker<OP_FMAX>{ static const casadi_int check=2;};
581  template<> struct NargChecker<OP_PRINTME>{ static const casadi_int check=2;};
582  template<> struct NargChecker<OP_ATAN2>{ static const casadi_int check=2;};
583  template<> struct NargChecker<OP_IF_ELSE_ZERO>{ static const casadi_int check=2;};
584  template<> struct NargChecker<OP_FMOD>{ static const casadi_int check=2;};
585  template<> struct NargChecker<OP_REMAINDER>{ static const casadi_int check=2;};
586  template<> struct NargChecker<OP_COPYSIGN>{ static const casadi_int check=2;};
587  template<> struct NargChecker<OP_CONST>{ static const casadi_int check=0;};
588  template<> struct NargChecker<OP_PARAMETER>{ static const casadi_int check=0;};
589  template<> struct NargChecker<OP_INPUT>{ static const casadi_int check=0;};
590  template<> struct NargChecker<OP_HYPOT>{ static const casadi_int check=2;};
592 
594  template<>
595  struct UnaryOperation<OP_ASSIGN>{
596  public:
597  template<typename T> static inline void fcn(const T& x, T& f) { f = x;}
598  template<typename T> static inline void der(const T& x, const T& f, T* d) { d[0] = 1; }
599  };
600 
602  template<>
603  struct BinaryOperation<OP_ADD>{
604  public:
605  template<typename T> static inline void fcn(const T& x, const T& y, T& f) { f = x+y;}
606  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d) {
607  d[0]=d[1]=1;}
608  };
609 
611  template<>
612  struct BinaryOperation<OP_SUB>{
613  public:
614  template<typename T> static inline void fcn(const T& x, const T& y, T& f) { f = x-y;}
615  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d) {
616  d[0]=1; d[1]=-1;}
617  };
618 
620  template<>
621  struct BinaryOperation<OP_MUL>{
622  public:
623  template<typename T> static inline void fcn(const T& x, const T& y, T& f) { f = x*y;}
624  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d) {
625  d[0]=y; d[1]=x;}
626  };
627 
629  template<>
630  struct BinaryOperation<OP_DIV>{
631  public:
632  template<typename T> static inline void fcn(const T& x, const T& y, T& f) { f = x/y;}
633  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d) {
634  d[0]=1/y; d[1]=-f/y;}
635  };
636 
638  template<>
639  struct UnaryOperation<OP_NEG>{
640  public:
641  template<typename T> static inline void fcn(const T& x, T& f) { f = -x;}
642  template<typename T> static inline void der(const T& x, const T& f, T* d) { d[0]=-1;}
643  };
644 
646  template<>
647  struct UnaryOperation<OP_EXP>{
648  public:
649  template<typename T> static inline void fcn(const T& x, T& f) { f = exp(x);}
650  template<typename T> static inline void der(const T& x, const T& f, T* d) { d[0]=f;}
651  };
652 
654  template<>
655  struct UnaryOperation<OP_LOG>{
656  public:
657  template<typename T> static inline void fcn(const T& x, T& f) { f = log(x);}
658  template<typename T> static inline void der(const T& x, const T& f, T* d) { d[0]=1/x;}
659  };
660 
662  template<>
663  struct BinaryOperation<OP_POW>{
664  public:
665  template<typename T> static inline void fcn(const T& x, const T& y, T& f) { f = pow(x, y);}
666  // See issue #104 why d[0] is no longer y*f/x
667  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d) {
668  d[0]=y*pow(x, y-1); d[1]=log(x)*f;}
669  };
670 
672  template<>
673  struct BinaryOperation<OP_CONSTPOW>{
674  public:
675  template<typename T> static inline void fcn(const T& x, const T& y, T& f) { f = pow(x, y);}
676  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d) {
677  d[0]=y*pow(x, y-1); d[1]=0;}
678  };
679 
681  template<>
682  struct UnaryOperation<OP_SQRT>{
683  public:
684  template<typename T> static inline void fcn(const T& x, T& f) { f = sqrt(x);}
685  template<typename T> static inline void der(const T& x, const T& f, T* d) { d[0]=1/(twice(f));}
686  };
687 
689  template<>
690  struct UnaryOperation<OP_SQ>{
691  public:
692  template<typename T> static inline void fcn(const T& x, T& f) { f = sq(x);}
693  template<typename T> static inline void der(const T& x, const T& f, T* d) { d[0]=twice(x);}
694  };
695 
697  template<>
698  struct UnaryOperation<OP_TWICE>{
699  template<typename T> static inline void fcn(const T& x, T& f) { f = 2.*x;}
700  template<typename T> static inline void der(const T& x, const T& f, T* d) { d[0] = 2; }
701  };
702 
704  template<>
705  struct UnaryOperation<OP_SIN>{
706  public:
707  template<typename T> static inline void fcn(const T& x, T& f) { f = sin(x);}
708  template<typename T> static inline void der(const T& x, const T& f, T* d) { d[0]=cos(x);}
709  };
710 
712  template<>
713  struct UnaryOperation<OP_COS>{
714  public:
715  template<typename T> static inline void fcn(const T& x, T& f) { f = cos(x);}
716  template<typename T> static inline void der(const T& x, const T& f, T* d) { d[0]=-sin(x);}
717  };
718 
720  template<>
721  struct UnaryOperation<OP_TAN>{
722  public:
723  template<typename T> static inline void fcn(const T& x, T& f) { f = tan(x);}
724  template<typename T> static inline void der(const T& x, const T& f, T* d)
725  { d[0] = 1/sq(cos(x));}
726  };
727 
729  template<>
730  struct UnaryOperation<OP_ASIN>{
731  public:
732  template<typename T> static inline void fcn(const T& x, T& f) { f = asin(x);}
733  template<typename T> static inline void der(const T& x, const T& f, T* d) { d[0]=1/sqrt(1-x*x);}
734  };
735 
737  template<>
738  struct UnaryOperation<OP_ACOS>{
739  public:
740  template<typename T> static inline void fcn(const T& x, T& f) { f = acos(x);}
741  template<typename T> static inline void der(const T& x, const T& f, T* d)
742  { d[0]=-1/sqrt(1-x*x);}
743  };
744 
746  template<>
747  struct UnaryOperation<OP_ATAN>{
748  public:
749  template<typename T> static inline void fcn(const T& x, T& f) { f = atan(x);}
750  template<typename T> static inline void der(const T& x, const T& f, T* d) { d[0] = 1/(1+x*x);}
751  };
752 
754  template<>
755  struct BinaryOperation<OP_LT>{
756  public:
757  template<typename T> static inline void fcn(const T& x, const T& y, T& f) { f = x < y;}
758  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d) {
759  d[0]=d[1]=0;}
760  };
761 
763  template<>
764  struct BinaryOperation<OP_LE>{
765  public:
766  template<typename T> static inline void fcn(const T& x, const T& y, T& f) { f = x <= y;}
767  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d) {
768  d[0]=d[1]=0;}
769  };
770 
772  template<>
773  struct UnaryOperation<OP_FLOOR>{
774  public:
775  template<typename T> static inline void fcn(const T& x, T& f) { f = floor(x);}
776  template<typename T> static inline void der(const T& x, const T& f, T* d) { d[0] = 0;}
777  };
778 
780  template<>
781  struct UnaryOperation<OP_CEIL>{
782  public:
783  template<typename T> static inline void fcn(const T& x, T& f) { f = ceil(x);}
784  template<typename T> static inline void der(const T& x, const T& f, T* d) { d[0] = 0;}
785  };
786 
788  template<>
789  struct BinaryOperation<OP_FMOD>{
790  template<typename T> static inline void fcn(const T& x, const T& y, T& f) { f = fmod(x, y);}
791  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d) {
792  d[0]=1; d[1]=(f-x)/y;}
793  };
794 
796  template<>
797  struct BinaryOperation<OP_REMAINDER>{
798  template<typename T> static inline void fcn(const T& x, const T& y, T& f) {
799  f = remainder(x, y);}
800  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d) {
801  d[0]=1; d[1]=(f-x)/y;}
802  };
803 
805  template<>
806  struct BinaryOperation<OP_EQ>{
807  template<typename T> static inline void fcn(const T& x, const T& y, T& f) { f = x==y;}
808  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d) {
809  d[0]=d[1]=0;}
810  };
811 
813  template<>
814  struct BinaryOperation<OP_NE>{
815  template<typename T> static inline void fcn(const T& x, const T& y, T& f) { f = x!=y;}
816  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d) {
817  d[0]=d[1]=0;}
818  };
819 
821  template<>
822  struct UnaryOperation<OP_NOT>{
823  public:
824  template<typename T> static inline void fcn(const T& x, T& f) { f = !x;}
825  template<typename T> static inline void der(const T& x, const T& f, T* d) { d[0] = 0;}
826  };
827 
829  template<>
830  struct BinaryOperation<OP_AND>{
831  template<typename T> static inline void fcn(const T& x, const T& y, T& f) { f = x && y;}
832  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d) {
833  d[0]=d[1]=0;}
834  };
835 
837  template<>
838  struct BinaryOperation<OP_OR>{
839  template<typename T> static inline void fcn(const T& x, const T& y, T& f) { f = x || y;}
840  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d) {
841  d[0]=d[1]=0;}
842  };
843 
845  template<>
846  struct UnaryOperation<OP_ERF>{
847  template<typename T> static inline void fcn(const T& x, T& f) { f = erf(x);}
848  template<typename T> static inline void der(const T& x, const T& f, T* d) {
849  d[0] = (2/sqrt(pi))*exp(-x*x);}
850  };
851 
853  template<>
854  struct UnaryOperation<OP_FABS>{
855  template<typename T> static inline void fcn(const T& x, T& f) { f = fabs(x);}
856  template<typename T> static inline void der(const T& x, const T& f, T* d) {
857  d[0]=sign(x);}
858  };
859 
861  template<>
862  struct UnaryOperation<OP_SIGN>{
863  template<typename T> static inline void fcn(const T& x, T& f) { f = sign(x);}
864  template<typename T> static inline void der(const T& x, const T& f, T* d) { d[0]=0;}
865  };
866 
868  template<>
869  struct BinaryOperation<OP_COPYSIGN>{
870  template<typename T> static inline void fcn(const T& x, const T& y, T& f) { f = copysign(x, y);}
871  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d) {
872  T e = 1; d[0]=copysign(e, y); d[1]=0;}
873  };
874 
876  template<>
877  struct BinaryOperation<OP_FMIN>{
878  template<typename T> static inline void fcn(const T& x, const T& y, T& f) { f = fmin(x, y);}
879  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d) {
880  T a = x<=y;
881  T b = y<=x;
882  T c = a+b;
883  d[0]=a/c; d[1]=b/c;}
884  };
885 
887  template<>
888  struct BinaryOperation<OP_FMAX>{
889  template<typename T> static inline void fcn(const T& x, const T& y, T& f) { f = fmax(x, y);}
890  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d) {
891  T a = y<=x;
892  T b = x<=y;
893  T c = a+b;
894  d[0]=a/c; d[1]=b/c;}
895  };
896 
898  template<>
899  struct UnaryOperation<OP_INV>{
900  template<typename T> static inline void fcn(const T& x, T& f) { f = 1./x;}
901  template<typename T> static inline void der(const T& x, const T& f, T* d) { d[0] = -f*f; }
902  };
903 
905  template<>
906  struct UnaryOperation<OP_SINH>{
907  template<typename T> static inline void fcn(const T& x, T& f) { f = sinh(x);}
908  template<typename T> static inline void der(const T& x, const T& f, T* d) { d[0] = cosh(x); }
909  };
910 
912  template<>
913  struct UnaryOperation<OP_COSH>{
914  template<typename T> static inline void fcn(const T& x, T& f) { f = cosh(x);}
915  template<typename T> static inline void der(const T& x, const T& f, T* d) { d[0] = sinh(x); }
916  };
917 
919  template<>
920  struct UnaryOperation<OP_TANH>{
921  template<typename T> static inline void fcn(const T& x, T& f) { f = tanh(x);}
922  template<typename T> static inline void der(const T& x, const T& f, T* d) { d[0] = 1-f*f; }
923  };
924 
926  template<>
927  struct UnaryOperation<OP_ASINH>{
928  template<typename T> static inline void fcn(const T& x, T& f) { f = asinh(x);}
929  template<typename T> static inline void der(const T& x, const T& f, T* d) {
930  d[0] = 1/sqrt(1+x*x); }
931  };
932 
934  template<>
935  struct UnaryOperation<OP_ACOSH>{
936  template<typename T> static inline void fcn(const T& x, T& f) { f = acosh(x);}
937  template<typename T> static inline void der(const T& x, const T& f, T* d) {
938  d[0] = 1/sqrt(x-1)/sqrt(x+1); }
939  };
940 
942  template<>
943  struct UnaryOperation<OP_ATANH>{
944  template<typename T> static inline void fcn(const T& x, T& f) { f = atanh(x);}
945  template<typename T> static inline void der(const T& x, const T& f, T* d) { d[0] = 1/(1-x*x); }
946  };
947 
949  template<>
950  struct UnaryOperation<OP_ERFINV>{
951  template<typename T> static inline void fcn(const T& x, T& f) { f = erfinv(x);}
952  template<typename T> static inline void der(const T& x, const T& f, T* d) {
953  d[0] = (sqrt(pi)/2)*exp(f*f); }
954  };
955 
957  template<>
958  struct UnaryOperation<OP_LOG1P>{
959  template<typename T> static inline void fcn(const T& x, T& f) { f = log1p(x);}
960  template<typename T> static inline void der(const T& x, const T& f, T* d) {
961  d[0] = 1/(1+x);}
962  };
963 
965  template<>
966  struct UnaryOperation<OP_EXPM1>{
967  template<typename T> static inline void fcn(const T& x, T& f) { f = expm1(x);}
968  template<typename T> static inline void der(const T& x, const T& f, T* d) {
969  d[0] = exp(x); }
970  };
971 
973  template<>
974  struct BinaryOperation<OP_PRINTME>{
975  template<typename T> static inline void fcn(const T& x, const T& y, T& f) {f = printme(x, y); }
976  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d) {
977  d[0]=1; d[1]=0;}
978  };
979 
981  template<>
982  struct BinaryOperation<OP_ATAN2>{
983  public:
984  template<typename T> static inline void fcn(const T& x, const T& y, T& f) { f = atan2(x, y);}
985  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d) {
986  T t = x*x+y*y; d[0]=y/t; d[1]=-x/t;}
987  };
988 
990  template<>
991  struct BinaryOperation<OP_IF_ELSE_ZERO>{
992  public:
993  template<typename T> static inline void fcn(const T& x, const T& y, T& f) {
994  f = if_else_zero(x, y);}
995  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d) {
996  d[0]=0; d[1]=x;}
997  };
998 
1000  template<>
1001  struct BinaryOperation<OP_LIFT>{
1002  template<typename T> static inline void fcn(const T& x, const T& y, T& f) { f = x;}
1003  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d) {
1004  d[0] = 1; d[1] = 0; }
1005  };
1006 
1008  template<>
1009  struct BinaryOperation<OP_HYPOT>{
1010  template<typename T> static inline void fcn(const T& x, const T& y, T& f) { f = hypot(x, y);}
1011  template<typename T> static inline void der(const T& x, const T& y, const T& f, T* d) {
1012  d[0] = x/f; d[1] = y/f; }
1013  };
1014 
1015  template<template<casadi_int> class F, typename T>
1016  T operation_getter(casadi_int op) {
1017  switch (static_cast<Operation>(op)) {
1018  case OP_ASSIGN: return F<OP_ASSIGN>::check;
1019  case OP_ADD: return F<OP_ADD>::check;
1020  case OP_SUB: return F<OP_SUB>::check;
1021  case OP_MUL: return F<OP_MUL>::check;
1022  case OP_DIV: return F<OP_DIV>::check;
1023  case OP_NEG: return F<OP_NEG>::check;
1024  case OP_EXP: return F<OP_EXP>::check;
1025  case OP_LOG: return F<OP_LOG>::check;
1026  case OP_POW: return F<OP_POW>::check;
1027  case OP_CONSTPOW: return F<OP_CONSTPOW>::check;
1028  case OP_SQRT: return F<OP_SQRT>::check;
1029  case OP_SQ: return F<OP_SQ>::check;
1030  case OP_TWICE: return F<OP_TWICE>::check;
1031  case OP_SIN: return F<OP_SIN>::check;
1032  case OP_COS: return F<OP_COS>::check;
1033  case OP_TAN: return F<OP_TAN>::check;
1034  case OP_ASIN: return F<OP_ASIN>::check;
1035  case OP_ACOS: return F<OP_ACOS>::check;
1036  case OP_ATAN: return F<OP_ATAN>::check;
1037  case OP_LT: return F<OP_LT>::check;
1038  case OP_LE: return F<OP_LE>::check;
1039  case OP_EQ: return F<OP_EQ>::check;
1040  case OP_NE: return F<OP_NE>::check;
1041  case OP_NOT: return F<OP_NOT>::check;
1042  case OP_AND: return F<OP_AND>::check;
1043  case OP_OR: return F<OP_OR>::check;
1044  case OP_FLOOR: return F<OP_FLOOR>::check;
1045  case OP_CEIL: return F<OP_CEIL>::check;
1046  case OP_FMOD: return F<OP_FMOD>::check;
1047  case OP_REMAINDER: return F<OP_REMAINDER>::check;
1048  case OP_FABS: return F<OP_FABS>::check;
1049  case OP_SIGN: return F<OP_SIGN>::check;
1050  case OP_COPYSIGN: return F<OP_COPYSIGN>::check;
1051  case OP_IF_ELSE_ZERO: return F<OP_IF_ELSE_ZERO>::check;
1052  case OP_ERF: return F<OP_ERF>::check;
1053  case OP_FMIN: return F<OP_FMIN>::check;
1054  case OP_FMAX: return F<OP_FMAX>::check;
1055  case OP_INV: return F<OP_INV>::check;
1056  case OP_SINH: return F<OP_SINH>::check;
1057  case OP_COSH: return F<OP_COSH>::check;
1058  case OP_TANH: return F<OP_TANH>::check;
1059  case OP_ASINH: return F<OP_ASINH>::check;
1060  case OP_ACOSH: return F<OP_ACOSH>::check;
1061  case OP_ATANH: return F<OP_ATANH>::check;
1062  case OP_ATAN2: return F<OP_ATAN2>::check;
1063  case OP_CONST: return F<OP_CONST>::check;
1064  case OP_INPUT: return F<OP_INPUT>::check;
1065  case OP_OUTPUT: return F<OP_OUTPUT>::check;
1066  case OP_PARAMETER: return F<OP_PARAMETER>::check;
1067  case OP_CALL: return F<OP_CALL>::check;
1068  case OP_FIND: return F<OP_FIND>::check;
1069  case OP_LOW: return F<OP_LOW>::check;
1070  case OP_MAP: return F<OP_MAP>::check;
1071  case OP_MTIMES: return F<OP_MTIMES>::check;
1072  case OP_SOLVE: return F<OP_SOLVE>::check;
1073  case OP_TRANSPOSE: return F<OP_TRANSPOSE>::check;
1074  case OP_DETERMINANT: return F<OP_DETERMINANT>::check;
1075  case OP_INVERSE: return F<OP_INVERSE>::check;
1076  case OP_DOT: return F<OP_DOT>::check;
1077  case OP_BILIN: return F<OP_BILIN>::check;
1078  case OP_RANK1: return F<OP_RANK1>::check;
1079  case OP_HORZCAT: return F<OP_HORZCAT>::check;
1080  case OP_VERTCAT: return F<OP_VERTCAT>::check;
1081  case OP_DIAGCAT: return F<OP_DIAGCAT>::check;
1082  case OP_HORZSPLIT: return F<OP_HORZSPLIT>::check;
1083  case OP_VERTSPLIT: return F<OP_VERTSPLIT>::check;
1084  case OP_DIAGSPLIT: return F<OP_DIAGSPLIT>::check;
1085  case OP_RESHAPE: return F<OP_RESHAPE>::check;
1086  case OP_SPARSITY_CAST: return F<OP_SPARSITY_CAST>::check;
1087  case OP_SUBREF: return F<OP_SUBREF>::check;
1088  case OP_SUBASSIGN: return F<OP_SUBASSIGN>::check;
1089  case OP_GETNONZEROS: return F<OP_GETNONZEROS>::check;
1090  case OP_GETNONZEROS_PARAM: return F<OP_GETNONZEROS_PARAM>::check;
1091  case OP_ADDNONZEROS: return F<OP_ADDNONZEROS>::check;
1092  case OP_ADDNONZEROS_PARAM: return F<OP_ADDNONZEROS>::check;
1093  case OP_SETNONZEROS: return F<OP_SETNONZEROS>::check;
1094  case OP_SETNONZEROS_PARAM: return F<OP_SETNONZEROS>::check;
1095  case OP_PROJECT: return F<OP_PROJECT>::check;
1096  case OP_ASSERTION: return F<OP_ASSERTION>::check;
1097  case OP_MONITOR: return F<OP_MONITOR>::check;
1098  case OP_NORM2: return F<OP_NORM2>::check;
1099  case OP_NORM1: return F<OP_NORM1>::check;
1100  case OP_NORMINF: return F<OP_NORMINF>::check;
1101  case OP_NORMF: return F<OP_NORMF>::check;
1102  case OP_MMIN: return F<OP_MMIN>::check;
1103  case OP_MMAX: return F<OP_MMAX>::check;
1104  case OP_HORZREPMAT: return F<OP_HORZREPMAT>::check;
1105  case OP_HORZREPSUM: return F<OP_HORZREPSUM>::check;
1106  case OP_ERFINV: return F<OP_ERFINV>::check;
1107  case OP_PRINTME: return F<OP_PRINTME>::check;
1108  case OP_LIFT: return F<OP_LIFT>::check;
1109  case OP_EINSTEIN: return F<OP_EINSTEIN>::check;
1110  case OP_BSPLINE: return F<OP_BSPLINE>::check;
1111  case OP_CONVEXIFY: return F<OP_CONVEXIFY>::check;
1112  case OP_LOG1P: return F<OP_LOG1P>::check;
1113  case OP_EXPM1: return F<OP_EXPM1>::check;
1114  case OP_HYPOT: return F<OP_HYPOT>::check;
1115  case OP_LOGSUMEXP: return F<OP_LOGSUMEXP>::check;
1116  }
1117  return T();
1118  }
1119 
1120  template<template<casadi_int> class F>
1121  bool operation_checker(casadi_int op) {
1122  return operation_getter<F, bool>(op);
1123  }
1124 
1126  template<typename T>
1127  struct casadi_math {
1128 
1132  static inline void fun(unsigned char op, const T& x, const T& y, T& f);
1133 
1137  static inline void fun(unsigned char op, const T* x, const T* y, T* f, casadi_int n);
1138 
1142  static inline void fun(unsigned char op, const T* x, const T& y, T* f, casadi_int n);
1143 
1147  static inline void fun(unsigned char op, const T& x, const T* y, T* f, casadi_int n);
1148 
1152  static inline void der(unsigned char op, const T& x, const T& y, const T& f, T* d);
1153 
1157  static inline void derF(unsigned char op, const T& x, const T& y, T& f, T* d);
1158 
1162  static inline bool is_binary(unsigned char op);
1163 
1167  static inline bool is_unary(unsigned char op);
1168 
1172  static inline casadi_int ndeps(unsigned char op);
1173 
1177  static inline std::string print(unsigned char op, const std::string& x,
1178  const std::string& y);
1179  static inline std::string print(unsigned char op, const std::string& x);
1180  static inline std::string name(unsigned char op);
1181  static inline std::string pre(unsigned char op);
1182  static inline std::string sep(unsigned char op);
1183  static inline std::string post(unsigned char op);
1184  };
1185 
1187  template<>
1188  struct casadi_math<casadi_int>{
1189 
1193  static inline void fun(unsigned char op, const casadi_int& x,
1194  const casadi_int& y, casadi_int& f) {
1195  double ff(0);
1196  casadi_math<double>::fun(op, static_cast<double>(x), static_cast<double>(y), ff);
1197  f = static_cast<casadi_int>(ff);
1198  }
1199 
1200  static inline void fun(unsigned char op, const casadi_int* x, const casadi_int* y,
1201  casadi_int* f, casadi_int n) {
1202  for (casadi_int i=0; i<n; ++i) {
1203  double ff(0);
1204  casadi_math<double>::fun(op, static_cast<double>(*x++), static_cast<double>(*y++), ff);
1205  *f++ = static_cast<casadi_int>(ff);
1206  }
1207  }
1208 
1209  static inline void fun(unsigned char op, const casadi_int* x, const casadi_int& y,
1210  casadi_int* f, casadi_int n) {
1211  for (casadi_int i=0; i<n; ++i) {
1212  double ff;
1213  casadi_math<double>::fun(op, static_cast<double>(*x++), static_cast<double>(y), ff);
1214  *f++ = static_cast<casadi_int>(ff);
1215  }
1216  }
1217 
1218  static inline void fun(unsigned char op, const casadi_int& x, const casadi_int* y,
1219  casadi_int* f, casadi_int n) {
1220  for (casadi_int i=0; i<n; ++i) {
1221  double ff;
1222  casadi_math<double>::fun(op, static_cast<double>(x), static_cast<double>(*y++), ff);
1223  *f++ = static_cast<casadi_int>(ff);
1224  }
1225  }
1226 
1230  static inline void der(unsigned char op, const casadi_int& x, const casadi_int& y,
1231  const casadi_int& f, casadi_int* d) {
1232  double d_real[2] = {static_cast<double>(d[0]), static_cast<double>(d[1])};
1233  casadi_math<double>::der(op, static_cast<double>(x), static_cast<double>(y),
1234  static_cast<double>(f), d_real);
1235  d[0] = static_cast<casadi_int>(d_real[0]);
1236  d[1] = static_cast<casadi_int>(d_real[1]);
1237  }
1238 
1242  static inline void derF(unsigned char op, const casadi_int& x, const casadi_int& y,
1243  casadi_int& f, casadi_int* d) {
1244  double d_real[2] = {static_cast<double>(d[0]), static_cast<double>(d[1])};
1245  double f_real = static_cast<double>(f);
1246  casadi_math<double>::derF(op, static_cast<double>(x), static_cast<double>(y), f_real, d_real);
1247  f = static_cast<casadi_int>(f_real);
1248  d[0] = static_cast<casadi_int>(d_real[0]);
1249  d[1] = static_cast<casadi_int>(d_real[1]);
1250  }
1251 
1255  static inline casadi_int ndeps(unsigned char op) {
1256  return casadi_math<double>::ndeps(op);
1257  }
1258 
1262  static inline std::string print(unsigned char op, const std::string& x,
1263  const std::string& y) {
1264  return casadi_math<double>::print(op, x, y);
1265  }
1266  static inline std::string print(unsigned char op, const std::string& x) {
1267  return casadi_math<double>::print(op, x);
1268  }
1269  static inline std::string pre(unsigned char op) {
1270  return casadi_math<double>::pre(op);
1271  }
1272  static inline std::string name(unsigned char op) {
1273  return casadi_math<double>::name(op);
1274  }
1275  static inline std::string sep(unsigned char op) {
1276  return casadi_math<double>::sep(op);
1277  }
1278  static inline std::string post(unsigned char op) {
1279  return casadi_math<double>::post(op);
1280  }
1281  };
1282 
1283  // Template implementations
1284 
1285  template<typename T>
1286  inline void casadi_math<T>::fun(unsigned char op, const T& x, const T& y, T& f) {
1287  // NOTE: We define the implementation in a preprocessor macro to be able to force inlining,
1288  // and to allow extensions in the VM
1289 #define CASADI_MATH_FUN_BUILTIN_GEN(CNAME, X, Y, F, N) \
1290  case OP_ASSIGN: CNAME<OP_ASSIGN>::fcn(X, Y, F, N); break; \
1291  case OP_ADD: CNAME<OP_ADD>::fcn(X, Y, F, N); break; \
1292  case OP_SUB: CNAME<OP_SUB>::fcn(X, Y, F, N); break; \
1293  case OP_MUL: CNAME<OP_MUL>::fcn(X, Y, F, N); break; \
1294  case OP_DIV: CNAME<OP_DIV>::fcn(X, Y, F, N); break; \
1295  case OP_NEG: CNAME<OP_NEG>::fcn(X, Y, F, N); break; \
1296  case OP_EXP: CNAME<OP_EXP>::fcn(X, Y, F, N); break; \
1297  case OP_LOG: CNAME<OP_LOG>::fcn(X, Y, F, N); break; \
1298  case OP_POW: CNAME<OP_POW>::fcn(X, Y, F, N); break; \
1299  case OP_CONSTPOW: CNAME<OP_CONSTPOW>::fcn(X, Y, F, N); break; \
1300  case OP_SQRT: CNAME<OP_SQRT>::fcn(X, Y, F, N); break; \
1301  case OP_SQ: CNAME<OP_SQ>::fcn(X, Y, F, N); break; \
1302  case OP_TWICE: CNAME<OP_TWICE>::fcn(X, Y, F, N); break; \
1303  case OP_SIN: CNAME<OP_SIN>::fcn(X, Y, F, N); break; \
1304  case OP_COS: CNAME<OP_COS>::fcn(X, Y, F, N); break; \
1305  case OP_TAN: CNAME<OP_TAN>::fcn(X, Y, F, N); break; \
1306  case OP_ASIN: CNAME<OP_ASIN>::fcn(X, Y, F, N); break; \
1307  case OP_ACOS: CNAME<OP_ACOS>::fcn(X, Y, F, N); break; \
1308  case OP_ATAN: CNAME<OP_ATAN>::fcn(X, Y, F, N); break; \
1309  case OP_LT: CNAME<OP_LT>::fcn(X, Y, F, N); break; \
1310  case OP_LE: CNAME<OP_LE>::fcn(X, Y, F, N); break; \
1311  case OP_EQ: CNAME<OP_EQ>::fcn(X, Y, F, N); break; \
1312  case OP_NE: CNAME<OP_NE>::fcn(X, Y, F, N); break; \
1313  case OP_NOT: CNAME<OP_NOT>::fcn(X, Y, F, N); break; \
1314  case OP_AND: CNAME<OP_AND>::fcn(X, Y, F, N); break; \
1315  case OP_OR: CNAME<OP_OR>::fcn(X, Y, F, N); break; \
1316  case OP_IF_ELSE_ZERO: CNAME<OP_IF_ELSE_ZERO>::fcn(X, Y, F, N); break; \
1317  case OP_FLOOR: CNAME<OP_FLOOR>::fcn(X, Y, F, N); break; \
1318  case OP_CEIL: CNAME<OP_CEIL>::fcn(X, Y, F, N); break; \
1319  case OP_FMOD: CNAME<OP_FMOD>::fcn(X, Y, F, N); break; \
1320  case OP_REMAINDER: CNAME<OP_REMAINDER>::fcn(X, Y, F, N); break; \
1321  case OP_FABS: CNAME<OP_FABS>::fcn(X, Y, F, N); break; \
1322  case OP_SIGN: CNAME<OP_SIGN>::fcn(X, Y, F, N); break; \
1323  case OP_COPYSIGN: CNAME<OP_COPYSIGN>::fcn(X, Y, F, N); break; \
1324  case OP_ERF: CNAME<OP_ERF>::fcn(X, Y, F, N); break; \
1325  case OP_FMIN: CNAME<OP_FMIN>::fcn(X, Y, F, N); break; \
1326  case OP_FMAX: CNAME<OP_FMAX>::fcn(X, Y, F, N); break; \
1327  case OP_INV: CNAME<OP_INV>::fcn(X, Y, F, N); break; \
1328  case OP_SINH: CNAME<OP_SINH>::fcn(X, Y, F, N); break; \
1329  case OP_COSH: CNAME<OP_COSH>::fcn(X, Y, F, N); break; \
1330  case OP_TANH: CNAME<OP_TANH>::fcn(X, Y, F, N); break; \
1331  case OP_ASINH: CNAME<OP_ASINH>::fcn(X, Y, F, N); break; \
1332  case OP_ACOSH: CNAME<OP_ACOSH>::fcn(X, Y, F, N); break; \
1333  case OP_ATANH: CNAME<OP_ATANH>::fcn(X, Y, F, N); break; \
1334  case OP_ATAN2: CNAME<OP_ATAN2>::fcn(X, Y, F, N); break; \
1335  case OP_ERFINV: CNAME<OP_ERFINV>::fcn(X, Y, F, N); break; \
1336  case OP_LIFT: CNAME<OP_LIFT>::fcn(X, Y, F, N); break; \
1337  case OP_PRINTME: CNAME<OP_PRINTME>::fcn(X, Y, F, N); break; \
1338  case OP_LOG1P: CNAME<OP_LOG1P>::fcn(X, Y, F, N); break; \
1339  case OP_EXPM1: CNAME<OP_EXPM1>::fcn(X, Y, F, N); break; \
1340  case OP_HYPOT: CNAME<OP_HYPOT>::fcn(X, Y, F, N); break;
1341 
1342 #define CASADI_MATH_FUN_BUILTIN(X, Y, F) CASADI_MATH_FUN_BUILTIN_GEN(BinaryOperationSS, X, Y, F, 1)
1343 
1344  switch (op) {
1345  CASADI_MATH_FUN_BUILTIN(x, y, f)
1346  }
1347  }
1348 
1349  template<typename T>
1350  inline void casadi_math<T>::fun(unsigned char op, const T* x, const T* y, T* f, casadi_int n) {
1351  switch (op) {
1352  CASADI_MATH_FUN_BUILTIN_GEN(BinaryOperationVV, x, y, f, n)
1353  }
1354  }
1355 
1356  template<typename T>
1357  inline void casadi_math<T>::fun(unsigned char op, const T* x, const T& y, T* f, casadi_int n) {
1358  switch (op) {
1359  CASADI_MATH_FUN_BUILTIN_GEN(BinaryOperationVS, x, y, f, n)
1360  }
1361  }
1362 
1363  template<typename T>
1364  inline void casadi_math<T>::fun(unsigned char op, const T& x, const T* y, T* f, casadi_int n) {
1365  switch (op) {
1366  CASADI_MATH_FUN_BUILTIN_GEN(BinaryOperationSV, x, y, f, n)
1367  }
1368  }
1369 
1370 
1371  template<typename T>
1372  inline void casadi_math<T>::der(unsigned char op, const T& x, const T& y, const T& f, T* d) {
1373  // NOTE: We define the implementation in a preprocessor macro to be able to force inlining,
1374  // and to allow extensions in the VM
1375 #define CASADI_MATH_DER_BUILTIN(X, Y, F, D) \
1376  case OP_ASSIGN: BinaryOperation<OP_ASSIGN>::der(X, Y, F, D); break; \
1377  case OP_ADD: BinaryOperation<OP_ADD>::der(X, Y, F, D); break; \
1378  case OP_SUB: BinaryOperation<OP_SUB>::der(X, Y, F, D); break; \
1379  case OP_MUL: BinaryOperation<OP_MUL>::der(X, Y, F, D); break; \
1380  case OP_DIV: BinaryOperation<OP_DIV>::der(X, Y, F, D); break; \
1381  case OP_NEG: BinaryOperation<OP_NEG>::der(X, Y, F, D); break; \
1382  case OP_EXP: BinaryOperation<OP_EXP>::der(X, Y, F, D); break; \
1383  case OP_LOG: BinaryOperation<OP_LOG>::der(X, Y, F, D); break; \
1384  case OP_POW: BinaryOperation<OP_POW>::der(X, Y, F, D); break; \
1385  case OP_CONSTPOW: BinaryOperation<OP_CONSTPOW>::der(X, Y, F, D); break; \
1386  case OP_SQRT: BinaryOperation<OP_SQRT>::der(X, Y, F, D); break; \
1387  case OP_SQ: BinaryOperation<OP_SQ>::der(X, Y, F, D); break; \
1388  case OP_TWICE: BinaryOperation<OP_TWICE>::der(X, Y, F, D); break; \
1389  case OP_SIN: BinaryOperation<OP_SIN>::der(X, Y, F, D); break; \
1390  case OP_COS: BinaryOperation<OP_COS>::der(X, Y, F, D); break; \
1391  case OP_TAN: BinaryOperation<OP_TAN>::der(X, Y, F, D); break; \
1392  case OP_ASIN: BinaryOperation<OP_ASIN>::der(X, Y, F, D); break; \
1393  case OP_ACOS: BinaryOperation<OP_ACOS>::der(X, Y, F, D); break; \
1394  case OP_ATAN: BinaryOperation<OP_ATAN>::der(X, Y, F, D); break; \
1395  case OP_LT: BinaryOperation<OP_LT>::der(X, Y, F, D); break; \
1396  case OP_LE: BinaryOperation<OP_LE>::der(X, Y, F, D); break; \
1397  case OP_EQ: BinaryOperation<OP_EQ>::der(X, Y, F, D); break; \
1398  case OP_NE: BinaryOperation<OP_NE>::der(X, Y, F, D); break; \
1399  case OP_NOT: BinaryOperation<OP_NOT>::der(X, Y, F, D); break; \
1400  case OP_AND: BinaryOperation<OP_AND>::der(X, Y, F, D); break; \
1401  case OP_OR: BinaryOperation<OP_OR>::der(X, Y, F, D); break; \
1402  case OP_IF_ELSE_ZERO: BinaryOperation<OP_IF_ELSE_ZERO>::der(X, Y, F, D); break; \
1403  case OP_FLOOR: BinaryOperation<OP_FLOOR>::der(X, Y, F, D); break; \
1404  case OP_CEIL: BinaryOperation<OP_CEIL>::der(X, Y, F, D); break; \
1405  case OP_FMOD: BinaryOperation<OP_FMOD>::der(X, Y, F, D); break; \
1406  case OP_REMAINDER: BinaryOperation<OP_REMAINDER>::der(X, Y, F, D); break; \
1407  case OP_FABS: BinaryOperation<OP_FABS>::der(X, Y, F, D); break; \
1408  case OP_SIGN: BinaryOperation<OP_SIGN>::der(X, Y, F, D); break; \
1409  case OP_COPYSIGN: BinaryOperation<OP_COPYSIGN>::der(X, Y, F, D); break; \
1410  case OP_ERF: BinaryOperation<OP_ERF>::der(X, Y, F, D); break; \
1411  case OP_FMIN: BinaryOperation<OP_FMIN>::der(X, Y, F, D); break; \
1412  case OP_FMAX: BinaryOperation<OP_FMAX>::der(X, Y, F, D); break; \
1413  case OP_INV: BinaryOperation<OP_INV>::der(X, Y, F, D); break; \
1414  case OP_SINH: BinaryOperation<OP_SINH>::der(X, Y, F, D); break; \
1415  case OP_COSH: BinaryOperation<OP_COSH>::der(X, Y, F, D); break; \
1416  case OP_TANH: BinaryOperation<OP_TANH>::der(X, Y, F, D); break; \
1417  case OP_ASINH: BinaryOperation<OP_ASINH>::der(X, Y, F, D); break; \
1418  case OP_ACOSH: BinaryOperation<OP_ACOSH>::der(X, Y, F, D); break; \
1419  case OP_ATANH: BinaryOperation<OP_ATANH>::der(X, Y, F, D); break; \
1420  case OP_ATAN2: BinaryOperation<OP_ATAN2>::der(X, Y, F, D); break; \
1421  case OP_ERFINV: BinaryOperation<OP_ERFINV>::der(X, Y, F, D); break; \
1422  case OP_LIFT: BinaryOperation<OP_LIFT>::der(X, Y, F, D); break; \
1423  case OP_PRINTME: BinaryOperation<OP_PRINTME>::der(X, Y, F, D); break; \
1424  case OP_LOG1P: BinaryOperation<OP_LOG1P>::der(X, Y, F, D); break; \
1425  case OP_EXPM1: BinaryOperation<OP_EXPM1>::der(X, Y, F, D); break; \
1426  case OP_HYPOT: BinaryOperation<OP_HYPOT>::der(X, Y, F, D); break;
1427  switch (op) {
1428  CASADI_MATH_DER_BUILTIN(x, y, f, d)
1429  }
1430  }
1431 
1432 
1433  template<typename T>
1434  inline void casadi_math<T>::derF(unsigned char op, const T& x, const T& y, T& f, T* d) {
1435  // NOTE: We define the implementation in a preprocessor macro to be able to force inlining,
1436  // and to allow extensions in the VM
1437 #define CASADI_MATH_DERF_BUILTIN(X, Y, F, D) \
1438 case OP_ASSIGN: DerBinaryOperation<OP_ASSIGN>::derf(X, Y, F, D); break; \
1439 case OP_ADD: DerBinaryOperation<OP_ADD>::derf(X, Y, F, D); break; \
1440 case OP_SUB: DerBinaryOperation<OP_SUB>::derf(X, Y, F, D); break; \
1441 case OP_MUL: DerBinaryOperation<OP_MUL>::derf(X, Y, F, D); break; \
1442 case OP_DIV: DerBinaryOperation<OP_DIV>::derf(X, Y, F, D); break; \
1443 case OP_NEG: DerBinaryOperation<OP_NEG>::derf(X, Y, F, D); break; \
1444 case OP_EXP: DerBinaryOperation<OP_EXP>::derf(X, Y, F, D); break; \
1445 case OP_LOG: DerBinaryOperation<OP_LOG>::derf(X, Y, F, D); break; \
1446 case OP_POW: DerBinaryOperation<OP_POW>::derf(X, Y, F, D); break; \
1447 case OP_CONSTPOW: DerBinaryOperation<OP_CONSTPOW>::derf(X, Y, F, D); break; \
1448 case OP_SQRT: DerBinaryOperation<OP_SQRT>::derf(X, Y, F, D); break; \
1449 case OP_SQ: DerBinaryOperation<OP_SQ>::derf(X, Y, F, D); break; \
1450 case OP_TWICE: DerBinaryOperation<OP_TWICE>::derf(X, Y, F, D); break; \
1451 case OP_SIN: DerBinaryOperation<OP_SIN>::derf(X, Y, F, D); break; \
1452 case OP_COS: DerBinaryOperation<OP_COS>::derf(X, Y, F, D); break; \
1453 case OP_TAN: DerBinaryOperation<OP_TAN>::derf(X, Y, F, D); break; \
1454 case OP_ASIN: DerBinaryOperation<OP_ASIN>::derf(X, Y, F, D); break; \
1455 case OP_ACOS: DerBinaryOperation<OP_ACOS>::derf(X, Y, F, D); break; \
1456 case OP_ATAN: DerBinaryOperation<OP_ATAN>::derf(X, Y, F, D); break; \
1457 case OP_LT: DerBinaryOperation<OP_LT>::derf(X, Y, F, D); break; \
1458 case OP_LE: DerBinaryOperation<OP_LE>::derf(X, Y, F, D); break; \
1459 case OP_EQ: DerBinaryOperation<OP_EQ>::derf(X, Y, F, D); break; \
1460 case OP_NE: DerBinaryOperation<OP_NE>::derf(X, Y, F, D); break; \
1461 case OP_NOT: DerBinaryOperation<OP_NOT>::derf(X, Y, F, D); break; \
1462 case OP_AND: DerBinaryOperation<OP_AND>::derf(X, Y, F, D); break; \
1463 case OP_OR: DerBinaryOperation<OP_OR>::derf(X, Y, F, D); break; \
1464 case OP_IF_ELSE_ZERO: DerBinaryOperation<OP_IF_ELSE_ZERO>::derf(X, Y, F, D); break; \
1465 case OP_FLOOR: DerBinaryOperation<OP_FLOOR>::derf(X, Y, F, D); break; \
1466 case OP_CEIL: DerBinaryOperation<OP_CEIL>::derf(X, Y, F, D); break; \
1467 case OP_FMOD: DerBinaryOperation<OP_FMOD>::derf(X, Y, F, D); break; \
1468 case OP_REMAINDER: DerBinaryOperation<OP_REMAINDER>::derf(X, Y, F, D); break; \
1469 case OP_FABS: DerBinaryOperation<OP_FABS>::derf(X, Y, F, D); break; \
1470 case OP_SIGN: DerBinaryOperation<OP_SIGN>::derf(X, Y, F, D); break; \
1471 case OP_COPYSIGN: DerBinaryOperation<OP_COPYSIGN>::derf(X, Y, F, D); break; \
1472 case OP_ERF: DerBinaryOperation<OP_ERF>::derf(X, Y, F, D); break; \
1473 case OP_FMIN: DerBinaryOperation<OP_FMIN>::derf(X, Y, F, D); break; \
1474 case OP_FMAX: DerBinaryOperation<OP_FMAX>::derf(X, Y, F, D); break; \
1475 case OP_INV: DerBinaryOperation<OP_INV>::derf(X, Y, F, D); break; \
1476 case OP_SINH: DerBinaryOperation<OP_SINH>::derf(X, Y, F, D); break; \
1477 case OP_COSH: DerBinaryOperation<OP_COSH>::derf(X, Y, F, D); break; \
1478 case OP_TANH: DerBinaryOperation<OP_TANH>::derf(X, Y, F, D); break; \
1479 case OP_ASINH: DerBinaryOperation<OP_ASINH>::derf(X, Y, F, D); break; \
1480 case OP_ACOSH: DerBinaryOperation<OP_ACOSH>::derf(X, Y, F, D); break; \
1481 case OP_ATANH: DerBinaryOperation<OP_ATANH>::derf(X, Y, F, D); break; \
1482 case OP_ATAN2: DerBinaryOperation<OP_ATAN2>::derf(X, Y, F, D); break; \
1483 case OP_ERFINV: DerBinaryOperation<OP_ERFINV>::derf(X, Y, F, D); break; \
1484 case OP_LIFT: DerBinaryOperation<OP_LIFT>::derf(X, Y, F, D); break; \
1485 case OP_PRINTME: DerBinaryOperation<OP_PRINTME>::derf(X, Y, F, D); break; \
1486 case OP_LOG1P: DerBinaryOperation<OP_LOG1P>::derf(X, Y, F, D); break; \
1487 case OP_EXPM1: DerBinaryOperation<OP_EXPM1>::derf(X, Y, F, D); break; \
1488 case OP_HYPOT: DerBinaryOperation<OP_HYPOT>::derf(X, Y, F, D); break;
1489  switch (op) {
1490  CASADI_MATH_DERF_BUILTIN(x, y, f, d)
1491  }
1492  }
1493 
1494  #define CASADI_MATH_BINARY_BUILTIN \
1495  case OP_ADD: \
1496  case OP_SUB: \
1497  case OP_MUL: \
1498  case OP_DIV: \
1499  case OP_POW: \
1500  case OP_CONSTPOW: \
1501  case OP_LT: \
1502  case OP_LE: \
1503  case OP_EQ: \
1504  case OP_NE: \
1505  case OP_AND: \
1506  case OP_OR: \
1507  case OP_COPYSIGN: \
1508  case OP_FMOD: \
1509  case OP_REMAINDER: \
1510  case OP_FMIN: \
1511  case OP_FMAX: \
1512  case OP_ATAN2: \
1513  case OP_PRINTME: \
1514  case OP_LIFT: \
1515  case OP_HYPOT:
1516 
1517  #define CASADI_MATH_UNARY_BUILTIN \
1518  case OP_ASSIGN: \
1519  case OP_NEG: \
1520  case OP_EXP: \
1521  case OP_LOG: \
1522  case OP_SQRT: \
1523  case OP_SQ: \
1524  case OP_TWICE: \
1525  case OP_SIN: \
1526  case OP_COS: \
1527  case OP_TAN: \
1528  case OP_ASIN: \
1529  case OP_ACOS: \
1530  case OP_ATAN: \
1531  case OP_FLOOR: \
1532  case OP_CEIL: \
1533  case OP_NOT: \
1534  case OP_ERF: \
1535  case OP_FABS: \
1536  case OP_SIGN: \
1537  case OP_INV: \
1538  case OP_SINH: \
1539  case OP_COSH: \
1540  case OP_TANH: \
1541  case OP_ASINH: \
1542  case OP_ACOSH: \
1543  case OP_ATANH: \
1544  case OP_ERFINV: \
1545  case OP_LOG1P: \
1546  case OP_EXPM1:
1547 
1548  template<typename T>
1549  bool casadi_math<T>::is_binary(unsigned char op) {
1550  switch (op) {
1551  CASADI_MATH_BINARY_BUILTIN
1552  case OP_IF_ELSE_ZERO:
1553  return true;
1554  default:
1555  return false;
1556  }
1557  }
1558 
1559  template<typename T>
1560  bool casadi_math<T>::is_unary(unsigned char op) {
1561  switch (op) {
1562  CASADI_MATH_UNARY_BUILTIN
1563  return true;
1564  default:
1565  return false;
1566  }
1567  }
1568 
1569  template<typename T>
1570  inline casadi_int casadi_math<T>::ndeps(unsigned char op) {
1571  switch (op) {
1572  case OP_CONST:
1573  case OP_PARAMETER:
1574  case OP_INPUT:
1575  return 0;
1576  CASADI_MATH_BINARY_BUILTIN
1577  case OP_IF_ELSE_ZERO:
1578  return 2;
1579  default:
1580  return 1;
1581  }
1582  }
1583 
1584  template<typename T>
1585  inline std::string
1586  casadi_math<T>::print(unsigned char op,
1587  const std::string& x, const std::string& y) {
1588  casadi_assert_dev(ndeps(op)==2);
1589  return pre(op) + x + sep(op) + y + post(op);
1590  }
1591 
1592  template<typename T>
1593  inline std::string
1594  casadi_math<T>::print(unsigned char op, const std::string& x) {
1595  casadi_assert_dev(ndeps(op)==1);
1596  return pre(op) + x + post(op);
1597  }
1598 
1599  template<typename T>
1600  inline std::string casadi_math<T>::name(unsigned char op) {
1601  switch (op) {
1602  case OP_ASSIGN: return "assign";
1603  case OP_ADD: return "add";
1604  case OP_SUB: return "sub";
1605  case OP_MUL: return "mul";
1606  case OP_DIV: return "div";
1607  case OP_NEG: return "neg";
1608  case OP_EXP: return "exp";
1609  case OP_LOG: return "log";
1610  case OP_CONSTPOW:
1611  case OP_POW: return "pow";
1612  case OP_SQRT: return "sqrt";
1613  case OP_SQ: return "sq";
1614  case OP_TWICE: return "twice";
1615  case OP_SIN: return "sin";
1616  case OP_COS: return "cos";
1617  case OP_TAN: return "tan";
1618  case OP_ASIN: return "asin";
1619  case OP_ACOS: return "acos";
1620  case OP_ATAN: return "atan";
1621  case OP_LT: return "lt";
1622  case OP_LE: return "le";
1623  case OP_EQ: return "eq";
1624  case OP_NE: return "ne";
1625  case OP_NOT: return "not";
1626  case OP_AND: return "and";
1627  case OP_OR: return "or";
1628  case OP_FLOOR: return "floor";
1629  case OP_CEIL: return "ceil";
1630  case OP_FMOD: return "fmod";
1631  case OP_REMAINDER: return "remainder";
1632  case OP_FABS: return "fabs";
1633  case OP_SIGN: return "sign";
1634  case OP_COPYSIGN: return "copysign";
1635  case OP_IF_ELSE_ZERO: return "if_else_zero";
1636  case OP_ERF: return "erf";
1637  case OP_FMIN: return "fmin";
1638  case OP_FMAX: return "fmax";
1639  case OP_INV: return "inv";
1640  case OP_SINH: return "sinh";
1641  case OP_COSH: return "cosh";
1642  case OP_TANH: return "tanh";
1643  case OP_ASINH: return "asinh";
1644  case OP_ACOSH: return "acosh";
1645  case OP_ATANH: return "atanh";
1646  case OP_ATAN2: return "atan2";
1647  case OP_CONST: return "const";
1648  case OP_INPUT: return "input";
1649  case OP_OUTPUT: return "output";
1650  case OP_PARAMETER: return "parameter";
1651  case OP_CALL: return "call";
1652  case OP_MTIMES: return "mtimes";
1653  case OP_SOLVE: return "solve";
1654  case OP_TRANSPOSE: return "transpose";
1655  case OP_DETERMINANT: return "determinant";
1656  case OP_INVERSE: return "inverse";
1657  case OP_DOT: return "dot";
1658  case OP_HORZCAT: return "horzcat";
1659  case OP_VERTCAT: return "vertcat";
1660  case OP_DIAGCAT: return "diagcat";
1661  case OP_HORZSPLIT: return "horzsplit";
1662  case OP_VERTSPLIT: return "vertsplit";
1663  case OP_DIAGSPLIT: return "diagsplit";
1664  case OP_RESHAPE: return "reshape";
1665  case OP_SPARSITY_CAST: return "sparsity_cast";
1666  case OP_SUBREF: return "subref";
1667  case OP_SUBASSIGN: return "subassign";
1668  case OP_GETNONZEROS: return "getnonzeros";
1669  case OP_GETNONZEROS_PARAM: return "getnonzeros_param";
1670  case OP_ADDNONZEROS: return "addnonzeros";
1671  case OP_ADDNONZEROS_PARAM: return "addnonzeros_param";
1672  case OP_SETNONZEROS: return "setnonzeros";
1673  case OP_SETNONZEROS_PARAM: return "setnonzeros_param";
1674  case OP_PROJECT: return "project";
1675  case OP_ASSERTION: return "assertion";
1676  case OP_NORM2: return "norm2";
1677  case OP_NORM1: return "norm1";
1678  case OP_NORMINF: return "norminf";
1679  case OP_NORMF: return "normf";
1680  case OP_ERFINV: return "erfinv";
1681  case OP_PRINTME: return "printme";
1682  case OP_LIFT: return "lift";
1683  case OP_EINSTEIN: return "einstein";
1684  case OP_BSPLINE: return "bspline";
1685  case OP_CONVEXIFY: return "convexify";
1686  case OP_LOG1P: return "log1p";
1687  case OP_EXPM1: return "expm1";
1688  case OP_HYPOT: return "hypot";
1689  case OP_LOGSUMEXP: return "logsumexp";
1690  }
1691  return "<invalid-op>";
1692  }
1693 
1694  template<typename T>
1695  inline std::string casadi_math<T>::pre(unsigned char op) {
1696  switch (op) {
1697  case OP_ASSIGN: return "";
1698  case OP_ADD: return "(";
1699  case OP_SUB: return "(";
1700  case OP_MUL: return "(";
1701  case OP_DIV: return "(";
1702  case OP_NEG: return "(-";
1703  case OP_TWICE: return "(2.*";
1704  case OP_LT: return "(";
1705  case OP_LE: return "(";
1706  case OP_EQ: return "(";
1707  case OP_NE: return "(";
1708  case OP_NOT: return "(!";
1709  case OP_AND: return "(";
1710  case OP_OR: return "(";
1711  case OP_IF_ELSE_ZERO: return "(";
1712  case OP_INV: return "(1./";
1713  default: return name(op) + "(";
1714  }
1715  }
1716 
1717  template<typename T>
1718  inline std::string casadi_math<T>::sep(unsigned char op) {
1719  switch (op) {
1720  case OP_ADD: return "+";
1721  case OP_SUB: return "-";
1722  case OP_MUL: return "*";
1723  case OP_DIV: return "/";
1724  case OP_LT: return "<";
1725  case OP_LE: return "<=";
1726  case OP_EQ: return "==";
1727  case OP_NE: return "!=";
1728  case OP_AND: return "&&";
1729  case OP_OR: return "||";
1730  case OP_IF_ELSE_ZERO: return "?";
1731  default: return ",";
1732  }
1733  }
1734 
1735  template<typename T>
1736  inline std::string casadi_math<T>::post(unsigned char op) {
1737  switch (op) {
1738  case OP_ASSIGN: return "";
1739  case OP_IF_ELSE_ZERO: return ":0)";
1740  default: return ")";
1741  }
1742  }
1743 
1744 #endif // SWIG
1745 
1746 } // namespace casadi
1747 
1749 
1750 #endif // CASADI_CALCULUS_HPP
The casadi namespace.
CASADI_EXPORT std::ostream & uout()