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