1 /*
2  *    This file is part of CasADi.
3  *
4  *    CasADi -- A symbolic framework for dynamic optimization.
5  *    Copyright (C) 2010-2014 Joel Andersson, Joris Gillis, Moritz Diehl,
6  *                            K.U. 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_SX_HPP
27 #define CASADI_CONSTANT_SX_HPP
28 
29 #include "sx_node.hpp"
30 #include "serializing_stream.hpp"
31 #include <cassert>
32 
33 /// \cond INTERNAL
34 
35 // Cashing of constants requires a map
36 #include <unordered_map>
37 #define CACHING_MAP std::unordered_map
38 
39 namespace casadi {
40 
41 /** \brief Represents a constant SX
42   \author Joel Andersson
43   \date 2010
44 */
45 class ConstantSX : public SXNode {
46 public:
47 
48 // Destructor
~ConstantSX()49 ~ConstantSX() override {}
50 
51 // Class name
class_name() const52 std::string class_name() const override {return "ConstantSX";}
53 
54 /** \brief  Get the value must be defined */
55 double to_double() const override = 0;
56 
57 /** \brief  Properties */
is_constant() const58 bool is_constant() const override { return true; }
59 
60 /** \brief  Get the operation */
op() const61 casadi_int op() const override { return OP_CONST;}
62 
63 /** \brief Check if two nodes are equivalent up to a given depth */
is_equal(const SXNode * node,casadi_int depth) const64 bool is_equal(const SXNode* node, casadi_int depth) const override {
65   const ConstantSX* n = dynamic_cast<const ConstantSX*>(node);
66   return n && n->to_double()==to_double();
67 }
68 
69 protected:
70 
71 /** \brief  Print expression */
print(const std::string & arg1,const std::string & arg2) const72 std::string print(const std::string& arg1, const std::string& arg2) const override {
73    std::stringstream ss;
74    ss << to_double();
75    return ss.str();
76  }
77 
78 };
79 
80 /** \brief  DERIVED CLASSES */
81 
82 /** \brief  Represents a constant real SX
83   \author Joel Andersson
84   \date 2010
85 */
86 class RealtypeSX : public ConstantSX {
87   private:
88     /// Constructor is private, use "create" below
RealtypeSX(double value)89     explicit RealtypeSX(double value) : value(value) {}
90 
91   public:
92 
93     /// Destructor
~RealtypeSX()94     ~RealtypeSX() override {
95       size_t num_erased = cached_constants_.erase(value);
96       assert(num_erased==1);
97       (void)num_erased;
98     }
99 
100     /// Static creator function (use instead of constructor)
create(double value)101     inline static RealtypeSX* create(double value) {
102       // Try to find the constant
103       CACHING_MAP<double, RealtypeSX*>::iterator it = cached_constants_.find(value);
104 
105       // If not found, add it,
106       if (it==cached_constants_.end()) {
107         // Allocate a new object
108         RealtypeSX* n = new RealtypeSX(value);
109 
110         // Add to hash_table
111         cached_constants_.insert(it, std::make_pair(value, n));
112 
113         // Return it to caller
114         return n;
115       } else { // Else, returned the object
116         return it->second;
117       }
118     }
119 
120     ///@{
121     /** \brief  Get the value */
to_double() const122     double to_double() const override { return value;}
to_int() const123     casadi_int to_int() const override { return static_cast<casadi_int>(value);}
124     ///@}
125 
is_almost_zero(double tol) const126     bool is_almost_zero(double tol) const override { return fabs(value)<=tol; }
127 
serialize_node(SerializingStream & s) const128     void serialize_node(SerializingStream& s) const override {
129       s.pack("ConstantSX::type", 'r');
130       s.pack("ConstantSX::value", value);
131     }
132 
133   protected:
134     /** \brief Hash map of all constants currently allocated
135      * (storage is allocated for it in sx_element.cpp) */
136     static CACHING_MAP<double, RealtypeSX*> cached_constants_;
137 
138     /** \brief  Data members */
139     double value;
140 };
141 
142 
143 /** \brief  Represents a constant integer SX
144   \author Joel Andersson
145   \date 2010
146 */
147 class IntegerSX : public ConstantSX {
148   private:
149     /// Constructor is private, use "create" below
IntegerSX(casadi_int value)150     explicit IntegerSX(casadi_int value) : value(static_cast<int>(value)) {
151       casadi_assert(value<=std::numeric_limits<int>::max() &&
152                     value>=std::numeric_limits<int>::min(), "Integer overflow");
153     }
154 
155   public:
156 
157     /// Destructor
~IntegerSX()158     ~IntegerSX() override {
159       size_t num_erased = cached_constants_.erase(value);
160       assert(num_erased==1);
161       (void)num_erased;
162     }
163 
164     /// Static creator function (use instead of constructor)
create(casadi_int value)165     inline static IntegerSX* create(casadi_int value) {
166       // Try to find the constant
167       CACHING_MAP<casadi_int, IntegerSX*>::iterator it = cached_constants_.find(value);
168 
169       // If not found, add it,
170       if (it==cached_constants_.end()) {
171         // Allocate a new object
172         IntegerSX* n = new IntegerSX(value);
173 
174         // Add to hash_table
175         cached_constants_.insert(it, std::make_pair(value, n));
176 
177         // Return it to caller
178         return n;
179       } else { // Else, returned the object
180         return it->second;
181       }
182     }
183 
184     ///@{
185     /** \brief  evaluate function */
to_double() const186     double to_double() const override {  return static_cast<double>(value); }
to_int() const187     casadi_int to_int() const override {  return static_cast<casadi_int>(value); }
188     ///@}
189 
190     /** \brief  Properties */
is_integer() const191     bool is_integer() const override { return true; }
192 
serialize_node(SerializingStream & s) const193     void serialize_node(SerializingStream& s) const override {
194       s.pack("ConstantSX::type", 'i');
195       s.pack("ConstantSX::value", value);
196     }
197 
198   protected:
199 
200     /** \brief Hash map of all constants currently allocated
201      * (storage is allocated for it in sx_element.cpp) */
202     static CACHING_MAP<casadi_int, IntegerSX*> cached_constants_;
203 
204     /** \brief  Data members */
205     int value;
206 };
207 
208 /** \brief  Represents a zero SX
209   \author Joel Andersson
210   \date 2010
211 */
212 class ZeroSX : public ConstantSX {
213 private:
214   /* Private constructor (singleton class) */
ZeroSX()215   explicit ZeroSX() {this->count++;}
216 public:
217   /* Get singleton instance */
singleton()218   static ZeroSX* singleton() {
219     static ZeroSX instance;
220     return &instance;
221   }
222   /* Destructor */
~ZeroSX()223   ~ZeroSX() override {this->count--;}
224   ///@{
225   /** \brief  Get the value */
to_double() const226   double to_double() const override { return 0;}
to_int() const227   casadi_int to_int() const override { return 0;}
228   ///@}
229 
230   ///@{
231   /** \brief  Properties */
is_integer() const232   bool is_integer() const override { return true; }
is_zero() const233   bool is_zero() const override { return true; }
is_almost_zero(double tol) const234   bool is_almost_zero(double tol) const override { return true; }
235   ///@}
236 
serialize_node(SerializingStream & s) const237   void serialize_node(SerializingStream& s) const override {
238     s.pack("ConstantSX::type", '0');
239   }
240 };
241 
242 
243 /** \brief  Represents a one SX
244   \author Joel Andersson
245   \date 2010
246 */
247 class OneSX : public ConstantSX {
248 private:
249   /* Private constructor (singleton class) */
OneSX()250   explicit OneSX() {this->count++;}
251 public:
252   /* Get singleton instance */
singleton()253   static OneSX* singleton() {
254     static OneSX instance;
255     return &instance;
256   }
257   /* Destructor */
~OneSX()258   ~OneSX() override {this->count--;}
259   /** \brief  Get the value */
to_double() const260   double to_double() const override { return 1;}
to_int() const261   casadi_int to_int() const override { return 1;}
262 
263   /** \brief  Properties */
is_integer() const264   bool is_integer() const override { return true; }
is_one() const265   bool is_one() const override { return true; }
266 
serialize_node(SerializingStream & s) const267   void serialize_node(SerializingStream& s) const override {
268     s.pack("ConstantSX::type", '1');
269   }
270 
271 };
272 
273 
274 /** \brief  Represents a minus one SX
275   \author Joel Andersson
276   \date 2010
277 */
278 class MinusOneSX : public ConstantSX {
279 private:
280   /* Private constructor (singleton class) */
MinusOneSX()281   explicit MinusOneSX() {this->count++;}
282 public:
283   /* Get singleton instance */
singleton()284   static MinusOneSX* singleton() {
285     static MinusOneSX instance;
286     return &instance;
287   }
288   /* Destructor */
~MinusOneSX()289   ~MinusOneSX() override {this->count--;}
290 
291   ///@{
292   /** \brief  Get the value */
to_double() const293   double to_double() const override { return -1;}
to_int() const294   casadi_int to_int() const override { return -1;}
295   ///@}
296 
297   ///@{
298   /** \brief  Properties */
is_integer() const299   bool is_integer() const override { return true; }
is_minus_one() const300   bool is_minus_one() const override { return true; }
301   ///@}
302 
serialize_node(SerializingStream & s) const303   void serialize_node(SerializingStream& s) const override {
304     s.pack("ConstantSX::type", 'm');
305   }
306 
307 };
308 
309 
310 /** \brief  Represents an infinity SX
311   \author Joel Andersson
312   \date 2010
313 */
314 class InfSX : public ConstantSX {
315 private:
316   /* Private constructor (singleton class) */
InfSX()317   explicit InfSX() {this->count++;}
318 public:
319   /* Get singleton instance */
singleton()320   static InfSX* singleton() {
321     static InfSX instance;
322     return &instance;
323   }
324   /* Destructor */
~InfSX()325   ~InfSX() override {this->count--;}
326   /** \brief  Get the value */
to_double() const327   double to_double() const override { return std::numeric_limits<double>::infinity();}
328 
329   /** \brief  Properties */
is_inf() const330   bool is_inf() const override { return true; }
331 
serialize_node(SerializingStream & s) const332   void serialize_node(SerializingStream& s) const override {
333     s.pack("ConstantSX::type", 'F');
334   }
335 
336 };
337 
338 
339 /** \brief  Represents a minus infinity SX
340   \author Joel Andersson
341   \date 2010
342 */
343 class MinusInfSX : public ConstantSX {
344 private:
345   /* Private constructor (singleton class) */
MinusInfSX()346   explicit MinusInfSX() {this->count++;}
347 public:
348   /* Get singleton instance */
singleton()349   static MinusInfSX* singleton() {
350     static MinusInfSX instance;
351     return &instance;
352   }
353   /* Destructor */
~MinusInfSX()354   ~MinusInfSX() override {this->count--;}
355 
356   /** \brief  Get the value */
to_double() const357   double to_double() const override { return -std::numeric_limits<double>::infinity();}
358 
359   /** \brief  Properties */
is_minus_inf() const360   bool is_minus_inf() const override { return true; }
361 
serialize_node(SerializingStream & s) const362   void serialize_node(SerializingStream& s) const override {
363     s.pack("ConstantSX::type", 'f');
364   }
365 };
366 
367 /** \brief  Represents a not-a-number SX
368   \author Joel Andersson
369   \date 2010
370 */
371 class NanSX : public ConstantSX {
372 private:
373   /* Private constructor (singleton class) */
NanSX()374   explicit NanSX() {this->count++;}
375 public:
376   /* Get singleton instance */
singleton()377   static NanSX* singleton() {
378     static NanSX instance;
379     return &instance;
380   }
381   /* Destructor */
~NanSX()382   ~NanSX() override {this->count--;}
383   /** \brief  Get the value */
to_double() const384   double to_double() const override { return std::numeric_limits<double>::quiet_NaN();}
385 
386   /** \brief  Properties */
is_nan() const387   bool is_nan() const override { return true; }
388 
serialize_node(SerializingStream & s) const389   void serialize_node(SerializingStream& s) const override {
390     s.pack("ConstantSX::type", 'n');
391   }
392 
393 };
394 
ConstantSX_deserialize(DeserializingStream & s)395 inline SXNode* ConstantSX_deserialize(DeserializingStream& s) {
396   char type;
397   s.unpack("ConstantSX::type", type);
398   switch (type) {
399     case '1': return casadi_limits<SXElem>::one.get();
400     case '0': return casadi_limits<SXElem>::zero.get();
401     case 'r': {
402       double value;
403       s.unpack("ConstantSX::value", value);
404       return RealtypeSX::create(value);
405     }
406     case 'i': {
407       int value;
408       s.unpack("ConstantSX::value", value);
409       if (value==2) return casadi_limits<SXElem>::two.get();
410       return IntegerSX::create(value);
411     }
412     case 'n': return casadi_limits<SXElem>::nan.get();
413     case 'f': return casadi_limits<SXElem>::minus_inf.get();
414     case 'F': return casadi_limits<SXElem>::inf.get();
415     case 'm': return casadi_limits<SXElem>::minus_one.get();
416     default: casadi_error("ConstantSX::deserialize error");
417   }
418 }
419 
420 } // namespace casadi
421 /// \endcond
422 
423 #endif // CASADI_CONSTANT_SX_HPP
424