27 #include "serializing_stream.hpp"
33 const std::vector<bool>& reduce_in,
34 const std::vector<bool>& reduce_out,
37 reduce_in, std::vector<bool>(f.
n_out(),
false));
38 casadi_assert(reduce_in.size()==f.
n_in(),
"Dimension mismatch");
39 casadi_assert(reduce_out.size()==f.
n_out(),
"Dimension mismatch");
42 std::string suffix =
str(reduce_in)+
str(reduce_out);
44 if (!f->
incache(name, ret, suffix)) {
47 casadi_assert_dev(ret.
name()==name);
58 const std::vector<bool>& reduce_in,
59 const std::vector<bool>& reduce_out)
60 :
FunctionInternal(name), f_(f), n_(n), reduce_in_(reduce_in), reduce_out_(reduce_out) {
61 casadi_assert_dev(reduce_in.size()==f.
n_in());
62 casadi_assert_dev(reduce_out.size()==f.
n_out());
91 casadi_error(
"class name '" +
class_name +
"' unknown.");
105 "No function \"" + name +
"\" in " +
name_ +
". " +
111 casadi_int max_depth)
const {
135 for (casadi_int j=0;j<
n_out_;++j) {
140 template<
typename T1>
143 if (!x || !y)
return;
144 for (i=0; i<n; ++i) *y++ += *x++;
150 if (!x || !y)
return;
151 for (i=0; i<n; ++i) *y++ |= *x++;
156 const T** arg1 = arg+
n_in_;
157 std::copy_n(arg,
n_in_, arg1);
161 for (casadi_int j=0;j<
n_out_;++j) {
170 for (casadi_int i=0; i<
n_; ++i) {
171 if (
f_(arg1, res1, iw, w, mem))
return 1;
172 for (casadi_int j=0; j<
n_in_; ++j) {
175 for (casadi_int j=0; j<
n_out_; ++j) {
189 casadi_int* iw,
SXElem* w,
void* mem,
190 bool always_inline,
bool never_inline)
const {
195 casadi_int* iw,
bvec_t* w,
void* mem)
const {
207 for (casadi_int j=0;j<
n_out_;++j) {
214 std::copy_n(arg,
n_in_, arg1);
216 std::copy_n(res,
n_out_, res1);
217 for (casadi_int i=0; i<
n_; ++i) {
219 w_scratch = w +
f_.
sz_w();
220 for (casadi_int j=0;j<
n_out_;++j) {
226 if (
f_.
rev(arg1, res1, iw, w))
return 1;
227 for (casadi_int j=0; j<
n_in_; ++j) {
230 for (casadi_int j=0; j<
n_out_; ++j) {
243 g.
local(
"i",
"casadi_int");
244 g.
local(
"arg1",
"const casadi_real*",
"*");
245 g.
local(
"res1",
"casadi_real*",
"*");
246 g.
local(
"w_scratch",
"casadi_real*",
"*");
248 g <<
"arg1 = arg+" <<
n_in_ <<
";\n"
249 <<
"for (i=0; i<" <<
n_in_ <<
"; ++i) arg1[i]=arg[i];\n";
251 g <<
"res1 = res+" <<
n_out_ <<
";\n";
252 g <<
"w_scratch = w+" <<
f_.
sz_w() <<
";\n";
253 for (casadi_int j=0;j<
n_out_;++j) {
255 g <<
"if (res[" << j <<
"]) {\n";
256 g <<
"casadi_clear(res[" << j <<
"], " <<
f_.
nnz_out(j) <<
");\n";
257 g <<
"res1[" << j <<
"] = w_scratch;\n";
258 g <<
"w_scratch+=" <<
f_.
nnz_out(j) <<
";\n";
260 g <<
"res1[" << j <<
"] = res[" << j <<
"];\n";
263 g <<
"res1[" << j <<
"] = res[" << j <<
"];\n";
267 g <<
"for (i=0; i<" <<
n_ <<
"; ++i) {\n";
269 g <<
"if (" << g(
f_,
"arg1",
"res1",
"iw",
"w") <<
") return 1;\n";
271 for (casadi_int j=0; j<
n_in_; ++j) {
273 g <<
"if (arg1[" << j <<
"]) arg1[" << j <<
"]+=" <<
f_.
nnz_in(j) <<
";\n";
277 for (casadi_int j=0; j<
n_out_; ++j) {
279 g <<
"if (res1[" << j <<
"]) ";
283 g <<
"if (res1[" << j <<
"]) ";
284 g <<
"res1[" << j <<
"]+=" <<
f_.
nnz_out(j) <<
";\n";
293 const std::vector<std::string>& inames,
294 const std::vector<std::string>& onames,
295 const Dict& opts)
const {
299 for (casadi_int i=0;i<n_out_;++i) {
300 if (reduce_out_[i]) casadi_assert(df.
nnz_in(n_in_+i)==0,
"Case not implemented");
303 std::vector<bool> reduce_in =
join(reduce_in_, reduce_out_, reduce_in_);
305 df, n_, reduce_in, reduce_out_);
308 std::vector<MX> arg = dm.
mx_in();
311 std::vector<MX> res = arg;
312 std::vector<MX>::iterator it=res.begin()+n_in_+n_out_;
313 std::vector<casadi_int> ind;
314 for (casadi_int i=0; i<n_in_; ++i, ++it) {
315 if (reduce_in_[i])
continue;
316 casadi_int sz = f_.size2_in(i);
318 for (casadi_int k=0; k<n_; ++k) {
319 for (casadi_int d=0; d<nfwd; ++d) {
320 for (casadi_int j=0; j<sz; ++j) {
321 ind.push_back((d*n_ + k)*sz + j);
325 *it = (*it)(
Slice(), ind);
333 for (casadi_int i=0; i<n_out_; ++i, ++it) {
334 if (reduce_out_[i])
continue;
335 casadi_int sz = f_.size2_out(i);
337 for (casadi_int d=0; d<nfwd; ++d) {
338 for (casadi_int k=0; k<n_; ++k) {
339 for (casadi_int j=0; j<sz; ++j) {
340 ind.push_back((k*nfwd + d)*sz + j);
344 *it = (*it)(
Slice(), ind);
348 Dict custom_opts = opts;
349 custom_opts[
"always_inline"] =
true;
350 custom_opts[
"allow_duplicate_io_names"] =
true;
351 return Function(name, arg, res, inames, onames, custom_opts);
356 const std::vector<std::string>& inames,
357 const std::vector<std::string>& onames,
358 const Dict& opts)
const {
362 for (casadi_int i=0;i<n_out_;++i) {
363 if (reduce_out_[i]) casadi_assert(df.
nnz_in(n_in_+i)==0,
"Case not implemented");
366 std::vector<bool> reduce_in =
join(reduce_in_, reduce_out_, reduce_out_);
368 df, n_, reduce_in, reduce_in_);
371 std::vector<MX> arg = dm.
mx_in();
374 std::vector<MX> res = arg;
375 std::vector<MX>::iterator it=res.begin()+n_in_+n_out_;
376 std::vector<casadi_int> ind;
377 for (casadi_int i=0; i<n_out_; ++i, ++it) {
378 if (reduce_out_[i])
continue;
379 casadi_int sz = f_.size2_out(i);
381 for (casadi_int k=0; k<n_; ++k) {
382 for (casadi_int d=0; d<nadj; ++d) {
383 for (casadi_int j=0; j<sz; ++j) {
384 ind.push_back((d*n_ + k)*sz + j);
388 *it = (*it)(
Slice(), ind);
396 for (casadi_int i=0; i<n_in_; ++i, ++it) {
397 if (reduce_in_[i])
continue;
398 casadi_int sz = f_.size2_in(i);
400 for (casadi_int d=0; d<nadj; ++d) {
401 for (casadi_int k=0; k<n_; ++k) {
402 for (casadi_int j=0; j<sz; ++j) {
403 ind.push_back((k*nadj + d)*sz + j);
407 *it = (*it)(
Slice(), ind);
411 Dict custom_opts = opts;
412 custom_opts[
"always_inline"] =
true;
413 custom_opts[
"allow_duplicate_io_names"] =
true;
414 return Function(name, arg, res, inames, onames, custom_opts);
417 int MapSum::eval(
const double** arg,
double** res, casadi_int* iw,
double* w,
void* mem)
const {
421 setup(mem, arg, res, iw, w);
423 return eval_gen(arg, res, iw, w, m);
Helper class for C code generation.
std::string axpy(casadi_int n, const std::string &a, const std::string &x, const std::string &y)
Codegen axpy: y += a*x.
std::string add_dependency(const Function &f)
Add a function dependency.
void local(const std::string &name, const std::string &type, const std::string &ref="")
Declare a local variable.
void add_auxiliary(Auxiliary f, const std::vector< std::string > &inst={"casadi_real"})
Add a built-in auxiliary function.
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
Internal class for Function.
void alloc_iw(size_t sz_iw, bool persistent=false)
Ensure required length of iw field.
void init(const Dict &opts) override
Initialize.
void tocache_if_missing(Function &f, const std::string &suffix="") const
Save function to cache, only if missing.
std::vector< bool > is_diff_out_
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
void alloc_res(size_t sz_res, bool persistent=false)
Ensure required length of res field.
void alloc_arg(size_t sz_arg, bool persistent=false)
Ensure required length of arg field.
void add_embedded(std::map< FunctionInternal *, std::pair< Function, size_t > > &all_fun, const Function &dep, casadi_int max_depth) const
virtual void find(std::map< FunctionInternal *, std::pair< Function, size_t > > &all_fun, casadi_int max_depth) const
bool incache(const std::string &fname, Function &f, const std::string &suffix="") const
Get function in cache.
size_t n_in_
Number of inputs and outputs.
void serialize_type(SerializingStream &s) const override
Serialize type information.
void alloc_w(size_t sz_w, bool persistent=false)
Ensure required length of w field.
void setup(void *mem, const double **arg, double **res, casadi_int *iw, double *w) const
Set the (persistent and temporary) work vectors.
std::vector< bool > is_diff_in_
Are inputs and outputs differentiable?
Function forward(casadi_int nfwd) const
Get a function that calculates nfwd forward derivatives.
casadi_int nnz_out() const
Get number of output nonzeros.
size_t sz_res() const
Get required length of res field.
const MX mx_in(casadi_int ind) const
Get symbolic primitives equivalent to the input expressions.
const std::string & name() const
Name of the function.
Function reverse(casadi_int nadj) const
Get a function that calculates nadj adjoint derivatives.
static Function create(FunctionInternal *node)
Create from node.
bool is_diff_out(casadi_int ind) const
Get differentiability of inputs/output.
int rev(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, int mem=0) const
Propagate sparsity backward.
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.
bool is_diff_in(casadi_int ind) const
Get differentiability of inputs/output.
size_t sz_w() const
Get required length of w field.
size_t sz_arg() const
Get required length of arg field.
Function wrap_as_needed(const Dict &opts) const
Wrap in a Function with options.
casadi_int nnz_in() const
Get number of input nonzeros.
MapSum(DeserializingStream &s)
Deserializing constructor.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
int eval_gen(const T **arg, T **res, casadi_int *iw, T *w, int mem=0) const
Evaluate or propagate sparsities.
int sp_reverse(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, void *mem) const override
Propagate sparsity backwards.
~MapSum() override
Destructor.
void serialize_type(SerializingStream &s) const override
Serialize type information.
int sp_forward(const bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, void *mem) const override
Propagate sparsity forward.
std::string class_name() const override
Get type name.
static Function create(const std::string &name, const std::string ¶llelization, const Function &f, casadi_int n, const std::vector< bool > &reduce_in, const std::vector< bool > &reduce_out, const Dict &opts=Dict())
void find(std::map< FunctionInternal *, std::pair< Function, size_t > > &all_fun, casadi_int max_depth) const override
virtual std::string parallelization() const
Type of parallellization.
void init(const Dict &opts) override
Initialize.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
std::vector< bool > reduce_in_
void codegen_declarations(CodeGenerator &g) const override
Generate code for the declarations of the C function.
virtual std::vector< std::string > get_function() const override
std::vector< bool > reduce_out_
int eval(const double **arg, double **res, casadi_int *iw, double *w, void *mem) const override
Evaluate the function numerically.
int eval_sx(const SXElem **arg, SXElem **res, casadi_int *iw, SXElem *w, void *mem, bool always_inline, bool never_inline) const override
evaluate symbolically while also propagating directional derivatives
void codegen_body(CodeGenerator &g) const override
Generate code for the body of the C function.
Function get_reverse(casadi_int nadj, const std::string &name, const std::vector< std::string > &inames, const std::vector< std::string > &onames, const Dict &opts) const override
Generate a function that calculates nadj adjoint derivatives.
bool has_function(const std::string &fname) const override
Function get_forward(casadi_int nfwd, const std::string &name, const std::vector< std::string > &inames, const std::vector< std::string > &onames, const Dict &opts) const override
Generate a function that calculates nfwd forward derivatives.
Base class for FunctionInternal and LinsolInternal.
void clear_mem()
Clear all memory (called from destructor)
The basic scalar symbolic class of CasADi.
Helper class for Serialization.
void pack(const Sparsity &e)
Serializes an object to the output stream.
Class representing a Slice.
std::string join(const std::vector< std::string > &l, const std::string &delim)
unsigned long long bvec_t
void casadi_copy(const T1 *x, casadi_int n, T1 *y)
COPY: y <-x.
std::string str(const T &v)
String representation, any type.
void casadi_add(casadi_int n, const T1 *x, T1 *y)
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
void casadi_clear(T1 *x, casadi_int n)
CLEAR: x <- 0.