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
1251  return casadi_limits<Scalar>::zero;
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  std::vector< Matrix<Scalar> > Matrix<Scalar>::call(const Function& f,
1269  const std::vector< Matrix<Scalar> > &x) {
1270  // Flatten all inputs
1271  std::vector<Scalar> dep;
1272  for (auto & e : x) {
1273  dep.insert(dep.end(), e.nonzeros().begin(), e.nonzeros().end());
1274  }
1275 
1276  std::vector<Scalar> r = Matrix<Scalar>::call(f, dep);
1277 
1278  // Package rsults in 1-by-1 Matrix objects
1279  std::vector< Matrix<Scalar> > ret;
1280  ret.reserve(r.size());
1281  for (auto & e : r) {
1282  ret.push_back(e);
1283  }
1284 
1285  return ret;
1286  }
1287 
1288 
1289  template<typename Scalar>
1290  std::vector<Scalar> Matrix<Scalar>::call(const Function& f, const std::vector< Scalar > &x) {
1291  casadi_error("'call' not defined for " + type_name());
1292  }
1293 
1294  template<typename Scalar>
1295  Matrix<Scalar> Matrix<Scalar>::
1296  scalar_matrix(casadi_int op, const Matrix<Scalar> &x, const Matrix<Scalar> &y) {
1297  if ( (operation_checker<FX0Checker>(op) && y.nnz()==0) ||
1298  (operation_checker<F0XChecker>(op) && x.nnz()==0))
1299  return Matrix<Scalar>::zeros(Sparsity(y.size()));
1300 
1301  // Return value
1302  Matrix<Scalar> ret = Matrix<Scalar>::zeros(y.sparsity());
1303 
1304  // Nonzeros
1305  std::vector<Scalar>& ret_data = ret.nonzeros();
1306  const std::vector<Scalar>& x_data = x.nonzeros();
1307  const Scalar& x_val = x_data.empty() ? casadi_limits<Scalar>::zero : x->front();
1308  const std::vector<Scalar>& y_data = y.nonzeros();
1309 
1310  // Do the operation on all non-zero elements
1311  for (casadi_int el=0; el<y.nnz(); ++el) {
1312  casadi_math<Scalar>::fun(op, x_val, y_data[el], ret_data[el]);
1313  }
1314 
1315  // Check the value of the structural zero-entries, if there are any
1316  if (!y.is_dense() && !operation_checker<FX0Checker>(op)) {
1317  // Get the value for the structural zeros
1318  Scalar fcn_0;
1319  casadi_math<Scalar>::fun(op, x_val, casadi_limits<Scalar>::zero, fcn_0);
1320  if (!casadi_limits<Scalar>::is_zero(fcn_0)) { // Remove this if?
1321  ret = densify(ret, fcn_0);
1322  }
1323  }
1324 
1325  return ret;
1326  }
1327 
1328  template<typename Scalar>
1329  Matrix<Scalar> Matrix<Scalar>::
1330  matrix_scalar(casadi_int op, const Matrix<Scalar> &x, const Matrix<Scalar> &y) {
1331 
1332  if ( (operation_checker<FX0Checker>(op) && y.nnz()==0) ||
1333  (operation_checker<F0XChecker>(op) && x.nnz()==0))
1334  return Matrix<Scalar>::zeros(Sparsity(x.size()));
1335 
1336  // Return value
1337  Matrix<Scalar> ret = Matrix<Scalar>::zeros(x.sparsity());
1338 
1339  // Nonzeros
1340  std::vector<Scalar>& ret_data = ret.nonzeros();
1341  const std::vector<Scalar>& x_data = x.nonzeros();
1342  const std::vector<Scalar>& y_data = y.nonzeros();
1343  const Scalar& y_val = y_data.empty() ? casadi_limits<Scalar>::zero : y->front();
1344 
1345  // Do the operation on all non-zero elements
1346  for (casadi_int el=0; el<x.nnz(); ++el) {
1347  casadi_math<Scalar>::fun(op, x_data[el], y_val, ret_data[el]);
1348  }
1349 
1350  // Check the value of the structural zero-entries, if there are any
1351  if (!x.is_dense() && !operation_checker<F0XChecker>(op)) {
1352  // Get the value for the structural zeros
1353  Scalar fcn_0;
1354  casadi_math<Scalar>::fun(op, casadi_limits<Scalar>::zero, y_val, fcn_0);
1355  if (!casadi_limits<Scalar>::is_zero(fcn_0)) { // Remove this if?
1356  ret = densify(ret, fcn_0);
1357  }
1358  }
1359 
1360  return ret;
1361  }
1362 
1363  template<typename Scalar>
1364  Matrix<Scalar> Matrix<Scalar>::
1365  matrix_matrix(casadi_int op, const Matrix<Scalar> &x, const Matrix<Scalar> &y) {
1366  // Check, correct dimensions
1367  if (x.size() != y.size()) {
1368  // x and y are horizontal multiples of each other?
1369  if (!x.is_empty() && !y.is_empty()) {
1370  if (x.size1() == y.size1() && x.size2() % y.size2() == 0) {
1371  return matrix_matrix(op, x, repmat(y, 1, x.size2() / y.size2()));
1372  } else if (y.size1() == x.size1() && y.size2() % x.size2() == 0) {
1373  return matrix_matrix(op, repmat(x, 1, y.size2() / x.size2()), y);
1374  }
1375  }
1376  // x and y are empty horizontal multiples of each other?
1377  if (x.size1()==0 && y.size1()==0 && x.size2()>0 && y.size2()>0) {
1378  if (x.size2() % y.size2() == 0) {
1379  return Matrix<Scalar>(0, x.size2());
1380  } else if (y.size2() % x.size2() == 0) {
1381  return Matrix<Scalar>(0, y.size2());
1382  }
1383  }
1384  // Dimension mismatch
1385  casadi_error("Dimension mismatch for " + casadi_math<Scalar>::print(op, "x", "y") +
1386  ", x is " + x.dim() + ", while y is " + y.dim());
1387  }
1388 
1389  // Get the sparsity pattern of the result
1390  // (ignoring structural zeros giving rise to nonzero result)
1391  const Sparsity& x_sp = x.sparsity();
1392  const Sparsity& y_sp = y.sparsity();
1393  Sparsity r_sp = x_sp.combine(y_sp, operation_checker<F0XChecker>(op),
1394  operation_checker<FX0Checker>(op));
1395 
1396  // Return value
1397  Matrix<Scalar> r = zeros(r_sp);
1398 
1399  // Perform the operations elementwise
1400  if (x_sp==y_sp) {
1401  // Matching sparsities
1402  casadi_math<Scalar>::fun(op, x.ptr(), y.ptr(), r.ptr(), r_sp.nnz());
1403  } else if (y_sp==r_sp) {
1404  // Project first argument
1405  Matrix<Scalar> x_mod = x(r_sp);
1406  casadi_math<Scalar>::fun(op, x_mod.ptr(), y.ptr(), r.ptr(), r_sp.nnz());
1407  } else if (x_sp==r_sp) {
1408  // Project second argument
1409  Matrix<Scalar> y_mod = y(r_sp);
1410  casadi_math<Scalar>::fun(op, x.ptr(), y_mod.ptr(), r.ptr(), r_sp.nnz());
1411  } else {
1412  // Project both arguments
1413  Matrix<Scalar> x_mod = x(r_sp);
1414  Matrix<Scalar> y_mod = y(r_sp);
1415  casadi_math<Scalar>::fun(op, x_mod.ptr(), y_mod.ptr(), r.ptr(), r_sp.nnz());
1416  }
1417 
1418  // Handle structural zeros giving rise to nonzero result, e.g. cos(0) == 1
1419  if (!r.is_dense() && !operation_checker<F00Checker>(op)) {
1420  // Get the value for the structural zeros
1421  Scalar fcn_0;
1422  casadi_math<Scalar>::fun(op, casadi_limits<Scalar>::zero,
1423  casadi_limits<Scalar>::zero, fcn_0);
1424  r = densify(r, fcn_0);
1425  }
1426 
1427  return r;
1428  }
1429 
1430  template<typename Scalar>
1431  Matrix<Scalar> Matrix<Scalar>::triplet(const std::vector<casadi_int>& row,
1432  const std::vector<casadi_int>& col,
1433  const Matrix<Scalar>& d) {
1434  return triplet(row, col, d, *std::max_element(row.begin(), row.end()),
1435  *std::max_element(col.begin(), col.end()));
1436  }
1437 
1438  template<typename Scalar>
1439  Matrix<Scalar> Matrix<Scalar>::triplet(const std::vector<casadi_int>& row,
1440  const std::vector<casadi_int>& col,
1441  const Matrix<Scalar>& d,
1442  const std::pair<casadi_int, casadi_int>& rc) {
1443  return triplet(row, col, d, rc.first, rc.second);
1444  }
1445 
1446  template<typename Scalar>
1447  Matrix<Scalar> Matrix<Scalar>::triplet(const std::vector<casadi_int>& row,
1448  const std::vector<casadi_int>& col,
1449  const Matrix<Scalar>& d,
1450  casadi_int nrow, casadi_int ncol) {
1451  casadi_assert(col.size()==row.size() && col.size()==d.nnz(),
1452  "Argument error in Matrix<Scalar>::triplet(row, col, d): "
1453  "supplied lists must all be of equal length, but got: "
1454  + str(row.size()) + ", " + str(col.size()) + " and " + str(d.nnz()));
1455  std::vector<casadi_int> mapping;
1456  Sparsity sp = Sparsity::triplet(nrow, ncol, row, col, mapping, false);
1457  return Matrix<Scalar>(sp, d.nz(mapping));
1458  }
1459 
1460  template<typename Scalar>
1461  Matrix<Scalar> Matrix<Scalar>::eye(casadi_int n) {
1462  return Matrix<Scalar>::ones(Sparsity::diag(n));
1463  }
1464 
1465  template<typename Scalar>
1466  Matrix<Scalar> Matrix<Scalar>::inf(const Sparsity& sp) {
1467  casadi_assert(std::numeric_limits<Scalar>::has_infinity,
1468  "Datatype cannot represent infinity");
1469  return Matrix<Scalar>(sp, std::numeric_limits<Scalar>::infinity(), false);
1470  }
1471 
1472 
1473  template<typename Scalar>
1474  Matrix<Scalar> Matrix<Scalar>::inf(const std::pair<casadi_int, casadi_int>& rc) {
1475  return inf(rc.first, rc.second);
1476  }
1477 
1478  template<typename Scalar>
1479  Matrix<Scalar> Matrix<Scalar>::inf(casadi_int nrow, casadi_int ncol) {
1480  return inf(Sparsity::dense(nrow, ncol));
1481  }
1482 
1483  template<typename Scalar>
1484  Matrix<Scalar> Matrix<Scalar>::nan(const Sparsity& sp) {
1485  casadi_assert(std::numeric_limits<Scalar>::has_quiet_NaN,
1486  "Datatype cannot represent not-a-number");
1487  return Matrix<Scalar>(sp, std::numeric_limits<Scalar>::quiet_NaN(), false);
1488  }
1489 
1490  template<typename Scalar>
1491  Matrix<Scalar> Matrix<Scalar>::nan(const std::pair<casadi_int, casadi_int>& rc) {
1492  return nan(rc.first, rc.second);
1493  }
1494 
1495  template<typename Scalar>
1496  Matrix<Scalar> Matrix<Scalar>::nan(casadi_int nrow, casadi_int ncol) {
1497  return nan(Sparsity::dense(nrow, ncol));
1498  }
1499 
1500  template<typename Scalar>
1501  bool Matrix<Scalar>::is_regular() const {
1502  return casadi::is_regular(nonzeros_);
1503  }
1504 
1505  template<typename Scalar>
1506  bool Matrix<Scalar>::is_smooth() const {
1507  return true;
1508  }
1509 
1510  template<typename Scalar>
1511  casadi_int Matrix<Scalar>::element_hash() const {
1512  casadi_error("'element_hash' not defined for " + type_name());
1513  }
1514 
1515  template<typename Scalar>
1516  bool Matrix<Scalar>::is_leaf() const {
1517  casadi_error("'is_leaf' not defined for " + type_name());
1518  }
1519 
1520  template<typename Scalar>
1521  bool Matrix<Scalar>::is_commutative() const {
1522  casadi_error("'is_commutative' not defined for " + type_name());
1523  }
1524 
1525  template<typename Scalar>
1526  bool Matrix<Scalar>::is_symbolic() const {
1527  return false;
1528  }
1529 
1530  template<typename Scalar>
1531  casadi_int Matrix<Scalar>::op() const {
1532  casadi_error("'op' not defined for " + type_name());
1533  }
1534 
1535  template<typename Scalar>
1536  bool Matrix<Scalar>::is_op(casadi_int k) const {
1537  casadi_error("'is_op' not defined for " + type_name());
1538  }
1539 
1540  template<typename Scalar>
1541  void Matrix<Scalar>::export_code(const std::string& lang,
1542  std::ostream &stream, const Dict& options) const {
1543  casadi_error("'export_code' not defined for " + type_name());
1544  }
1545 
1546  template<typename Scalar>
1547  bool Matrix<Scalar>::is_valid_input() const {
1548  return false;
1549  }
1550 
1551  template<typename Scalar>
1552  bool Matrix<Scalar>::has_duplicates() const {
1553  casadi_error("'has_duplicates' not defined for " + type_name());
1554  }
1555 
1556  template<typename Scalar>
1557  void Matrix<Scalar>::reset_input() const {
1558  casadi_error("'reset_input' not defined for " + type_name());
1559  }
1560 
1561  template<typename Scalar>
1562  Matrix<double> Matrix<Scalar>::from_file(const std::string& filename,
1563  const std::string& format_hint) {
1564  casadi_error("'from_file' not defined for " + type_name());
1565  }
1566 
1567  template<typename Scalar>
1568  bool Matrix<Scalar>::is_integer() const {
1569  // Look for non-integers
1570  for (auto&& e : nonzeros()) if (!casadi_limits<Scalar>::is_integer(e)) return false;
1571 
1572  // Integer if reached this point
1573  return true;
1574  }
1575 
1576  template<typename Scalar>
1577  bool Matrix<Scalar>::is_constant() const {
1578  // Look for non-constants
1579  for (auto&& e : nonzeros()) if (!casadi_limits<Scalar>::is_constant(e)) return false;
1580 
1581  // Constant if we reach this point
1582  return true;
1583  }
1584 
1585  template<typename Scalar>
1586  bool Matrix<Scalar>::is_call() const {
1587  casadi_assert(is_scalar(), "'is_call' only defined for scalar expressions");
1588 
1589  return false;
1590  }
1591 
1592  template<typename Scalar>
1593  bool Matrix<Scalar>::is_output() const {
1594  casadi_assert(is_scalar(), "'is_output' only defined for scalar expressions");
1595 
1596  return false;
1597  }
1598 
1599  template<typename Scalar>
1600  Matrix<Scalar> Matrix<Scalar>::get_output(casadi_int oind) const {
1601  casadi_error("'get_output' not defined for " + type_name());
1602  }
1603 
1604  template<typename Scalar>
1605  bool Matrix<Scalar>::has_output() const {
1606  casadi_assert(is_scalar(), "'has_output' only defined for scalar expressions");
1607 
1608  return false;
1609  }
1610 
1611  template<typename Scalar>
1612  Function Matrix<Scalar>::which_function() const {
1613  casadi_error("'which_function' not defined for " + type_name());
1614  }
1615 
1616  template<typename Scalar>
1617  casadi_int Matrix<Scalar>::which_output() const {
1618  casadi_error("'which_output' not defined for " + type_name());
1619  }
1620 
1621  template<typename Scalar>
1622  bool Matrix<Scalar>::is_one() const {
1623  if (!is_dense()) return false;
1624 
1625  // Look for non-ones
1626  for (auto&& e : nonzeros()) if (!casadi_limits<Scalar>::is_one(e)) return false;
1627 
1628  return true;
1629  }
1630 
1631  template<typename Scalar>
1632  bool Matrix<Scalar>::is_minus_one() const {
1633  if (!is_dense()) return false;
1634 
1635  // Look for non-minus-ones
1636  for (auto&& e : nonzeros()) if (!casadi_limits<Scalar>::is_minus_one(e)) return false;
1637 
1638  return true;
1639  }
1640 
1641  template<typename Scalar>
1642  bool Matrix<Scalar>::is_zero() const {
1643 
1644  // Look for non-zeros
1645  for (auto&& e : nonzeros()) if (!casadi_limits<Scalar>::is_zero(e)) return false;
1646 
1647  return true;
1648  }
1649 
1650  template<typename Scalar>
1651  bool Matrix<Scalar>::is_eye() const {
1652 
1653  // Make sure that the matrix is diagonal
1654  if (!sparsity().is_diag()) return false;
1655 
1656  // Make sure that all entries are one
1657  for (auto&& e : nonzeros()) if (!casadi_limits<Scalar>::is_one(e)) return false;
1658 
1659  return true;
1660  }
1661 
1662  template<typename Scalar>
1663  bool Matrix<Scalar>::is_equal(const Matrix<Scalar> &x, const Matrix<Scalar> &y,
1664  casadi_int depth) {
1665  // Assert matching dimensions
1666  casadi_assert(x.size() == y.size(), "Dimension mismatch");
1667 
1668  // Project to union of patterns and call recursively if different sparsity
1669  if (x.sparsity() != y.sparsity()) {
1670  Sparsity sp = x.sparsity() + y.sparsity();
1671  return is_equal(project(x, sp), project(y, sp), depth);
1672  }
1673 
1674  // Check individual elements
1675  auto y_it = y.nonzeros().begin();
1676  for (auto&& e : x.nonzeros()) {
1677  if (!casadi_limits<Scalar>::is_equal(e, *y_it++, depth)) return false;
1678  }
1679 
1680  // True if reched this point
1681  return true;
1682  }
1683 
1684  // To avoid overloaded function name conflicts
1685  template<typename Scalar>
1686  inline Matrix<Scalar> mmin_nonstatic(const Matrix<Scalar> &x) {
1687  if (x.is_empty()) return Matrix<Scalar>();
1688  return casadi_mmin(x.ptr(), x.nnz(), x.is_dense());
1689  }
1690 
1691  template<typename Scalar>
1692  Matrix<Scalar> Matrix<Scalar>::mmin(const Matrix<Scalar> &x) {
1693  return mmin_nonstatic(x);
1694  }
1695 
1696  // To avoid overloaded function name conflicts
1697  template<typename Scalar>
1698  inline Matrix<Scalar> mmax_nonstatic(const Matrix<Scalar> &x) {
1699  if (x.is_empty()) return Matrix<Scalar>();
1700  return casadi_mmax(x.ptr(), x.nnz(), x.is_dense());
1701  }
1702 
1703  template<typename Scalar>
1704  Matrix<Scalar> Matrix<Scalar>::mmax(const Matrix<Scalar> &x) {
1705  return mmax_nonstatic(x);
1706  }
1707 
1708  template<typename Scalar>
1709  bool Matrix<Scalar>::has_zeros() const {
1710  // Check if the structural nonzero is known to be zero
1711  for (auto&& e : nonzeros()) if (casadi_limits<Scalar>::is_zero(e)) return true;
1712 
1713  // No known zeros amongst the structurally nonzero entries
1714  return false;
1715  }
1716 
1717  template<typename Scalar>
1718  std::vector<Scalar> Matrix<Scalar>::get_nonzeros() const {
1719  return nonzeros_;
1720  }
1721 
1722  template<typename Scalar>
1723  std::vector<Scalar> Matrix<Scalar>::get_elements() const {
1724  return static_cast< std::vector<Scalar>>(*this);
1725  }
1726 
1727  template<typename Scalar>
1728  std::string Matrix<Scalar>::name() const {
1729  casadi_error("'name' not defined for " + type_name());
1730  }
1731 
1732  template<typename Scalar>
1733  Matrix<Scalar> Matrix<Scalar>::dep(casadi_int ch) const {
1734  casadi_error("'dep' not defined for " + type_name());
1735  }
1736 
1737  template<typename Scalar>
1738  casadi_int Matrix<Scalar>::n_dep() const {
1739  casadi_error("'n_dep' not defined for " + type_name());
1740  }
1741 
1742  template<typename Scalar>
1743  Matrix<Scalar> Matrix<Scalar>::rand( // NOLINT(runtime/threadsafe_fn)
1744  casadi_int nrow,
1745  casadi_int ncol) {
1746  return rand(Sparsity::dense(nrow, ncol)); // NOLINT(runtime/threadsafe_fn)
1747  }
1748 
1749  template<typename Scalar>
1750  Matrix<Scalar> Matrix<Scalar>::rand( // NOLINT(runtime/threadsafe_fn)
1751  const std::pair<casadi_int, casadi_int>& rc) {
1752  return rand(rc.first, rc.second); // NOLINT(runtime/threadsafe_fn)
1753  }
1754 
1755  template<typename Scalar>
1756  Matrix<Scalar> Matrix<Scalar>::project(const Matrix<Scalar>& x,
1757  const Sparsity& sp, bool intersect) {
1758  if (intersect) {
1759  return project(x, sp.intersect(x.sparsity()), false);
1760  } else {
1761  casadi_assert(sp.size()==x.size(), "Dimension mismatch");
1762  Matrix<Scalar> ret = Matrix<Scalar>::zeros(sp);
1763  std::vector<Scalar> w(x.size1());
1764  casadi_project(x.ptr(), x.sparsity(), ret.ptr(), sp, get_ptr(w));
1765  return ret;
1766  }
1767  }
1768 
1769  template<typename Scalar>
1770  void Matrix<Scalar>::set_max_depth(casadi_int eq_depth) {
1771  casadi_error("'set_max_depth' not defined for " + type_name());
1772  }
1773 
1774  template<typename Scalar>
1775  casadi_int Matrix<Scalar>::get_max_depth() {
1776  casadi_error("'get_max_depth' not defined for " + type_name());
1777  }
1778 
1779  template<typename Scalar>
1780  Matrix<Scalar> Matrix<Scalar>::det(const Matrix<Scalar>& x) {
1781  casadi_int n = x.size2();
1782  casadi_assert(n == x.size1(), "matrix must be square");
1783 
1784  // Trivial return if scalar
1785  if (x.is_scalar()) return x;
1786 
1787  // Trivial case 2 x 2
1788  if (n==2) return x(0, 0) * x(1, 1) - x(0, 1) * x(1, 0);
1789 
1790  // Return expression
1791  Matrix<Scalar> ret = 0;
1792 
1793  // Find out which is the best direction to expand along
1794 
1795  // Build up an IM with ones on the non-zeros
1796  Matrix<casadi_int> sp = IM::ones(x.sparsity());
1797 
1798  // Have a count of the nonzeros for each row
1799  Matrix<casadi_int> row_count = Matrix<casadi_int>::sum2(sp);
1800 
1801  // A blank row? determinant is structurally zero
1802  if (!row_count.is_dense()) return 0;
1803 
1804  // Have a count of the nonzeros for each col
1805  Matrix<casadi_int> col_count = Matrix<casadi_int>::sum1(sp).T();
1806 
1807  // A blank col? determinant is structurally zero
1808  if (!row_count.is_dense()) return 0;
1809 
1810  casadi_int min_row = std::distance(row_count.nonzeros().begin(),
1811  std::min_element(row_count.nonzeros().begin(),
1812  row_count.nonzeros().end()));
1813  casadi_int min_col = std::distance(col_count.nonzeros().begin(),
1814  std::min_element(col_count.nonzeros().begin(),
1815  col_count.nonzeros().end()));
1816 
1817  if (min_row <= min_col) {
1818  // Expand along row j
1819  casadi_int j = row_count.sparsity().row(min_row);
1820 
1821  Matrix<Scalar> row = x(j, Slice(0, n));
1822 
1823  std::vector< casadi_int > col_i = row.sparsity().get_col();
1824 
1825  for (casadi_int k=0; k<row.nnz(); ++k) {
1826  // Sum up the cofactors
1827  ret += row->at(k)*cofactor(x, col_i.at(k), j);
1828  }
1829  return ret;
1830  } else {
1831  // Expand along col i
1832  casadi_int i = col_count.sparsity().row(min_col);
1833 
1834  Matrix<Scalar> col = x(Slice(0, n), i);
1835 
1836  const casadi_int* row_i = col.row();
1837 
1838  for (casadi_int k=0; k<col.nnz(); ++k) {
1839  // Sum up the cofactors
1840  ret += col->at(k)*cofactor(x, i, row_i[k]);
1841  }
1842  return ret;
1843  }
1844 
1845  }
1846 
1847  template<typename Scalar>
1848  Matrix<Scalar> Matrix<Scalar>::sum2(const Matrix<Scalar>& x) {
1849  return mtimes(x, Matrix<Scalar>::ones(x.size2(), 1));
1850  }
1851 
1852  template<typename Scalar>
1853  Matrix<Scalar> Matrix<Scalar>::sum1(const Matrix<Scalar>& x) {
1854  return mtimes(Matrix<Scalar>::ones(1, x.size1()), x);
1855  }
1856 
1857  template<typename Scalar>
1858  Matrix<Scalar> Matrix<Scalar>::minor(const Matrix<Scalar>& x,
1859  casadi_int i, casadi_int j) {
1860  casadi_int n = x.size2();
1861  casadi_assert(n == x.size1(), "minor: matrix must be square");
1862 
1863  // Trivial return if scalar
1864  if (n==1) return 1;
1865 
1866  // Remove col i and row j
1867  Matrix<Scalar> M = Matrix<Scalar>(n-1, n-1);
1868 
1869  std::vector<casadi_int> col = x.sparsity().get_col();
1870  const casadi_int* row = x.sparsity().row();
1871 
1872  for (casadi_int k=0; k<x.nnz(); ++k) {
1873  casadi_int i1 = col[k];
1874  casadi_int j1 = row[k];
1875 
1876  if (i1 == i || j1 == j) continue;
1877 
1878  casadi_int i2 = (i1<i)?i1:i1-1;
1879  casadi_int j2 = (j1<j)?j1:j1-1;
1880 
1881  M(j2, i2) = x(j1, i1);
1882  }
1883  return det(M);
1884  }
1885 
1886  template<typename Scalar>
1887  Matrix<Scalar> Matrix<Scalar>::cofactor(const Matrix<Scalar>& A, casadi_int i, casadi_int j) {
1888 
1889  // Calculate the i, j minor
1890  Matrix<Scalar> minor_ij = minor(A, i, j);
1891  // Calculate the cofactor
1892  casadi_int sign_i = 1-2*((i+j) % 2);
1893 
1894  return sign_i * minor_ij;
1895  }
1896 
1897  template<typename Scalar>
1898  Matrix<Scalar> Matrix<Scalar>::adj(const Matrix<Scalar>& x) {
1899  casadi_int n = x.size2();
1900  casadi_assert(n == x.size1(), "adj: matrix must be square");
1901 
1902  // Temporary placeholder
1903  Matrix<Scalar> temp;
1904 
1905  // Cofactor matrix
1906  Matrix<Scalar> C = Matrix<Scalar>(n, n);
1907  for (casadi_int i=0; i<n; ++i)
1908  for (casadi_int j=0; j<n; ++j) {
1909  temp = cofactor(x, i, j);
1910  if (!temp.is_zero()) C(j, i) = temp;
1911  }
1912 
1913  return C.T();
1914  }
1915 
1916  template<typename Scalar>
1917  Matrix<Scalar> Matrix<Scalar>::inv_minor(const Matrix<Scalar>& x) {
1918  // laplace formula
1919  return adj(x)/det(x);
1920  }
1921 
1922  template<typename Scalar>
1923  Matrix<Scalar> Matrix<Scalar>::reshape(const Matrix<Scalar>& x,
1924  casadi_int nrow, casadi_int ncol) {
1925  Sparsity sp = Sparsity::reshape(x.sparsity(), nrow, ncol);
1926  return Matrix<Scalar>(sp, x.nonzeros(), false);
1927  }
1928 
1929  template<typename Scalar>
1930  Matrix<Scalar> Matrix<Scalar>::reshape(const Matrix<Scalar>& x, const Sparsity& sp) {
1931  // quick return if already the right shape
1932  if (sp==x.sparsity()) return x;
1933 
1934  // make sure that the patterns match
1935  casadi_assert_dev(sp.is_reshape(x.sparsity()));
1936 
1937  return Matrix<Scalar>(sp, x.nonzeros(), false);
1938  }
1939 
1940  template<typename Scalar>
1941  Matrix<Scalar> Matrix<Scalar>::sparsity_cast(const Matrix<Scalar>& x, const Sparsity& sp) {
1942  // quick return if already the right shape
1943  if (sp==x.sparsity()) return x;
1944 
1945  casadi_assert_dev(sp.nnz()==x.nnz());
1946 
1947  return Matrix<Scalar>(sp, x.nonzeros(), false);
1948  }
1949 
1950  template<typename Scalar>
1951  Matrix<Scalar> Matrix<Scalar>::trace(const Matrix<Scalar>& x) {
1952  casadi_assert(x.is_square(), "trace: must be square");
1953  Scalar res=0;
1954  const Scalar* d=x.ptr();
1955  casadi_int size2 = x.size2();
1956  const casadi_int *colind=x.colind(), *row=x.row();
1957  for (casadi_int c=0; c<size2; c++) {
1958  for (casadi_int k=colind[c]; k!=colind[c+1]; ++k) {
1959  if (row[k]==c) {
1960  res += d[k];
1961  }
1962  }
1963  }
1964  return res;
1965  }
1966 
1967  template<typename Scalar>
1968  Matrix<Scalar>
1969  Matrix<Scalar>::blockcat(const std::vector< std::vector<Matrix<Scalar> > > &v) {
1970  std::vector< Matrix<Scalar> > ret;
1971  for (casadi_int i=0; i<v.size(); ++i)
1972  ret.push_back(horzcat(v[i]));
1973  return vertcat(ret);
1974  }
1975 
1976  template<typename Scalar>
1977  Matrix<Scalar> Matrix<Scalar>::horzcat(const std::vector<Matrix<Scalar> > &v) {
1978  // Concatenate sparsity patterns
1979  std::vector<Sparsity> sp(v.size());
1980  for (casadi_int i=0; i<v.size(); ++i) sp[i] = v[i].sparsity();
1981  Matrix<Scalar> ret = zeros(Sparsity::horzcat(sp));
1982 
1983  // Copy nonzeros
1984  auto i=ret->begin();
1985  for (auto&& j : v) {
1986  std::copy(j->begin(), j->end(), i);
1987  i += j.nnz();
1988  }
1989  return ret;
1990  }
1991 
1992  template<typename Scalar>
1993  std::vector<Matrix<Scalar> >
1994  Matrix<Scalar>::horzsplit(const Matrix<Scalar>& x, const std::vector<casadi_int>& offset) {
1995  // Split up the sparsity pattern
1996  std::vector<Sparsity> sp = Sparsity::horzsplit(x.sparsity(), offset);
1997 
1998  // Return object
1999  std::vector<Matrix<Scalar> > ret;
2000  ret.reserve(sp.size());
2001 
2002  // Copy data
2003  auto i=x.nonzeros().begin();
2004  for (auto&& j : sp) {
2005  auto i_next = i + j.nnz();
2006  ret.push_back(Matrix<Scalar>(j, std::vector<Scalar>(i, i_next), false));
2007  i = i_next;
2008  }
2009 
2010  // Return the assembled matrix
2011  casadi_assert_dev(i==x.nonzeros().end());
2012  return ret;
2013  }
2014 
2015  template<typename Scalar>
2016  Matrix<Scalar> Matrix<Scalar>::vertcat(const std::vector<Matrix<Scalar> > &v) {
2017  std::vector<Matrix<Scalar> > vT(v.size());
2018  for (casadi_int i=0; i<v.size(); ++i) vT[i] = v[i].T();
2019  return horzcat(vT).T();
2020  }
2021 
2022  template<typename Scalar>
2023  std::vector< Matrix<Scalar> >
2024  Matrix<Scalar>::vertsplit(const Matrix<Scalar>& x, const std::vector<casadi_int>& offset) {
2025  std::vector< Matrix<Scalar> > ret = horzsplit(x.T(), offset);
2026  for (auto&& e : ret) e = e.T();
2027  return ret;
2028  }
2029 
2030  template<typename Scalar>
2031  std::vector< Matrix<Scalar> >
2032  Matrix<Scalar>::diagsplit(const Matrix<Scalar>& x, const std::vector<casadi_int>& offset1,
2033  const std::vector<casadi_int>& offset2) {
2034  // Consistency check
2035  casadi_assert_dev(!offset1.empty());
2036  casadi_assert_dev(offset1.front()==0);
2037  casadi_assert_dev(offset1.back()==x.size1());
2038  casadi_assert_dev(is_monotone(offset1));
2039 
2040  // Consistency check
2041  casadi_assert_dev(!offset2.empty());
2042  casadi_assert_dev(offset2.front()==0);
2043  casadi_assert_dev(offset2.back()==x.size2());
2044  casadi_assert_dev(is_monotone(offset2));
2045 
2046  // Number of outputs
2047  casadi_int n = offset1.size()-1;
2048 
2049  // Return value
2050  std::vector< Matrix<Scalar> > ret;
2051 
2052  // Caveat: this is a very silly implementation
2053  for (casadi_int i=0; i<n; ++i) {
2054  ret.push_back(x(Slice(offset1[i], offset1[i+1]), Slice(offset2[i], offset2[i+1])));
2055  }
2056 
2057  return ret;
2058  }
2059 
2060  template<typename Scalar>
2061  Matrix<Scalar> Matrix<Scalar>::dot(const Matrix<Scalar> &x,
2062  const Matrix<Scalar> &y) {
2063  casadi_assert(x.size()==y.size(), "dot: Dimension mismatch");
2064  if (x.sparsity()!=y.sparsity()) {
2065  Sparsity sp = x.sparsity() * y.sparsity();
2066  return dot(project(x, sp), project(y, sp));
2067  }
2068  return casadi_dot(x.nnz(), x.ptr(), y.ptr());
2069  }
2070 
2071  template<typename Scalar>
2072  Matrix<Scalar> Matrix<Scalar>::all(const Matrix<Scalar>& x) {
2073  if (!x.is_dense()) return false;
2074  Scalar ret=1;
2075  for (casadi_int i=0; i<x.nnz(); ++i) {
2076  ret = ret && x->at(i)==1;
2077  }
2078  return ret;
2079  }
2080 
2081  template<typename Scalar>
2082  Matrix<Scalar> Matrix<Scalar>::any(const Matrix<Scalar>& x) {
2083  if (!x.is_dense()) return false;
2084  Scalar ret=0;
2085  for (casadi_int i=0; i<x.nnz(); ++i) {
2086  ret = ret || x->at(i)==1;
2087  }
2088  return ret;
2089  }
2090 
2091  template<typename Scalar>
2092  Matrix<Scalar> Matrix<Scalar>::norm_1(const Matrix<Scalar>& x) {
2093  return casadi_norm_1(x.nnz(), x.ptr());
2094  }
2095 
2096  template<typename Scalar>
2097  Matrix<Scalar> Matrix<Scalar>::norm_2(const Matrix<Scalar>& x) {
2098  if (x.is_vector()) {
2099  return norm_fro(x);
2100  } else {
2101  casadi_error("2-norms currently only supported for vectors. "
2102  "Did you intend to calculate a Frobenius norms (norm_fro)?");
2103  }
2104  }
2105 
2106  template<typename Scalar>
2107  Matrix<Scalar> Matrix<Scalar>::norm_fro(const Matrix<Scalar>& x) {
2108  return casadi_norm_2(x.nnz(), x.ptr());
2109  }
2110 
2111  template<typename Scalar>
2112  Matrix<Scalar> Matrix<Scalar>::norm_inf(const Matrix<Scalar>& x) {
2113  // Get largest element by absolute value
2114  Matrix<Scalar> s = 0;
2115  for (auto i=x.nonzeros().begin(); i!=x.nonzeros().end(); ++i) {
2116  s = fmax(s, fabs(Matrix<Scalar>(*i)));
2117  }
2118  return s;
2119  }
2120 
2121  template<typename Scalar>
2122  void Matrix<Scalar>::
2123  qr_sparse(const Matrix<Scalar>& A,
2124  Matrix<Scalar>& V, Matrix<Scalar> &R, Matrix<Scalar>& beta,
2125  std::vector<casadi_int>& prinv, std::vector<casadi_int>& pc, bool amd) {
2126  // Calculate the pattern
2127  Sparsity spV, spR;
2128  A.sparsity().qr_sparse(spV, spR, prinv, pc, amd);
2129  // Calculate the nonzeros
2130  casadi_int nrow_ext = spV.size1(), ncol = spV.size2();
2131  V = nan(spV);
2132  R = nan(spR);
2133  beta = nan(ncol, 1);
2134  std::vector<Scalar> w(nrow_ext);
2135  casadi_qr(A.sparsity(), A.ptr(), get_ptr(w), spV, V.ptr(),
2136  spR, R.ptr(), beta.ptr(),
2137  get_ptr(prinv), get_ptr(pc));
2138  }
2139 
2140  template<typename Scalar>
2141  Matrix<Scalar> Matrix<Scalar>::
2142  qr_solve(const Matrix<Scalar>& b, const Matrix<Scalar>& v,
2143  const Matrix<Scalar>& r, const Matrix<Scalar>& beta,
2144  const std::vector<casadi_int>& prinv, const std::vector<casadi_int>& pc,
2145  bool tr) {
2146  // Get dimensions, check consistency
2147  casadi_int ncol = v.size2();
2148  casadi_int nrow = b.size1(), nrhs = b.size2();
2149  casadi_assert(r.size()==v.size(), "'r', 'v' dimension mismatch");
2150  casadi_assert(beta.is_vector() && beta.numel()==ncol, "'beta' has wrong dimension");
2151  casadi_assert(prinv.size()==r.size1(), "'pinv' has wrong dimension");
2152  // Work vector
2153  std::vector<Scalar> w(nrow+ncol);
2154  // Return value
2155  Matrix<Scalar> x = densify(b);
2156  casadi_qr_solve(x.ptr(), nrhs, tr, v.sparsity(), v.ptr(), r.sparsity(), r.ptr(),
2157  beta.ptr(), get_ptr(prinv), get_ptr(pc), get_ptr(w));
2158  return x;
2159  }
2160 
2161  template<typename Scalar>
2162  void Matrix<Scalar>::qr(const Matrix<Scalar>& A,
2163  Matrix<Scalar>& Q, Matrix<Scalar> &R) {
2164  // The following algorithm is taken from J. Demmel:
2165  // Applied Numerical Linear Algebra (algorithm 3.1.)
2166  casadi_assert(A.size1()>=A.size2(), "qr: fewer rows than columns");
2167 
2168  // compute Q and R column by column
2169  Q = R = Matrix<Scalar>();
2170  for (casadi_int i=0; i<A.size2(); ++i) {
2171  // Initialize qi to be the i-th column of *this
2172  Matrix<Scalar> ai = A(Slice(), i);
2173  Matrix<Scalar> qi = ai;
2174  // The i-th column of R
2175  Matrix<Scalar> ri = Matrix<Scalar>(A.size2(), 1);
2176 
2177  // subtract the projection of qi in the previous directions from ai
2178  for (casadi_int j=0; j<i; ++j) {
2179 
2180  // Get the j-th column of Q
2181  Matrix<Scalar> qj = Q(Slice(), j); // NOLINT(cppcoreguidelines-slicing)
2182 
2183  ri(j, 0) = mtimes(qi.T(), qj); // Modified Gram-Schmidt
2184  // ri[j] = dot(qj, ai); // Classical Gram-Schmidt
2185 
2186  // Remove projection in direction j
2187  if (ri.has_nz(j, 0))
2188  qi -= ri(j, 0) * qj;
2189  }
2190 
2191  // Normalize qi
2192  ri(i, 0) = norm_2(qi);
2193  qi /= ri(i, 0);
2194 
2195  // Update R and Q
2196  Q = Matrix<Scalar>::horzcat({Q, qi});
2197  R = Matrix<Scalar>::horzcat({R, ri});
2198  }
2199  }
2200 
2201  template<typename Scalar>
2202  void Matrix<Scalar>::ldl(const Matrix<Scalar>& A, Matrix<Scalar> &D,
2203  Matrix<Scalar>& LT, std::vector<casadi_int>& p, bool amd) {
2204  // Symbolic factorization
2205  Sparsity Lt_sp = A.sparsity().ldl(p, amd);
2206 
2207  // Get dimension
2208  casadi_int n=A.size1();
2209 
2210  // Calculate entries in L and D
2211  std::vector<Scalar> D_nz(n), L_nz(Lt_sp.nnz()), w(n);
2212  casadi_ldl(A.sparsity(), get_ptr(A.nonzeros()), Lt_sp,
2213  get_ptr(L_nz), get_ptr(D_nz), get_ptr(p), get_ptr(w));
2214 
2215  // Assemble L and D
2216  LT = Matrix<Scalar>(Lt_sp, L_nz);
2217  D = D_nz;
2218  }
2219 
2220  template<typename Scalar>
2221  Matrix<Scalar> Matrix<Scalar>::
2222  ldl_solve(const Matrix<Scalar>& b, const Matrix<Scalar>& D, const Matrix<Scalar>& LT,
2223  const std::vector<casadi_int>& p) {
2224  // Get dimensions, check consistency
2225  casadi_int n = b.size1(), nrhs = b.size2();
2226  casadi_assert(p.size()==n, "'p' has wrong dimension");
2227  casadi_assert(LT.size1()==n && LT.size2()==n, "'LT' has wrong dimension");
2228  casadi_assert(D.is_vector() && D.numel()==n, "'D' has wrong dimension");
2229  // Solve for all right-hand-sides
2230  Matrix<Scalar> x = densify(b);
2231  std::vector<Scalar> w(n);
2232  casadi_ldl_solve(x.ptr(), nrhs, LT.sparsity(), LT.ptr(), D.ptr(), get_ptr(p), get_ptr(w));
2233  return x;
2234  }
2235 
2236  template<typename Scalar>
2237  Matrix<Scalar> Matrix<Scalar>::nullspace(const Matrix<Scalar>& A) {
2238  Matrix<Scalar> X = A;
2239  casadi_int n = X.size1();
2240  casadi_int m = X.size2();
2241  casadi_assert(m>=n, "nullspace(): expecting a flat matrix (more columns than rows), "
2242  "but got " + str(X.dim()) + ".");
2243 
2244  Matrix<Scalar> seed = DM::eye(m)(Slice(0, m), Slice(n, m)); // NOLINT(cppcoreguidelines-slicing)
2245 
2246  std::vector< Matrix<Scalar> > us;
2247  std::vector< Matrix<Scalar> > betas;
2248 
2249  Matrix<Scalar> beta;
2250 
2251  for (casadi_int i=0;i<n;++i) {
2252  Matrix<Scalar> x = X(i, Slice(i, m)); // NOLINT(cppcoreguidelines-slicing)
2253  Matrix<Scalar> u = Matrix<Scalar>(x);
2254  Matrix<Scalar> sigma = sqrt(sum2(x*x));
2255  const Matrix<Scalar>& x0 = x(0, 0);
2256  u(0, 0) = 1;
2257 
2258  Matrix<Scalar> b = -copysign(sigma, x0);
2259 
2260  u(Slice(0), Slice(1, m-i))*= 1/(x0-b);
2261  beta = 1-x0/b;
2262 
2263  X(Slice(i, n), Slice(i, m)) -=
2264  beta*mtimes(mtimes(X(Slice(i, n), Slice(i, m)), u.T()), u);
2265  us.push_back(u);
2266  betas.push_back(beta);
2267  }
2268 
2269  for (casadi_int i=n-1;i>=0;--i) {
2270  seed(Slice(i, m), Slice(0, m-n)) -=
2271  betas[i]*mtimes(us[i].T(), mtimes(us[i], seed(Slice(i, m), Slice(0, m-n))));
2272  }
2273 
2274  return seed;
2275 
2276  }
2277 
2278  template<typename Scalar>
2279  Matrix<Scalar> Matrix<Scalar>::chol(const Matrix<Scalar>& A) {
2280  // Perform an LDL transformation
2281  Matrix<Scalar> D, LT;
2282  std::vector<casadi_int> p;
2283  ldl(A, D, LT, p, false);
2284  // Add unit diagonal
2285  LT += Matrix<Scalar>::eye(D.size1());
2286  // Get the cholesky factor: R*R' = L*D*L' = (sqrt(D)*L')'*(sqrt(D)*L')
2287  return mtimes(diag(sqrt(D)), LT);
2288  }
2289 
2290  template<typename Scalar>
2291  Matrix<Scalar> Matrix<Scalar>::solve(const Matrix<Scalar>& a, const Matrix<Scalar>& b) {
2292  // check dimensions
2293  casadi_assert(a.size1() == b.size1(), "solve Ax=b: dimension mismatch: b has "
2294  + str(b.size1()) + " rows while A has " + str(a.size1()) + ".");
2295  casadi_assert(a.size1() == a.size2(), "solve: A not square but " + str(a.dim()));
2296 
2297  if (a.is_tril()) {
2298  // forward substitution if lower triangular
2299  Matrix<Scalar> x = b;
2300  const casadi_int* Arow = a.row();
2301  const casadi_int* Acolind = a.colind();
2302  const std::vector<Scalar> & Adata = a.nonzeros();
2303  for (casadi_int i=0; i<a.size2(); ++i) { // loop over columns forwards
2304  for (casadi_int k=0; k<b.size2(); ++k) { // for every right hand side
2305  if (!x.has_nz(i, k)) continue;
2306  x(i, k) /= a(i, i);
2307  for (casadi_int kk=Acolind[i+1]-1; kk>=Acolind[i] && Arow[kk]>i; --kk) {
2308  casadi_int j = Arow[kk];
2309  x(j, k) -= Adata[kk]*x(i, k);
2310  }
2311  }
2312  }
2313  return x;
2314  } else if (a.is_triu()) {
2315  // backward substitution if upper triangular
2316  Matrix<Scalar> x = b;
2317  const casadi_int* Arow = a.row();
2318  const casadi_int* Acolind = a.colind();
2319  const std::vector<Scalar> & Adata = a.nonzeros();
2320  for (casadi_int i=a.size2()-1; i>=0; --i) { // loop over columns backwards
2321  for (casadi_int k=0; k<b.size2(); ++k) { // for every right hand side
2322  if (!x.has_nz(i, k)) continue;
2323  x(i, k) /= a(i, i);
2324  for (casadi_int kk=Acolind[i]; kk<Acolind[i+1] && Arow[kk]<i; ++kk) {
2325  casadi_int j = Arow[kk];
2326  x(j, k) -= Adata[kk]*x(i, k);
2327  }
2328  }
2329  }
2330  return x;
2331  } else if (a.has_zeros()) {
2332 
2333  // If there are structurally nonzero entries that are known to be zero,
2334  // remove these and rerun the algorithm
2335  return solve(sparsify(a), b);
2336 
2337  } else {
2338 
2339  // Make a BLT transformation of A
2340  std::vector<casadi_int> rowperm, colperm, rowblock, colblock;
2341  std::vector<casadi_int> coarse_rowblock, coarse_colblock;
2342  a.sparsity().btf(rowperm, colperm, rowblock, colblock,
2343  coarse_rowblock, coarse_colblock);
2344 
2345  // Permute the right hand side
2346  Matrix<Scalar> bperm = b(rowperm, Slice());
2347 
2348  // Permute the linear system
2349  Matrix<Scalar> Aperm = a(rowperm, colperm);
2350 
2351  // Solution
2352  Matrix<Scalar> xperm;
2353 
2354  // Solve permuted system
2355  if (Aperm.is_tril()) {
2356 
2357  // Forward substitution if lower triangular
2358  xperm = solve(Aperm, bperm);
2359 
2360  } else if (a.size2()<=3) {
2361 
2362  // Form inverse by minor expansion and multiply if very small (up to 3-by-3)
2363  xperm = mtimes(inv_minor(Aperm), bperm);
2364 
2365  } else {
2366 
2367  // Make a QR factorization
2368  Matrix<Scalar> Q, R;
2369  qr(Aperm, Q, R);
2370 
2371  // Solve the factorized system (note that solve will now be fast since it is triangular)
2372  xperm = solve(R, mtimes(Q.T(), bperm));
2373  }
2374 
2375  // get the inverted column permutation
2376  std::vector<casadi_int> inv_colperm(colperm.size());
2377  for (casadi_int k=0; k<colperm.size(); ++k)
2378  inv_colperm[colperm[k]] = k;
2379 
2380  // Permute back the solution and return
2381  Matrix<Scalar> x = xperm(inv_colperm, Slice()); // NOLINT(cppcoreguidelines-slicing)
2382  return x;
2383  }
2384  }
2385 
2386  template<typename Scalar>
2387  Matrix<Scalar> Matrix<Scalar>::
2388  solve(const Matrix<Scalar>& a, const Matrix<Scalar>& b,
2389  const std::string& lsolver, const Dict& dict) {
2390  casadi_error("'solve' with plugin not defined for " + type_name());
2391  return Matrix<Scalar>();
2392  }
2393 
2394  template<typename Scalar>
2395  Matrix<Scalar> Matrix<Scalar>::
2396  inv(const Matrix<Scalar>& a) {
2397  return solve(a, Matrix<Scalar>::eye(a.size1()));
2398  }
2399 
2400  template<typename Scalar>
2401  Matrix<Scalar> Matrix<Scalar>::
2402  inv(const Matrix<Scalar>& a,
2403  const std::string& lsolver, const Dict& dict) {
2404  casadi_error("'inv' with plugin not defined for " + type_name());
2405  return Matrix<Scalar>();
2406  }
2407 
2408  template<typename Scalar>
2409  Matrix<Scalar> Matrix<Scalar>::pinv(const Matrix<Scalar>& A) {
2410  if (A.size2()>=A.size1()) {
2411  return solve(mtimes(A, A.T()), A).T();
2412  } else {
2413  return solve(mtimes(A.T(), A), A.T());
2414  }
2415  }
2416 
2417  template<typename Scalar>
2418  Matrix<Scalar> Matrix<Scalar>::
2419  pinv(const Matrix<Scalar>& A, const std::string& lsolver, const Dict& dict) {
2420  casadi_error("'solve' not defined for " + type_name());
2421  return Matrix<Scalar>();
2422  }
2423 
2424  template<typename Scalar>
2425  Matrix<Scalar> Matrix<Scalar>::
2426  expm_const(const Matrix<Scalar>& A, const Matrix<Scalar>& t) {
2427  casadi_error("'solve' not defined for " + type_name());
2428  return Matrix<Scalar>();
2429  }
2430 
2431  template<typename Scalar>
2432  Matrix<Scalar> Matrix<Scalar>::
2433  expm(const Matrix<Scalar>& A) {
2434  casadi_error("'solve' not defined for " + type_name());
2435  return Matrix<Scalar>();
2436  }
2437 
2438  template<typename Scalar>
2439  Matrix<Scalar> Matrix<Scalar>::kron(const Matrix<Scalar>& a, const Matrix<Scalar>& b) {
2440  std::vector<Scalar> ret(a.nnz()*b.nnz());
2441  casadi_kron(get_ptr(a), a.sparsity(), get_ptr(b), b.sparsity(), get_ptr(ret));
2442 
2443  Sparsity sp_ret = Sparsity::kron(a.sparsity(), b.sparsity());
2444  return Matrix<Scalar>(sp_ret, ret, false);
2445  }
2446 
2447  template<typename Scalar>
2448  Matrix<Scalar> Matrix<Scalar>::diag(const Matrix<Scalar>& A) {
2449  // Nonzero mapping
2450  std::vector<casadi_int> mapping;
2451  // Get the sparsity
2452  Sparsity sp = A.sparsity().get_diag(mapping);
2453 
2454  Matrix<Scalar> ret = zeros(sp);
2455 
2456  for (casadi_int k=0; k<mapping.size(); k++) ret.nz(k) = A.nz(mapping[k]);
2457  return ret;
2458  }
2459 
2463  template<typename Scalar>
2464  Matrix<Scalar> Matrix<Scalar>::diagcat(const std::vector< Matrix<Scalar> > &A) {
2465  std::vector<Scalar> data;
2466 
2467  std::vector<Sparsity> sp;
2468  for (casadi_int i=0;i<A.size();++i) {
2469  data.insert(data.end(), A[i].nonzeros().begin(), A[i].nonzeros().end());
2470  sp.push_back(A[i].sparsity());
2471  }
2472 
2473  return Matrix<Scalar>(Sparsity::diagcat(sp), data, false);
2474  }
2475 
2476  template<typename Scalar>
2477  Matrix<Scalar> Matrix<Scalar>::unite(const Matrix<Scalar>& A, const Matrix<Scalar>& B) {
2478  // Join the sparsity patterns
2479  std::vector<unsigned char> mapping;
2480  Sparsity sp = A.sparsity().unite(B.sparsity(), mapping);
2481 
2482  // Create return matrix
2483  Matrix<Scalar> ret = zeros(sp);
2484 
2485  // Copy sparsity
2486  casadi_int elA=0, elB=0;
2487  for (casadi_int k=0; k<mapping.size(); ++k) {
2488  if (mapping[k]==1) {
2489  ret.nonzeros()[k] = A.nonzeros()[elA++];
2490  } else if (mapping[k]==2) {
2491  ret.nonzeros()[k] = B.nonzeros()[elB++];
2492  } else {
2493  casadi_error("Pattern intersection not empty");
2494  }
2495  }
2496 
2497  casadi_assert_dev(A.nnz()==elA);
2498  casadi_assert_dev(B.nnz()==elB);
2499 
2500  return ret;
2501  }
2502 
2503  template<typename Scalar>
2504  Matrix<Scalar> Matrix<Scalar>::polyval(const Matrix<Scalar>& p, const Matrix<Scalar>& x) {
2505  casadi_assert(p.is_dense(), "polynomial coefficients vector must be dense");
2506  casadi_assert(p.is_vector() && p.nnz()>0, "polynomial coefficients must be a vector");
2507  Matrix<Scalar> ret = x;
2508  for (auto&& e : ret.nonzeros()) {
2509  e = casadi_polyval(p.ptr(), p.numel()-1, e);
2510  }
2511  return ret;
2512  }
2513 
2514  template<typename Scalar>
2515  Matrix<Scalar> Matrix<Scalar>::norm_inf_mul(const Matrix<Scalar>& x,
2516  const Matrix<Scalar>& y) {
2517  casadi_assert(y.size1()==x.size2(), "Dimension error. Got " + x.dim()
2518  + " times " + y.dim() + ".");
2519 
2520  // Allocate work vectors
2521  std::vector<Scalar> dwork(x.size1());
2522  std::vector<casadi_int> iwork(x.size1()+1+y.size2());
2523 
2524  // Call C runtime
2525  return casadi_norm_inf_mul(x.ptr(), x.sparsity(), y.ptr(), y.sparsity(),
2526  get_ptr(dwork), get_ptr(iwork));
2527  }
2528 
2529  template<typename Scalar>
2530  void Matrix<Scalar>::expand(const Matrix<Scalar>& ex,
2531  Matrix<Scalar> &weights, Matrix<Scalar>& terms) {
2532  casadi_error("'expand' not defined for " + type_name());
2533  }
2534 
2535  template<typename Scalar>
2536  Matrix<Scalar> Matrix<Scalar>::pw_const(const Matrix<Scalar>& ex,
2537  const Matrix<Scalar>& tval,
2538  const Matrix<Scalar>& val) {
2539  casadi_error("'pw_const' not defined for " + type_name());
2540  return Matrix<Scalar>();
2541  }
2542 
2543  template<typename Scalar>
2544  Matrix<Scalar> Matrix<Scalar>::pw_lin(const Matrix<Scalar>& ex,
2545  const Matrix<Scalar>& tval,
2546  const Matrix<Scalar>& val) {
2547  casadi_error("'pw_lin' not defined for " + type_name());
2548  return Matrix<Scalar>();
2549  }
2550 
2551  template<typename Scalar>
2552  Matrix<Scalar> Matrix<Scalar>::if_else(const Matrix<Scalar> &cond,
2553  const Matrix<Scalar> &if_true,
2554  const Matrix<Scalar> &if_false,
2555  bool short_circuit) {
2556  return if_else_zero(cond, if_true) + if_else_zero(!cond, if_false);
2557  }
2558 
2559  template<typename Scalar>
2560  Matrix<Scalar> Matrix<Scalar>::conditional(const Matrix<Scalar>& ind,
2561  const std::vector<Matrix<Scalar> >& x,
2562  const Matrix<Scalar>& x_default,
2563  bool short_circuit) {
2564  casadi_assert(!short_circuit,
2565  "Short-circuiting 'conditional' not supported for " + type_name());
2566  casadi_assert(ind.is_scalar(true),
2567  "conditional: first argument must be scalar. Got " + ind.dim()+ " instead.");
2568 
2569  Matrix<Scalar> ret = x_default;
2570  for (casadi_int k=0; k<x.size(); ++k) {
2571  ret = if_else(ind==k, x[k], ret, short_circuit);
2572  }
2573  return ret;
2574  }
2575 
2576  template<typename Scalar>
2577  Matrix<Scalar> Matrix<Scalar>::heaviside(const Matrix<Scalar>& x) {
2578  return (1+sign(x))/2;
2579  }
2580 
2581  template<typename Scalar>
2582  Matrix<Scalar> Matrix<Scalar>::rectangle(const Matrix<Scalar>& x) {
2583  return 0.5*(sign(x+0.5)-sign(x-0.5));
2584  }
2585 
2586  template<typename Scalar>
2587  Matrix<Scalar> Matrix<Scalar>::triangle(const Matrix<Scalar>& x) {
2588  return rectangle(x/2)*(1-fabs(x));
2589  }
2590 
2591  template<typename Scalar>
2592  Matrix<Scalar> Matrix<Scalar>::ramp(const Matrix<Scalar>& x) {
2593  return x*heaviside(x);
2594  }
2595 
2596  template<typename Scalar>
2597  Matrix<Scalar> Matrix<Scalar>::
2598  gauss_quadrature(const Matrix<Scalar> &f,
2599  const Matrix<Scalar> &x, const Matrix<Scalar> &a,
2600  const Matrix<Scalar> &b, casadi_int order) {
2601  return gauss_quadrature(f, x, a, b, order, Matrix<Scalar>());
2602  }
2603 
2604  template<typename Scalar>
2605  Matrix<Scalar> Matrix<Scalar>::gauss_quadrature(const Matrix<Scalar>& f,
2606  const Matrix<Scalar>& x,
2607  const Matrix<Scalar>& a,
2608  const Matrix<Scalar>& b, casadi_int order,
2609  const Matrix<Scalar>& w) {
2610  casadi_error("'gauss_quadrature' not defined for " + type_name());
2611  return Matrix<Scalar>();
2612  }
2613 
2614  template<typename Scalar>
2615  Matrix<Scalar> Matrix<Scalar>::simplify(const Matrix<Scalar> &x) {
2616  return x;
2617  }
2618 
2619  template<typename Scalar>
2620  Matrix<Scalar> Matrix<Scalar>::substitute(const Matrix<Scalar>& ex,
2621  const Matrix<Scalar>& v,
2622  const Matrix<Scalar>& vdef) {
2623  casadi_error("'substitute' not defined for " + type_name());
2624  return Matrix<Scalar>();
2625  }
2626 
2627  template<typename Scalar>
2628  std::vector<Matrix<Scalar> >
2629  Matrix<Scalar>::substitute(const std::vector<Matrix<Scalar> >& ex,
2630  const std::vector<Matrix<Scalar> >& v,
2631  const std::vector<Matrix<Scalar> >& vdef) {
2632  casadi_error("'substitute' not defined for " + type_name());
2633  return std::vector<Matrix<Scalar> >();
2634  }
2635 
2636  template<typename Scalar>
2637  void Matrix<Scalar>::substitute_inplace(const std::vector<Matrix<Scalar> >& v,
2638  std::vector<Matrix<Scalar> >& vdef,
2639  std::vector<Matrix<Scalar> >& ex,
2640  bool reverse) {
2641  casadi_error("'substitute_inplace' not defined for " + type_name());
2642  }
2643 
2644  template<typename Scalar>
2645  void Matrix<Scalar>::extract_parametric(const Matrix<Scalar> &expr,
2646  const Matrix<Scalar>& par,
2647  Matrix<Scalar>& expr_ret,
2648  std::vector<Matrix<Scalar> >& symbols,
2649  std::vector< Matrix<Scalar> >& parametric,
2650  const Dict& opts) {
2651  casadi_error("'extract_parametric' not defined for " + type_name());
2652  }
2653 
2654  template<typename Scalar>
2655  void Matrix<Scalar>::separate_linear(const Matrix<Scalar> &expr,
2656  const Matrix<Scalar> &sym_lin, const Matrix<Scalar> &sym_const,
2657  Matrix<Scalar>& expr_const, Matrix<Scalar>& expr_lin, Matrix<Scalar>& expr_nonlin) {
2658  casadi_error("'separate_linear' not defined for " + type_name());
2659  }
2660 
2661  template<typename Scalar>
2662  bool Matrix<Scalar>::depends_on(const Matrix<Scalar> &x, const Matrix<Scalar> &arg) {
2663  casadi_error("'depends_on' not defined for " + type_name());
2664  return false;
2665  }
2666 
2667  template<typename Scalar>
2668  bool Matrix<Scalar>::contains_all(const std::vector <Matrix<Scalar> >& v,
2669  const std::vector <Matrix<Scalar> > &n) {
2670  casadi_error("'contains_all' not defined for " + type_name());
2671  return false;
2672  }
2673 
2674  template<typename Scalar>
2675  bool Matrix<Scalar>::contains_any(const std::vector<Matrix<Scalar> >& v,
2676  const std::vector <Matrix<Scalar> > &n) {
2677  casadi_error("'contains_any' not defined for " + type_name());
2678  return false;
2679  }
2680 
2681  template<typename Scalar>
2682  std::vector< Matrix<Scalar> > Matrix<Scalar>::cse(const std::vector< Matrix<Scalar> >& e) {
2683  casadi_error("'cse' not defined for " + type_name());
2684  return {};
2685  }
2686 
2687 
2688  template<typename Scalar>
2689  Matrix<Scalar> Matrix<Scalar>::
2690  jacobian(const Matrix<Scalar> &f, const Matrix<Scalar> &x, const Dict& opts) {
2691  casadi_error("'jacobian' not defined for " + type_name());
2692  return Matrix<Scalar>();
2693  }
2694 
2695  template<typename Scalar>
2696  Matrix<Scalar> Matrix<Scalar>::hessian(const Matrix<Scalar> &f,
2697  const Matrix<Scalar> &x,
2698  const Dict& opts) {
2699  casadi_error("'hessian' not defined for " + type_name());
2700  return Matrix<Scalar>();
2701  }
2702 
2703  template<typename Scalar>
2704  Matrix<Scalar> Matrix<Scalar>::hessian(const Matrix<Scalar> &f,
2705  const Matrix<Scalar> &x,
2706  Matrix<Scalar> &g,
2707  const Dict& opts) {
2708  casadi_error("'hessian' not defined for " + type_name());
2709  return Matrix<Scalar>();
2710  }
2711 
2712  template<typename Scalar>
2713  std::vector<std::vector<Matrix<Scalar> > >
2714  Matrix<Scalar>::
2715  forward(const std::vector<Matrix<Scalar> > &ex,
2716  const std::vector<Matrix<Scalar> > &arg,
2717  const std::vector<std::vector<Matrix<Scalar> > > &v,
2718  const Dict& opts) {
2719  casadi_error("'forward' not defined for " + type_name());
2720  }
2721 
2722  template<typename Scalar>
2723  std::vector<std::vector<Matrix<Scalar> > >
2724  Matrix<Scalar>::
2725  reverse(const std::vector<Matrix<Scalar> > &ex,
2726  const std::vector<Matrix<Scalar> > &arg,
2727  const std::vector<std::vector<Matrix<Scalar> > > &v,
2728  const Dict& opts) {
2729  casadi_error("'reverse' not defined for " + type_name());
2730  }
2731 
2732  template<typename Scalar>
2733  std::vector<bool>
2734  Matrix<Scalar>::which_depends(const Matrix<Scalar> &expr, const Matrix<Scalar> &var,
2735  casadi_int order, bool tr) {
2736  casadi_error("'which_depends' not defined for " + type_name());
2737  return std::vector<bool>();
2738  }
2739 
2740  template<typename Scalar>
2741  Sparsity
2742  Matrix<Scalar>::jacobian_sparsity(const Matrix<Scalar> &f, const Matrix<Scalar> &x) {
2743  casadi_error("'jacobian_sparsity' not defined for " + type_name());
2744  return Sparsity();
2745  }
2746 
2747  template<typename Scalar>
2748  Matrix<Scalar> Matrix<Scalar>::taylor(const Matrix<Scalar>& f,
2749  const Matrix<Scalar>& x,
2750  const Matrix<Scalar>& a, casadi_int order) {
2751  casadi_error("'taylor' not defined for " + type_name());
2752  return Matrix<Scalar>();
2753  }
2754 
2755  template<typename Scalar>
2756  Matrix<Scalar> Matrix<Scalar>::mtaylor(const Matrix<Scalar>& f,
2757  const Matrix<Scalar>& x,
2758  const Matrix<Scalar>& a, casadi_int order) {
2759  casadi_error("'mtaylor' not defined for " + type_name());
2760  return Matrix<Scalar>();
2761  }
2762 
2763  template<typename Scalar>
2764  Matrix<Scalar> Matrix<Scalar>::mtaylor(const Matrix<Scalar>& f,
2765  const Matrix<Scalar>& x,
2766  const Matrix<Scalar>& a, casadi_int order,
2767  const std::vector<casadi_int>&order_contributions) {
2768  casadi_error("'mtaylor' not defined for " + type_name());
2769  return Matrix<Scalar>();
2770  }
2771 
2772  template<typename Scalar>
2773  casadi_int Matrix<Scalar>::n_nodes(const Matrix<Scalar>& x) {
2774  casadi_error("'n_nodes' not defined for " + type_name());
2775  return 0;
2776  }
2777 
2778  template<typename Scalar>
2779  std::string
2780  Matrix<Scalar>::print_operator(const Matrix<Scalar>& x,
2781  const std::vector<std::string>& args) {
2782  casadi_error("'print_operator' not defined for " + type_name());
2783  return std::string();
2784  }
2785 
2786  template<typename Scalar>
2787  std::vector<Matrix<Scalar> > Matrix<Scalar>::symvar(const Matrix<Scalar>& x) {
2788  casadi_error("'symvar' not defined for " + type_name());
2789  return std::vector<Matrix<Scalar> >();
2790  }
2791 
2792  template<typename Scalar>
2793  void Matrix<Scalar>::extract(std::vector<Matrix<Scalar>>& ex, std::vector<Matrix<Scalar>>& v,
2794  std::vector<Matrix<Scalar>>& vdef, const Dict& opts) {
2795  casadi_error("'extract' not defined for " + type_name());
2796  }
2797 
2798  template<typename Scalar>
2799  void Matrix<Scalar>::shared(std::vector<Matrix<Scalar> >& ex,
2800  std::vector<Matrix<Scalar> >& v,
2801  std::vector<Matrix<Scalar> >& vdef,
2802  const std::string& v_prefix,
2803  const std::string& v_suffix) {
2804  casadi_error("'shared' not defined for " + type_name());
2805  }
2806 
2807  template<typename Scalar>
2808  Matrix<Scalar> Matrix<Scalar>::poly_coeff(const Matrix<Scalar>& f,
2809  const Matrix<Scalar>&x) {
2810  casadi_error("'poly_coeff' not defined for " + type_name());
2811  }
2812 
2813  template<typename Scalar>
2814  Matrix<Scalar> Matrix<Scalar>::poly_roots(const Matrix<Scalar>& p) {
2815  casadi_error("'poly_roots' not defined for " + type_name());
2816  }
2817 
2818  template<typename Scalar>
2819  Matrix<Scalar> Matrix<Scalar>::eig_symbolic(const Matrix<Scalar>& m) {
2820  casadi_error("'eig_symbolic' not defined for " + type_name());
2821  }
2822 
2823  template<typename Scalar>
2824  DM Matrix<Scalar>::evalf(const Matrix<Scalar>& m) {
2825  Function f("f", std::vector<SX>{}, std::vector<SX>{m});
2826  return f(std::vector<DM>{})[0];
2827  }
2828 
2829  template<typename Scalar>
2830  Matrix<Scalar> Matrix<Scalar>::sparsify(const Matrix<Scalar>& x, double tol) {
2831  // Quick return if there are no entries to be removed
2832  bool remove_nothing = true;
2833  for (auto it=x.nonzeros().begin(); it!=x.nonzeros().end() && remove_nothing; ++it) {
2834  remove_nothing = !casadi_limits<Scalar>::is_almost_zero(*it, tol);
2835  }
2836  if (remove_nothing) return x;
2837 
2838  // Get the current sparsity pattern
2839  casadi_int size1 = x.size1();
2840  casadi_int size2 = x.size2();
2841  const casadi_int* colind = x.colind();
2842  const casadi_int* row = x.row();
2843 
2844  // Construct the new sparsity pattern
2845  std::vector<casadi_int> new_colind(1, 0), new_row;
2846  std::vector<Scalar> new_data;
2847 
2848  // Loop over the columns
2849  for (casadi_int cc=0; cc<size2; ++cc) {
2850  // Loop over existing nonzeros
2851  for (casadi_int el=colind[cc]; el<colind[cc+1]; ++el) {
2852  // If it is not known to be a zero
2853  if (!casadi_limits<Scalar>::is_almost_zero(x->at(el), tol)) {
2854  // Save the nonzero in its new location
2855  new_data.push_back(x->at(el));
2856 
2857  // Add to pattern
2858  new_row.push_back(row[el]);
2859  }
2860  }
2861  // Save the new column offset
2862  new_colind.push_back(new_row.size());
2863  }
2864 
2865  // Construct the sparsity pattern
2866  Sparsity sp(size1, size2, new_colind, new_row);
2867 
2868  // Construct matrix and return
2869  return Matrix<Scalar>(sp, new_data);
2870  }
2871 
2872 
2873  template<typename Scalar>
2874  std::vector<Matrix<Scalar> > Matrix<Scalar>::get_input(const Function& f) {
2875  casadi_error("'get_input' not defined for " + type_name());
2876  }
2877 
2878  template<typename Scalar>
2879  std::vector<Matrix<Scalar> > Matrix<Scalar>::get_free(const Function& f) {
2880  casadi_error("'get_free' not defined for " + type_name());
2881  }
2882 
2883  template<typename Scalar>
2884  Matrix<Scalar>::operator double() const {
2885  casadi_assert_dev(is_scalar());
2886  return static_cast<double>(scalar());
2887  }
2888 
2889  template<typename Scalar>
2890  Matrix<Scalar>::operator casadi_int() const {
2891  casadi_assert_dev(is_scalar());
2892  return static_cast<casadi_int>(scalar());
2893  }
2894 
2895  template<typename Scalar>
2896  Matrix<Scalar> Matrix<Scalar>::_sym(const std::string& name, const Sparsity& sp) {
2897  casadi_error("'sym' not defined for " + type_name());
2898  }
2899 
2900  template<typename Scalar>
2901  Matrix<Scalar> Matrix<Scalar>::rand(const Sparsity& sp) { // NOLINT(runtime/threadsafe_fn)
2902 
2903  casadi_error("'rand' not defined for " + type_name());
2904  }
2905 
2906  template<typename Scalar>
2907  std::string Matrix<Scalar>::serialize() const {
2908  std::stringstream ss;
2909  serialize(ss);
2910  return ss.str();
2911  }
2912 
2913  template<typename Scalar>
2914  void Matrix<Scalar>::serialize(SerializingStream& s) const {
2915  s.pack("Matrix::sparsity", sparsity());
2916  s.pack("Matrix::nonzeros", nonzeros());
2917  }
2918 
2919  template<typename Scalar>
2920  Matrix<Scalar> Matrix<Scalar>::deserialize(DeserializingStream& s) {
2921  Sparsity sp;
2922  s.unpack("Matrix::sparsity", sp);
2923  std::vector<Scalar> nz;
2924  s.unpack("Matrix::nonzeros", nz);
2925  return Matrix<Scalar>(sp, nz, false);
2926  }
2927 
2928  template<typename Scalar>
2929  void Matrix<Scalar>::serialize(std::ostream &stream) const {
2930  SerializingStream s(stream);
2931  serialize(s);
2932  }
2933 
2934  template<typename Scalar>
2935  Matrix<Scalar> Matrix<Scalar>::deserialize(std::istream &stream) {
2936  DeserializingStream s(stream);
2937  return Matrix<Scalar>::deserialize(s);
2938  }
2939 
2940  template<typename Scalar>
2941  Matrix<Scalar> Matrix<Scalar>::deserialize(const std::string& s) {
2942  std::stringstream ss;
2943  ss << s;
2944  return deserialize(ss);
2945  }
2946 
2947 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
2948  template<typename Scalar>
2949  std::mutex& Matrix<Scalar>::get_mutex_temp() {
2950  casadi_error("'get_mutex_temp' not defined for " + type_name());
2951  }
2952 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
2953 
2954 } // namespace casadi
2955 
2956 #endif // CASADI_MATRIX_IMPL_HPP
Function object.
Definition: function.hpp:60
Sparsity sparsity() const
Get the sparsity pattern.
bool is_dense() const
Check if the matrix expression is dense.
bool is_column() const
Check if the matrix is a column vector (i.e. size2()==1)
casadi_int row(casadi_int el) const
Get the sparsity pattern. See the Sparsity class for details.
bool is_vector() const
Check if the matrix is a row or column vector.
casadi_int nnz() const
Get the number of (structural) non-zero elements.
casadi_int size2() const
Get the second dimension (i.e. number of columns)
bool is_row() const
Check if the matrix is a row vector (i.e. size1()==1)
casadi_int size1() const
Get the first dimension (i.e. number of rows)
casadi_int colind(casadi_int col) const
Get the sparsity pattern. See the Sparsity class for details.
static Matrix< Scalar > zeros(casadi_int nrow=1, casadi_int ncol=1)
Create a dense matrix or a matrix with specified sparsity with all entries zero.
std::pair< casadi_int, casadi_int > size() const
Get the shape.
bool is_scalar(bool scalar_and_dense=false) const
Check if the matrix expression is scalar.
Sparse matrix class. SX and DM are specializations.
Definition: matrix_decl.hpp:99
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
void print_split(std::vector< std::string > &nz, std::vector< std::string > &inter) const
Get strings corresponding to the nonzeros and the interdependencies.
Matrix< Scalar > T() const
Transpose the matrix.
static void set_precision(casadi_int precision)
Set the 'precision, width & scientific' used in printing and serializing to streams.
Definition: matrix_impl.hpp:39
void get(Matrix< Scalar > &m, bool ind1, const Slice &rr) const
void resize(casadi_int nrow, casadi_int ncol)
void print_sparse(std::ostream &stream, bool truncate=true) const
Print sparse matrix style.
static void set_width(casadi_int width)
Definition: matrix_impl.hpp:42
Matrix()
constructors
void set(const Matrix< Scalar > &m, bool ind1, const Slice &rr)
static std::string type_name()
Get name of the class.
void to_file(const std::string &filename, const std::string &format="") const
static void set_scientific(bool scientific)
Definition: matrix_impl.hpp:45
void disp(std::ostream &stream, bool more=false) const
Print a representation of the object.
bool __nonzero__() const
Returns the truth value of a Matrix.
Definition: matrix_impl.hpp:70
static void rng(casadi_int seed)
Seed the random number generator.
Definition: matrix_impl.hpp:60
void print_dense(std::ostream &stream, bool truncate=true) const
Print dense matrix-stype.
void reserve(casadi_int nnz)
void set_nz(const Matrix< Scalar > &m, bool ind1, const Slice &k)
void print_vector(std::ostream &stream, bool truncate=true) const
Print vector-style.
std::string get_str(bool more=false) const
Get string representation.
void get_nz(Matrix< Scalar > &m, bool ind1, const Slice &k) const
void print_scalar(std::ostream &stream) const
Print scalar.
Class representing a Slice.
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:106
std::vector< casadi_int > find(bool ind1=SWIG_IND1) const
Get the location of all non-zero elements as they would appear in a Dense matrix.
Sparsity sub(const std::vector< casadi_int > &rr, const std::vector< casadi_int > &cc, std::vector< casadi_int > &mapping, bool ind1=false) const
Get a submatrix.
casadi_int numel() const
The total number of elements, including structural zeros, i.e. size2()*size1()
casadi_int size1() const
Get the number of rows.
static Sparsity dense(casadi_int nrow, casadi_int ncol=1)
Create a dense rectangular sparsity pattern *.
Sparsity T() const
Transpose the matrix.
bool is_column() const
Check if the pattern is a column vector (i.e. size2()==1)
static Sparsity triplet(casadi_int nrow, casadi_int ncol, const std::vector< casadi_int > &row, const std::vector< casadi_int > &col, std::vector< casadi_int > &mapping, bool invert_mapping)
Create a sparsity pattern given the nonzeros in sparse triplet form *.
casadi_int nnz() const
Get the number of (structural) non-zeros.
casadi_int size2() const
Get the number of columns.
casadi_int row(casadi_int el) const
Get the row of a non-zero element.
bool is_empty(bool both=false) const
Check if the sparsity is empty.
std::pair< casadi_int, casadi_int > size() const
Get the shape.
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 > densify(const Matrix< Scalar > &x)
Make the matrix dense if not already.
friend Matrix< Scalar > cumsum(const Matrix< Scalar > &x, casadi_int axis=-1)
Returns cumulative sum along given axis (MATLAB convention)
The casadi namespace.
Definition: archiver.hpp:32
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.
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.