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  StreamStateGuard backup(stream);
613 
614  stream.precision(stream_precision_);
615  stream.width(stream_width_);
616  if (stream_scientific_) {
617  stream.setf(std::ios::scientific);
618  } else {
619  stream.unsetf(std::ios::scientific);
620  }
621 
622  if (nnz()==0) {
623  stream << "00";
624  } else {
625  stream << scalar();
626  }
627  stream << std::flush;
628  }
629 
630  template<typename Scalar>
631  void Matrix<Scalar>::print_vector(std::ostream &stream, bool truncate) const {
632  print_vector(stream, sparsity(), ptr(), truncate);
633  }
634 
635  template<typename Scalar>
636  void Matrix<Scalar>::print_vector(std::ostream &stream, const Sparsity& sp,
637  const Scalar* nonzeros, bool truncate) {
638  casadi_assert(sp.is_column(), "Not a vector");
639 
640  // Get components
641  std::vector<std::string> nz, inter;
642  print_split(sp.nnz(), nonzeros, nz, inter);
643 
644  // Print intermediate expressions
645  for (casadi_int i=0; i<inter.size(); ++i)
646  stream << "@" << (i+1) << "=" << inter[i] << ", ";
647  inter.clear();
648 
649  // Access data structures
650  const casadi_int* row = sp.row();
651  casadi_int nnz = sp.nnz();
652  casadi_int size1 = sp.size1();
653 
654  // No need to truncate if less than 1000 entries
655  const casadi_int max_numel = 1000;
656  if (truncate && size1<=max_numel) truncate=false;
657 
658  // Nonzero
659  casadi_int el=0;
660 
661  // Loop over rows
662  stream << "[";
663  for (casadi_int rr=0; rr<size1; ++rr) {
664  // String representation
665  std::string s = el<nnz && rr==row[el] ? nz.at(el++) : "00";
666 
667  // Truncate?
668  if (truncate && rr>=3 && rr<size1-3) {
669  // Do not print
670  if (rr==3) stream << ", ...";
671  } else {
672  // Print
673  if (rr!=0) stream << ", ";
674  stream << s;
675  }
676  }
677  stream << "]" << std::flush;
678  }
679 
680  template<typename Scalar>
681  void Matrix<Scalar>::print_dense(std::ostream &stream, bool truncate) const {
682  print_dense(stream, sparsity(), ptr(), truncate);
683  }
684 
685  template<typename Scalar>
686  void Matrix<Scalar>::print_sparse(std::ostream &stream, bool truncate) const {
687  print_sparse(stream, sparsity(), ptr(), truncate);
688  }
689 
690  template<typename Scalar>
691  void Matrix<Scalar>::print_split(std::vector<std::string>& nz,
692  std::vector<std::string>& inter) const {
693 
694  print_split(nnz(), ptr(), nz, inter);
695  }
696 
697  template<typename Scalar>
698  void Matrix<Scalar>::print_default(std::ostream &stream, const Sparsity& sp,
699  const Scalar* nonzeros, bool truncate) {
700  if (sp.is_empty()) {
701  stream << sp.size1() << "x" << sp.size2();
702  } else if (sp.numel()==1) {
703  if (sp.nnz()==0) {
704  stream << "00";
705  } else {
706  print_scalar(stream, *nonzeros);
707  }
708  } else if (sp.is_column()) {
709  print_vector(stream, sp, nonzeros, truncate);
710  } else if (std::max(sp.size1(), sp.size2())<=10 ||
711  static_cast<double>(sp.nnz())/static_cast<double>(sp.numel())>=0.5) {
712  // if "small" or "dense"
713  print_dense(stream, sp, nonzeros, truncate);
714  } else {
715  print_sparse(stream, sp, nonzeros, truncate);
716  }
717  }
718 
719  template<typename Scalar>
720  void Matrix<Scalar>::print_canonical(std::ostream &stream, const Sparsity& sp,
721  const Scalar* nonzeros, bool truncate) {
722  casadi_error("'print_canonical' not defined for " + type_name());
723  }
724 
725  template<typename Scalar>
726  void Matrix<Scalar>::print_scalar(std::ostream &stream, const Scalar& e) {
727  std::streamsize precision = stream.precision();
728  std::streamsize width = stream.width();
729  std::ios_base::fmtflags flags = stream.flags();
730 
731  stream.precision(stream_precision_);
732  stream.width(stream_width_);
733  if (stream_scientific_) {
734  stream.setf(std::ios::scientific);
735  } else {
736  stream.unsetf(std::ios::scientific);
737  }
738  stream << e;
739  stream << std::flush;
740 
741  stream.precision(precision);
742  stream.width(width);
743  stream.flags(flags);
744  }
745 
746  template<typename Scalar>
747  void Matrix<Scalar>::print_split(casadi_int nnz, const Scalar* nonzeros,
748  std::vector<std::string>& nz,
749  std::vector<std::string>& inter) {
750  nz.resize(nnz);
751  inter.resize(0);
752 
753  // Temporary
754  std::stringstream ss;
755  ss.precision(stream_precision_);
756  ss.width(stream_width_);
757  if (stream_scientific_) {
758  ss.setf(std::ios::scientific);
759  } else {
760  ss.unsetf(std::ios::scientific);
761  }
762 
763  // Print nonzeros
764  for (casadi_int i=0; i<nz.size(); ++i) {
765  ss.str(std::string());
766  ss << nonzeros[i];
767  nz[i] = ss.str();
768  }
769  }
770 
771  template<typename Scalar>
772  void Matrix<Scalar>::print_sparse(std::ostream &stream, const Sparsity& sp,
773  const Scalar* nonzeros, bool truncate) {
774  // Access data structures
775  casadi_int size1 = sp.size1();
776  casadi_int size2 = sp.size2();
777  const casadi_int* colind = sp.colind();
778  const casadi_int* row = sp.row();
779  casadi_int nnz = sp.nnz();
780 
781  // Quick return if all zero sparse
782  if (nnz==0) {
783  stream << "all zero sparse: " << size1 << "-by-" << size2 << std::flush;
784  return;
785  }
786 
787  // Print header
788  stream << "sparse: " << size1 << "-by-" << size2 << ", " << nnz << " nnz";
789 
790  // Get components
791  std::vector<std::string> nz, inter;
792  print_split(nnz, nonzeros, nz, inter);
793 
794  // Print intermediate expressions
795  for (casadi_int i=0; i<inter.size(); ++i)
796  stream << std::endl << " @" << (i+1) << "=" << inter[i] << ",";
797  inter.clear();
798 
799  // No need to truncate if less than 1000 nonzeros
800  const casadi_int max_nnz = 1000;
801  if (truncate && nnz<=max_nnz) truncate=false;
802 
803  // Print nonzeros
804  for (casadi_int cc=0; cc<size2; ++cc) {
805  for (casadi_int el=colind[cc]; el<colind[cc+1]; ++el) {
806  if (truncate && el>=3 && el<nnz-3) {
807  if (el==3) stream << std::endl << " ...";
808  } else {
809  stream << std::endl << " (" << row[el] << ", " << cc << ") -> " << nz.at(el);
810  InterruptHandler::check();
811  }
812  }
813  }
814  stream << std::flush;
815  }
816 
817  template<typename Scalar>
818  void Matrix<Scalar>::print_dense(std::ostream &stream, const Sparsity& sp,
819  const Scalar* nonzeros, bool truncate) {
820  // Get components
821  std::vector<std::string> nz, inter;
822  print_split(sp.nnz(), nonzeros, nz, inter);
823 
824  // Print intermediate expressions
825  for (casadi_int i=0; i<inter.size(); ++i)
826  stream << "@" << (i+1) << "=" << inter[i] << ", ";
827  inter.clear();
828 
829  // Access data structures
830  casadi_int size1 = sp.size1();
831  casadi_int size2 = sp.size2();
832  const casadi_int* colind = sp.colind();
833  const casadi_int* row = sp.row();
834 
835  // No need to truncate if less than 1000 entries
836  const casadi_int max_numel = 1000;
837  if (truncate && size1*size2<=max_numel) truncate=false;
838 
839  // Truncate rows and/or columns
840  bool truncate_rows = truncate && size1>=7;
841  bool truncate_columns = truncate && size2>=7;
842 
843  // Index counter for each column
844  std::vector<casadi_int> ind(colind, colind+size2+1);
845 
846  // Print as a single line?
847  bool oneliner=size1<=1;
848 
849  // Loop over rows
850  for (casadi_int rr=0; rr<size1; ++rr) {
851  // Print row?
852  bool print_row = !(truncate_rows && rr>=3 && rr<size1-3);
853 
854  // Beginning of row
855  if (rr==0) {
856  if (!oneliner) stream << std::endl;
857  stream << "[[";
858  } else if (print_row) {
859  stream << " [";
860  }
861 
862  // Loop over columns
863  for (casadi_int cc=0; cc<size2; ++cc) {
864  // String representation of element
865  std::string s = ind[cc]<colind[cc+1] && row[ind[cc]]==rr
866  ? nz.at(ind[cc]++) : "00";
867 
868  // Skip whole row?
869  if (!print_row) continue;
870 
871  // Print column?
872  bool print_column = !(truncate_columns && cc>=3 && cc<size2-3);
873 
874  // Print element
875  if (print_column) {
876  if (cc!=0) stream << ", ";
877  stream << s;
878  } else if (cc==3) {
879  stream << ", ...";
880  }
881  }
882 
883  // End of row
884  if (rr<size1-1) {
885  if (print_row) {
886  stream << "], ";
887  if (!oneliner) stream << std::endl;
888  } else if (rr==3) {
889  stream << " ...," << std::endl;
890  }
891  } else {
892  stream << "]]";
893  }
894  }
895  stream << std::flush;
896  }
897 
898  template<typename Scalar>
899  void Matrix<Scalar>::to_file(const std::string& filename, const std::string& format) const {
900  to_file(filename, sparsity(), ptr(), format);
901  }
902 
903  template<typename Scalar>
904  void Matrix<Scalar>::disp(std::ostream& stream, bool more) const {
905  print_default(stream, sparsity(), ptr());
906  }
907 
908  template<typename Scalar>
909  std::string Matrix<Scalar>::get_str(bool more) const {
910  std::stringstream ss;
911  disp(ss, more);
912  return ss.str();
913  }
914 
915  template<typename Scalar>
916  void Matrix<Scalar>::reserve(casadi_int nnz) {
917  reserve(nnz, size2());
918  }
919 
920  template<typename Scalar>
921  void Matrix<Scalar>::reserve(casadi_int nnz, casadi_int ncol) {
922  nonzeros().reserve(nnz);
923  }
924 
925  template<typename Scalar>
926  void Matrix<Scalar>::resize(casadi_int nrow, casadi_int ncol) {
927  sparsity_.resize(nrow, ncol);
928  }
929 
930  template<typename Scalar>
931  void Matrix<Scalar>::clear() {
932  sparsity_ = Sparsity(0, 0);
933  nonzeros().clear();
934  }
935 
936  template<typename Scalar>
937  Matrix<Scalar>::Matrix(double val) :
938  sparsity_(
939  Sparsity::dense(1, 1)),
940  nonzeros_(std::vector<Scalar>(1, static_cast<Scalar>(val))) {
941  }
942 
943  template<typename Scalar>
944  Matrix<Scalar>::Matrix(const std::vector< std::vector<double> >& d) {
945  // Get dimensions
946  casadi_int nrow=d.size();
947  casadi_int ncol=d.empty() ? 1 : d.front().size();
948 
949  // Assert consistency
950  for (casadi_int rr=0; rr<nrow; ++rr) {
951  casadi_assert(ncol==d[rr].size(),
952  "Shape mismatch.\n"
953  "Attempting to construct a matrix from a nested list.\n"
954  "I got convinced that the desired size is (" + str(nrow) + " x " + str(ncol)
955  + " ), but now I encounter a vector of size (" + str(d[rr].size()) + " )");
956  }
957 
958  // Form matrix
959  sparsity_ = Sparsity::dense(nrow, ncol);
960  nonzeros().resize(nrow*ncol);
961  typename std::vector<Scalar>::iterator it=nonzeros_.begin();
962  for (casadi_int cc=0; cc<ncol; ++cc) {
963  for (casadi_int rr=0; rr<nrow; ++rr) {
964  *it++ = static_cast<Scalar>(d[rr][cc]);
965  }
966  }
967  }
968 
969  template<typename Scalar>
970  Matrix<Scalar>::Matrix(const Sparsity& sp) : sparsity_(sp), nonzeros_(sp.nnz(), 1) {
971  }
972 
973  template<typename Scalar>
974  Matrix<Scalar>::Matrix(casadi_int nrow, casadi_int ncol) : sparsity_(nrow, ncol) {
975  }
976 
977  template<typename Scalar>
978  Matrix<Scalar>::Matrix(const std::pair<casadi_int, casadi_int>& rc) : sparsity_(rc) {
979  }
980 
981  template<typename Scalar>
982  Matrix<Scalar>::Matrix(const Sparsity& sp, const Scalar& val, bool dummy) :
983  sparsity_(sp), nonzeros_(sp.nnz(), val) {
984  }
985 
986  template<typename Scalar>
987  Matrix<Scalar>::Matrix(const Sparsity& sp, const std::vector<Scalar>& d, bool dummy) :
988  sparsity_(sp), nonzeros_(d) {
989  casadi_assert(sp.nnz()==d.size(), "Size mismatch.\n"
990  "You supplied a sparsity of " + sp.dim()
991  + ", but the supplied vector is of length " + str(d.size()));
992  }
993 
994  template<typename Scalar>
995  Matrix<Scalar>::Matrix(const Sparsity& sp, const Matrix<Scalar>& d) {
996  if (d.is_scalar()) {
997  *this = Matrix<Scalar>(sp, d.scalar(), false);
998  } else if (sp.nnz()==0) {
999  casadi_assert(d.nnz()==0,
1000  "You passed nonzeros (" + d.dim(true) +
1001  ") to the constructor of a fully sparse matrix (" + sp.dim(true) + ").");
1002  *this = Matrix<Scalar>(sp);
1003  } else if (d.is_column() || d.size1()==1) {
1004  casadi_assert_dev(sp.nnz()==d.numel());
1005  if (d.is_dense()) {
1006  *this = Matrix<Scalar>(sp, d.nonzeros(), false);
1007  } else {
1008  *this = Matrix<Scalar>(sp, densify(d).nonzeros(), false);
1009  }
1010  } else {
1011  casadi_error("Matrix(Sparsity, Matrix): Only allowed for scalars and vectors");
1012  }
1013  }
1014 
1015  template<typename Scalar>
1016  Matrix<Scalar> Matrix<Scalar>::unary(casadi_int op, const Matrix<Scalar> &x) {
1017  // Return value
1018  Matrix<Scalar> ret = Matrix<Scalar>::zeros(x.sparsity());
1019 
1020  // Nonzeros
1021  std::vector<Scalar>& ret_data = ret.nonzeros();
1022  const std::vector<Scalar>& x_data = x.nonzeros();
1023 
1024  // Do the operation on all non-zero elements
1025  for (casadi_int el=0; el<x.nnz(); ++el) {
1026  casadi_math<Scalar>::fun(op, x_data[el], x_data[el], ret_data[el]);
1027  }
1028 
1029  // Check the value of the structural zero-entries, if there are any
1030  if (!x.is_dense() && !operation_checker<F0XChecker>(op)) {
1031  // Get the value for the structural zeros
1032  Scalar fcn_0;
1033  casadi_math<Scalar>::fun(op, 0, 0, fcn_0);
1034  if (!casadi_limits<Scalar>::is_zero(fcn_0)) { // Remove this if?
1035  ret = densify(ret, fcn_0);
1036  }
1037  }
1038 
1039  return ret;
1040  }
1041 
1042  template<typename Scalar>
1043  Matrix<Scalar> Matrix<Scalar>::operator-() const {
1044  return unary(OP_NEG, *this);
1045  }
1046 
1047  template<typename Scalar>
1048  Matrix<Scalar> Matrix<Scalar>::operator+() const {
1049  return *this;
1050  }
1051 
1052  template<typename Scalar>
1053  Matrix<Scalar> Matrix<Scalar>::mrdivide(const Matrix<Scalar>& b,
1054  const Matrix<Scalar>& a) {
1055  if (a.is_scalar() || b.is_scalar()) return b/a;
1056  return solve(a.T(), b.T()).T();
1057  }
1058 
1059  template<typename Scalar>
1060  Matrix<Scalar> Matrix<Scalar>::mldivide(const Matrix<Scalar>& a,
1061  const Matrix<Scalar>& b) {
1062  if (a.is_scalar() || b.is_scalar()) return b/a;
1063  return solve(a, b);
1064  }
1065 
1066  template<typename Scalar>
1067  Matrix<Scalar> Matrix<Scalar>::printme(const Matrix<Scalar>& y) const {
1068  return binary(OP_PRINTME, *this, y);
1069  }
1070 
1071  template<typename Scalar>
1072  void Matrix<Scalar>::erase(const std::vector<casadi_int>& rr,
1073  const std::vector<casadi_int>& cc, bool ind1) {
1074  // Erase from sparsity pattern
1075  std::vector<casadi_int> mapping = sparsity_.erase(rr, cc, ind1);
1076 
1077  // Update non-zero entries
1078  for (casadi_int k=0; k<mapping.size(); ++k)
1079  nonzeros()[k] = nonzeros()[mapping[k]];
1080 
1081  // Truncate nonzero vector
1082  nonzeros().resize(mapping.size());
1083  }
1084 
1085  template<typename Scalar>
1086  void Matrix<Scalar>::erase(const std::vector<casadi_int>& rr, bool ind1) {
1087  // Erase from sparsity pattern
1088  std::vector<casadi_int> mapping = sparsity_.erase(rr, ind1);
1089 
1090  // Update non-zero entries
1091  for (casadi_int k=0; k<mapping.size(); ++k)
1092  nonzeros()[k] = nonzeros()[mapping[k]];
1093 
1094  // Truncate nonzero vector
1095  nonzeros().resize(mapping.size());
1096  }
1097 
1098  template<typename Scalar>
1099  void Matrix<Scalar>::remove(const std::vector<casadi_int>& rr,
1100  const std::vector<casadi_int>& cc) {
1101  casadi_assert_bounded(rr, size1());
1102  casadi_assert_bounded(cc, size2());
1103 
1104  // Remove by performing a complementary slice
1105  std::vector<casadi_int> rrc = complement(rr, size1());
1106  std::vector<casadi_int> ccc = complement(cc, size2());
1107 
1108  Matrix<Scalar> ret = (*this)(rrc, ccc); // NOLINT(cppcoreguidelines-slicing)
1109 
1110  operator=(ret);
1111 
1112  }
1113 
1114  template<typename Scalar>
1115  void Matrix<Scalar>::enlarge(casadi_int nrow, casadi_int ncol, const std::vector<casadi_int>& rr,
1116  const std::vector<casadi_int>& cc, bool ind1) {
1117  sparsity_.enlarge(nrow, ncol, rr, cc, ind1);
1118  }
1119 
1120  template<typename Scalar>
1121  const Sparsity& Matrix<Scalar>::sparsity() const {
1122  return sparsity_;
1123  }
1124 
1125  template<typename Scalar>
1126  std::vector<Scalar>& Matrix<Scalar>::nonzeros() {
1127  return nonzeros_;
1128  }
1129 
1130  template<typename Scalar>
1131  const std::vector<Scalar>& Matrix<Scalar>::nonzeros() const {
1132  return nonzeros_;
1133  }
1134 
1135  template<typename Scalar>
1136  Scalar* Matrix<Scalar>::ptr() {
1137  return nonzeros_.empty() ? nullptr : &nonzeros_.front();
1138  }
1139 
1140  template<typename Scalar>
1141  const Scalar* Matrix<Scalar>::ptr() const {
1142  return nonzeros_.empty() ? nullptr : &nonzeros_.front();
1143  }
1144 
1145  template<typename Scalar>
1146  Sparsity Matrix<Scalar>::get_sparsity() const {
1147  return sparsity();
1148  }
1149 
1150  template<typename Scalar>
1151  Matrix<Scalar> Matrix<Scalar>::mtimes(const Matrix<Scalar> &x, const Matrix<Scalar> &y) {
1152  if (x.is_scalar() || y.is_scalar()) {
1153  // Use element-wise multiplication if at least one factor scalar
1154  return x*y;
1155  } else {
1156  Matrix<Scalar> z = Matrix<Scalar>::zeros(Sparsity::mtimes(x.sparsity(), y.sparsity()));
1157  return mac(x, y, z);
1158  }
1159  }
1160 
1161  template<typename Scalar>
1162  Matrix<Scalar> Matrix<Scalar>::mac(const Matrix<Scalar> &x,
1163  const Matrix<Scalar> &y,
1164  const Matrix<Scalar> &z) {
1165  if (x.is_scalar() || y.is_scalar()) {
1166  // Use element-wise multiplication if at least one factor scalar
1167  return z + x*y;
1168  }
1169 
1170  // Check matching dimensions
1171  casadi_assert(x.size2()==y.size1(),
1172  "Matrix product with incompatible dimensions. Lhs is "
1173  + x.dim() + " and rhs is " + y.dim() + ".");
1174 
1175  casadi_assert(y.size2()==z.size2(),
1176  "Matrix addition with incompatible dimensions. Lhs is "
1177  + mtimes(x, y).dim() + " and rhs is " + z.dim() + ".");
1178 
1179  casadi_assert(x.size1()==z.size1(),
1180  "Matrix addition with incompatible dimensions. Lhs is "
1181  + mtimes(x, y).dim() + " and rhs is " + z.dim() + ".");
1182 
1183  // Check if we can simplify the product
1184  if (x.is_eye()) {
1185  return y + z;
1186  } else if (y.is_eye()) {
1187  return x + z;
1188  } else if (x.is_zero() || y.is_zero()) {
1189  return z;
1190  } else {
1191  // Carry out the matrix product
1192  Matrix<Scalar> ret = z;
1193  std::vector<Scalar> work(x.size1());
1194  casadi_mtimes(x.ptr(), x.sparsity(), y.ptr(), y.sparsity(),
1195  ret.ptr(), ret.sparsity(), get_ptr(work), false);
1196  return ret;
1197  }
1198  }
1199 
1200  template<typename Scalar>
1201  Matrix<Scalar> Matrix<Scalar>::
1202  _bilin(const Matrix<Scalar>& A, const Matrix<Scalar>& x,
1203  const Matrix<Scalar>& y) {
1204  return casadi_bilin(A.ptr(), A.sparsity(), x.ptr(), y.ptr());
1205  }
1206 
1207  template<typename Scalar>
1208  Matrix<Scalar> Matrix<Scalar>::
1209  _rank1(const Matrix<Scalar>& A, const Matrix<Scalar>& alpha,
1210  const Matrix<Scalar>& x, const Matrix<Scalar>& y) {
1211  Matrix<Scalar> ret = A;
1212  casadi_rank1(ret.ptr(), ret.sparsity(), *alpha.ptr(), x.ptr(), y.ptr());
1213  return ret;
1214  }
1215 
1216 
1217  template<typename Scalar>
1218  Matrix<Scalar> Matrix<Scalar>::
1219  _logsumexp(const Matrix<Scalar>& x) {
1220  Matrix<Scalar> mx = mmax(x);
1221  return mx+log(sum1(exp(x-mx)));
1222  }
1223 
1224  template<typename Scalar>
1225  Matrix<Scalar> Matrix<Scalar>::T() const {
1226  // quick return if empty or scalar
1227  if ((size1()==0 && size2()==0) || is_scalar()) return *this;
1228 
1229  // Create the new sparsity pattern and the mapping
1230  std::vector<casadi_int> mapping;
1231  Sparsity s = sparsity().transpose(mapping);
1232 
1233  // create the return matrix
1234  Matrix<Scalar> ret = zeros(s);
1235 
1236  // Copy the content
1237  for (casadi_int i=0; i<mapping.size(); ++i)
1238  ret->at(i) = nonzeros().at(mapping[i]);
1239 
1240  return ret;
1241  }
1242 
1243  template<typename Scalar>
1244  const Scalar Matrix<Scalar>::scalar() const {
1245  // Make sure that the matrix is 1-by-1
1246  casadi_assert(is_scalar(), "Can only convert 1-by-1 matrices to scalars");
1247 
1248  // return zero or the nonzero element
1249  if (nnz()==1)
1250  return nonzeros()[0];
1251  else
1252  return casadi_limits<Scalar>::zero;
1253  }
1254 
1255  template<typename Scalar>
1256  Matrix<Scalar> Matrix<Scalar>::binary(casadi_int op,
1257  const Matrix<Scalar> &x,
1258  const Matrix<Scalar> &y) {
1259  if (x.is_scalar()) {
1260  return scalar_matrix(op, x, y);
1261  } else if (y.is_scalar()) {
1262  return matrix_scalar(op, x, y);
1263  } else {
1264  return matrix_matrix(op, x, y);
1265  }
1266  }
1268  template<typename Scalar>
1269  std::vector< Matrix<Scalar> > Matrix<Scalar>::call(const Function& f,
1270  const std::vector< Matrix<Scalar> > &x) {
1271  // Flatten all inputs
1272  std::vector<Scalar> dep;
1273  for (auto & e : x) {
1274  dep.insert(dep.end(), e.nonzeros().begin(), e.nonzeros().end());
1275  }
1276 
1277  std::vector<Scalar> r = Matrix<Scalar>::call(f, dep);
1278 
1279  // Package rsults in 1-by-1 Matrix objects
1280  std::vector< Matrix<Scalar> > ret;
1281  ret.reserve(r.size());
1282  for (auto & e : r) {
1283  ret.push_back(e);
1284  }
1285 
1286  return ret;
1287  }
1288 
1289 
1290  template<typename Scalar>
1291  std::vector<Scalar> Matrix<Scalar>::call(const Function& f, const std::vector< Scalar > &x) {
1292  casadi_error("'call' not defined for " + type_name());
1293  }
1294 
1295  template<typename Scalar>
1296  Matrix<Scalar> Matrix<Scalar>::
1297  scalar_matrix(casadi_int op, const Matrix<Scalar> &x, const Matrix<Scalar> &y) {
1298  if ( (operation_checker<FX0Checker>(op) && y.nnz()==0) ||
1299  (operation_checker<F0XChecker>(op) && x.nnz()==0))
1300  return Matrix<Scalar>::zeros(Sparsity(y.size()));
1301 
1302  // Return value
1303  Matrix<Scalar> ret = Matrix<Scalar>::zeros(y.sparsity());
1304 
1305  // Nonzeros
1306  std::vector<Scalar>& ret_data = ret.nonzeros();
1307  const std::vector<Scalar>& x_data = x.nonzeros();
1308  const Scalar& x_val = x_data.empty() ? casadi_limits<Scalar>::zero : x->front();
1309  const std::vector<Scalar>& y_data = y.nonzeros();
1310 
1311  // Do the operation on all non-zero elements
1312  for (casadi_int el=0; el<y.nnz(); ++el) {
1313  casadi_math<Scalar>::fun(op, x_val, y_data[el], ret_data[el]);
1314  }
1315 
1316  // Check the value of the structural zero-entries, if there are any
1317  if (!y.is_dense() && !operation_checker<FX0Checker>(op)) {
1318  // Get the value for the structural zeros
1319  Scalar fcn_0;
1320  casadi_math<Scalar>::fun(op, x_val, casadi_limits<Scalar>::zero, fcn_0);
1321  if (!casadi_limits<Scalar>::is_zero(fcn_0)) { // Remove this if?
1322  ret = densify(ret, fcn_0);
1323  }
1324  }
1325 
1326  return ret;
1327  }
1328 
1329  template<typename Scalar>
1330  Matrix<Scalar> Matrix<Scalar>::
1331  matrix_scalar(casadi_int op, const Matrix<Scalar> &x, const Matrix<Scalar> &y) {
1332 
1333  if ( (operation_checker<FX0Checker>(op) && y.nnz()==0) ||
1334  (operation_checker<F0XChecker>(op) && x.nnz()==0))
1335  return Matrix<Scalar>::zeros(Sparsity(x.size()));
1336 
1337  // Return value
1338  Matrix<Scalar> ret = Matrix<Scalar>::zeros(x.sparsity());
1339 
1340  // Nonzeros
1341  std::vector<Scalar>& ret_data = ret.nonzeros();
1342  const std::vector<Scalar>& x_data = x.nonzeros();
1343  const std::vector<Scalar>& y_data = y.nonzeros();
1344  const Scalar& y_val = y_data.empty() ? casadi_limits<Scalar>::zero : y->front();
1345 
1346  // Do the operation on all non-zero elements
1347  for (casadi_int el=0; el<x.nnz(); ++el) {
1348  casadi_math<Scalar>::fun(op, x_data[el], y_val, ret_data[el]);
1349  }
1350 
1351  // Check the value of the structural zero-entries, if there are any
1352  if (!x.is_dense() && !operation_checker<F0XChecker>(op)) {
1353  // Get the value for the structural zeros
1354  Scalar fcn_0;
1355  casadi_math<Scalar>::fun(op, casadi_limits<Scalar>::zero, y_val, fcn_0);
1356  if (!casadi_limits<Scalar>::is_zero(fcn_0)) { // Remove this if?
1357  ret = densify(ret, fcn_0);
1358  }
1359  }
1360 
1361  return ret;
1362  }
1363 
1364  template<typename Scalar>
1365  Matrix<Scalar> Matrix<Scalar>::
1366  matrix_matrix(casadi_int op, const Matrix<Scalar> &x, const Matrix<Scalar> &y) {
1367  // Check, correct dimensions
1368  if (x.size() != y.size()) {
1369  // x and y are horizontal multiples of each other?
1370  if (!x.is_empty() && !y.is_empty()) {
1371  if (x.size1() == y.size1() && x.size2() % y.size2() == 0) {
1372  return matrix_matrix(op, x, repmat(y, 1, x.size2() / y.size2()));
1373  } else if (y.size1() == x.size1() && y.size2() % x.size2() == 0) {
1374  return matrix_matrix(op, repmat(x, 1, y.size2() / x.size2()), y);
1375  }
1376  }
1377  // x and y are empty horizontal multiples of each other?
1378  if (x.size1()==0 && y.size1()==0 && x.size2()>0 && y.size2()>0) {
1379  if (x.size2() % y.size2() == 0) {
1380  return Matrix<Scalar>(0, x.size2());
1381  } else if (y.size2() % x.size2() == 0) {
1382  return Matrix<Scalar>(0, y.size2());
1383  }
1384  }
1385  // Dimension mismatch
1386  casadi_error("Dimension mismatch for " + casadi_math<Scalar>::print(op, "x", "y") +
1387  ", x is " + x.dim() + ", while y is " + y.dim());
1388  }
1389 
1390  // Get the sparsity pattern of the result
1391  // (ignoring structural zeros giving rise to nonzero result)
1392  const Sparsity& x_sp = x.sparsity();
1393  const Sparsity& y_sp = y.sparsity();
1394  Sparsity r_sp = x_sp.combine(y_sp, operation_checker<F0XChecker>(op),
1395  operation_checker<FX0Checker>(op));
1396 
1397  // Return value
1398  Matrix<Scalar> r = zeros(r_sp);
1399 
1400  // Perform the operations elementwise
1401  if (x_sp==y_sp) {
1402  // Matching sparsities
1403  casadi_math<Scalar>::fun(op, x.ptr(), y.ptr(), r.ptr(), r_sp.nnz());
1404  } else if (y_sp==r_sp) {
1405  // Project first argument
1406  Matrix<Scalar> x_mod = x(r_sp);
1407  casadi_math<Scalar>::fun(op, x_mod.ptr(), y.ptr(), r.ptr(), r_sp.nnz());
1408  } else if (x_sp==r_sp) {
1409  // Project second argument
1410  Matrix<Scalar> y_mod = y(r_sp);
1411  casadi_math<Scalar>::fun(op, x.ptr(), y_mod.ptr(), r.ptr(), r_sp.nnz());
1412  } else {
1413  // Project both arguments
1414  Matrix<Scalar> x_mod = x(r_sp);
1415  Matrix<Scalar> y_mod = y(r_sp);
1416  casadi_math<Scalar>::fun(op, x_mod.ptr(), y_mod.ptr(), r.ptr(), r_sp.nnz());
1417  }
1418 
1419  // Handle structural zeros giving rise to nonzero result, e.g. cos(0) == 1
1420  if (!r.is_dense() && !operation_checker<F00Checker>(op)) {
1421  // Get the value for the structural zeros
1422  Scalar fcn_0;
1423  casadi_math<Scalar>::fun(op, casadi_limits<Scalar>::zero,
1424  casadi_limits<Scalar>::zero, fcn_0);
1425  r = densify(r, fcn_0);
1426  }
1427 
1428  return r;
1429  }
1430 
1431  template<typename Scalar>
1432  Matrix<Scalar> Matrix<Scalar>::triplet(const std::vector<casadi_int>& row,
1433  const std::vector<casadi_int>& col,
1434  const Matrix<Scalar>& d) {
1435  return triplet(row, col, d, *std::max_element(row.begin(), row.end()),
1436  *std::max_element(col.begin(), col.end()));
1437  }
1438 
1439  template<typename Scalar>
1440  Matrix<Scalar> Matrix<Scalar>::triplet(const std::vector<casadi_int>& row,
1441  const std::vector<casadi_int>& col,
1442  const Matrix<Scalar>& d,
1443  const std::pair<casadi_int, casadi_int>& rc) {
1444  return triplet(row, col, d, rc.first, rc.second);
1445  }
1446 
1447  template<typename Scalar>
1448  Matrix<Scalar> Matrix<Scalar>::triplet(const std::vector<casadi_int>& row,
1449  const std::vector<casadi_int>& col,
1450  const Matrix<Scalar>& d,
1451  casadi_int nrow, casadi_int ncol) {
1452  casadi_assert(col.size()==row.size() && col.size()==d.nnz(),
1453  "Argument error in Matrix<Scalar>::triplet(row, col, d): "
1454  "supplied lists must all be of equal length, but got: "
1455  + str(row.size()) + ", " + str(col.size()) + " and " + str(d.nnz()));
1456  std::vector<casadi_int> mapping;
1457  Sparsity sp = Sparsity::triplet(nrow, ncol, row, col, mapping, false);
1458  return Matrix<Scalar>(sp, d.nz(mapping));
1459  }
1460 
1461  template<typename Scalar>
1462  Matrix<Scalar> Matrix<Scalar>::eye(casadi_int n) {
1463  return Matrix<Scalar>::ones(Sparsity::diag(n));
1464  }
1465 
1466  template<typename Scalar>
1467  Matrix<Scalar> Matrix<Scalar>::inf(const Sparsity& sp) {
1468  casadi_assert(std::numeric_limits<Scalar>::has_infinity,
1469  "Datatype cannot represent infinity");
1470  return Matrix<Scalar>(sp, std::numeric_limits<Scalar>::infinity(), false);
1471  }
1472 
1473 
1474  template<typename Scalar>
1475  Matrix<Scalar> Matrix<Scalar>::inf(const std::pair<casadi_int, casadi_int>& rc) {
1476  return inf(rc.first, rc.second);
1477  }
1478 
1479  template<typename Scalar>
1480  Matrix<Scalar> Matrix<Scalar>::inf(casadi_int nrow, casadi_int ncol) {
1481  return inf(Sparsity::dense(nrow, ncol));
1482  }
1483 
1484  template<typename Scalar>
1485  Matrix<Scalar> Matrix<Scalar>::nan(const Sparsity& sp) {
1486  casadi_assert(std::numeric_limits<Scalar>::has_quiet_NaN,
1487  "Datatype cannot represent not-a-number");
1488  return Matrix<Scalar>(sp, std::numeric_limits<Scalar>::quiet_NaN(), false);
1489  }
1490 
1491  template<typename Scalar>
1492  Matrix<Scalar> Matrix<Scalar>::nan(const std::pair<casadi_int, casadi_int>& rc) {
1493  return nan(rc.first, rc.second);
1494  }
1495 
1496  template<typename Scalar>
1497  Matrix<Scalar> Matrix<Scalar>::nan(casadi_int nrow, casadi_int ncol) {
1498  return nan(Sparsity::dense(nrow, ncol));
1499  }
1500 
1501  template<typename Scalar>
1502  bool Matrix<Scalar>::is_regular() const {
1503  return casadi::is_regular(nonzeros_);
1504  }
1505 
1506  template<typename Scalar>
1507  bool Matrix<Scalar>::is_smooth() const {
1508  return true;
1509  }
1510 
1511  template<typename Scalar>
1512  casadi_int Matrix<Scalar>::element_hash() const {
1513  casadi_error("'element_hash' not defined for " + type_name());
1514  }
1515 
1516  template<typename Scalar>
1517  bool Matrix<Scalar>::is_leaf() const {
1518  casadi_error("'is_leaf' not defined for " + type_name());
1519  }
1520 
1521  template<typename Scalar>
1522  bool Matrix<Scalar>::is_commutative() const {
1523  casadi_error("'is_commutative' not defined for " + type_name());
1524  }
1525 
1526  template<typename Scalar>
1527  bool Matrix<Scalar>::is_symbolic() const {
1528  return false;
1529  }
1530 
1531  template<typename Scalar>
1532  casadi_int Matrix<Scalar>::op() const {
1533  casadi_error("'op' not defined for " + type_name());
1534  }
1535 
1536  template<typename Scalar>
1537  bool Matrix<Scalar>::is_op(casadi_int k) const {
1538  casadi_error("'is_op' not defined for " + type_name());
1539  }
1540 
1541  template<typename Scalar>
1542  void Matrix<Scalar>::export_code(const std::string& lang,
1543  std::ostream &stream, const Dict& options) const {
1544  casadi_error("'export_code' not defined for " + type_name());
1545  }
1546 
1547  template<typename Scalar>
1548  bool Matrix<Scalar>::is_valid_input() const {
1549  return false;
1550  }
1551 
1552  template<typename Scalar>
1553  bool Matrix<Scalar>::has_duplicates() const {
1554  casadi_error("'has_duplicates' not defined for " + type_name());
1555  }
1556 
1557  template<typename Scalar>
1558  void Matrix<Scalar>::reset_input() const {
1559  casadi_error("'reset_input' not defined for " + type_name());
1560  }
1561 
1562  template<typename Scalar>
1563  Matrix<double> Matrix<Scalar>::from_file(const std::string& filename,
1564  const std::string& format_hint) {
1565  casadi_error("'from_file' not defined for " + type_name());
1566  }
1567 
1568  template<typename Scalar>
1569  bool Matrix<Scalar>::is_integer() const {
1570  // Look for non-integers
1571  for (auto&& e : nonzeros()) if (!casadi_limits<Scalar>::is_integer(e)) return false;
1572 
1573  // Integer if reached this point
1574  return true;
1575  }
1576 
1577  template<typename Scalar>
1578  bool Matrix<Scalar>::is_constant() const {
1579  // Look for non-constants
1580  for (auto&& e : nonzeros()) if (!casadi_limits<Scalar>::is_constant(e)) return false;
1581 
1582  // Constant if we reach this point
1583  return true;
1584  }
1585 
1586  template<typename Scalar>
1587  bool Matrix<Scalar>::is_call() const {
1588  casadi_assert(is_scalar(), "'is_call' only defined for scalar expressions");
1589 
1590  return false;
1591  }
1592 
1593  template<typename Scalar>
1594  bool Matrix<Scalar>::is_output() const {
1595  casadi_assert(is_scalar(), "'is_output' only defined for scalar expressions");
1596 
1597  return false;
1598  }
1599 
1600  template<typename Scalar>
1601  Matrix<Scalar> Matrix<Scalar>::get_output(casadi_int oind) const {
1602  casadi_error("'get_output' not defined for " + type_name());
1603  }
1604 
1605  template<typename Scalar>
1606  bool Matrix<Scalar>::has_output() const {
1607  casadi_assert(is_scalar(), "'has_output' only defined for scalar expressions");
1608 
1609  return false;
1610  }
1611 
1612  template<typename Scalar>
1613  Function Matrix<Scalar>::which_function() const {
1614  casadi_error("'which_function' not defined for " + type_name());
1615  }
1616 
1617  template<typename Scalar>
1618  casadi_int Matrix<Scalar>::which_output() const {
1619  casadi_error("'which_output' not defined for " + type_name());
1620  }
1621 
1622  template<typename Scalar>
1623  bool Matrix<Scalar>::is_one() const {
1624  if (!is_dense()) return false;
1625 
1626  // Look for non-ones
1627  for (auto&& e : nonzeros()) if (!casadi_limits<Scalar>::is_one(e)) return false;
1628 
1629  return true;
1630  }
1631 
1632  template<typename Scalar>
1633  bool Matrix<Scalar>::is_minus_one() const {
1634  if (!is_dense()) return false;
1635 
1636  // Look for non-minus-ones
1637  for (auto&& e : nonzeros()) if (!casadi_limits<Scalar>::is_minus_one(e)) return false;
1638 
1639  return true;
1640  }
1641 
1642  template<typename Scalar>
1643  bool Matrix<Scalar>::is_zero() const {
1644 
1645  // Look for non-zeros
1646  for (auto&& e : nonzeros()) if (!casadi_limits<Scalar>::is_zero(e)) return false;
1647 
1648  return true;
1649  }
1650 
1651  template<typename Scalar>
1652  bool Matrix<Scalar>::is_eye() const {
1653 
1654  // Make sure that the matrix is diagonal
1655  if (!sparsity().is_diag()) return false;
1656 
1657  // Make sure that all entries are one
1658  for (auto&& e : nonzeros()) if (!casadi_limits<Scalar>::is_one(e)) return false;
1659 
1660  return true;
1661  }
1662 
1663  template<typename Scalar>
1664  bool Matrix<Scalar>::is_equal(const Matrix<Scalar> &x, const Matrix<Scalar> &y,
1665  casadi_int depth) {
1666  // Assert matching dimensions
1667  casadi_assert(x.size() == y.size(), "Dimension mismatch");
1668 
1669  // Project to union of patterns and call recursively if different sparsity
1670  if (x.sparsity() != y.sparsity()) {
1671  Sparsity sp = x.sparsity() + y.sparsity();
1672  return is_equal(project(x, sp), project(y, sp), depth);
1673  }
1674 
1675  // Check individual elements
1676  auto y_it = y.nonzeros().begin();
1677  for (auto&& e : x.nonzeros()) {
1678  if (!casadi_limits<Scalar>::is_equal(e, *y_it++, depth)) return false;
1679  }
1680 
1681  // True if reched this point
1682  return true;
1683  }
1684 
1685  // To avoid overloaded function name conflicts
1686  template<typename Scalar>
1687  inline Matrix<Scalar> mmin_nonstatic(const Matrix<Scalar> &x) {
1688  if (x.is_empty()) return Matrix<Scalar>();
1689  return casadi_mmin(x.ptr(), x.nnz(), x.is_dense());
1690  }
1691 
1692  template<typename Scalar>
1693  Matrix<Scalar> Matrix<Scalar>::mmin(const Matrix<Scalar> &x) {
1694  return mmin_nonstatic(x);
1695  }
1696 
1697  // To avoid overloaded function name conflicts
1698  template<typename Scalar>
1699  inline Matrix<Scalar> mmax_nonstatic(const Matrix<Scalar> &x) {
1700  if (x.is_empty()) return Matrix<Scalar>();
1701  return casadi_mmax(x.ptr(), x.nnz(), x.is_dense());
1702  }
1703 
1704  template<typename Scalar>
1705  Matrix<Scalar> Matrix<Scalar>::mmax(const Matrix<Scalar> &x) {
1706  return mmax_nonstatic(x);
1707  }
1708 
1709  template<typename Scalar>
1710  bool Matrix<Scalar>::has_zeros() const {
1711  // Check if the structural nonzero is known to be zero
1712  for (auto&& e : nonzeros()) if (casadi_limits<Scalar>::is_zero(e)) return true;
1713 
1714  // No known zeros amongst the structurally nonzero entries
1715  return false;
1716  }
1717 
1718  template<typename Scalar>
1719  std::vector<Scalar> Matrix<Scalar>::get_nonzeros() const {
1720  return nonzeros_;
1721  }
1722 
1723  template<typename Scalar>
1724  std::vector<Scalar> Matrix<Scalar>::get_elements() const {
1725  return static_cast< std::vector<Scalar>>(*this);
1726  }
1727 
1728  template<typename Scalar>
1729  std::string Matrix<Scalar>::name() const {
1730  casadi_error("'name' not defined for " + type_name());
1731  }
1732 
1733  template<typename Scalar>
1734  Matrix<Scalar> Matrix<Scalar>::dep(casadi_int ch) const {
1735  casadi_error("'dep' not defined for " + type_name());
1736  }
1737 
1738  template<typename Scalar>
1739  casadi_int Matrix<Scalar>::n_dep() const {
1740  casadi_error("'n_dep' not defined for " + type_name());
1741  }
1742 
1743  template<typename Scalar>
1744  Matrix<Scalar> Matrix<Scalar>::rand( // NOLINT(runtime/threadsafe_fn)
1745  casadi_int nrow,
1746  casadi_int ncol) {
1747  return rand(Sparsity::dense(nrow, ncol)); // NOLINT(runtime/threadsafe_fn)
1748  }
1749 
1750  template<typename Scalar>
1751  Matrix<Scalar> Matrix<Scalar>::rand( // NOLINT(runtime/threadsafe_fn)
1752  const std::pair<casadi_int, casadi_int>& rc) {
1753  return rand(rc.first, rc.second); // NOLINT(runtime/threadsafe_fn)
1754  }
1755 
1756  template<typename Scalar>
1757  Matrix<Scalar> Matrix<Scalar>::project(const Matrix<Scalar>& x,
1758  const Sparsity& sp, bool intersect) {
1759  if (intersect) {
1760  return project(x, sp.intersect(x.sparsity()), false);
1761  } else {
1762  casadi_assert(sp.size()==x.size(), "Dimension mismatch");
1763  Matrix<Scalar> ret = Matrix<Scalar>::zeros(sp);
1764  std::vector<Scalar> w(x.size1());
1765  casadi_project(x.ptr(), x.sparsity(), ret.ptr(), sp, get_ptr(w));
1766  return ret;
1767  }
1768  }
1769 
1770  template<typename Scalar>
1771  void Matrix<Scalar>::set_max_depth(casadi_int eq_depth) {
1772  casadi_error("'set_max_depth' not defined for " + type_name());
1773  }
1774 
1775  template<typename Scalar>
1776  casadi_int Matrix<Scalar>::get_max_depth() {
1777  casadi_error("'get_max_depth' not defined for " + type_name());
1778  }
1779 
1780  template<typename Scalar>
1781  Matrix<Scalar> Matrix<Scalar>::det(const Matrix<Scalar>& x) {
1782  casadi_int n = x.size2();
1783  casadi_assert(n == x.size1(), "matrix must be square");
1784 
1785  // Trivial return if scalar
1786  if (x.is_scalar()) return x;
1787 
1788  // Trivial case 2 x 2
1789  if (n==2) return x(0, 0) * x(1, 1) - x(0, 1) * x(1, 0);
1790 
1791  // Return expression
1792  Matrix<Scalar> ret = 0;
1793 
1794  // Find out which is the best direction to expand along
1795 
1796  // Build up an IM with ones on the non-zeros
1797  Matrix<casadi_int> sp = IM::ones(x.sparsity());
1798 
1799  // Have a count of the nonzeros for each row
1800  Matrix<casadi_int> row_count = Matrix<casadi_int>::sum2(sp);
1801 
1802  // A blank row? determinant is structurally zero
1803  if (!row_count.is_dense()) return 0;
1804 
1805  // Have a count of the nonzeros for each col
1806  Matrix<casadi_int> col_count = Matrix<casadi_int>::sum1(sp).T();
1807 
1808  // A blank col? determinant is structurally zero
1809  if (!row_count.is_dense()) return 0;
1810 
1811  casadi_int min_row = std::distance(row_count.nonzeros().begin(),
1812  std::min_element(row_count.nonzeros().begin(),
1813  row_count.nonzeros().end()));
1814  casadi_int min_col = std::distance(col_count.nonzeros().begin(),
1815  std::min_element(col_count.nonzeros().begin(),
1816  col_count.nonzeros().end()));
1817 
1818  if (min_row <= min_col) {
1819  // Expand along row j
1820  casadi_int j = row_count.sparsity().row(min_row);
1821 
1822  Matrix<Scalar> row = x(j, Slice(0, n));
1823 
1824  std::vector< casadi_int > col_i = row.sparsity().get_col();
1825 
1826  for (casadi_int k=0; k<row.nnz(); ++k) {
1827  // Sum up the cofactors
1828  ret += row->at(k)*cofactor(x, col_i.at(k), j);
1829  }
1830  return ret;
1831  } else {
1832  // Expand along col i
1833  casadi_int i = col_count.sparsity().row(min_col);
1834 
1835  Matrix<Scalar> col = x(Slice(0, n), i);
1836 
1837  const casadi_int* row_i = col.row();
1838 
1839  for (casadi_int k=0; k<col.nnz(); ++k) {
1840  // Sum up the cofactors
1841  ret += col->at(k)*cofactor(x, i, row_i[k]);
1842  }
1843  return ret;
1844  }
1845 
1846  }
1847 
1848  template<typename Scalar>
1849  Matrix<Scalar> Matrix<Scalar>::sum2(const Matrix<Scalar>& x) {
1850  return mtimes(x, Matrix<Scalar>::ones(x.size2(), 1));
1851  }
1852 
1853  template<typename Scalar>
1854  Matrix<Scalar> Matrix<Scalar>::sum1(const Matrix<Scalar>& x) {
1855  return mtimes(Matrix<Scalar>::ones(1, x.size1()), x);
1856  }
1857 
1858  template<typename Scalar>
1859  Matrix<Scalar> Matrix<Scalar>::minor(const Matrix<Scalar>& x,
1860  casadi_int i, casadi_int j) {
1861  casadi_int n = x.size2();
1862  casadi_assert(n == x.size1(), "minor: matrix must be square");
1863 
1864  // Trivial return if scalar
1865  if (n==1) return 1;
1866 
1867  // Remove col i and row j
1868  Matrix<Scalar> M = Matrix<Scalar>(n-1, n-1);
1869 
1870  std::vector<casadi_int> col = x.sparsity().get_col();
1871  const casadi_int* row = x.sparsity().row();
1872 
1873  for (casadi_int k=0; k<x.nnz(); ++k) {
1874  casadi_int i1 = col[k];
1875  casadi_int j1 = row[k];
1876 
1877  if (i1 == i || j1 == j) continue;
1878 
1879  casadi_int i2 = (i1<i)?i1:i1-1;
1880  casadi_int j2 = (j1<j)?j1:j1-1;
1881 
1882  M(j2, i2) = x(j1, i1);
1883  }
1884  return det(M);
1885  }
1886 
1887  template<typename Scalar>
1888  Matrix<Scalar> Matrix<Scalar>::cofactor(const Matrix<Scalar>& A, casadi_int i, casadi_int j) {
1889 
1890  // Calculate the i, j minor
1891  Matrix<Scalar> minor_ij = minor(A, i, j);
1892  // Calculate the cofactor
1893  casadi_int sign_i = 1-2*((i+j) % 2);
1894 
1895  return sign_i * minor_ij;
1896  }
1897 
1898  template<typename Scalar>
1899  Matrix<Scalar> Matrix<Scalar>::adj(const Matrix<Scalar>& x) {
1900  casadi_int n = x.size2();
1901  casadi_assert(n == x.size1(), "adj: matrix must be square");
1902 
1903  // Temporary placeholder
1904  Matrix<Scalar> temp;
1905 
1906  // Cofactor matrix
1907  Matrix<Scalar> C = Matrix<Scalar>(n, n);
1908  for (casadi_int i=0; i<n; ++i)
1909  for (casadi_int j=0; j<n; ++j) {
1910  temp = cofactor(x, i, j);
1911  if (!temp.is_zero()) C(j, i) = temp;
1912  }
1913 
1914  return C.T();
1915  }
1916 
1917  template<typename Scalar>
1918  Matrix<Scalar> Matrix<Scalar>::inv_minor(const Matrix<Scalar>& x) {
1919  // laplace formula
1920  return adj(x)/det(x);
1921  }
1922 
1923  template<typename Scalar>
1924  Matrix<Scalar> Matrix<Scalar>::reshape(const Matrix<Scalar>& x,
1925  casadi_int nrow, casadi_int ncol) {
1926  Sparsity sp = Sparsity::reshape(x.sparsity(), nrow, ncol);
1927  return Matrix<Scalar>(sp, x.nonzeros(), false);
1928  }
1929 
1930  template<typename Scalar>
1931  Matrix<Scalar> Matrix<Scalar>::reshape(const Matrix<Scalar>& x, const Sparsity& sp) {
1932  // quick return if already the right shape
1933  if (sp==x.sparsity()) return x;
1934 
1935  // make sure that the patterns match
1936  casadi_assert_dev(sp.is_reshape(x.sparsity()));
1937 
1938  return Matrix<Scalar>(sp, x.nonzeros(), false);
1939  }
1940 
1941  template<typename Scalar>
1942  Matrix<Scalar> Matrix<Scalar>::sparsity_cast(const Matrix<Scalar>& x, const Sparsity& sp) {
1943  // quick return if already the right shape
1944  if (sp==x.sparsity()) return x;
1945 
1946  casadi_assert_dev(sp.nnz()==x.nnz());
1947 
1948  return Matrix<Scalar>(sp, x.nonzeros(), false);
1949  }
1950 
1951  template<typename Scalar>
1952  Matrix<Scalar> Matrix<Scalar>::trace(const Matrix<Scalar>& x) {
1953  casadi_assert(x.is_square(), "trace: must be square");
1954  Scalar res=0;
1955  const Scalar* d=x.ptr();
1956  casadi_int size2 = x.size2();
1957  const casadi_int *colind=x.colind(), *row=x.row();
1958  for (casadi_int c=0; c<size2; c++) {
1959  for (casadi_int k=colind[c]; k!=colind[c+1]; ++k) {
1960  if (row[k]==c) {
1961  res += d[k];
1962  }
1963  }
1964  }
1965  return res;
1966  }
1967 
1968  template<typename Scalar>
1969  Matrix<Scalar>
1970  Matrix<Scalar>::blockcat(const std::vector< std::vector<Matrix<Scalar> > > &v) {
1971  std::vector< Matrix<Scalar> > ret;
1972  for (casadi_int i=0; i<v.size(); ++i)
1973  ret.push_back(horzcat(v[i]));
1974  return vertcat(ret);
1975  }
1976 
1977  template<typename Scalar>
1978  Matrix<Scalar> Matrix<Scalar>::horzcat(const std::vector<Matrix<Scalar> > &v) {
1979  // Concatenate sparsity patterns
1980  std::vector<Sparsity> sp(v.size());
1981  for (casadi_int i=0; i<v.size(); ++i) sp[i] = v[i].sparsity();
1982  Matrix<Scalar> ret = zeros(Sparsity::horzcat(sp));
1983 
1984  // Copy nonzeros
1985  auto i=ret->begin();
1986  for (auto&& j : v) {
1987  std::copy(j->begin(), j->end(), i);
1988  i += j.nnz();
1989  }
1990  return ret;
1991  }
1992 
1993  template<typename Scalar>
1994  std::vector<Matrix<Scalar> >
1995  Matrix<Scalar>::horzsplit(const Matrix<Scalar>& x, const std::vector<casadi_int>& offset) {
1996  // Split up the sparsity pattern
1997  std::vector<Sparsity> sp = Sparsity::horzsplit(x.sparsity(), offset);
1998 
1999  // Return object
2000  std::vector<Matrix<Scalar> > ret;
2001  ret.reserve(sp.size());
2002 
2003  // Copy data
2004  auto i=x.nonzeros().begin();
2005  for (auto&& j : sp) {
2006  auto i_next = i + j.nnz();
2007  ret.push_back(Matrix<Scalar>(j, std::vector<Scalar>(i, i_next), false));
2008  i = i_next;
2009  }
2010 
2011  // Return the assembled matrix
2012  casadi_assert_dev(i==x.nonzeros().end());
2013  return ret;
2014  }
2015 
2016  template<typename Scalar>
2017  Matrix<Scalar> Matrix<Scalar>::vertcat(const std::vector<Matrix<Scalar> > &v) {
2018  std::vector<Matrix<Scalar> > vT(v.size());
2019  for (casadi_int i=0; i<v.size(); ++i) vT[i] = v[i].T();
2020  return horzcat(vT).T();
2021  }
2022 
2023  template<typename Scalar>
2024  std::vector< Matrix<Scalar> >
2025  Matrix<Scalar>::vertsplit(const Matrix<Scalar>& x, const std::vector<casadi_int>& offset) {
2026  std::vector< Matrix<Scalar> > ret = horzsplit(x.T(), offset);
2027  for (auto&& e : ret) e = e.T();
2028  return ret;
2029  }
2030 
2031  template<typename Scalar>
2032  std::vector< Matrix<Scalar> >
2033  Matrix<Scalar>::diagsplit(const Matrix<Scalar>& x, const std::vector<casadi_int>& offset1,
2034  const std::vector<casadi_int>& offset2) {
2035  // Consistency check
2036  casadi_assert_dev(!offset1.empty());
2037  casadi_assert_dev(offset1.front()==0);
2038  casadi_assert_dev(offset1.back()==x.size1());
2039  casadi_assert_dev(is_monotone(offset1));
2040 
2041  // Consistency check
2042  casadi_assert_dev(!offset2.empty());
2043  casadi_assert_dev(offset2.front()==0);
2044  casadi_assert_dev(offset2.back()==x.size2());
2045  casadi_assert_dev(is_monotone(offset2));
2046 
2047  // Number of outputs
2048  casadi_int n = offset1.size()-1;
2049 
2050  // Return value
2051  std::vector< Matrix<Scalar> > ret;
2052 
2053  // Caveat: this is a very silly implementation
2054  for (casadi_int i=0; i<n; ++i) {
2055  ret.push_back(x(Slice(offset1[i], offset1[i+1]), Slice(offset2[i], offset2[i+1])));
2056  }
2057 
2058  return ret;
2059  }
2060 
2061  template<typename Scalar>
2062  Matrix<Scalar> Matrix<Scalar>::dot(const Matrix<Scalar> &x,
2063  const Matrix<Scalar> &y) {
2064  casadi_assert(x.size()==y.size(), "dot: Dimension mismatch");
2065  if (x.sparsity()!=y.sparsity()) {
2066  Sparsity sp = x.sparsity() * y.sparsity();
2067  return dot(project(x, sp), project(y, sp));
2068  }
2069  return casadi_dot(x.nnz(), x.ptr(), y.ptr());
2070  }
2071 
2072  template<typename Scalar>
2073  Matrix<Scalar> Matrix<Scalar>::all(const Matrix<Scalar>& x) {
2074  if (!x.is_dense()) return false;
2075  Scalar ret=1;
2076  for (casadi_int i=0; i<x.nnz(); ++i) {
2077  ret = ret && x->at(i)==1;
2078  }
2079  return ret;
2080  }
2081 
2082  template<typename Scalar>
2083  Matrix<Scalar> Matrix<Scalar>::any(const Matrix<Scalar>& x) {
2084  if (!x.is_dense()) return false;
2085  Scalar ret=0;
2086  for (casadi_int i=0; i<x.nnz(); ++i) {
2087  ret = ret || x->at(i)==1;
2088  }
2089  return ret;
2090  }
2091 
2092  template<typename Scalar>
2093  Matrix<Scalar> Matrix<Scalar>::norm_1(const Matrix<Scalar>& x) {
2094  return casadi_norm_1(x.nnz(), x.ptr());
2095  }
2096 
2097  template<typename Scalar>
2098  Matrix<Scalar> Matrix<Scalar>::norm_2(const Matrix<Scalar>& x) {
2099  if (x.is_vector()) {
2100  return norm_fro(x);
2101  } else {
2102  casadi_error("2-norms currently only supported for vectors. "
2103  "Did you intend to calculate a Frobenius norms (norm_fro)?");
2104  }
2105  }
2106 
2107  template<typename Scalar>
2108  Matrix<Scalar> Matrix<Scalar>::norm_fro(const Matrix<Scalar>& x) {
2109  return casadi_norm_2(x.nnz(), x.ptr());
2110  }
2111 
2112  template<typename Scalar>
2113  Matrix<Scalar> Matrix<Scalar>::norm_inf(const Matrix<Scalar>& x) {
2114  // Get largest element by absolute value
2115  Matrix<Scalar> s = 0;
2116  for (auto i=x.nonzeros().begin(); i!=x.nonzeros().end(); ++i) {
2117  s = fmax(s, fabs(Matrix<Scalar>(*i)));
2118  }
2119  return s;
2120  }
2121 
2122  template<typename Scalar>
2123  void Matrix<Scalar>::
2124  qr_sparse(const Matrix<Scalar>& A,
2125  Matrix<Scalar>& V, Matrix<Scalar> &R, Matrix<Scalar>& beta,
2126  std::vector<casadi_int>& prinv, std::vector<casadi_int>& pc, bool amd) {
2127  // Calculate the pattern
2128  Sparsity spV, spR;
2129  A.sparsity().qr_sparse(spV, spR, prinv, pc, amd);
2130  // Calculate the nonzeros
2131  casadi_int nrow_ext = spV.size1(), ncol = spV.size2();
2132  V = nan(spV);
2133  R = nan(spR);
2134  beta = nan(ncol, 1);
2135  std::vector<Scalar> w(nrow_ext);
2136  casadi_qr(A.sparsity(), A.ptr(), get_ptr(w), spV, V.ptr(),
2137  spR, R.ptr(), beta.ptr(),
2138  get_ptr(prinv), get_ptr(pc));
2139  }
2140 
2141  template<typename Scalar>
2142  Matrix<Scalar> Matrix<Scalar>::
2143  qr_solve(const Matrix<Scalar>& b, const Matrix<Scalar>& v,
2144  const Matrix<Scalar>& r, const Matrix<Scalar>& beta,
2145  const std::vector<casadi_int>& prinv, const std::vector<casadi_int>& pc,
2146  bool tr) {
2147  // Get dimensions, check consistency
2148  casadi_int ncol = v.size2();
2149  casadi_int nrow = b.size1(), nrhs = b.size2();
2150  casadi_assert(r.size()==v.size(), "'r', 'v' dimension mismatch");
2151  casadi_assert(beta.is_vector() && beta.numel()==ncol, "'beta' has wrong dimension");
2152  casadi_assert(prinv.size()==r.size1(), "'pinv' has wrong dimension");
2153  // Work vector
2154  std::vector<Scalar> w(nrow+ncol);
2155  // Return value
2156  Matrix<Scalar> x = densify(b);
2157  casadi_qr_solve(x.ptr(), nrhs, tr, v.sparsity(), v.ptr(), r.sparsity(), r.ptr(),
2158  beta.ptr(), get_ptr(prinv), get_ptr(pc), get_ptr(w));
2159  return x;
2160  }
2161 
2162  template<typename Scalar>
2163  void Matrix<Scalar>::qr(const Matrix<Scalar>& A,
2164  Matrix<Scalar>& Q, Matrix<Scalar> &R) {
2165  // The following algorithm is taken from J. Demmel:
2166  // Applied Numerical Linear Algebra (algorithm 3.1.)
2167  casadi_assert(A.size1()>=A.size2(), "qr: fewer rows than columns");
2168 
2169  // compute Q and R column by column
2170  Q = R = Matrix<Scalar>();
2171  for (casadi_int i=0; i<A.size2(); ++i) {
2172  // Initialize qi to be the i-th column of *this
2173  Matrix<Scalar> ai = A(Slice(), i);
2174  Matrix<Scalar> qi = ai;
2175  // The i-th column of R
2176  Matrix<Scalar> ri = Matrix<Scalar>(A.size2(), 1);
2177 
2178  // subtract the projection of qi in the previous directions from ai
2179  for (casadi_int j=0; j<i; ++j) {
2180 
2181  // Get the j-th column of Q
2182  Matrix<Scalar> qj = Q(Slice(), j); // NOLINT(cppcoreguidelines-slicing)
2183 
2184  ri(j, 0) = mtimes(qi.T(), qj); // Modified Gram-Schmidt
2185  // ri[j] = dot(qj, ai); // Classical Gram-Schmidt
2186 
2187  // Remove projection in direction j
2188  if (ri.has_nz(j, 0))
2189  qi -= ri(j, 0) * qj;
2190  }
2191 
2192  // Normalize qi
2193  ri(i, 0) = norm_2(qi);
2194  qi /= ri(i, 0);
2195 
2196  // Update R and Q
2197  Q = Matrix<Scalar>::horzcat({Q, qi});
2198  R = Matrix<Scalar>::horzcat({R, ri});
2199  }
2200  }
2201 
2202  template<typename Scalar>
2203  void Matrix<Scalar>::ldl(const Matrix<Scalar>& A, Matrix<Scalar> &D,
2204  Matrix<Scalar>& LT, std::vector<casadi_int>& p, bool amd) {
2205  // Symbolic factorization
2206  Sparsity Lt_sp = A.sparsity().ldl(p, amd);
2207 
2208  // Get dimension
2209  casadi_int n=A.size1();
2210 
2211  // Calculate entries in L and D
2212  std::vector<Scalar> D_nz(n), L_nz(Lt_sp.nnz()), w(n);
2213  casadi_ldl(A.sparsity(), get_ptr(A.nonzeros()), Lt_sp,
2214  get_ptr(L_nz), get_ptr(D_nz), get_ptr(p), get_ptr(w));
2215 
2216  // Assemble L and D
2217  LT = Matrix<Scalar>(Lt_sp, L_nz);
2218  D = D_nz;
2219  }
2220 
2221  template<typename Scalar>
2222  Matrix<Scalar> Matrix<Scalar>::
2223  ldl_solve(const Matrix<Scalar>& b, const Matrix<Scalar>& D, const Matrix<Scalar>& LT,
2224  const std::vector<casadi_int>& p) {
2225  // Get dimensions, check consistency
2226  casadi_int n = b.size1(), nrhs = b.size2();
2227  casadi_assert(p.size()==n, "'p' has wrong dimension");
2228  casadi_assert(LT.size1()==n && LT.size2()==n, "'LT' has wrong dimension");
2229  casadi_assert(D.is_vector() && D.numel()==n, "'D' has wrong dimension");
2230  // Solve for all right-hand-sides
2231  Matrix<Scalar> x = densify(b);
2232  std::vector<Scalar> w(n);
2233  casadi_ldl_solve(x.ptr(), nrhs, LT.sparsity(), LT.ptr(), D.ptr(), get_ptr(p), get_ptr(w));
2234  return x;
2235  }
2236 
2237  template<typename Scalar>
2238  Matrix<Scalar> Matrix<Scalar>::nullspace(const Matrix<Scalar>& A) {
2239  Matrix<Scalar> X = A;
2240  casadi_int n = X.size1();
2241  casadi_int m = X.size2();
2242  casadi_assert(m>=n, "nullspace(): expecting a flat matrix (more columns than rows), "
2243  "but got " + str(X.dim()) + ".");
2244 
2245  Matrix<Scalar> seed = DM::eye(m)(Slice(0, m), Slice(n, m)); // NOLINT(cppcoreguidelines-slicing)
2246 
2247  std::vector< Matrix<Scalar> > us;
2248  std::vector< Matrix<Scalar> > betas;
2249 
2250  Matrix<Scalar> beta;
2251 
2252  for (casadi_int i=0;i<n;++i) {
2253  Matrix<Scalar> x = X(i, Slice(i, m)); // NOLINT(cppcoreguidelines-slicing)
2254  Matrix<Scalar> u = Matrix<Scalar>(x);
2255  Matrix<Scalar> sigma = sqrt(sum2(x*x));
2256  const Matrix<Scalar>& x0 = x(0, 0);
2257  u(0, 0) = 1;
2258 
2259  Matrix<Scalar> b = -copysign(sigma, x0);
2260 
2261  u(Slice(0), Slice(1, m-i))*= 1/(x0-b);
2262  beta = 1-x0/b;
2263 
2264  X(Slice(i, n), Slice(i, m)) -=
2265  beta*mtimes(mtimes(X(Slice(i, n), Slice(i, m)), u.T()), u);
2266  us.push_back(u);
2267  betas.push_back(beta);
2268  }
2269 
2270  for (casadi_int i=n-1;i>=0;--i) {
2271  seed(Slice(i, m), Slice(0, m-n)) -=
2272  betas[i]*mtimes(us[i].T(), mtimes(us[i], seed(Slice(i, m), Slice(0, m-n))));
2273  }
2274 
2275  return seed;
2276 
2277  }
2278 
2279  template<typename Scalar>
2280  Matrix<Scalar> Matrix<Scalar>::chol(const Matrix<Scalar>& A) {
2281  // Perform an LDL transformation
2282  Matrix<Scalar> D, LT;
2283  std::vector<casadi_int> p;
2284  ldl(A, D, LT, p, false);
2285  // Add unit diagonal
2286  LT += Matrix<Scalar>::eye(D.size1());
2287  // Get the cholesky factor: R*R' = L*D*L' = (sqrt(D)*L')'*(sqrt(D)*L')
2288  return mtimes(diag(sqrt(D)), LT);
2289  }
2290 
2291  template<typename Scalar>
2292  Matrix<Scalar> Matrix<Scalar>::solve(const Matrix<Scalar>& a, const Matrix<Scalar>& b) {
2293  // check dimensions
2294  casadi_assert(a.size1() == b.size1(), "solve Ax=b: dimension mismatch: b has "
2295  + str(b.size1()) + " rows while A has " + str(a.size1()) + ".");
2296  casadi_assert(a.size1() == a.size2(), "solve: A not square but " + str(a.dim()));
2297 
2298  if (a.is_tril()) {
2299  // forward substitution if lower triangular
2300  Matrix<Scalar> x = b;
2301  const casadi_int* Arow = a.row();
2302  const casadi_int* Acolind = a.colind();
2303  const std::vector<Scalar> & Adata = a.nonzeros();
2304  for (casadi_int i=0; i<a.size2(); ++i) { // loop over columns forwards
2305  for (casadi_int k=0; k<b.size2(); ++k) { // for every right hand side
2306  if (!x.has_nz(i, k)) continue;
2307  x(i, k) /= a(i, i);
2308  for (casadi_int kk=Acolind[i+1]-1; kk>=Acolind[i] && Arow[kk]>i; --kk) {
2309  casadi_int j = Arow[kk];
2310  x(j, k) -= Adata[kk]*x(i, k);
2311  }
2312  }
2313  }
2314  return x;
2315  } else if (a.is_triu()) {
2316  // backward substitution if upper triangular
2317  Matrix<Scalar> x = b;
2318  const casadi_int* Arow = a.row();
2319  const casadi_int* Acolind = a.colind();
2320  const std::vector<Scalar> & Adata = a.nonzeros();
2321  for (casadi_int i=a.size2()-1; i>=0; --i) { // loop over columns backwards
2322  for (casadi_int k=0; k<b.size2(); ++k) { // for every right hand side
2323  if (!x.has_nz(i, k)) continue;
2324  x(i, k) /= a(i, i);
2325  for (casadi_int kk=Acolind[i]; kk<Acolind[i+1] && Arow[kk]<i; ++kk) {
2326  casadi_int j = Arow[kk];
2327  x(j, k) -= Adata[kk]*x(i, k);
2328  }
2329  }
2330  }
2331  return x;
2332  } else if (a.has_zeros()) {
2333 
2334  // If there are structurally nonzero entries that are known to be zero,
2335  // remove these and rerun the algorithm
2336  return solve(sparsify(a), b);
2337 
2338  } else {
2339 
2340  // Make a BLT transformation of A
2341  std::vector<casadi_int> rowperm, colperm, rowblock, colblock;
2342  std::vector<casadi_int> coarse_rowblock, coarse_colblock;
2343  a.sparsity().btf(rowperm, colperm, rowblock, colblock,
2344  coarse_rowblock, coarse_colblock);
2345 
2346  // Permute the right hand side
2347  Matrix<Scalar> bperm = b(rowperm, Slice());
2348 
2349  // Permute the linear system
2350  Matrix<Scalar> Aperm = a(rowperm, colperm);
2351 
2352  // Solution
2353  Matrix<Scalar> xperm;
2354 
2355  // Solve permuted system
2356  if (Aperm.is_tril()) {
2357 
2358  // Forward substitution if lower triangular
2359  xperm = solve(Aperm, bperm);
2360 
2361  } else if (a.size2()<=3) {
2362 
2363  // Form inverse by minor expansion and multiply if very small (up to 3-by-3)
2364  xperm = mtimes(inv_minor(Aperm), bperm);
2365 
2366  } else {
2367 
2368  // Make a QR factorization
2369  Matrix<Scalar> Q, R;
2370  qr(Aperm, Q, R);
2371 
2372  // Solve the factorized system (note that solve will now be fast since it is triangular)
2373  xperm = solve(R, mtimes(Q.T(), bperm));
2374  }
2375 
2376  // get the inverted column permutation
2377  std::vector<casadi_int> inv_colperm(colperm.size());
2378  for (casadi_int k=0; k<colperm.size(); ++k)
2379  inv_colperm[colperm[k]] = k;
2380 
2381  // Permute back the solution and return
2382  Matrix<Scalar> x = xperm(inv_colperm, Slice()); // NOLINT(cppcoreguidelines-slicing)
2383  return x;
2384  }
2385  }
2386 
2387  template<typename Scalar>
2388  Matrix<Scalar> Matrix<Scalar>::
2389  solve(const Matrix<Scalar>& a, const Matrix<Scalar>& b,
2390  const std::string& lsolver, const Dict& dict) {
2391  casadi_error("'solve' with plugin not defined for " + type_name());
2392  return Matrix<Scalar>();
2393  }
2394 
2395  template<typename Scalar>
2396  Matrix<Scalar> Matrix<Scalar>::
2397  inv(const Matrix<Scalar>& a) {
2398  return solve(a, Matrix<Scalar>::eye(a.size1()));
2399  }
2400 
2401  template<typename Scalar>
2402  Matrix<Scalar> Matrix<Scalar>::
2403  inv(const Matrix<Scalar>& a,
2404  const std::string& lsolver, const Dict& dict) {
2405  casadi_error("'inv' with plugin not defined for " + type_name());
2406  return Matrix<Scalar>();
2407  }
2408 
2409  template<typename Scalar>
2410  Matrix<Scalar> Matrix<Scalar>::pinv(const Matrix<Scalar>& A) {
2411  if (A.size2()>=A.size1()) {
2412  return solve(mtimes(A, A.T()), A).T();
2413  } else {
2414  return solve(mtimes(A.T(), A), A.T());
2415  }
2416  }
2417 
2418  template<typename Scalar>
2419  Matrix<Scalar> Matrix<Scalar>::
2420  pinv(const Matrix<Scalar>& A, const std::string& lsolver, const Dict& dict) {
2421  casadi_error("'solve' not defined for " + type_name());
2422  return Matrix<Scalar>();
2423  }
2424 
2425  template<typename Scalar>
2426  Matrix<Scalar> Matrix<Scalar>::
2427  expm_const(const Matrix<Scalar>& A, const Matrix<Scalar>& t) {
2428  casadi_error("'solve' not defined for " + type_name());
2429  return Matrix<Scalar>();
2430  }
2431 
2432  template<typename Scalar>
2433  Matrix<Scalar> Matrix<Scalar>::
2434  expm(const Matrix<Scalar>& A) {
2435  casadi_error("'solve' not defined for " + type_name());
2436  return Matrix<Scalar>();
2437  }
2438 
2439  template<typename Scalar>
2440  Matrix<Scalar> Matrix<Scalar>::kron(const Matrix<Scalar>& a, const Matrix<Scalar>& b) {
2441  std::vector<Scalar> ret(a.nnz()*b.nnz());
2442  casadi_kron(get_ptr(a), a.sparsity(), get_ptr(b), b.sparsity(), get_ptr(ret));
2443 
2444  Sparsity sp_ret = Sparsity::kron(a.sparsity(), b.sparsity());
2445  return Matrix<Scalar>(sp_ret, ret, false);
2446  }
2447 
2448  template<typename Scalar>
2449  Matrix<Scalar> Matrix<Scalar>::diag(const Matrix<Scalar>& A) {
2450  // Nonzero mapping
2451  std::vector<casadi_int> mapping;
2452  // Get the sparsity
2453  Sparsity sp = A.sparsity().get_diag(mapping);
2454 
2455  Matrix<Scalar> ret = zeros(sp);
2456 
2457  for (casadi_int k=0; k<mapping.size(); k++) ret.nz(k) = A.nz(mapping[k]);
2458  return ret;
2459  }
2460 
2464  template<typename Scalar>
2465  Matrix<Scalar> Matrix<Scalar>::diagcat(const std::vector< Matrix<Scalar> > &A) {
2466  std::vector<Scalar> data;
2467 
2468  std::vector<Sparsity> sp;
2469  for (casadi_int i=0;i<A.size();++i) {
2470  data.insert(data.end(), A[i].nonzeros().begin(), A[i].nonzeros().end());
2471  sp.push_back(A[i].sparsity());
2472  }
2473 
2474  return Matrix<Scalar>(Sparsity::diagcat(sp), data, false);
2475  }
2476 
2477  template<typename Scalar>
2478  Matrix<Scalar> Matrix<Scalar>::unite(const Matrix<Scalar>& A, const Matrix<Scalar>& B) {
2479  // Join the sparsity patterns
2480  std::vector<unsigned char> mapping;
2481  Sparsity sp = A.sparsity().unite(B.sparsity(), mapping);
2482 
2483  // Create return matrix
2484  Matrix<Scalar> ret = zeros(sp);
2485 
2486  // Copy sparsity
2487  casadi_int elA=0, elB=0;
2488  for (casadi_int k=0; k<mapping.size(); ++k) {
2489  if (mapping[k]==1) {
2490  ret.nonzeros()[k] = A.nonzeros()[elA++];
2491  } else if (mapping[k]==2) {
2492  ret.nonzeros()[k] = B.nonzeros()[elB++];
2493  } else {
2494  casadi_error("Pattern intersection not empty");
2495  }
2496  }
2497 
2498  casadi_assert_dev(A.nnz()==elA);
2499  casadi_assert_dev(B.nnz()==elB);
2500 
2501  return ret;
2502  }
2503 
2504  template<typename Scalar>
2505  Matrix<Scalar> Matrix<Scalar>::polyval(const Matrix<Scalar>& p, const Matrix<Scalar>& x) {
2506  casadi_assert(p.is_dense(), "polynomial coefficients vector must be dense");
2507  casadi_assert(p.is_vector() && p.nnz()>0, "polynomial coefficients must be a vector");
2508  Matrix<Scalar> ret = x;
2509  for (auto&& e : ret.nonzeros()) {
2510  e = casadi_polyval(p.ptr(), p.numel()-1, e);
2511  }
2512  return ret;
2513  }
2514 
2515  template<typename Scalar>
2516  Matrix<Scalar> Matrix<Scalar>::norm_inf_mul(const Matrix<Scalar>& x,
2517  const Matrix<Scalar>& y) {
2518  casadi_assert(y.size1()==x.size2(), "Dimension error. Got " + x.dim()
2519  + " times " + y.dim() + ".");
2520 
2521  // Allocate work vectors
2522  std::vector<Scalar> dwork(x.size1());
2523  std::vector<casadi_int> iwork(x.size1()+1+y.size2());
2524 
2525  // Call C runtime
2526  return casadi_norm_inf_mul(x.ptr(), x.sparsity(), y.ptr(), y.sparsity(),
2527  get_ptr(dwork), get_ptr(iwork));
2528  }
2529 
2530  template<typename Scalar>
2531  void Matrix<Scalar>::expand(const Matrix<Scalar>& ex,
2532  Matrix<Scalar> &weights, Matrix<Scalar>& terms) {
2533  casadi_error("'expand' not defined for " + type_name());
2534  }
2535 
2536  template<typename Scalar>
2537  Matrix<Scalar> Matrix<Scalar>::pw_const(const Matrix<Scalar>& ex,
2538  const Matrix<Scalar>& tval,
2539  const Matrix<Scalar>& val) {
2540  casadi_error("'pw_const' not defined for " + type_name());
2541  return Matrix<Scalar>();
2542  }
2543 
2544  template<typename Scalar>
2545  Matrix<Scalar> Matrix<Scalar>::pw_lin(const Matrix<Scalar>& ex,
2546  const Matrix<Scalar>& tval,
2547  const Matrix<Scalar>& val) {
2548  casadi_error("'pw_lin' not defined for " + type_name());
2549  return Matrix<Scalar>();
2550  }
2551 
2552  template<typename Scalar>
2553  Matrix<Scalar> Matrix<Scalar>::if_else(const Matrix<Scalar> &cond,
2554  const Matrix<Scalar> &if_true,
2555  const Matrix<Scalar> &if_false,
2556  bool short_circuit) {
2557  return if_else_zero(cond, if_true) + if_else_zero(!cond, if_false);
2558  }
2559 
2560  template<typename Scalar>
2561  Matrix<Scalar> Matrix<Scalar>::conditional(const Matrix<Scalar>& ind,
2562  const std::vector<Matrix<Scalar> >& x,
2563  const Matrix<Scalar>& x_default,
2564  bool short_circuit) {
2565  casadi_assert(!short_circuit,
2566  "Short-circuiting 'conditional' not supported for " + type_name());
2567  casadi_assert(ind.is_scalar(true),
2568  "conditional: first argument must be scalar. Got " + ind.dim()+ " instead.");
2569 
2570  Matrix<Scalar> ret = x_default;
2571  for (casadi_int k=0; k<x.size(); ++k) {
2572  ret = if_else(ind==k, x[k], ret, short_circuit);
2573  }
2574  return ret;
2575  }
2576 
2577  template<typename Scalar>
2578  Matrix<Scalar> Matrix<Scalar>::heaviside(const Matrix<Scalar>& x) {
2579  return (1+sign(x))/2;
2580  }
2581 
2582  template<typename Scalar>
2583  Matrix<Scalar> Matrix<Scalar>::rectangle(const Matrix<Scalar>& x) {
2584  return 0.5*(sign(x+0.5)-sign(x-0.5));
2585  }
2586 
2587  template<typename Scalar>
2588  Matrix<Scalar> Matrix<Scalar>::triangle(const Matrix<Scalar>& x) {
2589  return rectangle(x/2)*(1-fabs(x));
2590  }
2591 
2592  template<typename Scalar>
2593  Matrix<Scalar> Matrix<Scalar>::ramp(const Matrix<Scalar>& x) {
2594  return x*heaviside(x);
2595  }
2596 
2597  template<typename Scalar>
2598  Matrix<Scalar> Matrix<Scalar>::
2599  gauss_quadrature(const Matrix<Scalar> &f,
2600  const Matrix<Scalar> &x, const Matrix<Scalar> &a,
2601  const Matrix<Scalar> &b, casadi_int order) {
2602  return gauss_quadrature(f, x, a, b, order, Matrix<Scalar>());
2603  }
2604 
2605  template<typename Scalar>
2606  Matrix<Scalar> Matrix<Scalar>::gauss_quadrature(const Matrix<Scalar>& f,
2607  const Matrix<Scalar>& x,
2608  const Matrix<Scalar>& a,
2609  const Matrix<Scalar>& b, casadi_int order,
2610  const Matrix<Scalar>& w) {
2611  casadi_error("'gauss_quadrature' not defined for " + type_name());
2612  return Matrix<Scalar>();
2613  }
2614 
2615  template<typename Scalar>
2616  Matrix<Scalar> Matrix<Scalar>::simplify(const Matrix<Scalar> &x) {
2617  return x;
2618  }
2619 
2620  template<typename Scalar>
2621  Matrix<Scalar> Matrix<Scalar>::substitute(const Matrix<Scalar>& ex,
2622  const Matrix<Scalar>& v,
2623  const Matrix<Scalar>& vdef) {
2624  casadi_error("'substitute' not defined for " + type_name());
2625  return Matrix<Scalar>();
2626  }
2627 
2628  template<typename Scalar>
2629  std::vector<Matrix<Scalar> >
2630  Matrix<Scalar>::substitute(const std::vector<Matrix<Scalar> >& ex,
2631  const std::vector<Matrix<Scalar> >& v,
2632  const std::vector<Matrix<Scalar> >& vdef) {
2633  casadi_error("'substitute' not defined for " + type_name());
2634  return std::vector<Matrix<Scalar> >();
2635  }
2636 
2637  template<typename Scalar>
2638  void Matrix<Scalar>::substitute_inplace(const std::vector<Matrix<Scalar> >& v,
2639  std::vector<Matrix<Scalar> >& vdef,
2640  std::vector<Matrix<Scalar> >& ex,
2641  bool reverse) {
2642  casadi_error("'substitute_inplace' not defined for " + type_name());
2643  }
2644 
2645  template<typename Scalar>
2646  void Matrix<Scalar>::extract_parametric(const Matrix<Scalar> &expr,
2647  const Matrix<Scalar>& par,
2648  Matrix<Scalar>& expr_ret,
2649  std::vector<Matrix<Scalar> >& symbols,
2650  std::vector< Matrix<Scalar> >& parametric,
2651  const Dict& opts) {
2652  casadi_error("'extract_parametric' not defined for " + type_name());
2653  }
2654 
2655  template<typename Scalar>
2656  void Matrix<Scalar>::separate_linear(const Matrix<Scalar> &expr,
2657  const Matrix<Scalar> &sym_lin, const Matrix<Scalar> &sym_const,
2658  Matrix<Scalar>& expr_const, Matrix<Scalar>& expr_lin, Matrix<Scalar>& expr_nonlin) {
2659  casadi_error("'separate_linear' not defined for " + type_name());
2660  }
2661 
2662  template<typename Scalar>
2663  bool Matrix<Scalar>::depends_on(const Matrix<Scalar> &x, const Matrix<Scalar> &arg) {
2664  casadi_error("'depends_on' not defined for " + type_name());
2665  return false;
2666  }
2667 
2668  template<typename Scalar>
2669  bool Matrix<Scalar>::contains_all(const std::vector <Matrix<Scalar> >& v,
2670  const std::vector <Matrix<Scalar> > &n) {
2671  casadi_error("'contains_all' not defined for " + type_name());
2672  return false;
2673  }
2674 
2675  template<typename Scalar>
2676  bool Matrix<Scalar>::contains_any(const std::vector<Matrix<Scalar> >& v,
2677  const std::vector <Matrix<Scalar> > &n) {
2678  casadi_error("'contains_any' not defined for " + type_name());
2679  return false;
2680  }
2681 
2682  template<typename Scalar>
2683  std::vector< Matrix<Scalar> > Matrix<Scalar>::cse(const std::vector< Matrix<Scalar> >& e) {
2684  casadi_error("'cse' not defined for " + type_name());
2685  return {};
2686  }
2687 
2688 
2689  template<typename Scalar>
2690  Matrix<Scalar> Matrix<Scalar>::
2691  jacobian(const Matrix<Scalar> &f, const Matrix<Scalar> &x, const Dict& opts) {
2692  casadi_error("'jacobian' not defined for " + type_name());
2693  return Matrix<Scalar>();
2694  }
2695 
2696  template<typename Scalar>
2697  Matrix<Scalar> Matrix<Scalar>::hessian(const Matrix<Scalar> &f,
2698  const Matrix<Scalar> &x,
2699  const Dict& opts) {
2700  casadi_error("'hessian' not defined for " + type_name());
2701  return Matrix<Scalar>();
2702  }
2703 
2704  template<typename Scalar>
2705  Matrix<Scalar> Matrix<Scalar>::hessian(const Matrix<Scalar> &f,
2706  const Matrix<Scalar> &x,
2707  Matrix<Scalar> &g,
2708  const Dict& opts) {
2709  casadi_error("'hessian' not defined for " + type_name());
2710  return Matrix<Scalar>();
2711  }
2712 
2713  template<typename Scalar>
2714  std::vector<std::vector<Matrix<Scalar> > >
2715  Matrix<Scalar>::
2716  forward(const std::vector<Matrix<Scalar> > &ex,
2717  const std::vector<Matrix<Scalar> > &arg,
2718  const std::vector<std::vector<Matrix<Scalar> > > &v,
2719  const Dict& opts) {
2720  casadi_error("'forward' not defined for " + type_name());
2721  }
2722 
2723  template<typename Scalar>
2724  std::vector<std::vector<Matrix<Scalar> > >
2725  Matrix<Scalar>::
2726  reverse(const std::vector<Matrix<Scalar> > &ex,
2727  const std::vector<Matrix<Scalar> > &arg,
2728  const std::vector<std::vector<Matrix<Scalar> > > &v,
2729  const Dict& opts) {
2730  casadi_error("'reverse' not defined for " + type_name());
2731  }
2732 
2733  template<typename Scalar>
2734  std::vector<bool>
2735  Matrix<Scalar>::which_depends(const Matrix<Scalar> &expr, const Matrix<Scalar> &var,
2736  casadi_int order, bool tr) {
2737  casadi_error("'which_depends' not defined for " + type_name());
2738  return std::vector<bool>();
2739  }
2740 
2741  template<typename Scalar>
2742  Sparsity
2743  Matrix<Scalar>::jacobian_sparsity(const Matrix<Scalar> &f, const Matrix<Scalar> &x) {
2744  casadi_error("'jacobian_sparsity' not defined for " + type_name());
2745  return Sparsity();
2746  }
2747 
2748  template<typename Scalar>
2749  Matrix<Scalar> Matrix<Scalar>::taylor(const Matrix<Scalar>& f,
2750  const Matrix<Scalar>& x,
2751  const Matrix<Scalar>& a, casadi_int order) {
2752  casadi_error("'taylor' not defined for " + type_name());
2753  return Matrix<Scalar>();
2754  }
2755 
2756  template<typename Scalar>
2757  Matrix<Scalar> Matrix<Scalar>::mtaylor(const Matrix<Scalar>& f,
2758  const Matrix<Scalar>& x,
2759  const Matrix<Scalar>& a, casadi_int order) {
2760  casadi_error("'mtaylor' not defined for " + type_name());
2761  return Matrix<Scalar>();
2762  }
2763 
2764  template<typename Scalar>
2765  Matrix<Scalar> Matrix<Scalar>::mtaylor(const Matrix<Scalar>& f,
2766  const Matrix<Scalar>& x,
2767  const Matrix<Scalar>& a, casadi_int order,
2768  const std::vector<casadi_int>&order_contributions) {
2769  casadi_error("'mtaylor' not defined for " + type_name());
2770  return Matrix<Scalar>();
2771  }
2772 
2773  template<typename Scalar>
2774  casadi_int Matrix<Scalar>::n_nodes(const Matrix<Scalar>& x) {
2775  casadi_error("'n_nodes' not defined for " + type_name());
2776  return 0;
2777  }
2778 
2779  template<typename Scalar>
2780  std::string
2781  Matrix<Scalar>::print_operator(const Matrix<Scalar>& x,
2782  const std::vector<std::string>& args) {
2783  casadi_error("'print_operator' not defined for " + type_name());
2784  return std::string();
2785  }
2786 
2787  template<typename Scalar>
2788  std::vector<Matrix<Scalar> > Matrix<Scalar>::symvar(const Matrix<Scalar>& x) {
2789  casadi_error("'symvar' not defined for " + type_name());
2790  return std::vector<Matrix<Scalar> >();
2791  }
2792 
2793  template<typename Scalar>
2794  void Matrix<Scalar>::extract(std::vector<Matrix<Scalar>>& ex, std::vector<Matrix<Scalar>>& v,
2795  std::vector<Matrix<Scalar>>& vdef, const Dict& opts) {
2796  casadi_error("'extract' not defined for " + type_name());
2797  }
2798 
2799  template<typename Scalar>
2800  void Matrix<Scalar>::shared(std::vector<Matrix<Scalar> >& ex,
2801  std::vector<Matrix<Scalar> >& v,
2802  std::vector<Matrix<Scalar> >& vdef,
2803  const std::string& v_prefix,
2804  const std::string& v_suffix) {
2805  casadi_error("'shared' not defined for " + type_name());
2806  }
2807 
2808  template<typename Scalar>
2809  Matrix<Scalar> Matrix<Scalar>::poly_coeff(const Matrix<Scalar>& f,
2810  const Matrix<Scalar>&x) {
2811  casadi_error("'poly_coeff' not defined for " + type_name());
2812  }
2813 
2814  template<typename Scalar>
2815  Matrix<Scalar> Matrix<Scalar>::poly_roots(const Matrix<Scalar>& p) {
2816  casadi_error("'poly_roots' not defined for " + type_name());
2817  }
2818 
2819  template<typename Scalar>
2820  Matrix<Scalar> Matrix<Scalar>::eig_symbolic(const Matrix<Scalar>& m) {
2821  casadi_error("'eig_symbolic' not defined for " + type_name());
2822  }
2823 
2824  template<typename Scalar>
2825  DM Matrix<Scalar>::evalf(const Matrix<Scalar>& m) {
2826  Function f("f", std::vector<SX>{}, std::vector<SX>{m});
2827  return f(std::vector<DM>{})[0];
2828  }
2829 
2830  template<typename Scalar>
2831  Matrix<Scalar> Matrix<Scalar>::sparsify(const Matrix<Scalar>& x, double tol) {
2832  // Quick return if there are no entries to be removed
2833  bool remove_nothing = true;
2834  for (auto it=x.nonzeros().begin(); it!=x.nonzeros().end() && remove_nothing; ++it) {
2835  remove_nothing = !casadi_limits<Scalar>::is_almost_zero(*it, tol);
2836  }
2837  if (remove_nothing) return x;
2838 
2839  // Get the current sparsity pattern
2840  casadi_int size1 = x.size1();
2841  casadi_int size2 = x.size2();
2842  const casadi_int* colind = x.colind();
2843  const casadi_int* row = x.row();
2844 
2845  // Construct the new sparsity pattern
2846  std::vector<casadi_int> new_colind(1, 0), new_row;
2847  std::vector<Scalar> new_data;
2848 
2849  // Loop over the columns
2850  for (casadi_int cc=0; cc<size2; ++cc) {
2851  // Loop over existing nonzeros
2852  for (casadi_int el=colind[cc]; el<colind[cc+1]; ++el) {
2853  // If it is not known to be a zero
2854  if (!casadi_limits<Scalar>::is_almost_zero(x->at(el), tol)) {
2855  // Save the nonzero in its new location
2856  new_data.push_back(x->at(el));
2857 
2858  // Add to pattern
2859  new_row.push_back(row[el]);
2860  }
2861  }
2862  // Save the new column offset
2863  new_colind.push_back(new_row.size());
2864  }
2865 
2866  // Construct the sparsity pattern
2867  Sparsity sp(size1, size2, new_colind, new_row);
2868 
2869  // Construct matrix and return
2870  return Matrix<Scalar>(sp, new_data);
2871  }
2872 
2873 
2874  template<typename Scalar>
2875  std::vector<Matrix<Scalar> > Matrix<Scalar>::get_input(const Function& f) {
2876  casadi_error("'get_input' not defined for " + type_name());
2877  }
2878 
2879  template<typename Scalar>
2880  std::vector<Matrix<Scalar> > Matrix<Scalar>::get_free(const Function& f) {
2881  casadi_error("'get_free' not defined for " + type_name());
2882  }
2883 
2884  template<typename Scalar>
2885  Matrix<Scalar>::operator double() const {
2886  casadi_assert_dev(is_scalar());
2887  return static_cast<double>(scalar());
2888  }
2889 
2890  template<typename Scalar>
2891  Matrix<Scalar>::operator casadi_int() const {
2892  casadi_assert_dev(is_scalar());
2893  return static_cast<casadi_int>(scalar());
2894  }
2895 
2896  template<typename Scalar>
2897  Matrix<Scalar> Matrix<Scalar>::_sym(const std::string& name, const Sparsity& sp) {
2898  casadi_error("'sym' not defined for " + type_name());
2899  }
2900 
2901  template<typename Scalar>
2902  Matrix<Scalar> Matrix<Scalar>::rand(const Sparsity& sp) { // NOLINT(runtime/threadsafe_fn)
2903 
2904  casadi_error("'rand' not defined for " + type_name());
2905  }
2906 
2907  template<typename Scalar>
2908  std::string Matrix<Scalar>::serialize() const {
2909  std::stringstream ss;
2910  serialize(ss);
2911  return ss.str();
2912  }
2913 
2914  template<typename Scalar>
2915  void Matrix<Scalar>::serialize(SerializingStream& s) const {
2916  s.pack("Matrix::sparsity", sparsity());
2917  s.pack("Matrix::nonzeros", nonzeros());
2918  }
2919 
2920  template<typename Scalar>
2921  Matrix<Scalar> Matrix<Scalar>::deserialize(DeserializingStream& s) {
2922  Sparsity sp;
2923  s.unpack("Matrix::sparsity", sp);
2924  std::vector<Scalar> nz;
2925  s.unpack("Matrix::nonzeros", nz);
2926  return Matrix<Scalar>(sp, nz, false);
2927  }
2928 
2929  template<typename Scalar>
2930  void Matrix<Scalar>::serialize(std::ostream &stream) const {
2931  SerializingStream s(stream);
2932  serialize(s);
2933  }
2934 
2935  template<typename Scalar>
2936  Matrix<Scalar> Matrix<Scalar>::deserialize(std::istream &stream) {
2937  DeserializingStream s(stream);
2938  return Matrix<Scalar>::deserialize(s);
2939  }
2940 
2941  template<typename Scalar>
2942  Matrix<Scalar> Matrix<Scalar>::deserialize(const std::string& s) {
2943  std::stringstream ss;
2944  ss << s;
2945  return deserialize(ss);
2946  }
2947 
2948 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
2949  template<typename Scalar>
2950  std::mutex& Matrix<Scalar>::get_mutex_temp() {
2951  casadi_error("'get_mutex_temp' not defined for " + type_name());
2952  }
2953 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
2954 
2955 } // namespace casadi
2956 
2957 #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.