constant_mx.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_CONSTANT_MX_HPP
27 #define CASADI_CONSTANT_MX_HPP
28 
29 #include "mx_node.hpp"
30 #include <iomanip>
31 #include <iostream>
32 #include "serializing_stream.hpp"
33 
35 
36 namespace casadi {
37 
48  class CASADI_EXPORT ConstantMX : public MXNode {
49  public:
51  explicit ConstantMX(const Sparsity& sp);
52 
54  ~ConstantMX() override = 0;
55 
56  // Creator (all values are the same integer)
57  static ConstantMX* create(const Sparsity& sp, casadi_int val);
58  static ConstantMX* create(const Sparsity& sp, int val) {
59  return create(sp, static_cast<casadi_int>(val));
60  }
61 
62  // Creator (all values are the same floating point value)
63  static ConstantMX* create(const Sparsity& sp, double val);
64 
65  // Creator (values may be different)
66  static ConstantMX* create(const Matrix<double>& val);
67 
68  // Creator (values may be different)
69  static ConstantMX* create(const Sparsity& sp, const std::string& fname);
70 
71  // Creator (values may be different)
72  static ConstantMX* create(const Matrix<double>& val, const std::string& name);
73 
75  int eval(const double** arg, double** res, casadi_int* iw, double* w) const override = 0;
76 
78  int eval_sx(const SXElem** arg, SXElem** res,
79  casadi_int* iw, SXElem* w) const override = 0;
80 
84  void eval_mx(const std::vector<MX>& arg, std::vector<MX>& res,
85  const std::vector<bool>& unique={}) const override;
86 
90  void ad_forward(const std::vector<std::vector<MX> >& fseed,
91  std::vector<std::vector<MX> >& fsens) const override;
92 
96  void ad_reverse(const std::vector<std::vector<MX> >& aseed,
97  std::vector<std::vector<MX> >& asens) const override;
98 
102  int sp_forward(const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const override;
103 
107  int eval_activity(const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const override;
108 
112  void nonzeros_to_activity(const double* v, bvec_t* res) const;
113 
117  int sp_reverse(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const override;
118 
122  casadi_int op() const override { return OP_CONST;}
123 
125  double to_double() const override = 0;
126 
128  casadi_int to_int() const override = 0;
129 
131  Matrix<double> get_DM() const override = 0;
132 
134  // virtual MX get_mac(const MX& y) const;
135 
137  MX get_dot(const MX& y) const override;
138 
140  bool __nonzero__() const override;
141 
145  bool is_valid_input() const override;
146 
150  casadi_int n_primitives() const override;
151 
155  void primitives(std::vector<MX>::iterator& it) const override;
156 
158  template<typename T>
159  void split_primitives_gen(const T& x, typename std::vector<T>::iterator& it) const;
160 
162 
165  void split_primitives(const MX& x, std::vector<MX>::iterator& it) const override;
166  void split_primitives(const SX& x, std::vector<SX>::iterator& it) const override;
167  void split_primitives(const DM& x, std::vector<DM>::iterator& it) const override;
169 
171  template<typename T>
172  T join_primitives_gen(typename std::vector<T>::const_iterator& it) const;
173 
175 
178  MX join_primitives(std::vector<MX>::const_iterator& it) const override;
179  SX join_primitives(std::vector<SX>::const_iterator& it) const override;
180  DM join_primitives(std::vector<DM>::const_iterator& it) const override;
182 
186  bool has_duplicates() const override { return false;}
187 
191  void reset_input() const override {}
192 
196  static MXNode* deserialize(DeserializingStream& s);
197 
201  explicit ConstantMX(DeserializingStream& s) : MXNode(s) {}
202  };
203 
205  class CASADI_EXPORT ConstantDM : public ConstantMX {
206  public:
207 
211  explicit ConstantDM(const Matrix<double>& x) : ConstantMX(x.sparsity()), x_(x) {}
212 
214  ~ConstantDM() override {}
215 
219  std::string disp(const std::vector<std::string>& arg) const override {
220  return x_.get_str();
221  }
222 
226  int eval(const double** arg, double** res, casadi_int* iw, double* w) const override {
227  std::copy(x_->begin(), x_->end(), res[0]);
228  return 0;
229  }
230 
234  int eval_sx(const SXElem** arg, SXElem** res,
235  casadi_int* iw, SXElem* w) const override {
236  std::copy(x_->begin(), x_->end(), res[0]);
237  return 0;
238  }
239 
243  void generate(CodeGenerator& g,
244  const std::vector<casadi_int>& arg,
245  const std::vector<casadi_int>& res,
246  const std::vector<bool>& arg_is_ref,
247  std::vector<bool>& res_is_ref) const override;
248 
252  bool is_zero() const override;
253  bool is_one() const override;
254  bool is_minus_one() const override;
255  bool is_inf() const override;
256  bool is_minus_inf() const override;
257  bool is_half() const override;
258  bool is_value(double val) const override;
259  bool is_nonnegative() const override;
260  bool is_integer() const override;
261  bool is_eye() const override;
262 
264  double to_double() const override {return x_.scalar();}
265 
267  casadi_int to_int() const override {return static_cast<casadi_int>(x_.scalar());}
268 
270  Matrix<double> get_DM() const override { return x_;}
271 
275  int eval_activity(const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const override {
276  nonzeros_to_activity(x_->data(), res[0]);
277  return 0;
278  }
279 
283  bool is_equal(const MXNode* node, casadi_int depth) const override;
284 
288  Matrix<double> x_;
289 
293  void serialize_body(SerializingStream& s) const override;
297  void serialize_type(SerializingStream& s) const override;
298 
302  explicit ConstantDM(DeserializingStream& s);
303  };
304 
306  class CASADI_EXPORT ConstantFile : public ConstantMX {
307  public:
308 
312  explicit ConstantFile(const Sparsity& x, const std::string& fname);
313 
315  ~ConstantFile() override {}
316 
320  bool has_refcount() const override { return true; }
321 
325  void codegen_incref(CodeGenerator& g, std::set<void*>& added) const override;
326 
330  std::string disp(const std::vector<std::string>& arg) const override;
331 
333  double to_double() const override;
334 
336  casadi_int to_int() const override;
337 
339  Matrix<double> get_DM() const override;
340 
344  int eval(const double** arg, double** res, casadi_int* iw, double* w) const override {
345  std::copy(x_.begin(), x_.end(), res[0]);
346  return 0;
347  }
348 
352  int eval_sx(const SXElem** arg, SXElem** res,
353  casadi_int* iw, SXElem* w) const override {
354  std::copy(x_.begin(), x_.end(), res[0]);
355  return 0;
356  }
357 
361  int eval_activity(const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const override {
362  nonzeros_to_activity(x_.data(), res[0]);
363  return 0;
364  }
365 
369  void generate(CodeGenerator& g,
370  const std::vector<casadi_int>& arg,
371  const std::vector<casadi_int>& res,
372  const std::vector<bool>& arg_is_ref,
373  std::vector<bool>& res_is_ref) const override;
374 
378  void add_dependency(CodeGenerator& g) const override;
379 
383  std::string fname_;
384 
388  std::vector<double> x_;
389 
393  void serialize_body(SerializingStream& s) const override;
397  void serialize_type(SerializingStream& s) const override;
398 
402  explicit ConstantFile(DeserializingStream& s);
403  };
404 
406  class CASADI_EXPORT ConstantPool : public ConstantMX {
407  public:
408 
412  explicit ConstantPool(const DM& x, const std::string& name);
413 
415  ~ConstantPool() override {}
416 
420  std::string disp(const std::vector<std::string>& arg) const override;
421 
423  double to_double() const override;
424 
426  casadi_int to_int() const override;
427 
429  Matrix<double> get_DM() const override;
430 
434  int eval(const double** arg, double** res, casadi_int* iw, double* w) const override {
435  if (res[0]) std::copy(x_.begin(), x_.end(), res[0]);
436  return 0;
437  }
438 
442  int eval_activity(const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const override {
443  nonzeros_to_activity(x_.data(), res[0]);
444  return 0;
445  }
446 
450  int eval_sx(const SXElem** arg, SXElem** res,
451  casadi_int* iw, SXElem* w) const override {
452  casadi_error("eval_sx not supported");
453  return 0;
454  }
455 
459  void generate(CodeGenerator& g,
460  const std::vector<casadi_int>& arg,
461  const std::vector<casadi_int>& res,
462  const std::vector<bool>& arg_is_ref,
463  std::vector<bool>& res_is_ref) const override;
464 
468  void add_dependency(CodeGenerator& g) const override;
469 
473  std::string name_;
474 
478  std::vector<double> x_;
479 
483  void serialize_body(SerializingStream& s) const override;
484 
488  void serialize_type(SerializingStream& s) const override;
489 
493  explicit ConstantPool(DeserializingStream& s);
494  };
495 
497  class CASADI_EXPORT ZeroByZero : public ConstantMX {
498  private:
502  explicit ZeroByZero() : ConstantMX(Sparsity(0, 0)) {
503  initSingleton();
504  }
505 
506  public:
510  static ZeroByZero* getInstance() {
511  static ZeroByZero instance;
512  return &instance;
513  }
514 
516  ~ZeroByZero() override {
517  destroySingleton();
518  }
519 
523  std::string disp(const std::vector<std::string>& arg) const override;
524 
529  int eval(const double** arg, double** res, casadi_int* iw, double* w) const override {
530  return 0;
531  }
532 
534  int eval_sx(const SXElem** arg, SXElem** res,
535  casadi_int* iw, SXElem* w) const override {
536  return 0;
537  }
538 
542  void generate(CodeGenerator& g,
543  const std::vector<casadi_int>& arg,
544  const std::vector<casadi_int>& res,
545  const std::vector<bool>& arg_is_ref,
546  std::vector<bool>& res_is_ref) const override {}
547 
549  double to_double() const override { return 0;}
550 
552  casadi_int to_int() const override {return 0;}
553 
555  DM get_DM() const override { return DM(); }
556 
558  MX get_project(const Sparsity& sp, bool unique=false) const override;
559 
561  MX get_nzref(const Sparsity& sp, const std::vector<casadi_int>& nz,
562  bool unique=false) const override;
563 
565  MX get_nzassign(const MX& y, const std::vector<casadi_int>& nz) const override;
566 
568  MX get_transpose() const override;
569 
571  MX get_unary(casadi_int op, bool unique) const override;
572 
574  MX _get_binary(casadi_int op, const MX& y, bool ScX, bool ScY,
575  bool unique_x=false, bool unique_y=false) const override;
576 
578  MX get_reshape(const Sparsity& sp) const override;
579 
583  bool is_valid_input() const override { return true;}
584 
588  const std::string& name() const override {
589  static std::string dummyname;
590  return dummyname;
591  }
592 
596  void serialize_type(SerializingStream& s) const override;
600  void serialize_body(SerializingStream& s) const override;
601 
602  };
603 
607  template<typename T>
608  struct RuntimeConst {
609  const T value;
610  RuntimeConst() {}
611  RuntimeConst(T v) : value(v) {}
612  static char type_char();
613  void serialize_type(SerializingStream& s) const {
614  s.pack("Constant::value", value);
615  }
616  static RuntimeConst deserialize(DeserializingStream& s) {
617  T v;
618  s.unpack("Constant::value", v);
619  return RuntimeConst(v);
620  }
621  };
622 
623  template<typename T>
624  inline char RuntimeConst<T>::type_char() { return 'u'; }
625 
626  template<>
627  inline char RuntimeConst<casadi_int>::type_char() { return 'I'; }
628 
629  template<>
630  inline char RuntimeConst<double>::type_char() { return 'D'; }
631 
632  template<int v>
633  struct CompiletimeConst {
634  static const int value = v;
635  static char type_char();
636  void serialize_type(SerializingStream& s) const {}
637  static CompiletimeConst deserialize(DeserializingStream& s) {
638  return CompiletimeConst();
639  }
640  };
641 
642  template<int v>
643  inline char CompiletimeConst<v>::type_char() { return 'u'; }
644 
645  template<>
646  inline char CompiletimeConst<0>::type_char() { return '0'; }
647  template<>
648  inline char CompiletimeConst<(-1)>::type_char() { return 'm'; }
649  template<>
650  inline char CompiletimeConst<1>::type_char() { return '1'; }
651 
653  template<typename Value>
654  class CASADI_EXPORT Constant : public ConstantMX {
655  public:
656 
660  explicit Constant(const Sparsity& sp, Value v = Value()) : ConstantMX(sp), v_(v) {}
661 
665  explicit Constant(DeserializingStream& s, const Value& v);
666 
668  ~Constant() override {}
669 
673  std::string disp(const std::vector<std::string>& arg) const override;
674 
679  int eval(const double** arg, double** res, casadi_int* iw, double* w) const override;
680 
682  int eval_sx(const SXElem** arg, SXElem** res, casadi_int* iw, SXElem* w) const override;
683 
687  int eval_activity(const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const override {
688  std::fill_n(res[0], nnz(), v_.value!=0 ? ~static_cast<bvec_t>(0) : 0);
689  return 0;
690  }
691 
695  void generate(CodeGenerator& g,
696  const std::vector<casadi_int>& arg,
697  const std::vector<casadi_int>& res,
698  const std::vector<bool>& arg_is_ref,
699  std::vector<bool>& res_is_ref) const override;
700 
704  bool is_zero() const override;
705  bool is_one() const override;
706  bool is_minus_one() const override;
707  bool is_half() const override;
708  bool is_inf() const override;
709  bool is_minus_inf() const override;
710  bool is_nonnegative() const override;
711  bool is_integer() const override;
712  bool is_eye() const override;
713  bool is_value(double val) const override;
714 
716  double to_double() const override {
717  return static_cast<double>(v_.value);
718  }
719 
721  casadi_int to_int() const override {
722  return static_cast<casadi_int>(v_.value);
723  }
724 
726  Matrix<double> get_DM() const override {
727  return Matrix<double>(sparsity(), to_double(), false);
728  }
729 
731  MX get_project(const Sparsity& sp, bool unique=false) const override;
732 
734  MX get_nzref(const Sparsity& sp, const std::vector<casadi_int>& nz,
735  bool unique=false) const override;
736 
738  MX get_nzassign(const MX& y, const std::vector<casadi_int>& nz) const override;
739 
741  MX get_transpose() const override;
742 
744  MX get_unary(casadi_int op, bool unique=false) const override;
745 
747  MX _get_binary(casadi_int op, const MX& y, bool ScX, bool ScY,
748  bool unique_x=false, bool unique_y=false) const override;
749 
751  MX get_reshape(const Sparsity& sp) const override;
752 
754  MX get_horzcat(const std::vector<MX>& x) const override;
755 
757  MX get_vertcat(const std::vector<MX>& x) const override;
758 
762  bool is_equal(const MXNode* node, casadi_int depth) const override;
763 
767  void serialize_body(SerializingStream& s) const override;
771  void serialize_type(SerializingStream& s) const override;
772 
773  Value v_;
774  };
775 
776  template<typename Value>
777  bool Constant<Value>::is_zero() const {
778  return v_.value==0;
779  }
780 
781  template<typename Value>
782  bool Constant<Value>::is_one() const {
783  return sparsity().is_dense() && v_.value==1;
784  }
785 
786  template<typename Value>
787  bool Constant<Value>::is_minus_one() const {
788  return sparsity().is_dense() && v_.value==-1;
789  }
790 
791  template<typename Value>
792  bool Constant<Value>::is_half() const {
793  return sparsity().is_dense() && v_.value==0.5;
794  }
795 
796  template<typename Value>
797  bool Constant<Value>::is_inf() const {
798  return sparsity().is_dense() && casadi_limits<double>::is_inf(v_.value);
799  }
800 
801  template<typename Value>
802  bool Constant<Value>::is_minus_inf() const {
803  return sparsity().is_dense() && casadi_limits<double>::is_minus_inf(v_.value);
804  }
805 
806  template<typename Value>
807  bool Constant<Value>::is_nonnegative() const {
808  return casadi_limits<double>::is_nonnegative(v_.value);
809  }
810 
811  template<typename Value>
812  bool Constant<Value>::is_integer() const {
813  return casadi_limits<double>::is_integer(v_.value);
814  }
815 
816  template<typename Value>
817  bool Constant<Value>::is_eye() const {
818  return v_.value==1 && sparsity().is_diag();
819  }
820 
821  template<typename Value>
822  bool Constant<Value>::is_value(double val) const {
823  if (val==0) return is_zero();
824  return sparsity().is_dense() && v_.value==val;
825  }
826 
827  template<typename Value>
828  void Constant<Value>::serialize_type(SerializingStream& s) const {
830  s.pack("ConstantMX::type", Value::type_char());
831  v_.serialize_type(s);
832  }
833 
834  template<typename Value>
835  void Constant<Value>::serialize_body(SerializingStream& s) const {
837  }
838 
839  template<typename Value>
840  Constant<Value>::Constant(DeserializingStream& s, const Value& v) : ConstantMX(s), v_(v) {
841  }
842 
843  template<typename Value>
844  MX Constant<Value>::get_horzcat(const std::vector<MX>& x) const {
845  // Check if all arguments have the same constant value
846  for (auto&& i : x) {
847  if (!i->is_value(to_double())) {
848  // Not all the same value, fall back to base class
849  return ConstantMX::get_horzcat(x);
850  }
851  }
852 
853  // Assemble the sparsity pattern
854  std::vector<Sparsity> sp;
855  for (auto&& i : x) sp.push_back(i.sparsity());
856  return MX(horzcat(sp), v_.value, false);
857  }
858 
859  template<typename Value>
860  MX Constant<Value>::get_vertcat(const std::vector<MX>& x) const {
861  // Check if all arguments have the same constant value
862  for (auto&& i : x) {
863  if (!i->is_value(to_double())) {
864  // Not all the same value, fall back to base class
865  return ConstantMX::get_vertcat(x);
866  }
867  }
868 
869  // Assemble the sparsity pattern
870  std::vector<Sparsity> sp;
871  for (auto&& i : x) sp.push_back(i.sparsity());
872  return MX(vertcat(sp), v_.value, false);
873  }
874 
875  template<typename Value>
876  MX Constant<Value>::get_reshape(const Sparsity& sp) const {
877  return MX::create(new Constant<Value>(sp, v_));
878  }
879 
880  template<typename Value>
881  MX Constant<Value>::get_transpose() const {
882  return MX::create(new Constant<Value>(sparsity().T(), v_));
883  }
884 
885  template<typename Value>
886  MX Constant<Value>::get_unary(casadi_int op, bool unique) const {
887  // Constant folding
888  double ret(0);
889  casadi_math<double>::fun(op, to_double(), 0.0, ret);
890  if (operation_checker<F0XChecker>(op) || sparsity().is_dense()) {
891  return MX(sparsity(), ret);
892  } else {
893  if (v_.value==0) {
894  if (is_zero() && operation_checker<F0XChecker>(op)) {
895  return MX(sparsity(), ret, false);
896  } else {
897  return repmat(MX(ret), size1(), size2());
898  }
899  }
900  double ret2;
901  casadi_math<double>::fun(op, 0, 0.0, ret2);
902  return DM(sparsity(), ret, false)
903  + DM(sparsity().pattern_inverse(), ret2, false);
904  }
905  }
906 
907  template<typename Value>
908  MX Constant<Value>::_get_binary(casadi_int op, const MX& y, bool ScX, bool ScY,
909  bool unique_x, bool unique_y) const {
910  casadi_assert_dev(sparsity()==y.sparsity() || ScX || ScY);
911 
912  if (ScX && !operation_checker<FX0Checker>(op)) {
913  double ret;
914  casadi_math<double>::fun(op, nnz()> 0 ? to_double(): 0.0, 0, ret);
915 
916  if (ret!=0) {
917  Sparsity f = Sparsity::dense(y.size1(), y.size2());
918  MX yy = project(y, f);
919  return MX(f, shared_from_this<MX>())->_get_binary(op, yy, false, false, unique_x, unique_y);
920  }
921  } else if (ScY && !operation_checker<F0XChecker>(op)) {
922  bool grow = true;
923  if (y->op()==OP_CONST && dynamic_cast<const ConstantDM*>(y.get())==nullptr) {
924  double ret;
925  casadi_math<double>::fun(op, 0, y.nnz()>0 ? y->to_double() : 0, ret);
926  grow = ret!=0;
927  }
928  if (grow) {
929  Sparsity f = Sparsity::dense(size1(), size2());
930  MX xx = project(shared_from_this<MX>(), f);
931  return xx->_get_binary(op, MX(f, y), false, false, unique_x, unique_y);
932  }
933  }
934 
935  switch (op) {
936  case OP_ADD:
937  if (v_.value==0) return ScY && !y->is_zero() ? repmat(y, size1(), size2()) : y;
938  break;
939  case OP_SUB:
940  if (v_.value==0) return ScY && !y->is_zero() ? repmat(-y, size1(), size2()) : -y;
941  break;
942  case OP_MUL:
943  if (v_.value==1) return y;
944  if (v_.value==-1) return -y;
945  if (v_.value==2) return y->get_unary(OP_TWICE);
946  break;
947  case OP_DIV:
948  if (v_.value==1) return y->get_unary(OP_INV);
949  if (v_.value==-1) return -y->get_unary(OP_INV);
950  break;
951  case OP_POW:
952  // Note: v_.value can still lead to one when a y entry is zero
953  if (v_.value==1) return MX::ones(y.sparsity());
954  if (v_.value==std::exp(1.0)) return y->get_unary(OP_EXP);
955  break;
956  default: break; //no rule
957  }
958 
959  // Constant folding
960  // NOTE: ugly, should use a function instead of a cast
961  if (y->op()==OP_CONST && dynamic_cast<const ConstantDM*>(y.get())==nullptr) {
962  double y_value = y.nnz()>0 ? y->to_double() : 0;
963  double ret;
964  casadi_math<double>::fun(op, nnz()> 0.0 ? to_double(): 0, y_value, ret);
965 
966  return MX(y.sparsity(), ret, false);
967  }
968 
969  // Fallback
970  return MXNode::_get_binary(op, y, ScX, ScY, unique_x, unique_y);
971  }
972 
973  template<typename Value>
974  int Constant<Value>::eval(const double** arg, double** res, casadi_int* iw, double* w) const {
975  std::fill(res[0], res[0]+nnz(), to_double());
976  return 0;
977  }
978 
979  template<typename Value>
980  int Constant<Value>::
981  eval_sx(const SXElem** arg, SXElem** res, casadi_int* iw, SXElem* w) const {
982  std::fill(res[0], res[0]+nnz(), SXElem(v_.value));
983  return 0;
984  }
985 
986  template<typename Value>
987  void Constant<Value>::generate(CodeGenerator& g,
988  const std::vector<casadi_int>& arg,
989  const std::vector<casadi_int>& res,
990  const std::vector<bool>& arg_is_ref,
991  std::vector<bool>& res_is_ref) const {
992  if (nnz()==0) {
993  // Quick return
994  } else if (nnz()==1) {
995  g << g.workel(res[0]) << " = " << g.constant(to_double()) << ";\n";
996  } else {
997  if (to_double()==0) {
998  g << g.clear(g.work(res[0], nnz(), false), nnz()) << '\n';
999  } else {
1000  g << g.fill(g.work(res[0], nnz(), false), nnz(), g.constant(to_double())) << '\n';
1001  }
1002  }
1003  }
1004 
1005  template<typename Value>
1006  MX Constant<Value>::get_nzref(const Sparsity& sp, const std::vector<casadi_int>& nz,
1007  bool unique) const {
1008  if (v_.value!=0) {
1009  // Check if any "holes"
1010  for (std::vector<casadi_int>::const_iterator k=nz.begin(); k!=nz.end(); ++k) {
1011  if (*k<0) {
1012  // Do not simplify
1013  return MXNode::get_nzref(sp, nz);
1014  }
1015  }
1016  }
1017  return MX::create(new Constant<Value>(sp, v_));
1018  }
1019 
1020  template<typename Value>
1021  MX Constant<Value>::get_nzassign(const MX& y, const std::vector<casadi_int>& nz) const {
1022  if (y.is_constant() && y->is_zero() && v_.value==0) {
1023  return y;
1024  }
1025 
1026  // Fall-back
1027  return MXNode::get_nzassign(y, nz);
1028  }
1029 
1030  template<typename Value>
1031  MX Constant<Value>::get_project(const Sparsity& sp, bool unique) const {
1032  if (is_zero()) {
1033  return MX::create(new Constant<Value>(sp, v_));
1034  } else if (sp.is_dense()) {
1035  return densify(get_DM());
1036  } else {
1037  return MXNode::get_project(sp, unique);
1038  }
1039  }
1040 
1041  template<typename Value>
1042  std::string
1043  Constant<Value>::disp(const std::vector<std::string>& arg) const {
1044  std::stringstream ss;
1045  ss.precision(Matrix<double>::get_precision());
1046  ss.width(Matrix<double>::get_width());
1048  ss.setf(std::ios::scientific);
1049  } else {
1050  ss.unsetf(std::ios::scientific);
1051  }
1052  if (sparsity().is_scalar()) {
1053  // Print scalar
1054  if (sparsity().nnz()==0) {
1055  ss << "00";
1056  } else {
1057  ss << v_.value;
1058  }
1059  } else if (sparsity().is_empty()) {
1060  // Print empty
1061  sparsity().disp(ss);
1062  } else {
1063  // Print value
1064  if (v_.value==0) {
1065  ss << "zeros(";
1066  } else if (v_.value==1) {
1067  ss << "ones(";
1068  } else if (v_.value!=v_.value) {
1069  ss << "nan(";
1070  } else if (v_.value==std::numeric_limits<double>::infinity()) {
1071  ss << "inf(";
1072  } else if (v_.value==-std::numeric_limits<double>::infinity()) {
1073  ss << "-inf(";
1074  } else {
1075  ss << "all_" << v_.value << "(";
1076  }
1077 
1078  // Print sparsity
1079  sparsity().disp(ss);
1080  ss << ")";
1081  }
1082  return ss.str();
1083  }
1084 
1085  template<typename Value>
1086  bool Constant<Value>::is_equal(const MXNode* node, casadi_int depth) const {
1087  return node->is_value(to_double()) && sparsity()==node->sparsity();
1088  }
1089 
1090 
1091 } // namespace casadi
1093 
1094 
1095 #endif // CASADI_CONSTANT_MX_HPP
virtual void serialize_type(SerializingStream &s) const
Serialize type information.
virtual void serialize_body(SerializingStream &s) const
Serialize an object without type information.
static casadi_int get_precision()
Get the 'precision, width & scientific' used in printing and serializing to streams.
Definition: matrix_impl.hpp:49
static casadi_int get_width()
Definition: matrix_impl.hpp:52
static bool get_scientific()
Definition: matrix_impl.hpp:55
static bool is_inf(const T &val)
static bool is_nonnegative(const T &val)
static bool is_minus_inf(const T &val)
static bool is_integer(const T &val)
The casadi namespace.
Definition: archiver.hpp:32
Matrix< SXElem > SX
Definition: sx_fwd.hpp:32
bool is_zero(const T &x)
Matrix< double > DM
Definition: dm_fwd.hpp:33