code_generator.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 
27 #include "code_generator.hpp"
28 #include "function_internal.hpp"
29 #include "convexify.hpp"
30 #include <casadi_runtime_str.h>
31 #include "global_options.hpp"
32 #include "filesystem_impl.hpp"
33 #include <iomanip>
34 
35 namespace casadi {
36 
37  CodeGenerator::CodeGenerator(const std::string& name, const Dict& opts) {
38  // Default options
39  this->verbose = true;
40  this->verbose_runtime = false;
41  this->mex = false;
42  this->with_sfunction = false;
43  this->unroll_args = false;
44  this->cpp = false;
45  this->main = false;
46  this->casadi_real_type = "double";
47  this->casadi_int_type = CASADI_INT_TYPE_STR;
48  this->codegen_scalars = false;
49  this->with_header = false;
50  this->with_mem = false;
51  this->with_export = true;
52  this->with_import = false;
53  this->include_math = true;
54  this->infinity = "INFINITY";
55  this->nan = "NAN";
56  this->real_min = "";
57  bool prefix_set = false;
58  this->prefix = "";
59  this->max_declarations_per_line = 12;
61  this->force_canonical = false;
62 
63  avoid_stack_ = false;
64  indent_ = 2;
65  sz_zeros_ = 0;
66  sz_ones_ = 0;
67 
68  // Read options
69  for (auto&& e : opts) {
70  if (e.first=="verbose") {
71  this->verbose = e.second;
72  } else if (e.first=="verbose_runtime") {
73  this->verbose_runtime = e.second;
74  } else if (e.first=="mex") {
75  this->mex = e.second;
76  } else if (e.first=="with_sfunction") {
77  this->with_sfunction = e.second;
78  } else if (e.first=="unroll_args") {
79  this->unroll_args = e.second;
80  } else if (e.first=="cpp") {
81  this->cpp = e.second;
82  } else if (e.first=="main") {
83  this->main = e.second;
84  } else if (e.first=="casadi_real") {
85  this->casadi_real_type = e.second.to_string();
86  } else if (e.first=="casadi_int") {
87  this->casadi_int_type = e.second.to_string();
88  } else if (e.first=="codegen_scalars") {
89  this->codegen_scalars = e.second;
90  } else if (e.first=="with_header") {
91  this->with_header = e.second;
92  } else if (e.first=="with_mem") {
93  this->with_mem = e.second;
94  } else if (e.first=="with_export") {
95  this->with_export = e.second;
96  } else if (e.first=="with_import") {
97  this->with_import = e.second;
98  } else if (e.first=="include_math") {
99  this->include_math = e.second;
100  } else if (e.first=="infinity") {
101  this->infinity = e.second.to_string();
102  } else if (e.first=="nan") {
103  this->nan = e.second.to_string();
104  } else if (e.first=="real_min") {
105  this->real_min = e.second.to_string();
106  } else if (e.first=="indent") {
107  indent_ = e.second;
108  casadi_assert_dev(indent_>=0);
109  } else if (e.first=="avoid_stack") {
110  avoid_stack_ = e.second;
111  } else if (e.first=="prefix") {
112  this->prefix = e.second.to_string();
113  prefix_set = true;
114  } else if (e.first=="max_declarations_per_line") {
115  this->max_declarations_per_line = e.second;
116  casadi_assert(this->max_declarations_per_line>=0,
117  "Option max_declarations_per_line must be >=0");
118  } else if (e.first=="max_initializer_elements_per_line") {
119  this->max_initializer_elements_per_line = e.second;
120  casadi_assert(this->max_initializer_elements_per_line>=0,
121  "Option max_initializer_elements_per_line must be >=0");
122  } else if (e.first=="force_canonical") {
123  this->force_canonical = e.second;
124  } else {
125  casadi_error("Unrecognized option: " + str(e.first));
126  }
127  }
128 
129  // If real_min is not specified, make an educated guess
130  if (this->real_min.empty()) {
131  std::stringstream ss;
132  ss << std::scientific << std::setprecision(std::numeric_limits<double>::digits10 + 1);
133  if (casadi_real_type=="float") {
134  ss << std::numeric_limits<float>::min();
135  this->real_min = ss.str();
136  } else if (casadi_real_type=="double") {
137  ss << std::numeric_limits<double>::min();
138  this->real_min = ss.str();
139  } else {
140  this->real_min = "<NOT SPECIFIED>";
141  }
142  }
143 
144  // Start at new line with no indentation
145  newline_ = true;
146  current_indent_ = 0;
147 
148  // Start off without the need for thread-local memory
149  needs_mem_ = false;
150 
151  // Divide name into base and suffix (if any)
152  std::string::size_type dotpos = name.rfind('.');
153  if (dotpos==std::string::npos) {
154  this->name = name;
155  this->suffix = this->cpp ? ".cpp" : ".c";
156  } else {
157  this->name = name.substr(0, dotpos);
158  this->suffix = name.substr(dotpos);
159  }
160 
161  // Symbol prefix
162  if (this->with_export) dll_export = "CASADI_SYMBOL_EXPORT ";
163  if (this->with_import) dll_import = "CASADI_SYMBOL_IMPORT ";
164 
165  // Make sure that the base name is sane
166  casadi_assert_dev(Function::check_name(this->name));
167 
168  // Includes needed
169  if (this->include_math) add_include("math.h");
170  if (this->main) add_include("stdio.h");
172 
173  // Mex and main need string.h
174  if (this->mex || this->main) {
175  add_include("string.h");
176  }
177 
178  // Mex
179  if (this->mex) {
180  add_include("mex.h", false, "MATLAB_MEX_FILE");
181  }
182 
183  // s-Function
184  if (this->with_sfunction) {
185  this->casadi_real_type = "real_T";
186  this->casadi_int_type = "int_T";
187  this->with_header = true;
188  add_include("simstruc.h");
189  }
190 
191  // Memory struct entry point
192  if (this->with_mem) {
193  this->header << "#include <casadi/mem.h>\n";
194  }
195 
196  // Use name as default prefix
197  if (!prefix_set) {
198  this->prefix = this->name;
199  }
200 
201  }
202 
204  local_variables_.clear();
205  local_default_.clear();
206  }
207 
209  // Order local variables
210  std::map<std::string, std::set<std::pair<std::string, std::string>>> local_variables_by_type;
211  for (auto&& e : local_variables_) {
212  local_variables_by_type[e.second.first].insert(std::make_pair(e.first, e.second.second));
213  }
214 
215  // Codegen local variables
216  for (auto&& e : local_variables_by_type) {
217  casadi_int cnt = 0;
218  for (auto it=e.second.begin(); it!=e.second.end(); ++it) {
219  bool split_declaration = it==e.second.begin() ||
221  if (split_declaration) {
222  if (it!=e.second.begin()) body << ";\n";
223  body << " " << e.first << " ";
224  } else {
225  body << ", ";
226  }
227  body << it->second << it->first;
228  // Insert definition, if any
229  auto k=local_default_.find(it->first);
230  if (k!=local_default_.end()) body << "=" << k->second;
231  cnt++;
232  }
233  body << ";\n";
234  }
235  }
236 
237  std::string CodeGenerator::wrapper(const Function& base, const std::string& name) {
238  FunctionInternal* f = base.get();
239  std::map<FunctionInternal*, casadi_int>& funs = added_wrappers_[name];
240  auto it = funs.find(f);
241  if (it==funs.end()) {
242  casadi_int n = funs.size();
243  funs[f] = n;
244  return name + str(n);
245  } else {
246  return name + str(it->second);
247  }
248  }
249 
250  std::string CodeGenerator::add_dependency(const Function& f) {
251  // Quick return if it already exists
252  for (auto&& e : added_functions_) if (e.f==f) return e.codegen_name;
253 
254  // Give it a name
255  std::string fname = shorthand("f" + str(added_functions_.size()));
256 
257  // Add to list of functions
258  added_functions_.push_back({f, fname});
259 
260  // Generate declarations
261  f->codegen_declarations(*this);
262 
263  // Print to file
264  f->codegen(*this, fname);
265 
266  // Codegen reference count functions, if needed
267  if (f->has_refcount_) {
268  // Increase reference counter
269  *this << "void " << fname << "_incref(void) {\n";
270  f->codegen_incref(*this);
271  *this << "}\n\n";
272 
273  // Decrease reference counter
274  *this << "void " << fname << "_decref(void) {\n";
275  f->codegen_decref(*this);
276  *this << "}\n\n";
277  }
278 
279  bool fun_needs_mem = !f->codegen_mem_type().empty();
280  needs_mem_ |= fun_needs_mem;
281 
282  if (fun_needs_mem) {
283  // Alloc memory
284  *this << "int " << fname << "_alloc_mem(void) {\n";
285  flush(this->body);
286  scope_enter();
287  f->codegen_alloc_mem(*this);
288  scope_exit();
289  *this << "}\n\n";
290 
291  // Initialize memory
292  *this << "int " << fname << "_init_mem(int mem) {\n";
293  flush(this->body);
294  scope_enter();
295  f->codegen_init_mem(*this);
296  scope_exit();
297  *this << "}\n\n";
298 
299  // Clear memory
300  *this << "void " << fname << "_free_mem(int mem) {\n";
301  flush(this->body);
302  scope_enter();
303  f->codegen_free_mem(*this);
304  scope_exit();
305  *this << "}\n\n";
306 
307  // Checkout
308  *this << "int " << fname << "_checkout(void) {\n";
309  flush(this->body);
310  scope_enter();
311  f->codegen_checkout(*this);
312  scope_exit();
313  *this << "}\n\n";
314 
315  // Clear memory
316  *this << "void " << fname << "_release(int mem) {\n";
317  flush(this->body);
318  scope_enter();
319  f->codegen_release(*this);
320  scope_exit();
321  *this << "}\n\n";
322 
323  }
324 
325  // Flush to body
326  flush(this->body);
327 
328  return fname;
329  }
330 
331  void CodeGenerator::add(const Function& f, bool with_jac_sparsity) {
332  // Add if not already added
333  std::string codegen_name = add_dependency(f);
334 
335  // Define function
336  *this << declare(f->signature(f.name())) << "{\n"
337  << "return " << codegen_name << "(arg, res, iw, w, mem);\n"
338  << "}\n\n";
339 
340  if (this->unroll_args) {
341  // Define function
342  *this << declare(f->signature_unrolled(f.name())) << "{\n";
343  for (casadi_int i=0; i<f.n_in(); ++i) {
344  *this << "arg[" << i << "] = " << f.name_in(i) << ";\n";
345  }
346  for (casadi_int i=0; i<f.n_out(); ++i) {
347  *this << "res[" << i << "] = " << f.name_out(i) << ";\n";
348  }
349  *this << "return " << codegen_name << "(arg, res, iw, w, mem);\n";
350  *this << "}\n\n";
351  // Flush buffers
352  flush(this->body);
353  }
354 
355  // Generate meta information
356  f->codegen_meta(*this);
357 
358  // Generate Jacobian sparsity information
359  if (with_jac_sparsity) {
360  // Generate/get Jacobian sparsity
361  std::vector<Sparsity> jac = f.jac_sparsity();
362  // Code generate the sparsity pattern
363  add_io_sparsities("jac_" + f.name(), f->sparsity_in_, jac);
364 
365  // Flush buffers
366  flush(this->body);
367  }
368 
369  // Generate function specific code for Simulink sfunction
370  if (this->with_sfunction) this->added_sfunctions.push_back( this->codegen_sfunction(f) );
371 
372  // Add to list of exposed symbols
373  this->exposed_fname.push_back(f.name());
374  }
375 
376  std::string CodeGenerator::dump() {
377  std::stringstream s;
378  dump(s);
379  return s.str();
380  }
381 
383  std::stringstream ss;
384  ss << CASADI_MAJOR_VERSION << "." << CASADI_MINOR_VERSION << "." << CASADI_PATCH_VERSION;
385  if (!CASADI_IS_RELEASE) ss << "+";
386  return ss.str();
387  }
388 
389  void CodeGenerator::stream_open(std::ostream& f, bool cpp) {
390 
391  // Print header
392  f << "/* This file was automatically generated by CasADi " << casadi_version() << ".\n"
393  << " * It consists of: \n"
394  << " * 1) content generated by CasADi runtime: not copyrighted\n"
395  << " * 2) template code copied from CasADi source: permissively licensed (MIT-0)\n"
396  << " * 3) user code: owned by the user\n"
397  << " *\n"
398  << " */\n";
399 
400  // C linkage
401  if (!cpp) {
402  f << "#ifdef __cplusplus\n"
403  << "extern \"C\" {\n"
404  << "#endif\n\n";
405  }
406  }
407 
408  void CodeGenerator::stream_close(std::ostream& f, bool cpp) {
409  // C linkage
410  if (!cpp) {
411  f << "#ifdef __cplusplus\n"
412  << "} /* extern \"C\" */\n"
413  << "#endif\n";
414  }
415  }
416 
417  void CodeGenerator::generate_casadi_real(std::ostream &s) const {
418  s << "#ifndef casadi_real\n"
419  << "#define casadi_real " << this->casadi_real_type << std::endl
420  << "#endif\n\n";
421  }
422 
423  void CodeGenerator::generate_export_symbol(std::ostream &s) const {
424  s << "/* Symbol visibility in DLLs */\n"
425  << "#ifndef CASADI_SYMBOL_EXPORT\n"
426  << " #if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)\n"
427  << " #if defined(STATIC_LINKED)\n"
428  << " #define CASADI_SYMBOL_EXPORT\n"
429  << " #else\n"
430  << " #define CASADI_SYMBOL_EXPORT __declspec(dllexport)\n"
431  << " #endif\n"
432  << " #elif defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY)\n"
433  << " #define CASADI_SYMBOL_EXPORT __attribute__ ((visibility (\"default\")))\n"
434  << " #else" << std::endl
435  << " #define CASADI_SYMBOL_EXPORT\n"
436  << " #endif\n"
437  << "#endif\n\n";
438  }
439 
440  void CodeGenerator::generate_import_symbol(std::ostream &s) const {
441  s << "/* Symbol visibility in DLLs */\n"
442  << "#ifndef CASADI_SYMBOL_IMPORT\n"
443  << " #if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)\n"
444  << " #if defined(STATIC_LINKED)\n"
445  << " #define CASADI_SYMBOL_IMPORT\n"
446  << " #else\n"
447  << " #define CASADI_SYMBOL_IMPORT __declspec(dllimport)\n"
448  << " #endif\n"
449  << " #elif defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY)\n"
450  << " #define CASADI_SYMBOL_IMPORT __attribute__ ((visibility (\"default\")))\n"
451  << " #else" << std::endl
452  << " #define CASADI_SYMBOL_IMPORT\n"
453  << " #endif\n"
454  << "#endif\n\n";
455  }
456 
457  void CodeGenerator::generate_casadi_int(std::ostream &s) const {
458  s << "#ifndef casadi_int\n"
459  << "#define casadi_int " << this->casadi_int_type << std::endl
460  << "#endif\n\n";
461  }
462 
463  std::string CodeGenerator::generate(const std::string& prefix) {
464  // Throw an error if the prefix contains the filename, since since syntax
465  // has changed
466  casadi_assert(prefix.find(this->name + this->suffix)==std::string::npos,
467  "The signature of CodeGenerator::generate has changed. "
468  "Instead of providing the filename, only provide the prefix.");
469 
470  // Create c file
471  std::string fullname = prefix + this->name + this->suffix;
472 
473  auto s_ptr = Filesystem::ofstream_ptr(fullname);
474  std::ostream& s = *s_ptr;
475  stream_open(s, this->cpp);
476 
477  // Dump code to file
478  dump(s);
479 
480  if (!pool_double_defaults_.empty()) {
481  s << "CASADI_SYMBOL_EXPORT casadi_real* CASADI_PREFIX(get_pool_double)(const char* name) {\n";
482  for (const auto& e : pool_double_) {
483  casadi_int i = e.second;
484  s << " if (strcmp(name, \"" + e.first + "\")==0) "
485  << "return casadi_pd" + str(i) + ";\n";
486  }
487  s << " return 0;\n";
488  s << "}\n";
489  }
490 
491  // Mex entry point
492  if (this->mex) generate_mex(s);
493 
494  // Main entry point
495  if (this->main) generate_main(s);
496 
497  // Finalize file
498  stream_close(s, this->cpp);
499  s_ptr.reset();
500 
501  // Generate s-function
502  if (this->with_sfunction) {
503  for (unsigned ii=0; ii<this->added_sfunctions.size(); ii++) {
504  std::string sfunction_code = this->added_sfunctions.at(ii);
505  std::string sfunction_name = this->exposed_fname.at(ii);
506  generate_sfunction(sfunction_name, sfunction_code);
507  }
508  }
509 
510  // Generate header
511  if (this->with_header) {
512  auto s_ptr = Filesystem::ofstream_ptr(prefix + this->name + ".h");
513  std::ostream& s = *s_ptr;
514  // Create a header file
515  stream_open(s, this->cpp);
516 
517  // Define the casadi_real type (typically double)
518  generate_casadi_real(s);
519 
520  // Define the casadi_int type
521  generate_casadi_int(s);
522 
523  // Generate export symbol macros
524  if (this->with_import) generate_import_symbol(s);
525 
526  // Add declarations
527  s << this->header.str();
528 
529  // Finalize file
530  stream_close(s, this->cpp);
531  s_ptr.reset();
532  }
533  return fullname;
534  }
535 
536  void CodeGenerator::generate_mex(std::ostream &s) const {
537  // Begin conditional compilation
538  s << "#ifdef MATLAB_MEX_FILE\n";
539 
540  // Function prototype
541  if (this->cpp) s << "extern \"C\"\n"; // C linkage
542  s << "void mexFunction(int resc, mxArray *resv[], int argc, const mxArray *argv[]) {"
543  << std::endl;
544 
545  // Create a buffer
546  size_t buf_len = 0;
547  for (casadi_int i=0; i<exposed_fname.size(); ++i) {
548  buf_len = std::max(buf_len, exposed_fname[i].size());
549  }
550  s << " char buf[" << (buf_len+1) << "];\n";
551 
552  // Read std::string argument
553  s << " int buf_ok = argc > 0 && !mxGetString(*argv, buf, sizeof(buf));\n";
554 
555  // Create switch
556  s << " if (!buf_ok) {\n";
557  // Allow stringless call when unambiguous
558  if (exposed_fname.size()==1) {
559  s << " mex_" << exposed_fname[0] << "(resc, resv, argc, argv);\n"
560  << " return;\n";
561  } else {
562  s << " /* name error */\n";
563  }
564  for (casadi_int i=0; i<exposed_fname.size(); ++i) {
565  s << " } else if (strcmp(buf, \"" << exposed_fname[i] << "\")==0) {\n"
566  << " mex_" << exposed_fname[i] << "(resc, resv, argc-1, argv+1);\n"
567  << " return;\n";
568  }
569  s << " }\n";
570 
571  // Error
572  s << " mexErrMsgTxt(\"First input should be a command string. Possible values:";
573  for (casadi_int i=0; i<exposed_fname.size(); ++i) {
574  s << " '" << exposed_fname[i] << "'";
575  }
576  s << "\");\n";
577 
578  // End conditional compilation and function
579  s << "}\n"
580  << "#endif\n";
581  }
582 
583  void CodeGenerator::generate_sfunction(const std::string& name,
584  const std::string& sfunction) const {
585  // Create c file
586  auto f_ptr = Filesystem::ofstream_ptr("sfun_"+ name + ".c");
587  std::ostream& f = *f_ptr;
588 
589  // Print header
590  f << "// Must specify the S_FUNCTION_NAME as the name of the S-function\n"
591  << "#define S_FUNCTION_NAME sfun_" << name << "\n"
592  << "#define S_FUNCTION_LEVEL 2\n\n"
593  << "// Need to include simstruc.h for the definition of the SimStruct and its\n"
594  << "// associated macro definitions\n"
595  << "#ifndef __SIMSTRUC__\n"
596  << "#include \"simstruc.h\"\n"
597  << "#endif\n\n"
598  << "// Specific header file(s) required by the legacy code function\n"
599  << "#include \"" << this->name << ".h\"\n\n\n";
600 
601  // Codegenerate s-function
602  f << sfunction;
603 
604  }
605 
606  std::string CodeGenerator::codegen_sfunction(const Function& f) const {
607  std::stringstream g;
608  // TODO(@jaeandersson): These helper functions really should be moved
609  // to the runtime directory
610 
611  // Initialize function
612  g << "/* Function: mdlInitializeSizes ===========================================\n"
613  << "* Abstract:\n"
614  << "* The sizes information is used by Simulink to determine the S-function\n"
615  << "* blocks characteristics (number of inputs, outputs, states, etc.).\n"
616  << "*/\n"
617  << "static void mdlInitializeSizes(SimStruct *S)\n"
618  << "{\n\n"
619  << " /* Declare auxilary variables */\n"
620  << " int_T ii;\n"
621  << " const int_T* sp;\n\n"
622  << " /* Set number of simulink s-function block parameters "
623  "(the ones which appear by double click on simulink block) */\n"
624  << " ssSetNumSFcnParams(S, 0);\n\n"
625  << " /* Report if parameter mismatch occurs */\n"
626  << " if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) return;\n\n"
627  << " /* Specify the number of states for which a block detects "
628  "zero crossings that occur between sample points */\n"
629  << " ssSetNumNonsampledZCs(S, 0);\n\n"
630  << " /* Set number of simulink input ports */\n"
631  << " if (!ssSetNumInputPorts(S, " << f->n_in_ << ")) return;\n\n"
632  << " /* Configure simulink input ports (inputs are assumed to be dense "
633  "vectors or matrices) */\n"
634  << " for (ii=0; ii<" << f->n_in_ << "; ++ii) {\n"
635  << " sp = " << f.name() << "_sparsity_in(ii);\n"
636  << " if (sp[1]==1) {\n"
637  << " ssSetInputPortWidth(S, ii, sp[0]);\n"
638  << " }\n"
639  << " else {\n"
640  << " ssSetInputPortMatrixDimensions(S, ii, sp[0], sp[1]);\n"
641  << " }\n"
642  << " ssSetInputPortDirectFeedThrough(S, ii, 1);\n"
643  << " }\n\n"
644  << " /* Set number of simulink output ports */\n"
645  << " if (!ssSetNumOutputPorts(S, " << f->n_out_ << ")) return;\n\n"
646  << " /* Configure simulink output ports (dense or sparse vectors or matrices allowed) */\n"
647  << " for (ii=0; ii<" << f->n_out_ << "; ++ii) {\n"
648  << " sp = " << f.name() << "_sparsity_out(ii);\n"
649  << " if (sp[1]==1) {\n"
650  << " ssSetOutputPortWidth(S, ii, sp[0]);\n"
651  << " }\n"
652  << " else {\n"
653  << " ssSetOutputPortMatrixDimensions(S, ii, sp[0], sp[1]);\n"
654  << " }\n"
655  << " }\n"
656  << " ssSetOutputPortOutputExprInRTW(S, 0, 0);\n\n"
657  << " /* This S-function can be used in referenced model simulating in normal mode */\n"
658  << " ssSetModelReferenceNormalModeSupport(S, MDL_START_AND_MDL_PROCESS_PARAMS_OK);\n\n"
659  << " /* Set the number of sample time */\n"
660  << " ssSetNumSampleTimes(S, 1);\n\n"
661  << " /* Set the compliance with the SimState feature */\n"
662  << " ssSetSimStateCompliance(S, USE_DEFAULT_SIM_STATE);\n\n"
663  << " /**\n"
664  << " * All options have the form SS_OPTION_<name> and are documented in\n"
665  << " * matlabroot/simulink/include/simstruc.h. The options should be\n"
666  << " * bitwise ord together as in\n"
667  << " * ssSetOptions(S, (SS_OPTION_name1 | SS_OPTION_name2))\n"
668  << " */\n"
669  << "}\n\n\n";
670 
671  // Initialize sample times function
672  g << "/* Function: mdlInitializeSampleTimes =====================================\n"
673  << " * Abstract:\n"
674  << " * This function is used to specify the sample time(s) for your\n"
675  << " * S-function. You must register the same number of sample times as\n"
676  << " * specified in ssSetNumSampleTimes.\n"
677  << " */\n"
678  << "static void mdlInitializeSampleTimes(SimStruct *S)\n"
679  << "{\n"
680  << " ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);\n"
681  << " ssSetOffsetTime(S, 0, FIXED_IN_MINOR_STEP_OFFSET);\n"
682  << " #if defined(ssSetModelReferenceSampleTimeDefaultInheritance)\n"
683  << " ssSetModelReferenceSampleTimeDefaultInheritance(S);\n"
684  << " #endif\n"
685  << "}\n\n\n";
686 
687  // Model output function
688  g << "/* Function: mdlOutputs ===================================================\n"
689  << " * Abstract:\n"
690  << " * In this function, you compute the outputs of your S-function\n"
691  << " * block. Generally outputs are placed in the output vector(s),\n"
692  << " * ssGetOutputPortSignal.\n"
693  << " */\n"
694  << "static void mdlOutputs(SimStruct *S, int_T tid)\n"
695  << "{\n\n"
696  << " /* Declare auxilary variables */\n"
697  << " int_T ii, jj, row, col, nnz_col, ind_start_row_index, offset = 0, jj_total = 0;\n"
698  << " const int_T* sp;\n\n"
699  << " /* Allocate buffers for casadi input and output and simulink output */\n"
700  << " " + array("real_T", "w", f->sz_w()+f->nnz_out())
701  << " " + array("int_T", "iw", f->sz_iw())
702  << " const real_T* arg[" << f->sz_arg() <<"] = {0};\n"
703  << " real_T* res[" << f->sz_res() << "] = {0};\n"
704  << " real_T* y[" << f->n_out_ << "] = {0};\n\n"
705  << " /* Point inputs directly to casadi input buffer */\n"
706  << " for (ii=0; ii<" << f->n_in_ << ";++ii) {\n"
707  << " arg[ii] = *ssGetInputPortRealSignalPtrs( S, ii );\n"
708  << " }\n\n"
709  << " /* Point outputs to buffer */\n"
710  << " for (ii=0; ii<" << f->n_out_ << ";++ii) {\n"
711  << " y[ii] = ssGetOutputPortRealSignal( S, ii );\n"
712  << " }\n\n"
713  << " /* Point allocated working array to casadi output buffer */\n";
714  for (casadi_int ii=0; ii<f->n_out_; ++ii) {
715  g << " res[" << ii << "] = w + offset;\n"
716  << " offset += " << f.nnz_out(ii) << ";\n";
717  }
718  g << " \n"
719  << " /* Call CasADi function */\n"
720  << " " << f.name() << "( arg, res, iw, w+offset, 0 );\n\n"
721  << " /* Assign results to Simulink output array */\n"
722  << " for (ii=0; ii<" << f->n_out_ << "; ++ii){\n\n"
723  << " /* Get sparsity information of casadi function output "
724  "(sp[0] - n_rows, sp[1] - n_cols, sp[2] - dense/sparse) */\n"
725  << " sp = " << f.name() << "_sparsity_out(ii);\n\n"
726  << " /* Check if output is dense (sp[2]=1) or sparse (sp[2]=0) */\n"
727  << " if (sp[2]==0) {\n"
728  << " jj_total = 0;\n"
729  << " ind_start_row_index = 2 + sp[1] + 1;\n\n"
730  << " /* Distribute nonzero elements column by column */\n"
731  << " for (col=0; col<sp[1]; col++) {\n\n"
732  << " /* The cumulative sum of nonzero elements after each column starts at index 2, "
733  "after last entry of CCS array col_ptr; number of nonzero elements in current column is "
734  "obtained by the difference of two consecutive values */\n"
735  << " nnz_col = sp[2+col+1] - sp[2+col];\n\n"
736  << " /* Distribute nonzero elements of current column to correct row position */\n"
737  << " for (jj=0; jj<nnz_col; jj++) {\n"
738  << " row = sp[ind_start_row_index+jj_total];\n"
739  << " y[ii][row + sp[0]*col] = res[ii][jj_total];\n"
740  << " jj_total++;\n"
741  << " }\n"
742  << " }\n"
743  << " }\n"
744  << " else {\n"
745  << " y[ii] = res[ii];\n"
746  << " }\n"
747  << " }\n"
748  << "}\n\n\n";
749 
750  // Model terminate function
751  g << "/* Function: mdlTerminate =================================================\n"
752  << " * Abstract:\n"
753  << " * In this function, you should perform any actions that are necessary\n"
754  << " * at the termination of a simulation.\n"
755  << " */\n"
756  << "static void mdlTerminate(SimStruct *S)\n"
757  << "{\n"
758  << "}\n\n\n"
759  << "/* Required S-function trailer */\n"
760  << "#ifdef MATLAB_MEX_FILE\n"
761  << "# include \"simulink.c\"\n"
762  << "#else\n"
763  << "# include \"cg_sfun.h\"\n"
764  << "#endif";
765 
766  return g.str();
767  }
768 
769  void CodeGenerator::generate_main(std::ostream &s) const {
770  s << this->dll_export << "int main(int argc, char* argv[]) {\n";
771 
772  // Create switch
773  s << " if (argc<2) {\n"
774  << " /* name error */\n";
775  for (casadi_int i=0; i<exposed_fname.size(); ++i) {
776  s << " } else if (strcmp(argv[1], \"" << exposed_fname[i] << "\")==0) {\n"
777  << " return main_" << exposed_fname[i] << "(argc-2, argv+2);\n";
778  }
779  s << " }\n";
780 
781  // Error
782  s << " fprintf(stderr, \"First input should be a command string. Possible values:";
783  for (casadi_int i=0; i<exposed_fname.size(); ++i) {
784  s << " '" << exposed_fname[i] << "'";
785  }
786  s << "\\n";
787  s << "Note: you may use function.generate_input to create a command string.";
788  s << "\\n\");\n";
789 
790  // End main
791  s << " return 1;\n"
792  << "}\n";
793  }
794 
795  void CodeGenerator::define_rom_double(const void* id, casadi_int size) {
796  auto it = file_scope_double_.find(id);
797  casadi_assert(it==file_scope_double_.end(), "Already defined.");
798  shorthand("rd" + str(file_scope_double_.size()));
799  file_scope_double_[id] = size;
800  }
801 
802  std::string CodeGenerator::rom_double(const void* id) const {
803  auto it = file_scope_double_.find(id);
804  casadi_assert(it!=file_scope_double_.end(), "Not defined.");
805  casadi_int size = std::distance(file_scope_double_.begin(), it);
806  return "casadi_rd" + str(size);
807  }
808 
809  void CodeGenerator::define_rom_integer(const void* id, casadi_int size) {
810  auto it = file_scope_double_.find(id);
811  casadi_assert(it==file_scope_double_.end(), "Already defined.");
812  shorthand("ri" + str(file_scope_double_.size()));
813  file_scope_double_[id] = size;
814  }
815 
816  std::string CodeGenerator::rom_integer(const void* id) const {
817  auto it = file_scope_double_.find(id);
818  casadi_assert(it!=file_scope_double_.end(), "Not defined.");
819  casadi_int size = std::distance(file_scope_double_.begin(), it);
820  return "casadi_ri" + str(size);
821  }
822 
823  void CodeGenerator::define_pool_double(const std::string& name, const std::vector<double>& def) {
824  auto it = pool_double_.find(name);
825  if (it==pool_double_.end()) {
826  casadi_int index = pool_double_defaults_.size();
827  pool_double_defaults_.push_back(def);
828  shorthand("pd" + str(index));
829  pool_double_[name] = index;
830  } else {
831  casadi_assert_dev(def==pool_double_defaults_[it->second]);
832  }
833  }
834 
835  std::string CodeGenerator::pool_double(const std::string& name) const {
836  auto it = pool_double_.find(name);
837  casadi_assert(it!=pool_double_.end(), "Not defined.");
838  return "casadi_pd" + str(it->second);
839  }
840 
841  void CodeGenerator::dump(std::ostream& s) {
842  // Consistency check
843  casadi_assert_dev(current_indent_ == 0);
844 
845  // Prefix internal symbols to avoid symbol collisions
846  s << "/* How to prefix internal symbols */\n"
847  << "#ifdef CASADI_CODEGEN_PREFIX\n"
848  << " #define CASADI_NAMESPACE_CONCAT(NS, ID) _CASADI_NAMESPACE_CONCAT(NS, ID)\n"
849  << " #define _CASADI_NAMESPACE_CONCAT(NS, ID) NS ## ID\n"
850  << " #define CASADI_PREFIX(ID) CASADI_NAMESPACE_CONCAT(CODEGEN_PREFIX, ID)\n"
851  << "#else\n"
852  << " #define CASADI_PREFIX(ID) " << this->prefix << "_ ## ID\n"
853  << "#endif\n\n";
854 
855  s << this->includes.str();
856  s << std::endl;
857 
858  // Numeric types after includes: may depend on them. e.g. mex type
859  // Real type (usually double)
860  generate_casadi_real(s);
861 
862  // Integer type (usually long long)
863  generate_casadi_int(s);
864 
865  if (needs_mem_) {
866  s << "#ifndef CASADI_MAX_NUM_THREADS\n";
867  s << "#define CASADI_MAX_NUM_THREADS 1\n";
868  s << "#endif\n\n";
869  }
870 
871  // casadi/mem after numeric types to define derived types
872  // Memory struct entry point
873  if (this->with_mem) {
874  s << "#include <casadi/mem.h>\n" << std::endl;
875  }
876 
877  // Macros
878  if (!added_shorthands_.empty()) {
879  s << "/* Add prefix to internal symbols */\n";
880  for (auto&& i : added_shorthands_) {
881  s << "#define " << "casadi_" << i << " CASADI_PREFIX(" << i << ")\n";
882  }
883  s << std::endl;
884  }
885 
886  if (this->with_export) generate_export_symbol(s);
887 
888  // Check if inf/nan is needed
889  for (const auto& d : double_constants_) {
890  for (double e : d) {
891  if (isinf(e)) add_auxiliary(AUX_INF);
892  if (isnan(e)) add_auxiliary(AUX_NAN);
893  }
894  }
895 
896  // Codegen auxiliary functions
897  s << this->auxiliaries.str();
898 
899  // Print integer constants
900  if (!integer_constants_.empty()) {
901  for (casadi_int i=0; i<integer_constants_.size(); ++i) {
902  print_vector(s, "casadi_s" + str(i), integer_constants_[i]);
903  }
904  s << std::endl;
905  }
906 
907  // Print double constants
908  if (!double_constants_.empty()) {
909  for (casadi_int i=0; i<double_constants_.size(); ++i) {
910  print_vector(s, "casadi_c" + str(i), double_constants_[i]);
911  }
912  s << std::endl;
913  }
914 
915  // Print char constants
916  if (!char_constants_.empty()) {
917  for (casadi_int i=0; i<char_constants_.size(); ++i) {
918  print_vector(s, "casadi_b" + str(i), char_constants_[i]);
919  }
920  s << std::endl;
921  }
922 
923  // Print string constants
924  if (!string_constants_.empty()) {
925  for (casadi_int i=0; i<string_constants_.size(); ++i) {
926  print_vector(s, "casadi_a" + str(i), string_constants_[i]);
927  }
928  s << std::endl;
929  }
930 
931  if (sz_zeros_) {
932  std::vector<double> sz_zeros(sz_zeros_, 0);
933  print_vector(s, "casadi_zeros", std::vector<double>(sz_zeros));
934  s << std::endl;
935  }
936 
937  if (sz_ones_) {
938  std::vector<double> sz_ones(sz_ones_, 0);
939  print_vector(s, "casadi_ones", std::vector<double>(sz_ones));
940  s << std::endl;
941  }
942 
943  // Print file scope double work
944  if (!file_scope_double_.empty()) {
945  casadi_int i=0;
946  for (const auto& it : file_scope_double_) {
947  s << "static casadi_real casadi_rd" + str(i++) + "[" + str(it.second) + "];\n";
948  }
949  s << std::endl;
950  }
951 
952  // Print file scope integer work
953  if (!file_scope_integer_.empty()) {
954  casadi_int i=0;
955  for (const auto& it : file_scope_integer_) {
956  s << "static casadi_real casadi_ri" + str(i++) + "[" + str(it.second) + "];\n";
957  }
958  s << std::endl;
959  }
960 
961  // Print file scope double pool
962  if (!pool_double_.empty()) {
963  casadi_int i=0;
964  for (const auto& v : pool_double_defaults_) {
965  s << "casadi_real casadi_pd" + str(i) +
966  "[" + str(v.size()) + "] = " + initializer(v) + ";\n";
967  i++;
968  }
969  s << std::endl;
970  }
971 
972  // External function declarations
973  if (!added_externals_.empty()) {
974  s << "/* External functions */\n";
975  for (auto&& i : added_externals_) {
976  s << i << std::endl;
977  }
978  s << std::endl << std::endl;
979  }
980 
981  // Codegen body
982  s << this->body.str();
983 
984  // End with new line
985  s << std::endl;
986  }
987 
988  std::string CodeGenerator::work(casadi_int n, casadi_int sz, bool is_ref) const {
989  if (is_ref) {
990  return "wr" + format_padded(n);
991  }
992  if (n<0 || sz==0) {
993  return "0";
994  } else if (sz==1 && !this->codegen_scalars) {
995  return "(&w" + format_padded(n) + ")";
996  } else {
997  return "w" + format_padded(n);
998  }
999  }
1000 
1001  std::string CodeGenerator::workel(casadi_int n) const {
1002  if (n<0) return "0";
1003  std::stringstream s;
1004  if (this->codegen_scalars) s << "*";
1005  s << "w" << format_padded(n);
1006  return s.str();
1007  }
1008 
1009  void CodeGenerator::reserve_work(casadi_int n) {
1010  if (n == 0) {
1011  padding_length_ = 1;
1012  } else {
1013  // Zero based counting. The 10th entry is to be rendered as '9'
1014  padding_length_ = str(n-1).length();
1015  }
1016  }
1017 
1018  std::string CodeGenerator::format_padded(casadi_int i) const {
1019  std::stringstream ss;
1020  ss.str("");
1021  ss << std::setw(padding_length_) << std::setfill('0') << i;
1022  return ss.str();
1023  }
1024 
1025  std::string CodeGenerator::array(const std::string& type, const std::string& name, casadi_int len,
1026  const std::string& def) {
1027  std::stringstream s;
1028  s << type << " ";
1029  if (len==0) {
1030  s << "*" << name << " = 0";
1031  } else {
1032  s << name << "[" << len << "]";
1033  if (!def.empty()) s << " = " << def;
1034  }
1035  s << ";\n";
1036  return s.str();
1037  }
1038 
1039  void CodeGenerator::print_vector(std::ostream &s, const std::string& name,
1040  const std::vector<casadi_int>& v) {
1041  s << array("static const casadi_int", name, v.size(), initializer(v));
1042  }
1043 
1044  void CodeGenerator::print_vector(std::ostream &s, const std::string& name,
1045  const std::vector<char>& v) {
1046  s << array("static const char", name, v.size(), initializer(v));
1047  }
1048 
1049  void CodeGenerator::print_vector(std::ostream &s, const std::string& name,
1050  const std::vector<double>& v) {
1051  s << array("static const casadi_real", name, v.size(), initializer(v));
1052  }
1053 
1054  void CodeGenerator::print_vector(std::ostream &s, const std::string& name,
1055  const std::vector<std::string>& v) {
1056  s << array("static const char*", name, v.size(), initializer(v));
1057  }
1058 
1059  std::string CodeGenerator::print_canonical(const Sparsity& sp, const std::string& arg) {
1061  std::stringstream s;
1062  s << "casadi_print_canonical(" << sparsity(sp) << ", " << arg << ");";
1063  return s.str();
1064  }
1065 
1066  std::string CodeGenerator::print_vector(casadi_int sz, const std::string& arg) {
1068  std::stringstream s;
1069  s << "casadi_print_vector(" << sz << ", " << arg << ");";
1070  return s.str();
1071  }
1072 
1073  std::string CodeGenerator::print_scalar(const std::string& arg) {
1075  std::stringstream s;
1076  s << "casadi_print_scalar(" << arg << ");";
1077  return s.str();
1078  }
1079 
1080 
1081  std::string CodeGenerator::print_op(casadi_int op, const std::string& a0) {
1082  switch (op) {
1083  case OP_FABS:
1085  return "casadi_fabs("+a0+")";
1086  case OP_SQ:
1088  return "casadi_sq("+a0+")";
1089  case OP_SIGN:
1091  return "casadi_sign("+a0+")";
1092  case OP_LOG1P:
1094  return "casadi_log1p("+a0+")";
1095  case OP_EXPM1:
1097  return "casadi_expm1("+a0+")";
1098  default:
1099  return casadi_math<double>::print(op, a0);
1100  }
1101  }
1102  std::string CodeGenerator::print_op(casadi_int op, const std::string& a0, const std::string& a1) {
1103  switch (op) {
1104  case OP_FMIN:
1106  return "casadi_fmin("+a0+","+a1+")";
1107  case OP_FMAX:
1109  return "casadi_fmax("+a0+","+a1+")";
1110  case OP_HYPOT:
1112  return "casadi_hypot("+a0+","+a1+")";
1113  case OP_PRINTME:
1115  return "casadi_printme("+a0+","+a1+")";
1116  default:
1117  return casadi_math<double>::print(op, a0, a1);
1118  }
1119  }
1120 
1121  void CodeGenerator::add_include(const std::string& new_include, bool relative_path,
1122  const std::string& use_ifdef) {
1123  // Register the new element
1124  bool added = added_includes_.insert(new_include).second;
1125 
1126  // Quick return if it already exists
1127  if (!added) return;
1128 
1129  // Ifdef opening
1130  if (!use_ifdef.empty()) this->includes << "#ifdef " << use_ifdef << std::endl;
1131 
1132  // Print to the header section
1133  if (relative_path) {
1134  this->includes << "#include \"" << new_include << "\"\n";
1135  } else {
1136  this->includes << "#include <" << new_include << ">\n";
1137  }
1138 
1139  // Ifdef closing
1140  if (!use_ifdef.empty()) this->includes << "#endif\n";
1141  }
1142 
1143  void CodeGenerator::setup_callback(const std::string& s, const Function& f) {
1144  std::string name = add_dependency(f);
1145  bool needs_mem = !f->codegen_mem_type().empty();
1146  if (needs_mem) {
1147  *this << s << ".checkout = " << name << "_checkout;\n";
1148  } else {
1149  *this << s << ".checkout = 0;\n";
1150  }
1151 
1152  *this << s << ".eval = " << name << ";\n";
1153  if (needs_mem) {
1154  *this << s << ".release = " << name << "_release;\n";
1155  } else {
1156  *this << s << ".release = 0;\n";
1157  }
1158  }
1159 
1160  std::string CodeGenerator::
1161  operator()(const Function& f, const std::string& arg,
1162  const std::string& res, const std::string& iw,
1163  const std::string& w, const std::string& failure_ret) {
1164  std::string name = add_dependency(f);
1165  bool needs_mem = !f->codegen_mem_type().empty();
1166  if (needs_mem) {
1167  std::string mem = "mid";
1168  local("flag", "int");
1169  local(mem, "int");
1170  *this << mem << " = " << name << "_checkout();\n";
1171  *this << "if (" << mem << "<0) return " << failure_ret << ";\n";
1172  *this << "flag = " + name + "(" + arg + ", " + res + ", "
1173  + iw + ", " + w + ", " << mem << ");\n";
1174  *this << name << "_release(" << mem << ");\n";
1175  return "flag";
1176  } else {
1177  return name + "(" + arg + ", " + res + ", "
1178  + iw + ", " + w + ", 0)";
1179  }
1180  }
1181 
1182  void CodeGenerator::add_external(const std::string& new_external) {
1183  added_externals_.insert(new_external);
1184  }
1185 
1186  std::string CodeGenerator::shorthand(const std::string& name) const {
1187  casadi_assert(added_shorthands_.count(name), "No such macro: " + name);
1188  return "casadi_" + name;
1189  }
1190 
1191  std::string CodeGenerator::shorthand(const std::string& name, bool allow_adding) {
1192  bool added = added_shorthands_.insert(name).second;
1193  if (!allow_adding) {
1194  casadi_assert(added, "Duplicate macro: " + name);
1195  }
1196  return "casadi_" + name;
1197  }
1198 
1199  casadi_int CodeGenerator::add_sparsity(const Sparsity& sp, bool canonical) {
1200  return get_constant(sp.compress(canonical), true);
1201  }
1202 
1203  std::string CodeGenerator::sparsity(const Sparsity& sp, bool canonical) {
1204  return shorthand("s" + str(add_sparsity(sp, canonical)));
1205  }
1206 
1207  casadi_int CodeGenerator::get_sparsity(const Sparsity& sp) const {
1208  return const_cast<CodeGenerator&>(*this).get_constant(sp, false);
1209  }
1210 
1211  size_t CodeGenerator::hash(const std::vector<double>& v) {
1212  // Calculate a hash value for the vector
1213  std::size_t seed=0;
1214  if (!v.empty()) {
1215  casadi_assert_dev(sizeof(double) % sizeof(size_t)==0);
1216  const casadi_int int_len = v.size()*(sizeof(double)/sizeof(size_t));
1217  const size_t* int_v = reinterpret_cast<const size_t*>(&v.front());
1218  for (size_t i=0; i<int_len; ++i) {
1219  hash_combine(seed, int_v[i]);
1220  }
1221  }
1222  return seed;
1223  }
1224 
1225  size_t CodeGenerator::hash(const std::vector<casadi_int>& v) {
1226  size_t seed=0;
1227  hash_combine(seed, v);
1228  return seed;
1229  }
1230 
1231  size_t CodeGenerator::hash(const std::vector<char>& v) {
1232  size_t seed=0;
1233  hash_combine(seed, v);
1234  return seed;
1235  }
1236 
1237  size_t CodeGenerator::hash(const std::vector<std::string>& v) {
1238  size_t seed=0;
1239  hash_combine(seed, v);
1240  return seed;
1241  }
1242 
1243  casadi_int CodeGenerator::get_constant(const std::vector<double>& v, bool allow_adding) {
1244  // Hash the vector
1245  size_t h = hash(v);
1246 
1247  // Try to locate it in already added constants
1248  auto eq = added_double_constants_.equal_range(h);
1249  for (auto i=eq.first; i!=eq.second; ++i) {
1250  if (equal(v, double_constants_[i->second])) return i->second;
1251  }
1252 
1253  if (allow_adding) {
1254  // Add to constants
1255  casadi_int ind = double_constants_.size();
1256  double_constants_.push_back(v);
1257  added_double_constants_.insert(std::make_pair(h, ind));
1258  return ind;
1259  } else {
1260  casadi_error("Constant not found");
1261  return -1;
1262  }
1263  }
1264 
1265  casadi_int CodeGenerator::get_constant(const std::vector<casadi_int>& v, bool allow_adding) {
1266  // Hash the vector
1267  size_t h = hash(v);
1268 
1269  // Try to locate it in already added constants
1270  std::pair<std::multimap<size_t, size_t>::iterator, std::multimap<size_t, size_t>::iterator> eq =
1271  added_integer_constants_.equal_range(h);
1272  for (std::multimap<size_t, size_t>::iterator i=eq.first; i!=eq.second; ++i) {
1273  if (equal(v, integer_constants_[i->second])) return i->second;
1274  }
1275 
1276  if (allow_adding) {
1277  // Add to constants
1278  casadi_int ind = integer_constants_.size();
1279  integer_constants_.push_back(v);
1280  added_integer_constants_.insert(std::pair<size_t, size_t>(h, ind));
1281  return ind;
1282  } else {
1283  casadi_error("Constant not found");
1284  return -1;
1285  }
1286  }
1287 
1288  casadi_int CodeGenerator::get_constant(const std::vector<char>& v, bool allow_adding) {
1289  // Hash the vector
1290  size_t h = hash(v);
1291 
1292  // Try to locate it in already added constants
1293  std::pair<std::multimap<size_t, size_t>::iterator, std::multimap<size_t, size_t>::iterator> eq =
1294  added_char_constants_.equal_range(h);
1295  for (std::multimap<size_t, size_t>::iterator i=eq.first; i!=eq.second; ++i) {
1296  if (equal(v, char_constants_[i->second])) return i->second;
1297  }
1298 
1299  if (allow_adding) {
1300  // Add to constants
1301  casadi_int ind = char_constants_.size();
1302  char_constants_.push_back(v);
1303  added_char_constants_.insert(std::pair<size_t, size_t>(h, ind));
1304  return ind;
1305  } else {
1306  casadi_error("Constant not found");
1307  return -1;
1308  }
1309  }
1310 
1311  casadi_int CodeGenerator::get_constant(const std::vector<std::string>& v, bool allow_adding) {
1312  // Hash the vector
1313  size_t h = hash(v);
1314 
1315  // Try to locate it in already added constants
1316  std::pair<std::multimap<size_t, size_t>::iterator, std::multimap<size_t, size_t>::iterator> eq =
1317  added_string_constants_.equal_range(h);
1318  for (std::multimap<size_t, size_t>::iterator i=eq.first; i!=eq.second; ++i) {
1319  if (equal(v, string_constants_[i->second])) return i->second;
1320  }
1321 
1322  if (allow_adding) {
1323  // Add to constants
1324  casadi_int ind = string_constants_.size();
1325  string_constants_.push_back(v);
1326  added_string_constants_.insert(std::pair<size_t, size_t>(h, ind));
1327  return ind;
1328  } else {
1329  casadi_error("Constant not found");
1330  return -1;
1331  }
1332  }
1333 
1334  std::string CodeGenerator::constant(const std::vector<casadi_int>& v) {
1335  return shorthand("s" + str(get_constant(v, true)));
1336  }
1337 
1338  std::string CodeGenerator::constant(const std::vector<char>& v) {
1339  return shorthand("b" + str(get_constant(v, true)));
1340  }
1341 
1342  std::string CodeGenerator::constant(const std::vector<std::string>& v) {
1343  return shorthand("a" + str(get_constant(v, true)));
1344  }
1345 
1346  std::string CodeGenerator::zeros(casadi_int sz) {
1347  sz_zeros_ = std::max(sz_zeros_, sz);
1348  return shorthand("zeros");
1349  }
1350 
1351  std::string CodeGenerator::ones(casadi_int sz) {
1352  sz_ones_ = std::max(sz_ones_, sz);
1353  return shorthand("ones");
1354  }
1355 
1357  const std::string& name, const std::vector<casadi_int>& v, const std::string& type) {
1358  std::string ref = constant(v);
1359  if (!v.empty()) {
1360  local(name+"[" + str(v.size()) + "]", type);
1361  } else {
1362  local(name, type, "*");
1363  }
1364  if (!v.empty()) {
1365  local("i", type);
1366  (*this) << "for (i=0;i<" << v.size() << ";++i) " + name + "[i] = " + ref + "[i];\n";
1367  } else {
1368  init_local(name, "0");
1369  }
1370  }
1371 
1372  std::string CodeGenerator::constant(const std::vector<double>& v) {
1373  return shorthand("c" + str(get_constant(v, true)));
1374  }
1375 
1376  void CodeGenerator::add_auxiliary(Auxiliary f, const std::vector<std::string>& inst) {
1377  // Look for existing instantiations
1378  auto f_match = added_auxiliaries_.equal_range(f);
1379  // Look for duplicates
1380  for (auto it=f_match.first; it!=f_match.second; ++it) {
1381  if (it->second==inst) return;
1382  }
1383  added_auxiliaries_.insert(std::make_pair(f, inst));
1384 
1385  // Add the appropriate function
1386  switch (f) {
1387  case AUX_COPY:
1388  this->auxiliaries << sanitize_source(casadi_copy_str, inst);
1389  break;
1390  case AUX_SCALED_COPY:
1391  this->auxiliaries << sanitize_source(casadi_scaled_copy_str, inst);
1392  break;
1393  case AUX_SWAP:
1394  this->auxiliaries << sanitize_source(casadi_swap_str, inst);
1395  break;
1396  case AUX_SCAL:
1397  this->auxiliaries << sanitize_source(casadi_scal_str, inst);
1398  break;
1399  case AUX_AXPY:
1400  this->auxiliaries << sanitize_source(casadi_axpy_str, inst);
1401  break;
1402  case AUX_DOT:
1403  this->auxiliaries << sanitize_source(casadi_dot_str, inst);
1404  break;
1405  case AUX_BILIN:
1406  this->auxiliaries << sanitize_source(casadi_bilin_str, inst);
1407  break;
1408  case AUX_RANK1:
1409  this->auxiliaries << sanitize_source(casadi_rank1_str, inst);
1410  break;
1411  case AUX_IAMAX:
1412  this->auxiliaries << sanitize_source(casadi_iamax_str, inst);
1413  break;
1414  case AUX_INTERPN:
1417  add_auxiliary(AUX_FLIP, {});
1419  add_auxiliary(AUX_CLEAR, {"casadi_int"});
1420  this->auxiliaries << sanitize_source(casadi_interpn_str, inst);
1421  break;
1422  case AUX_INTERPN_GRAD:
1424  this->auxiliaries << sanitize_source(casadi_interpn_grad_str, inst);
1425  break;
1426  case AUX_DE_BOOR:
1427  this->auxiliaries << sanitize_source(casadi_de_boor_str, inst);
1428  break;
1429  case AUX_ND_BOOR_EVAL:
1432  add_auxiliary(AUX_FILL, {"casadi_int"});
1434  add_auxiliary(AUX_CLEAR, {"casadi_int"});
1436  this->auxiliaries << sanitize_source(casadi_nd_boor_eval_str, inst);
1437  break;
1438  case AUX_FLIP:
1439  this->auxiliaries << sanitize_source(casadi_flip_str, inst);
1440  break;
1441  case AUX_LOW:
1442  this->auxiliaries << sanitize_source(casadi_low_str, inst);
1443  break;
1444  case AUX_INTERPN_WEIGHTS:
1446  this->auxiliaries << sanitize_source(casadi_interpn_weights_str, inst);
1447  break;
1449  this->auxiliaries << sanitize_source(casadi_interpn_interpolate_str, inst);
1450  break;
1451  case AUX_NORM_1:
1452  this->auxiliaries << sanitize_source(casadi_norm_1_str, inst);
1453  break;
1454  case AUX_NORM_2:
1456  this->auxiliaries << sanitize_source(casadi_norm_2_str, inst);
1457  break;
1458  case AUX_NORM_INF:
1460  this->auxiliaries << sanitize_source(casadi_norm_inf_str, inst);
1461  break;
1462  case AUX_VECTOR_FMAX:
1464  this->auxiliaries << sanitize_source(casadi_vector_fmax_str, inst);
1465  break;
1466  case AUX_VECTOR_FMIN:
1468  this->auxiliaries << sanitize_source(casadi_vector_fmin_str, inst);
1469  break;
1470  case AUX_MASKED_NORM_INF:
1472  this->auxiliaries << sanitize_source(casadi_masked_norm_inf_str, inst);
1473  break;
1474  case AUX_CLIP_MIN:
1475  // add_auxiliary(AUX_CLIP_MIN);
1476  this->auxiliaries << sanitize_source(casadi_clip_min_str, inst);
1477  break;
1478  case AUX_CLIP_MAX:
1479  // add_auxiliary(AUX_CLIP_MAX);
1480  this->auxiliaries << sanitize_source(casadi_clip_max_str, inst);
1481  break;
1482  case AUX_CLEAR:
1483  this->auxiliaries << sanitize_source(casadi_clear_str, inst);
1484  break;
1485  case AUX_FILL:
1486  this->auxiliaries << sanitize_source(casadi_fill_str, inst);
1487  break;
1488  case AUX_MV:
1489  this->auxiliaries << sanitize_source(casadi_mv_str, inst);
1490  break;
1491  case AUX_MV_DENSE:
1492  this->auxiliaries << sanitize_source(casadi_mv_dense_str, inst);
1493  break;
1494  case AUX_MTIMES:
1495  this->auxiliaries << sanitize_source(casadi_mtimes_str, inst);
1496  break;
1497  case AUX_TRILSOLVE:
1498  this->auxiliaries << sanitize_source(casadi_trilsolve_str, inst);
1499  break;
1500  case AUX_TRIUSOLVE:
1501  this->auxiliaries << sanitize_source(casadi_triusolve_str, inst);
1502  break;
1503  case AUX_PROJECT:
1504  this->auxiliaries << sanitize_source(casadi_project_str, inst);
1505  break;
1506  case AUX_TRI_PROJECT:
1507  this->auxiliaries << sanitize_source(casadi_tri_project_str, inst);
1508  break;
1509  case AUX_DENSIFY:
1512  {
1513  std::vector<std::string> inst2 = inst;
1514  if (inst.size()==1) inst2.push_back(inst[0]);
1515  this->auxiliaries << sanitize_source(casadi_densify_str, inst2);
1516  }
1517  break;
1518  case AUX_SPARSIFY:
1520  {
1521  std::vector<std::string> inst2 = inst;
1522  if (inst.size()==1) inst2.push_back(inst[0]);
1523  this->auxiliaries << sanitize_source(casadi_sparsify_str, inst2);
1524  }
1525  break;
1526  case AUX_TRANS:
1527  this->auxiliaries << sanitize_source(casadi_trans_str, inst);
1528  break;
1529  case AUX_TO_MEX:
1531  this->auxiliaries << "#ifdef MATLAB_MEX_FILE\n"
1532  << sanitize_source(casadi_to_mex_str, inst)
1533  << "#endif\n\n";
1534  break;
1535  case AUX_FROM_MEX:
1537  this->auxiliaries << "#ifdef MATLAB_MEX_FILE\n"
1538  << sanitize_source(casadi_from_mex_str, inst)
1539  << "#endif\n\n";
1540  break;
1541  case AUX_FINITE_DIFF:
1543  this->auxiliaries << sanitize_source(casadi_finite_diff_str, inst);
1544  break;
1545  case AUX_QR:
1550  this->auxiliaries << sanitize_source(casadi_qr_str, inst);
1551  break;
1552  case AUX_LSQR:
1559  this->auxiliaries << sanitize_source(casadi_lsqr_str, inst);
1560  break;
1561  case AUX_QP:
1562  this->auxiliaries << sanitize_source(casadi_qp_str, inst);
1563  break;
1564  case AUX_QRQP:
1578  add_include("stdarg.h");
1579  add_include("stdio.h");
1580  add_include("math.h");
1581 
1582  this->auxiliaries << sanitize_source(casadi_qrqp_str, inst);
1583  break;
1584  case AUX_NLP:
1586  this->auxiliaries << sanitize_source(casadi_nlp_str, inst);
1587  break;
1588  case AUX_SQPMETHOD:
1593  this->auxiliaries << sanitize_source(casadi_sqpmethod_str, inst);
1594  break;
1595  case AUX_FEASIBLESQPMETHOD:
1598  this->auxiliaries << sanitize_source(casadi_feasiblesqpmethod_str, inst);
1599  break;
1600  case AUX_LDL:
1601  this->auxiliaries << sanitize_source(casadi_ldl_str, inst);
1602  break;
1603  case AUX_NEWTON:
1608  this->auxiliaries << sanitize_source(casadi_newton_str, inst);
1609  break;
1610  case AUX_MAX_VIOL:
1612  this->auxiliaries << sanitize_source(casadi_max_viol_str, inst);
1613  break;
1614  case AUX_SUM_VIOL:
1615  this->auxiliaries << sanitize_source(casadi_sum_viol_str, inst);
1616  break;
1617  case AUX_SUM:
1618  this->auxiliaries << sanitize_source(casadi_sum_str, inst);
1619  break;
1620  case AUX_VFMIN:
1622  this->auxiliaries << sanitize_source(casadi_vfmin_str, inst);
1623  break;
1624  case AUX_VFMAX:
1626  this->auxiliaries << sanitize_source(casadi_vfmax_str, inst);
1627  break;
1628  case AUX_REGULARIZE:
1631  this->auxiliaries << sanitize_source(casadi_regularize_str, inst);
1632  break;
1637  this->auxiliaries << sanitize_source(casadi_bound_consistency_str, inst);
1638  break;
1639  case AUX_FILE_SLURP:
1640  add_include("stdio.h");
1641  this->auxiliaries << sanitize_source(casadi_file_slurp_str, inst);
1642  break;
1643  case AUX_CACHE:
1644  this->auxiliaries << sanitize_source(casadi_cache_str, inst);
1645  break;
1646  case AUX_CVX:
1653  this->auxiliaries << sanitize_source(casadi_cvx_str, inst);
1654  break;
1655  case AUX_CONVEXIFY:
1660  this->auxiliaries << sanitize_source(casadi_convexify_str, inst);
1661  break;
1662  case AUX_LOGSUMEXP:
1665  this->auxiliaries << sanitize_source(casadi_logsumexp_str, inst);
1666  break;
1667  case AUX_SPARSITY:
1668  this->auxiliaries << sanitize_source(casadi_sparsity_str, inst);
1669  break;
1670  case AUX_BFGS:
1679  this->auxiliaries << sanitize_source(casadi_bfgs_str, inst);
1680  break;
1681  case AUX_ORACLE:
1682  this->auxiliaries << sanitize_source(casadi_oracle_str, inst);
1683  break;
1684  case AUX_ORACLE_CALLBACK:
1685  this->auxiliaries << sanitize_source(casadi_oracle_callback_str, inst);
1686  break;
1687  case AUX_OCP_BLOCK:
1688  this->auxiliaries << sanitize_source(casadi_ocp_block_str, inst);
1689  break;
1690  case AUX_TO_DOUBLE:
1691  this->auxiliaries << "#define casadi_to_double(x) "
1692  << "(" << (this->cpp ? "static_cast<double>(x)" : "(double) x") << ")\n\n";
1693  break;
1694  case AUX_TO_INT:
1695  this->auxiliaries << "#define casadi_to_int(x) "
1696  << "(" << (this->cpp ? "static_cast<casadi_int>(x)" : "(casadi_int) x")
1697  << ")\n\n";
1698  break;
1699  case AUX_CAST:
1700  this->auxiliaries << "#define CASADI_CAST(x,y) "
1701  << "(" << (this->cpp ? "static_cast<x>(y)" : "(x) y") << ")\n\n";
1702  break;
1703  case AUX_SQ:
1704  shorthand("sq");
1705  this->auxiliaries << "casadi_real casadi_sq(casadi_real x) { return x*x;}\n\n";
1706  break;
1707  case AUX_SIGN:
1708  shorthand("sign");
1709  this->auxiliaries << "casadi_real casadi_sign(casadi_real x) "
1710  << "{ return x<0 ? -1 : x>0 ? 1 : x;}\n\n";
1711  break;
1712  case AUX_IF_ELSE:
1713  shorthand("if_else");
1714  this->auxiliaries << "casadi_real casadi_if_else"
1715  << "(casadi_real c, casadi_real x, casadi_real y) "
1716  << "{ return c!=0 ? x : y;}\n\n";
1717  break;
1718  case AUX_PRINTF:
1719  this->auxiliaries << "#ifndef CASADI_PRINTF\n";
1720  if (this->mex) {
1721  this->auxiliaries << "#ifdef MATLAB_MEX_FILE\n"
1722  << " #define CASADI_PRINTF mexPrintf\n"
1723  << "#else\n"
1724  << " #define CASADI_PRINTF printf\n"
1725  << "#endif\n";
1726  } else {
1727  add_include("stdio.h");
1728  this->auxiliaries << "#define CASADI_PRINTF printf\n";
1729  this->auxiliaries << "#ifndef CASADI_SNPRINTF\n";
1730  this->auxiliaries << "#define CASADI_SNPRINTF snprintf\n";
1731  this->auxiliaries << "#endif\n\n";
1732  }
1733  this->auxiliaries << "#endif\n\n";
1734  break;
1735  case AUX_FMIN:
1736  shorthand("fmin");
1737  this->auxiliaries << "casadi_real casadi_fmin(casadi_real x, casadi_real y) {\n"
1738  << "/* Pre-c99 compatibility */\n"
1739  << "#if __STDC_VERSION__ < 199901L\n"
1740  << " return x<y ? x : y;\n"
1741  << "#else\n"
1742  << " return fmin(x, y);\n"
1743  << "#endif\n"
1744  << "}\n\n";
1745  break;
1746  case AUX_FMAX:
1747  shorthand("fmax");
1748  this->auxiliaries << "casadi_real casadi_fmax(casadi_real x, casadi_real y) {\n"
1749  << "/* Pre-c99 compatibility */\n"
1750  << "#if __STDC_VERSION__ < 199901L\n"
1751  << " return x>y ? x : y;\n"
1752  << "#else\n"
1753  << " return fmax(x, y);\n"
1754  << "#endif\n"
1755  << "}\n\n";
1756  break;
1757  case AUX_FABS:
1758  shorthand("fabs");
1759  this->auxiliaries << "casadi_real casadi_fabs(casadi_real x) {\n"
1760  << "/* Pre-c99 compatibility */\n"
1761  << "#if __STDC_VERSION__ < 199901L\n"
1762  << " return x>0 ? x : -x;\n"
1763  << "#else\n"
1764  << " return fabs(x);\n"
1765  << "#endif\n"
1766  << "}\n\n";
1767  break;
1768  case AUX_ISINF:
1769  shorthand("isinf");
1770  this->auxiliaries << "casadi_real casadi_isinf(casadi_real x) {\n"
1771  << "/* Pre-c99 compatibility */\n"
1772  << "#if __STDC_VERSION__ < 199901L\n"
1773  << " return x== INFINITY || x==-INFINITY;\n"
1774  << "#else\n"
1775  << " return isinf(x);\n"
1776  << "#endif\n"
1777  << "}\n\n";
1778  break;
1779  case AUX_MIN:
1780  this->auxiliaries << "casadi_int casadi_min(casadi_int x, casadi_int y) {\n"
1781  << " return x>y ? y : x;\n"
1782  << "}\n\n";
1783  break;
1784  case AUX_MAX:
1785  this->auxiliaries << "casadi_int casadi_max(casadi_int x, casadi_int y) {\n"
1786  << " return x>y ? x : y;\n"
1787  << "}\n\n";
1788  break;
1789  case AUX_MMIN:
1792  this->auxiliaries << sanitize_source(casadi_mmin_str, inst);
1793  break;
1794  case AUX_MMAX:
1797  this->auxiliaries << sanitize_source(casadi_mmax_str, inst);
1798  break;
1799  case AUX_INF:
1800  this->auxiliaries << "#ifndef casadi_inf\n"
1801  << " #define casadi_inf " << this->infinity << "\n"
1802  << "#endif\n\n";
1803  break;
1804  case AUX_NAN:
1805  this->auxiliaries << "#ifndef casadi_nan\n"
1806  << " #define casadi_nan " << this->nan << "\n"
1807  << "#endif\n\n";
1808  break;
1809  case AUX_REAL_MIN:
1810  this->auxiliaries << "#ifndef casadi_real_min\n"
1811  << " #define casadi_real_min " << this->real_min << "\n"
1812  << "#endif\n\n";
1813  break;
1814  case AUX_LOG1P:
1815  shorthand("log1p");
1816  this->auxiliaries << "casadi_real casadi_log1p(casadi_real x) {\n"
1817  << "/* Pre-c99 compatibility */\n"
1818  << "#if __STDC_VERSION__ < 199901L\n"
1819  << " return log(1+x);\n"
1820  << "#else\n"
1821  << " return log1p(x);\n"
1822  << "#endif\n"
1823  << "}\n\n";
1824  break;
1825  case AUX_EXPM1:
1826  shorthand("expm1");
1827  this->auxiliaries << "casadi_real casadi_expm1(casadi_real x) {\n"
1828  << "/* Pre-c99 compatibility */\n"
1829  << "#if __STDC_VERSION__ < 199901L\n"
1830  << " return exp(x)-1;\n"
1831  << "#else\n"
1832  << " return expm1(x);\n"
1833  << "#endif\n"
1834  << "}\n\n";
1835  break;
1836  case AUX_HYPOT:
1837  shorthand("hypot");
1838  this->auxiliaries << "casadi_real casadi_hypot(casadi_real x, casadi_real y) {\n"
1839  << "/* Pre-c99 compatibility */\n"
1840  << "#if __STDC_VERSION__ < 199901L\n"
1841  << " return sqrt(x*x+y*y);\n"
1842  << "#else\n"
1843  << " return hypot(x, y);\n"
1844  << "#endif\n"
1845  << "}\n\n";
1846  break;
1847  case AUX_BLAZING_DE_BOOR:
1848  this->auxiliaries << sanitize_source(casadi_blazing_de_boor_str, inst);
1849  break;
1853  this->auxiliaries << sanitize_source(casadi_blazing_1d_boor_eval_str, inst);
1854  break;
1858  this->auxiliaries << sanitize_source(casadi_blazing_2d_boor_eval_str, inst);
1859  break;
1863  this->auxiliaries << sanitize_source(casadi_blazing_3d_boor_eval_str, inst);
1864  break;
1865  case AUX_PRINTME:
1867  this->auxiliaries << sanitize_source(casadi_printme_str, inst);
1868  break;
1869  case AUX_PRINT_SCALAR:
1871  this->auxiliaries << sanitize_source(casadi_print_scalar_str, inst);
1872  break;
1873  case AUX_PRINT_VECTOR:
1875  this->auxiliaries << sanitize_source(casadi_print_vector_str, inst);
1876  break;
1877  case AUX_PRINT_CANONICAL:
1879  this->auxiliaries << sanitize_source(casadi_print_canonical_str, inst);
1880  break;
1881  }
1882  }
1883 
1884  std::string CodeGenerator::to_mex(const Sparsity& sp, const std::string& arg) {
1886  std::stringstream s;
1887  s << "casadi_to_mex(" << sparsity(sp) << ", " << arg << ");";
1888  return s.str();
1889  }
1890 
1891  std::string CodeGenerator::from_mex(std::string& arg,
1892  const std::string& res, std::size_t res_off,
1893  const Sparsity& sp_res, const std::string& w) {
1894  // Handle offset with recursion
1895  if (res_off!=0) return from_mex(arg, res+"+"+str(res_off), 0, sp_res, w);
1896 
1898  std::stringstream s;
1899  s << "casadi_from_mex(" << arg
1900  << ", " << res << ", " << sparsity(sp_res) << ", " << w << ");";
1901  return s.str();
1902  }
1903 
1904  std::string CodeGenerator::fmu_helpers(const std::string& modelname) {
1905  // Process C++ source
1906  std::stringstream ret;
1907  std::string line;
1908  std::istringstream stream(casadi_fmu_str);
1909  while (std::getline(stream, line)) {
1910  // Replacements
1911  if (line.find("MODELNAME") != std::string::npos) {
1912  line = replace(line, "MODELNAME", modelname);
1913  }
1914  // Append to return
1915  ret << line << "\n";
1916  }
1917  return ret.str();
1918  }
1919 
1920  std::string CodeGenerator::constant(const std::string& v) {
1921  std::string ret = v;
1922  ret = replace(ret, "\\", "\\\\");
1923  ret = replace(ret, "\"", "\\\"");
1924  return "\"" + ret + "\"";
1925  }
1926 
1927  std::string CodeGenerator::constant(casadi_int v) {
1928  return str(v);
1929  }
1930 
1931  std::string CodeGenerator::constant(char v) {
1932  return constant(static_cast<casadi_int>(v));
1933  }
1934  std::string CodeGenerator::constant(double v) {
1935  std::stringstream s;
1936  if (isnan(v)) {
1938  s << "casadi_nan";
1939  } else if (isinf(v)) {
1941  if (v<0) s << "-";
1942  s << "casadi_inf";
1943  } else {
1944  casadi_int v_int = static_cast<casadi_int>(v);
1945  if (static_cast<double>(v_int)==v) {
1946  // Print integer
1947  s << v_int << ".";
1948  } else {
1949  // Print real
1950  std::ios_base::fmtflags fmtfl = s.flags(); // get current format flags
1951  s << std::scientific << std::setprecision(std::numeric_limits<double>::digits10 + 1) << v;
1952  s.flags(fmtfl); // reset current format flags
1953  }
1954  }
1955  return s.str();
1956  }
1957 
1958  std::string CodeGenerator::copy(const std::string& arg,
1959  std::size_t n, const std::string& res) {
1960  std::stringstream s;
1961  // Perform operation
1963  s << "casadi_copy(" << arg << ", " << n << ", " << res << ");";
1964  return s.str();
1965  }
1966 
1967  bool CodeGenerator::elide_copy(casadi_int sz) {
1968  if (casadi::GlobalOptions::copy_elision_min_size==-1) return false;
1970  }
1971 
1972  void CodeGenerator::copy_check(const std::string& arg, size_t n, const std::string& res,
1973  bool check_lhs, bool check_rhs) {
1974  std::vector<std::string> checks;
1975  if (check_lhs) checks.push_back(arg);
1976  if (check_rhs) checks.push_back(res);
1977  if (!checks.empty()) *this << "if (" << join(checks, " && ") << ") ";
1978  *this << copy(arg, n, res) << "\n";
1979  }
1980 
1981  void CodeGenerator::copy_default(const std::string& arg, size_t n, const std::string& res,
1982  const std::string& def, bool check_rhs) {
1983  *this << "if (" << arg << ") {\n";
1984  if (check_rhs) *this << "if (" << res << ") ";
1985  *this << copy(arg, n, res) << "\n";
1986  *this << "} else {\n";
1987  if (check_rhs) *this << "if (" << res << ") ";
1988  *this << fill(res, n, def) << "\n";
1989  *this << "}\n";
1990  }
1991 
1992  std::string CodeGenerator::clear(const std::string& res, std::size_t n) {
1993  std::stringstream s;
1994  // Perform operation
1996  s << "casadi_clear(" << res << ", " << n << ");";
1997  return s.str();
1998  }
1999 
2000  std::string CodeGenerator::arg(casadi_int i) const {
2001  return "arg[" + str(i) + "]";
2002  }
2003 
2004  std::string CodeGenerator::res(casadi_int i) const {
2005  return "res[" + str(i) + "]";
2006  }
2007 
2008  std::string CodeGenerator::mem(const Function& f) {
2009  std::string name = f->codegen_name(*this, false);
2010  std::string mem_array = shorthand(name + "_mem");
2011  return mem_array+"[mem]";
2012  }
2013 
2014  std::string CodeGenerator::fill(const std::string& res,
2015  std::size_t n, const std::string& v) {
2016  if (v=="0") return clear(res, n);
2017  std::stringstream s;
2018  // Perform operation
2020  s << "casadi_fill(" << res << ", " << n << ", " << v << ");";
2021  return s.str();
2022  }
2023 
2024  std::string CodeGenerator::dot(casadi_int n, const std::string& x,
2025  const std::string& y) {
2027  std::stringstream s;
2028  s << "casadi_dot(" << n << ", " << x << ", " << y << ")";
2029  return s.str();
2030  }
2031 
2032  std::string CodeGenerator::bilin(const std::string& A, const Sparsity& sp_A,
2033  const std::string& x, const std::string& y) {
2035  std::stringstream s;
2036  s << "casadi_bilin(" << A << ", " << sparsity(sp_A) << ", " << x << ", " << y << ")";
2037  return s.str();
2038  }
2039 
2040  std::string CodeGenerator::rank1(const std::string& A, const Sparsity& sp_A,
2041  const std::string& alpha, const std::string& x,
2042  const std::string& y) {
2044  std::stringstream s;
2045  s << "casadi_rank1(" << A << ", " << sparsity(sp_A) << ", "
2046  << alpha << ", " << x << ", " << y << ");";
2047  return s.str();
2048  }
2049 
2051  const std::string& res, casadi_int ndim, const std::string& grid,
2052  const std::string& offset,
2053  const std::string& values, const std::string& x,
2054  const std::string& lookup_mode, casadi_int m,
2055  const std::string& iw, const std::string& w) {
2057  std::stringstream s;
2058  s << "casadi_interpn(" << res << ", " << ndim << ", " << grid << ", " << offset << ", "
2059  << values << ", " << x << ", " << lookup_mode << ", " << m << ", " << iw << ", " << w << ");";
2060  return s.str();
2061  }
2062 
2063  std::string CodeGenerator::interpn_grad(const std::string& grad,
2064  casadi_int ndim, const std::string& grid, const std::string& offset,
2065  const std::string& values, const std::string& x,
2066  const std::string& lookup_mode, casadi_int m,
2067  const std::string& iw, const std::string& w) {
2069  std::stringstream s;
2070  s << "casadi_interpn_grad(" << grad << ", " << ndim << ", " << grid << ", " << offset << ", "
2071  << values << ", " << x << ", " << lookup_mode << "," << m << ", " << iw << ", " << w << ");";
2072  return s.str();
2073  }
2074 
2075  std::string CodeGenerator::trans(const std::string& x, const Sparsity& sp_x,
2076  const std::string& y, const Sparsity& sp_y,
2077  const std::string& iw) {
2079  return "casadi_trans(" + x + "," + sparsity(sp_x) + ", "
2080  + y + ", " + sparsity(sp_y) + ", " + iw + ")";
2081  }
2082 
2083  std::string CodeGenerator::declare(std::string s) {
2084  // Add c linkage
2085  std::string cpp_prefix = this->cpp ? "extern \"C\" " : "";
2086 
2087  // To header file
2088  if (this->with_header) {
2089  this->header << cpp_prefix << this->dll_import << s << ";\n";
2090  }
2091 
2092  // Return name with declarations
2093  return cpp_prefix + this->dll_export + s;
2094  }
2095 
2096  std::string
2097  CodeGenerator::project(const std::string& arg, const Sparsity& sp_arg,
2098  const std::string& res, const Sparsity& sp_res,
2099  const std::string& w) {
2100  // If sparsity match, simple copy
2101  if (sp_arg==sp_res) return copy(arg, sp_arg.nnz(), res);
2102 
2103  // Create call
2105  std::stringstream s;
2106  s << "casadi_project(" << arg << ", " << sparsity(sp_arg) << ", " << res << ", "
2107  << sparsity(sp_res) << ", " << w << ");";
2108  return s.str();
2109  }
2110 
2111  std::string
2112  CodeGenerator::tri_project(const std::string& arg, const Sparsity& sp_arg,
2113  const std::string& res, bool lower) {
2114  // Create call
2116  std::stringstream s;
2117  s << "casadi_tri_project(" << arg << ", " << sparsity(sp_arg) << ", ";
2118  s << res << ", " << (lower ? 1: 0) << ");";
2119  return s.str();
2120  }
2121 
2122  std::string
2123  CodeGenerator::densify(const std::string& arg, const Sparsity& sp_arg,
2124  const std::string& res, bool tr) {
2125  // Create call
2127  std::stringstream s;
2128  s << "casadi_densify(" << arg << ", " << sparsity(sp_arg) << ", " << res << ", "
2129  << (tr ? 1 : 0) << ");";
2130  return s.str();
2131  }
2132 
2133  std::string
2134  CodeGenerator::sparsify(const std::string& arg, const std::string& res,
2135  const Sparsity& sp_res, bool tr) {
2136  // Create call
2138  std::stringstream s;
2139  s << "casadi_sparsify(" << arg << ", " << res << ", "
2140  << sparsity(sp_res) << ", " << (tr ? 1 : 0) << ");";
2141  return s.str();
2142  }
2143 
2144  std::string CodeGenerator::printf(const std::string& str, const std::vector<std::string>& arg) {
2146  std::stringstream s;
2147  s << "CASADI_PRINTF(";
2148  // Loop over lines in str
2149  std::string::size_type pos = 0, prev = 0;
2150  while ((pos = str.find('\n', prev)) != std::string::npos) {
2151  // Any line containing a trailing new line
2152  s << "\"" << str.substr(prev, pos-prev) << "\\n\"\n";
2153  prev = pos + 1;
2154  }
2155  // Remainder without trailing new line
2156  s << "\"" << str.substr(prev) << "\"";
2157  for (casadi_int i=0; i<arg.size(); ++i) s << ", " << arg[i];
2158  s << ");";
2159  return s.str();
2160  }
2161 
2162  std::string CodeGenerator::printf(const std::string& str, const std::string& arg1) {
2163  std::vector<std::string> arg;
2164  arg.push_back(arg1);
2165  return printf(str, arg);
2166  }
2167 
2168  std::string CodeGenerator::printf(const std::string& str, const std::string& arg1,
2169  const std::string& arg2) {
2170  std::vector<std::string> arg;
2171  arg.push_back(arg1);
2172  arg.push_back(arg2);
2173  return printf(str, arg);
2174  }
2175 
2176  std::string CodeGenerator::printf(const std::string& str, const std::string& arg1,
2177  const std::string& arg2, const std::string& arg3) {
2178  std::vector<std::string> arg;
2179  arg.push_back(arg1);
2180  arg.push_back(arg2);
2181  arg.push_back(arg3);
2182  return printf(str, arg);
2183  }
2184 
2185  std::string CodeGenerator::axpy(casadi_int n, const std::string& a,
2186  const std::string& x, const std::string& y) {
2188  return "casadi_axpy(" + str(n) + ", " + a + ", " + x + ", " + y + ");";
2189  }
2190 
2191  std::string CodeGenerator::clip_min(const std::string& x, casadi_int n,
2192  const std::string& min, const std::string& mask) {
2194  return "casadi_clip_min(" + x + ", " + str(n) + ", " + min + ", " + mask + ");";
2195  }
2196 
2197  std::string CodeGenerator::clip_max(const std::string& x, casadi_int n,
2198  const std::string& min, const std::string& mask) {
2200  return "casadi_clip_max(" + x + ", " + str(n) + ", " + min + ", " + mask + ");";
2201  }
2202 
2203  std::string CodeGenerator::vector_fmax(casadi_int n, const std::string& x,
2204  const std::string& y, const std::string& z) {
2206  return "casadi_vector_fmax(" + str(n) + ", " + x + ", " + y + ", " + z + ");";
2207  }
2208 
2209  std::string CodeGenerator::vector_fmin(casadi_int n, const std::string& x,
2210  const std::string& y, const std::string& z) {
2212  return "casadi_vector_fmin(" + str(n) + ", " + x + ", " + y + ", " + z + ");";
2213  }
2214 
2215  std::string CodeGenerator::masked_norm_inf(casadi_int n, const std::string& x,
2216  const std::string& mask) {
2218  return "casadi_masked_norm_inf(" + str(n) + ", " + x + ", " + mask + ")";
2219  }
2220 
2221  std::string CodeGenerator::scal(casadi_int n, const std::string& alpha, const std::string& x) {
2223  return "casadi_scal(" + str(n) + ", " + alpha + ", " + x + ");";
2224  }
2225 
2226  std::string CodeGenerator::mv(const std::string& x, const Sparsity& sp_x,
2227  const std::string& y, const std::string& z, bool tr) {
2229  return "casadi_mv(" + x + ", " + sparsity(sp_x) + ", " + y + ", "
2230  + z + ", " + (tr ? "1" : "0") + ");";
2231  }
2232 
2233  std::string CodeGenerator::mv(const std::string& x, casadi_int nrow_x, casadi_int ncol_x,
2234  const std::string& y, const std::string& z, bool tr) {
2236  return "casadi_mv_dense(" + x + ", " + str(nrow_x) + ", " + str(ncol_x) + ", "
2237  + y + ", " + z + ", " + (tr ? "1" : "0") + ");";
2238  }
2239 
2240  std::string CodeGenerator::mtimes(const std::string& x, const Sparsity& sp_x,
2241  const std::string& y, const Sparsity& sp_y,
2242  const std::string& z, const Sparsity& sp_z,
2243  const std::string& w, bool tr) {
2245  return "casadi_mtimes(" + x + ", " + sparsity(sp_x) + ", " + y + ", " + sparsity(sp_y) + ", "
2246  + z + ", " + sparsity(sp_z) + ", " + w + ", " + (tr ? "1" : "0") + ");";
2247  }
2248 
2249  std::string CodeGenerator::trilsolve(const Sparsity& sp_x, const std::string& x,
2250  const std::string& y, bool tr, bool unity, casadi_int nrhs) {
2252  return "casadi_trilsolve(" + sparsity(sp_x) + ", " + x + ", " + y + ", " + str(tr) + ", "
2253  + str(unity) + ", " + str(nrhs) + ");";
2254  }
2255 
2256  std::string CodeGenerator::triusolve(const Sparsity& sp_x, const std::string& x,
2257  const std::string& y, bool tr, bool unity, casadi_int nrhs) {
2259  return "casadi_triusolve(" + sparsity(sp_x) + ", " + x + ", " + y + ", " + str(tr) + ", "
2260  + str(unity) + ", " + str(nrhs) + ");";
2261  }
2262 
2263 
2264  std::string CodeGenerator::logsumexp(const std::string& A, casadi_int n) {
2266  std::stringstream s;
2267  s << "casadi_logsumexp(" << A << ", " << n << ");";
2268  return s.str();
2269  }
2270 
2271  void CodeGenerator::print_formatted(const std::string& s) {
2272  // Quick return if empty
2273  if (s.empty()) return;
2274 
2275  // If new line, add indentation
2276  if (newline_) {
2277  casadi_int shift = s.front()=='}' ? -1 : 0;
2278  casadi_assert_dev(current_indent_+shift>=0);
2279  this->buffer << std::string(indent_*(current_indent_+shift), ' ');
2280  newline_ = false;
2281  }
2282 
2283  // Print to body
2284  this->buffer << s;
2285 
2286  // Brackets change indentation for next row
2287  // NOTE(@jaeandersson): Should ignore strings, comments
2288  for (char c : s) {
2289  if (c=='{') {
2290  indent();
2291  } else if (c=='}') {
2292  unindent();
2293  }
2294  }
2295  }
2296 
2297  CodeGenerator& CodeGenerator::operator<<(const std::string& s) {
2298  // Loop over newline characters
2299  size_t off=0;
2300  while (true) {
2301  size_t pos = s.find('\n', off);
2302  if (pos==std::string::npos) {
2303  // No more newline characters
2304  print_formatted(s.substr(off));
2305  break;
2306  } else {
2307  // Ends with newline
2308  print_formatted(s.substr(off, pos-off));
2309  this->buffer << '\n';
2310  newline_ = true;
2311  off = pos+1;
2312  }
2313  }
2314 
2315  return *this;
2316  }
2317 
2318  void CodeGenerator::flush(std::ostream &s) {
2319  s << this->buffer.str();
2320  this->buffer.str(std::string());
2321  }
2322 
2323  void CodeGenerator::local(const std::string& name, const std::string& type,
2324  const std::string& ref) {
2325  // Check if the variable already exists
2326  auto it = local_variables_.find(name);
2327  if (it==local_variables_.end()) {
2328  // Add it
2329  local_variables_[name] = std::make_pair(type, ref);
2330  } else {
2331  // Consistency check
2332  casadi_assert(it->second.first==type, "Type mismatch for " + name);
2333  casadi_assert(it->second.second==ref, "Type mismatch for " + name);
2334  }
2335  }
2336 
2337  std::string CodeGenerator::sx_work(casadi_int i) {
2338  if (avoid_stack_) {
2339  return "w[" + str(i) + "]";
2340  } else {
2341  std::string name = "a"+format_padded(i);
2342 
2343  // Make sure work vector element has been declared
2344  local(name, "casadi_real");
2345 
2346  return name;
2347  }
2348  }
2349 
2350  void CodeGenerator::init_local(const std::string& name, const std::string& def) {
2351  auto it = local_default_.find(name);
2352  if (it!=local_default_.end()) {
2353  casadi_assert(it->second==def, "Initial value mismatch for " + name);
2354  }
2355  local_default_.insert(std::make_pair(name, def));
2356  }
2357 
2358  std::string CodeGenerator::
2359  sanitize_source(const std::string& src,
2360  const std::vector<std::string>& inst, bool add_shorthand) {
2361  // Create suffix if templates type are not all "casadi_real"
2362  std::string suffix;
2363  for (const std::string& s : inst) {
2364  if (s!="casadi_real") {
2365  for (const std::string& s : inst) suffix += "_" + s;
2366  break;
2367  }
2368  }
2369 
2370  // Construct map of name replacements
2371  std::vector<std::pair<std::string, std::string> > rep;
2372  for (casadi_int i=0; i<inst.size(); ++i) {
2373  rep.push_back(std::make_pair("T" + str(i+1), inst[i]));
2374  }
2375 
2376  // Return object
2377  std::stringstream ret;
2378  // Process C++ source
2379  std::string line;
2380  std::istringstream stream(src);
2381  while (std::getline(stream, line)) {
2382  size_t n1, n2;
2383 
2384  // C++ template declarations are ignored
2385  if (line.find("template")==0) continue;
2386 
2387  // Macro definitions are ignored
2388  if (line.find("#define")==0) continue;
2389  if (line.find("#undef")==0) continue;
2390 
2391  // Inline declaration
2392  if (line == "inline") continue;
2393 
2394  // If line starts with "// SYMBOL", add shorthand
2395  if (line.find("// SYMBOL") != std::string::npos) {
2396  n1 = line.find("\"");
2397  n2 = line.find("\"", n1+1);
2398  std::string sym = line.substr(n1+1, n2-n1-1);
2399  if (add_shorthand) shorthand(sym + suffix);
2400  if (!suffix.empty()) {
2401  rep.push_back(std::make_pair(sym, sym + suffix));
2402  }
2403  continue;
2404  }
2405 
2406  // If line starts with "// C-REPLACE", add to list of replacements
2407  if (line.find("// C-REPLACE") != std::string::npos) {
2408  // Get C++ string
2409  n1 = line.find("\"");
2410  n2 = line.find("\"", n1+1);
2411  std::string key = line.substr(n1+1, n2-n1-1);
2412  // Get C string
2413  n1 = line.find("\"", n2+1);
2414  n2 = line.find("\"", n1+1);
2415  std::string sub = line.substr(n1+1, n2-n1-1);
2416  // Add to replacements
2417  rep.push_back(std::make_pair(key, sub));
2418  continue;
2419  }
2420 
2421  // If line starts with "// C-VERBOSE", skip the next line
2422  if (!verbose_runtime && line.find("// C-VERBOSE") != std::string::npos) {
2423  // Ignore next line
2424  std::getline(stream, line);
2425  continue;
2426  }
2427 
2428  // Ignore other C++ style comment
2429  if ((n1 = line.find("//")) != std::string::npos) line.erase(n1);
2430 
2431  // Remove trailing spaces
2432  if ((n1 = line.find_last_not_of(' ')) != std::string::npos) {
2433  line.erase(n1 + 1);
2434  } else {
2435  continue;
2436  }
2437 
2438  // Perform string replacements
2439  for (auto&& it = rep.rbegin(); it!=rep.rend(); ++it) {
2440  line = replace(line, it->first, it->second);
2441  }
2442 
2443  // Append to return
2444  ret << line << "\n";
2445  }
2446 
2447  // Trailing newline
2448  ret << "\n";
2449  return ret.str();
2450  }
2451 
2452  void CodeGenerator::comment(const std::string& s) {
2453  if (verbose) {
2454  *this << "/* " << s << " */\n";
2455  }
2456  }
2457 
2459  add_io_sparsities(const std::string& name,
2460  const std::vector<Sparsity>& sp_in,
2461  const std::vector<Sparsity>& sp_out) {
2462  // Insert element, quick return if it already exists
2463  if (!sparsity_meta.insert(name).second) return;
2464 
2465  // Input sparsities
2466  *this << declare("const casadi_int* " + name + "_sparsity_in(casadi_int i)") << " {\n"
2467  << "switch (i) {\n";
2468  for (casadi_int i=0; i<sp_in.size(); ++i) {
2469  *this << "case " << i << ": return " << sparsity(sp_in[i], force_canonical) << ";\n";
2470  }
2471  *this << "default: return 0;\n}\n"
2472  << "}\n\n";
2473 
2474  // Output sparsities
2475  *this << declare("const casadi_int* " + name + "_sparsity_out(casadi_int i)") << " {\n"
2476  << "switch (i) {\n";
2477  for (casadi_int i=0; i<sp_out.size(); ++i) {
2478  *this << "case " << i << ": return " << sparsity(sp_out[i], force_canonical) << ";\n";
2479  }
2480  *this << "default: return 0;\n}\n"
2481  << "}\n\n";
2482  }
2483 
2484  std::string CodeGenerator::
2485  qr(const std::string& sp, const std::string& A, const std::string& w,
2486  const std::string& sp_v, const std::string& v, const std::string& sp_r,
2487  const std::string& r, const std::string& beta, const std::string& prinv,
2488  const std::string& pc) {
2490  return "casadi_qr(" + sp + ", " + A + ", " + w + ", "
2491  + sp_v + ", " + v + ", " + sp_r + ", " + r + ", "
2492  + beta + ", " + prinv + ", " + pc + ");";
2493  }
2494 
2495  std::string CodeGenerator::
2496  qr_solve(const std::string& x, casadi_int nrhs, bool tr,
2497  const std::string& sp_v, const std::string& v,
2498  const std::string& sp_r, const std::string& r,
2499  const std::string& beta, const std::string& prinv,
2500  const std::string& pc, const std::string& w) {
2502  return "casadi_qr_solve(" + x + ", " + str(nrhs) + ", " + (tr ? "1" : "0") + ", "
2503  + sp_v + ", " + v + ", " + sp_r + ", " + r + ", "
2504  + beta + ", " + prinv + ", " + pc + ", " + w + ");";
2505  }
2506 
2507  std::string CodeGenerator::
2508  lsqr_solve(const std::string& A, const std::string&x,
2509  casadi_int nrhs, bool tr, const std::string& sp, const std::string& w) {
2511  return "casadi_lsqr_solve(" + A + ", " + x + ", " + str(nrhs) + ", "
2512  + (tr ? "1" : "0") + ", " + sp + ", " + w + ");";
2513  }
2514 
2515  std::string CodeGenerator::
2516  ldl(const std::string& sp_a, const std::string& a,
2517  const std::string& sp_lt, const std::string& lt, const std::string& d,
2518  const std::string& p, const std::string& w) {
2520  return "casadi_ldl(" + sp_a + ", " + a + ", " + sp_lt + ", " + lt + ", "
2521  + d + ", " + p + ", " + w + ");";
2522  }
2523 
2524  std::string CodeGenerator::
2525  ldl_solve(const std::string& x, casadi_int nrhs,
2526  const std::string& sp_lt, const std::string& lt, const std::string& d,
2527  const std::string& p, const std::string& w) {
2529  return "casadi_ldl_solve(" + x + ", " + str(nrhs) + ", " + sp_lt + ", "
2530  + lt + ", " + d + ", " + p + ", " + w + ");";
2531  }
2532 
2533  std::string CodeGenerator::
2534  fmax(const std::string& x, const std::string& y) {
2536  return "casadi_fmax(" + x + ", " + y + ");";
2537  }
2538 
2539  std::string CodeGenerator::
2540  fmin(const std::string& x, const std::string& y) {
2542  return "casadi_fmin(" + x + ", " + y + ");";
2543  }
2544 
2545  std::string CodeGenerator::
2546  vfmax(const std::string& x, casadi_int n, const std::string& y) {
2548  return "casadi_vfmax(" + x + ", " + str(n) + ", " + y + ");";
2549  }
2550 
2551  std::string CodeGenerator::
2552  vfmin(const std::string& x, casadi_int n, const std::string& y) {
2554  return "casadi_vfmin(" + x + ", " + str(n) + ", " + y + ");";
2555  }
2556 
2557  std::string CodeGenerator::
2558  vfmax(const std::string& x, const std::string& n, const std::string& y) {
2560  return "casadi_vfmax(" + x + ", " + n + ", " + y + ");";
2561  }
2562 
2563  std::string CodeGenerator::
2564  vfmin(const std::string& x, const std::string& n, const std::string& y) {
2566  return "casadi_vfmin(" + x + ", " + n + ", " + y + ");";
2567  }
2568 
2569  std::string CodeGenerator::
2570  max(const std::string& x, const std::string& y) {
2572  return "casadi_max(" + x + ", " + y + ")";
2573  }
2574 
2575  std::string CodeGenerator::
2576  min(const std::string& x, const std::string& y) {
2578  return "casadi_min(" + x + ", " + y + ")";
2579  }
2580 
2581  std::string CodeGenerator::
2582  mmax(const std::string& x, casadi_int n, bool is_dense) {
2584  return "casadi_mmax(" + x + ", " + str(n) + ", " + str(casadi_int(is_dense)) + ")";
2585  }
2586 
2587  std::string CodeGenerator::
2588  mmin(const std::string& x, casadi_int n, bool is_dense) {
2590  return "casadi_mmin(" + x + ", " + str(n) + ", " + str(casadi_int(is_dense)) + ")";
2591  }
2592 
2593  std::string CodeGenerator::
2594  max_viol(casadi_int n, const std::string& x, const std::string& lb, const std::string& ub) {
2596  return "casadi_max_viol(" + str(n) + ", " + x+ ", " + lb + ", " + ub + ")";
2597  }
2598 
2599  std::string CodeGenerator::
2600  sum_viol(casadi_int n, const std::string& x, const std::string& lb, const std::string& ub) {
2602  return "casadi_sum_viol(" + str(n) + ", " + x+ ", " + lb + ", " + ub + ")";
2603  }
2604 
2605  std::string CodeGenerator::
2606  norm_inf(casadi_int n, const std::string& x) {
2608  return "casadi_norm_inf(" + str(n) + ", " + x + ")";
2609  }
2610 
2611  std::string CodeGenerator::
2612  norm_1(casadi_int n, const std::string& x) {
2614  return "casadi_norm_1(" + str(n) + ", " + x + ")";
2615  }
2616 
2617  std::string CodeGenerator::
2618  norm_2(casadi_int n, const std::string& x) {
2620  return "casadi_norm_2(" + str(n) + ", " + x + ")";
2621  }
2622 
2623  std::string CodeGenerator::
2624  lb_eig(const Sparsity& sp_h, const std::string& h) {
2626  return "casadi_lb_eig(" + sparsity(sp_h) + ", " + h + ")";
2627  }
2628 
2629  std::string CodeGenerator::
2630  regularize(const Sparsity& sp_h, const std::string& h, const std::string& reg) {
2632  return "casadi_regularize(" + sparsity(sp_h) + ", " + h + ", " + reg + ");";
2633  }
2634 
2635  std::string CodeGenerator::
2637  const std::string& Hin, const std::string& Hout, const std::string& iw, const std::string& w) {
2639  return Convexify::generate(*this, d, Hin, Hout, iw, w);
2640  }
2641 
2642  std::string CodeGenerator::
2643  low(const std::string& x, const std::string& grid, casadi_int ng, casadi_int lookup_mode) {
2645  return "casadi_low(" + x + ", " + grid + ", " + str(ng) + ", " + str(lookup_mode) + ");";
2646  }
2647 
2648  std::string CodeGenerator::
2649  bound_consistency(casadi_int n, const std::string& x,
2650  const std::string& lam, const std::string& lbx, const std::string& ubx) {
2652  return "casadi_bound_consistency(" + str(n) + ", " + x + ", " + lam +
2653  ", " + lbx + ", " + ubx + ")";
2654  }
2655 
2656  std::string CodeGenerator::
2657  file_slurp(const std::string& fname, casadi_int n, const std::string& a) {
2659  return "casadi_file_slurp(\"" + fname + "\", " + str(n) + ", " + a + ")";
2660  }
2661 
2662  std::string CodeGenerator::
2663  cache_check(const std::string& key, const std::string& cache, const std::string& loc,
2664  casadi_int stride, casadi_int sz, casadi_int key_sz, const std::string& val) {
2666  return "cache_check(" + key + ", " + cache + ", " + loc + ", " +
2667  str(stride) + ", " + str(sz) + ", " + str(key_sz) + ", " + val + ")";
2668  }
2669 
2670  void CodeGenerator::sz_work(size_t& sz_arg, size_t& sz_res, size_t& sz_iw, size_t& sz_w) const {
2671  sz_arg = sz_res = sz_iw = sz_w = 0;
2672  for (auto&& f : added_functions_) {
2673  sz_arg = std::max(sz_arg, f.f.sz_arg());
2674  sz_res = std::max(sz_res, f.f.sz_res());
2675  sz_iw = std::max(sz_iw, f.f.sz_iw());
2676  sz_w = std::max(sz_w, f.f.sz_w());
2677  }
2678  }
2679 
2680 } // namespace casadi
Helper class for C code generation.
std::string triusolve(const Sparsity &sp_x, const std::string &x, const std::string &y, bool tr, bool unity, casadi_int nrhs)
Codegen upper triangular solve.
void define_pool_double(const std::string &name, const std::vector< double > &def)
Allocate file scope double writeable memory.
bool codegen_scalars
Codegen scalar.
std::string fill(const std::string &res, std::size_t n, const std::string &v)
Create a fill operation.
std::stringstream includes
std::string axpy(casadi_int n, const std::string &a, const std::string &x, const std::string &y)
Codegen axpy: y += a*x.
static std::string fmu_helpers(const std::string &modelname)
FMU helper functions.
std::string lsqr_solve(const std::string &A, const std::string &x, casadi_int nrhs, bool tr, const std::string &sp, const std::string &w)
std::set< std::string > added_externals_
std::string logsumexp(const std::string &A, casadi_int n)
std::string clip_min(const std::string &x, casadi_int n, const std::string &min, const std::string &mask)
Codegen clip_min: Clips the smaller entries in a vector than min to the min.
std::string project(const std::string &arg, const Sparsity &sp_arg, const std::string &res, const Sparsity &sp_res, const std::string &w)
Sparse assignment.
std::string add_dependency(const Function &f)
Add a function dependency.
std::string mmax(const std::string &x, casadi_int n, bool is_dense)
mmax
std::string work(casadi_int n, casadi_int sz, bool is_ref) const
std::string arg(casadi_int i) const
Refer to argument.
std::string dump()
Generate a file, return code as string.
std::string wrapper(const Function &base, const std::string &name)
std::vector< std::string > added_sfunctions
std::string pool_double(const std::string &name) const
Access file scope double writeable memory.
void add_io_sparsities(const std::string &name, const std::vector< Sparsity > &sp_in, const std::vector< Sparsity > &sp_out)
Add io sparsity patterns of a function.
void scope_enter()
Enter a local scope.
std::string rom_integer(const void *id) const
Access file scope integer read-only memory.
std::string norm_2(casadi_int n, const std::string &x)
norm_2
std::string copy(const std::string &arg, std::size_t n, const std::string &res)
Create a copy operation.
std::map< std::string, casadi_int > pool_double_
void comment(const std::string &s)
Write a comment line (ignored if not verbose)
void reserve_work(casadi_int n)
Reserve a maximum size of work elements, used for padding of index.
std::string masked_norm_inf(casadi_int n, const std::string &x, const std::string &mask)
codegen masked_norm_inf: The mask tells what entry is used in the inf-norm.
std::set< std::string > added_includes_
std::string constant(const std::vector< casadi_int > &v)
Represent an array constant; adding it when new.
void add(const Function &f, bool with_jac_sparsity=false)
Add a function (name generated)
void flush(std::ostream &s)
Flush the buffer to a stream of choice.
casadi_int add_sparsity(const Sparsity &sp, bool canonical=true)
std::string scal(casadi_int n, const std::string &alpha, const std::string &x)
What does scal do??
static void stream_open(std::ostream &f, bool cpp)
Print file header.
std::string rank1(const std::string &A, const Sparsity &sp_A, const std::string &alpha, const std::string &x, const std::string &y)
Rank-1 update.
std::string low(const std::string &x, const std::string &grid, casadi_int ng, casadi_int lookup_mode)
low
std::multimap< Auxiliary, std::vector< std::string > > added_auxiliaries_
CodeGenerator(const std::string &name, const Dict &opts=Dict())
Constructor.
std::string fmin(const std::string &x, const std::string &y)
fmin
static void stream_close(std::ostream &f, bool cpp)
Print file header.
std::string sum_viol(casadi_int n, const std::string &x, const std::string &lb, const std::string &ub)
sum_viol
std::string to_mex(const Sparsity &sp, const std::string &arg)
Create matrix in MATLAB's MEX format.
std::string printf(const std::string &str, const std::vector< std::string > &arg=std::vector< std::string >())
Printf.
std::string print_op(casadi_int op, const std::string &a0)
Print an operation to a c file.
std::map< std::string, std::pair< std::string, std::string > > local_variables_
std::string max(const std::string &x, const std::string &y)
max
void indent()
Increase indentation.
std::string rom_double(const void *id) const
Access file scope double read-only memory.
std::map< std::string, std::string > local_default_
std::vector< std::vector< char > > char_constants_
static std::string array(const std::string &type, const std::string &name, casadi_int len, const std::string &def=std::string())
std::string bilin(const std::string &A, const Sparsity &sp_A, const std::string &x, const std::string &y)
Codegen bilinear form.
std::string bound_consistency(casadi_int n, const std::string &x, const std::string &lam, const std::string &lbx, const std::string &ubx)
bound_consistency
std::string vector_fmax(casadi_int n, const std::string &x, const std::string &y, const std::string &z)
Codegen vector_fmax: Takes vectorwise max of a vector and writes the result to second vector.
std::string sparsify(const std::string &arg, const std::string &res, const Sparsity &sp_res, bool tr=false)
Sparsify.
std::string mv(const std::string &x, const Sparsity &sp_x, const std::string &y, const std::string &z, bool tr)
Codegen sparse matrix-vector multiplication.
static size_t hash(const std::vector< double > &v)
std::vector< std::vector< double > > pool_double_defaults_
std::string ldl_solve(const std::string &x, casadi_int nrhs, const std::string &sp_lt, const std::string &lt, const std::string &d, const std::string &p, const std::string &w)
LDL solve.
CodeGenerator & operator<<(const std::string &s)
Print a string to buffer.
std::string generate(const std::string &prefix="")
Generate file(s)
std::string ldl(const std::string &sp_a, const std::string &a, const std::string &sp_lt, const std::string &lt, const std::string &d, const std::string &p, const std::string &w)
LDL factorization.
std::string lb_eig(const Sparsity &sp_h, const std::string &h)
lb_eig
std::string operator()(const Function &f, const std::string &arg, const std::string &res, const std::string &iw, const std::string &w, const std::string &failure_ret="1")
Generate a call to a function (generic signature)
std::stringstream buffer
std::string mmin(const std::string &x, casadi_int n, bool is_dense)
mmin
std::string densify(const std::string &arg, const Sparsity &sp_arg, const std::string &res, bool tr=false)
Densify.
std::multimap< size_t, size_t > added_double_constants_
void local(const std::string &name, const std::string &type, const std::string &ref="")
Declare a local variable.
void add_external(const std::string &new_external)
Add an external function declaration.
std::string workel(casadi_int n) const
std::string min(const std::string &x, const std::string &y)
min
void setup_callback(const std::string &s, const Function &f)
Setup a callback.
casadi_int max_initializer_elements_per_line
std::string mem(const Function &f)
Access thread-local memory.
void print_vector(std::ostream &s, const std::string &name, const std::vector< casadi_int > &v)
Print casadi_int vector to a c file.
std::stringstream header
void unindent()
Decrease indentation.
std::string from_mex(std::string &arg, const std::string &res, std::size_t res_off, const Sparsity &sp_res, const std::string &w)
Get matrix from MATLAB's MEX format.
std::vector< std::vector< double > > double_constants_
std::string res(casadi_int i) const
Refer to resuly.
std::vector< std::vector< casadi_int > > integer_constants_
std::string interpn(const std::string &res, casadi_int ndim, const std::string &grid, const std::string &offset, const std::string &values, const std::string &x, const std::string &lookup_mode, casadi_int m, const std::string &iw, const std::string &w)
Multilinear interpolation.
void sz_work(size_t &sz_arg, size_t &sz_res, size_t &sz_iw, size_t &sz_w) const
Get number of temporary variables needed for all functions.
std::multimap< size_t, size_t > added_char_constants_
std::vector< std::vector< std::string > > string_constants_
std::string vfmax(const std::string &x, casadi_int n, const std::string &y)
vfmax
std::string norm_inf(casadi_int n, const std::string &x)
norm_inf
std::string ones(casadi_int sz)
std::string vector_fmin(casadi_int n, const std::string &x, const std::string &y, const std::string &z)
Codegen vector_fmin: Takes vectorwise min of a vector and writes the result to second vector.
std::map< const void *, casadi_int > file_scope_integer_
std::string declare(std::string s)
Declare a function.
std::string mtimes(const std::string &x, const Sparsity &sp_x, const std::string &y, const Sparsity &sp_y, const std::string &z, const Sparsity &sp_z, const std::string &w, bool tr)
Codegen sparse matrix-matrix multiplication.
void scope_exit()
Exit a local scope.
std::string vfmin(const std::string &x, casadi_int n, const std::string &y)
vfmin
void init_local(const std::string &name, const std::string &def)
Specify the default value for a local variable.
std::string cache_check(const std::string &key, const std::string &cache, const std::string &loc, casadi_int stride, casadi_int sz, casadi_int key_sz, const std::string &val)
cache check
void define_rom_integer(const void *id, casadi_int size)
Allocate file scope integer read-only memory.
std::string qr_solve(const std::string &x, casadi_int nrhs, bool tr, const std::string &sp_v, const std::string &v, const std::string &sp_r, const std::string &r, const std::string &beta, const std::string &prinv, const std::string &pc, const std::string &w)
QR solve.
casadi_int max_declarations_per_line
std::string sanitize_source(const std::string &src, const std::vector< std::string > &inst, bool add_shorthand=true)
Sanitize source files for codegen.
std::string dot(casadi_int n, const std::string &x, const std::string &y)
Codegen inner product.
std::vector< FunctionMeta > added_functions_
std::string clip_max(const std::string &x, casadi_int n, const std::string &min, const std::string &mask)
Codegen clip_max: Clips the larger entries in a vector than max to the max.
static std::string casadi_version()
Current CasADi version as string.
void define_rom_double(const void *id, casadi_int size)
Allocate file scope double read-only memory.
std::string interpn_grad(const std::string &grad, casadi_int ndim, const std::string &grid, const std::string &offset, const std::string &values, const std::string &x, const std::string &lookup_mode, casadi_int m, const std::string &iw, const std::string &w)
Multilinear interpolation - calculate gradient.
void add_include(const std::string &new_include, bool relative_path=false, const std::string &use_ifdef=std::string())
Add an include file optionally using a relative path "..." instead of an absolute path <....
std::string shorthand(const std::string &name) const
Get a shorthand.
Auxiliary
Auxiliary functions.
void constant_copy(const std::string &var_name, const std::vector< casadi_int > &v, const std::string &type="casadi_int")
Represent an array constant; adding it when new.
std::map< std::string, std::map< FunctionInternal *, casadi_int > > added_wrappers_
void copy_check(const std::string &arg, std::size_t n, const std::string &res, bool check_lhs=true, bool check_rhs=true)
std::stringstream body
std::string tri_project(const std::string &arg, const Sparsity &sp_arg, const std::string &res, bool lower)
Project triangular part.
std::multimap< size_t, size_t > added_integer_constants_
std::multimap< size_t, size_t > added_string_constants_
std::map< const void *, casadi_int > file_scope_double_
std::string file_slurp(const std::string &fname, casadi_int n, const std::string &a)
Slurp a file.
std::string initializer(const std::vector< T > &v)
Print an initializer.
std::string norm_1(casadi_int n, const std::string &x)
norm_1
std::set< std::string > sparsity_meta
std::string max_viol(casadi_int n, const std::string &x, const std::string &lb, const std::string &ub)
max_viol
std::string convexify_eval(const ConvexifyData &d, const std::string &Hin, const std::string &Hout, const std::string &iw, const std::string &w)
convexify
std::vector< std::string > exposed_fname
std::string sparsity(const Sparsity &sp, bool canonical=true)
std::string print_scalar(const std::string &arg)
Print canonical representaion of a scalar.
void copy_default(const std::string &arg, std::size_t n, const std::string &res, const std::string &def, bool check_rhs=true)
std::string trans(const std::string &x, const Sparsity &sp_x, const std::string &y, const Sparsity &sp_y, const std::string &iw)
Transpose.
casadi_int get_constant(const std::vector< double > &v, bool allow_adding=false)
Get or add a constant.
casadi_int get_sparsity(const Sparsity &sp) const
Get the index of an existing sparsity pattern.
void print_formatted(const std::string &s)
Print without newline characters.
bool elide_copy(casadi_int sz)
std::string zeros(casadi_int sz)
std::string trilsolve(const Sparsity &sp_x, const std::string &x, const std::string &y, bool tr, bool unity, casadi_int nrhs)
Codegen lower triangular solve.
std::set< std::string > added_shorthands_
static bool equal(const std::vector< T > &v1, const std::vector< T > &v2)
std::stringstream auxiliaries
std::string qr(const std::string &sp, const std::string &A, const std::string &w, const std::string &sp_v, const std::string &v, const std::string &sp_r, const std::string &r, const std::string &beta, const std::string &prinv, const std::string &pc)
QR factorization.
std::string fmax(const std::string &x, const std::string &y)
fmax
std::string clear(const std::string &res, std::size_t n)
Create a fill operation.
std::string print_canonical(const Sparsity &sp, const std::string &arg)
Print canonical representaion of a matrix.
std::string format_padded(casadi_int i) const
std::string regularize(const Sparsity &sp_h, const std::string &h, const std::string &reg)
regularize
void add_auxiliary(Auxiliary f, const std::vector< std::string > &inst={"casadi_real"})
Add a built-in auxiliary function.
std::string sx_work(casadi_int i)
Declare a work vector element.
void generate(CodeGenerator &g, const std::vector< casadi_int > &arg, const std::vector< casadi_int > &res, const std::vector< bool > &arg_is_ref, std::vector< bool > &res_is_ref) const override
Generate code for the operation.
Definition: convexify.cpp:156
static std::unique_ptr< std::ostream > ofstream_ptr(const std::string &path, std::ios_base::openmode mode=std::ios_base::out)
Definition: filesystem.cpp:115
Internal class for Function.
bool has_refcount_
Reference counting in codegen?
virtual std::string codegen_mem_type() const
Thread-local memory object type.
std::vector< Sparsity > sparsity_in_
Input and output sparsity.
virtual void codegen_free_mem(CodeGenerator &g) const
Codegen for free_mem.
virtual void codegen_incref(CodeGenerator &g) const
Codegen incref for dependencies.
std::string signature_unrolled(const std::string &fname) const
Code generate the function.
virtual std::string codegen_name(const CodeGenerator &g, bool ns=true) const
Get name in codegen.
void codegen(CodeGenerator &g, const std::string &fname) const
Generate code the function.
virtual void codegen_release(CodeGenerator &g) const
Codegen for release.
virtual void codegen_alloc_mem(CodeGenerator &g) const
Codegen decref for alloc_mem.
virtual void codegen_checkout(CodeGenerator &g) const
Codegen for checkout.
virtual void codegen_declarations(CodeGenerator &g) const
Generate code for the declarations of the C function.
std::string signature(const std::string &fname) const
Code generate the function.
void codegen_meta(CodeGenerator &g) const
Generate meta-information allowing a user to evaluate a generated function.
virtual void codegen_init_mem(CodeGenerator &g) const
Codegen decref for init_mem.
virtual void codegen_decref(CodeGenerator &g) const
Codegen decref for dependencies.
Function object.
Definition: function.hpp:60
FunctionInternal * get() const
Definition: function.cpp:353
const std::vector< std::string > & name_in() const
Get input scheme.
Definition: function.cpp:961
const std::string & name() const
Name of the function.
Definition: function.cpp:1315
static bool check_name(const std::string &name)
Check if a string is a valid function name.
Definition: function.cpp:1324
casadi_int n_out() const
Get the number of function outputs.
Definition: function.cpp:823
casadi_int n_in() const
Get the number of function inputs.
Definition: function.cpp:819
const std::vector< Sparsity > & jac_sparsity(bool compact=false) const
Get, if necessary generate, the sparsity of all Jacobian blocks.
Definition: function.cpp:940
const std::vector< std::string > & name_out() const
Get output scheme.
Definition: function.cpp:965
static casadi_int copy_elision_min_size
General sparsity class.
Definition: sparsity.hpp:106
casadi_int nnz() const
Get the number of (structural) non-zeros.
Definition: sparsity.cpp:148
std::vector< casadi_int > compress(bool canonical=true) const
Compress a sparsity pattern.
Definition: sparsity.cpp:1305
The casadi namespace.
Definition: archiver.cpp:28
std::string join(const std::vector< std::string > &l, const std::string &delim)
CASADI_EXPORT std::string replace(const std::string &s, const std::string &p, const std::string &r)
Replace all occurences of p with r in s.
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
void hash_combine(std::size_t &seed, T v)
Generate a hash value incrementally (function taken from boost)
Definition: sparsity.hpp:1207
@ OP_SIGN
Definition: calculus.hpp:71
@ OP_FMAX
Definition: calculus.hpp:72
@ OP_LOG1P
Definition: calculus.hpp:202
@ OP_PRINTME
Definition: calculus.hpp:190
@ OP_HYPOT
Definition: calculus.hpp:206
@ OP_FMIN
Definition: calculus.hpp:72
@ OP_EXPM1
Definition: calculus.hpp:204
@ OP_FABS
Definition: calculus.hpp:71
@ OP_SQ
Definition: calculus.hpp:67
static std::string print(unsigned char op, const std::string &x, const std::string &y)
Print.
Definition: calculus.hpp:1641