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 "blas_impl.hpp"
31 #include <casadi_runtime_str.h>
32 #include "global_options.hpp"
33 #include "filesystem_impl.hpp"
34 #include <iomanip>
35 
36 namespace casadi {
37 
38  CodeGenerator::CodeGenerator(const std::string& name, const Dict& opts) {
39  // Default options
40  this->verbose = true;
41  this->verbose_runtime = false;
42  this->mex = false;
43  this->with_sfunction = false;
44  this->unroll_args = false;
45  this->static_aux = false;
46  this->inline_aux = false;
47  this->cpp = false;
48  this->main = false;
49  this->casadi_real_type = "double";
50  this->casadi_int_type = CASADI_INT_TYPE_STR;
51  this->codegen_scalars = false;
52  this->with_header = false;
53  this->with_mem = false;
54  this->with_export = true;
55  this->with_import = false;
56  this->include_math = true;
57  this->infinity = "INFINITY";
58  this->nan = "NAN";
59  this->real_min = "";
60  bool prefix_set = false;
61  this->prefix = "";
62  this->dump_dir_prefix = "";
63  this->dump_dir_suffix = "";
64  this->max_declarations_per_line = 12;
66  this->force_canonical = false;
67  this->l1_blas = false;
68 
69  avoid_stack_ = false;
70  indent_ = 2;
71  sz_zeros_ = 0;
72  sz_ones_ = 0;
73  thread_safe_ = false;
74 
75  // Read options
76  for (auto&& e : opts) {
77  if (e.first=="verbose") {
78  this->verbose = e.second;
79  } else if (e.first=="verbose_runtime") {
80  this->verbose_runtime = e.second;
81  } else if (e.first=="mex") {
82  this->mex = e.second;
83  } else if (e.first=="with_sfunction") {
84  this->with_sfunction = e.second;
85  } else if (e.first=="unroll_args") {
86  this->unroll_args = e.second;
87  } else if (e.first=="static_aux") {
88  this->static_aux = e.second;
89  } else if (e.first=="inline_aux") {
90  this->inline_aux = e.second;
91  } else if (e.first=="cpp") {
92  this->cpp = e.second;
93  } else if (e.first=="main") {
94  this->main = e.second;
95  } else if (e.first=="casadi_real") {
96  this->casadi_real_type = e.second.to_string();
97  } else if (e.first=="casadi_int") {
98  this->casadi_int_type = e.second.to_string();
99  } else if (e.first=="codegen_scalars") {
100  this->codegen_scalars = e.second;
101  } else if (e.first=="with_header") {
102  this->with_header = e.second;
103  } else if (e.first=="with_mem") {
104  this->with_mem = e.second;
105  } else if (e.first=="with_export") {
106  this->with_export = e.second;
107  } else if (e.first=="with_import") {
108  this->with_import = e.second;
109  } else if (e.first=="include_math") {
110  this->include_math = e.second;
111  } else if (e.first=="infinity") {
112  this->infinity = e.second.to_string();
113  } else if (e.first=="nan") {
114  this->nan = e.second.to_string();
115  } else if (e.first=="real_min") {
116  this->real_min = e.second.to_string();
117  } else if (e.first=="indent") {
118  indent_ = e.second;
119  casadi_assert_dev(indent_>=0);
120  } else if (e.first=="avoid_stack") {
121  avoid_stack_ = e.second;
122  } else if (e.first=="prefix") {
123  this->prefix = e.second.to_string();
124  prefix_set = true;
125  } else if (e.first=="dump_dir_prefix") {
126  this->dump_dir_prefix = e.second.to_string();
127  } else if (e.first=="dump_dir_suffix") {
128  this->dump_dir_suffix = e.second.to_string();
129  } else if (e.first=="max_declarations_per_line") {
130  this->max_declarations_per_line = e.second;
131  casadi_assert(this->max_declarations_per_line>=0,
132  "Option max_declarations_per_line must be >=0");
133  } else if (e.first=="max_initializer_elements_per_line") {
134  this->max_initializer_elements_per_line = e.second;
135  casadi_assert(this->max_initializer_elements_per_line>=0,
136  "Option max_initializer_elements_per_line must be >=0");
137  } else if (e.first=="force_canonical") {
138  this->force_canonical = e.second;
139  } else if (e.first=="l1_blas") {
140  this->l1_blas = e.second;
141  } else if (e.first=="thread_safe") {
142  thread_safe_ = e.second;
143  } else {
144  casadi_error("Unrecognized option: " + str(e.first));
145  }
146  }
147 
148  if (with_mem && !force_canonical) {
149  casadi_error("Codegen options 'with_mem' and 'force_canonical=false' (the default) "
150  "are incompatible. If you rely on with_mem, please explicitly set force_canonical=true.");
151  }
152 
153  // If real_min is not specified, make an educated guess
154  if (this->real_min.empty()) {
155  std::stringstream ss;
156  ss << std::scientific << std::setprecision(std::numeric_limits<double>::digits10 + 1);
157  if (casadi_real_type=="float") {
158  ss << std::numeric_limits<float>::min();
159  this->real_min = ss.str();
160  } else if (casadi_real_type=="double") {
161  ss << std::numeric_limits<double>::min();
162  this->real_min = ss.str();
163  } else {
164  this->real_min = "<NOT SPECIFIED>";
165  }
166  }
167 
169 
170  // Start at new line with no indentation
171  newline_ = true;
172  current_indent_ = 0;
173 
174  // Start off without the need for thread-local memory
175  needs_mem_ = false;
176 
177  // Divide name into base and suffix (if any)
178  std::string::size_type dotpos = name.rfind('.');
179  if (dotpos==std::string::npos) {
180  this->name = name;
181  this->suffix = this->cpp ? ".cpp" : ".c";
182  } else {
183  this->name = name.substr(0, dotpos);
184  this->suffix = name.substr(dotpos);
185  }
186 
187  // Symbol prefix
188  if (this->with_export) dll_export = "CASADI_SYMBOL_EXPORT ";
189  if (this->with_import) dll_import = "CASADI_SYMBOL_IMPORT ";
190 
191  // Make sure that the base name is sane
192  casadi_assert_dev(Function::check_name(this->name));
193 
194  // Includes needed
195  if (this->include_math) add_include("math.h");
196  if (this->main) add_include("stdio.h");
198 
199  // Mex and main need string.h
200  if (this->mex || this->main) {
201  add_include("string.h");
202  }
203 
204  // Mex
205  if (this->mex) {
206  add_include("mex.h", false, "MATLAB_MEX_FILE");
207  }
208 
209  // s-Function
210  if (this->with_sfunction) {
211  this->casadi_real_type = "real_T";
212  this->casadi_int_type = "int_T";
213  this->with_header = true;
214  add_include("simstruc.h");
215  }
216 
217  // Memory struct entry point
218  if (this->with_mem) {
219  this->header << "#include <casadi/mem.h>\n";
220  }
221 
222  // Use name as default prefix
223  if (!prefix_set) {
224  this->prefix = this->name;
225  }
226 
227  }
228 
230  local_variables_.clear();
231  local_default_.clear();
232  local_cleanup_.clear();
233  local_void_ = true;
234  }
235 
236  void CodeGenerator::scope_return(const std::string& value) {
237  local_void_ = false;
238  if (local_cleanup_.empty()) {
239  *this << "return " << value << ";\n";
240  return;
241  }
242  local("ret", "int");
243  *this << "ret = " << value << ";\n";
244  *this << "goto done" << local_cleanup_.size() << ";\n";
245  }
246 
248  if (local_cleanup_.empty()) {
249  *this << "return;\n";
250  return;
251  }
252  *this << "goto done" << local_cleanup_.size() << ";\n";
253  }
254 
255 
256  void CodeGenerator::scope_add_cleanup(const std::string& code) {
257  local_cleanup_.push_back(code);
258  }
259 
261  // Order local variables
262  std::map<std::string, std::set<std::pair<std::string, std::string>>> local_variables_by_type;
263  for (auto&& e : local_variables_) {
264  local_variables_by_type[e.second.first].insert(std::make_pair(e.first, e.second.second));
265  }
266 
267  // Codegen local variables
268  for (auto&& e : local_variables_by_type) {
269  casadi_int cnt = 0;
270  for (auto it=e.second.begin(); it!=e.second.end(); ++it) {
271  bool split_declaration = it==e.second.begin() ||
273  if (split_declaration) {
274  if (it!=e.second.begin()) body << ";\n";
275  body << " " << e.first << " ";
276  } else {
277  body << ", ";
278  }
279  body << it->second << it->first;
280  // Insert definition, if any
281  auto k=local_default_.find(it->first);
282  if (k!=local_default_.end()) body << "=" << k->second;
283  cnt++;
284  }
285  body << ";\n";
286  }
287 
288  // Loop over local_cleanup_ in reverse order
289  if (!local_cleanup_.empty()) {
290  *this << "done" << local_cleanup_.size() << ":\n";
291  for (casadi_int i=local_cleanup_.size()-1; i>=0; --i) {
292  *this << local_cleanup_[i];
293  }
294  if (local_void_) {
295  *this << "return;\n";
296  } else {
297  *this << "return ret;\n";
298  }
299  }
300  }
301 
302  std::string CodeGenerator::wrapper(const Function& base, const std::string& name) {
303  FunctionInternal* f = base.get();
304  std::map<FunctionInternal*, casadi_int>& funs = added_wrappers_[name];
305  auto it = funs.find(f);
306  if (it==funs.end()) {
307  casadi_int n = funs.size();
308  funs[f] = n;
309  return name + str(n);
310  } else {
311  return name + str(it->second);
312  }
313  }
314 
315  std::string CodeGenerator::add_dependency(const Function& f) {
316  // Quick return if it already exists
317  for (auto&& e : added_functions_) if (e.f==f) return e.codegen_name;
318 
319  // Give it a name
320  std::string fname = shorthand("f" + str(added_functions_.size()));
321 
322  // Add to list of functions
323  added_functions_.push_back({f, fname});
324 
325  // Generate declarations
326  f->codegen_declarations(*this);
327 
328  // Print to file
329  f->codegen(*this, fname);
330 
331  bool fun_needs_mem = f->codegen_needs_mem();
332  needs_mem_ |= fun_needs_mem;
333 
334  if (fun_needs_mem) {
335 
336  if (!f->codegen_mem_is_opaque()) {
337  // Alloc memory
338  *this << "int " << fname << "_alloc_mem(void) {\n";
339  flush(this->body);
340  scope_enter();
341  f->codegen_alloc_mem(*this);
342  scope_exit();
343  *this << "}\n\n";
344 
345  // Initialize memory
346  *this << "int " << fname << "_init_mem(int mem) {\n";
347  flush(this->body);
348  scope_enter();
349  f->codegen_init_mem(*this);
350  scope_exit();
351  *this << "}\n\n";
352 
353  // Clear memory
354  *this << "void " << fname << "_free_mem(int mem) {\n";
355  flush(this->body);
356  scope_enter();
357  f->codegen_free_mem(*this);
358  scope_exit();
359  *this << "}\n\n";
360  }
361 
362  // Checkout
363  *this << "int " << fname << "_checkout(void) {\n";
364  flush(this->body);
365  scope_enter();
366  f->codegen_checkout(*this);
367  scope_exit();
368  *this << "}\n\n";
369 
370  // Clear memory
371  *this << "void " << fname << "_release(int mem) {\n";
372  flush(this->body);
373  scope_enter();
374  f->codegen_release(*this);
375  scope_exit();
376  *this << "}\n\n";
377 
378  }
379 
380  // Codegen reference count functions, if needed
381  if (f->has_refcount_in_deps_) {
382  // Increase reference counter
383  *this << "void " << fname << "_incref(void) {\n";
384  f->codegen_incref(*this);
385  *this << "}\n\n";
386 
387  // Decrease reference counter
388  *this << "void " << fname << "_decref(void) {\n";
389  f->codegen_decref(*this);
390  *this << "}\n\n";
391  }
392 
393  // Flush to body
394  flush(this->body);
395 
396  return fname;
397  }
398 
399  void CodeGenerator::add(const Function& f, bool with_jac_sparsity) {
400  // Add if not already added
401  std::string codegen_name = add_dependency(f);
402  casadi_assert(!external_names_.count(f.name()),
403  "Cannot code generate '" + f.name() + "': name conflicts with an external dependency.");
404 
405  // Define function
406  *this << declare(f->signature(f.name())) << "{\n"
407  << "return " << codegen_name << "(arg, res, iw, w, mem);\n"
408  << "}\n\n";
409 
410  if (this->unroll_args) {
411  // Define function
412  *this << declare(f->signature_unrolled(f.name())) << "{\n";
413  for (casadi_int i=0; i<f.n_in(); ++i) {
414  *this << "arg[" << i << "] = " << f.name_in(i) << ";\n";
415  }
416  for (casadi_int i=0; i<f.n_out(); ++i) {
417  *this << "res[" << i << "] = " << f.name_out(i) << ";\n";
418  }
419  *this << "return " << codegen_name << "(arg, res, iw, w, mem);\n";
420  *this << "}\n\n";
421  // Flush buffers
422  flush(this->body);
423  }
424 
425  // Generate meta information
426  f->codegen_meta(*this);
427 
428  // Generate Jacobian sparsity information
429  if (with_jac_sparsity) {
430  // Generate/get Jacobian sparsity
431  std::vector<Sparsity> jac = f.jac_sparsity();
432  // Code generate the sparsity pattern
433  add_io_sparsities("jac_" + f.name(), f->sparsity_in_, jac);
434 
435  // Flush buffers
436  flush(this->body);
437  }
438 
439  // Generate function specific code for Simulink sfunction
440  if (this->with_sfunction) this->added_sfunctions.push_back( this->codegen_sfunction(f) );
441 
442  // Add to list of exposed symbols
443  this->exposed_fname.push_back(f.name());
444  }
445 
446  std::string CodeGenerator::dump() {
447  std::stringstream s;
448  dump(s);
449  return s.str();
450  }
451 
453  std::stringstream ss;
454  ss << CASADI_MAJOR_VERSION << "." << CASADI_MINOR_VERSION << "." << CASADI_PATCH_VERSION;
455  if (!CASADI_IS_RELEASE) ss << "+";
456  return ss.str();
457  }
458 
459  void CodeGenerator::stream_open(std::ostream& f, bool cpp) {
460 
461  // Print header
462  f << "/* This file was automatically generated by CasADi " << casadi_version() << ".\n"
463  << " * It consists of: \n"
464  << " * 1) content generated by CasADi runtime: not copyrighted\n"
465  << " * 2) template code copied from CasADi source: permissively licensed (MIT-0)\n"
466  << " * 3) user code: owned by the user\n"
467  << " *\n"
468  << " */\n";
469 
470  // C linkage
471  if (!cpp) {
472  f << "#ifdef __cplusplus\n"
473  << "extern \"C\" {\n"
474  << "#endif\n\n";
475  }
476  }
477 
478  void CodeGenerator::stream_close(std::ostream& f, bool cpp) {
479  // C linkage
480  if (!cpp) {
481  f << "#ifdef __cplusplus\n"
482  << "} /* extern \"C\" */\n"
483  << "#endif\n";
484  }
485  }
486 
487  void CodeGenerator::generate_casadi_real(std::ostream &s) const {
488  s << "#ifndef casadi_real\n"
489  << "#define casadi_real " << this->casadi_real_type << std::endl
490  << "#endif\n\n";
491  }
492 
493  void CodeGenerator::generate_export_symbol(std::ostream &s) const {
494  s << "/* Symbol visibility in DLLs */\n"
495  << "#ifndef CASADI_SYMBOL_EXPORT\n"
496  << " #if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)\n"
497  << " #if defined(STATIC_LINKED)\n"
498  << " #define CASADI_SYMBOL_EXPORT\n"
499  << " #else\n"
500  << " #define CASADI_SYMBOL_EXPORT __declspec(dllexport)\n"
501  << " #endif\n"
502  << " #elif defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY)\n"
503  << " #define CASADI_SYMBOL_EXPORT __attribute__ ((visibility (\"default\")))\n"
504  << " #else" << std::endl
505  << " #define CASADI_SYMBOL_EXPORT\n"
506  << " #endif\n"
507  << "#endif\n\n";
508  }
509 
510  void CodeGenerator::generate_import_symbol(std::ostream &s) const {
511  s << "/* Symbol visibility in DLLs */\n"
512  << "#ifndef CASADI_SYMBOL_IMPORT\n"
513  << " #if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)\n"
514  << " #if defined(STATIC_LINKED)\n"
515  << " #define CASADI_SYMBOL_IMPORT\n"
516  << " #else\n"
517  << " #define CASADI_SYMBOL_IMPORT __declspec(dllimport)\n"
518  << " #endif\n"
519  << " #elif defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY)\n"
520  << " #define CASADI_SYMBOL_IMPORT __attribute__ ((visibility (\"default\")))\n"
521  << " #else" << std::endl
522  << " #define CASADI_SYMBOL_IMPORT\n"
523  << " #endif\n"
524  << "#endif\n\n";
525  }
526 
527  void CodeGenerator::generate_casadi_int(std::ostream &s) const {
528  s << "#ifndef casadi_int\n"
529  << "#define casadi_int " << this->casadi_int_type << std::endl
530  << "#endif\n\n";
531  }
532 
533  std::string CodeGenerator::generate(const std::string& prefix) {
534  // Throw an error if the prefix contains the filename, since since syntax
535  // has changed
536  casadi_assert(prefix.find(this->name + this->suffix)==std::string::npos,
537  "The signature of CodeGenerator::generate has changed. "
538  "Instead of providing the filename, only provide the prefix.");
539 
540  // Create c file
541  std::string fullname = prefix + this->name + this->suffix;
542 
543  auto s_ptr = Filesystem::ofstream_ptr(fullname);
544  std::ostream& s = *s_ptr;
545  stream_open(s, this->cpp);
546 
547  // Dump code to file
548  dump(s);
549 
550  if (!pool_double_defaults_.empty()) {
551  s << "CASADI_SYMBOL_EXPORT casadi_real* CASADI_PREFIX(get_pool_double)(const char* name) {\n";
552  for (const auto& e : pool_double_) {
553  casadi_int i = e.second;
554  s << " if (strcmp(name, \"" + e.first + "\")==0) "
555  << "return casadi_pd" + str(i) + ";\n";
556  }
557  s << " return 0;\n";
558  s << "}\n";
559  }
560 
561  // Mex entry point
562  if (this->mex) generate_mex(s);
563 
564  // Main entry point
565  if (this->main) generate_main(s);
566 
567  // Finalize file
568  stream_close(s, this->cpp);
569  s_ptr.reset();
570 
571  // Generate s-function
572  if (this->with_sfunction) {
573  for (unsigned ii=0; ii<this->added_sfunctions.size(); ii++) {
574  std::string sfunction_code = this->added_sfunctions.at(ii);
575  std::string sfunction_name = this->exposed_fname.at(ii);
576  generate_sfunction(sfunction_name, sfunction_code);
577  }
578  }
579 
580  // Generate header
581  if (this->with_header) {
582  auto s_ptr = Filesystem::ofstream_ptr(prefix + this->name + ".h");
583  std::ostream& s = *s_ptr;
584  // Create a header file
585  stream_open(s, this->cpp);
586 
587  // Define the casadi_real type (typically double)
588  generate_casadi_real(s);
589 
590  // Define the casadi_int type
591  generate_casadi_int(s);
592 
593  // Generate export symbol macros
594  if (this->with_import) generate_import_symbol(s);
595 
596  // Add declarations
597  s << this->header.str();
598 
599  // Finalize file
600  stream_close(s, this->cpp);
601  s_ptr.reset();
602  }
603  return fullname;
604  }
605 
606  void CodeGenerator::generate_mex(std::ostream &s) const {
607  // Begin conditional compilation
608  s << "#ifdef MATLAB_MEX_FILE\n";
609 
610  // Function prototype
611  if (this->cpp) s << "extern \"C\"\n"; // C linkage
612  s << "void mexFunction(int resc, mxArray *resv[], int argc, const mxArray *argv[]) {"
613  << std::endl;
614 
615  // Create a buffer
616  size_t buf_len = 0;
617  for (casadi_int i=0; i<exposed_fname.size(); ++i) {
618  buf_len = std::max(buf_len, exposed_fname[i].size());
619  }
620  s << " char buf[" << (buf_len+1) << "];\n";
621 
622  // Read std::string argument
623  s << " int buf_ok = argc > 0 && !mxGetString(*argv, buf, sizeof(buf));\n";
624 
625  // Create switch
626  s << " if (!buf_ok) {\n";
627  // Allow stringless call when unambiguous
628  if (exposed_fname.size()==1) {
629  s << " mex_" << exposed_fname[0] << "(resc, resv, argc, argv);\n"
630  << " return;\n";
631  } else {
632  s << " /* name error */\n";
633  }
634  for (casadi_int i=0; i<exposed_fname.size(); ++i) {
635  s << " } else if (strcmp(buf, \"" << exposed_fname[i] << "\")==0) {\n"
636  << " mex_" << exposed_fname[i] << "(resc, resv, argc-1, argv+1);\n"
637  << " return;\n";
638  }
639  s << " }\n";
640 
641  // Error
642  s << " mexErrMsgTxt(\"First input should be a command string. Possible values:";
643  for (casadi_int i=0; i<exposed_fname.size(); ++i) {
644  s << " '" << exposed_fname[i] << "'";
645  }
646  s << "\");\n";
647 
648  // End conditional compilation and function
649  s << "}\n"
650  << "#endif\n";
651  }
652 
653  void CodeGenerator::generate_sfunction(const std::string& name,
654  const std::string& sfunction) const {
655  // Create c file
656  auto f_ptr = Filesystem::ofstream_ptr("sfun_"+ name + ".c");
657  std::ostream& f = *f_ptr;
658 
659  // Print header
660  f << "// Must specify the S_FUNCTION_NAME as the name of the S-function\n"
661  << "#define S_FUNCTION_NAME sfun_" << name << "\n"
662  << "#define S_FUNCTION_LEVEL 2\n\n"
663  << "// Need to include simstruc.h for the definition of the SimStruct and its\n"
664  << "// associated macro definitions\n"
665  << "#ifndef __SIMSTRUC__\n"
666  << "#include \"simstruc.h\"\n"
667  << "#endif\n\n"
668  << "// Specific header file(s) required by the legacy code function\n"
669  << "#include \"" << this->name << ".h\"\n\n\n";
670 
671  // Codegenerate s-function
672  f << sfunction;
673 
674  }
675 
676  std::string CodeGenerator::codegen_sfunction(const Function& f) const {
677  std::stringstream g;
678  // TODO(@jaeandersson): These helper functions really should be moved
679  // to the runtime directory
680 
681  // Initialize function
682  g << "/* Function: mdlInitializeSizes ===========================================\n"
683  << "* Abstract:\n"
684  << "* The sizes information is used by Simulink to determine the S-function\n"
685  << "* blocks characteristics (number of inputs, outputs, states, etc.).\n"
686  << "*/\n"
687  << "static void mdlInitializeSizes(SimStruct *S)\n"
688  << "{\n\n"
689  << " /* Declare auxilary variables */\n"
690  << " int_T ii;\n"
691  << " const int_T* sp;\n\n"
692  << " /* Set number of simulink s-function block parameters "
693  "(the ones which appear by double click on simulink block) */\n"
694  << " ssSetNumSFcnParams(S, 0);\n\n"
695  << " /* Report if parameter mismatch occurs */\n"
696  << " if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) return;\n\n"
697  << " /* Specify the number of states for which a block detects "
698  "zero crossings that occur between sample points */\n"
699  << " ssSetNumNonsampledZCs(S, 0);\n\n"
700  << " /* Set number of simulink input ports */\n"
701  << " if (!ssSetNumInputPorts(S, " << f->n_in_ << ")) return;\n\n"
702  << " /* Configure simulink input ports (inputs are assumed to be dense "
703  "vectors or matrices) */\n"
704  << " for (ii=0; ii<" << f->n_in_ << "; ++ii) {\n"
705  << " sp = " << f.name() << "_sparsity_in(ii);\n"
706  << " if (sp[1]==1) {\n"
707  << " ssSetInputPortWidth(S, ii, sp[0]);\n"
708  << " }\n"
709  << " else {\n"
710  << " ssSetInputPortMatrixDimensions(S, ii, sp[0], sp[1]);\n"
711  << " }\n"
712  << " ssSetInputPortDirectFeedThrough(S, ii, 1);\n"
713  << " }\n\n"
714  << " /* Set number of simulink output ports */\n"
715  << " if (!ssSetNumOutputPorts(S, " << f->n_out_ << ")) return;\n\n"
716  << " /* Configure simulink output ports (dense or sparse vectors or matrices allowed) */\n"
717  << " for (ii=0; ii<" << f->n_out_ << "; ++ii) {\n"
718  << " sp = " << f.name() << "_sparsity_out(ii);\n"
719  << " if (sp[1]==1) {\n"
720  << " ssSetOutputPortWidth(S, ii, sp[0]);\n"
721  << " }\n"
722  << " else {\n"
723  << " ssSetOutputPortMatrixDimensions(S, ii, sp[0], sp[1]);\n"
724  << " }\n"
725  << " }\n"
726  << " ssSetOutputPortOutputExprInRTW(S, 0, 0);\n\n"
727  << " /* This S-function can be used in referenced model simulating in normal mode */\n"
728  << " ssSetModelReferenceNormalModeSupport(S, MDL_START_AND_MDL_PROCESS_PARAMS_OK);\n\n"
729  << " /* Set the number of sample time */\n"
730  << " ssSetNumSampleTimes(S, 1);\n\n"
731  << " /* Set the compliance with the SimState feature */\n"
732  << " ssSetSimStateCompliance(S, USE_DEFAULT_SIM_STATE);\n\n"
733  << " /**\n"
734  << " * All options have the form SS_OPTION_<name> and are documented in\n"
735  << " * matlabroot/simulink/include/simstruc.h. The options should be\n"
736  << " * bitwise ord together as in\n"
737  << " * ssSetOptions(S, (SS_OPTION_name1 | SS_OPTION_name2))\n"
738  << " */\n"
739  << "}\n\n\n";
740 
741  // Initialize sample times function
742  g << "/* Function: mdlInitializeSampleTimes =====================================\n"
743  << " * Abstract:\n"
744  << " * This function is used to specify the sample time(s) for your\n"
745  << " * S-function. You must register the same number of sample times as\n"
746  << " * specified in ssSetNumSampleTimes.\n"
747  << " */\n"
748  << "static void mdlInitializeSampleTimes(SimStruct *S)\n"
749  << "{\n"
750  << " ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);\n"
751  << " ssSetOffsetTime(S, 0, FIXED_IN_MINOR_STEP_OFFSET);\n"
752  << " #if defined(ssSetModelReferenceSampleTimeDefaultInheritance)\n"
753  << " ssSetModelReferenceSampleTimeDefaultInheritance(S);\n"
754  << " #endif\n"
755  << "}\n\n\n";
756 
757  // Model output function
758  g << "/* Function: mdlOutputs ===================================================\n"
759  << " * Abstract:\n"
760  << " * In this function, you compute the outputs of your S-function\n"
761  << " * block. Generally outputs are placed in the output vector(s),\n"
762  << " * ssGetOutputPortSignal.\n"
763  << " */\n"
764  << "static void mdlOutputs(SimStruct *S, int_T tid)\n"
765  << "{\n\n"
766  << " /* Declare auxilary variables */\n"
767  << " int_T ii, jj, row, col, nnz_col, ind_start_row_index, offset = 0, jj_total = 0;\n"
768  << " const int_T* sp;\n\n"
769  << " /* Allocate buffers for casadi input and output and simulink output */\n"
770  << " " + array("real_T", "w", f->sz_w()+f->nnz_out())
771  << " " + array("int_T", "iw", f->sz_iw())
772  << " const real_T* arg[" << f->sz_arg() <<"] = {0};\n"
773  << " real_T* res[" << f->sz_res() << "] = {0};\n"
774  << " real_T* y[" << f->n_out_ << "] = {0};\n\n"
775  << " /* Point inputs directly to casadi input buffer */\n"
776  << " for (ii=0; ii<" << f->n_in_ << ";++ii) {\n"
777  << " arg[ii] = *ssGetInputPortRealSignalPtrs( S, ii );\n"
778  << " }\n\n"
779  << " /* Point outputs to buffer */\n"
780  << " for (ii=0; ii<" << f->n_out_ << ";++ii) {\n"
781  << " y[ii] = ssGetOutputPortRealSignal( S, ii );\n"
782  << " }\n\n"
783  << " /* Point allocated working array to casadi output buffer */\n";
784  for (casadi_int ii=0; ii<f->n_out_; ++ii) {
785  g << " res[" << ii << "] = w + offset;\n"
786  << " offset += " << f.nnz_out(ii) << ";\n";
787  }
788  g << " \n"
789  << " /* Call CasADi function */\n"
790  << " " << f.name() << "( arg, res, iw, w+offset, 0 );\n\n"
791  << " /* Assign results to Simulink output array */\n"
792  << " for (ii=0; ii<" << f->n_out_ << "; ++ii){\n\n"
793  << " /* Get sparsity information of casadi function output "
794  "(sp[0] - n_rows, sp[1] - n_cols, sp[2] - dense/sparse) */\n"
795  << " sp = " << f.name() << "_sparsity_out(ii);\n\n"
796  << " /* Check if output is dense (sp[2]=1) or sparse (sp[2]=0) */\n"
797  << " if (sp[2]==0) {\n"
798  << " for (jj=0; jj<sp[0]*sp[1]; ++jj) y[ii][jj] = 0;\n"
799  << " jj_total = 0;\n"
800  << " ind_start_row_index = 2 + sp[1] + 1;\n\n"
801  << " /* Distribute nonzero elements column by column */\n"
802  << " for (col=0; col<sp[1]; col++) {\n\n"
803  << " /* The cumulative sum of nonzero elements after each column starts at index 2, "
804  "after last entry of CCS array col_ptr; number of nonzero elements in current column is "
805  "obtained by the difference of two consecutive values */\n"
806  << " nnz_col = sp[2+col+1] - sp[2+col];\n\n"
807  << " /* Distribute nonzero elements of current column to correct row position */\n"
808  << " for (jj=0; jj<nnz_col; jj++) {\n"
809  << " row = sp[ind_start_row_index+jj_total];\n"
810  << " y[ii][row + sp[0]*col] = res[ii][jj_total];\n"
811  << " jj_total++;\n"
812  << " }\n"
813  << " }\n"
814  << " }\n"
815  << " else {\n"
816  << " for (jj=0; jj<sp[0]*sp[1]; ++jj) y[ii][jj] = res[ii][jj];\n"
817  << " }\n"
818  << " }\n"
819  << "}\n\n\n";
820 
821  // Model terminate function
822  g << "/* Function: mdlTerminate =================================================\n"
823  << " * Abstract:\n"
824  << " * In this function, you should perform any actions that are necessary\n"
825  << " * at the termination of a simulation.\n"
826  << " */\n"
827  << "static void mdlTerminate(SimStruct *S)\n"
828  << "{\n"
829  << "}\n\n\n"
830  << "/* Required S-function trailer */\n"
831  << "#ifdef MATLAB_MEX_FILE\n"
832  << "# include \"simulink.c\"\n"
833  << "#else\n"
834  << "# include \"cg_sfun.h\"\n"
835  << "#endif";
836 
837  return g.str();
838  }
839 
840  void CodeGenerator::generate_main(std::ostream &s) const {
841  s << this->dll_export << "int main(int argc, char* argv[]) {\n";
842 
843  // Create switch
844  s << " if (argc<2) {\n"
845  << " /* name error */\n";
846  for (casadi_int i=0; i<exposed_fname.size(); ++i) {
847  s << " } else if (strcmp(argv[1], \"" << exposed_fname[i] << "\")==0) {\n"
848  << " return main_" << exposed_fname[i] << "(argc-2, argv+2);\n";
849  }
850  s << " }\n";
851 
852  // Error
853  s << " fprintf(stderr, \"First input should be a command string. Possible values:";
854  for (casadi_int i=0; i<exposed_fname.size(); ++i) {
855  s << " '" << exposed_fname[i] << "'";
856  }
857  s << "\\n";
858  s << "Note: you may use function.generate_input to create a command string.";
859  s << "\\n\");\n";
860 
861  // End main
862  s << " return 1;\n"
863  << "}\n";
864  }
865 
866  void CodeGenerator::define_rom_double(const void* id, casadi_int size) {
867  auto it = file_scope_double_.find(id);
868  casadi_assert(it==file_scope_double_.end(), "Already defined.");
869  shorthand("rd" + str(file_scope_double_.size()));
870  file_scope_double_[id] = size;
871  }
872 
873  std::string CodeGenerator::rom_double(const void* id) const {
874  auto it = file_scope_double_.find(id);
875  casadi_assert(it!=file_scope_double_.end(), "Not defined.");
876  casadi_int size = std::distance(file_scope_double_.begin(), it);
877  return "casadi_rd" + str(size);
878  }
879 
880  void CodeGenerator::define_rom_integer(const void* id, casadi_int size) {
881  auto it = file_scope_double_.find(id);
882  casadi_assert(it==file_scope_double_.end(), "Already defined.");
883  shorthand("ri" + str(file_scope_double_.size()));
884  file_scope_double_[id] = size;
885  }
886 
887  std::string CodeGenerator::rom_integer(const void* id) const {
888  auto it = file_scope_double_.find(id);
889  casadi_assert(it!=file_scope_double_.end(), "Not defined.");
890  casadi_int size = std::distance(file_scope_double_.begin(), it);
891  return "casadi_ri" + str(size);
892  }
893 
894  void CodeGenerator::define_pool_double(const std::string& name, const std::vector<double>& def) {
895  auto it = pool_double_.find(name);
896  if (it==pool_double_.end()) {
897  casadi_int index = pool_double_defaults_.size();
898  pool_double_defaults_.push_back(def);
899  shorthand("pd" + str(index));
900  pool_double_[name] = index;
901  } else {
902  casadi_assert_dev(def==pool_double_defaults_[it->second]);
903  }
904  }
905 
906  std::string CodeGenerator::pool_double(const std::string& name) const {
907  auto it = pool_double_.find(name);
908  casadi_assert(it!=pool_double_.end(), "Not defined.");
909  return "casadi_pd" + str(it->second);
910  }
911 
913  const std::string& name) {
914  if (!thread_safe()) return;
915  if (!local_mutexes_[f.get()].insert(name).second) return; // already defined
916  std::string sh = shorthand(name);
917  auxiliaries << "#if CASADI_MUTEX_USE_STATIC_INIT == 0\n";
918  auxiliaries << "static CASADI_MUTEX_TYPE " << sh << ";\n";
919  auxiliaries << "#else\n";
920  auxiliaries << "static CASADI_MUTEX_TYPE " << sh
921  << " = CASADI_MUTEX_STATIC_INIT;\n";
922  auxiliaries << "#endif\n";
923  }
924 
925  std::string CodeGenerator::local_mutex(const Function& f,
926  const std::string& name) const {
927  auto it = local_mutexes_.find(f.get());
928  casadi_assert(it != local_mutexes_.end() && it->second.count(name),
929  "Mutex not defined: " + name);
930  return shorthand(name);
931  }
932 
933  static const std::set<std::string> empty_mutex_set_;
934 
935  const std::set<std::string>& CodeGenerator::local_mutexes(
936  const Function& f) const {
937  auto it = local_mutexes_.find(f.get());
938  if (it == local_mutexes_.end()) return empty_mutex_set_;
939  return it->second;
940  }
941 
942  void CodeGenerator::dump(std::ostream& s) {
943  // Consistency check
944  casadi_assert_dev(current_indent_ == 0);
945 
946  // Prefix internal symbols to avoid symbol collisions
947  s << "/* How to prefix internal symbols */\n"
948  << "#ifdef CASADI_CODEGEN_PREFIX\n"
949  << " #define CASADI_NAMESPACE_CONCAT(NS, ID) _CASADI_NAMESPACE_CONCAT(NS, ID)\n"
950  << " #define _CASADI_NAMESPACE_CONCAT(NS, ID) NS ## ID\n"
951  << " #define CASADI_PREFIX(ID) CASADI_NAMESPACE_CONCAT(CODEGEN_PREFIX, ID)\n"
952  << "#else\n"
953  << " #define CASADI_PREFIX(ID) " << this->prefix << "_ ## ID\n"
954  << "#endif\n\n";
955 
956  s << this->includes.str();
957  s << std::endl;
958 
959  // Numeric types after includes: may depend on them. e.g. mex type
960  // Real type (usually double)
961  generate_casadi_real(s);
962 
963  // Integer type (usually long long)
964  generate_casadi_int(s);
965 
966  if (needs_mem_) {
967  s << "#ifndef CASADI_MAX_NUM_THREADS\n";
968  s << "#define CASADI_MAX_NUM_THREADS 1\n";
969  s << "#endif\n\n";
970  }
971 
972  // casadi/mem after numeric types to define derived types
973  // Memory struct entry point
974  if (this->with_mem) {
975  s << "#include <casadi/mem.h>\n" << std::endl;
976  }
977 
978  // Macros
979  if (!added_shorthands_.empty()) {
980  s << "/* Add prefix to internal symbols */\n";
981  for (auto&& i : added_shorthands_) {
982  s << "#define " << "casadi_" << i << " CASADI_PREFIX(" << i << ")\n";
983  }
984  s << std::endl;
985  }
986 
987  if (this->with_export) generate_export_symbol(s);
988 
989  // Check if inf/nan is needed
990  for (const auto& d : double_constants_) {
991  for (double e : d) {
992  if (isinf(e)) add_auxiliary(AUX_INF);
993  if (isnan(e)) add_auxiliary(AUX_NAN);
994  }
995  }
996 
997  // Codegen auxiliary functions
998  s << this->auxiliaries.str();
999 
1000  // The configuration this file is compiled with, for whoever loads it
1001  s << "/* Configuration this file was compiled with */\n"
1002  << declare("void " + this->prefix + "_casadi_version(int* major, int* minor, int* patch)")
1003  << " {\n"
1004  << " *major = " << CASADI_MAJOR_VERSION << ";\n"
1005  << " *minor = " << CASADI_MINOR_VERSION << ";\n"
1006  << " *patch = " << CASADI_PATCH_VERSION << ";\n"
1007  << "}\n"
1008  << declare("int " + this->prefix + "_casadi_int_size(void)")
1009  << " { return (int) sizeof(casadi_int); }\n"
1010  << declare("int " + this->prefix + "_casadi_real_size(void)")
1011  << " { return (int) sizeof(casadi_real); }\n";
1012  if (needs_mem_) {
1013  s << declare("int " + this->prefix + "_max_num_threads(void)")
1014  << " { return CASADI_MAX_NUM_THREADS; }\n";
1015  }
1016  if (added_auxiliaries_.count(AUX_THREADS)) {
1017  s << declare("int " + this->prefix + "_thread_type(void)")
1018  << " { return CASADI_THREAD_TYPE; }\n";
1019  }
1020  s << "\n";
1021 
1022  // Print integer constants
1023  if (!integer_constants_.empty()) {
1024  for (casadi_int i=0; i<integer_constants_.size(); ++i) {
1025  print_vector(s, "casadi_s" + str(i), integer_constants_[i]);
1026  }
1027  s << std::endl;
1028  }
1029 
1030  // Print double constants
1031  if (!double_constants_.empty()) {
1032  for (casadi_int i=0; i<double_constants_.size(); ++i) {
1033  print_vector(s, "casadi_c" + str(i), double_constants_[i]);
1034  }
1035  s << std::endl;
1036  }
1037 
1038  // Print char constants
1039  if (!char_constants_.empty()) {
1040  for (casadi_int i=0; i<char_constants_.size(); ++i) {
1041  print_vector(s, "casadi_b" + str(i), char_constants_[i]);
1042  }
1043  s << std::endl;
1044  }
1045 
1046  // Print string constants
1047  if (!string_constants_.empty()) {
1048  for (casadi_int i=0; i<string_constants_.size(); ++i) {
1049  print_vector(s, "casadi_a" + str(i), string_constants_[i]);
1050  }
1051  s << std::endl;
1052  }
1053 
1054  if (sz_zeros_) {
1055  std::vector<double> sz_zeros(sz_zeros_, 0);
1056  print_vector(s, "casadi_zeros", std::vector<double>(sz_zeros));
1057  s << std::endl;
1058  }
1059 
1060  if (sz_ones_) {
1061  std::vector<double> sz_ones(sz_ones_, 0);
1062  print_vector(s, "casadi_ones", std::vector<double>(sz_ones));
1063  s << std::endl;
1064  }
1065 
1066  // Print file scope double work
1067  if (!file_scope_double_.empty()) {
1068  casadi_int i=0;
1069  for (const auto& it : file_scope_double_) {
1070  s << "static casadi_real casadi_rd" + str(i++) + "[" + str(it.second) + "];\n";
1071  }
1072  s << std::endl;
1073  }
1074 
1075  // Print file scope integer work
1076  if (!file_scope_integer_.empty()) {
1077  casadi_int i=0;
1078  for (const auto& it : file_scope_integer_) {
1079  s << "static casadi_real casadi_ri" + str(i++) + "[" + str(it.second) + "];\n";
1080  }
1081  s << std::endl;
1082  }
1083 
1084  // Print file scope double pool
1085  if (!pool_double_.empty()) {
1086  casadi_int i=0;
1087  for (const auto& v : pool_double_defaults_) {
1088  s << "casadi_real casadi_pd" + str(i) +
1089  "[" + str(v.size()) + "] = " + initializer(v) + ";\n";
1090  i++;
1091  }
1092  s << std::endl;
1093  }
1094 
1095  // External function declarations
1096  if (!added_externals_.empty()) {
1097  s << "/* External functions */\n";
1098  for (auto&& i : added_externals_) {
1099  s << i << std::endl;
1100  }
1101  s << std::endl << std::endl;
1102  }
1103 
1104  // Codegen body
1105  s << this->body.str();
1106 
1107  // End with new line
1108  s << std::endl;
1109  }
1110 
1111  std::string CodeGenerator::work(casadi_int n, casadi_int sz, bool is_ref) const {
1112  if (is_ref) {
1113  return "wr" + format_padded(n);
1114  }
1115  if (n<0 || sz==0) {
1116  return "0";
1117  } else if (sz==1 && !this->codegen_scalars) {
1118  return "(&w" + format_padded(n) + ")";
1119  } else {
1120  return "w" + format_padded(n);
1121  }
1122  }
1123 
1124  std::string CodeGenerator::workel(casadi_int n) const {
1125  if (n<0) return "0";
1126  std::stringstream s;
1127  if (this->codegen_scalars) s << "*";
1128  s << "w" << format_padded(n);
1129  return s.str();
1130  }
1131 
1132  void CodeGenerator::reserve_work(casadi_int n) {
1133  if (n == 0) {
1134  padding_length_ = 1;
1135  } else {
1136  // Zero based counting. The 10th entry is to be rendered as '9'
1137  padding_length_ = str(n-1).length();
1138  }
1139  }
1140 
1142  codegen_sz_w_[f] = sz_w;
1143  }
1144 
1145  bool CodeGenerator::get_codegen_sz_w(const FunctionInternal* f, size_t& sz_w) const {
1146  auto it = codegen_sz_w_.find(f);
1147  if (it==codegen_sz_w_.end()) return false;
1148  sz_w = it->second;
1149  return true;
1150  }
1151 
1152  std::string CodeGenerator::format_padded(casadi_int i) const {
1153  std::stringstream ss;
1154  ss.str("");
1155  ss << std::setw(padding_length_) << std::setfill('0') << i;
1156  return ss.str();
1157  }
1158 
1159  std::string CodeGenerator::array(const std::string& type, const std::string& name, casadi_int len,
1160  const std::string& def) {
1161  std::stringstream s;
1162  s << type << " ";
1163  if (len==0) {
1164  s << "*" << name << " = 0";
1165  } else {
1166  s << name << "[" << len << "]";
1167  if (!def.empty()) s << " = " << def;
1168  }
1169  s << ";\n";
1170  return s.str();
1171  }
1172 
1173  void CodeGenerator::print_vector(std::ostream &s, const std::string& name,
1174  const std::vector<casadi_int>& v) {
1175  s << array("static const casadi_int", name, v.size(), initializer(v));
1176  }
1177 
1178  void CodeGenerator::print_vector(std::ostream &s, const std::string& name,
1179  const std::vector<char>& v) {
1180  s << array("static const char", name, v.size(), initializer(v));
1181  }
1182 
1183  void CodeGenerator::print_vector(std::ostream &s, const std::string& name,
1184  const std::vector<double>& v) {
1185  s << array("static const casadi_real", name, v.size(), initializer(v));
1186  }
1187 
1188  void CodeGenerator::print_vector(std::ostream &s, const std::string& name,
1189  const std::vector<std::string>& v) {
1190  s << array("static const char*", name, v.size(), initializer(v));
1191  }
1192 
1193  std::string CodeGenerator::print_canonical(const Sparsity& sp, const std::string& arg) {
1195  std::stringstream s;
1196  s << "casadi_print_canonical(" << sparsity(sp) << ", " << arg << ");";
1197  return s.str();
1198  }
1199 
1200  std::string CodeGenerator::print_vector(casadi_int sz, const std::string& arg) {
1202  std::stringstream s;
1203  s << "casadi_print_vector(" << sz << ", " << arg << ");";
1204  return s.str();
1205  }
1206 
1207  std::string CodeGenerator::print_scalar(const std::string& arg) {
1209  std::stringstream s;
1210  s << "casadi_print_scalar(" << arg << ");";
1211  return s.str();
1212  }
1213 
1214  std::string CodeGenerator::fprintf_scalar(const std::string& f, const std::string& arg) {
1216  std::stringstream s;
1217  s << "casadi_fprintf_scalar(" << f << ", " << arg << ");";
1218  return s.str();
1219  }
1220 
1221  std::string CodeGenerator::fprintf_vector(const std::string& f, casadi_int sz,
1222  const std::string& arg, const std::string& sep) {
1224  std::stringstream s;
1225  s << "casadi_fprintf_vector(" << f << ", " << sz << ", " << arg << ", \"" << sep << "\");";
1226  return s.str();
1227  }
1228 
1229  std::string CodeGenerator::print_op(casadi_int op, const std::string& a0) {
1230  switch (op) {
1231  case OP_FABS:
1233  return "casadi_fabs("+a0+")";
1234  case OP_SQ:
1236  return "casadi_sq("+a0+")";
1237  case OP_SIGN:
1239  return "casadi_sign("+a0+")";
1240  case OP_LOG1P:
1242  return "casadi_log1p("+a0+")";
1243  case OP_EXPM1:
1245  return "casadi_expm1("+a0+")";
1246  default:
1247  return casadi_math<double>::print(op, a0);
1248  }
1249  }
1250  std::string CodeGenerator::print_op(casadi_int op, const std::string& a0, const std::string& a1) {
1251  switch (op) {
1252  case OP_FMIN:
1254  return "casadi_fmin("+a0+","+a1+")";
1255  case OP_FMAX:
1257  return "casadi_fmax("+a0+","+a1+")";
1258  case OP_HYPOT:
1260  return "casadi_hypot("+a0+","+a1+")";
1261  case OP_PRINTME:
1263  return "casadi_printme("+a0+","+a1+")";
1264  default:
1265  return casadi_math<double>::print(op, a0, a1);
1266  }
1267  }
1268 
1269  void CodeGenerator::add_include(const std::string& new_include, bool relative_path,
1270  const std::string& use_ifdef) {
1271  // Register the new element
1272  bool added = added_includes_.insert(new_include).second;
1273 
1274  // Quick return if it already exists
1275  if (!added) return;
1276 
1277  // Ifdef opening
1278  if (!use_ifdef.empty()) this->includes << "#ifdef " << use_ifdef << std::endl;
1279 
1280  // Print to the header section
1281  if (relative_path) {
1282  this->includes << "#include \"" << new_include << "\"\n";
1283  } else {
1284  this->includes << "#include <" << new_include << ">\n";
1285  }
1286 
1287  // Ifdef closing
1288  if (!use_ifdef.empty()) this->includes << "#endif\n";
1289  }
1290 
1291  void CodeGenerator::setup_callback(const std::string& s, const Function& f) {
1292  std::string name = add_dependency(f);
1293  bool needs_mem = f->codegen_needs_mem();
1294  if (needs_mem) {
1295  *this << s << ".checkout = " << name << "_checkout;\n";
1296  } else {
1297  *this << s << ".checkout = 0;\n";
1298  }
1299 
1300  *this << s << ".eval = " << name << ";\n";
1301  if (needs_mem) {
1302  *this << s << ".release = " << name << "_release;\n";
1303  } else {
1304  *this << s << ".release = 0;\n";
1305  }
1306  }
1307 
1308  std::string CodeGenerator::
1309  operator()(const Function& f, const std::string& arg,
1310  const std::string& res, const std::string& iw,
1311  const std::string& w, const std::string& failure_ret) {
1312  std::string name = add_dependency(f);
1313 
1314  std::string cg_name = f->codegen_name(*this, false);
1315  bool needs_mem = f->codegen_needs_mem();
1316  if (needs_mem) {
1317  std::string mem = "mid";
1318  local("flag", "int");
1319  local(mem, "int");
1320  std::string checkout = shorthand(cg_name + "_checkout");
1321  *this << mem << " = " << checkout << "();\n";
1322  if (failure_ret.empty()) {
1323  *this << "if (" << mem << "<0) {\n";
1324  *this << "flag = 1;\n";
1325  *this << "} else {\n";
1326  } else {
1327  *this << "if (" << mem << "<0) return " << failure_ret << ";\n";
1328  }
1329 
1330  *this << "flag = " + name + "(" + arg + ", " + res + ", "
1331  + iw + ", " + w + ", " << mem << ");\n";
1332 
1333  if (failure_ret.empty()) {
1334  *this << "}\n";
1335  }
1336 
1337  std::string release = shorthand(cg_name + "_release");
1338  *this << release << "(" << mem << ");\n";
1339  return "flag";
1340  } else {
1341  return name + "(" + arg + ", " + res + ", "
1342  + iw + ", " + w + ", 0)";
1343  }
1344  }
1345 
1346  void CodeGenerator::add_external(const std::string& new_external, const std::string& name) {
1347  if (!name.empty()) {
1348  casadi_assert(std::find(exposed_fname.begin(), exposed_fname.end(), name)
1349  ==exposed_fname.end(),
1350  "Cannot code generate '" + name + "': name conflicts with an external dependency.");
1351  external_names_.insert(name);
1352  }
1353  added_externals_.insert(new_external);
1354  }
1355 
1356  std::string CodeGenerator::shorthand(const std::string& name) const {
1357  casadi_assert(added_shorthands_.count(name), "No such macro: " + name);
1358  return "casadi_" + name;
1359  }
1360 
1361  std::string CodeGenerator::shorthand(const std::string& name, bool allow_adding) {
1362  bool added = added_shorthands_.insert(name).second;
1363  if (!allow_adding) {
1364  casadi_assert(added, "Duplicate macro: " + name);
1365  }
1366  return "casadi_" + name;
1367  }
1368 
1369  casadi_int CodeGenerator::add_sparsity(const Sparsity& sp, bool canonical) {
1370  return get_constant(sp.compress(canonical), true);
1371  }
1372 
1373  std::string CodeGenerator::sparsity(const Sparsity& sp, bool canonical) {
1374  return shorthand("s" + str(add_sparsity(sp, canonical)));
1375  }
1376 
1377  casadi_int CodeGenerator::get_sparsity(const Sparsity& sp) const {
1378  return const_cast<CodeGenerator&>(*this).get_constant(sp, false);
1379  }
1380 
1381  size_t CodeGenerator::hash(const std::vector<double>& v) {
1382  // Calculate a hash value for the vector
1383  std::size_t seed=0;
1384  if (!v.empty()) {
1385  casadi_assert_dev(sizeof(double) % sizeof(size_t)==0);
1386  const casadi_int int_len = v.size()*(sizeof(double)/sizeof(size_t));
1387  const size_t* int_v = reinterpret_cast<const size_t*>(&v.front());
1388  for (size_t i=0; i<int_len; ++i) {
1389  hash_combine(seed, int_v[i]);
1390  }
1391  }
1392  return seed;
1393  }
1394 
1395  size_t CodeGenerator::hash(const std::vector<casadi_int>& v) {
1396  size_t seed=0;
1397  hash_combine(seed, v);
1398  return seed;
1399  }
1400 
1401  size_t CodeGenerator::hash(const std::vector<char>& v) {
1402  size_t seed=0;
1403  hash_combine(seed, v);
1404  return seed;
1405  }
1406 
1407  size_t CodeGenerator::hash(const std::vector<std::string>& v) {
1408  size_t seed=0;
1409  hash_combine(seed, v);
1410  return seed;
1411  }
1412 
1413  casadi_int CodeGenerator::get_constant(const std::vector<double>& v, bool allow_adding) {
1414  // Hash the vector
1415  size_t h = hash(v);
1416 
1417  // Try to locate it in already added constants
1418  auto eq = added_double_constants_.equal_range(h);
1419  for (auto i=eq.first; i!=eq.second; ++i) {
1420  if (equal(v, double_constants_[i->second])) return i->second;
1421  }
1422 
1423  if (allow_adding) {
1424  // Add to constants
1425  casadi_int ind = double_constants_.size();
1426  double_constants_.push_back(v);
1427  added_double_constants_.insert(std::make_pair(h, ind));
1428  return ind;
1429  } else {
1430  casadi_error("Constant not found");
1431  return -1;
1432  }
1433  }
1434 
1435  casadi_int CodeGenerator::get_constant(const std::vector<casadi_int>& v, bool allow_adding) {
1436  // Hash the vector
1437  size_t h = hash(v);
1438 
1439  // Try to locate it in already added constants
1440  std::pair<std::multimap<size_t, size_t>::iterator, std::multimap<size_t, size_t>::iterator> eq =
1441  added_integer_constants_.equal_range(h);
1442  for (std::multimap<size_t, size_t>::iterator i=eq.first; i!=eq.second; ++i) {
1443  if (equal(v, integer_constants_[i->second])) return i->second;
1444  }
1445 
1446  if (allow_adding) {
1447  // Add to constants
1448  casadi_int ind = integer_constants_.size();
1449  integer_constants_.push_back(v);
1450  added_integer_constants_.insert(std::pair<size_t, size_t>(h, ind));
1451  return ind;
1452  } else {
1453  casadi_error("Constant not found");
1454  return -1;
1455  }
1456  }
1457 
1458  casadi_int CodeGenerator::get_constant(const std::vector<char>& v, bool allow_adding) {
1459  // Hash the vector
1460  size_t h = hash(v);
1461 
1462  // Try to locate it in already added constants
1463  std::pair<std::multimap<size_t, size_t>::iterator, std::multimap<size_t, size_t>::iterator> eq =
1464  added_char_constants_.equal_range(h);
1465  for (std::multimap<size_t, size_t>::iterator i=eq.first; i!=eq.second; ++i) {
1466  if (equal(v, char_constants_[i->second])) return i->second;
1467  }
1468 
1469  if (allow_adding) {
1470  // Add to constants
1471  casadi_int ind = char_constants_.size();
1472  char_constants_.push_back(v);
1473  added_char_constants_.insert(std::pair<size_t, size_t>(h, ind));
1474  return ind;
1475  } else {
1476  casadi_error("Constant not found");
1477  return -1;
1478  }
1479  }
1480 
1481  casadi_int CodeGenerator::get_constant(const std::vector<std::string>& v, bool allow_adding) {
1482  // Hash the vector
1483  size_t h = hash(v);
1484 
1485  // Try to locate it in already added constants
1486  std::pair<std::multimap<size_t, size_t>::iterator, std::multimap<size_t, size_t>::iterator> eq =
1487  added_string_constants_.equal_range(h);
1488  for (std::multimap<size_t, size_t>::iterator i=eq.first; i!=eq.second; ++i) {
1489  if (equal(v, string_constants_[i->second])) return i->second;
1490  }
1491 
1492  if (allow_adding) {
1493  // Add to constants
1494  casadi_int ind = string_constants_.size();
1495  string_constants_.push_back(v);
1496  added_string_constants_.insert(std::pair<size_t, size_t>(h, ind));
1497  return ind;
1498  } else {
1499  casadi_error("Constant not found");
1500  return -1;
1501  }
1502  }
1503 
1504  std::string CodeGenerator::constant(const std::vector<casadi_int>& v) {
1505  return shorthand("s" + str(get_constant(v, true)));
1506  }
1507 
1508  std::string CodeGenerator::constant(const std::vector<char>& v) {
1509  return shorthand("b" + str(get_constant(v, true)));
1510  }
1511 
1512  std::string CodeGenerator::constant(const std::vector<std::string>& v) {
1513  return shorthand("a" + str(get_constant(v, true)));
1514  }
1515 
1516  std::string CodeGenerator::zeros(casadi_int sz) {
1517  sz_zeros_ = std::max(sz_zeros_, sz);
1518  return shorthand("zeros");
1519  }
1520 
1521  std::string CodeGenerator::ones(casadi_int sz) {
1522  sz_ones_ = std::max(sz_ones_, sz);
1523  return shorthand("ones");
1524  }
1525 
1527  const std::string& name, const std::vector<casadi_int>& v, const std::string& type) {
1528  std::string ref = constant(v);
1529  if (!v.empty()) {
1530  local(name+"[" + str(v.size()) + "]", type);
1531  } else {
1532  local(name, type, "*");
1533  }
1534  if (!v.empty()) {
1535  local("i", type);
1536  (*this) << "for (i=0;i<" << v.size() << ";++i) " + name + "[i] = " + ref + "[i];\n";
1537  } else {
1538  init_local(name, "0");
1539  }
1540  }
1541 
1542  std::string CodeGenerator::constant(const std::vector<double>& v) {
1543  return shorthand("c" + str(get_constant(v, true)));
1544  }
1545 
1546  void CodeGenerator::add_auxiliary(Auxiliary f, const std::vector<std::string>& inst) {
1547  // Look for existing instantiations
1548  auto f_match = added_auxiliaries_.equal_range(f);
1549  // Look for duplicates
1550  for (auto it=f_match.first; it!=f_match.second; ++it) {
1551  if (it->second==inst) return;
1552  }
1553  added_auxiliaries_.insert(std::make_pair(f, inst));
1554 
1555  // Add the appropriate function
1556  switch (f) {
1557  case AUX_COPY:
1558  if (this->l1_blas) {
1559  Blas::codegen_copy_aux(*this, inst);
1560  } else {
1561  this->auxiliaries << sanitize_source(casadi_copy_str, inst);
1562  }
1563  break;
1564  case AUX_SCALED_COPY:
1565  this->auxiliaries << sanitize_source(casadi_scaled_copy_str, inst);
1566  break;
1567  case AUX_SWAP:
1568  this->auxiliaries << sanitize_source(casadi_swap_str, inst);
1569  break;
1570  case AUX_SCAL:
1571  if (!(this->l1_blas && Blas::codegen_scal_aux(*this, inst)))
1572  this->auxiliaries << sanitize_source(casadi_scal_str, inst);
1573  break;
1574  case AUX_AXPY:
1575  if (!(this->l1_blas && Blas::codegen_axpy_aux(*this, inst)))
1576  this->auxiliaries << sanitize_source(casadi_axpy_str, inst);
1577  break;
1578  case AUX_DOT:
1579  if (!(this->l1_blas && Blas::codegen_dot_aux(*this, inst)))
1580  this->auxiliaries << sanitize_source(casadi_dot_str, inst);
1581  break;
1582  case AUX_BILIN:
1583  this->auxiliaries << sanitize_source(casadi_bilin_str, inst);
1584  break;
1585  case AUX_KRON:
1586  this->auxiliaries << sanitize_source(casadi_kron_str, inst);
1587  break;
1588  case AUX_KRON_DENSE:
1589  this->auxiliaries << sanitize_source(casadi_kron_dense_str, inst);
1590  break;
1591  case AUX_KRON_DENSE_SPARSE:
1592  this->auxiliaries << sanitize_source(casadi_kron_dense_sparse_str, inst);
1593  break;
1594  case AUX_KRON_SPARSE_DENSE:
1595  this->auxiliaries << sanitize_source(casadi_kron_sparse_dense_str, inst);
1596  break;
1598  this->auxiliaries << sanitize_source(casadi_kron_contract_inner_str, inst);
1599  break;
1601  this->auxiliaries << sanitize_source(casadi_kron_contract_inner_dense_str, inst);
1602  break;
1604  this->auxiliaries << sanitize_source(casadi_kron_contract_inner_dense_sparse_str, inst);
1605  break;
1607  this->auxiliaries << sanitize_source(casadi_kron_contract_inner_sparse_dense_str, inst);
1608  break;
1610  this->auxiliaries << sanitize_source(casadi_kron_contract_outer_str, inst);
1611  break;
1613  this->auxiliaries << sanitize_source(casadi_kron_contract_outer_dense_str, inst);
1614  break;
1616  this->auxiliaries << sanitize_source(casadi_kron_contract_outer_dense_sparse_str, inst);
1617  break;
1619  this->auxiliaries << sanitize_source(casadi_kron_contract_outer_sparse_dense_str, inst);
1620  break;
1621  case AUX_RANK1:
1622  this->auxiliaries << sanitize_source(casadi_rank1_str, inst);
1623  break;
1624  case AUX_IAMAX:
1626  this->auxiliaries << sanitize_source(casadi_iamax_str, inst);
1627  break;
1628  case AUX_INTERPN:
1631  add_auxiliary(AUX_FLIP, {});
1633  add_auxiliary(AUX_CLEAR, {"casadi_int"});
1634  this->auxiliaries << sanitize_source(casadi_interpn_str, inst);
1635  break;
1636  case AUX_INTERPN_GRAD:
1638  this->auxiliaries << sanitize_source(casadi_interpn_grad_str, inst);
1639  break;
1640  case AUX_DE_BOOR:
1641  this->auxiliaries << sanitize_source(casadi_de_boor_str, inst);
1642  break;
1643  case AUX_TENSOR_TTV:
1644  this->auxiliaries << sanitize_source(casadi_tensor_ttv_str, inst);
1645  break;
1646  case AUX_ND_BOOR_EVAL:
1652  this->auxiliaries << sanitize_source(casadi_nd_boor_eval_str, inst);
1653  break;
1654  case AUX_FLIP:
1655  this->auxiliaries << sanitize_source(casadi_flip_str, inst);
1656  break;
1657  case AUX_LOW:
1658  this->auxiliaries << sanitize_source(casadi_low_str, inst);
1659  break;
1660  case AUX_INTERPN_WEIGHTS:
1662  this->auxiliaries << sanitize_source(casadi_interpn_weights_str, inst);
1663  break;
1665  this->auxiliaries << sanitize_source(casadi_interpn_interpolate_str, inst);
1666  break;
1667  case AUX_NORM_1:
1668  if (!(this->l1_blas && Blas::codegen_norm_1_aux(*this, inst))) {
1670  this->auxiliaries << sanitize_source(casadi_norm_1_str, inst);
1671  }
1672  break;
1673  case AUX_NORM_2:
1674  if (!(this->l1_blas && Blas::codegen_norm_2_aux(*this, inst))) {
1676  this->auxiliaries << sanitize_source(casadi_norm_2_str, inst);
1677  }
1678  break;
1679  case AUX_NORM_INF:
1682  this->auxiliaries << sanitize_source(casadi_norm_inf_str, inst);
1683  break;
1684  case AUX_VECTOR_FMAX:
1686  this->auxiliaries << sanitize_source(casadi_vector_fmax_str, inst);
1687  break;
1688  case AUX_VECTOR_FMIN:
1690  this->auxiliaries << sanitize_source(casadi_vector_fmin_str, inst);
1691  break;
1692  case AUX_MASKED_NORM_INF:
1695  this->auxiliaries << sanitize_source(casadi_masked_norm_inf_str, inst);
1696  break;
1697  case AUX_CLIP_MIN:
1698  // add_auxiliary(AUX_CLIP_MIN);
1699  this->auxiliaries << sanitize_source(casadi_clip_min_str, inst);
1700  break;
1701  case AUX_CLIP_MAX:
1702  // add_auxiliary(AUX_CLIP_MAX);
1703  this->auxiliaries << sanitize_source(casadi_clip_max_str, inst);
1704  break;
1705  case AUX_CLEAR:
1706  this->auxiliaries << sanitize_source(casadi_clear_str, inst);
1707  break;
1708  case AUX_FILL:
1709  this->auxiliaries << sanitize_source(casadi_fill_str, inst);
1710  break;
1711  case AUX_MV:
1712  this->auxiliaries << sanitize_source(casadi_mv_str, inst);
1713  break;
1714  case AUX_MV_DENSE:
1715  this->auxiliaries << sanitize_source(casadi_mv_dense_str, inst);
1716  break;
1717  case AUX_MTIMES:
1718  this->auxiliaries << sanitize_source(casadi_mtimes_str, inst);
1719  break;
1720  case AUX_MTIMES_DENSE:
1721  this->auxiliaries << sanitize_source(casadi_mtimes_dense_str, inst);
1722  break;
1724  this->auxiliaries << sanitize_source(casadi_mtimes_dense_sparse_str, inst);
1725  break;
1726  case AUX_TRILSOLVE:
1727  this->auxiliaries << sanitize_source(casadi_trilsolve_str, inst);
1728  break;
1729  case AUX_TRIUSOLVE:
1730  this->auxiliaries << sanitize_source(casadi_triusolve_str, inst);
1731  break;
1732  case AUX_PROJECT:
1733  this->auxiliaries << sanitize_source(casadi_project_str, inst);
1734  break;
1735  case AUX_TRI_PROJECT:
1736  this->auxiliaries << sanitize_source(casadi_tri_project_str, inst);
1737  break;
1738  case AUX_DENSIFY:
1741  {
1742  std::vector<std::string> inst2 = inst;
1743  if (inst.size()==1) inst2.push_back(inst[0]);
1744  this->auxiliaries << sanitize_source(casadi_densify_str, inst2);
1745  }
1746  break;
1747  case AUX_SPARSIFY:
1749  {
1750  std::vector<std::string> inst2 = inst;
1751  if (inst.size()==1) inst2.push_back(inst[0]);
1752  this->auxiliaries << sanitize_source(casadi_sparsify_str, inst2);
1753  }
1754  break;
1755  case AUX_TRANS:
1756  this->auxiliaries << sanitize_source(casadi_trans_str, inst);
1757  break;
1758  case AUX_TO_MEX:
1760  this->auxiliaries << "#ifdef MATLAB_MEX_FILE\n"
1761  << sanitize_source(casadi_to_mex_str, inst)
1762  << "#endif\n\n";
1763  break;
1764  case AUX_FROM_MEX:
1766  this->auxiliaries << "#ifdef MATLAB_MEX_FILE\n"
1767  << sanitize_source(casadi_from_mex_str, inst)
1768  << "#endif\n\n";
1769  break;
1770  case AUX_FINITE_DIFF:
1775  this->auxiliaries << sanitize_source(casadi_finite_diff_str, inst);
1776  break;
1777  case AUX_QR:
1782  this->auxiliaries << sanitize_source(casadi_qr_str, inst);
1783  break;
1784  case AUX_DET:
1785  this->auxiliaries << sanitize_source(casadi_det_str, inst);
1786  break;
1787  case AUX_LSQR:
1794  this->auxiliaries << sanitize_source(casadi_lsqr_str, inst);
1795  break;
1796  case AUX_QP:
1797  this->auxiliaries << sanitize_source(casadi_qp_str, inst);
1798  break;
1799  case AUX_SOCP:
1801  this->auxiliaries << sanitize_source(casadi_socp_str, inst);
1802  break;
1803  case AUX_QRQP:
1818  add_include("stdarg.h");
1819  add_include("stdio.h");
1820  add_include("math.h");
1821 
1822  this->auxiliaries << sanitize_source(casadi_qrqp_str, inst);
1823  break;
1824  case AUX_IVP:
1830  add_include("math.h");
1831  this->auxiliaries << sanitize_source(casadi_ivp_str, inst);
1832  break;
1833  case AUX_IVP_ADAPT:
1838  this->auxiliaries << sanitize_source(casadi_ivp_adapt_str, inst);
1839  break;
1840  case AUX_IVP_EVENT:
1843  this->auxiliaries << sanitize_source(casadi_ivp_event_str, inst);
1844  break;
1845  case AUX_ROSENBROCK:
1851  add_include("math.h");
1852  this->auxiliaries << sanitize_source(casadi_rosenbrock_str, inst);
1853  break;
1854  case AUX_ERK:
1857  this->auxiliaries << sanitize_source(casadi_erk_str, inst);
1858  break;
1859  case AUX_NLP:
1861  this->auxiliaries << sanitize_source(casadi_nlp_str, inst);
1862  break;
1863  case AUX_SQPMETHOD:
1868  this->auxiliaries << sanitize_source(casadi_sqpmethod_str, inst);
1869  break;
1870  case AUX_FEASIBLESQPMETHOD:
1873  this->auxiliaries << sanitize_source(casadi_feasiblesqpmethod_str, inst);
1874  break;
1875  case AUX_LDL:
1876  this->auxiliaries << sanitize_source(casadi_ldl_str, inst);
1877  break;
1878  case AUX_NEWTON:
1883  this->auxiliaries << sanitize_source(casadi_newton_str, inst);
1884  break;
1885  case AUX_MAX_VIOL:
1887  this->auxiliaries << sanitize_source(casadi_max_viol_str, inst);
1888  break;
1889  case AUX_SUM_VIOL:
1890  this->auxiliaries << sanitize_source(casadi_sum_viol_str, inst);
1891  break;
1892  case AUX_SUM:
1893  this->auxiliaries << sanitize_source(casadi_sum_str, inst);
1894  break;
1895  case AUX_VFMIN:
1897  this->auxiliaries << sanitize_source(casadi_vfmin_str, inst);
1898  break;
1899  case AUX_VFMAX:
1901  this->auxiliaries << sanitize_source(casadi_vfmax_str, inst);
1902  break;
1903  case AUX_REGULARIZE:
1906  this->auxiliaries << sanitize_source(casadi_regularize_str, inst);
1907  break;
1912  this->auxiliaries << sanitize_source(casadi_bound_consistency_str, inst);
1913  break;
1914  case AUX_FILE_SLURP:
1915  add_include("stdio.h");
1916  this->auxiliaries << sanitize_source(casadi_file_slurp_str, inst);
1917  break;
1918  case AUX_CACHE:
1919  this->auxiliaries << sanitize_source(casadi_cache_str, inst);
1920  break;
1921  case AUX_CVX:
1928  this->auxiliaries << sanitize_source(casadi_cvx_str, inst);
1929  break;
1930  case AUX_CONVEXIFY:
1935  this->auxiliaries << sanitize_source(casadi_convexify_str, inst);
1936  break;
1937  case AUX_LOGSUMEXP:
1940  this->auxiliaries << sanitize_source(casadi_logsumexp_str, inst);
1941  break;
1942  case AUX_SPARSITY:
1943  this->auxiliaries << sanitize_source(casadi_sparsity_str, inst);
1944  break;
1945  case AUX_BFGS:
1954  this->auxiliaries << sanitize_source(casadi_bfgs_str, inst);
1955  break;
1956  case AUX_ORACLE:
1957  this->auxiliaries << sanitize_source(casadi_oracle_str, inst);
1958  break;
1959  case AUX_ORACLE_CALLBACK:
1960  this->auxiliaries << sanitize_source(casadi_oracle_callback_str, inst);
1961  break;
1962  case AUX_OCP_BLOCK:
1963  this->auxiliaries << sanitize_source(casadi_ocp_block_str, inst);
1964  break;
1965  case AUX_TO_DOUBLE:
1966  this->auxiliaries << "#define casadi_to_double(x) "
1967  << "(" << (this->cpp ? "static_cast<double>(x)" : "(double) x") << ")\n\n";
1968  break;
1969  case AUX_TO_INT:
1970  this->auxiliaries << "#define casadi_to_int(x) "
1971  << "(" << (this->cpp ? "static_cast<casadi_int>(x)" : "(casadi_int) x")
1972  << ")\n\n";
1973  break;
1974  case AUX_CAST:
1975  this->auxiliaries << "#define CASADI_CAST(x,y) "
1976  << "(" << (this->cpp ? "static_cast<x>(y)" : "(x) y") << ")\n\n";
1977  break;
1978  case AUX_SQ:
1979  this->auxiliaries << sanitize_source(
1980  "// SYMBOL \"sq\"\n"
1981  "casadi_real casadi_sq(casadi_real x) { return x*x;}\n\n",
1982  inst);
1983  break;
1984  case AUX_SIGN:
1985  this->auxiliaries << sanitize_source(
1986  "// SYMBOL \"sign\"\n"
1987  "casadi_real casadi_sign(casadi_real x) "
1988  "{ return x<0 ? -1 : x>0 ? 1 : x;}\n\n",
1989  inst);
1990  break;
1991  case AUX_IF_ELSE:
1992  this->auxiliaries << sanitize_source(
1993  "// SYMBOL \"if_else\"\n"
1994  "casadi_real casadi_if_else"
1995  "(casadi_real c, casadi_real x, casadi_real y) "
1996  "{ return c!=0 ? x : y;}\n\n",
1997  inst);
1998  break;
1999  case AUX_PRINTF:
2000  this->auxiliaries << "#ifndef CASADI_PRINTF\n";
2001  if (this->mex) {
2002  this->auxiliaries << "#ifdef MATLAB_MEX_FILE\n"
2003  << " #define CASADI_PRINTF mexPrintf\n"
2004  << "#else\n"
2005  << " #define CASADI_PRINTF printf\n"
2006  << "#endif\n";
2007  } else {
2008  add_include("stdio.h");
2009  this->auxiliaries << "#define CASADI_PRINTF printf\n";
2010  this->auxiliaries << "#ifndef CASADI_SNPRINTF\n";
2011  this->auxiliaries << "#define CASADI_SNPRINTF snprintf\n";
2012  this->auxiliaries << "#endif\n\n";
2013  }
2014  this->auxiliaries << "#endif\n\n";
2015  break;
2016  case AUX_FMIN:
2017  this->auxiliaries << sanitize_source(
2018  "// SYMBOL \"fmin\"\n"
2019  "casadi_real casadi_fmin(casadi_real x, casadi_real y) {\n"
2020  "/* Pre-c99 compatibility */\n"
2021  "#if __STDC_VERSION__ < 199901L\n"
2022  " return x<y ? x : y;\n"
2023  "#else\n"
2024  " return fmin(x, y);\n"
2025  "#endif\n"
2026  "}\n\n",
2027  inst);
2028  break;
2029  case AUX_FMAX:
2030  this->auxiliaries << sanitize_source(
2031  "// SYMBOL \"fmax\"\n"
2032  "casadi_real casadi_fmax(casadi_real x, casadi_real y) {\n"
2033  "/* Pre-c99 compatibility */\n"
2034  "#if __STDC_VERSION__ < 199901L\n"
2035  " return x>y ? x : y;\n"
2036  "#else\n"
2037  " return fmax(x, y);\n"
2038  "#endif\n"
2039  "}\n\n",
2040  inst);
2041  break;
2042  case AUX_FABS:
2043  this->auxiliaries << sanitize_source(
2044  "// SYMBOL \"fabs\"\n"
2045  "casadi_real casadi_fabs(casadi_real x) {\n"
2046  "/* Pre-c99 compatibility */\n"
2047  "#if __STDC_VERSION__ < 199901L\n"
2048  " return x>0 ? x : -x;\n"
2049  "#else\n"
2050  " return fabs(x);\n"
2051  "#endif\n"
2052  "}\n\n",
2053  inst);
2054  break;
2055  case AUX_ISINF:
2056  this->auxiliaries << sanitize_source(
2057  "// SYMBOL \"isinf\"\n"
2058  "casadi_real casadi_isinf(casadi_real x) {\n"
2059  "/* Pre-c99 compatibility */\n"
2060  "#if __STDC_VERSION__ < 199901L\n"
2061  " return x== INFINITY || x==-INFINITY;\n"
2062  "#else\n"
2063  " return isinf(x);\n"
2064  "#endif\n"
2065  "}\n\n",
2066  inst);
2067  break;
2068  case AUX_ISFINITE:
2069  this->auxiliaries << sanitize_source(
2070  "// SYMBOL \"isfinite\"\n"
2071  "casadi_real casadi_isfinite(casadi_real x) {\n"
2072  "/* Pre-c99 compatibility */\n"
2073  "#if __STDC_VERSION__ < 199901L\n"
2074  " return x==x && x!=INFINITY && x!=-INFINITY;\n"
2075  "#else\n"
2076  " return isfinite(x);\n"
2077  "#endif\n"
2078  "}\n\n",
2079  inst);
2080  break;
2081  case AUX_MIN:
2082  this->auxiliaries << sanitize_source(
2083  "// SYMBOL \"min\"\n"
2084  "casadi_int casadi_min(casadi_int x, casadi_int y) {\n"
2085  " return x>y ? y : x;\n"
2086  "}\n\n",
2087  inst);
2088  break;
2089  case AUX_MAX:
2090  this->auxiliaries << sanitize_source(
2091  "// SYMBOL \"max\"\n"
2092  "casadi_int casadi_max(casadi_int x, casadi_int y) {\n"
2093  " return x>y ? x : y;\n"
2094  "}\n\n",
2095  inst);
2096  break;
2097  case AUX_MMIN:
2100  this->auxiliaries << sanitize_source(casadi_mmin_str, inst);
2101  break;
2102  case AUX_MMAX:
2105  this->auxiliaries << sanitize_source(casadi_mmax_str, inst);
2106  break;
2107  case AUX_INF:
2108  this->auxiliaries << "#ifndef casadi_inf\n"
2109  << " #define casadi_inf " << this->infinity << "\n"
2110  << "#endif\n\n";
2111  break;
2112  case AUX_NAN:
2113  this->auxiliaries << "#ifndef casadi_nan\n"
2114  << " #define casadi_nan " << this->nan << "\n"
2115  << "#endif\n\n";
2116  break;
2117  case AUX_REAL_MIN:
2118  this->auxiliaries << "#ifndef casadi_real_min\n"
2119  << " #define casadi_real_min " << this->real_min << "\n"
2120  << "#endif\n\n";
2121  break;
2122  case AUX_LOG1P:
2123  this->auxiliaries << sanitize_source(
2124  "// SYMBOL \"log1p\"\n"
2125  "casadi_real casadi_log1p(casadi_real x) {\n"
2126  "/* Pre-c99 compatibility */\n"
2127  "#if __STDC_VERSION__ < 199901L\n"
2128  " return log(1+x);\n"
2129  "#else\n"
2130  " return log1p(x);\n"
2131  "#endif\n"
2132  "}\n\n",
2133  inst);
2134  break;
2135  case AUX_EXPM1:
2136  this->auxiliaries << sanitize_source(
2137  "// SYMBOL \"expm1\"\n"
2138  "casadi_real casadi_expm1(casadi_real x) {\n"
2139  "/* Pre-c99 compatibility */\n"
2140  "#if __STDC_VERSION__ < 199901L\n"
2141  " return exp(x)-1;\n"
2142  "#else\n"
2143  " return expm1(x);\n"
2144  "#endif\n"
2145  "}\n\n",
2146  inst);
2147  break;
2148  case AUX_HYPOT:
2149  this->auxiliaries << sanitize_source(
2150  "// SYMBOL \"hypot\"\n"
2151  "casadi_real casadi_hypot(casadi_real x, casadi_real y) {\n"
2152  "/* Pre-c99 compatibility */\n"
2153  "#if __STDC_VERSION__ < 199901L\n"
2154  " return sqrt(x*x+y*y);\n"
2155  "#else\n"
2156  " return hypot(x, y);\n"
2157  "#endif\n"
2158  "}\n\n",
2159  inst);
2160  break;
2161  case AUX_BLAZING_COMMON:
2163  add_include("simde/x86/avx2.h");
2164  add_include("simde/x86/fma.h");
2165  this->auxiliaries << sanitize_source(casadi_blazing_common_str, inst);
2166  break;
2169  this->auxiliaries << sanitize_source(casadi_blazing_1d_boor_eval_str, inst);
2170  break;
2173  this->auxiliaries << sanitize_source(casadi_blazing_2d_boor_eval_str, inst);
2174  break;
2177  this->auxiliaries << sanitize_source(casadi_blazing_3d_boor_eval_str, inst);
2178  break;
2181  this->auxiliaries << sanitize_source(casadi_blazing_4d_boor_eval_str, inst);
2182  break;
2185  this->auxiliaries << sanitize_source(casadi_blazing_5d_boor_eval_str, inst);
2186  break;
2187  case AUX_PRINTME:
2189  this->auxiliaries << sanitize_source(casadi_printme_str, inst);
2190  break;
2191  case AUX_PRINT_SCALAR:
2193  this->auxiliaries << sanitize_source(casadi_print_scalar_str, inst);
2194  break;
2195  case AUX_PRINT_VECTOR:
2197  this->auxiliaries << sanitize_source(casadi_print_vector_str, inst);
2198  break;
2199  case AUX_PRINT_CANONICAL:
2201  this->auxiliaries << sanitize_source(casadi_print_canonical_str, inst);
2202  break;
2203  case AUX_FPRINTF_SCALAR:
2204  add_include("stdio.h");
2206  this->auxiliaries << sanitize_source(casadi_fprintf_scalar_str, inst);
2207  break;
2208  case AUX_FPRINTF_VECTOR:
2210  this->auxiliaries << sanitize_source(casadi_fprintf_vector_str, inst);
2211  break;
2212  case AUX_TO_FILE:
2213  add_include("stdio.h");
2215  this->auxiliaries << sanitize_source(casadi_to_file_str, inst);
2216  break;
2217  case AUX_THREADS:
2218  this->auxiliaries << sanitize_source(casadi_threads_str, inst);
2219  break;
2220  }
2221  }
2222 
2223  std::string CodeGenerator::to_mex(const Sparsity& sp, const std::string& arg) {
2225  std::stringstream s;
2226  s << "casadi_to_mex(" << sparsity(sp) << ", " << arg << ");";
2227  return s.str();
2228  }
2229 
2230  std::string CodeGenerator::from_mex(std::string& arg,
2231  const std::string& res, std::size_t res_off,
2232  const Sparsity& sp_res, const std::string& w) {
2233  // Handle offset with recursion
2234  if (res_off!=0) return from_mex(arg, res+"+"+str(res_off), 0, sp_res, w);
2235 
2237  std::stringstream s;
2238  s << "casadi_from_mex(" << arg
2239  << ", " << res << ", " << sparsity(sp_res) << ", " << w << ");";
2240  return s.str();
2241  }
2242 
2243  std::string CodeGenerator::fmu_helpers(const std::string& modelname) {
2244  // Process C++ source
2245  std::stringstream ret;
2246  std::string line;
2247  std::istringstream stream(casadi_fmu_str);
2248  while (std::getline(stream, line)) {
2249  // Replacements
2250  if (line.find("MODELNAME") != std::string::npos) {
2251  line = replace(line, "MODELNAME", modelname);
2252  }
2253  // Append to return
2254  ret << line << "\n";
2255  }
2256  return ret.str();
2257  }
2258 
2259  std::string CodeGenerator::constant(const std::string& v) {
2260  std::string ret = v;
2261  ret = replace(ret, "\\", "\\\\");
2262  ret = replace(ret, "\"", "\\\"");
2263  return "\"" + ret + "\"";
2264  }
2265 
2266  std::string CodeGenerator::constant(casadi_int v) {
2267  return str(v);
2268  }
2269 
2270  std::string CodeGenerator::constant(char v) {
2271  return constant(static_cast<casadi_int>(v));
2272  }
2273  std::string CodeGenerator::constant(double v) {
2274  std::stringstream s;
2275  if (isnan(v)) {
2277  s << "casadi_nan";
2278  } else if (isinf(v)) {
2280  if (v<0) s << "-";
2281  s << "casadi_inf";
2282  } else {
2283  casadi_int v_int = static_cast<casadi_int>(v);
2284  if (static_cast<double>(v_int)==v) {
2285  // Print integer
2286  s << v_int << ".";
2287  } else {
2288  // Print real
2289  std::ios_base::fmtflags fmtfl = s.flags(); // get current format flags
2290  s << std::scientific << std::setprecision(std::numeric_limits<double>::digits10 + 1) << v;
2291  s.flags(fmtfl); // reset current format flags
2292  }
2293  }
2294  return s.str();
2295  }
2296 
2297  std::string CodeGenerator::copy(const std::string& arg,
2298  std::size_t n, const std::string& res) {
2299  std::stringstream s;
2300  // Perform operation
2302  s << "casadi_copy(" << arg << ", " << n << ", " << res << ");";
2303  return s.str();
2304  }
2305 
2306  bool CodeGenerator::elide_copy(casadi_int sz) {
2307  if (casadi::GlobalOptions::copy_elision_min_size==-1) return false;
2309  }
2310 
2311  void CodeGenerator::copy_check(const std::string& arg, size_t n, const std::string& res,
2312  bool check_lhs, bool check_rhs) {
2313  std::vector<std::string> checks;
2314  if (check_lhs) checks.push_back(arg);
2315  if (check_rhs) checks.push_back(res);
2316  if (!checks.empty()) *this << "if (" << join(checks, " && ") << ") ";
2317  *this << copy(arg, n, res) << "\n";
2318  }
2319 
2320  void CodeGenerator::copy_default(const std::string& arg, size_t n, const std::string& res,
2321  const std::string& def, bool check_rhs) {
2322  *this << "if (" << arg << ") {\n";
2323  if (check_rhs) *this << "if (" << res << ") ";
2324  *this << copy(arg, n, res) << "\n";
2325  *this << "} else {\n";
2326  if (check_rhs) *this << "if (" << res << ") ";
2327  *this << fill(res, n, def) << "\n";
2328  *this << "}\n";
2329  }
2330 
2331  std::string CodeGenerator::clear(const std::string& res, std::size_t n) {
2332  std::stringstream s;
2333  // Perform operation
2335  s << "casadi_clear(" << res << ", " << n << ");";
2336  return s.str();
2337  }
2338 
2339  std::string CodeGenerator::arg(casadi_int i) const {
2340  return "arg[" + str(i) + "]";
2341  }
2342 
2343  std::string CodeGenerator::res(casadi_int i) const {
2344  return "res[" + str(i) + "]";
2345  }
2346 
2347  std::string CodeGenerator::mem(const Function& f) {
2348  std::string name = f->codegen_name(*this, false);
2349  std::string mem_array = shorthand(name + "_mem");
2350  return mem_array+"[mem]";
2351  }
2352 
2353  std::string CodeGenerator::fill(const std::string& res,
2354  std::size_t n, const std::string& v) {
2355  if (v=="0") return clear(res, n);
2356  std::stringstream s;
2357  // Perform operation
2359  s << "casadi_fill(" << res << ", " << n << ", " << v << ");";
2360  return s.str();
2361  }
2362 
2363  std::string CodeGenerator::dot(casadi_int n, const std::string& x,
2364  const std::string& y) {
2366  std::stringstream s;
2367  s << "casadi_dot(" << n << ", " << x << ", " << y << ")";
2368  return s.str();
2369  }
2370 
2371  std::string CodeGenerator::bilin(const std::string& A, const Sparsity& sp_A,
2372  const std::string& x, const std::string& y) {
2374  std::stringstream s;
2375  s << "casadi_bilin(" << A << ", " << sparsity(sp_A) << ", " << x << ", " << y << ")";
2376  return s.str();
2377  }
2378 
2379  std::string CodeGenerator::rank1(const std::string& A, const Sparsity& sp_A,
2380  const std::string& alpha, const std::string& x,
2381  const std::string& y) {
2383  std::stringstream s;
2384  s << "casadi_rank1(" << A << ", " << sparsity(sp_A) << ", "
2385  << alpha << ", " << x << ", " << y << ");";
2386  return s.str();
2387  }
2388 
2390  const std::string& res, casadi_int ndim, const std::string& grid,
2391  const std::string& offset,
2392  const std::string& values, const std::string& x,
2393  const std::string& lookup_mode, casadi_int m,
2394  const std::string& iw, const std::string& w) {
2396  std::stringstream s;
2397  s << "casadi_interpn(" << res << ", " << ndim << ", " << grid << ", " << offset << ", "
2398  << values << ", " << x << ", " << lookup_mode << ", " << m << ", " << iw << ", " << w << ");";
2399  return s.str();
2400  }
2401 
2402  std::string CodeGenerator::interpn_grad(const std::string& grad,
2403  casadi_int ndim, const std::string& grid, const std::string& offset,
2404  const std::string& values, const std::string& x,
2405  const std::string& lookup_mode, casadi_int m,
2406  const std::string& iw, const std::string& w) {
2408  std::stringstream s;
2409  s << "casadi_interpn_grad(" << grad << ", " << ndim << ", " << grid << ", " << offset << ", "
2410  << values << ", " << x << ", " << lookup_mode << "," << m << ", " << iw << ", " << w << ");";
2411  return s.str();
2412  }
2413 
2414  std::string CodeGenerator::trans(const std::string& x, const Sparsity& sp_x,
2415  const std::string& y, const Sparsity& sp_y,
2416  const std::string& iw) {
2418  return "casadi_trans(" + x + "," + sparsity(sp_x) + ", "
2419  + y + ", " + sparsity(sp_y) + ", " + iw + ")";
2420  }
2421 
2422  std::string CodeGenerator::declare(std::string s) {
2423  // Add c linkage
2424  std::string cpp_prefix = this->cpp ? "extern \"C\" " : "";
2425 
2426  // To header file
2427  if (this->with_header) {
2428  this->header << cpp_prefix << this->dll_import << s << ";\n";
2429  }
2430 
2431  // Return name with declarations
2432  return cpp_prefix + this->dll_export + s;
2433  }
2434 
2435  std::string
2436  CodeGenerator::project(const std::string& arg, const Sparsity& sp_arg,
2437  const std::string& res, const Sparsity& sp_res,
2438  const std::string& w) {
2439  // If sparsity match, simple copy
2440  if (sp_arg==sp_res) return copy(arg, sp_arg.nnz(), res);
2441 
2442  // Create call
2444  std::stringstream s;
2445  s << "casadi_project(" << arg << ", " << sparsity(sp_arg) << ", " << res << ", "
2446  << sparsity(sp_res) << ", " << w << ");";
2447  return s.str();
2448  }
2449 
2450  std::string
2451  CodeGenerator::tri_project(const std::string& arg, const Sparsity& sp_arg,
2452  const std::string& res, bool lower) {
2453  // Create call
2455  std::stringstream s;
2456  s << "casadi_tri_project(" << arg << ", " << sparsity(sp_arg) << ", ";
2457  s << res << ", " << (lower ? 1: 0) << ");";
2458  return s.str();
2459  }
2460 
2461  std::string
2462  CodeGenerator::densify(const std::string& arg, const Sparsity& sp_arg,
2463  const std::string& res, bool tr) {
2464  // Create call
2466  std::stringstream s;
2467  s << "casadi_densify(" << arg << ", " << sparsity(sp_arg) << ", " << res << ", "
2468  << (tr ? 1 : 0) << ");";
2469  return s.str();
2470  }
2471 
2472  std::string
2473  CodeGenerator::sparsify(const std::string& arg, const std::string& res,
2474  const Sparsity& sp_res, bool tr) {
2475  // Create call
2477  std::stringstream s;
2478  s << "casadi_sparsify(" << arg << ", " << res << ", "
2479  << sparsity(sp_res) << ", " << (tr ? 1 : 0) << ");";
2480  return s.str();
2481  }
2482 
2483  std::string CodeGenerator::printf(const std::string& str, const std::vector<std::string>& arg) {
2485  std::stringstream s;
2486  s << "CASADI_PRINTF(";
2487  // Loop over lines in str
2488  std::string::size_type pos = 0, prev = 0;
2489  while ((pos = str.find('\n', prev)) != std::string::npos) {
2490  // Any line containing a trailing new line
2491  s << "\"" << str.substr(prev, pos-prev) << "\\n\"\n";
2492  prev = pos + 1;
2493  }
2494  // Remainder without trailing new line
2495  s << "\"" << str.substr(prev) << "\"";
2496  for (casadi_int i=0; i<arg.size(); ++i) s << ", " << arg[i];
2497  s << ");";
2498  return s.str();
2499  }
2500 
2501  std::string CodeGenerator::printf(const std::string& str, const std::string& arg1) {
2502  std::vector<std::string> arg;
2503  arg.push_back(arg1);
2504  return printf(str, arg);
2505  }
2506 
2507  std::string CodeGenerator::printf(const std::string& str, const std::string& arg1,
2508  const std::string& arg2) {
2509  std::vector<std::string> arg;
2510  arg.push_back(arg1);
2511  arg.push_back(arg2);
2512  return printf(str, arg);
2513  }
2514 
2515  std::string CodeGenerator::printf(const std::string& str, const std::string& arg1,
2516  const std::string& arg2, const std::string& arg3) {
2517  std::vector<std::string> arg;
2518  arg.push_back(arg1);
2519  arg.push_back(arg2);
2520  arg.push_back(arg3);
2521  return printf(str, arg);
2522  }
2523 
2524  std::string CodeGenerator::axpy(casadi_int n, const std::string& a,
2525  const std::string& x, const std::string& y) {
2527  return "casadi_axpy(" + str(n) + ", " + a + ", " + x + ", " + y + ");";
2528  }
2529 
2530  std::string CodeGenerator::clip_min(const std::string& x, casadi_int n,
2531  const std::string& min, const std::string& mask) {
2533  return "casadi_clip_min(" + x + ", " + str(n) + ", " + min + ", " + mask + ");";
2534  }
2535 
2536  std::string CodeGenerator::clip_max(const std::string& x, casadi_int n,
2537  const std::string& min, const std::string& mask) {
2539  return "casadi_clip_max(" + x + ", " + str(n) + ", " + min + ", " + mask + ");";
2540  }
2541 
2542  std::string CodeGenerator::vector_fmax(casadi_int n, const std::string& x,
2543  const std::string& y, const std::string& z) {
2545  return "casadi_vector_fmax(" + str(n) + ", " + x + ", " + y + ", " + z + ");";
2546  }
2547 
2548  std::string CodeGenerator::vector_fmin(casadi_int n, const std::string& x,
2549  const std::string& y, const std::string& z) {
2551  return "casadi_vector_fmin(" + str(n) + ", " + x + ", " + y + ", " + z + ");";
2552  }
2553 
2554  std::string CodeGenerator::masked_norm_inf(casadi_int n, const std::string& x,
2555  const std::string& mask) {
2557  return "casadi_masked_norm_inf(" + str(n) + ", " + x + ", " + mask + ")";
2558  }
2559 
2560  std::string CodeGenerator::scal(casadi_int n, const std::string& alpha, const std::string& x) {
2562  return "casadi_scal(" + str(n) + ", " + alpha + ", " + x + ");";
2563  }
2564 
2565  std::string CodeGenerator::mv(const std::string& x, const Sparsity& sp_x,
2566  const std::string& y, const std::string& z, bool tr) {
2568  return "casadi_mv(" + x + ", " + sparsity(sp_x) + ", " + y + ", "
2569  + z + ", " + (tr ? "1" : "0") + ");";
2570  }
2571 
2572  std::string CodeGenerator::mv(const std::string& x, casadi_int nrow_x, casadi_int ncol_x,
2573  const std::string& y, const std::string& z, bool tr) {
2575  return "casadi_mv_dense(" + x + ", " + str(nrow_x) + ", " + str(ncol_x) + ", "
2576  + y + ", " + z + ", " + (tr ? "1" : "0") + ");";
2577  }
2578 
2579  std::string CodeGenerator::mtimes(const std::string& x, const Sparsity& sp_x,
2580  const std::string& y, const Sparsity& sp_y,
2581  const std::string& z, const Sparsity& sp_z,
2582  const std::string& w, bool tr) {
2584  return "casadi_mtimes(" + x + ", " + sparsity(sp_x) + ", " + y + ", " + sparsity(sp_y) + ", "
2585  + z + ", " + sparsity(sp_z) + ", " + w + ", " + (tr ? "1" : "0") + ");";
2586  }
2587 
2588  std::string CodeGenerator::mtimes(const std::string& x, casadi_int nrow_x, casadi_int ncol_x,
2589  const std::string& y, casadi_int ncol_y,
2590  const std::string& z, bool tr) {
2592  return "casadi_mtimes_dense(" + x + ", " + str(nrow_x) + ", " + str(ncol_x) + ", "
2593  + y + ", " + str(ncol_y) + ", " + z + ", " + (tr ? "1" : "0") + ");";
2594  }
2595 
2596  std::string CodeGenerator::mtimes_dense_sparse(const std::string& x, casadi_int nrow_x,
2597  const std::string& y, const Sparsity& sp_y, const std::string& z) {
2599  return "casadi_mtimes_dense_sparse(" + x + ", " + str(nrow_x) + ", "
2600  + y + ", " + sparsity(sp_y) + ", " + z + ");";
2601  }
2602 
2603  std::string CodeGenerator::trilsolve(const Sparsity& sp_x, const std::string& x,
2604  const std::string& y, bool tr, bool unity, casadi_int nrhs) {
2606  return "casadi_trilsolve(" + sparsity(sp_x) + ", " + x + ", " + y + ", " + str(tr) + ", "
2607  + str(unity) + ", " + str(nrhs) + ");";
2608  }
2609 
2610  std::string CodeGenerator::triusolve(const Sparsity& sp_x, const std::string& x,
2611  const std::string& y, bool tr, bool unity, casadi_int nrhs) {
2613  return "casadi_triusolve(" + sparsity(sp_x) + ", " + x + ", " + y + ", " + str(tr) + ", "
2614  + str(unity) + ", " + str(nrhs) + ");";
2615  }
2616 
2617 
2618  std::string CodeGenerator::logsumexp(const std::string& A, casadi_int n) {
2620  std::stringstream s;
2621  s << "casadi_logsumexp(" << A << ", " << n << ");";
2622  return s.str();
2623  }
2624 
2625  void CodeGenerator::print_formatted(const std::string& s) {
2626  // Quick return if empty
2627  if (s.empty()) return;
2628 
2629  // If new line, add indentation
2630  if (newline_) {
2631  casadi_int shift = s.front()=='}' ? -1 : 0;
2632  casadi_assert_dev(current_indent_+shift>=0);
2633  this->buffer << std::string(indent_*(current_indent_+shift), ' ');
2634  newline_ = false;
2635  }
2636 
2637  // Print to body
2638  this->buffer << s;
2639 
2640  // Brackets change indentation for next row
2641  // NOTE(@jaeandersson): Should ignore strings, comments
2642  for (char c : s) {
2643  if (c=='{') {
2644  indent();
2645  } else if (c=='}') {
2646  unindent();
2647  }
2648  }
2649  }
2650 
2651  CodeGenerator& CodeGenerator::operator<<(const std::string& s) {
2652  // Loop over newline characters
2653  size_t off=0;
2654  while (true) {
2655  size_t pos = s.find('\n', off);
2656  if (pos==std::string::npos) {
2657  // No more newline characters
2658  print_formatted(s.substr(off));
2659  break;
2660  } else {
2661  // Ends with newline
2662  print_formatted(s.substr(off, pos-off));
2663  this->buffer << '\n';
2664  newline_ = true;
2665  off = pos+1;
2666  }
2667  }
2668 
2669  return *this;
2670  }
2671 
2672  void CodeGenerator::flush(std::ostream &s) {
2673  s << this->buffer.str();
2674  this->buffer.str(std::string());
2675  }
2676 
2677  void CodeGenerator::local(const std::string& name, const std::string& type,
2678  const std::string& ref) {
2679  // Check if the variable already exists
2680  auto it = local_variables_.find(name);
2681  if (it==local_variables_.end()) {
2682  // Add it
2683  local_variables_[name] = std::make_pair(type, ref);
2684  } else {
2685  // Consistency check
2686  casadi_assert(it->second.first==type, "Type mismatch for " + name);
2687  casadi_assert(it->second.second==ref, "Type mismatch for " + name);
2688  }
2689  }
2690 
2691  std::string CodeGenerator::sx_work(casadi_int i) {
2692  if (avoid_stack_) {
2693  return "w[" + str(i) + "]";
2694  } else {
2695  std::string name = "a"+format_padded(i);
2696 
2697  // Make sure work vector element has been declared
2698  local(name, "casadi_real");
2699 
2700  return name;
2701  }
2702  }
2703 
2704  void CodeGenerator::init_local(const std::string& name, const std::string& def) {
2705  auto it = local_default_.find(name);
2706  if (it!=local_default_.end()) {
2707  casadi_assert(it->second==def, "Initial value mismatch for " + name);
2708  }
2709  local_default_.insert(std::make_pair(name, def));
2710  }
2711 
2712  // Read the next double-quoted token from line, starting at pos.
2713  // Backslash escapes the next character, so \" and \\ may appear inside.
2714  // On return, pos points just past the closing quote.
2715  static std::string next_quoted_token(const std::string& line, size_t& pos) {
2716  size_t n1 = line.find('"', pos);
2717  casadi_assert(n1 != std::string::npos, "Missing quoted token in: " + line);
2718  std::string r;
2719  size_t i = n1 + 1;
2720  for (; i < line.size(); ++i) {
2721  if (line[i] == '\\' && i + 1 < line.size()) {
2722  r += line[++i];
2723  } else if (line[i] == '"') {
2724  break;
2725  } else {
2726  r += line[i];
2727  }
2728  }
2729  casadi_assert(i < line.size(), "Unterminated quoted token in: " + line);
2730  pos = i + 1;
2731  return r;
2732  }
2733 
2734  void CodeGenerator::add_runtime(const std::string& key, const std::string& src,
2735  const std::vector<std::string>& inst) {
2736  std::string k = key;
2737  for (const std::string& s : inst) k += "_" + s;
2738  if (added_runtimes_.insert(k).second) auxiliaries << sanitize_source(src, inst);
2739  }
2740 
2741  std::string CodeGenerator::
2742  sanitize_source(const std::string& src,
2743  const std::vector<std::string>& inst, bool add_shorthand) {
2744  // Create suffix if templates type are not all "casadi_real"
2745  std::string suffix;
2746  for (const std::string& s : inst) {
2747  if (s!="casadi_real") {
2748  for (const std::string& s : inst) suffix += "_" + s;
2749  break;
2750  }
2751  }
2752 
2753  // Construct map of name replacements
2754  std::vector<std::pair<std::string, std::string> > rep;
2755  for (casadi_int i=0; i<inst.size(); ++i) {
2756  rep.push_back(std::make_pair("T" + str(i+1), inst[i]));
2757  }
2758 
2759  // Return object
2760  std::stringstream ret;
2761  // Process C++ source
2762  std::string line;
2763  std::istringstream stream(src);
2764 
2765  bool filter_macros = true; // Macro definitions are ignored
2766 
2767  // Set by `// SYMBOL "X"` to "casadi_X"; cleared when the matching
2768  // function signature is found and the prefix is prepended.
2769  std::string active_symbol;
2770 
2771  while (std::getline(stream, line)) {
2772  size_t n1, n2;
2773 
2774  // C++ template declarations are ignored
2775  if (line.find("template")==0) continue;
2776 
2777  // Macro definitions are ignored
2778  if (filter_macros && line.find("#define")==0) continue;
2779  if (filter_macros && line.find("#undef")==0) continue;
2780 
2781  // casadi_assert and error are ignored
2782  if (line.find("casadi_assert") != std::string::npos) continue;
2783  if (line.find("casadi_error") != std::string::npos) continue;
2784  if (line.find("casadi_message") != std::string::npos) continue;
2785 
2786  // Inline declaration
2787  if (line == "inline") continue;
2788 
2789  // If line starts with "// SYMBOL", add shorthand and track the symbol
2790  if (line.find("// SYMBOL") != std::string::npos) {
2791  n1 = line.find("\"");
2792  n2 = line.find("\"", n1+1);
2793  std::string sym = line.substr(n1+1, n2-n1-1);
2794  if (add_shorthand) shorthand(sym + suffix);
2795  if (!suffix.empty()) {
2796  rep.push_back(std::make_pair(sym, sym + suffix));
2797  }
2798  active_symbol = "casadi_" + sym;
2799  continue;
2800  }
2801 
2802  // If line starts with "// C-REPLACE", add to list of replacements
2803  if (line.find("// C-REPLACE") != std::string::npos) {
2804  // Get C++ string, then C string; \" and \\ are unescaped
2805  size_t pos = line.find("// C-REPLACE");
2806  std::string key = next_quoted_token(line, pos);
2807  std::string sub = next_quoted_token(line, pos);
2808  // Add to replacements
2809  rep.push_back(std::make_pair(key, sub));
2810  continue;
2811  }
2812 
2813  // If line starts with "// C-VERBOSE", skip the next line
2814  if (!verbose_runtime && line.find("// C-VERBOSE") != std::string::npos) {
2815  // Ignore next line
2816  std::getline(stream, line);
2817  continue;
2818  }
2819 
2820  if (line.find("// FILTER-MACROS ON") != std::string::npos) {
2821  filter_macros = true;
2822  }
2823 
2824  if (line.find("// FILTER-MACROS OFF") != std::string::npos) {
2825  filter_macros = false;
2826  }
2827 
2828  // Ignore other C++ style comment
2829  n1 = line.find("//");
2830  if (n1 != std::string::npos) line.erase(n1);
2831 
2832  // Remove trailing spaces
2833  n1 = line.find_last_not_of(' ');
2834  if (n1 != std::string::npos) {
2835  line.erase(n1 + 1);
2836  } else {
2837  continue;
2838  }
2839 
2840  // Prepend storage-class/inline-hint to the symbol's signature line
2841  if (!active_symbol.empty() &&
2842  line.find(active_symbol + "(") != std::string::npos) {
2843  std::string sig_prefix;
2844  if (this->static_aux) sig_prefix += "static ";
2845  if (this->inline_aux) sig_prefix += "inline ";
2846  if (!sig_prefix.empty()) line = sig_prefix + line;
2847  active_symbol.clear();
2848  }
2849 
2850  // Perform string replacements
2851  for (auto&& it = rep.rbegin(); it!=rep.rend(); ++it) {
2852  line = replace(line, it->first, it->second);
2853  }
2854 
2855  // Append to return
2856  ret << line << "\n";
2857  }
2858 
2859  // Trailing newline
2860  ret << "\n";
2861  return ret.str();
2862  }
2863 
2864  void CodeGenerator::comment(const std::string& s) {
2865  if (verbose) {
2866  *this << "/* " << s << " */\n";
2867  }
2868  }
2869 
2871  add_io_sparsities(const std::string& name,
2872  const std::vector<Sparsity>& sp_in,
2873  const std::vector<Sparsity>& sp_out) {
2874  // Insert element, quick return if it already exists
2875  if (!sparsity_meta.insert(name).second) return;
2876 
2877  // Input sparsities
2878  *this << declare("const casadi_int* " + name + "_sparsity_in(casadi_int i)") << " {\n"
2879  << "switch (i) {\n";
2880  for (casadi_int i=0; i<sp_in.size(); ++i) {
2881  *this << "case " << i << ": return " << sparsity(sp_in[i], force_canonical) << ";\n";
2882  }
2883  *this << "default: return 0;\n}\n"
2884  << "}\n\n";
2885 
2886  // Output sparsities
2887  *this << declare("const casadi_int* " + name + "_sparsity_out(casadi_int i)") << " {\n"
2888  << "switch (i) {\n";
2889  for (casadi_int i=0; i<sp_out.size(); ++i) {
2890  *this << "case " << i << ": return " << sparsity(sp_out[i], force_canonical) << ";\n";
2891  }
2892  *this << "default: return 0;\n}\n"
2893  << "}\n\n";
2894  }
2895 
2896  std::string CodeGenerator::
2897  qr(const std::string& sp, const std::string& A, const std::string& w,
2898  const std::string& sp_v, const std::string& v, const std::string& sp_r,
2899  const std::string& r, const std::string& beta, const std::string& prinv,
2900  const std::string& pc) {
2902  return "casadi_qr(" + sp + ", " + A + ", " + w + ", "
2903  + sp_v + ", " + v + ", " + sp_r + ", " + r + ", "
2904  + beta + ", " + prinv + ", " + pc + ");";
2905  }
2906 
2907  std::string CodeGenerator::
2908  det(const std::string& sp_v, const std::string& v,
2909  const std::string& sp_r, const std::string& r, const std::string& beta) {
2911  return "casadi_det(" + sp_v + ", " + v + ", " + sp_r + ", " + r + ", " + beta + ")";
2912  }
2913 
2914  std::string CodeGenerator::
2915  qr_solve(const std::string& x, casadi_int nrhs, bool tr,
2916  const std::string& sp_v, const std::string& v,
2917  const std::string& sp_r, const std::string& r,
2918  const std::string& beta, const std::string& prinv,
2919  const std::string& pc, const std::string& w) {
2921  return "casadi_qr_solve(" + x + ", " + str(nrhs) + ", " + (tr ? "1" : "0") + ", "
2922  + sp_v + ", " + v + ", " + sp_r + ", " + r + ", "
2923  + beta + ", " + prinv + ", " + pc + ", " + w + ");";
2924  }
2925 
2926  std::string CodeGenerator::
2927  lsqr_solve(const std::string& A, const std::string&x,
2928  casadi_int nrhs, bool tr, const std::string& sp, const std::string& w) {
2930  return "casadi_lsqr_solve(" + A + ", " + x + ", " + str(nrhs) + ", "
2931  + (tr ? "1" : "0") + ", " + sp + ", " + w + ");";
2932  }
2933 
2934  std::string CodeGenerator::
2935  ldl(const std::string& sp_a, const std::string& a,
2936  const std::string& sp_lt, const std::string& lt, const std::string& d,
2937  const std::string& p, const std::string& w) {
2939  return "casadi_ldl(" + sp_a + ", " + a + ", " + sp_lt + ", " + lt + ", "
2940  + d + ", " + p + ", " + w + ");";
2941  }
2942 
2943  std::string CodeGenerator::
2944  ldl_solve(const std::string& x, casadi_int nrhs,
2945  const std::string& sp_lt, const std::string& lt, const std::string& d,
2946  const std::string& p, const std::string& w) {
2948  return "casadi_ldl_solve(" + x + ", " + str(nrhs) + ", " + sp_lt + ", "
2949  + lt + ", " + d + ", " + p + ", " + w + ");";
2950  }
2951 
2952  std::string CodeGenerator::
2953  fmax(const std::string& x, const std::string& y) {
2955  return "casadi_fmax(" + x + ", " + y + ");";
2956  }
2957 
2958  std::string CodeGenerator::
2959  fmin(const std::string& x, const std::string& y) {
2961  return "casadi_fmin(" + x + ", " + y + ");";
2962  }
2963 
2964  std::string CodeGenerator::
2965  vfmax(const std::string& x, casadi_int n, const std::string& y) {
2967  return "casadi_vfmax(" + x + ", " + str(n) + ", " + y + ");";
2968  }
2969 
2970  std::string CodeGenerator::
2971  vfmin(const std::string& x, casadi_int n, const std::string& y) {
2973  return "casadi_vfmin(" + x + ", " + str(n) + ", " + y + ");";
2974  }
2975 
2976  std::string CodeGenerator::
2977  vfmax(const std::string& x, const std::string& n, const std::string& y) {
2979  return "casadi_vfmax(" + x + ", " + n + ", " + y + ");";
2980  }
2981 
2982  std::string CodeGenerator::
2983  vfmin(const std::string& x, const std::string& n, const std::string& y) {
2985  return "casadi_vfmin(" + x + ", " + n + ", " + y + ");";
2986  }
2987 
2988  std::string CodeGenerator::
2989  max(const std::string& x, const std::string& y) {
2991  return "casadi_max(" + x + ", " + y + ")";
2992  }
2993 
2994  std::string CodeGenerator::
2995  min(const std::string& x, const std::string& y) {
2997  return "casadi_min(" + x + ", " + y + ")";
2998  }
2999 
3000  std::string CodeGenerator::
3001  mmax(const std::string& x, casadi_int n, bool is_dense) {
3003  return "casadi_mmax(" + x + ", " + str(n) + ", " + str(casadi_int(is_dense)) + ")";
3004  }
3005 
3006  std::string CodeGenerator::
3007  mmin(const std::string& x, casadi_int n, bool is_dense) {
3009  return "casadi_mmin(" + x + ", " + str(n) + ", " + str(casadi_int(is_dense)) + ")";
3010  }
3011 
3012  std::string CodeGenerator::
3013  max_viol(casadi_int n, const std::string& x, const std::string& lb, const std::string& ub) {
3015  return "casadi_max_viol(" + str(n) + ", " + x+ ", " + lb + ", " + ub + ")";
3016  }
3017 
3018  std::string CodeGenerator::
3019  sum_viol(casadi_int n, const std::string& x, const std::string& lb, const std::string& ub) {
3021  return "casadi_sum_viol(" + str(n) + ", " + x+ ", " + lb + ", " + ub + ")";
3022  }
3023 
3024  std::string CodeGenerator::
3025  norm_inf(casadi_int n, const std::string& x) {
3027  return "casadi_norm_inf(" + str(n) + ", " + x + ")";
3028  }
3029 
3030  std::string CodeGenerator::
3031  norm_1(casadi_int n, const std::string& x) {
3033  return "casadi_norm_1(" + str(n) + ", " + x + ")";
3034  }
3035 
3036  std::string CodeGenerator::
3037  norm_2(casadi_int n, const std::string& x) {
3039  return "casadi_norm_2(" + str(n) + ", " + x + ")";
3040  }
3041 
3042  std::string CodeGenerator::
3043  lb_eig(const Sparsity& sp_h, const std::string& h) {
3045  return "casadi_lb_eig(" + sparsity(sp_h) + ", " + h + ")";
3046  }
3047 
3048  std::string CodeGenerator::
3049  regularize(const Sparsity& sp_h, const std::string& h, const std::string& reg) {
3051  return "casadi_regularize(" + sparsity(sp_h) + ", " + h + ", " + reg + ");";
3052  }
3053 
3054  std::string CodeGenerator::
3056  const std::string& Hin, const std::string& Hout, const std::string& iw, const std::string& w) {
3058  return Convexify::generate(*this, d, Hin, Hout, iw, w);
3059  }
3060 
3061  std::string CodeGenerator::
3062  low(const std::string& x, const std::string& grid, casadi_int ng, casadi_int lookup_mode) {
3064  return "casadi_low(" + x + ", " + grid + ", " + str(ng) + ", " + str(lookup_mode) + ");";
3065  }
3066 
3067  std::string CodeGenerator::
3068  bound_consistency(casadi_int n, const std::string& x,
3069  const std::string& lam, const std::string& lbx, const std::string& ubx) {
3071  return "casadi_bound_consistency(" + str(n) + ", " + x + ", " + lam +
3072  ", " + lbx + ", " + ubx + ")";
3073  }
3074 
3075  std::string CodeGenerator::
3076  file_slurp(const std::string& fname, casadi_int n, const std::string& a) {
3078  return "casadi_file_slurp(\"" + fname + "\", " + str(n) + ", " + a + ")";
3079  }
3080 
3081  std::string CodeGenerator::
3082  to_file(const std::string& f, const Sparsity& sp, const std::string& x) {
3084  return "casadi_to_file(" + f + ", " + sparsity(sp) + ", " + x + ")";
3085  }
3086 
3088  generate_dump(const Function& f, const std::string& arr, bool is_input) {
3089  casadi_int n = is_input ? f.n_in() : f.n_out();
3090  std::string dump_format = f->dump_format_.empty() ? "mtx" : f->dump_format_;
3091  std::string effective_dir = dump_dir_prefix + f->dump_dir_ + dump_dir_suffix;
3092  std::string prefix;
3093  if (!effective_dir.empty()) prefix = effective_dir + "/";
3094  std::string inout = is_input ? "in" : "out";
3095 
3096  // Ensure directory exists at codegen time
3097  if (!effective_dir.empty() && Filesystem::is_enabled()) {
3098  std::string dir = Filesystem::ensure_trailing_slash(effective_dir);
3099  casadi_assert(Filesystem::ensure_directory_exists(dir),
3100  "Unable to create the required directory for '" + dir + "'.");
3101  }
3102 
3103  // Assumes dump_id_local is declared in the enclosing scope
3104  // Per-input/output format files (e.g. .mtx)
3105  for (casadi_int i = 0; i < n; ++i) {
3106  std::string io_name = is_input ? f.name_in(i) : f.name_out(i);
3107  Sparsity sp = is_input ? f.sparsity_in(i) : f.sparsity_out(i);
3108  std::string fixed_part = prefix + f.name() + "." + inout + "." + io_name + "." + dump_format;
3109  casadi_int buf_size = fixed_part.size() + 1 + 6 + 1; // +7 for the counter field
3110  *this << "{\n";
3111  *this << "char dump_fname[" << buf_size << "];\n";
3112  *this << "FILE* dump_file;\n";
3113  *this << "snprintf(dump_fname, " << buf_size << ", \""
3114  << prefix << f.name() << ".%06d." << inout << "." << io_name
3115  << "." << dump_format << "\", dump_id_local);\n";
3116  if (f->verbose_) {
3117  *this << printf("dump -> %s\\n", "dump_fname") << "\n";
3118  }
3119  *this << "dump_file = fopen(dump_fname, \"w\");\n";
3120  *this << "if (dump_file) {\n";
3121  *this << to_file("dump_file", sp, arr + "[" + str(i) + "]") << ";\n";
3122  *this << "fclose(dump_file);\n";
3123  *this << "}\n";
3124  *this << "}\n";
3125  }
3126  // Combined .txt file (normalized doubles, one per line)
3127  {
3128  add_include("stdio.h");
3129  std::string fixed_part = prefix + f.name() + "." + inout + ".txt";
3130  casadi_int buf_size = fixed_part.size() + 1 + 6 + 1;
3131  *this << "{\n";
3132  *this << "char dump_fname[" << buf_size << "];\n";
3133  *this << "FILE* dump_file;\n";
3134  *this << "casadi_int dump_k;\n";
3135  *this << "snprintf(dump_fname, " << buf_size << ", \""
3136  << prefix << f.name() << ".%06d." << inout << ".txt\", dump_id_local);\n";
3137  *this << "dump_file = fopen(dump_fname, \"w\");\n";
3138  *this << "if (dump_file) {\n";
3139  for (casadi_int i = 0; i < n; ++i) {
3140  Sparsity sp = is_input ? f.sparsity_in(i) : f.sparsity_out(i);
3141  casadi_int nnz = sp.nnz();
3142  std::string a = arr + "[" + str(i) + "]";
3143  if (nnz > 0) {
3144  *this << "if (" << a << ") {\n";
3145  *this << fprintf_vector("dump_file", nnz, a, "\\n") << "\n";
3146  *this << "fprintf(dump_file, \"\\n\");\n";
3147  *this << "} else {\n";
3148  std::string zero_str = is_input ? "0.0000000000000000e+00" : "nan";
3149  *this << "for (dump_k=0; dump_k<" << nnz << "; ++dump_k) "
3150  << "fprintf(dump_file, \"" << zero_str << "\\n\");\n";
3151  *this << "}\n";
3152  }
3153  }
3154  *this << "fclose(dump_file);\n";
3155  *this << "}\n";
3156  *this << "}\n";
3157  }
3158  }
3159 
3161  generate_print(const Function& f, const std::string& arr, bool is_input) {
3162  casadi_int n = is_input ? f.n_in() : f.n_out();
3163  std::string inout = is_input ? "Input" : "Output";
3164 
3165  *this << printf("Function " + f.name() + "\\n") << "\n";
3166  for (casadi_int i = 0; i < n; ++i) {
3167  std::string io_name = is_input ? f.name_in(i) : f.name_out(i);
3168  Sparsity sp = is_input ? f.sparsity_in(i) : f.sparsity_out(i);
3169  *this << printf(inout + " " + str(i) + " (" + io_name + "): ") << "\n";
3170  *this << print_canonical(sp, arr + "[" + str(i) + "]") << "\n";
3171  *this << printf("\\n") << "\n";
3172  }
3173  }
3174 
3175  std::string CodeGenerator::
3176  cache_check(const std::string& key, const std::string& cache, const std::string& loc,
3177  casadi_int stride, casadi_int sz, casadi_int key_sz, const std::string& val) {
3179  return "casadi_cache_check(" + key + ", " + cache + ", " + loc + ", " +
3180  str(stride) + ", " + str(sz) + ", " + str(key_sz) + ", " + val + ")";
3181  }
3182 
3183  void CodeGenerator::sz_work(size_t& sz_arg, size_t& sz_res, size_t& sz_iw, size_t& sz_w) const {
3184  sz_arg = sz_res = sz_iw = sz_w = 0;
3185  for (auto&& f : added_functions_) {
3186  sz_arg = std::max(sz_arg, f.f.sz_arg());
3187  sz_res = std::max(sz_res, f.f.sz_res());
3188  sz_iw = std::max(sz_iw, f.f.sz_iw());
3189  sz_w = std::max(sz_w, f.f.sz_w());
3190  }
3191  }
3192 
3193 } // namespace casadi
static bool codegen_dot_aux(CodeGenerator &g, const std::vector< std::string > &inst)
Definition: blas.cpp:305
static bool codegen_norm_1_aux(CodeGenerator &g, const std::vector< std::string > &inst)
Definition: blas.cpp:332
static void codegen_copy_aux(CodeGenerator &g, const std::vector< std::string > &inst)
Definition: blas.cpp:283
static bool codegen_scal_aux(CodeGenerator &g, const std::vector< std::string > &inst)
Definition: blas.cpp:314
static bool codegen_axpy_aux(CodeGenerator &g, const std::vector< std::string > &inst)
Definition: blas.cpp:296
static bool codegen_norm_2_aux(CodeGenerator &g, const std::vector< std::string > &inst)
Definition: blas.cpp:323
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
void scope_add_cleanup(const std::string &code)
Add cleanup code to be executed upon scope exit.
std::set< std::string > external_names_
const std::set< std::string > & local_mutexes(const Function &f) const
Get all mutex names associated with a function.
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.
void add_runtime(const std::string &key, const std::string &src, const std::vector< std::string > &inst)
Add a sanitized runtime source once per key.
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.
bool thread_safe() const
Emit thead safe code chekout/release?
std::vector< std::string > local_cleanup_
std::map< std::string, std::string > local_default_
std::map< const FunctionInternal *, std::set< std::string > > local_mutexes_
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.
void generate_dump(const Function &f, const std::string &arr, bool is_input)
Generate dump_in or dump_out code for a function call.
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 to_file(const std::string &f, const Sparsity &sp, const std::string &x)
Write matrix to file in MatrixMarket format.
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::set< std::string > added_runtimes_
std::string generate(const std::string &prefix="")
Generate file(s)
std::string fprintf_scalar(const std::string &f, const std::string &arg)
fprintf a normalized scalar (canonical nan/inf) to a file
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
void generate_print(const Function &f, const std::string &arr, bool is_input)
Generate print_in or print_out code for a function call.
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.
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::string fprintf_vector(const std::string &f, casadi_int sz, const std::string &arg, const std::string &sep)
fprintf a normalized vector to a file with a separator
std::vector< std::vector< double > > double_constants_
std::map< const FunctionInternal *, size_t > codegen_sz_w_
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.
void add_external(const std::string &new_external, const std::string &name="")
Add an external function declaration.
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.
std::string mtimes_dense_sparse(const std::string &x, casadi_int nrow_x, const std::string &y, const Sparsity &sp_y, const std::string &z)
Codegen dense-sparse matrix-matrix multiplication (z, x dense)
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 local_mutex(const Function &f, const std::string &name) const
Access a static mutex associated with a function.
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.
std::string det(const std::string &sp_v, const std::string &v, const std::string &sp_r, const std::string &r, const std::string &beta)
Determinant from sparse QR factors.
casadi_int max_declarations_per_line
bool get_codegen_sz_w(const FunctionInternal *f, size_t &sz_w) const
Retrieve a work vector size registered by set_codegen_sz_w.
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.
void scope_return()
Return from a scope without a value.
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
void set_codegen_sz_w(const FunctionInternal *f, size_t sz_w)
Register the work vector size a function needs in generated code.
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.
void define_local_mutex(const Function &f, const std::string &name)
Declare a static mutex associated with a 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:157
static std::string ensure_trailing_slash(const std::string &path)
Definition: filesystem.cpp:155
static bool ensure_directory_exists(const std::string &path)
Definition: filesystem.cpp:105
static bool is_enabled()
Definition: filesystem.cpp:83
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.
std::vector< Sparsity > sparsity_in_
Input and output sparsity.
virtual void codegen_decref(CodeGenerator &g) const
Codegen decref for dependencies.
virtual bool codegen_mem_is_opaque() const
Is thread-local memory object managed by checkout/release.
virtual void codegen_free_mem(CodeGenerator &g) const
Codegen for free_mem.
std::string signature_unrolled(const std::string &fname) const
Code generate the function.
bool has_refcount_in_deps_
Reference counting in dependent functions.
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 bool codegen_needs_mem() const
Is thread-local memory object needed?
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_incref(CodeGenerator &g) const
Codegen incref for dependencies.
Function object.
Definition: function.hpp:126
const Sparsity & sparsity_out(casadi_int ind) const
Get the sparsity pattern of an output, by index or name.
Definition: function.cpp:1183
FunctionInternal * get() const
Definition: function.cpp:505
const std::vector< std::string > & name_in() const
Get the names of all inputs, in order.
Definition: function.cpp:1113
const std::string & name() const
Get the name given at construction ("null" for a null object)
Definition: function.cpp:1504
static bool check_name(const std::string &name)
Check whether a string is a valid function name.
Definition: function.cpp:1513
const Sparsity & sparsity_in(casadi_int ind) const
Get the sparsity pattern of an input, by index or name.
Definition: function.cpp:1167
casadi_int n_out() const
Get the number of function outputs.
Definition: function.cpp:975
casadi_int n_in() const
Get the number of function inputs.
Definition: function.cpp:971
const std::vector< Sparsity > & jac_sparsity(bool compact=false) const
Get the sparsity patterns of all Jacobian blocks.
Definition: function.cpp:1092
const std::vector< std::string > & name_out() const
Get the names of all outputs, in order.
Definition: function.cpp:1117
static casadi_int copy_elision_min_size
bool verbose_
Verbose printout.
General sparsity class.
Definition: sparsity.hpp:200
casadi_int nnz() const
Number of structural nonzeros.
Definition: sparsity.cpp:150
std::vector< casadi_int > compress(bool canonical=true) const
Compact single-vector representation of the pattern.
Definition: sparsity.cpp:1335
The casadi namespace.
Definition: archiver.cpp:28
static const std::set< std::string > empty_mutex_set_
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)
static std::string next_quoted_token(const std::string &line, size_t &pos)
@ 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:1665