1 /* Siconos is a program dedicated to modeling, simulation and control
2  * of non smooth dynamical systems.
3  *
4  * Copyright 2021 INRIA.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 #include "SimpleMatrix.hpp"
19 
20 #include <assert.h>                                             // for assert
21 #include <memory>                                               // for __sha...
22 #include <iostream>                                             // for ostream
23 #include <boost/numeric/ublas/io.hpp>                           // for opera...
24 #include <boost/numeric/ublas/matrix_proxy.hpp>                 // for matri...
25 #include <boost/numeric/bindings/blas.hpp>
26 #include <boost/numeric/bindings/ublas/matrix.hpp>
27 #include "SimpleMatrixFriends.hpp"                              // for subprod
28 #include "SiconosAlgebra.hpp"    // for symmetric, triangular ...
29 #include "BlockMatrix.hpp"                                      // for Block...
30 #include "BlockMatrixIterators.hpp"                             // for Const...
31 #include "SiconosException.hpp"                           // for Sicon...
32 #include "ioMatrix.hpp"                                         // for read
33 #include "Tools.hpp"                                            // for toString
34 #include "bindings_utils.hpp"                                   // for fill
35 #include "NumericsMatrix.h"
36 
37 #include "NumericsSparseMatrix.h"
38 #include "CSparseMatrix.h"
39 
40 //#define DEBUG_MESSAGES
41 #include "siconos_debug.h"
42 
43 #ifdef DEBUG_MESSAGES
44 #include "NumericsVector.h"
45 #include <cs.h>
46 #endif
47 
48 
49 
50 
51 
52 using namespace Siconos;
53 namespace siconosBindings = boost::numeric::bindings::blas;
54 using std::cout;
55 using std::endl;
56 
57 
58 // =================================================
59 //                CONSTRUCTORS
60 // =================================================
61 
SimpleMatrix()62 SimpleMatrix::SimpleMatrix():
63   SiconosMatrix(Siconos::DENSE)
64 {
65   mat.Dense = new DenseMat(ublas::zero_matrix<double>());
66 }
67 
68 // parameters: dimensions and type.
SimpleMatrix(unsigned int row,unsigned int col,UBLAS_TYPE typ,unsigned int upper,unsigned int lower)69 SimpleMatrix::SimpleMatrix(unsigned int row,
70                            unsigned int col,
71                            UBLAS_TYPE typ,
72                            unsigned int upper,
73                            unsigned int lower):
74   SiconosMatrix(Siconos::DENSE)
75 {
76   if(typ == DENSE)
77   {
78     mat.Dense = new DenseMat(ublas::zero_matrix<double>(row, col));
79     // _num = 1; default value
80   }
81   else if(typ == TRIANGULAR)
82   {
83     mat.Triang = new TriangMat(ublas::zero_matrix<double>(row, col));
84     _num = TRIANGULAR;
85   }
86   else if(typ == SYMMETRIC)
87   {
88     mat.Sym = new SymMat(ublas::zero_matrix<double>(row, col));
89     _num = SYMMETRIC;
90   }
91   else if(typ == SPARSE)
92   {
93     mat.Sparse = new SparseMat(row, col, upper);
94     _num = SPARSE;
95     zero();
96   }
97   else if(typ == SPARSE_COORDINATE)
98   {
99     mat.SparseCoordinate = new SparseCoordinateMat(row, col, upper);
100     _num = SPARSE_COORDINATE;
101     zero();
102   }
103   else if(typ == BANDED)
104   {
105     mat.Banded = new BandedMat(row, col, upper, lower);
106     _num = BANDED;
107     zero();
108   }
109   else if(typ == ZERO)
110   {
111     mat.Zero = new ZeroMat(row, col);
112     _num = ZERO;
113   }
114   else if(typ == IDENTITY)
115   {
116     mat.Identity = new IdentityMat(row, col);
117     _num = IDENTITY;
118   }
119   else THROW_EXCEPTION("invalid type.");
120 }
121 
122 // parameters: dimensions, input value and type
SimpleMatrix(unsigned int row,unsigned int col,double inputValue,UBLAS_TYPE typ,unsigned int upper,unsigned int lower)123 SimpleMatrix::SimpleMatrix(unsigned int row, unsigned int col, double inputValue, UBLAS_TYPE typ, unsigned int upper, unsigned int lower):
124   SiconosMatrix(typ)
125 {
126   // This constructor has sense only for dense matrices ...
127   if(typ == DENSE)
128   {
129     mat.Dense = new DenseMat(ublas::scalar_matrix<double>(row, col, inputValue));
130     // _num = Siconos::DENSE; default value
131   }
132   else
133      THROW_EXCEPTION("invalid type.");
134 }
135 
136 // // parameters: a vector (stl) of double and the type.
137 // SimpleMatrix::SimpleMatrix(const std::vector<double>& v, unsigned int row, unsigned int col, UBLAS_TYPE typ, unsigned int lower, unsigned int upper):
138 //   SiconosMatrix(1, row, col), _isPLUFactorized(false), _isQRFactorized(false), _isPLUInversed(false), _isCholeskyFactorized(false), _isCholeskyFactorizedInPlace(false)
139 // {
140 //   if( (  (v.size() != row*col) && (typ != SYMMETRIC && typ != BANDED) )
141 //       || (v.size() != row*row && typ == SYMMETRIC)
142 //       || (typ == BANDED && ( (v.size()) != (unsigned int)(std::max)(row, col)*(lower+1+upper) ) ))
143 //      THROW_EXCEPTION("invalid vector size");
144 
145 //   if(typ == DENSE)
146 //     {
147 //       mat.Dense = new DenseMat(row,col);
148 //       // _num = Siconos::DENSE; default value
149 //     }
150 //   else if(typ == TRIANGULAR)
151 //     {
152 //       mat.Triang = new TriangMat(row,col);
153 //       _num = Siconos::TRIANGULAR;
154 //     }
155 //   else if(typ == SYMMETRIC)
156 //     {
157 //       mat.Sym = new SymMat(row);
158 //       _num = Siconos::SYMMETRIC;
159 //     }
160 //   else if(typ == SPARSE)
161 //     {
162 //        THROW_EXCEPTION("warning -- use constructor(const SparseMat &m) or constructor(UBLAS_TYPE, int row, int col) with UBLAS_TYPE = SPARSE");
163 
164 //     }
165 //   else if(typ == BANDED)
166 //     {
167 //       mat.Banded = new BandedMat(row, col, lower, upper);
168 //       _num = Siconos::BANDED;
169 //     }
170 //   else
171 //      THROW_EXCEPTION("invalid type of matrix given");
172 
173 //   std::copy(v.begin(), v.end(), (vect.Dense)->begin());
174 
175 
176 // }
177 
178 // Copy constructors
SimpleMatrix(const SimpleMatrix & m)179 SimpleMatrix::SimpleMatrix(const SimpleMatrix &m):
180   SiconosMatrix(m.num())
181 {
182 
183   _isSymmetric = m.isSymmetric();
184   _isPositiveDefinite = m.isPositiveDefinite();
185 
186   _isPLUFactorized= m.isPLUFactorized();
187   _isPLUFactorizedInPlace= m.isPLUFactorizedInPlace();
188   _isPLUInversed= m.isPLUInversed();
189 
190   if(_num == Siconos::DENSE)
191   {
192     mat.Dense = new DenseMat(m.size(0), m.size(1));
193     noalias(*mat.Dense) = (*m.dense());
194   }
195   //   mat.Dense = new DenseMat(*m.dense());
196 
197   else if(_num == Siconos::TRIANGULAR)
198     mat.Triang = new TriangMat(*m.triang());
199 
200   else if(_num == Siconos::SYMMETRIC)
201 
202     mat.Sym = new SymMat(*m.sym());
203 
204   else if(_num == Siconos::SPARSE)
205     mat.Sparse = new SparseMat(*m.sparse());
206 
207   else if(_num == Siconos::SPARSE_COORDINATE)
208     mat.SparseCoordinate = new SparseCoordinateMat(*m.sparseCoordinate());
209 
210   else if(_num == Siconos::BANDED)
211     mat.Banded = new BandedMat(*m.banded());
212 
213   else if(_num == Siconos::ZERO)
214     mat.Zero = new ZeroMat(m.size(0), m.size(1));
215 
216   else// if(_num == Siconos::IDENTITY)
217     mat.Identity = new IdentityMat(m.size(0), m.size(1));
218 }
219 
220 /** copy constructor of a block given by the coord = [r0A r1A c0A c1A]
221  *  \param A the matrix for extracting the block
222  */
SimpleMatrix(const SimpleMatrix & A,const Index & coord)223 SimpleMatrix::SimpleMatrix(const SimpleMatrix& A, const Index& coord):
224   SiconosMatrix(A.num())
225 {
226   if(coord[0]>=coord[1])
227      THROW_EXCEPTION("Empty row range coord[0]>= coord[1]");
228   if(coord[2]>=coord[3])
229      THROW_EXCEPTION("Empty column range coord[2]>= coord[3]");
230   if(coord[1] > A.size(0))
231      THROW_EXCEPTION("row index too large.");
232   if(coord[3] > A.size(1))
233      THROW_EXCEPTION("column index too large.");
234 
235   if(_num == Siconos::DENSE)
236   {
237     ublas::matrix_range<DenseMat> subA(*A.dense(), ublas::range(coord[0], coord[1]), ublas::range(coord[2], coord[3]));
238     mat.Dense=new DenseMat(subA);
239   }
240   else if(_num == Siconos::TRIANGULAR)
241   {
242     ublas::matrix_range<TriangMat> subA(*A.triang(), ublas::range(coord[0], coord[1]), ublas::range(coord[2], coord[3]));
243     mat.Triang=new TriangMat(subA);
244   }
245   else if(_num == Siconos::SYMMETRIC)
246   {
247     ublas::matrix_range<SymMat> subA(*A.sym(), ublas::range(coord[0], coord[1]), ublas::range(coord[2], coord[3]));
248     mat.Sym=new SymMat(subA);
249   }
250   else if(_num == Siconos::SPARSE)
251   {
252     ublas::matrix_range<SparseMat> subA(*A.sparse(), ublas::range(coord[0], coord[1]), ublas::range(coord[2], coord[3]));
253     mat.Sparse=new SparseMat(subA);
254   }
255   else if(_num == Siconos::SPARSE_COORDINATE)
256   {
257     ublas::matrix_range<SparseCoordinateMat> subA(*A.sparseCoordinate(), ublas::range(coord[0], coord[1]), ublas::range(coord[2], coord[3]));
258     mat.SparseCoordinate=new SparseCoordinateMat(subA);
259   }
260   else if(_num == Siconos::BANDED)
261   {
262     ublas::matrix_range<BandedMat> subA(*A.banded(), ublas::range(coord[0], coord[1]), ublas::range(coord[2], coord[3]));
263     mat.Banded=new BandedMat(subA);
264   }
265   else if(_num == Siconos::ZERO)
266   {
267     mat.Zero = new ZeroMat(coord[1]-coord[0], coord[3]-coord[2]);
268   }
269   else// if(_num == Siconos::IDENTITY)
270     mat.Identity = new IdentityMat(coord[1]-coord[0], coord[3]-coord[2]);
271 }
272 
273 
274 
275 
SimpleMatrix(const SiconosMatrix & m)276 SimpleMatrix::SimpleMatrix(const SiconosMatrix &m):
277   SiconosMatrix(m.num())
278 {
279   // _num is set in SiconosMatrix constructor with m.num() ... must be changed if m is Block
280   Siconos::UBLAS_TYPE numM = m.num();
281 
282   _isSymmetric = m.isSymmetric();
283   _isPositiveDefinite = m.isPositiveDefinite();
284 
285   _isPLUFactorized= m.isPLUFactorized();
286   _isPLUFactorizedInPlace= m.isPLUFactorizedInPlace();
287   _isPLUInversed= m.isPLUInversed();
288 
289 
290   if(m.ipiv())
291     _ipiv.reset(new VInt(*(m.ipiv())));
292 
293   if(numM == 0)  // ie if m is Block, this matrix is set to a dense.
294   {
295     const BlockMatrix& mB = static_cast<const BlockMatrix&>(m);
296     _num = Siconos::DENSE;
297     // get number of blocks in a row/col of m.
298     mat.Dense = new DenseMat(m.size(0), m.size(1));
299     ConstBlocksIterator1 it;
300     ConstBlocksIterator2 it2;
301     unsigned int posRow = 0;
302     unsigned int posCol = 0;
303 
304     for(it = mB._mat->begin1(); it != mB._mat->end1(); ++it)
305     {
306       for(it2 = it.begin(); it2 != it.end(); ++it2)
307       {
308         setBlock(posRow, posCol, **it2);
309         posCol += (*it2)->size(1);
310       }
311       posRow += (*it)->size(0);
312       posCol = 0;
313     }
314   }
315   else if(_num == Siconos::DENSE)
316   {
317     mat.Dense = new DenseMat(m.size(0), m.size(1));
318     noalias(*mat.Dense) = (*m.dense());
319   }
320 
321   else if(_num == Siconos::TRIANGULAR)
322     mat.Triang = new TriangMat(*m.triang());
323 
324   else if(_num == Siconos::SYMMETRIC)
325     mat.Sym = new SymMat(*m.sym());
326 
327   else if(_num == Siconos::SPARSE)
328     mat.Sparse = new SparseMat(*m.sparse());
329 
330   else if(_num == Siconos::SPARSE_COORDINATE)
331     mat.SparseCoordinate = new SparseCoordinateMat(*m.sparseCoordinate());
332 
333   else if(_num == Siconos::BANDED)
334     mat.Banded = new BandedMat(*m.banded());
335 
336   else if(_num == Siconos::ZERO)
337     mat.Zero = new ZeroMat(m.size(0), m.size(1));
338 
339   else // if(_num == Siconos::IDENTITY)
340     mat.Identity = new IdentityMat(m.size(0), m.size(1));
341 }
342 
SimpleMatrix(const DenseMat & m)343 SimpleMatrix::SimpleMatrix(const DenseMat& m):
344   SiconosMatrix(Siconos::DENSE)
345 {
346   mat.Dense = new DenseMat(m);
347 }
348 
SimpleMatrix(const TriangMat & m)349 SimpleMatrix::SimpleMatrix(const TriangMat& m):
350   SiconosMatrix(Siconos::TRIANGULAR)
351 {
352   mat.Triang = new TriangMat(m);
353 }
354 
SimpleMatrix(const SymMat & m)355 SimpleMatrix::SimpleMatrix(const SymMat& m):
356   SiconosMatrix(Siconos::SYMMETRIC)
357 {
358   mat.Sym = new SymMat(m);
359 }
360 
SimpleMatrix(const SparseMat & m)361 SimpleMatrix::SimpleMatrix(const SparseMat& m):
362   SiconosMatrix(Siconos::SPARSE)
363 {
364   mat.Sparse = new SparseMat(m);
365 }
366 
SimpleMatrix(const SparseCoordinateMat & m)367 SimpleMatrix::SimpleMatrix(const SparseCoordinateMat& m):
368   SiconosMatrix(SPARSE_COORDINATE)
369 {
370   mat.SparseCoordinate = new SparseCoordinateMat(m);
371 }
372 
SimpleMatrix(const BandedMat & m)373 SimpleMatrix::SimpleMatrix(const BandedMat& m):
374   SiconosMatrix(Siconos::BANDED)
375 {
376   mat.Banded = new BandedMat(m);
377 }
378 
SimpleMatrix(const ZeroMat & m)379 SimpleMatrix::SimpleMatrix(const ZeroMat& m):
380   SiconosMatrix(Siconos::ZERO)
381 {
382   mat.Zero = new ZeroMat(m);
383 }
384 
SimpleMatrix(const IdentityMat & m)385 SimpleMatrix::SimpleMatrix(const IdentityMat& m):
386   SiconosMatrix(Siconos::IDENTITY)
387 {
388   mat.Identity = new IdentityMat(m);
389 }
390 
SimpleMatrix(const std::string & file,bool ascii)391 SimpleMatrix::SimpleMatrix(const std::string &file, bool ascii):
392   SiconosMatrix(Siconos::DENSE)
393 {
394   mat.Dense = new DenseMat();
395   if(ascii)
396   {
397     ioMatrix::read(file, "ascii", *this);
398   }
399   else
400   {
401     ioMatrix::read(file, "binary", *this);
402   }
403 }
404 
~SimpleMatrix()405 SimpleMatrix::~SimpleMatrix()
406 {
407   if(_num == Siconos::DENSE)
408   {
409     delete(mat.Dense);
410     if (_numericsMatrix)
411     {
412       // _numericsMatrix->matrix0 points to the array contained in the ublas matrix
413       // To avoid double free on this pointer, we set it to NULL before deletion
414       if (_numericsMatrix->matrix0)
415         _numericsMatrix->matrix0 =nullptr;
416     }
417   }
418   else if(_num == Siconos::TRIANGULAR)
419     delete(mat.Triang);
420   else if(_num == Siconos::SYMMETRIC)
421     delete(mat.Sym);
422   else if(_num == Siconos::SPARSE_COORDINATE)
423     delete(mat.SparseCoordinate);
424   else if(_num == Siconos::SPARSE)
425     delete(mat.Sparse);
426   else if(_num == Siconos::BANDED)
427     delete(mat.Banded);
428   else if(_num == Siconos::ZERO)
429     delete(mat.Zero);
430   else if(_num == Siconos::IDENTITY)
431     delete(mat.Identity);
432 }
433 
434 
updateNumericsMatrix()435 void SimpleMatrix::updateNumericsMatrix()
436 {
437   /* set the numericsMatrix */
438   NumericsMatrix * NM;
439   if(_num == DENSE)
440   {
441     _numericsMatrix.reset(NM_new(),NM_free_not_dense); // When we reset, we do not free the matrix0
442                                                         //that is linked to the array of the boost container
443     NM = _numericsMatrix.get();
444     double * data = (double*)(getArray());
445     DEBUG_EXPR(NV_display(data,size(0)*size(1)););
446     NM_fill(NM, NM_DENSE, size(0), size(1), data ); // Pointer link
447   }
448   else
449   {
450     // For all the other cases, we build a sparse matrix and we call numerics for the factorization of a sparse matrix.
451     _numericsMatrix.reset(NM_create(NM_SPARSE, size(0), size(1)),NM_free);
452     NM = _numericsMatrix.get();
453     _numericsMatrix->matrix2->origin = NSM_CSC;
454     NM_csc_alloc(NM, nnz());
455     fillCSC(numericsSparseMatrix(NM)->csc, std::numeric_limits<double>::epsilon());
456     DEBUG_EXPR(cs_print(numericsSparseMatrix(NM)->csc, 0););
457   }
458 }
459 
460 
461 
checkSymmetry(double tol) const462 bool SimpleMatrix::checkSymmetry(double tol) const
463 {
464   SP::SimpleMatrix  m_trans(new SimpleMatrix(*this));
465   m_trans->trans();
466   double err = (*this-*m_trans).normInf();
467   if((*m_trans).normInf() > 0.0)
468   {
469     err /= (*m_trans).normInf();
470   }
471   // std::cout << "err_rel  ="<< err <<std::endl;
472   return (err < tol);
473 }
474 //======================================
475 // get Ublas component (dense, sym ...)
476 //======================================
477 
getDense(unsigned int,unsigned int) const478 const DenseMat SimpleMatrix::getDense(unsigned int, unsigned int) const
479 {
480   if(_num != Siconos::DENSE)
481      THROW_EXCEPTION(" the current matrix is not a Dense matrix");
482 
483   return *mat.Dense;
484 }
485 
getTriang(unsigned int,unsigned int) const486 const TriangMat SimpleMatrix::getTriang(unsigned int, unsigned int) const
487 {
488   if(_num != Siconos::TRIANGULAR)
489      THROW_EXCEPTION("the current matrix is not a Triangular matrix");
490 
491   return *mat.Triang;
492 }
493 
getSym(unsigned int,unsigned int) const494 const SymMat SimpleMatrix::getSym(unsigned int, unsigned int) const
495 {
496   if(_num != Siconos::SYMMETRIC)
497      THROW_EXCEPTION("he current matrix is not a Symmetric matrix");
498 
499   return *mat.Sym;
500 }
501 
getSparse(unsigned int,unsigned int) const502 const SparseMat SimpleMatrix::getSparse(unsigned int, unsigned int) const
503 {
504   if(_num != Siconos::SPARSE)
505      THROW_EXCEPTION("the current matrix is not a Sparse matrix");
506 
507   return *mat.Sparse;
508 }
509 
getSparseCoordinate(unsigned int,unsigned int) const510 const SparseCoordinateMat SimpleMatrix::getSparseCoordinate(unsigned int, unsigned int) const
511 {
512   if(_num != Siconos::SPARSE_COORDINATE)
513      THROW_EXCEPTION("the current matrix is not a Sparse Coordinate matrix");
514 
515   return *mat.SparseCoordinate;
516 }
getBanded(unsigned int,unsigned int) const517 const BandedMat SimpleMatrix::getBanded(unsigned int, unsigned int) const
518 {
519   if(_num != Siconos::BANDED)
520      THROW_EXCEPTION("the current matrix is not a Banded matrix");
521 
522   return *mat.Banded;
523 }
524 
getZero(unsigned int,unsigned int) const525 const ZeroMat SimpleMatrix::getZero(unsigned int, unsigned int) const
526 {
527   if(_num != Siconos::ZERO)
528      THROW_EXCEPTION("the current matrix is not a Zero matrix");
529 
530   return *mat.Zero;
531 }
532 
getIdentity(unsigned int,unsigned int) const533 const IdentityMat SimpleMatrix::getIdentity(unsigned int, unsigned int) const
534 {
535   if(_num != Siconos::IDENTITY)
536      THROW_EXCEPTION("the current matrix is not a Identity matrix");
537 
538   return *mat.Identity;
539 }
540 
dense(unsigned int,unsigned int) const541 DenseMat* SimpleMatrix::dense(unsigned int, unsigned int) const
542 {
543   if(_num != Siconos::DENSE)
544      THROW_EXCEPTION("the current matrix is not a Dense matrix");
545 
546   return mat.Dense;
547 }
548 
triang(unsigned int,unsigned int) const549 TriangMat* SimpleMatrix::triang(unsigned int, unsigned int) const
550 {
551   if(_num != Siconos::TRIANGULAR)
552      THROW_EXCEPTION("the current matrix is not a Triangular matrix");
553 
554   return mat.Triang;
555 }
556 
sym(unsigned int,unsigned int) const557 SymMat* SimpleMatrix::sym(unsigned int, unsigned int) const
558 {
559   if(_num != Siconos::SYMMETRIC)
560      THROW_EXCEPTION("the current matrix is not a Symmetric matrix");
561 
562   return mat.Sym;
563 }
564 
sparse(unsigned int,unsigned int) const565 SparseMat* SimpleMatrix::sparse(unsigned int, unsigned int) const
566 {
567   if(_num != Siconos::SPARSE)
568      THROW_EXCEPTION("the current matrix is not a Sparse matrix");
569 
570   return mat.Sparse;
571 }
572 
sparseCoordinate(unsigned int,unsigned int) const573 SparseCoordinateMat* SimpleMatrix::sparseCoordinate(unsigned int, unsigned int) const
574 {
575   if(_num != Siconos::SPARSE_COORDINATE)
576      THROW_EXCEPTION("the current matrix is not a Sparse matrix");
577 
578   return mat.SparseCoordinate;
579 }
580 
banded(unsigned int,unsigned int) const581 BandedMat* SimpleMatrix::banded(unsigned int, unsigned int) const
582 {
583   if(_num != Siconos::BANDED)
584      THROW_EXCEPTION("the current matrix is not a Banded matrix");
585 
586   return mat.Banded;
587 }
588 
zero_mat(unsigned int,unsigned int) const589 ZeroMat* SimpleMatrix::zero_mat(unsigned int, unsigned int) const
590 {
591   if(_num != Siconos::ZERO)
592      THROW_EXCEPTION("the current matrix is not a Zero matrix");
593 
594   return mat.Zero;
595 }
596 
identity(unsigned int,unsigned int) const597 IdentityMat* SimpleMatrix::identity(unsigned int, unsigned int) const
598 {
599   if(_num != Siconos::IDENTITY)
600      THROW_EXCEPTION("the current matrix is not a Identity matrix");
601 
602   return mat.Identity;
603 }
604 
getArray(unsigned int,unsigned int) const605 double* SimpleMatrix::getArray(unsigned int, unsigned int) const
606 {
607   if(_num == Siconos::SPARSE)
608      THROW_EXCEPTION("not yet implemented for sparse matrix.");
609 
610   if(_num == Siconos::DENSE)
611     return (((*mat.Dense).data()).data());
612   else if(_num == Siconos::TRIANGULAR)
613     return &(((*mat.Triang).data())[0]);
614   else if(_num == Siconos::SYMMETRIC)
615     return &(((*mat.Sym).data())[0]);
616   else if(_num == Siconos::ZERO)
617   {
618     ZeroMat::iterator1 it = (*mat.Zero).begin1();
619     return const_cast<double*>(&(*it));
620   }
621   else if(_num == Siconos::IDENTITY)
622   {
623     IdentityMat::iterator1 it = (*mat.Identity).begin1();
624     return const_cast<double*>(&(*it));
625   }
626   else
627     return &(((*mat.Banded).data())[0]);
628 }
629 
630 // ===========================
631 //       fill matrix
632 // ===========================
633 
zero()634 void SimpleMatrix::zero()
635 {
636   unsigned int size1 = size(0);
637   unsigned int size2 = size(1);
638   if(_num == Siconos::DENSE)
639     *mat.Dense = ublas::zero_matrix<double>(size1, size2);
640   else if(_num == Siconos::TRIANGULAR)
641     *mat.Triang = ublas::zero_matrix<double>(size1, size2);
642 
643   else if(_num == Siconos::SYMMETRIC)
644     *mat.Sym = ublas::zero_matrix<double>(size1, size2);
645 
646   else if(_num == Siconos::SPARSE)
647     *mat.Sparse = ublas::zero_matrix<double>(size1, size2);
648 
649   else if(_num == Siconos::SPARSE_COORDINATE)
650     *mat.SparseCoordinate = ublas::zero_matrix<double>(size1, size2);
651 
652   else if(_num == Siconos::BANDED)
653     *mat.Banded = ublas::zero_matrix<double>(size1, size2);
654 
655   else if(_num == Siconos::IDENTITY)
656      THROW_EXCEPTION("you can not set to zero a matrix of type Identity!.");
657   resetFactorizationFlags();
658   // if _num == Siconos::ZERO: nothing
659 }
660 
randomize()661 void SimpleMatrix::randomize()
662 {
663   if(_num == Siconos::DENSE)
664     Siconos::algebra::fill(*mat.Dense);
665   else
666      THROW_EXCEPTION("only implemented for dense matrices.");
667   resetFactorizationFlags();
668 }
669 
randomize_sym()670 void SimpleMatrix::randomize_sym()
671 {
672   if(_num == Siconos::DENSE)
673     Siconos::algebra::fill_sym(*mat.Dense);
674   else
675      THROW_EXCEPTION("only implemented for dense matrices.");
676   resetFactorizationFlags();
677 }
678 
eye()679 void SimpleMatrix::eye()
680 {
681   unsigned int size1 = size(0);
682   unsigned int size2 = size(1);
683   if(_num == Siconos::DENSE)
684     *mat.Dense = ublas::identity_matrix<double>(size1, size2);
685 
686   else if(_num == Siconos::TRIANGULAR)
687     *mat.Triang = ublas::identity_matrix<double>(size1, size2);
688 
689   else if(_num == Siconos::SYMMETRIC)
690     *mat.Sym = ublas::identity_matrix<double>(size1, size2);
691 
692   else if(_num == Siconos::SPARSE)
693     *mat.Sparse = ublas::identity_matrix<double>(size1, size2);
694 
695   else if(_num == Siconos::BANDED)
696     *mat.Banded = ublas::identity_matrix<double>(size1, size2);
697 
698   else if(_num == Siconos::ZERO)
699      THROW_EXCEPTION("you can not set to identity a matrix of type Zero!.");
700   resetFactorizationFlags();
701 }
702 
703 
704 
size(unsigned int index) const705 unsigned int SimpleMatrix::size(unsigned int index) const
706 {
707   if(_num == Siconos::DENSE)
708   {
709     if(index == 0) return (*mat.Dense).size1();
710     else  return (*mat.Dense).size2();
711   }
712   else if(_num == Siconos::TRIANGULAR)
713   {
714     if(index == 0) return (*mat.Triang).size1();
715     else return (*mat.Triang).size2();
716   }
717   else if(_num == Siconos::SYMMETRIC)
718   {
719     if(index == 0) return (*mat.Sym).size1();
720     else  return (*mat.Sym).size2();
721   }
722   else if(_num == Siconos::SPARSE)
723   {
724     if(index == 0) return (*mat.Sparse).size1();
725     else return (*mat.Sparse).size2();
726   }
727   else if(_num == Siconos::SPARSE_COORDINATE)
728   {
729     if(index == 0) return (*mat.SparseCoordinate).size1();
730     else return (*mat.SparseCoordinate).size2();
731   }
732   else if(_num == Siconos::BANDED)
733   {
734     if(index == 0) return (*mat.Banded).size1();
735     else  return (*mat.Banded).size2();
736   }
737   else if(_num == Siconos::ZERO)
738   {
739     if(index == 0) return (*mat.Zero).size1();
740     else  return (*mat.Zero).size2();
741   }
742   else if(_num == Siconos::IDENTITY)
743   {
744     if(index == 0) return (*mat.Identity).size1();
745     else  return (*mat.Identity).size2();
746   }
747   else return 0;
748 
749 
750 };
751 
752 
753 //=======================
754 // set matrix dimension
755 //=======================
756 
resize(unsigned int row,unsigned int col,unsigned int lower,unsigned int upper,bool preserve)757 void SimpleMatrix::resize(unsigned int row, unsigned int col, unsigned int lower, unsigned int upper, bool preserve)
758 {
759 
760   if(_num == Siconos::DENSE)
761   {
762     (*mat.Dense).resize(row, col, preserve);
763   }
764   else if(_num == Siconos::TRIANGULAR)
765   {
766     (*mat.Triang).resize(row, col, preserve);
767   }
768   else if(_num == Siconos::SYMMETRIC)
769   {
770     (*mat.Sym).resize(row, col, preserve);
771   }
772   else if(_num == Siconos::SPARSE)
773   {
774     (*mat.Sparse).resize(row, col, preserve);
775   }
776   else if(_num == Siconos::SPARSE_COORDINATE)
777   {
778     (*mat.SparseCoordinate).resize(row, col, preserve);
779   }
780   else if(_num == Siconos::BANDED)
781   {
782     (*mat.Banded).resize(row, col, lower, upper, preserve);
783   }
784   else if(_num == Siconos::ZERO)
785   {
786     (*mat.Zero).resize(row, col, preserve);
787   }
788   else if(_num == Siconos::IDENTITY)
789   {
790     (*mat.Identity).resize(row, col, preserve);
791   }
792   resetFactorizationFlags();
793 }
794 
795 
796 //=====================
797 // screen display
798 //=====================
799 
display() const800 void SimpleMatrix::display() const
801 {
802   std::cout.setf(std::ios::scientific);
803   std::cout.precision(6);
804 
805   if(size(0) == 0 || size(1) ==0)
806   {
807     std::cout << "SimpleMatrix::display(): empty matrix" << std::endl;
808   }
809   std::cout << "SimpleMatrix storage type - num = " << _num << "\n";
810   if(_num == Siconos::DENSE)
811   {
812     Siconos::algebra::print_m(*mat.Dense);
813     //std::cout << *mat.Dense << std::endl;
814   }
815   else if(_num == Siconos::TRIANGULAR)
816     std::cout << *mat.Triang << std::endl;
817   else if(_num == Siconos::SYMMETRIC)
818     std::cout << *mat.Sym << std::endl;
819   else if(_num == Siconos::SPARSE)
820   {
821     std::cout << "non zero element (nnz) = " <<  mat.Sparse->nnz() << std::endl;
822 
823     std::cout << *mat.Sparse << std::endl;
824   }
825   else if(_num == Siconos::SPARSE_COORDINATE)
826   {
827     std::cout << *mat.SparseCoordinate << std::endl;
828   }
829   else if(_num == Siconos::BANDED)
830     std::cout << *mat.Banded << std::endl;
831   else if(_num == Siconos::ZERO)
832     std::cout << *mat.Zero << std::endl;
833   else if(_num == Siconos::IDENTITY)
834     std::cout << *mat.Identity << std::endl;
835 }
displayExpert(bool brief) const836 void SimpleMatrix::displayExpert(bool brief) const
837 {
838   std::cout.setf(std::ios::scientific);
839   std::cout.precision(6);
840 
841   if(size(0) == 0 || size(1) ==0)
842   {
843     std::cout << "SimpleMatrix::display(): empty matrix" << std::endl;
844   }
845   std::cout << "SimpleMatrix storage type - num = " << _num << "\n";
846   if(_num == Siconos::DENSE)
847   {
848     Siconos::algebra::print_m(*mat.Dense);
849     //std::cout << *mat.Dense << std::endl;
850   }
851   else if(_num == Siconos::TRIANGULAR)
852     std::cout << *mat.Triang << std::endl;
853   else if(_num == Siconos::SYMMETRIC)
854     std::cout << *mat.Sym << std::endl;
855   else if(_num == Siconos::SPARSE)
856   {
857     std::cout << "non zero element (nnz) = " <<  mat.Sparse->nnz() << std::endl;
858     std::cout << "non zero element (nnz_capacity) = " <<  mat.Sparse->nnz_capacity() << std::endl;
859     std::cout << "filled1 = " <<  mat.Sparse->filled1() << std::endl;
860     std::cout << "filled2 = " <<  mat.Sparse->filled2() << std::endl;
861 
862     std::cout << "index_data1 = [ " ;
863     size_t i=0;
864     for(i = 0; i < mat.Sparse->filled1()-1 ; i++)
865     {
866       std::cout << mat.Sparse->index1_data()[i] << ", " ;
867     }
868     std::cout << mat.Sparse->index1_data()[i] << "]" <<  std::endl;
869 
870     std::cout << "index_data2 = [" ;
871     for(i = 0; i < mat.Sparse->filled2()-1 ; i++)
872     {
873       std::cout << mat.Sparse->index2_data()[i] << ", " ;
874     }
875     std::cout << mat.Sparse->index2_data()[i] << "]" << std::endl;
876 
877     std::cout << "value_data = [" ;
878     for(i = 0; i < mat.Sparse->filled2()-1 ; i++)
879     {
880       std::cout << mat.Sparse->value_data()[i] << ", " ;
881     }
882     std::cout << mat.Sparse->value_data()[i] << "]" << std::endl;
883 
884     std::cout << *mat.Sparse << std::endl;
885   }
886   else if(_num == Siconos::SPARSE_COORDINATE)
887   {
888     std::cout << "non zero element (nnz) = " <<  mat.SparseCoordinate->nnz() << std::endl;
889 
890 
891 
892     for(size_t i = 0; i < mat.SparseCoordinate->nnz(); ++i)
893     {
894       //std::cout << i << std::endl;
895       std::cout << "M(" << mat.SparseCoordinate->index1_data()[i] << ", " ;
896       std::cout << mat.SparseCoordinate->index2_data()[i] << ") =  " ;
897       std::cout << mat.SparseCoordinate->value_data()[i] << std::endl;
898     }
899   }
900   else if(_num == Siconos::BANDED)
901     std::cout << *mat.Banded << std::endl;
902   else if(_num == Siconos::ZERO)
903     std::cout << *mat.Zero << std::endl;
904   else if(_num == Siconos::IDENTITY)
905     std::cout << *mat.Identity << std::endl;
906 }
907 
908 
909 
910 //=====================
911 // convert to a string
912 //=====================
913 
toString() const914 std::string SimpleMatrix::toString() const
915 {
916   return ::toString(*this);
917 }
918 
919 //=====================
920 // convert to an ostream
921 //=====================
922 
operator <<(std::ostream & os,const SimpleMatrix & sm)923 std::ostream& operator<<(std::ostream& os, const SimpleMatrix& sm)
924 {
925   if(sm._num == Siconos::DENSE)
926     os << *sm.mat.Dense;
927   else if(sm._num == Siconos::TRIANGULAR)
928     os << *sm.mat.Triang;
929   else if(sm._num == Siconos::SYMMETRIC)
930     os << *sm.mat.Sym;
931   else if(sm._num == Siconos::SPARSE)
932     os << *sm.mat.Sparse;
933   else if(sm._num == Siconos::BANDED)
934     os << *sm.mat.Banded;
935   else if(sm._num == Siconos::ZERO)
936     os << *sm.mat.Zero;
937   else if(sm._num == Siconos::IDENTITY)
938     os << *sm.mat.Identity;
939   return os;
940 }
941 
942 
assign(const SimpleMatrix & smat)943 void SimpleMatrix::assign(const SimpleMatrix &smat)
944 {
945 
946   switch(_num)
947   {
948   case Siconos::SPARSE:
949   {
950 
951 
952     switch(smat.num())
953     {
954     case Siconos::SPARSE:
955     {
956       mat.Sparse->assign(smat.getSparse());
957       break;
958     }
959     default:
960     {
961     }
962 
963     }
964   }
965   default:
966   {
967      THROW_EXCEPTION("do not know how to assign for the given storage type ");
968   }
969   }
970 }
971 
972 // void prod(const SiconosMatrix& A, const BlockVector& x, SiconosVector& y, bool init)
973 // {
974 //   assert(!(A.isPLUFactorizedInPlace()) && "A is PLUFactorizedInPlace in prod !!");
975 //   if(init)
976 //     y.zero();
977 //   unsigned int startRow = 0;
978 //   unsigned int startCol = 0;
979 //   // In private_addprod, the sum of all blocks of x, x[i], is computed: y = Sum_i (subA x[i]), with subA a submatrix of A,
980 //   // starting from position startRow in rows and startCol in columns.
981 //   // private_prod takes also into account the fact that each block of x can also be a block.
982 //   VectorOfVectors::const_iterator it;
983 //   for(it = x.begin(); it != x.end(); ++it)
984 //   {
985 //     private_addprod(A, startRow, startCol, **it, y);
986 //     startCol += (*it)->size();
987 //   }
988 // }
989 
990 
991 
992 // void private_addprod(const SiconosMatrix& A, unsigned int startRow, unsigned int startCol, const BlockVector& x, SiconosVector& y)
993 // {
994 //   assert(!(A.isPLUFactorizedInPlace()) && "A is PLUFactorizedInPlace in prod !!");
995 //   assert(!A.isBlock() && "private_addprod(A,start,x,y) error: not yet implemented for block matrix.");
996 //   VectorOfVectors::const_iterator it;
997 //   unsigned int startColBis = startCol;
998 //   for(it = x.begin(); it != x.end(); ++it)
999 //   {
1000 //     private_addprod(A, startRow, startColBis, **it, y);
1001 //     startColBis += (*it)->size();
1002 //   }
1003 
1004 // }
1005 
1006 // // x block, y siconos
1007 // void private_prod(const SiconosMatrix& A, unsigned int startRow, const BlockVector& x, SiconosVector& y, bool init)
1008 // {
1009 //   assert(!(A.isPLUFactorizedInPlace()) && "A is PLUFactorizedInPlace in prod !!");
1010 //   // Computes y = subA *x (or += if init = false), subA being a sub-matrix of A, between el. of index (row) startRow and startRow + sizeY
1011 //   if(init)  // y = subA * x , else y += subA * x
1012 //     y.zero();
1013 //   private_addprod(A, startRow, 0, x, y);
1014 // }
1015 
1016 // // x and y blocks
1017 // void private_prod(SPC::SiconosMatrix A, const unsigned int startRow, SPC::BlockVector x, SP::BlockVector y, bool init)
1018 // {
1019 //   assert(!(A->isPLUFactorizedInPlace()) && "A is PLUFactorizedInPlace in prod !!");
1020 
1021 //   unsigned int row = startRow;
1022 //   VectorOfVectors::const_iterator it;
1023 //   for(it = y->begin(); it != y->end(); ++it)
1024 //   {
1025 //     private_prod(*A, row, *x, **it, init);
1026 //     row += (*it)->size();
1027 //   }
1028 // }
1029 
1030 // // x and y blocks
1031 // void private_prod(SPC::SiconosMatrix A, const unsigned int startRow, SPC::SiconosVector x, SP::BlockVector y, bool init)
1032 // {
1033 //   assert(!(A->isPLUFactorizedInPlace()) && "A is PLUFactorizedInPlace in prod !!");
1034 
1035 //   unsigned int row = startRow;
1036 //   VectorOfVectors::const_iterator it;
1037 //   for(it = y->begin(); it != y->end(); ++it)
1038 //   {
1039 //     private_prod(*A, row, *x, **it, init);
1040 //     row += (*it)->size();
1041 //   }
1042 // }
1043 
1044 // void private_addprod(SPC::BlockVector x, SPC::SiconosMatrix A, unsigned int startRow, unsigned int startCol, SP::SiconosVector y)
1045 // {
1046 //   assert(!(A->isPLUFactorizedInPlace()) && "A is PLUFactorizedInPlace in prod !!");
1047 //   VectorOfVectors::const_iterator it;
1048 //   unsigned int startColBis = startCol;
1049 //   for(it = x->begin(); it != x->end(); ++it)
1050 //   {
1051 //     private_addprod((*it), A, startRow, startColBis, y);
1052 //     startColBis += (*it)->size();
1053 //   }
1054 
1055 // }
1056 
1057 // void private_prod(SPC::SiconosVector x, SPC::SiconosMatrix A, unsigned int startCol, SP::BlockVector  y, bool init)
1058 // {
1059 //   assert(!(A->isPLUFactorizedInPlace()) && "A is PLUFactorizedInPlace in prod !!");
1060 
1061 //   unsigned int col = startCol;
1062 //   VectorOfVectors::const_iterator it;
1063 //   for(it = y->begin(); it != y->end(); ++it)
1064 //   {
1065 //     private_prod(x, A, col, *it, init);
1066 //     col += (*it)->size();
1067 //   }
1068 // }
1069 
1070 // void private_prod(SPC::BlockVector x, SPC::SiconosMatrix A, unsigned int startCol, SP::SiconosVector  y, bool init)
1071 // {
1072 //   assert(!(A->isPLUFactorizedInPlace()) && "A is PLUFactorizedInPlace in prod !!");
1073 
1074 //   // Computes y = subA *x (or += if init = false), subA being a sub-matrix of trans(A), between el. of A of index (col) startCol and startCol + sizeY
1075 //   if(init)  // y = subA * x , else y += subA * x
1076 //     y->zero();
1077 //   private_addprod(x, A, startCol, 0, y);
1078 
1079 // }
1080 
1081 // void private_prod(SPC::BlockVector x, SPC::SiconosMatrix A, unsigned int startCol, SP::BlockVector  y, bool init)
1082 // {
1083 //   assert(!(A->isPLUFactorizedInPlace()) && "A is PLUFactorizedInPlace in prod !!");
1084 
1085 //   unsigned int col = startCol;
1086 //   VectorOfVectors::const_iterator it;
1087 //   for(it = y->begin(); it != y->end(); ++it)
1088 //   {
1089 //     private_prod(x, A, col, *it, init);
1090 //     col += (*it)->size();
1091 //   }
1092 // }
1093 
1094 // void private_addprod(double a, SPC::SiconosMatrix A, unsigned int startRow, unsigned int startCol, SPC::SiconosVector x, SP::SiconosVector y)
1095 // {
1096 //   assert(!(A->isPLUFactorizedInPlace()) && "A is PLUFactorizedInPlace in prod !!");
1097 
1098 //   if(A->isBlock())
1099 //      THROW_EXCEPTION("not yet implemented for block matrix.");
1100 
1101 //   // we take a submatrix subA of A, starting from row startRow to row (startRow+sizeY) and between columns startCol and (startCol+sizeX).
1102 //   // Then computation of y = subA*x + y.
1103 //   Siconos::UBLAS_TYPE numA = A->num();
1104 //   Siconos::UBLAS_TYPE numY = y->num();
1105 //   Siconos::UBLAS_TYPE numX = x->num();
1106 //   unsigned int sizeX = x->size();
1107 //   unsigned int sizeY = y->size();
1108 
1109 //   if(numX != numY)
1110 //      THROW_EXCEPTION("not yet implemented for x and y of different types.");
1111 
1112 //   if(numY == 1 && numX == 1)
1113 //   {
1114 
1115 //     assert(y->dense() != x->dense());
1116 
1117 //     if(numA == 1)
1118 //       noalias(*y->dense()) += a * prod(ublas::subrange(*A->dense(), startRow, startRow + sizeY, startCol, startCol + sizeX), *x->dense());
1119 //     else if(numA == 2)
1120 //       noalias(*y->dense()) += a * prod(ublas::subrange(*A->triang(), startRow, startRow + sizeY, startCol, startCol + sizeX), *x->dense());
1121 //     else if(numA == 3)
1122 //       noalias(*y->dense()) += a * prod(ublas::subrange(*A->sym(), startRow, startRow + sizeY, startCol, startCol + sizeX), *x->dense());
1123 //     else if(numA == 4)
1124 //       noalias(*y->dense()) += a * prod(ublas::subrange(*A->sparse(), startRow, startRow + sizeY, startCol, startCol + sizeX), *x->dense());
1125 //     else //if(numA==5)
1126 //       noalias(*y->dense()) += a * prod(ublas::subrange(*A->banded(), startRow, startRow + sizeY, startCol, startCol + sizeX), *x->dense());
1127 //   }
1128 //   else // x and y sparse
1129 //   {
1130 //     if(numA == 4)
1131 //       *y->sparse() += a * prod(ublas::subrange(*A->sparse(), startRow, startRow + sizeY, startCol, startCol + sizeX), *x->sparse());
1132 //     else
1133 //        THROW_EXCEPTION("not yet implemented for x, y  sparse and A not sparse.");
1134 //   }
1135 
1136 // }
1137 
1138 // void private_prod(double a, SPC::SiconosMatrix A, unsigned int startRow, SPC::SiconosVector x, SP::SiconosVector  y, bool init)
1139 // {
1140 //   assert(!(A->isPLUFactorizedInPlace()) && "A is PLUFactorizedInPlace in prod !!");
1141 
1142 
1143 //   // Computes y = subA *x (or += if init = false), subA being a sub-matrix of A, between el. of index (row) startRow and startRow + sizeY
1144 
1145 //   if(init)  // y = subA * x , else y += subA * x
1146 //     y->zero();
1147 //   private_addprod(a, A, startRow, 0, x, y);
1148 
1149 // }
1150 
copyData(double * data) const1151 unsigned SimpleMatrix::copyData(double* data) const
1152 {
1153   assert((_num == Siconos::DENSE) && "SiconosMatrix::copyData : forbidden: the current matrix is not dense.");
1154 
1155   unsigned size = mat.Dense->size1() * mat.Dense->size2();
1156   siconosBindings::detail::copy(size, getArray(), 1, data, 1);
1157   return size;
1158 }
1159