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 "matrix_decl.hpp"
32 #include <cassert>
33 
35 
36 // Cashing of constants requires a map
37 #include <unordered_map>
38 #define CACHING_MAP std::unordered_map
39 
40 namespace casadi {
41 
48 class ConstantSX : public SXNode {
49 public:
50 
51 // Destructor
52 ~ConstantSX() override {}
53 
54 // Class name
55 std::string class_name() const override {return "ConstantSX";}
56 
60 double to_double() const override = 0;
61 
65 bool is_constant() const override { return true; }
66 
70 casadi_int op() const override { return OP_CONST;}
71 
75 bool is_value(double v) const override {
76  return casadi_limits<double>::is_value(to_double(), v);
77 }
78 bool is_half() const override { return casadi_limits<double>::is_half(to_double()); }
79 bool is_integer() const override { return casadi_limits<double>::is_integer(to_double()); }
80 
84 bool is_equal(const SXNode* node, casadi_int depth) const override {
85  const ConstantSX* n = dynamic_cast<const ConstantSX*>(node);
86  return n && n->to_double()==to_double();
87 }
88 
89 protected:
90 
94 std::string print(const std::string& arg1, const std::string& arg2) const override {
95  std::stringstream ss;
96  ss.precision(Matrix<SXElem>::get_precision());
97  ss.width(Matrix<SXElem>::get_width());
99  ss.setf(std::ios::scientific);
100  } else {
101  ss.unsetf(std::ios::scientific);
102  }
103  ss << to_double();
104  return ss.str();
105  }
106 
107 };
108 
119 class RealtypeSX : public ConstantSX {
120  private:
122  explicit RealtypeSX(double value) : value(value) {}
123 
124  public:
125 
127  ~RealtypeSX() override {
128 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
129  // Safe access to cached_constants_
130  std::lock_guard<std::mutex> lock(mutex_cached_constants);
131 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
132  size_t num_erased = cached_constants_.erase(value);
133  assert(num_erased==1);
134  (void)num_erased;
135  }
136 
138  inline static RealtypeSX* create(double value) {
139 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
140  // Safe access to cached_constants_
141  std::lock_guard<std::mutex> lock(mutex_cached_constants);
142 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
143  // Try to find the constant
144  CACHING_MAP<double, RealtypeSX*>::iterator it = cached_constants_.find(value);
145 
146  // If not found, add it,
147  if (it==cached_constants_.end()) {
148  // Allocate a new object
149  RealtypeSX* n = new RealtypeSX(value);
150 
151  // Add to hash_table
152  cached_constants_.insert(it, std::make_pair(value, n));
153 
154  // Return it to caller
155  return n;
156  } else { // Else, returned the object
157  return it->second;
158  }
159  }
160 
162 
165  double to_double() const override { return value;}
166  casadi_int to_int() const override { return static_cast<casadi_int>(value);}
168 
169  bool is_almost_zero(double tol) const override { return fabs(value)<=tol; }
170 
171  void serialize_node(SerializingStream& s) const override {
172  s.pack("ConstantSX::type", 'r');
173  s.pack("ConstantSX::value", value);
174  }
175 
176  protected:
182  static CACHING_MAP<double, RealtypeSX*> cached_constants_;
183 
184 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
185  static std::mutex mutex_cached_constants;
186 #endif //CASADI_WITH_THREADSAFE_SYMBOLICS
187 
191  double value;
192 };
193 
194 
201 class IntegerSX : public ConstantSX {
202  private:
204  explicit IntegerSX(casadi_int value) : value(static_cast<int>(value)) {
205  casadi_assert(value<=std::numeric_limits<int>::max() &&
206  value>=std::numeric_limits<int>::min(), "Integer overflow");
207  }
208 
209  public:
210 
212  ~IntegerSX() override {
213 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
214  // Safe access to cached_constants_
215  std::lock_guard<std::mutex> lock(mutex_cached_constants);
216 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
217  size_t num_erased = cached_constants_.erase(value);
218  assert(num_erased==1);
219  (void)num_erased;
220  }
221 
223  inline static IntegerSX* create(casadi_int value) {
224 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
225  // Safe access to cached_constants_
226  std::lock_guard<std::mutex> lock(mutex_cached_constants);
227 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
228  // Try to find the constant
229  CACHING_MAP<casadi_int, IntegerSX*>::iterator it = cached_constants_.find(value);
230 
231  // If not found, add it,
232  if (it==cached_constants_.end()) {
233  // Allocate a new object
234  IntegerSX* n = new IntegerSX(value);
235 
236  // Add to hash_table
237  cached_constants_.insert(it, std::make_pair(value, n));
238 
239  // Return it to caller
240  return n;
241  } else { // Else, returned the object
242  return it->second;
243  }
244  }
245 
247 
250  double to_double() const override { return static_cast<double>(value); }
251  casadi_int to_int() const override { return static_cast<casadi_int>(value); }
253 
257  bool is_integer() const override { return true; }
258 
259  void serialize_node(SerializingStream& s) const override {
260  s.pack("ConstantSX::type", 'i');
261  s.pack("ConstantSX::value", value);
262  }
263 
264  protected:
265 
271  static CACHING_MAP<casadi_int, IntegerSX*> cached_constants_;
272 
273 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
274  static std::mutex mutex_cached_constants;
275 #endif //CASADI_WITH_THREADSAFE_SYMBOLICS
276 
280  int value;
281 };
282 
289 class ZeroSX : public ConstantSX {
290 private:
291  /* Private constructor (singleton class) */
292  explicit ZeroSX() {this->count++;}
293 public:
294  /* Get singleton instance */
295  static ZeroSX* singleton() {
296  static ZeroSX instance;
297  return &instance;
298  }
299  /* Destructor */
300  ~ZeroSX() override {this->count--;}
302 
305  double to_double() const override { return 0;}
306  casadi_int to_int() const override { return 0;}
308 
310 
313  bool is_integer() const override { return true; }
314  bool is_zero() const override { return true; }
315  bool is_almost_zero(double tol) const override { return true; }
317 
318  void serialize_node(SerializingStream& s) const override {
319  s.pack("ConstantSX::type", '0');
320  }
321 };
322 
323 
330 class OneSX : public ConstantSX {
331 private:
332  /* Private constructor (singleton class) */
333  explicit OneSX() {this->count++;}
334 public:
335  /* Get singleton instance */
336  static OneSX* singleton() {
337  static OneSX instance;
338  return &instance;
339  }
340  /* Destructor */
341  ~OneSX() override {this->count--;}
345  double to_double() const override { return 1;}
346  casadi_int to_int() const override { return 1;}
347 
351  bool is_integer() const override { return true; }
352  bool is_one() const override { return true; }
353 
354  void serialize_node(SerializingStream& s) const override {
355  s.pack("ConstantSX::type", '1');
356  }
357 
358 };
359 
360 
367 class MinusOneSX : public ConstantSX {
368 private:
369  /* Private constructor (singleton class) */
370  explicit MinusOneSX() {this->count++;}
371 public:
372  /* Get singleton instance */
373  static MinusOneSX* singleton() {
374  static MinusOneSX instance;
375  return &instance;
376  }
377  /* Destructor */
378  ~MinusOneSX() override {this->count--;}
379 
381 
384  double to_double() const override { return -1;}
385  casadi_int to_int() const override { return -1;}
387 
389 
392  bool is_integer() const override { return true; }
393  bool is_minus_one() const override { return true; }
395 
396  void serialize_node(SerializingStream& s) const override {
397  s.pack("ConstantSX::type", 'm');
398  }
399 
400 };
401 
402 
409 class InfSX : public ConstantSX {
410 private:
411  /* Private constructor (singleton class) */
412  explicit InfSX() {this->count++;}
413 public:
414  /* Get singleton instance */
415  static InfSX* singleton() {
416  static InfSX instance;
417  return &instance;
418  }
419  /* Destructor */
420  ~InfSX() override {this->count--;}
424  double to_double() const override { return std::numeric_limits<double>::infinity();}
425 
429  bool is_inf() const override { return true; }
430 
431  void serialize_node(SerializingStream& s) const override {
432  s.pack("ConstantSX::type", 'F');
433  }
434 
435 };
436 
437 
444 class MinusInfSX : public ConstantSX {
445 private:
446  /* Private constructor (singleton class) */
447  explicit MinusInfSX() {this->count++;}
448 public:
449  /* Get singleton instance */
450  static MinusInfSX* singleton() {
451  static MinusInfSX instance;
452  return &instance;
453  }
454  /* Destructor */
455  ~MinusInfSX() override {this->count--;}
456 
460  double to_double() const override { return -std::numeric_limits<double>::infinity();}
461 
465  bool is_minus_inf() const override { return true; }
466 
467  void serialize_node(SerializingStream& s) const override {
468  s.pack("ConstantSX::type", 'f');
469  }
470 };
471 
478 class NanSX : public ConstantSX {
479 private:
480  /* Private constructor (singleton class) */
481  explicit NanSX() {this->count++;}
482 public:
483  /* Get singleton instance */
484  static NanSX* singleton() {
485  static NanSX instance;
486  return &instance;
487  }
488  /* Destructor */
489  ~NanSX() override {this->count--;}
493  double to_double() const override { return std::numeric_limits<double>::quiet_NaN();}
494 
498  bool is_nan() const override { return true; }
499 
500  void serialize_node(SerializingStream& s) const override {
501  s.pack("ConstantSX::type", 'n');
502  }
503 
504 };
505 
506 inline SXNode* ConstantSX_deserialize(DeserializingStream& s) {
507  char type;
508  s.unpack("ConstantSX::type", type);
509  switch (type) {
510  case '1': return casadi_limits<SXElem>::one.get();
511  case '0': return casadi_limits<SXElem>::zero.get();
512  case 'r': {
513  double value;
514  s.unpack("ConstantSX::value", value);
515  return RealtypeSX::create(value);
516  }
517  case 'i': {
518  int value;
519  s.unpack("ConstantSX::value", value);
520  if (value==2) return casadi_limits<SXElem>::two.get();
521  return IntegerSX::create(value);
522  }
523  case 'n': return casadi_limits<SXElem>::nan.get();
524  case 'f': return casadi_limits<SXElem>::minus_inf.get();
525  case 'F': return casadi_limits<SXElem>::inf.get();
526  case 'm': return casadi_limits<SXElem>::minus_one.get();
527  default: casadi_error("ConstantSX::deserialize error");
528  }
529 }
530 
531 } // namespace casadi
533 
534 #endif // CASADI_CONSTANT_SX_HPP
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 const T minus_one
static bool is_half(const T &val)
static bool is_integer(const T &val)
static bool is_value(const T &val, T v)
The casadi namespace.
Definition: archiver.hpp:32
bool is_zero(const T &x)