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 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
112  // Safe access to cached_constants_
113  std::lock_guard<std::mutex> lock(mutex_cached_constants);
114 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
115  size_t num_erased = cached_constants_.erase(value);
116  assert(num_erased==1);
117  (void)num_erased;
118  }
119 
121  inline static RealtypeSX* create(double value) {
122 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
123  // Safe access to cached_constants_
124  std::lock_guard<std::mutex> lock(mutex_cached_constants);
125 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
126  // Try to find the constant
127  CACHING_MAP<double, RealtypeSX*>::iterator it = cached_constants_.find(value);
128 
129  // If not found, add it,
130  if (it==cached_constants_.end()) {
131  // Allocate a new object
132  RealtypeSX* n = new RealtypeSX(value);
133 
134  // Add to hash_table
135  cached_constants_.insert(it, std::make_pair(value, n));
136 
137  // Return it to caller
138  return n;
139  } else { // Else, returned the object
140  return it->second;
141  }
142  }
143 
145 
148  double to_double() const override { return value;}
149  casadi_int to_int() const override { return static_cast<casadi_int>(value);}
151 
152  bool is_almost_zero(double tol) const override { return fabs(value)<=tol; }
153 
154  void serialize_node(SerializingStream& s) const override {
155  s.pack("ConstantSX::type", 'r');
156  s.pack("ConstantSX::value", value);
157  }
158 
159  protected:
165  static CACHING_MAP<double, RealtypeSX*> cached_constants_;
166 
167 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
168  static std::mutex mutex_cached_constants;
169 #endif //CASADI_WITH_THREADSAFE_SYMBOLICS
170 
174  double value;
175 };
176 
177 
184 class IntegerSX : public ConstantSX {
185  private:
187  explicit IntegerSX(casadi_int value) : value(static_cast<int>(value)) {
188  casadi_assert(value<=std::numeric_limits<int>::max() &&
189  value>=std::numeric_limits<int>::min(), "Integer overflow");
190  }
191 
192  public:
193 
195  ~IntegerSX() override {
196 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
197  // Safe access to cached_constants_
198  std::lock_guard<std::mutex> lock(mutex_cached_constants);
199 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
200  size_t num_erased = cached_constants_.erase(value);
201  assert(num_erased==1);
202  (void)num_erased;
203  }
204 
206  inline static IntegerSX* create(casadi_int value) {
207 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
208  // Safe access to cached_constants_
209  std::lock_guard<std::mutex> lock(mutex_cached_constants);
210 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
211  // Try to find the constant
212  CACHING_MAP<casadi_int, IntegerSX*>::iterator it = cached_constants_.find(value);
213 
214  // If not found, add it,
215  if (it==cached_constants_.end()) {
216  // Allocate a new object
217  IntegerSX* n = new IntegerSX(value);
218 
219  // Add to hash_table
220  cached_constants_.insert(it, std::make_pair(value, n));
221 
222  // Return it to caller
223  return n;
224  } else { // Else, returned the object
225  return it->second;
226  }
227  }
228 
230 
233  double to_double() const override { return static_cast<double>(value); }
234  casadi_int to_int() const override { return static_cast<casadi_int>(value); }
236 
240  bool is_integer() const override { return true; }
241 
242  void serialize_node(SerializingStream& s) const override {
243  s.pack("ConstantSX::type", 'i');
244  s.pack("ConstantSX::value", value);
245  }
246 
247  protected:
248 
254  static CACHING_MAP<casadi_int, IntegerSX*> cached_constants_;
255 
256 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
257  static std::mutex mutex_cached_constants;
258 #endif //CASADI_WITH_THREADSAFE_SYMBOLICS
259 
263  int value;
264 };
265 
272 class ZeroSX : public ConstantSX {
273 private:
274  /* Private constructor (singleton class) */
275  explicit ZeroSX() {this->count++;}
276 public:
277  /* Get singleton instance */
278  static ZeroSX* singleton() {
279  static ZeroSX instance;
280  return &instance;
281  }
282  /* Destructor */
283  ~ZeroSX() override {this->count--;}
285 
288  double to_double() const override { return 0;}
289  casadi_int to_int() const override { return 0;}
291 
293 
296  bool is_integer() const override { return true; }
297  bool is_zero() const override { return true; }
298  bool is_almost_zero(double tol) const override { return true; }
300 
301  void serialize_node(SerializingStream& s) const override {
302  s.pack("ConstantSX::type", '0');
303  }
304 };
305 
306 
313 class OneSX : public ConstantSX {
314 private:
315  /* Private constructor (singleton class) */
316  explicit OneSX() {this->count++;}
317 public:
318  /* Get singleton instance */
319  static OneSX* singleton() {
320  static OneSX instance;
321  return &instance;
322  }
323  /* Destructor */
324  ~OneSX() override {this->count--;}
328  double to_double() const override { return 1;}
329  casadi_int to_int() const override { return 1;}
330 
334  bool is_integer() const override { return true; }
335  bool is_one() const override { return true; }
336 
337  void serialize_node(SerializingStream& s) const override {
338  s.pack("ConstantSX::type", '1');
339  }
340 
341 };
342 
343 
350 class MinusOneSX : public ConstantSX {
351 private:
352  /* Private constructor (singleton class) */
353  explicit MinusOneSX() {this->count++;}
354 public:
355  /* Get singleton instance */
356  static MinusOneSX* singleton() {
357  static MinusOneSX instance;
358  return &instance;
359  }
360  /* Destructor */
361  ~MinusOneSX() override {this->count--;}
362 
364 
367  double to_double() const override { return -1;}
368  casadi_int to_int() const override { return -1;}
370 
372 
375  bool is_integer() const override { return true; }
376  bool is_minus_one() const override { return true; }
378 
379  void serialize_node(SerializingStream& s) const override {
380  s.pack("ConstantSX::type", 'm');
381  }
382 
383 };
384 
385 
392 class InfSX : public ConstantSX {
393 private:
394  /* Private constructor (singleton class) */
395  explicit InfSX() {this->count++;}
396 public:
397  /* Get singleton instance */
398  static InfSX* singleton() {
399  static InfSX instance;
400  return &instance;
401  }
402  /* Destructor */
403  ~InfSX() override {this->count--;}
407  double to_double() const override { return std::numeric_limits<double>::infinity();}
408 
412  bool is_inf() const override { return true; }
413 
414  void serialize_node(SerializingStream& s) const override {
415  s.pack("ConstantSX::type", 'F');
416  }
417 
418 };
419 
420 
427 class MinusInfSX : public ConstantSX {
428 private:
429  /* Private constructor (singleton class) */
430  explicit MinusInfSX() {this->count++;}
431 public:
432  /* Get singleton instance */
433  static MinusInfSX* singleton() {
434  static MinusInfSX instance;
435  return &instance;
436  }
437  /* Destructor */
438  ~MinusInfSX() override {this->count--;}
439 
443  double to_double() const override { return -std::numeric_limits<double>::infinity();}
444 
448  bool is_minus_inf() const override { return true; }
449 
450  void serialize_node(SerializingStream& s) const override {
451  s.pack("ConstantSX::type", 'f');
452  }
453 };
454 
461 class NanSX : public ConstantSX {
462 private:
463  /* Private constructor (singleton class) */
464  explicit NanSX() {this->count++;}
465 public:
466  /* Get singleton instance */
467  static NanSX* singleton() {
468  static NanSX instance;
469  return &instance;
470  }
471  /* Destructor */
472  ~NanSX() override {this->count--;}
476  double to_double() const override { return std::numeric_limits<double>::quiet_NaN();}
477 
481  bool is_nan() const override { return true; }
482 
483  void serialize_node(SerializingStream& s) const override {
484  s.pack("ConstantSX::type", 'n');
485  }
486 
487 };
488 
489 inline SXNode* ConstantSX_deserialize(DeserializingStream& s) {
490  char type;
491  s.unpack("ConstantSX::type", type);
492  switch (type) {
493  case '1': return casadi_limits<SXElem>::one.get();
494  case '0': return casadi_limits<SXElem>::zero.get();
495  case 'r': {
496  double value;
497  s.unpack("ConstantSX::value", value);
498  return RealtypeSX::create(value);
499  }
500  case 'i': {
501  int value;
502  s.unpack("ConstantSX::value", value);
503  if (value==2) return casadi_limits<SXElem>::two.get();
504  return IntegerSX::create(value);
505  }
506  case 'n': return casadi_limits<SXElem>::nan.get();
507  case 'f': return casadi_limits<SXElem>::minus_inf.get();
508  case 'F': return casadi_limits<SXElem>::inf.get();
509  case 'm': return casadi_limits<SXElem>::minus_one.get();
510  default: casadi_error("ConstantSX::deserialize error");
511  }
512 }
513 
514 } // namespace casadi
516 
517 #endif // CASADI_CONSTANT_SX_HPP
static const T minus_one
The casadi namespace.
Definition: archiver.hpp:32
bool is_zero(const T &x)