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