25 #ifndef CASADI_MATRIX_IMPL_HPP
26 #define CASADI_MATRIX_IMPL_HPP
32 #include "sx_node.hpp"
35 #include "serializing_stream.hpp"
36 #include "blas_impl.hpp"
39 template<
typename Scalar>
42 template<
typename Scalar>
45 template<
typename Scalar>
48 template<
typename Scalar>
51 template<
typename Scalar>
54 template<
typename Scalar>
57 template<
typename Scalar>
59 template<
typename Scalar>
61 template<
typename Scalar>
64 template<
typename Scalar>
67 std::chrono::system_clock::now().time_since_epoch().count());
69 template<
typename Scalar>
74 template<
typename Scalar>
76 return sparsity().has_nz(rr, cc);
79 template<
typename Scalar>
82 casadi_error(
"Only scalar Matrix could have a truth value, but you "
83 "provided a shape" + dim());
85 return nonzeros().at(0)!=0;
88 template<
typename Scalar>
93 casadi_int k = sparsity().get_nz(rr.
scalar(size1()), cc.
scalar(size2()));
103 get(m, ind1, rr.
all(size1(), ind1), cc.
all(size2(), ind1));
106 template<
typename Scalar>
110 get(m, ind1, rr.
all(size1(), ind1), cc);
113 template<
typename Scalar>
117 get(m, ind1, rr, cc.
all(size2(), ind1));
120 template<
typename Scalar>
130 "Marix::get: First index must be a dense vector");
132 "Marix::get: Second index must be a dense vector");
135 std::vector<casadi_int> mapping;
136 Sparsity sp = sparsity().
sub(rr.nonzeros(), cc.nonzeros(), mapping, ind1);
140 for (casadi_int k=0; k<mapping.size(); ++k) m->at(k) = nonzeros().at(mapping[k]);
143 template<
typename Scalar>
147 casadi_int r = rr.
scalar(numel());
148 casadi_int k = sparsity().get_nz(r % size1(), r / size1());
150 m = nonzeros().at(k);
158 get(m, ind1, rr.
all(numel(), ind1));
161 template<
typename Scalar>
165 return get(m, ind1,
to_slice(rr, ind1));
170 return get_nz(m, ind1, rr);
174 std::vector<casadi_int> mapping;
178 bool tr = (is_column() && rr.
is_row()) || (is_row() && rr.
is_column());
182 for (casadi_int k=0; k<mapping.size(); ++k) m->at(k) = nonzeros().at(mapping[k]);
185 template<
typename Scalar>
187 casadi_assert(size()==sp.
size(),
188 "Shape mismatch. This matrix has shape "
189 + str(size()) +
", but supplied sparsity index has shape "
190 + str(sp.
size()) +
".");
191 m = project(*
this, sp);
194 template<
typename Scalar>
199 casadi_int oldsize = sparsity_.nnz();
200 casadi_int ind = sparsity_.add_nz(rr.
scalar(size1()), cc.
scalar(size2()));
201 if (oldsize == sparsity_.nnz()) {
202 nonzeros_.at(ind) = m.scalar();
204 nonzeros_.insert(nonzeros_.begin()+ind, m.scalar());
210 set(m, ind1, rr.
all(size1(), ind1), cc.
all(size2(), ind1));
213 template<
typename Scalar>
217 set(m, ind1, rr.
all(size1(), ind1), cc);
220 template<
typename Scalar>
224 set(m, ind1, rr, cc.
all(size2(), ind1));
227 template<
typename Scalar>
237 return set(m, ind1, rr.
T(), cc);
242 return set(m, ind1, rr, cc.
T());
247 "Matrix::set: First index not dense vector");
249 "Matrix::set: Second index not dense vector");
255 return set(repmat(m, rr.
size1(), cc.
size1()), ind1, rr, cc);
259 return set(m.
T(), ind1, rr, cc);
262 casadi_error(
"Dimension mismatch. lhs is " + str(rr.
size1()) +
"-by-"
263 + str(cc.
size1()) +
", while rhs is " + str(m.
size()));
268 casadi_int sz1 = size1(), sz2 = size2();
271 casadi_assert_in_range(rr.nonzeros(), -sz1+ind1, sz1+ind1);
272 casadi_assert_in_range(cc.nonzeros(), -sz2+ind1, sz2+ind1);
276 erase(rr.nonzeros(), cc.nonzeros(), ind1);
281 for (casadi_int j=0; j<el.
size2(); ++j) {
282 casadi_int this_j = cc->at(j) - ind1;
283 if (this_j<0) this_j += sz2;
284 for (casadi_int k=el.
colind(j); k<el.
colind(j+1); ++k) {
285 casadi_int i = m.
row(k);
286 casadi_int this_i = rr->at(i) - ind1;
287 if (this_i<0) this_i += sz1;
288 el->at(k) = this_i + this_j*sz1;
291 return set(m,
false, el);
294 template<
typename Scalar>
298 casadi_int r = rr.
scalar(numel());
299 casadi_int oldsize = sparsity_.nnz();
300 casadi_int ind = sparsity_.add_nz(r % size1(), r / size1());
301 if (oldsize == sparsity_.nnz()) {
302 nonzeros_.at(ind) = m.scalar();
304 nonzeros_.insert(nonzeros_.begin()+ind, m.scalar());
310 set(m, ind1, rr.
all(numel(), ind1));
313 template<
typename Scalar>
317 return set(m, ind1,
to_slice(rr, ind1));
324 erase(rr.nonzeros(), ind1);
341 return set(m.
T(), ind1, rr);
344 casadi_error(
"Dimension mismatch. lhs is " + str(rr.
size())
345 +
", while rhs is " + str(m.
size()));
350 casadi_int sz1 = size1(), sz2 = size2(), sz = nnz(), nel = numel(), rrsz = rr.
nnz();
356 casadi_assert_in_range(rr.nonzeros(), -nel+ind1, nel+ind1);
360 return set_nz(m, ind1, rr);
364 std::vector<casadi_int> new_row =
365 sparsity().get_row(), new_col=sparsity().get_col(), nz(rr.nonzeros());
366 new_row.reserve(sz+rrsz);
367 new_col.reserve(sz+rrsz);
369 for (std::vector<casadi_int>::iterator i=nz.begin(); i!=nz.end(); ++i) {
372 new_row.push_back(*i % sz1);
373 new_col.push_back(*i / sz1);
378 if (sp != sparsity()) *
this = project(*
this, sp);
381 sparsity().get_nz(nz);
384 for (casadi_int i=0; i<nz.size(); ++i) {
385 nonzeros().at(nz[i]) = m->at(i);
389 template<
typename Scalar>
391 casadi_assert(size()==sp.
size(),
392 "set(Sparsity sp): shape mismatch. This matrix has shape "
393 + str(size()) +
", but supplied sparsity index has shape "
394 + str(sp.
size()) +
".");
395 std::vector<casadi_int> ii = sp.
find();
397 (*this)(ii) = densify(m);
399 (*this)(ii) = densify(m(ii));
403 template<
typename Scalar>
407 m = nonzeros().at(kk.
scalar(nnz()));
412 get_nz(m, ind1, kk.
all(nnz(), ind1));
415 template<
typename Scalar>
419 return get_nz(m, ind1,
to_slice(kk, ind1));
423 const std::vector<casadi_int>& k = kk.nonzeros();
424 casadi_int sz = nnz();
427 casadi_assert_in_range(k, -sz+ind1, sz+ind1);
430 bool tr = (is_column() && kk.
is_row()) || (is_row() && kk.
is_column());
434 for (casadi_int el=0; el<k.
size(); ++el) {
435 casadi_assert(!(ind1 && k[el]<=0),
"Matlab is 1-based, but requested index "
436 + str(k[el]) +
". Note that negative slices are"
437 " disabled in the Matlab interface. "
438 "Possibly you may want to use 'end'.");
439 casadi_int k_el = k[el]-ind1;
440 m->at(el) = nonzeros().at(k_el>=0 ? k_el : k_el+sz);
444 template<
typename Scalar>
448 nonzeros().at(kk.
scalar(nnz())) = m.scalar();
453 set_nz(m, ind1, kk.
all(nnz(), ind1));
456 template<
typename Scalar>
460 return set_nz(m, ind1,
to_slice(kk, ind1));
471 return set_nz(project(m, kk.
sparsity()), ind1, kk);
475 return set_nz(m.
T(), ind1, kk);
478 casadi_error(
"Dimension mismatch. lhs is " + str(kk.
size())
479 +
", while rhs is " + str(m.
size()));
484 const std::vector<casadi_int>& k = kk.nonzeros();
485 casadi_int sz = nnz();
488 casadi_assert_in_range(k, -sz+ind1, sz+ind1);
491 for (casadi_int el=0; el<k.
size(); ++el) {
492 casadi_assert(!(ind1 && k[el]<=0),
493 "Matlab is 1-based, but requested index " + str(k[el])
494 +
". Note that negative slices are disabled in the Matlab interface. "
495 "Possibly you may want to use 'end'.");
496 casadi_int k_el = k[el]-ind1;
497 nonzeros().at(k_el>=0 ? k_el : k_el+sz) = m->at(el);
501 template<
typename Scalar>
503 return densify(x, 0);
506 template<
typename Scalar>
508 const Matrix<Scalar>& val) {
510 casadi_assert_dev(val.is_scalar());
513 if (x.is_dense())
return x;
516 casadi_int nrow = x.size1();
517 casadi_int ncol = x.size2();
518 const casadi_int* colind = x.colind();
519 const casadi_int* row = x.row();
520 auto it = x.nonzeros().cbegin();
523 std::vector<Scalar> d(nrow*ncol, val.scalar());
526 for (casadi_int cc=0; cc<ncol; ++cc) {
527 for (casadi_int el=colind[cc]; el<colind[cc+1]; ++el) {
528 d[cc*nrow + row[el]] = *it++;
536 template<
typename Scalar>
538 if (axis==-1) axis = x.is_row();
539 Matrix<Scalar> ret = x;
541 for (casadi_int i=1;i<x.size1();++i)
542 ret(i, Slice()) += ret(i-1, Slice());
544 for (casadi_int i=1;i<x.size2();++i)
545 ret(Slice(), i) += ret(Slice(), i-1);
550 template<
typename Scalar>
552 const Matrix<Scalar>& A,
const Matrix<Scalar>& B,
const Matrix<Scalar>& C,
553 const std::vector<casadi_int>& dim_a,
const std::vector<casadi_int>& dim_b,
554 const std::vector<casadi_int>& dim_c,
555 const std::vector<casadi_int>& a,
const std::vector<casadi_int>& b,
556 const std::vector<casadi_int>& c) {
557 std::vector<casadi_int> iter_dims;
558 std::vector<casadi_int> strides_a;
559 std::vector<casadi_int> strides_b;
560 std::vector<casadi_int> strides_c;
562 iter_dims, strides_a, strides_b, strides_c);
564 const std::vector<Scalar>& Av = A.nonzeros();
565 const std::vector<Scalar>& Bv = B.nonzeros();
567 Matrix<Scalar> ret =
C;
568 std::vector<Scalar>& Cv = ret.nonzeros();
570 einstein_eval(n_iter, iter_dims, strides_a, strides_b, strides_c,
571 get_ptr(Av), get_ptr(Bv), get_ptr(Cv));
575 template<
typename Scalar>
577 const std::vector<casadi_int>& dim_a,
const std::vector<casadi_int>& dim_b,
578 const std::vector<casadi_int>& dim_c,
579 const std::vector<casadi_int>& a,
const std::vector<casadi_int>& b,
580 const std::vector<casadi_int>& c) {
582 dim_a, dim_b, dim_c, a, b, c);
585 template<
typename Scalar>
589 template<
typename Scalar>
593 template<
typename Scalar>
595 sparsity_(
Sparsity::dense(x.size(), 1)), nonzeros_(x) {
598 template<
typename Scalar>
600 sparsity_ = m.sparsity_;
601 nonzeros_ = m.nonzeros_;
605 template<
typename Scalar>
606 std::vector<Scalar>* Matrix<Scalar>::operator->() {
610 template<
typename Scalar>
611 const std::vector<Scalar>* Matrix<Scalar>::operator->()
const {
615 template<
typename Scalar>
618 template<
typename Scalar>
620 casadi_assert(numel()==1,
"Not a scalar");
624 stream.precision(stream_precision_);
625 stream.width(stream_width_);
626 if (stream_scientific_) {
627 stream.setf(std::ios::scientific);
629 stream.unsetf(std::ios::scientific);
637 stream << std::flush;
640 template<
typename Scalar>
642 print_vector(stream, sparsity(), ptr(), truncate);
645 template<
typename Scalar>
647 const Scalar* nonzeros,
bool truncate) {
648 casadi_assert(sp.
is_column(),
"Not a vector");
651 std::vector<std::string> nz, inter;
652 print_split(sp.
nnz(), nonzeros, nz, inter);
655 for (casadi_int i=0; i<inter.size(); ++i)
656 stream <<
"@" << (i+1) <<
"=" << inter[i] <<
", ";
660 const casadi_int* row = sp.
row();
661 casadi_int nnz = sp.
nnz();
662 casadi_int size1 = sp.
size1();
665 const casadi_int max_numel = 1000;
666 if (truncate && size1<=max_numel) truncate=
false;
673 for (casadi_int rr=0; rr<size1; ++rr) {
675 std::string s = el<nnz && rr==row[el] ? nz.at(el++) :
"00";
678 if (truncate && rr>=3 && rr<size1-3) {
680 if (rr==3) stream <<
", ...";
683 if (rr!=0) stream <<
", ";
687 stream <<
"]" << std::flush;
690 template<
typename Scalar>
692 print_dense(stream, sparsity(), ptr(), truncate);
695 template<
typename Scalar>
697 print_sparse(stream, sparsity(), ptr(), truncate);
700 template<
typename Scalar>
702 std::vector<std::string>& inter)
const {
704 print_split(nnz(), ptr(), nz, inter);
707 template<
typename Scalar>
709 const Scalar* nonzeros,
bool truncate) {
712 }
else if (sp.
numel()==1) {
716 print_scalar(stream, *nonzeros);
719 print_vector(stream, sp, nonzeros, truncate);
720 }
else if (std::max(sp.
size1(), sp.
size2())<=10 ||
721 static_cast<double>(sp.
nnz())/
static_cast<double>(sp.
numel())>=0.5) {
723 print_dense(stream, sp, nonzeros, truncate);
725 print_sparse(stream, sp, nonzeros, truncate);
729 template<
typename Scalar>
730 void Matrix<Scalar>::print_canonical(std::ostream &stream,
const Sparsity& sp,
731 const Scalar* nonzeros,
bool truncate) {
732 casadi_error(
"'print_canonical' not defined for " + type_name());
735 template<
typename Scalar>
737 std::streamsize precision = stream.precision();
738 std::streamsize width = stream.width();
739 std::ios_base::fmtflags flags = stream.flags();
741 stream.precision(stream_precision_);
742 stream.width(stream_width_);
743 if (stream_scientific_) {
744 stream.setf(std::ios::scientific);
746 stream.unsetf(std::ios::scientific);
749 stream << std::flush;
751 stream.precision(precision);
756 template<
typename Scalar>
758 std::vector<std::string>& nz,
759 std::vector<std::string>& inter) {
764 std::stringstream ss;
765 ss.precision(stream_precision_);
766 ss.width(stream_width_);
767 if (stream_scientific_) {
768 ss.setf(std::ios::scientific);
770 ss.unsetf(std::ios::scientific);
774 for (casadi_int i=0; i<nz.size(); ++i) {
775 ss.str(std::string());
781 template<
typename Scalar>
783 const Scalar* nonzeros,
bool truncate) {
785 casadi_int size1 = sp.size1();
786 casadi_int size2 = sp.size2();
787 const casadi_int* colind = sp.colind();
788 const casadi_int* row = sp.row();
789 casadi_int nnz = sp.nnz();
793 stream <<
"all zero sparse: " << size1 <<
"-by-" << size2 << std::flush;
798 stream <<
"sparse: " << size1 <<
"-by-" << size2 <<
", " << nnz <<
" nnz";
801 std::vector<std::string> nz, inter;
802 print_split(nnz, nonzeros, nz, inter);
805 for (casadi_int i=0; i<inter.size(); ++i)
806 stream << std::endl <<
" @" << (i+1) <<
"=" << inter[i] <<
",";
810 const casadi_int max_nnz = 1000;
811 if (truncate && nnz<=max_nnz) truncate=
false;
814 for (casadi_int cc=0; cc<size2; ++cc) {
815 for (casadi_int el=colind[cc]; el<colind[cc+1]; ++el) {
816 if (truncate && el>=3 && el<nnz-3) {
817 if (el==3) stream << std::endl <<
" ...";
819 stream << std::endl <<
" (" << row[el] <<
", " << cc <<
") -> " << nz.at(el);
820 InterruptHandler::check();
824 stream << std::flush;
827 template<
typename Scalar>
829 const Scalar* nonzeros,
bool truncate) {
831 std::vector<std::string> nz, inter;
832 print_split(sp.nnz(), nonzeros, nz, inter);
835 for (casadi_int i=0; i<inter.size(); ++i)
836 stream <<
"@" << (i+1) <<
"=" << inter[i] <<
", ";
840 casadi_int size1 = sp.size1();
841 casadi_int size2 = sp.size2();
842 const casadi_int* colind = sp.colind();
843 const casadi_int* row = sp.row();
846 const casadi_int max_numel = 1000;
847 if (truncate && size1*size2<=max_numel) truncate=
false;
850 bool truncate_rows = truncate && size1>=7;
851 bool truncate_columns = truncate && size2>=7;
854 std::vector<casadi_int> ind(colind, colind+size2+1);
857 bool oneliner=size1<=1;
860 for (casadi_int rr=0; rr<size1; ++rr) {
862 bool print_row = !(truncate_rows && rr>=3 && rr<size1-3);
866 if (!oneliner) stream << std::endl;
868 }
else if (print_row) {
873 for (casadi_int cc=0; cc<size2; ++cc) {
875 std::string s = ind[cc]<colind[cc+1] && row[ind[cc]]==rr
876 ? nz.at(ind[cc]++) :
"00";
879 if (!print_row)
continue;
882 bool print_column = !(truncate_columns && cc>=3 && cc<size2-3);
886 if (cc!=0) stream <<
", ";
897 if (!oneliner) stream << std::endl;
899 stream <<
" ...," << std::endl;
905 stream << std::flush;
908 template<
typename Scalar>
910 to_file(filename, sparsity(), ptr(), format);
913 template<
typename Scalar>
915 print_default(stream, sparsity(), ptr());
918 template<
typename Scalar>
920 std::stringstream ss;
925 template<
typename Scalar>
927 reserve(nnz, size2());
930 template<
typename Scalar>
932 nonzeros().reserve(nnz);
935 template<
typename Scalar>
937 sparsity_.resize(nrow, ncol);
940 template<
typename Scalar>
942 sparsity_ = Sparsity(0, 0);
946 template<
typename Scalar>
950 nonzeros_(std::vector<Scalar>(1, static_cast<Scalar>(val))) {
953 template<
typename Scalar>
956 casadi_int nrow=d.
size();
957 casadi_int ncol=d.empty() ? 1 : d.front().size();
960 for (casadi_int rr=0; rr<nrow; ++rr) {
961 casadi_assert(ncol==d[rr].size(),
963 "Attempting to construct a matrix from a nested list.\n"
964 "I got convinced that the desired size is (" + str(nrow) +
" x " + str(ncol)
965 +
" ), but now I encounter a vector of size (" + str(d[rr].size()) +
" )");
969 sparsity_ = Sparsity::dense(nrow, ncol);
970 nonzeros().resize(nrow*ncol);
971 typename std::vector<Scalar>::iterator it=nonzeros_.begin();
972 for (casadi_int cc=0; cc<ncol; ++cc) {
973 for (casadi_int rr=0; rr<nrow; ++rr) {
974 *it++ =
static_cast<Scalar
>(d[rr][cc]);
979 template<
typename Scalar>
983 template<
typename Scalar>
984 Matrix<Scalar>::Matrix(casadi_int nrow, casadi_int ncol) : sparsity_(nrow, ncol) {
987 template<
typename Scalar>
988 Matrix<Scalar>::Matrix(
const std::pair<casadi_int, casadi_int>& rc) : sparsity_(rc) {
991 template<
typename Scalar>
992 Matrix<Scalar>::Matrix(
const Sparsity& sp,
const Scalar& val,
bool dummy) :
993 sparsity_(sp), nonzeros_(sp.nnz(), val) {
996 template<
typename Scalar>
997 Matrix<Scalar>::Matrix(
const Sparsity& sp,
const std::vector<Scalar>& d,
bool dummy) :
998 sparsity_(sp), nonzeros_(d) {
999 casadi_assert(sp.nnz()==d.size(),
"Size mismatch.\n"
1000 "You supplied a sparsity of " + sp.dim()
1001 +
", but the supplied vector is of length " + str(d.size()));
1004 template<
typename Scalar>
1005 Matrix<Scalar>::Matrix(
const Sparsity& sp,
const Matrix<Scalar>& d) {
1006 if (d.is_scalar()) {
1007 *
this = Matrix<Scalar>(sp, d.scalar(),
false);
1008 }
else if (sp.nnz()==0) {
1009 casadi_assert(d.nnz()==0,
1010 "You passed nonzeros (" + d.dim(
true) +
1011 ") to the constructor of a fully sparse matrix (" + sp.dim(
true) +
").");
1012 *
this = Matrix<Scalar>(sp);
1013 }
else if (d.is_column() || d.size1()==1) {
1014 casadi_assert_dev(sp.nnz()==d.numel());
1016 *
this = Matrix<Scalar>(sp, d.nonzeros(),
false);
1018 *
this = Matrix<Scalar>(sp, densify(d).nonzeros(),
false);
1021 casadi_error(
"Matrix(Sparsity, Matrix): Only allowed for scalars and vectors");
1025 template<
typename Scalar>
1026 Matrix<Scalar> Matrix<Scalar>::unary(casadi_int op,
const Matrix<Scalar> &x) {
1028 Matrix<Scalar> ret = Matrix<Scalar>::zeros(x.sparsity());
1031 std::vector<Scalar>& ret_data = ret.nonzeros();
1032 const std::vector<Scalar>& x_data = x.nonzeros();
1035 for (casadi_int el=0; el<x.nnz(); ++el) {
1036 casadi_math<Scalar>::fun(op, x_data[el], x_data[el], ret_data[el]);
1040 if (!x.is_dense() && !operation_checker<F0XChecker>(op)) {
1043 casadi_math<Scalar>::fun(op, 0, 0, fcn_0);
1044 if (!casadi_limits<Scalar>::is_zero(fcn_0)) {
1045 ret = densify(ret, fcn_0);
1052 template<
typename Scalar>
1053 Matrix<Scalar> Matrix<Scalar>::operator-()
const {
1054 return unary(OP_NEG, *
this);
1057 template<
typename Scalar>
1058 Matrix<Scalar> Matrix<Scalar>::operator+()
const {
1062 template<
typename Scalar>
1063 Matrix<Scalar> Matrix<Scalar>::mrdivide(
const Matrix<Scalar>& b,
1064 const Matrix<Scalar>& a) {
1065 if (a.is_scalar() || b.is_scalar())
return b/a;
1066 return solve(a.T(), b.T()).T();
1069 template<
typename Scalar>
1070 Matrix<Scalar> Matrix<Scalar>::mldivide(
const Matrix<Scalar>& a,
1071 const Matrix<Scalar>& b) {
1072 if (a.is_scalar() || b.is_scalar())
return b/a;
1076 template<
typename Scalar>
1077 Matrix<Scalar> Matrix<Scalar>::printme(
const Matrix<Scalar>& y)
const {
1078 return binary(OP_PRINTME, *
this, y);
1081 template<
typename Scalar>
1082 void Matrix<Scalar>::erase(
const std::vector<casadi_int>& rr,
1083 const std::vector<casadi_int>& cc,
bool ind1) {
1085 std::vector<casadi_int> mapping = sparsity_.erase(rr, cc, ind1);
1088 for (casadi_int k=0; k<mapping.size(); ++k)
1089 nonzeros()[k] = nonzeros()[mapping[k]];
1092 nonzeros().resize(mapping.size());
1095 template<
typename Scalar>
1096 void Matrix<Scalar>::erase(
const std::vector<casadi_int>& rr,
bool ind1) {
1098 std::vector<casadi_int> mapping = sparsity_.erase(rr, ind1);
1101 for (casadi_int k=0; k<mapping.size(); ++k)
1102 nonzeros()[k] = nonzeros()[mapping[k]];
1105 nonzeros().resize(mapping.size());
1108 template<
typename Scalar>
1109 void Matrix<Scalar>::remove(
const std::vector<casadi_int>& rr,
1110 const std::vector<casadi_int>& cc) {
1111 casadi_assert_bounded(rr, size1());
1112 casadi_assert_bounded(cc, size2());
1115 std::vector<casadi_int> rrc =
complement(rr, size1());
1116 std::vector<casadi_int> ccc =
complement(cc, size2());
1118 Matrix<Scalar> ret = (*this)(rrc, ccc);
1124 template<
typename Scalar>
1125 void Matrix<Scalar>::enlarge(casadi_int nrow, casadi_int ncol,
const std::vector<casadi_int>& rr,
1126 const std::vector<casadi_int>& cc,
bool ind1) {
1127 sparsity_.enlarge(nrow, ncol, rr, cc, ind1);
1130 template<
typename Scalar>
1131 const Sparsity& Matrix<Scalar>::sparsity()
const {
1135 template<
typename Scalar>
1136 std::vector<Scalar>& Matrix<Scalar>::nonzeros() {
1140 template<
typename Scalar>
1141 const std::vector<Scalar>& Matrix<Scalar>::nonzeros()
const {
1145 template<
typename Scalar>
1146 Scalar* Matrix<Scalar>::ptr() {
1147 return nonzeros_.empty() ? nullptr : &nonzeros_.front();
1150 template<
typename Scalar>
1151 const Scalar* Matrix<Scalar>::ptr()
const {
1152 return nonzeros_.empty() ? nullptr : &nonzeros_.front();
1155 template<
typename Scalar>
1156 Sparsity Matrix<Scalar>::get_sparsity()
const {
1160 template<
typename Scalar>
1161 Matrix<Scalar> Matrix<Scalar>::mtimes(
const Matrix<Scalar> &x,
const Matrix<Scalar> &y,
1162 const std::string& blas) {
1163 if (x.is_scalar() || y.is_scalar()) {
1167 Matrix<Scalar> z = Matrix<Scalar>::zeros(Sparsity::mtimes(x.sparsity(), y.sparsity()));
1168 return mac(x, y, z, blas);
1173 template<
typename T>
1174 inline void mtimes_dense_dispatch(
const std::string& ,
1175 const T* A, casadi_int m, casadi_int k,
1176 const T* B, casadi_int n, T* C) {
1177 casadi_mtimes_dense(A, m, k, B, n, C, 0);
1180 void CASADI_EXPORT mtimes_dense_dispatch<double>(
const std::string& blas,
1182 casadi_int m, casadi_int k,
1183 const double* B, casadi_int n,
1186 template<
typename Scalar>
1187 Matrix<Scalar> Matrix<Scalar>::mac(
const Matrix<Scalar> &x,
1188 const Matrix<Scalar> &y,
1189 const Matrix<Scalar> &z,
1190 const std::string& blas) {
1191 if (x.is_scalar() || y.is_scalar()) {
1197 casadi_assert(x.size2()==y.size1(),
1198 "Matrix product with incompatible dimensions. Lhs is "
1199 + x.dim() +
" and rhs is " + y.dim() +
".");
1201 casadi_assert(y.size2()==z.size2(),
1202 "Matrix addition with incompatible dimensions. Lhs is "
1203 + mtimes(x, y).dim() +
" and rhs is " + z.dim() +
".");
1205 casadi_assert(x.size1()==z.size1(),
1206 "Matrix addition with incompatible dimensions. Lhs is "
1207 + mtimes(x, y).dim() +
" and rhs is " + z.dim() +
".");
1210 if (x.is_eye())
return y + z;
1211 if (y.is_eye())
return x + z;
1212 if (x.is_zero() || y.is_zero())
return z;
1214 Matrix<Scalar> ret = z;
1215 if (x.is_dense() && y.is_dense() && z.is_dense()) {
1218 mtimes_dense_dispatch<Scalar>(blas,
1219 x.ptr(), x.size1(), x.size2(),
1220 y.ptr(), y.size2(), ret.ptr());
1224 std::vector<Scalar> work(x.size1());
1225 casadi_mtimes(x.ptr(), x.sparsity(), y.ptr(), y.sparsity(),
1226 ret.ptr(), ret.sparsity(), get_ptr(work),
false);
1230 template<
typename Scalar>
1231 Matrix<Scalar> Matrix<Scalar>::
1232 _bilin(
const Matrix<Scalar>& A,
const Matrix<Scalar>& x,
1233 const Matrix<Scalar>& y) {
1234 return casadi_bilin(A.ptr(), A.sparsity(), x.ptr(), y.ptr());
1237 template<
typename Scalar>
1238 Matrix<Scalar> Matrix<Scalar>::
1239 _rank1(
const Matrix<Scalar>& A,
const Matrix<Scalar>& alpha,
1240 const Matrix<Scalar>& x,
const Matrix<Scalar>& y) {
1241 Matrix<Scalar> ret = A;
1242 casadi_rank1(ret.ptr(), ret.sparsity(), *alpha.ptr(), x.ptr(), y.ptr());
1247 template<
typename Scalar>
1248 Matrix<Scalar> Matrix<Scalar>::
1249 _logsumexp(
const Matrix<Scalar>& x) {
1250 Matrix<Scalar> mx = mmax(x);
1251 return mx+log(sum1(exp(x-mx)));
1254 template<
typename Scalar>
1255 Matrix<Scalar> Matrix<Scalar>::T()
const {
1257 if ((size1()==0 && size2()==0) || is_scalar())
return *
this;
1260 std::vector<casadi_int> mapping;
1261 Sparsity s = sparsity().transpose(mapping);
1264 Matrix<Scalar> ret = zeros(s);
1267 for (casadi_int i=0; i<mapping.size(); ++i)
1268 ret->at(i) = nonzeros().at(mapping[i]);
1273 template<
typename Scalar>
1274 const Scalar Matrix<Scalar>::scalar()
const {
1276 casadi_assert(is_scalar(),
"Can only convert 1-by-1 matrices to scalars");
1280 return nonzeros()[0];
1282 return casadi_limits<Scalar>::zero;
1285 template<
typename Scalar>
1286 Matrix<Scalar> Matrix<Scalar>::binary(casadi_int op,
1287 const Matrix<Scalar> &x,
1288 const Matrix<Scalar> &y) {
1289 if (x.is_scalar()) {
1290 return scalar_matrix(op, x, y);
1291 }
else if (y.is_scalar()) {
1292 return matrix_scalar(op, x, y);
1294 return matrix_matrix(op, x, y);
1298 template<
typename Scalar>
1299 std::vector< Matrix<Scalar> > Matrix<Scalar>::call(
const Function& f,
1300 const std::vector< Matrix<Scalar> > &x) {
1302 std::vector<Scalar> dep;
1303 for (
auto & e : x) {
1304 dep.insert(dep.end(), e.nonzeros().begin(), e.nonzeros().end());
1307 std::vector<Scalar> r = Matrix<Scalar>::call(f, dep);
1310 std::vector< Matrix<Scalar> > ret;
1311 ret.reserve(r.size());
1312 for (
auto & e : r) {
1320 template<
typename Scalar>
1322 casadi_error(
"'call' not defined for " + type_name());
1325 template<
typename Scalar>
1328 if ( (operation_checker<FX0Checker>(op) && y.
nnz()==0) ||
1329 (operation_checker<F0XChecker>(op) && x.
nnz()==0))
1336 std::vector<Scalar>& ret_data = ret.nonzeros();
1337 const std::vector<Scalar>& x_data = x.nonzeros();
1339 const std::vector<Scalar>& y_data = y.nonzeros();
1342 for (casadi_int el=0; el<y.
nnz(); ++el) {
1343 casadi_math<Scalar>::fun(op, x_val, y_data[el], ret_data[el]);
1347 if (!y.
is_dense() && !operation_checker<FX0Checker>(op)) {
1352 ret = densify(ret, fcn_0);
1359 template<
typename Scalar>
1360 Matrix<Scalar> Matrix<Scalar>::
1361 matrix_scalar(casadi_int op,
const Matrix<Scalar> &x,
const Matrix<Scalar> &y) {
1363 if ( (operation_checker<FX0Checker>(op) && y.nnz()==0) ||
1364 (operation_checker<F0XChecker>(op) && x.nnz()==0))
1365 return Matrix<Scalar>::zeros(Sparsity(x.size()));
1368 Matrix<Scalar> ret = Matrix<Scalar>::zeros(x.sparsity());
1371 std::vector<Scalar>& ret_data = ret.nonzeros();
1372 const std::vector<Scalar>& x_data = x.nonzeros();
1373 const std::vector<Scalar>& y_data = y.nonzeros();
1374 const Scalar& y_val = y_data.empty() ? casadi_limits<Scalar>::zero : y->front();
1377 for (casadi_int el=0; el<x.nnz(); ++el) {
1378 casadi_math<Scalar>::fun(op, x_data[el], y_val, ret_data[el]);
1382 if (!x.is_dense() && !operation_checker<F0XChecker>(op)) {
1385 casadi_math<Scalar>::fun(op, casadi_limits<Scalar>::zero, y_val, fcn_0);
1386 if (!casadi_limits<Scalar>::is_zero(fcn_0)) {
1387 ret = densify(ret, fcn_0);
1394 template<
typename Scalar>
1395 Matrix<Scalar> Matrix<Scalar>::
1396 matrix_matrix(casadi_int op,
const Matrix<Scalar> &x,
const Matrix<Scalar> &y) {
1398 if (x.size() != y.size()) {
1400 if (!x.is_empty() && !y.is_empty()) {
1401 if (x.size1() == y.size1() && x.size2() % y.size2() == 0) {
1402 return matrix_matrix(op, x, repmat(y, 1, x.size2() / y.size2()));
1403 }
else if (y.size1() == x.size1() && y.size2() % x.size2() == 0) {
1404 return matrix_matrix(op, repmat(x, 1, y.size2() / x.size2()), y);
1408 if (x.size1()==0 && y.size1()==0 && x.size2()>0 && y.size2()>0) {
1409 if (x.size2() % y.size2() == 0) {
1410 return Matrix<Scalar>(0, x.size2());
1411 }
else if (y.size2() % x.size2() == 0) {
1412 return Matrix<Scalar>(0, y.size2());
1416 casadi_error(
"Dimension mismatch for " + casadi_math<Scalar>::print(op,
"x",
"y") +
1417 ", x is " + x.dim() +
", while y is " + y.dim());
1422 const Sparsity& x_sp = x.sparsity();
1423 const Sparsity& y_sp = y.sparsity();
1424 Sparsity r_sp = x_sp.combine(y_sp, operation_checker<F0XChecker>(op),
1425 operation_checker<FX0Checker>(op));
1428 Matrix<Scalar> r = zeros(r_sp);
1433 casadi_math<Scalar>::fun(op, x.ptr(), y.ptr(), r.ptr(), r_sp.nnz());
1434 }
else if (y_sp==r_sp) {
1436 Matrix<Scalar> x_mod = x(r_sp);
1437 casadi_math<Scalar>::fun(op, x_mod.ptr(), y.ptr(), r.ptr(), r_sp.nnz());
1438 }
else if (x_sp==r_sp) {
1440 Matrix<Scalar> y_mod = y(r_sp);
1441 casadi_math<Scalar>::fun(op, x.ptr(), y_mod.ptr(), r.ptr(), r_sp.nnz());
1444 Matrix<Scalar> x_mod = x(r_sp);
1445 Matrix<Scalar> y_mod = y(r_sp);
1446 casadi_math<Scalar>::fun(op, x_mod.ptr(), y_mod.ptr(), r.ptr(), r_sp.nnz());
1450 if (!r.is_dense() && !operation_checker<F00Checker>(op)) {
1453 casadi_math<Scalar>::fun(op, casadi_limits<Scalar>::zero,
1454 casadi_limits<Scalar>::zero, fcn_0);
1455 r = densify(r, fcn_0);
1461 template<
typename Scalar>
1462 Matrix<Scalar> Matrix<Scalar>::triplet(
const std::vector<casadi_int>& row,
1463 const std::vector<casadi_int>& col,
1464 const Matrix<Scalar>& d) {
1465 return triplet(row, col, d, *std::max_element(row.begin(), row.end()),
1466 *std::max_element(col.begin(), col.end()));
1469 template<
typename Scalar>
1470 Matrix<Scalar> Matrix<Scalar>::triplet(
const std::vector<casadi_int>& row,
1471 const std::vector<casadi_int>& col,
1472 const Matrix<Scalar>& d,
1473 const std::pair<casadi_int, casadi_int>& rc) {
1474 return triplet(row, col, d, rc.first, rc.second);
1477 template<
typename Scalar>
1478 Matrix<Scalar> Matrix<Scalar>::triplet(
const std::vector<casadi_int>& row,
1479 const std::vector<casadi_int>& col,
1480 const Matrix<Scalar>& d,
1481 casadi_int nrow, casadi_int ncol) {
1482 casadi_assert(col.size()==row.size() && col.size()==d.nnz(),
1483 "Argument error in Matrix<Scalar>::triplet(row, col, d): "
1484 "supplied lists must all be of equal length, but got: "
1485 + str(row.size()) +
", " + str(col.size()) +
" and " + str(d.nnz()));
1486 std::vector<casadi_int> mapping;
1487 Sparsity sp = Sparsity::triplet(nrow, ncol, row, col, mapping,
false);
1488 return Matrix<Scalar>(sp, d.nz(mapping));
1491 template<
typename Scalar>
1492 Matrix<Scalar> Matrix<Scalar>::eye(casadi_int n) {
1493 return Matrix<Scalar>::ones(Sparsity::diag(n));
1496 template<
typename Scalar>
1497 Matrix<Scalar> Matrix<Scalar>::inf(
const Sparsity& sp) {
1498 casadi_assert(std::numeric_limits<Scalar>::has_infinity,
1499 "Datatype cannot represent infinity");
1500 return Matrix<Scalar>(sp, std::numeric_limits<Scalar>::infinity(),
false);
1504 template<
typename Scalar>
1505 Matrix<Scalar> Matrix<Scalar>::inf(
const std::pair<casadi_int, casadi_int>& rc) {
1506 return inf(rc.first, rc.second);
1509 template<
typename Scalar>
1510 Matrix<Scalar> Matrix<Scalar>::inf(casadi_int nrow, casadi_int ncol) {
1511 return inf(Sparsity::dense(nrow, ncol));
1514 template<
typename Scalar>
1515 Matrix<Scalar> Matrix<Scalar>::nan(
const Sparsity& sp) {
1516 casadi_assert(std::numeric_limits<Scalar>::has_quiet_NaN,
1517 "Datatype cannot represent not-a-number");
1518 return Matrix<Scalar>(sp, std::numeric_limits<Scalar>::quiet_NaN(),
false);
1521 template<
typename Scalar>
1522 Matrix<Scalar> Matrix<Scalar>::nan(
const std::pair<casadi_int, casadi_int>& rc) {
1523 return nan(rc.first, rc.second);
1526 template<
typename Scalar>
1527 Matrix<Scalar> Matrix<Scalar>::nan(casadi_int nrow, casadi_int ncol) {
1528 return nan(Sparsity::dense(nrow, ncol));
1531 template<
typename Scalar>
1532 bool Matrix<Scalar>::is_regular()
const {
1536 template<
typename Scalar>
1537 bool Matrix<Scalar>::is_smooth()
const {
1541 template<
typename Scalar>
1542 casadi_int Matrix<Scalar>::element_hash()
const {
1543 casadi_error(
"'element_hash' not defined for " + type_name());
1546 template<
typename Scalar>
1547 bool Matrix<Scalar>::is_leaf()
const {
1548 casadi_error(
"'is_leaf' not defined for " + type_name());
1551 template<
typename Scalar>
1552 bool Matrix<Scalar>::is_commutative()
const {
1553 casadi_error(
"'is_commutative' not defined for " + type_name());
1556 template<
typename Scalar>
1557 bool Matrix<Scalar>::is_symbolic()
const {
1561 template<
typename Scalar>
1562 casadi_int Matrix<Scalar>::op()
const {
1563 casadi_error(
"'op' not defined for " + type_name());
1566 template<
typename Scalar>
1567 bool Matrix<Scalar>::is_op(casadi_int k)
const {
1568 casadi_error(
"'is_op' not defined for " + type_name());
1571 template<
typename Scalar>
1572 void Matrix<Scalar>::export_code(
const std::string& lang,
1573 std::ostream &stream,
const Dict& options)
const {
1574 casadi_error(
"'export_code' not defined for " + type_name());
1577 template<
typename Scalar>
1578 bool Matrix<Scalar>::is_valid_input()
const {
1582 template<
typename Scalar>
1583 bool Matrix<Scalar>::has_duplicates()
const {
1584 casadi_error(
"'has_duplicates' not defined for " + type_name());
1587 template<
typename Scalar>
1588 void Matrix<Scalar>::reset_input()
const {
1589 casadi_error(
"'reset_input' not defined for " + type_name());
1592 template<
typename Scalar>
1593 Matrix<double> Matrix<Scalar>::from_file(
const std::string& filename,
1594 const std::string& format_hint) {
1595 casadi_error(
"'from_file' not defined for " + type_name());
1598 template<
typename Scalar>
1599 bool Matrix<Scalar>::is_integer()
const {
1601 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_integer(e))
return false;
1607 template<
typename Scalar>
1608 bool Matrix<Scalar>::is_constant()
const {
1610 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_constant(e))
return false;
1616 template<
typename Scalar>
1617 bool Matrix<Scalar>::is_call()
const {
1618 casadi_assert(is_scalar(),
"'is_call' only defined for scalar expressions");
1623 template<
typename Scalar>
1624 bool Matrix<Scalar>::is_output()
const {
1625 casadi_assert(is_scalar(),
"'is_output' only defined for scalar expressions");
1630 template<
typename Scalar>
1631 Matrix<Scalar> Matrix<Scalar>::get_output(casadi_int oind)
const {
1632 casadi_error(
"'get_output' not defined for " + type_name());
1635 template<
typename Scalar>
1636 bool Matrix<Scalar>::has_output()
const {
1637 casadi_assert(is_scalar(),
"'has_output' only defined for scalar expressions");
1642 template<
typename Scalar>
1643 Function Matrix<Scalar>::which_function()
const {
1644 casadi_error(
"'which_function' not defined for " + type_name());
1647 template<
typename Scalar>
1648 casadi_int Matrix<Scalar>::which_output()
const {
1649 casadi_error(
"'which_output' not defined for " + type_name());
1652 template<
typename Scalar>
1653 bool Matrix<Scalar>::is_one()
const {
1654 if (!is_dense())
return false;
1657 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_one(e))
return false;
1662 template<
typename Scalar>
1663 bool Matrix<Scalar>::is_minus_one()
const {
1664 if (!is_dense())
return false;
1667 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_minus_one(e))
return false;
1672 template<
typename Scalar>
1673 bool Matrix<Scalar>::is_half()
const {
1674 if (!is_dense())
return false;
1677 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_half(e))
return false;
1682 template<
typename Scalar>
1683 bool Matrix<Scalar>::is_value(
double val)
const {
1684 if (val==0.0)
return is_zero();
1685 if (!is_dense())
return false;
1688 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_value(e, val))
return false;
1693 template<
typename Scalar>
1694 bool Matrix<Scalar>::is_inf()
const {
1695 if (!is_dense())
return false;
1698 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_inf(e))
return false;
1703 template<
typename Scalar>
1704 bool Matrix<Scalar>::is_minus_inf()
const {
1705 if (!is_dense())
return false;
1708 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_minus_inf(e))
return false;
1713 template<
typename Scalar>
1714 bool Matrix<Scalar>::is_nonnegative()
const {
1715 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_nonnegative(e))
return false;
1719 template<
typename Scalar>
1720 bool Matrix<Scalar>::is_zero()
const {
1723 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_zero(e))
return false;
1728 template<
typename Scalar>
1729 bool Matrix<Scalar>::is_eye()
const {
1732 if (!sparsity().is_diag())
return false;
1735 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_one(e))
return false;
1740 template<
typename Scalar>
1741 bool Matrix<Scalar>::is_equal(
const Matrix<Scalar> &x,
const Matrix<Scalar> &y,
1744 casadi_assert(x.size() == y.size(),
"Dimension mismatch");
1747 if (x.sparsity() != y.sparsity()) {
1748 Sparsity sp = x.sparsity() + y.sparsity();
1749 return is_equal(project(x, sp), project(y, sp), depth);
1753 auto y_it = y.nonzeros().begin();
1754 for (
auto&& e : x.nonzeros()) {
1755 if (!casadi_limits<Scalar>::is_equal(e, *y_it++, depth))
return false;
1763 template<
typename Scalar>
1764 inline Matrix<Scalar> mmin_nonstatic(
const Matrix<Scalar> &x) {
1765 if (x.is_empty())
return Matrix<Scalar>();
1766 return casadi_mmin(x.ptr(), x.nnz(), x.is_dense());
1769 template<
typename Scalar>
1770 Matrix<Scalar> Matrix<Scalar>::mmin(
const Matrix<Scalar> &x) {
1771 return mmin_nonstatic(x);
1775 template<
typename Scalar>
1776 inline Matrix<Scalar> mmax_nonstatic(
const Matrix<Scalar> &x) {
1777 if (x.is_empty())
return Matrix<Scalar>();
1778 return casadi_mmax(x.ptr(), x.nnz(), x.is_dense());
1781 template<
typename Scalar>
1782 Matrix<Scalar> Matrix<Scalar>::mmax(
const Matrix<Scalar> &x) {
1783 return mmax_nonstatic(x);
1786 template<
typename Scalar>
1787 bool Matrix<Scalar>::has_zeros()
const {
1789 for (
auto&& e : nonzeros())
if (casadi_limits<Scalar>::is_zero(e))
return true;
1795 template<
typename Scalar>
1796 std::vector<Scalar> Matrix<Scalar>::get_nonzeros()
const {
1800 template<
typename Scalar>
1801 std::vector<Scalar> Matrix<Scalar>::get_elements()
const {
1802 return static_cast< std::vector<Scalar>
>(*this);
1805 template<
typename Scalar>
1806 std::string Matrix<Scalar>::name()
const {
1807 casadi_error(
"'name' not defined for " + type_name());
1810 template<
typename Scalar>
1811 Matrix<Scalar> Matrix<Scalar>::dep(casadi_int ch)
const {
1812 casadi_error(
"'dep' not defined for " + type_name());
1815 template<
typename Scalar>
1816 casadi_int Matrix<Scalar>::n_dep()
const {
1817 casadi_error(
"'n_dep' not defined for " + type_name());
1820 template<
typename Scalar>
1821 Matrix<Scalar> Matrix<Scalar>::rand(
1824 return rand(Sparsity::dense(nrow, ncol));
1827 template<
typename Scalar>
1828 Matrix<Scalar> Matrix<Scalar>::rand(
1829 const std::pair<casadi_int, casadi_int>& rc) {
1830 return rand(rc.first, rc.second);
1833 template<
typename Scalar>
1834 Matrix<Scalar> Matrix<Scalar>::project(
const Matrix<Scalar>& x,
1835 const Sparsity& sp,
bool intersect) {
1837 return project(x, sp.intersect(x.sparsity()),
false);
1839 casadi_assert(sp.size()==x.size(),
"Dimension mismatch");
1840 Matrix<Scalar> ret = Matrix<Scalar>::zeros(sp);
1841 std::vector<Scalar> w(x.size1());
1842 casadi_project(x.ptr(), x.sparsity(), ret.ptr(), sp, get_ptr(w));
1847 template<
typename Scalar>
1848 void Matrix<Scalar>::set_max_depth(casadi_int eq_depth) {
1849 casadi_error(
"'set_max_depth' not defined for " + type_name());
1852 template<
typename Scalar>
1853 casadi_int Matrix<Scalar>::get_max_depth() {
1854 casadi_error(
"'get_max_depth' not defined for " + type_name());
1857 template<
typename Scalar>
1858 Matrix<Scalar> Matrix<Scalar>::det(
const Matrix<Scalar>& x) {
1859 casadi_int n = x.size2();
1860 casadi_assert(n == x.size1(),
"matrix must be square");
1863 if (x.is_scalar())
return x;
1866 if (n==2)
return x(0, 0) * x(1, 1) - x(0, 1) * x(1, 0);
1869 Matrix<Scalar> ret = 0;
1874 Matrix<casadi_int> sp = IM::ones(x.sparsity());
1877 Matrix<casadi_int> row_count = Matrix<casadi_int>::sum2(sp);
1880 if (!row_count.is_dense())
return 0;
1883 Matrix<casadi_int> col_count = Matrix<casadi_int>::sum1(sp).T();
1886 if (!row_count.is_dense())
return 0;
1888 casadi_int min_row = std::distance(row_count.nonzeros().begin(),
1889 std::min_element(row_count.nonzeros().begin(),
1890 row_count.nonzeros().end()));
1891 casadi_int min_col = std::distance(col_count.nonzeros().begin(),
1892 std::min_element(col_count.nonzeros().begin(),
1893 col_count.nonzeros().end()));
1895 if (min_row <= min_col) {
1897 casadi_int j = row_count.sparsity().row(min_row);
1899 Matrix<Scalar> row = x(j, Slice(0, n));
1901 std::vector< casadi_int > col_i = row.sparsity().get_col();
1903 for (casadi_int k=0; k<row.nnz(); ++k) {
1905 ret += row->at(k)*cofactor(x, col_i.at(k), j);
1910 casadi_int i = col_count.sparsity().row(min_col);
1912 Matrix<Scalar> col = x(Slice(0, n), i);
1914 const casadi_int* row_i = col.row();
1916 for (casadi_int k=0; k<col.nnz(); ++k) {
1918 ret += col->at(k)*cofactor(x, i, row_i[k]);
1925 template<
typename Scalar>
1926 Matrix<Scalar> Matrix<Scalar>::
1927 det(
const Matrix<Scalar>& x,
const std::string& lsolver,
const Dict& dict) {
1928 casadi_error(
"'det' with plugin not defined for " + type_name());
1929 return Matrix<Scalar>();
1932 template<
typename Scalar>
1933 Matrix<Scalar> Matrix<Scalar>::sum2(
const Matrix<Scalar>& x) {
1934 return mtimes(x, Matrix<Scalar>::ones(x.size2(), 1));
1937 template<
typename Scalar>
1938 Matrix<Scalar> Matrix<Scalar>::sum1(
const Matrix<Scalar>& x) {
1939 return mtimes(Matrix<Scalar>::ones(1, x.size1()), x);
1942 template<
typename Scalar>
1943 Matrix<Scalar> Matrix<Scalar>::minor(
const Matrix<Scalar>& x,
1944 casadi_int i, casadi_int j) {
1945 casadi_int n = x.size2();
1946 casadi_assert(n == x.size1(),
"minor: matrix must be square");
1952 Matrix<Scalar> M = Matrix<Scalar>(n-1, n-1);
1954 std::vector<casadi_int> col = x.sparsity().get_col();
1955 const casadi_int* row = x.sparsity().row();
1957 for (casadi_int k=0; k<x.nnz(); ++k) {
1958 casadi_int i1 = col[k];
1959 casadi_int j1 = row[k];
1961 if (i1 == i || j1 == j)
continue;
1963 casadi_int i2 = (i1<i)?i1:i1-1;
1964 casadi_int j2 = (j1<j)?j1:j1-1;
1966 M(j2, i2) = x(j1, i1);
1971 template<
typename Scalar>
1972 Matrix<Scalar> Matrix<Scalar>::cofactor(
const Matrix<Scalar>& A, casadi_int i, casadi_int j) {
1975 Matrix<Scalar> minor_ij = minor(A, i, j);
1977 casadi_int sign_i = 1-2*((i+j) % 2);
1979 return sign_i * minor_ij;
1982 template<
typename Scalar>
1983 Matrix<Scalar> Matrix<Scalar>::adj(
const Matrix<Scalar>& x) {
1984 casadi_int n = x.size2();
1985 casadi_assert(n == x.size1(),
"adj: matrix must be square");
1988 Matrix<Scalar> temp;
1991 Matrix<Scalar>
C = Matrix<Scalar>(n, n);
1992 for (casadi_int i=0; i<n; ++i)
1993 for (casadi_int j=0; j<n; ++j) {
1994 temp = cofactor(x, i, j);
1995 if (!temp.is_zero())
C(j, i) = temp;
2001 template<
typename Scalar>
2002 Matrix<Scalar> Matrix<Scalar>::inv_minor(
const Matrix<Scalar>& x) {
2004 return adj(x)/det(x);
2007 template<
typename Scalar>
2008 Matrix<Scalar> Matrix<Scalar>::reshape(
const Matrix<Scalar>& x,
2009 casadi_int nrow, casadi_int ncol) {
2010 Sparsity sp = Sparsity::reshape(x.sparsity(), nrow, ncol);
2011 return Matrix<Scalar>(sp, x.nonzeros(),
false);
2014 template<
typename Scalar>
2015 Matrix<Scalar> Matrix<Scalar>::reshape(
const Matrix<Scalar>& x,
const Sparsity& sp) {
2017 if (sp==x.sparsity())
return x;
2020 casadi_assert_dev(sp.is_reshape(x.sparsity()));
2022 return Matrix<Scalar>(sp, x.nonzeros(),
false);
2025 template<
typename Scalar>
2026 Matrix<Scalar> Matrix<Scalar>::sparsity_cast(
const Matrix<Scalar>& x,
const Sparsity& sp) {
2028 if (sp==x.sparsity())
return x;
2030 casadi_assert_dev(sp.nnz()==x.nnz());
2032 return Matrix<Scalar>(sp, x.nonzeros(),
false);
2035 template<
typename Scalar>
2036 Matrix<Scalar> Matrix<Scalar>::trace(
const Matrix<Scalar>& x) {
2037 casadi_assert(x.is_square(),
"trace: must be square");
2039 const Scalar* d=x.ptr();
2040 casadi_int size2 = x.size2();
2041 const casadi_int *colind=x.colind(), *row=x.row();
2042 for (casadi_int c=0; c<size2; c++) {
2043 for (casadi_int k=colind[c]; k!=colind[c+1]; ++k) {
2052 template<
typename Scalar>
2054 Matrix<Scalar>::blockcat(
const std::vector< std::vector<Matrix<Scalar> > > &v) {
2055 std::vector< Matrix<Scalar> > ret;
2056 for (casadi_int i=0; i<v.size(); ++i)
2057 ret.push_back(horzcat(v[i]));
2058 return vertcat(ret);
2061 template<
typename Scalar>
2062 Matrix<Scalar> Matrix<Scalar>::horzcat(
const std::vector<Matrix<Scalar> > &v) {
2064 std::vector<Sparsity> sp(v.size());
2065 for (casadi_int i=0; i<v.size(); ++i) sp[i] = v[i].sparsity();
2066 Matrix<Scalar> ret = zeros(Sparsity::horzcat(sp));
2069 auto i=ret->begin();
2070 for (
auto&& j : v) {
2071 std::copy(j->begin(), j->end(), i);
2077 template<
typename Scalar>
2078 std::vector<Matrix<Scalar> >
2079 Matrix<Scalar>::horzsplit(
const Matrix<Scalar>& x,
const std::vector<casadi_int>& offset) {
2081 std::vector<Sparsity> sp = Sparsity::horzsplit(x.sparsity(), offset);
2084 std::vector<Matrix<Scalar> > ret;
2085 ret.reserve(sp.size());
2088 auto i=x.nonzeros().begin();
2089 for (
auto&& j : sp) {
2090 auto i_next = i + j.nnz();
2091 ret.push_back(Matrix<Scalar>(j, std::vector<Scalar>(i, i_next),
false));
2096 casadi_assert_dev(i==x.nonzeros().end());
2100 template<
typename Scalar>
2101 Matrix<Scalar> Matrix<Scalar>::vertcat(
const std::vector<Matrix<Scalar> > &v) {
2102 std::vector<Matrix<Scalar> > vT(v.size());
2103 for (casadi_int i=0; i<v.size(); ++i) vT[i] = v[i].
T();
2104 return horzcat(vT).T();
2107 template<
typename Scalar>
2108 std::vector< Matrix<Scalar> >
2109 Matrix<Scalar>::vertsplit(
const Matrix<Scalar>& x,
const std::vector<casadi_int>& offset) {
2110 std::vector< Matrix<Scalar> > ret = horzsplit(x.T(), offset);
2111 for (
auto&& e : ret) e = e.T();
2115 template<
typename Scalar>
2116 std::vector< Matrix<Scalar> >
2117 Matrix<Scalar>::diagsplit(
const Matrix<Scalar>& x,
const std::vector<casadi_int>& offset1,
2118 const std::vector<casadi_int>& offset2) {
2120 casadi_assert_dev(!offset1.empty());
2121 casadi_assert_dev(offset1.front()==0);
2122 casadi_assert_dev(offset1.back()==x.size1());
2126 casadi_assert_dev(!offset2.empty());
2127 casadi_assert_dev(offset2.front()==0);
2128 casadi_assert_dev(offset2.back()==x.size2());
2132 casadi_int n = offset1.size()-1;
2135 std::vector< Matrix<Scalar> > ret;
2138 for (casadi_int i=0; i<n; ++i) {
2139 ret.push_back(x(Slice(offset1[i], offset1[i+1]), Slice(offset2[i], offset2[i+1])));
2145 template<
typename Scalar>
2146 Matrix<Scalar> Matrix<Scalar>::dot(
const Matrix<Scalar> &x,
2147 const Matrix<Scalar> &y) {
2148 casadi_assert(x.size()==y.size(),
"dot: Dimension mismatch");
2149 if (x.sparsity()!=y.sparsity()) {
2150 Sparsity sp = x.sparsity() * y.sparsity();
2151 return dot(project(x, sp), project(y, sp));
2153 return casadi_dot(x.nnz(), x.ptr(), y.ptr());
2156 template<
typename Scalar>
2157 Matrix<Scalar> Matrix<Scalar>::all(
const Matrix<Scalar>& x) {
2158 if (!x.is_dense())
return false;
2160 for (casadi_int i=0; i<x.nnz(); ++i) {
2161 ret = ret && x->at(i)==1;
2166 template<
typename Scalar>
2167 Matrix<Scalar> Matrix<Scalar>::any(
const Matrix<Scalar>& x) {
2168 if (!x.is_dense())
return false;
2170 for (casadi_int i=0; i<x.nnz(); ++i) {
2171 ret = ret || x->at(i)==1;
2176 template<
typename Scalar>
2177 Matrix<Scalar> Matrix<Scalar>::norm_1(
const Matrix<Scalar>& x) {
2178 return casadi_norm_1(x.nnz(), x.ptr());
2181 template<
typename Scalar>
2182 Matrix<Scalar> Matrix<Scalar>::norm_2(
const Matrix<Scalar>& x) {
2183 if (x.is_vector()) {
2186 casadi_error(
"2-norms currently only supported for vectors. "
2187 "Did you intend to calculate a Frobenius norms (norm_fro)?");
2191 template<
typename Scalar>
2192 Matrix<Scalar> Matrix<Scalar>::norm_fro(
const Matrix<Scalar>& x) {
2193 return casadi_norm_2(x.nnz(), x.ptr());
2196 template<
typename Scalar>
2197 Matrix<Scalar> Matrix<Scalar>::norm_inf(
const Matrix<Scalar>& x) {
2199 Matrix<Scalar> s = 0;
2200 for (
auto i=x.nonzeros().begin(); i!=x.nonzeros().end(); ++i) {
2201 s = fmax(s, fabs(Matrix<Scalar>(*i)));
2206 template<
typename Scalar>
2207 void Matrix<Scalar>::
2208 qr_sparse(
const Matrix<Scalar>& A,
2209 Matrix<Scalar>& V, Matrix<Scalar> &R, Matrix<Scalar>& beta,
2210 std::vector<casadi_int>& prinv, std::vector<casadi_int>& pc,
bool amd) {
2213 A.sparsity().qr_sparse(spV, spR, prinv, pc, amd);
2215 casadi_int nrow_ext = spV.size1(), ncol = spV.size2();
2218 beta = nan(ncol, 1);
2219 std::vector<Scalar> w(nrow_ext);
2220 casadi_qr(A.sparsity(), A.ptr(), get_ptr(w), spV, V.ptr(),
2221 spR, R.ptr(), beta.ptr(),
2222 get_ptr(prinv), get_ptr(pc));
2225 template<
typename Scalar>
2226 Matrix<Scalar> Matrix<Scalar>::
2227 qr_solve(
const Matrix<Scalar>& b,
const Matrix<Scalar>& v,
2228 const Matrix<Scalar>& r,
const Matrix<Scalar>& beta,
2229 const std::vector<casadi_int>& prinv,
const std::vector<casadi_int>& pc,
2232 casadi_int ncol = v.size2();
2233 casadi_int nrow = b.size1(), nrhs = b.size2();
2234 casadi_assert(r.size()==v.size(),
"'r', 'v' dimension mismatch");
2235 casadi_assert(beta.is_vector() && beta.numel()==ncol,
"'beta' has wrong dimension");
2236 casadi_assert(prinv.size()==r.size1(),
"'pinv' has wrong dimension");
2238 std::vector<Scalar> w(nrow+ncol);
2240 Matrix<Scalar> x = densify(b);
2241 casadi_qr_solve(x.ptr(), nrhs, tr, v.sparsity(), v.ptr(), r.sparsity(), r.ptr(),
2242 beta.ptr(), get_ptr(prinv), get_ptr(pc), get_ptr(w));
2246 template<
typename Scalar>
2247 void Matrix<Scalar>::qr(
const Matrix<Scalar>& A,
2248 Matrix<Scalar>& Q, Matrix<Scalar> &R) {
2251 casadi_assert(A.size1()>=A.size2(),
"qr: fewer rows than columns");
2254 Q = R = Matrix<Scalar>();
2255 for (casadi_int i=0; i<A.size2(); ++i) {
2257 Matrix<Scalar> ai = A(Slice(), i);
2258 Matrix<Scalar> qi = ai;
2260 Matrix<Scalar> ri = Matrix<Scalar>(A.size2(), 1);
2263 for (casadi_int j=0; j<i; ++j) {
2266 Matrix<Scalar> qj =
Q(Slice(), j);
2268 ri(j, 0) = mtimes(qi.T(), qj);
2272 if (ri.has_nz(j, 0))
2273 qi -= ri(j, 0) * qj;
2277 ri(i, 0) = norm_2(qi);
2281 Q = Matrix<Scalar>::horzcat({
Q, qi});
2282 R = Matrix<Scalar>::horzcat({R, ri});
2286 template<
typename Scalar>
2287 void Matrix<Scalar>::ldl(
const Matrix<Scalar>& A, Matrix<Scalar> &D,
2288 Matrix<Scalar>& LT, std::vector<casadi_int>& p,
bool amd) {
2290 Sparsity Lt_sp = A.sparsity().ldl(p, amd);
2293 casadi_int n=A.size1();
2296 std::vector<Scalar> D_nz(n), L_nz(Lt_sp.nnz()), w(n);
2297 casadi_ldl(A.sparsity(), get_ptr(A.nonzeros()), Lt_sp,
2298 get_ptr(L_nz), get_ptr(D_nz), get_ptr(p), get_ptr(w));
2301 LT = Matrix<Scalar>(Lt_sp, L_nz);
2305 template<
typename Scalar>
2306 Matrix<Scalar> Matrix<Scalar>::
2307 ldl_solve(
const Matrix<Scalar>& b,
const Matrix<Scalar>& D,
const Matrix<Scalar>& LT,
2308 const std::vector<casadi_int>& p) {
2310 casadi_int n = b.size1(), nrhs = b.size2();
2311 casadi_assert(p.size()==n,
"'p' has wrong dimension");
2312 casadi_assert(LT.size1()==n && LT.size2()==n,
"'LT' has wrong dimension");
2313 casadi_assert(
D.is_vector() &&
D.numel()==n,
"'D' has wrong dimension");
2315 Matrix<Scalar> x = densify(b);
2316 std::vector<Scalar> w(n);
2317 casadi_ldl_solve(x.ptr(), nrhs, LT.sparsity(), LT.ptr(),
D.ptr(), get_ptr(p), get_ptr(w));
2321 template<
typename Scalar>
2322 Matrix<Scalar> Matrix<Scalar>::nullspace(
const Matrix<Scalar>& A) {
2323 Matrix<Scalar>
X = A;
2324 casadi_int n =
X.size1();
2325 casadi_int m =
X.size2();
2326 casadi_assert(m>=n,
"nullspace(): expecting a flat matrix (more columns than rows), "
2327 "but got " + str(
X.dim()) +
".");
2329 Matrix<Scalar> seed = DM::eye(m)(Slice(0, m), Slice(n, m));
2331 std::vector< Matrix<Scalar> > us;
2332 std::vector< Matrix<Scalar> > betas;
2334 Matrix<Scalar> beta;
2336 for (casadi_int i=0;i<n;++i) {
2337 Matrix<Scalar> x =
X(i, Slice(i, m));
2338 Matrix<Scalar> u = Matrix<Scalar>(x);
2339 Matrix<Scalar> sigma = sqrt(sum2(x*x));
2340 const Matrix<Scalar>& x0 = x(0, 0);
2343 Matrix<Scalar> b = -copysign(sigma, x0);
2345 u(Slice(0), Slice(1, m-i))*= 1/(x0-b);
2348 X(Slice(i, n), Slice(i, m)) -=
2349 beta*mtimes(mtimes(
X(Slice(i, n), Slice(i, m)), u.T()), u);
2351 betas.push_back(beta);
2354 for (casadi_int i=n-1;i>=0;--i) {
2355 seed(Slice(i, m), Slice(0, m-n)) -=
2356 betas[i]*mtimes(us[i].
T(), mtimes(us[i], seed(Slice(i, m), Slice(0, m-n))));
2363 template<
typename Scalar>
2364 Matrix<Scalar> Matrix<Scalar>::chol(
const Matrix<Scalar>& A) {
2366 Matrix<Scalar>
D, LT;
2367 std::vector<casadi_int> p;
2368 ldl(A, D, LT, p,
false);
2370 LT += Matrix<Scalar>::eye(
D.size1());
2372 return mtimes(diag(sqrt(D)), LT);
2375 template<
typename Scalar>
2376 Matrix<Scalar> Matrix<Scalar>::solve(
const Matrix<Scalar>& a,
const Matrix<Scalar>& b) {
2378 casadi_assert(a.size1() == b.size1(),
"solve Ax=b: dimension mismatch: b has "
2379 + str(b.size1()) +
" rows while A has " + str(a.size1()) +
".");
2380 casadi_assert(a.size1() == a.size2(),
"solve: A not square but " + str(a.dim()));
2384 Matrix<Scalar> x = b;
2385 const casadi_int* Arow = a.row();
2386 const casadi_int* Acolind = a.colind();
2387 const std::vector<Scalar> & Adata = a.nonzeros();
2388 for (casadi_int i=0; i<a.size2(); ++i) {
2389 for (casadi_int k=0; k<b.size2(); ++k) {
2390 if (!x.has_nz(i, k))
continue;
2392 for (casadi_int kk=Acolind[i+1]-1; kk>=Acolind[i] && Arow[kk]>i; --kk) {
2393 casadi_int j = Arow[kk];
2394 x(j, k) -= Adata[kk]*x(i, k);
2399 }
else if (a.is_triu()) {
2401 Matrix<Scalar> x = b;
2402 const casadi_int* Arow = a.row();
2403 const casadi_int* Acolind = a.colind();
2404 const std::vector<Scalar> & Adata = a.nonzeros();
2405 for (casadi_int i=a.size2()-1; i>=0; --i) {
2406 for (casadi_int k=0; k<b.size2(); ++k) {
2407 if (!x.has_nz(i, k))
continue;
2409 for (casadi_int kk=Acolind[i]; kk<Acolind[i+1] && Arow[kk]<i; ++kk) {
2410 casadi_int j = Arow[kk];
2411 x(j, k) -= Adata[kk]*x(i, k);
2416 }
else if (a.has_zeros()) {
2420 return solve(sparsify(a), b);
2425 std::vector<casadi_int> rowperm, colperm, rowblock, colblock;
2426 std::vector<casadi_int> coarse_rowblock, coarse_colblock;
2427 a.sparsity().btf(rowperm, colperm, rowblock, colblock,
2428 coarse_rowblock, coarse_colblock);
2431 Matrix<Scalar> bperm = b(rowperm, Slice());
2434 Matrix<Scalar> Aperm = a(rowperm, colperm);
2437 Matrix<Scalar> xperm;
2440 if (Aperm.is_tril()) {
2443 xperm = solve(Aperm, bperm);
2445 }
else if (a.size2()<=3) {
2448 xperm = mtimes(inv_minor(Aperm), bperm);
2453 Matrix<Scalar>
Q, R;
2457 xperm = solve(R, mtimes(
Q.T(), bperm));
2461 std::vector<casadi_int> inv_colperm(colperm.size());
2462 for (casadi_int k=0; k<colperm.size(); ++k)
2463 inv_colperm[colperm[k]] = k;
2466 Matrix<Scalar> x = xperm(inv_colperm, Slice());
2471 template<
typename Scalar>
2472 Matrix<Scalar> Matrix<Scalar>::
2473 solve(
const Matrix<Scalar>& a,
const Matrix<Scalar>& b,
2474 const std::string& lsolver,
const Dict& dict) {
2475 casadi_error(
"'solve' with plugin not defined for " + type_name());
2476 return Matrix<Scalar>();
2479 template<
typename Scalar>
2480 Matrix<Scalar> Matrix<Scalar>::
2481 inv(
const Matrix<Scalar>& a) {
2482 return solve(a, Matrix<Scalar>::eye(a.size1()));
2485 template<
typename Scalar>
2486 Matrix<Scalar> Matrix<Scalar>::
2487 inv(
const Matrix<Scalar>& a,
2488 const std::string& lsolver,
const Dict& dict) {
2489 casadi_error(
"'inv' with plugin not defined for " + type_name());
2490 return Matrix<Scalar>();
2493 template<
typename Scalar>
2494 Matrix<Scalar> Matrix<Scalar>::pinv(
const Matrix<Scalar>& A) {
2495 if (A.size2()>=A.size1()) {
2496 return solve(mtimes(A, A.T()), A).T();
2498 return solve(mtimes(A.T(), A), A.T());
2502 template<
typename Scalar>
2503 Matrix<Scalar> Matrix<Scalar>::
2504 pinv(
const Matrix<Scalar>& A,
const std::string& lsolver,
const Dict& dict) {
2505 casadi_error(
"'solve' not defined for " + type_name());
2506 return Matrix<Scalar>();
2509 template<
typename Scalar>
2510 Matrix<Scalar> Matrix<Scalar>::
2511 expm_const(
const Matrix<Scalar>& A,
const Matrix<Scalar>& t) {
2512 casadi_error(
"'solve' not defined for " + type_name());
2513 return Matrix<Scalar>();
2516 template<
typename Scalar>
2517 Matrix<Scalar> Matrix<Scalar>::
2518 expm(
const Matrix<Scalar>& A) {
2519 casadi_error(
"'solve' not defined for " + type_name());
2520 return Matrix<Scalar>();
2523 template<
typename Scalar>
2524 Matrix<Scalar> Matrix<Scalar>::kron(
const Matrix<Scalar>& a,
const Matrix<Scalar>& b) {
2525 std::vector<Scalar> ret(a.nnz()*b.nnz());
2526 casadi_kron(get_ptr(a), a.sparsity(), get_ptr(b), b.sparsity(), get_ptr(ret));
2528 Sparsity sp_ret = Sparsity::kron(a.sparsity(), b.sparsity());
2529 return Matrix<Scalar>(sp_ret, ret,
false);
2532 template<
typename Scalar>
2533 Matrix<Scalar> Matrix<Scalar>::diag(
const Matrix<Scalar>& A) {
2535 std::vector<casadi_int> mapping;
2537 Sparsity sp = A.sparsity().get_diag(mapping);
2539 Matrix<Scalar> ret = zeros(sp);
2541 for (casadi_int k=0; k<mapping.size(); k++) ret.nz(k) = A.nz(mapping[k]);
2548 template<
typename Scalar>
2549 Matrix<Scalar> Matrix<Scalar>::diagcat(
const std::vector< Matrix<Scalar> > &A) {
2550 std::vector<Scalar> data;
2552 std::vector<Sparsity> sp;
2553 for (casadi_int i=0;i<A.size();++i) {
2554 data.insert(data.end(), A[i].nonzeros().begin(), A[i].nonzeros().end());
2555 sp.push_back(A[i].sparsity());
2558 return Matrix<Scalar>(Sparsity::diagcat(sp), data,
false);
2564 template<
typename Scalar>
2565 bool Matrix<Scalar>::simplify_ref_count(std::vector< Matrix<Scalar> >& arg,
2566 std::vector< Matrix<Scalar> >& res,
2568 casadi_error(
"'simplify_ref_count' not defined for " + type_name());
2574 template<
typename Scalar>
2575 bool Matrix<Scalar>::simplify_const_folding(std::vector< Matrix<Scalar> >& arg,
2576 std::vector< Matrix<Scalar> >& res,
2578 casadi_error(
"'simplify_const_folding' not defined for " + type_name());
2581 template<
typename Scalar>
2582 bool Matrix<Scalar>::simplify_combine_terms(std::vector< Matrix<Scalar> >& arg,
2583 std::vector< Matrix<Scalar> >& res,
2585 casadi_error(
"'simplify_combine_terms' not defined for " + type_name());
2588 template<
typename Scalar>
2589 Matrix<Scalar> Matrix<Scalar>::unite(
const Matrix<Scalar>& A,
const Matrix<Scalar>& B) {
2591 std::vector<unsigned char> mapping;
2592 Sparsity sp = A.sparsity().unite(B.sparsity(), mapping);
2595 Matrix<Scalar> ret = zeros(sp);
2598 casadi_int elA=0, elB=0;
2599 for (casadi_int k=0; k<mapping.size(); ++k) {
2600 if (mapping[k]==1) {
2601 ret.nonzeros()[k] = A.nonzeros()[elA++];
2602 }
else if (mapping[k]==2) {
2603 ret.nonzeros()[k] = B.nonzeros()[elB++];
2605 casadi_error(
"Pattern intersection not empty");
2609 casadi_assert_dev(A.nnz()==elA);
2610 casadi_assert_dev(B.nnz()==elB);
2615 template<
typename Scalar>
2616 Matrix<Scalar> Matrix<Scalar>::polyval(
const Matrix<Scalar>& p,
const Matrix<Scalar>& x) {
2617 casadi_assert(p.is_dense(),
"polynomial coefficients vector must be dense");
2618 casadi_assert(p.is_vector() && p.nnz()>0,
"polynomial coefficients must be a vector");
2619 Matrix<Scalar> ret = x;
2620 for (
auto&& e : ret.nonzeros()) {
2621 e = casadi_polyval(p.ptr(), p.numel()-1, e);
2626 template<
typename Scalar>
2627 Matrix<Scalar> Matrix<Scalar>::norm_inf_mul(
const Matrix<Scalar>& x,
2628 const Matrix<Scalar>& y) {
2629 casadi_assert(y.size1()==x.size2(),
"Dimension error. Got " + x.dim()
2630 +
" times " + y.dim() +
".");
2633 std::vector<Scalar> dwork(x.size1());
2634 std::vector<casadi_int> iwork(x.size1()+1+y.size2());
2637 return casadi_norm_inf_mul(x.ptr(), x.sparsity(), y.ptr(), y.sparsity(),
2638 get_ptr(dwork), get_ptr(iwork));
2641 template<
typename Scalar>
2642 void Matrix<Scalar>::expand(
const Matrix<Scalar>& ex,
2643 Matrix<Scalar> &weights, Matrix<Scalar>& terms) {
2644 casadi_error(
"'expand' not defined for " + type_name());
2647 template<
typename Scalar>
2648 Matrix<Scalar> Matrix<Scalar>::pw_const(
const Matrix<Scalar>& ex,
2649 const Matrix<Scalar>& tval,
2650 const Matrix<Scalar>& val) {
2651 casadi_error(
"'pw_const' not defined for " + type_name());
2652 return Matrix<Scalar>();
2655 template<
typename Scalar>
2656 Matrix<Scalar> Matrix<Scalar>::pw_lin(
const Matrix<Scalar>& ex,
2657 const Matrix<Scalar>& tval,
2658 const Matrix<Scalar>& val) {
2659 casadi_error(
"'pw_lin' not defined for " + type_name());
2660 return Matrix<Scalar>();
2663 template<
typename Scalar>
2664 Matrix<Scalar> Matrix<Scalar>::if_else(
const Matrix<Scalar> &cond,
2665 const Matrix<Scalar> &if_true,
2666 const Matrix<Scalar> &if_false,
2667 bool short_circuit) {
2668 return if_else_zero(cond, if_true) + if_else_zero(!cond, if_false);
2671 template<
typename Scalar>
2672 Matrix<Scalar> Matrix<Scalar>::conditional(
const Matrix<Scalar>& ind,
2673 const std::vector<Matrix<Scalar> >& x,
2674 const Matrix<Scalar>& x_default,
2675 bool short_circuit) {
2676 casadi_assert(!short_circuit,
2677 "Short-circuiting 'conditional' not supported for " + type_name());
2678 casadi_assert(ind.is_scalar(
true),
2679 "conditional: first argument must be scalar. Got " + ind.dim()+
" instead.");
2681 Matrix<Scalar> ret = x_default;
2682 for (casadi_int k=0; k<x.size(); ++k) {
2683 ret = if_else(ind==k, x[k], ret, short_circuit);
2688 template<
typename Scalar>
2689 Matrix<Scalar> Matrix<Scalar>::heaviside(
const Matrix<Scalar>& x) {
2690 return (1+sign(x))/2;
2693 template<
typename Scalar>
2694 Matrix<Scalar> Matrix<Scalar>::rectangle(
const Matrix<Scalar>& x) {
2695 return 0.5*(sign(x+0.5)-sign(x-0.5));
2698 template<
typename Scalar>
2699 Matrix<Scalar> Matrix<Scalar>::triangle(
const Matrix<Scalar>& x) {
2700 return rectangle(x/2)*(1-fabs(x));
2703 template<
typename Scalar>
2704 Matrix<Scalar> Matrix<Scalar>::ramp(
const Matrix<Scalar>& x) {
2705 return x*heaviside(x);
2708 template<
typename Scalar>
2709 Matrix<Scalar> Matrix<Scalar>::
2710 gauss_quadrature(
const Matrix<Scalar> &f,
2711 const Matrix<Scalar> &x,
const Matrix<Scalar> &a,
2712 const Matrix<Scalar> &b, casadi_int order) {
2713 return gauss_quadrature(f, x, a, b, order, Matrix<Scalar>());
2716 template<
typename Scalar>
2717 Matrix<Scalar> Matrix<Scalar>::gauss_quadrature(
const Matrix<Scalar>& f,
2718 const Matrix<Scalar>& x,
2719 const Matrix<Scalar>& a,
2720 const Matrix<Scalar>& b, casadi_int order,
2721 const Matrix<Scalar>& w) {
2722 casadi_error(
"'gauss_quadrature' not defined for " + type_name());
2723 return Matrix<Scalar>();
2726 template<
typename Scalar>
2727 Matrix<Scalar> Matrix<Scalar>::simplify(
const Matrix<Scalar> &x) {
2731 template<
typename Scalar>
2732 Matrix<Scalar> Matrix<Scalar>::transform(
const Matrix<Scalar> &x,
const Dict& opts) {
2733 casadi_error(
"'transform' not defined for " + type_name());
2736 template<
typename Scalar>
2737 Matrix<Scalar> Matrix<Scalar>::transform(
const Matrix<Scalar> &x,
2738 const std::vector<std::vector<GenericType> >& passes,
const Dict& opts) {
2739 casadi_error(
"'transform' not defined for " + type_name());
2742 template<
typename Scalar>
2743 std::vector<Matrix<Scalar> > Matrix<Scalar>::transform(
const std::vector<Matrix<Scalar> >& x,
2745 casadi_error(
"'transform' not defined for " + type_name());
2748 template<
typename Scalar>
2749 std::vector<Matrix<Scalar> > Matrix<Scalar>::transform(
const std::vector<Matrix<Scalar> >& x,
2750 const std::vector<std::vector<GenericType> >& passes,
const Dict& opts) {
2751 casadi_error(
"'transform' not defined for " + type_name());
2754 template<
typename Scalar>
2755 Matrix<Scalar> Matrix<Scalar>::substitute(
const Matrix<Scalar>& ex,
2756 const Matrix<Scalar>& v,
2757 const Matrix<Scalar>& vdef) {
2758 casadi_error(
"'substitute' not defined for " + type_name());
2759 return Matrix<Scalar>();
2762 template<
typename Scalar>
2763 std::vector<Matrix<Scalar> >
2764 Matrix<Scalar>::substitute(
const std::vector<Matrix<Scalar> >& ex,
2765 const std::vector<Matrix<Scalar> >& v,
2766 const std::vector<Matrix<Scalar> >& vdef) {
2767 casadi_error(
"'substitute' not defined for " + type_name());
2768 return std::vector<Matrix<Scalar> >();
2771 template<
typename Scalar>
2772 void Matrix<Scalar>::substitute_inplace(
const std::vector<Matrix<Scalar> >& v,
2773 std::vector<Matrix<Scalar> >& vdef,
2774 std::vector<Matrix<Scalar> >& ex,
2776 casadi_error(
"'substitute_inplace' not defined for " + type_name());
2779 template<
typename Scalar>
2780 void Matrix<Scalar>::extract_parametric(
const Matrix<Scalar> &expr,
2781 const Matrix<Scalar>& par,
2782 Matrix<Scalar>& expr_ret,
2783 std::vector<Matrix<Scalar> >& symbols,
2784 std::vector< Matrix<Scalar> >& parametric,
2786 casadi_error(
"'extract_parametric' not defined for " + type_name());
2789 template<
typename Scalar>
2790 void Matrix<Scalar>::separate_linear(
const Matrix<Scalar> &expr,
2791 const Matrix<Scalar> &sym_lin,
const Matrix<Scalar> &sym_const,
2792 Matrix<Scalar>& expr_const, Matrix<Scalar>& expr_lin, Matrix<Scalar>& expr_nonlin) {
2793 casadi_error(
"'separate_linear' not defined for " + type_name());
2796 template<
typename Scalar>
2797 bool Matrix<Scalar>::depends_on(
const Matrix<Scalar> &x,
const Matrix<Scalar> &arg) {
2798 casadi_error(
"'depends_on' not defined for " + type_name());
2802 template<
typename Scalar>
2803 bool Matrix<Scalar>::contains_all(
const std::vector <Matrix<Scalar> >& v,
2804 const std::vector <Matrix<Scalar> > &n) {
2805 casadi_error(
"'contains_all' not defined for " + type_name());
2809 template<
typename Scalar>
2810 bool Matrix<Scalar>::contains_any(
const std::vector<Matrix<Scalar> >& v,
2811 const std::vector <Matrix<Scalar> > &n) {
2812 casadi_error(
"'contains_any' not defined for " + type_name());
2816 template<
typename Scalar>
2817 std::vector< Matrix<Scalar> > Matrix<Scalar>::cse(
const std::vector< Matrix<Scalar> >& e) {
2818 casadi_error(
"'cse' not defined for " + type_name());
2823 template<
typename Scalar>
2824 Matrix<Scalar> Matrix<Scalar>::
2825 jacobian(
const Matrix<Scalar> &f,
const Matrix<Scalar> &x,
const Dict& opts) {
2826 casadi_error(
"'jacobian' not defined for " + type_name());
2827 return Matrix<Scalar>();
2830 template<
typename Scalar>
2831 Matrix<Scalar> Matrix<Scalar>::hessian(
const Matrix<Scalar> &f,
2832 const Matrix<Scalar> &x,
2834 casadi_error(
"'hessian' not defined for " + type_name());
2835 return Matrix<Scalar>();
2838 template<
typename Scalar>
2839 Matrix<Scalar> Matrix<Scalar>::hessian(
const Matrix<Scalar> &f,
2840 const Matrix<Scalar> &x,
2843 casadi_error(
"'hessian' not defined for " + type_name());
2844 return Matrix<Scalar>();
2847 template<
typename Scalar>
2848 std::vector<std::vector<Matrix<Scalar> > >
2850 forward(
const std::vector<Matrix<Scalar> > &ex,
2851 const std::vector<Matrix<Scalar> > &arg,
2852 const std::vector<std::vector<Matrix<Scalar> > > &v,
2854 casadi_error(
"'forward' not defined for " + type_name());
2857 template<
typename Scalar>
2858 std::vector<std::vector<Matrix<Scalar> > >
2860 reverse(
const std::vector<Matrix<Scalar> > &ex,
2861 const std::vector<Matrix<Scalar> > &arg,
2862 const std::vector<std::vector<Matrix<Scalar> > > &v,
2864 casadi_error(
"'reverse' not defined for " + type_name());
2867 template<
typename Scalar>
2869 Matrix<Scalar>::which_depends(
const Matrix<Scalar> &expr,
const Matrix<Scalar> &var,
2870 casadi_int order,
bool tr) {
2871 casadi_error(
"'which_depends' not defined for " + type_name());
2872 return std::vector<bool>();
2875 template<
typename Scalar>
2877 Matrix<Scalar>::jacobian_sparsity(
const Matrix<Scalar> &f,
const Matrix<Scalar> &x) {
2878 casadi_error(
"'jacobian_sparsity' not defined for " + type_name());
2882 template<
typename Scalar>
2883 Matrix<Scalar> Matrix<Scalar>::taylor(
const Matrix<Scalar>& f,
2884 const Matrix<Scalar>& x,
2885 const Matrix<Scalar>& a, casadi_int order) {
2886 casadi_error(
"'taylor' not defined for " + type_name());
2887 return Matrix<Scalar>();
2890 template<
typename Scalar>
2891 Matrix<Scalar> Matrix<Scalar>::mtaylor(
const Matrix<Scalar>& f,
2892 const Matrix<Scalar>& x,
2893 const Matrix<Scalar>& a, casadi_int order) {
2894 casadi_error(
"'mtaylor' not defined for " + type_name());
2895 return Matrix<Scalar>();
2898 template<
typename Scalar>
2899 Matrix<Scalar> Matrix<Scalar>::mtaylor(
const Matrix<Scalar>& f,
2900 const Matrix<Scalar>& x,
2901 const Matrix<Scalar>& a, casadi_int order,
2902 const std::vector<casadi_int>&order_contributions) {
2903 casadi_error(
"'mtaylor' not defined for " + type_name());
2904 return Matrix<Scalar>();
2907 template<
typename Scalar>
2908 casadi_int Matrix<Scalar>::n_nodes(
const Matrix<Scalar>& x) {
2909 casadi_error(
"'n_nodes' not defined for " + type_name());
2913 template<
typename Scalar>
2915 Matrix<Scalar>::print_operator(
const Matrix<Scalar>& x,
2916 const std::vector<std::string>& args) {
2917 casadi_error(
"'print_operator' not defined for " + type_name());
2918 return std::string();
2921 template<
typename Scalar>
2922 std::vector<Matrix<Scalar> > Matrix<Scalar>::symvar(
const Matrix<Scalar>& x) {
2923 casadi_error(
"'symvar' not defined for " + type_name());
2924 return std::vector<Matrix<Scalar> >();
2927 template<
typename Scalar>
2928 void Matrix<Scalar>::extract(std::vector<Matrix<Scalar>>& ex, std::vector<Matrix<Scalar>>& v,
2929 std::vector<Matrix<Scalar>>& vdef,
const Dict& opts) {
2930 casadi_error(
"'extract' not defined for " + type_name());
2933 template<
typename Scalar>
2934 void Matrix<Scalar>::shared(std::vector<Matrix<Scalar> >& ex,
2935 std::vector<Matrix<Scalar> >& v,
2936 std::vector<Matrix<Scalar> >& vdef,
2937 const std::string& v_prefix,
2938 const std::string& v_suffix) {
2939 casadi_error(
"'shared' not defined for " + type_name());
2942 template<
typename Scalar>
2943 Matrix<Scalar> Matrix<Scalar>::poly_coeff(
const Matrix<Scalar>& f,
2944 const Matrix<Scalar>&x) {
2945 casadi_error(
"'poly_coeff' not defined for " + type_name());
2948 template<
typename Scalar>
2949 Matrix<Scalar> Matrix<Scalar>::poly_roots(
const Matrix<Scalar>& p) {
2950 casadi_error(
"'poly_roots' not defined for " + type_name());
2953 template<
typename Scalar>
2954 Matrix<Scalar> Matrix<Scalar>::eig_symbolic(
const Matrix<Scalar>& m) {
2955 casadi_error(
"'eig_symbolic' not defined for " + type_name());
2958 template<
typename Scalar>
2959 DM Matrix<Scalar>::evalf(
const Matrix<Scalar>& m) {
2960 Function f(
"f", std::vector<SX>{}, std::vector<SX>{m});
2961 return f(std::vector<DM>{})[0];
2964 template<
typename Scalar>
2965 Matrix<Scalar> Matrix<Scalar>::sparsify(
const Matrix<Scalar>& x,
double tol) {
2967 bool remove_nothing =
true;
2968 for (
auto it=x.nonzeros().begin(); it!=x.nonzeros().end() && remove_nothing; ++it) {
2969 remove_nothing = !casadi_limits<Scalar>::is_almost_zero(*it, tol);
2971 if (remove_nothing)
return x;
2974 casadi_int size1 = x.size1();
2975 casadi_int size2 = x.size2();
2976 const casadi_int* colind = x.colind();
2977 const casadi_int* row = x.row();
2980 std::vector<casadi_int> new_colind(1, 0), new_row;
2981 std::vector<Scalar> new_data;
2984 for (casadi_int cc=0; cc<size2; ++cc) {
2986 for (casadi_int el=colind[cc]; el<colind[cc+1]; ++el) {
2988 if (!casadi_limits<Scalar>::is_almost_zero(x->at(el), tol)) {
2990 new_data.push_back(x->at(el));
2993 new_row.push_back(row[el]);
2997 new_colind.push_back(new_row.size());
3001 Sparsity sp(size1, size2, new_colind, new_row);
3004 return Matrix<Scalar>(sp, new_data);
3008 template<
typename Scalar>
3009 std::vector<Matrix<Scalar> > Matrix<Scalar>::get_input(
const Function& f) {
3010 casadi_error(
"'get_input' not defined for " + type_name());
3013 template<
typename Scalar>
3014 std::vector<Matrix<Scalar> > Matrix<Scalar>::get_free(
const Function& f) {
3015 casadi_error(
"'get_free' not defined for " + type_name());
3018 template<
typename Scalar>
3019 Matrix<Scalar>::operator double()
const {
3020 casadi_assert_dev(is_scalar());
3021 return static_cast<double>(scalar());
3024 template<
typename Scalar>
3025 Matrix<Scalar>::operator casadi_int()
const {
3026 casadi_assert_dev(is_scalar());
3027 return static_cast<casadi_int
>(scalar());
3030 template<
typename Scalar>
3031 Matrix<Scalar> Matrix<Scalar>::_sym(
const std::string& name,
const Sparsity& sp) {
3032 casadi_error(
"'sym' not defined for " + type_name());
3035 template<
typename Scalar>
3036 Matrix<Scalar> Matrix<Scalar>::rand(
const Sparsity& sp) {
3038 casadi_error(
"'rand' not defined for " + type_name());
3041 template<
typename Scalar>
3042 std::string Matrix<Scalar>::serialize()
const {
3043 std::stringstream ss;
3048 template<
typename Scalar>
3049 void Matrix<Scalar>::serialize(SerializingStream& s)
const {
3050 s.pack(
"Matrix::sparsity", sparsity());
3051 s.pack(
"Matrix::nonzeros", nonzeros());
3054 template<
typename Scalar>
3055 Matrix<Scalar> Matrix<Scalar>::deserialize(DeserializingStream& s) {
3057 s.unpack(
"Matrix::sparsity", sp);
3058 std::vector<Scalar> nz;
3059 s.unpack(
"Matrix::nonzeros", nz);
3060 return Matrix<Scalar>(sp, nz,
false);
3063 template<
typename Scalar>
3064 void Matrix<Scalar>::serialize(std::ostream &stream)
const {
3065 SerializingStream s(stream);
3069 template<
typename Scalar>
3070 Matrix<Scalar> Matrix<Scalar>::deserialize(std::istream &stream) {
3071 DeserializingStream s(stream);
3072 return Matrix<Scalar>::deserialize(s);
3075 template<
typename Scalar>
3076 Matrix<Scalar> Matrix<Scalar>::deserialize(
const std::string& s) {
3077 std::stringstream ss;
3079 return deserialize(ss);
3082 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
3083 template<
typename Scalar>
3084 std::mutex& Matrix<Scalar>::get_mutex_temp() {
3085 casadi_error(
"'get_mutex_temp' not defined for " + type_name());
Sparsity sparsity() const
Get the sparsity pattern.
bool is_dense() const
Check if the matrix expression is dense.
bool is_column() const
Check if the matrix is a column vector (i.e. size2()==1)
casadi_int row(casadi_int el) const
Get the sparsity pattern. See the Sparsity class for details.
bool is_vector() const
Check if the matrix is a row or column vector.
casadi_int nnz() const
Get the number of (structural) non-zero elements.
casadi_int size2() const
Get the second dimension (i.e. number of columns)
bool is_row() const
Check if the matrix is a row vector (i.e. size1()==1)
casadi_int size1() const
Get the first dimension (i.e. number of rows)
casadi_int colind(casadi_int col) const
Get the sparsity pattern. See the Sparsity class for details.
static Matrix< Scalar > zeros(casadi_int nrow=1, casadi_int ncol=1)
Create a dense matrix or a matrix with specified sparsity with all entries zero.
std::pair< casadi_int, casadi_int > size() const
Get the shape.
bool is_scalar(bool scalar_and_dense=false) const
Check if the matrix expression is scalar.
Sparse matrix class. SX and DM are specializations.
bool has_nz(casadi_int rr, casadi_int cc) const
Returns true if the matrix has a non-zero at location rr, cc.
void print_split(std::vector< std::string > &nz, std::vector< std::string > &inter) const
Get strings corresponding to the nonzeros and the interdependencies.
Matrix< Scalar > T() const
Transpose the matrix.
static void set_precision(casadi_int precision)
Set the 'precision, width & scientific' used in printing and serializing to streams.
static casadi_int get_precision()
Get the 'precision, width & scientific' used in printing and serializing to streams.
void get(Matrix< Scalar > &m, bool ind1, const Slice &rr) const
void resize(casadi_int nrow, casadi_int ncol)
void print_sparse(std::ostream &stream, bool truncate=true) const
Print sparse matrix style.
static void set_width(casadi_int width)
void set(const Matrix< Scalar > &m, bool ind1, const Slice &rr)
static casadi_int get_width()
static bool get_scientific()
static std::string type_name()
Get name of the class.
void to_file(const std::string &filename, const std::string &format="") const
static void set_scientific(bool scientific)
void disp(std::ostream &stream, bool more=false) const
Print a representation of the object.
bool __nonzero__() const
Returns the truth value of a Matrix.
static void rng(casadi_int seed)
Seed the random number generator.
void print_dense(std::ostream &stream, bool truncate=true) const
Print dense matrix-stype.
void reserve(casadi_int nnz)
void set(const Matrix< Scalar > &m, bool ind1, const Slice &rr, const Slice &cc)
void set_nz(const Matrix< Scalar > &m, bool ind1, const Slice &k)
void print_vector(std::ostream &stream, bool truncate=true) const
Print vector-style.
std::string get_str(bool more=false) const
Get string representation.
void get_nz(Matrix< Scalar > &m, bool ind1, const Slice &k) const
void print_scalar(std::ostream &stream) const
Print scalar.
Class representing a Slice.
std::vector< casadi_int > all() const
Get a vector of indices.
casadi_int scalar(casadi_int len) const
Get scalar (if is_scalar)
bool is_scalar(casadi_int len) const
Is the slice a scalar.
std::vector< casadi_int > find(bool ind1=SWIG_IND1) const
Get the location of all non-zero elements as they would appear in a Dense matrix.
Sparsity sub(const std::vector< casadi_int > &rr, const std::vector< casadi_int > &cc, std::vector< casadi_int > &mapping, bool ind1=false) const
Get a submatrix.
casadi_int numel() const
The total number of elements, including structural zeros, i.e. size2()*size1()
casadi_int size1() const
Get the number of rows.
static Sparsity dense(casadi_int nrow, casadi_int ncol=1)
Create a dense rectangular sparsity pattern *.
Sparsity T() const
Transpose the matrix.
bool is_column() const
Check if the pattern is a column vector (i.e. size2()==1)
static Sparsity triplet(casadi_int nrow, casadi_int ncol, const std::vector< casadi_int > &row, const std::vector< casadi_int > &col, std::vector< casadi_int > &mapping, bool invert_mapping)
Create a sparsity pattern given the nonzeros in sparse triplet form *.
casadi_int nnz() const
Get the number of (structural) non-zeros.
casadi_int size2() const
Get the number of columns.
casadi_int row(casadi_int el) const
Get the row of a non-zero element.
bool is_empty(bool both=false) const
Check if the sparsity is empty.
std::pair< casadi_int, casadi_int > size() const
Get the shape.
void einstein_eval(casadi_int n_iter, const std::vector< casadi_int > &iter_dims, const std::vector< casadi_int > &strides_a, const std::vector< casadi_int > &strides_b, const std::vector< casadi_int > &strides_c, const T *a_in, const T *b_in, T *c_in)
casadi_int einstein_process(const T &A, const T &B, const T &C, const std::vector< casadi_int > &dim_a, const std::vector< casadi_int > &dim_b, const std::vector< casadi_int > &dim_c, const std::vector< casadi_int > &a, const std::vector< casadi_int > &b, const std::vector< casadi_int > &c, std::vector< casadi_int > &iter_dims, std::vector< casadi_int > &strides_a, std::vector< casadi_int > &strides_b, std::vector< casadi_int > &strides_c)
bool is_monotone(const std::vector< T > &v)
Check if the vector is monotone.
CASADI_EXPORT std::vector< casadi_int > complement(const std::vector< casadi_int > &v, casadi_int size)
Returns the list of all i in [0, size[ not found in supplied list.
bool is_regular(const std::vector< T > &v)
Checks if array does not contain NaN or Inf.
Slice CASADI_EXPORT to_slice(const IM &x, bool ind1=false)
Convert IM to Slice.