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_ +
". " +
128 for (casadi_int j=0;j<
n_out_;++j) {
133 template<
typename T1>
136 if (!x || !y)
return;
137 for (i=0; i<n; ++i) *y++ += *x++;
143 if (!x || !y)
return;
144 for (i=0; i<n; ++i) *y++ |= *x++;
149 const T** arg1 = arg+
n_in_;
150 std::copy_n(arg,
n_in_, arg1);
154 for (casadi_int j=0;j<
n_out_;++j) {
163 for (casadi_int i=0; i<
n_; ++i) {
164 if (
f_(arg1, res1, iw, w, mem))
return 1;
165 for (casadi_int j=0; j<
n_in_; ++j) {
168 for (casadi_int j=0; j<
n_out_; ++j) {
182 casadi_int* iw,
SXElem* w,
void* mem,
183 bool always_inline,
bool never_inline)
const {
188 casadi_int* iw,
bvec_t* w,
void* mem)
const {
200 for (casadi_int j=0;j<
n_out_;++j) {
207 std::copy_n(arg,
n_in_, arg1);
209 std::copy_n(res,
n_out_, res1);
210 for (casadi_int i=0; i<
n_; ++i) {
212 w_scratch = w +
f_.
sz_w();
213 for (casadi_int j=0;j<
n_out_;++j) {
219 if (
f_.
rev(arg1, res1, iw, w))
return 1;
220 for (casadi_int j=0; j<
n_in_; ++j) {
223 for (casadi_int j=0; j<
n_out_; ++j) {
236 g.
local(
"i",
"casadi_int");
237 g.
local(
"arg1",
"const casadi_real*",
"*");
238 g.
local(
"res1",
"casadi_real*",
"*");
239 g.
local(
"w_scratch",
"casadi_real*",
"*");
241 g <<
"arg1 = arg+" <<
n_in_ <<
";\n"
242 <<
"for (i=0; i<" <<
n_in_ <<
"; ++i) arg1[i]=arg[i];\n";
244 g <<
"res1 = res+" <<
n_out_ <<
";\n";
245 g <<
"w_scratch = w+" <<
f_.
sz_w() <<
";\n";
246 for (casadi_int j=0;j<
n_out_;++j) {
248 g <<
"if (res[" << j <<
"]) {\n";
249 g <<
"casadi_clear(res[" << j <<
"], " <<
f_.
nnz_out(j) <<
");\n";
250 g <<
"res1[" << j <<
"] = w_scratch;\n";
251 g <<
"w_scratch+=" <<
f_.
nnz_out(j) <<
";\n";
253 g <<
"res1[" << j <<
"] = res[" << j <<
"];\n";
256 g <<
"res1[" << j <<
"] = res[" << j <<
"];\n";
260 g <<
"for (i=0; i<" <<
n_ <<
"; ++i) {\n";
262 g <<
"if (" << g(
f_,
"arg1",
"res1",
"iw",
"w") <<
") return 1;\n";
264 for (casadi_int j=0; j<
n_in_; ++j) {
266 g <<
"if (arg1[" << j <<
"]) arg1[" << j <<
"]+=" <<
f_.
nnz_in(j) <<
";\n";
270 for (casadi_int j=0; j<
n_out_; ++j) {
272 g <<
"if (res1[" << j <<
"]) ";
276 g <<
"if (res1[" << j <<
"]) ";
277 g <<
"res1[" << j <<
"]+=" <<
f_.
nnz_out(j) <<
";\n";
286 const std::vector<std::string>& inames,
287 const std::vector<std::string>& onames,
288 const Dict& opts)
const {
292 for (casadi_int i=0;i<n_out_;++i) {
293 if (reduce_out_[i]) casadi_assert(df.
nnz_in(n_in_+i)==0,
"Case not implemented");
296 std::vector<bool> reduce_in =
join(reduce_in_, reduce_out_, reduce_in_);
298 df, n_, reduce_in, reduce_out_);
301 std::vector<MX> arg = dm.
mx_in();
304 std::vector<MX> res = arg;
305 std::vector<MX>::iterator it=res.begin()+n_in_+n_out_;
306 std::vector<casadi_int> ind;
307 for (casadi_int i=0; i<n_in_; ++i, ++it) {
308 if (reduce_in_[i])
continue;
309 casadi_int sz = f_.size2_in(i);
311 for (casadi_int k=0; k<n_; ++k) {
312 for (casadi_int d=0; d<nfwd; ++d) {
313 for (casadi_int j=0; j<sz; ++j) {
314 ind.push_back((d*n_ + k)*sz + j);
318 *it = (*it)(
Slice(), ind);
326 for (casadi_int i=0; i<n_out_; ++i, ++it) {
327 if (reduce_out_[i])
continue;
328 casadi_int sz = f_.size2_out(i);
330 for (casadi_int d=0; d<nfwd; ++d) {
331 for (casadi_int k=0; k<n_; ++k) {
332 for (casadi_int j=0; j<sz; ++j) {
333 ind.push_back((k*nfwd + d)*sz + j);
337 *it = (*it)(
Slice(), ind);
341 Dict custom_opts = opts;
342 custom_opts[
"always_inline"] =
true;
343 custom_opts[
"allow_duplicate_io_names"] =
true;
344 return Function(name, arg, res, inames, onames, custom_opts);
349 const std::vector<std::string>& inames,
350 const std::vector<std::string>& onames,
351 const Dict& opts)
const {
355 for (casadi_int i=0;i<n_out_;++i) {
356 if (reduce_out_[i]) casadi_assert(df.
nnz_in(n_in_+i)==0,
"Case not implemented");
359 std::vector<bool> reduce_in =
join(reduce_in_, reduce_out_, reduce_out_);
361 df, n_, reduce_in, reduce_in_);
364 std::vector<MX> arg = dm.
mx_in();
367 std::vector<MX> res = arg;
368 std::vector<MX>::iterator it=res.begin()+n_in_+n_out_;
369 std::vector<casadi_int> ind;
370 for (casadi_int i=0; i<n_out_; ++i, ++it) {
371 if (reduce_out_[i])
continue;
372 casadi_int sz = f_.size2_out(i);
374 for (casadi_int k=0; k<n_; ++k) {
375 for (casadi_int d=0; d<nadj; ++d) {
376 for (casadi_int j=0; j<sz; ++j) {
377 ind.push_back((d*n_ + k)*sz + j);
381 *it = (*it)(
Slice(), ind);
389 for (casadi_int i=0; i<n_in_; ++i, ++it) {
390 if (reduce_in_[i])
continue;
391 casadi_int sz = f_.size2_in(i);
393 for (casadi_int d=0; d<nadj; ++d) {
394 for (casadi_int k=0; k<n_; ++k) {
395 for (casadi_int j=0; j<sz; ++j) {
396 ind.push_back((k*nadj + d)*sz + j);
400 *it = (*it)(
Slice(), ind);
404 Dict custom_opts = opts;
405 custom_opts[
"always_inline"] =
true;
406 custom_opts[
"allow_duplicate_io_names"] =
true;
407 return Function(name, arg, res, inames, onames, custom_opts);
410 int MapSum::eval(
const double** arg,
double** res, casadi_int* iw,
double* w,
void* mem)
const {
414 setup(mem, arg, res, iw, w);
416 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.
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())
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.