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)
544 for (casadi_int i=1;i<x.size2();++i)
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>
980 Matrix<Scalar>::Matrix(
const Sparsity& sp) : sparsity_(sp), nonzeros_(sp.nnz(), 1) {
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>
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>
1321 std::vector<Scalar> Matrix<Scalar>::call(
const Function& f,
const std::vector< Scalar > &x) {
1322 casadi_error(
"'call' not defined for " + type_name());
1325 template<
typename Scalar>
1326 Matrix<Scalar> Matrix<Scalar>::
1327 scalar_matrix(casadi_int op,
const Matrix<Scalar> &x,
const Matrix<Scalar> &y) {
1328 if ( (operation_checker<FX0Checker>(op) && y.nnz()==0) ||
1329 (operation_checker<F0XChecker>(op) && x.nnz()==0))
1330 return Matrix<Scalar>::zeros(Sparsity(y.size()));
1333 Matrix<Scalar> ret = Matrix<Scalar>::zeros(y.sparsity());
1336 std::vector<Scalar>& ret_data = ret.nonzeros();
1337 const std::vector<Scalar>& x_data = x.nonzeros();
1338 const Scalar& x_val = x_data.empty() ? casadi_limits<Scalar>::zero : x->front();
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)) {
1350 casadi_math<Scalar>::fun(op, x_val, casadi_limits<Scalar>::zero, fcn_0);
1351 if (!casadi_limits<Scalar>::is_zero(fcn_0)) {
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 casadi_int nrow = row.empty() ? 0 : *std::max_element(row.begin(), row.end()) + 1;
1466 casadi_int ncol = col.empty() ? 0 : *std::max_element(col.begin(), col.end()) + 1;
1467 return triplet(row, col, d, nrow, ncol);
1470 template<
typename Scalar>
1471 Matrix<Scalar> Matrix<Scalar>::triplet(
const std::vector<casadi_int>& row,
1472 const std::vector<casadi_int>& col,
1473 const Matrix<Scalar>& d,
1474 const std::pair<casadi_int, casadi_int>& rc) {
1475 return triplet(row, col, d, rc.first, rc.second);
1478 template<
typename Scalar>
1479 Matrix<Scalar> Matrix<Scalar>::triplet(
const std::vector<casadi_int>& row,
1480 const std::vector<casadi_int>& col,
1481 const Matrix<Scalar>& d,
1482 casadi_int nrow, casadi_int ncol) {
1483 casadi_assert(col.size()==row.size() && col.size()==d.nnz(),
1484 "Argument error in Matrix<Scalar>::triplet(row, col, d): "
1485 "supplied lists must all be of equal length, but got: "
1486 + str(row.size()) +
", " + str(col.size()) +
" and " + str(d.nnz()));
1487 std::vector<casadi_int> mapping;
1488 Sparsity sp = Sparsity::triplet(nrow, ncol, row, col, mapping,
false);
1489 return Matrix<Scalar>(sp, d.nz(mapping));
1492 template<
typename Scalar>
1493 Matrix<Scalar> Matrix<Scalar>::eye(casadi_int n) {
1494 return Matrix<Scalar>::ones(Sparsity::diag(n));
1497 template<
typename Scalar>
1498 Matrix<Scalar> Matrix<Scalar>::inf(
const Sparsity& sp) {
1499 casadi_assert(std::numeric_limits<Scalar>::has_infinity,
1500 "Datatype cannot represent infinity");
1501 return Matrix<Scalar>(sp, std::numeric_limits<Scalar>::infinity(),
false);
1505 template<
typename Scalar>
1506 Matrix<Scalar> Matrix<Scalar>::inf(
const std::pair<casadi_int, casadi_int>& rc) {
1507 return inf(rc.first, rc.second);
1510 template<
typename Scalar>
1511 Matrix<Scalar> Matrix<Scalar>::inf(casadi_int nrow, casadi_int ncol) {
1512 return inf(Sparsity::dense(nrow, ncol));
1515 template<
typename Scalar>
1516 Matrix<Scalar> Matrix<Scalar>::nan(
const Sparsity& sp) {
1517 casadi_assert(std::numeric_limits<Scalar>::has_quiet_NaN,
1518 "Datatype cannot represent not-a-number");
1519 return Matrix<Scalar>(sp, std::numeric_limits<Scalar>::quiet_NaN(),
false);
1522 template<
typename Scalar>
1523 Matrix<Scalar> Matrix<Scalar>::nan(
const std::pair<casadi_int, casadi_int>& rc) {
1524 return nan(rc.first, rc.second);
1527 template<
typename Scalar>
1528 Matrix<Scalar> Matrix<Scalar>::nan(casadi_int nrow, casadi_int ncol) {
1529 return nan(Sparsity::dense(nrow, ncol));
1532 template<
typename Scalar>
1533 bool Matrix<Scalar>::is_regular()
const {
1537 template<
typename Scalar>
1538 bool Matrix<Scalar>::is_smooth()
const {
1542 template<
typename Scalar>
1543 casadi_int Matrix<Scalar>::element_hash()
const {
1544 casadi_error(
"'element_hash' not defined for " + type_name());
1547 template<
typename Scalar>
1548 bool Matrix<Scalar>::is_leaf()
const {
1549 casadi_error(
"'is_leaf' not defined for " + type_name());
1552 template<
typename Scalar>
1553 bool Matrix<Scalar>::is_commutative()
const {
1554 casadi_error(
"'is_commutative' not defined for " + type_name());
1557 template<
typename Scalar>
1558 bool Matrix<Scalar>::is_symbolic()
const {
1562 template<
typename Scalar>
1563 casadi_int Matrix<Scalar>::op()
const {
1564 casadi_error(
"'op' not defined for " + type_name());
1567 template<
typename Scalar>
1568 bool Matrix<Scalar>::is_op(casadi_int k)
const {
1569 casadi_error(
"'is_op' not defined for " + type_name());
1572 template<
typename Scalar>
1573 void Matrix<Scalar>::export_code(
const std::string& lang,
1574 std::ostream &stream,
const Dict& options)
const {
1575 casadi_error(
"'export_code' not defined for " + type_name());
1578 template<
typename Scalar>
1579 bool Matrix<Scalar>::is_valid_input()
const {
1583 template<
typename Scalar>
1584 bool Matrix<Scalar>::has_duplicates()
const {
1585 casadi_error(
"'has_duplicates' not defined for " + type_name());
1588 template<
typename Scalar>
1589 void Matrix<Scalar>::reset_input()
const {
1590 casadi_error(
"'reset_input' not defined for " + type_name());
1593 template<
typename Scalar>
1594 Matrix<double> Matrix<Scalar>::from_file(
const std::string& filename,
1595 const std::string& format_hint) {
1596 casadi_error(
"'from_file' not defined for " + type_name());
1599 template<
typename Scalar>
1600 bool Matrix<Scalar>::is_integer()
const {
1602 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_integer(e))
return false;
1608 template<
typename Scalar>
1609 bool Matrix<Scalar>::is_constant()
const {
1611 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_constant(e))
return false;
1617 template<
typename Scalar>
1618 bool Matrix<Scalar>::is_call()
const {
1619 casadi_assert(is_scalar(),
"'is_call' only defined for scalar expressions");
1624 template<
typename Scalar>
1625 bool Matrix<Scalar>::is_output()
const {
1626 casadi_assert(is_scalar(),
"'is_output' only defined for scalar expressions");
1631 template<
typename Scalar>
1632 Matrix<Scalar> Matrix<Scalar>::get_output(casadi_int oind)
const {
1633 casadi_error(
"'get_output' not defined for " + type_name());
1636 template<
typename Scalar>
1637 bool Matrix<Scalar>::has_output()
const {
1638 casadi_assert(is_scalar(),
"'has_output' only defined for scalar expressions");
1643 template<
typename Scalar>
1644 Function Matrix<Scalar>::which_function()
const {
1645 casadi_error(
"'which_function' not defined for " + type_name());
1648 template<
typename Scalar>
1649 casadi_int Matrix<Scalar>::which_output()
const {
1650 casadi_error(
"'which_output' not defined for " + type_name());
1653 template<
typename Scalar>
1654 bool Matrix<Scalar>::is_one()
const {
1655 if (!is_dense())
return false;
1658 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_one(e))
return false;
1663 template<
typename Scalar>
1664 bool Matrix<Scalar>::is_minus_one()
const {
1665 if (!is_dense())
return false;
1668 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_minus_one(e))
return false;
1673 template<
typename Scalar>
1674 bool Matrix<Scalar>::is_half()
const {
1675 if (!is_dense())
return false;
1678 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_half(e))
return false;
1683 template<
typename Scalar>
1684 bool Matrix<Scalar>::is_value(
double val)
const {
1685 if (val==0.0)
return is_zero();
1686 if (!is_dense())
return false;
1689 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_value(e, val))
return false;
1694 template<
typename Scalar>
1695 bool Matrix<Scalar>::is_inf()
const {
1696 if (!is_dense())
return false;
1699 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_inf(e))
return false;
1704 template<
typename Scalar>
1705 bool Matrix<Scalar>::is_minus_inf()
const {
1706 if (!is_dense())
return false;
1709 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_minus_inf(e))
return false;
1714 template<
typename Scalar>
1715 bool Matrix<Scalar>::is_nonnegative()
const {
1716 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_nonnegative(e))
return false;
1720 template<
typename Scalar>
1721 bool Matrix<Scalar>::is_zero()
const {
1724 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_zero(e))
return false;
1729 template<
typename Scalar>
1730 bool Matrix<Scalar>::is_eye()
const {
1733 if (!sparsity().is_diag())
return false;
1736 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_one(e))
return false;
1741 template<
typename Scalar>
1742 bool Matrix<Scalar>::is_equal(
const Matrix<Scalar> &x,
const Matrix<Scalar> &y,
1745 casadi_assert(x.size() == y.size(),
"Dimension mismatch");
1748 if (x.sparsity() != y.sparsity()) {
1749 Sparsity sp = x.sparsity() + y.sparsity();
1750 return is_equal(project(x, sp), project(y, sp), depth);
1754 auto y_it = y.nonzeros().begin();
1755 for (
auto&& e : x.nonzeros()) {
1756 if (!casadi_limits<Scalar>::is_equal(e, *y_it++, depth))
return false;
1764 template<
typename Scalar>
1765 inline Matrix<Scalar> mmin_nonstatic(
const Matrix<Scalar> &x) {
1766 if (x.is_empty())
return Matrix<Scalar>();
1767 return casadi_mmin(x.ptr(), x.nnz(), x.is_dense());
1770 template<
typename Scalar>
1771 Matrix<Scalar> Matrix<Scalar>::mmin(
const Matrix<Scalar> &x) {
1772 return mmin_nonstatic(x);
1776 template<
typename Scalar>
1777 inline Matrix<Scalar> mmax_nonstatic(
const Matrix<Scalar> &x) {
1778 if (x.is_empty())
return Matrix<Scalar>();
1779 return casadi_mmax(x.ptr(), x.nnz(), x.is_dense());
1782 template<
typename Scalar>
1783 Matrix<Scalar> Matrix<Scalar>::mmax(
const Matrix<Scalar> &x) {
1784 return mmax_nonstatic(x);
1787 template<
typename Scalar>
1788 bool Matrix<Scalar>::has_zeros()
const {
1790 for (
auto&& e : nonzeros())
if (casadi_limits<Scalar>::is_zero(e))
return true;
1796 template<
typename Scalar>
1797 std::vector<Scalar> Matrix<Scalar>::get_nonzeros()
const {
1801 template<
typename Scalar>
1802 std::vector<Scalar> Matrix<Scalar>::get_elements()
const {
1803 return static_cast< std::vector<Scalar>
>(*this);
1806 template<
typename Scalar>
1807 std::string Matrix<Scalar>::name()
const {
1808 casadi_error(
"'name' not defined for " + type_name());
1811 template<
typename Scalar>
1812 Matrix<Scalar> Matrix<Scalar>::dep(casadi_int ch)
const {
1813 casadi_error(
"'dep' not defined for " + type_name());
1816 template<
typename Scalar>
1817 casadi_int Matrix<Scalar>::n_dep()
const {
1818 casadi_error(
"'n_dep' not defined for " + type_name());
1821 template<
typename Scalar>
1822 Matrix<Scalar> Matrix<Scalar>::rand(
1825 return rand(Sparsity::dense(nrow, ncol));
1828 template<
typename Scalar>
1829 Matrix<Scalar> Matrix<Scalar>::rand(
1830 const std::pair<casadi_int, casadi_int>& rc) {
1831 return rand(rc.first, rc.second);
1834 template<
typename Scalar>
1835 Matrix<Scalar> Matrix<Scalar>::project(
const Matrix<Scalar>& x,
1836 const Sparsity& sp,
bool intersect) {
1838 return project(x, sp.intersect(x.sparsity()),
false);
1840 casadi_assert(sp.size()==x.size(),
"Dimension mismatch");
1841 Matrix<Scalar> ret = Matrix<Scalar>::zeros(sp);
1842 std::vector<Scalar> w(x.size1());
1843 casadi_project(x.ptr(), x.sparsity(), ret.ptr(), sp, get_ptr(w));
1848 template<
typename Scalar>
1849 void Matrix<Scalar>::set_max_depth(casadi_int eq_depth) {
1850 casadi_error(
"'set_max_depth' not defined for " + type_name());
1853 template<
typename Scalar>
1854 casadi_int Matrix<Scalar>::get_max_depth() {
1855 casadi_error(
"'get_max_depth' not defined for " + type_name());
1858 template<
typename Scalar>
1859 Matrix<Scalar> Matrix<Scalar>::det(
const Matrix<Scalar>& x) {
1860 casadi_int n = x.size2();
1861 casadi_assert(n == x.size1(),
"matrix must be square");
1864 if (x.is_scalar())
return x;
1867 if (n==2)
return x(0, 0) * x(1, 1) - x(0, 1) * x(1, 0);
1870 Matrix<Scalar> ret = 0;
1875 Matrix<casadi_int> sp = IM::ones(x.sparsity());
1878 Matrix<casadi_int> row_count = Matrix<casadi_int>::sum2(sp);
1881 if (!row_count.is_dense())
return 0;
1884 Matrix<casadi_int> col_count = Matrix<casadi_int>::sum1(sp).T();
1887 if (!col_count.is_dense())
return 0;
1889 casadi_int min_row = std::distance(row_count.nonzeros().begin(),
1890 std::min_element(row_count.nonzeros().begin(),
1891 row_count.nonzeros().end()));
1892 casadi_int min_col = std::distance(col_count.nonzeros().begin(),
1893 std::min_element(col_count.nonzeros().begin(),
1894 col_count.nonzeros().end()));
1896 if (min_row <= min_col) {
1898 casadi_int j = row_count.sparsity().row(min_row);
1900 Matrix<Scalar> row = x(j, Slice(0, n));
1902 std::vector< casadi_int > col_i = row.sparsity().get_col();
1904 for (casadi_int k=0; k<row.nnz(); ++k) {
1906 ret += row->at(k)*cofactor(x, col_i.at(k), j);
1911 casadi_int i = col_count.sparsity().row(min_col);
1913 Matrix<Scalar> col = x(Slice(0, n), i);
1915 const casadi_int* row_i = col.row();
1917 for (casadi_int k=0; k<col.nnz(); ++k) {
1919 ret += col->at(k)*cofactor(x, i, row_i[k]);
1926 template<
typename Scalar>
1927 Matrix<Scalar> Matrix<Scalar>::
1928 det(
const Matrix<Scalar>& x,
const std::string& lsolver,
const Dict& dict) {
1929 casadi_error(
"'det' with plugin not defined for " + type_name());
1930 return Matrix<Scalar>();
1933 template<
typename Scalar>
1934 Matrix<Scalar> Matrix<Scalar>::sum2(
const Matrix<Scalar>& x) {
1935 return mtimes(x, Matrix<Scalar>::ones(x.size2(), 1));
1938 template<
typename Scalar>
1939 Matrix<Scalar> Matrix<Scalar>::sum1(
const Matrix<Scalar>& x) {
1940 return mtimes(Matrix<Scalar>::ones(1, x.size1()), x);
1943 template<
typename Scalar>
1944 Matrix<Scalar> Matrix<Scalar>::minor(
const Matrix<Scalar>& x,
1945 casadi_int i, casadi_int j) {
1946 casadi_int n = x.size2();
1947 casadi_assert(n == x.size1(),
"minor: matrix must be square");
1953 Matrix<Scalar> M = Matrix<Scalar>(n-1, n-1);
1955 std::vector<casadi_int> col = x.sparsity().get_col();
1956 const casadi_int* row = x.sparsity().row();
1958 for (casadi_int k=0; k<x.nnz(); ++k) {
1959 casadi_int i1 = col[k];
1960 casadi_int j1 = row[k];
1962 if (i1 == i || j1 == j)
continue;
1964 casadi_int i2 = (i1<i)?i1:i1-1;
1965 casadi_int j2 = (j1<j)?j1:j1-1;
1967 M(j2, i2) = x(j1, i1);
1972 template<
typename Scalar>
1973 Matrix<Scalar> Matrix<Scalar>::cofactor(
const Matrix<Scalar>& A, casadi_int i, casadi_int j) {
1976 Matrix<Scalar> minor_ij = minor(A, i, j);
1978 casadi_int sign_i = 1-2*((i+j) % 2);
1980 return sign_i * minor_ij;
1983 template<
typename Scalar>
1984 Matrix<Scalar> Matrix<Scalar>::adj(
const Matrix<Scalar>& x) {
1985 casadi_int n = x.size2();
1986 casadi_assert(n == x.size1(),
"adj: matrix must be square");
1989 Matrix<Scalar> temp;
1992 Matrix<Scalar>
C = Matrix<Scalar>(n, n);
1993 for (casadi_int i=0; i<n; ++i)
1994 for (casadi_int j=0; j<n; ++j) {
1995 temp = cofactor(x, i, j);
1996 if (!temp.is_zero())
C(j, i) = temp;
2002 template<
typename Scalar>
2003 Matrix<Scalar> Matrix<Scalar>::inv_minor(
const Matrix<Scalar>& x) {
2005 return adj(x)/det(x);
2008 template<
typename Scalar>
2009 Matrix<Scalar> Matrix<Scalar>::reshape(
const Matrix<Scalar>& x,
2010 casadi_int nrow, casadi_int ncol) {
2011 Sparsity sp = Sparsity::reshape(x.sparsity(), nrow, ncol);
2012 return Matrix<Scalar>(sp, x.nonzeros(),
false);
2015 template<
typename Scalar>
2016 Matrix<Scalar> Matrix<Scalar>::reshape(
const Matrix<Scalar>& x,
const Sparsity& sp) {
2018 if (sp==x.sparsity())
return x;
2021 casadi_assert(sp.is_reshape(x.sparsity()),
2022 "Reshape mismatch: cannot reshape " + x.dim() +
" to " + sp.dim(
true));
2024 return Matrix<Scalar>(sp, x.nonzeros(),
false);
2027 template<
typename Scalar>
2028 Matrix<Scalar> Matrix<Scalar>::sparsity_cast(
const Matrix<Scalar>& x,
const Sparsity& sp) {
2030 if (sp==x.sparsity())
return x;
2032 casadi_assert(sp.nnz()==x.nnz(),
"sparsity_cast: x has " + str(x.nnz()) +
" nonzeros, "
2033 "but the target pattern has " + str(sp.nnz()));
2035 return Matrix<Scalar>(sp, x.nonzeros(),
false);
2038 template<
typename Scalar>
2039 Matrix<Scalar> Matrix<Scalar>::trace(
const Matrix<Scalar>& x) {
2040 casadi_assert(x.is_square(),
"trace: must be square");
2042 const Scalar* d=x.ptr();
2043 casadi_int size2 = x.size2();
2044 const casadi_int *colind=x.colind(), *row=x.row();
2045 for (casadi_int c=0; c<size2; c++) {
2046 for (casadi_int k=colind[c]; k!=colind[c+1]; ++k) {
2055 template<
typename Scalar>
2057 Matrix<Scalar>::blockcat(
const std::vector< std::vector<Matrix<Scalar> > > &v) {
2058 std::vector< Matrix<Scalar> > ret;
2059 for (casadi_int i=0; i<v.size(); ++i)
2060 if (!v[i].empty()) ret.push_back(horzcat(v[i]));
2061 if (ret.empty())
return Matrix<Scalar>(0, 0);
2062 return vertcat(ret);
2065 template<
typename Scalar>
2066 Matrix<Scalar> Matrix<Scalar>::horzcat(
const std::vector<Matrix<Scalar> > &v) {
2068 std::vector<Sparsity> sp(v.size());
2069 for (casadi_int i=0; i<v.size(); ++i) sp[i] = v[i].sparsity();
2070 Matrix<Scalar> ret = zeros(Sparsity::horzcat(sp));
2073 auto i=ret->begin();
2074 for (
auto&& j : v) {
2075 std::copy(j->begin(), j->end(), i);
2081 template<
typename Scalar>
2082 std::vector<Matrix<Scalar> >
2083 Matrix<Scalar>::horzsplit(
const Matrix<Scalar>& x,
const std::vector<casadi_int>& offset) {
2085 std::vector<Sparsity> sp = Sparsity::horzsplit(x.sparsity(), offset);
2088 std::vector<Matrix<Scalar> > ret;
2089 ret.reserve(sp.size());
2092 auto i=x.nonzeros().begin();
2093 for (
auto&& j : sp) {
2094 auto i_next = i + j.nnz();
2095 ret.push_back(Matrix<Scalar>(j, std::vector<Scalar>(i, i_next),
false));
2100 casadi_assert_dev(i==x.nonzeros().end());
2104 template<
typename Scalar>
2105 Matrix<Scalar> Matrix<Scalar>::vertcat(
const std::vector<Matrix<Scalar> > &v) {
2107 casadi_int ncol = 0;
2108 for (
auto&& e : v) {
2109 if (e.size2()==0)
continue;
2110 casadi_assert(ncol==0 || e.size2()==ncol,
"vertcat: Mismatching number of columns, "
2111 "got " + str(ncol) +
" and " + str(e.size2()));
2115 std::vector<Matrix<Scalar> > vT(v.size());
2116 for (casadi_int i=0; i<v.size(); ++i) vT[i] = v[i].
T();
2117 return horzcat(vT).T();
2120 template<
typename Scalar>
2121 std::vector< Matrix<Scalar> >
2122 Matrix<Scalar>::vertsplit(
const Matrix<Scalar>& x,
const std::vector<casadi_int>& offset) {
2123 std::vector< Matrix<Scalar> > ret = horzsplit(x.T(), offset);
2124 for (
auto&& e : ret) e = e.T();
2128 template<
typename Scalar>
2129 std::vector< Matrix<Scalar> >
2130 Matrix<Scalar>::diagsplit(
const Matrix<Scalar>& x,
const std::vector<casadi_int>& offset1,
2131 const std::vector<casadi_int>& offset2) {
2133 check_offset(offset1, x.size1(),
"diagsplit");
2134 check_offset(offset2, x.size2(),
"diagsplit");
2135 casadi_assert(offset1.size()==offset2.size(),
2136 "diagsplit: offset1 and offset2 must have the same length");
2139 casadi_int n = offset1.size()-1;
2142 std::vector< Matrix<Scalar> > ret;
2145 for (casadi_int i=0; i<n; ++i) {
2146 ret.push_back(x(Slice(offset1[i], offset1[i+1]), Slice(offset2[i], offset2[i+1])));
2150 casadi_int n_dropped = 0;
2151 for (
auto&& e : x.nonzeros()) n_dropped += !casadi_limits<Scalar>::is_zero(e);
2152 for (
auto&& r : ret) {
2153 for (
auto&& e : r.nonzeros()) n_dropped -= !casadi_limits<Scalar>::is_zero(e);
2155 casadi_assert(n_dropped==0,
2156 "diagsplit: the presence of nonzeros outside the diagonal blocks is unsupported.");
2161 template<
typename Scalar>
2162 Matrix<Scalar> Matrix<Scalar>::dot(
const Matrix<Scalar> &x,
2163 const Matrix<Scalar> &y) {
2164 casadi_assert(x.size()==y.size(),
"dot: Dimension mismatch");
2165 if (x.sparsity()!=y.sparsity()) {
2166 Sparsity sp = x.sparsity() * y.sparsity();
2167 return dot(project(x, sp), project(y, sp));
2169 return casadi_dot(x.nnz(), x.ptr(), y.ptr());
2172 template<
typename Scalar>
2173 Matrix<Scalar> Matrix<Scalar>::all(
const Matrix<Scalar>& x) {
2174 if (!x.is_dense())
return false;
2176 for (casadi_int i=0; i<x.nnz(); ++i) {
2177 ret = ret && x->at(i)==1;
2182 template<
typename Scalar>
2183 Matrix<Scalar> Matrix<Scalar>::any(
const Matrix<Scalar>& x) {
2184 if (!x.is_dense())
return false;
2186 for (casadi_int i=0; i<x.nnz(); ++i) {
2187 ret = ret || x->at(i)==1;
2192 template<
typename Scalar>
2193 Matrix<Scalar> Matrix<Scalar>::norm_1(
const Matrix<Scalar>& x) {
2194 return casadi_norm_1(x.nnz(), x.ptr());
2197 template<
typename Scalar>
2198 Matrix<Scalar> Matrix<Scalar>::norm_2(
const Matrix<Scalar>& x) {
2199 if (x.is_vector()) {
2202 casadi_error(
"2-norms currently only supported for vectors. "
2203 "Did you intend to calculate a Frobenius norms (norm_fro)?");
2207 template<
typename Scalar>
2208 Matrix<Scalar> Matrix<Scalar>::norm_fro(
const Matrix<Scalar>& x) {
2209 return casadi_norm_2(x.nnz(), x.ptr());
2212 template<
typename Scalar>
2213 Matrix<Scalar> Matrix<Scalar>::norm_inf(
const Matrix<Scalar>& x) {
2215 Matrix<Scalar> s = 0;
2216 for (
auto i=x.nonzeros().begin(); i!=x.nonzeros().end(); ++i) {
2217 s = fmax(s, fabs(Matrix<Scalar>(*i)));
2222 template<
typename Scalar>
2223 void Matrix<Scalar>::
2224 qr_sparse(
const Matrix<Scalar>& A,
2225 Matrix<Scalar>& V, Matrix<Scalar> &R, Matrix<Scalar>& beta,
2226 std::vector<casadi_int>& prinv, std::vector<casadi_int>& pc,
bool amd) {
2229 A.sparsity().qr_sparse(spV, spR, prinv, pc, amd);
2231 casadi_int nrow_ext = spV.size1(), ncol = spV.size2();
2234 beta = nan(ncol, 1);
2235 std::vector<Scalar> w(nrow_ext);
2236 casadi_qr(A.sparsity(), A.ptr(), get_ptr(w), spV, V.ptr(),
2237 spR, R.ptr(), beta.ptr(),
2238 get_ptr(prinv), get_ptr(pc));
2241 template<
typename Scalar>
2242 Matrix<Scalar> Matrix<Scalar>::
2243 qr_solve(
const Matrix<Scalar>& b,
const Matrix<Scalar>& v,
2244 const Matrix<Scalar>& r,
const Matrix<Scalar>& beta,
2245 const std::vector<casadi_int>& prinv,
const std::vector<casadi_int>& pc,
2248 casadi_int ncol = v.size2();
2249 casadi_int nrow =
b.size1(), nrhs =
b.size2();
2250 casadi_assert(r.size()==v.size(),
"'r', 'v' dimension mismatch");
2251 casadi_assert(beta.is_vector() && beta.numel()==ncol,
"'beta' has wrong dimension");
2252 casadi_assert(prinv.size()==r.size1(),
"'pinv' has wrong dimension");
2254 std::vector<Scalar> w(nrow+ncol);
2256 Matrix<Scalar> x = densify(b);
2257 casadi_qr_solve(x.ptr(), nrhs, tr, v.sparsity(), v.ptr(), r.sparsity(), r.ptr(),
2258 beta.ptr(), get_ptr(prinv), get_ptr(pc), get_ptr(w));
2262 template<
typename Scalar>
2263 void Matrix<Scalar>::qr(
const Matrix<Scalar>& A,
2264 Matrix<Scalar>& Q, Matrix<Scalar> &R) {
2267 casadi_assert(A.size1()>=A.size2(),
"qr: fewer rows than columns");
2270 Q = R = Matrix<Scalar>();
2271 for (casadi_int i=0; i<A.size2(); ++i) {
2273 Matrix<Scalar> ai = A(Slice(), i);
2274 Matrix<Scalar> qi = ai;
2276 Matrix<Scalar> ri = Matrix<Scalar>(A.size2(), 1);
2279 for (casadi_int j=0; j<i; ++j) {
2282 Matrix<Scalar> qj =
Q(Slice(), j);
2284 ri(j, 0) = mtimes(qi.T(), qj);
2288 if (ri.has_nz(j, 0))
2289 qi -= ri(j, 0) * qj;
2293 ri(i, 0) = norm_2(qi);
2297 Q = Matrix<Scalar>::horzcat({
Q, qi});
2298 R = Matrix<Scalar>::horzcat({R, ri});
2302 template<
typename Scalar>
2303 void Matrix<Scalar>::ldl(
const Matrix<Scalar>& A, Matrix<Scalar> &D,
2304 Matrix<Scalar>& LT, std::vector<casadi_int>& p,
bool amd) {
2306 Sparsity Lt_sp = A.sparsity().ldl(p, amd);
2309 casadi_int n=A.size1();
2312 std::vector<Scalar> D_nz(n), L_nz(Lt_sp.nnz()), w(n);
2313 casadi_ldl(A.sparsity(), get_ptr(A.nonzeros()), Lt_sp,
2314 get_ptr(L_nz), get_ptr(D_nz), get_ptr(p), get_ptr(w));
2317 LT = Matrix<Scalar>(Lt_sp, L_nz);
2321 template<
typename Scalar>
2322 Matrix<Scalar> Matrix<Scalar>::
2323 ldl_solve(
const Matrix<Scalar>& b,
const Matrix<Scalar>& D,
const Matrix<Scalar>& LT,
2324 const std::vector<casadi_int>& p) {
2326 casadi_int n =
b.size1(), nrhs =
b.size2();
2327 casadi_assert(p.size()==n,
"'p' has wrong dimension");
2328 casadi_assert(LT.size1()==n && LT.size2()==n,
"'LT' has wrong dimension");
2329 casadi_assert(
D.is_vector() &&
D.numel()==n,
"'D' has wrong dimension");
2331 Matrix<Scalar> x = densify(b);
2332 std::vector<Scalar> w(n);
2333 casadi_ldl_solve(x.ptr(), nrhs, LT.sparsity(), LT.ptr(),
D.ptr(), get_ptr(p), get_ptr(w));
2337 template<
typename Scalar>
2338 Matrix<Scalar> Matrix<Scalar>::nullspace(
const Matrix<Scalar>& A) {
2339 Matrix<Scalar>
X = A;
2340 casadi_int n =
X.size1();
2341 casadi_int m =
X.size2();
2342 casadi_assert(m>=n,
"nullspace(): expecting a flat matrix (more columns than rows), "
2343 "but got " + str(
X.dim()) +
".");
2345 Matrix<Scalar> seed = DM::eye(m)(Slice(0, m), Slice(n, m));
2347 std::vector< Matrix<Scalar> > us;
2348 std::vector< Matrix<Scalar> > betas;
2350 Matrix<Scalar> beta;
2352 for (casadi_int i=0;i<n;++i) {
2353 Matrix<Scalar> x =
X(i, Slice(i, m));
2354 Matrix<Scalar> u = Matrix<Scalar>(x);
2355 Matrix<Scalar> sigma = sqrt(sum2(x*x));
2356 const Matrix<Scalar>& x0 = x(0, 0);
2359 Matrix<Scalar>
b = -copysign(sigma, x0);
2361 u(Slice(0), Slice(1, m-i))*= 1/(x0-
b);
2364 X(Slice(i, n), Slice(i, m)) -=
2365 beta*mtimes(mtimes(
X(Slice(i, n), Slice(i, m)), u.T()), u);
2367 betas.push_back(beta);
2370 for (casadi_int i=n-1;i>=0;--i) {
2371 seed(Slice(i, m), Slice(0, m-n)) -=
2372 betas[i]*mtimes(us[i].
T(), mtimes(us[i], seed(Slice(i, m), Slice(0, m-n))));
2379 template<
typename Scalar>
2380 Matrix<Scalar> Matrix<Scalar>::chol(
const Matrix<Scalar>& A) {
2382 Matrix<Scalar>
D, LT;
2383 std::vector<casadi_int> p;
2384 ldl(A, D, LT, p,
false);
2386 LT += Matrix<Scalar>::eye(
D.size1());
2388 return mtimes(diag(sqrt(D)), LT);
2391 template<
typename Scalar>
2392 Matrix<Scalar> Matrix<Scalar>::solve(
const Matrix<Scalar>& a,
const Matrix<Scalar>& b) {
2394 casadi_assert(a.size1() ==
b.size1(),
"solve Ax=b: dimension mismatch: b has "
2395 + str(
b.size1()) +
" rows while A has " + str(a.size1()) +
".");
2396 casadi_assert(a.size1() == a.size2(),
"solve: A not square but " + str(a.dim()));
2400 Matrix<Scalar> x =
b;
2401 const casadi_int* Arow = a.row();
2402 const casadi_int* Acolind = a.colind();
2403 const std::vector<Scalar> & Adata = a.nonzeros();
2404 for (casadi_int i=0; i<a.size2(); ++i) {
2405 for (casadi_int k=0; k<
b.size2(); ++k) {
2406 if (!x.has_nz(i, k))
continue;
2408 for (casadi_int kk=Acolind[i+1]-1; kk>=Acolind[i] && Arow[kk]>i; --kk) {
2409 casadi_int j = Arow[kk];
2410 x(j, k) -= Adata[kk]*x(i, k);
2415 }
else if (a.is_triu()) {
2417 Matrix<Scalar> x =
b;
2418 const casadi_int* Arow = a.row();
2419 const casadi_int* Acolind = a.colind();
2420 const std::vector<Scalar> & Adata = a.nonzeros();
2421 for (casadi_int i=a.size2()-1; i>=0; --i) {
2422 for (casadi_int k=0; k<
b.size2(); ++k) {
2423 if (!x.has_nz(i, k))
continue;
2425 for (casadi_int kk=Acolind[i]; kk<Acolind[i+1] && Arow[kk]<i; ++kk) {
2426 casadi_int j = Arow[kk];
2427 x(j, k) -= Adata[kk]*x(i, k);
2432 }
else if (a.has_zeros()) {
2436 return solve(sparsify(a), b);
2441 std::vector<casadi_int> rowperm, colperm, rowblock, colblock;
2442 std::vector<casadi_int> coarse_rowblock, coarse_colblock;
2443 a.sparsity().btf(rowperm, colperm, rowblock, colblock,
2444 coarse_rowblock, coarse_colblock);
2447 Matrix<Scalar> bperm =
b(rowperm, Slice());
2450 Matrix<Scalar> Aperm = a(rowperm, colperm);
2453 Matrix<Scalar> xperm;
2456 if (Aperm.is_tril()) {
2459 xperm = solve(Aperm, bperm);
2461 }
else if (a.size2()<=3) {
2464 xperm = mtimes(inv_minor(Aperm), bperm);
2469 Matrix<Scalar>
Q, R;
2473 xperm = solve(R, mtimes(
Q.T(), bperm));
2477 std::vector<casadi_int> inv_colperm(colperm.size());
2478 for (casadi_int k=0; k<colperm.size(); ++k)
2479 inv_colperm[colperm[k]] = k;
2482 Matrix<Scalar> x = xperm(inv_colperm, Slice());
2487 template<
typename Scalar>
2488 Matrix<Scalar> Matrix<Scalar>::
2489 solve(
const Matrix<Scalar>& a,
const Matrix<Scalar>& b,
2490 const std::string& lsolver,
const Dict& dict) {
2491 casadi_error(
"'solve' with plugin not defined for " + type_name());
2492 return Matrix<Scalar>();
2495 template<
typename Scalar>
2496 Matrix<Scalar> Matrix<Scalar>::
2497 inv(
const Matrix<Scalar>& a) {
2498 return solve(a, Matrix<Scalar>::eye(a.size1()));
2501 template<
typename Scalar>
2502 Matrix<Scalar> Matrix<Scalar>::
2503 inv(
const Matrix<Scalar>& a,
2504 const std::string& lsolver,
const Dict& dict) {
2505 casadi_error(
"'inv' with plugin not defined for " + type_name());
2506 return Matrix<Scalar>();
2509 template<
typename Scalar>
2510 Matrix<Scalar> Matrix<Scalar>::pinv(
const Matrix<Scalar>& A) {
2511 if (A.size2()>=A.size1()) {
2512 return solve(mtimes(A, A.T()), A).T();
2514 return solve(mtimes(A.T(), A), A.T());
2518 template<
typename Scalar>
2519 Matrix<Scalar> Matrix<Scalar>::
2520 pinv(
const Matrix<Scalar>& A,
const std::string& lsolver,
const Dict& dict) {
2521 casadi_error(
"'solve' not defined for " + type_name());
2522 return Matrix<Scalar>();
2525 template<
typename Scalar>
2526 Matrix<Scalar> Matrix<Scalar>::
2527 expm_const(
const Matrix<Scalar>& A,
const Matrix<Scalar>& t) {
2528 casadi_error(
"'solve' not defined for " + type_name());
2529 return Matrix<Scalar>();
2532 template<
typename Scalar>
2533 Matrix<Scalar> Matrix<Scalar>::
2534 expm(
const Matrix<Scalar>& A) {
2535 casadi_error(
"'solve' not defined for " + type_name());
2536 return Matrix<Scalar>();
2539 template<
typename Scalar>
2540 Matrix<Scalar> Matrix<Scalar>::kron(
const Matrix<Scalar>& a,
const Matrix<Scalar>& b) {
2541 std::vector<Scalar> ret(a.nnz()*
b.nnz());
2542 casadi_kron(get_ptr(a), a.sparsity(), get_ptr(b),
b.sparsity(), get_ptr(ret));
2544 Sparsity sp_ret = Sparsity::kron(a.sparsity(),
b.sparsity());
2545 return Matrix<Scalar>(sp_ret, ret,
false);
2548 template<
typename Scalar>
2549 Matrix<Scalar> Matrix<Scalar>::diag(
const Matrix<Scalar>& A) {
2551 std::vector<casadi_int> mapping;
2553 Sparsity sp = A.sparsity().get_diag(mapping);
2555 Matrix<Scalar> ret = zeros(sp);
2557 for (casadi_int k=0; k<mapping.size(); k++) ret.nz(k) = A.nz(mapping[k]);
2564 template<
typename Scalar>
2565 Matrix<Scalar> Matrix<Scalar>::diagcat(
const std::vector< Matrix<Scalar> > &A) {
2566 std::vector<Scalar> data;
2568 std::vector<Sparsity> sp;
2569 for (casadi_int i=0;i<A.size();++i) {
2570 data.insert(data.end(), A[i].nonzeros().begin(), A[i].nonzeros().end());
2571 sp.push_back(A[i].sparsity());
2574 return Matrix<Scalar>(Sparsity::diagcat(sp), data,
false);
2580 template<
typename Scalar>
2581 bool Matrix<Scalar>::simplify_ref_count(std::vector< Matrix<Scalar> >& arg,
2582 std::vector< Matrix<Scalar> >& res,
2584 casadi_error(
"'simplify_ref_count' not defined for " + type_name());
2590 template<
typename Scalar>
2591 bool Matrix<Scalar>::simplify_const_folding(std::vector< Matrix<Scalar> >& arg,
2592 std::vector< Matrix<Scalar> >& res,
2594 casadi_error(
"'simplify_const_folding' not defined for " + type_name());
2597 template<
typename Scalar>
2598 bool Matrix<Scalar>::simplify_combine_terms(std::vector< Matrix<Scalar> >& arg,
2599 std::vector< Matrix<Scalar> >& res,
2601 casadi_error(
"'simplify_combine_terms' not defined for " + type_name());
2604 template<
typename Scalar>
2605 Matrix<Scalar> Matrix<Scalar>::unite(
const Matrix<Scalar>& A,
const Matrix<Scalar>& B) {
2607 std::vector<unsigned char> mapping;
2608 Sparsity sp = A.sparsity().unite(B.sparsity(), mapping);
2611 Matrix<Scalar> ret = zeros(sp);
2614 casadi_int elA=0, elB=0;
2615 for (casadi_int k=0; k<mapping.size(); ++k) {
2616 if (mapping[k]==1) {
2617 ret.nonzeros()[k] = A.nonzeros()[elA++];
2618 }
else if (mapping[k]==2) {
2619 ret.nonzeros()[k] = B.nonzeros()[elB++];
2621 casadi_error(
"Pattern intersection not empty");
2625 casadi_assert_dev(A.nnz()==elA);
2626 casadi_assert_dev(B.nnz()==elB);
2631 template<
typename Scalar>
2632 Matrix<Scalar> Matrix<Scalar>::polyval(
const Matrix<Scalar>& p,
const Matrix<Scalar>& x) {
2633 casadi_assert(p.is_dense(),
"polynomial coefficients vector must be dense");
2634 casadi_assert(p.is_vector() && p.nnz()>0,
"polynomial coefficients must be a vector");
2636 Matrix<Scalar> ret = casadi_limits<Scalar>::is_zero(p->back()) ? x : densify(x);
2637 for (
auto&& e : ret.nonzeros()) {
2638 e = casadi_polyval(p.ptr(), p.numel()-1, e);
2643 template<
typename Scalar>
2644 Matrix<Scalar> Matrix<Scalar>::norm_inf_mul(
const Matrix<Scalar>& x,
2645 const Matrix<Scalar>& y) {
2646 casadi_assert(y.size1()==x.size2(),
"Dimension error. Got " + x.dim()
2647 +
" times " + y.dim() +
".");
2650 std::vector<Scalar> dwork(x.size1());
2651 std::vector<casadi_int> iwork(x.size1()+1+y.size2());
2654 return casadi_norm_inf_mul(x.ptr(), x.sparsity(), y.ptr(), y.sparsity(),
2655 get_ptr(dwork), get_ptr(iwork));
2658 template<
typename Scalar>
2659 void Matrix<Scalar>::expand(
const Matrix<Scalar>& ex,
2660 Matrix<Scalar> &weights, Matrix<Scalar>& terms) {
2661 casadi_error(
"'expand' not defined for " + type_name());
2664 template<
typename Scalar>
2665 Matrix<Scalar> Matrix<Scalar>::pw_const(
const Matrix<Scalar>& ex,
2666 const Matrix<Scalar>& tval,
2667 const Matrix<Scalar>& val) {
2668 casadi_error(
"'pw_const' not defined for " + type_name());
2669 return Matrix<Scalar>();
2672 template<
typename Scalar>
2673 Matrix<Scalar> Matrix<Scalar>::pw_lin(
const Matrix<Scalar>& ex,
2674 const Matrix<Scalar>& tval,
2675 const Matrix<Scalar>& val) {
2676 casadi_error(
"'pw_lin' not defined for " + type_name());
2677 return Matrix<Scalar>();
2680 template<
typename Scalar>
2681 Matrix<Scalar> Matrix<Scalar>::if_else(
const Matrix<Scalar> &cond,
2682 const Matrix<Scalar> &if_true,
2683 const Matrix<Scalar> &if_false,
2684 bool short_circuit) {
2685 return if_else_zero(cond, if_true) + if_else_zero(!cond, if_false);
2688 template<
typename Scalar>
2689 Matrix<Scalar> Matrix<Scalar>::conditional(
const Matrix<Scalar>& ind,
2690 const std::vector<Matrix<Scalar> >& x,
2691 const Matrix<Scalar>& x_default,
2692 bool short_circuit) {
2693 casadi_assert(!short_circuit,
2694 "Short-circuiting 'conditional' not supported for " + type_name());
2695 casadi_assert(ind.is_scalar(
true),
2696 "conditional: first argument must be scalar. Got " + ind.dim()+
" instead.");
2698 Matrix<Scalar> ret = x_default;
2699 for (casadi_int k=0; k<x.size(); ++k) {
2700 ret = if_else(ind==k, x[k], ret, short_circuit);
2705 template<
typename Scalar>
2706 Matrix<Scalar> Matrix<Scalar>::heaviside(
const Matrix<Scalar>& x) {
2707 return (1+sign(x))/2;
2710 template<
typename Scalar>
2711 Matrix<Scalar> Matrix<Scalar>::rectangle(
const Matrix<Scalar>& x) {
2712 return 0.5*(sign(x+0.5)-sign(x-0.5));
2715 template<
typename Scalar>
2716 Matrix<Scalar> Matrix<Scalar>::triangle(
const Matrix<Scalar>& x) {
2717 return rectangle(x/2)*(1-fabs(x));
2720 template<
typename Scalar>
2721 Matrix<Scalar> Matrix<Scalar>::ramp(
const Matrix<Scalar>& x) {
2722 return x*heaviside(x);
2725 template<
typename Scalar>
2726 Matrix<Scalar> Matrix<Scalar>::
2727 gauss_quadrature(
const Matrix<Scalar> &f,
2728 const Matrix<Scalar> &x,
const Matrix<Scalar> &a,
2729 const Matrix<Scalar> &b, casadi_int order) {
2730 return gauss_quadrature(f, x, a, b, order, Matrix<Scalar>());
2733 template<
typename Scalar>
2734 Matrix<Scalar> Matrix<Scalar>::gauss_quadrature(
const Matrix<Scalar>& f,
2735 const Matrix<Scalar>& x,
2736 const Matrix<Scalar>& a,
2737 const Matrix<Scalar>& b, casadi_int order,
2738 const Matrix<Scalar>& w) {
2739 casadi_error(
"'gauss_quadrature' not defined for " + type_name());
2740 return Matrix<Scalar>();
2743 template<
typename Scalar>
2744 Matrix<Scalar> Matrix<Scalar>::simplify(
const Matrix<Scalar> &x) {
2748 template<
typename Scalar>
2749 Matrix<Scalar> Matrix<Scalar>::transform(
const Matrix<Scalar> &x,
const Dict& opts) {
2750 casadi_error(
"'transform' not defined for " + type_name());
2753 template<
typename Scalar>
2754 Matrix<Scalar> Matrix<Scalar>::transform(
const Matrix<Scalar> &x,
2755 const std::vector<std::vector<GenericType> >& passes,
const Dict& opts) {
2756 casadi_error(
"'transform' not defined for " + type_name());
2759 template<
typename Scalar>
2760 std::vector<Matrix<Scalar> > Matrix<Scalar>::transform(
const std::vector<Matrix<Scalar> >& x,
2762 casadi_error(
"'transform' not defined for " + type_name());
2765 template<
typename Scalar>
2766 std::vector<Matrix<Scalar> > Matrix<Scalar>::transform(
const std::vector<Matrix<Scalar> >& x,
2767 const std::vector<std::vector<GenericType> >& passes,
const Dict& opts) {
2768 casadi_error(
"'transform' not defined for " + type_name());
2771 template<
typename Scalar>
2772 Matrix<Scalar> Matrix<Scalar>::substitute(
const Matrix<Scalar>& ex,
2773 const Matrix<Scalar>& v,
2774 const Matrix<Scalar>& vdef) {
2775 casadi_error(
"'substitute' not defined for " + type_name());
2776 return Matrix<Scalar>();
2779 template<
typename Scalar>
2780 std::vector<Matrix<Scalar> >
2781 Matrix<Scalar>::substitute(
const std::vector<Matrix<Scalar> >& ex,
2782 const std::vector<Matrix<Scalar> >& v,
2783 const std::vector<Matrix<Scalar> >& vdef) {
2784 casadi_error(
"'substitute' not defined for " + type_name());
2785 return std::vector<Matrix<Scalar> >();
2788 template<
typename Scalar>
2789 void Matrix<Scalar>::substitute_inplace(
const std::vector<Matrix<Scalar> >& v,
2790 std::vector<Matrix<Scalar> >& vdef,
2791 std::vector<Matrix<Scalar> >& ex,
2793 casadi_error(
"'substitute_inplace' not defined for " + type_name());
2796 template<
typename Scalar>
2797 void Matrix<Scalar>::extract_parametric(
const Matrix<Scalar> &expr,
2798 const Matrix<Scalar>& par,
2799 Matrix<Scalar>& expr_ret,
2800 std::vector<Matrix<Scalar> >& symbols,
2801 std::vector< Matrix<Scalar> >& parametric,
2803 casadi_error(
"'extract_parametric' not defined for " + type_name());
2806 template<
typename Scalar>
2807 void Matrix<Scalar>::separate_linear(
const Matrix<Scalar> &expr,
2808 const Matrix<Scalar> &sym_lin,
const Matrix<Scalar> &sym_const,
2809 Matrix<Scalar>& expr_const, Matrix<Scalar>& expr_lin, Matrix<Scalar>& expr_nonlin) {
2810 casadi_error(
"'separate_linear' not defined for " + type_name());
2813 template<
typename Scalar>
2814 bool Matrix<Scalar>::depends_on(
const Matrix<Scalar> &x,
const Matrix<Scalar> &arg) {
2815 casadi_error(
"'depends_on' not defined for " + type_name());
2819 template<
typename Scalar>
2820 bool Matrix<Scalar>::contains_all(
const std::vector <Matrix<Scalar> >& v,
2821 const std::vector <Matrix<Scalar> > &n) {
2822 casadi_error(
"'contains_all' not defined for " + type_name());
2826 template<
typename Scalar>
2827 bool Matrix<Scalar>::contains_any(
const std::vector<Matrix<Scalar> >& v,
2828 const std::vector <Matrix<Scalar> > &n) {
2829 casadi_error(
"'contains_any' not defined for " + type_name());
2833 template<
typename Scalar>
2834 std::vector< Matrix<Scalar> > Matrix<Scalar>::cse(
const std::vector< Matrix<Scalar> >& e) {
2835 casadi_error(
"'cse' not defined for " + type_name());
2840 template<
typename Scalar>
2841 Matrix<Scalar> Matrix<Scalar>::
2842 jacobian(
const Matrix<Scalar> &f,
const Matrix<Scalar> &x,
const Dict& opts) {
2843 casadi_error(
"'jacobian' not defined for " + type_name());
2844 return Matrix<Scalar>();
2847 template<
typename Scalar>
2848 Matrix<Scalar> Matrix<Scalar>::hessian(
const Matrix<Scalar> &f,
2849 const Matrix<Scalar> &x,
2851 casadi_error(
"'hessian' not defined for " + type_name());
2852 return Matrix<Scalar>();
2855 template<
typename Scalar>
2856 Matrix<Scalar> Matrix<Scalar>::hessian(
const Matrix<Scalar> &f,
2857 const Matrix<Scalar> &x,
2860 casadi_error(
"'hessian' not defined for " + type_name());
2861 return Matrix<Scalar>();
2864 template<
typename Scalar>
2865 std::vector<std::vector<Matrix<Scalar> > >
2867 forward(
const std::vector<Matrix<Scalar> > &ex,
2868 const std::vector<Matrix<Scalar> > &arg,
2869 const std::vector<std::vector<Matrix<Scalar> > > &v,
2871 casadi_error(
"'forward' not defined for " + type_name());
2874 template<
typename Scalar>
2875 std::vector<std::vector<Matrix<Scalar> > >
2877 reverse(
const std::vector<Matrix<Scalar> > &ex,
2878 const std::vector<Matrix<Scalar> > &arg,
2879 const std::vector<std::vector<Matrix<Scalar> > > &v,
2881 casadi_error(
"'reverse' not defined for " + type_name());
2884 template<
typename Scalar>
2886 Matrix<Scalar>::which_depends(
const Matrix<Scalar> &expr,
const Matrix<Scalar> &var,
2887 casadi_int order,
bool tr) {
2888 casadi_error(
"'which_depends' not defined for " + type_name());
2889 return std::vector<bool>();
2892 template<
typename Scalar>
2894 Matrix<Scalar>::jacobian_sparsity(
const Matrix<Scalar> &f,
const Matrix<Scalar> &x) {
2895 casadi_error(
"'jacobian_sparsity' not defined for " + type_name());
2899 template<
typename Scalar>
2900 Matrix<Scalar> Matrix<Scalar>::taylor(
const Matrix<Scalar>& f,
2901 const Matrix<Scalar>& x,
2902 const Matrix<Scalar>& a, casadi_int order) {
2903 casadi_error(
"'taylor' not defined for " + type_name());
2904 return Matrix<Scalar>();
2907 template<
typename Scalar>
2908 Matrix<Scalar> Matrix<Scalar>::mtaylor(
const Matrix<Scalar>& f,
2909 const Matrix<Scalar>& x,
2910 const Matrix<Scalar>& a, casadi_int order) {
2911 casadi_error(
"'mtaylor' not defined for " + type_name());
2912 return Matrix<Scalar>();
2915 template<
typename Scalar>
2916 Matrix<Scalar> Matrix<Scalar>::mtaylor(
const Matrix<Scalar>& f,
2917 const Matrix<Scalar>& x,
2918 const Matrix<Scalar>& a, casadi_int order,
2919 const std::vector<casadi_int>&order_contributions) {
2920 casadi_error(
"'mtaylor' not defined for " + type_name());
2921 return Matrix<Scalar>();
2924 template<
typename Scalar>
2925 casadi_int Matrix<Scalar>::n_nodes(
const Matrix<Scalar>& x) {
2926 casadi_error(
"'n_nodes' not defined for " + type_name());
2930 template<
typename Scalar>
2932 Matrix<Scalar>::print_operator(
const Matrix<Scalar>& x,
2933 const std::vector<std::string>& args) {
2934 casadi_error(
"'print_operator' not defined for " + type_name());
2935 return std::string();
2938 template<
typename Scalar>
2940 casadi_error(
"'symvar' not defined for " + type_name());
2941 return std::vector<Matrix<Scalar> >();
2944 template<
typename Scalar>
2947 casadi_error(
"'extract' not defined for " + type_name());
2950 template<
typename Scalar>
2951 void Matrix<Scalar>::shared(std::vector<Matrix<Scalar> >& ex,
2952 std::vector<Matrix<Scalar> >& v,
2953 std::vector<Matrix<Scalar> >& vdef,
2954 const std::string& v_prefix,
2955 const std::string& v_suffix) {
2956 casadi_error(
"'shared' not defined for " + type_name());
2959 template<
typename Scalar>
2960 Matrix<Scalar> Matrix<Scalar>::poly_coeff(
const Matrix<Scalar>& f,
2961 const Matrix<Scalar>&x) {
2962 casadi_error(
"'poly_coeff' not defined for " + type_name());
2965 template<
typename Scalar>
2966 Matrix<Scalar> Matrix<Scalar>::poly_roots(
const Matrix<Scalar>& p) {
2967 casadi_error(
"'poly_roots' not defined for " + type_name());
2970 template<
typename Scalar>
2971 Matrix<Scalar> Matrix<Scalar>::eig_symbolic(
const Matrix<Scalar>& m) {
2972 casadi_error(
"'eig_symbolic' not defined for " + type_name());
2975 template<
typename Scalar>
2976 DM Matrix<Scalar>::evalf(
const Matrix<Scalar>& m) {
2977 Function f(
"f", std::vector<SX>{}, std::vector<SX>{m});
2978 return f(std::vector<DM>{})[0];
2981 template<
typename Scalar>
2982 Matrix<Scalar> Matrix<Scalar>::sparsify(
const Matrix<Scalar>& x,
double tol) {
2984 bool remove_nothing =
true;
2985 for (
auto it=x.nonzeros().begin(); it!=x.nonzeros().end() && remove_nothing; ++it) {
2988 if (remove_nothing)
return x;
2991 casadi_int size1 = x.size1();
2992 casadi_int size2 = x.size2();
2993 const casadi_int* colind = x.colind();
2994 const casadi_int* row = x.row();
2997 std::vector<casadi_int> new_colind(1, 0), new_row;
2998 std::vector<Scalar> new_data;
3001 for (casadi_int cc=0; cc<size2; ++cc) {
3003 for (casadi_int el=colind[cc]; el<colind[cc+1]; ++el) {
3007 new_data.push_back(x->at(el));
3010 new_row.push_back(row[el]);
3014 new_colind.push_back(new_row.size());
3018 Sparsity sp(size1, size2, new_colind, new_row);
3021 return Matrix<Scalar>(sp, new_data);
3025 template<
typename Scalar>
3027 casadi_error(
"'get_input' not defined for " + type_name());
3030 template<
typename Scalar>
3031 std::vector<Matrix<Scalar> > Matrix<Scalar>::get_free(
const Function& f) {
3032 casadi_error(
"'get_free' not defined for " + type_name());
3035 template<
typename Scalar>
3036 Matrix<Scalar>::operator double()
const {
3037 casadi_assert_dev(is_scalar());
3038 return static_cast<double>(scalar());
3041 template<
typename Scalar>
3042 Matrix<Scalar>::operator casadi_int()
const {
3043 casadi_assert_dev(is_scalar());
3044 return static_cast<casadi_int
>(scalar());
3047 template<
typename Scalar>
3049 casadi_error(
"'sym' not defined for " + type_name());
3052 template<
typename Scalar>
3053 Matrix<Scalar> Matrix<Scalar>::rand(
const Sparsity& sp) {
3055 casadi_error(
"'rand' not defined for " + type_name());
3058 template<
typename Scalar>
3059 std::string Matrix<Scalar>::serialize()
const {
3060 std::stringstream ss;
3065 template<
typename Scalar>
3066 void Matrix<Scalar>::serialize(SerializingStream& s)
const {
3067 s.pack(
"Matrix::sparsity", sparsity());
3068 s.pack(
"Matrix::nonzeros", nonzeros());
3071 template<
typename Scalar>
3072 Matrix<Scalar> Matrix<Scalar>::deserialize(DeserializingStream& s) {
3074 s.unpack(
"Matrix::sparsity", sp);
3075 std::vector<Scalar> nz;
3076 s.unpack(
"Matrix::nonzeros", nz);
3080 template<
typename Scalar>
3086 template<
typename Scalar>
3087 Matrix<Scalar> Matrix<Scalar>::deserialize(std::istream &stream) {
3088 DeserializingStream s(stream);
3089 return Matrix<Scalar>::deserialize(s);
3092 template<
typename Scalar>
3093 Matrix<Scalar> Matrix<Scalar>::deserialize(
const std::string& s) {
3094 std::stringstream ss;
3096 return deserialize(ss);
3099 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
3100 template<
typename Scalar>
3101 std::mutex& Matrix<Scalar>::get_mutex_temp() {
3102 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 is dense, i.e. nnz() equals numel()
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 nonzeros.
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 as a pair (number of rows, number of columns)
bool is_scalar(bool scalar_and_dense=false) const
Check if the matrix is scalar, i.e. 1-by-1.
Sparse matrix class. SX and DM are specializations.
bool has_nz(casadi_int rr, casadi_int cc) const
Check whether element (rr, cc) is a structural nonzero.
void print_split(std::vector< std::string > &nz, std::vector< std::string > &inter) const
String representation of each nonzero and of the shared subexpressions.
Matrix< Scalar > T() const
Transpose the matrix.
static void set_precision(casadi_int precision)
Set the precision, field width and scientific flag used when printing nonzeros.
static casadi_int get_precision()
Get the precision, field width and scientific flag used when printing nonzeros.
void get(Matrix< Scalar > &m, bool ind1, const Slice &rr) const
Get elements by a single (linear) index.
void resize(casadi_int nrow, casadi_int ncol)
Change the shape in place, keeping nonzeros that remain inside the new bounds.
void print_sparse(std::ostream &stream, bool truncate=true) const
Print as a list of (row, col) -> value triplets, column-major order.
static void set_width(casadi_int width)
void clear()
Reset to an empty 0-by-0 matrix, in place.
Matrix()
Empty 0-by-0 matrix.
void set(const Matrix< Scalar > &m, bool ind1, const Slice &rr)
Assign elements by a single (linear) index.
static casadi_int get_width()
static bool get_scientific()
static std::string type_name()
Name of the class: "DM" or "SX".
void to_file(const std::string &filename, const std::string &format="") const
Write a numerical matrix to a text file (DM only)
static void set_scientific(bool scientific)
void disp(std::ostream &stream, bool more=false) const
Print a representation of the object to a stream.
bool __nonzero__() const
Truth value of a 1-by-1 matrix (Python: bool(x))
void erase(const std::vector< casadi_int > &rr, const std::vector< casadi_int > &cc, bool ind1=false)
Erase the block at the given rows and columns, leaving structural zeros.
static void rng(casadi_int seed)
Seed the random number generator used by rand.
void print_dense(std::ostream &stream, bool truncate=true) const
Print as a dense matrix, one row per line, structural zeros as 00.
void reserve(casadi_int nnz)
Reserve storage for the given number of nonzeros (performance hint, no visible effect)
void set_nz(const Matrix< Scalar > &m, bool ind1, const Slice &k)
Assign structural nonzeros by their position in the nonzero storage.
void print_vector(std::ostream &stream, bool truncate=true) const
Print a column vector as [a, b, ...], structural zeros as 00.
std::string get_str(bool more=false) const
Get the string representation that disp prints.
void get_nz(Matrix< Scalar > &m, bool ind1, const Slice &k) const
Get structural nonzeros by their position in the nonzero storage.
void print_scalar(std::ostream &stream) const
Print a 1-by-1 matrix as a bare number or expression.
Helper class for Serialization.
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
Flat (column-major) element index of every nonzero.
Sparsity sub(const std::vector< casadi_int > &rr, const std::vector< casadi_int > &cc, std::vector< casadi_int > &mapping, bool ind1=false) const
Pattern of the submatrix with rows rr and columns cc.
casadi_int numel() const
Total number of entries, structural zeros included, i.e. size1()*size2()
casadi_int size1() const
Number of rows.
static Sparsity dense(casadi_int nrow, casadi_int ncol=1)
Create a dense rectangular sparsity pattern.
Sparsity T() const
Transposed pattern.
bool is_column() const
Check whether 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 from the (row, col) index of every nonzero.
casadi_int nnz() const
Number of structural nonzeros.
casadi_int size2() const
Number of columns.
casadi_int row(casadi_int el) const
Row index of nonzero el.
bool is_empty(bool both=false) const
Check whether the pattern has a zero dimension.
std::pair< casadi_int, casadi_int > size() const
Shape as a pair (number of rows, number of columns)
const long double alpha[8][8]
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)
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
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.