casadi_common.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_COMMON_HPP
27 #define CASADI_COMMON_HPP
28 
29 #include <algorithm>
30 #include <climits>
31 #include <cmath>
32 #include <fstream>
33 #include <iostream>
34 #include <new>
35 #include <iterator>
36 #include <limits>
37 #include <map>
38 #include <set>
39 #include <sstream>
40 #include <string>
41 #include <utility>
42 #include <vector>
43 
44 #ifdef SWIG
45 #define SWIG_IF_ELSE(is_swig, not_swig) is_swig
46 #define SWIG_OUTPUT(arg) OUTPUT
47 #define SWIG_INOUT(arg) INOUT
48 // Numbered variants: SWIG matches the &INOUT typemaps by parameter NAME, so a
49 // function with several in-out arguments needs distinct ones (casadi.i %applies
50 // INOUT1..INOUT6). Reusing plain SWIG_INOUT twice emits duplicate parameter
51 // names into the generated .pyi, which is then not valid Python.
52 #define SWIG_INOUT1(arg) INOUT1
53 #define SWIG_INOUT2(arg) INOUT2
54 #define SWIG_INOUT3(arg) INOUT3
55 #define SWIG_INOUT4(arg) INOUT4
56 #define SWIG_INOUT5(arg) INOUT5
57 #define SWIG_INOUT6(arg) INOUT6
58 #define SWIG_CONSTREF(arg) const arg
59 #ifdef SWIGMATLAB
60 #define SWIG_IND1 true
61 #else // SWIGMATLAB
62 #define SWIG_IND1 false
63 #endif // SWIGMATLAB
64 #else // SWIG
65 #define SWIG_IF_ELSE(is_swig, not_swig) not_swig
66 #define SWIG_OUTPUT(arg) arg
67 #define SWIG_INOUT(arg) arg
68 #define SWIG_INOUT1(arg) arg
69 #define SWIG_INOUT2(arg) arg
70 #define SWIG_INOUT3(arg) arg
71 #define SWIG_INOUT4(arg) arg
72 #define SWIG_INOUT5(arg) arg
73 #define SWIG_INOUT6(arg) arg
74 #define SWIG_CONSTREF(arg) const arg &
75 #define SWIG_IND1 false
76 #endif // SWIG
77 
78 #include "casadi_types.hpp"
79 
80 namespace casadi {
81 
83  class SXElem;
84  class MX;
85  template<class T> class Matrix;
86  class Function;
87  class Sparsity;
88  class CodeGenerator;
89  class NlpBuilder;
90  struct Variable;
91  class DaeBuilder;
92  class XmlFile;
93  class Importer;
94 
95 #ifndef SWIG
96 // Get GCC version if GCC is used
97 #ifdef __GNUC__
98 #ifdef __GNUC_MINOR__
99 #ifdef __GNUC_PATCHLEVEL__
100 #define GCC_VERSION (__GNUC__ * 10000 +__GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
101 #endif // __GNUC_PATCHLEVEL__
102 #endif // __GNUC_MINOR__
103 #endif // __GNUC__
104 
105 // Disable some Visual studio warnings
106 #ifdef _MSC_VER
107 
108 // warning C4018: '<' : signed/unsigned mismatch
109 #pragma warning(disable:4018)
110 
111 // warning C4244: Potential loss of data converting double to int
112 #pragma warning(disable:4244)
113 
114 // warning C4251: Need a dll interface?
115 #pragma warning(disable:4251)
116 
117 // warning C4275: non dll-interface class 'std::exception' used as base for dll-interface
118 // class 'casadi::CasadiException'
119 #pragma warning(disable:4275)
120 
121 // warning C4715: Not all control paths return a value
122 #pragma warning(disable:4715)
123 
124 // warning C4800: 'int' : forcing value to bool 'true'or 'false'(performance warning)
125 #pragma warning(disable:4800)
126 
127 // warning C4910: __declspec(dllexport) and extern incompatible on an explicit instantiation
128 #pragma warning(disable:4910)
129 
130 // warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s
131 // instead
132 #pragma warning(disable:4996)
133 
134 #endif // _MSC_VER
135 
136  // Macro "minor" is sometimes defined, cf.
137  // https://stackoverflow.com/questions/22240973/major-and-minor-macros-defined-in-sys-sysmacros-h-pulled-in-by-iterator
138 #undef minor
139 
140  // Type with a size corresponding to that of double (or smaller) that can be used to hold a set
141  // of booleans
142  typedef unsigned long long bvec_t;
143 
144  // Number of directions we can deal with at a time
145  // the size of bvec_t in bits (CHAR_BIT is the number of bits per byte, usually 8)
146  const int bvec_size = CHAR_BIT*sizeof(bvec_t);
147 
148  // Make sure that the integer datatype is indeed smaller or equal to the double
149  //assert(sizeof(bvec_t) <= sizeof(double)); // doesn't work - very strange
150 
152 
155  typedef int (*config_t)(int, const char**);
156  typedef void (*signal_t)(void);
157  typedef casadi_int (*getint_t)(void);
158  typedef double (*default_t)(casadi_int i);
159  typedef const char* (*name_t)(casadi_int i);
160  typedef const casadi_int* (*sparsity_t)(casadi_int i);
161  typedef int (*diff_t)(casadi_int i);
162  typedef int (*casadi_checkout_t)(void);
163  typedef void (*casadi_release_t)(int);
164  typedef int (*work_t)(casadi_int* sz_arg, casadi_int* sz_res,
165  casadi_int* sz_iw, casadi_int* sz_w);
166  typedef int (*eval_t)(const double** arg, double** res,
167  casadi_int* iw, double* w, int);
169 
170  // Easier to maintain than an enum (serialization/codegen)
171  constexpr casadi_int LOOKUP_LINEAR = 0;
172  constexpr casadi_int LOOKUP_EXACT = 1;
173  constexpr casadi_int LOOKUP_BINARY = 2;
174 
176  template<typename T>
177  std::string str(const T& v);
178 
180  template<typename T>
181  std::string str(const T& v, bool more);
182 
184  template<typename T>
185  std::string str(const std::vector<T>& v, bool more=false);
186 
188  template<typename T>
189  std::string str(const std::set<T>& v, bool more=false);
190 
192  template<typename T1, typename T2>
193  std::string str(const std::pair<T1, T2>& p, bool more=false);
194 
196  template<typename T1, typename T2>
197  std::string str(const std::map<T1, T2> &p, bool more=false);
198 
200  template<typename T2>
201  std::string str(const std::map<std::string, T2> &p, bool more=false);
202 
204  template<typename T, size_t N>
205  std::string str(const std::array<T, N> &p, bool more=false);
206 
208  inline std::vector<std::string> strvec() {
209  return {};
210  }
211 
213  template<typename T1>
214  inline std::vector<std::string> strvec(const T1& t1) {
215  return {str(t1)};
216  }
217 
219  template<typename T1, typename T2>
220  inline std::vector<std::string> strvec(const T1& t1, const T2& t2) {
221  return {str(t1), str(t2)};
222  }
223 
225  template<typename T1, typename T2, typename T3>
226  inline std::vector<std::string> strvec(const T1& t1, const T2& t2, const T3& t3) {
227  return {str(t1), str(t2), str(t3)};
228  }
229 
231  template<typename T1, typename T2, typename T3, typename T4>
232  inline std::vector<std::string> strvec(const T1& t1, const T2& t2, const T3& t3,
233  const T4& t4) {
234  return {str(t1), str(t2), str(t3), str(t4)};
235  }
236 
238  template<typename T1, typename T2, typename T3, typename T4, typename T5>
239  inline std::vector<std::string> strvec(const T1& t1, const T2& t2, const T3& t3,
240  const T4& t4, const T5& t5) {
241  return {str(t1), str(t2), str(t3), str(t4), str(t5)};
242  }
243 
245  template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
246  inline std::vector<std::string> strvec(const T1& t1, const T2& t2, const T3& t3,
247  const T4& t4, const T5& t5, const T6& t6) {
248  return {str(t1), str(t2), str(t3), str(t4), str(t5), str(t6)};
249  }
250 
252  inline std::string fmtstr(const std::string& fmt, const std::vector<std::string>& args) {
253  std::string s = fmt;
254  for (auto&& e : args) {
255  std::string::size_type n = s.find("%s");
256  if (n==std::string::npos) return "** Ill-formatted string ** " + fmt;
257  s.replace(n, 2, e);
258  }
259  return s;
260  }
261 
262  // Implementations
263  template<typename T>
264  std::string str(const T& v) {
265  std::stringstream ss;
266  ss << v;
267  return ss.str();
268  }
269 
270  template<typename T>
271  std::string str(const T& v, bool more) {
272  return v.get_str(more);
273  }
274 
275  template<typename T>
276  std::string str(const std::vector<T>& v, bool more) {
277  std::stringstream ss;
278  ss << "[";
279  for (casadi_int i=0; i<v.size(); ++i) {
280  if (i!=0) ss << ", ";
281  ss << str(v[i]);
282  }
283  ss << "]";
284  return ss.str();
285  }
286 
287  template<typename T>
288  std::string str(const std::set<T>& v, bool more) {
289  std::stringstream ss;
290  ss << "{";
291  casadi_int cnt = 0;
292  for (const auto& e : v) {
293  if (cnt++!=0) ss << ", ";
294  ss << str(e);
295  }
296  ss << "}";
297  return ss.str();
298  }
299 
300  template<typename T1, typename T2>
301  std::string str(const std::pair<T1, T2>& p, bool more) {
302  std::stringstream ss;
303  ss << "[" << str(p.first) << "," << str(p.second) << "]";
304  return ss.str();
305  }
306 
307  template<typename T1, typename T2>
308  std::string str(const std::map<T1, T2>& p, bool more) {
309  std::stringstream ss;
310  ss << "{";
311  casadi_int count = 0;
312  for (auto& e : p) {
313  ss << str(e.first) << ": " << str(e.second);
314  if (++count < p.size()) ss << ", ";
315  }
316  ss << "}";
317  return ss.str();
318  }
319 
320  template<typename T2>
321  std::string str(const std::map<std::string, T2>& p, bool more) {
322  std::stringstream ss;
323  ss << "{";
324  casadi_int count = 0;
325  for (auto& e : p) {
326  ss << "\"" << e.first << "\": " << str(e.second);
327  if (++count < p.size()) ss << ", ";
328  }
329  ss << "}";
330  return ss.str();
331  }
332 
333  template<typename T, size_t N>
334  std::string str(const std::array<T, N> &v, bool more) {
335  std::stringstream ss;
336  ss << "[";
337  for (casadi_int i=0; i<N; ++i) {
338  if (i!=0) ss << ", ";
339  ss << str(v[i]);
340  }
341  ss << "]";
342  return ss.str();
343  }
344 
345 
354  template<typename T>
355  class ThreadLocalStorage {
356  alignas(T) char storage_[sizeof(T)];
357  bool init_ = false;
358  public:
359  T& get() {
360  if (!init_) {
361  new (storage_) T();
362  init_ = true;
363  }
364  return *reinterpret_cast<T*>(storage_);
365  }
366  // Trivial destructor - intentionally no cleanup
367  };
368 
369  template<typename _Mutex>
370  class conditional_lock_guard {
371  public:
372  typedef _Mutex mutex_type;
373 
374  conditional_lock_guard(mutex_type& m, bool condition) : mtx_(m), condition_(condition) {
375  if (condition_) mtx_.lock();
376  }
377 
378  ~conditional_lock_guard() {
379  if (condition_) mtx_.unlock();
380  }
381 
382  conditional_lock_guard(const conditional_lock_guard&) = delete;
383  conditional_lock_guard& operator=(const conditional_lock_guard&) = delete;
384 
385  private:
386  mutex_type& mtx_;
387  bool condition_;
388  };
389 
390 #endif // SWIG
391 } // namespace casadi
392 
393 #include "casadi_logger.hpp"
394 
395 #endif // CASADI_COMMON_HPP
The casadi namespace.
Definition: archiver.hpp:32