25 #ifndef CASADI_MATRIX_IMPL_HPP
26 #define CASADI_MATRIX_IMPL_HPP
32 #include "sx_node.hpp"
35 #include "serializing_stream.hpp"
38 template<
typename Scalar>
41 template<
typename Scalar>
44 template<
typename Scalar>
47 template<
typename Scalar>
49 template<
typename Scalar>
51 template<
typename Scalar>
54 template<
typename Scalar>
57 std::chrono::system_clock::now().time_since_epoch().count());
59 template<
typename Scalar>
64 template<
typename Scalar>
66 return sparsity().has_nz(rr, cc);
69 template<
typename Scalar>
72 casadi_error(
"Only scalar Matrix could have a truth value, but you "
73 "provided a shape" + dim());
75 return nonzeros().at(0)!=0;
78 template<
typename Scalar>
83 casadi_int k = sparsity().get_nz(rr.
scalar(size1()), cc.
scalar(size2()));
93 get(m, ind1, rr.
all(size1(), ind1), cc.
all(size2(), ind1));
96 template<
typename Scalar>
100 get(m, ind1, rr.
all(size1(), ind1), cc);
103 template<
typename Scalar>
107 get(m, ind1, rr, cc.
all(size2(), ind1));
110 template<
typename Scalar>
120 "Marix::get: First index must be a dense vector");
122 "Marix::get: Second index must be a dense vector");
125 std::vector<casadi_int> mapping;
126 Sparsity sp = sparsity().
sub(rr.nonzeros(), cc.nonzeros(), mapping, ind1);
130 for (casadi_int k=0; k<mapping.size(); ++k) m->at(k) = nonzeros().at(mapping[k]);
133 template<
typename Scalar>
137 casadi_int r = rr.
scalar(numel());
138 casadi_int k = sparsity().get_nz(r % size1(), r / size1());
140 m = nonzeros().at(k);
148 get(m, ind1, rr.
all(numel(), ind1));
151 template<
typename Scalar>
155 return get(m, ind1,
to_slice(rr, ind1));
160 return get_nz(m, ind1, rr);
164 std::vector<casadi_int> mapping;
168 bool tr = (is_column() && rr.
is_row()) || (is_row() && rr.
is_column());
172 for (casadi_int k=0; k<mapping.size(); ++k) m->at(k) = nonzeros().at(mapping[k]);
175 template<
typename Scalar>
177 casadi_assert(size()==sp.
size(),
178 "Shape mismatch. This matrix has shape "
179 + str(size()) +
", but supplied sparsity index has shape "
180 + str(sp.
size()) +
".");
181 m = project(*
this, sp);
184 template<
typename Scalar>
189 casadi_int oldsize = sparsity_.nnz();
190 casadi_int ind = sparsity_.add_nz(rr.
scalar(size1()), cc.
scalar(size2()));
191 if (oldsize == sparsity_.nnz()) {
192 nonzeros_.at(ind) = m.scalar();
194 nonzeros_.insert(nonzeros_.begin()+ind, m.scalar());
200 set(m, ind1, rr.
all(size1(), ind1), cc.
all(size2(), ind1));
203 template<
typename Scalar>
207 set(m, ind1, rr.
all(size1(), ind1), cc);
210 template<
typename Scalar>
214 set(m, ind1, rr, cc.
all(size2(), ind1));
217 template<
typename Scalar>
227 return set(m, ind1, rr.
T(), cc);
232 return set(m, ind1, rr, cc.
T());
237 "Matrix::set: First index not dense vector");
239 "Matrix::set: Second index not dense vector");
245 return set(repmat(m, rr.
size1(), cc.
size1()), ind1, rr, cc);
249 return set(m.
T(), ind1, rr, cc);
252 casadi_error(
"Dimension mismatch. lhs is " + str(rr.
size1()) +
"-by-"
258 casadi_int sz1 = size1(), sz2 = size2();
261 casadi_assert_in_range(rr.nonzeros(), -sz1+ind1, sz1+ind1);
262 casadi_assert_in_range(cc.nonzeros(), -sz2+ind1, sz2+ind1);
266 erase(rr.nonzeros(), cc.nonzeros(), ind1);
271 for (casadi_int j=0; j<el.
size2(); ++j) {
272 casadi_int this_j = cc->at(j) - ind1;
273 if (this_j<0) this_j += sz2;
276 casadi_int this_i = rr->at(i) - ind1;
277 if (this_i<0) this_i += sz1;
278 el->at(k) = this_i + this_j*sz1;
281 return set(m,
false, el);
284 template<
typename Scalar>
288 casadi_int r = rr.
scalar(numel());
289 casadi_int oldsize = sparsity_.nnz();
290 casadi_int ind = sparsity_.add_nz(r % size1(), r / size1());
291 if (oldsize == sparsity_.nnz()) {
292 nonzeros_.at(ind) = m.scalar();
294 nonzeros_.insert(nonzeros_.begin()+ind, m.scalar());
300 set(m, ind1, rr.
all(numel(), ind1));
303 template<
typename Scalar>
307 return set(m, ind1,
to_slice(rr, ind1));
314 erase(rr.nonzeros(), ind1);
331 return set(m.
T(), ind1, rr);
334 casadi_error(
"Dimension mismatch. lhs is " + str(rr.
size())
335 +
", while rhs is " + str(m.
size()));
340 casadi_int sz1 = size1(), sz2 = size2(), sz = nnz(), nel = numel(), rrsz = rr.
nnz();
346 casadi_assert_in_range(rr.nonzeros(), -nel+ind1, nel+ind1);
350 return set_nz(m, ind1, rr);
354 std::vector<casadi_int> new_row =
355 sparsity().get_row(), new_col=sparsity().get_col(), nz(rr.nonzeros());
356 new_row.reserve(sz+rrsz);
357 new_col.reserve(sz+rrsz);
359 for (std::vector<casadi_int>::iterator i=nz.begin(); i!=nz.end(); ++i) {
362 new_row.push_back(*i % sz1);
363 new_col.push_back(*i / sz1);
368 if (sp != sparsity()) *
this = project(*
this, sp);
371 sparsity().get_nz(nz);
374 for (casadi_int i=0; i<nz.size(); ++i) {
375 nonzeros().at(nz[i]) = m->at(i);
379 template<
typename Scalar>
381 casadi_assert(size()==sp.
size(),
382 "set(Sparsity sp): shape mismatch. This matrix has shape "
383 + str(size()) +
", but supplied sparsity index has shape "
384 + str(sp.
size()) +
".");
385 std::vector<casadi_int> ii = sp.
find();
387 (*this)(ii) = densify(m);
389 (*this)(ii) = densify(m(ii));
393 template<
typename Scalar>
397 m = nonzeros().at(kk.
scalar(nnz()));
402 get_nz(m, ind1, kk.
all(nnz(), ind1));
405 template<
typename Scalar>
409 return get_nz(m, ind1,
to_slice(kk, ind1));
413 const std::vector<casadi_int>& k = kk.nonzeros();
414 casadi_int sz = nnz();
417 casadi_assert_in_range(k, -sz+ind1, sz+ind1);
420 bool tr = (is_column() && kk.
is_row()) || (is_row() && kk.
is_column());
424 for (casadi_int el=0; el<k.
size(); ++el) {
425 casadi_assert(!(ind1 && k[el]<=0),
"Matlab is 1-based, but requested index "
426 + str(k[el]) +
". Note that negative slices are"
427 " disabled in the Matlab interface. "
428 "Possibly you may want to use 'end'.");
429 casadi_int k_el = k[el]-ind1;
430 m->at(el) = nonzeros().at(k_el>=0 ? k_el : k_el+sz);
434 template<
typename Scalar>
438 nonzeros().at(kk.
scalar(nnz())) = m.scalar();
443 set_nz(m, ind1, kk.
all(nnz(), ind1));
446 template<
typename Scalar>
450 return set_nz(m, ind1,
to_slice(kk, ind1));
461 return set_nz(project(m, kk.
sparsity()), ind1, kk);
465 return set_nz(m.
T(), ind1, kk);
468 casadi_error(
"Dimension mismatch. lhs is " + str(kk.
size())
469 +
", while rhs is " + str(m.
size()));
474 const std::vector<casadi_int>& k = kk.nonzeros();
475 casadi_int sz = nnz();
478 casadi_assert_in_range(k, -sz+ind1, sz+ind1);
481 for (casadi_int el=0; el<k.
size(); ++el) {
482 casadi_assert(!(ind1 && k[el]<=0),
483 "Matlab is 1-based, but requested index " + str(k[el])
484 +
". Note that negative slices are disabled in the Matlab interface. "
485 "Possibly you may want to use 'end'.");
486 casadi_int k_el = k[el]-ind1;
487 nonzeros().at(k_el>=0 ? k_el : k_el+sz) = m->at(el);
491 template<
typename Scalar>
493 return densify(x, 0);
496 template<
typename Scalar>
498 const Matrix<Scalar>& val) {
500 casadi_assert_dev(val.is_scalar());
503 if (x.is_dense())
return x;
506 casadi_int nrow = x.size1();
507 casadi_int ncol = x.size2();
508 const casadi_int* colind = x.colind();
509 const casadi_int* row = x.row();
510 auto it = x.nonzeros().cbegin();
513 std::vector<Scalar> d(nrow*ncol, val.scalar());
516 for (casadi_int cc=0; cc<ncol; ++cc) {
517 for (casadi_int el=colind[cc]; el<colind[cc+1]; ++el) {
518 d[cc*nrow + row[el]] = *it++;
526 template<
typename Scalar>
528 if (axis==-1) axis = x.is_row();
529 Matrix<Scalar> ret = x;
531 for (casadi_int i=1;i<x.size1();++i)
532 ret(i, Slice()) += ret(i-1, Slice());
534 for (casadi_int i=1;i<x.size2();++i)
535 ret(Slice(), i) += ret(Slice(), i-1);
540 template<
typename Scalar>
542 const Matrix<Scalar>& A,
const Matrix<Scalar>& B,
const Matrix<Scalar>& C,
543 const std::vector<casadi_int>& dim_a,
const std::vector<casadi_int>& dim_b,
544 const std::vector<casadi_int>& dim_c,
545 const std::vector<casadi_int>& a,
const std::vector<casadi_int>& b,
546 const std::vector<casadi_int>& c) {
547 std::vector<casadi_int> iter_dims;
548 std::vector<casadi_int> strides_a;
549 std::vector<casadi_int> strides_b;
550 std::vector<casadi_int> strides_c;
552 iter_dims, strides_a, strides_b, strides_c);
554 const std::vector<Scalar>& Av = A.nonzeros();
555 const std::vector<Scalar>& Bv = B.nonzeros();
557 Matrix<Scalar> ret =
C;
558 std::vector<Scalar>& Cv = ret.nonzeros();
560 einstein_eval(n_iter, iter_dims, strides_a, strides_b, strides_c,
561 get_ptr(Av), get_ptr(Bv), get_ptr(Cv));
565 template<
typename Scalar>
567 const std::vector<casadi_int>& dim_a,
const std::vector<casadi_int>& dim_b,
568 const std::vector<casadi_int>& dim_c,
569 const std::vector<casadi_int>& a,
const std::vector<casadi_int>& b,
570 const std::vector<casadi_int>& c) {
572 dim_a, dim_b, dim_c, a, b, c);
575 template<
typename Scalar>
579 template<
typename Scalar>
583 template<
typename Scalar>
585 sparsity_(
Sparsity::dense(x.size(), 1)), nonzeros_(x) {
588 template<
typename Scalar>
590 sparsity_ = m.sparsity_;
591 nonzeros_ = m.nonzeros_;
595 template<
typename Scalar>
596 std::vector<Scalar>* Matrix<Scalar>::operator->() {
600 template<
typename Scalar>
601 const std::vector<Scalar>* Matrix<Scalar>::operator->()
const {
605 template<
typename Scalar>
608 template<
typename Scalar>
610 casadi_assert(numel()==1,
"Not a scalar");
612 std::streamsize precision = stream.precision();
613 std::streamsize width = stream.width();
614 std::ios_base::fmtflags flags = stream.flags();
616 stream.precision(stream_precision_);
617 stream.width(stream_width_);
618 if (stream_scientific_) {
619 stream.setf(std::ios::scientific);
621 stream.unsetf(std::ios::scientific);
629 stream << std::flush;
630 stream.precision(precision);
635 template<
typename Scalar>
637 print_vector(stream, sparsity(), ptr(), truncate);
640 template<
typename Scalar>
642 const Scalar* nonzeros,
bool truncate) {
643 casadi_assert(sp.
is_column(),
"Not a vector");
646 std::vector<std::string> nz, inter;
647 print_split(sp.
nnz(), nonzeros, nz, inter);
650 for (casadi_int i=0; i<inter.size(); ++i)
651 stream <<
"@" << (i+1) <<
"=" << inter[i] <<
", ";
655 const casadi_int* row = sp.
row();
656 casadi_int nnz = sp.
nnz();
657 casadi_int size1 = sp.
size1();
660 const casadi_int max_numel = 1000;
661 if (truncate && size1<=max_numel) truncate=
false;
668 for (casadi_int rr=0; rr<size1; ++rr) {
670 std::string s = el<nnz && rr==row[el] ? nz.at(el++) :
"00";
673 if (truncate && rr>=3 && rr<size1-3) {
675 if (rr==3) stream <<
", ...";
678 if (rr!=0) stream <<
", ";
682 stream <<
"]" << std::flush;
685 template<
typename Scalar>
687 print_dense(stream, sparsity(), ptr(), truncate);
690 template<
typename Scalar>
692 print_sparse(stream, sparsity(), ptr(), truncate);
695 template<
typename Scalar>
697 std::vector<std::string>& inter)
const {
699 print_split(nnz(), ptr(), nz, inter);
702 template<
typename Scalar>
704 const Scalar* nonzeros,
bool truncate) {
707 }
else if (sp.
numel()==1) {
711 print_scalar(stream, *nonzeros);
714 print_vector(stream, sp, nonzeros, truncate);
715 }
else if (std::max(sp.
size1(), sp.
size2())<=10 ||
716 static_cast<double>(sp.
nnz())/
static_cast<double>(sp.
numel())>=0.5) {
718 print_dense(stream, sp, nonzeros, truncate);
720 print_sparse(stream, sp, nonzeros, truncate);
724 template<
typename Scalar>
726 std::streamsize precision = stream.precision();
727 std::streamsize width = stream.width();
728 std::ios_base::fmtflags flags = stream.flags();
730 stream.precision(stream_precision_);
731 stream.width(stream_width_);
732 if (stream_scientific_) {
733 stream.setf(std::ios::scientific);
735 stream.unsetf(std::ios::scientific);
738 stream << std::flush;
740 stream.precision(precision);
745 template<
typename Scalar>
747 std::vector<std::string>& nz,
748 std::vector<std::string>& inter) {
753 std::stringstream ss;
754 ss.precision(stream_precision_);
755 ss.width(stream_width_);
756 if (stream_scientific_) {
757 ss.setf(std::ios::scientific);
759 ss.unsetf(std::ios::scientific);
763 for (casadi_int i=0; i<nz.size(); ++i) {
764 ss.str(std::string());
770 template<
typename Scalar>
772 const Scalar* nonzeros,
bool truncate) {
774 casadi_int size1 = sp.size1();
775 casadi_int size2 = sp.size2();
776 const casadi_int* colind = sp.colind();
777 const casadi_int* row = sp.row();
778 casadi_int nnz = sp.nnz();
782 stream <<
"all zero sparse: " << size1 <<
"-by-" << size2 << std::flush;
787 stream <<
"sparse: " << size1 <<
"-by-" << size2 <<
", " << nnz <<
" nnz";
790 std::vector<std::string> nz, inter;
791 print_split(nnz, nonzeros, nz, inter);
794 for (casadi_int i=0; i<inter.size(); ++i)
795 stream << std::endl <<
" @" << (i+1) <<
"=" << inter[i] <<
",";
799 const casadi_int max_nnz = 1000;
800 if (truncate && nnz<=max_nnz) truncate=
false;
803 for (casadi_int cc=0; cc<size2; ++cc) {
804 for (casadi_int el=colind[cc]; el<colind[cc+1]; ++el) {
805 if (truncate && el>=3 && el<nnz-3) {
806 if (el==3) stream << std::endl <<
" ...";
808 stream << std::endl <<
" (" << row[el] <<
", " << cc <<
") -> " << nz.at(el);
809 InterruptHandler::check();
813 stream << std::flush;
816 template<
typename Scalar>
818 const Scalar* nonzeros,
bool truncate) {
820 std::vector<std::string> nz, inter;
821 print_split(sp.nnz(), nonzeros, nz, inter);
824 for (casadi_int i=0; i<inter.size(); ++i)
825 stream <<
"@" << (i+1) <<
"=" << inter[i] <<
", ";
829 casadi_int size1 = sp.size1();
830 casadi_int size2 = sp.size2();
831 const casadi_int* colind = sp.colind();
832 const casadi_int* row = sp.row();
835 const casadi_int max_numel = 1000;
836 if (truncate && size1*size2<=max_numel) truncate=
false;
839 bool truncate_rows = truncate && size1>=7;
840 bool truncate_columns = truncate && size2>=7;
843 std::vector<casadi_int> ind(colind, colind+size2+1);
846 bool oneliner=size1<=1;
849 for (casadi_int rr=0; rr<size1; ++rr) {
851 bool print_row = !(truncate_rows && rr>=3 && rr<size1-3);
855 if (!oneliner) stream << std::endl;
857 }
else if (print_row) {
862 for (casadi_int cc=0; cc<size2; ++cc) {
864 std::string s = ind[cc]<colind[cc+1] && row[ind[cc]]==rr
865 ? nz.at(ind[cc]++) :
"00";
868 if (!print_row)
continue;
871 bool print_column = !(truncate_columns && cc>=3 && cc<size2-3);
875 if (cc!=0) stream <<
", ";
886 if (!oneliner) stream << std::endl;
888 stream <<
" ...," << std::endl;
894 stream << std::flush;
897 template<
typename Scalar>
899 to_file(filename, sparsity(), ptr(), format);
902 template<
typename Scalar>
904 print_default(stream, sparsity(), ptr());
907 template<
typename Scalar>
909 std::stringstream ss;
914 template<
typename Scalar>
916 reserve(nnz, size2());
919 template<
typename Scalar>
921 nonzeros().reserve(nnz);
924 template<
typename Scalar>
926 sparsity_.resize(nrow, ncol);
929 template<
typename Scalar>
935 template<
typename Scalar>
938 Sparsity::dense(1, 1)),
939 nonzeros_(std::vector<Scalar>(1, static_cast<Scalar>(val))) {
942 template<
typename Scalar>
943 Matrix<Scalar>::Matrix(
const std::vector< std::vector<double> >& d) {
945 casadi_int nrow=d.size();
946 casadi_int ncol=d.empty() ? 1 : d.front().size();
949 for (casadi_int rr=0; rr<nrow; ++rr) {
950 casadi_assert(ncol==d[rr].size(),
952 "Attempting to construct a matrix from a nested list.\n"
953 "I got convinced that the desired size is (" + str(nrow) +
" x " + str(ncol)
954 +
" ), but now I encounter a vector of size (" + str(d[rr].size()) +
" )");
958 sparsity_ = Sparsity::dense(nrow, ncol);
959 nonzeros().resize(nrow*ncol);
960 typename std::vector<Scalar>::iterator it=nonzeros_.begin();
961 for (casadi_int cc=0; cc<ncol; ++cc) {
962 for (casadi_int rr=0; rr<nrow; ++rr) {
963 *it++ =
static_cast<Scalar
>(d[rr][cc]);
968 template<
typename Scalar>
969 Matrix<Scalar>::Matrix(
const Sparsity& sp) : sparsity_(sp), nonzeros_(sp.nnz(), 1) {
972 template<
typename Scalar>
973 Matrix<Scalar>::Matrix(casadi_int nrow, casadi_int ncol) : sparsity_(nrow, ncol) {
976 template<
typename Scalar>
977 Matrix<Scalar>::Matrix(
const std::pair<casadi_int, casadi_int>& rc) : sparsity_(rc) {
980 template<
typename Scalar>
981 Matrix<Scalar>::Matrix(
const Sparsity& sp,
const Scalar& val,
bool dummy) :
982 sparsity_(sp), nonzeros_(sp.nnz(), val) {
985 template<
typename Scalar>
986 Matrix<Scalar>::Matrix(
const Sparsity& sp,
const std::vector<Scalar>& d,
bool dummy) :
987 sparsity_(sp), nonzeros_(d) {
988 casadi_assert(sp.nnz()==d.size(),
"Size mismatch.\n"
989 "You supplied a sparsity of " + sp.dim()
990 +
", but the supplied vector is of length " + str(d.size()));
993 template<
typename Scalar>
994 Matrix<Scalar>::Matrix(
const Sparsity& sp,
const Matrix<Scalar>& d) {
996 *
this = Matrix<Scalar>(sp, d.scalar(),
false);
997 }
else if (sp.nnz()==0) {
998 casadi_assert(d.nnz()==0,
999 "You passed nonzeros (" + d.dim(
true) +
1000 ") to the constructor of a fully sparse matrix (" + sp.dim(
true) +
").");
1001 *
this = Matrix<Scalar>(sp);
1002 }
else if (d.is_column() || d.size1()==1) {
1003 casadi_assert_dev(sp.nnz()==d.numel());
1005 *
this = Matrix<Scalar>(sp, d.nonzeros(),
false);
1007 *
this = Matrix<Scalar>(sp, densify(d).nonzeros(),
false);
1010 casadi_error(
"Matrix(Sparsity, Matrix): Only allowed for scalars and vectors");
1014 template<
typename Scalar>
1015 Matrix<Scalar> Matrix<Scalar>::unary(casadi_int op,
const Matrix<Scalar> &x) {
1017 Matrix<Scalar> ret = Matrix<Scalar>::zeros(x.sparsity());
1020 std::vector<Scalar>& ret_data = ret.nonzeros();
1021 const std::vector<Scalar>& x_data = x.nonzeros();
1024 for (casadi_int el=0; el<x.nnz(); ++el) {
1025 casadi_math<Scalar>::fun(op, x_data[el], x_data[el], ret_data[el]);
1029 if (!x.is_dense() && !operation_checker<F0XChecker>(op)) {
1032 casadi_math<Scalar>::fun(op, 0, 0, fcn_0);
1033 if (!casadi_limits<Scalar>::is_zero(fcn_0)) {
1034 ret = densify(ret, fcn_0);
1041 template<
typename Scalar>
1042 Matrix<Scalar> Matrix<Scalar>::operator-()
const {
1043 return unary(OP_NEG, *
this);
1046 template<
typename Scalar>
1047 Matrix<Scalar> Matrix<Scalar>::operator+()
const {
1051 template<
typename Scalar>
1052 Matrix<Scalar> Matrix<Scalar>::mrdivide(
const Matrix<Scalar>& b,
1053 const Matrix<Scalar>& a) {
1054 if (a.is_scalar() || b.is_scalar())
return b/a;
1055 return solve(a.T(), b.T()).T();
1058 template<
typename Scalar>
1059 Matrix<Scalar> Matrix<Scalar>::mldivide(
const Matrix<Scalar>& a,
1060 const Matrix<Scalar>& b) {
1061 if (a.is_scalar() || b.is_scalar())
return b/a;
1065 template<
typename Scalar>
1066 Matrix<Scalar> Matrix<Scalar>::printme(
const Matrix<Scalar>& y)
const {
1067 return binary(OP_PRINTME, *
this, y);
1070 template<
typename Scalar>
1071 void Matrix<Scalar>::erase(
const std::vector<casadi_int>& rr,
1072 const std::vector<casadi_int>& cc,
bool ind1) {
1074 std::vector<casadi_int> mapping = sparsity_.erase(rr, cc, ind1);
1077 for (casadi_int k=0; k<mapping.size(); ++k)
1078 nonzeros()[k] = nonzeros()[mapping[k]];
1081 nonzeros().resize(mapping.size());
1084 template<
typename Scalar>
1085 void Matrix<Scalar>::erase(
const std::vector<casadi_int>& rr,
bool ind1) {
1087 std::vector<casadi_int> mapping = sparsity_.erase(rr, ind1);
1090 for (casadi_int k=0; k<mapping.size(); ++k)
1091 nonzeros()[k] = nonzeros()[mapping[k]];
1094 nonzeros().resize(mapping.size());
1097 template<
typename Scalar>
1098 void Matrix<Scalar>::remove(
const std::vector<casadi_int>& rr,
1099 const std::vector<casadi_int>& cc) {
1100 casadi_assert_bounded(rr, size1());
1101 casadi_assert_bounded(cc, size2());
1104 std::vector<casadi_int> rrc =
complement(rr, size1());
1105 std::vector<casadi_int> ccc =
complement(cc, size2());
1107 Matrix<Scalar> ret = (*this)(rrc, ccc);
1113 template<
typename Scalar>
1114 void Matrix<Scalar>::enlarge(casadi_int nrow, casadi_int ncol,
const std::vector<casadi_int>& rr,
1115 const std::vector<casadi_int>& cc,
bool ind1) {
1116 sparsity_.enlarge(nrow, ncol, rr, cc, ind1);
1119 template<
typename Scalar>
1120 const Sparsity& Matrix<Scalar>::sparsity()
const {
1124 template<
typename Scalar>
1125 std::vector<Scalar>& Matrix<Scalar>::nonzeros() {
1129 template<
typename Scalar>
1130 const std::vector<Scalar>& Matrix<Scalar>::nonzeros()
const {
1134 template<
typename Scalar>
1135 Scalar* Matrix<Scalar>::ptr() {
1136 return nonzeros_.empty() ? nullptr : &nonzeros_.front();
1139 template<
typename Scalar>
1140 const Scalar* Matrix<Scalar>::ptr()
const {
1141 return nonzeros_.empty() ? nullptr : &nonzeros_.front();
1144 template<
typename Scalar>
1145 Sparsity Matrix<Scalar>::get_sparsity()
const {
1149 template<
typename Scalar>
1150 Matrix<Scalar> Matrix<Scalar>::mtimes(
const Matrix<Scalar> &x,
const Matrix<Scalar> &y) {
1151 if (x.is_scalar() || y.is_scalar()) {
1155 Matrix<Scalar> z = Matrix<Scalar>::zeros(Sparsity::mtimes(x.sparsity(), y.sparsity()));
1156 return mac(x, y, z);
1160 template<
typename Scalar>
1161 Matrix<Scalar> Matrix<Scalar>::mac(
const Matrix<Scalar> &x,
1162 const Matrix<Scalar> &y,
1163 const Matrix<Scalar> &z) {
1164 if (x.is_scalar() || y.is_scalar()) {
1170 casadi_assert(x.size2()==y.size1(),
1171 "Matrix product with incompatible dimensions. Lhs is "
1172 + x.dim() +
" and rhs is " + y.dim() +
".");
1174 casadi_assert(y.size2()==z.size2(),
1175 "Matrix addition with incompatible dimensions. Lhs is "
1176 + mtimes(x, y).dim() +
" and rhs is " + z.dim() +
".");
1178 casadi_assert(x.size1()==z.size1(),
1179 "Matrix addition with incompatible dimensions. Lhs is "
1180 + mtimes(x, y).dim() +
" and rhs is " + z.dim() +
".");
1185 }
else if (y.is_eye()) {
1187 }
else if (x.is_zero() || y.is_zero()) {
1191 Matrix<Scalar> ret = z;
1192 std::vector<Scalar> work(x.size1());
1193 casadi_mtimes(x.ptr(), x.sparsity(), y.ptr(), y.sparsity(),
1194 ret.ptr(), ret.sparsity(), get_ptr(work),
false);
1199 template<
typename Scalar>
1200 Matrix<Scalar> Matrix<Scalar>::
1201 _bilin(
const Matrix<Scalar>& A,
const Matrix<Scalar>& x,
1202 const Matrix<Scalar>& y) {
1203 return casadi_bilin(A.ptr(), A.sparsity(), x.ptr(), y.ptr());
1206 template<
typename Scalar>
1207 Matrix<Scalar> Matrix<Scalar>::
1208 _rank1(
const Matrix<Scalar>& A,
const Matrix<Scalar>& alpha,
1209 const Matrix<Scalar>& x,
const Matrix<Scalar>& y) {
1210 Matrix<Scalar> ret = A;
1211 casadi_rank1(ret.ptr(), ret.sparsity(), *alpha.ptr(), x.ptr(), y.ptr());
1216 template<
typename Scalar>
1217 Matrix<Scalar> Matrix<Scalar>::
1218 _logsumexp(
const Matrix<Scalar>& x) {
1219 Matrix<Scalar> mx = mmax(x);
1220 return mx+log(sum1(exp(x-mx)));
1223 template<
typename Scalar>
1224 Matrix<Scalar> Matrix<Scalar>::T()
const {
1226 if ((size1()==0 && size2()==0) || is_scalar())
return *
this;
1229 std::vector<casadi_int> mapping;
1230 Sparsity s = sparsity().transpose(mapping);
1233 Matrix<Scalar> ret = zeros(s);
1236 for (casadi_int i=0; i<mapping.size(); ++i)
1237 ret->at(i) = nonzeros().at(mapping[i]);
1242 template<
typename Scalar>
1243 const Scalar Matrix<Scalar>::scalar()
const {
1245 casadi_assert(is_scalar(),
"Can only convert 1-by-1 matrices to scalars");
1249 return nonzeros()[0];
1251 return casadi_limits<Scalar>::zero;
1254 template<
typename Scalar>
1255 Matrix<Scalar> Matrix<Scalar>::binary(casadi_int op,
1256 const Matrix<Scalar> &x,
1257 const Matrix<Scalar> &y) {
1258 if (x.is_scalar()) {
1259 return scalar_matrix(op, x, y);
1260 }
else if (y.is_scalar()) {
1261 return matrix_scalar(op, x, y);
1263 return matrix_matrix(op, x, y);
1267 template<
typename Scalar>
1271 std::vector<Scalar> dep;
1272 for (
auto & e : x) {
1273 dep.insert(dep.end(), e.nonzeros().begin(), e.nonzeros().end());
1279 std::vector< Matrix<Scalar> > ret;
1280 ret.reserve(r.size());
1281 for (
auto & e : r) {
1289 template<
typename Scalar>
1291 casadi_error(
"'call' not defined for " + type_name());
1294 template<
typename Scalar>
1295 Matrix<Scalar> Matrix<Scalar>::
1296 scalar_matrix(casadi_int op,
const Matrix<Scalar> &x,
const Matrix<Scalar> &y) {
1297 if ( (operation_checker<FX0Checker>(op) && y.nnz()==0) ||
1298 (operation_checker<F0XChecker>(op) && x.nnz()==0))
1299 return Matrix<Scalar>::zeros(Sparsity(y.size()));
1302 Matrix<Scalar> ret = Matrix<Scalar>::zeros(y.sparsity());
1305 std::vector<Scalar>& ret_data = ret.nonzeros();
1306 const std::vector<Scalar>& x_data = x.nonzeros();
1307 const Scalar& x_val = x_data.empty() ? casadi_limits<Scalar>::zero : x->front();
1308 const std::vector<Scalar>& y_data = y.nonzeros();
1311 for (casadi_int el=0; el<y.nnz(); ++el) {
1312 casadi_math<Scalar>::fun(op, x_val, y_data[el], ret_data[el]);
1316 if (!y.is_dense() && !operation_checker<FX0Checker>(op)) {
1319 casadi_math<Scalar>::fun(op, x_val, casadi_limits<Scalar>::zero, fcn_0);
1320 if (!casadi_limits<Scalar>::is_zero(fcn_0)) {
1321 ret = densify(ret, fcn_0);
1328 template<
typename Scalar>
1329 Matrix<Scalar> Matrix<Scalar>::
1330 matrix_scalar(casadi_int op,
const Matrix<Scalar> &x,
const Matrix<Scalar> &y) {
1332 if ( (operation_checker<FX0Checker>(op) && y.nnz()==0) ||
1333 (operation_checker<F0XChecker>(op) && x.nnz()==0))
1334 return Matrix<Scalar>::zeros(Sparsity(x.size()));
1337 Matrix<Scalar> ret = Matrix<Scalar>::zeros(x.sparsity());
1340 std::vector<Scalar>& ret_data = ret.nonzeros();
1341 const std::vector<Scalar>& x_data = x.nonzeros();
1342 const std::vector<Scalar>& y_data = y.nonzeros();
1343 const Scalar& y_val = y_data.empty() ? casadi_limits<Scalar>::zero : y->front();
1346 for (casadi_int el=0; el<x.nnz(); ++el) {
1347 casadi_math<Scalar>::fun(op, x_data[el], y_val, ret_data[el]);
1351 if (!x.is_dense() && !operation_checker<F0XChecker>(op)) {
1354 casadi_math<Scalar>::fun(op, casadi_limits<Scalar>::zero, y_val, fcn_0);
1355 if (!casadi_limits<Scalar>::is_zero(fcn_0)) {
1356 ret = densify(ret, fcn_0);
1363 template<
typename Scalar>
1364 Matrix<Scalar> Matrix<Scalar>::
1365 matrix_matrix(casadi_int op,
const Matrix<Scalar> &x,
const Matrix<Scalar> &y) {
1367 if (x.size() != y.size()) {
1369 if (!x.is_empty() && !y.is_empty()) {
1370 if (x.size1() == y.size1() && x.size2() % y.size2() == 0) {
1371 return matrix_matrix(op, x, repmat(y, 1, x.size2() / y.size2()));
1372 }
else if (y.size1() == x.size1() && y.size2() % x.size2() == 0) {
1373 return matrix_matrix(op, repmat(x, 1, y.size2() / x.size2()), y);
1377 if (x.size1()==0 && y.size1()==0 && x.size2()>0 && y.size2()>0) {
1378 if (x.size2() % y.size2() == 0) {
1379 return Matrix<Scalar>(0, x.size2());
1380 }
else if (y.size2() % x.size2() == 0) {
1381 return Matrix<Scalar>(0, y.size2());
1385 casadi_error(
"Dimension mismatch for " + casadi_math<Scalar>::print(op,
"x",
"y") +
1386 ", x is " + x.dim() +
", while y is " + y.dim());
1391 const Sparsity& x_sp = x.sparsity();
1392 const Sparsity& y_sp = y.sparsity();
1393 Sparsity r_sp = x_sp.combine(y_sp, operation_checker<F0XChecker>(op),
1394 operation_checker<FX0Checker>(op));
1397 Matrix<Scalar> r = zeros(r_sp);
1402 casadi_math<Scalar>::fun(op, x.ptr(), y.ptr(), r.ptr(), r_sp.nnz());
1403 }
else if (y_sp==r_sp) {
1405 Matrix<Scalar> x_mod = x(r_sp);
1406 casadi_math<Scalar>::fun(op, x_mod.ptr(), y.ptr(), r.ptr(), r_sp.nnz());
1407 }
else if (x_sp==r_sp) {
1409 Matrix<Scalar> y_mod = y(r_sp);
1410 casadi_math<Scalar>::fun(op, x.ptr(), y_mod.ptr(), r.ptr(), r_sp.nnz());
1413 Matrix<Scalar> x_mod = x(r_sp);
1414 Matrix<Scalar> y_mod = y(r_sp);
1415 casadi_math<Scalar>::fun(op, x_mod.ptr(), y_mod.ptr(), r.ptr(), r_sp.nnz());
1419 if (!r.is_dense() && !operation_checker<F00Checker>(op)) {
1422 casadi_math<Scalar>::fun(op, casadi_limits<Scalar>::zero,
1423 casadi_limits<Scalar>::zero, fcn_0);
1424 r = densify(r, fcn_0);
1430 template<
typename Scalar>
1431 Matrix<Scalar> Matrix<Scalar>::triplet(
const std::vector<casadi_int>& row,
1432 const std::vector<casadi_int>& col,
1433 const Matrix<Scalar>& d) {
1434 return triplet(row, col, d, *std::max_element(row.begin(), row.end()),
1435 *std::max_element(col.begin(), col.end()));
1438 template<
typename Scalar>
1439 Matrix<Scalar> Matrix<Scalar>::triplet(
const std::vector<casadi_int>& row,
1440 const std::vector<casadi_int>& col,
1441 const Matrix<Scalar>& d,
1442 const std::pair<casadi_int, casadi_int>& rc) {
1443 return triplet(row, col, d, rc.first, rc.second);
1446 template<
typename Scalar>
1447 Matrix<Scalar> Matrix<Scalar>::triplet(
const std::vector<casadi_int>& row,
1448 const std::vector<casadi_int>& col,
1449 const Matrix<Scalar>& d,
1450 casadi_int nrow, casadi_int ncol) {
1451 casadi_assert(col.size()==row.size() && col.size()==d.nnz(),
1452 "Argument error in Matrix<Scalar>::triplet(row, col, d): "
1453 "supplied lists must all be of equal length, but got: "
1454 + str(row.size()) +
", " + str(col.size()) +
" and " + str(d.nnz()));
1455 std::vector<casadi_int> mapping;
1456 Sparsity sp = Sparsity::triplet(nrow, ncol, row, col, mapping,
false);
1457 return Matrix<Scalar>(sp, d.nz(mapping));
1460 template<
typename Scalar>
1461 Matrix<Scalar> Matrix<Scalar>::eye(casadi_int n) {
1462 return Matrix<Scalar>::ones(Sparsity::diag(n));
1465 template<
typename Scalar>
1466 Matrix<Scalar> Matrix<Scalar>::inf(
const Sparsity& sp) {
1467 casadi_assert(std::numeric_limits<Scalar>::has_infinity,
1468 "Datatype cannot represent infinity");
1469 return Matrix<Scalar>(sp, std::numeric_limits<Scalar>::infinity(),
false);
1473 template<
typename Scalar>
1474 Matrix<Scalar> Matrix<Scalar>::inf(
const std::pair<casadi_int, casadi_int>& rc) {
1475 return inf(rc.first, rc.second);
1478 template<
typename Scalar>
1479 Matrix<Scalar> Matrix<Scalar>::inf(casadi_int nrow, casadi_int ncol) {
1480 return inf(Sparsity::dense(nrow, ncol));
1483 template<
typename Scalar>
1484 Matrix<Scalar> Matrix<Scalar>::nan(
const Sparsity& sp) {
1485 casadi_assert(std::numeric_limits<Scalar>::has_quiet_NaN,
1486 "Datatype cannot represent not-a-number");
1487 return Matrix<Scalar>(sp, std::numeric_limits<Scalar>::quiet_NaN(),
false);
1490 template<
typename Scalar>
1491 Matrix<Scalar> Matrix<Scalar>::nan(
const std::pair<casadi_int, casadi_int>& rc) {
1492 return nan(rc.first, rc.second);
1495 template<
typename Scalar>
1496 Matrix<Scalar> Matrix<Scalar>::nan(casadi_int nrow, casadi_int ncol) {
1497 return nan(Sparsity::dense(nrow, ncol));
1500 template<
typename Scalar>
1501 bool Matrix<Scalar>::is_regular()
const {
1505 template<
typename Scalar>
1506 bool Matrix<Scalar>::is_smooth()
const {
1510 template<
typename Scalar>
1511 casadi_int Matrix<Scalar>::element_hash()
const {
1512 casadi_error(
"'element_hash' not defined for " + type_name());
1515 template<
typename Scalar>
1516 bool Matrix<Scalar>::is_leaf()
const {
1517 casadi_error(
"'is_leaf' not defined for " + type_name());
1520 template<
typename Scalar>
1521 bool Matrix<Scalar>::is_commutative()
const {
1522 casadi_error(
"'is_commutative' not defined for " + type_name());
1525 template<
typename Scalar>
1526 bool Matrix<Scalar>::is_symbolic()
const {
1530 template<
typename Scalar>
1531 casadi_int Matrix<Scalar>::op()
const {
1532 casadi_error(
"'op' not defined for " + type_name());
1535 template<
typename Scalar>
1536 bool Matrix<Scalar>::is_op(casadi_int k)
const {
1537 casadi_error(
"'is_op' not defined for " + type_name());
1540 template<
typename Scalar>
1541 void Matrix<Scalar>::export_code(
const std::string& lang,
1542 std::ostream &stream,
const Dict& options)
const {
1543 casadi_error(
"'export_code' not defined for " + type_name());
1546 template<
typename Scalar>
1547 bool Matrix<Scalar>::is_valid_input()
const {
1551 template<
typename Scalar>
1552 bool Matrix<Scalar>::has_duplicates()
const {
1553 casadi_error(
"'has_duplicates' not defined for " + type_name());
1556 template<
typename Scalar>
1557 void Matrix<Scalar>::reset_input()
const {
1558 casadi_error(
"'reset_input' not defined for " + type_name());
1561 template<
typename Scalar>
1562 Matrix<double> Matrix<Scalar>::from_file(
const std::string& filename,
1563 const std::string& format_hint) {
1564 casadi_error(
"'from_file' not defined for " + type_name());
1567 template<
typename Scalar>
1568 bool Matrix<Scalar>::is_integer()
const {
1570 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_integer(e))
return false;
1576 template<
typename Scalar>
1577 bool Matrix<Scalar>::is_constant()
const {
1579 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_constant(e))
return false;
1585 template<
typename Scalar>
1586 bool Matrix<Scalar>::is_call()
const {
1587 casadi_assert(is_scalar(),
"'is_call' only defined for scalar expressions");
1592 template<
typename Scalar>
1593 bool Matrix<Scalar>::is_output()
const {
1594 casadi_assert(is_scalar(),
"'is_output' only defined for scalar expressions");
1599 template<
typename Scalar>
1600 Matrix<Scalar> Matrix<Scalar>::get_output(casadi_int oind)
const {
1601 casadi_error(
"'get_output' not defined for " + type_name());
1604 template<
typename Scalar>
1605 bool Matrix<Scalar>::has_output()
const {
1606 casadi_assert(is_scalar(),
"'has_output' only defined for scalar expressions");
1611 template<
typename Scalar>
1612 Function Matrix<Scalar>::which_function()
const {
1613 casadi_error(
"'which_function' not defined for " + type_name());
1616 template<
typename Scalar>
1617 casadi_int Matrix<Scalar>::which_output()
const {
1618 casadi_error(
"'which_output' not defined for " + type_name());
1621 template<
typename Scalar>
1622 bool Matrix<Scalar>::is_one()
const {
1623 if (!is_dense())
return false;
1626 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_one(e))
return false;
1631 template<
typename Scalar>
1632 bool Matrix<Scalar>::is_minus_one()
const {
1633 if (!is_dense())
return false;
1636 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_minus_one(e))
return false;
1641 template<
typename Scalar>
1642 bool Matrix<Scalar>::is_zero()
const {
1645 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_zero(e))
return false;
1650 template<
typename Scalar>
1651 bool Matrix<Scalar>::is_eye()
const {
1654 if (!sparsity().is_diag())
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_equal(
const Matrix<Scalar> &x,
const Matrix<Scalar> &y,
1666 casadi_assert(x.size() == y.size(),
"Dimension mismatch");
1669 if (x.sparsity() != y.sparsity()) {
1670 Sparsity sp = x.sparsity() + y.sparsity();
1671 return is_equal(project(x, sp), project(y, sp), depth);
1675 auto y_it = y.nonzeros().begin();
1676 for (
auto&& e : x.nonzeros()) {
1677 if (!casadi_limits<Scalar>::is_equal(e, *y_it++, depth))
return false;
1685 template<
typename Scalar>
1686 inline Matrix<Scalar> mmin_nonstatic(
const Matrix<Scalar> &x) {
1687 if (x.is_empty())
return Matrix<Scalar>();
1688 return casadi_mmin(x.ptr(), x.nnz(), x.is_dense());
1691 template<
typename Scalar>
1692 Matrix<Scalar> Matrix<Scalar>::mmin(
const Matrix<Scalar> &x) {
1693 return mmin_nonstatic(x);
1697 template<
typename Scalar>
1698 inline Matrix<Scalar> mmax_nonstatic(
const Matrix<Scalar> &x) {
1699 if (x.is_empty())
return Matrix<Scalar>();
1700 return casadi_mmax(x.ptr(), x.nnz(), x.is_dense());
1703 template<
typename Scalar>
1704 Matrix<Scalar> Matrix<Scalar>::mmax(
const Matrix<Scalar> &x) {
1705 return mmax_nonstatic(x);
1708 template<
typename Scalar>
1709 bool Matrix<Scalar>::has_zeros()
const {
1711 for (
auto&& e : nonzeros())
if (casadi_limits<Scalar>::is_zero(e))
return true;
1717 template<
typename Scalar>
1718 std::vector<Scalar> Matrix<Scalar>::get_nonzeros()
const {
1722 template<
typename Scalar>
1723 std::vector<Scalar> Matrix<Scalar>::get_elements()
const {
1724 return static_cast< std::vector<Scalar>
>(*this);
1727 template<
typename Scalar>
1728 std::string Matrix<Scalar>::name()
const {
1729 casadi_error(
"'name' not defined for " + type_name());
1732 template<
typename Scalar>
1733 Matrix<Scalar> Matrix<Scalar>::dep(casadi_int ch)
const {
1734 casadi_error(
"'dep' not defined for " + type_name());
1737 template<
typename Scalar>
1738 casadi_int Matrix<Scalar>::n_dep()
const {
1739 casadi_error(
"'n_dep' not defined for " + type_name());
1742 template<
typename Scalar>
1743 Matrix<Scalar> Matrix<Scalar>::rand(
1746 return rand(Sparsity::dense(nrow, ncol));
1749 template<
typename Scalar>
1750 Matrix<Scalar> Matrix<Scalar>::rand(
1751 const std::pair<casadi_int, casadi_int>& rc) {
1752 return rand(rc.first, rc.second);
1755 template<
typename Scalar>
1756 Matrix<Scalar> Matrix<Scalar>::project(
const Matrix<Scalar>& x,
1757 const Sparsity& sp,
bool intersect) {
1759 return project(x, sp.intersect(x.sparsity()),
false);
1761 casadi_assert(sp.size()==x.size(),
"Dimension mismatch");
1762 Matrix<Scalar> ret = Matrix<Scalar>::zeros(sp);
1763 std::vector<Scalar> w(x.size1());
1764 casadi_project(x.ptr(), x.sparsity(), ret.ptr(), sp, get_ptr(w));
1769 template<
typename Scalar>
1770 void Matrix<Scalar>::set_max_depth(casadi_int eq_depth) {
1771 casadi_error(
"'set_max_depth' not defined for " + type_name());
1774 template<
typename Scalar>
1775 casadi_int Matrix<Scalar>::get_max_depth() {
1776 casadi_error(
"'get_max_depth' not defined for " + type_name());
1779 template<
typename Scalar>
1780 Matrix<Scalar> Matrix<Scalar>::det(
const Matrix<Scalar>& x) {
1781 casadi_int n = x.size2();
1782 casadi_assert(n == x.size1(),
"matrix must be square");
1785 if (x.is_scalar())
return x;
1788 if (n==2)
return x(0, 0) * x(1, 1) - x(0, 1) * x(1, 0);
1791 Matrix<Scalar> ret = 0;
1796 Matrix<casadi_int> sp = IM::ones(x.sparsity());
1799 Matrix<casadi_int> row_count = Matrix<casadi_int>::sum2(sp);
1802 if (!row_count.is_dense())
return 0;
1805 Matrix<casadi_int> col_count = Matrix<casadi_int>::sum1(sp).T();
1808 if (!row_count.is_dense())
return 0;
1810 casadi_int min_row = std::distance(row_count.nonzeros().begin(),
1811 std::min_element(row_count.nonzeros().begin(),
1812 row_count.nonzeros().end()));
1813 casadi_int min_col = std::distance(col_count.nonzeros().begin(),
1814 std::min_element(col_count.nonzeros().begin(),
1815 col_count.nonzeros().end()));
1817 if (min_row <= min_col) {
1819 casadi_int j = row_count.sparsity().row(min_row);
1821 Matrix<Scalar> row = x(j, Slice(0, n));
1823 std::vector< casadi_int > col_i = row.sparsity().get_col();
1825 for (casadi_int k=0; k<row.nnz(); ++k) {
1827 ret += row->at(k)*cofactor(x, col_i.at(k), j);
1832 casadi_int i = col_count.sparsity().row(min_col);
1834 Matrix<Scalar> col = x(Slice(0, n), i);
1836 const casadi_int* row_i = col.row();
1838 for (casadi_int k=0; k<col.nnz(); ++k) {
1840 ret += col->at(k)*cofactor(x, i, row_i[k]);
1847 template<
typename Scalar>
1848 Matrix<Scalar> Matrix<Scalar>::sum2(
const Matrix<Scalar>& x) {
1849 return mtimes(x, Matrix<Scalar>::ones(x.size2(), 1));
1852 template<
typename Scalar>
1853 Matrix<Scalar> Matrix<Scalar>::sum1(
const Matrix<Scalar>& x) {
1854 return mtimes(Matrix<Scalar>::ones(1, x.size1()), x);
1857 template<
typename Scalar>
1858 Matrix<Scalar> Matrix<Scalar>::minor(
const Matrix<Scalar>& x,
1859 casadi_int i, casadi_int j) {
1860 casadi_int n = x.size2();
1861 casadi_assert(n == x.size1(),
"minor: matrix must be square");
1867 Matrix<Scalar> M = Matrix<Scalar>(n-1, n-1);
1869 std::vector<casadi_int> col = x.sparsity().get_col();
1870 const casadi_int* row = x.sparsity().row();
1872 for (casadi_int k=0; k<x.nnz(); ++k) {
1873 casadi_int i1 = col[k];
1874 casadi_int j1 = row[k];
1876 if (i1 == i || j1 == j)
continue;
1878 casadi_int i2 = (i1<i)?i1:i1-1;
1879 casadi_int j2 = (j1<j)?j1:j1-1;
1881 M(j2, i2) = x(j1, i1);
1886 template<
typename Scalar>
1887 Matrix<Scalar> Matrix<Scalar>::cofactor(
const Matrix<Scalar>& A, casadi_int i, casadi_int j) {
1890 Matrix<Scalar> minor_ij = minor(A, i, j);
1892 casadi_int sign_i = 1-2*((i+j) % 2);
1894 return sign_i * minor_ij;
1897 template<
typename Scalar>
1898 Matrix<Scalar> Matrix<Scalar>::adj(
const Matrix<Scalar>& x) {
1899 casadi_int n = x.size2();
1900 casadi_assert(n == x.size1(),
"adj: matrix must be square");
1903 Matrix<Scalar> temp;
1906 Matrix<Scalar>
C = Matrix<Scalar>(n, n);
1907 for (casadi_int i=0; i<n; ++i)
1908 for (casadi_int j=0; j<n; ++j) {
1909 temp = cofactor(x, i, j);
1910 if (!temp.is_zero())
C(j, i) = temp;
1916 template<
typename Scalar>
1917 Matrix<Scalar> Matrix<Scalar>::inv_minor(
const Matrix<Scalar>& x) {
1919 return adj(x)/det(x);
1922 template<
typename Scalar>
1923 Matrix<Scalar> Matrix<Scalar>::reshape(
const Matrix<Scalar>& x,
1924 casadi_int nrow, casadi_int ncol) {
1925 Sparsity sp = Sparsity::reshape(x.sparsity(), nrow, ncol);
1926 return Matrix<Scalar>(sp, x.nonzeros(),
false);
1929 template<
typename Scalar>
1930 Matrix<Scalar> Matrix<Scalar>::reshape(
const Matrix<Scalar>& x,
const Sparsity& sp) {
1932 if (sp==x.sparsity())
return x;
1935 casadi_assert_dev(sp.is_reshape(x.sparsity()));
1937 return Matrix<Scalar>(sp, x.nonzeros(),
false);
1940 template<
typename Scalar>
1941 Matrix<Scalar> Matrix<Scalar>::sparsity_cast(
const Matrix<Scalar>& x,
const Sparsity& sp) {
1943 if (sp==x.sparsity())
return x;
1945 casadi_assert_dev(sp.nnz()==x.nnz());
1947 return Matrix<Scalar>(sp, x.nonzeros(),
false);
1950 template<
typename Scalar>
1951 Matrix<Scalar> Matrix<Scalar>::trace(
const Matrix<Scalar>& x) {
1952 casadi_assert(x.is_square(),
"trace: must be square");
1954 const Scalar* d=x.ptr();
1955 casadi_int size2 = x.size2();
1956 const casadi_int *colind=x.colind(), *row=x.row();
1957 for (casadi_int c=0; c<size2; c++) {
1958 for (casadi_int k=colind[c]; k!=colind[c+1]; ++k) {
1967 template<
typename Scalar>
1969 Matrix<Scalar>::blockcat(
const std::vector< std::vector<Matrix<Scalar> > > &v) {
1970 std::vector< Matrix<Scalar> > ret;
1971 for (casadi_int i=0; i<v.size(); ++i)
1972 ret.push_back(horzcat(v[i]));
1973 return vertcat(ret);
1976 template<
typename Scalar>
1977 Matrix<Scalar> Matrix<Scalar>::horzcat(
const std::vector<Matrix<Scalar> > &v) {
1979 std::vector<Sparsity> sp(v.size());
1980 for (casadi_int i=0; i<v.size(); ++i) sp[i] = v[i].sparsity();
1981 Matrix<Scalar> ret = zeros(Sparsity::horzcat(sp));
1984 auto i=ret->begin();
1985 for (
auto&& j : v) {
1986 std::copy(j->begin(), j->end(), i);
1992 template<
typename Scalar>
1993 std::vector<Matrix<Scalar> >
1994 Matrix<Scalar>::horzsplit(
const Matrix<Scalar>& x,
const std::vector<casadi_int>& offset) {
1996 std::vector<Sparsity> sp = Sparsity::horzsplit(x.sparsity(), offset);
1999 std::vector<Matrix<Scalar> > ret;
2000 ret.reserve(sp.size());
2003 auto i=x.nonzeros().begin();
2004 for (
auto&& j : sp) {
2005 auto i_next = i + j.nnz();
2006 ret.push_back(Matrix<Scalar>(j, std::vector<Scalar>(i, i_next),
false));
2011 casadi_assert_dev(i==x.nonzeros().end());
2015 template<
typename Scalar>
2016 Matrix<Scalar> Matrix<Scalar>::vertcat(
const std::vector<Matrix<Scalar> > &v) {
2017 std::vector<Matrix<Scalar> > vT(v.size());
2018 for (casadi_int i=0; i<v.size(); ++i) vT[i] = v[i].
T();
2019 return horzcat(vT).T();
2022 template<
typename Scalar>
2023 std::vector< Matrix<Scalar> >
2024 Matrix<Scalar>::vertsplit(
const Matrix<Scalar>& x,
const std::vector<casadi_int>& offset) {
2025 std::vector< Matrix<Scalar> > ret = horzsplit(x.T(), offset);
2026 for (
auto&& e : ret) e = e.T();
2030 template<
typename Scalar>
2031 std::vector< Matrix<Scalar> >
2032 Matrix<Scalar>::diagsplit(
const Matrix<Scalar>& x,
const std::vector<casadi_int>& offset1,
2033 const std::vector<casadi_int>& offset2) {
2035 casadi_assert_dev(!offset1.empty());
2036 casadi_assert_dev(offset1.front()==0);
2037 casadi_assert_dev(offset1.back()==x.size1());
2041 casadi_assert_dev(!offset2.empty());
2042 casadi_assert_dev(offset2.front()==0);
2043 casadi_assert_dev(offset2.back()==x.size2());
2047 casadi_int n = offset1.size()-1;
2050 std::vector< Matrix<Scalar> > ret;
2053 for (casadi_int i=0; i<n; ++i) {
2054 ret.push_back(x(Slice(offset1[i], offset1[i+1]), Slice(offset2[i], offset2[i+1])));
2060 template<
typename Scalar>
2061 Matrix<Scalar> Matrix<Scalar>::dot(
const Matrix<Scalar> &x,
2062 const Matrix<Scalar> &y) {
2063 casadi_assert(x.size()==y.size(),
"dot: Dimension mismatch");
2064 if (x.sparsity()!=y.sparsity()) {
2065 Sparsity sp = x.sparsity() * y.sparsity();
2066 return dot(project(x, sp), project(y, sp));
2068 return casadi_dot(x.nnz(), x.ptr(), y.ptr());
2071 template<
typename Scalar>
2072 Matrix<Scalar> Matrix<Scalar>::all(
const Matrix<Scalar>& x) {
2073 if (!x.is_dense())
return false;
2075 for (casadi_int i=0; i<x.nnz(); ++i) {
2076 ret = ret && x->at(i)==1;
2081 template<
typename Scalar>
2082 Matrix<Scalar> Matrix<Scalar>::any(
const Matrix<Scalar>& x) {
2083 if (!x.is_dense())
return false;
2085 for (casadi_int i=0; i<x.nnz(); ++i) {
2086 ret = ret || x->at(i)==1;
2091 template<
typename Scalar>
2092 Matrix<Scalar> Matrix<Scalar>::norm_1(
const Matrix<Scalar>& x) {
2093 return casadi_norm_1(x.nnz(), x.ptr());
2096 template<
typename Scalar>
2097 Matrix<Scalar> Matrix<Scalar>::norm_2(
const Matrix<Scalar>& x) {
2098 if (x.is_vector()) {
2101 casadi_error(
"2-norms currently only supported for vectors. "
2102 "Did you intend to calculate a Frobenius norms (norm_fro)?");
2106 template<
typename Scalar>
2107 Matrix<Scalar> Matrix<Scalar>::norm_fro(
const Matrix<Scalar>& x) {
2108 return casadi_norm_2(x.nnz(), x.ptr());
2111 template<
typename Scalar>
2112 Matrix<Scalar> Matrix<Scalar>::norm_inf(
const Matrix<Scalar>& x) {
2114 Matrix<Scalar> s = 0;
2115 for (
auto i=x.nonzeros().begin(); i!=x.nonzeros().end(); ++i) {
2116 s = fmax(s, fabs(Matrix<Scalar>(*i)));
2121 template<
typename Scalar>
2122 void Matrix<Scalar>::
2123 qr_sparse(
const Matrix<Scalar>& A,
2124 Matrix<Scalar>& V, Matrix<Scalar> &R, Matrix<Scalar>& beta,
2125 std::vector<casadi_int>& prinv, std::vector<casadi_int>& pc,
bool amd) {
2128 A.sparsity().qr_sparse(spV, spR, prinv, pc, amd);
2130 casadi_int nrow_ext = spV.size1(), ncol = spV.size2();
2133 beta = nan(ncol, 1);
2134 std::vector<Scalar> w(nrow_ext);
2135 casadi_qr(A.sparsity(), A.ptr(), get_ptr(w), spV, V.ptr(),
2136 spR, R.ptr(), beta.ptr(),
2137 get_ptr(prinv), get_ptr(pc));
2140 template<
typename Scalar>
2141 Matrix<Scalar> Matrix<Scalar>::
2142 qr_solve(
const Matrix<Scalar>& b,
const Matrix<Scalar>& v,
2143 const Matrix<Scalar>& r,
const Matrix<Scalar>& beta,
2144 const std::vector<casadi_int>& prinv,
const std::vector<casadi_int>& pc,
2147 casadi_int ncol = v.size2();
2148 casadi_int nrow = b.size1(), nrhs = b.size2();
2149 casadi_assert(r.size()==v.size(),
"'r', 'v' dimension mismatch");
2150 casadi_assert(beta.is_vector() && beta.numel()==ncol,
"'beta' has wrong dimension");
2151 casadi_assert(prinv.size()==r.size1(),
"'pinv' has wrong dimension");
2153 std::vector<Scalar> w(nrow+ncol);
2155 Matrix<Scalar> x = densify(b);
2156 casadi_qr_solve(x.ptr(), nrhs, tr, v.sparsity(), v.ptr(), r.sparsity(), r.ptr(),
2157 beta.ptr(), get_ptr(prinv), get_ptr(pc), get_ptr(w));
2161 template<
typename Scalar>
2162 void Matrix<Scalar>::qr(
const Matrix<Scalar>& A,
2163 Matrix<Scalar>& Q, Matrix<Scalar> &R) {
2166 casadi_assert(A.size1()>=A.size2(),
"qr: fewer rows than columns");
2169 Q = R = Matrix<Scalar>();
2170 for (casadi_int i=0; i<A.size2(); ++i) {
2172 Matrix<Scalar> ai = A(Slice(), i);
2173 Matrix<Scalar> qi = ai;
2175 Matrix<Scalar> ri = Matrix<Scalar>(A.size2(), 1);
2178 for (casadi_int j=0; j<i; ++j) {
2181 Matrix<Scalar> qj =
Q(Slice(), j);
2183 ri(j, 0) = mtimes(qi.T(), qj);
2187 if (ri.has_nz(j, 0))
2188 qi -= ri(j, 0) * qj;
2192 ri(i, 0) = norm_2(qi);
2196 Q = Matrix<Scalar>::horzcat({
Q, qi});
2197 R = Matrix<Scalar>::horzcat({R, ri});
2201 template<
typename Scalar>
2202 void Matrix<Scalar>::ldl(
const Matrix<Scalar>& A, Matrix<Scalar> &D,
2203 Matrix<Scalar>& LT, std::vector<casadi_int>& p,
bool amd) {
2205 Sparsity Lt_sp = A.sparsity().ldl(p, amd);
2208 casadi_int n=A.size1();
2211 std::vector<Scalar> D_nz(n), L_nz(Lt_sp.nnz()), w(n);
2212 casadi_ldl(A.sparsity(), get_ptr(A.nonzeros()), Lt_sp,
2213 get_ptr(L_nz), get_ptr(D_nz), get_ptr(p), get_ptr(w));
2216 LT = Matrix<Scalar>(Lt_sp, L_nz);
2220 template<
typename Scalar>
2221 Matrix<Scalar> Matrix<Scalar>::
2222 ldl_solve(
const Matrix<Scalar>& b,
const Matrix<Scalar>& D,
const Matrix<Scalar>& LT,
2223 const std::vector<casadi_int>& p) {
2225 casadi_int n = b.size1(), nrhs = b.size2();
2226 casadi_assert(p.size()==n,
"'p' has wrong dimension");
2227 casadi_assert(LT.size1()==n && LT.size2()==n,
"'LT' has wrong dimension");
2228 casadi_assert(
D.is_vector() &&
D.numel()==n,
"'D' has wrong dimension");
2230 Matrix<Scalar> x = densify(b);
2231 std::vector<Scalar> w(n);
2232 casadi_ldl_solve(x.ptr(), nrhs, LT.sparsity(), LT.ptr(),
D.ptr(), get_ptr(p), get_ptr(w));
2236 template<
typename Scalar>
2237 Matrix<Scalar> Matrix<Scalar>::nullspace(
const Matrix<Scalar>& A) {
2238 Matrix<Scalar>
X = A;
2239 casadi_int n =
X.size1();
2240 casadi_int m =
X.size2();
2241 casadi_assert(m>=n,
"nullspace(): expecting a flat matrix (more columns than rows), "
2242 "but got " + str(
X.dim()) +
".");
2244 Matrix<Scalar> seed = DM::eye(m)(Slice(0, m), Slice(n, m));
2246 std::vector< Matrix<Scalar> > us;
2247 std::vector< Matrix<Scalar> > betas;
2249 Matrix<Scalar> beta;
2251 for (casadi_int i=0;i<n;++i) {
2252 Matrix<Scalar> x =
X(i, Slice(i, m));
2253 Matrix<Scalar> u = Matrix<Scalar>(x);
2254 Matrix<Scalar> sigma = sqrt(sum2(x*x));
2255 const Matrix<Scalar>& x0 = x(0, 0);
2258 Matrix<Scalar> b = -copysign(sigma, x0);
2260 u(Slice(0), Slice(1, m-i))*= 1/(x0-b);
2263 X(Slice(i, n), Slice(i, m)) -=
2264 beta*mtimes(mtimes(
X(Slice(i, n), Slice(i, m)), u.T()), u);
2266 betas.push_back(beta);
2269 for (casadi_int i=n-1;i>=0;--i) {
2270 seed(Slice(i, m), Slice(0, m-n)) -=
2271 betas[i]*mtimes(us[i].
T(), mtimes(us[i], seed(Slice(i, m), Slice(0, m-n))));
2278 template<
typename Scalar>
2279 Matrix<Scalar> Matrix<Scalar>::chol(
const Matrix<Scalar>& A) {
2281 Matrix<Scalar>
D, LT;
2282 std::vector<casadi_int> p;
2283 ldl(A, D, LT, p,
false);
2285 LT += Matrix<Scalar>::eye(
D.size1());
2287 return mtimes(diag(sqrt(D)), LT);
2290 template<
typename Scalar>
2291 Matrix<Scalar> Matrix<Scalar>::solve(
const Matrix<Scalar>& a,
const Matrix<Scalar>& b) {
2293 casadi_assert(a.size1() == b.size1(),
"solve Ax=b: dimension mismatch: b has "
2294 + str(b.size1()) +
" rows while A has " + str(a.size1()) +
".");
2295 casadi_assert(a.size1() == a.size2(),
"solve: A not square but " + str(a.dim()));
2299 Matrix<Scalar> x = b;
2300 const casadi_int* Arow = a.row();
2301 const casadi_int* Acolind = a.colind();
2302 const std::vector<Scalar> & Adata = a.nonzeros();
2303 for (casadi_int i=0; i<a.size2(); ++i) {
2304 for (casadi_int k=0; k<b.size2(); ++k) {
2305 if (!x.has_nz(i, k))
continue;
2307 for (casadi_int kk=Acolind[i+1]-1; kk>=Acolind[i] && Arow[kk]>i; --kk) {
2308 casadi_int j = Arow[kk];
2309 x(j, k) -= Adata[kk]*x(i, k);
2314 }
else if (a.is_triu()) {
2316 Matrix<Scalar> x = b;
2317 const casadi_int* Arow = a.row();
2318 const casadi_int* Acolind = a.colind();
2319 const std::vector<Scalar> & Adata = a.nonzeros();
2320 for (casadi_int i=a.size2()-1; i>=0; --i) {
2321 for (casadi_int k=0; k<b.size2(); ++k) {
2322 if (!x.has_nz(i, k))
continue;
2324 for (casadi_int kk=Acolind[i]; kk<Acolind[i+1] && Arow[kk]<i; ++kk) {
2325 casadi_int j = Arow[kk];
2326 x(j, k) -= Adata[kk]*x(i, k);
2331 }
else if (a.has_zeros()) {
2335 return solve(sparsify(a), b);
2340 std::vector<casadi_int> rowperm, colperm, rowblock, colblock;
2341 std::vector<casadi_int> coarse_rowblock, coarse_colblock;
2342 a.sparsity().btf(rowperm, colperm, rowblock, colblock,
2343 coarse_rowblock, coarse_colblock);
2346 Matrix<Scalar> bperm = b(rowperm, Slice());
2349 Matrix<Scalar> Aperm = a(rowperm, colperm);
2352 Matrix<Scalar> xperm;
2355 if (Aperm.is_tril()) {
2358 xperm = solve(Aperm, bperm);
2360 }
else if (a.size2()<=3) {
2363 xperm = mtimes(inv_minor(Aperm), bperm);
2368 Matrix<Scalar>
Q, R;
2372 xperm = solve(R, mtimes(
Q.T(), bperm));
2376 std::vector<casadi_int> inv_colperm(colperm.size());
2377 for (casadi_int k=0; k<colperm.size(); ++k)
2378 inv_colperm[colperm[k]] = k;
2381 Matrix<Scalar> x = xperm(inv_colperm, Slice());
2386 template<
typename Scalar>
2387 Matrix<Scalar> Matrix<Scalar>::
2388 solve(
const Matrix<Scalar>& a,
const Matrix<Scalar>& b,
2389 const std::string& lsolver,
const Dict& dict) {
2390 casadi_error(
"'solve' with plugin not defined for " + type_name());
2391 return Matrix<Scalar>();
2394 template<
typename Scalar>
2395 Matrix<Scalar> Matrix<Scalar>::
2396 inv(
const Matrix<Scalar>& a) {
2397 return solve(a, Matrix<Scalar>::eye(a.size1()));
2400 template<
typename Scalar>
2401 Matrix<Scalar> Matrix<Scalar>::
2402 inv(
const Matrix<Scalar>& a,
2403 const std::string& lsolver,
const Dict& dict) {
2404 casadi_error(
"'inv' with plugin not defined for " + type_name());
2405 return Matrix<Scalar>();
2408 template<
typename Scalar>
2409 Matrix<Scalar> Matrix<Scalar>::pinv(
const Matrix<Scalar>& A) {
2410 if (A.size2()>=A.size1()) {
2411 return solve(mtimes(A, A.T()), A).T();
2413 return solve(mtimes(A.T(), A), A.T());
2417 template<
typename Scalar>
2418 Matrix<Scalar> Matrix<Scalar>::
2419 pinv(
const Matrix<Scalar>& A,
const std::string& lsolver,
const Dict& dict) {
2420 casadi_error(
"'solve' not defined for " + type_name());
2421 return Matrix<Scalar>();
2424 template<
typename Scalar>
2425 Matrix<Scalar> Matrix<Scalar>::
2426 expm_const(
const Matrix<Scalar>& A,
const Matrix<Scalar>& t) {
2427 casadi_error(
"'solve' not defined for " + type_name());
2428 return Matrix<Scalar>();
2431 template<
typename Scalar>
2432 Matrix<Scalar> Matrix<Scalar>::
2433 expm(
const Matrix<Scalar>& A) {
2434 casadi_error(
"'solve' not defined for " + type_name());
2435 return Matrix<Scalar>();
2438 template<
typename Scalar>
2439 Matrix<Scalar> Matrix<Scalar>::kron(
const Matrix<Scalar>& a,
const Matrix<Scalar>& b) {
2440 std::vector<Scalar> ret(a.nnz()*b.nnz());
2441 casadi_kron(get_ptr(a), a.sparsity(), get_ptr(b), b.sparsity(), get_ptr(ret));
2443 Sparsity sp_ret = Sparsity::kron(a.sparsity(), b.sparsity());
2444 return Matrix<Scalar>(sp_ret, ret,
false);
2447 template<
typename Scalar>
2448 Matrix<Scalar> Matrix<Scalar>::diag(
const Matrix<Scalar>& A) {
2450 std::vector<casadi_int> mapping;
2452 Sparsity sp = A.sparsity().get_diag(mapping);
2454 Matrix<Scalar> ret = zeros(sp);
2456 for (casadi_int k=0; k<mapping.size(); k++) ret.nz(k) = A.nz(mapping[k]);
2463 template<
typename Scalar>
2464 Matrix<Scalar> Matrix<Scalar>::diagcat(
const std::vector< Matrix<Scalar> > &A) {
2465 std::vector<Scalar> data;
2467 std::vector<Sparsity> sp;
2468 for (casadi_int i=0;i<A.size();++i) {
2469 data.insert(data.end(), A[i].nonzeros().begin(), A[i].nonzeros().end());
2470 sp.push_back(A[i].sparsity());
2473 return Matrix<Scalar>(Sparsity::diagcat(sp), data,
false);
2476 template<
typename Scalar>
2477 Matrix<Scalar> Matrix<Scalar>::unite(
const Matrix<Scalar>& A,
const Matrix<Scalar>& B) {
2479 std::vector<unsigned char> mapping;
2480 Sparsity sp = A.sparsity().unite(B.sparsity(), mapping);
2483 Matrix<Scalar> ret = zeros(sp);
2486 casadi_int elA=0, elB=0;
2487 for (casadi_int k=0; k<mapping.size(); ++k) {
2488 if (mapping[k]==1) {
2489 ret.nonzeros()[k] = A.nonzeros()[elA++];
2490 }
else if (mapping[k]==2) {
2491 ret.nonzeros()[k] = B.nonzeros()[elB++];
2493 casadi_error(
"Pattern intersection not empty");
2497 casadi_assert_dev(A.nnz()==elA);
2498 casadi_assert_dev(B.nnz()==elB);
2503 template<
typename Scalar>
2504 Matrix<Scalar> Matrix<Scalar>::polyval(
const Matrix<Scalar>& p,
const Matrix<Scalar>& x) {
2505 casadi_assert(p.is_dense(),
"polynomial coefficients vector must be dense");
2506 casadi_assert(p.is_vector() && p.nnz()>0,
"polynomial coefficients must be a vector");
2507 Matrix<Scalar> ret = x;
2508 for (
auto&& e : ret.nonzeros()) {
2509 e = casadi_polyval(p.ptr(), p.numel()-1, e);
2514 template<
typename Scalar>
2515 Matrix<Scalar> Matrix<Scalar>::norm_inf_mul(
const Matrix<Scalar>& x,
2516 const Matrix<Scalar>& y) {
2517 casadi_assert(y.size1()==x.size2(),
"Dimension error. Got " + x.dim()
2518 +
" times " + y.dim() +
".");
2521 std::vector<Scalar> dwork(x.size1());
2522 std::vector<casadi_int> iwork(x.size1()+1+y.size2());
2525 return casadi_norm_inf_mul(x.ptr(), x.sparsity(), y.ptr(), y.sparsity(),
2526 get_ptr(dwork), get_ptr(iwork));
2529 template<
typename Scalar>
2530 void Matrix<Scalar>::expand(
const Matrix<Scalar>& ex,
2531 Matrix<Scalar> &weights, Matrix<Scalar>& terms) {
2532 casadi_error(
"'expand' not defined for " + type_name());
2535 template<
typename Scalar>
2536 Matrix<Scalar> Matrix<Scalar>::pw_const(
const Matrix<Scalar>& ex,
2537 const Matrix<Scalar>& tval,
2538 const Matrix<Scalar>& val) {
2539 casadi_error(
"'pw_const' not defined for " + type_name());
2540 return Matrix<Scalar>();
2543 template<
typename Scalar>
2544 Matrix<Scalar> Matrix<Scalar>::pw_lin(
const Matrix<Scalar>& ex,
2545 const Matrix<Scalar>& tval,
2546 const Matrix<Scalar>& val) {
2547 casadi_error(
"'pw_lin' not defined for " + type_name());
2548 return Matrix<Scalar>();
2551 template<
typename Scalar>
2552 Matrix<Scalar> Matrix<Scalar>::if_else(
const Matrix<Scalar> &cond,
2553 const Matrix<Scalar> &if_true,
2554 const Matrix<Scalar> &if_false,
2555 bool short_circuit) {
2556 return if_else_zero(cond, if_true) + if_else_zero(!cond, if_false);
2559 template<
typename Scalar>
2560 Matrix<Scalar> Matrix<Scalar>::conditional(
const Matrix<Scalar>& ind,
2561 const std::vector<Matrix<Scalar> >& x,
2562 const Matrix<Scalar>& x_default,
2563 bool short_circuit) {
2564 casadi_assert(!short_circuit,
2565 "Short-circuiting 'conditional' not supported for " + type_name());
2566 casadi_assert(ind.is_scalar(
true),
2567 "conditional: first argument must be scalar. Got " + ind.dim()+
" instead.");
2569 Matrix<Scalar> ret = x_default;
2570 for (casadi_int k=0; k<x.size(); ++k) {
2571 ret = if_else(ind==k, x[k], ret, short_circuit);
2576 template<
typename Scalar>
2577 Matrix<Scalar> Matrix<Scalar>::heaviside(
const Matrix<Scalar>& x) {
2578 return (1+sign(x))/2;
2581 template<
typename Scalar>
2582 Matrix<Scalar> Matrix<Scalar>::rectangle(
const Matrix<Scalar>& x) {
2583 return 0.5*(sign(x+0.5)-sign(x-0.5));
2586 template<
typename Scalar>
2587 Matrix<Scalar> Matrix<Scalar>::triangle(
const Matrix<Scalar>& x) {
2588 return rectangle(x/2)*(1-fabs(x));
2591 template<
typename Scalar>
2592 Matrix<Scalar> Matrix<Scalar>::ramp(
const Matrix<Scalar>& x) {
2593 return x*heaviside(x);
2596 template<
typename Scalar>
2597 Matrix<Scalar> Matrix<Scalar>::
2598 gauss_quadrature(
const Matrix<Scalar> &f,
2599 const Matrix<Scalar> &x,
const Matrix<Scalar> &a,
2600 const Matrix<Scalar> &b, casadi_int order) {
2601 return gauss_quadrature(f, x, a, b, order, Matrix<Scalar>());
2604 template<
typename Scalar>
2605 Matrix<Scalar> Matrix<Scalar>::gauss_quadrature(
const Matrix<Scalar>& f,
2606 const Matrix<Scalar>& x,
2607 const Matrix<Scalar>& a,
2608 const Matrix<Scalar>& b, casadi_int order,
2609 const Matrix<Scalar>& w) {
2610 casadi_error(
"'gauss_quadrature' not defined for " + type_name());
2611 return Matrix<Scalar>();
2614 template<
typename Scalar>
2615 Matrix<Scalar> Matrix<Scalar>::simplify(
const Matrix<Scalar> &x) {
2619 template<
typename Scalar>
2620 Matrix<Scalar> Matrix<Scalar>::substitute(
const Matrix<Scalar>& ex,
2621 const Matrix<Scalar>& v,
2622 const Matrix<Scalar>& vdef) {
2623 casadi_error(
"'substitute' not defined for " + type_name());
2624 return Matrix<Scalar>();
2627 template<
typename Scalar>
2628 std::vector<Matrix<Scalar> >
2629 Matrix<Scalar>::substitute(
const std::vector<Matrix<Scalar> >& ex,
2630 const std::vector<Matrix<Scalar> >& v,
2631 const std::vector<Matrix<Scalar> >& vdef) {
2632 casadi_error(
"'substitute' not defined for " + type_name());
2633 return std::vector<Matrix<Scalar> >();
2636 template<
typename Scalar>
2637 void Matrix<Scalar>::substitute_inplace(
const std::vector<Matrix<Scalar> >& v,
2638 std::vector<Matrix<Scalar> >& vdef,
2639 std::vector<Matrix<Scalar> >& ex,
2641 casadi_error(
"'substitute_inplace' not defined for " + type_name());
2644 template<
typename Scalar>
2645 void Matrix<Scalar>::extract_parametric(
const Matrix<Scalar> &expr,
2646 const Matrix<Scalar>& par,
2647 Matrix<Scalar>& expr_ret,
2648 std::vector<Matrix<Scalar> >& symbols,
2649 std::vector< Matrix<Scalar> >& parametric,
2651 casadi_error(
"'extract_parametric' not defined for " + type_name());
2654 template<
typename Scalar>
2655 void Matrix<Scalar>::separate_linear(
const Matrix<Scalar> &expr,
2656 const Matrix<Scalar> &sym_lin,
const Matrix<Scalar> &sym_const,
2657 Matrix<Scalar>& expr_const, Matrix<Scalar>& expr_lin, Matrix<Scalar>& expr_nonlin) {
2658 casadi_error(
"'separate_linear' not defined for " + type_name());
2661 template<
typename Scalar>
2662 bool Matrix<Scalar>::depends_on(
const Matrix<Scalar> &x,
const Matrix<Scalar> &arg) {
2663 casadi_error(
"'depends_on' not defined for " + type_name());
2667 template<
typename Scalar>
2668 bool Matrix<Scalar>::contains_all(
const std::vector <Matrix<Scalar> >& v,
2669 const std::vector <Matrix<Scalar> > &n) {
2670 casadi_error(
"'contains_all' not defined for " + type_name());
2674 template<
typename Scalar>
2675 bool Matrix<Scalar>::contains_any(
const std::vector<Matrix<Scalar> >& v,
2676 const std::vector <Matrix<Scalar> > &n) {
2677 casadi_error(
"'contains_any' not defined for " + type_name());
2681 template<
typename Scalar>
2682 std::vector< Matrix<Scalar> > Matrix<Scalar>::cse(
const std::vector< Matrix<Scalar> >& e) {
2683 casadi_error(
"'cse' not defined for " + type_name());
2688 template<
typename Scalar>
2689 Matrix<Scalar> Matrix<Scalar>::
2690 jacobian(
const Matrix<Scalar> &f,
const Matrix<Scalar> &x,
const Dict& opts) {
2691 casadi_error(
"'jacobian' not defined for " + type_name());
2692 return Matrix<Scalar>();
2695 template<
typename Scalar>
2696 Matrix<Scalar> Matrix<Scalar>::hessian(
const Matrix<Scalar> &f,
2697 const Matrix<Scalar> &x,
2699 casadi_error(
"'hessian' not defined for " + type_name());
2700 return Matrix<Scalar>();
2703 template<
typename Scalar>
2704 Matrix<Scalar> Matrix<Scalar>::hessian(
const Matrix<Scalar> &f,
2705 const Matrix<Scalar> &x,
2708 casadi_error(
"'hessian' not defined for " + type_name());
2709 return Matrix<Scalar>();
2712 template<
typename Scalar>
2713 std::vector<std::vector<Matrix<Scalar> > >
2715 forward(
const std::vector<Matrix<Scalar> > &ex,
2716 const std::vector<Matrix<Scalar> > &arg,
2717 const std::vector<std::vector<Matrix<Scalar> > > &v,
2719 casadi_error(
"'forward' not defined for " + type_name());
2722 template<
typename Scalar>
2723 std::vector<std::vector<Matrix<Scalar> > >
2725 reverse(
const std::vector<Matrix<Scalar> > &ex,
2726 const std::vector<Matrix<Scalar> > &arg,
2727 const std::vector<std::vector<Matrix<Scalar> > > &v,
2729 casadi_error(
"'reverse' not defined for " + type_name());
2732 template<
typename Scalar>
2734 Matrix<Scalar>::which_depends(
const Matrix<Scalar> &expr,
const Matrix<Scalar> &var,
2735 casadi_int order,
bool tr) {
2736 casadi_error(
"'which_depends' not defined for " + type_name());
2737 return std::vector<bool>();
2740 template<
typename Scalar>
2742 Matrix<Scalar>::jacobian_sparsity(
const Matrix<Scalar> &f,
const Matrix<Scalar> &x) {
2743 casadi_error(
"'jacobian_sparsity' not defined for " + type_name());
2747 template<
typename Scalar>
2748 Matrix<Scalar> Matrix<Scalar>::taylor(
const Matrix<Scalar>& f,
2749 const Matrix<Scalar>& x,
2750 const Matrix<Scalar>& a, casadi_int order) {
2751 casadi_error(
"'taylor' not defined for " + type_name());
2752 return Matrix<Scalar>();
2755 template<
typename Scalar>
2756 Matrix<Scalar> Matrix<Scalar>::mtaylor(
const Matrix<Scalar>& f,
2757 const Matrix<Scalar>& x,
2758 const Matrix<Scalar>& a, casadi_int order) {
2759 casadi_error(
"'mtaylor' not defined for " + type_name());
2760 return Matrix<Scalar>();
2763 template<
typename Scalar>
2764 Matrix<Scalar> Matrix<Scalar>::mtaylor(
const Matrix<Scalar>& f,
2765 const Matrix<Scalar>& x,
2766 const Matrix<Scalar>& a, casadi_int order,
2767 const std::vector<casadi_int>&order_contributions) {
2768 casadi_error(
"'mtaylor' not defined for " + type_name());
2769 return Matrix<Scalar>();
2772 template<
typename Scalar>
2773 casadi_int Matrix<Scalar>::n_nodes(
const Matrix<Scalar>& x) {
2774 casadi_error(
"'n_nodes' not defined for " + type_name());
2778 template<
typename Scalar>
2780 Matrix<Scalar>::print_operator(
const Matrix<Scalar>& x,
2781 const std::vector<std::string>& args) {
2782 casadi_error(
"'print_operator' not defined for " + type_name());
2783 return std::string();
2786 template<
typename Scalar>
2787 std::vector<Matrix<Scalar> > Matrix<Scalar>::symvar(
const Matrix<Scalar>& x) {
2788 casadi_error(
"'symvar' not defined for " + type_name());
2789 return std::vector<Matrix<Scalar> >();
2792 template<
typename Scalar>
2793 void Matrix<Scalar>::extract(std::vector<Matrix<Scalar>>& ex, std::vector<Matrix<Scalar>>& v,
2794 std::vector<Matrix<Scalar>>& vdef,
const Dict& opts) {
2795 casadi_error(
"'extract' not defined for " + type_name());
2798 template<
typename Scalar>
2799 void Matrix<Scalar>::shared(std::vector<Matrix<Scalar> >& ex,
2800 std::vector<Matrix<Scalar> >& v,
2801 std::vector<Matrix<Scalar> >& vdef,
2802 const std::string& v_prefix,
2803 const std::string& v_suffix) {
2804 casadi_error(
"'shared' not defined for " + type_name());
2807 template<
typename Scalar>
2808 Matrix<Scalar> Matrix<Scalar>::poly_coeff(
const Matrix<Scalar>& f,
2809 const Matrix<Scalar>&x) {
2810 casadi_error(
"'poly_coeff' not defined for " + type_name());
2813 template<
typename Scalar>
2814 Matrix<Scalar> Matrix<Scalar>::poly_roots(
const Matrix<Scalar>& p) {
2815 casadi_error(
"'poly_roots' not defined for " + type_name());
2818 template<
typename Scalar>
2819 Matrix<Scalar> Matrix<Scalar>::eig_symbolic(
const Matrix<Scalar>& m) {
2820 casadi_error(
"'eig_symbolic' not defined for " + type_name());
2823 template<
typename Scalar>
2824 DM Matrix<Scalar>::evalf(
const Matrix<Scalar>& m) {
2825 Function f(
"f", std::vector<SX>{}, std::vector<SX>{m});
2826 return f(std::vector<DM>{})[0];
2829 template<
typename Scalar>
2830 Matrix<Scalar> Matrix<Scalar>::sparsify(
const Matrix<Scalar>& x,
double tol) {
2832 bool remove_nothing =
true;
2833 for (
auto it=x.nonzeros().begin(); it!=x.nonzeros().end() && remove_nothing; ++it) {
2834 remove_nothing = !casadi_limits<Scalar>::is_almost_zero(*it, tol);
2836 if (remove_nothing)
return x;
2839 casadi_int size1 = x.size1();
2840 casadi_int size2 = x.size2();
2841 const casadi_int* colind = x.colind();
2842 const casadi_int* row = x.row();
2845 std::vector<casadi_int> new_colind(1, 0), new_row;
2846 std::vector<Scalar> new_data;
2849 for (casadi_int cc=0; cc<size2; ++cc) {
2851 for (casadi_int el=colind[cc]; el<colind[cc+1]; ++el) {
2853 if (!casadi_limits<Scalar>::is_almost_zero(x->at(el), tol)) {
2855 new_data.push_back(x->at(el));
2858 new_row.push_back(row[el]);
2862 new_colind.push_back(new_row.size());
2866 Sparsity sp(size1, size2, new_colind, new_row);
2869 return Matrix<Scalar>(sp, new_data);
2873 template<
typename Scalar>
2874 std::vector<Matrix<Scalar> > Matrix<Scalar>::get_input(
const Function& f) {
2875 casadi_error(
"'get_input' not defined for " + type_name());
2878 template<
typename Scalar>
2879 std::vector<Matrix<Scalar> > Matrix<Scalar>::get_free(
const Function& f) {
2880 casadi_error(
"'get_free' not defined for " + type_name());
2883 template<
typename Scalar>
2884 Matrix<Scalar>::operator double()
const {
2885 casadi_assert_dev(is_scalar());
2886 return static_cast<double>(scalar());
2889 template<
typename Scalar>
2890 Matrix<Scalar>::operator casadi_int()
const {
2891 casadi_assert_dev(is_scalar());
2892 return static_cast<casadi_int
>(scalar());
2895 template<
typename Scalar>
2896 Matrix<Scalar> Matrix<Scalar>::_sym(
const std::string& name,
const Sparsity& sp) {
2897 casadi_error(
"'sym' not defined for " + type_name());
2900 template<
typename Scalar>
2901 Matrix<Scalar> Matrix<Scalar>::rand(
const Sparsity& sp) {
2903 casadi_error(
"'rand' not defined for " + type_name());
2906 template<
typename Scalar>
2907 std::string Matrix<Scalar>::serialize()
const {
2908 std::stringstream ss;
2913 template<
typename Scalar>
2914 void Matrix<Scalar>::serialize(SerializingStream& s)
const {
2915 s.pack(
"Matrix::sparsity", sparsity());
2916 s.pack(
"Matrix::nonzeros", nonzeros());
2919 template<
typename Scalar>
2920 Matrix<Scalar> Matrix<Scalar>::deserialize(DeserializingStream& s) {
2922 s.unpack(
"Matrix::sparsity", sp);
2923 std::vector<Scalar> nz;
2924 s.unpack(
"Matrix::nonzeros", nz);
2925 return Matrix<Scalar>(sp, nz,
false);
2928 template<
typename Scalar>
2929 void Matrix<Scalar>::serialize(std::ostream &stream)
const {
2930 SerializingStream s(stream);
2934 template<
typename Scalar>
2935 Matrix<Scalar> Matrix<Scalar>::deserialize(std::istream &stream) {
2936 DeserializingStream s(stream);
2937 return Matrix<Scalar>::deserialize(s);
2940 template<
typename Scalar>
2941 Matrix<Scalar> Matrix<Scalar>::deserialize(
const std::string& s) {
2942 std::stringstream ss;
2944 return deserialize(ss);
2947 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
2948 template<
typename Scalar>
2949 std::mutex& Matrix<Scalar>::get_mutex_temp() {
2950 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.
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 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_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.