constant_sx.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_SX_HPP
27 #define CASADI_CONSTANT_SX_HPP
28 
29 #include "sx_node.hpp"
30 #include "serializing_stream.hpp"
31 #include <cassert>
32 
34 
35 // Cashing of constants requires a map
36 #include <unordered_map>
37 #define CACHING_MAP std::unordered_map
38 
39 namespace casadi {
40 
47 class ConstantSX : public SXNode {
48 public:
49 
50 // Destructor
51 ~ConstantSX() override {}
52 
53 // Class name
54 std::string class_name() const override {return "ConstantSX";}
55 
59 double to_double() const override = 0;
60 
64 bool is_constant() const override { return true; }
65 
69 casadi_int op() const override { return OP_CONST;}
70 
74 bool is_equal(const SXNode* node, casadi_int depth) const override {
75  const ConstantSX* n = dynamic_cast<const ConstantSX*>(node);
76  return n && n->to_double()==to_double();
77 }
78 
79 protected:
80 
84 std::string print(const std::string& arg1, const std::string& arg2) const override {
85  std::stringstream ss;
86  ss << to_double();
87  return ss.str();
88  }
89 
90 };
91 
102 class RealtypeSX : public ConstantSX {
103  private:
105  explicit RealtypeSX(double value) : value(value) {}
106 
107  public:
108 
110  ~RealtypeSX() override {
111  size_t num_erased = cached_constants_.erase(value);
112  assert(num_erased==1);
113  (void)num_erased;
114  }
115 
117  inline static RealtypeSX* create(double value) {
118  // Try to find the constant
119  CACHING_MAP<double, RealtypeSX*>::iterator it = cached_constants_.find(value);
120 
121  // If not found, add it,
122  if (it==cached_constants_.end()) {
123  // Allocate a new object
124  RealtypeSX* n = new RealtypeSX(value);
125 
126  // Add to hash_table
127  cached_constants_.insert(it, std::make_pair(value, n));
128 
129  // Return it to caller
130  return n;
131  } else { // Else, returned the object
132  return it->second;
133  }
134  }
135 
137 
140  double to_double() const override { return value;}
141  casadi_int to_int() const override { return static_cast<casadi_int>(value);}
143 
144  bool is_almost_zero(double tol) const override { return fabs(value)<=tol; }
145 
146  void serialize_node(SerializingStream& s) const override {
147  s.pack("ConstantSX::type", 'r');
148  s.pack("ConstantSX::value", value);
149  }
150 
151  protected:
157  static CACHING_MAP<double, RealtypeSX*> cached_constants_;
158 
162  double value;
163 };
164 
165 
172 class IntegerSX : public ConstantSX {
173  private:
175  explicit IntegerSX(casadi_int value) : value(static_cast<int>(value)) {
176  casadi_assert(value<=std::numeric_limits<int>::max() &&
177  value>=std::numeric_limits<int>::min(), "Integer overflow");
178  }
179 
180  public:
181 
183  ~IntegerSX() override {
184  size_t num_erased = cached_constants_.erase(value);
185  assert(num_erased==1);
186  (void)num_erased;
187  }
188 
190  inline static IntegerSX* create(casadi_int value) {
191  // Try to find the constant
192  CACHING_MAP<casadi_int, IntegerSX*>::iterator it = cached_constants_.find(value);
193 
194  // If not found, add it,
195  if (it==cached_constants_.end()) {
196  // Allocate a new object
197  IntegerSX* n = new IntegerSX(value);
198 
199  // Add to hash_table
200  cached_constants_.insert(it, std::make_pair(value, n));
201 
202  // Return it to caller
203  return n;
204  } else { // Else, returned the object
205  return it->second;
206  }
207  }
208 
210 
213  double to_double() const override { return static_cast<double>(value); }
214  casadi_int to_int() const override { return static_cast<casadi_int>(value); }
216 
220  bool is_integer() const override { return true; }
221 
222  void serialize_node(SerializingStream& s) const override {
223  s.pack("ConstantSX::type", 'i');
224  s.pack("ConstantSX::value", value);
225  }
226 
227  protected:
228 
234  static CACHING_MAP<casadi_int, IntegerSX*> cached_constants_;
235 
239  int value;
240 };
241 
248 class ZeroSX : public ConstantSX {
249 private:
250  /* Private constructor (singleton class) */
251  explicit ZeroSX() {this->count++;}
252 public:
253  /* Get singleton instance */
254  static ZeroSX* singleton() {
255  static ZeroSX instance;
256  return &instance;
257  }
258  /* Destructor */
259  ~ZeroSX() override {this->count--;}
261 
264  double to_double() const override { return 0;}
265  casadi_int to_int() const override { return 0;}
267 
269 
272  bool is_integer() const override { return true; }
273  bool is_zero() const override { return true; }
274  bool is_almost_zero(double tol) const override { return true; }
276 
277  void serialize_node(SerializingStream& s) const override {
278  s.pack("ConstantSX::type", '0');
279  }
280 };
281 
282 
289 class OneSX : public ConstantSX {
290 private:
291  /* Private constructor (singleton class) */
292  explicit OneSX() {this->count++;}
293 public:
294  /* Get singleton instance */
295  static OneSX* singleton() {
296  static OneSX instance;
297  return &instance;
298  }
299  /* Destructor */
300  ~OneSX() override {this->count--;}
304  double to_double() const override { return 1;}
305  casadi_int to_int() const override { return 1;}
306 
310  bool is_integer() const override { return true; }
311  bool is_one() const override { return true; }
312 
313  void serialize_node(SerializingStream& s) const override {
314  s.pack("ConstantSX::type", '1');
315  }
316 
317 };
318 
319 
326 class MinusOneSX : public ConstantSX {
327 private:
328  /* Private constructor (singleton class) */
329  explicit MinusOneSX() {this->count++;}
330 public:
331  /* Get singleton instance */
332  static MinusOneSX* singleton() {
333  static MinusOneSX instance;
334  return &instance;
335  }
336  /* Destructor */
337  ~MinusOneSX() override {this->count--;}
338 
340 
343  double to_double() const override { return -1;}
344  casadi_int to_int() const override { return -1;}
346 
348 
351  bool is_integer() const override { return true; }
352  bool is_minus_one() const override { return true; }
354 
355  void serialize_node(SerializingStream& s) const override {
356  s.pack("ConstantSX::type", 'm');
357  }
358 
359 };
360 
361 
368 class InfSX : public ConstantSX {
369 private:
370  /* Private constructor (singleton class) */
371  explicit InfSX() {this->count++;}
372 public:
373  /* Get singleton instance */
374  static InfSX* singleton() {
375  static InfSX instance;
376  return &instance;
377  }
378  /* Destructor */
379  ~InfSX() override {this->count--;}
383  double to_double() const override { return std::numeric_limits<double>::infinity();}
384 
388  bool is_inf() const override { return true; }
389 
390  void serialize_node(SerializingStream& s) const override {
391  s.pack("ConstantSX::type", 'F');
392  }
393 
394 };
395 
396 
403 class MinusInfSX : public ConstantSX {
404 private:
405  /* Private constructor (singleton class) */
406  explicit MinusInfSX() {this->count++;}
407 public:
408  /* Get singleton instance */
409  static MinusInfSX* singleton() {
410  static MinusInfSX instance;
411  return &instance;
412  }
413  /* Destructor */
414  ~MinusInfSX() override {this->count--;}
415 
419  double to_double() const override { return -std::numeric_limits<double>::infinity();}
420 
424  bool is_minus_inf() const override { return true; }
425 
426  void serialize_node(SerializingStream& s) const override {
427  s.pack("ConstantSX::type", 'f');
428  }
429 };
430 
437 class NanSX : public ConstantSX {
438 private:
439  /* Private constructor (singleton class) */
440  explicit NanSX() {this->count++;}
441 public:
442  /* Get singleton instance */
443  static NanSX* singleton() {
444  static NanSX instance;
445  return &instance;
446  }
447  /* Destructor */
448  ~NanSX() override {this->count--;}
452  double to_double() const override { return std::numeric_limits<double>::quiet_NaN();}
453 
457  bool is_nan() const override { return true; }
458 
459  void serialize_node(SerializingStream& s) const override {
460  s.pack("ConstantSX::type", 'n');
461  }
462 
463 };
464 
465 inline SXNode* ConstantSX_deserialize(DeserializingStream& s) {
466  char type;
467  s.unpack("ConstantSX::type", type);
468  switch (type) {
469  case '1': return casadi_limits<SXElem>::one.get();
470  case '0': return casadi_limits<SXElem>::zero.get();
471  case 'r': {
472  double value;
473  s.unpack("ConstantSX::value", value);
474  return RealtypeSX::create(value);
475  }
476  case 'i': {
477  int value;
478  s.unpack("ConstantSX::value", value);
479  if (value==2) return casadi_limits<SXElem>::two.get();
480  return IntegerSX::create(value);
481  }
482  case 'n': return casadi_limits<SXElem>::nan.get();
483  case 'f': return casadi_limits<SXElem>::minus_inf.get();
484  case 'F': return casadi_limits<SXElem>::inf.get();
485  case 'm': return casadi_limits<SXElem>::minus_one.get();
486  default: casadi_error("ConstantSX::deserialize error");
487  }
488 }
489 
490 } // namespace casadi
492 
493 #endif // CASADI_CONSTANT_SX_HPP
static const T minus_one
The casadi namespace.
bool is_zero(const T &x)