1 /*
2 XLiFE++ is an extended library of finite elements written in C++
3     Copyright (C) 2014  Lunéville, Eric; Kielbasiewicz, Nicolas; Lafranche, Yvon; Nguyen, Manh-Ha; Chambeyron, Colin
4 
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13     You should have received a copy of the GNU General Public License
14     along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 /*!
18   \file MatrixStorage.cpp
19   \authors D. Martin, E. Lunéville, M.-H. Nguyen, N. Kielbasiewicz
20   \since 21 jun 2011
21   \date 21 feb 2013
22 
23   \brief Implementation of xlifepp::MatrixStorage class and functionnalities
24 */
25 
26 #include "MatrixStorage.hpp"
27 #include "denseStorage/ColDenseStorage.hpp"
28 #include "denseStorage/RowDenseStorage.hpp"
29 #include "denseStorage/DualDenseStorage.hpp"
30 #include "denseStorage/SymDenseStorage.hpp"
31 #include "csStorage/ColCsStorage.hpp"
32 #include "csStorage/RowCsStorage.hpp"
33 #include "csStorage/DualCsStorage.hpp"
34 #include "csStorage/SymCsStorage.hpp"
35 #include "skylineStorage/SkylineStorage.hpp"
36 #include "skylineStorage/DualSkylineStorage.hpp"
37 #include "skylineStorage/SymSkylineStorage.hpp"
38 
39 namespace xlifepp
40 {
41 /*---------------------------------------------------------------------------------------
42   Constructors, destructor
43   ---------------------------------------------------------------------------------------*/
44 // default constructor
MatrixStorage(string_t id)45 MatrixStorage::MatrixStorage(string_t id)
46   : storageType_(_noStorage), accessType_(_noAccess), nbRows_(0), nbCols_(0), nbObjectsSharingThis_(0), stringId(id) {}
47 
48 // construct MatrixStorage with no size
MatrixStorage(StorageType st,AccessType at,string_t id)49 MatrixStorage::MatrixStorage(StorageType st, AccessType at, string_t id)
50   : storageType_(st), accessType_(at), nbRows_(0), nbCols_(0), nbObjectsSharingThis_(0), stringId(id)
51 {
52   theMatrixStorages.push_back(this);
53 }
54 
55 // construct MatrixStorage with size
MatrixStorage(StorageType st,AccessType at,number_t nr,number_t nc,string_t id)56 MatrixStorage::MatrixStorage(StorageType st, AccessType at, number_t nr, number_t nc, string_t id)
57   : storageType_(st), accessType_(at), nbRows_(nr), nbCols_(nc), nbObjectsSharingThis_(0), stringId(id)
58 {
59   if(trackingObjects) theMatrixStorages.push_back(this);
60 }
61 
62 //copy constructor, NOTE : nbObjectsSharingThis_ is reset to 0
MatrixStorage(const MatrixStorage & ms)63 MatrixStorage::MatrixStorage(const MatrixStorage& ms)
64 {
65   storageType_=ms.storageType_;
66   accessType_=ms.accessType_;
67   nbRows_=ms.nbRows_;
68   nbCols_=ms.nbCols_;
69   nbObjectsSharingThis_=0;
70 }
71 
72 // create matrix storage from indices (vector of column indices for each row)
73 // like a constructor
74 // if storage already exists we force its creation by changing id
createMatrixStorage(StorageType st,AccessType at,number_t nbr,number_t nbc,const std::vector<std::vector<number_t>> & indices,const string_t & idu)75 MatrixStorage* createMatrixStorage(StorageType st, AccessType at, number_t nbr, number_t nbc,
76                                    const std::vector<std::vector<number_t> >& indices, const string_t & idu)
77 {
78   string_t id=idu;
79   number_t k=0;
80   MatrixStorage* ms= findMatrixStorage(id,st,at);
81   while(ms!=0)
82     {
83       id=idu+"_"+tostring(k);
84       ms= findMatrixStorage(id,st,at);
85       k++;
86     }
87   switch(st)
88     {
89       case _cs :
90         switch(at)
91           {
92             case _row  : return new RowCsStorage(nbr, nbc, indices, id);
93             case _col  :
94               {
95                 std::vector<std::vector<number_t> > rowindices(nbc);
96                 std::vector<std::vector<number_t> >::const_iterator itr=indices.begin();
97                 std::vector<number_t>::const_iterator itc;
98                 number_t r=1;
99                 for(; itr!=indices.end(); itr++, r++)
100                   for(itc=itr->begin(); itc!= itr->end(); itc++)
101                     rowindices[*itc - 1].push_back(r);
102                 return new ColCsStorage(nbr, nbc, rowindices, id);
103               }
104             case _dual : return new DualCsStorage(nbr, nbc, indices, id);
105             case _sym  : return new SymCsStorage(nbr, indices,_all, id);   //nbr=nbc if symmetric
106             default :
107               where("createMatrixStorage");
108               error("storage_bad_access",words("access type",at),words("storage type",st));
109           }
110         break;
111       case _skyline :
112         switch(at)
113           {
114             case _dual : return new DualSkylineStorage(nbr, nbc, indices, id);
115             case _sym  : return new SymSkylineStorage(nbr, indices, id); //nbr=nbc if symmetric
116             default :
117               where("createMatrixStorage");
118               error("storage_bad_access",words("access type",at),words("storage type",st));
119           }
120       case _dense :
121         switch(at)
122           {
123             case _row  : return new RowDenseStorage(nbr, nbc, id);
124             case _col  : return new ColDenseStorage(nbr, nbc, id);
125             case _dual : return new DualDenseStorage(nbr, nbc, id);
126             case _sym  : return new SymDenseStorage(nbr, id); //nbr=nbc if symmetric
127             default :
128               where("createMatrixStorage");
129               error("storage_bad_access",words("access type",at),words("storage type",st));
130           }
131       default :
132         where("createMatrixStorage");
133         error("storage_not_handled",words("storage type",st),words("storage type",at));
134     }
135   return 0;
136 }
137 
138 // construct a storage from submatrix of current storage, storage type is not changed
extract(const std::vector<number_t> & rowIndex,const std::vector<number_t> & colIndex,const string_t & ids)139 MatrixStorage* MatrixStorage::extract(const std::vector<number_t>& rowIndex, const std::vector<number_t>& colIndex, const string_t& ids)
140 {
141   number_t nbr=rowIndex.size(), nbc = colIndex.size();
142   if (nbr==0 || nbr>nbRows_)
143   {
144     where("MatrixStorage::extract(...)");
145     error("dim_not_in_range", 1, nbRows_);
146   }
147   if (nbc==0 || nbc>nbCols_)
148   {
149     where("MatrixStorage::extract(...)");
150     error("dim_not_in_range", 1, nbCols_);
151   }
152   string_t id= ids;
153   if(id=="") id=stringId+"_submatrix";
154 
155   if(storageType_==_dense) //dense storage
156     {
157       switch(accessType_)
158         {
159           case _row  : return new RowDenseStorage(nbr, nbc, id);
160           case _col  : return new ColDenseStorage(nbr, nbc, id);
161           case _dual : return new DualDenseStorage(nbr, nbc, id);
162           case _sym  : return new SymDenseStorage(nbr, id); //nbr=nbc if symmetric
163           default :
164             where("MatrixStorage constructor");
165             error("storage_bad_access",words("access type",accessType_),words("storage type",storageType_));
166         }
167     }
168 
169   //extract indices array
170   std::vector<number_t> revCol(nbCols_,0);  //reverse colIndex
171   std::vector<number_t>::const_iterator itn=colIndex.begin();
172   for(number_t i=1; i<=nbc; ++i, ++itn) revCol[*itn]=i;
173   std::vector<std::vector<number_t> > indices(nbr);
174   itn=rowIndex.begin();
175   for(number_t r=0; r<nbr; r++, ++itn)
176     {
177       std::vector<std::pair<number_t, number_t> > rowr=getRow(_noSymmetry, *itn);
178       std::vector<std::pair<number_t, number_t> > ::iterator itp=rowr.begin();
179       number_t s=0;
180       for(; itp!=rowr.end(); ++itp)
181         if(revCol[itp->first]>0) s++;
182       if(s>0)
183         {
184           std::vector<number_t>& indr=indices[r];
185           indr.reserve(s);
186           for(; itp!=rowr.end(); ++itp)
187             {
188               number_t c=revCol[itp->first];
189               if(c>0) indr.push_back(c);
190             }
191         }
192     }
193   //general construction for cs or skyline, could be improved for skyline
194   return createMatrixStorage(storageType_, accessType_, nbr, nbc, indices, id);
195 }
196 
197 // destruct MatrixStorage, error if storage is shared by other matrices
~MatrixStorage()198 MatrixStorage::~MatrixStorage()
199 {
200   if(nbObjectsSharingThis_ > 0)
201     {
202       error("storage_baddelete", name(), nbObjectsSharingThis_);
203     }
204   // remove pointer of current object from vector of MatrixStorage*
205   std::vector<MatrixStorage*>::iterator it(find(theMatrixStorages.begin(), theMatrixStorages.end(), this));
206   if(it != theMatrixStorages.end())
207     {
208       theMatrixStorages.erase(it);
209     }
210 }
211 
212 // delete all MatrixStorage objects
clearGlobalVector()213 void MatrixStorage::clearGlobalVector()
214 {
215   while(MatrixStorage::theMatrixStorages.size() > 0)
216     {
217       MatrixStorage* ms = MatrixStorage::theMatrixStorages[0];
218       if(ms!=0)
219         {
220           if(ms->nbObjectsSharingThis_>0)  //force deletion
221             {
222               warning("storage_hasardousdelete", ms->name(), ms->nbObjectsSharingThis_);
223               ms->nbObjectsSharingThis_=0;
224             }
225           delete MatrixStorage::theMatrixStorages[0];
226         }
227     }
228 }
229 
230 //--------------------------------------------------------------------------
231 //  Error handlers
232 //--------------------------------------------------------------------------
noFactorization(const string_t & f) const233 void MatrixStorage::noFactorization(const string_t& f) const
234 {
235   theMessageData << f + " " + name() + " no factorization";
236   error("largematrix_nofactorization", theMessageData);
237 }
238 
noSolver(const string_t & f) const239 void MatrixStorage::noSolver(const string_t& f) const
240 {
241   theMessageData << f + " " + name() + " no solver";
242   error("largematrix_nosolver", theMessageData);
243 }
244 
isSingular(const string_t & f,const number_t r) const245 void MatrixStorage::isSingular(const string_t& f, const number_t r) const
246 {
247   theMessageData << f + " " + name() + " is singular" << r;
248   error("largematrix_singular", theMessageData);
249 }
250 
251 /*--------------------------------------------------------------------------------
252    "visualization" to output stream of the structure of matrix storage
253    using virtual function pos(i,j), pos(i,j) =0 means that (i,j) is outside the storage
254    part must be equal to _all, _lower or _upper
255 --------------------------------------------------------------------------------*/
visual(std::ostream & os) const256 void MatrixStorage::visual(std::ostream& os) const
257 {
258   if(theVerboseLevel > 0)
259     {
260       printHeader(os);
261     }
262   if(theVerboseLevel < 2)
263     {
264       return;
265     }
266   number_t rmax = std::min(nbRows_, number_t(10 * theVerboseLevel)),
267            cmax = std::min(nbCols_, number_t(10 * theVerboseLevel + 5));
268   os << std::setw(11);
269   for(number_t j = 1; j <= cmax; j++)
270     {
271       os << j % 10;    //col numbers
272     }
273   for(number_t r = 1; r <= rmax; r++)
274     {
275       string_t str(cmax, '.');
276       for(number_t c = 1; c <= cmax; c++)
277         {
278           number_t p = pos(r, c);
279           if(p != 0 && (accessType_ != _sym || (accessType_ == _sym && r > c)))
280             {
281               str.at(c - 1) = 'x';
282             }
283           if(r == c)
284             {
285               str.at(c - 1) = 'd';
286             }
287         }
288       os << std::endl << std::setw(8) << r << "  " << str;
289       if(cmax < nbCols_)
290         {
291           os << " ...(continued)";
292         }
293     }
294   os << std::endl << std::setw(11);
295   for(number_t j = 1; j <= cmax; j++)
296     {
297       os << j % 10;
298     }
299   os << std::endl;
300 }
301 
302 /*--------------------------------------------------------------------------------
303    I/O utilities
304 --------------------------------------------------------------------------------*/
printHeader(std::ostream & os) const305 void MatrixStorage::printHeader(std::ostream& os) const
306 {
307   os << words("matrix storage") << " :" << name() << ", " << words("size") << " = " << size()
308      << ", id = " << stringId
309      << ", " << nbRows_ << " " << words("rows") << ", " << nbCols_ << " " << words("columns")
310      << " (" << words("shared by") << " " << nbObjectsSharingThis_ << " " << words("objects") << ").\n";
311 }
312 
print(std::ostream & os) const313 void MatrixStorage::print(std::ostream& os) const
314 {
315   printHeader(os);
316   //see child if something to write
317 }
318 
operator <<(std::ostream & os,const MatrixStorage & ms)319 std::ostream& operator<<(std::ostream& os, const MatrixStorage& ms)
320 {
321   ms.print(os);
322   return os;
323 }
324 
printCoo(std::ostream & os,const real_t & v,number_t i,number_t j,real_t tol)325 void printCoo(std::ostream& os, const real_t& v, number_t i, number_t j, real_t tol)
326 {
327   if(std::abs(v) > tol)
328     {
329       os << i << " " << j << " " << v << std::endl;
330     }
331 }
332 
printCoo(std::ostream & os,const complex_t & v,number_t i,number_t j,real_t tol)333 void printCoo(std::ostream& os, const complex_t& v, number_t i, number_t j, real_t tol)
334 {
335   if(std::abs(v) > tol)
336     {
337       os << i << " " << j << " " << v.real() << " " << v.imag() << std::endl;
338     }
339 }
340 
printDense(std::ostream & os,const real_t & v,number_t k)341 void printDense(std::ostream& os, const real_t& v, number_t k)
342 {
343   os << v << " ";
344 }
345 
printDense(std::ostream & os,const complex_t & v,number_t k)346 void printDense(std::ostream& os, const complex_t& v, number_t k)
347 {
348   os << v.real() << " " << v.imag() << "   ";
349 }
350 
readItem(std::istream & ifs,complex_t & v,bool realAsCmplx)351 void readItem(std::istream& ifs, complex_t& v, bool realAsCmplx)
352 {
353   real_t r1 = 0.;
354   real_t r2 = 0.;
355   if(realAsCmplx)
356     {
357       ifs >> r1;    //cast real to complex
358     }
359   else
360     {
361       ifs >> r1 >> r2;
362     }
363   v = complex_t(r1, r2);
364 }
365 
readItem(std::istream & ifs,real_t & v,bool realAsCmplx)366 void readItem(std::istream& ifs, real_t& v, bool realAsCmplx)
367 {
368   ifs >> v;
369 }
370 
numberOfRows(const real_t & v)371 number_t numberOfRows(const real_t& v)
372 {
373   return 1;
374 }
numberOfRows(const complex_t & v)375 number_t numberOfRows(const complex_t& v)
376 {
377   return 1;
378 }
numberOfCols(const real_t & v)379 number_t numberOfCols(const real_t& v)
380 {
381   return 1;
382 }
numberOfCols(const complex_t & v)383 number_t numberOfCols(const complex_t& v)
384 {
385   return 1;
386 }
387 
388 // find matrix storage in vector theMatrixStorages of class MatrixStorage
findMatrixStorage(const string_t & id,StorageType st,AccessType at)389 MatrixStorage* findMatrixStorage(const string_t& id, StorageType st, AccessType at)
390 {
391   for(std::vector<MatrixStorage*>::iterator it = MatrixStorage::theMatrixStorages.begin(); it != MatrixStorage::theMatrixStorages.end(); it++)
392     {
393       if(id == (*it)->stringId && (*it)->storageType()==st && (*it)->accessType()==at)
394         {
395           return *it;
396         }
397     }
398   return 0;
399 }
400 
printMatrixStorages(std::ostream & out)401 void printMatrixStorages(std::ostream& out)
402 {
403   for(std::vector<MatrixStorage*>::iterator it = MatrixStorage::theMatrixStorages.begin(); it != MatrixStorage::theMatrixStorages.end(); it++)
404     {
405       (*it)->printHeader(out);
406     }
407 }
408 
409 //! get (row indices, adress) of col c in set [r1,r2], generic algorithm, see child for better algorithms
getCol(SymType s,number_t c,number_t r1,number_t r2) const410 std::vector<std::pair<number_t, number_t> > MatrixStorage::getCol(SymType s, number_t c, number_t r1, number_t r2) const
411 {
412   if(accessType_!=_sym) s=_noSymmetry;
413   number_t lr=r2;
414   std::vector<std::pair<number_t, number_t> > rowadrs;
415   if(lr==0) lr=nbRows_;
416   if(lr<r1) return rowadrs;
417   number_t nbr=lr-r1+1;
418   rowadrs.resize(nbr);
419   std::vector<number_t> cols(1,c), rows(nbr,1);
420   std::vector<number_t>::iterator itr=rows.begin();
421   for(number_t r=r1; r<=lr; r++,itr++) *itr=r;
422   std::vector<number_t> adrs;
423   positions(rows,cols,adrs,false,s);
424   std::vector<std::pair<number_t, number_t> >::iterator itra=rowadrs.begin();
425   itr=adrs.begin();
426   number_t k=0;
427   for(number_t r=r1; r<=lr; r++,itr++)
428     if(*itr!=0)
429       {
430         *itra=std::make_pair(r,*itr);
431         itra++; k++;
432       }
433   rowadrs.resize(k);
434   return rowadrs;
435 }
436 
getRow(SymType s,number_t r,number_t c1,number_t c2) const437 std::vector<std::pair<number_t, number_t> > MatrixStorage::getRow(SymType s, number_t r, number_t c1, number_t c2) const
438 {
439   if(accessType_!=_sym) s=_noSymmetry;
440   number_t lc=c2;
441   std::vector<std::pair<number_t, number_t> > coladrs;
442   if(lc==0) lc=nbCols_;
443   if(lc<c1) return coladrs;
444   number_t nbc=lc-c1+1;
445   coladrs.resize(nbc);
446   std::vector<number_t> rows(1,r), cols(nbc,1);
447   std::vector<number_t>::iterator itc=cols.begin();
448   for(number_t c=c1; c<=lc; c++,itc++) *itc=c;
449   std::vector<number_t> adrs;
450   positions(rows,cols,adrs,false,s);
451   std::vector<std::pair<number_t, number_t> >::iterator itca=coladrs.begin();
452   itc=adrs.begin();
453   number_t k=0;
454   for(number_t c=c1; c<=lc; c++,itc++,itca++)
455     if(*itc!=0)
456       {
457         *itca=std::make_pair(c,*itc);
458         k++;
459       }
460   coladrs.resize(k);
461   return coladrs;
462 }
463 
464 
465 //! get col indices of row r in set [c1,c2], generic algorithm using position, see children for better algorithms
getCols(number_t r,number_t c1,number_t c2) const466 std::set<number_t> MatrixStorage::getCols(number_t r, number_t c1, number_t c2) const
467 {
468   number_t lc=c2;
469   std::set<number_t> colset;
470   if(lc==0) lc=nbCols_;
471   if(lc<c1) return colset;
472   number_t nbc=lc-c1+1;
473   std::vector<number_t> rows(1,r), cols(nbc,1);
474   std::vector<number_t>::iterator itc=cols.begin();
475   for(number_t c=c1; c<=lc; c++,itc++) *itc=c;
476   std::vector<number_t> adrs;
477   positions(rows,cols,adrs,false);  //retry adress
478   itc=adrs.begin();
479   for(number_t c=c1; c<=lc; c++, itc++)
480     if(*itc!=0) colset.insert(c);
481   return colset;
482 }
483 
484 //! get row indices of col c in set [r1,r2], generic algorithm using position, see children for better algorithms
getRows(number_t c,number_t r1,number_t r2) const485 std::set<number_t> MatrixStorage::getRows(number_t c, number_t r1, number_t r2) const
486 {
487   number_t lr=r2;
488   std::set<number_t> rowset;
489   if(lr==0) lr=nbRows_;
490   if(lr<r1) return rowset;
491   number_t nbr=lr-r1+1;
492   std::vector<number_t> cols(1,c), rows(nbr,1);
493   std::vector<number_t>::iterator itr=rows.begin();
494   for(number_t r=r1; r<=lr; r++,itr++) *itr=r;
495   std::vector<number_t> adrs;
496   positions(rows,cols,adrs,false);  //retry adress
497   itr=adrs.begin();
498   for(number_t r=r1; r<=lr; r++, itr++)
499     if(*itr!=0) rowset.insert(r);
500   return rowset;
501 }
502 
503 //! get diagonal adresses, algorithm using position in non sym/dual storage cases
getDiag() const504 std::vector<number_t> MatrixStorage::getDiag() const
505 {
506   if(accessType_==_sym || accessType_==_dual)       //diagonal is stored at the beginning
507     return trivialNumbering<number_t>(1,diagonalSize());
508   //other cases
509   number_t nd=diagonalSize();
510   std::vector<number_t> diag(nd);
511   std::vector<number_t>::iterator itd=diag.begin();
512   for(number_t i=1; i<=nd; i++, itd++) *itd=pos(i,i);
513   return diag;
514 }
515 
516 /*!
517   get col indices of row r in set [c1,c2], generic algorithm using position, see children for better algorithms
518   update a vector of numbers with no reallocation, size it before. nbcol is the number of loaded col indices
519 */
getColsV(std::vector<number_t> & colV,number_t & nbcol,number_t r,number_t c1,number_t c2) const520 void MatrixStorage::getColsV(std::vector<number_t>& colV, number_t& nbcol, number_t r, number_t c1, number_t c2) const
521 {
522   number_t lc=c2;
523   if(lc==0) lc=nbCols_;
524   if(lc<c1) {nbcol=0; return;};
525   number_t nbc=lc-c1+1;
526   std::vector<number_t> rows(1,r), cols(nbc,1);
527   std::vector<number_t>::iterator itc=cols.begin();
528   for(number_t c=c1; c<=lc; c++,itc++) *itc=c;
529   std::vector<number_t> adrs;
530   positions(rows,cols,adrs,false);  //retry adress
531   itc=adrs.begin();
532   std::vector<number_t>::iterator itV=colV.begin();
533   for(number_t c=c1; c<=lc; c++, itc++)
534     if(*itc!=0) {*itV=c; ++itV; nbcol++;}
535 }
536 
537 /*!
538   get col indices of row r in set [c1,c2], generic algorithm using position, see children for better algorithms
539   update a vector of numbers with no reallocation, size it before. nbrow is the number of loaded row indices
540 */
getRowsV(std::vector<number_t> & rowV,number_t & nbrow,number_t c,number_t r1,number_t r2) const541 void MatrixStorage::getRowsV(std::vector<number_t>& rowV, number_t& nbrow, number_t c, number_t r1, number_t r2) const
542 {
543   number_t lr=r2;
544   if(lr==0) lr=nbCols_;
545   nbrow=0;
546   if(lr<r1) return;
547   number_t nbr=lr-r1+1;
548   std::vector<number_t> rows(1,nbr), cols(1,c);
549   std::vector<number_t>::iterator itr=rows.begin();
550   for(number_t r=r1; r<=lr; r++,itr++) *itr=r;
551   std::vector<number_t> adrs;
552   positions(rows,cols,adrs,false);  //retry adress
553   itr=adrs.begin();
554   std::vector<number_t>::iterator itV=rowV.begin();
555   for(number_t r=r1; r<=lr; r++, itr++)
556     if(*itr!=0) {*itV=r; ++itV; nbrow++;}
557 }
558 
559 /*! add storage in current storage with row/col mapping (generic algorithm, use addRow, addCol, getRow and getCol of children)
560     ms is the matrix storage to add to current storage
561     rowmap(r) gives the row number in current storage of row r of MatrixStorage ms (start index : 1)
562     colmap(c) gives the col number in current storage of col c of MatrixStorage ms (start index : 1)
563     if rowmap (resp. colmap) is void, it means that row numberings are the same for the both storages
564     !!! warning : ms storage has to be smaller than the current storage
565 */
add(const MatrixStorage & ms,const std::vector<number_t> & rowmap,const std::vector<number_t> & colmap)566 void MatrixStorage::add(const MatrixStorage& ms, const std::vector<number_t>& rowmap, const std::vector<number_t>& colmap)
567 {
568   if(storageType_==_dense) return;   //nothing to do
569 
570   std::vector<number_t> rowmap_=rowmap, colmap_=colmap;
571   std::vector<number_t>::iterator it;
572   if(rowmap_.size()==0)
573     {
574       rowmap_.resize(nbRows_);
575       number_t k=1;
576       for(it=rowmap_.begin(); it!=rowmap_.end(); it++, k++) *it=k;
577     }
578   if(colmap_.size()==0)
579     {
580       colmap_.resize(nbCols_);
581       number_t k=1;
582       for(it=colmap_.begin(); it!=colmap_.end(); it++, k++) *it=k;
583     }
584   it=std::max_element(rowmap_.begin(),rowmap_.end());
585   if(*it>nbRows_)
586     {
587       where("MatrixStorage::add");
588       error("storage_numbering_too_large",words("row"),"ms");
589     }
590   it=std::max_element(colmap_.begin(),colmap_.end());
591   if(*it>nbCols_)
592     {
593       where("MatrixStorage::add");
594       error("storage_numbering_too_large",words("column"),"ms");
595     }
596 
597   if(accessType_==_row || accessType_==_dual || accessType_==_sym) //row algorithm
598     {
599       MatrixPart mp=_all;
600       if(accessType_!=_row) mp=_lower;
601       number_t k=1, n=ms.nbCols_;
602       for(it=rowmap_.begin(); it!=rowmap_.end(); it++, k++)
603         {
604           //if(accessType_==_dual) n=k;
605           std::set<number_t> cols=ms.getCols(k,1,n);          // retry col indices of row k in ms storage
606           std::set<number_t>::iterator its=cols.begin();
607           std::set<number_t> mapcols;
608           for(; its!=cols.end(); its++) mapcols.insert(colmap_[*its-1]); // apply col numbering map
609           addRow(*it,mapcols,mp);
610         }
611     }
612   if(accessType_==_col || accessType_==_dual) //col algorithm
613     {
614       MatrixPart mp=_all;
615       if(accessType_!=_col) mp=_upper;
616       number_t k=1,  n=ms.nbRows_;
617       for(it=colmap_.begin(); it!=colmap_.end(); it++, k++)
618         {
619           //if(accessType_==_dual) n=k;
620           std::set<number_t> rows=ms.getRows(k,1,n);           // retry row indices of col k in ms storage
621           std::set<number_t>::iterator its=rows.begin();
622           std::set<number_t> maprows;
623           for(; its!=rows.end(); its++) maprows.insert(rowmap_[*its-1]);  // apply col numbering map
624           addCol(*it,maprows,mp);
625         }
626     }
627   return;
628 }
629 
630 /*! create scalar col indices for each row from current storage and submatrix sizes
631     this is a generic tool used by toScalar() member function of storage children
632     it is based on getRow function (virtual function)
633     nbr : row size of submatrix
634     nbc : col size of submatrix
635     if nbc=nbr=1 (scalar case) return the same col indices of current storage
636         See children for optimized algorithms
637 */
scalarColIndices(dimen_t nbr,dimen_t nbc)638 std::vector<std::vector<number_t> > MatrixStorage::scalarColIndices(dimen_t nbr, dimen_t nbc)
639 {
640   std::vector<std::vector<number_t> > cols(nbr*nbRows_);
641   std::vector<std::vector<number_t> >::iterator itcs=cols.begin();
642   for(number_t r=0; r<nbRows_; r++)
643     {
644       std::vector<std::pair<number_t, number_t> > row = getRow(_noSymmetry,r+1);
645       std::vector<std::pair<number_t, number_t> >::iterator itr;
646       for(dimen_t rr=0; rr<nbr; rr++, itcs++)
647         {
648           itcs->resize(nbc*row.size());
649           std::vector<number_t>::iterator itc=itcs->begin();
650           for(itr=row.begin(); itr!=row.end(); itr++)
651             for(dimen_t cc=0; cc <nbc; cc++, itc++) *itc= nbc*(itr->first-1) + cc + 1;
652         }
653     }
654   return cols;
655 }
656 
657 // Matrix * Matrix (result in row dense storage) - generic algorithm - (see child bor better algorithm)
multMatrixMatrix(const std::vector<real_t> & mA,const MatrixStorage & stB,const std::vector<real_t> & mB,std::vector<real_t> & mR,SymType symA,SymType symB) const658 void MatrixStorage::multMatrixMatrix(const std::vector<real_t>& mA, const MatrixStorage& stB, const std::vector<real_t>& mB, std::vector<real_t>& mR, SymType symA, SymType symB) const
659 {
660   multMatrixMatrixGeneric(mA.begin(), stB, mB.begin(), mR.begin(),symA, symB);
661 }
multMatrixMatrix(const std::vector<real_t> & mA,const MatrixStorage & stB,const std::vector<complex_t> & mB,std::vector<complex_t> & mR,SymType symA,SymType symB) const662 void MatrixStorage::multMatrixMatrix(const std::vector<real_t>& mA, const MatrixStorage& stB, const std::vector<complex_t>& mB, std::vector<complex_t>& mR, SymType symA, SymType symB) const
663 {
664   multMatrixMatrixGeneric(mA.begin(), stB, mB.begin(), mR.begin(),symA,symB);
665 }
multMatrixMatrix(const std::vector<complex_t> & mA,const MatrixStorage & stB,const std::vector<real_t> & mB,std::vector<complex_t> & mR,SymType symA,SymType symB) const666 void MatrixStorage::multMatrixMatrix(const std::vector<complex_t>& mA, const MatrixStorage& stB, const std::vector<real_t>& mB, std::vector<complex_t>& mR, SymType symA, SymType symB) const
667 {
668   multMatrixMatrixGeneric(mA.begin(), stB, mB.begin(), mR.begin(),symA, symB);
669 }
multMatrixMatrix(const std::vector<complex_t> & mA,const MatrixStorage & stB,const std::vector<complex_t> & mB,std::vector<complex_t> & mR,SymType symA,SymType symB) const670 void MatrixStorage::multMatrixMatrix(const std::vector<complex_t>& mA, const MatrixStorage& stB, const std::vector<complex_t>& mB, std::vector<complex_t>& mR, SymType symA, SymType symB) const
671 {
672   multMatrixMatrixGeneric(mA.begin(), stB, mB.begin(), mR.begin(),symA, symB);
673 }
674 
675 //matrix of matrices
multMatrixMatrix(const std::vector<Matrix<real_t>> & mA,const MatrixStorage & stB,const std::vector<Matrix<real_t>> & mB,std::vector<Matrix<real_t>> & mR,SymType symA,SymType symB) const676 void MatrixStorage::multMatrixMatrix(const std::vector<Matrix<real_t> >& mA, const MatrixStorage& stB, const std::vector<Matrix<real_t> >& mB, std::vector<Matrix<real_t> >& mR, SymType symA, SymType symB) const
677 {
678   multMatrixMatrixGeneric(mA.begin(), stB, mB.begin(), mR.begin(),symA, symB);
679 }
multMatrixMatrix(const std::vector<Matrix<real_t>> & mA,const MatrixStorage & stB,const std::vector<Matrix<complex_t>> & mB,std::vector<Matrix<complex_t>> & mR,SymType symA,SymType symB) const680 void MatrixStorage::multMatrixMatrix(const std::vector<Matrix<real_t> >& mA, const MatrixStorage& stB, const std::vector<Matrix<complex_t> >& mB, std::vector<Matrix<complex_t> >& mR, SymType symA, SymType symB) const
681 {
682   multMatrixMatrixGeneric(mA.begin(), stB, mB.begin(), mR.begin(),symA, symB);
683 }
multMatrixMatrix(const std::vector<Matrix<complex_t>> & mA,const MatrixStorage & stB,const std::vector<Matrix<real_t>> & mB,std::vector<Matrix<complex_t>> & mR,SymType symA,SymType symB) const684 void MatrixStorage::multMatrixMatrix(const std::vector<Matrix<complex_t> >& mA, const MatrixStorage& stB, const std::vector<Matrix<real_t> >& mB, std::vector<Matrix<complex_t> >& mR, SymType symA, SymType symB) const
685 {
686   multMatrixMatrixGeneric(mA.begin(), stB, mB.begin(), mR.begin(),symA, symB);
687 }
multMatrixMatrix(const std::vector<Matrix<complex_t>> & mA,const MatrixStorage & stB,const std::vector<Matrix<complex_t>> & mB,std::vector<Matrix<complex_t>> & mR,SymType symA,SymType symB) const688 void MatrixStorage::multMatrixMatrix(const std::vector<Matrix<complex_t> >& mA, const MatrixStorage& stB, const std::vector<Matrix<complex_t> >& mB, std::vector<Matrix<complex_t> >& mR, SymType symA, SymType symB) const
689 {
690   multMatrixMatrixGeneric(mA.begin(), stB, mB.begin(), mR.begin(),symA, symB);
691 }
692 
693 // Matrix * diag Matrix (result in current storage) - generic algorithm - (see child bor better algorithm)
multMatrixDiagMatrix(const std::vector<real_t> & mA,const std::vector<real_t> & vB,std::vector<real_t> & mR) const694 void MatrixStorage::multMatrixDiagMatrix(const std::vector<real_t>& mA, const std::vector<real_t>& vB, std::vector<real_t>& mR) const
695 {
696   multMatrixDiagMatrixGeneric(mA.begin(), vB.begin(), mR.begin());
697 }
multMatrixDiagMatrix(const std::vector<real_t> & mA,const std::vector<complex_t> & vB,std::vector<complex_t> & mR) const698 void MatrixStorage::multMatrixDiagMatrix(const std::vector<real_t>& mA, const std::vector<complex_t>& vB, std::vector<complex_t>& mR) const
699 {
700   multMatrixDiagMatrixGeneric(mA.begin(), vB.begin(), mR.begin());
701 }
multMatrixDiagMatrix(const std::vector<complex_t> & mA,const std::vector<real_t> & vB,std::vector<complex_t> & mR) const702 void MatrixStorage::multMatrixDiagMatrix(const std::vector<complex_t>& mA, const std::vector<real_t>& vB, std::vector<complex_t>& mR) const
703 {
704   multMatrixDiagMatrixGeneric(mA.begin(), vB.begin(), mR.begin());
705 }
multMatrixDiagMatrix(const std::vector<complex_t> & mA,const std::vector<complex_t> & vB,std::vector<complex_t> & mR) const706 void MatrixStorage::multMatrixDiagMatrix(const std::vector<complex_t>& mA, const std::vector<complex_t>& vB, std::vector<complex_t>& mR) const
707 {
708   multMatrixDiagMatrixGeneric(mA.begin(), vB.begin(), mR.begin());
709 }
710 //matrix of matrices
multMatrixDiagMatrix(const std::vector<Matrix<real_t>> & mA,const std::vector<Vector<real_t>> & vB,std::vector<Matrix<real_t>> & mR) const711 void MatrixStorage::multMatrixDiagMatrix(const std::vector<Matrix<real_t> >& mA, const std::vector<Vector<real_t> >& vB, std::vector<Matrix<real_t> >& mR)const
712 {
713   multMatrixDiagMatrixGeneric(mA.begin(), vB.begin(), mR.begin());
714 }
multMatrixDiagMatrix(const std::vector<Matrix<real_t>> & mA,const std::vector<Vector<complex_t>> & vB,std::vector<Matrix<complex_t>> & mR) const715 void MatrixStorage::multMatrixDiagMatrix(const std::vector<Matrix<real_t> >& mA, const std::vector<Vector<complex_t> >& vB, std::vector<Matrix<complex_t> >& mR)const
716 {
717   multMatrixDiagMatrixGeneric(mA.begin(), vB.begin(), mR.begin());
718 }
multMatrixDiagMatrix(const std::vector<Matrix<complex_t>> & mA,const std::vector<Vector<real_t>> & vB,std::vector<Matrix<complex_t>> & mR) const719 void MatrixStorage::multMatrixDiagMatrix(const std::vector<Matrix<complex_t> >& mA, const std::vector<Vector<real_t> >& vB, std::vector<Matrix<complex_t> >& mR) const
720 {
721   multMatrixDiagMatrixGeneric(mA.begin(), vB.begin(), mR.begin());
722 }
multMatrixDiagMatrix(const std::vector<Matrix<complex_t>> & mA,const std::vector<Vector<complex_t>> & vB,std::vector<Matrix<complex_t>> & mR) const723 void MatrixStorage::multMatrixDiagMatrix(const std::vector<Matrix<complex_t> >& mA, const std::vector<Vector<complex_t> >& vB, std::vector<Matrix<complex_t> >& mR)const
724 {
725   multMatrixDiagMatrixGeneric(mA.begin(), vB.begin(), mR.begin());
726 }
727 
728 // diag Matrix * Matrix (result in current storage) - generic algorithm - (see child bor better algorithm)
multDiagMatrixMatrix(const std::vector<real_t> & vA,const std::vector<real_t> & mB,std::vector<real_t> & mR) const729 void MatrixStorage::multDiagMatrixMatrix(const std::vector<real_t>& vA, const std::vector<real_t>& mB, std::vector<real_t>& mR) const
730 {
731   multDiagMatrixMatrixGeneric(vA.begin(), mB.begin(), mR.begin());
732 }
multDiagMatrixMatrix(const std::vector<real_t> & vA,const std::vector<complex_t> & mB,std::vector<complex_t> & mR) const733 void MatrixStorage::multDiagMatrixMatrix(const std::vector<real_t>& vA, const std::vector<complex_t>& mB, std::vector<complex_t>& mR) const
734 {
735   multDiagMatrixMatrixGeneric(vA.begin(), mB.begin(), mR.begin());
736 }
multDiagMatrixMatrix(const std::vector<complex_t> & vA,const std::vector<real_t> & mB,std::vector<complex_t> & mR) const737 void MatrixStorage::multDiagMatrixMatrix(const std::vector<complex_t>& vA, const std::vector<real_t>& mB, std::vector<complex_t>& mR) const
738 {
739   multDiagMatrixMatrixGeneric(vA.begin(), mB.begin(), mR.begin());
740 }
multDiagMatrixMatrix(const std::vector<complex_t> & vA,const std::vector<complex_t> & mB,std::vector<complex_t> & mR) const741 void MatrixStorage::multDiagMatrixMatrix(const std::vector<complex_t>& vA, const std::vector<complex_t>& mB, std::vector<complex_t>& mR) const
742 {
743   multDiagMatrixMatrixGeneric(vA.begin(), mB.begin(), mR.begin());
744 }
745 
multDiagMatrixMatrix(const std::vector<Vector<real_t>> & vA,const std::vector<Matrix<real_t>> & mB,std::vector<Matrix<real_t>> & mR) const746 void MatrixStorage::multDiagMatrixMatrix(const std::vector<Vector<real_t> >& vA, const std::vector<Matrix<real_t> >& mB, std::vector<Matrix<real_t> >& mR)const
747 {
748   multDiagMatrixMatrixGeneric(vA.begin(), mB.begin(), mR.begin());
749 }
multDiagMatrixMatrix(const std::vector<Vector<real_t>> & vA,const std::vector<Matrix<complex_t>> & mB,std::vector<Matrix<complex_t>> & mR) const750 void MatrixStorage::multDiagMatrixMatrix(const std::vector<Vector<real_t> >& vA, const std::vector<Matrix<complex_t> >& mB, std::vector<Matrix<complex_t> >& mR)const
751 {
752   multDiagMatrixMatrixGeneric(vA.begin(), mB.begin(), mR.begin());
753 }
multDiagMatrixMatrix(const std::vector<Vector<complex_t>> & vA,const std::vector<Matrix<real_t>> & mB,std::vector<Matrix<complex_t>> & mR) const754 void MatrixStorage::multDiagMatrixMatrix(const std::vector<Vector<complex_t> >& vA, const std::vector<Matrix<real_t> >& mB, std::vector<Matrix<complex_t> >& mR) const
755 {
756   multDiagMatrixMatrixGeneric(vA.begin(), mB.begin(), mR.begin());
757 }
multDiagMatrixMatrix(const std::vector<Vector<complex_t>> & vA,const std::vector<Matrix<complex_t>> & mB,std::vector<Matrix<complex_t>> & mR) const758 void MatrixStorage::multDiagMatrixMatrix(const std::vector<Vector<complex_t> >& vA, const std::vector<Matrix<complex_t> >& mB, std::vector<Matrix<complex_t> >& mR)const
759 {
760   multDiagMatrixMatrixGeneric(vA.begin(), mB.begin(), mR.begin());
761 }
762 
763 /* =====================================================================================
764    colamd/symamd - sparse matrix column ordering algorithm adapt from SuiteSparse colamd
765   ======================================================================================
766   from compressed sparse storage data (rowIndices, colPointer) produces
767   column permutation Q (colPermvector) of A such that P(AQ)=LU or (AQ)'AQ=LL' have less fill-in
768   return false if fails
769 
770   nbr        : number of rows
771   nbc        : number of columns
772   rowIndices : list of row indices of non zeros
773   colPointer : pointer to column entries
774   colPerm    : the vector permutation of columns (size nbc)
775 
776      exemple : nbr=5, nbc=4 matrix with 11 nonzero entries
777             row/col  0 1 2 3
778                0     x 0 x 0
779                1     x 0 x x
780                2     0 x x 0
781                3     0 0 x x
782                4     x x 0 0
783             rowIndices = {0, 1, 4,  2, 4,  0, 1, 2, 3,  1, 3} ;
784             colPinter  = {0,        3,     5,           9,   11} ;
785     note : nnz = colPointer[nbc]= rowIndices.size()
786 
787 */
colAmd(number_t nbr,number_t nbc,const std::vector<number_t> & rowIndices,const std::vector<number_t> & colPointer,std::vector<number_t> & colPerm)788 bool colAmd(number_t nbr, number_t nbc, const std::vector<number_t>& rowIndices,
789             const std::vector<number_t>& colPointer, std::vector<number_t>& colPerm)
790 {
791 //
792 //   // copy rowIndices and resize to  2*nnz + n_col + Col_size + Row_size in rowIndices
793 //   number_t nnz=rowIndices.size(), s= 2*nnz + n_col + Col_size + Row_size
794 //   std::vector<number_t> A(rowIndices)
795   error("not_yet_implemented","colAmd(...)");
796   return false; // dummy return
797 }
798 
symAmd(number_t nbr,number_t nbc,const std::vector<number_t> & colIndices,const std::vector<number_t> & rowPointer,std::vector<number_t> & colPerm)799 bool symAmd(number_t nbr, number_t nbc, const std::vector<number_t>& colIndices,
800             const std::vector<number_t>& rowPointer, std::vector<number_t>& colPerm)
801 {
802   error("not_yet_implemented","symAmd(...)");
803   return false; // dummy return
804 }
805 
806 /*! compare two storages, they are same if all the coefficients are travelled in the same way
807     - storage pointers are the same
808     - storage types are the same, sizes are the same and storage structure are the same
809 */
sameStorage(const MatrixStorage & sto1,const MatrixStorage & sto2)810 bool sameStorage(const MatrixStorage& sto1,const MatrixStorage& sto2)
811 {
812   if(&sto1==&sto2) return true;   //same storage pointers
813   if(sto2.storageType()!=sto1.storageType() || sto2.accessType()!=sto1.accessType()) return false;
814   if(sto1.sameStorage(sto2)) return true;
815   return false;
816 }
817 
818 } // end of namespace xlifepp
819