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