26 #include "casadi_call.hpp"
27 #include "function_internal.hpp"
28 #include "casadi_misc.hpp"
29 #include "serializing_stream.hpp"
31 #define CASADI_THROW_ERROR(FNAME, WHAT) \
32 throw CasadiException("Error in Call::" FNAME " for '" + fcn_.name() + "' "\
33 "[" + fcn_.class_name() + "] at " + CASADI_WHERE + ":\n" + std::string(WHAT));
40 return project(x, sp);
54 casadi_error(
"Cannot create function call node: Dimension mismatch for argument "
55 +
str(i) +
". Argument has shape " +
str(x.
size())
56 +
" but function input has shape " +
str(sp.
size()));
62 MX this_ = shared_from_this<MX>();
66 if (!
cache_.incache(oind, ret)) {
68 cache_.tocache_if_missing(oind, ret);
76 casadi_int num_in = fcn.
n_in();
77 casadi_assert(arg.size()==num_in,
"Argument list length (" +
str(arg.size())
78 +
") does not match number of inputs (" +
str(num_in)
79 +
") for function " + fcn.
name());
82 std::vector<MX> arg1(num_in);
83 for (casadi_int i=0; i<num_in; ++i) {
90 std::string
Call::disp(
const std::vector<std::string>& arg)
const {
93 for (casadi_int i=0; i<
n_dep(); ++i) {
101 int Call::eval(
const double** arg,
double** res, casadi_int* iw,
double* w)
const {
102 return fcn_(arg, res, iw, w);
114 return fcn_(arg, res, iw, w);
117 void Call::eval_mx(
const std::vector<MX>& arg, std::vector<MX>& res)
const {
122 std::vector<std::vector<MX>>& fsens)
const {
125 std::vector<MX> arg(
n_dep());
126 for (casadi_int i=0; i<arg.size(); ++i) arg[i] =
dep(i);
127 std::vector<MX> res(
nout());
128 for (casadi_int i=0; i<res.size(); ++i) res[i] =
get_output(i);
132 }
catch (std::exception& e) {
133 CASADI_THROW_ERROR(
"ad_forward", e.what());
138 std::vector<std::vector<MX>>& asens)
const {
143 std::vector<MX> arg(
n_dep());
144 for (casadi_int i=0; i<arg.size(); ++i) arg[i] =
dep(i);
145 std::vector<MX> res(
nout());
146 for (casadi_int i=0; i<res.size(); ++i) res[i] =
get_output(i);
148 std::vector<std::vector<MX>> v;
150 for (casadi_int i=0; i<v.size(); ++i) {
151 for (casadi_int j=0; j<v[i].size(); ++j) {
153 if (v[i][j].is_empty())
continue;
157 asens[i][j] += v[i][j];
160 }
catch (std::exception& e) {
161 CASADI_THROW_ERROR(
"ad_reverse", e.what());
166 return fcn_(arg, res, iw, w);
170 return fcn_.
rev(arg, res, iw, w);
182 const std::vector<casadi_int>& arg,
183 const std::vector<casadi_int>& res,
184 const std::vector<bool>& arg_is_ref,
185 std::vector<bool>& res_is_ref)
const {
187 g.
local(
"arg1",
"const casadi_real",
"**");
188 for (casadi_int i=0; i<arg.size(); ++i) {
189 g <<
"arg1[" << i <<
"]=" << g.
work(arg[i],
fcn_.
nnz_in(i), arg_is_ref[i]) <<
";\n";
193 g.
local(
"res1",
"casadi_real",
"**");
194 for (casadi_int i=0; i<res.size(); ++i) {
195 g <<
"res1[" << i <<
"]=" << g.
work(res[i],
fcn_.
nnz_out(i),
false) <<
";\n";
199 std::string flag = g(
fcn_,
"arg1",
"res1",
"iw",
"w");
200 g <<
"if (" << flag <<
") return 1;\n";
205 auto i = added.insert(
fcn_.
get());
214 auto i = added.insert(
fcn_.
get());
257 for (
const std::vector<MX>& seed_dir : seed) {
258 for (
const MX& s : seed_dir) {
260 if (s.is_zero())
continue;
void codegen_incref(CodeGenerator &g, std::set< void * > &added) const override
Codegen incref.
static std::vector< MX > create(const Function &fcn, const std::vector< MX > &arg)
Create function call node.
Call(const Function &fcn, const std::vector< MX > &arg)
Constructor (should not be used directly)
WeakCache< casadi_int, MX > cache_
Output node cache.
int sp_reverse(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const override
Propagate sparsity backwards.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
size_t sz_w() const override
Get required length of w field.
MX get_output(casadi_int oind) const override
Get an output.
int eval(const double **arg, double **res, casadi_int *iw, double *w) const override
Evaluate the function numerically.
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.
void codegen_decref(CodeGenerator &g, std::set< void * > &added) const override
Codegen decref.
bool has_refcount() const override
Is reference counting needed in codegen?
size_t sz_res() const override
Get required length of res field.
static MX create_call(const Function &fcn, const std::vector< MX > &arg)
Create function call node.
void ad_forward(const std::vector< std::vector< MX > > &fseed, std::vector< std::vector< MX > > &fsens) const override
Calculate forward mode directional derivatives.
size_t sz_iw() const override
Get required length of iw field.
int sp_forward(const bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const override
Propagate sparsity forward.
size_t sz_arg() const override
Get required length of arg field.
void eval_mx(const std::vector< MX > &arg, std::vector< MX > &res) const override
Evaluate symbolically (MX)
casadi_int nout() const override
Number of outputs.
void add_dependency(CodeGenerator &g) const override
Add a dependent function.
void ad_reverse(const std::vector< std::vector< MX > > &aseed, std::vector< std::vector< MX > > &asens) const override
Calculate reverse mode directional derivatives.
static MX projectArg(const MX &x, const Sparsity &sp, casadi_int i)
Project a function input to a particular sparsity.
std::string disp(const std::vector< std::string > &arg) const override
Print expression.
static MX common_cond(const std::vector< std::vector< MX >> &seed)
Find a common conditional argument for all seeds.
int eval_sx(const SXElem **arg, SXElem **res, casadi_int *iw, SXElem *w) const override
Evaluate the function symbolically (SX)
Helper class for C code generation.
std::string add_dependency(const Function &f)
Add a function dependency.
std::string work(casadi_int n, casadi_int sz, bool is_ref) const
void local(const std::string &name, const std::string &type, const std::string &ref="")
Declare a local variable.
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
bool has_refcount_
Reference counting in codegen?
virtual void call_forward(const std::vector< MX > &arg, const std::vector< MX > &res, const std::vector< std::vector< MX > > &fseed, std::vector< std::vector< MX > > &fsens, bool always_inline, bool never_inline) const
Forward mode AD, virtual functions overloaded in derived classes.
virtual void call_reverse(const std::vector< MX > &arg, const std::vector< MX > &res, const std::vector< std::vector< MX > > &aseed, std::vector< std::vector< MX > > &asens, bool always_inline, bool never_inline) const
Reverse mode, virtual functions overloaded in derived classes.
virtual std::string codegen_name(const CodeGenerator &g, bool ns=true) const
Get name in codegen.
casadi_int nnz_out() const
Get number of output nonzeros.
size_t sz_res() const
Get required length of res field.
const Sparsity & sparsity_out(casadi_int ind) const
Get sparsity of a given output.
FunctionInternal * get() const
const std::string & name() const
Name of the function.
int rev(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, int mem=0) const
Propagate sparsity backward.
const Sparsity & sparsity_in(casadi_int ind) const
Get sparsity of a given input.
size_t sz_iw() const
Get required length of iw field.
casadi_int n_out() const
Get the number of function outputs.
casadi_int n_in() const
Get the number of function inputs.
size_t sz_w() const
Get required length of w field.
size_t sz_arg() const
Get required length of arg field.
casadi_int nnz_in() const
Get number of input nonzeros.
bool is_empty(bool both=false) const
Check if the sparsity is empty, i.e. if one of the dimensions is zero.
std::pair< casadi_int, casadi_int > size() const
Get the shape.
casadi_int size2() const
Get the second dimension (i.e. number of columns)
casadi_int size1() const
Get the first dimension (i.e. number of rows)
static MX zeros(casadi_int nrow=1, casadi_int ncol=1)
Create a dense matrix or a matrix with specified sparsity with all entries zero.
bool is_scalar(bool scalar_and_dense=false) const
Check if the matrix expression is scalar.
const Sparsity & sparsity() const
Get the sparsity.
const MX & dep(casadi_int ind=0) const
dependencies - functions that have to be evaluated before this one
casadi_int n_dep() const
Number of dependencies.
virtual void serialize_body(SerializingStream &s) const
Serialize an object without type information.
void set_sparsity(const Sparsity &sparsity)
Set the sparsity.
void set_dep(const MX &dep)
Set unary dependency.
static MX create(MXNode *node)
Create from node.
static bool is_equal(const MX &x, const MX &y, casadi_int depth=0)
MX T() const
Transpose the matrix.
static std::vector< MX > createMultipleOutput(MXNode *node)
Create from node (multiple-outputs)
MX dep(casadi_int ch=0) const
Get the nth dependency as MX.
The basic scalar symbolic class of CasADi.
Helper class for Serialization.
void pack(const Sparsity &e)
Serializes an object to the output stream.
bool is_vector() const
Check if the pattern is a row or column vector.
casadi_int size1() const
Get the number of rows.
casadi_int nnz() const
Get the number of (structural) non-zeros.
casadi_int size2() const
Get the number of columns.
std::pair< casadi_int, casadi_int > size() const
Get the shape.
static Sparsity scalar(bool dense_scalar=true)
Create a scalar sparsity pattern *.
bool is_empty(bool both=false) const
Check if the sparsity is empty.
unsigned long long bvec_t
double if_else(double x, double y, double z)
std::string str(const T &v)
String representation, any type.