| 841 | } |
| 842 | |
| 843 | MX MXNode::_get_binary(casadi_int op, const MX& y, bool scX, bool scY) const { |
| 844 | casadi_assert_dev(sparsity()==y.sparsity() || scX || scY); |
| 845 | |
| 846 | if (GlobalOptions::simplification_on_the_fly) { |
| 847 | |
| 848 | // If identically zero due to one argument being zero |
| 849 | if ((operation_checker<F0XChecker>(op) && nnz()==0) || |
| 850 | (operation_checker<FX0Checker>(op) && y->nnz()==0)) { |
| 851 | return MX::zeros(Sparsity(size())); |
| 852 | } |
| 853 | |
| 854 | if ((operation_checker<F0XChecker>(op) && is_zero()) || |
| 855 | (operation_checker<FX0Checker>(op) && y->is_zero())) { |
| 856 | return MX::zeros(sparsity()); |
| 857 | } |
| 858 | |
| 859 | // Handle special operations (independent of type) |
| 860 | switch (op) { |
| 861 | case OP_ADD: |
| 862 | if (MXNode::is_equal(y.get(), this, maxDepth())) return get_unary(OP_TWICE); |
| 863 | break; |
| 864 | case OP_SUB: |
| 865 | case OP_NE: |
| 866 | case OP_LT: |
| 867 | if (MXNode::is_equal(y.get(), this, maxDepth())) return MX::zeros(sparsity()); |
| 868 | break; |
| 869 | case OP_DIV: |
| 870 | if (y->is_zero()) return MX::nan(sparsity()); |
| 871 | // fall-through |
| 872 | case OP_EQ: |
| 873 | case OP_LE: |
| 874 | if (MXNode::is_equal(y.get(), this, maxDepth())) return MX::ones(sparsity()); |
| 875 | break; |
| 876 | case OP_MUL: |
| 877 | if (MXNode::is_equal(y.get(), this, maxDepth())) return get_unary(OP_SQ); |
| 878 | break; |
| 879 | default: break; // no rule |
| 880 | } |
| 881 | |
| 882 | // Handle special cases for the second argument |
| 883 | switch (y->op()) { |
| 884 | case OP_CONST: |
| 885 | // Make the constant the first argument, if possible |
| 886 | if (this->op()!=OP_CONST && operation_checker<CommChecker>(op)) { |
| 887 | return y->_get_binary(op, shared_from_this<MX>(), scY, scX); |
| 888 | } else { |
| 889 | switch (op) { |
| 890 | case OP_POW: |
| 891 | return _get_binary(OP_CONSTPOW, y, scX, scY); |
| 892 | case OP_CONSTPOW: |
| 893 | if (y->is_value(-1)) return get_unary(OP_INV); |
| 894 | else if (y->is_value(0)) return MX::ones(size()); |
| 895 | else if (y->is_value(1)) return shared_from_this<MX>(); |
| 896 | else if (y->is_value(2)) return get_unary(OP_SQ); |
| 897 | break; |
| 898 | case OP_ADD: |
| 899 | case OP_SUB: |
| 900 | if (y->is_zero()) |