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");
614 stream.precision(stream_precision_);
615 stream.width(stream_width_);
616 if (stream_scientific_) {
617 stream.setf(std::ios::scientific);
619 stream.unsetf(std::ios::scientific);
627 stream << std::flush;
630 template<
typename Scalar>
632 print_vector(stream, sparsity(), ptr(), truncate);
635 template<
typename Scalar>
637 const Scalar* nonzeros,
bool truncate) {
638 casadi_assert(sp.
is_column(),
"Not a vector");
641 std::vector<std::string> nz, inter;
642 print_split(sp.
nnz(), nonzeros, nz, inter);
645 for (casadi_int i=0; i<inter.size(); ++i)
646 stream <<
"@" << (i+1) <<
"=" << inter[i] <<
", ";
650 const casadi_int* row = sp.
row();
651 casadi_int nnz = sp.
nnz();
652 casadi_int size1 = sp.
size1();
655 const casadi_int max_numel = 1000;
656 if (truncate && size1<=max_numel) truncate=
false;
663 for (casadi_int rr=0; rr<size1; ++rr) {
665 std::string s = el<nnz && rr==row[el] ? nz.at(el++) :
"00";
668 if (truncate && rr>=3 && rr<size1-3) {
670 if (rr==3) stream <<
", ...";
673 if (rr!=0) stream <<
", ";
677 stream <<
"]" << std::flush;
680 template<
typename Scalar>
682 print_dense(stream, sparsity(), ptr(), truncate);
685 template<
typename Scalar>
687 print_sparse(stream, sparsity(), ptr(), truncate);
690 template<
typename Scalar>
692 std::vector<std::string>& inter)
const {
694 print_split(nnz(), ptr(), nz, inter);
697 template<
typename Scalar>
699 const Scalar* nonzeros,
bool truncate) {
702 }
else if (sp.
numel()==1) {
706 print_scalar(stream, *nonzeros);
709 print_vector(stream, sp, nonzeros, truncate);
710 }
else if (std::max(sp.
size1(), sp.
size2())<=10 ||
711 static_cast<double>(sp.
nnz())/
static_cast<double>(sp.
numel())>=0.5) {
713 print_dense(stream, sp, nonzeros, truncate);
715 print_sparse(stream, sp, nonzeros, truncate);
719 template<
typename Scalar>
720 void Matrix<Scalar>::print_canonical(std::ostream &stream,
const Sparsity& sp,
721 const Scalar* nonzeros,
bool truncate) {
722 casadi_error(
"'print_canonical' not defined for " + type_name());
725 template<
typename Scalar>
727 std::streamsize precision = stream.precision();
728 std::streamsize width = stream.width();
729 std::ios_base::fmtflags flags = stream.flags();
731 stream.precision(stream_precision_);
732 stream.width(stream_width_);
733 if (stream_scientific_) {
734 stream.setf(std::ios::scientific);
736 stream.unsetf(std::ios::scientific);
739 stream << std::flush;
741 stream.precision(precision);
746 template<
typename Scalar>
748 std::vector<std::string>& nz,
749 std::vector<std::string>& inter) {
754 std::stringstream ss;
755 ss.precision(stream_precision_);
756 ss.width(stream_width_);
757 if (stream_scientific_) {
758 ss.setf(std::ios::scientific);
760 ss.unsetf(std::ios::scientific);
764 for (casadi_int i=0; i<nz.size(); ++i) {
765 ss.str(std::string());
771 template<
typename Scalar>
773 const Scalar* nonzeros,
bool truncate) {
775 casadi_int size1 = sp.size1();
776 casadi_int size2 = sp.size2();
777 const casadi_int* colind = sp.colind();
778 const casadi_int* row = sp.row();
779 casadi_int nnz = sp.nnz();
783 stream <<
"all zero sparse: " << size1 <<
"-by-" << size2 << std::flush;
788 stream <<
"sparse: " << size1 <<
"-by-" << size2 <<
", " << nnz <<
" nnz";
791 std::vector<std::string> nz, inter;
792 print_split(nnz, nonzeros, nz, inter);
795 for (casadi_int i=0; i<inter.size(); ++i)
796 stream << std::endl <<
" @" << (i+1) <<
"=" << inter[i] <<
",";
800 const casadi_int max_nnz = 1000;
801 if (truncate && nnz<=max_nnz) truncate=
false;
804 for (casadi_int cc=0; cc<size2; ++cc) {
805 for (casadi_int el=colind[cc]; el<colind[cc+1]; ++el) {
806 if (truncate && el>=3 && el<nnz-3) {
807 if (el==3) stream << std::endl <<
" ...";
809 stream << std::endl <<
" (" << row[el] <<
", " << cc <<
") -> " << nz.at(el);
810 InterruptHandler::check();
814 stream << std::flush;
817 template<
typename Scalar>
819 const Scalar* nonzeros,
bool truncate) {
821 std::vector<std::string> nz, inter;
822 print_split(sp.nnz(), nonzeros, nz, inter);
825 for (casadi_int i=0; i<inter.size(); ++i)
826 stream <<
"@" << (i+1) <<
"=" << inter[i] <<
", ";
830 casadi_int size1 = sp.size1();
831 casadi_int size2 = sp.size2();
832 const casadi_int* colind = sp.colind();
833 const casadi_int* row = sp.row();
836 const casadi_int max_numel = 1000;
837 if (truncate && size1*size2<=max_numel) truncate=
false;
840 bool truncate_rows = truncate && size1>=7;
841 bool truncate_columns = truncate && size2>=7;
844 std::vector<casadi_int> ind(colind, colind+size2+1);
847 bool oneliner=size1<=1;
850 for (casadi_int rr=0; rr<size1; ++rr) {
852 bool print_row = !(truncate_rows && rr>=3 && rr<size1-3);
856 if (!oneliner) stream << std::endl;
858 }
else if (print_row) {
863 for (casadi_int cc=0; cc<size2; ++cc) {
865 std::string s = ind[cc]<colind[cc+1] && row[ind[cc]]==rr
866 ? nz.at(ind[cc]++) :
"00";
869 if (!print_row)
continue;
872 bool print_column = !(truncate_columns && cc>=3 && cc<size2-3);
876 if (cc!=0) stream <<
", ";
887 if (!oneliner) stream << std::endl;
889 stream <<
" ...," << std::endl;
895 stream << std::flush;
898 template<
typename Scalar>
900 to_file(filename, sparsity(), ptr(), format);
903 template<
typename Scalar>
905 print_default(stream, sparsity(), ptr());
908 template<
typename Scalar>
910 std::stringstream ss;
915 template<
typename Scalar>
917 reserve(nnz, size2());
920 template<
typename Scalar>
922 nonzeros().reserve(nnz);
925 template<
typename Scalar>
927 sparsity_.resize(nrow, ncol);
930 template<
typename Scalar>
936 template<
typename Scalar>
939 Sparsity::dense(1, 1)),
940 nonzeros_(std::vector<Scalar>(1, static_cast<Scalar>(val))) {
943 template<
typename Scalar>
944 Matrix<Scalar>::Matrix(
const std::vector< std::vector<double> >& d) {
946 casadi_int nrow=d.size();
947 casadi_int ncol=d.empty() ? 1 : d.front().size();
950 for (casadi_int rr=0; rr<nrow; ++rr) {
951 casadi_assert(ncol==d[rr].size(),
953 "Attempting to construct a matrix from a nested list.\n"
954 "I got convinced that the desired size is (" + str(nrow) +
" x " + str(ncol)
955 +
" ), but now I encounter a vector of size (" + str(d[rr].size()) +
" )");
959 sparsity_ = Sparsity::dense(nrow, ncol);
960 nonzeros().resize(nrow*ncol);
961 typename std::vector<Scalar>::iterator it=nonzeros_.begin();
962 for (casadi_int cc=0; cc<ncol; ++cc) {
963 for (casadi_int rr=0; rr<nrow; ++rr) {
964 *it++ =
static_cast<Scalar
>(d[rr][cc]);
969 template<
typename Scalar>
970 Matrix<Scalar>::Matrix(
const Sparsity& sp) : sparsity_(sp), nonzeros_(sp.nnz(), 1) {
973 template<
typename Scalar>
974 Matrix<Scalar>::Matrix(casadi_int nrow, casadi_int ncol) : sparsity_(nrow, ncol) {
977 template<
typename Scalar>
978 Matrix<Scalar>::Matrix(
const std::pair<casadi_int, casadi_int>& rc) : sparsity_(rc) {
981 template<
typename Scalar>
982 Matrix<Scalar>::Matrix(
const Sparsity& sp,
const Scalar& val,
bool dummy) :
983 sparsity_(sp), nonzeros_(sp.nnz(), val) {
986 template<
typename Scalar>
987 Matrix<Scalar>::Matrix(
const Sparsity& sp,
const std::vector<Scalar>& d,
bool dummy) :
988 sparsity_(sp), nonzeros_(d) {
989 casadi_assert(sp.nnz()==d.size(),
"Size mismatch.\n"
990 "You supplied a sparsity of " + sp.dim()
991 +
", but the supplied vector is of length " + str(d.size()));
994 template<
typename Scalar>
995 Matrix<Scalar>::Matrix(
const Sparsity& sp,
const Matrix<Scalar>& d) {
997 *
this = Matrix<Scalar>(sp, d.scalar(),
false);
998 }
else if (sp.nnz()==0) {
999 casadi_assert(d.nnz()==0,
1000 "You passed nonzeros (" + d.dim(
true) +
1001 ") to the constructor of a fully sparse matrix (" + sp.dim(
true) +
").");
1002 *
this = Matrix<Scalar>(sp);
1003 }
else if (d.is_column() || d.size1()==1) {
1004 casadi_assert_dev(sp.nnz()==d.numel());
1006 *
this = Matrix<Scalar>(sp, d.nonzeros(),
false);
1008 *
this = Matrix<Scalar>(sp, densify(d).nonzeros(),
false);
1011 casadi_error(
"Matrix(Sparsity, Matrix): Only allowed for scalars and vectors");
1015 template<
typename Scalar>
1016 Matrix<Scalar> Matrix<Scalar>::unary(casadi_int op,
const Matrix<Scalar> &x) {
1018 Matrix<Scalar> ret = Matrix<Scalar>::zeros(x.sparsity());
1021 std::vector<Scalar>& ret_data = ret.nonzeros();
1022 const std::vector<Scalar>& x_data = x.nonzeros();
1025 for (casadi_int el=0; el<x.nnz(); ++el) {
1026 casadi_math<Scalar>::fun(op, x_data[el], x_data[el], ret_data[el]);
1030 if (!x.is_dense() && !operation_checker<F0XChecker>(op)) {
1033 casadi_math<Scalar>::fun(op, 0, 0, fcn_0);
1034 if (!casadi_limits<Scalar>::is_zero(fcn_0)) {
1035 ret = densify(ret, fcn_0);
1042 template<
typename Scalar>
1043 Matrix<Scalar> Matrix<Scalar>::operator-()
const {
1044 return unary(OP_NEG, *
this);
1047 template<
typename Scalar>
1048 Matrix<Scalar> Matrix<Scalar>::operator+()
const {
1052 template<
typename Scalar>
1053 Matrix<Scalar> Matrix<Scalar>::mrdivide(
const Matrix<Scalar>& b,
1054 const Matrix<Scalar>& a) {
1055 if (a.is_scalar() || b.is_scalar())
return b/a;
1056 return solve(a.T(), b.T()).T();
1059 template<
typename Scalar>
1060 Matrix<Scalar> Matrix<Scalar>::mldivide(
const Matrix<Scalar>& a,
1061 const Matrix<Scalar>& b) {
1062 if (a.is_scalar() || b.is_scalar())
return b/a;
1066 template<
typename Scalar>
1067 Matrix<Scalar> Matrix<Scalar>::printme(
const Matrix<Scalar>& y)
const {
1068 return binary(OP_PRINTME, *
this, y);
1071 template<
typename Scalar>
1072 void Matrix<Scalar>::erase(
const std::vector<casadi_int>& rr,
1073 const std::vector<casadi_int>& cc,
bool ind1) {
1075 std::vector<casadi_int> mapping = sparsity_.erase(rr, cc, ind1);
1078 for (casadi_int k=0; k<mapping.size(); ++k)
1079 nonzeros()[k] = nonzeros()[mapping[k]];
1082 nonzeros().resize(mapping.size());
1085 template<
typename Scalar>
1086 void Matrix<Scalar>::erase(
const std::vector<casadi_int>& rr,
bool ind1) {
1088 std::vector<casadi_int> mapping = sparsity_.erase(rr, ind1);
1091 for (casadi_int k=0; k<mapping.size(); ++k)
1092 nonzeros()[k] = nonzeros()[mapping[k]];
1095 nonzeros().resize(mapping.size());
1098 template<
typename Scalar>
1099 void Matrix<Scalar>::remove(
const std::vector<casadi_int>& rr,
1100 const std::vector<casadi_int>& cc) {
1101 casadi_assert_bounded(rr, size1());
1102 casadi_assert_bounded(cc, size2());
1105 std::vector<casadi_int> rrc =
complement(rr, size1());
1106 std::vector<casadi_int> ccc =
complement(cc, size2());
1108 Matrix<Scalar> ret = (*this)(rrc, ccc);
1114 template<
typename Scalar>
1115 void Matrix<Scalar>::enlarge(casadi_int nrow, casadi_int ncol,
const std::vector<casadi_int>& rr,
1116 const std::vector<casadi_int>& cc,
bool ind1) {
1117 sparsity_.enlarge(nrow, ncol, rr, cc, ind1);
1120 template<
typename Scalar>
1121 const Sparsity& Matrix<Scalar>::sparsity()
const {
1125 template<
typename Scalar>
1126 std::vector<Scalar>& Matrix<Scalar>::nonzeros() {
1130 template<
typename Scalar>
1131 const std::vector<Scalar>& Matrix<Scalar>::nonzeros()
const {
1135 template<
typename Scalar>
1136 Scalar* Matrix<Scalar>::ptr() {
1137 return nonzeros_.empty() ? nullptr : &nonzeros_.front();
1140 template<
typename Scalar>
1141 const Scalar* Matrix<Scalar>::ptr()
const {
1142 return nonzeros_.empty() ? nullptr : &nonzeros_.front();
1145 template<
typename Scalar>
1146 Sparsity Matrix<Scalar>::get_sparsity()
const {
1150 template<
typename Scalar>
1151 Matrix<Scalar> Matrix<Scalar>::mtimes(
const Matrix<Scalar> &x,
const Matrix<Scalar> &y) {
1152 if (x.is_scalar() || y.is_scalar()) {
1156 Matrix<Scalar> z = Matrix<Scalar>::zeros(Sparsity::mtimes(x.sparsity(), y.sparsity()));
1157 return mac(x, y, z);
1161 template<
typename Scalar>
1162 Matrix<Scalar> Matrix<Scalar>::mac(
const Matrix<Scalar> &x,
1163 const Matrix<Scalar> &y,
1164 const Matrix<Scalar> &z) {
1165 if (x.is_scalar() || y.is_scalar()) {
1171 casadi_assert(x.size2()==y.size1(),
1172 "Matrix product with incompatible dimensions. Lhs is "
1173 + x.dim() +
" and rhs is " + y.dim() +
".");
1175 casadi_assert(y.size2()==z.size2(),
1176 "Matrix addition with incompatible dimensions. Lhs is "
1177 + mtimes(x, y).dim() +
" and rhs is " + z.dim() +
".");
1179 casadi_assert(x.size1()==z.size1(),
1180 "Matrix addition with incompatible dimensions. Lhs is "
1181 + mtimes(x, y).dim() +
" and rhs is " + z.dim() +
".");
1186 }
else if (y.is_eye()) {
1188 }
else if (x.is_zero() || y.is_zero()) {
1192 Matrix<Scalar> ret = z;
1193 std::vector<Scalar> work(x.size1());
1194 casadi_mtimes(x.ptr(), x.sparsity(), y.ptr(), y.sparsity(),
1195 ret.ptr(), ret.sparsity(), get_ptr(work),
false);
1200 template<
typename Scalar>
1201 Matrix<Scalar> Matrix<Scalar>::
1202 _bilin(
const Matrix<Scalar>& A,
const Matrix<Scalar>& x,
1203 const Matrix<Scalar>& y) {
1204 return casadi_bilin(A.ptr(), A.sparsity(), x.ptr(), y.ptr());
1207 template<
typename Scalar>
1208 Matrix<Scalar> Matrix<Scalar>::
1209 _rank1(
const Matrix<Scalar>& A,
const Matrix<Scalar>& alpha,
1210 const Matrix<Scalar>& x,
const Matrix<Scalar>& y) {
1211 Matrix<Scalar> ret = A;
1212 casadi_rank1(ret.ptr(), ret.sparsity(), *alpha.ptr(), x.ptr(), y.ptr());
1217 template<
typename Scalar>
1218 Matrix<Scalar> Matrix<Scalar>::
1219 _logsumexp(
const Matrix<Scalar>& x) {
1220 Matrix<Scalar> mx = mmax(x);
1221 return mx+log(sum1(exp(x-mx)));
1224 template<
typename Scalar>
1225 Matrix<Scalar> Matrix<Scalar>::T()
const {
1227 if ((size1()==0 && size2()==0) || is_scalar())
return *
this;
1230 std::vector<casadi_int> mapping;
1231 Sparsity s = sparsity().transpose(mapping);
1234 Matrix<Scalar> ret = zeros(s);
1237 for (casadi_int i=0; i<mapping.size(); ++i)
1238 ret->at(i) = nonzeros().at(mapping[i]);
1243 template<
typename Scalar>
1244 const Scalar Matrix<Scalar>::scalar()
const {
1246 casadi_assert(is_scalar(),
"Can only convert 1-by-1 matrices to scalars");
1250 return nonzeros()[0];
1252 return casadi_limits<Scalar>::zero;
1255 template<
typename Scalar>
1256 Matrix<Scalar> Matrix<Scalar>::binary(casadi_int op,
1257 const Matrix<Scalar> &x,
1258 const Matrix<Scalar> &y) {
1259 if (x.is_scalar()) {
1260 return scalar_matrix(op, x, y);
1261 }
else if (y.is_scalar()) {
1262 return matrix_scalar(op, x, y);
1264 return matrix_matrix(op, x, y);
1268 template<
typename Scalar>
1272 std::vector<Scalar> dep;
1273 for (
auto & e : x) {
1274 dep.insert(dep.end(), e.nonzeros().begin(), e.nonzeros().end());
1280 std::vector< Matrix<Scalar> > ret;
1281 ret.reserve(r.size());
1282 for (
auto & e : r) {
1290 template<
typename Scalar>
1291 std::vector<Scalar> Matrix<Scalar>::call(
const Function& f,
const std::vector< Scalar > &x) {
1292 casadi_error(
"'call' not defined for " + type_name());
1295 template<
typename Scalar>
1296 Matrix<Scalar> Matrix<Scalar>::
1297 scalar_matrix(casadi_int op,
const Matrix<Scalar> &x,
const Matrix<Scalar> &y) {
1298 if ( (operation_checker<FX0Checker>(op) && y.nnz()==0) ||
1299 (operation_checker<F0XChecker>(op) && x.nnz()==0))
1300 return Matrix<Scalar>::zeros(Sparsity(y.size()));
1303 Matrix<Scalar> ret = Matrix<Scalar>::zeros(y.sparsity());
1306 std::vector<Scalar>& ret_data = ret.nonzeros();
1307 const std::vector<Scalar>& x_data = x.nonzeros();
1308 const Scalar& x_val = x_data.empty() ? casadi_limits<Scalar>::zero : x->front();
1309 const std::vector<Scalar>& y_data = y.nonzeros();
1312 for (casadi_int el=0; el<y.nnz(); ++el) {
1313 casadi_math<Scalar>::fun(op, x_val, y_data[el], ret_data[el]);
1317 if (!y.is_dense() && !operation_checker<FX0Checker>(op)) {
1320 casadi_math<Scalar>::fun(op, x_val, casadi_limits<Scalar>::zero, fcn_0);
1321 if (!casadi_limits<Scalar>::is_zero(fcn_0)) {
1322 ret = densify(ret, fcn_0);
1329 template<
typename Scalar>
1330 Matrix<Scalar> Matrix<Scalar>::
1331 matrix_scalar(casadi_int op,
const Matrix<Scalar> &x,
const Matrix<Scalar> &y) {
1333 if ( (operation_checker<FX0Checker>(op) && y.nnz()==0) ||
1334 (operation_checker<F0XChecker>(op) && x.nnz()==0))
1335 return Matrix<Scalar>::zeros(Sparsity(x.size()));
1338 Matrix<Scalar> ret = Matrix<Scalar>::zeros(x.sparsity());
1341 std::vector<Scalar>& ret_data = ret.nonzeros();
1342 const std::vector<Scalar>& x_data = x.nonzeros();
1343 const std::vector<Scalar>& y_data = y.nonzeros();
1344 const Scalar& y_val = y_data.empty() ? casadi_limits<Scalar>::zero : y->front();
1347 for (casadi_int el=0; el<x.nnz(); ++el) {
1348 casadi_math<Scalar>::fun(op, x_data[el], y_val, ret_data[el]);
1352 if (!x.is_dense() && !operation_checker<F0XChecker>(op)) {
1355 casadi_math<Scalar>::fun(op, casadi_limits<Scalar>::zero, y_val, fcn_0);
1356 if (!casadi_limits<Scalar>::is_zero(fcn_0)) {
1357 ret = densify(ret, fcn_0);
1364 template<
typename Scalar>
1365 Matrix<Scalar> Matrix<Scalar>::
1366 matrix_matrix(casadi_int op,
const Matrix<Scalar> &x,
const Matrix<Scalar> &y) {
1368 if (x.size() != y.size()) {
1370 if (!x.is_empty() && !y.is_empty()) {
1371 if (x.size1() == y.size1() && x.size2() % y.size2() == 0) {
1372 return matrix_matrix(op, x, repmat(y, 1, x.size2() / y.size2()));
1373 }
else if (y.size1() == x.size1() && y.size2() % x.size2() == 0) {
1374 return matrix_matrix(op, repmat(x, 1, y.size2() / x.size2()), y);
1378 if (x.size1()==0 && y.size1()==0 && x.size2()>0 && y.size2()>0) {
1379 if (x.size2() % y.size2() == 0) {
1380 return Matrix<Scalar>(0, x.size2());
1381 }
else if (y.size2() % x.size2() == 0) {
1382 return Matrix<Scalar>(0, y.size2());
1386 casadi_error(
"Dimension mismatch for " + casadi_math<Scalar>::print(op,
"x",
"y") +
1387 ", x is " + x.dim() +
", while y is " + y.dim());
1392 const Sparsity& x_sp = x.sparsity();
1393 const Sparsity& y_sp = y.sparsity();
1394 Sparsity r_sp = x_sp.combine(y_sp, operation_checker<F0XChecker>(op),
1395 operation_checker<FX0Checker>(op));
1398 Matrix<Scalar> r = zeros(r_sp);
1403 casadi_math<Scalar>::fun(op, x.ptr(), y.ptr(), r.ptr(), r_sp.nnz());
1404 }
else if (y_sp==r_sp) {
1406 Matrix<Scalar> x_mod = x(r_sp);
1407 casadi_math<Scalar>::fun(op, x_mod.ptr(), y.ptr(), r.ptr(), r_sp.nnz());
1408 }
else if (x_sp==r_sp) {
1410 Matrix<Scalar> y_mod = y(r_sp);
1411 casadi_math<Scalar>::fun(op, x.ptr(), y_mod.ptr(), r.ptr(), r_sp.nnz());
1414 Matrix<Scalar> x_mod = x(r_sp);
1415 Matrix<Scalar> y_mod = y(r_sp);
1416 casadi_math<Scalar>::fun(op, x_mod.ptr(), y_mod.ptr(), r.ptr(), r_sp.nnz());
1420 if (!r.is_dense() && !operation_checker<F00Checker>(op)) {
1423 casadi_math<Scalar>::fun(op, casadi_limits<Scalar>::zero,
1424 casadi_limits<Scalar>::zero, fcn_0);
1425 r = densify(r, fcn_0);
1431 template<
typename Scalar>
1432 Matrix<Scalar> Matrix<Scalar>::triplet(
const std::vector<casadi_int>& row,
1433 const std::vector<casadi_int>& col,
1434 const Matrix<Scalar>& d) {
1435 return triplet(row, col, d, *std::max_element(row.begin(), row.end()),
1436 *std::max_element(col.begin(), col.end()));
1439 template<
typename Scalar>
1440 Matrix<Scalar> Matrix<Scalar>::triplet(
const std::vector<casadi_int>& row,
1441 const std::vector<casadi_int>& col,
1442 const Matrix<Scalar>& d,
1443 const std::pair<casadi_int, casadi_int>& rc) {
1444 return triplet(row, col, d, rc.first, rc.second);
1447 template<
typename Scalar>
1448 Matrix<Scalar> Matrix<Scalar>::triplet(
const std::vector<casadi_int>& row,
1449 const std::vector<casadi_int>& col,
1450 const Matrix<Scalar>& d,
1451 casadi_int nrow, casadi_int ncol) {
1452 casadi_assert(col.size()==row.size() && col.size()==d.nnz(),
1453 "Argument error in Matrix<Scalar>::triplet(row, col, d): "
1454 "supplied lists must all be of equal length, but got: "
1455 + str(row.size()) +
", " + str(col.size()) +
" and " + str(d.nnz()));
1456 std::vector<casadi_int> mapping;
1457 Sparsity sp = Sparsity::triplet(nrow, ncol, row, col, mapping,
false);
1458 return Matrix<Scalar>(sp, d.nz(mapping));
1461 template<
typename Scalar>
1462 Matrix<Scalar> Matrix<Scalar>::eye(casadi_int n) {
1463 return Matrix<Scalar>::ones(Sparsity::diag(n));
1466 template<
typename Scalar>
1467 Matrix<Scalar> Matrix<Scalar>::inf(
const Sparsity& sp) {
1468 casadi_assert(std::numeric_limits<Scalar>::has_infinity,
1469 "Datatype cannot represent infinity");
1470 return Matrix<Scalar>(sp, std::numeric_limits<Scalar>::infinity(),
false);
1474 template<
typename Scalar>
1475 Matrix<Scalar> Matrix<Scalar>::inf(
const std::pair<casadi_int, casadi_int>& rc) {
1476 return inf(rc.first, rc.second);
1479 template<
typename Scalar>
1480 Matrix<Scalar> Matrix<Scalar>::inf(casadi_int nrow, casadi_int ncol) {
1481 return inf(Sparsity::dense(nrow, ncol));
1484 template<
typename Scalar>
1485 Matrix<Scalar> Matrix<Scalar>::nan(
const Sparsity& sp) {
1486 casadi_assert(std::numeric_limits<Scalar>::has_quiet_NaN,
1487 "Datatype cannot represent not-a-number");
1488 return Matrix<Scalar>(sp, std::numeric_limits<Scalar>::quiet_NaN(),
false);
1491 template<
typename Scalar>
1492 Matrix<Scalar> Matrix<Scalar>::nan(
const std::pair<casadi_int, casadi_int>& rc) {
1493 return nan(rc.first, rc.second);
1496 template<
typename Scalar>
1497 Matrix<Scalar> Matrix<Scalar>::nan(casadi_int nrow, casadi_int ncol) {
1498 return nan(Sparsity::dense(nrow, ncol));
1501 template<
typename Scalar>
1502 bool Matrix<Scalar>::is_regular()
const {
1506 template<
typename Scalar>
1507 bool Matrix<Scalar>::is_smooth()
const {
1511 template<
typename Scalar>
1512 casadi_int Matrix<Scalar>::element_hash()
const {
1513 casadi_error(
"'element_hash' not defined for " + type_name());
1516 template<
typename Scalar>
1517 bool Matrix<Scalar>::is_leaf()
const {
1518 casadi_error(
"'is_leaf' not defined for " + type_name());
1521 template<
typename Scalar>
1522 bool Matrix<Scalar>::is_commutative()
const {
1523 casadi_error(
"'is_commutative' not defined for " + type_name());
1526 template<
typename Scalar>
1527 bool Matrix<Scalar>::is_symbolic()
const {
1531 template<
typename Scalar>
1532 casadi_int Matrix<Scalar>::op()
const {
1533 casadi_error(
"'op' not defined for " + type_name());
1536 template<
typename Scalar>
1537 bool Matrix<Scalar>::is_op(casadi_int k)
const {
1538 casadi_error(
"'is_op' not defined for " + type_name());
1541 template<
typename Scalar>
1542 void Matrix<Scalar>::export_code(
const std::string& lang,
1543 std::ostream &stream,
const Dict& options)
const {
1544 casadi_error(
"'export_code' not defined for " + type_name());
1547 template<
typename Scalar>
1548 bool Matrix<Scalar>::is_valid_input()
const {
1552 template<
typename Scalar>
1553 bool Matrix<Scalar>::has_duplicates()
const {
1554 casadi_error(
"'has_duplicates' not defined for " + type_name());
1557 template<
typename Scalar>
1558 void Matrix<Scalar>::reset_input()
const {
1559 casadi_error(
"'reset_input' not defined for " + type_name());
1562 template<
typename Scalar>
1563 Matrix<double> Matrix<Scalar>::from_file(
const std::string& filename,
1564 const std::string& format_hint) {
1565 casadi_error(
"'from_file' not defined for " + type_name());
1568 template<
typename Scalar>
1569 bool Matrix<Scalar>::is_integer()
const {
1571 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_integer(e))
return false;
1577 template<
typename Scalar>
1578 bool Matrix<Scalar>::is_constant()
const {
1580 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_constant(e))
return false;
1586 template<
typename Scalar>
1587 bool Matrix<Scalar>::is_call()
const {
1588 casadi_assert(is_scalar(),
"'is_call' only defined for scalar expressions");
1593 template<
typename Scalar>
1594 bool Matrix<Scalar>::is_output()
const {
1595 casadi_assert(is_scalar(),
"'is_output' only defined for scalar expressions");
1600 template<
typename Scalar>
1601 Matrix<Scalar> Matrix<Scalar>::get_output(casadi_int oind)
const {
1602 casadi_error(
"'get_output' not defined for " + type_name());
1605 template<
typename Scalar>
1606 bool Matrix<Scalar>::has_output()
const {
1607 casadi_assert(is_scalar(),
"'has_output' only defined for scalar expressions");
1612 template<
typename Scalar>
1613 Function Matrix<Scalar>::which_function()
const {
1614 casadi_error(
"'which_function' not defined for " + type_name());
1617 template<
typename Scalar>
1618 casadi_int Matrix<Scalar>::which_output()
const {
1619 casadi_error(
"'which_output' not defined for " + type_name());
1622 template<
typename Scalar>
1623 bool Matrix<Scalar>::is_one()
const {
1624 if (!is_dense())
return false;
1627 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_one(e))
return false;
1632 template<
typename Scalar>
1633 bool Matrix<Scalar>::is_minus_one()
const {
1634 if (!is_dense())
return false;
1637 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_minus_one(e))
return false;
1642 template<
typename Scalar>
1643 bool Matrix<Scalar>::is_zero()
const {
1646 for (
auto&& e : nonzeros())
if (!casadi_limits<Scalar>::is_zero(e))
return false;
1651 template<
typename Scalar>
1652 bool Matrix<Scalar>::is_eye()
const {
1655 if (!sparsity().is_diag())
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_equal(
const Matrix<Scalar> &x,
const Matrix<Scalar> &y,
1667 casadi_assert(x.size() == y.size(),
"Dimension mismatch");
1670 if (x.sparsity() != y.sparsity()) {
1671 Sparsity sp = x.sparsity() + y.sparsity();
1672 return is_equal(project(x, sp), project(y, sp), depth);
1676 auto y_it = y.nonzeros().begin();
1677 for (
auto&& e : x.nonzeros()) {
1678 if (!casadi_limits<Scalar>::is_equal(e, *y_it++, depth))
return false;
1686 template<
typename Scalar>
1687 inline Matrix<Scalar> mmin_nonstatic(
const Matrix<Scalar> &x) {
1688 if (x.is_empty())
return Matrix<Scalar>();
1689 return casadi_mmin(x.ptr(), x.nnz(), x.is_dense());
1692 template<
typename Scalar>
1693 Matrix<Scalar> Matrix<Scalar>::mmin(
const Matrix<Scalar> &x) {
1694 return mmin_nonstatic(x);
1698 template<
typename Scalar>
1699 inline Matrix<Scalar> mmax_nonstatic(
const Matrix<Scalar> &x) {
1700 if (x.is_empty())
return Matrix<Scalar>();
1701 return casadi_mmax(x.ptr(), x.nnz(), x.is_dense());
1704 template<
typename Scalar>
1705 Matrix<Scalar> Matrix<Scalar>::mmax(
const Matrix<Scalar> &x) {
1706 return mmax_nonstatic(x);
1709 template<
typename Scalar>
1710 bool Matrix<Scalar>::has_zeros()
const {
1712 for (
auto&& e : nonzeros())
if (casadi_limits<Scalar>::is_zero(e))
return true;
1718 template<
typename Scalar>
1719 std::vector<Scalar> Matrix<Scalar>::get_nonzeros()
const {
1723 template<
typename Scalar>
1724 std::vector<Scalar> Matrix<Scalar>::get_elements()
const {
1725 return static_cast< std::vector<Scalar>
>(*this);
1728 template<
typename Scalar>
1729 std::string Matrix<Scalar>::name()
const {
1730 casadi_error(
"'name' not defined for " + type_name());
1733 template<
typename Scalar>
1734 Matrix<Scalar> Matrix<Scalar>::dep(casadi_int ch)
const {
1735 casadi_error(
"'dep' not defined for " + type_name());
1738 template<
typename Scalar>
1739 casadi_int Matrix<Scalar>::n_dep()
const {
1740 casadi_error(
"'n_dep' not defined for " + type_name());
1743 template<
typename Scalar>
1744 Matrix<Scalar> Matrix<Scalar>::rand(
1747 return rand(Sparsity::dense(nrow, ncol));
1750 template<
typename Scalar>
1751 Matrix<Scalar> Matrix<Scalar>::rand(
1752 const std::pair<casadi_int, casadi_int>& rc) {
1753 return rand(rc.first, rc.second);
1756 template<
typename Scalar>
1757 Matrix<Scalar> Matrix<Scalar>::project(
const Matrix<Scalar>& x,
1758 const Sparsity& sp,
bool intersect) {
1760 return project(x, sp.intersect(x.sparsity()),
false);
1762 casadi_assert(sp.size()==x.size(),
"Dimension mismatch");
1763 Matrix<Scalar> ret = Matrix<Scalar>::zeros(sp);
1764 std::vector<Scalar> w(x.size1());
1765 casadi_project(x.ptr(), x.sparsity(), ret.ptr(), sp, get_ptr(w));
1770 template<
typename Scalar>
1771 void Matrix<Scalar>::set_max_depth(casadi_int eq_depth) {
1772 casadi_error(
"'set_max_depth' not defined for " + type_name());
1775 template<
typename Scalar>
1776 casadi_int Matrix<Scalar>::get_max_depth() {
1777 casadi_error(
"'get_max_depth' not defined for " + type_name());
1780 template<
typename Scalar>
1781 Matrix<Scalar> Matrix<Scalar>::det(
const Matrix<Scalar>& x) {
1782 casadi_int n = x.size2();
1783 casadi_assert(n == x.size1(),
"matrix must be square");
1786 if (x.is_scalar())
return x;
1789 if (n==2)
return x(0, 0) * x(1, 1) - x(0, 1) * x(1, 0);
1792 Matrix<Scalar> ret = 0;
1797 Matrix<casadi_int> sp = IM::ones(x.sparsity());
1800 Matrix<casadi_int> row_count = Matrix<casadi_int>::sum2(sp);
1803 if (!row_count.is_dense())
return 0;
1806 Matrix<casadi_int> col_count = Matrix<casadi_int>::sum1(sp).T();
1809 if (!row_count.is_dense())
return 0;
1811 casadi_int min_row = std::distance(row_count.nonzeros().begin(),
1812 std::min_element(row_count.nonzeros().begin(),
1813 row_count.nonzeros().end()));
1814 casadi_int min_col = std::distance(col_count.nonzeros().begin(),
1815 std::min_element(col_count.nonzeros().begin(),
1816 col_count.nonzeros().end()));
1818 if (min_row <= min_col) {
1820 casadi_int j = row_count.sparsity().row(min_row);
1822 Matrix<Scalar> row = x(j, Slice(0, n));
1824 std::vector< casadi_int > col_i = row.sparsity().get_col();
1826 for (casadi_int k=0; k<row.nnz(); ++k) {
1828 ret += row->at(k)*cofactor(x, col_i.at(k), j);
1833 casadi_int i = col_count.sparsity().row(min_col);
1835 Matrix<Scalar> col = x(Slice(0, n), i);
1837 const casadi_int* row_i = col.row();
1839 for (casadi_int k=0; k<col.nnz(); ++k) {
1841 ret += col->at(k)*cofactor(x, i, row_i[k]);
1848 template<
typename Scalar>
1849 Matrix<Scalar> Matrix<Scalar>::sum2(
const Matrix<Scalar>& x) {
1850 return mtimes(x, Matrix<Scalar>::ones(x.size2(), 1));
1853 template<
typename Scalar>
1854 Matrix<Scalar> Matrix<Scalar>::sum1(
const Matrix<Scalar>& x) {
1855 return mtimes(Matrix<Scalar>::ones(1, x.size1()), x);
1858 template<
typename Scalar>
1859 Matrix<Scalar> Matrix<Scalar>::minor(
const Matrix<Scalar>& x,
1860 casadi_int i, casadi_int j) {
1861 casadi_int n = x.size2();
1862 casadi_assert(n == x.size1(),
"minor: matrix must be square");
1868 Matrix<Scalar> M = Matrix<Scalar>(n-1, n-1);
1870 std::vector<casadi_int> col = x.sparsity().get_col();
1871 const casadi_int* row = x.sparsity().row();
1873 for (casadi_int k=0; k<x.nnz(); ++k) {
1874 casadi_int i1 = col[k];
1875 casadi_int j1 = row[k];
1877 if (i1 == i || j1 == j)
continue;
1879 casadi_int i2 = (i1<i)?i1:i1-1;
1880 casadi_int j2 = (j1<j)?j1:j1-1;
1882 M(j2, i2) = x(j1, i1);
1887 template<
typename Scalar>
1888 Matrix<Scalar> Matrix<Scalar>::cofactor(
const Matrix<Scalar>& A, casadi_int i, casadi_int j) {
1891 Matrix<Scalar> minor_ij = minor(A, i, j);
1893 casadi_int sign_i = 1-2*((i+j) % 2);
1895 return sign_i * minor_ij;
1898 template<
typename Scalar>
1899 Matrix<Scalar> Matrix<Scalar>::adj(
const Matrix<Scalar>& x) {
1900 casadi_int n = x.size2();
1901 casadi_assert(n == x.size1(),
"adj: matrix must be square");
1904 Matrix<Scalar> temp;
1907 Matrix<Scalar>
C = Matrix<Scalar>(n, n);
1908 for (casadi_int i=0; i<n; ++i)
1909 for (casadi_int j=0; j<n; ++j) {
1910 temp = cofactor(x, i, j);
1911 if (!temp.is_zero())
C(j, i) = temp;
1917 template<
typename Scalar>
1918 Matrix<Scalar> Matrix<Scalar>::inv_minor(
const Matrix<Scalar>& x) {
1920 return adj(x)/det(x);
1923 template<
typename Scalar>
1924 Matrix<Scalar> Matrix<Scalar>::reshape(
const Matrix<Scalar>& x,
1925 casadi_int nrow, casadi_int ncol) {
1926 Sparsity sp = Sparsity::reshape(x.sparsity(), nrow, ncol);
1927 return Matrix<Scalar>(sp, x.nonzeros(),
false);
1930 template<
typename Scalar>
1931 Matrix<Scalar> Matrix<Scalar>::reshape(
const Matrix<Scalar>& x,
const Sparsity& sp) {
1933 if (sp==x.sparsity())
return x;
1936 casadi_assert_dev(sp.is_reshape(x.sparsity()));
1938 return Matrix<Scalar>(sp, x.nonzeros(),
false);
1941 template<
typename Scalar>
1942 Matrix<Scalar> Matrix<Scalar>::sparsity_cast(
const Matrix<Scalar>& x,
const Sparsity& sp) {
1944 if (sp==x.sparsity())
return x;
1946 casadi_assert_dev(sp.nnz()==x.nnz());
1948 return Matrix<Scalar>(sp, x.nonzeros(),
false);
1951 template<
typename Scalar>
1952 Matrix<Scalar> Matrix<Scalar>::trace(
const Matrix<Scalar>& x) {
1953 casadi_assert(x.is_square(),
"trace: must be square");
1955 const Scalar* d=x.ptr();
1956 casadi_int size2 = x.size2();
1957 const casadi_int *colind=x.colind(), *row=x.row();
1958 for (casadi_int c=0; c<size2; c++) {
1959 for (casadi_int k=colind[c]; k!=colind[c+1]; ++k) {
1968 template<
typename Scalar>
1970 Matrix<Scalar>::blockcat(
const std::vector< std::vector<Matrix<Scalar> > > &v) {
1971 std::vector< Matrix<Scalar> > ret;
1972 for (casadi_int i=0; i<v.size(); ++i)
1973 ret.push_back(horzcat(v[i]));
1974 return vertcat(ret);
1977 template<
typename Scalar>
1978 Matrix<Scalar> Matrix<Scalar>::horzcat(
const std::vector<Matrix<Scalar> > &v) {
1980 std::vector<Sparsity> sp(v.size());
1981 for (casadi_int i=0; i<v.size(); ++i) sp[i] = v[i].sparsity();
1982 Matrix<Scalar> ret = zeros(Sparsity::horzcat(sp));
1985 auto i=ret->begin();
1986 for (
auto&& j : v) {
1987 std::copy(j->begin(), j->end(), i);
1993 template<
typename Scalar>
1994 std::vector<Matrix<Scalar> >
1995 Matrix<Scalar>::horzsplit(
const Matrix<Scalar>& x,
const std::vector<casadi_int>& offset) {
1997 std::vector<Sparsity> sp = Sparsity::horzsplit(x.sparsity(), offset);
2000 std::vector<Matrix<Scalar> > ret;
2001 ret.reserve(sp.size());
2004 auto i=x.nonzeros().begin();
2005 for (
auto&& j : sp) {
2006 auto i_next = i + j.nnz();
2007 ret.push_back(Matrix<Scalar>(j, std::vector<Scalar>(i, i_next),
false));
2012 casadi_assert_dev(i==x.nonzeros().end());
2016 template<
typename Scalar>
2017 Matrix<Scalar> Matrix<Scalar>::vertcat(
const std::vector<Matrix<Scalar> > &v) {
2018 std::vector<Matrix<Scalar> > vT(v.size());
2019 for (casadi_int i=0; i<v.size(); ++i) vT[i] = v[i].
T();
2020 return horzcat(vT).T();
2023 template<
typename Scalar>
2024 std::vector< Matrix<Scalar> >
2025 Matrix<Scalar>::vertsplit(
const Matrix<Scalar>& x,
const std::vector<casadi_int>& offset) {
2026 std::vector< Matrix<Scalar> > ret = horzsplit(x.T(), offset);
2027 for (
auto&& e : ret) e = e.T();
2031 template<
typename Scalar>
2032 std::vector< Matrix<Scalar> >
2033 Matrix<Scalar>::diagsplit(
const Matrix<Scalar>& x,
const std::vector<casadi_int>& offset1,
2034 const std::vector<casadi_int>& offset2) {
2036 casadi_assert_dev(!offset1.empty());
2037 casadi_assert_dev(offset1.front()==0);
2038 casadi_assert_dev(offset1.back()==x.size1());
2042 casadi_assert_dev(!offset2.empty());
2043 casadi_assert_dev(offset2.front()==0);
2044 casadi_assert_dev(offset2.back()==x.size2());
2048 casadi_int n = offset1.size()-1;
2051 std::vector< Matrix<Scalar> > ret;
2054 for (casadi_int i=0; i<n; ++i) {
2055 ret.push_back(x(Slice(offset1[i], offset1[i+1]), Slice(offset2[i], offset2[i+1])));
2061 template<
typename Scalar>
2062 Matrix<Scalar> Matrix<Scalar>::dot(
const Matrix<Scalar> &x,
2063 const Matrix<Scalar> &y) {
2064 casadi_assert(x.size()==y.size(),
"dot: Dimension mismatch");
2065 if (x.sparsity()!=y.sparsity()) {
2066 Sparsity sp = x.sparsity() * y.sparsity();
2067 return dot(project(x, sp), project(y, sp));
2069 return casadi_dot(x.nnz(), x.ptr(), y.ptr());
2072 template<
typename Scalar>
2073 Matrix<Scalar> Matrix<Scalar>::all(
const Matrix<Scalar>& x) {
2074 if (!x.is_dense())
return false;
2076 for (casadi_int i=0; i<x.nnz(); ++i) {
2077 ret = ret && x->at(i)==1;
2082 template<
typename Scalar>
2083 Matrix<Scalar> Matrix<Scalar>::any(
const Matrix<Scalar>& x) {
2084 if (!x.is_dense())
return false;
2086 for (casadi_int i=0; i<x.nnz(); ++i) {
2087 ret = ret || x->at(i)==1;
2092 template<
typename Scalar>
2093 Matrix<Scalar> Matrix<Scalar>::norm_1(
const Matrix<Scalar>& x) {
2094 return casadi_norm_1(x.nnz(), x.ptr());
2097 template<
typename Scalar>
2098 Matrix<Scalar> Matrix<Scalar>::norm_2(
const Matrix<Scalar>& x) {
2099 if (x.is_vector()) {
2102 casadi_error(
"2-norms currently only supported for vectors. "
2103 "Did you intend to calculate a Frobenius norms (norm_fro)?");
2107 template<
typename Scalar>
2108 Matrix<Scalar> Matrix<Scalar>::norm_fro(
const Matrix<Scalar>& x) {
2109 return casadi_norm_2(x.nnz(), x.ptr());
2112 template<
typename Scalar>
2113 Matrix<Scalar> Matrix<Scalar>::norm_inf(
const Matrix<Scalar>& x) {
2115 Matrix<Scalar> s = 0;
2116 for (
auto i=x.nonzeros().begin(); i!=x.nonzeros().end(); ++i) {
2117 s = fmax(s, fabs(Matrix<Scalar>(*i)));
2122 template<
typename Scalar>
2123 void Matrix<Scalar>::
2124 qr_sparse(
const Matrix<Scalar>& A,
2125 Matrix<Scalar>& V, Matrix<Scalar> &R, Matrix<Scalar>& beta,
2126 std::vector<casadi_int>& prinv, std::vector<casadi_int>& pc,
bool amd) {
2129 A.sparsity().qr_sparse(spV, spR, prinv, pc, amd);
2131 casadi_int nrow_ext = spV.size1(), ncol = spV.size2();
2134 beta = nan(ncol, 1);
2135 std::vector<Scalar> w(nrow_ext);
2136 casadi_qr(A.sparsity(), A.ptr(), get_ptr(w), spV, V.ptr(),
2137 spR, R.ptr(), beta.ptr(),
2138 get_ptr(prinv), get_ptr(pc));
2141 template<
typename Scalar>
2142 Matrix<Scalar> Matrix<Scalar>::
2143 qr_solve(
const Matrix<Scalar>& b,
const Matrix<Scalar>& v,
2144 const Matrix<Scalar>& r,
const Matrix<Scalar>& beta,
2145 const std::vector<casadi_int>& prinv,
const std::vector<casadi_int>& pc,
2148 casadi_int ncol = v.size2();
2149 casadi_int nrow = b.size1(), nrhs = b.size2();
2150 casadi_assert(r.size()==v.size(),
"'r', 'v' dimension mismatch");
2151 casadi_assert(beta.is_vector() && beta.numel()==ncol,
"'beta' has wrong dimension");
2152 casadi_assert(prinv.size()==r.size1(),
"'pinv' has wrong dimension");
2154 std::vector<Scalar> w(nrow+ncol);
2156 Matrix<Scalar> x = densify(b);
2157 casadi_qr_solve(x.ptr(), nrhs, tr, v.sparsity(), v.ptr(), r.sparsity(), r.ptr(),
2158 beta.ptr(), get_ptr(prinv), get_ptr(pc), get_ptr(w));
2162 template<
typename Scalar>
2163 void Matrix<Scalar>::qr(
const Matrix<Scalar>& A,
2164 Matrix<Scalar>& Q, Matrix<Scalar> &R) {
2167 casadi_assert(A.size1()>=A.size2(),
"qr: fewer rows than columns");
2170 Q = R = Matrix<Scalar>();
2171 for (casadi_int i=0; i<A.size2(); ++i) {
2173 Matrix<Scalar> ai = A(Slice(), i);
2174 Matrix<Scalar> qi = ai;
2176 Matrix<Scalar> ri = Matrix<Scalar>(A.size2(), 1);
2179 for (casadi_int j=0; j<i; ++j) {
2182 Matrix<Scalar> qj =
Q(Slice(), j);
2184 ri(j, 0) = mtimes(qi.T(), qj);
2188 if (ri.has_nz(j, 0))
2189 qi -= ri(j, 0) * qj;
2193 ri(i, 0) = norm_2(qi);
2197 Q = Matrix<Scalar>::horzcat({
Q, qi});
2198 R = Matrix<Scalar>::horzcat({R, ri});
2202 template<
typename Scalar>
2203 void Matrix<Scalar>::ldl(
const Matrix<Scalar>& A, Matrix<Scalar> &D,
2204 Matrix<Scalar>& LT, std::vector<casadi_int>& p,
bool amd) {
2206 Sparsity Lt_sp = A.sparsity().ldl(p, amd);
2209 casadi_int n=A.size1();
2212 std::vector<Scalar> D_nz(n), L_nz(Lt_sp.nnz()), w(n);
2213 casadi_ldl(A.sparsity(), get_ptr(A.nonzeros()), Lt_sp,
2214 get_ptr(L_nz), get_ptr(D_nz), get_ptr(p), get_ptr(w));
2217 LT = Matrix<Scalar>(Lt_sp, L_nz);
2221 template<
typename Scalar>
2222 Matrix<Scalar> Matrix<Scalar>::
2223 ldl_solve(
const Matrix<Scalar>& b,
const Matrix<Scalar>& D,
const Matrix<Scalar>& LT,
2224 const std::vector<casadi_int>& p) {
2226 casadi_int n = b.size1(), nrhs = b.size2();
2227 casadi_assert(p.size()==n,
"'p' has wrong dimension");
2228 casadi_assert(LT.size1()==n && LT.size2()==n,
"'LT' has wrong dimension");
2229 casadi_assert(
D.is_vector() &&
D.numel()==n,
"'D' has wrong dimension");
2231 Matrix<Scalar> x = densify(b);
2232 std::vector<Scalar> w(n);
2233 casadi_ldl_solve(x.ptr(), nrhs, LT.sparsity(), LT.ptr(),
D.ptr(), get_ptr(p), get_ptr(w));
2237 template<
typename Scalar>
2238 Matrix<Scalar> Matrix<Scalar>::nullspace(
const Matrix<Scalar>& A) {
2239 Matrix<Scalar>
X = A;
2240 casadi_int n =
X.size1();
2241 casadi_int m =
X.size2();
2242 casadi_assert(m>=n,
"nullspace(): expecting a flat matrix (more columns than rows), "
2243 "but got " + str(
X.dim()) +
".");
2245 Matrix<Scalar> seed = DM::eye(m)(Slice(0, m), Slice(n, m));
2247 std::vector< Matrix<Scalar> > us;
2248 std::vector< Matrix<Scalar> > betas;
2250 Matrix<Scalar> beta;
2252 for (casadi_int i=0;i<n;++i) {
2253 Matrix<Scalar> x =
X(i, Slice(i, m));
2254 Matrix<Scalar> u = Matrix<Scalar>(x);
2255 Matrix<Scalar> sigma = sqrt(sum2(x*x));
2256 const Matrix<Scalar>& x0 = x(0, 0);
2259 Matrix<Scalar> b = -copysign(sigma, x0);
2261 u(Slice(0), Slice(1, m-i))*= 1/(x0-b);
2264 X(Slice(i, n), Slice(i, m)) -=
2265 beta*mtimes(mtimes(
X(Slice(i, n), Slice(i, m)), u.T()), u);
2267 betas.push_back(beta);
2270 for (casadi_int i=n-1;i>=0;--i) {
2271 seed(Slice(i, m), Slice(0, m-n)) -=
2272 betas[i]*mtimes(us[i].
T(), mtimes(us[i], seed(Slice(i, m), Slice(0, m-n))));
2279 template<
typename Scalar>
2280 Matrix<Scalar> Matrix<Scalar>::chol(
const Matrix<Scalar>& A) {
2282 Matrix<Scalar>
D, LT;
2283 std::vector<casadi_int> p;
2284 ldl(A, D, LT, p,
false);
2286 LT += Matrix<Scalar>::eye(
D.size1());
2288 return mtimes(diag(sqrt(D)), LT);
2291 template<
typename Scalar>
2292 Matrix<Scalar> Matrix<Scalar>::solve(
const Matrix<Scalar>& a,
const Matrix<Scalar>& b) {
2294 casadi_assert(a.size1() == b.size1(),
"solve Ax=b: dimension mismatch: b has "
2295 + str(b.size1()) +
" rows while A has " + str(a.size1()) +
".");
2296 casadi_assert(a.size1() == a.size2(),
"solve: A not square but " + str(a.dim()));
2300 Matrix<Scalar> x = b;
2301 const casadi_int* Arow = a.row();
2302 const casadi_int* Acolind = a.colind();
2303 const std::vector<Scalar> & Adata = a.nonzeros();
2304 for (casadi_int i=0; i<a.size2(); ++i) {
2305 for (casadi_int k=0; k<b.size2(); ++k) {
2306 if (!x.has_nz(i, k))
continue;
2308 for (casadi_int kk=Acolind[i+1]-1; kk>=Acolind[i] && Arow[kk]>i; --kk) {
2309 casadi_int j = Arow[kk];
2310 x(j, k) -= Adata[kk]*x(i, k);
2315 }
else if (a.is_triu()) {
2317 Matrix<Scalar> x = b;
2318 const casadi_int* Arow = a.row();
2319 const casadi_int* Acolind = a.colind();
2320 const std::vector<Scalar> & Adata = a.nonzeros();
2321 for (casadi_int i=a.size2()-1; i>=0; --i) {
2322 for (casadi_int k=0; k<b.size2(); ++k) {
2323 if (!x.has_nz(i, k))
continue;
2325 for (casadi_int kk=Acolind[i]; kk<Acolind[i+1] && Arow[kk]<i; ++kk) {
2326 casadi_int j = Arow[kk];
2327 x(j, k) -= Adata[kk]*x(i, k);
2332 }
else if (a.has_zeros()) {
2336 return solve(sparsify(a), b);
2341 std::vector<casadi_int> rowperm, colperm, rowblock, colblock;
2342 std::vector<casadi_int> coarse_rowblock, coarse_colblock;
2343 a.sparsity().btf(rowperm, colperm, rowblock, colblock,
2344 coarse_rowblock, coarse_colblock);
2347 Matrix<Scalar> bperm = b(rowperm, Slice());
2350 Matrix<Scalar> Aperm = a(rowperm, colperm);
2353 Matrix<Scalar> xperm;
2356 if (Aperm.is_tril()) {
2359 xperm = solve(Aperm, bperm);
2361 }
else if (a.size2()<=3) {
2364 xperm = mtimes(inv_minor(Aperm), bperm);
2369 Matrix<Scalar>
Q, R;
2373 xperm = solve(R, mtimes(
Q.T(), bperm));
2377 std::vector<casadi_int> inv_colperm(colperm.size());
2378 for (casadi_int k=0; k<colperm.size(); ++k)
2379 inv_colperm[colperm[k]] = k;
2382 Matrix<Scalar> x = xperm(inv_colperm, Slice());
2387 template<
typename Scalar>
2388 Matrix<Scalar> Matrix<Scalar>::
2389 solve(
const Matrix<Scalar>& a,
const Matrix<Scalar>& b,
2390 const std::string& lsolver,
const Dict& dict) {
2391 casadi_error(
"'solve' with plugin not defined for " + type_name());
2392 return Matrix<Scalar>();
2395 template<
typename Scalar>
2396 Matrix<Scalar> Matrix<Scalar>::
2397 inv(
const Matrix<Scalar>& a) {
2398 return solve(a, Matrix<Scalar>::eye(a.size1()));
2401 template<
typename Scalar>
2402 Matrix<Scalar> Matrix<Scalar>::
2403 inv(
const Matrix<Scalar>& a,
2404 const std::string& lsolver,
const Dict& dict) {
2405 casadi_error(
"'inv' with plugin not defined for " + type_name());
2406 return Matrix<Scalar>();
2409 template<
typename Scalar>
2410 Matrix<Scalar> Matrix<Scalar>::pinv(
const Matrix<Scalar>& A) {
2411 if (A.size2()>=A.size1()) {
2412 return solve(mtimes(A, A.T()), A).T();
2414 return solve(mtimes(A.T(), A), A.T());
2418 template<
typename Scalar>
2419 Matrix<Scalar> Matrix<Scalar>::
2420 pinv(
const Matrix<Scalar>& A,
const std::string& lsolver,
const Dict& dict) {
2421 casadi_error(
"'solve' not defined for " + type_name());
2422 return Matrix<Scalar>();
2425 template<
typename Scalar>
2426 Matrix<Scalar> Matrix<Scalar>::
2427 expm_const(
const Matrix<Scalar>& A,
const Matrix<Scalar>& t) {
2428 casadi_error(
"'solve' not defined for " + type_name());
2429 return Matrix<Scalar>();
2432 template<
typename Scalar>
2433 Matrix<Scalar> Matrix<Scalar>::
2434 expm(
const Matrix<Scalar>& A) {
2435 casadi_error(
"'solve' not defined for " + type_name());
2436 return Matrix<Scalar>();
2439 template<
typename Scalar>
2440 Matrix<Scalar> Matrix<Scalar>::kron(
const Matrix<Scalar>& a,
const Matrix<Scalar>& b) {
2441 std::vector<Scalar> ret(a.nnz()*b.nnz());
2442 casadi_kron(get_ptr(a), a.sparsity(), get_ptr(b), b.sparsity(), get_ptr(ret));
2444 Sparsity sp_ret = Sparsity::kron(a.sparsity(), b.sparsity());
2445 return Matrix<Scalar>(sp_ret, ret,
false);
2448 template<
typename Scalar>
2449 Matrix<Scalar> Matrix<Scalar>::diag(
const Matrix<Scalar>& A) {
2451 std::vector<casadi_int> mapping;
2453 Sparsity sp = A.sparsity().get_diag(mapping);
2455 Matrix<Scalar> ret = zeros(sp);
2457 for (casadi_int k=0; k<mapping.size(); k++) ret.nz(k) = A.nz(mapping[k]);
2464 template<
typename Scalar>
2465 Matrix<Scalar> Matrix<Scalar>::diagcat(
const std::vector< Matrix<Scalar> > &A) {
2466 std::vector<Scalar> data;
2468 std::vector<Sparsity> sp;
2469 for (casadi_int i=0;i<A.size();++i) {
2470 data.insert(data.end(), A[i].nonzeros().begin(), A[i].nonzeros().end());
2471 sp.push_back(A[i].sparsity());
2474 return Matrix<Scalar>(Sparsity::diagcat(sp), data,
false);
2477 template<
typename Scalar>
2478 Matrix<Scalar> Matrix<Scalar>::unite(
const Matrix<Scalar>& A,
const Matrix<Scalar>& B) {
2480 std::vector<unsigned char> mapping;
2481 Sparsity sp = A.sparsity().unite(B.sparsity(), mapping);
2484 Matrix<Scalar> ret = zeros(sp);
2487 casadi_int elA=0, elB=0;
2488 for (casadi_int k=0; k<mapping.size(); ++k) {
2489 if (mapping[k]==1) {
2490 ret.nonzeros()[k] = A.nonzeros()[elA++];
2491 }
else if (mapping[k]==2) {
2492 ret.nonzeros()[k] = B.nonzeros()[elB++];
2494 casadi_error(
"Pattern intersection not empty");
2498 casadi_assert_dev(A.nnz()==elA);
2499 casadi_assert_dev(B.nnz()==elB);
2504 template<
typename Scalar>
2505 Matrix<Scalar> Matrix<Scalar>::polyval(
const Matrix<Scalar>& p,
const Matrix<Scalar>& x) {
2506 casadi_assert(p.is_dense(),
"polynomial coefficients vector must be dense");
2507 casadi_assert(p.is_vector() && p.nnz()>0,
"polynomial coefficients must be a vector");
2508 Matrix<Scalar> ret = x;
2509 for (
auto&& e : ret.nonzeros()) {
2510 e = casadi_polyval(p.ptr(), p.numel()-1, e);
2515 template<
typename Scalar>
2516 Matrix<Scalar> Matrix<Scalar>::norm_inf_mul(
const Matrix<Scalar>& x,
2517 const Matrix<Scalar>& y) {
2518 casadi_assert(y.size1()==x.size2(),
"Dimension error. Got " + x.dim()
2519 +
" times " + y.dim() +
".");
2522 std::vector<Scalar> dwork(x.size1());
2523 std::vector<casadi_int> iwork(x.size1()+1+y.size2());
2526 return casadi_norm_inf_mul(x.ptr(), x.sparsity(), y.ptr(), y.sparsity(),
2527 get_ptr(dwork), get_ptr(iwork));
2530 template<
typename Scalar>
2531 void Matrix<Scalar>::expand(
const Matrix<Scalar>& ex,
2532 Matrix<Scalar> &weights, Matrix<Scalar>& terms) {
2533 casadi_error(
"'expand' not defined for " + type_name());
2536 template<
typename Scalar>
2537 Matrix<Scalar> Matrix<Scalar>::pw_const(
const Matrix<Scalar>& ex,
2538 const Matrix<Scalar>& tval,
2539 const Matrix<Scalar>& val) {
2540 casadi_error(
"'pw_const' not defined for " + type_name());
2541 return Matrix<Scalar>();
2544 template<
typename Scalar>
2545 Matrix<Scalar> Matrix<Scalar>::pw_lin(
const Matrix<Scalar>& ex,
2546 const Matrix<Scalar>& tval,
2547 const Matrix<Scalar>& val) {
2548 casadi_error(
"'pw_lin' not defined for " + type_name());
2549 return Matrix<Scalar>();
2552 template<
typename Scalar>
2553 Matrix<Scalar> Matrix<Scalar>::if_else(
const Matrix<Scalar> &cond,
2554 const Matrix<Scalar> &if_true,
2555 const Matrix<Scalar> &if_false,
2556 bool short_circuit) {
2557 return if_else_zero(cond, if_true) + if_else_zero(!cond, if_false);
2560 template<
typename Scalar>
2561 Matrix<Scalar> Matrix<Scalar>::conditional(
const Matrix<Scalar>& ind,
2562 const std::vector<Matrix<Scalar> >& x,
2563 const Matrix<Scalar>& x_default,
2564 bool short_circuit) {
2565 casadi_assert(!short_circuit,
2566 "Short-circuiting 'conditional' not supported for " + type_name());
2567 casadi_assert(ind.is_scalar(
true),
2568 "conditional: first argument must be scalar. Got " + ind.dim()+
" instead.");
2570 Matrix<Scalar> ret = x_default;
2571 for (casadi_int k=0; k<x.size(); ++k) {
2572 ret = if_else(ind==k, x[k], ret, short_circuit);
2577 template<
typename Scalar>
2578 Matrix<Scalar> Matrix<Scalar>::heaviside(
const Matrix<Scalar>& x) {
2579 return (1+sign(x))/2;
2582 template<
typename Scalar>
2583 Matrix<Scalar> Matrix<Scalar>::rectangle(
const Matrix<Scalar>& x) {
2584 return 0.5*(sign(x+0.5)-sign(x-0.5));
2587 template<
typename Scalar>
2588 Matrix<Scalar> Matrix<Scalar>::triangle(
const Matrix<Scalar>& x) {
2589 return rectangle(x/2)*(1-fabs(x));
2592 template<
typename Scalar>
2593 Matrix<Scalar> Matrix<Scalar>::ramp(
const Matrix<Scalar>& x) {
2594 return x*heaviside(x);
2597 template<
typename Scalar>
2598 Matrix<Scalar> Matrix<Scalar>::
2599 gauss_quadrature(
const Matrix<Scalar> &f,
2600 const Matrix<Scalar> &x,
const Matrix<Scalar> &a,
2601 const Matrix<Scalar> &b, casadi_int order) {
2602 return gauss_quadrature(f, x, a, b, order, Matrix<Scalar>());
2605 template<
typename Scalar>
2606 Matrix<Scalar> Matrix<Scalar>::gauss_quadrature(
const Matrix<Scalar>& f,
2607 const Matrix<Scalar>& x,
2608 const Matrix<Scalar>& a,
2609 const Matrix<Scalar>& b, casadi_int order,
2610 const Matrix<Scalar>& w) {
2611 casadi_error(
"'gauss_quadrature' not defined for " + type_name());
2612 return Matrix<Scalar>();
2615 template<
typename Scalar>
2616 Matrix<Scalar> Matrix<Scalar>::simplify(
const Matrix<Scalar> &x) {
2620 template<
typename Scalar>
2621 Matrix<Scalar> Matrix<Scalar>::substitute(
const Matrix<Scalar>& ex,
2622 const Matrix<Scalar>& v,
2623 const Matrix<Scalar>& vdef) {
2624 casadi_error(
"'substitute' not defined for " + type_name());
2625 return Matrix<Scalar>();
2628 template<
typename Scalar>
2629 std::vector<Matrix<Scalar> >
2630 Matrix<Scalar>::substitute(
const std::vector<Matrix<Scalar> >& ex,
2631 const std::vector<Matrix<Scalar> >& v,
2632 const std::vector<Matrix<Scalar> >& vdef) {
2633 casadi_error(
"'substitute' not defined for " + type_name());
2634 return std::vector<Matrix<Scalar> >();
2637 template<
typename Scalar>
2638 void Matrix<Scalar>::substitute_inplace(
const std::vector<Matrix<Scalar> >& v,
2639 std::vector<Matrix<Scalar> >& vdef,
2640 std::vector<Matrix<Scalar> >& ex,
2642 casadi_error(
"'substitute_inplace' not defined for " + type_name());
2645 template<
typename Scalar>
2646 void Matrix<Scalar>::extract_parametric(
const Matrix<Scalar> &expr,
2647 const Matrix<Scalar>& par,
2648 Matrix<Scalar>& expr_ret,
2649 std::vector<Matrix<Scalar> >& symbols,
2650 std::vector< Matrix<Scalar> >& parametric,
2652 casadi_error(
"'extract_parametric' not defined for " + type_name());
2655 template<
typename Scalar>
2656 void Matrix<Scalar>::separate_linear(
const Matrix<Scalar> &expr,
2657 const Matrix<Scalar> &sym_lin,
const Matrix<Scalar> &sym_const,
2658 Matrix<Scalar>& expr_const, Matrix<Scalar>& expr_lin, Matrix<Scalar>& expr_nonlin) {
2659 casadi_error(
"'separate_linear' not defined for " + type_name());
2662 template<
typename Scalar>
2663 bool Matrix<Scalar>::depends_on(
const Matrix<Scalar> &x,
const Matrix<Scalar> &arg) {
2664 casadi_error(
"'depends_on' not defined for " + type_name());
2668 template<
typename Scalar>
2669 bool Matrix<Scalar>::contains_all(
const std::vector <Matrix<Scalar> >& v,
2670 const std::vector <Matrix<Scalar> > &n) {
2671 casadi_error(
"'contains_all' not defined for " + type_name());
2675 template<
typename Scalar>
2676 bool Matrix<Scalar>::contains_any(
const std::vector<Matrix<Scalar> >& v,
2677 const std::vector <Matrix<Scalar> > &n) {
2678 casadi_error(
"'contains_any' not defined for " + type_name());
2682 template<
typename Scalar>
2683 std::vector< Matrix<Scalar> > Matrix<Scalar>::cse(
const std::vector< Matrix<Scalar> >& e) {
2684 casadi_error(
"'cse' not defined for " + type_name());
2689 template<
typename Scalar>
2690 Matrix<Scalar> Matrix<Scalar>::
2691 jacobian(
const Matrix<Scalar> &f,
const Matrix<Scalar> &x,
const Dict& opts) {
2692 casadi_error(
"'jacobian' not defined for " + type_name());
2693 return Matrix<Scalar>();
2696 template<
typename Scalar>
2697 Matrix<Scalar> Matrix<Scalar>::hessian(
const Matrix<Scalar> &f,
2698 const Matrix<Scalar> &x,
2700 casadi_error(
"'hessian' not defined for " + type_name());
2701 return Matrix<Scalar>();
2704 template<
typename Scalar>
2705 Matrix<Scalar> Matrix<Scalar>::hessian(
const Matrix<Scalar> &f,
2706 const Matrix<Scalar> &x,
2709 casadi_error(
"'hessian' not defined for " + type_name());
2710 return Matrix<Scalar>();
2713 template<
typename Scalar>
2714 std::vector<std::vector<Matrix<Scalar> > >
2716 forward(
const std::vector<Matrix<Scalar> > &ex,
2717 const std::vector<Matrix<Scalar> > &arg,
2718 const std::vector<std::vector<Matrix<Scalar> > > &v,
2720 casadi_error(
"'forward' not defined for " + type_name());
2723 template<
typename Scalar>
2724 std::vector<std::vector<Matrix<Scalar> > >
2726 reverse(
const std::vector<Matrix<Scalar> > &ex,
2727 const std::vector<Matrix<Scalar> > &arg,
2728 const std::vector<std::vector<Matrix<Scalar> > > &v,
2730 casadi_error(
"'reverse' not defined for " + type_name());
2733 template<
typename Scalar>
2735 Matrix<Scalar>::which_depends(
const Matrix<Scalar> &expr,
const Matrix<Scalar> &var,
2736 casadi_int order,
bool tr) {
2737 casadi_error(
"'which_depends' not defined for " + type_name());
2738 return std::vector<bool>();
2741 template<
typename Scalar>
2743 Matrix<Scalar>::jacobian_sparsity(
const Matrix<Scalar> &f,
const Matrix<Scalar> &x) {
2744 casadi_error(
"'jacobian_sparsity' not defined for " + type_name());
2748 template<
typename Scalar>
2749 Matrix<Scalar> Matrix<Scalar>::taylor(
const Matrix<Scalar>& f,
2750 const Matrix<Scalar>& x,
2751 const Matrix<Scalar>& a, casadi_int order) {
2752 casadi_error(
"'taylor' not defined for " + type_name());
2753 return Matrix<Scalar>();
2756 template<
typename Scalar>
2757 Matrix<Scalar> Matrix<Scalar>::mtaylor(
const Matrix<Scalar>& f,
2758 const Matrix<Scalar>& x,
2759 const Matrix<Scalar>& a, casadi_int order) {
2760 casadi_error(
"'mtaylor' not defined for " + type_name());
2761 return Matrix<Scalar>();
2764 template<
typename Scalar>
2765 Matrix<Scalar> Matrix<Scalar>::mtaylor(
const Matrix<Scalar>& f,
2766 const Matrix<Scalar>& x,
2767 const Matrix<Scalar>& a, casadi_int order,
2768 const std::vector<casadi_int>&order_contributions) {
2769 casadi_error(
"'mtaylor' not defined for " + type_name());
2770 return Matrix<Scalar>();
2773 template<
typename Scalar>
2774 casadi_int Matrix<Scalar>::n_nodes(
const Matrix<Scalar>& x) {
2775 casadi_error(
"'n_nodes' not defined for " + type_name());
2779 template<
typename Scalar>
2781 Matrix<Scalar>::print_operator(
const Matrix<Scalar>& x,
2782 const std::vector<std::string>& args) {
2783 casadi_error(
"'print_operator' not defined for " + type_name());
2784 return std::string();
2787 template<
typename Scalar>
2788 std::vector<Matrix<Scalar> > Matrix<Scalar>::symvar(
const Matrix<Scalar>& x) {
2789 casadi_error(
"'symvar' not defined for " + type_name());
2790 return std::vector<Matrix<Scalar> >();
2793 template<
typename Scalar>
2794 void Matrix<Scalar>::extract(std::vector<Matrix<Scalar>>& ex, std::vector<Matrix<Scalar>>& v,
2795 std::vector<Matrix<Scalar>>& vdef,
const Dict& opts) {
2796 casadi_error(
"'extract' not defined for " + type_name());
2799 template<
typename Scalar>
2800 void Matrix<Scalar>::shared(std::vector<Matrix<Scalar> >& ex,
2801 std::vector<Matrix<Scalar> >& v,
2802 std::vector<Matrix<Scalar> >& vdef,
2803 const std::string& v_prefix,
2804 const std::string& v_suffix) {
2805 casadi_error(
"'shared' not defined for " + type_name());
2808 template<
typename Scalar>
2809 Matrix<Scalar> Matrix<Scalar>::poly_coeff(
const Matrix<Scalar>& f,
2810 const Matrix<Scalar>&x) {
2811 casadi_error(
"'poly_coeff' not defined for " + type_name());
2814 template<
typename Scalar>
2815 Matrix<Scalar> Matrix<Scalar>::poly_roots(
const Matrix<Scalar>& p) {
2816 casadi_error(
"'poly_roots' not defined for " + type_name());
2819 template<
typename Scalar>
2820 Matrix<Scalar> Matrix<Scalar>::eig_symbolic(
const Matrix<Scalar>& m) {
2821 casadi_error(
"'eig_symbolic' not defined for " + type_name());
2824 template<
typename Scalar>
2825 DM Matrix<Scalar>::evalf(
const Matrix<Scalar>& m) {
2826 Function f(
"f", std::vector<SX>{}, std::vector<SX>{m});
2827 return f(std::vector<DM>{})[0];
2830 template<
typename Scalar>
2831 Matrix<Scalar> Matrix<Scalar>::sparsify(
const Matrix<Scalar>& x,
double tol) {
2833 bool remove_nothing =
true;
2834 for (
auto it=x.nonzeros().begin(); it!=x.nonzeros().end() && remove_nothing; ++it) {
2835 remove_nothing = !casadi_limits<Scalar>::is_almost_zero(*it, tol);
2837 if (remove_nothing)
return x;
2840 casadi_int size1 = x.size1();
2841 casadi_int size2 = x.size2();
2842 const casadi_int* colind = x.colind();
2843 const casadi_int* row = x.row();
2846 std::vector<casadi_int> new_colind(1, 0), new_row;
2847 std::vector<Scalar> new_data;
2850 for (casadi_int cc=0; cc<size2; ++cc) {
2852 for (casadi_int el=colind[cc]; el<colind[cc+1]; ++el) {
2854 if (!casadi_limits<Scalar>::is_almost_zero(x->at(el), tol)) {
2856 new_data.push_back(x->at(el));
2859 new_row.push_back(row[el]);
2863 new_colind.push_back(new_row.size());
2867 Sparsity sp(size1, size2, new_colind, new_row);
2870 return Matrix<Scalar>(sp, new_data);
2874 template<
typename Scalar>
2875 std::vector<Matrix<Scalar> > Matrix<Scalar>::get_input(
const Function& f) {
2876 casadi_error(
"'get_input' not defined for " + type_name());
2879 template<
typename Scalar>
2880 std::vector<Matrix<Scalar> > Matrix<Scalar>::get_free(
const Function& f) {
2881 casadi_error(
"'get_free' not defined for " + type_name());
2884 template<
typename Scalar>
2885 Matrix<Scalar>::operator double()
const {
2886 casadi_assert_dev(is_scalar());
2887 return static_cast<double>(scalar());
2890 template<
typename Scalar>
2891 Matrix<Scalar>::operator casadi_int()
const {
2892 casadi_assert_dev(is_scalar());
2893 return static_cast<casadi_int
>(scalar());
2896 template<
typename Scalar>
2897 Matrix<Scalar> Matrix<Scalar>::_sym(
const std::string& name,
const Sparsity& sp) {
2898 casadi_error(
"'sym' not defined for " + type_name());
2901 template<
typename Scalar>
2902 Matrix<Scalar> Matrix<Scalar>::rand(
const Sparsity& sp) {
2904 casadi_error(
"'rand' not defined for " + type_name());
2907 template<
typename Scalar>
2908 std::string Matrix<Scalar>::serialize()
const {
2909 std::stringstream ss;
2914 template<
typename Scalar>
2915 void Matrix<Scalar>::serialize(SerializingStream& s)
const {
2916 s.pack(
"Matrix::sparsity", sparsity());
2917 s.pack(
"Matrix::nonzeros", nonzeros());
2920 template<
typename Scalar>
2921 Matrix<Scalar> Matrix<Scalar>::deserialize(DeserializingStream& s) {
2923 s.unpack(
"Matrix::sparsity", sp);
2924 std::vector<Scalar> nz;
2925 s.unpack(
"Matrix::nonzeros", nz);
2926 return Matrix<Scalar>(sp, nz,
false);
2929 template<
typename Scalar>
2930 void Matrix<Scalar>::serialize(std::ostream &stream)
const {
2931 SerializingStream s(stream);
2935 template<
typename Scalar>
2936 Matrix<Scalar> Matrix<Scalar>::deserialize(std::istream &stream) {
2937 DeserializingStream s(stream);
2938 return Matrix<Scalar>::deserialize(s);
2941 template<
typename Scalar>
2942 Matrix<Scalar> Matrix<Scalar>::deserialize(
const std::string& s) {
2943 std::stringstream ss;
2945 return deserialize(ss);
2948 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
2949 template<
typename Scalar>
2950 std::mutex& Matrix<Scalar>::get_mutex_temp() {
2951 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.