26 #ifndef CASADI_SETNONZEROS_IMPL_HPP
27 #define CASADI_SETNONZEROS_IMPL_HPP
29 #include "setnonzeros.hpp"
30 #include "casadi_misc.hpp"
31 #include "serializing_stream.hpp"
38 MX SetNonzeros<Add>::create(
const MX& y,
const MX& x,
const std::vector<casadi_int>& nz) {
41 std::pair<Slice, Slice> sl =
to_slice2(nz);
42 return create(y, x, sl.first, sl.second);
44 return MX::create(
new SetNonzerosVector<Add>(y, x, nz));
48 MX SetNonzeros<Add>::create(
const MX& y,
const MX& x,
const Slice& s) {
50 if (y.sparsity()==x.sparsity() && s.start==0 && s.step==1 && s.stop==x.nnz()) {
57 return MX::create(
new SetNonzerosSlice<Add>(y, x, s));
61 MX SetNonzeros<Add>::create(
const MX& y,
const MX& x,
const Slice& inner,
const Slice& outer) {
62 return MX::create(
new SetNonzerosSlice2<Add>(y, x, inner, outer));
66 SetNonzeros<Add>::SetNonzeros(
const MX& y,
const MX& x) {
67 this->set_sparsity(y.sparsity());
72 SetNonzerosVector<Add>::SetNonzerosVector(
const MX& y,
const MX& x,
73 const std::vector<casadi_int>& nz) : SetNonzeros<Add>(y, x), nz_(nz) {
76 std::vector<bool> already_set(this->nnz(),
false);
77 for (std::vector<casadi_int>::reverse_iterator i=nz_.rbegin(); i!=nz_.rend(); ++i) {
79 if (already_set[*i]) {
82 already_set[*i] =
true;
90 SetNonzeros<Add>:: ~SetNonzeros() {
94 void SetNonzerosVector<Add>::eval_mx(
const std::vector<MX>& arg, std::vector<MX>& res,
95 const std::vector<bool>& unique)
const {
96 if (!MXNode::matches_sparsity(arg)) {
97 SetNonzeros<Add>::eval_mx(arg, res, unique);
100 res[0] = SetNonzeros<Add>::create(arg[0], arg[1], nz_);
104 void SetNonzerosSlice<Add>::eval_mx(
const std::vector<MX>& arg, std::vector<MX>& res,
105 const std::vector<bool>& unique)
const {
106 if (!MXNode::matches_sparsity(arg)) {
107 SetNonzeros<Add>::eval_mx(arg, res, unique);
110 res[0] = SetNonzeros<Add>::create(arg[0], arg[1], s_);
114 void SetNonzerosSlice2<Add>::eval_mx(
const std::vector<MX>& arg, std::vector<MX>& res,
115 const std::vector<bool>& unique)
const {
116 if (!MXNode::matches_sparsity(arg)) {
117 SetNonzeros<Add>::eval_mx(arg, res, unique);
120 res[0] = SetNonzeros<Add>::create(arg[0], arg[1], inner_, outer_);
124 void SetNonzeros<Add>::eval_mx(
const std::vector<MX>& arg, std::vector<MX>& res,
125 const std::vector<bool>& unique)
const {
127 std::vector<casadi_int> nz = all();
130 const Sparsity &osp = sparsity();
131 const casadi_int* orow = osp.row();
132 std::vector<casadi_int> ocol = osp.get_col();
135 const Sparsity &isp = dep(1).sparsity();
136 std::vector<casadi_int> icol = isp.get_col();
140 std::vector<casadi_int> onz_count(osp.nnz()+2, 0);
141 for (std::vector<casadi_int>::const_iterator it=nz.begin(); it!=nz.end(); ++it) {
146 for (casadi_int i=0; i<onz_count.size()-1; ++i) {
147 onz_count[i+1] += onz_count[i];
151 std::vector<casadi_int> nz_order(nz.size());
152 for (casadi_int k=0; k<nz.size(); ++k) {
154 nz_order[onz_count[1+nz[k]]++] = k;
158 std::vector<casadi_int>& with_duplicates = onz_count;
159 onz_count.resize(nz.size());
160 for (casadi_int k=0; k<nz.size(); ++k) {
162 casadi_int onz_k = nz[nz_order[k]];
166 with_duplicates[k] = ocol[onz_k]*osp.size1() + orow[onz_k];
168 with_duplicates[k] = -1;
173 std::vector<casadi_int> el_output;
177 std::vector<casadi_int> r_colind, r_row, r_nz, r_ind;
186 r_nz.resize(with_duplicates.size());
187 std::copy(with_duplicates.begin(), with_duplicates.end(), r_nz.begin());
188 res[0].sparsity().get_nz(r_nz);
191 res[0] = MX::zeros(isp)->get_nzassign(res[0], r_nz);
195 arg[1].sparsity().find(r_nz);
199 bool elements_to_add =
false;
200 for (std::vector<casadi_int>::iterator k=r_nz.begin(); k!=r_nz.end(); ++k) {
203 elements_to_add =
true;
211 if (!elements_to_add)
return;
214 r_ind.resize(el_output.size());
215 std::copy(el_output.begin(), el_output.end(), r_ind.begin());
216 res[0].sparsity().get_nz(r_ind);
219 for (std::vector<casadi_int>::iterator k=r_nz.begin(); k!=r_nz.end(); ++k) {
220 if (*k>=0 && nz[*k]>=0 && r_ind[nz[*k]]<0) {
224 Sparsity sp = res[0].sparsity().unite(osp);
225 res[0] = res[0]->get_project(sp);
228 std::copy(el_output.begin(), el_output.end(), r_ind.begin());
229 res[0].sparsity().get_nz(r_ind);
236 for (std::vector<casadi_int>::iterator k=r_nz.begin(); k!=r_nz.end(); ++k) {
243 res[0] = arg[1]->get_nzadd(res[0], r_nz);
247 void SetNonzeros<Add>::ad_forward(
const std::vector<std::vector<MX> >& fseed,
248 std::vector<std::vector<MX> >& fsens)
const {
250 std::vector<casadi_int> nz = all();
253 casadi_int nfwd = fsens.size();
256 const Sparsity &osp = sparsity();
257 const casadi_int* orow = osp.row();
258 std::vector<casadi_int> ocol;
261 const Sparsity &isp = dep(1).sparsity();
262 std::vector<casadi_int> icol;
264 bool first_run =
true;
266 std::vector<casadi_int> onz_count;
268 std::vector<casadi_int> nz_order;
271 std::vector<casadi_int>& with_duplicates = onz_count;
274 std::vector<casadi_int> el_output;
277 std::vector<casadi_int> r_colind, r_row, r_nz, r_ind;
280 for (casadi_int d=0; d<nfwd; ++d) {
283 const MX& arg = fseed[d][1];
284 const MX& arg0 = fseed[d][0];
286 MX& res = fsens[d][0];
289 if (isp==arg.sparsity() && arg0.sparsity()==osp) {
303 res = MX::zeros(isp)->get_nzassign(res, nz);
306 res = arg->get_nzadd(res, nz);
310 ocol = osp.get_col();
311 icol = isp.get_col();
315 onz_count.resize(osp.nnz()+2, 0);
316 for (std::vector<casadi_int>::const_iterator it=nz.begin(); it!=nz.end(); ++it) {
321 for (casadi_int i=0; i<onz_count.size()-1; ++i) {
322 onz_count[i+1] += onz_count[i];
326 nz_order.resize(nz.size());
327 for (casadi_int k=0; k<nz.size(); ++k) {
329 nz_order[onz_count[1+nz[k]]++] = k;
332 onz_count.resize(nz.size());
333 for (casadi_int k=0; k<nz.size(); ++k) {
335 casadi_int onz_k = nz[nz_order[k]];
339 with_duplicates[k] = ocol[onz_k]*osp.size1() + orow[onz_k];
341 with_duplicates[k] = -1;
353 r_nz.resize(with_duplicates.size());
354 std::copy(with_duplicates.begin(), with_duplicates.end(), r_nz.begin());
355 res.sparsity().get_nz(r_nz);
358 res = MX::zeros(isp)->get_nzassign(res, r_nz);
363 arg.sparsity().find(r_nz);
367 bool elements_to_add =
false;
368 for (std::vector<casadi_int>::iterator k=r_nz.begin(); k!=r_nz.end(); ++k) {
371 elements_to_add =
true;
379 if (!elements_to_add)
continue;
382 r_ind.resize(el_output.size());
383 std::copy(el_output.begin(), el_output.end(), r_ind.begin());
384 res.sparsity().get_nz(r_ind);
387 for (std::vector<casadi_int>::iterator k=r_nz.begin(); k!=r_nz.end(); ++k) {
388 if (*k>=0 && nz[*k]>=0 && r_ind[nz[*k]]<0) {
392 Sparsity sp = res.sparsity().unite(osp);
393 res = res->get_project(sp);
396 std::copy(el_output.begin(), el_output.end(), r_ind.begin());
397 res.sparsity().get_nz(r_ind);
404 for (std::vector<casadi_int>::iterator k=r_nz.begin(); k!=r_nz.end(); ++k) {
411 res = arg->get_nzadd(res, r_nz);
417 void SetNonzeros<Add>::ad_reverse(
const std::vector<std::vector<MX> >& aseed,
418 std::vector<std::vector<MX> >& asens)
const {
420 std::vector<casadi_int> nz = all();
423 casadi_int nadj = aseed.size();
426 const Sparsity &osp = sparsity();
427 const casadi_int* orow = osp.row();
428 std::vector<casadi_int> ocol;
431 const Sparsity &isp = dep(1).sparsity();
432 const casadi_int* irow = isp.row();
433 std::vector<casadi_int> icol;
435 std::vector<casadi_int> onz_count;
438 std::vector<casadi_int> nz_order;
440 std::vector<casadi_int>& with_duplicates = onz_count;
443 std::vector<casadi_int> el_output;
445 bool first_run =
true;
448 std::vector<casadi_int> r_colind, r_row, r_nz, r_ind;
450 for (casadi_int d=0; d<nadj; ++d) {
451 if (osp==aseed[d][0].sparsity()) {
461 asens[d][1] += aseed[d][0]->get_nzref(isp, nz);
463 asens[d][0] += MX::zeros(isp)->get_nzassign(aseed[d][0], nz);
465 asens[d][0] += aseed[d][0];
469 ocol = osp.get_col();
470 icol = isp.get_col();
473 onz_count.resize(osp.nnz()+2, 0);
474 for (std::vector<casadi_int>::const_iterator it=nz.begin(); it!=nz.end(); ++it) {
479 for (casadi_int i=0; i<onz_count.size()-1; ++i) {
480 onz_count[i+1] += onz_count[i];
484 nz_order.resize(nz.size());
485 for (casadi_int k=0; k<nz.size(); ++k) {
487 nz_order[onz_count[1+nz[k]]++] = k;
491 onz_count.resize(nz.size());
492 for (casadi_int k=0; k<nz.size(); ++k) {
494 casadi_int onz_k = nz[nz_order[k]];
498 with_duplicates[k] = ocol[onz_k]*osp.size1() + orow[onz_k];
500 with_duplicates[k] = -1;
509 r_ind.resize(el_output.size());
510 std::copy(el_output.begin(), el_output.end(), r_ind.begin());
511 aseed[d][0].sparsity().get_nz(r_ind);
514 r_colind.resize(isp.size2()+1);
515 std::fill(r_colind.begin(), r_colind.end(), 0);
520 for (casadi_int k=0; k<nz.size(); ++k) {
523 casadi_int el = nz[k];
526 if (el==-1)
continue;
529 casadi_int el_arg = r_ind[el];
532 if (el_arg==-1)
continue;
535 r_nz.push_back(el_arg);
538 casadi_int i=icol[k], j=irow[k];
546 for (casadi_int i=1; i<r_colind.size(); ++i) r_colind[i] += r_colind[i-1];
551 Sparsity f_sp(isp.size1(), isp.size2(), r_colind, r_row);
552 asens[d][1] += aseed[d][0]->get_nzref(f_sp, r_nz);
554 asens[d][0] += MX::zeros(f_sp)->get_nzassign(aseed[d][0], r_nz);
556 asens[d][0] += aseed[d][0];
559 asens[d][0] += aseed[d][0];
566 int SetNonzerosVector<Add>::
567 eval(
const double** arg,
double** res, casadi_int* iw,
double* w)
const {
568 return eval_gen<double>(arg, res, iw, w);
572 int SetNonzerosVector<Add>::
573 eval_sx(
const SXElem** arg, SXElem** res, casadi_int* iw, SXElem* w)
const {
574 return eval_gen<SXElem>(arg, res, iw, w);
579 int SetNonzerosVector<Add>::
580 eval_gen(
const T** arg, T** res, casadi_int* iw, T* w)
const {
581 const T* idata0 = arg[0];
582 const T* idata = arg[1];
584 if (idata0 != odata) {
585 std::copy(idata0, idata0+this->dep(0).nnz(), odata);
587 for (
auto k=this->nz_.begin(); k!=this->nz_.end(); ++k, ++idata) {
589 if (*k>=0) odata[*k] += *idata;
591 if (*k>=0) odata[*k] = *idata;
598 int SetNonzerosSlice<Add>::
599 eval(
const double** arg,
double** res, casadi_int* iw,
double* w)
const {
600 return eval_gen<double>(arg, res, iw, w);
604 int SetNonzerosSlice<Add>::
605 eval_sx(
const SXElem** arg, SXElem** res, casadi_int* iw, SXElem* w)
const {
606 return eval_gen<SXElem>(arg, res, iw, w);
611 int SetNonzerosSlice<Add>::
612 eval_gen(
const T** arg, T** res, casadi_int* iw, T* w)
const {
613 const T* idata0 = arg[0];
614 const T* idata = arg[1];
616 if (idata0 != odata) {
617 std::copy(idata0, idata0+this->dep(0).nnz(), odata);
619 T* odata_stop = odata + s_.stop;
620 for (odata += s_.start; odata != odata_stop; odata += s_.step) {
631 int SetNonzerosSlice2<Add>::
632 eval(
const double** arg,
double** res, casadi_int* iw,
double* w)
const {
633 return eval_gen<double>(arg, res, iw, w);
637 int SetNonzerosSlice2<Add>::
638 eval_sx(
const SXElem** arg, SXElem** res, casadi_int* iw, SXElem* w)
const {
639 return eval_gen<SXElem>(arg, res, iw, w);
644 int SetNonzerosSlice2<Add>::
645 eval_gen(
const T** arg, T** res, casadi_int* iw, T* w)
const {
646 const T* idata0 = arg[0];
647 const T* idata = arg[1];
649 if (idata0 != odata) {
650 std::copy(idata0, idata0 + this->dep(0).nnz(), odata);
652 T* outer_stop = odata + outer_.stop;
653 T* outer = odata + outer_.start;
654 for (; outer != outer_stop; outer += outer_.step) {
655 for (T* inner = outer+inner_.start;
656 inner != outer+inner_.stop;
657 inner += inner_.step) {
669 int SetNonzerosVector<Add>::
670 sp_forward(
const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w)
const {
671 const bvec_t *a0 = arg[0];
672 const bvec_t *a = arg[1];
674 casadi_int n = this->nnz();
677 if (r != a0) std::copy(a0, a0+n, r);
678 for (
auto k=this->nz_.begin(); k!=this->nz_.end(); ++k, ++a) {
680 if (*k>=0) r[*k] |= *a;
682 if (*k>=0) r[*k] = *a;
689 int SetNonzerosVector<Add>::
690 sp_reverse(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w)
const {
693 for (
auto k=this->nz_.begin(); k!=this->nz_.end(); ++k, ++a) {
701 MXNode::copy_rev(arg[0], r, this->nnz());
706 int SetNonzerosSlice<Add>::
707 sp_forward(
const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w)
const {
708 const bvec_t *a0 = arg[0];
709 const bvec_t *a = arg[1];
711 casadi_int n = this->nnz();
714 if (r != a0) std::copy(a0, a0+n, r);
715 for (casadi_int k=s_.start; k!=s_.stop; k+=s_.step) {
726 int SetNonzerosSlice<Add>::
727 sp_reverse(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w)
const {
730 for (casadi_int k=s_.start; k!=s_.stop; k+=s_.step) {
736 MXNode::copy_rev(arg[0], r, this->nnz());
741 int SetNonzerosSlice2<Add>::
742 sp_forward(
const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w)
const {
743 const bvec_t *a0 = arg[0];
744 const bvec_t *a = arg[1];
746 casadi_int n = this->nnz();
749 if (r != a0) std::copy(a0, a0+n, r);
750 for (casadi_int k1=outer_.start; k1!=outer_.stop; k1+=outer_.step) {
751 for (casadi_int k2=k1+inner_.start; k2!=k1+inner_.stop; k2+=inner_.step) {
763 int SetNonzerosSlice2<Add>::
764 sp_reverse(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w)
const {
767 for (casadi_int k1=outer_.start; k1!=outer_.stop; k1+=outer_.step) {
768 for (casadi_int k2=k1+inner_.start; k2!=k1+inner_.stop; k2+=inner_.step) {
775 MXNode::copy_rev(arg[0], r, this->nnz());
780 std::string SetNonzerosVector<Add>::disp(
const std::vector<std::string>& arg)
const {
781 std::stringstream ss;
782 ss <<
"(" << arg.at(0) << nz_ << (Add ?
" += " :
" = ") << arg.at(1) <<
")";
787 std::string SetNonzerosSlice<Add>::disp(
const std::vector<std::string>& arg)
const {
788 std::stringstream ss;
789 ss <<
"(" << arg.at(0) <<
"[" << s_ <<
"]" << (Add ?
" += " :
" = ") << arg.at(1) <<
")";
794 std::string SetNonzerosSlice2<Add>::disp(
const std::vector<std::string>& arg)
const {
795 std::stringstream ss;
796 ss <<
"(" << arg.at(0) <<
"[" << outer_ <<
";" << inner_ <<
"]" << (Add ?
" += " :
" = ")
802 Matrix<casadi_int> SetNonzeros<Add>::mapping()
const {
803 std::vector<casadi_int> nz = all();
804 return Matrix<casadi_int>(this->dep(1).sparsity(), nz,
false);
808 bool SetNonzerosVector<Add>::is_equal(
const MXNode* node, casadi_int depth)
const {
810 if (!this->sameOpAndDeps(node, depth))
return false;
813 const SetNonzerosVector<Add>* n =
dynamic_cast<const SetNonzerosVector<Add>*
>(node);
814 if (n==
nullptr)
return false;
817 if (this->sparsity()!=node->sparsity())
return false;
820 if (this->nz_.size()!=n->nz_.size())
return false;
821 if (!std::equal(this->nz_.begin(), this->nz_.end(), n->nz_.begin()))
return false;
827 bool SetNonzerosSlice<Add>::is_equal(
const MXNode* node, casadi_int depth)
const {
829 if (!this->sameOpAndDeps(node, depth))
return false;
832 const SetNonzerosSlice<Add>* n =
dynamic_cast<const SetNonzerosSlice<Add>*
>(node);
833 if (n==
nullptr)
return false;
836 if (this->sparsity()!=node->sparsity())
return false;
839 if (this->s_ != n->s_)
return false;
845 bool SetNonzerosSlice2<Add>::is_equal(
const MXNode* node, casadi_int depth)
const {
847 if (!this->sameOpAndDeps(node, depth))
return false;
850 const SetNonzerosSlice2<Add>* n =
dynamic_cast<const SetNonzerosSlice2<Add>*
>(node);
851 if (n==
nullptr)
return false;
854 if (this->sparsity()!=node->sparsity())
return false;
857 if (this->inner_ != n->inner_ || this->outer_!=n->outer_)
return false;
863 void SetNonzerosVector<Add>::
864 generate(CodeGenerator& g,
865 const std::vector<casadi_int>& arg,
866 const std::vector<casadi_int>& res,
867 const std::vector<bool>& arg_is_ref,
868 std::vector<bool>& res_is_ref)
const {
870 if (arg[0]!=res[0] || arg_is_ref[0]) {
871 g << g.copy(g.work(arg[0], this->dep(0).nnz(), arg_is_ref[0]), this->nnz(),
872 g.work(res[0], this->nnz(),
false)) <<
'\n';
876 std::string ind = g.constant(this->nz_);
879 g.local(
"cii",
"const casadi_int",
"*");
880 g.local(
"rr",
"casadi_real",
"*");
881 g.local(
"cs",
"const casadi_real",
"*");
882 g <<
"for (cii=" << ind <<
", rr=" << g.work(res[0], this->nnz(),
false) <<
", "
883 <<
"cs=" << g.work(arg[1], this->dep(1).nnz(), arg_is_ref[1]) <<
"; cii!=" << ind
884 <<
"+" << this->nz_.size() <<
"; ++cii, ++cs) ";
886 g <<
"if (*cii>=0) ";
888 g <<
"rr[*cii] " << (Add?
"+=":
"=") <<
" *cs;\n";
892 void SetNonzerosSlice<Add>::
893 generate(CodeGenerator& g,
894 const std::vector<casadi_int>& arg,
895 const std::vector<casadi_int>& res,
896 const std::vector<bool>& arg_is_ref,
897 std::vector<bool>& res_is_ref)
const {
899 if (arg[0]!=res[0] || arg_is_ref[0]) {
900 g << g.copy(g.work(arg[0], this->dep(0).nnz(), arg_is_ref[0]), this->nnz(),
901 g.work(res[0], this->nnz(),
false)) <<
'\n';
905 g.local(
"rr",
"casadi_real",
"*");
906 g.local(
"cs",
"const casadi_real",
"*");
907 g <<
"for (rr=" << g.work(res[0], this->nnz(),
false) <<
"+" << s_.start <<
", cs="
908 << g.work(arg[1], this->dep(1).nnz(), arg_is_ref[1]) <<
"; rr!="
909 << g.work(res[0], this->nnz(),
false) <<
"+" << s_.stop
910 <<
"; rr+=" << s_.step <<
")"
911 <<
" *rr " << (Add?
"+=":
"=") <<
" *cs++;\n";
915 void SetNonzerosSlice2<Add>::
916 generate(CodeGenerator& g,
917 const std::vector<casadi_int>& arg,
918 const std::vector<casadi_int>& res,
919 const std::vector<bool>& arg_is_ref,
920 std::vector<bool>& res_is_ref)
const {
922 if (arg[0]!=res[0] || arg_is_ref[0]) {
923 g << g.copy(g.work(arg[0], this->dep(0).nnz(), arg_is_ref[0]), this->nnz(),
924 g.work(res[0], this->nnz(),
false)) <<
'\n';
928 g.local(
"rr",
"casadi_real",
"*");
929 g.local(
"cs",
"const casadi_real",
"*");
930 g.local(
"tt",
"casadi_real",
"*");
931 g <<
"for (rr=" << g.work(res[0], this->nnz(),
false) <<
"+" << outer_.start
932 <<
", cs=" << g.work(arg[1], this->dep(1).nnz(), arg_is_ref[1]) <<
"; rr!="
933 << g.work(res[0], this->nnz(),
false) <<
"+" << outer_.stop
934 <<
"; rr+=" << outer_.step <<
")"
935 <<
" for (tt=rr+" << inner_.start <<
"; tt!=rr+" << inner_.stop
936 <<
"; tt+=" << inner_.step <<
")"
937 <<
" *tt " << (Add?
"+=":
"=") <<
" *cs++;\n";
941 void SetNonzerosVector<Add>::serialize_body(SerializingStream& s)
const {
942 MXNode::serialize_body(s);
943 s.pack(
"SetNonzerosVector::nonzeros", nz_);
947 SetNonzerosVector<Add>::SetNonzerosVector(DeserializingStream& s) : SetNonzeros<Add>(s) {
948 s.unpack(
"SetNonzerosVector::nonzeros", nz_);
952 void SetNonzerosVector<Add>::serialize_type(SerializingStream& s)
const {
953 MXNode::serialize_type(s);
954 s.pack(
"SetNonzeros::type",
'a');
958 void SetNonzerosSlice<Add>::serialize_body(SerializingStream& s)
const {
959 MXNode::serialize_body(s);
960 s.pack(
"SetNonzerosSlice::slice", s_);
964 SetNonzerosSlice<Add>::SetNonzerosSlice(DeserializingStream& s) : SetNonzeros<Add>(s) {
965 s.unpack(
"SetNonzerosSlice::slice", s_);
969 void SetNonzerosSlice<Add>::serialize_type(SerializingStream& s)
const {
970 MXNode::serialize_type(s);
971 s.pack(
"SetNonzeros::type",
'b');
975 void SetNonzerosSlice2<Add>::serialize_body(SerializingStream& s)
const {
976 MXNode::serialize_body(s);
977 s.pack(
"SetNonzerosSlice2::inner", inner_);
978 s.pack(
"SetNonzerosSlice2::outer", outer_);
982 SetNonzerosSlice2<Add>::SetNonzerosSlice2(DeserializingStream& s) : SetNonzeros<Add>(s) {
983 s.unpack(
"SetNonzerosSlice2::inner", inner_);
984 s.unpack(
"SetNonzerosSlice2::outer", outer_);
988 void SetNonzerosSlice2<Add>::serialize_type(SerializingStream& s)
const {
989 MXNode::serialize_type(s);
990 s.pack(
"SetNonzeros::type",
'c');
994 MXNode* SetNonzeros<Add>::deserialize(DeserializingStream& s) {
996 s.unpack(
"SetNonzeros::type", t);
998 case 'a':
return new SetNonzerosVector<Add>(s);
999 case 'b':
return new SetNonzerosSlice<Add>(s);
1000 case 'c':
return new SetNonzerosSlice2<Add>(s);
1001 default: casadi_assert_dev(
false);
bool has_negative(const std::vector< T > &v)
Check if the vector has negative entries.
bool CASADI_EXPORT is_slice(const IM &x, bool ind1=false)
Is the IM a Slice.
std::pair< Slice, Slice > CASADI_EXPORT to_slice2(const std::vector< casadi_int > &v)
Construct nested slices from an index vector (requires is_slice2(v) to be true)
bool CASADI_EXPORT is_slice2(const std::vector< casadi_int > &v)
Check if an index vector can be represented more efficiently as two nested slices.
Slice CASADI_EXPORT to_slice(const IM &x, bool ind1=false)
Convert IM to Slice.