casadi_c.cpp
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 #include "function.hpp"
27 #include "../casadi_c.h"
28 #include "serializer.hpp"
29 #include <deque>
30 
31 using namespace casadi;
32 
33 // Immortal (leaked) containers: never destructed at process exit, avoiding a
34 // static-destruction-order crash when the user forgets to casadi_c_pop() (#2457)
35 static std::vector<Function>& casadi_c_loaded_functions = *new std::vector<Function>();
36 static std::deque<int>& casadi_c_load_stack = *new std::deque<int>();
37 static int casadi_c_active = -1;
38 
39 int casadi_c_int_width() {
40  return sizeof(casadi_int);
41 }
42 int casadi_c_real_width() {
43  return sizeof(double);
44 }
45 
46 int casadi_c_id(const char* funname) {
47  int ret = -1;
48  std::string fname = funname;
49  for (int i=0;i<casadi_c_loaded_functions.size();++i) {
50  if (fname==casadi_c_loaded_functions.at(i).name()) {
51  if (ret!=-1) {
52  std::cerr << "Ambiguous function name '" << fname << "'" << std::endl;
53  return -2;
54  } else {
55  ret = i;
56  }
57  }
58  }
59  if (ret==-1) {
60  std::cerr << "Could not find function named '" << fname << "'." << std::endl;
61  std::cerr << "Available functions: ";
62  for (const auto& f : casadi_c_loaded_functions) {
63  std::cerr << f.name() << " ";
64  }
65  std::cerr << std::endl;
66  return -1;
67  }
68  return ret;
69 }
70 
71 int casadi_c_n_loaded() { return casadi_c_loaded_functions.size(); }
72 
73 inline int casadi_c_push_file_internal(const char *filename) {
74  try {
76  auto type = fs.pop_type();
77  if (type==SerializerBase::SerializationType::SERIALIZED_FUNCTION) {
78  casadi_c_loaded_functions.push_back(fs.blind_unpack_function());
79  return 0;
80  } else if (type==SerializerBase::SerializationType::SERIALIZED_FUNCTION_VECTOR) {
81  for (const Function& f : fs.blind_unpack_function_vector()) {
82  casadi_c_loaded_functions.push_back(f);
83  }
84  return 0;
85  } else {
86  std::cerr << "Serializer file should contain a 'function' or 'function_vector'. "
87  "Got '" + SerializerBase::type_to_string(type) + "' instead." << std::endl;
88  return -1;
89  }
90  } catch (const std::exception& e) {
91  std::cerr << e.what() << std::endl;
92  return -2;
93  } catch (...) {
94  std::cerr << "Uncaught exception" << std::endl;
95  return -3;
96  }
97 }
98 
99 int casadi_c_push_file(const char *filename) {
100  int before = casadi_c_loaded_functions.size();
101  int ret = casadi_c_push_file_internal(filename);
102  int after = casadi_c_loaded_functions.size();
103  casadi_c_load_stack.push_back(after-before);
104  return ret;
105 }
106 
107 void casadi_c_clear(void) {
108  casadi_c_load_stack.clear();
109  casadi_c_loaded_functions.clear();
110  casadi_c_active = -1;
111 }
112 
113 void casadi_c_pop(void) {
114  int count = casadi_c_load_stack.back();
115  casadi_c_load_stack.pop_back();
116  casadi_c_loaded_functions.erase(
117  casadi_c_loaded_functions.begin()+(casadi_c_loaded_functions.size()-count),
118  casadi_c_loaded_functions.end());
119 }
120 
121 inline int sanitize_id(int id) {
122  if (id<0 || id>=casadi_c_loaded_functions.size()) {
123  std::cerr << "id " << id << " is out of range: must be in [0, ";
124  std::cerr << casadi_c_loaded_functions.size() << "[" << std::endl;
125  return 1;
126  }
127  return 0;
128 }
129 
130 int casadi_c_activate(int id) {
131  if (sanitize_id(id)) return -1;
132  casadi_c_active = id;
133  return 0;
134 }
135 
136 void casadi_c_incref(void) {}
137 void casadi_c_decref(void) {}
138 void casadi_c_incref_id(int id) {}
139 void casadi_c_decref_id(int id) {}
140 
141 int casadi_c_checkout(void) {
142  return casadi_c_checkout_id(casadi_c_active);
143 }
144 int casadi_c_checkout_id(int id) {
145  if (sanitize_id(id)) return -1;
146  try {
147  return casadi_c_loaded_functions.at(id).checkout();
148  } catch (const std::exception& e) {
149  std::cerr << e.what() << std::endl;
150  return -2;
151  } catch (...) {
152  std::cerr << "Uncaught exception" << std::endl;
153  return -3;
154  }
155 }
156 
157 void casadi_c_release(int mem) {
158  casadi_c_release_id(casadi_c_active, mem);
159 }
160 void casadi_c_release_id(int id, int mem) {
161  sanitize_id(id);
162  try {
163  casadi_c_loaded_functions.at(id).release(mem);
164  } catch (const std::exception& e) {
165  std::cerr << e.what() << std::endl;
166  } catch (...) {
167  std::cerr << "Uncaught exception" << std::endl;
168  }
169 }
170 
171 double casadi_c_default_in(casadi_int i) {
172  return casadi_c_default_in_id(casadi_c_active, i);
173 }
174 double casadi_c_default_in_id(int id, casadi_int i) {
175  if (sanitize_id(id)) return -1;
176  try {
177  return casadi_c_loaded_functions.at(id).default_in(i);
178  } catch (const std::exception& e) {
179  std::cerr << e.what() << std::endl;
180  return -2;
181  } catch (...) {
182  std::cerr << "Uncaught exception" << std::endl;
183  return -3;
184  }
185 }
186 
187 casadi_int casadi_c_n_in(void) {
188  return casadi_c_n_in_id(casadi_c_active);
189 }
190 casadi_int casadi_c_n_in_id(int id) {
191  if (sanitize_id(id)) return -1;
192  try {
193  return casadi_c_loaded_functions.at(id).n_in();
194  } catch (const std::exception& e) {
195  std::cerr << e.what() << std::endl;
196  return -2;
197  } catch (...) {
198  std::cerr << "Uncaught exception" << std::endl;
199  return -3;
200  }
201 }
202 
203 casadi_int casadi_c_n_out(void) {
204  return casadi_c_n_out_id(casadi_c_active);
205 }
206 casadi_int casadi_c_n_out_id(int id) {
207  if (sanitize_id(id)) return -1;
208  try {
209  return casadi_c_loaded_functions.at(id).n_out();
210  } catch (const std::exception& e) {
211  std::cerr << e.what() << std::endl;
212  return -2;
213  } catch (...) {
214  std::cerr << "Uncaught exception" << std::endl;
215  return -3;
216  }
217 }
218 
219 const char* casadi_c_name() {
220  return casadi_c_name_id(casadi_c_active);
221 }
222 const char* casadi_c_name_id(int id) {
223  if (sanitize_id(id)) return "";
224  static std::string name;
225  name = casadi_c_loaded_functions.at(id).name();
226  return name.c_str();
227 }
228 
229 const char* casadi_c_name_in(casadi_int i) {
230  return casadi_c_name_in_id(casadi_c_active, i);
231 }
232 const char* casadi_c_name_in_id(int id, casadi_int i) {
233  if (sanitize_id(id)) return "";
234  try {
235  return casadi_c_loaded_functions.at(id).name_in(i).c_str();
236  } catch (const std::exception& e) {
237  std::cerr << e.what() << std::endl;
238  return "";
239  } catch (...) {
240  std::cerr << "Uncaught exception" << std::endl;
241  return "";
242  }
243 }
244 
245 const char* casadi_c_name_out(casadi_int i) {
246  return casadi_c_name_out_id(casadi_c_active, i);
247 }
248 const char* casadi_c_name_out_id(int id, casadi_int i) {
249  if (sanitize_id(id)) return "";
250  try {
251  return casadi_c_loaded_functions.at(id).name_out(i).c_str();
252  } catch (const std::exception& e) {
253  std::cerr << e.what() << std::endl;
254  return "";
255  } catch (...) {
256  std::cerr << "Uncaught exception" << std::endl;
257  return "";
258  }
259 }
260 
261 const casadi_int* casadi_c_sparsity_in(casadi_int i) {
262  return casadi_c_sparsity_in_id(casadi_c_active, i);
263 }
264 const casadi_int* casadi_c_sparsity_in_id(int id, casadi_int i) {
265  if (sanitize_id(id)) return nullptr;
266  try {
267  return casadi_c_loaded_functions.at(id).sparsity_in(i);
268  } catch (const std::exception& e) {
269  std::cerr << e.what() << std::endl;
270  return nullptr;
271  } catch (...) {
272  std::cerr << "Uncaught exception" << std::endl;
273  return nullptr;
274  }
275 }
276 
277 const casadi_int* casadi_c_sparsity_out(casadi_int i) {
278  return casadi_c_sparsity_out_id(casadi_c_active, i);
279 }
280 const casadi_int* casadi_c_sparsity_out_id(int id, casadi_int i) {
281  if (sanitize_id(id)) return nullptr;
282  try {
283  return casadi_c_loaded_functions.at(id).sparsity_out(i);
284  } catch (const std::exception& e) {
285  std::cerr << e.what() << std::endl;
286  return nullptr;
287  } catch (...) {
288  std::cerr << "Uncaught exception" << std::endl;
289  return nullptr;
290  }
291 }
292 
293 int casadi_c_work(casadi_int *sz_arg, casadi_int* sz_res,
294  casadi_int *sz_iw, casadi_int *sz_w) {
295  return casadi_c_work_id(casadi_c_active, sz_arg, sz_res, sz_iw, sz_w);
296 }
297 
298 int casadi_c_work_id(int id, casadi_int *sz_arg, casadi_int* sz_res,
299  casadi_int *sz_iw, casadi_int *sz_w) {
300  if (sanitize_id(id)) return -1;
301  try {
302  *sz_arg = casadi_c_loaded_functions.at(id).sz_arg();
303  *sz_res = casadi_c_loaded_functions.at(id).sz_res();
304  *sz_iw = casadi_c_loaded_functions.at(id).sz_iw();
305  *sz_w = casadi_c_loaded_functions.at(id).sz_w();
306  } catch (const std::exception& e) {
307  std::cerr << e.what() << std::endl;
308  return -2;
309  } catch (...) {
310  std::cerr << "Uncaught exception" << std::endl;
311  return -3;
312  }
313  return 0;
314 }
315 
316 int casadi_c_eval(const double** arg, double** res, casadi_int* iw, double* w, int mem) {
317  return casadi_c_eval_id(casadi_c_active, arg, res, iw, w, mem);
318 }
319 
320 int casadi_c_eval_id(int id, const double** arg, double** res, casadi_int* iw, double* w, int mem) {
321  if (sanitize_id(id)) return -1;
322  try {
323  return casadi_c_loaded_functions.at(id)(arg, res, iw, w, mem);
324  } catch (const std::exception& e) {
325  std::cerr << e.what() << std::endl;
326  return -2;
327  } catch (...) {
328  std::cerr << "Uncaught exception" << std::endl;
329  return -3;
330  }
331  return 0;
332 }
333 
334 
335 void casadi_c_logger_write(const char* msg, int num) {
336  casadi::uout().write(msg, num);
337 }
338 
339 void casadi_c_logger_flush(void) {
340  casadi::uout() << std::flush;
341 }
Function object.
Definition: function.hpp:60
static std::string type_to_string(SerializationType type)
Definition: serializer.cpp:53
The casadi namespace.
Definition: archiver.cpp:28
std::ostream & uout()
std::string filename(const std::string &path)
Definition: ghc.cpp:55