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