matrix_impl.hpp
1 /*
2  * This file is part of CasADi.
3  *
4  * CasADi -- A symbolic framework for dynamic optimization.
5  * Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl,
6  * KU Leuven. All rights reserved.
7  * Copyright (C) 2011-2014 Greg Horn
8  *
9  * CasADi is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 3 of the License, or (at your option) any later version.
13  *
14  * CasADi is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with CasADi; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 #ifndef CASADI_MATRIX_IMPL_HPP
26 #define CASADI_MATRIX_IMPL_HPP
27 
28 #include "dm.hpp"
29 #include "im.hpp"
30 #include "sx.hpp"
31 
32 #include "sx_node.hpp"
33 #include "linsol.hpp"
34 #include "expm.hpp"
35 #include "serializing_stream.hpp"
36 
37 namespace casadi {
38  template<typename Scalar>
39  void Matrix<Scalar>::set_precision(casadi_int precision) { stream_precision_ = precision; }
40 
41  template<typename Scalar>
42  void Matrix<Scalar>::set_width(casadi_int width) { stream_width_ = width; }
43 
44  template<typename Scalar>
45  void Matrix<Scalar>::set_scientific(bool scientific) { stream_scientific_ = scientific; }
46 
47  template<typename Scalar>
48  casadi_int Matrix<Scalar>::stream_precision_ = 6;
49  template<typename Scalar>
50  casadi_int Matrix<Scalar>::stream_width_ = 0;
51  template<typename Scalar>
53 
54  template<typename Scalar>
55  std::default_random_engine Matrix<Scalar>::rng_(
56  // Seed with current time
57  std::chrono::system_clock::now().time_since_epoch().count());
58 
59  template<typename Scalar>
60  void Matrix<Scalar>::rng(casadi_int seed) {
61  rng_.seed(seed);
62  }
63 
64  template<typename Scalar>
65  bool Matrix<Scalar>::has_nz(casadi_int rr, casadi_int cc) const {
66  return sparsity().has_nz(rr, cc);
67  }
68 
69  template<typename Scalar>
71  if (numel()!=1) {
72  casadi_error("Only scalar Matrix could have a truth value, but you "
73  "provided a shape" + dim());
74  }
75  return nonzeros().at(0)!=0;
76  }
77 
78  template<typename Scalar>
79  void Matrix<Scalar>::get(Matrix<Scalar>& m, bool ind1,
80  const Slice& rr, const Slice& cc) const {
81  // Both are scalar
82  if (rr.is_scalar(size1()) && cc.is_scalar(size2())) {
83  casadi_int k = sparsity().get_nz(rr.scalar(size1()), cc.scalar(size2()));
84  if (k>=0) {
85  m = nonzeros().at(k);
86  } else {
87  m = Matrix<Scalar>(1, 1);
88  }
89  return;
90  }
91 
92  // Fall back on IM-IM
93  get(m, ind1, rr.all(size1(), ind1), cc.all(size2(), ind1));
94  }
95 
96  template<typename Scalar>
97  void Matrix<Scalar>::get(Matrix<Scalar>& m, bool ind1,
98  const Slice& rr, const Matrix<casadi_int>& cc) const {
99  // Fall back on IM-IM
100  get(m, ind1, rr.all(size1(), ind1), cc);
101  }
102 
103  template<typename Scalar>
105  const Matrix<casadi_int>& rr, const Slice& cc) const {
106  // Fall back on IM-IM
107  get(m, ind1, rr, cc.all(size2(), ind1));
108  }
109 
110  template<typename Scalar>
112  const Matrix<casadi_int>& rr, const Matrix<casadi_int>& cc) const {
113  // Scalar
114  if (rr.is_scalar(true) && cc.is_scalar(true)) {
115  return get(m, ind1, to_slice(rr, ind1), to_slice(cc, ind1));
116  }
117 
118  // Make sure dense vectors
119  casadi_assert(rr.is_dense() && rr.is_vector(),
120  "Marix::get: First index must be a dense vector");
121  casadi_assert(cc.is_dense() && cc.is_vector(),
122  "Marix::get: Second index must be a dense vector");
123 
124  // Get the sparsity pattern - does bounds checking
125  std::vector<casadi_int> mapping;
126  Sparsity sp = sparsity().sub(rr.nonzeros(), cc.nonzeros(), mapping, ind1);
127 
128  // Copy nonzeros
129  m = Matrix<Scalar>::zeros(sp);
130  for (casadi_int k=0; k<mapping.size(); ++k) m->at(k) = nonzeros().at(mapping[k]);
131  }
132 
133  template<typename Scalar>
134  void Matrix<Scalar>::get(Matrix<Scalar>& m, bool ind1, const Slice& rr) const {
135  // Scalar
136  if (rr.is_scalar(numel())) {
137  casadi_int r = rr.scalar(numel());
138  casadi_int k = sparsity().get_nz(r % size1(), r / size1());
139  if (k>=0) {
140  m = nonzeros().at(k);
141  } else {
142  m = Matrix<Scalar>(1, 1);
143  }
144  return;
145  }
146 
147  // Fall back on IM
148  get(m, ind1, rr.all(numel(), ind1));
149  }
150 
151  template<typename Scalar>
152  void Matrix<Scalar>::get(Matrix<Scalar>& m, bool ind1, const Matrix<casadi_int>& rr) const {
153  // Scalar
154  if (rr.is_scalar(true)) {
155  return get(m, ind1, to_slice(rr, ind1));
156  }
157 
158  // If the indexed matrix is dense, use nonzero indexing
159  if (is_dense()) {
160  return get_nz(m, ind1, rr);
161  }
162 
163  // Get the sparsity pattern - does bounds checking
164  std::vector<casadi_int> mapping;
165  Sparsity sp = sparsity().sub(rr.nonzeros(), rr.sparsity(), mapping, ind1);
166 
167  // If indexed matrix was a row/column vector, make sure that the result is too
168  bool tr = (is_column() && rr.is_row()) || (is_row() && rr.is_column());
169 
170  // Copy nonzeros
171  m = Matrix<Scalar>::zeros(tr ? sp.T() : sp);
172  for (casadi_int k=0; k<mapping.size(); ++k) m->at(k) = nonzeros().at(mapping[k]);
173  }
174 
175  template<typename Scalar>
176  void Matrix<Scalar>::get(Matrix<Scalar>& m, bool ind1, const Sparsity& sp) const {
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);
182  }
183 
184  template<typename Scalar>
185  void Matrix<Scalar>::set(const Matrix<Scalar>& m, bool ind1,
186  const Slice& rr, const Slice& cc) {
187  // Both are scalar
188  if (rr.is_scalar(size1()) && cc.is_scalar(size2()) && m.is_dense()) {
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();
193  } else {
194  nonzeros_.insert(nonzeros_.begin()+ind, m.scalar());
195  }
196  return;
197  }
198 
199  // Fall back on (IM, IM)
200  set(m, ind1, rr.all(size1(), ind1), cc.all(size2(), ind1));
201  }
202 
203  template<typename Scalar>
204  void Matrix<Scalar>::set(const Matrix<Scalar>& m, bool ind1,
205  const Slice& rr, const Matrix<casadi_int>& cc) {
206  // Fall back on (IM, IM)
207  set(m, ind1, rr.all(size1(), ind1), cc);
208  }
209 
210  template<typename Scalar>
211  void Matrix<Scalar>::set(const Matrix<Scalar>& m, bool ind1,
212  const Matrix<casadi_int>& rr, const Slice& cc) {
213  // Fall back on (IM, IM)
214  set(m, ind1, rr, cc.all(size2(), ind1));
215  }
216 
217  template<typename Scalar>
218  void Matrix<Scalar>::set(const Matrix<Scalar>& m, bool ind1,
219  const Matrix<casadi_int>& rr, const Matrix<casadi_int>& cc) {
220  // Scalar
221  if (rr.is_scalar(true) && cc.is_scalar(true) && m.is_dense()) {
222  return set(m, ind1, to_slice(rr, ind1), to_slice(cc, ind1));
223  }
224 
225  // Row vector rr (e.g. in MATLAB) is transposed to column vector
226  if (rr.size1()==1 && rr.size2()>1) {
227  return set(m, ind1, rr.T(), cc);
228  }
229 
230  // Row vector cc (e.g. in MATLAB) is transposed to column vector
231  if (cc.size1()==1 && cc.size2()>1) {
232  return set(m, ind1, rr, cc.T());
233  }
234 
235  // Make sure rr and cc are dense vectors
236  casadi_assert(rr.is_dense() && rr.is_column(),
237  "Matrix::set: First index not dense vector");
238  casadi_assert(cc.is_dense() && cc.is_column(),
239  "Matrix::set: Second index not dense vector");
240 
241  // Assert dimensions of assigning matrix
242  if (rr.size1() != m.size1() || cc.size1() != m.size2()) {
243  if (m.is_scalar()) {
244  // m scalar means "set all"
245  return set(repmat(m, rr.size1(), cc.size1()), ind1, rr, cc);
246  } else if (rr.size1() == m.size2() && cc.size1() == m.size1()
247  && std::min(m.size1(), m.size2()) == 1) {
248  // m is transposed if necessary
249  return set(m.T(), ind1, rr, cc);
250  } else {
251  // Error otherwise
252  casadi_error("Dimension mismatch. lhs is " + str(rr.size1()) + "-by-"
253  + str(cc.size1()) + ", while rhs is " + str(m.size()));
254  }
255  }
256 
257  // Dimensions
258  casadi_int sz1 = size1(), sz2 = size2();
259 
260  // Report out-of-bounds
261  casadi_assert_in_range(rr.nonzeros(), -sz1+ind1, sz1+ind1);
262  casadi_assert_in_range(cc.nonzeros(), -sz2+ind1, sz2+ind1);
263 
264  // If we are assigning with something sparse, first remove existing entries
265  if (!m.is_dense()) {
266  erase(rr.nonzeros(), cc.nonzeros(), ind1);
267  }
268 
269  // Collect all assignments
270  IM el = IM::zeros(m.sparsity());
271  for (casadi_int j=0; j<el.size2(); ++j) { // Loop over columns of m
272  casadi_int this_j = cc->at(j) - ind1; // Corresponding column in this
273  if (this_j<0) this_j += sz2;
274  for (casadi_int k=el.colind(j); k<el.colind(j+1); ++k) { // Loop over rows of m
275  casadi_int i = m.row(k);
276  casadi_int this_i = rr->at(i) - ind1; // Corresponding row in this
277  if (this_i<0) this_i += sz1;
278  el->at(k) = this_i + this_j*sz1;
279  }
280  }
281  return set(m, false, el);
282  }
283 
284  template<typename Scalar>
285  void Matrix<Scalar>::set(const Matrix<Scalar>& m, bool ind1, const Slice& rr) {
286  // Scalar
287  if (rr.is_scalar(numel()) && m.is_dense()) {
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();
293  } else {
294  nonzeros_.insert(nonzeros_.begin()+ind, m.scalar());
295  }
296  return;
297  }
298 
299  // Fall back on IM
300  set(m, ind1, rr.all(numel(), ind1));
301  }
302 
303  template<typename Scalar>
304  void Matrix<Scalar>::set(const Matrix<Scalar>& m, bool ind1, const Matrix<casadi_int>& rr) {
305  // Scalar
306  if (rr.is_scalar(true) && m.is_dense()) {
307  return set(m, ind1, to_slice(rr, ind1));
308  }
309 
310  // Assert dimensions of assigning matrix
311  if (rr.sparsity() != m.sparsity()) {
312  if (rr.size() == m.size()) {
313  // Remove submatrix to be replaced
314  erase(rr.nonzeros(), ind1);
315 
316  // Find the intersection between rr's and m's sparsity patterns
317  Sparsity sp = rr.sparsity() * m.sparsity();
318 
319  // Project both matrices to this sparsity
320  return set(project(m, sp), ind1, Matrix<casadi_int>::project(rr, sp));
321  } else if (m.is_scalar()) {
322  // m scalar means "set all"
323  if (m.is_dense()) {
324  return set(Matrix<Scalar>(rr.sparsity(), m), ind1, rr);
325  } else {
326  return set(Matrix<Scalar>(rr.size()), ind1, rr);
327  }
328  } else if (rr.size1() == m.size2() && rr.size2() == m.size1()
329  && std::min(m.size1(), m.size2()) == 1) {
330  // m is transposed if necessary
331  return set(m.T(), ind1, rr);
332  } else {
333  // Error otherwise
334  casadi_error("Dimension mismatch. lhs is " + str(rr.size())
335  + ", while rhs is " + str(m.size()));
336  }
337  }
338 
339  // Dimensions of this
340  casadi_int sz1 = size1(), sz2 = size2(), sz = nnz(), nel = numel(), rrsz = rr.nnz();
341 
342  // Quick return if nothing to set
343  if (rrsz==0) return;
344 
345  // Check bounds
346  casadi_assert_in_range(rr.nonzeros(), -nel+ind1, nel+ind1);
347 
348  // Dense mode
349  if (is_dense() && m.is_dense()) {
350  return set_nz(m, ind1, rr);
351  }
352 
353  // Construct new sparsity pattern
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);
358  nz.reserve(rrsz);
359  for (std::vector<casadi_int>::iterator i=nz.begin(); i!=nz.end(); ++i) {
360  if (ind1) (*i)--;
361  if (*i<0) *i += nel;
362  new_row.push_back(*i % sz1);
363  new_col.push_back(*i / sz1);
364  }
365  Sparsity sp = Sparsity::triplet(sz1, sz2, new_row, new_col);
366 
367  // If needed, update pattern
368  if (sp != sparsity()) *this = project(*this, sp);
369 
370  // Find the nonzeros corresponding to rr
371  sparsity().get_nz(nz);
372 
373  // Carry out the assignments
374  for (casadi_int i=0; i<nz.size(); ++i) {
375  nonzeros().at(nz[i]) = m->at(i);
376  }
377  }
378 
379  template<typename Scalar>
380  void Matrix<Scalar>::set(const Matrix<Scalar>& m, bool ind1, const Sparsity& sp) {
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();
386  if (m.is_scalar()) {
387  (*this)(ii) = densify(m);
388  } else {
389  (*this)(ii) = densify(m(ii));
390  }
391  }
392 
393  template<typename Scalar>
394  void Matrix<Scalar>::get_nz(Matrix<Scalar>& m, bool ind1, const Slice& kk) const {
395  // Scalar
396  if (kk.is_scalar(nnz())) {
397  m = nonzeros().at(kk.scalar(nnz()));
398  return;
399  }
400 
401  // Fall back on IM
402  get_nz(m, ind1, kk.all(nnz(), ind1));
403  }
404 
405  template<typename Scalar>
406  void Matrix<Scalar>::get_nz(Matrix<Scalar>& m, bool ind1, const Matrix<casadi_int>& kk) const {
407  // Scalar
408  if (kk.is_scalar(true)) {
409  return get_nz(m, ind1, to_slice(kk, ind1));
410  }
411 
412  // Get nonzeros of kk
413  const std::vector<casadi_int>& k = kk.nonzeros();
414  casadi_int sz = nnz();
415 
416  // Check bounds
417  casadi_assert_in_range(k, -sz+ind1, sz+ind1);
418 
419  // If indexed matrix was a row/column vector, make sure that the result is too
420  bool tr = (is_column() && kk.is_row()) || (is_row() && kk.is_column());
421 
422  // Copy nonzeros
423  m = zeros(tr ? kk.sparsity().T() : kk.sparsity());
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);
431  }
432  }
433 
434  template<typename Scalar>
435  void Matrix<Scalar>::set_nz(const Matrix<Scalar>& m, bool ind1, const Slice& kk) {
436  // Scalar
437  if (kk.is_scalar(nnz())) {
438  nonzeros().at(kk.scalar(nnz())) = m.scalar();
439  return;
440  }
441 
442  // Fallback on IM
443  set_nz(m, ind1, kk.all(nnz(), ind1));
444  }
445 
446  template<typename Scalar>
447  void Matrix<Scalar>::set_nz(const Matrix<Scalar>& m, bool ind1, const Matrix<casadi_int>& kk) {
448  // Scalar
449  if (kk.is_scalar(true)) {
450  return set_nz(m, ind1, to_slice(kk, ind1));
451  }
452 
453  // Assert dimensions of assigning matrix
454  if (kk.sparsity() != m.sparsity()) {
455  if (m.is_scalar()) {
456  // m scalar means "set all"
457  if (!m.is_dense()) return; // Nothing to set
458  return set_nz(Matrix<Scalar>(kk.sparsity(), m), ind1, kk);
459  } else if (kk.size() == m.size()) {
460  // Project sparsity if needed
461  return set_nz(project(m, kk.sparsity()), ind1, kk);
462  } else if (kk.size1() == m.size2() && kk.size2() == m.size1()
463  && std::min(m.size1(), m.size2()) == 1) {
464  // m is transposed if necessary
465  return set_nz(m.T(), ind1, kk);
466  } else {
467  // Error otherwise
468  casadi_error("Dimension mismatch. lhs is " + str(kk.size())
469  + ", while rhs is " + str(m.size()));
470  }
471  }
472 
473  // Get nonzeros
474  const std::vector<casadi_int>& k = kk.nonzeros();
475  casadi_int sz = nnz();
476 
477  // Check bounds
478  casadi_assert_in_range(k, -sz+ind1, sz+ind1);
479 
480  // Set nonzeros, ignoring negative indices
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);
488  }
489  }
490 
491  template<typename Scalar>
493  return densify(x, 0);
494  }
495 
496  template<typename Scalar>
497  Matrix<Scalar> Matrix<Scalar>::densify(const Matrix<Scalar>& x,
498  const Matrix<Scalar>& val) {
499  // Check argument
500  casadi_assert_dev(val.is_scalar());
501 
502  // Quick return if possible
503  if (x.is_dense()) return x;
504 
505  // Get sparsity pattern
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();
511 
512  // New data vector
513  std::vector<Scalar> d(nrow*ncol, val.scalar());
514 
515  // Copy nonzeros
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++;
519  }
520  }
521 
522  // Construct return matrix
523  return Matrix<Scalar>(Sparsity::dense(x.size()), d);
524  }
525 
526  template<typename Scalar>
527  Matrix<Scalar> Matrix<Scalar>::cumsum(const Matrix<Scalar> &x, casadi_int axis) {
528  if (axis==-1) axis = x.is_row();
529  Matrix<Scalar> ret = x;
530  if (axis==0) {
531  for (casadi_int i=1;i<x.size1();++i)
532  ret(i, Slice()) += ret(i-1, Slice());
533  } else {
534  for (casadi_int i=1;i<x.size2();++i)
535  ret(Slice(), i) += ret(Slice(), i-1);
536  }
537  return ret;
538  }
539 
540  template<typename Scalar>
541  Matrix<Scalar> Matrix<Scalar>::einstein(
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;
551  casadi_int n_iter = einstein_process(A, B, C, dim_a, dim_b, dim_c, a, b, c,
552  iter_dims, strides_a, strides_b, strides_c);
553 
554  const std::vector<Scalar>& Av = A.nonzeros();
555  const std::vector<Scalar>& Bv = B.nonzeros();
556 
557  Matrix<Scalar> ret = C;
558  std::vector<Scalar>& Cv = ret.nonzeros();
559 
560  einstein_eval(n_iter, iter_dims, strides_a, strides_b, strides_c,
561  get_ptr(Av), get_ptr(Bv), get_ptr(Cv));
562  return ret;
563  }
564 
565  template<typename Scalar>
566  Matrix<Scalar> Matrix<Scalar>::einstein(const Matrix<Scalar>& A, const Matrix<Scalar>& B,
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) {
571  return Matrix<Scalar>::einstein(A, B, Matrix<Scalar>::zeros(product(dim_c), 1),
572  dim_a, dim_b, dim_c, a, b, c);
573  }
574 
575  template<typename Scalar>
576  Matrix<Scalar>::Matrix() : sparsity_(Sparsity(0, 0)) {
577  }
578 
579  template<typename Scalar>
580  Matrix<Scalar>::Matrix(const Matrix<Scalar>& m) : sparsity_(m.sparsity_), nonzeros_(m.nonzeros_) {
581  }
582 
583  template<typename Scalar>
584  Matrix<Scalar>::Matrix(const std::vector<Scalar>& x) :
585  sparsity_(Sparsity::dense(x.size(), 1)), nonzeros_(x) {
586  }
587 
588  template<typename Scalar>
590  sparsity_ = m.sparsity_;
591  nonzeros_ = m.nonzeros_;
592  return *this;
593  }
594 
595  template<typename Scalar>
596  std::vector<Scalar>* Matrix<Scalar>::operator->() {
597  return &nonzeros_;
598  }
599 
600  template<typename Scalar>
601  const std::vector<Scalar>* Matrix<Scalar>::operator->() const {
602  return &nonzeros_;
603  }
604 
605  template<typename Scalar>
606  std::string Matrix<Scalar>::type_name() { return matrixName<Scalar>(); }
607 
608  template<typename Scalar>
609  void Matrix<Scalar>::print_scalar(std::ostream &stream) const {
610  casadi_assert(numel()==1, "Not a scalar");
611 
612  std::streamsize precision = stream.precision();
613  std::streamsize width = stream.width();
614  std::ios_base::fmtflags flags = stream.flags();
615 
616  stream.precision(stream_precision_);
617  stream.width(stream_width_);
618  if (stream_scientific_) {
619  stream.setf(std::ios::scientific);
620  } else {
621  stream.unsetf(std::ios::scientific);
622  }
623 
624  if (nnz()==0) {
625  stream << "00";
626  } else {
627  stream << scalar();
628  }
629  stream << std::flush;
630  stream.precision(precision);
631  stream.width(width);
632  stream.flags(flags);
633  }
634 
635  template<typename Scalar>
636  void Matrix<Scalar>::print_vector(std::ostream &stream, bool truncate) const {
637  print_vector(stream, sparsity(), ptr(), truncate);
638  }
639 
640  template<typename Scalar>
641  void Matrix<Scalar>::print_vector(std::ostream &stream, const Sparsity& sp,
642  const Scalar* nonzeros, bool truncate) {
643  casadi_assert(sp.is_column(), "Not a vector");
644 
645  // Get components
646  std::vector<std::string> nz, inter;
647  print_split(sp.nnz(), nonzeros, nz, inter);
648 
649  // Print intermediate expressions
650  for (casadi_int i=0; i<inter.size(); ++i)
651  stream << "@" << (i+1) << "=" << inter[i] << ", ";
652  inter.clear();
653 
654  // Access data structures
655  const casadi_int* row = sp.row();
656  casadi_int nnz = sp.nnz();
657  casadi_int size1 = sp.size1();
658 
659  // No need to truncate if less than 1000 entries
660  const casadi_int max_numel = 1000;
661  if (truncate && size1<=max_numel) truncate=false;
662 
663  // Nonzero
664  casadi_int el=0;
665 
666  // Loop over rows
667  stream << "[";
668  for (casadi_int rr=0; rr<size1; ++rr) {
669  // String representation
670  std::string s = el<nnz && rr==row[el] ? nz.at(el++) : "00";
671 
672  // Truncate?
673  if (truncate && rr>=3 && rr<size1-3) {
674  // Do not print
675  if (rr==3) stream << ", ...";
676  } else {
677  // Print
678  if (rr!=0) stream << ", ";
679  stream << s;
680  }
681  }
682  stream << "]" << std::flush;
683  }
684 
685  template<typename Scalar>
686  void Matrix<Scalar>::print_dense(std::ostream &stream, bool truncate) const {
687  print_dense(stream, sparsity(), ptr(), truncate);
688  }
689 
690  template<typename Scalar>
691  void Matrix<Scalar>::print_sparse(std::ostream &stream, bool truncate) const {
692  print_sparse(stream, sparsity(), ptr(), truncate);
693  }
694 
695  template<typename Scalar>
696  void Matrix<Scalar>::print_split(std::vector<std::string>& nz,
697  std::vector<std::string>& inter) const {
698 
699  print_split(nnz(), ptr(), nz, inter);
700  }
701 
702  template<typename Scalar>
703  void Matrix<Scalar>::print_default(std::ostream &stream, const Sparsity& sp,
704  const Scalar* nonzeros, bool truncate) {
705  if (sp.is_empty()) {
706  stream << sp.size1() << "x" << sp.size2();
707  } else if (sp.numel()==1) {
708  if (sp.nnz()==0) {
709  stream << "00";
710  } else {
711  print_scalar(stream, *nonzeros);
712  }
713  } else if (sp.is_column()) {
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) {
717  // if "small" or "dense"
718  print_dense(stream, sp, nonzeros, truncate);
719  } else {
720  print_sparse(stream, sp, nonzeros, truncate);
721  }
722  }
723 
724  template<typename Scalar>
725  void Matrix<Scalar>::print_scalar(std::ostream &stream, const Scalar& e) {
726  std::streamsize precision = stream.precision();
727  std::streamsize width = stream.width();
728  std::ios_base::fmtflags flags = stream.flags();
729 
730  stream.precision(stream_precision_);
731  stream.width(stream_width_);
732  if (stream_scientific_) {
733  stream.setf(std::ios::scientific);
734  } else {
735  stream.unsetf(std::ios::scientific);
736  }
737  stream << e;
738  stream << std::flush;
739 
740  stream.precision(precision);
741  stream.width(width);
742  stream.flags(flags);
743  }
744 
745  template<typename Scalar>
746  void Matrix<Scalar>::print_split(casadi_int nnz, const Scalar* nonzeros,
747  std::vector<std::string>& nz,
748  std::vector<std::string>& inter) {
749  nz.resize(nnz);
750  inter.resize(0);
751 
752  // Temporary
753  std::stringstream ss;
754  ss.precision(stream_precision_);
755  ss.width(stream_width_);
756  if (stream_scientific_) {
757  ss.setf(std::ios::scientific);
758  } else {
759  ss.unsetf(std::ios::scientific);
760  }
761 
762  // Print nonzeros
763  for (casadi_int i=0; i<nz.size(); ++i) {
764  ss.str(std::string());
765  ss << nonzeros[i];
766  nz[i] = ss.str();
767  }
768  }
769 
770  template<typename Scalar>
771  void Matrix<Scalar>::print_sparse(std::ostream &stream, const Sparsity& sp,
772  const Scalar* nonzeros, bool truncate) {
773  // Access data structures
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();
779 
780  // Quick return if all zero sparse
781  if (nnz==0) {
782  stream << "all zero sparse: " << size1 << "-by-" << size2 << std::flush;
783  return;
784  }
785 
786  // Print header
787  stream << "sparse: " << size1 << "-by-" << size2 << ", " << nnz << " nnz";
788 
789  // Get components
790  std::vector<std::string> nz, inter;
791  print_split(nnz, nonzeros, nz, inter);
792 
793  // Print intermediate expressions
794  for (casadi_int i=0; i<inter.size(); ++i)
795  stream << std::endl << " @" << (i+1) << "=" << inter[i] << ",";
796  inter.clear();
797 
798  // No need to truncate if less than 1000 nonzeros
799  const casadi_int max_nnz = 1000;
800  if (truncate && nnz<=max_nnz) truncate=false;
801 
802  // Print nonzeros
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 << " ...";
807  } else {
808  stream << std::endl << " (" << row[el] << ", " << cc << ") -> " << nz.at(el);
809  InterruptHandler::check();
810  }
811  }
812  }
813  stream << std::flush;
814  }
815 
816  template<typename Scalar>
817  void Matrix<Scalar>::print_dense(std::ostream &stream, const Sparsity& sp,
818  const Scalar* nonzeros, bool truncate) {
819  // Get components
820  std::vector<std::string> nz, inter;
821  print_split(sp.nnz(), nonzeros, nz, inter);
822 
823  // Print intermediate expressions
824  for (casadi_int i=0; i<inter.size(); ++i)
825  stream << "@" << (i+1) << "=" << inter[i] << ", ";
826  inter.clear();
827 
828  // Access data structures
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();
833 
834  // No need to truncate if less than 1000 entries
835  const casadi_int max_numel = 1000;
836  if (truncate && size1*size2<=max_numel) truncate=false;
837 
838  // Truncate rows and/or columns
839  bool truncate_rows = truncate && size1>=7;
840  bool truncate_columns = truncate && size2>=7;
841 
842  // Index counter for each column
843  std::vector<casadi_int> ind(colind, colind+size2+1);
844 
845  // Print as a single line?
846  bool oneliner=size1<=1;
847 
848  // Loop over rows
849  for (casadi_int rr=0; rr<size1; ++rr) {
850  // Print row?
851  bool print_row = !(truncate_rows && rr>=3 && rr<size1-3);
852 
853  // Beginning of row
854  if (rr==0) {
855  if (!oneliner) stream << std::endl;
856  stream << "[[";
857  } else if (print_row) {
858  stream << " [";
859  }
860 
861  // Loop over columns
862  for (casadi_int cc=0; cc<size2; ++cc) {
863  // String representation of element
864  std::string s = ind[cc]<colind[cc+1] && row[ind[cc]]==rr
865  ? nz.at(ind[cc]++) : "00";
866 
867  // Skip whole row?
868  if (!print_row) continue;
869 
870  // Print column?
871  bool print_column = !(truncate_columns && cc>=3 && cc<size2-3);
872 
873  // Print element
874  if (print_column) {
875  if (cc!=0) stream << ", ";
876  stream << s;
877  } else if (cc==3) {
878  stream << ", ...";
879  }
880  }
881 
882  // End of row
883  if (rr<size1-1) {
884  if (print_row) {
885  stream << "], ";
886  if (!oneliner) stream << std::endl;
887  } else if (rr==3) {
888  stream << " ...," << std::endl;
889  }
890  } else {
891  stream << "]]";
892  }
893  }
894  stream << std::flush;
895  }
896 
897  template<typename Scalar>
898  void Matrix<Scalar>::to_file(const std::string& filename, const std::string& format) const {
899  to_file(filename, sparsity(), ptr(), format);
900  }
901 
902  template<typename Scalar>
903  void Matrix<Scalar>::disp(std::ostream& stream, bool more) const {
904  print_default(stream, sparsity(), ptr());
905  }
906 
907  template<typename Scalar>
908  std::string Matrix<Scalar>::get_str(bool more) const {
909  std::stringstream ss;
910  disp(ss, more);
911  return ss.str();
912  }
913 
914  template<typename Scalar>
915  void Matrix<Scalar>::reserve(casadi_int nnz) {
916  reserve(nnz, size2());
917  }
918 
919  template<typename Scalar>
920  void Matrix<Scalar>::reserve(casadi_int nnz, casadi_int ncol) {
921  nonzeros().reserve(nnz);
922  }
923 
924  template<typename Scalar>
925  void Matrix<Scalar>::resize(casadi_int nrow, casadi_int ncol) {
926  sparsity_.resize(nrow, ncol);
927  }
928 
929  template<typename Scalar>
930  void Matrix<Scalar>::clear() {
931  sparsity_ = Sparsity(0, 0);
932  nonzeros().clear();
933  }
934 
935  template<typename Scalar>
936  Matrix<Scalar>::Matrix(double val) :
937  sparsity_(
938  Sparsity::dense(1, 1)),
939  nonzeros_(std::vector<Scalar>(1, static_cast<Scalar>(val))) {
940  }
941 
942  template<typename Scalar>
943  Matrix<Scalar>::Matrix(const std::vector< std::vector<double> >& d) {
944  // Get dimensions
945  casadi_int nrow=d.size();
946  casadi_int ncol=d.empty() ? 1 : d.front().size();
947 
948  // Assert consistency
949  for (casadi_int rr=0; rr<nrow; ++rr) {
950  casadi_assert(ncol==d[rr].size(),
951  "Shape mismatch.\n"
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()) + " )");
955  }
956 
957  // Form matrix
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]);
964  }
965  }
966  }
967 
968  template<typename Scalar>
969  Matrix<Scalar>::Matrix(const Sparsity& sp) : sparsity_(sp), nonzeros_(sp.nnz(), 1) {
970  }
971 
972  template<typename Scalar>
973  Matrix<Scalar>::Matrix(casadi_int nrow, casadi_int ncol) : sparsity_(nrow, ncol) {
974  }
975 
976  template<typename Scalar>
977  Matrix<Scalar>::Matrix(const std::pair<casadi_int, casadi_int>& rc) : sparsity_(rc) {
978  }
979 
980  template<typename Scalar>
981  Matrix<Scalar>::Matrix(const Sparsity& sp, const Scalar& val, bool dummy) :
982  sparsity_(sp), nonzeros_(sp.nnz(), val) {
983  }
984 
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()));
991  }
992 
993  template<typename Scalar>
994  Matrix<Scalar>::Matrix(const Sparsity& sp, const Matrix<Scalar>& d) {
995  if (d.is_scalar()) {
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());
1004  if (d.is_dense()) {
1005  *this = Matrix<Scalar>(sp, d.nonzeros(), false);
1006  } else {
1007  *this = Matrix<Scalar>(sp, densify(d).nonzeros(), false);
1008  }
1009  } else {
1010  casadi_error("Matrix(Sparsity, Matrix): Only allowed for scalars and vectors");
1011  }
1012  }
1013 
1014  template<typename Scalar>
1015  Matrix<Scalar> Matrix<Scalar>::unary(casadi_int op, const Matrix<Scalar> &x) {
1016  // Return value
1017  Matrix<Scalar> ret = Matrix<Scalar>::zeros(x.sparsity());
1018 
1019  // Nonzeros
1020  std::vector<Scalar>& ret_data = ret.nonzeros();
1021  const std::vector<Scalar>& x_data = x.nonzeros();
1022 
1023  // Do the operation on all non-zero elements
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]);
1026  }
1027 
1028  // Check the value of the structural zero-entries, if there are any
1029  if (!x.is_dense() && !operation_checker<F0XChecker>(op)) {
1030  // Get the value for the structural zeros
1031  Scalar fcn_0;
1032  casadi_math<Scalar>::fun(op, 0, 0, fcn_0);
1033  if (!casadi_limits<Scalar>::is_zero(fcn_0)) { // Remove this if?
1034  ret = densify(ret, fcn_0);
1035  }
1036  }
1037 
1038  return ret;
1039  }
1040 
1041  template<typename Scalar>
1042  Matrix<Scalar> Matrix<Scalar>::operator-() const {
1043  return unary(OP_NEG, *this);
1044  }
1045 
1046  template<typename Scalar>
1047  Matrix<Scalar> Matrix<Scalar>::operator+() const {
1048  return *this;
1049  }
1050 
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();
1056  }
1057 
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;
1062  return solve(a, b);
1063  }
1064 
1065  template<typename Scalar>
1066  Matrix<Scalar> Matrix<Scalar>::printme(const Matrix<Scalar>& y) const {
1067  return binary(OP_PRINTME, *this, y);
1068  }
1069 
1070  template<typename Scalar>
1071  void Matrix<Scalar>::erase(const std::vector<casadi_int>& rr,
1072  const std::vector<casadi_int>& cc, bool ind1) {
1073  // Erase from sparsity pattern
1074  std::vector<casadi_int> mapping = sparsity_.erase(rr, cc, ind1);
1075 
1076  // Update non-zero entries
1077  for (casadi_int k=0; k<mapping.size(); ++k)
1078  nonzeros()[k] = nonzeros()[mapping[k]];
1079 
1080  // Truncate nonzero vector
1081  nonzeros().resize(mapping.size());
1082  }
1083 
1084  template<typename Scalar>
1085  void Matrix<Scalar>::erase(const std::vector<casadi_int>& rr, bool ind1) {
1086  // Erase from sparsity pattern
1087  std::vector<casadi_int> mapping = sparsity_.erase(rr, ind1);
1088 
1089  // Update non-zero entries
1090  for (casadi_int k=0; k<mapping.size(); ++k)
1091  nonzeros()[k] = nonzeros()[mapping[k]];
1092 
1093  // Truncate nonzero vector
1094  nonzeros().resize(mapping.size());
1095  }
1096 
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());
1102 
1103  // Remove by performing a complementary slice
1104  std::vector<casadi_int> rrc = complement(rr, size1());
1105  std::vector<casadi_int> ccc = complement(cc, size2());
1106 
1107  Matrix<Scalar> ret = (*this)(rrc, ccc); // NOLINT(cppcoreguidelines-slicing)
1108 
1109  operator=(ret);
1110 
1111  }
1112 
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);
1117  }
1118 
1119  template<typename Scalar>
1120  const Sparsity& Matrix<Scalar>::sparsity() const {
1121  return sparsity_;
1122  }
1123 
1124  template<typename Scalar>
1125  std::vector<Scalar>& Matrix<Scalar>::nonzeros() {
1126  return nonzeros_;
1127  }
1128 
1129  template<typename Scalar>
1130  const std::vector<Scalar>& Matrix<Scalar>::nonzeros() const {
1131  return nonzeros_;
1132  }
1133 
1134  template<typename Scalar>
1135  Scalar* Matrix<Scalar>::ptr() {
1136  return nonzeros_.empty() ? nullptr : &nonzeros_.front();
1137  }
1138 
1139  template<typename Scalar>
1140  const Scalar* Matrix<Scalar>::ptr() const {
1141  return nonzeros_.empty() ? nullptr : &nonzeros_.front();
1142  }
1143 
1144  template<typename Scalar>
1145  Sparsity Matrix<Scalar>::get_sparsity() const {
1146  return sparsity();
1147  }
1148 
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()) {
1152  // Use element-wise multiplication if at least one factor scalar
1153  return x*y;
1154  } else {
1155  Matrix<Scalar> z = Matrix<Scalar>::zeros(Sparsity::mtimes(x.sparsity(), y.sparsity()));
1156  return mac(x, y, z);
1157  }
1158  }
1159 
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()) {
1165  // Use element-wise multiplication if at least one factor scalar
1166  return z + x*y;
1167  }
1168 
1169  // Check matching dimensions
1170  casadi_assert(x.size2()==y.size1(),
1171  "Matrix product with incompatible dimensions. Lhs is "
1172  + x.dim() + " and rhs is " + y.dim() + ".");
1173 
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() + ".");
1177 
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() + ".");
1181 
1182  // Check if we can simplify the product
1183  if (x.is_eye()) {
1184  return y + z;
1185  } else if (y.is_eye()) {
1186  return x + z;
1187  } else if (x.is_zero() || y.is_zero()) {
1188  return z;
1189  } else {
1190  // Carry out the matrix product
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);
1195  return ret;
1196  }
1197  }
1198 
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());
1204  }
1205 
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());
1212  return ret;
1213  }
1214 
1215 
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)));
1221  }
1222 
1223  template<typename Scalar>
1224  Matrix<Scalar> Matrix<Scalar>::T() const {
1225  // quick return if empty or scalar
1226  if ((size1()==0 && size2()==0) || is_scalar()) return *this;
1227 
1228  // Create the new sparsity pattern and the mapping
1229  std::vector<casadi_int> mapping;
1230  Sparsity s = sparsity().transpose(mapping);
1231 
1232  // create the return matrix
1233  Matrix<Scalar> ret = zeros(s);
1234 
1235  // Copy the content
1236  for (casadi_int i=0; i<mapping.size(); ++i)
1237  ret->at(i) = nonzeros().at(mapping[i]);
1238 
1239  return ret;
1240  }
1241 
1242  template<typename Scalar>
1243  const Scalar Matrix<Scalar>::scalar() const {
1244  // Make sure that the matrix is 1-by-1
1245  casadi_assert(is_scalar(), "Can only convert 1-by-1 matrices to scalars");
1246 
1247  // return zero or the nonzero element
1248  if (nnz()==1)
1249  return nonzeros()[0];
1250  else
1252  }
1253 
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);
1262  } else {
1263  return matrix_matrix(op, x, y);
1264  }
1265  }
1266 
1267  template<typename Scalar>
1268  Matrix<Scalar> Matrix<Scalar>::
1269  scalar_matrix(casadi_int op, const Matrix<Scalar> &x, const Matrix<Scalar> &y) {
1270  if ( (operation_checker<FX0Checker>(op) && y.nnz()==0) ||
1271  (operation_checker<F0XChecker>(op) && x.nnz()==0))
1272  return Matrix<Scalar>::zeros(Sparsity(y.size()));
1273 
1274  // Return value
1275  Matrix<Scalar> ret = Matrix<Scalar>::zeros(y.sparsity());
1276 
1277  // Nonzeros
1278  std::vector<Scalar>& ret_data = ret.nonzeros();
1279  const std::vector<Scalar>& x_data = x.nonzeros();
1280  const Scalar& x_val = x_data.empty() ? casadi_limits<Scalar>::zero : x->front();
1281  const std::vector<Scalar>& y_data = y.nonzeros();
1282 
1283  // Do the operation on all non-zero elements
1284  for (casadi_int el=0; el<y.nnz(); ++el) {
1285  casadi_math<Scalar>::fun(op, x_val, y_data[el], ret_data[el]);
1286  }
1287 
1288  // Check the value of the structural zero-entries, if there are any
1289  if (!y.is_dense() && !operation_checker<FX0Checker>(op)) {
1290  // Get the value for the structural zeros
1291  Scalar fcn_0;
1292  casadi_math<Scalar>::fun(op, x_val, casadi_limits<Scalar>::zero, fcn_0);
1293  if (!casadi_limits<Scalar>::is_zero(fcn_0)) { // Remove this if?
1294  ret = densify(ret, fcn_0);
1295  }
1296  }
1297 
1298  return ret;
1299  }
1300 
1301  template<typename Scalar>
1302  Matrix<Scalar> Matrix<Scalar>::
1303  matrix_scalar(casadi_int op, const Matrix<Scalar> &x, const Matrix<Scalar> &y) {
1304 
1305  if ( (operation_checker<FX0Checker>(op) && y.nnz()==0) ||
1306  (operation_checker<F0XChecker>(op) && x.nnz()==0))
1307  return Matrix<Scalar>::zeros(Sparsity(x.size()));
1308 
1309  // Return value
1310  Matrix<Scalar> ret = Matrix<Scalar>::zeros(x.sparsity());
1311 
1312  // Nonzeros
1313  std::vector<Scalar>& ret_data = ret.nonzeros();
1314  const std::vector<Scalar>& x_data = x.nonzeros();
1315  const std::vector<Scalar>& y_data = y.nonzeros();
1316  const Scalar& y_val = y_data.empty() ? casadi_limits<Scalar>::zero : y->front();
1317 
1318  // Do the operation on all non-zero elements
1319  for (casadi_int el=0; el<x.nnz(); ++el) {
1320  casadi_math<Scalar>::fun(op, x_data[el], y_val, ret_data[el]);
1321  }
1322 
1323  // Check the value of the structural zero-entries, if there are any
1324  if (!x.is_dense() && !operation_checker<F0XChecker>(op)) {
1325  // Get the value for the structural zeros
1326  Scalar fcn_0;
1327  casadi_math<Scalar>::fun(op, casadi_limits<Scalar>::zero, y_val, fcn_0);
1328  if (!casadi_limits<Scalar>::is_zero(fcn_0)) { // Remove this if?
1329  ret = densify(ret, fcn_0);
1330  }
1331  }
1332 
1333  return ret;
1334  }
1335 
1336  template<typename Scalar>
1337  Matrix<Scalar> Matrix<Scalar>::
1338  matrix_matrix(casadi_int op, const Matrix<Scalar> &x, const Matrix<Scalar> &y) {
1339  // Check, correct dimensions
1340  if (x.size() != y.size()) {
1341  // x and y are horizontal multiples of each other?
1342  if (!x.is_empty() && !y.is_empty()) {
1343  if (x.size1() == y.size1() && x.size2() % y.size2() == 0) {
1344  return matrix_matrix(op, x, repmat(y, 1, x.size2() / y.size2()));
1345  } else if (y.size1() == x.size1() && y.size2() % x.size2() == 0) {
1346  return matrix_matrix(op, repmat(x, 1, y.size2() / x.size2()), y);
1347  }
1348  }
1349  // x and y are empty horizontal multiples of each other?
1350  if (x.size1()==0 && y.size1()==0 && x.size2()>0 && y.size2()>0) {
1351  if (x.size2() % y.size2() == 0) {
1352  return Matrix<Scalar>(0, x.size2());
1353  } else if (y.size2() % x.size2() == 0) {
1354  return Matrix<Scalar>(0, y.size2());
1355  }
1356  }
1357  // Dimension mismatch
1358  casadi_error("Dimension mismatch for " + casadi_math<Scalar>::print(op, "x", "y") +
1359  ", x is " + x.dim() + ", while y is " + y.dim());
1360  }
1361 
1362  // Get the sparsity pattern of the result
1363  // (ignoring structural zeros giving rise to nonzero result)
1364  const Sparsity& x_sp = x.sparsity();
1365  const Sparsity& y_sp = y.sparsity();
1366  Sparsity r_sp = x_sp.combine(y_sp, operation_checker<F0XChecker>(op),
1367  operation_checker<FX0Checker>(op));
1368 
1369  // Return value
1370  Matrix<Scalar> r = zeros(r_sp);
1371 
1372  // Perform the operations elementwise
1373  if (x_sp==y_sp) {
1374  // Matching sparsities
1375  casadi_math<Scalar>::fun(op, x.ptr(), y.ptr(), r.ptr(), r_sp.nnz());
1376  } else if (y_sp==r_sp) {
1377  // Project first argument
1378  Matrix<Scalar> x_mod = x(r_sp);
1379  casadi_math<Scalar>::fun(op, x_mod.ptr(), y.ptr(), r.ptr(), r_sp.nnz());
1380  } else if (x_sp==r_sp) {
1381  // Project second argument
1382  Matrix<Scalar> y_mod = y(r_sp);
1383  casadi_math<Scalar>::fun(op, x.ptr(), y_mod.ptr(), r.ptr(), r_sp.nnz());
1384  } else {
1385  // Project both arguments
1386  Matrix<Scalar> x_mod = x(r_sp);
1387  Matrix<Scalar> y_mod = y(r_sp);
1388  casadi_math<Scalar>::fun(op, x_mod.ptr(), y_mod.ptr(), r.ptr(), r_sp.nnz());
1389  }
1390 
1391  // Handle structural zeros giving rise to nonzero result, e.g. cos(0) == 1
1392  if (!r.is_dense() && !operation_checker<F00Checker>(op)) {
1393  // Get the value for the structural zeros
1394  Scalar fcn_0;
1395  casadi_math<Scalar>::fun(op, casadi_limits<Scalar>::zero,
1397  r = densify(r, fcn_0);
1398  }
1399 
1400  return r;
1401  }
1402 
1403  template<typename Scalar>
1404  Matrix<Scalar> Matrix<Scalar>::triplet(const std::vector<casadi_int>& row,
1405  const std::vector<casadi_int>& col,
1406  const Matrix<Scalar>& d) {
1407  return triplet(row, col, d, *std::max_element(row.begin(), row.end()),
1408  *std::max_element(col.begin(), col.end()));
1409  }
1410 
1411  template<typename Scalar>
1412  Matrix<Scalar> Matrix<Scalar>::triplet(const std::vector<casadi_int>& row,
1413  const std::vector<casadi_int>& col,
1414  const Matrix<Scalar>& d,
1415  const std::pair<casadi_int, casadi_int>& rc) {
1416  return triplet(row, col, d, rc.first, rc.second);
1417  }
1418 
1419  template<typename Scalar>
1420  Matrix<Scalar> Matrix<Scalar>::triplet(const std::vector<casadi_int>& row,
1421  const std::vector<casadi_int>& col,
1422  const Matrix<Scalar>& d,
1423  casadi_int nrow, casadi_int ncol) {
1424  casadi_assert(col.size()==row.size() && col.size()==d.nnz(),
1425  "Argument error in Matrix<Scalar>::triplet(row, col, d): "
1426  "supplied lists must all be of equal length, but got: "
1427  + str(row.size()) + ", " + str(col.size()) + " and " + str(d.nnz()));
1428  std::vector<casadi_int> mapping;
1429  Sparsity sp = Sparsity::triplet(nrow, ncol, row, col, mapping, false);
1430  return Matrix<Scalar>(sp, d.nz(mapping));
1431  }
1432 
1433  template<typename Scalar>
1434  Matrix<Scalar> Matrix<Scalar>::eye(casadi_int n) {
1436  }
1437 
1438  template<typename Scalar>
1439  Matrix<Scalar> Matrix<Scalar>::inf(const Sparsity& sp) {
1440  casadi_assert(std::numeric_limits<Scalar>::has_infinity,
1441  "Datatype cannot represent infinity");
1442  return Matrix<Scalar>(sp, std::numeric_limits<Scalar>::infinity(), false);
1443  }
1444 
1445 
1446  template<typename Scalar>
1447  Matrix<Scalar> Matrix<Scalar>::inf(const std::pair<casadi_int, casadi_int>& rc) {
1448  return inf(rc.first, rc.second);
1449  }
1450 
1451  template<typename Scalar>
1452  Matrix<Scalar> Matrix<Scalar>::inf(casadi_int nrow, casadi_int ncol) {
1453  return inf(Sparsity::dense(nrow, ncol));
1454  }
1455 
1456  template<typename Scalar>
1457  Matrix<Scalar> Matrix<Scalar>::nan(const Sparsity& sp) {
1458  casadi_assert(std::numeric_limits<Scalar>::has_quiet_NaN,
1459  "Datatype cannot represent not-a-number");
1460  return Matrix<Scalar>(sp, std::numeric_limits<Scalar>::quiet_NaN(), false);
1461  }
1462 
1463  template<typename Scalar>
1464  Matrix<Scalar> Matrix<Scalar>::nan(const std::pair<casadi_int, casadi_int>& rc) {
1465  return nan(rc.first, rc.second);
1466  }
1467 
1468  template<typename Scalar>
1469  Matrix<Scalar> Matrix<Scalar>::nan(casadi_int nrow, casadi_int ncol) {
1470  return nan(Sparsity::dense(nrow, ncol));
1471  }
1472 
1473  template<typename Scalar>
1474  bool Matrix<Scalar>::is_regular() const {
1475  return casadi::is_regular(nonzeros_);
1476  }
1477 
1478  template<typename Scalar>
1479  bool Matrix<Scalar>::is_smooth() const {
1480  return true;
1481  }
1482 
1483  template<typename Scalar>
1484  casadi_int Matrix<Scalar>::element_hash() const {
1485  casadi_error("'element_hash' not defined for " + type_name());
1486  }
1487 
1488  template<typename Scalar>
1489  bool Matrix<Scalar>::is_leaf() const {
1490  casadi_error("'is_leaf' not defined for " + type_name());
1491  }
1492 
1493  template<typename Scalar>
1494  bool Matrix<Scalar>::is_commutative() const {
1495  casadi_error("'is_commutative' not defined for " + type_name());
1496  }
1497 
1498  template<typename Scalar>
1499  bool Matrix<Scalar>::is_symbolic() const {
1500  return false;
1501  }
1502 
1503  template<typename Scalar>
1504  casadi_int Matrix<Scalar>::op() const {
1505  casadi_error("'op' not defined for " + type_name());
1506  }
1507 
1508  template<typename Scalar>
1509  bool Matrix<Scalar>::is_op(casadi_int k) const {
1510  casadi_error("'is_op' not defined for " + type_name());
1511  }
1512 
1513  template<typename Scalar>
1514  void Matrix<Scalar>::export_code(const std::string& lang,
1515  std::ostream &stream, const Dict& options) const {
1516  casadi_error("'export_code' not defined for " + type_name());
1517  }
1518 
1519  template<typename Scalar>
1520  bool Matrix<Scalar>::is_valid_input() const {
1521  return false;
1522  }
1523 
1524  template<typename Scalar>
1525  bool Matrix<Scalar>::has_duplicates() const {
1526  casadi_error("'has_duplicates' not defined for " + type_name());
1527  }
1528 
1529  template<typename Scalar>
1530  void Matrix<Scalar>::reset_input() const {
1531  casadi_error("'reset_input' not defined for " + type_name());
1532  }
1533 
1534  template<typename Scalar>
1535  Matrix<double> Matrix<Scalar>::from_file(const std::string& filename,
1536  const std::string& format_hint) {
1537  casadi_error("'from_file' not defined for " + type_name());
1538  }
1539 
1540  template<typename Scalar>
1541  bool Matrix<Scalar>::is_integer() const {
1542  // Look for non-integers
1543  for (auto&& e : nonzeros()) if (!casadi_limits<Scalar>::is_integer(e)) return false;
1544 
1545  // Integer if reached this point
1546  return true;
1547  }
1548 
1549  template<typename Scalar>
1550  bool Matrix<Scalar>::is_constant() const {
1551  // Look for non-constants
1552  for (auto&& e : nonzeros()) if (!casadi_limits<Scalar>::is_constant(e)) return false;
1553 
1554  // Constant if we reach this point
1555  return true;
1556  }
1557 
1558  template<typename Scalar>
1559  bool Matrix<Scalar>::is_one() const {
1560  if (!is_dense()) return false;
1561 
1562  // Look for non-ones
1563  for (auto&& e : nonzeros()) if (!casadi_limits<Scalar>::is_one(e)) return false;
1564 
1565  return true;
1566  }
1567 
1568  template<typename Scalar>
1569  bool Matrix<Scalar>::is_minus_one() const {
1570  if (!is_dense()) return false;
1571 
1572  // Look for non-minus-ones
1573  for (auto&& e : nonzeros()) if (!casadi_limits<Scalar>::is_minus_one(e)) return false;
1574 
1575  return true;
1576  }
1577 
1578  template<typename Scalar>
1579  bool Matrix<Scalar>::is_zero() const {
1580 
1581  // Look for non-zeros
1582  for (auto&& e : nonzeros()) if (!casadi_limits<Scalar>::is_zero(e)) return false;
1583 
1584  return true;
1585  }
1586 
1587  template<typename Scalar>
1588  bool Matrix<Scalar>::is_eye() const {
1589 
1590  // Make sure that the matrix is diagonal
1591  if (!sparsity().is_diag()) return false;
1592 
1593  // Make sure that all entries are one
1594  for (auto&& e : nonzeros()) if (!casadi_limits<Scalar>::is_one(e)) return false;
1595 
1596  return true;
1597  }
1598 
1599  template<typename Scalar>
1600  bool Matrix<Scalar>::is_equal(const Matrix<Scalar> &x, const Matrix<Scalar> &y,
1601  casadi_int depth) {
1602  // Assert matching dimensions
1603  casadi_assert(x.size() == y.size(), "Dimension mismatch");
1604 
1605  // Project to union of patterns and call recursively if different sparsity
1606  if (x.sparsity() != y.sparsity()) {
1607  Sparsity sp = x.sparsity() + y.sparsity();
1608  return is_equal(project(x, sp), project(y, sp), depth);
1609  }
1610 
1611  // Check individual elements
1612  auto y_it = y.nonzeros().begin();
1613  for (auto&& e : x.nonzeros()) {
1614  if (!casadi_limits<Scalar>::is_equal(e, *y_it++, depth)) return false;
1615  }
1616 
1617  // True if reched this point
1618  return true;
1619  }
1620 
1621  // To avoid overloaded function name conflicts
1622  template<typename Scalar>
1623  inline Matrix<Scalar> mmin_nonstatic(const Matrix<Scalar> &x) {
1624  if (x.is_empty()) return Matrix<Scalar>();
1625  return casadi_mmin(x.ptr(), x.nnz(), x.is_dense());
1626  }
1627 
1628  template<typename Scalar>
1629  Matrix<Scalar> Matrix<Scalar>::mmin(const Matrix<Scalar> &x) {
1630  return mmin_nonstatic(x);
1631  }
1632 
1633  // To avoid overloaded function name conflicts
1634  template<typename Scalar>
1635  inline Matrix<Scalar> mmax_nonstatic(const Matrix<Scalar> &x) {
1636  if (x.is_empty()) return Matrix<Scalar>();
1637  return casadi_mmax(x.ptr(), x.nnz(), x.is_dense());
1638  }
1639 
1640  template<typename Scalar>
1641  Matrix<Scalar> Matrix<Scalar>::mmax(const Matrix<Scalar> &x) {
1642  return mmax_nonstatic(x);
1643  }
1644 
1645  template<typename Scalar>
1646  bool Matrix<Scalar>::has_zeros() const {
1647  // Check if the structural nonzero is known to be zero
1648  for (auto&& e : nonzeros()) if (casadi_limits<Scalar>::is_zero(e)) return true;
1649 
1650  // No known zeros amongst the structurally nonzero entries
1651  return false;
1652  }
1653 
1654  template<typename Scalar>
1655  std::vector<Scalar> Matrix<Scalar>::get_nonzeros() const {
1656  return nonzeros_;
1657  }
1658 
1659  template<typename Scalar>
1660  std::vector<Scalar> Matrix<Scalar>::get_elements() const {
1661  return static_cast< std::vector<Scalar>>(*this);
1662  }
1663 
1664  template<typename Scalar>
1665  std::string Matrix<Scalar>::name() const {
1666  casadi_error("'name' not defined for " + type_name());
1667  }
1668 
1669  template<typename Scalar>
1670  Matrix<Scalar> Matrix<Scalar>::dep(casadi_int ch) const {
1671  casadi_error("'dep' not defined for " + type_name());
1672  }
1673 
1674  template<typename Scalar>
1675  casadi_int Matrix<Scalar>::n_dep() const {
1676  casadi_error("'n_dep' not defined for " + type_name());
1677  }
1678 
1679  template<typename Scalar>
1680  Matrix<Scalar> Matrix<Scalar>::rand( // NOLINT(runtime/threadsafe_fn)
1681  casadi_int nrow,
1682  casadi_int ncol) {
1683  return rand(Sparsity::dense(nrow, ncol)); // NOLINT(runtime/threadsafe_fn)
1684  }
1685 
1686  template<typename Scalar>
1687  Matrix<Scalar> Matrix<Scalar>::rand( // NOLINT(runtime/threadsafe_fn)
1688  const std::pair<casadi_int, casadi_int>& rc) {
1689  return rand(rc.first, rc.second); // NOLINT(runtime/threadsafe_fn)
1690  }
1691 
1692  template<typename Scalar>
1693  Matrix<Scalar> Matrix<Scalar>::project(const Matrix<Scalar>& x,
1694  const Sparsity& sp, bool intersect) {
1695  if (intersect) {
1696  return project(x, sp.intersect(x.sparsity()), false);
1697  } else {
1698  casadi_assert(sp.size()==x.size(), "Dimension mismatch");
1699  Matrix<Scalar> ret = Matrix<Scalar>::zeros(sp);
1700  std::vector<Scalar> w(x.size1());
1701  casadi_project(x.ptr(), x.sparsity(), ret.ptr(), sp, get_ptr(w));
1702  return ret;
1703  }
1704  }
1705 
1706  template<typename Scalar>
1707  void Matrix<Scalar>::set_max_depth(casadi_int eq_depth) {
1708  casadi_error("'set_max_depth' not defined for " + type_name());
1709  }
1710 
1711  template<typename Scalar>
1712  casadi_int Matrix<Scalar>::get_max_depth() {
1713  casadi_error("'get_max_depth' not defined for " + type_name());
1714  }
1715 
1716  template<typename Scalar>
1717  Matrix<Scalar> Matrix<Scalar>::det(const Matrix<Scalar>& x) {
1718  casadi_int n = x.size2();
1719  casadi_assert(n == x.size1(), "matrix must be square");
1720 
1721  // Trivial return if scalar
1722  if (x.is_scalar()) return x;
1723 
1724  // Trivial case 2 x 2
1725  if (n==2) return x(0, 0) * x(1, 1) - x(0, 1) * x(1, 0);
1726 
1727  // Return expression
1728  Matrix<Scalar> ret = 0;
1729 
1730  // Find out which is the best direction to expand along
1731 
1732  // Build up an IM with ones on the non-zeros
1733  Matrix<casadi_int> sp = IM::ones(x.sparsity());
1734 
1735  // Have a count of the nonzeros for each row
1736  Matrix<casadi_int> row_count = Matrix<casadi_int>::sum2(sp);
1737 
1738  // A blank row? determinant is structurally zero
1739  if (!row_count.is_dense()) return 0;
1740 
1741  // Have a count of the nonzeros for each col
1742  Matrix<casadi_int> col_count = Matrix<casadi_int>::sum1(sp).T();
1743 
1744  // A blank col? determinant is structurally zero
1745  if (!row_count.is_dense()) return 0;
1746 
1747  casadi_int min_row = std::distance(row_count.nonzeros().begin(),
1748  std::min_element(row_count.nonzeros().begin(),
1749  row_count.nonzeros().end()));
1750  casadi_int min_col = std::distance(col_count.nonzeros().begin(),
1751  std::min_element(col_count.nonzeros().begin(),
1752  col_count.nonzeros().end()));
1753 
1754  if (min_row <= min_col) {
1755  // Expand along row j
1756  casadi_int j = row_count.sparsity().row(min_row);
1757 
1758  Matrix<Scalar> row = x(j, Slice(0, n));
1759 
1760  std::vector< casadi_int > col_i = row.sparsity().get_col();
1761 
1762  for (casadi_int k=0; k<row.nnz(); ++k) {
1763  // Sum up the cofactors
1764  ret += row->at(k)*cofactor(x, col_i.at(k), j);
1765  }
1766  return ret;
1767  } else {
1768  // Expand along col i
1769  casadi_int i = col_count.sparsity().row(min_col);
1770 
1771  Matrix<Scalar> col = x(Slice(0, n), i);
1772 
1773  const casadi_int* row_i = col.row();
1774 
1775  for (casadi_int k=0; k<col.nnz(); ++k) {
1776  // Sum up the cofactors
1777  ret += col->at(k)*cofactor(x, i, row_i[k]);
1778  }
1779  return ret;
1780  }
1781 
1782  }
1783 
1784  template<typename Scalar>
1785  Matrix<Scalar> Matrix<Scalar>::sum2(const Matrix<Scalar>& x) {
1786  return mtimes(x, Matrix<Scalar>::ones(x.size2(), 1));
1787  }
1788 
1789  template<typename Scalar>
1790  Matrix<Scalar> Matrix<Scalar>::sum1(const Matrix<Scalar>& x) {
1791  return mtimes(Matrix<Scalar>::ones(1, x.size1()), x);
1792  }
1793 
1794  template<typename Scalar>
1795  Matrix<Scalar> Matrix<Scalar>::minor(const Matrix<Scalar>& x,
1796  casadi_int i, casadi_int j) {
1797  casadi_int n = x.size2();
1798  casadi_assert(n == x.size1(), "minor: matrix must be square");
1799 
1800  // Trivial return if scalar
1801  if (n==1) return 1;
1802 
1803  // Remove col i and row j
1804  Matrix<Scalar> M = Matrix<Scalar>(n-1, n-1);
1805 
1806  std::vector<casadi_int> col = x.sparsity().get_col();
1807  const casadi_int* row = x.sparsity().row();
1808 
1809  for (casadi_int k=0; k<x.nnz(); ++k) {
1810  casadi_int i1 = col[k];
1811  casadi_int j1 = row[k];
1812 
1813  if (i1 == i || j1 == j) continue;
1814 
1815  casadi_int i2 = (i1<i)?i1:i1-1;
1816  casadi_int j2 = (j1<j)?j1:j1-1;
1817 
1818  M(j2, i2) = x(j1, i1);
1819  }
1820  return det(M);
1821  }
1822 
1823  template<typename Scalar>
1824  Matrix<Scalar> Matrix<Scalar>::cofactor(const Matrix<Scalar>& A, casadi_int i, casadi_int j) {
1825 
1826  // Calculate the i, j minor
1827  Matrix<Scalar> minor_ij = minor(A, i, j);
1828  // Calculate the cofactor
1829  casadi_int sign_i = 1-2*((i+j) % 2);
1830 
1831  return sign_i * minor_ij;
1832  }
1833 
1834  template<typename Scalar>
1835  Matrix<Scalar> Matrix<Scalar>::adj(const Matrix<Scalar>& x) {
1836  casadi_int n = x.size2();
1837  casadi_assert(n == x.size1(), "adj: matrix must be square");
1838 
1839  // Temporary placeholder
1840  Matrix<Scalar> temp;
1841 
1842  // Cofactor matrix
1843  Matrix<Scalar> C = Matrix<Scalar>(n, n);
1844  for (casadi_int i=0; i<n; ++i)
1845  for (casadi_int j=0; j<n; ++j) {
1846  temp = cofactor(x, i, j);
1847  if (!temp.is_zero()) C(j, i) = temp;
1848  }
1849 
1850  return C.T();
1851  }
1852 
1853  template<typename Scalar>
1854  Matrix<Scalar> Matrix<Scalar>::inv_minor(const Matrix<Scalar>& x) {
1855  // laplace formula
1856  return adj(x)/det(x);
1857  }
1858 
1859  template<typename Scalar>
1860  Matrix<Scalar> Matrix<Scalar>::reshape(const Matrix<Scalar>& x,
1861  casadi_int nrow, casadi_int ncol) {
1862  Sparsity sp = Sparsity::reshape(x.sparsity(), nrow, ncol);
1863  return Matrix<Scalar>(sp, x.nonzeros(), false);
1864  }
1865 
1866  template<typename Scalar>
1867  Matrix<Scalar> Matrix<Scalar>::reshape(const Matrix<Scalar>& x, const Sparsity& sp) {
1868  // quick return if already the right shape
1869  if (sp==x.sparsity()) return x;
1870 
1871  // make sure that the patterns match
1872  casadi_assert_dev(sp.is_reshape(x.sparsity()));
1873 
1874  return Matrix<Scalar>(sp, x.nonzeros(), false);
1875  }
1876 
1877  template<typename Scalar>
1878  Matrix<Scalar> Matrix<Scalar>::sparsity_cast(const Matrix<Scalar>& x, const Sparsity& sp) {
1879  // quick return if already the right shape
1880  if (sp==x.sparsity()) return x;
1881 
1882  casadi_assert_dev(sp.nnz()==x.nnz());
1883 
1884  return Matrix<Scalar>(sp, x.nonzeros(), false);
1885  }
1886 
1887  template<typename Scalar>
1888  Matrix<Scalar> Matrix<Scalar>::trace(const Matrix<Scalar>& x) {
1889  casadi_assert(x.is_square(), "trace: must be square");
1890  Scalar res=0;
1891  const Scalar* d=x.ptr();
1892  casadi_int size2 = x.size2();
1893  const casadi_int *colind=x.colind(), *row=x.row();
1894  for (casadi_int c=0; c<size2; c++) {
1895  for (casadi_int k=colind[c]; k!=colind[c+1]; ++k) {
1896  if (row[k]==c) {
1897  res += d[k];
1898  }
1899  }
1900  }
1901  return res;
1902  }
1903 
1904  template<typename Scalar>
1905  Matrix<Scalar>
1906  Matrix<Scalar>::blockcat(const std::vector< std::vector<Matrix<Scalar> > > &v) {
1907  std::vector< Matrix<Scalar> > ret;
1908  for (casadi_int i=0; i<v.size(); ++i)
1909  ret.push_back(horzcat(v[i]));
1910  return vertcat(ret);
1911  }
1912 
1913  template<typename Scalar>
1914  Matrix<Scalar> Matrix<Scalar>::horzcat(const std::vector<Matrix<Scalar> > &v) {
1915  // Concatenate sparsity patterns
1916  std::vector<Sparsity> sp(v.size());
1917  for (casadi_int i=0; i<v.size(); ++i) sp[i] = v[i].sparsity();
1918  Matrix<Scalar> ret = zeros(Sparsity::horzcat(sp));
1919 
1920  // Copy nonzeros
1921  auto i=ret->begin();
1922  for (auto&& j : v) {
1923  std::copy(j->begin(), j->end(), i);
1924  i += j.nnz();
1925  }
1926  return ret;
1927  }
1928 
1929  template<typename Scalar>
1930  std::vector<Matrix<Scalar> >
1931  Matrix<Scalar>::horzsplit(const Matrix<Scalar>& x, const std::vector<casadi_int>& offset) {
1932  // Split up the sparsity pattern
1933  std::vector<Sparsity> sp = Sparsity::horzsplit(x.sparsity(), offset);
1934 
1935  // Return object
1936  std::vector<Matrix<Scalar> > ret;
1937  ret.reserve(sp.size());
1938 
1939  // Copy data
1940  auto i=x.nonzeros().begin();
1941  for (auto&& j : sp) {
1942  auto i_next = i + j.nnz();
1943  ret.push_back(Matrix<Scalar>(j, std::vector<Scalar>(i, i_next), false));
1944  i = i_next;
1945  }
1946 
1947  // Return the assembled matrix
1948  casadi_assert_dev(i==x.nonzeros().end());
1949  return ret;
1950  }
1951 
1952  template<typename Scalar>
1953  Matrix<Scalar> Matrix<Scalar>::vertcat(const std::vector<Matrix<Scalar> > &v) {
1954  std::vector<Matrix<Scalar> > vT(v.size());
1955  for (casadi_int i=0; i<v.size(); ++i) vT[i] = v[i].T();
1956  return horzcat(vT).T();
1957  }
1958 
1959  template<typename Scalar>
1960  std::vector< Matrix<Scalar> >
1961  Matrix<Scalar>::vertsplit(const Matrix<Scalar>& x, const std::vector<casadi_int>& offset) {
1962  std::vector< Matrix<Scalar> > ret = horzsplit(x.T(), offset);
1963  for (auto&& e : ret) e = e.T();
1964  return ret;
1965  }
1966 
1967  template<typename Scalar>
1968  std::vector< Matrix<Scalar> >
1969  Matrix<Scalar>::diagsplit(const Matrix<Scalar>& x, const std::vector<casadi_int>& offset1,
1970  const std::vector<casadi_int>& offset2) {
1971  // Consistency check
1972  casadi_assert_dev(!offset1.empty());
1973  casadi_assert_dev(offset1.front()==0);
1974  casadi_assert_dev(offset1.back()==x.size1());
1975  casadi_assert_dev(is_monotone(offset1));
1976 
1977  // Consistency check
1978  casadi_assert_dev(!offset2.empty());
1979  casadi_assert_dev(offset2.front()==0);
1980  casadi_assert_dev(offset2.back()==x.size2());
1981  casadi_assert_dev(is_monotone(offset2));
1982 
1983  // Number of outputs
1984  casadi_int n = offset1.size()-1;
1985 
1986  // Return value
1987  std::vector< Matrix<Scalar> > ret;
1988 
1989  // Caveat: this is a very silly implementation
1990  for (casadi_int i=0; i<n; ++i) {
1991  ret.push_back(x(Slice(offset1[i], offset1[i+1]), Slice(offset2[i], offset2[i+1])));
1992  }
1993 
1994  return ret;
1995  }
1996 
1997  template<typename Scalar>
1998  Matrix<Scalar> Matrix<Scalar>::dot(const Matrix<Scalar> &x,
1999  const Matrix<Scalar> &y) {
2000  casadi_assert(x.size()==y.size(), "dot: Dimension mismatch");
2001  if (x.sparsity()!=y.sparsity()) {
2002  Sparsity sp = x.sparsity() * y.sparsity();
2003  return dot(project(x, sp), project(y, sp));
2004  }
2005  return casadi_dot(x.nnz(), x.ptr(), y.ptr());
2006  }
2007 
2008  template<typename Scalar>
2009  Matrix<Scalar> Matrix<Scalar>::all(const Matrix<Scalar>& x) {
2010  if (!x.is_dense()) return false;
2011  Scalar ret=1;
2012  for (casadi_int i=0; i<x.nnz(); ++i) {
2013  ret = ret && x->at(i)==1;
2014  }
2015  return ret;
2016  }
2017 
2018  template<typename Scalar>
2019  Matrix<Scalar> Matrix<Scalar>::any(const Matrix<Scalar>& x) {
2020  if (!x.is_dense()) return false;
2021  Scalar ret=0;
2022  for (casadi_int i=0; i<x.nnz(); ++i) {
2023  ret = ret || x->at(i)==1;
2024  }
2025  return ret;
2026  }
2027 
2028  template<typename Scalar>
2029  Matrix<Scalar> Matrix<Scalar>::norm_1(const Matrix<Scalar>& x) {
2030  return casadi_norm_1(x.nnz(), x.ptr());
2031  }
2032 
2033  template<typename Scalar>
2034  Matrix<Scalar> Matrix<Scalar>::norm_2(const Matrix<Scalar>& x) {
2035  if (x.is_vector()) {
2036  return norm_fro(x);
2037  } else {
2038  casadi_error("2-norms currently only supported for vectors. "
2039  "Did you intend to calculate a Frobenius norms (norm_fro)?");
2040  }
2041  }
2042 
2043  template<typename Scalar>
2044  Matrix<Scalar> Matrix<Scalar>::norm_fro(const Matrix<Scalar>& x) {
2045  return casadi_norm_2(x.nnz(), x.ptr());
2046  }
2047 
2048  template<typename Scalar>
2049  Matrix<Scalar> Matrix<Scalar>::norm_inf(const Matrix<Scalar>& x) {
2050  // Get largest element by absolute value
2051  Matrix<Scalar> s = 0;
2052  for (auto i=x.nonzeros().begin(); i!=x.nonzeros().end(); ++i) {
2053  s = fmax(s, fabs(Matrix<Scalar>(*i)));
2054  }
2055  return s;
2056  }
2057 
2058  template<typename Scalar>
2059  void Matrix<Scalar>::
2060  qr_sparse(const Matrix<Scalar>& A,
2061  Matrix<Scalar>& V, Matrix<Scalar> &R, Matrix<Scalar>& beta,
2062  std::vector<casadi_int>& prinv, std::vector<casadi_int>& pc, bool amd) {
2063  // Calculate the pattern
2064  Sparsity spV, spR;
2065  A.sparsity().qr_sparse(spV, spR, prinv, pc, amd);
2066  // Calculate the nonzeros
2067  casadi_int nrow_ext = spV.size1(), ncol = spV.size2();
2068  V = nan(spV);
2069  R = nan(spR);
2070  beta = nan(ncol, 1);
2071  std::vector<Scalar> w(nrow_ext);
2072  casadi_qr(A.sparsity(), A.ptr(), get_ptr(w), spV, V.ptr(),
2073  spR, R.ptr(), beta.ptr(),
2074  get_ptr(prinv), get_ptr(pc));
2075  }
2076 
2077  template<typename Scalar>
2078  Matrix<Scalar> Matrix<Scalar>::
2079  qr_solve(const Matrix<Scalar>& b, const Matrix<Scalar>& v,
2080  const Matrix<Scalar>& r, const Matrix<Scalar>& beta,
2081  const std::vector<casadi_int>& prinv, const std::vector<casadi_int>& pc,
2082  bool tr) {
2083  // Get dimensions, check consistency
2084  casadi_int ncol = v.size2();
2085  casadi_int nrow = b.size1(), nrhs = b.size2();
2086  casadi_assert(r.size()==v.size(), "'r', 'v' dimension mismatch");
2087  casadi_assert(beta.is_vector() && beta.numel()==ncol, "'beta' has wrong dimension");
2088  casadi_assert(prinv.size()==r.size1(), "'pinv' has wrong dimension");
2089  // Work vector
2090  std::vector<Scalar> w(nrow+ncol);
2091  // Return value
2092  Matrix<Scalar> x = densify(b);
2093  casadi_qr_solve(x.ptr(), nrhs, tr, v.sparsity(), v.ptr(), r.sparsity(), r.ptr(),
2094  beta.ptr(), get_ptr(prinv), get_ptr(pc), get_ptr(w));
2095  return x;
2096  }
2097 
2098  template<typename Scalar>
2099  void Matrix<Scalar>::qr(const Matrix<Scalar>& A,
2100  Matrix<Scalar>& Q, Matrix<Scalar> &R) {
2101  // The following algorithm is taken from J. Demmel:
2102  // Applied Numerical Linear Algebra (algorithm 3.1.)
2103  casadi_assert(A.size1()>=A.size2(), "qr: fewer rows than columns");
2104 
2105  // compute Q and R column by column
2106  Q = R = Matrix<Scalar>();
2107  for (casadi_int i=0; i<A.size2(); ++i) {
2108  // Initialize qi to be the i-th column of *this
2109  Matrix<Scalar> ai = A(Slice(), i);
2110  Matrix<Scalar> qi = ai;
2111  // The i-th column of R
2112  Matrix<Scalar> ri = Matrix<Scalar>(A.size2(), 1);
2113 
2114  // subtract the projection of qi in the previous directions from ai
2115  for (casadi_int j=0; j<i; ++j) {
2116 
2117  // Get the j-th column of Q
2118  Matrix<Scalar> qj = Q(Slice(), j); // NOLINT(cppcoreguidelines-slicing)
2119 
2120  ri(j, 0) = mtimes(qi.T(), qj); // Modified Gram-Schmidt
2121  // ri[j] = dot(qj, ai); // Classical Gram-Schmidt
2122 
2123  // Remove projection in direction j
2124  if (ri.has_nz(j, 0))
2125  qi -= ri(j, 0) * qj;
2126  }
2127 
2128  // Normalize qi
2129  ri(i, 0) = norm_2(qi);
2130  qi /= ri(i, 0);
2131 
2132  // Update R and Q
2133  Q = Matrix<Scalar>::horzcat({Q, qi});
2134  R = Matrix<Scalar>::horzcat({R, ri});
2135  }
2136  }
2137 
2138  template<typename Scalar>
2139  void Matrix<Scalar>::ldl(const Matrix<Scalar>& A, Matrix<Scalar> &D,
2140  Matrix<Scalar>& LT, std::vector<casadi_int>& p, bool amd) {
2141  // Symbolic factorization
2142  Sparsity Lt_sp = A.sparsity().ldl(p, amd);
2143 
2144  // Get dimension
2145  casadi_int n=A.size1();
2146 
2147  // Calculate entries in L and D
2148  std::vector<Scalar> D_nz(n), L_nz(Lt_sp.nnz()), w(n);
2149  casadi_ldl(A.sparsity(), get_ptr(A.nonzeros()), Lt_sp,
2150  get_ptr(L_nz), get_ptr(D_nz), get_ptr(p), get_ptr(w));
2151 
2152  // Assemble L and D
2153  LT = Matrix<Scalar>(Lt_sp, L_nz);
2154  D = D_nz;
2155  }
2156 
2157  template<typename Scalar>
2158  Matrix<Scalar> Matrix<Scalar>::
2159  ldl_solve(const Matrix<Scalar>& b, const Matrix<Scalar>& D, const Matrix<Scalar>& LT,
2160  const std::vector<casadi_int>& p) {
2161  // Get dimensions, check consistency
2162  casadi_int n = b.size1(), nrhs = b.size2();
2163  casadi_assert(p.size()==n, "'p' has wrong dimension");
2164  casadi_assert(LT.size1()==n && LT.size2()==n, "'LT' has wrong dimension");
2165  casadi_assert(D.is_vector() && D.numel()==n, "'D' has wrong dimension");
2166  // Solve for all right-hand-sides
2167  Matrix<Scalar> x = densify(b);
2168  std::vector<Scalar> w(n);
2169  casadi_ldl_solve(x.ptr(), nrhs, LT.sparsity(), LT.ptr(), D.ptr(), get_ptr(p), get_ptr(w));
2170  return x;
2171  }
2172 
2173  template<typename Scalar>
2174  Matrix<Scalar> Matrix<Scalar>::nullspace(const Matrix<Scalar>& A) {
2175  Matrix<Scalar> X = A;
2176  casadi_int n = X.size1();
2177  casadi_int m = X.size2();
2178  casadi_assert(m>=n, "nullspace(): expecting a flat matrix (more columns than rows), "
2179  "but got " + str(X.dim()) + ".");
2180 
2181  Matrix<Scalar> seed = DM::eye(m)(Slice(0, m), Slice(n, m)); // NOLINT(cppcoreguidelines-slicing)
2182 
2183  std::vector< Matrix<Scalar> > us;
2184  std::vector< Matrix<Scalar> > betas;
2185 
2186  Matrix<Scalar> beta;
2187 
2188  for (casadi_int i=0;i<n;++i) {
2189  Matrix<Scalar> x = X(i, Slice(i, m)); // NOLINT(cppcoreguidelines-slicing)
2190  Matrix<Scalar> u = Matrix<Scalar>(x);
2191  Matrix<Scalar> sigma = sqrt(sum2(x*x));
2192  const Matrix<Scalar>& x0 = x(0, 0);
2193  u(0, 0) = 1;
2194 
2195  Matrix<Scalar> b = -copysign(sigma, x0);
2196 
2197  u(Slice(0), Slice(1, m-i))*= 1/(x0-b);
2198  beta = 1-x0/b;
2199 
2200  X(Slice(i, n), Slice(i, m)) -=
2201  beta*mtimes(mtimes(X(Slice(i, n), Slice(i, m)), u.T()), u);
2202  us.push_back(u);
2203  betas.push_back(beta);
2204  }
2205 
2206  for (casadi_int i=n-1;i>=0;--i) {
2207  seed(Slice(i, m), Slice(0, m-n)) -=
2208  betas[i]*mtimes(us[i].T(), mtimes(us[i], seed(Slice(i, m), Slice(0, m-n))));
2209  }
2210 
2211  return seed;
2212 
2213  }
2214 
2215  template<typename Scalar>
2216  Matrix<Scalar> Matrix<Scalar>::chol(const Matrix<Scalar>& A) {
2217  // Perform an LDL transformation
2218  Matrix<Scalar> D, LT;
2219  std::vector<casadi_int> p;
2220  ldl(A, D, LT, p, false);
2221  // Add unit diagonal
2222  LT += Matrix<Scalar>::eye(D.size1());
2223  // Get the cholesky factor: R*R' = L*D*L' = (sqrt(D)*L')'*(sqrt(D)*L')
2224  return mtimes(diag(sqrt(D)), LT);
2225  }
2226 
2227  template<typename Scalar>
2228  Matrix<Scalar> Matrix<Scalar>::solve(const Matrix<Scalar>& a, const Matrix<Scalar>& b) {
2229  // check dimensions
2230  casadi_assert(a.size1() == b.size1(), "solve Ax=b: dimension mismatch: b has "
2231  + str(b.size1()) + " rows while A has " + str(a.size1()) + ".");
2232  casadi_assert(a.size1() == a.size2(), "solve: A not square but " + str(a.dim()));
2233 
2234  if (a.is_tril()) {
2235  // forward substitution if lower triangular
2236  Matrix<Scalar> x = b;
2237  const casadi_int* Arow = a.row();
2238  const casadi_int* Acolind = a.colind();
2239  const std::vector<Scalar> & Adata = a.nonzeros();
2240  for (casadi_int i=0; i<a.size2(); ++i) { // loop over columns forwards
2241  for (casadi_int k=0; k<b.size2(); ++k) { // for every right hand side
2242  if (!x.has_nz(i, k)) continue;
2243  x(i, k) /= a(i, i);
2244  for (casadi_int kk=Acolind[i+1]-1; kk>=Acolind[i] && Arow[kk]>i; --kk) {
2245  casadi_int j = Arow[kk];
2246  x(j, k) -= Adata[kk]*x(i, k);
2247  }
2248  }
2249  }
2250  return x;
2251  } else if (a.is_triu()) {
2252  // backward substitution if upper triangular
2253  Matrix<Scalar> x = b;
2254  const casadi_int* Arow = a.row();
2255  const casadi_int* Acolind = a.colind();
2256  const std::vector<Scalar> & Adata = a.nonzeros();
2257  for (casadi_int i=a.size2()-1; i>=0; --i) { // loop over columns backwards
2258  for (casadi_int k=0; k<b.size2(); ++k) { // for every right hand side
2259  if (!x.has_nz(i, k)) continue;
2260  x(i, k) /= a(i, i);
2261  for (casadi_int kk=Acolind[i]; kk<Acolind[i+1] && Arow[kk]<i; ++kk) {
2262  casadi_int j = Arow[kk];
2263  x(j, k) -= Adata[kk]*x(i, k);
2264  }
2265  }
2266  }
2267  return x;
2268  } else if (a.has_zeros()) {
2269 
2270  // If there are structurally nonzero entries that are known to be zero,
2271  // remove these and rerun the algorithm
2272  return solve(sparsify(a), b);
2273 
2274  } else {
2275 
2276  // Make a BLT transformation of A
2277  std::vector<casadi_int> rowperm, colperm, rowblock, colblock;
2278  std::vector<casadi_int> coarse_rowblock, coarse_colblock;
2279  a.sparsity().btf(rowperm, colperm, rowblock, colblock,
2280  coarse_rowblock, coarse_colblock);
2281 
2282  // Permute the right hand side
2283  Matrix<Scalar> bperm = b(rowperm, Slice());
2284 
2285  // Permute the linear system
2286  Matrix<Scalar> Aperm = a(rowperm, colperm);
2287 
2288  // Solution
2289  Matrix<Scalar> xperm;
2290 
2291  // Solve permuted system
2292  if (Aperm.is_tril()) {
2293 
2294  // Forward substitution if lower triangular
2295  xperm = solve(Aperm, bperm);
2296 
2297  } else if (a.size2()<=3) {
2298 
2299  // Form inverse by minor expansion and multiply if very small (up to 3-by-3)
2300  xperm = mtimes(inv_minor(Aperm), bperm);
2301 
2302  } else {
2303 
2304  // Make a QR factorization
2305  Matrix<Scalar> Q, R;
2306  qr(Aperm, Q, R);
2307 
2308  // Solve the factorized system (note that solve will now be fast since it is triangular)
2309  xperm = solve(R, mtimes(Q.T(), bperm));
2310  }
2311 
2312  // get the inverted column permutation
2313  std::vector<casadi_int> inv_colperm(colperm.size());
2314  for (casadi_int k=0; k<colperm.size(); ++k)
2315  inv_colperm[colperm[k]] = k;
2316 
2317  // Permute back the solution and return
2318  Matrix<Scalar> x = xperm(inv_colperm, Slice()); // NOLINT(cppcoreguidelines-slicing)
2319  return x;
2320  }
2321  }
2322 
2323  template<typename Scalar>
2324  Matrix<Scalar> Matrix<Scalar>::
2325  solve(const Matrix<Scalar>& a, const Matrix<Scalar>& b,
2326  const std::string& lsolver, const Dict& dict) {
2327  casadi_error("'solve' with plugin not defined for " + type_name());
2328  return Matrix<Scalar>();
2329  }
2330 
2331  template<typename Scalar>
2332  Matrix<Scalar> Matrix<Scalar>::
2333  inv(const Matrix<Scalar>& a) {
2334  return solve(a, Matrix<Scalar>::eye(a.size1()));
2335  }
2336 
2337  template<typename Scalar>
2338  Matrix<Scalar> Matrix<Scalar>::
2339  inv(const Matrix<Scalar>& a,
2340  const std::string& lsolver, const Dict& dict) {
2341  casadi_error("'inv' with plugin not defined for " + type_name());
2342  return Matrix<Scalar>();
2343  }
2344 
2345  template<typename Scalar>
2346  Matrix<Scalar> Matrix<Scalar>::pinv(const Matrix<Scalar>& A) {
2347  if (A.size2()>=A.size1()) {
2348  return solve(mtimes(A, A.T()), A).T();
2349  } else {
2350  return solve(mtimes(A.T(), A), A.T());
2351  }
2352  }
2353 
2354  template<typename Scalar>
2355  Matrix<Scalar> Matrix<Scalar>::
2356  pinv(const Matrix<Scalar>& A, const std::string& lsolver, const Dict& dict) {
2357  casadi_error("'solve' not defined for " + type_name());
2358  return Matrix<Scalar>();
2359  }
2360 
2361  template<typename Scalar>
2362  Matrix<Scalar> Matrix<Scalar>::
2363  expm_const(const Matrix<Scalar>& A, const Matrix<Scalar>& t) {
2364  casadi_error("'solve' not defined for " + type_name());
2365  return Matrix<Scalar>();
2366  }
2367 
2368  template<typename Scalar>
2369  Matrix<Scalar> Matrix<Scalar>::
2370  expm(const Matrix<Scalar>& A) {
2371  casadi_error("'solve' not defined for " + type_name());
2372  return Matrix<Scalar>();
2373  }
2374 
2375  template<typename Scalar>
2376  Matrix<Scalar> Matrix<Scalar>::kron(const Matrix<Scalar>& a, const Matrix<Scalar>& b) {
2377  std::vector<Scalar> ret(a.nnz()*b.nnz());
2378  casadi_kron(get_ptr(a), a.sparsity(), get_ptr(b), b.sparsity(), get_ptr(ret));
2379 
2380  Sparsity sp_ret = Sparsity::kron(a.sparsity(), b.sparsity());
2381  return Matrix<Scalar>(sp_ret, ret, false);
2382  }
2383 
2384  template<typename Scalar>
2385  Matrix<Scalar> Matrix<Scalar>::diag(const Matrix<Scalar>& A) {
2386  // Nonzero mapping
2387  std::vector<casadi_int> mapping;
2388  // Get the sparsity
2389  Sparsity sp = A.sparsity().get_diag(mapping);
2390 
2391  Matrix<Scalar> ret = zeros(sp);
2392 
2393  for (casadi_int k=0; k<mapping.size(); k++) ret.nz(k) = A.nz(mapping[k]);
2394  return ret;
2395  }
2396 
2400  template<typename Scalar>
2401  Matrix<Scalar> Matrix<Scalar>::diagcat(const std::vector< Matrix<Scalar> > &A) {
2402  std::vector<Scalar> data;
2403 
2404  std::vector<Sparsity> sp;
2405  for (casadi_int i=0;i<A.size();++i) {
2406  data.insert(data.end(), A[i].nonzeros().begin(), A[i].nonzeros().end());
2407  sp.push_back(A[i].sparsity());
2408  }
2409 
2410  return Matrix<Scalar>(Sparsity::diagcat(sp), data, false);
2411  }
2412 
2413  template<typename Scalar>
2414  Matrix<Scalar> Matrix<Scalar>::unite(const Matrix<Scalar>& A, const Matrix<Scalar>& B) {
2415  // Join the sparsity patterns
2416  std::vector<unsigned char> mapping;
2417  Sparsity sp = A.sparsity().unite(B.sparsity(), mapping);
2418 
2419  // Create return matrix
2420  Matrix<Scalar> ret = zeros(sp);
2421 
2422  // Copy sparsity
2423  casadi_int elA=0, elB=0;
2424  for (casadi_int k=0; k<mapping.size(); ++k) {
2425  if (mapping[k]==1) {
2426  ret.nonzeros()[k] = A.nonzeros()[elA++];
2427  } else if (mapping[k]==2) {
2428  ret.nonzeros()[k] = B.nonzeros()[elB++];
2429  } else {
2430  casadi_error("Pattern intersection not empty");
2431  }
2432  }
2433 
2434  casadi_assert_dev(A.nnz()==elA);
2435  casadi_assert_dev(B.nnz()==elB);
2436 
2437  return ret;
2438  }
2439 
2440  template<typename Scalar>
2441  Matrix<Scalar> Matrix<Scalar>::polyval(const Matrix<Scalar>& p, const Matrix<Scalar>& x) {
2442  casadi_assert(p.is_dense(), "polynomial coefficients vector must be dense");
2443  casadi_assert(p.is_vector() && p.nnz()>0, "polynomial coefficients must be a vector");
2444  Matrix<Scalar> ret = x;
2445  for (auto&& e : ret.nonzeros()) {
2446  e = casadi_polyval(p.ptr(), p.numel()-1, e);
2447  }
2448  return ret;
2449  }
2450 
2451  template<typename Scalar>
2452  Matrix<Scalar> Matrix<Scalar>::norm_inf_mul(const Matrix<Scalar>& x,
2453  const Matrix<Scalar>& y) {
2454  casadi_assert(y.size1()==x.size2(), "Dimension error. Got " + x.dim()
2455  + " times " + y.dim() + ".");
2456 
2457  // Allocate work vectors
2458  std::vector<Scalar> dwork(x.size1());
2459  std::vector<casadi_int> iwork(x.size1()+1+y.size2());
2460 
2461  // Call C runtime
2462  return casadi_norm_inf_mul(x.ptr(), x.sparsity(), y.ptr(), y.sparsity(),
2463  get_ptr(dwork), get_ptr(iwork));
2464  }
2465 
2466  template<typename Scalar>
2467  void Matrix<Scalar>::expand(const Matrix<Scalar>& ex,
2468  Matrix<Scalar> &weights, Matrix<Scalar>& terms) {
2469  casadi_error("'expand' not defined for " + type_name());
2470  }
2471 
2472  template<typename Scalar>
2473  Matrix<Scalar> Matrix<Scalar>::pw_const(const Matrix<Scalar>& ex,
2474  const Matrix<Scalar>& tval,
2475  const Matrix<Scalar>& val) {
2476  casadi_error("'pw_const' not defined for " + type_name());
2477  return Matrix<Scalar>();
2478  }
2479 
2480  template<typename Scalar>
2481  Matrix<Scalar> Matrix<Scalar>::pw_lin(const Matrix<Scalar>& ex,
2482  const Matrix<Scalar>& tval,
2483  const Matrix<Scalar>& val) {
2484  casadi_error("'pw_lin' not defined for " + type_name());
2485  return Matrix<Scalar>();
2486  }
2487 
2488  template<typename Scalar>
2489  Matrix<Scalar> Matrix<Scalar>::if_else(const Matrix<Scalar> &cond,
2490  const Matrix<Scalar> &if_true,
2491  const Matrix<Scalar> &if_false,
2492  bool short_circuit) {
2493  return if_else_zero(cond, if_true) + if_else_zero(!cond, if_false);
2494  }
2495 
2496  template<typename Scalar>
2497  Matrix<Scalar> Matrix<Scalar>::conditional(const Matrix<Scalar>& ind,
2498  const std::vector<Matrix<Scalar> >& x,
2499  const Matrix<Scalar>& x_default,
2500  bool short_circuit) {
2501  casadi_assert(!short_circuit,
2502  "Short-circuiting 'conditional' not supported for " + type_name());
2503  casadi_assert(ind.is_scalar(true),
2504  "conditional: first argument must be scalar. Got " + ind.dim()+ " instead.");
2505 
2506  Matrix<Scalar> ret = x_default;
2507  for (casadi_int k=0; k<x.size(); ++k) {
2508  ret = if_else(ind==k, x[k], ret, short_circuit);
2509  }
2510  return ret;
2511  }
2512 
2513  template<typename Scalar>
2514  Matrix<Scalar> Matrix<Scalar>::heaviside(const Matrix<Scalar>& x) {
2515  return (1+sign(x))/2;
2516  }
2517 
2518  template<typename Scalar>
2519  Matrix<Scalar> Matrix<Scalar>::rectangle(const Matrix<Scalar>& x) {
2520  return 0.5*(sign(x+0.5)-sign(x-0.5));
2521  }
2522 
2523  template<typename Scalar>
2524  Matrix<Scalar> Matrix<Scalar>::triangle(const Matrix<Scalar>& x) {
2525  return rectangle(x/2)*(1-fabs(x));
2526  }
2527 
2528  template<typename Scalar>
2529  Matrix<Scalar> Matrix<Scalar>::ramp(const Matrix<Scalar>& x) {
2530  return x*heaviside(x);
2531  }
2532 
2533  template<typename Scalar>
2534  Matrix<Scalar> Matrix<Scalar>::
2535  gauss_quadrature(const Matrix<Scalar> &f,
2536  const Matrix<Scalar> &x, const Matrix<Scalar> &a,
2537  const Matrix<Scalar> &b, casadi_int order) {
2538  return gauss_quadrature(f, x, a, b, order, Matrix<Scalar>());
2539  }
2540 
2541  template<typename Scalar>
2542  Matrix<Scalar> Matrix<Scalar>::gauss_quadrature(const Matrix<Scalar>& f,
2543  const Matrix<Scalar>& x,
2544  const Matrix<Scalar>& a,
2545  const Matrix<Scalar>& b, casadi_int order,
2546  const Matrix<Scalar>& w) {
2547  casadi_error("'gauss_quadrature' not defined for " + type_name());
2548  return Matrix<Scalar>();
2549  }
2550 
2551  template<typename Scalar>
2552  Matrix<Scalar> Matrix<Scalar>::simplify(const Matrix<Scalar> &x) {
2553  return x;
2554  }
2555 
2556  template<typename Scalar>
2557  Matrix<Scalar> Matrix<Scalar>::substitute(const Matrix<Scalar>& ex,
2558  const Matrix<Scalar>& v,
2559  const Matrix<Scalar>& vdef) {
2560  casadi_error("'substitute' not defined for " + type_name());
2561  return Matrix<Scalar>();
2562  }
2563 
2564  template<typename Scalar>
2565  std::vector<Matrix<Scalar> >
2566  Matrix<Scalar>::substitute(const std::vector<Matrix<Scalar> >& ex,
2567  const std::vector<Matrix<Scalar> >& v,
2568  const std::vector<Matrix<Scalar> >& vdef) {
2569  casadi_error("'substitute' not defined for " + type_name());
2570  return std::vector<Matrix<Scalar> >();
2571  }
2572 
2573  template<typename Scalar>
2574  void Matrix<Scalar>::substitute_inplace(const std::vector<Matrix<Scalar> >& v,
2575  std::vector<Matrix<Scalar> >& vdef,
2576  std::vector<Matrix<Scalar> >& ex,
2577  bool reverse) {
2578  casadi_error("'substitute_inplace' not defined for " + type_name());
2579  }
2580 
2581  template<typename Scalar>
2582  bool Matrix<Scalar>::depends_on(const Matrix<Scalar> &x, const Matrix<Scalar> &arg) {
2583  casadi_error("'depends_on' not defined for " + type_name());
2584  return false;
2585  }
2586 
2587  template<typename Scalar>
2588  std::vector< Matrix<Scalar> > Matrix<Scalar>::cse(const std::vector< Matrix<Scalar> >& e) {
2589  casadi_error("'cse' not defined for " + type_name());
2590  return {};
2591  }
2592 
2593 
2594  template<typename Scalar>
2595  Matrix<Scalar> Matrix<Scalar>::
2596  jacobian(const Matrix<Scalar> &f, const Matrix<Scalar> &x, const Dict& opts) {
2597  casadi_error("'jacobian' not defined for " + type_name());
2598  return Matrix<Scalar>();
2599  }
2600 
2601  template<typename Scalar>
2602  Matrix<Scalar> Matrix<Scalar>::hessian(const Matrix<Scalar> &f,
2603  const Matrix<Scalar> &x,
2604  const Dict& opts) {
2605  casadi_error("'hessian' not defined for " + type_name());
2606  return Matrix<Scalar>();
2607  }
2608 
2609  template<typename Scalar>
2610  Matrix<Scalar> Matrix<Scalar>::hessian(const Matrix<Scalar> &f,
2611  const Matrix<Scalar> &x,
2612  Matrix<Scalar> &g,
2613  const Dict& opts) {
2614  casadi_error("'hessian' not defined for " + type_name());
2615  return Matrix<Scalar>();
2616  }
2617 
2618  template<typename Scalar>
2619  std::vector<std::vector<Matrix<Scalar> > >
2621  forward(const std::vector<Matrix<Scalar> > &ex,
2622  const std::vector<Matrix<Scalar> > &arg,
2623  const std::vector<std::vector<Matrix<Scalar> > > &v,
2624  const Dict& opts) {
2625  casadi_error("'forward' not defined for " + type_name());
2626  }
2627 
2628  template<typename Scalar>
2629  std::vector<std::vector<Matrix<Scalar> > >
2631  reverse(const std::vector<Matrix<Scalar> > &ex,
2632  const std::vector<Matrix<Scalar> > &arg,
2633  const std::vector<std::vector<Matrix<Scalar> > > &v,
2634  const Dict& opts) {
2635  casadi_error("'reverse' not defined for " + type_name());
2636  }
2637 
2638  template<typename Scalar>
2639  std::vector<bool>
2640  Matrix<Scalar>::which_depends(const Matrix<Scalar> &expr, const Matrix<Scalar> &var,
2641  casadi_int order, bool tr) {
2642  casadi_error("'which_depends' not defined for " + type_name());
2643  return std::vector<bool>();
2644  }
2645 
2646  template<typename Scalar>
2647  Sparsity
2648  Matrix<Scalar>::jacobian_sparsity(const Matrix<Scalar> &f, const Matrix<Scalar> &x) {
2649  casadi_error("'jacobian_sparsity' not defined for " + type_name());
2650  return Sparsity();
2651  }
2652 
2653  template<typename Scalar>
2654  Matrix<Scalar> Matrix<Scalar>::taylor(const Matrix<Scalar>& f,
2655  const Matrix<Scalar>& x,
2656  const Matrix<Scalar>& a, casadi_int order) {
2657  casadi_error("'taylor' not defined for " + type_name());
2658  return Matrix<Scalar>();
2659  }
2660 
2661  template<typename Scalar>
2662  Matrix<Scalar> Matrix<Scalar>::mtaylor(const Matrix<Scalar>& f,
2663  const Matrix<Scalar>& x,
2664  const Matrix<Scalar>& a, casadi_int order) {
2665  casadi_error("'mtaylor' not defined for " + type_name());
2666  return Matrix<Scalar>();
2667  }
2668 
2669  template<typename Scalar>
2670  Matrix<Scalar> Matrix<Scalar>::mtaylor(const Matrix<Scalar>& f,
2671  const Matrix<Scalar>& x,
2672  const Matrix<Scalar>& a, casadi_int order,
2673  const std::vector<casadi_int>&order_contributions) {
2674  casadi_error("'mtaylor' not defined for " + type_name());
2675  return Matrix<Scalar>();
2676  }
2677 
2678  template<typename Scalar>
2679  casadi_int Matrix<Scalar>::n_nodes(const Matrix<Scalar>& x) {
2680  casadi_error("'n_nodes' not defined for " + type_name());
2681  return 0;
2682  }
2683 
2684  template<typename Scalar>
2685  std::string
2686  Matrix<Scalar>::print_operator(const Matrix<Scalar>& x,
2687  const std::vector<std::string>& args) {
2688  casadi_error("'print_operator' not defined for " + type_name());
2689  return std::string();
2690  }
2691 
2692  template<typename Scalar>
2693  std::vector<Matrix<Scalar> > Matrix<Scalar>::symvar(const Matrix<Scalar>& x) {
2694  casadi_error("'symvar' not defined for " + type_name());
2695  return std::vector<Matrix<Scalar> >();
2696  }
2697 
2698  template<typename Scalar>
2699  void Matrix<Scalar>::extract(std::vector<Matrix<Scalar>>& ex, std::vector<Matrix<Scalar>>& v,
2700  std::vector<Matrix<Scalar>>& vdef, const Dict& opts) {
2701  casadi_error("'extract' not defined for " + type_name());
2702  }
2703 
2704  template<typename Scalar>
2705  void Matrix<Scalar>::shared(std::vector<Matrix<Scalar> >& ex,
2706  std::vector<Matrix<Scalar> >& v,
2707  std::vector<Matrix<Scalar> >& vdef,
2708  const std::string& v_prefix,
2709  const std::string& v_suffix) {
2710  casadi_error("'shared' not defined for " + type_name());
2711  }
2712 
2713  template<typename Scalar>
2714  Matrix<Scalar> Matrix<Scalar>::poly_coeff(const Matrix<Scalar>& f,
2715  const Matrix<Scalar>&x) {
2716  casadi_error("'poly_coeff' not defined for " + type_name());
2717  }
2718 
2719  template<typename Scalar>
2720  Matrix<Scalar> Matrix<Scalar>::poly_roots(const Matrix<Scalar>& p) {
2721  casadi_error("'poly_roots' not defined for " + type_name());
2722  }
2723 
2724  template<typename Scalar>
2725  Matrix<Scalar> Matrix<Scalar>::eig_symbolic(const Matrix<Scalar>& m) {
2726  casadi_error("'eig_symbolic' not defined for " + type_name());
2727  }
2728 
2729  template<typename Scalar>
2730  DM Matrix<Scalar>::evalf(const Matrix<Scalar>& m) {
2731  Function f("f", std::vector<SX>{}, std::vector<SX>{m});
2732  return f(std::vector<DM>{})[0];
2733  }
2734 
2735  template<typename Scalar>
2736  Matrix<Scalar> Matrix<Scalar>::sparsify(const Matrix<Scalar>& x, double tol) {
2737  // Quick return if there are no entries to be removed
2738  bool remove_nothing = true;
2739  for (auto it=x.nonzeros().begin(); it!=x.nonzeros().end() && remove_nothing; ++it) {
2740  remove_nothing = !casadi_limits<Scalar>::is_almost_zero(*it, tol);
2741  }
2742  if (remove_nothing) return x;
2743 
2744  // Get the current sparsity pattern
2745  casadi_int size1 = x.size1();
2746  casadi_int size2 = x.size2();
2747  const casadi_int* colind = x.colind();
2748  const casadi_int* row = x.row();
2749 
2750  // Construct the new sparsity pattern
2751  std::vector<casadi_int> new_colind(1, 0), new_row;
2752  std::vector<Scalar> new_data;
2753 
2754  // Loop over the columns
2755  for (casadi_int cc=0; cc<size2; ++cc) {
2756  // Loop over existing nonzeros
2757  for (casadi_int el=colind[cc]; el<colind[cc+1]; ++el) {
2758  // If it is not known to be a zero
2759  if (!casadi_limits<Scalar>::is_almost_zero(x->at(el), tol)) {
2760  // Save the nonzero in its new location
2761  new_data.push_back(x->at(el));
2762 
2763  // Add to pattern
2764  new_row.push_back(row[el]);
2765  }
2766  }
2767  // Save the new column offset
2768  new_colind.push_back(new_row.size());
2769  }
2770 
2771  // Construct the sparsity pattern
2772  Sparsity sp(size1, size2, new_colind, new_row);
2773 
2774  // Construct matrix and return
2775  return Matrix<Scalar>(sp, new_data);
2776  }
2777 
2778 
2779  template<typename Scalar>
2780  std::vector<Matrix<Scalar> > Matrix<Scalar>::get_input(const Function& f) {
2781  casadi_error("'get_input' not defined for " + type_name());
2782  }
2783 
2784  template<typename Scalar>
2785  std::vector<Matrix<Scalar> > Matrix<Scalar>::get_free(const Function& f) {
2786  casadi_error("'get_free' not defined for " + type_name());
2787  }
2788 
2789  template<typename Scalar>
2790  Matrix<Scalar>::operator double() const {
2791  casadi_assert_dev(is_scalar());
2792  return static_cast<double>(scalar());
2793  }
2794 
2795  template<typename Scalar>
2796  Matrix<Scalar>::operator casadi_int() const {
2797  casadi_assert_dev(is_scalar());
2798  return static_cast<casadi_int>(scalar());
2799  }
2800 
2801  template<typename Scalar>
2802  Matrix<Scalar> Matrix<Scalar>::_sym(const std::string& name, const Sparsity& sp) {
2803  casadi_error("'sym' not defined for " + type_name());
2804  }
2805 
2806  template<typename Scalar>
2807  Matrix<Scalar> Matrix<Scalar>::rand(const Sparsity& sp) { // NOLINT(runtime/threadsafe_fn)
2808 
2809  casadi_error("'rand' not defined for " + type_name());
2810  }
2811 
2812  template<typename Scalar>
2813  std::string Matrix<Scalar>::serialize() const {
2814  std::stringstream ss;
2815  serialize(ss);
2816  return ss.str();
2817  }
2818 
2819  template<typename Scalar>
2820  void Matrix<Scalar>::serialize(SerializingStream& s) const {
2821  s.pack("Matrix::sparsity", sparsity());
2822  s.pack("Matrix::nonzeros", nonzeros());
2823  }
2824 
2825  template<typename Scalar>
2826  Matrix<Scalar> Matrix<Scalar>::deserialize(DeserializingStream& s) {
2827  Sparsity sp;
2828  s.unpack("Matrix::sparsity", sp);
2829  std::vector<Scalar> nz;
2830  s.unpack("Matrix::nonzeros", nz);
2831  return Matrix<Scalar>(sp, nz, false);
2832  }
2833 
2834  template<typename Scalar>
2835  void Matrix<Scalar>::serialize(std::ostream &stream) const {
2836  SerializingStream s(stream);
2837  serialize(s);
2838  }
2839 
2840  template<typename Scalar>
2841  Matrix<Scalar> Matrix<Scalar>::deserialize(std::istream &stream) {
2842  DeserializingStream s(stream);
2843  return Matrix<Scalar>::deserialize(s);
2844  }
2845 
2846  template<typename Scalar>
2847  Matrix<Scalar> Matrix<Scalar>::deserialize(const std::string& s) {
2848  std::stringstream ss;
2849  ss << s;
2850  return deserialize(ss);
2851  }
2852 
2853 
2854 } // namespace casadi
2855 
2856 #endif // CASADI_MATRIX_IMPL_HPP
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)
static Matrix< Scalar > ones(casadi_int nrow=1, casadi_int ncol=1)
Create a dense matrix or a matrix with specified sparsity with all entries one.
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.
Definition: matrix_decl.hpp:92
bool has_nz(casadi_int rr, casadi_int cc) const
Returns true if the matrix has a non-zero at location rr, cc.
Definition: matrix_impl.hpp:65
bool has_zeros() const
Check if the matrix has any zero entries which are not structural zeros.
void print_split(std::vector< std::string > &nz, std::vector< std::string > &inter) const
Get strings corresponding to the nonzeros and the interdependencies.
bool is_one() const
check if the matrix is 1 (note that false negative answers are possible)
void remove(const std::vector< casadi_int > &rr, const std::vector< casadi_int > &cc)
Remove columns and rows.
bool is_regular() const
Checks if expression does not contain NaN or Inf.
Matrix< Scalar > T() const
Transpose the matrix.
static void set_max_depth(casadi_int eq_depth=1)
Set or reset the depth to which equalities are being checked for simplifications.
static void set_precision(casadi_int precision)
Set the 'precision, width & scientific' used in printing and serializing to streams.
Definition: matrix_impl.hpp:39
void get(Matrix< Scalar > &m, bool ind1, const Slice &rr) const
void resize(casadi_int nrow, casadi_int ncol)
Sparsity get_sparsity() const
Get an owning reference to the sparsity pattern.
void print_sparse(std::ostream &stream, bool truncate=true) const
Print sparse matrix style.
static void set_width(casadi_int width)
Definition: matrix_impl.hpp:42
static Matrix< Scalar > deserialize(std::istream &stream)
Build Sparsity from serialization.
casadi_int element_hash() const
Returns a number that is unique for a given symbolic scalar.
Matrix()
constructors
bool is_commutative() const
Check whether a binary SX is commutative.
void set(const Matrix< Scalar > &m, bool ind1, const Slice &rr)
bool is_symbolic() const
Check if symbolic (Dense)
static std::vector< Matrix< Scalar > > get_free(const Function &f)
Get free.
static casadi_int get_max_depth()
Get the depth to which equalities are being checked for simplifications.
Matrix< Scalar > operator+() const
bool is_smooth() const
Check if smooth.
static std::string type_name()
Get name of the class.
static Matrix< Scalar > nan(const Sparsity &sp)
create a matrix with all nan
bool is_minus_one() const
check if the matrix is -1 (note that false negative answers are possible)
void to_file(const std::string &filename, const std::string &format="") const
static void set_scientific(bool scientific)
Definition: matrix_impl.hpp:45
static Matrix< Scalar > triplet(const std::vector< casadi_int > &row, const std::vector< casadi_int > &col, const Matrix< Scalar > &d)
Construct a sparse matrix from triplet form.
void disp(std::ostream &stream, bool more=false) const
Print a representation of the object.
static Matrix< Scalar > rand(casadi_int nrow=1, casadi_int ncol=1)
Create a matrix with uniformly distributed random numbers.
bool __nonzero__() const
Returns the truth value of a Matrix.
Definition: matrix_impl.hpp:70
bool is_eye() const
check if the matrix is an identity matrix (note that false negative answers
bool is_op(casadi_int op) const
Is it a certain operation.
void erase(const std::vector< casadi_int > &rr, const std::vector< casadi_int > &cc, bool ind1=false)
Erase a submatrix (leaving structural zeros in its place)
static void rng(casadi_int seed)
Seed the random number generator.
Definition: matrix_impl.hpp:60
std::vector< Scalar > get_elements() const
Get all elements.
static std::vector< Matrix< Scalar > > get_input(const Function &f)
Get function input.
Matrix< Scalar > dep(casadi_int ch=0) const
Get expressions of the children of the expression.
bool is_zero() const
check if the matrix is 0 (note that false negative answers are possible)
static Matrix< Scalar > inf(const Sparsity &sp)
create a matrix with all inf
std::string serialize() const
Serialize.
void enlarge(casadi_int nrow, casadi_int ncol, const std::vector< casadi_int > &rr, const std::vector< casadi_int > &cc, bool ind1=false)
Enlarge matrix.
void print_dense(std::ostream &stream, bool truncate=true) const
Print dense matrix-stype.
bool is_constant() const
Check if the matrix is constant (note that false negative answers are possible)
void reserve(casadi_int nnz)
void export_code(const std::string &lang, std::ostream &stream=casadi::uout(), const Dict &options=Dict()) const
Export matrix in specific language.
casadi_int op() const
Get operation type.
static Matrix< Scalar > eye(casadi_int n)
create an n-by-n identity matrix
bool is_valid_input() const
Check if matrix can be used to define function inputs.
void set_nz(const Matrix< Scalar > &m, bool ind1, const Slice &k)
bool is_integer() const
Check if the matrix is integer-valued.
Matrix< Scalar > operator-() const
void print_vector(std::ostream &stream, bool truncate=true) const
Print vector-style.
casadi_int n_dep() const
Get the number of dependencies of a binary SXElem.
std::string get_str(bool more=false) const
Get string representation.
Matrix< Scalar > printme(const Matrix< Scalar > &y) const
bool is_leaf() const
Check if SX is a leaf of the SX graph.
void get_nz(Matrix< Scalar > &m, bool ind1, const Slice &k) const
std::string name() const
Get name (only if symbolic scalar)
std::vector< Scalar > get_nonzeros() const
Get all nonzeros.
void print_scalar(std::ostream &stream) const
Print scalar.
static Matrix< double > from_file(const std::string &filename, const std::string &format_hint="")
Class representing a Slice.
Definition: slice.hpp:48
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.
General sparsity class.
Definition: sparsity.hpp:99
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 *.
static Sparsity diag(casadi_int nrow)
Create diagonal sparsity pattern *.
Definition: sparsity.hpp:183
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.
static bool is_almost_zero(const T &val, double tol)
static bool is_constant(const T &val)
static bool is_equal(const T &x, const T &y, casadi_int depth)
static bool is_one(const T &val)
static bool is_integer(const T &val)
static bool is_minus_one(const T &val)
static bool is_zero(const T &val)
friend Matrix< Scalar > solve(const Matrix< Scalar > &A, const Matrix< Scalar > &b)
Solve a system of equations: A*x = b.
friend Matrix< Scalar > mtaylor(const Matrix< Scalar > &ex, const Matrix< Scalar > &x, const Matrix< Scalar > &a, casadi_int order=1)
multivariate Taylor series expansion
friend Matrix< Scalar > nullspace(const Matrix< Scalar > &A)
Computes the nullspace of a matrix A.
friend bool depends_on(const Matrix< Scalar > &f, const Matrix< Scalar > &arg)
Check if expression depends on the argument.
friend Matrix< Scalar > trace(const Matrix< Scalar > &x)
Matrix trace.
friend Matrix< Scalar > cofactor(const Matrix< Scalar > &x, casadi_int i, casadi_int j)
Get the (i,j) cofactor matrix.
friend Matrix< Scalar > norm_2(const Matrix< Scalar > &x)
2-norm
friend Matrix< Scalar > simplify(const Matrix< Scalar > &x)
Simplify an expression.
friend Matrix< Scalar > any(const Matrix< Scalar > &x)
Returns true only if any element in the matrix is true.
friend void ldl(const Matrix< Scalar > &A, Matrix< Scalar > &D, Matrix< Scalar > &LT, std::vector< casadi_int > &p, bool amd=true)
Sparse LDL^T factorization.
friend Matrix< Scalar > norm_inf_mul(const Matrix< Scalar > &x, const Matrix< Scalar > &y)
Inf-norm of a Matrix-Matrix product.
friend Matrix< Scalar > eig_symbolic(const Matrix< Scalar > &m)
Attempts to find the eigenvalues of a symbolic matrix.
friend Matrix< Scalar > einstein(const Matrix< Scalar > &A, const Matrix< Scalar > &B, const Matrix< Scalar > &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)
Compute any contraction of two dense tensors, using index/einstein notation.
friend Matrix< Scalar > project(const Matrix< Scalar > &A, const Sparsity &sp, bool intersect=false)
Create a new matrix with a given sparsity pattern but with the.
friend Matrix< double > evalf(const Matrix< Scalar > &expr)
Evaluates the expression numerically.
friend Matrix< Scalar > chol(const Matrix< Scalar > &A)
Obtain a Cholesky factorisation of a matrix.
friend std::vector< bool > which_depends(const Matrix< Scalar > &expr, const Matrix< Scalar > &var, casadi_int order, bool tr)
Find out which variables enter with some order.
friend Matrix< Scalar > inv(const Matrix< Scalar > &A)
Matrix inverse.
friend Matrix< Scalar > pw_lin(const Matrix< Scalar > &t, const Matrix< Scalar > &tval, const Matrix< Scalar > &val)
t a scalar variable (e.g. time)
friend Matrix< Scalar > norm_fro(const Matrix< Scalar > &x)
Frobenius norm.
friend Matrix< Scalar > hessian(const Matrix< Scalar > &ex, const Matrix< Scalar > &arg, const Dict &opts=Dict())
Hessian and (optionally) gradient.
friend Matrix< Scalar > mldivide(const Matrix< Scalar > &x, const Matrix< Scalar > &n)
Matrix divide (cf. backslash '\' in MATLAB)
friend std::vector< std::vector< Matrix< Scalar > > > reverse(const std::vector< Matrix< Scalar > > &ex, const std::vector< Matrix< Scalar > > &arg, const std::vector< std::vector< Matrix< Scalar > > > &v, const Dict &opts=Dict())
Reverse directional derivative.
friend std::string print_operator(const Matrix< Scalar > &xb, const std::vector< std::string > &args)
Get a string representation for a binary MatType, using custom arguments.
friend Matrix< Scalar > ldl_solve(const Matrix< Scalar > &b, const Matrix< Scalar > &D, const Matrix< Scalar > &LT, const std::vector< casadi_int > &p)
Solve using a sparse LDL^T factorization.
friend casadi_int n_nodes(const Matrix< Scalar > &A)
friend std::vector< Matrix< Scalar > > symvar(const Matrix< Scalar > &x)
Get all symbols contained in the supplied expression.
friend Matrix< Scalar > det(const Matrix< Scalar > &A)
Matrix determinant (experimental)
friend void expand(const Matrix< Scalar > &ex, Matrix< Scalar > &weights, Matrix< Scalar > &terms)
Expand the expression as a weighted sum (with constant weights)
friend Matrix< Scalar > expm_const(const Matrix< Scalar > &A, const Matrix< Scalar > &t)
Calculate Matrix exponential.
friend Matrix< Scalar > substitute(const Matrix< Scalar > &ex, const Matrix< Scalar > &v, const Matrix< Scalar > &vdef)
Substitute variable v with expression vdef in an expression ex.
friend Matrix< Scalar > poly_coeff(const Matrix< Scalar > &f, const Matrix< Scalar > &x)
extracts polynomial coefficients from an expression
friend Matrix< Scalar > pw_const(const Matrix< Scalar > &t, const Matrix< Scalar > &tval, const Matrix< Scalar > &val)
Create a piecewise constant function.
friend Matrix< Scalar > taylor(const Matrix< Scalar > &ex, const Matrix< Scalar > &x, const Matrix< Scalar > &a, casadi_int order=1)
univariate Taylor series expansion
friend void qr_sparse(const Matrix< Scalar > &A, Matrix< Scalar > &V, Matrix< Scalar > &R, Matrix< Scalar > &beta, std::vector< casadi_int > &prinv, std::vector< casadi_int > &pc, bool amd=true)
Sparse direct QR factorization.
friend Matrix< Scalar > norm_1(const Matrix< Scalar > &x)
1-norm
friend Matrix< Scalar > mrdivide(const Matrix< Scalar > &x, const Matrix< Scalar > &n)
Matrix divide (cf. slash '/' in MATLAB)
friend Sparsity jacobian_sparsity(const Matrix< Scalar > &f, const Matrix< Scalar > &x)
Get the sparsity pattern of a jacobian.
friend Matrix< Scalar > mmax(const Matrix< Scalar > &x)
Largest element in a matrix.
friend Matrix< Scalar > all(const Matrix< Scalar > &x)
Returns true only if every element in the matrix is true.
friend Matrix< Scalar > poly_roots(const Matrix< Scalar > &p)
Attempts to find the roots of a polynomial.
friend void substitute_inplace(const std::vector< Matrix< Scalar > > &v, std::vector< Matrix< Scalar > > &inout_vdef, std::vector< Matrix< Scalar > > &inout_ex, bool reverse=false)
Inplace substitution with piggyback expressions.
friend Matrix< Scalar > densify(const Matrix< Scalar > &x)
Make the matrix dense if not already.
friend Matrix< Scalar > inv_minor(const Matrix< Scalar > &A)
Matrix inverse (experimental)
friend void qr(const Matrix< Scalar > &A, Matrix< Scalar > &Q, Matrix< Scalar > &R)
QR factorization using the modified Gram-Schmidt algorithm.
friend Matrix< Scalar > heaviside(const Matrix< Scalar > &x)
Heaviside function.
friend void extract(std::vector< Matrix< Scalar > > &ex, std::vector< Matrix< Scalar > > &v, std::vector< Matrix< Scalar > > &vdef, const Dict &opts=Dict())
Introduce intermediate variables for selected nodes in a graph.
friend Matrix< Scalar > mmin(const Matrix< Scalar > &x)
Smallest element in a matrix.
friend Matrix< Scalar > dot(const Matrix< Scalar > &x, const Matrix< Scalar > &y)
Inner product of two matrices.
friend std::vector< std::vector< Matrix< Scalar > > > forward(const std::vector< Matrix< Scalar > > &ex, const std::vector< Matrix< Scalar > > &arg, const std::vector< std::vector< Matrix< Scalar > > > &v, const Dict &opts=Dict())
Forward directional derivative.
friend Matrix< Scalar > rectangle(const Matrix< Scalar > &x)
rectangle function
friend Matrix< Scalar > triangle(const Matrix< Scalar > &x)
triangle function
friend Matrix< Scalar > cse(const Matrix< Scalar > &e)
Common subexpression elimination.
friend Matrix< Scalar > polyval(const Matrix< Scalar > &p, const Matrix< Scalar > &x)
Evaluate a polynomial with coefficients p in x.
friend Matrix< Scalar > conditional(const Matrix< Scalar > &ind, const std::vector< Matrix< Scalar > > &x, const Matrix< Scalar > &x_default, bool short_circuit=false)
Create a switch.
friend Matrix< Scalar > if_else(const Matrix< Scalar > &cond, const Matrix< Scalar > &if_true, const Matrix< Scalar > &if_false, bool short_circuit=false)
Branching on MX nodes.
friend Matrix< Scalar > sparsify(const Matrix< Scalar > &A, double tol=0)
Make a matrix sparse by removing numerical zeros.
friend Matrix< Scalar > expm(const Matrix< Scalar > &A)
Calculate Matrix exponential.
friend Matrix< Scalar > ramp(const Matrix< Scalar > &x)
ramp function
friend Matrix< Scalar > gauss_quadrature(const Matrix< Scalar > &f, const Matrix< Scalar > &x, const Matrix< Scalar > &a, const Matrix< Scalar > &b, casadi_int order=5)
Integrate f from a to b using Gaussian quadrature with n points.
friend void shared(std::vector< Matrix< Scalar > > &ex, std::vector< Matrix< Scalar > > &v, std::vector< Matrix< Scalar > > &vdef, const std::string &v_prefix="v_", const std::string &v_suffix="")
Extract shared subexpressions from an set of expressions.
friend Matrix< Scalar > qr_solve(const Matrix< Scalar > &b, const Matrix< Scalar > &v, const Matrix< Scalar > &r, const Matrix< Scalar > &beta, const std::vector< casadi_int > &prinv, const std::vector< casadi_int > &pc, bool tr=false)
Solve using a sparse QR factorization.
friend Matrix< Scalar > adj(const Matrix< Scalar > &A)
Matrix adjoint.
friend Matrix< Scalar > cumsum(const Matrix< Scalar > &x, casadi_int axis=-1)
Returns cumulative sum along given axis (MATLAB convention)
friend Matrix< Scalar > minor(const Matrix< Scalar > &x, casadi_int i, casadi_int j)
Get the (i,j) minor matrix.
friend Matrix< Scalar > unite(const Matrix< Scalar > &A, const Matrix< Scalar > &B)
Unite two matrices no overlapping sparsity.
friend Matrix< Scalar > diag(const Matrix< Scalar > &A)
Get the diagonal of a matrix or construct a diagonal.
friend Matrix< Scalar > jacobian(const Matrix< Scalar > &ex, const Matrix< Scalar > &arg, const Dict &opts=Dict())
Calculate Jacobian.
friend Matrix< Scalar > norm_inf(const Matrix< Scalar > &x)
Infinity-norm.
friend Matrix< Scalar > pinv(const Matrix< Scalar > &A)
Computes the Moore-Penrose pseudo-inverse.
The casadi namespace.
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)
Definition: shared.hpp:161
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)
Definition: shared.hpp:35
bool is_monotone(const std::vector< T > &v)
Check if the vector is monotone.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
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.
Matrix< double > DM
Definition: dm_fwd.hpp:33
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.