27 #include "casadi_misc.hpp"
28 #include "serializing_stream.hpp"
39 template<
bool Fwd>
struct KronSpTraits;
40 template<>
struct KronSpTraits<true> {
41 typedef const bvec_t** arg_t;
43 static inline void step(arg_t arg, res_t res,
44 casadi_int a_el, casadi_int b_el, casadi_int k) {
45 res[0][k] = arg[0][a_el] | arg[1][b_el];
48 template<>
struct KronSpTraits<false> {
51 static inline void step(arg_t arg, res_t res,
52 casadi_int a_el, casadi_int b_el, casadi_int k) {
53 arg[0][a_el] |= res[0][k];
54 arg[1][b_el] |= res[0][k];
62 typename KronSpTraits<Fwd>::arg_t arg,
63 typename KronSpTraits<Fwd>::res_t res) {
64 const casadi_int* a_colind = sp_a.
colind();
65 const casadi_int* b_colind = sp_b.
colind();
66 const casadi_int a_ncol = sp_a.
size2();
67 const casadi_int b_ncol = sp_b.
size2();
69 for (casadi_int a_cc=0; a_cc<a_ncol; ++a_cc) {
70 for (casadi_int b_cc=0; b_cc<b_ncol; ++b_cc) {
71 for (casadi_int a_el=a_colind[a_cc]; a_el<a_colind[a_cc+1]; ++a_el) {
72 for (casadi_int b_el=b_colind[b_cc]; b_el<b_colind[b_cc+1]; ++b_el) {
73 KronSpTraits<Fwd>::step(arg, res, a_el, b_el, k);
98 std::string
Kron::disp(
const std::vector<std::string>& arg)
const {
99 return "kron(" + arg.at(0) +
", " + arg.at(1) +
")";
111 const std::vector<bool>& unique)
const {
112 res[0] = kron(arg[0], arg[1]);
124 std::vector<std::vector<MX> >& fsens)
const {
125 const MX& A =
dep(0);
126 const MX& B =
dep(1);
127 for (casadi_int d=0; d<fsens.size(); ++d) {
128 fsens[d][0] = kron(fseed[d][0], B) + kron(A, fseed[d][1]);
133 std::vector<std::vector<MX> >& asens)
const {
134 const MX& A =
dep(0);
135 const MX& B =
dep(1);
136 for (casadi_int d=0; d<aseed.size(); ++d) {
137 const MX& Fbar = aseed[d][0];
144 const std::vector<casadi_int>& arg,
145 const std::vector<casadi_int>& res,
146 const std::vector<bool>& arg_is_ref,
147 std::vector<bool>& res_is_ref)
const {
150 << g.
work(arg[0],
dep(0).
nnz(), arg_is_ref[0]) <<
", "
152 << g.
work(arg[1],
dep(1).
nnz(), arg_is_ref[1]) <<
", "
154 << g.
work(res[0],
nnz(),
false) <<
");\n";
159 s.
pack(
"Kron::kind", std::string(
"base"));
164 s.
unpack(
"Kron::kind", kind);
165 if (kind ==
"base")
return new Kron(s);
166 if (kind ==
"dense")
return new DenseKron(s);
169 casadi_error(
"Unknown Kron kind: " + kind);
191 const std::vector<casadi_int>& arg,
192 const std::vector<casadi_int>& res,
193 const std::vector<bool>& arg_is_ref,
194 std::vector<bool>& res_is_ref)
const {
196 g <<
"casadi_kron_dense("
197 << g.
work(arg[0],
dep(0).
nnz(), arg_is_ref[0]) <<
", "
199 << g.
work(arg[1],
dep(1).
nnz(), arg_is_ref[1]) <<
", "
201 << g.
work(res[0],
nnz(),
false) <<
");\n";
206 s.
pack(
"Kron::kind", std::string(
"dense"));
228 const std::vector<casadi_int>& arg,
229 const std::vector<casadi_int>& res,
230 const std::vector<bool>& arg_is_ref,
231 std::vector<bool>& res_is_ref)
const {
233 g <<
"casadi_kron_dense_sparse("
234 << g.
work(arg[0],
dep(0).
nnz(), arg_is_ref[0]) <<
", "
236 << g.
work(arg[1],
dep(1).
nnz(), arg_is_ref[1]) <<
", "
238 << g.
work(res[0],
nnz(),
false) <<
");\n";
243 s.
pack(
"Kron::kind", std::string(
"dense_sparse"));
265 const std::vector<casadi_int>& arg,
266 const std::vector<casadi_int>& res,
267 const std::vector<bool>& arg_is_ref,
268 std::vector<bool>& res_is_ref)
const {
270 g <<
"casadi_kron_sparse_dense("
271 << g.
work(arg[0],
dep(0).
nnz(), arg_is_ref[0]) <<
", "
273 << g.
work(arg[1],
dep(1).
nnz(), arg_is_ref[1]) <<
", "
275 << g.
work(res[0],
nnz(),
false) <<
");\n";
280 s.
pack(
"Kron::kind", std::string(
"sparse_dense"));
295 "KronContract: X must be nonempty");
297 "KronContract: M dims must be multiples of X dims");
303 return std::string(
"kron_contract(") + arg.at(0) +
", " + arg.at(1)
304 +
", " + (
inner_ ?
"inner" :
"outer") +
")";
308 return static_cast<size_t>(
dep(1).
numel());
336 const std::vector<bool>& unique)
const {
341 casadi_int* iw,
bvec_t* w)
const {
353 const casadi_int xrow = sp_x.
size1(), xcol = sp_x.
size2();
354 const casadi_int yrow = sp_y.
size1(), ycol = sp_y.
size2();
355 const casadi_int* m_colind = sp_m.
colind();
356 const casadi_int* m_row = sp_m.
row();
357 const casadi_int* x_colind = sp_x.
colind();
358 const casadi_int* x_row = sp_x.
row();
359 const casadi_int* y_colind = sp_y.
colind();
360 const casadi_int* y_row = sp_y.
row();
361 const casadi_int mB =
inner_ ? xrow : yrow;
362 const casadi_int nB =
inner_ ? xcol : ycol;
363 const casadi_int nA =
inner_ ? ycol : xcol;
365 const casadi_int xn = xrow*xcol;
366 for (casadi_int k=0; k<xn; ++k) w_x[k] = 0;
367 for (casadi_int cc=0; cc<xcol; ++cc) {
368 for (casadi_int el=x_colind[cc]; el<x_colind[cc+1]; ++el) {
369 w_x[cc*xrow + x_row[el]] = arg[1][el];
372 const casadi_int yn_total = y_colind[ycol];
373 for (casadi_int k=0; k<yn_total; ++k) res[0][k] = 0;
374 for (casadi_int j=0; j<nA; ++j) {
375 for (casadi_int s=0; s<nB; ++s) {
376 casadi_int cc = j*nB + s;
377 casadi_int y_cc =
inner_ ? j : s;
378 casadi_int x_cc =
inner_ ? s : j;
379 casadi_int y_col_start = y_colind[y_cc];
380 casadi_int y_col_end = y_colind[y_cc+1];
381 if (y_col_start == y_col_end)
continue;
382 for (casadi_int el=m_colind[cc]; el<m_colind[cc+1]; ++el) {
383 casadi_int rr = m_row[el];
384 casadi_int outer_row = rr / mB;
385 casadi_int inner_row = rr % mB;
386 casadi_int y_rr =
inner_ ? outer_row : inner_row;
387 casadi_int x_rr =
inner_ ? inner_row : outer_row;
388 bvec_t x_pat = w_x[x_cc*xrow + x_rr];
389 for (casadi_int y_el=y_col_start; y_el<y_col_end; ++y_el) {
390 if (y_row[y_el] == y_rr) { res[0][y_el] |= arg[0][el] | x_pat;
break; }
391 if (y_row[y_el] > y_rr)
break;
400 casadi_int* iw,
bvec_t* w)
const {
404 const casadi_int xrow = sp_x.
size1(), xcol = sp_x.
size2();
405 const casadi_int yrow = sp_y.
size1(), ycol = sp_y.
size2();
406 const casadi_int* m_colind = sp_m.
colind();
407 const casadi_int* m_row = sp_m.
row();
408 const casadi_int* x_colind = sp_x.
colind();
409 const casadi_int* x_row = sp_x.
row();
410 const casadi_int* y_colind = sp_y.
colind();
411 const casadi_int* y_row = sp_y.
row();
412 const casadi_int mB =
inner_ ? xrow : yrow;
413 const casadi_int nB =
inner_ ? xcol : ycol;
414 const casadi_int nA =
inner_ ? ycol : xcol;
415 for (casadi_int j=0; j<nA; ++j) {
416 for (casadi_int s=0; s<nB; ++s) {
417 casadi_int cc = j*nB + s;
418 casadi_int y_cc =
inner_ ? j : s;
419 casadi_int x_cc =
inner_ ? s : j;
420 casadi_int y_col_start = y_colind[y_cc];
421 casadi_int y_col_end = y_colind[y_cc+1];
422 if (y_col_start == y_col_end)
continue;
423 casadi_int x_col_start = x_colind[x_cc];
424 casadi_int x_col_end = x_colind[x_cc+1];
425 for (casadi_int el=m_colind[cc]; el<m_colind[cc+1]; ++el) {
426 casadi_int rr = m_row[el];
427 casadi_int outer_row = rr / mB;
428 casadi_int inner_row = rr % mB;
429 casadi_int y_rr =
inner_ ? outer_row : inner_row;
430 casadi_int x_rr =
inner_ ? inner_row : outer_row;
431 for (casadi_int y_el=y_col_start; y_el<y_col_end; ++y_el) {
432 if (y_row[y_el] == y_rr) {
433 bvec_t sval = res[0][y_el];
435 for (casadi_int x_el=x_col_start; x_el<x_col_end; ++x_el) {
436 if (x_row[x_el] == x_rr) { arg[1][x_el] |= sval;
break; }
437 if (x_row[x_el] > x_rr)
break;
441 if (y_row[y_el] > y_rr)
break;
446 const casadi_int yn_total = y_colind[ycol];
447 for (casadi_int k=0; k<yn_total; ++k) res[0][k] = 0;
452 std::vector<std::vector<MX> >& fsens)
const {
453 const MX& M =
dep(0);
455 for (casadi_int d=0; d<fsens.size(); ++d) {
462 std::vector<std::vector<MX> >& asens)
const {
463 const MX& M =
dep(0);
465 for (casadi_int d=0; d<aseed.size(); ++d) {
466 const MX& Ybar = aseed[d][0];
467 MX m_kron =
inner_ ? kron(Ybar,
X) : kron(
X, Ybar);
468 asens[d][0] += project(m_kron, M.
sparsity());
474 const std::vector<casadi_int>& arg,
475 const std::vector<casadi_int>& res,
476 const std::vector<bool>& arg_is_ref,
477 std::vector<bool>& res_is_ref)
const {
480 g <<
"casadi_kron_contract_inner(";
483 g <<
"casadi_kron_contract_outer(";
485 g << g.
work(arg[0],
dep(0).
nnz(), arg_is_ref[0]) <<
", "
487 << g.
work(arg[1],
dep(1).
nnz(), arg_is_ref[1]) <<
", "
489 << g.
work(res[0],
nnz(),
false) <<
", "
500 s.
pack(
"KronContract::kind", std::string(
"base"));
509 s.
unpack(
"KronContract::kind", kind);
514 casadi_error(
"Unknown KronContract kind: " + kind);
550 const std::vector<casadi_int>& arg,
551 const std::vector<casadi_int>& res,
552 const std::vector<bool>& arg_is_ref,
553 std::vector<bool>& res_is_ref)
const {
558 g <<
"casadi_kron_contract_inner_dense("
559 << g.
work(arg[0],
dep(0).
nnz(), arg_is_ref[0]) <<
", "
560 << mA <<
", " << nA <<
", "
561 << g.
work(arg[1],
dep(1).
nnz(), arg_is_ref[1]) <<
", "
562 << mB <<
", " << nB <<
", "
563 << g.
work(res[0],
nnz(),
false) <<
");\n";
568 g <<
"casadi_kron_contract_outer_dense("
569 << g.
work(arg[0],
dep(0).
nnz(), arg_is_ref[0]) <<
", "
570 << mB <<
", " << nB <<
", "
571 << g.
work(arg[1],
dep(1).
nnz(), arg_is_ref[1]) <<
", "
572 << mA <<
", " << nA <<
", "
573 << g.
work(res[0],
nnz(),
false) <<
");\n";
579 s.
pack(
"KronContract::kind", std::string(
"dense"));
615 const std::vector<casadi_int>& arg,
616 const std::vector<casadi_int>& res,
617 const std::vector<bool>& arg_is_ref,
618 std::vector<bool>& res_is_ref)
const {
622 g <<
"casadi_kron_contract_inner_dense_sparse("
623 << g.
work(arg[0],
dep(0).
nnz(), arg_is_ref[0]) <<
", "
624 << mA <<
", " << nA <<
", "
625 << g.
work(arg[1],
dep(1).
nnz(), arg_is_ref[1]) <<
", "
627 << g.
work(res[0],
nnz(),
false) <<
");\n";
631 g <<
"casadi_kron_contract_outer_dense_sparse("
632 << g.
work(arg[0],
dep(0).
nnz(), arg_is_ref[0]) <<
", "
633 << mB <<
", " << nB <<
", "
634 << g.
work(arg[1],
dep(1).
nnz(), arg_is_ref[1]) <<
", "
636 << g.
work(res[0],
nnz(),
false) <<
");\n";
642 s.
pack(
"KronContract::kind", std::string(
"dense_sparse"));
678 const std::vector<casadi_int>& arg,
679 const std::vector<casadi_int>& res,
680 const std::vector<bool>& arg_is_ref,
681 std::vector<bool>& res_is_ref)
const {
684 g <<
"casadi_kron_contract_inner_sparse_dense("
685 << g.
work(arg[0],
dep(0).
nnz(), arg_is_ref[0]) <<
", "
687 << g.
work(arg[1],
dep(1).
nnz(), arg_is_ref[1]) <<
", "
689 << g.
work(res[0],
nnz(),
false) <<
", "
693 g <<
"casadi_kron_contract_outer_sparse_dense("
694 << g.
work(arg[0],
dep(0).
nnz(), arg_is_ref[0]) <<
", "
696 << g.
work(arg[1],
dep(1).
nnz(), arg_is_ref[1]) <<
", "
698 << g.
work(res[0],
nnz(),
false) <<
", "
705 s.
pack(
"KronContract::kind", std::string(
"sparse_dense"));
Helper class for C code generation.
std::string work(casadi_int n, casadi_int sz, bool is_ref) const
@ AUX_KRON_CONTRACT_INNER_DENSE
@ AUX_KRON_CONTRACT_INNER
@ AUX_KRON_CONTRACT_OUTER_SPARSE_DENSE
@ AUX_KRON_CONTRACT_OUTER_DENSE_SPARSE
@ AUX_KRON_CONTRACT_OUTER_DENSE
@ AUX_KRON_CONTRACT_OUTER
@ AUX_KRON_CONTRACT_INNER_SPARSE_DENSE
@ AUX_KRON_CONTRACT_INNER_DENSE_SPARSE
std::string sparsity(const Sparsity &sp, bool canonical=true)
void add_auxiliary(Auxiliary f, const std::vector< std::string > &inst={"casadi_real"})
Add a built-in auxiliary function.
KronContract specialization: M dense, X dense (=> Y dense)
void serialize_type(SerializingStream &s) const override
Serialize specific part of node.
DenseKronContract(const MX &m, const MX &x, bool inner)
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.
static MXNode * try_create(const MX &m, const MX &x, bool inner)
void eval_kernel(const double **arg, double **res, double *w) const override
Kron specialization: both operands dense.
void eval_kernel(const double **arg, double **res) const override
Subclass hook: r = kron(a, b) on the input buffers.
void serialize_type(SerializingStream &s) const override
Serialize specific part of node.
static MXNode * try_create(const MX &a, const MX &b)
DenseKron(const MX &a, const MX &b)
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.
KronContract specialization: M dense, X sparse (=> Y dense)
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 serialize_type(SerializingStream &s) const override
Serialize specific part of node.
DenseSparseKronContract(const MX &m, const MX &x, bool inner)
void eval_kernel(const double **arg, double **res, double *w) const override
static MXNode * try_create(const MX &m, const MX &x, bool inner)
Kron specialization: dense a + sparse b.
DenseSparseKron(const MX &a, const MX &b)
void eval_kernel(const double **arg, double **res) const override
Subclass hook: r = kron(a, b) on the input buffers.
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 serialize_type(SerializingStream &s) const override
Serialize specific part of node.
static MXNode * try_create(const MX &a, const MX &b)
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
casadi_int numel() const
Get the number of elements.
bool is_dense() const
Check if the matrix expression is dense.
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)
void ad_reverse(const std::vector< std::vector< MX > > &aseed, std::vector< std::vector< MX > > &asens) const override
Calculate reverse mode directional derivatives.
int sp_reverse(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const override
Propagate sparsity backwards.
void eval_mx(const std::vector< MX > &arg, std::vector< MX > &res, const std::vector< bool > &unique={}) const override
Evaluate symbolically (MX)
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 serialize_body(SerializingStream &s) const override
Serialize an object without type information.
static MX create(const MX &m, const MX &x, bool inner)
Factory: dispatch to the most specific subclass for the given operands.
int sp_forward(const bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const override
Propagate sparsity forward.
void ad_forward(const std::vector< std::vector< MX > > &fseed, std::vector< std::vector< MX > > &fsens) const override
Calculate forward mode directional derivatives.
std::string disp(const std::vector< std::string > &arg) const override
Print expression.
virtual void eval_kernel(const double **arg, double **res, double *w) const
static MXNode * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
bool inner_
Which axes are contracted (true = inner (mB, nB); false = outer (mA, nA))
KronContract(const MX &m, const MX &x, bool inner)
Constructor (auto-derives output sparsity)
void serialize_type(SerializingStream &s) const override
Serialize specific part of node.
size_t sz_w() const override
Get required length of w field.
static MXNode * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
Kron(const MX &a, const MX &b)
Constructor.
void serialize_type(SerializingStream &s) const override
Serialize specific part of node.
std::string disp(const std::vector< std::string > &arg) const override
Print expression.
static MX create(const MX &a, const MX &b)
Factory: dispatch to the most specific subclass for the given operands.
int sp_reverse(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const override
Propagate sparsity backwards.
virtual void eval_kernel(const double **arg, double **res) const
Subclass hook: r = kron(a, b) on the input buffers.
int sp_forward(const bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const override
Propagate sparsity forward.
void eval_mx(const std::vector< MX > &arg, std::vector< MX > &res, const std::vector< bool > &unique={}) const override
Evaluate symbolically (MX)
void ad_reverse(const std::vector< std::vector< MX > > &aseed, std::vector< std::vector< MX > > &asens) const override
Calculate reverse mode directional derivatives.
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 ad_forward(const std::vector< std::vector< MX > > &fseed, std::vector< std::vector< MX > > &fsens) const override
Calculate forward mode directional derivatives.
Node class for MX objects.
virtual void serialize_type(SerializingStream &s) const
Serialize type information.
const Sparsity & sparsity() const
Get the sparsity.
casadi_int nnz(casadi_int i=0) const
const MX & dep(casadi_int ind=0) const
dependencies - functions that have to be evaluated before this one
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.
const Sparsity & sparsity() const
Get the sparsity pattern.
The basic scalar symbolic class of CasADi.
Helper class for Serialization.
void pack(const Sparsity &e)
Serializes an object to the output stream.
KronContract specialization: M sparse, X dense.
SparseDenseKronContract(const MX &m, const MX &x, bool inner)
void serialize_type(SerializingStream &s) const override
Serialize specific part of node.
void eval_kernel(const double **arg, double **res, double *w) const override
static MXNode * try_create(const MX &m, const MX &x, bool inner)
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.
Kron specialization: sparse a + dense b.
void serialize_type(SerializingStream &s) const override
Serialize specific part of node.
SparseDenseKron(const MX &a, const MX &b)
static MXNode * try_create(const MX &a, const MX &b)
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 eval_kernel(const double **arg, double **res) const override
Subclass hook: r = kron(a, b) on the input buffers.
casadi_int size1() const
Get the number of rows.
casadi_int size2() const
Get the number of columns.
const casadi_int * row() const
Get a reference to row-vector,.
static Sparsity kron(const Sparsity &a, const Sparsity &b)
Enlarge matrix.
const casadi_int * colind() const
Get a reference to the colindex of all column element (see class description)
static Sparsity kron_contract(const Sparsity &sp_m, const Sparsity &sp_x, bool inner)
Output sparsity of casadi::KronContract.
void casadi_kron_contract_inner(const T1 *m, const casadi_int *sp_m, const T1 *b, const casadi_int *sp_b, T1 *y, const casadi_int *sp_y, T1 *w)
static int kron_sp_gen(const Sparsity &sp_a, const Sparsity &sp_b, typename KronSpTraits< Fwd >::arg_t arg, typename KronSpTraits< Fwd >::res_t res)
void casadi_kron_contract_inner_dense(const T1 *m, casadi_int mA, casadi_int nA, const T1 *b, casadi_int mB, casadi_int nB, T1 *y)
void casadi_kron_sparse_dense(const T1 *a, const casadi_int *sp_a, const T1 *b, casadi_int mB, casadi_int nB, T1 *r)
unsigned long long bvec_t
void casadi_kron_contract_outer_dense(const T1 *m, casadi_int mB, casadi_int nB, const T1 *a, casadi_int mA, casadi_int nA, T1 *y)
void casadi_kron_contract_inner_sparse_dense(const T1 *m, const casadi_int *sp_m, const T1 *b, casadi_int mB, casadi_int nB, T1 *y, const casadi_int *sp_y)
void casadi_kron_contract_inner_dense_sparse(const T1 *m, casadi_int mA, casadi_int nA, const T1 *b, const casadi_int *sp_b, T1 *y)
void casadi_kron_contract_outer_dense_sparse(const T1 *m, casadi_int mB, casadi_int nB, const T1 *a, const casadi_int *sp_a, T1 *y)
void casadi_kron(const T1 *a, const casadi_int *sp_a, const T1 *b, const casadi_int *sp_b, T1 *r)
MX kron_contract(const MX &m, const MX &x, bool inner)
Kronecker contraction.
void casadi_kron_contract_outer_sparse_dense(const T1 *m, const casadi_int *sp_m, const T1 *a, casadi_int mA, casadi_int nA, T1 *y, const casadi_int *sp_y)
void casadi_kron_dense(const T1 *a, casadi_int mA, casadi_int nA, const T1 *b, casadi_int mB, casadi_int nB, T1 *r)
void casadi_kron_contract_outer(const T1 *m, const casadi_int *sp_m, const T1 *a, const casadi_int *sp_a, T1 *y, const casadi_int *sp_y, T1 *w)
void casadi_kron_dense_sparse(const T1 *a, casadi_int mA, casadi_int nA, const T1 *b, const casadi_int *sp_b, T1 *r)