code_generator.hpp
1 /*
2  * This file is part of CasADi.
3  *
4  * CasADi -- A symbolic framework for dynamic optimization.
5  * Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl,
6  * KU Leuven. All rights reserved.
7  * Copyright (C) 2011-2014 Greg Horn
8  *
9  * CasADi is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 3 of the License, or (at your option) any later version.
13  *
14  * CasADi is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with CasADi; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 
26 #ifndef CASADI_CODE_GENERATOR_HPP
27 #define CASADI_CODE_GENERATOR_HPP
28 
29 #include "function.hpp"
30 
31 #include <map>
32 #include <set>
33 #include <sstream>
34 
35 namespace casadi {
36 
43  class CASADI_EXPORT CodeGenerator {
44  public:
46  CodeGenerator(const std::string& name, const Dict& opts = Dict());
47 
49  void add(const Function& f, bool with_jac_sparsity=false);
50 
51 #ifndef SWIG
53  void dump(std::ostream& s);
54 #endif // SWIG
55 
57  std::string dump();
58 
66  std::string generate(const std::string& prefix="");
67 
69  void add_include(const std::string& new_include, bool relative_path=false,
70  const std::string& use_ifdef=std::string());
71 
72 #ifndef SWIG
74  std::string add_dependency(const Function& f);
75 
77  void add_external(const std::string& new_external);
78 
80  std::string shorthand(const std::string& name) const;
81 
83  std::string shorthand(const std::string& name, bool allow_adding=true);
84 
85  /* Add a sparsity pattern
86  *
87  * \param canonical If true, request canonical form,
88  * as opposed to potential dense abbreviation
89  */
90  std::string sparsity(const Sparsity& sp, bool canonical=true);
91 
92  /* Add a sparsity pattern, get index
93  *
94  * \param canonical If true, request canonical form,
95  * as opposed to potential dense abbreviation
96  */
97  casadi_int add_sparsity(const Sparsity& sp, bool canonical=true);
98 
102  casadi_int get_sparsity(const Sparsity& sp) const;
103 
107  casadi_int get_constant(const std::vector<double>& v, bool allow_adding=false);
108 
112  casadi_int get_constant(const std::vector<casadi_int>& v, bool allow_adding=false);
113 
117  casadi_int get_constant(const std::vector<char>& v, bool allow_adding=false);
118 
122  casadi_int get_constant(const std::vector<std::string>& v, bool allow_adding=false);
123 
127  std::string constant(const std::vector<casadi_int>& v);
128 
132  std::string constant(const std::vector<int>& v) {
133  return constant(vector_static_cast<casadi_int>(v));
134  }
135 
139  void constant_copy(
140  const std::string& var_name,
141  const std::vector<casadi_int>& v,
142  const std::string& type="casadi_int");
143 
147  std::string constant(const std::vector<double>& v);
148 
152  std::string constant(const std::vector<char>& v);
153 
157  std::string constant(const std::vector<std::string>& v);
158 
162  void define_rom_double(const void* id, casadi_int size);
163 
167  std::string rom_double(const void* id) const;
168 
172  void define_rom_integer(const void* id, casadi_int size);
173 
177  std::string rom_integer(const void* id) const;
178 
182  void define_pool_double(const std::string& name, const std::vector<double>& def);
183 
187  std::string pool_double(const std::string& name) const;
188 
192  void setup_callback(const std::string& s, const Function& f);
193 
197  std::string operator()(const Function& f, const std::string& arg,
198  const std::string& res, const std::string& iw,
199  const std::string& w, const std::string& failure_ret="1");
200 
204  CodeGenerator& operator<<(const std::string& s);
205 
209  void print_formatted(const std::string& s);
210 
214  template<typename T>
216  std::stringstream ss;
217  ss << s;
218  return (*this) << ss.str();
219  }
220 
224  void flush(std::ostream &s);
225 
229  void local(const std::string& name, const std::string& type, const std::string& ref="");
230 
234  void scope_enter();
235 
239  void scope_exit();
240 
244  std::string sx_work(casadi_int i);
245 
249  void init_local(const std::string& name, const std::string& def);
250 
254  void indent() {current_indent_++;}
255 
259  void unindent() {current_indent_--;}
260 
264  bool avoid_stack() const { return avoid_stack_;}
265 
269  std::string constant(double v);
270  std::string constant(casadi_int v);
271  std::string constant(const std::string& v);
272  std::string constant(char v);
273 
274  std::string format_padded(casadi_int i) const;
275 
276  std::string zeros(casadi_int sz);
277  std::string ones(casadi_int sz);
278 
282  template <typename T>
283  std::string initializer(const std::vector<T>& v) {
284  std::stringstream s;
285  if (v.size() > max_initializer_elements_per_line) {
286  s << "\n ";
287  }
288 
289  s << "{";
290  for (casadi_int i = 0; i < v.size(); ++i) {
291  if (i != 0) {
292  if (max_initializer_elements_per_line > 1 &&
293  i % max_initializer_elements_per_line == 0) {
294  s << ",\n ";
295  } else {
296  s << ", ";
297  }
298  }
299  s << constant(v[i]);
300  }
301  s << "}";
302  return s.str();
303  }
304 
308  std::string sanitize_source(const std::string& src,
309  const std::vector<std::string>& inst,
310  bool add_shorthand=true);
311 
315  std::string dot(casadi_int n, const std::string& x, const std::string& y);
316 
320  std::string mv(const std::string& x, const Sparsity& sp_x,
321  const std::string& y, const std::string& z, bool tr);
322 
326  std::string mv(const std::string& x, casadi_int nrow_x, casadi_int ncol_x,
327  const std::string& y, const std::string& z, bool tr);
328 
332  std::string axpy(casadi_int n, const std::string& a,
333  const std::string& x, const std::string& y);
334 
340  std::string clip_min(const std::string& x, casadi_int n,
341  const std::string& min, const std::string& mask);
342 
348  std::string clip_max(const std::string& x, casadi_int n,
349  const std::string& min, const std::string& mask);
350 
355  std::string vector_fmax(casadi_int n, const std::string& x,
356  const std::string& y, const std::string& z);
357 
362  std::string vector_fmin(casadi_int n, const std::string& x,
363  const std::string& y, const std::string& z);
364 
369  std::string masked_norm_inf(casadi_int n, const std::string& x,
370  const std::string& mask);
371 
372 
376  std::string scal(casadi_int n, const std::string& alpha, const std::string& x);
377 
381  std::string mtimes(const std::string& x, const Sparsity& sp_x,
382  const std::string& y, const Sparsity& sp_y,
383  const std::string& z, const Sparsity& sp_z,
384  const std::string& w, bool tr);
385 
389  std::string trilsolve(const Sparsity& sp_x, const std::string& x, const std::string& y,
390  bool tr, bool unity, casadi_int nrhs);
391 
395  std::string triusolve(const Sparsity& sp_x, const std::string& x, const std::string& y,
396  bool tr, bool unity, casadi_int nrhs);
397 
401  std::string bilin(const std::string& A, const Sparsity& sp_A,
402  const std::string& x, const std::string& y);
403 
407  std::string rank1(const std::string& A, const Sparsity& sp_A, const std::string& alpha,
408  const std::string& x, const std::string& y);
409 
411  std::string logsumexp(const std::string& A, casadi_int n);
412 
416  std::string interpn(const std::string& res, casadi_int ndim, const std::string& grid,
417  const std::string& offset,
418  const std::string& values, const std::string& x,
419  const std::string& lookup_mode, casadi_int m,
420  const std::string& iw, const std::string& w);
421 
425  std::string interpn_grad(const std::string& grad,
426  casadi_int ndim, const std::string& grid,
427  const std::string& offset,
428  const std::string& values, const std::string& x,
429  const std::string& lookup_mode, casadi_int m,
430  const std::string& iw, const std::string& w);
431 
435  std::string trans(const std::string& x, const Sparsity& sp_x,
436  const std::string& y, const Sparsity& sp_y, const std::string& iw);
437 
441  std::string qr(const std::string& sp, const std::string& A,
442  const std::string& w, const std::string& sp_v,
443  const std::string& v, const std::string& sp_r,
444  const std::string& r, const std::string& beta,
445  const std::string& prinv, const std::string& pc);
446 
450  std::string qr_solve(const std::string& x, casadi_int nrhs, bool tr,
451  const std::string& sp_v, const std::string& v,
452  const std::string& sp_r, const std::string& r,
453  const std::string& beta, const std::string& prinv,
454  const std::string& pc, const std::string& w);
455 
459  std::string lsqr_solve(const std::string& A, const std::string&x,
460  casadi_int nrhs, bool tr, const std::string& sp, const std::string& w);
461 
465  std::string ldl(const std::string& sp_a, const std::string& a,
466  const std::string& sp_lt, const std::string& lt,
467  const std::string& d, const std::string& p,
468  const std::string& w);
469 
473  std::string ldl_solve(const std::string& x, casadi_int nrhs,
474  const std::string& sp_lt, const std::string& lt,
475  const std::string& d, const std::string& p,
476  const std::string& w);
477 
481  std::string fmax(const std::string& x, const std::string& y);
482 
486  std::string fmin(const std::string& x, const std::string& y);
487 
491  std::string mmax(const std::string& x, casadi_int n, bool is_dense);
492 
496  std::string mmin(const std::string& x, casadi_int n, bool is_dense);
497 
501  std::string vfmax(const std::string& x, casadi_int n, const std::string& y);
502 
506  std::string vfmin(const std::string& x, casadi_int n, const std::string& y);
507 
511  std::string vfmax(const std::string& x, const std::string& n, const std::string& y);
512 
516  std::string vfmin(const std::string& x, const std::string& n, const std::string& y);
517 
521  std::string max(const std::string& x, const std::string& y);
522 
526  std::string min(const std::string& x, const std::string& y);
527 
531  std::string norm_inf(casadi_int n, const std::string& x);
532 
536  std::string norm_1(casadi_int n, const std::string& x);
537 
543  std::string norm_2(casadi_int n, const std::string& x);
544 
548  std::string max_viol(casadi_int n, const std::string& x,
549  const std::string& lb, const std::string& ub);
550 
554  std::string sum_viol(casadi_int n, const std::string& x,
555  const std::string& lb, const std::string& ub);
556 
560  std::string bound_consistency(casadi_int n, const std::string& x,
561  const std::string& lam, const std::string& lbx, const std::string& ubx);
562 
566  std::string lb_eig(const Sparsity& sp_h, const std::string& h);
567 
571  std::string regularize(const Sparsity& sp_h, const std::string& h, const std::string& reg);
572 
576  std::string convexify_eval(const ConvexifyData& d,
577  const std::string& Hin, const std::string& Hout, const std::string& iw, const std::string& w);
578 
582  std::string low(const std::string& x, const std::string& grid,
583  casadi_int ng, casadi_int lookup_mode);
584 
588  std::string declare(std::string s);
589 
593  void comment(const std::string& s);
594 
598  enum Auxiliary {
690  AUX_PRINTME
691  };
692 
696  void add_auxiliary(Auxiliary f, const std::vector<std::string>& inst = {"casadi_real"});
697 
701  void add_io_sparsities(const std::string& name,
702  const std::vector<Sparsity>& sp_in,
703  const std::vector<Sparsity>& sp_out);
704 
706  std::string work(casadi_int n, casadi_int sz, bool is_ref) const;
707 
709  std::string workel(casadi_int n) const;
710 
714  void reserve_work(casadi_int n);
715 
717  static std::string array(const std::string& type, const std::string& name, casadi_int len,
718  const std::string& def=std::string());
719 
723  void print_vector(std::ostream &s, const std::string& name,
724  const std::vector<casadi_int>& v);
725 
729  void print_vector(std::ostream &s, const std::string& name,
730  const std::vector<char>& v);
731 
735  void print_vector(std::ostream &s, const std::string& name,
736  const std::vector<double>& v);
737 
741  void print_vector(std::ostream &s, const std::string& name,
742  const std::vector<std::string>& v);
743 
747  std::string copy(const std::string& arg, std::size_t n, const std::string& res);
748  void copy_check(const std::string& arg, std::size_t n, const std::string& res,
749  bool check_lhs=true, bool check_rhs=true);
750  void copy_default(const std::string& arg, std::size_t n, const std::string& res,
751  const std::string& def, bool check_rhs=true);
752 
753  // Should we elide a copy?
754  bool elide_copy(casadi_int sz);
755 
759  std::string fill(const std::string& res, std::size_t n, const std::string& v);
760 
764  std::string clear(const std::string& res, std::size_t n);
765 
769  std::string arg(casadi_int i) const;
770 
774  std::string res(casadi_int i) const;
775 
779  std::string mem(const Function& f);
780 
784  std::string project(const std::string& arg, const Sparsity& sp_arg,
785  const std::string& res, const Sparsity& sp_res,
786  const std::string& w);
787 
791  std::string tri_project(const std::string& arg, const Sparsity& sp_arg,
792  const std::string& res, bool lower);
793 
797  std::string densify(const std::string& arg, const Sparsity& sp_arg,
798  const std::string& res, bool tr=false);
799 
803  std::string sparsify(const std::string& arg, const std::string& res,
804  const Sparsity& sp_res, bool tr=false);
805 
809  std::string to_mex(const Sparsity& sp, const std::string& arg);
810 
814  std::string from_mex(std::string& arg,
815  const std::string& res, std::size_t res_off, const Sparsity& sp_res,
816  const std::string& w);
817 
821  static std::string fmu_helpers(const std::string& modelname);
822 
826  std::string printf(const std::string& str,
827  const std::vector<std::string>& arg=std::vector<std::string>());
828  std::string printf(const std::string& str, const std::string& arg1);
829  std::string printf(const std::string& str, const std::string& arg1, const std::string& arg2);
830  std::string printf(const std::string& str, const std::string& arg1, const std::string& arg2,
831  const std::string& arg3);
832 
836  std::string print_op(casadi_int op, const std::string& a0);
837  std::string print_op(casadi_int op, const std::string& a0, const std::string& a1);
838 
842  std::string file_slurp(const std::string& fname, casadi_int n, const std::string& a);
843 
847  std::string cache_check(const std::string& key, const std::string& cache,
848  const std::string& loc, casadi_int stride, casadi_int sz, casadi_int key_sz,
849  const std::string& val);
850 
852  static std::string casadi_version();
853 
855  static void file_open(std::ofstream& f, const std::string& name, bool cpp);
856 
858  static void file_close(std::ofstream& f, bool cpp);
859 
863  void sz_work(size_t& sz_arg, size_t& sz_res, size_t& sz_iw, size_t& sz_w) const;
864 
865  private:
866 
867  // Generate casadi_real definition
868  void generate_casadi_real(std::ostream &s) const;
869 
870  // Generate casadi_int definition
871  void generate_casadi_int(std::ostream &s) const;
872 
873  // Generate mex entry point
874  void generate_mex(std::ostream &s) const;
875 
876  // Generate function specific code for Simulink s-Function
877  std::string codegen_sfunction(const Function& f) const;
878 
879  // Export s-Function to file
880  void generate_sfunction(const std::string& name, const std::string& sfunction) const;
881 
882  // Generate main entry point
883  void generate_main(std::ostream &s) const;
884 
885  // Generate export symbol macros
886  void generate_export_symbol(std::ostream &s) const;
887 
888  // Generate import symbol macros
889  void generate_import_symbol(std::ostream &s) const;
890 
891  // private:
892  public:
894 
895  // Name of generated file
896  std::string name, suffix;
897 
898  // Real-type used for the codegen
899  std::string casadi_real_type;
900 
901  // Int-type used for the codegen
902  std::string casadi_int_type;
903 
904  // Should we create a memory entry point?
905  bool with_mem;
906 
907  // Generate header file?
909 
910  // Are we creating a MEX file?
911  bool mex;
912 
913  // Are we creating a s-function?
915  std::vector<std::string> added_sfunctions;
916 
917  // Unroll arguments?
919 
920  // Verbose codegen?
921  bool verbose;
922 
923  // Verbose runtime?
925 
926  // Are we generating C++?
927  bool cpp;
928 
929  // Should we generate a main (allowing evaluation from command line)
930  bool main;
931 
932  // Should we include mayth library?
934 
935  // Do we want to be lean on stack usage?
937 
938  std::string infinity, nan, real_min;
939 
947 
948  // Have a flag for exporting/importing symbols
949  bool with_export, with_import;
950 
951  // Maximum number of declarations per line
953 
954  // Maximum number of initializer elements per line
956 
957  // Force the external API to use canonical sparsity
959 
960  // Prefix symbols in DLLs?
961  std::string dll_export, dll_import;
962 
963  // Prefix
964  std::string prefix;
965 
966  // std::stringstreams holding the different parts of the file being generated
967  std::stringstream includes;
968  std::stringstream auxiliaries;
969  std::stringstream body;
970  std::stringstream header;
971  std::stringstream buffer;
972 
973  // Are we at a new line?
974  bool newline_;
975 
976  // Indentation
977  casadi_int indent_;
978  casadi_int current_indent_;
979 
980  // Number of zeros/ones
981  casadi_int sz_zeros_;
982  casadi_int sz_ones_;
983 
984  casadi_int padding_length_;
985 
986  // Names of exposed functions
987  std::vector<std::string> exposed_fname;
988 
989  // Code generated sparsities
990  std::set<std::string> sparsity_meta;
991 
992  // Set of already included header files
993  std::set<std::string> added_includes_;
994  std::set<std::string> added_externals_;
995  std::set<std::string> added_shorthands_;
996  std::multimap<Auxiliary, std::vector<std::string>> added_auxiliaries_;
997  std::multimap<size_t, size_t> added_double_constants_;
998  std::multimap<size_t, size_t> added_integer_constants_;
999  std::multimap<size_t, size_t> added_char_constants_;
1000  std::multimap<size_t, size_t> added_string_constants_;
1001  std::map<std::string, std::pair<std::string, std::string> > local_variables_;
1002  std::map<std::string, std::string> local_default_;
1003  std::map<const void *, casadi_int> file_scope_double_;
1004  std::map<const void *, casadi_int> file_scope_integer_;
1005  std::vector< std::vector<double> > pool_double_defaults_;
1006  std::map<std::string, casadi_int> pool_double_;
1007 
1008  // Added functions
1009  struct FunctionMeta {
1010  // The function object
1012  // Name in codegen
1013  std::string codegen_name;
1014  };
1015  std::vector<FunctionMeta> added_functions_;
1016 
1017  // Counters for creating unique identifiers
1018  std::map<std::string, std::map<FunctionInternal*, casadi_int> > added_wrappers_;
1019 
1020  // Constants
1021  std::vector<std::vector<double> > double_constants_;
1022  std::vector<std::vector<casadi_int> > integer_constants_;
1023  std::vector<std::vector<char> > char_constants_;
1024  std::vector<std::vector<std::string> > string_constants_;
1025 
1026  // Does any function need thread-local memory?
1028 
1029  // Hash a vector
1030  static size_t hash(const std::vector<double>& v);
1031  static size_t hash(const std::vector<casadi_int>& v);
1032  static size_t hash(const std::vector<char>& v);
1033  static size_t hash(const std::vector<std::string>& v);
1034 
1035  std::string wrapper(const Function& base, const std::string& name);
1036 
1037  // Compare two vectors
1038  template<typename T>
1039  static bool equal(const std::vector<T>& v1, const std::vector<T>& v2) {
1040  if (v1.size()!=v2.size()) return false;
1041  for (casadi_int j=0; j<v1.size(); ++j) {
1042  if (v1[j]!=v2[j]) return false;
1043  }
1044  return true;
1045  }
1047 #endif // SWIG
1048  };
1049 
1050 
1051 } // namespace casadi
1052 
1053 #endif // CASADI_CODE_GENERATOR_HPP
Helper class for C code generation.
bool codegen_scalars
Codegen scalar.
std::string constant(const std::vector< int > &v)
Represent an array constant; adding it when new.
std::stringstream includes
std::set< std::string > added_externals_
std::vector< std::string > added_sfunctions
std::map< std::string, casadi_int > pool_double_
std::set< std::string > added_includes_
std::multimap< Auxiliary, std::vector< std::string > > added_auxiliaries_
std::map< std::string, std::pair< std::string, std::string > > local_variables_
void indent()
Increase indentation.
std::map< std::string, std::string > local_default_
std::vector< std::vector< char > > char_constants_
std::vector< std::vector< double > > pool_double_defaults_
std::stringstream buffer
std::multimap< size_t, size_t > added_double_constants_
casadi_int max_initializer_elements_per_line
std::stringstream header
void unindent()
Decrease indentation.
std::vector< std::vector< double > > double_constants_
std::vector< std::vector< casadi_int > > integer_constants_
std::multimap< size_t, size_t > added_char_constants_
std::vector< std::vector< std::string > > string_constants_
std::map< const void *, casadi_int > file_scope_integer_
casadi_int max_declarations_per_line
std::vector< FunctionMeta > added_functions_
Auxiliary
Auxiliary functions.
std::map< std::string, std::map< FunctionInternal *, casadi_int > > added_wrappers_
std::stringstream body
CodeGenerator & operator<<(T s)
Print an arbitrary type to buffer.
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 initializer(const std::vector< T > &v)
Print an initializer.
bool avoid_stack() const
Avoid stack?
std::set< std::string > sparsity_meta
std::vector< std::string > exposed_fname
std::set< std::string > added_shorthands_
static bool equal(const std::vector< T > &v1, const std::vector< T > &v2)
std::stringstream auxiliaries
Function object.
Definition: function.hpp:60
General sparsity class.
Definition: sparsity.hpp:106
The casadi namespace.
Definition: archiver.cpp:28
T norm_1(const std::vector< T > &x)
T norm_inf(const std::vector< T > &x)
std::ostream & operator<<(std::ostream &stream, const XmlNode &node)
Definition: xml_node.cpp:79
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
void copy(const T1 *x, casadi_int n, T2 *y)
T dot(const std::vector< T > &a, const std::vector< T > &b)
const double nan
Not a number.
Definition: calculus.hpp:53
T norm_2(const std::vector< T > &x)