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)
const {
95 if (!MXNode::matches_sparsity(arg)) {
96 SetNonzeros<Add>::eval_mx(arg, res);
99 res[0] = SetNonzeros<Add>::create(arg[0], arg[1], nz_);
103 void SetNonzerosSlice<Add>::eval_mx(
const std::vector<MX>& arg, std::vector<MX>& res)
const {
104 if (!MXNode::matches_sparsity(arg)) {
105 SetNonzeros<Add>::eval_mx(arg, res);
108 res[0] = SetNonzeros<Add>::create(arg[0], arg[1], s_);
112 void SetNonzerosSlice2<Add>::eval_mx(
const std::vector<MX>& arg, std::vector<MX>& res)
const {
113 if (!MXNode::matches_sparsity(arg)) {
114 SetNonzeros<Add>::eval_mx(arg, res);
117 res[0] = SetNonzeros<Add>::create(arg[0], arg[1], inner_, outer_);
121 void SetNonzeros<Add>::eval_mx(
const std::vector<MX>& arg, std::vector<MX>& res)
const {
123 std::vector<casadi_int> nz = all();
126 const Sparsity &osp = sparsity();
127 const casadi_int* orow = osp.row();
128 std::vector<casadi_int> ocol = osp.get_col();
131 const Sparsity &isp = dep(1).sparsity();
132 std::vector<casadi_int> icol = isp.get_col();
136 std::vector<casadi_int> onz_count(osp.nnz()+2, 0);
137 for (std::vector<casadi_int>::const_iterator it=nz.begin(); it!=nz.end(); ++it) {
142 for (casadi_int i=0; i<onz_count.size()-1; ++i) {
143 onz_count[i+1] += onz_count[i];
147 std::vector<casadi_int> nz_order(nz.size());
148 for (casadi_int k=0; k<nz.size(); ++k) {
150 nz_order[onz_count[1+nz[k]]++] = k;
154 std::vector<casadi_int>& with_duplicates = onz_count;
155 onz_count.resize(nz.size());
156 for (casadi_int k=0; k<nz.size(); ++k) {
158 casadi_int onz_k = nz[nz_order[k]];
162 with_duplicates[k] = ocol[onz_k]*osp.size1() + orow[onz_k];
164 with_duplicates[k] = -1;
169 std::vector<casadi_int> el_output;
173 std::vector<casadi_int> r_colind, r_row, r_nz, r_ind;
182 r_nz.resize(with_duplicates.size());
183 std::copy(with_duplicates.begin(), with_duplicates.end(), r_nz.begin());
184 res[0].sparsity().get_nz(r_nz);
187 res[0] = MX::zeros(isp)->get_nzassign(res[0], r_nz);
191 arg[1].sparsity().find(r_nz);
195 bool elements_to_add =
false;
196 for (std::vector<casadi_int>::iterator k=r_nz.begin(); k!=r_nz.end(); ++k) {
199 elements_to_add =
true;
207 if (!elements_to_add)
return;
210 r_ind.resize(el_output.size());
211 std::copy(el_output.begin(), el_output.end(), r_ind.begin());
212 res[0].sparsity().get_nz(r_ind);
215 for (std::vector<casadi_int>::iterator k=r_nz.begin(); k!=r_nz.end(); ++k) {
216 if (*k>=0 && nz[*k]>=0 && r_ind[nz[*k]]<0) {
220 Sparsity sp = res[0].sparsity().unite(osp);
221 res[0] = res[0]->get_project(sp);
224 std::copy(el_output.begin(), el_output.end(), r_ind.begin());
225 res[0].sparsity().get_nz(r_ind);
232 for (std::vector<casadi_int>::iterator k=r_nz.begin(); k!=r_nz.end(); ++k) {
239 res[0] = arg[1]->get_nzadd(res[0], r_nz);
243 void SetNonzeros<Add>::ad_forward(
const std::vector<std::vector<MX> >& fseed,
244 std::vector<std::vector<MX> >& fsens)
const {
246 std::vector<casadi_int> nz = all();
249 casadi_int nfwd = fsens.size();
252 const Sparsity &osp = sparsity();
253 const casadi_int* orow = osp.row();
254 std::vector<casadi_int> ocol;
257 const Sparsity &isp = dep(1).sparsity();
258 std::vector<casadi_int> icol;
260 bool first_run =
true;
262 std::vector<casadi_int> onz_count;
264 std::vector<casadi_int> nz_order;
267 std::vector<casadi_int>& with_duplicates = onz_count;
270 std::vector<casadi_int> el_output;
273 std::vector<casadi_int> r_colind, r_row, r_nz, r_ind;
276 for (casadi_int d=0; d<nfwd; ++d) {
279 const MX& arg = fseed[d][1];
280 const MX& arg0 = fseed[d][0];
282 MX& res = fsens[d][0];
285 if (isp==arg.sparsity() && arg0.sparsity()==osp) {
299 res = MX::zeros(isp)->get_nzassign(res, nz);
302 res = arg->get_nzadd(res, nz);
306 ocol = osp.get_col();
307 icol = isp.get_col();
311 onz_count.resize(osp.nnz()+2, 0);
312 for (std::vector<casadi_int>::const_iterator it=nz.begin(); it!=nz.end(); ++it) {
317 for (casadi_int i=0; i<onz_count.size()-1; ++i) {
318 onz_count[i+1] += onz_count[i];
322 nz_order.resize(nz.size());
323 for (casadi_int k=0; k<nz.size(); ++k) {
325 nz_order[onz_count[1+nz[k]]++] = k;
328 onz_count.resize(nz.size());
329 for (casadi_int k=0; k<nz.size(); ++k) {
331 casadi_int onz_k = nz[nz_order[k]];
335 with_duplicates[k] = ocol[onz_k]*osp.size1() + orow[onz_k];
337 with_duplicates[k] = -1;
349 r_nz.resize(with_duplicates.size());
350 std::copy(with_duplicates.begin(), with_duplicates.end(), r_nz.begin());
351 res.sparsity().get_nz(r_nz);
354 res = MX::zeros(isp)->get_nzassign(res, r_nz);
359 arg.sparsity().find(r_nz);
363 bool elements_to_add =
false;
364 for (std::vector<casadi_int>::iterator k=r_nz.begin(); k!=r_nz.end(); ++k) {
367 elements_to_add =
true;
375 if (!elements_to_add)
continue;
378 r_ind.resize(el_output.size());
379 std::copy(el_output.begin(), el_output.end(), r_ind.begin());
380 res.sparsity().get_nz(r_ind);
383 for (std::vector<casadi_int>::iterator k=r_nz.begin(); k!=r_nz.end(); ++k) {
384 if (*k>=0 && nz[*k]>=0 && r_ind[nz[*k]]<0) {
388 Sparsity sp = res.sparsity().unite(osp);
389 res = res->get_project(sp);
392 std::copy(el_output.begin(), el_output.end(), r_ind.begin());
393 res.sparsity().get_nz(r_ind);
400 for (std::vector<casadi_int>::iterator k=r_nz.begin(); k!=r_nz.end(); ++k) {
407 res = arg->get_nzadd(res, r_nz);
413 void SetNonzeros<Add>::ad_reverse(
const std::vector<std::vector<MX> >& aseed,
414 std::vector<std::vector<MX> >& asens)
const {
416 std::vector<casadi_int> nz = all();
419 casadi_int nadj = aseed.size();
422 const Sparsity &osp = sparsity();
423 const casadi_int* orow = osp.row();
424 std::vector<casadi_int> ocol;
427 const Sparsity &isp = dep(1).sparsity();
428 const casadi_int* irow = isp.row();
429 std::vector<casadi_int> icol;
431 std::vector<casadi_int> onz_count;
434 std::vector<casadi_int> nz_order;
436 std::vector<casadi_int>& with_duplicates = onz_count;
439 std::vector<casadi_int> el_output;
441 bool first_run =
true;
444 std::vector<casadi_int> r_colind, r_row, r_nz, r_ind;
446 for (casadi_int d=0; d<nadj; ++d) {
447 if (osp==aseed[d][0].sparsity()) {
457 asens[d][1] += aseed[d][0]->get_nzref(isp, nz);
459 asens[d][0] += MX::zeros(isp)->get_nzassign(aseed[d][0], nz);
461 asens[d][0] += aseed[d][0];
465 ocol = osp.get_col();
466 icol = isp.get_col();
469 onz_count.resize(osp.nnz()+2, 0);
470 for (std::vector<casadi_int>::const_iterator it=nz.begin(); it!=nz.end(); ++it) {
475 for (casadi_int i=0; i<onz_count.size()-1; ++i) {
476 onz_count[i+1] += onz_count[i];
480 nz_order.resize(nz.size());
481 for (casadi_int k=0; k<nz.size(); ++k) {
483 nz_order[onz_count[1+nz[k]]++] = k;
487 onz_count.resize(nz.size());
488 for (casadi_int k=0; k<nz.size(); ++k) {
490 casadi_int onz_k = nz[nz_order[k]];
494 with_duplicates[k] = ocol[onz_k]*osp.size1() + orow[onz_k];
496 with_duplicates[k] = -1;
505 r_ind.resize(el_output.size());
506 std::copy(el_output.begin(), el_output.end(), r_ind.begin());
507 aseed[d][0].sparsity().get_nz(r_ind);
510 r_colind.resize(isp.size2()+1);
511 std::fill(r_colind.begin(), r_colind.end(), 0);
516 for (casadi_int k=0; k<nz.size(); ++k) {
519 casadi_int el = nz[k];
522 if (el==-1)
continue;
525 casadi_int el_arg = r_ind[el];
528 if (el_arg==-1)
continue;
531 r_nz.push_back(el_arg);
534 casadi_int i=icol[k], j=irow[k];
542 for (casadi_int i=1; i<r_colind.size(); ++i) r_colind[i] += r_colind[i-1];
547 Sparsity f_sp(isp.size1(), isp.size2(), r_colind, r_row);
548 asens[d][1] += aseed[d][0]->get_nzref(f_sp, r_nz);
550 asens[d][0] += MX::zeros(f_sp)->get_nzassign(aseed[d][0], r_nz);
552 asens[d][0] += aseed[d][0];
555 asens[d][0] += aseed[d][0];
562 int SetNonzerosVector<Add>::
563 eval(
const double** arg,
double** res, casadi_int* iw,
double* w)
const {
564 return eval_gen<double>(arg, res, iw, w);
568 int SetNonzerosVector<Add>::
569 eval_sx(
const SXElem** arg, SXElem** res, casadi_int* iw, SXElem* w)
const {
570 return eval_gen<SXElem>(arg, res, iw, w);
575 int SetNonzerosVector<Add>::
576 eval_gen(
const T** arg, T** res, casadi_int* iw, T* w)
const {
577 const T* idata0 = arg[0];
578 const T* idata = arg[1];
580 if (idata0 != odata) {
581 std::copy(idata0, idata0+this->dep(0).nnz(), odata);
583 for (
auto k=this->nz_.begin(); k!=this->nz_.end(); ++k, ++idata) {
585 if (*k>=0) odata[*k] += *idata;
587 if (*k>=0) odata[*k] = *idata;
594 int SetNonzerosSlice<Add>::
595 eval(
const double** arg,
double** res, casadi_int* iw,
double* w)
const {
596 return eval_gen<double>(arg, res, iw, w);
600 int SetNonzerosSlice<Add>::
601 eval_sx(
const SXElem** arg, SXElem** res, casadi_int* iw, SXElem* w)
const {
602 return eval_gen<SXElem>(arg, res, iw, w);
607 int SetNonzerosSlice<Add>::
608 eval_gen(
const T** arg, T** res, casadi_int* iw, T* w)
const {
609 const T* idata0 = arg[0];
610 const T* idata = arg[1];
612 if (idata0 != odata) {
613 std::copy(idata0, idata0+this->dep(0).nnz(), odata);
615 T* odata_stop = odata + s_.stop;
616 for (odata += s_.start; odata != odata_stop; odata += s_.step) {
627 int SetNonzerosSlice2<Add>::
628 eval(
const double** arg,
double** res, casadi_int* iw,
double* w)
const {
629 return eval_gen<double>(arg, res, iw, w);
633 int SetNonzerosSlice2<Add>::
634 eval_sx(
const SXElem** arg, SXElem** res, casadi_int* iw, SXElem* w)
const {
635 return eval_gen<SXElem>(arg, res, iw, w);
640 int SetNonzerosSlice2<Add>::
641 eval_gen(
const T** arg, T** res, casadi_int* iw, T* w)
const {
642 const T* idata0 = arg[0];
643 const T* idata = arg[1];
645 if (idata0 != odata) {
646 std::copy(idata0, idata0 + this->dep(0).nnz(), odata);
648 T* outer_stop = odata + outer_.stop;
649 T* outer = odata + outer_.start;
650 for (; outer != outer_stop; outer += outer_.step) {
651 for (T* inner = outer+inner_.start;
652 inner != outer+inner_.stop;
653 inner += inner_.step) {
665 int SetNonzerosVector<Add>::
666 sp_forward(
const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w)
const {
667 const bvec_t *a0 = arg[0];
668 const bvec_t *a = arg[1];
670 casadi_int n = this->nnz();
673 if (r != a0) std::copy(a0, a0+n, r);
674 for (
auto k=this->nz_.begin(); k!=this->nz_.end(); ++k, ++a) {
676 if (*k>=0) r[*k] |= *a;
678 if (*k>=0) r[*k] = *a;
685 int SetNonzerosVector<Add>::
686 sp_reverse(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w)
const {
689 for (
auto k=this->nz_.begin(); k!=this->nz_.end(); ++k, ++a) {
697 MXNode::copy_rev(arg[0], r, this->nnz());
702 int SetNonzerosSlice<Add>::
703 sp_forward(
const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w)
const {
704 const bvec_t *a0 = arg[0];
705 const bvec_t *a = arg[1];
707 casadi_int n = this->nnz();
710 if (r != a0) std::copy(a0, a0+n, r);
711 for (casadi_int k=s_.start; k!=s_.stop; k+=s_.step) {
722 int SetNonzerosSlice<Add>::
723 sp_reverse(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w)
const {
726 for (casadi_int k=s_.start; k!=s_.stop; k+=s_.step) {
732 MXNode::copy_rev(arg[0], r, this->nnz());
737 int SetNonzerosSlice2<Add>::
738 sp_forward(
const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w)
const {
739 const bvec_t *a0 = arg[0];
740 const bvec_t *a = arg[1];
742 casadi_int n = this->nnz();
745 if (r != a0) std::copy(a0, a0+n, r);
746 for (casadi_int k1=outer_.start; k1!=outer_.stop; k1+=outer_.step) {
747 for (casadi_int k2=k1+inner_.start; k2!=k1+inner_.stop; k2+=inner_.step) {
759 int SetNonzerosSlice2<Add>::
760 sp_reverse(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w)
const {
763 for (casadi_int k1=outer_.start; k1!=outer_.stop; k1+=outer_.step) {
764 for (casadi_int k2=k1+inner_.start; k2!=k1+inner_.stop; k2+=inner_.step) {
771 MXNode::copy_rev(arg[0], r, this->nnz());
776 std::string SetNonzerosVector<Add>::disp(
const std::vector<std::string>& arg)
const {
777 std::stringstream ss;
778 ss <<
"(" << arg.at(0) << nz_ << (Add ?
" += " :
" = ") << arg.at(1) <<
")";
783 std::string SetNonzerosSlice<Add>::disp(
const std::vector<std::string>& arg)
const {
784 std::stringstream ss;
785 ss <<
"(" << arg.at(0) <<
"[" << s_ <<
"]" << (Add ?
" += " :
" = ") << arg.at(1) <<
")";
790 std::string SetNonzerosSlice2<Add>::disp(
const std::vector<std::string>& arg)
const {
791 std::stringstream ss;
792 ss <<
"(" << arg.at(0) <<
"[" << outer_ <<
";" << inner_ <<
"]" << (Add ?
" += " :
" = ")
798 Matrix<casadi_int> SetNonzeros<Add>::mapping()
const {
799 std::vector<casadi_int> nz = all();
800 return Matrix<casadi_int>(this->dep(1).sparsity(), nz,
false);
804 bool SetNonzerosVector<Add>::is_equal(
const MXNode* node, casadi_int depth)
const {
806 if (!this->sameOpAndDeps(node, depth))
return false;
809 const SetNonzerosVector<Add>* n =
dynamic_cast<const SetNonzerosVector<Add>*
>(node);
810 if (n==
nullptr)
return false;
813 if (this->sparsity()!=node->sparsity())
return false;
816 if (this->nz_.size()!=n->nz_.size())
return false;
817 if (!std::equal(this->nz_.begin(), this->nz_.end(), n->nz_.begin()))
return false;
823 bool SetNonzerosSlice<Add>::is_equal(
const MXNode* node, casadi_int depth)
const {
825 if (!this->sameOpAndDeps(node, depth))
return false;
828 const SetNonzerosSlice<Add>* n =
dynamic_cast<const SetNonzerosSlice<Add>*
>(node);
829 if (n==
nullptr)
return false;
832 if (this->sparsity()!=node->sparsity())
return false;
835 if (this->s_ != n->s_)
return false;
841 bool SetNonzerosSlice2<Add>::is_equal(
const MXNode* node, casadi_int depth)
const {
843 if (!this->sameOpAndDeps(node, depth))
return false;
846 const SetNonzerosSlice2<Add>* n =
dynamic_cast<const SetNonzerosSlice2<Add>*
>(node);
847 if (n==
nullptr)
return false;
850 if (this->sparsity()!=node->sparsity())
return false;
853 if (this->inner_ != n->inner_ || this->outer_!=n->outer_)
return false;
859 void SetNonzerosVector<Add>::
860 generate(CodeGenerator& g,
861 const std::vector<casadi_int>& arg,
const std::vector<casadi_int>& res)
const {
863 if (arg[0]!=res[0]) {
864 g << g.copy(g.work(arg[0], this->dep(0).nnz()), this->nnz(),
865 g.work(res[0], this->nnz())) <<
'\n';
869 std::string ind = g.constant(this->nz_);
872 g.local(
"cii",
"const casadi_int",
"*");
873 g.local(
"rr",
"casadi_real",
"*");
874 g.local(
"ss",
"casadi_real",
"*");
875 g <<
"for (cii=" << ind <<
", rr=" << g.work(res[0], this->nnz()) <<
", "
876 <<
"ss=" << g.work(arg[1], this->dep(1).nnz()) <<
"; cii!=" << ind
877 <<
"+" << this->nz_.size() <<
"; ++cii, ++ss) ";
879 g <<
"if (*cii>=0) ";
881 g <<
"rr[*cii] " << (Add?
"+=":
"=") <<
" *ss;\n";
885 void SetNonzerosSlice<Add>::
886 generate(CodeGenerator& g,
887 const std::vector<casadi_int>& arg,
const std::vector<casadi_int>& res)
const {
889 if (arg[0]!=res[0]) {
890 g << g.copy(g.work(arg[0], this->dep(0).nnz()), this->nnz(),
891 g.work(res[0], this->nnz())) <<
'\n';
895 g.local(
"rr",
"casadi_real",
"*");
896 g.local(
"ss",
"casadi_real",
"*");
897 g <<
"for (rr=" << g.work(res[0], this->nnz()) <<
"+" << s_.start <<
", ss="
898 << g.work(arg[1], this->dep(1).nnz()) <<
"; rr!="
899 << g.work(res[0], this->nnz()) <<
"+" << s_.stop
900 <<
"; rr+=" << s_.step <<
")"
901 <<
" *rr " << (Add?
"+=":
"=") <<
" *ss++;\n";
905 void SetNonzerosSlice2<Add>::
906 generate(CodeGenerator& g,
907 const std::vector<casadi_int>& arg,
const std::vector<casadi_int>& res)
const {
909 if (arg[0]!=res[0]) {
910 g << g.copy(g.work(arg[0], this->dep(0).nnz()), this->nnz(),
911 g.work(res[0], this->nnz())) <<
'\n';
915 g.local(
"rr",
"casadi_real",
"*");
916 g.local(
"ss",
"casadi_real",
"*");
917 g.local(
"tt",
"casadi_real",
"*");
918 g <<
"for (rr=" << g.work(res[0], this->nnz()) <<
"+" << outer_.start
919 <<
", ss=" << g.work(arg[1], this->dep(1).nnz()) <<
"; rr!="
920 << g.work(res[0], this->nnz()) <<
"+" << outer_.stop
921 <<
"; rr+=" << outer_.step <<
")"
922 <<
" for (tt=rr+" << inner_.start <<
"; tt!=rr+" << inner_.stop
923 <<
"; tt+=" << inner_.step <<
")"
924 <<
" *tt " << (Add?
"+=":
"=") <<
" *ss++;\n";
928 void SetNonzerosVector<Add>::serialize_body(SerializingStream& s)
const {
929 MXNode::serialize_body(s);
930 s.pack(
"SetNonzerosVector::nonzeros", nz_);
934 SetNonzerosVector<Add>::SetNonzerosVector(DeserializingStream& s) : SetNonzeros<Add>(s) {
935 s.unpack(
"SetNonzerosVector::nonzeros", nz_);
939 void SetNonzerosVector<Add>::serialize_type(SerializingStream& s)
const {
940 MXNode::serialize_type(s);
941 s.pack(
"SetNonzeros::type",
'a');
945 void SetNonzerosSlice<Add>::serialize_body(SerializingStream& s)
const {
946 MXNode::serialize_body(s);
947 s.pack(
"SetNonzerosSlice::slice", s_);
951 SetNonzerosSlice<Add>::SetNonzerosSlice(DeserializingStream& s) : SetNonzeros<Add>(s) {
952 s.unpack(
"SetNonzerosSlice::slice", s_);
956 void SetNonzerosSlice<Add>::serialize_type(SerializingStream& s)
const {
957 MXNode::serialize_type(s);
958 s.pack(
"SetNonzeros::type",
'b');
962 void SetNonzerosSlice2<Add>::serialize_body(SerializingStream& s)
const {
963 MXNode::serialize_body(s);
964 s.pack(
"SetNonzerosSlice2::inner", inner_);
965 s.pack(
"SetNonzerosSlice2::outer", outer_);
969 SetNonzerosSlice2<Add>::SetNonzerosSlice2(DeserializingStream& s) : SetNonzeros<Add>(s) {
970 s.unpack(
"SetNonzerosSlice2::inner", inner_);
971 s.unpack(
"SetNonzerosSlice2::outer", outer_);
975 void SetNonzerosSlice2<Add>::serialize_type(SerializingStream& s)
const {
976 MXNode::serialize_type(s);
977 s.pack(
"SetNonzeros::type",
'c');
981 MXNode* SetNonzeros<Add>::deserialize(DeserializingStream& s) {
983 s.unpack(
"SetNonzeros::type", t);
985 case 'a':
return new SetNonzerosVector<Add>(s);
986 case 'b':
return new SetNonzerosSlice<Add>(s);
987 case 'c':
return new SetNonzerosSlice2<Add>(s);
988 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.