26 #ifndef CASADI_SETNONZEROS_PARAM_IMPL_HPP
27 #define CASADI_SETNONZEROS_PARAM_IMPL_HPP
29 #include "setnonzeros_param.hpp"
30 #include "casadi_misc.hpp"
31 #include "serializing_stream.hpp"
38 MX SetNonzerosParam<Add>::create(
const MX& y,
const MX& x,
const MX& nz) {
39 return MX::create(
new SetNonzerosParamVector<Add>(y, x, nz));
43 MX SetNonzerosParam<Add>::create(
const MX& y,
const MX& x,
const Slice& inner,
const MX& outer) {
44 casadi_assert(outer.is_vector() && outer.is_dense(),
"outer must be dense vector");
45 return MX::create(
new SetNonzerosSliceParam<Add>(y, x, inner, outer));
49 MX SetNonzerosParam<Add>::create(
const MX& y,
const MX& x,
const MX& inner,
const Slice& outer) {
50 casadi_assert(inner.is_vector() && inner.is_dense(),
"inner must be dense vector");
51 return MX::create(
new SetNonzerosParamSlice<Add>(y, x, inner, outer));
55 MX SetNonzerosParam<Add>::create(
const MX& y,
const MX& x,
const MX& inner,
const MX& outer) {
56 casadi_assert(inner.is_vector() && inner.is_dense(),
"inner must be dense vector");
57 casadi_assert(outer.is_vector() && outer.is_dense(),
"outer must be dense vector");
58 return MX::create(
new SetNonzerosParamParam<Add>(y, x, inner, outer));
62 SetNonzerosParam<Add>::SetNonzerosParam(
const MX& y,
const MX& x,
const MX& nz) {
63 this->set_sparsity(y.sparsity());
64 this->set_dep(y, x, nz);
68 SetNonzerosParam<Add>::SetNonzerosParam(
const MX& y,
const MX& x,
const MX& nz,
const MX& nz2) {
69 this->set_sparsity(y.sparsity());
70 this->set_dep({y, x, nz, nz2});
74 SetNonzerosParamVector<Add>::SetNonzerosParamVector(
const MX& y,
const MX& x,
75 const MX& nz) : SetNonzerosParam<Add>(y, x, nz) {
79 SetNonzerosParam<Add>:: ~SetNonzerosParam() {
83 void SetNonzerosParamVector<Add>::
84 eval_mx(
const std::vector<MX>& arg, std::vector<MX>& res)
const {
86 MX arg0 = project(arg[0], this->dep(0).sparsity());
87 MX arg1 = project(arg[1], this->dep(1).sparsity());
90 res[0] = arg1->get_nzadd(arg0, nz);
92 res[0] = arg1->get_nzassign(arg0, nz);
97 void SetNonzerosParamSlice<Add>::
98 eval_mx(
const std::vector<MX>& arg, std::vector<MX>& res)
const {
100 MX arg0 = project(arg[0], this->dep(0).sparsity());
101 MX arg1 = project(arg[1], this->dep(1).sparsity());
104 res[0] = arg1->get_nzadd(arg0, inner, outer_);
106 res[0] = arg1->get_nzassign(arg0, inner, outer_);
111 void SetNonzerosSliceParam<Add>::
112 eval_mx(
const std::vector<MX>& arg, std::vector<MX>& res)
const {
114 MX arg0 = project(arg[0], this->dep(0).sparsity());
115 MX arg1 = project(arg[1], this->dep(1).sparsity());
118 res[0] = arg1->get_nzadd(arg0, inner_, outer);
120 res[0] = arg1->get_nzassign(arg0, inner_, outer);
125 void SetNonzerosParamParam<Add>::
126 eval_mx(
const std::vector<MX>& arg, std::vector<MX>& res)
const {
128 MX arg0 = project(arg[0], this->dep(0).sparsity());
129 MX arg1 = project(arg[1], this->dep(1).sparsity());
133 res[0] = arg1->get_nzadd(arg0, inner, outer);
135 res[0] = arg1->get_nzassign(arg0, inner, outer);
140 void SetNonzerosParamVector<Add>::ad_forward(
const std::vector<std::vector<MX> >& fseed,
141 std::vector<std::vector<MX> >& fsens)
const {
142 const MX& nz = this->dep(2);
144 for (casadi_int d=0; d<fsens.size(); ++d) {
147 MX arg0 = project(fseed[d][0], this->dep(0).sparsity());
148 MX arg1 = project(fseed[d][1], this->dep(1).sparsity());
162 MX& res = fsens[d][0];
166 res = arg1->get_nzadd(res, nz);
168 res = arg1->get_nzassign(res, nz);
174 void SetNonzerosParamVector<Add>::ad_reverse(
const std::vector<std::vector<MX> >& aseed,
175 std::vector<std::vector<MX> >& asens)
const {
176 const MX& nz = this->dep(2);
177 for (casadi_int d=0; d<aseed.size(); ++d) {
178 MX seed = project(aseed[d][0], this->sparsity());
189 asens[d][1] += seed->get_nz_ref(nz);
191 asens[d][0] += MX::zeros(this->dep(1).sparsity())->get_nzassign(seed, nz);
200 void SetNonzerosParamSlice<Add>::ad_forward(
const std::vector<std::vector<MX> >& fseed,
201 std::vector<std::vector<MX> >& fsens)
const {
202 const MX& inner = this->dep(2);
203 for (casadi_int d=0; d<fsens.size(); ++d) {
204 MX arg0 = project(fseed[d][0], this->dep(0).sparsity());
205 MX arg1 = project(fseed[d][1], this->dep(1).sparsity());
207 MX& res = fsens[d][0];
211 res = arg1->get_nzadd(res, inner, outer_);
213 res = arg1->get_nzassign(res, inner, outer_);
219 void SetNonzerosParamSlice<Add>::ad_reverse(
const std::vector<std::vector<MX> >& aseed,
220 std::vector<std::vector<MX> >& asens)
const {
221 const MX& inner = this->dep(2);
222 for (casadi_int d=0; d<aseed.size(); ++d) {
223 MX seed = project(aseed[d][0], this->sparsity());
224 asens[d][1] += seed->get_nz_ref(inner, outer_);
226 asens[d][0] += MX::zeros(this->dep(1).sparsity())->get_nzassign(seed, inner, outer_);
234 void SetNonzerosSliceParam<Add>::ad_forward(
const std::vector<std::vector<MX> >& fseed,
235 std::vector<std::vector<MX> >& fsens)
const {
236 const MX& outer = this->dep(2);
237 for (casadi_int d=0; d<fsens.size(); ++d) {
238 MX arg0 = project(fseed[d][0], this->dep(0).sparsity());
239 MX arg1 = project(fseed[d][1], this->dep(1).sparsity());
241 MX& res = fsens[d][0];
245 res = arg1->get_nzadd(res, inner_, outer);
247 res = arg1->get_nzassign(res, inner_, outer);
253 void SetNonzerosSliceParam<Add>::ad_reverse(
const std::vector<std::vector<MX> >& aseed,
254 std::vector<std::vector<MX> >& asens)
const {
255 const MX& outer = this->dep(2);
256 for (casadi_int d=0; d<aseed.size(); ++d) {
257 MX seed = project(aseed[d][0], this->sparsity());
258 asens[d][1] += seed->get_nz_ref(inner_, outer);
260 asens[d][0] += MX::zeros(this->dep(1).sparsity())->get_nzassign(seed, inner_, outer);
268 void SetNonzerosParamParam<Add>::ad_forward(
const std::vector<std::vector<MX> >& fseed,
269 std::vector<std::vector<MX> >& fsens)
const {
270 const MX& inner = this->dep(2);
271 const MX& outer = this->dep(3);
272 for (casadi_int d=0; d<fsens.size(); ++d) {
273 MX arg0 = project(fseed[d][0], this->dep(0).sparsity());
274 MX arg1 = project(fseed[d][1], this->dep(1).sparsity());
276 MX& res = fsens[d][0];
280 res = arg1->get_nzadd(res, inner, outer);
282 res = arg1->get_nzassign(res, inner, outer);
288 void SetNonzerosParamParam<Add>::ad_reverse(
const std::vector<std::vector<MX> >& aseed,
289 std::vector<std::vector<MX> >& asens)
const {
290 const MX& inner = this->dep(2);
291 const MX& outer = this->dep(3);
292 for (casadi_int d=0; d<aseed.size(); ++d) {
293 MX seed = project(aseed[d][0], this->sparsity());
294 asens[d][1] += seed->get_nz_ref(inner, outer);
296 asens[d][0] += MX::zeros(this->dep(1).sparsity())->get_nzassign(seed, inner, outer);
304 int SetNonzerosParamVector<Add>::
305 eval(
const double** arg,
double** res, casadi_int* iw,
double* w)
const {
306 const double* idata0 = arg[0];
307 const double* idata = arg[1];
308 const double* nz = arg[2];
309 double* odata = res[0];
311 casadi_int nnz = this->dep(2).nnz();
312 casadi_int max_ind = this->dep(0).nnz();
313 if (idata0 != odata) {
314 std::copy(idata0, idata0+this->dep(0).nnz(), odata);
316 for (casadi_int k=0; k<nnz; ++k) {
318 casadi_int index =
static_cast<casadi_int
>(*nz++);
320 if (index>=0 && index<max_ind) odata[index] += *idata;
322 if (index>=0 && index<max_ind) odata[index] = *idata;
330 int SetNonzerosParamSlice<Add>::
331 eval(
const double** arg,
double** res, casadi_int* iw,
double* w)
const {
332 const double* idata0 = arg[0];
333 const double* idata = arg[1];
334 const double* nz = arg[2];
335 double* odata = res[0];
337 casadi_int nnz = this->dep(2).nnz();
338 casadi_int max_ind = this->dep(0).nnz();
339 if (idata0 != odata) {
340 std::copy(idata0, idata0+this->dep(0).nnz(), odata);
343 casadi_int* inner = iw; iw += nnz;
344 for (casadi_int i=0; i<nnz; ++i) {
346 inner[i] =
static_cast<casadi_int
>(*nz++);
348 for (casadi_int i=outer_.start;i<outer_.stop;i+= outer_.step) {
350 for (casadi_int* inner_it=inner; inner_it!=inner+nnz; ++inner_it) {
351 casadi_int index = i+*inner_it;
353 if (index>=0 && index<max_ind) odata[index] += *idata;
355 if (index>=0 && index<max_ind) odata[index] = *idata;
364 int SetNonzerosSliceParam<Add>::
365 eval(
const double** arg,
double** res, casadi_int* iw,
double* w)
const {
366 const double* idata0 = arg[0];
367 const double* idata = arg[1];
368 const double* nz = arg[2];
369 double* odata = res[0];
371 casadi_int nnz = this->dep(2).nnz();
372 casadi_int max_ind = this->dep(0).nnz();
373 if (idata0 != odata) {
374 std::copy(idata0, idata0+this->dep(0).nnz(), odata);
376 for (casadi_int k=0; k<nnz; ++k) {
378 casadi_int ind =
static_cast<casadi_int
>(*nz++);
379 for (casadi_int j=0;j<inner_.stop;j+= inner_.step) {
380 casadi_int index = ind+j;
382 if (index>=0 && index<max_ind) odata[index] += *idata;
384 if (index>=0 && index<max_ind) odata[index] = *idata;
393 int SetNonzerosParamParam<Add>::
394 eval(
const double** arg,
double** res, casadi_int* iw,
double* w)
const {
395 const double* idata0 = arg[0];
396 const double* idata = arg[1];
397 const double* nz = arg[2];
398 const double* nz2 = arg[3];
399 double* odata = res[0];
401 casadi_int nnz = this->dep(2).nnz();
402 casadi_int nnz2 = this->dep(3).nnz();
403 casadi_int max_ind = this->dep(0).nnz();
404 if (idata0 != odata) {
405 std::copy(idata0, idata0+this->dep(0).nnz(), odata);
408 casadi_int* inner = iw; iw += nnz;
409 for (casadi_int i=0; i<nnz; ++i) {
411 inner[i] =
static_cast<casadi_int
>(*nz++);
414 for (casadi_int k=0; k<nnz2; ++k) {
416 casadi_int ind =
static_cast<casadi_int
>(*nz2++);
417 for (casadi_int* inner_it=inner; inner_it!=inner+nnz; ++inner_it) {
418 casadi_int index = ind+*inner_it;
420 if (index>=0 && index<max_ind) odata[index] += *idata;
422 if (index>=0 && index<max_ind) odata[index] = *idata;
431 size_t SetNonzerosParamSlice<Add>::
433 return this->dep(2).nnz();
437 size_t SetNonzerosParamParam<Add>::
439 return this->dep(2).nnz();
444 int SetNonzerosParam<Add>::
445 sp_forward(
const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w)
const {
447 bvec_t arg0 = bvec_or(arg[0], this->dep(0).nnz());
448 bvec_t arg1 = bvec_or(arg[1], this->dep(1).nnz());
451 std::fill(r, r+this->nnz(), arg0 | arg1);
456 int SetNonzerosParam<Add>::
457 sp_reverse(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w)
const {
458 bvec_t *arg0 = arg[0];
459 bvec_t *arg1 = arg[1];
460 bvec_t r = bvec_or(res[0], this->nnz());
461 std::fill(res[0], res[0]+this->nnz(), bvec_t(0));
463 for (casadi_int i=0;i<this->dep(0).nnz();++i) {
466 for (casadi_int i=0;i<this->dep(1).nnz();++i) {
473 std::string SetNonzerosParamVector<Add>::disp(
const std::vector<std::string>& arg)
const {
474 std::stringstream ss;
475 ss <<
"(" << arg.at(0) <<
"[" << arg.at(2) <<
"]";
476 ss << (Add ?
" += " :
" = ") << arg.at(1) <<
")";
481 std::string SetNonzerosParamSlice<Add>::disp(
const std::vector<std::string>& arg)
const {
482 std::stringstream ss;
483 ss <<
"(" << arg.at(0) <<
"[(" << arg.at(2) <<
";" << outer_ <<
")]";
484 ss << (Add ?
" += " :
" = ") << arg.at(1) <<
")";
489 std::string SetNonzerosSliceParam<Add>::disp(
const std::vector<std::string>& arg)
const {
490 std::stringstream ss;
491 ss <<
"(" << arg.at(0) <<
"[(" << inner_ <<
";" << arg.at(2) <<
")]";
492 ss << (Add ?
" += " :
" = ") << arg.at(1) <<
")";
497 std::string SetNonzerosParamParam<Add>::disp(
const std::vector<std::string>& arg)
const {
498 std::stringstream ss;
499 ss <<
"(" << arg.at(0) <<
"[(" << arg.at(2) <<
";" << arg.at(3) <<
")]";
500 ss << (Add ?
" += " :
" = ") << arg.at(1) <<
")";
505 void SetNonzerosParam<Add>::
506 generate(CodeGenerator& g,
507 const std::vector<casadi_int>& arg,
const std::vector<casadi_int>& res)
const {
509 if (arg[0]!=res[0]) {
510 g << g.copy(g.work(arg[0], this->dep(0).nnz()), this->nnz(),
511 g.work(res[0], this->nnz())) <<
'\n';
516 void SetNonzerosParamVector<Add>::
517 generate(CodeGenerator& g,
518 const std::vector<casadi_int>& arg,
const std::vector<casadi_int>& res)
const {
519 SetNonzerosParam<Add>::generate(g, arg, res);
521 casadi_int n = this->dep(1).nnz();
523 g.local(
"i",
"casadi_int");
524 g.local(
"cr",
"const casadi_real",
"*");
525 g.local(
"cs",
"const casadi_real",
"*");
526 g <<
"for (cs=" << g.work(arg[1], n) <<
", cr=" << g.work(arg[2], n)
527 <<
"; cs!=" << g.work(arg[1], n) <<
"+" << n
528 <<
"; ++cs) { i=(int) *cr++; if (i>=0 && i<" << this->dep(0).nnz() <<
") "
529 << g.work(res[0], this->nnz()) <<
"[i] " << (Add?
"+= ":
"= ")
534 void SetNonzerosParamSlice<Add>::
535 generate(CodeGenerator& g,
536 const std::vector<casadi_int>& arg,
const std::vector<casadi_int>& res)
const {
537 SetNonzerosParam<Add>::generate(g, arg, res);
539 casadi_int n = this->dep(1).nnz();
540 casadi_int n_inner = this->dep(2).nnz();
542 g.local(
"cii",
"const casadi_int",
"*");
543 g.local(
"i",
"casadi_int");
544 g <<
"for (i=0;i<" << n_inner <<
";++i) iw[i] = (int) "
545 << g.work(arg[2], n_inner) <<
"[i];\n";
547 g.local(
"cs",
"const casadi_real",
"*");
548 g.local(
"k",
"casadi_int");
549 g <<
"for (cs=" << g.work(arg[1], n)
550 <<
", k=" << outer_.start <<
";k<" << outer_.stop <<
";k+=" << outer_.step <<
") ";
551 g <<
"for (cii=iw; cii!=iw" <<
"+" << n_inner <<
"; ++cii) { i=k+*cii; "
552 <<
"if (i>=0 && i<" << this->dep(0).nnz() <<
") "
553 << g.work(res[0], this->nnz()) <<
"[i] " << (Add?
"+= ":
"= ")
558 void SetNonzerosSliceParam<Add>::
559 generate(CodeGenerator& g,
560 const std::vector<casadi_int>& arg,
const std::vector<casadi_int>& res)
const {
561 SetNonzerosParam<Add>::generate(g, arg, res);
563 casadi_int n = this->dep(1).nnz();
564 casadi_int n_outer = this->dep(2).nnz();
566 g.local(
"i",
"casadi_int");
567 g.local(
"j",
"casadi_int");
568 g.local(
"k",
"casadi_int");
569 g.local(
"cr",
"const casadi_real",
"*");
570 g.local(
"cs",
"const casadi_real",
"*");
571 g <<
"for (cr=" << g.work(arg[2], n_outer)
572 <<
", cs=" << g.work(arg[1], n)
573 <<
"; cr!=" << g.work(arg[2], n_outer) <<
"+" << n_outer
575 g <<
"for (j=(int) *cr, "
576 <<
"k=" << inner_.start <<
";k<" << inner_.stop <<
";k+=" << inner_.step <<
") ";
578 <<
"if (i>=0 && i<" << this->dep(0).nnz() <<
") "
579 << g.work(res[0], this->nnz()) <<
"[i] " << (Add?
"+= ":
"= ")
584 void SetNonzerosParamParam<Add>::
585 generate(CodeGenerator& g,
586 const std::vector<casadi_int>& arg,
const std::vector<casadi_int>& res)
const {
587 SetNonzerosParam<Add>::generate(g, arg, res);
588 casadi_int n = this->dep(1).nnz();
589 casadi_int n_outer = this->dep(3).nnz();
590 casadi_int n_inner = this->dep(2).nnz();
592 g.local(
"cii",
"const casadi_int",
"*");
593 g.local(
"i",
"casadi_int");
594 g <<
"for (i=0;i<" << n_inner <<
";++i) iw[i] = (int) "
595 << g.work(arg[2], n_inner) <<
"[i];\n";
597 g.local(
"j",
"casadi_int");
598 g.local(
"cr",
"const casadi_real",
"*");
599 g.local(
"cs",
"const casadi_real",
"*");
600 g <<
"for (cr=" << g.work(arg[3], n_outer)
601 <<
", cs=" << g.work(arg[1], n)
602 <<
"; cr!=" << g.work(arg[3], n_outer) <<
"+" << n_outer
604 g <<
"for (j=(int) *cr, cii=iw; cii!=iw" <<
"+" << n_inner <<
"; ++cii) { i=j+*cii; "
605 <<
"if (i>=0 && i<" << this->dep(0).nnz() <<
") "
606 << g.work(res[0], this->nnz()) <<
"[i] " << (Add?
"+= ":
"= ")
611 void SetNonzerosParamVector<Add>::serialize_body(SerializingStream& s)
const {
612 MXNode::serialize_body(s);
616 SetNonzerosParamVector<Add>::SetNonzerosParamVector(DeserializingStream& s) :
617 SetNonzerosParam<Add>(s) {
621 void SetNonzerosParamVector<Add>::serialize_type(SerializingStream& s)
const {
622 MXNode::serialize_type(s);
623 s.pack(
"SetNonzerosParam::type",
'a');
627 void SetNonzerosParamSlice<Add>::serialize_body(SerializingStream& s)
const {
628 MXNode::serialize_body(s);
629 s.pack(
"SetNonzerosParamSlice::outer", outer_);
633 SetNonzerosParamSlice<Add>::SetNonzerosParamSlice(DeserializingStream& s) :
634 SetNonzerosParam<Add>(s) {
635 s.unpack(
"SetNonzerosParamSlice::outer", outer_);
639 void SetNonzerosParamSlice<Add>::serialize_type(SerializingStream& s)
const {
640 MXNode::serialize_type(s);
641 s.pack(
"SetNonzerosParam::type",
'b');
645 void SetNonzerosSliceParam<Add>::serialize_body(SerializingStream& s)
const {
646 MXNode::serialize_body(s);
647 s.pack(
"SetNonzerosSliceParam::inner", inner_);
651 SetNonzerosSliceParam<Add>::SetNonzerosSliceParam(DeserializingStream& s) :
652 SetNonzerosParam<Add>(s) {
653 s.unpack(
"SetNonzerosSliceParam::inner", inner_);
657 void SetNonzerosSliceParam<Add>::serialize_type(SerializingStream& s)
const {
658 MXNode::serialize_type(s);
659 s.pack(
"SetNonzerosParam::type",
'c');
664 void SetNonzerosParamParam<Add>::serialize_type(SerializingStream& s)
const {
665 MXNode::serialize_type(s);
666 s.pack(
"SetNonzerosParam::type",
'd');
670 SetNonzerosParamParam<Add>::SetNonzerosParamParam(DeserializingStream& s) :
671 SetNonzerosParam<Add>(s) {
675 MXNode* SetNonzerosParam<Add>::deserialize(DeserializingStream& s) {
677 s.unpack(
"SetNonzerosParam::type", t);
679 case 'a':
return new SetNonzerosParamVector<Add>(s);
680 case 'b':
return new SetNonzerosParamSlice<Add>(s);
681 case 'c':
return new SetNonzerosSliceParam<Add>(s);
682 case 'd':
return new SetNonzerosParamParam<Add>(s);
683 default: casadi_assert_dev(
false);