26 #ifndef CASADI_CALCULUS_HPP
27 #define CASADI_CALCULUS_HPP
34 #include "casadi_common.hpp"
44 const double pi = M_PI;
46 const double pi = 3.14159265358979323846;
50 const double inf = std::numeric_limits<double>::infinity();
53 const double nan = std::numeric_limits<double>::quiet_NaN();
56 const double eps = std::numeric_limits<double>::epsilon();
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,
74 OP_SINH, OP_COSH, OP_TANH,
75 OP_ASINH, OP_ACOSH, OP_ATANH,
154 OP_GETNONZEROS_PARAM,
160 OP_ADDNONZEROS_PARAM,
166 OP_SETNONZEROS_PARAM,
178 OP_NORM2, OP_NORM1, OP_NORMINF, OP_NORMF,
219 #define NUM_BUILT_IN_OPS (OP_KRON_CONTRACT+1)
249 using std::remainder;
270 inline double sign(
double x) {
return x<0 ? -1 : x>0 ? 1 : x;}
277 inline double simplify(
double x) {
return x;}
278 inline double constpow(
double x,
double y) {
return pow(x, y);}
279 inline double printme(
double x,
double y) {
280 std::ios::fmtflags f(
uout().flags());
281 uout() <<
"|> " << y <<
" : ";
282 uout() << std::setprecision(std::numeric_limits<double>::digits10 + 1) << std::scientific;
283 uout() << x << std::endl;
287 inline bool is_equal(
double x,
double y, casadi_int depth=0) {
return x==y;}
291 inline casadi_int casadi_max(casadi_int x, casadi_int y) {
return std::max(x, y);}
292 inline casadi_int casadi_min(casadi_int x, casadi_int y) {
return std::min(x, y);}
295 inline double if_else_zero(
double x,
double y) {
return x==0 ? 0 : y;}
296 inline double if_else(
double x,
double y,
double z) {
return x==0 ? z : y;}
300 inline double erfinv(
double x)
throw() {
303 return x==1 ? inf : nan;
305 return x==-1 ? -inf : nan;
307 double z = sqrt(-log((1.0+x)/2.0));
308 return -(((1.641345311*z+3.429567803)*z-1.624906493)*z-1.970840454)/
309 ((1.637067800*z+3.543889200)*z+1.0);
314 y = x*(((-0.140543331*z+0.914624893)*z-1.645349621)*z+0.886226899)/
315 ((((-0.329097515*z+0.012229801)*z+1.442710462)*z-2.118377725)*z+1.0);
317 double z = sqrt(-log((1.0-x)/2.0));
318 y = (((1.641345311*z+3.429567803)*z-1.624906493)*z-1.970840454)/
319 ((1.637067800*z+3.543889200)*z+1.0);
323 y = y - (erf(y) - x) / (2.0/sqrt(pi) * exp(-y*y));
324 y = y - (erf(y) - x) / (2.0/sqrt(pi) * exp(-y*y));
332 T twice(
const T& x) {
341 template<casadi_
int I>
342 struct UnaryOperation {
344 template<
typename T>
static inline void fcn(
const T& x, T& f);
347 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d);
350 template<casadi_
int I>
351 struct BinaryOperation {
353 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f) {
354 UnaryOperation<I>::fcn(x, f);}
357 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d) {
358 UnaryOperation<I>::der(x, f, d); d[1]=0; }
361 template<casadi_
int I>
362 struct BinaryOperationE {
364 template<
typename T>
static inline T fcn(
const T& x,
const T& y) {
366 BinaryOperation<I>::fcn(x, y, ret);
372 template<casadi_
int I>
373 struct DerBinaryOperation {
375 template<
typename T>
static inline void derf(
const T& x,
const T& y, T& f, T* d) {
383 BinaryOperation<I>::fcn(x, y, tmp);
386 BinaryOperation<I>::der(x, y, tmp, d);
394 template<casadi_
int I>
395 struct BinaryOperationSS {
397 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f, casadi_int n) {
398 BinaryOperation<I>::fcn(x, y, f);
402 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d,
404 BinaryOperation<I>::der(x, y, f, d);
410 template<casadi_
int I>
411 struct BinaryOperationVV {
413 template<
typename T>
static inline void fcn(
const T* x,
const T* y, T* f, casadi_int n) {
414 for (casadi_int i=0; i<n; ++i) {
415 BinaryOperation<I>::fcn(*x++, *y++, *f++);
420 template<
typename T>
static inline void der(
const T* x,
const T* y,
421 const T* f, T* d, casadi_int n) {
422 for (casadi_int i=0; i<n; ++i, d+=2) {
423 BinaryOperation<I>::der(*x++, *y++, *f++, d);
429 template<casadi_
int I>
430 struct BinaryOperationVS {
432 template<
typename T>
static inline void fcn(
const T* x,
const T& y, T* f, casadi_int n) {
433 for (casadi_int i=0; i<n; ++i) {
434 BinaryOperation<I>::fcn(*x++, y, *f++);
439 template<
typename T>
static inline void der(
const T* x,
const T& y,
440 const T* f, T* d, casadi_int n) {
441 for (casadi_int i=0; i<n; ++i, d+=2) {
442 BinaryOperation<I>::der(*x++, y, *f++, d);
448 template<casadi_
int I>
449 struct BinaryOperationSV {
451 template<
typename T>
static inline void fcn(
const T& x,
const T* y, T* f, casadi_int n) {
452 for (casadi_int i=0; i<n; ++i) {
453 BinaryOperation<I>::fcn(x, *y++, *f++);
458 template<
typename T>
static inline void der(
const T& x,
const T* y,
459 const T* f, T* d, casadi_int n) {
460 for (casadi_int i=0; i<n; ++i, d+=2) {
461 BinaryOperation<I>::der(x, *y++, *f++, d);
468 template<casadi_
int I>
struct SmoothChecker {
static const bool check=
true;};
469 template<>
struct SmoothChecker<OP_LT>{
static const bool check=
false;};
470 template<>
struct SmoothChecker<OP_LE>{
static const bool check=
false;};
471 template<>
struct SmoothChecker<OP_FLOOR>{
static const bool check=
false;};
472 template<>
struct SmoothChecker<OP_CEIL>{
static const bool check=
false;};
473 template<>
struct SmoothChecker<OP_FMOD>{
static const bool check=
false;};
474 template<>
struct SmoothChecker<OP_REMAINDER>{
static const bool check=
false;};
475 template<>
struct SmoothChecker<OP_EQ>{
static const bool check=
false;};
476 template<>
struct SmoothChecker<OP_NE>{
static const bool check=
false;};
477 template<>
struct SmoothChecker<OP_SIGN>{
static const bool check=
false;};
478 template<>
struct SmoothChecker<OP_COPYSIGN>{
static const bool check=
false;};
479 template<>
struct SmoothChecker<OP_NOT>{
static const bool check=
false;};
480 template<>
struct SmoothChecker<OP_AND>{
static const bool check=
false;};
481 template<>
struct SmoothChecker<OP_OR>{
static const bool check=
false;};
482 template<>
struct SmoothChecker<OP_IF_ELSE_ZERO>{
static const bool check=
false;};
487 template<casadi_
int I>
struct F0XChecker {
static const bool check=
false;};
488 template<>
struct F0XChecker<OP_ASSIGN>{
static const bool check=
true;};
489 template<>
struct F0XChecker<OP_MUL>{
static const bool check=
true;};
490 template<>
struct F0XChecker<OP_DIV>{
static const bool check=
true;};
491 template<>
struct F0XChecker<OP_NEG>{
static const bool check=
true;};
492 template<>
struct F0XChecker<OP_SQRT>{
static const bool check=
true;};
493 template<>
struct F0XChecker<OP_SQ>{
static const bool check=
true;};
494 template<>
struct F0XChecker<OP_TWICE>{
static const bool check=
true;};
495 template<>
struct F0XChecker<OP_SIN>{
static const bool check=
true;};
496 template<>
struct F0XChecker<OP_TAN>{
static const bool check=
true;};
497 template<>
struct F0XChecker<OP_ATAN>{
static const bool check=
true;};
498 template<>
struct F0XChecker<OP_ASIN>{
static const bool check=
true;};
499 template<>
struct F0XChecker<OP_FLOOR>{
static const bool check=
true;};
500 template<>
struct F0XChecker<OP_CEIL>{
static const bool check=
true;};
501 template<>
struct F0XChecker<OP_FMOD>{
static const bool check=
true;};
502 template<>
struct F0XChecker<OP_REMAINDER>{
static const bool check=
true;};
503 template<>
struct F0XChecker<OP_FABS>{
static const bool check=
true;};
504 template<>
struct F0XChecker<OP_SIGN>{
static const bool check=
true;};
505 template<>
struct F0XChecker<OP_COPYSIGN>{
static const bool check=
true;};
506 template<>
struct F0XChecker<OP_ERF>{
static const bool check=
true;};
507 template<>
struct F0XChecker<OP_SINH>{
static const bool check=
true;};
508 template<>
struct F0XChecker<OP_TANH>{
static const bool check=
true;};
509 template<>
struct F0XChecker<OP_ASINH>{
static const bool check=
true;};
510 template<>
struct F0XChecker<OP_ATANH>{
static const bool check=
true;};
511 template<>
struct F0XChecker<OP_ERFINV>{
static const bool check=
true;};
512 template<>
struct F0XChecker<OP_AND>{
static const bool check=
true;};
513 template<>
struct F0XChecker<OP_IF_ELSE_ZERO>{
static const bool check=
true;};
514 template<>
struct F0XChecker<OP_LOG1P>{
static const bool check=
true;};
515 template<>
struct F0XChecker<OP_EXPM1>{
static const bool check=
true;};
520 template<casadi_
int I>
struct FX0Checker {
static const bool check=
false;};
521 template<>
struct FX0Checker<OP_MUL>{
static const bool check=
true;};
522 template<>
struct FX0Checker<OP_AND>{
static const bool check=
true;};
523 template<>
struct FX0Checker<OP_IF_ELSE_ZERO>{
static const bool check=
true;};
528 template<casadi_
int I>
struct F00Checker {
529 static const bool check=F0XChecker<I>::check || FX0Checker<I>::check;
531 template<>
struct F00Checker<OP_ADD>{
static const bool check=
true;};
532 template<>
struct F00Checker<OP_SUB>{
static const bool check=
true;};
533 template<>
struct F00Checker<OP_FMIN>{
static const bool check=
true;};
534 template<>
struct F00Checker<OP_FMAX>{
static const bool check=
true;};
535 template<>
struct F00Checker<OP_AND>{
static const bool check=
true;};
536 template<>
struct F00Checker<OP_OR>{
static const bool check=
true;};
537 template<>
struct F00Checker<OP_COPYSIGN>{
static const bool check=
true;};
538 template<>
struct F00Checker<OP_LT>{
static const bool check=
true;};
539 template<>
struct F00Checker<OP_HYPOT>{
static const bool check=
true;};
544 template<casadi_
int I>
struct CommChecker {
static const bool check=
false;};
545 template<>
struct CommChecker<OP_ADD>{
static const bool check=
true;};
546 template<>
struct CommChecker<OP_MUL>{
static const bool check=
true;};
547 template<>
struct CommChecker<OP_EQ>{
static const bool check=
true;};
548 template<>
struct CommChecker<OP_NE>{
static const bool check=
true;};
549 template<>
struct CommChecker<OP_AND>{
static const bool check=
true;};
550 template<>
struct CommChecker<OP_OR>{
static const bool check=
true;};
551 template<>
struct CommChecker<OP_HYPOT>{
static const bool check=
true;};
552 template<>
struct CommChecker<OP_FMIN>{
static const bool check=
true;};
553 template<>
struct CommChecker<OP_FMAX>{
static const bool check=
true;};
558 template<casadi_
int I>
struct NonnegativeChecker {
static const bool check=
false;};
559 template<>
struct NonnegativeChecker<OP_SQRT>{
static const bool check=
true;};
560 template<>
struct NonnegativeChecker<OP_SQ>{
static const bool check=
true;};
561 template<>
struct NonnegativeChecker<OP_EXP>{
static const bool check=
true;};
562 template<>
struct NonnegativeChecker<OP_LT>{
static const bool check=
true;};
563 template<>
struct NonnegativeChecker<OP_LE>{
static const bool check=
true;};
564 template<>
struct NonnegativeChecker<OP_EQ>{
static const bool check=
true;};
565 template<>
struct NonnegativeChecker<OP_NE>{
static const bool check=
true;};
566 template<>
struct NonnegativeChecker<OP_NOT>{
static const bool check=
true;};
567 template<>
struct NonnegativeChecker<OP_AND>{
static const bool check=
true;};
568 template<>
struct NonnegativeChecker<OP_OR>{
static const bool check=
true;};
569 template<>
struct NonnegativeChecker<OP_HYPOT>{
static const bool check=
true;};
570 template<>
struct NonnegativeChecker<OP_FABS>{
static const bool check=
true;};
575 template<casadi_
int I>
struct BooleanChecker {
static const bool check=
false;};
576 template<>
struct BooleanChecker<OP_LT>{
static const bool check=
true;};
577 template<>
struct BooleanChecker<OP_LE>{
static const bool check=
true;};
578 template<>
struct BooleanChecker<OP_EQ>{
static const bool check=
true;};
579 template<>
struct BooleanChecker<OP_NE>{
static const bool check=
true;};
580 template<>
struct BooleanChecker<OP_NOT>{
static const bool check=
true;};
581 template<>
struct BooleanChecker<OP_AND>{
static const bool check=
true;};
582 template<>
struct BooleanChecker<OP_OR>{
static const bool check=
true;};
587 template<casadi_
int I>
struct NargChecker {
static const casadi_int check=1;};
588 template<>
struct NargChecker<OP_ADD>{
static const casadi_int check=2;};
589 template<>
struct NargChecker<OP_SUB>{
static const casadi_int check=2;};
590 template<>
struct NargChecker<OP_MUL>{
static const casadi_int check=2;};
591 template<>
struct NargChecker<OP_DIV>{
static const casadi_int check=2;};
592 template<>
struct NargChecker<OP_POW>{
static const casadi_int check=2;};
593 template<>
struct NargChecker<OP_CONSTPOW>{
static const casadi_int check=2;};
594 template<>
struct NargChecker<OP_EQ>{
static const casadi_int check=2;};
595 template<>
struct NargChecker<OP_NE>{
static const casadi_int check=2;};
596 template<>
struct NargChecker<OP_AND>{
static const casadi_int check=2;};
597 template<>
struct NargChecker<OP_OR>{
static const casadi_int check=2;};
598 template<>
struct NargChecker<OP_FMIN>{
static const casadi_int check=2;};
599 template<>
struct NargChecker<OP_FMAX>{
static const casadi_int check=2;};
600 template<>
struct NargChecker<OP_PRINTME>{
static const casadi_int check=2;};
601 template<>
struct NargChecker<OP_ATAN2>{
static const casadi_int check=2;};
602 template<>
struct NargChecker<OP_IF_ELSE_ZERO>{
static const casadi_int check=2;};
603 template<>
struct NargChecker<OP_FMOD>{
static const casadi_int check=2;};
604 template<>
struct NargChecker<OP_REMAINDER>{
static const casadi_int check=2;};
605 template<>
struct NargChecker<OP_COPYSIGN>{
static const casadi_int check=2;};
606 template<>
struct NargChecker<OP_CONST>{
static const casadi_int check=0;};
607 template<>
struct NargChecker<OP_PARAMETER>{
static const casadi_int check=0;};
608 template<>
struct NargChecker<OP_INPUT>{
static const casadi_int check=0;};
609 template<>
struct NargChecker<OP_HYPOT>{
static const casadi_int check=2;};
614 struct UnaryOperation<OP_ASSIGN>{
616 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = x;}
617 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) { d[0] = 1; }
622 struct BinaryOperation<OP_ADD>{
624 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f) { f = x+y;}
625 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d) {
631 struct BinaryOperation<OP_SUB>{
633 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f) { f = x-y;}
634 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d) {
640 struct BinaryOperation<OP_MUL>{
642 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f) { f = x*y;}
643 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d) {
649 struct BinaryOperation<OP_DIV>{
651 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f) { f = x/y;}
652 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d) {
653 d[0]=1/y; d[1]=-f/y;}
658 struct UnaryOperation<OP_NEG>{
660 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = -x;}
661 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) { d[0]=-1;}
666 struct UnaryOperation<OP_EXP>{
668 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = exp(x);}
669 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) { d[0]=f;}
674 struct UnaryOperation<OP_LOG>{
676 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = log(x);}
677 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) { d[0]=1/x;}
682 struct BinaryOperation<OP_POW>{
684 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f) { f = pow(x, y);}
686 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d) {
687 d[0]=y*pow(x, y-1); d[1]=log(x)*f;}
692 struct BinaryOperation<OP_CONSTPOW>{
694 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f) { f = pow(x, y);}
695 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d) {
696 d[0]=y*pow(x, y-1); d[1]=0;}
701 struct UnaryOperation<OP_SQRT>{
703 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = sqrt(x);}
704 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) { d[0]=1/(twice(f));}
709 struct UnaryOperation<OP_SQ>{
711 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = sq(x);}
712 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) { d[0]=twice(x);}
717 struct UnaryOperation<OP_TWICE>{
718 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = 2.*x;}
719 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) { d[0] = 2; }
724 struct UnaryOperation<OP_SIN>{
726 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = sin(x);}
727 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) { d[0]=cos(x);}
732 struct UnaryOperation<OP_COS>{
734 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = cos(x);}
735 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) { d[0]=-sin(x);}
740 struct UnaryOperation<OP_TAN>{
742 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = tan(x);}
743 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d)
744 { d[0] = 1/sq(cos(x));}
749 struct UnaryOperation<OP_ASIN>{
751 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = asin(x);}
752 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) { d[0]=1/sqrt(1-x*x);}
757 struct UnaryOperation<OP_ACOS>{
759 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = acos(x);}
760 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d)
761 { d[0]=-1/sqrt(1-x*x);}
766 struct UnaryOperation<OP_ATAN>{
768 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = atan(x);}
769 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) { d[0] = 1/(1+x*x);}
774 struct BinaryOperation<OP_LT>{
776 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f) { f = x < y;}
777 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d) {
783 struct BinaryOperation<OP_LE>{
785 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f) { f = x <= y;}
786 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d) {
792 struct UnaryOperation<OP_FLOOR>{
794 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = floor(x);}
795 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) { d[0] = 0;}
800 struct UnaryOperation<OP_CEIL>{
802 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = ceil(x);}
803 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) { d[0] = 0;}
808 struct BinaryOperation<OP_FMOD>{
809 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f) { f = fmod(x, y);}
810 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d) {
811 d[0]=1; d[1]=(f-x)/y;}
816 struct BinaryOperation<OP_REMAINDER>{
817 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f) {
818 f = remainder(x, y);}
819 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d) {
820 d[0]=1; d[1]=(f-x)/y;}
825 struct BinaryOperation<OP_EQ>{
826 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f) { f = x==y;}
827 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d) {
833 struct BinaryOperation<OP_NE>{
834 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f) { f = x!=y;}
835 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d) {
841 struct UnaryOperation<OP_NOT>{
843 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = !x;}
844 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) { d[0] = 0;}
849 struct BinaryOperation<OP_AND>{
850 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f) { f = x && y;}
851 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d) {
857 struct BinaryOperation<OP_OR>{
858 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f) { f = x || y;}
859 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d) {
865 struct UnaryOperation<OP_ERF>{
866 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = erf(x);}
867 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) {
868 d[0] = (2/sqrt(pi))*exp(-x*x);}
873 struct UnaryOperation<OP_FABS>{
874 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = fabs(x);}
875 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) {
881 struct UnaryOperation<OP_SIGN>{
882 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = sign(x);}
883 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) { d[0]=0;}
888 struct BinaryOperation<OP_COPYSIGN>{
889 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f) { f = copysign(x, y);}
890 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d) {
891 T e = 1; d[0]=copysign(e, y)*sign(x); d[1]=0;}
896 struct BinaryOperation<OP_FMIN>{
897 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f) { f = fmin(x, y);}
898 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d) {
907 struct BinaryOperation<OP_FMAX>{
908 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f) { f = fmax(x, y);}
909 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d) {
918 struct UnaryOperation<OP_INV>{
919 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = 1./x;}
920 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) { d[0] = -f*f; }
925 struct UnaryOperation<OP_SINH>{
926 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = sinh(x);}
927 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) { d[0] = cosh(x); }
932 struct UnaryOperation<OP_COSH>{
933 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = cosh(x);}
934 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) { d[0] = sinh(x); }
939 struct UnaryOperation<OP_TANH>{
940 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = tanh(x);}
941 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) { d[0] = 1-f*f; }
946 struct UnaryOperation<OP_ASINH>{
947 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = asinh(x);}
948 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) {
949 d[0] = 1/sqrt(1+x*x); }
954 struct UnaryOperation<OP_ACOSH>{
955 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = acosh(x);}
956 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) {
957 d[0] = 1/sqrt(x-1)/sqrt(x+1); }
962 struct UnaryOperation<OP_ATANH>{
963 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = atanh(x);}
964 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) { d[0] = 1/(1-x*x); }
969 struct UnaryOperation<OP_ERFINV>{
970 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = erfinv(x);}
971 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) {
972 d[0] = (sqrt(pi)/2)*exp(f*f); }
977 struct UnaryOperation<OP_LOG1P>{
978 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = log1p(x);}
979 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) {
985 struct UnaryOperation<OP_EXPM1>{
986 template<
typename T>
static inline void fcn(
const T& x, T& f) { f = expm1(x);}
987 template<
typename T>
static inline void der(
const T& x,
const T& f, T* d) {
993 struct BinaryOperation<OP_PRINTME>{
994 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f) {f = printme(x, y); }
995 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d) {
1001 struct BinaryOperation<OP_ATAN2>{
1003 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f) { f = atan2(x, y);}
1004 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d) {
1005 T t = x*x+y*y; d[0]=y/t; d[1]=-x/t;}
1010 struct BinaryOperation<OP_IF_ELSE_ZERO>{
1012 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f) {
1013 f = if_else_zero(x, y);}
1014 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d) {
1020 struct BinaryOperation<OP_LIFT>{
1021 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f) { f = x;}
1022 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d) {
1023 d[0] = 1; d[1] = 0; }
1028 struct BinaryOperation<OP_HYPOT>{
1029 template<
typename T>
static inline void fcn(
const T& x,
const T& y, T& f) { f = hypot(x, y);}
1030 template<
typename T>
static inline void der(
const T& x,
const T& y,
const T& f, T* d) {
1031 d[0] = x/f; d[1] = y/f; }
1034 template<
template<casadi_
int>
class F,
typename T>
1035 T operation_getter(casadi_int op) {
1036 switch (
static_cast<Operation
>(op)) {
1037 case OP_ASSIGN:
return F<OP_ASSIGN>::check;
1038 case OP_ADD:
return F<OP_ADD>::check;
1039 case OP_SUB:
return F<OP_SUB>::check;
1040 case OP_MUL:
return F<OP_MUL>::check;
1041 case OP_DIV:
return F<OP_DIV>::check;
1042 case OP_NEG:
return F<OP_NEG>::check;
1043 case OP_EXP:
return F<OP_EXP>::check;
1044 case OP_LOG:
return F<OP_LOG>::check;
1045 case OP_POW:
return F<OP_POW>::check;
1046 case OP_CONSTPOW:
return F<OP_CONSTPOW>::check;
1047 case OP_SQRT:
return F<OP_SQRT>::check;
1048 case OP_SQ:
return F<OP_SQ>::check;
1049 case OP_TWICE:
return F<OP_TWICE>::check;
1050 case OP_SIN:
return F<OP_SIN>::check;
1051 case OP_COS:
return F<OP_COS>::check;
1052 case OP_TAN:
return F<OP_TAN>::check;
1053 case OP_ASIN:
return F<OP_ASIN>::check;
1054 case OP_ACOS:
return F<OP_ACOS>::check;
1055 case OP_ATAN:
return F<OP_ATAN>::check;
1056 case OP_LT:
return F<OP_LT>::check;
1057 case OP_LE:
return F<OP_LE>::check;
1058 case OP_EQ:
return F<OP_EQ>::check;
1059 case OP_NE:
return F<OP_NE>::check;
1060 case OP_NOT:
return F<OP_NOT>::check;
1061 case OP_AND:
return F<OP_AND>::check;
1062 case OP_OR:
return F<OP_OR>::check;
1063 case OP_FLOOR:
return F<OP_FLOOR>::check;
1064 case OP_CEIL:
return F<OP_CEIL>::check;
1065 case OP_FMOD:
return F<OP_FMOD>::check;
1066 case OP_REMAINDER:
return F<OP_REMAINDER>::check;
1067 case OP_FABS:
return F<OP_FABS>::check;
1068 case OP_SIGN:
return F<OP_SIGN>::check;
1069 case OP_COPYSIGN:
return F<OP_COPYSIGN>::check;
1070 case OP_IF_ELSE_ZERO:
return F<OP_IF_ELSE_ZERO>::check;
1071 case OP_ERF:
return F<OP_ERF>::check;
1072 case OP_FMIN:
return F<OP_FMIN>::check;
1073 case OP_FMAX:
return F<OP_FMAX>::check;
1074 case OP_INV:
return F<OP_INV>::check;
1075 case OP_SINH:
return F<OP_SINH>::check;
1076 case OP_COSH:
return F<OP_COSH>::check;
1077 case OP_TANH:
return F<OP_TANH>::check;
1078 case OP_ASINH:
return F<OP_ASINH>::check;
1079 case OP_ACOSH:
return F<OP_ACOSH>::check;
1080 case OP_ATANH:
return F<OP_ATANH>::check;
1081 case OP_ATAN2:
return F<OP_ATAN2>::check;
1082 case OP_CONST:
return F<OP_CONST>::check;
1083 case OP_INPUT:
return F<OP_INPUT>::check;
1084 case OP_OUTPUT:
return F<OP_OUTPUT>::check;
1085 case OP_PARAMETER:
return F<OP_PARAMETER>::check;
1086 case OP_CALL:
return F<OP_CALL>::check;
1087 case OP_FIND:
return F<OP_FIND>::check;
1088 case OP_LOW:
return F<OP_LOW>::check;
1089 case OP_MAP:
return F<OP_MAP>::check;
1090 case OP_MTIMES:
return F<OP_MTIMES>::check;
1091 case OP_SOLVE:
return F<OP_SOLVE>::check;
1092 case OP_TRANSPOSE:
return F<OP_TRANSPOSE>::check;
1093 case OP_DETERMINANT:
return F<OP_DETERMINANT>::check;
1094 case OP_INVERSE:
return F<OP_INVERSE>::check;
1095 case OP_DOT:
return F<OP_DOT>::check;
1096 case OP_BILIN:
return F<OP_BILIN>::check;
1097 case OP_RANK1:
return F<OP_RANK1>::check;
1098 case OP_HORZCAT:
return F<OP_HORZCAT>::check;
1099 case OP_VERTCAT:
return F<OP_VERTCAT>::check;
1100 case OP_DIAGCAT:
return F<OP_DIAGCAT>::check;
1101 case OP_HORZSPLIT:
return F<OP_HORZSPLIT>::check;
1102 case OP_VERTSPLIT:
return F<OP_VERTSPLIT>::check;
1103 case OP_DIAGSPLIT:
return F<OP_DIAGSPLIT>::check;
1104 case OP_RESHAPE:
return F<OP_RESHAPE>::check;
1105 case OP_SPARSITY_CAST:
return F<OP_SPARSITY_CAST>::check;
1106 case OP_SUBREF:
return F<OP_SUBREF>::check;
1107 case OP_SUBASSIGN:
return F<OP_SUBASSIGN>::check;
1108 case OP_GETNONZEROS:
return F<OP_GETNONZEROS>::check;
1109 case OP_GETNONZEROS_PARAM:
return F<OP_GETNONZEROS_PARAM>::check;
1110 case OP_ADDNONZEROS:
return F<OP_ADDNONZEROS>::check;
1111 case OP_ADDNONZEROS_PARAM:
return F<OP_ADDNONZEROS>::check;
1112 case OP_SETNONZEROS:
return F<OP_SETNONZEROS>::check;
1113 case OP_SETNONZEROS_PARAM:
return F<OP_SETNONZEROS>::check;
1114 case OP_PROJECT:
return F<OP_PROJECT>::check;
1115 case OP_ASSERTION:
return F<OP_ASSERTION>::check;
1116 case OP_MONITOR:
return F<OP_MONITOR>::check;
1117 case OP_DUMP:
return F<OP_DUMP>::check;
1118 case OP_NORM2:
return F<OP_NORM2>::check;
1119 case OP_NORM1:
return F<OP_NORM1>::check;
1120 case OP_NORMINF:
return F<OP_NORMINF>::check;
1121 case OP_NORMF:
return F<OP_NORMF>::check;
1122 case OP_MMIN:
return F<OP_MMIN>::check;
1123 case OP_MMAX:
return F<OP_MMAX>::check;
1124 case OP_HORZREPMAT:
return F<OP_HORZREPMAT>::check;
1125 case OP_HORZREPSUM:
return F<OP_HORZREPSUM>::check;
1126 case OP_ERFINV:
return F<OP_ERFINV>::check;
1127 case OP_PRINTME:
return F<OP_PRINTME>::check;
1128 case OP_LIFT:
return F<OP_LIFT>::check;
1129 case OP_EINSTEIN:
return F<OP_EINSTEIN>::check;
1130 case OP_BSPLINE:
return F<OP_BSPLINE>::check;
1131 case OP_CONVEXIFY:
return F<OP_CONVEXIFY>::check;
1132 case OP_LOG1P:
return F<OP_LOG1P>::check;
1133 case OP_EXPM1:
return F<OP_EXPM1>::check;
1134 case OP_HYPOT:
return F<OP_HYPOT>::check;
1135 case OP_LOGSUMEXP:
return F<OP_LOGSUMEXP>::check;
1136 case OP_KRON:
return F<OP_KRON>::check;
1137 case OP_KRON_CONTRACT:
return F<OP_KRON_CONTRACT>::check;
1142 template<
template<casadi_
int>
class F>
1143 bool operation_checker(casadi_int op) {
1144 return operation_getter<F, bool>(op);
1148 template<
typename T>
1149 struct casadi_math {
1154 static inline void fun(
unsigned char op,
const T& x,
const T& y, T& f);
1159 static inline void fun(
unsigned char op,
const T* x,
const T* y, T* f, casadi_int n);
1164 static inline void fun(
unsigned char op,
const T* x,
const T& y, T* f, casadi_int n);
1169 static inline void fun(
unsigned char op,
const T& x,
const T* y, T* f, casadi_int n);
1174 static inline void der(
unsigned char op,
const T& x,
const T& y,
const T& f, T* d);
1179 static inline void derF(
unsigned char op,
const T& x,
const T& y, T& f, T* d);
1184 static inline void fun_linear(
unsigned char op,
const T*x,
const T* y, T* f);
1189 static inline bool is_binary(
unsigned char op);
1194 static inline bool is_unary(
unsigned char op);
1199 static inline casadi_int ndeps(
unsigned char op);
1204 static inline std::string print(
unsigned char op,
const std::string& x,
1205 const std::string& y);
1206 static inline std::string print(
unsigned char op,
const std::string& x);
1207 static inline std::string name(
unsigned char op);
1208 static inline std::string pre(
unsigned char op);
1209 static inline std::string sep(
unsigned char op);
1210 static inline std::string post(
unsigned char op);
1215 struct casadi_math<casadi_int>{
1220 static inline void fun(
unsigned char op,
const casadi_int& x,
1221 const casadi_int& y, casadi_int& f) {
1223 casadi_math<double>::fun(op,
static_cast<double>(x),
static_cast<double>(y), ff);
1224 f =
static_cast<casadi_int
>(ff);
1227 static inline void fun(
unsigned char op,
const casadi_int* x,
const casadi_int* y,
1228 casadi_int* f, casadi_int n) {
1229 for (casadi_int i=0; i<n; ++i) {
1231 casadi_math<double>::fun(op,
static_cast<double>(*x++),
static_cast<double>(*y++), ff);
1232 *f++ =
static_cast<casadi_int
>(ff);
1236 static inline void fun(
unsigned char op,
const casadi_int* x,
const casadi_int& y,
1237 casadi_int* f, casadi_int n) {
1238 for (casadi_int i=0; i<n; ++i) {
1240 casadi_math<double>::fun(op,
static_cast<double>(*x++),
static_cast<double>(y), ff);
1241 *f++ =
static_cast<casadi_int
>(ff);
1245 static inline void fun(
unsigned char op,
const casadi_int& x,
const casadi_int* y,
1246 casadi_int* f, casadi_int n) {
1247 for (casadi_int i=0; i<n; ++i) {
1249 casadi_math<double>::fun(op,
static_cast<double>(x),
static_cast<double>(*y++), ff);
1250 *f++ =
static_cast<casadi_int
>(ff);
1257 static inline void der(
unsigned char op,
const casadi_int& x,
const casadi_int& y,
1258 const casadi_int& f, casadi_int* d) {
1259 double d_real[2] = {
static_cast<double>(d[0]),
static_cast<double>(d[1])};
1260 casadi_math<double>::der(op,
static_cast<double>(x),
static_cast<double>(y),
1261 static_cast<double>(f), d_real);
1262 d[0] =
static_cast<casadi_int
>(d_real[0]);
1263 d[1] =
static_cast<casadi_int
>(d_real[1]);
1269 static inline void derF(
unsigned char op,
const casadi_int& x,
const casadi_int& y,
1270 casadi_int& f, casadi_int* d) {
1271 double d_real[2] = {
static_cast<double>(d[0]),
static_cast<double>(d[1])};
1272 double f_real =
static_cast<double>(f);
1273 casadi_math<double>::derF(op,
static_cast<double>(x),
static_cast<double>(y), f_real, d_real);
1274 f =
static_cast<casadi_int
>(f_real);
1275 d[0] =
static_cast<casadi_int
>(d_real[0]);
1276 d[1] =
static_cast<casadi_int
>(d_real[1]);
1282 static inline casadi_int ndeps(
unsigned char op) {
1283 return casadi_math<double>::ndeps(op);
1289 static inline std::string print(
unsigned char op,
const std::string& x,
1290 const std::string& y) {
1291 return casadi_math<double>::print(op, x, y);
1293 static inline std::string print(
unsigned char op,
const std::string& x) {
1294 return casadi_math<double>::print(op, x);
1296 static inline std::string pre(
unsigned char op) {
1297 return casadi_math<double>::pre(op);
1299 static inline std::string name(
unsigned char op) {
1300 return casadi_math<double>::name(op);
1302 static inline std::string sep(
unsigned char op) {
1303 return casadi_math<double>::sep(op);
1305 static inline std::string post(
unsigned char op) {
1306 return casadi_math<double>::post(op);
1312 template<
typename T>
1313 inline void casadi_math<T>::fun(
unsigned char op,
const T& x,
const T& y, T& f) {
1316 #define CASADI_MATH_FUN_BUILTIN_GEN(CNAME, X, Y, F, N) \
1317 case OP_ASSIGN: CNAME<OP_ASSIGN>::fcn(X, Y, F, N); break; \
1318 case OP_ADD: CNAME<OP_ADD>::fcn(X, Y, F, N); break; \
1319 case OP_SUB: CNAME<OP_SUB>::fcn(X, Y, F, N); break; \
1320 case OP_MUL: CNAME<OP_MUL>::fcn(X, Y, F, N); break; \
1321 case OP_DIV: CNAME<OP_DIV>::fcn(X, Y, F, N); break; \
1322 case OP_NEG: CNAME<OP_NEG>::fcn(X, Y, F, N); break; \
1323 case OP_EXP: CNAME<OP_EXP>::fcn(X, Y, F, N); break; \
1324 case OP_LOG: CNAME<OP_LOG>::fcn(X, Y, F, N); break; \
1325 case OP_POW: CNAME<OP_POW>::fcn(X, Y, F, N); break; \
1326 case OP_CONSTPOW: CNAME<OP_CONSTPOW>::fcn(X, Y, F, N); break; \
1327 case OP_SQRT: CNAME<OP_SQRT>::fcn(X, Y, F, N); break; \
1328 case OP_SQ: CNAME<OP_SQ>::fcn(X, Y, F, N); break; \
1329 case OP_TWICE: CNAME<OP_TWICE>::fcn(X, Y, F, N); break; \
1330 case OP_SIN: CNAME<OP_SIN>::fcn(X, Y, F, N); break; \
1331 case OP_COS: CNAME<OP_COS>::fcn(X, Y, F, N); break; \
1332 case OP_TAN: CNAME<OP_TAN>::fcn(X, Y, F, N); break; \
1333 case OP_ASIN: CNAME<OP_ASIN>::fcn(X, Y, F, N); break; \
1334 case OP_ACOS: CNAME<OP_ACOS>::fcn(X, Y, F, N); break; \
1335 case OP_ATAN: CNAME<OP_ATAN>::fcn(X, Y, F, N); break; \
1336 case OP_LT: CNAME<OP_LT>::fcn(X, Y, F, N); break; \
1337 case OP_LE: CNAME<OP_LE>::fcn(X, Y, F, N); break; \
1338 case OP_EQ: CNAME<OP_EQ>::fcn(X, Y, F, N); break; \
1339 case OP_NE: CNAME<OP_NE>::fcn(X, Y, F, N); break; \
1340 case OP_NOT: CNAME<OP_NOT>::fcn(X, Y, F, N); break; \
1341 case OP_AND: CNAME<OP_AND>::fcn(X, Y, F, N); break; \
1342 case OP_OR: CNAME<OP_OR>::fcn(X, Y, F, N); break; \
1343 case OP_IF_ELSE_ZERO: CNAME<OP_IF_ELSE_ZERO>::fcn(X, Y, F, N); break; \
1344 case OP_FLOOR: CNAME<OP_FLOOR>::fcn(X, Y, F, N); break; \
1345 case OP_CEIL: CNAME<OP_CEIL>::fcn(X, Y, F, N); break; \
1346 case OP_FMOD: CNAME<OP_FMOD>::fcn(X, Y, F, N); break; \
1347 case OP_REMAINDER: CNAME<OP_REMAINDER>::fcn(X, Y, F, N); break; \
1348 case OP_FABS: CNAME<OP_FABS>::fcn(X, Y, F, N); break; \
1349 case OP_SIGN: CNAME<OP_SIGN>::fcn(X, Y, F, N); break; \
1350 case OP_COPYSIGN: CNAME<OP_COPYSIGN>::fcn(X, Y, F, N); break; \
1351 case OP_ERF: CNAME<OP_ERF>::fcn(X, Y, F, N); break; \
1352 case OP_FMIN: CNAME<OP_FMIN>::fcn(X, Y, F, N); break; \
1353 case OP_FMAX: CNAME<OP_FMAX>::fcn(X, Y, F, N); break; \
1354 case OP_INV: CNAME<OP_INV>::fcn(X, Y, F, N); break; \
1355 case OP_SINH: CNAME<OP_SINH>::fcn(X, Y, F, N); break; \
1356 case OP_COSH: CNAME<OP_COSH>::fcn(X, Y, F, N); break; \
1357 case OP_TANH: CNAME<OP_TANH>::fcn(X, Y, F, N); break; \
1358 case OP_ASINH: CNAME<OP_ASINH>::fcn(X, Y, F, N); break; \
1359 case OP_ACOSH: CNAME<OP_ACOSH>::fcn(X, Y, F, N); break; \
1360 case OP_ATANH: CNAME<OP_ATANH>::fcn(X, Y, F, N); break; \
1361 case OP_ATAN2: CNAME<OP_ATAN2>::fcn(X, Y, F, N); break; \
1362 case OP_ERFINV: CNAME<OP_ERFINV>::fcn(X, Y, F, N); break; \
1363 case OP_LIFT: CNAME<OP_LIFT>::fcn(X, Y, F, N); break; \
1364 case OP_PRINTME: CNAME<OP_PRINTME>::fcn(X, Y, F, N); break; \
1365 case OP_LOG1P: CNAME<OP_LOG1P>::fcn(X, Y, F, N); break; \
1366 case OP_EXPM1: CNAME<OP_EXPM1>::fcn(X, Y, F, N); break; \
1367 case OP_HYPOT: CNAME<OP_HYPOT>::fcn(X, Y, F, N); break;
1369 #define CASADI_MATH_FUN_BUILTIN(X, Y, F) CASADI_MATH_FUN_BUILTIN_GEN(BinaryOperationSS, X, Y, F, 1)
1372 CASADI_MATH_FUN_BUILTIN(x, y, f)
1376 template<
typename T>
1377 inline void casadi_math<T>::fun(
unsigned char op,
const T* x,
const T* y, T* f, casadi_int n) {
1379 CASADI_MATH_FUN_BUILTIN_GEN(BinaryOperationVV, x, y, f, n)
1383 template<
typename T>
1384 inline void casadi_math<T>::fun(
unsigned char op,
const T* x,
const T& y, T* f, casadi_int n) {
1386 CASADI_MATH_FUN_BUILTIN_GEN(BinaryOperationVS, x, y, f, n)
1390 template<
typename T>
1391 inline void casadi_math<T>::fun(
unsigned char op,
const T& x,
const T* y, T* f, casadi_int n) {
1393 CASADI_MATH_FUN_BUILTIN_GEN(BinaryOperationSV, x, y, f, n)
1398 template<
typename T>
1399 inline void casadi_math<T>::der(
unsigned char op,
const T& x,
const T& y,
const T& f, T* d) {
1402 #define CASADI_MATH_DER_BUILTIN(X, Y, F, D) \
1403 case OP_ASSIGN: BinaryOperation<OP_ASSIGN>::der(X, Y, F, D); break; \
1404 case OP_ADD: BinaryOperation<OP_ADD>::der(X, Y, F, D); break; \
1405 case OP_SUB: BinaryOperation<OP_SUB>::der(X, Y, F, D); break; \
1406 case OP_MUL: BinaryOperation<OP_MUL>::der(X, Y, F, D); break; \
1407 case OP_DIV: BinaryOperation<OP_DIV>::der(X, Y, F, D); break; \
1408 case OP_NEG: BinaryOperation<OP_NEG>::der(X, Y, F, D); break; \
1409 case OP_EXP: BinaryOperation<OP_EXP>::der(X, Y, F, D); break; \
1410 case OP_LOG: BinaryOperation<OP_LOG>::der(X, Y, F, D); break; \
1411 case OP_POW: BinaryOperation<OP_POW>::der(X, Y, F, D); break; \
1412 case OP_CONSTPOW: BinaryOperation<OP_CONSTPOW>::der(X, Y, F, D); break; \
1413 case OP_SQRT: BinaryOperation<OP_SQRT>::der(X, Y, F, D); break; \
1414 case OP_SQ: BinaryOperation<OP_SQ>::der(X, Y, F, D); break; \
1415 case OP_TWICE: BinaryOperation<OP_TWICE>::der(X, Y, F, D); break; \
1416 case OP_SIN: BinaryOperation<OP_SIN>::der(X, Y, F, D); break; \
1417 case OP_COS: BinaryOperation<OP_COS>::der(X, Y, F, D); break; \
1418 case OP_TAN: BinaryOperation<OP_TAN>::der(X, Y, F, D); break; \
1419 case OP_ASIN: BinaryOperation<OP_ASIN>::der(X, Y, F, D); break; \
1420 case OP_ACOS: BinaryOperation<OP_ACOS>::der(X, Y, F, D); break; \
1421 case OP_ATAN: BinaryOperation<OP_ATAN>::der(X, Y, F, D); break; \
1422 case OP_LT: BinaryOperation<OP_LT>::der(X, Y, F, D); break; \
1423 case OP_LE: BinaryOperation<OP_LE>::der(X, Y, F, D); break; \
1424 case OP_EQ: BinaryOperation<OP_EQ>::der(X, Y, F, D); break; \
1425 case OP_NE: BinaryOperation<OP_NE>::der(X, Y, F, D); break; \
1426 case OP_NOT: BinaryOperation<OP_NOT>::der(X, Y, F, D); break; \
1427 case OP_AND: BinaryOperation<OP_AND>::der(X, Y, F, D); break; \
1428 case OP_OR: BinaryOperation<OP_OR>::der(X, Y, F, D); break; \
1429 case OP_IF_ELSE_ZERO: BinaryOperation<OP_IF_ELSE_ZERO>::der(X, Y, F, D); break; \
1430 case OP_FLOOR: BinaryOperation<OP_FLOOR>::der(X, Y, F, D); break; \
1431 case OP_CEIL: BinaryOperation<OP_CEIL>::der(X, Y, F, D); break; \
1432 case OP_FMOD: BinaryOperation<OP_FMOD>::der(X, Y, F, D); break; \
1433 case OP_REMAINDER: BinaryOperation<OP_REMAINDER>::der(X, Y, F, D); break; \
1434 case OP_FABS: BinaryOperation<OP_FABS>::der(X, Y, F, D); break; \
1435 case OP_SIGN: BinaryOperation<OP_SIGN>::der(X, Y, F, D); break; \
1436 case OP_COPYSIGN: BinaryOperation<OP_COPYSIGN>::der(X, Y, F, D); break; \
1437 case OP_ERF: BinaryOperation<OP_ERF>::der(X, Y, F, D); break; \
1438 case OP_FMIN: BinaryOperation<OP_FMIN>::der(X, Y, F, D); break; \
1439 case OP_FMAX: BinaryOperation<OP_FMAX>::der(X, Y, F, D); break; \
1440 case OP_INV: BinaryOperation<OP_INV>::der(X, Y, F, D); break; \
1441 case OP_SINH: BinaryOperation<OP_SINH>::der(X, Y, F, D); break; \
1442 case OP_COSH: BinaryOperation<OP_COSH>::der(X, Y, F, D); break; \
1443 case OP_TANH: BinaryOperation<OP_TANH>::der(X, Y, F, D); break; \
1444 case OP_ASINH: BinaryOperation<OP_ASINH>::der(X, Y, F, D); break; \
1445 case OP_ACOSH: BinaryOperation<OP_ACOSH>::der(X, Y, F, D); break; \
1446 case OP_ATANH: BinaryOperation<OP_ATANH>::der(X, Y, F, D); break; \
1447 case OP_ATAN2: BinaryOperation<OP_ATAN2>::der(X, Y, F, D); break; \
1448 case OP_ERFINV: BinaryOperation<OP_ERFINV>::der(X, Y, F, D); break; \
1449 case OP_LIFT: BinaryOperation<OP_LIFT>::der(X, Y, F, D); break; \
1450 case OP_PRINTME: BinaryOperation<OP_PRINTME>::der(X, Y, F, D); break; \
1451 case OP_LOG1P: BinaryOperation<OP_LOG1P>::der(X, Y, F, D); break; \
1452 case OP_EXPM1: BinaryOperation<OP_EXPM1>::der(X, Y, F, D); break; \
1453 case OP_HYPOT: BinaryOperation<OP_HYPOT>::der(X, Y, F, D); break;
1455 CASADI_MATH_DER_BUILTIN(x, y, f, d)
1460 template<
typename T>
1461 inline void casadi_math<T>::derF(
unsigned char op,
const T& x,
const T& y, T& f, T* d) {
1464 #define CASADI_MATH_DERF_BUILTIN(X, Y, F, D) \
1465 case OP_ASSIGN: DerBinaryOperation<OP_ASSIGN>::derf(X, Y, F, D); break; \
1466 case OP_ADD: DerBinaryOperation<OP_ADD>::derf(X, Y, F, D); break; \
1467 case OP_SUB: DerBinaryOperation<OP_SUB>::derf(X, Y, F, D); break; \
1468 case OP_MUL: DerBinaryOperation<OP_MUL>::derf(X, Y, F, D); break; \
1469 case OP_DIV: DerBinaryOperation<OP_DIV>::derf(X, Y, F, D); break; \
1470 case OP_NEG: DerBinaryOperation<OP_NEG>::derf(X, Y, F, D); break; \
1471 case OP_EXP: DerBinaryOperation<OP_EXP>::derf(X, Y, F, D); break; \
1472 case OP_LOG: DerBinaryOperation<OP_LOG>::derf(X, Y, F, D); break; \
1473 case OP_POW: DerBinaryOperation<OP_POW>::derf(X, Y, F, D); break; \
1474 case OP_CONSTPOW: DerBinaryOperation<OP_CONSTPOW>::derf(X, Y, F, D); break; \
1475 case OP_SQRT: DerBinaryOperation<OP_SQRT>::derf(X, Y, F, D); break; \
1476 case OP_SQ: DerBinaryOperation<OP_SQ>::derf(X, Y, F, D); break; \
1477 case OP_TWICE: DerBinaryOperation<OP_TWICE>::derf(X, Y, F, D); break; \
1478 case OP_SIN: DerBinaryOperation<OP_SIN>::derf(X, Y, F, D); break; \
1479 case OP_COS: DerBinaryOperation<OP_COS>::derf(X, Y, F, D); break; \
1480 case OP_TAN: DerBinaryOperation<OP_TAN>::derf(X, Y, F, D); break; \
1481 case OP_ASIN: DerBinaryOperation<OP_ASIN>::derf(X, Y, F, D); break; \
1482 case OP_ACOS: DerBinaryOperation<OP_ACOS>::derf(X, Y, F, D); break; \
1483 case OP_ATAN: DerBinaryOperation<OP_ATAN>::derf(X, Y, F, D); break; \
1484 case OP_LT: DerBinaryOperation<OP_LT>::derf(X, Y, F, D); break; \
1485 case OP_LE: DerBinaryOperation<OP_LE>::derf(X, Y, F, D); break; \
1486 case OP_EQ: DerBinaryOperation<OP_EQ>::derf(X, Y, F, D); break; \
1487 case OP_NE: DerBinaryOperation<OP_NE>::derf(X, Y, F, D); break; \
1488 case OP_NOT: DerBinaryOperation<OP_NOT>::derf(X, Y, F, D); break; \
1489 case OP_AND: DerBinaryOperation<OP_AND>::derf(X, Y, F, D); break; \
1490 case OP_OR: DerBinaryOperation<OP_OR>::derf(X, Y, F, D); break; \
1491 case OP_IF_ELSE_ZERO: DerBinaryOperation<OP_IF_ELSE_ZERO>::derf(X, Y, F, D); break; \
1492 case OP_FLOOR: DerBinaryOperation<OP_FLOOR>::derf(X, Y, F, D); break; \
1493 case OP_CEIL: DerBinaryOperation<OP_CEIL>::derf(X, Y, F, D); break; \
1494 case OP_FMOD: DerBinaryOperation<OP_FMOD>::derf(X, Y, F, D); break; \
1495 case OP_REMAINDER: DerBinaryOperation<OP_REMAINDER>::derf(X, Y, F, D); break; \
1496 case OP_FABS: DerBinaryOperation<OP_FABS>::derf(X, Y, F, D); break; \
1497 case OP_SIGN: DerBinaryOperation<OP_SIGN>::derf(X, Y, F, D); break; \
1498 case OP_COPYSIGN: DerBinaryOperation<OP_COPYSIGN>::derf(X, Y, F, D); break; \
1499 case OP_ERF: DerBinaryOperation<OP_ERF>::derf(X, Y, F, D); break; \
1500 case OP_FMIN: DerBinaryOperation<OP_FMIN>::derf(X, Y, F, D); break; \
1501 case OP_FMAX: DerBinaryOperation<OP_FMAX>::derf(X, Y, F, D); break; \
1502 case OP_INV: DerBinaryOperation<OP_INV>::derf(X, Y, F, D); break; \
1503 case OP_SINH: DerBinaryOperation<OP_SINH>::derf(X, Y, F, D); break; \
1504 case OP_COSH: DerBinaryOperation<OP_COSH>::derf(X, Y, F, D); break; \
1505 case OP_TANH: DerBinaryOperation<OP_TANH>::derf(X, Y, F, D); break; \
1506 case OP_ASINH: DerBinaryOperation<OP_ASINH>::derf(X, Y, F, D); break; \
1507 case OP_ACOSH: DerBinaryOperation<OP_ACOSH>::derf(X, Y, F, D); break; \
1508 case OP_ATANH: DerBinaryOperation<OP_ATANH>::derf(X, Y, F, D); break; \
1509 case OP_ATAN2: DerBinaryOperation<OP_ATAN2>::derf(X, Y, F, D); break; \
1510 case OP_ERFINV: DerBinaryOperation<OP_ERFINV>::derf(X, Y, F, D); break; \
1511 case OP_LIFT: DerBinaryOperation<OP_LIFT>::derf(X, Y, F, D); break; \
1512 case OP_PRINTME: DerBinaryOperation<OP_PRINTME>::derf(X, Y, F, D); break; \
1513 case OP_LOG1P: DerBinaryOperation<OP_LOG1P>::derf(X, Y, F, D); break; \
1514 case OP_EXPM1: DerBinaryOperation<OP_EXPM1>::derf(X, Y, F, D); break; \
1515 case OP_HYPOT: DerBinaryOperation<OP_HYPOT>::derf(X, Y, F, D); break;
1517 CASADI_MATH_DERF_BUILTIN(x, y, f, d)
1521 #define CASADI_MATH_BINARY_BUILTIN \
1536 case OP_REMAINDER: \
1544 #define CASADI_MATH_UNARY_BUILTIN \
1575 template<
typename T>
1576 inline void casadi_math<T>::fun_linear(
unsigned char op,
const T* x,
const T* y, T* f) {
1577 if (op==OP_ADD || op==OP_SUB) {
1578 for (
int i=0;i<3;++i) {
1579 f[i] = T::binary(op, x[i], y[i]);
1581 }
else if (op==OP_TWICE || op==OP_NEG) {
1582 for (
int i=0;i<3;++i) {
1583 f[i] = T::unary(op, x[i]);
1585 }
else if (op==OP_MUL) {
1595 }
else if (op==OP_DIV) {
1596 bool const_argy = y[1].is_zero() && y[2].is_zero();
1602 f[2] = (x[0]+x[1]+x[2])/(y[0]+y[1]+y[2]);
1604 }
else if (casadi_math<T>::is_unary(op)) {
1605 bool const_arg = x[1].is_zero() && x[2].is_zero();
1607 f[0] = T::unary(op, x[0]);
1609 f[2] = T::unary(op, x[0]+x[1]+x[2]);
1612 }
else if (casadi_math<T>::is_binary(op)) {
1613 bool const_argx = x[1].is_zero() && x[2].is_zero();
1614 bool const_argy = y[1].is_zero() && y[2].is_zero();
1615 if (const_argx && const_argy) {
1616 f[0] = T::binary(op, x[0], y[0]);
1618 f[2] = T::binary(op, x[0]+x[1]+x[2], y[0]+y[1]+y[2]);
1621 casadi_error(
"Not implemented");
1625 template<
typename T>
1626 bool casadi_math<T>::is_binary(
unsigned char op) {
1628 CASADI_MATH_BINARY_BUILTIN
1629 case OP_IF_ELSE_ZERO:
1636 template<
typename T>
1637 bool casadi_math<T>::is_unary(
unsigned char op) {
1639 CASADI_MATH_UNARY_BUILTIN
1646 template<
typename T>
1647 inline casadi_int casadi_math<T>::ndeps(
unsigned char op) {
1653 CASADI_MATH_BINARY_BUILTIN
1654 case OP_IF_ELSE_ZERO:
1663 template<
typename T>
1665 casadi_math<T>::print(
unsigned char op,
1666 const std::string& x,
const std::string& y) {
1667 casadi_assert_dev(ndeps(op)==2);
1668 return pre(op) + x + sep(op) + y + post(op);
1671 template<
typename T>
1673 casadi_math<T>::print(
unsigned char op,
const std::string& x) {
1674 casadi_assert_dev(ndeps(op)==1);
1675 return pre(op) + x + post(op);
1678 template<
typename T>
1679 inline std::string casadi_math<T>::name(
unsigned char op) {
1681 case OP_ASSIGN:
return "assign";
1682 case OP_ADD:
return "add";
1683 case OP_SUB:
return "sub";
1684 case OP_MUL:
return "mul";
1685 case OP_DIV:
return "div";
1686 case OP_NEG:
return "neg";
1687 case OP_EXP:
return "exp";
1688 case OP_LOG:
return "log";
1690 case OP_POW:
return "pow";
1691 case OP_SQRT:
return "sqrt";
1692 case OP_SQ:
return "sq";
1693 case OP_TWICE:
return "twice";
1694 case OP_SIN:
return "sin";
1695 case OP_COS:
return "cos";
1696 case OP_TAN:
return "tan";
1697 case OP_ASIN:
return "asin";
1698 case OP_ACOS:
return "acos";
1699 case OP_ATAN:
return "atan";
1700 case OP_LT:
return "lt";
1701 case OP_LE:
return "le";
1702 case OP_EQ:
return "eq";
1703 case OP_NE:
return "ne";
1704 case OP_NOT:
return "not";
1705 case OP_AND:
return "and";
1706 case OP_OR:
return "or";
1707 case OP_FLOOR:
return "floor";
1708 case OP_CEIL:
return "ceil";
1709 case OP_FMOD:
return "fmod";
1710 case OP_REMAINDER:
return "remainder";
1711 case OP_FABS:
return "fabs";
1712 case OP_SIGN:
return "sign";
1713 case OP_COPYSIGN:
return "copysign";
1714 case OP_IF_ELSE_ZERO:
return "if_else_zero";
1715 case OP_ERF:
return "erf";
1716 case OP_FMIN:
return "fmin";
1717 case OP_FMAX:
return "fmax";
1718 case OP_INV:
return "inv";
1719 case OP_SINH:
return "sinh";
1720 case OP_COSH:
return "cosh";
1721 case OP_TANH:
return "tanh";
1722 case OP_ASINH:
return "asinh";
1723 case OP_ACOSH:
return "acosh";
1724 case OP_ATANH:
return "atanh";
1725 case OP_ATAN2:
return "atan2";
1726 case OP_CONST:
return "const";
1727 case OP_INPUT:
return "input";
1728 case OP_OUTPUT:
return "output";
1729 case OP_PARAMETER:
return "parameter";
1730 case OP_CALL:
return "call";
1731 case OP_MTIMES:
return "mtimes";
1732 case OP_SOLVE:
return "solve";
1733 case OP_TRANSPOSE:
return "transpose";
1734 case OP_DETERMINANT:
return "determinant";
1735 case OP_INVERSE:
return "inverse";
1736 case OP_DOT:
return "dot";
1737 case OP_HORZCAT:
return "horzcat";
1738 case OP_VERTCAT:
return "vertcat";
1739 case OP_DIAGCAT:
return "diagcat";
1740 case OP_HORZSPLIT:
return "horzsplit";
1741 case OP_VERTSPLIT:
return "vertsplit";
1742 case OP_DIAGSPLIT:
return "diagsplit";
1743 case OP_RESHAPE:
return "reshape";
1744 case OP_SPARSITY_CAST:
return "sparsity_cast";
1745 case OP_SUBREF:
return "subref";
1746 case OP_SUBASSIGN:
return "subassign";
1747 case OP_GETNONZEROS:
return "getnonzeros";
1748 case OP_GETNONZEROS_PARAM:
return "getnonzeros_param";
1749 case OP_ADDNONZEROS:
return "addnonzeros";
1750 case OP_ADDNONZEROS_PARAM:
return "addnonzeros_param";
1751 case OP_SETNONZEROS:
return "setnonzeros";
1752 case OP_SETNONZEROS_PARAM:
return "setnonzeros_param";
1753 case OP_PROJECT:
return "project";
1754 case OP_ASSERTION:
return "assertion";
1755 case OP_NORM2:
return "norm2";
1756 case OP_NORM1:
return "norm1";
1757 case OP_NORMINF:
return "norminf";
1758 case OP_NORMF:
return "normf";
1759 case OP_ERFINV:
return "erfinv";
1760 case OP_PRINTME:
return "printme";
1761 case OP_LIFT:
return "lift";
1762 case OP_EINSTEIN:
return "einstein";
1763 case OP_BSPLINE:
return "bspline";
1764 case OP_CONVEXIFY:
return "convexify";
1765 case OP_LOG1P:
return "log1p";
1766 case OP_EXPM1:
return "expm1";
1767 case OP_HYPOT:
return "hypot";
1768 case OP_LOGSUMEXP:
return "logsumexp";
1769 case OP_KRON:
return "kron";
1770 case OP_KRON_CONTRACT:
return "kron_contract";
1772 return "<invalid-op>";
1775 template<
typename T>
1776 inline std::string casadi_math<T>::pre(
unsigned char op) {
1778 case OP_ASSIGN:
return "";
1779 case OP_ADD:
return "(";
1780 case OP_SUB:
return "(";
1781 case OP_MUL:
return "(";
1782 case OP_DIV:
return "(";
1783 case OP_NEG:
return "(-";
1784 case OP_TWICE:
return "(2.*";
1785 case OP_LT:
return "(";
1786 case OP_LE:
return "(";
1787 case OP_EQ:
return "(";
1788 case OP_NE:
return "(";
1789 case OP_NOT:
return "(!";
1790 case OP_AND:
return "(";
1791 case OP_OR:
return "(";
1792 case OP_IF_ELSE_ZERO:
return "(";
1793 case OP_INV:
return "(1./";
1794 default:
return name(op) +
"(";
1798 template<
typename T>
1799 inline std::string casadi_math<T>::sep(
unsigned char op) {
1801 case OP_ADD:
return "+";
1802 case OP_SUB:
return "-";
1803 case OP_MUL:
return "*";
1804 case OP_DIV:
return "/";
1805 case OP_LT:
return "<";
1806 case OP_LE:
return "<=";
1807 case OP_EQ:
return "==";
1808 case OP_NE:
return "!=";
1809 case OP_AND:
return "&&";
1810 case OP_OR:
return "||";
1811 case OP_IF_ELSE_ZERO:
return "?";
1812 default:
return ",";
1816 template<
typename T>
1817 inline std::string casadi_math<T>::post(
unsigned char op) {
1819 case OP_ASSIGN:
return "";
1820 case OP_IF_ELSE_ZERO:
return ":0)";
1821 default:
return ")";
1826 template<
class T,
typename SU>
1827 T common_simp_unary(casadi_int op,
const T& x, casadi_int depth,
1834 if (x.is_op(OP_MUL) && x.dep(0).is_constant() &&
1837 else if (x.is_op(OP_MUL) && x.dep(1).is_constant() &&
1842 if (x.is_op(OP_SQRT))
1844 else if (x.is_op(OP_NEG))
1846 else if (x.is_op(OP_FABS))
1850 if (x.is_nonnegative())
1852 else if (x.is_op(OP_NEG))
1853 return fabs(x.dep());
1856 if (x.is_op(OP_EXP))
1860 if (x.is_op(OP_INV))
1865 return fabs(x.dep());
1868 if (x.is_op(OP_NEG))
1869 return cos(x.dep());
1870 else if (x.is_op(OP_FABS))
1871 return cos(x.dep());
1874 if (x.is_op(OP_NEG))
1876 else if (unique && x.is_op(OP_SUB))
1877 return x.dep(1) - x.dep(0);
1886 bool is_ineq(
const T& x) {
1887 return x.is_op(OP_LE) || x.is_op(OP_LT);
1890 template<
class T,
typename SU,
typename SB>
1891 T common_simp_binary(casadi_int op,
const T& x,
const T& y, casadi_int depth,
1902 else if (y->is_zero())
1904 else if (y.is_op(OP_NEG))
1906 else if (x.is_op(OP_NEG))
1908 else if (is_equal(x, y, depth))
1910 else if (x.is_op(OP_MUL) && y.is_op(OP_MUL) &&
1911 x.dep(0).is_constant() &&
static_cast<double>(x.dep(0))==0.5 &&
1912 y.dep(0).is_constant() &&
static_cast<double>(y.dep(0))==0.5 &&
1913 is_equal(y.dep(1), x.dep(1), depth))
1915 else if (x.is_op(OP_DIV) && y.is_op(OP_DIV) &&
1916 x.dep(1).is_constant() &&
static_cast<double>(x.dep(1))==2 &&
1917 y.dep(1).is_constant() &&
static_cast<double>(y.dep(1))==2 &&
1918 is_equal(y.dep(0), x.dep(0), depth))
1920 else if (x.is_op(OP_MUL) && y.is_op(OP_MUL) &&
1921 x.dep(0).is_constant() && y.dep(0).is_constant() &&
1922 static_cast<double>(x.dep(0))+
static_cast<double>(y.dep(0))==1 &&
1923 is_equal(y.dep(1), x.dep(1), depth)
1926 else if (x.is_op(OP_SUB) && is_equal(x.dep(1), y, depth))
1928 else if (y.is_op(OP_SUB) && is_equal(x, y.dep(1), depth))
1930 else if (x.is_op(OP_SQ) && y.is_op(OP_SQ) &&
1931 ((x.dep().is_op(OP_SIN) && y.dep().is_op(OP_COS))
1932 || (x.dep().is_op(OP_COS) && y.dep().is_op(OP_SIN)))
1933 && is_equal(x.dep().dep(), y.dep().dep(), depth))
1935 else if (x.is_doubled() && is_equal(x.dep(0), y, depth))
1937 else if (y.is_doubled() && is_equal(y.dep(0), x, depth))
1939 else if (x.is_op(OP_MUL) && y.is_op(OP_MUL) &&
1940 is_equal(x.dep(0), y.dep(0), depth) && (x.dep(1)+y.dep(1)).is_one())
1948 if (is_equal(x, y, depth))
1950 else if (y.is_op(OP_NEG))
1952 else if (x.is_op(OP_ADD) && is_equal(x.dep(1), y, depth))
1954 else if (x.is_op(OP_ADD) && is_equal(x.dep(0), y, depth))
1956 else if (y.is_op(OP_ADD) && is_equal(x, y.dep(1), depth))
1958 else if (y.is_op(OP_ADD) && is_equal(x, y.dep(0), depth))
1960 else if (x.is_op(OP_NEG))
1961 return -(x.dep() + y);
1962 else if (x.is_op(OP_MUL) && y.is_op(OP_MUL) &&
1963 x.dep(0).is_constant() && y.dep(0).is_constant() &&
1964 static_cast<double>(x.dep(0))-
static_cast<double>(y.dep(0))==1 &&
1965 is_equal(y.dep(1), x.dep(1), depth)
1968 else if (x.is_doubled() && is_equal(x.dep(0), y, depth))
1970 else if (y.is_doubled() && is_equal(y.dep(0), x, depth))
1974 if (is_equal(y, x, depth))
1976 else if (!x.is_constant() && y.is_constant())
1978 else if (x.is_zero() || y->is_zero())
1980 else if (x.is_one())
1982 else if (y.is_one())
1984 else if (y.is_minus_one())
1986 else if (x.is_minus_one())
1988 else if (y.is_op(OP_INV))
1990 else if (x.is_op(OP_INV))
1992 else if (x.is_constant() && y.is_op(OP_MUL) && y.dep(0).is_constant() &&
1993 static_cast<double>(x)*
static_cast<double>(y.dep(0))==1)
1995 else if (x.is_constant() && y.is_doubled() &&
1996 static_cast<double>(x)*2==1)
1998 else if (x.is_constant() && y.is_op(OP_DIV) && y.dep(1).is_constant() &&
1999 static_cast<double>(x)==
static_cast<double>(y.dep(1)))
2001 else if (x.is_constant() &&
static_cast<double>(x)==2)
2002 return gen_unary(OP_TWICE, y);
2003 else if (y.is_constant() &&
static_cast<double>(y)==2)
2004 return gen_unary(OP_TWICE, x);
2005 else if (x.is_op(OP_DIV) && is_equal(x.dep(1), y, depth))
2007 else if (y.is_op(OP_DIV) &&
2008 is_equal(y.dep(1), x, depth))
2010 else if (x.is_op(OP_NEG))
2011 return -(x.dep() * y);
2012 else if (y.is_op(OP_NEG))
2013 return -(x * y.dep());
2014 else if (unique_x && x.is_op(OP_ADD) && x.dep(1).is_op(OP_DIV) &&
2015 is_equal(x.dep(1).dep(1), y, depth))
2016 return x.dep(0)*y + x.dep(1).dep(0);
2017 else if (unique_x && x.is_op(OP_ADD) && x.dep(0).is_op(OP_DIV) &&
2018 is_equal(x.dep(0).dep(1), y, depth))
2019 return x.dep(0).dep(0)+x.dep(1)*y;
2020 else if (unique_y && y.is_op(OP_ADD) && y.dep(1).is_op(OP_DIV) &&
2021 is_equal(y.dep(1).dep(1), x, depth))
2022 return x*y.dep(0) + y.dep(1).dep(0);
2023 else if (unique_y && y.is_op(OP_ADD) && y.dep(0).is_op(OP_DIV) &&
2024 is_equal(y.dep(0).dep(1), x, depth))
2025 return y.dep(0).dep(0) + x*y.dep(1);
2026 else if (unique_x && x.is_op(OP_SUB) && x.dep(1).is_op(OP_DIV) &&
2027 is_equal(x.dep(1).dep(1), y, depth))
2028 return x.dep(0)*y - x.dep(1).dep(0);
2029 else if (unique_x && x.is_op(OP_SUB) && x.dep(0).is_op(OP_DIV) &&
2030 is_equal(x.dep(0).dep(1), y, depth))
2031 return x.dep(0).dep(0)-x.dep(1)*y;
2032 else if (unique_y && y.is_op(OP_SUB) && y.dep(1).is_op(OP_DIV) &&
2033 is_equal(y.dep(1).dep(1), x, depth))
2034 return x*y.dep(0) - y.dep(1).dep(0);
2035 else if (unique_y && y.is_op(OP_SUB) && y.dep(0).is_op(OP_DIV) &&
2036 is_equal(y.dep(0).dep(1), x, depth))
2037 return y.dep(0).dep(0) - x*y.dep(1);
2038 else if (x.is_constant() && y.is_op(OP_MUL) && y.dep(0).is_constant())
2039 return x*y.dep(0)*y.dep(1);
2040 else if (y.is_constant() && x.is_op(OP_MUL) && x.dep(0).is_constant())
2041 return y*x.dep(0)*x.dep(1);
2045 return std::numeric_limits<double>::infinity();
2046 else if (x.is_zero())
2048 else if (y.is_one())
2050 else if (y.is_minus_one())
2052 else if (y.is_half())
2054 else if (is_equal(x, y, depth))
2056 else if (x.is_doubled() && y.is_constant() &&
static_cast<double>(y)==2)
2058 else if (x.is_doubled() && is_equal(y, x.dep(0), depth))
2060 else if (x.is_op(OP_MUL) && is_equal(y, x.dep(0), depth))
2062 else if (x.is_op(OP_MUL) && is_equal(y, x.dep(1), depth))
2064 else if (x.is_one())
2066 else if (y.is_op(OP_INV))
2068 else if (x.is_doubled() && y.is_doubled())
2069 return x.dep(0) / y->dep(0);
2070 else if (y.is_constant() && x.is_op(OP_DIV) && x.dep(1).is_constant() &&
2071 static_cast<double>(y)*
static_cast<double>(x.dep(1))==1)
2073 else if (y.is_op(OP_MUL) &&
2074 is_equal(y.dep(1), x, depth))
2076 else if (y.is_doubled() &&
2077 is_equal(y.dep(0), x, depth))
2079 else if (x.is_op(OP_NEG) &&
2080 is_equal(x.dep(0), y, depth))
2082 else if (y.is_op(OP_NEG) &&
2083 is_equal(y.dep(0), x, depth))
2085 else if (y.is_op(OP_NEG) && x.is_op(OP_NEG) &&
2086 is_equal(x.dep(0), y.dep(0), depth))
2088 else if (x.is_op(OP_DIV) && is_equal(y, x.dep(0), depth))
2089 return x.dep(1).inv();
2090 else if (x.is_op(OP_NEG))
2091 return -(x.dep() / y);
2092 else if (y.is_op(OP_NEG))
2093 return -(x / y.dep());
2096 if (y.is_constant()) {
2097 if (y.is_integer()) {
2098 casadi_int nn = y->to_int();
2101 }
else if (nn>100 || nn<-100) {
2102 return gen_binary(OP_CONSTPOW, x, nn);
2104 return 1/pow(x, -nn);
2105 }
else if (nn%2 == 1) {
2106 return x*pow(x, nn-1);
2108 T rt = pow(x,
static_cast<casadi_int
>(nn/2));
2111 }
else if (y->to_double()==0.5) {
2114 return gen_binary(OP_CONSTPOW, x, y);
2120 if (!unique_x && !unique_y && (is_ineq(x) || is_ineq(y)))
break;
2121 if ((y-x).is_nonnegative())
2125 if (x.is_inf())
return y;
2126 if (y.is_inf())
return x;
2127 if (x.is_minus_inf() || y.is_minus_inf())
return -std::numeric_limits<double>::infinity();
2128 if (is_equal(x, y, depth))
return x;
2131 if (x.is_minus_inf())
return y;
2132 if (y.is_minus_inf())
return x;
2133 if (x.is_inf() || y.is_inf())
return std::numeric_limits<double>::infinity();
2134 if (is_equal(x, y, depth))
return x;
2137 if (!unique_x && !unique_y && (is_ineq(x) || is_ineq(y)))
break;
2138 if (((x)-y).is_nonnegative())
2142 if (is_equal(x, y, depth))
2146 if (is_equal(x, y, depth))
2149 case OP_IF_ELSE_ZERO:
2152 }
else if (x.is_constant()) {
2153 if (
static_cast<double>(x)!=0) {
CASADI_EXPORT std::ostream & uout()