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  std::string sparsity(const Sparsity& sp);
87 
88  // Add a sparsity pattern, get index
89  casadi_int add_sparsity(const Sparsity& sp);
90 
94  casadi_int get_sparsity(const Sparsity& sp) const;
95 
99  casadi_int get_constant(const std::vector<double>& v, bool allow_adding=false);
100 
104  casadi_int get_constant(const std::vector<casadi_int>& v, bool allow_adding=false);
105 
109  casadi_int get_constant(const std::vector<char>& v, bool allow_adding=false);
110 
114  casadi_int get_constant(const std::vector<std::string>& v, bool allow_adding=false);
115 
119  std::string constant(const std::vector<casadi_int>& v);
120 
124  std::string constant(const std::vector<int>& v) {
125  return constant(vector_static_cast<casadi_int>(v));
126  }
127 
131  void constant_copy(
132  const std::string& var_name,
133  const std::vector<casadi_int>& v,
134  const std::string& type="casadi_int");
135 
139  std::string constant(const std::vector<double>& v);
140 
144  std::string constant(const std::vector<char>& v);
145 
149  std::string constant(const std::vector<std::string>& v);
150 
154  void define_rom_double(const void* id, casadi_int size);
155 
159  std::string rom_double(const void* id) const;
160 
164  void define_rom_integer(const void* id, casadi_int size);
165 
169  void setup_callback(const std::string& s, const Function& f);
173  std::string rom_integer(const void* id) const;
174 
178  std::string operator()(const Function& f, const std::string& arg,
179  const std::string& res, const std::string& iw,
180  const std::string& w, const std::string& failure_ret="1");
181 
185  CodeGenerator& operator<<(const std::string& s);
186 
190  void print_formatted(const std::string& s);
191 
195  template<typename T>
196  CodeGenerator& operator<<(T s) {
197  std::stringstream ss;
198  ss << s;
199  return (*this) << ss.str();
200  }
201 
205  void flush(std::ostream &s);
206 
210  void local(const std::string& name, const std::string& type, const std::string& ref="");
211 
215  void scope_enter();
216 
220  void scope_exit();
221 
225  std::string sx_work(casadi_int i);
226 
230  void init_local(const std::string& name, const std::string& def);
231 
235  void indent() {current_indent_++;}
236 
240  void unindent() {current_indent_--;}
241 
245  bool avoid_stack() { return avoid_stack_;}
246 
250  std::string constant(double v);
251  std::string constant(casadi_int v);
252  std::string constant(const std::string& v);
253 
257  std::string initializer(const std::vector<double>& v);
258  std::string initializer(const std::vector<casadi_int>& v);
259  std::string initializer(const std::vector<char>& v);
260  std::string initializer(const std::vector<std::string>& v);
261 
265  std::string sanitize_source(const std::string& src,
266  const std::vector<std::string>& inst,
267  bool add_shorthand=true);
268 
272  std::string dot(casadi_int n, const std::string& x, const std::string& y);
273 
277  std::string mv(const std::string& x, const Sparsity& sp_x,
278  const std::string& y, const std::string& z, bool tr);
279 
283  std::string mv(const std::string& x, casadi_int nrow_x, casadi_int ncol_x,
284  const std::string& y, const std::string& z, bool tr);
285 
289  std::string axpy(casadi_int n, const std::string& a,
290  const std::string& x, const std::string& y);
291 
297  std::string clip_min(const std::string& x, casadi_int n,
298  const std::string& min, const std::string& mask);
299 
305  std::string clip_max(const std::string& x, casadi_int n,
306  const std::string& min, const std::string& mask);
307 
312  std::string vector_fmax(casadi_int n, const std::string& x,
313  const std::string& y, const std::string& z);
314 
319  std::string vector_fmin(casadi_int n, const std::string& x,
320  const std::string& y, const std::string& z);
321 
326  std::string masked_norm_inf(casadi_int n, const std::string& x,
327  const std::string& mask);
328 
329 
333  std::string scal(casadi_int n, const std::string& alpha, const std::string& x);
334 
338  std::string mtimes(const std::string& x, const Sparsity& sp_x,
339  const std::string& y, const Sparsity& sp_y,
340  const std::string& z, const Sparsity& sp_z,
341  const std::string& w, bool tr);
342 
346  std::string trilsolve(const Sparsity& sp_x, const std::string& x, const std::string& y,
347  bool tr, bool unity, casadi_int nrhs);
348 
352  std::string triusolve(const Sparsity& sp_x, const std::string& x, const std::string& y,
353  bool tr, bool unity, casadi_int nrhs);
354 
358  std::string bilin(const std::string& A, const Sparsity& sp_A,
359  const std::string& x, const std::string& y);
360 
364  std::string rank1(const std::string& A, const Sparsity& sp_A, const std::string& alpha,
365  const std::string& x, const std::string& y);
366 
368  std::string logsumexp(const std::string& A, casadi_int n);
369 
373  std::string interpn(const std::string& res, casadi_int ndim, const std::string& grid,
374  const std::string& offset,
375  const std::string& values, const std::string& x,
376  const std::string& lookup_mode, casadi_int m,
377  const std::string& iw, const std::string& w);
378 
382  std::string interpn_grad(const std::string& grad,
383  casadi_int ndim, const std::string& grid,
384  const std::string& offset,
385  const std::string& values, const std::string& x,
386  const std::string& lookup_mode, casadi_int m,
387  const std::string& iw, const std::string& w);
388 
392  std::string trans(const std::string& x, const Sparsity& sp_x,
393  const std::string& y, const Sparsity& sp_y, const std::string& iw);
394 
398  std::string qr(const std::string& sp, const std::string& A,
399  const std::string& w, const std::string& sp_v,
400  const std::string& v, const std::string& sp_r,
401  const std::string& r, const std::string& beta,
402  const std::string& prinv, const std::string& pc);
403 
407  std::string qr_solve(const std::string& x, casadi_int nrhs, bool tr,
408  const std::string& sp_v, const std::string& v,
409  const std::string& sp_r, const std::string& r,
410  const std::string& beta, const std::string& prinv,
411  const std::string& pc, const std::string& w);
412 
416  std::string lsqr_solve(const std::string& A, const std::string&x,
417  casadi_int nrhs, bool tr, const std::string& sp, const std::string& w);
418 
422  std::string ldl(const std::string& sp_a, const std::string& a,
423  const std::string& sp_lt, const std::string& lt,
424  const std::string& d, const std::string& p,
425  const std::string& w);
426 
430  std::string ldl_solve(const std::string& x, casadi_int nrhs,
431  const std::string& sp_lt, const std::string& lt,
432  const std::string& d, const std::string& p,
433  const std::string& w);
434 
438  std::string fmax(const std::string& x, const std::string& y);
439 
443  std::string fmin(const std::string& x, const std::string& y);
444 
448  std::string mmax(const std::string& x, casadi_int n, bool is_dense);
449 
453  std::string mmin(const std::string& x, casadi_int n, bool is_dense);
454 
458  std::string vfmax(const std::string& x, casadi_int n, const std::string& y);
459 
463  std::string vfmin(const std::string& x, casadi_int n, const std::string& y);
464 
468  std::string vfmax(const std::string& x, const std::string& n, const std::string& y);
469 
473  std::string vfmin(const std::string& x, const std::string& n, const std::string& y);
474 
478  std::string max(const std::string& x, const std::string& y);
479 
483  std::string min(const std::string& x, const std::string& y);
484 
488  std::string norm_inf(casadi_int n, const std::string& x);
489 
495  std::string norm_2(casadi_int n, const std::string& x);
496 
500  std::string max_viol(casadi_int n, const std::string& x,
501  const std::string& lb, const std::string& ub);
502 
506  std::string sum_viol(casadi_int n, const std::string& x,
507  const std::string& lb, const std::string& ub);
508 
512  std::string bound_consistency(casadi_int n, const std::string& x,
513  const std::string& lam, const std::string& lbx, const std::string& ubx);
514 
518  std::string lb_eig(const Sparsity& sp_h, const std::string& h);
519 
523  std::string regularize(const Sparsity& sp_h, const std::string& h, const std::string& reg);
524 
528  std::string convexify_eval(const ConvexifyData& d,
529  const std::string& Hin, const std::string& Hout, const std::string& iw, const std::string& w);
530 
534  std::string low(const std::string& x, const std::string& grid,
535  casadi_int ng, casadi_int lookup_mode);
536 
540  std::string declare(std::string s);
541 
545  void comment(const std::string& s);
546 
550  enum Auxiliary {
551  AUX_COPY,
552  AUX_CVX,
553  AUX_CONVEXIFY,
554  AUX_SWAP,
555  AUX_SCAL,
556  AUX_AXPY,
557  AUX_DOT,
558  AUX_BILIN,
559  AUX_RANK1,
560  AUX_NORM_1,
561  AUX_NORM_2,
562  AUX_CLIP_MAX,
563  AUX_CLIP_MIN,
564  AUX_VECTOR_FMAX,
565  AUX_VECTOR_FMIN,
566  AUX_NORM_INF,
567  AUX_MASKED_NORM_INF,
568  AUX_IAMAX,
569  AUX_CLEAR,
570  AUX_FILL,
571  AUX_MV,
572  AUX_MV_DENSE,
573  AUX_MTIMES,
574  AUX_TRILSOLVE,
575  AUX_TRIUSOLVE,
576  AUX_PROJECT,
577  AUX_TRI_PROJECT,
578  AUX_DENSIFY,
579  AUX_SPARSIFY,
580  AUX_TRANS,
581  AUX_TO_MEX,
582  AUX_FROM_MEX,
583  AUX_INTERPN,
584  AUX_INTERPN_GRAD,
585  AUX_FLIP,
586  AUX_INTERPN_WEIGHTS,
587  AUX_LOW,
588  AUX_INTERPN_INTERPOLATE,
589  AUX_DE_BOOR,
590  AUX_ND_BOOR_EVAL,
591  AUX_FINITE_DIFF,
592  AUX_QR,
593  AUX_QP,
594  AUX_QRQP,
595  AUX_NLP,
596  AUX_SQPMETHOD,
597  AUX_FEASIBLESQPMETHOD,
598  AUX_LDL,
599  AUX_NEWTON,
600  AUX_TO_DOUBLE,
601  AUX_TO_INT,
602  AUX_CAST,
603  AUX_SQ,
604  AUX_SIGN,
605  AUX_IF_ELSE,
606  AUX_PRINTF,
607  AUX_FMIN,
608  AUX_FMAX,
609  AUX_FABS,
610  AUX_MIN,
611  AUX_MAX,
612  AUX_VFMIN,
613  AUX_VFMAX,
614  AUX_MAX_VIOL,
615  AUX_SUM_VIOL,
616  AUX_SUM,
617  AUX_REGULARIZE,
618  AUX_INF,
619  AUX_NAN,
620  AUX_REAL_MIN,
621  AUX_ISINF,
622  AUX_BOUNDS_CONSISTENCY,
623  AUX_LSQR,
624  AUX_FILE_SLURP,
625  AUX_CACHE,
626  AUX_LOG1P,
627  AUX_EXPM1,
628  AUX_HYPOT,
629  AUX_MMIN,
630  AUX_MMAX,
631  AUX_LOGSUMEXP,
632  AUX_SPARSITY,
633  AUX_BFGS,
634  AUX_ORACLE_CALLBACK,
635  AUX_OCP_BLOCK,
636  AUX_ORACLE,
637  AUX_SCALED_COPY
638  };
639 
643  void add_auxiliary(Auxiliary f, const std::vector<std::string>& inst = {"casadi_real"});
644 
648  void add_io_sparsities(const std::string& name,
649  const std::vector<Sparsity>& sp_in,
650  const std::vector<Sparsity>& sp_out);
651 
653  std::string work(casadi_int n, casadi_int sz) const;
654 
656  std::string workel(casadi_int n) const;
657 
659  static std::string array(const std::string& type, const std::string& name, casadi_int len,
660  const std::string& def=std::string());
661 
665  void print_vector(std::ostream &s, const std::string& name,
666  const std::vector<casadi_int>& v);
667 
671  void print_vector(std::ostream &s, const std::string& name,
672  const std::vector<char>& v);
673 
677  void print_vector(std::ostream &s, const std::string& name,
678  const std::vector<double>& v);
679 
683  void print_vector(std::ostream &s, const std::string& name,
684  const std::vector<std::string>& v);
685 
689  std::string copy(const std::string& arg, std::size_t n, const std::string& res);
690  void copy_check(const std::string& arg, std::size_t n, const std::string& res,
691  bool check_lhs=true, bool check_rhs=true);
692  void copy_default(const std::string& arg, std::size_t n, const std::string& res,
693  const std::string& def, bool check_rhs=true);
694 
698  std::string fill(const std::string& res, std::size_t n, const std::string& v);
699 
703  std::string clear(const std::string& res, std::size_t n);
704 
708  std::string arg(casadi_int i) const;
709 
713  std::string res(casadi_int i) const;
714 
718  std::string mem(const Function& f);
719 
723  std::string project(const std::string& arg, const Sparsity& sp_arg,
724  const std::string& res, const Sparsity& sp_res,
725  const std::string& w);
726 
730  std::string tri_project(const std::string& arg, const Sparsity& sp_arg,
731  const std::string& res, bool lower);
732 
736  std::string densify(const std::string& arg, const Sparsity& sp_arg,
737  const std::string& res, bool tr=false);
738 
742  std::string sparsify(const std::string& arg, const std::string& res,
743  const Sparsity& sp_res, bool tr=false);
744 
748  std::string to_mex(const Sparsity& sp, const std::string& arg);
749 
753  std::string from_mex(std::string& arg,
754  const std::string& res, std::size_t res_off, const Sparsity& sp_res,
755  const std::string& w);
756 
760  static std::string fmu_helpers(const std::string& modelname);
761 
765  std::string printf(const std::string& str,
766  const std::vector<std::string>& arg=std::vector<std::string>());
767  std::string printf(const std::string& str, const std::string& arg1);
768  std::string printf(const std::string& str, const std::string& arg1, const std::string& arg2);
769  std::string printf(const std::string& str, const std::string& arg1, const std::string& arg2,
770  const std::string& arg3);
771 
775  std::string print_op(casadi_int op, const std::string& a0);
776  std::string print_op(casadi_int op, const std::string& a0, const std::string& a1);
777 
781  std::string file_slurp(const std::string& fname, casadi_int n, const std::string& a);
782 
786  std::string cache_check(const std::string& key, const std::string& cache,
787  const std::string& loc, casadi_int stride, casadi_int sz, casadi_int key_sz,
788  const std::string& val);
789 
791  static std::string casadi_version();
792 
794  static void file_open(std::ofstream& f, const std::string& name, bool cpp);
795 
797  static void file_close(std::ofstream& f, bool cpp);
798 
802  void sz_work(size_t& sz_arg, size_t& sz_res, size_t& sz_iw, size_t& sz_w) const;
803 
804  private:
805 
806  // Generate casadi_real definition
807  void generate_casadi_real(std::ostream &s) const;
808 
809  // Generate casadi_int definition
810  void generate_casadi_int(std::ostream &s) const;
811 
812  // Generate mex entry point
813  void generate_mex(std::ostream &s) const;
814 
815  // Generate function specific code for Simulink s-Function
816  std::string codegen_sfunction(const Function& f) const;
817 
818  // Export s-Function to file
819  void generate_sfunction(const std::string& name, const std::string& sfunction) const;
820 
821  // Generate main entry point
822  void generate_main(std::ostream &s) const;
823 
824  // Generate export symbol macros
825  void generate_export_symbol(std::ostream &s) const;
826 
827  // Generate import symbol macros
828  void generate_import_symbol(std::ostream &s) const;
829 
830  // private:
831  public:
833 
834  // Name of generated file
835  std::string name, suffix;
836 
837  // Real-type used for the codegen
838  std::string casadi_real_type;
839 
840  // Int-type used for the codegen
841  std::string casadi_int_type;
842 
843  // Should we create a memory entry point?
844  bool with_mem;
845 
846  // Generate header file?
847  bool with_header;
848 
849  // Are we creating a MEX file?
850  bool mex;
851 
852  // Are we creating a s-function?
853  bool with_sfunction;
854  std::vector<std::string> added_sfunctions;
855 
856  // Unroll arguments?
857  bool unroll_args;
858 
859  // Verbose codegen?
860  bool verbose;
861 
862  // Verbose runtime?
863  bool verbose_runtime;
864 
865  // Are we generating C++?
866  bool cpp;
867 
868  // Should we generate a main (allowing evaluation from command line)
869  bool main;
870 
871  // Should we include mayth library?
872  bool include_math;
873 
874  // Do we want to be lean on stack usage?
875  bool avoid_stack_;
876 
877  std::string infinity, nan, real_min;
878 
885  bool codegen_scalars;
886 
887  // Have a flag for exporting/importing symbols
888  bool with_export, with_import;
889 
890  // Prefix symbols in DLLs?
891  std::string dll_export, dll_import;
892 
893  // Prefix
894  std::string prefix;
895 
896  // std::stringstreams holding the different parts of the file being generated
897  std::stringstream includes;
898  std::stringstream auxiliaries;
899  std::stringstream body;
900  std::stringstream header;
901  std::stringstream buffer;
902 
903  // Are we at a new line?
904  bool newline_;
905 
906  // Indentation
907  casadi_int indent_;
908  casadi_int current_indent_;
909 
910  // Names of exposed functions
911  std::vector<std::string> exposed_fname;
912 
913  // Code generated sparsities
914  std::set<std::string> sparsity_meta;
915 
916  // Set of already included header files
917  std::set<std::string> added_includes_;
918  std::set<std::string> added_externals_;
919  std::set<std::string> added_shorthands_;
920  std::multimap<Auxiliary, std::vector<std::string>> added_auxiliaries_;
921  std::multimap<size_t, size_t> added_double_constants_;
922  std::multimap<size_t, size_t> added_integer_constants_;
923  std::multimap<size_t, size_t> added_char_constants_;
924  std::multimap<size_t, size_t> added_string_constants_;
925  std::map<std::string, std::pair<std::string, std::string> > local_variables_;
926  std::map<std::string, std::string> local_default_;
927  std::map<const void *, casadi_int> file_scope_double_;
928  std::map<const void *, casadi_int> file_scope_integer_;
929 
930  // Added functions
931  struct FunctionMeta {
932  // The function object
933  Function f;
934  // Name in codegen
935  std::string codegen_name;
936  };
937  std::vector<FunctionMeta> added_functions_;
938 
939  // Counters for creating unique identifiers
940  std::map<std::string, std::map<FunctionInternal*, casadi_int> > added_wrappers_;
941 
942  // Constants
943  std::vector<std::vector<double> > double_constants_;
944  std::vector<std::vector<casadi_int> > integer_constants_;
945  std::vector<std::vector<char> > char_constants_;
946  std::vector<std::vector<std::string> > string_constants_;
947 
948  // Does any function need thread-local memory?
949  bool needs_mem_;
950 
951  // Hash a vector
952  static size_t hash(const std::vector<double>& v);
953  static size_t hash(const std::vector<casadi_int>& v);
954  static size_t hash(const std::vector<char>& v);
955  static size_t hash(const std::vector<std::string>& v);
956 
957  std::string wrapper(const Function& base, const std::string& name);
958 
959  // Compare two vectors
960  template<typename T>
961  static bool equal(const std::vector<T>& v1, const std::vector<T>& v2) {
962  if (v1.size()!=v2.size()) return false;
963  for (casadi_int j=0; j<v1.size(); ++j) {
964  if (v1[j]!=v2[j]) return false;
965  }
966  return true;
967  }
969 #endif // SWIG
970  };
971 
972 
973 } // namespace casadi
974 
975 #endif // CASADI_CODE_GENERATOR_HPP
Helper class for C code generation.
std::string dump()
Generate a file, return code as string.
void add(const Function &f, bool with_jac_sparsity=false)
Add a function (name generated)
CodeGenerator(const std::string &name, const Dict &opts=Dict())
Constructor.
std::string generate(const std::string &prefix="")
Generate file(s)
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 <....
Function object.
Definition: function.hpp:60
General sparsity class.
Definition: sparsity.hpp:99
The casadi namespace.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.