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 RowCsStorage.cpp
19   \authors D. Martin, E. Lunéville, NGUYEN Manh Ha, N. Kielbasiewicz
20   \since 21 jun 2011
21   \date 21 feb 2013
22 
23   \brief Implementation of xlifepp::RowCsStorage class and functionnalities
24 */
25 
26 #include "RowCsStorage.hpp"
27 #include <functional>
28 
29 namespace xlifepp
30 {
31 
32 /*--------------------------------------------------------------------------------
33   Constructors, Destructor
34 --------------------------------------------------------------------------------*/
35 //! default constructor
RowCsStorage(number_t nr,number_t nc,string_t id)36 RowCsStorage::RowCsStorage(number_t nr, number_t nc, string_t id)
37   : CsStorage(nr, nc, _row, id)
38 {
39   trace_p->push("RowCsStorage constructor");
40   std::vector<std::vector<number_t> > cols(nr);
41   buildCsStorage(cols, colIndex_, rowPointer_); //construct colIndex_ and rowPointer_
42   trace_p->pop();
43 }
44 
45 /*! constructor by a pair of numbering vectors rowNumbers and colNumbers (same size)
46    rowNumbers[k] is the row numbers of submatrix k
47    colNumbers[k] is the col numbers of submatrix k
48  indices start from 1 !!!!
49  this constructor is well adapted to FE matrix where submatrix is linked to an element
50  */
RowCsStorage(number_t nr,number_t nc,const std::vector<std::vector<number_t>> & rowNumbers,const std::vector<std::vector<number_t>> & colNumbers,string_t id)51 RowCsStorage::RowCsStorage(number_t nr, number_t nc, const std::vector<std::vector<number_t> >& rowNumbers, const std::vector<std::vector<number_t> >& colNumbers, string_t id)
52   : CsStorage(nr, nc, _row, id)
53 {
54   trace_p->push("RowCsStorage constructor");
55   // build list of col index for each rows
56   std::vector<std::set<number_t> > colset(nbRows_);   //temporary vector of col index
57   std::vector<std::vector<number_t> >::const_iterator itrs, itcs = colNumbers.begin();
58   std::vector<number_t>::const_iterator itr, itc;
59   for(itrs = rowNumbers.begin(); itrs != rowNumbers.end(); itrs++, itcs++)
60     {
61       for(itr = itrs->begin(); itr != itrs->end(); itr++)
62         for(itc = itcs->begin(); itc != itcs->end(); itc++)
63           { colset[*itr - 1].insert(*itc); }
64     }
65   // convert set to vector
66   std::vector<std::vector<number_t> > cols(nbRows_);   //temporary vector of col index
67   std::vector<std::set<number_t> >::iterator itset;
68   std::vector<std::vector<number_t> >::iterator itcols = cols.begin();
69   for(itset = colset.begin(); itset != colset.end(); itset++, itcols++)
70     { *itcols = std::vector<number_t>(itset->begin(), itset->end()); }
71   // construct colIndex_ and rowPointer_
72   buildCsStorage(cols, colIndex_, rowPointer_);
73   trace_p->pop();
74 }
75 
76 //! create a new scalar RowCs storage from current RowCs storage and submatrix sizes
toScalar(dimen_t nbr,dimen_t nbc)77 RowCsStorage* RowCsStorage::toScalar(dimen_t nbr, dimen_t nbc)
78 {
79   RowCsStorage* cs = new RowCsStorage(nbr*nbRows_, nbc*nbCols_, stringId+"_scalar");
80   cs->colIndex_.resize(nbr*nbc*colIndex_.size());
81   toScalarCs(rowPointer_, colIndex_, nbc, nbr, cs->rowPointer_, cs->colIndex_);
82   return cs;
83 }
84 
85 //! check if two storages have the same structures
sameStorage(const MatrixStorage & sto) const86 bool RowCsStorage::sameStorage(const MatrixStorage& sto) const
87 {
88   if(!(sto.storageType()==storageType_ &&
89        sto.accessType()==accessType_ &&
90        sto.nbOfRows()==nbRows_ &&
91        sto.nbOfColumns()==nbCols_&&
92        sto.size()==size()))
93     return false;
94   const RowCsStorage& csto=static_cast<const RowCsStorage&>(sto);
95   if(rowPointer_!=csto.rowPointer_) return false;
96   if(colIndex_!=csto.colIndex_) return false;
97   return true;
98 }
99 
100 /*!--------------------------------------------------------------------------------
101  add submatrix indices given by its row and column indices (>= 1)
102 --------------------------------------------------------------------------------*/
addSubMatrixIndices(const std::vector<number_t> & rows,const std::vector<number_t> & cols)103 void RowCsStorage::addSubMatrixIndices(const std::vector<number_t>& rows,const std::vector<number_t>& cols)
104 {
105   addCsSubMatrixIndices(rowPointer_,colIndex_,rows,cols, false,true);
106 }
107 
108 /*!--------------------------------------------------------------------------------
109  add in storage indexes (i,j) given by rows (i) and columns (j) (i,j >= 1)
110  rows and cols are of same size
111 --------------------------------------------------------------------------------*/
addIndices(const std::vector<number_t> & rows,const std::vector<number_t> & cols)112 void RowCsStorage::addIndices(const std::vector<number_t>& rows, const std::vector<number_t>& cols)
113 {
114   if(rows.size()==0) return;  //nothing to do
115 
116   std::vector<number_t>::const_iterator itr = rows.begin(),itc=cols.end();
117   std::map<number_t, std::set<number_t> > rowsmap;
118   std::map<number_t, std::set<number_t> >::iterator itm;;
119   //collect col indexes by row
120   for(; itr!=rows.end(); itr++, itc++)
121     {
122       itm=rowsmap.find(*itr);
123       if(itm==rowsmap.end()) rowsmap[*itr]=std::set<number_t>();
124       rowsmap[*itr].insert(*itc);
125     }
126   //modify current rowpointer and colindex (expansive operation)
127   for(itm=rowsmap.begin(); itm!=rowsmap.end(); itm++)
128     if(itm->second.size()>0) addRow(itm->first,itm->second,_all);  //insert col at row r in storage
129 }
130 
131 /*!--------------------------------------------------------------------------------
132 insert in storage indexes (r,c1), (r,c2), .... c1,c2, ... given by cols (r,c>=1)
133   expansive operation !
134   MatrixPart not managed !
135 --------------------------------------------------------------------------------*/
addRow(number_t r,const std::set<number_t> & cols,MatrixPart)136 void RowCsStorage::addRow(number_t r, const std::set<number_t>& cols, MatrixPart)
137 {
138   if(cols.size()==0) return;
139   number_t rb=rowPointer_[r-1], re=rowPointer_[r];
140   std::set<number_t> allcols(colIndex_.begin()+rb, colIndex_.begin()+re);
141   std::set<number_t>::iterator its=cols.begin();
142   for(; its!=cols.end(); its++) allcols.insert(*its -1); //add current cols (-1 shift)
143   number_t nc=allcols.size()- (re - rb);
144   if(nc==0) return;                      //nothing to do , no new cols
145 
146   std::vector<number_t>::iterator itc=colIndex_.begin()+re;
147   colIndex_.insert(itc, nc, 0);          //insert nc element initialized to 0
148   its=allcols.begin();
149   itc=colIndex_.begin()+rb;
150   for(; its!=allcols.end(); its++,itc++) *itc=*its; //copy new columns set
151   std::vector<number_t>::iterator itr=rowPointer_.begin()+r;
152   for(; itr!=rowPointer_.end(); itr++) *itr+=nc; //shift rowPointer
153 }
154 
155 /*!--------------------------------------------------------------------------------
156  access operator to position of (i,j)>0 coefficients (return 0 if outside)
157  This DIRECT access to (i,j) pointer SHOULD NOT be used in matrix computation
158 --------------------------------------------------------------------------------*/
pos(number_t i,number_t j,SymType s) const159 number_t RowCsStorage::pos(number_t i, number_t j, SymType s) const
160 {
161   if(i == 0 || i > nbRows_ || j == 0 || j > nbCols_) { return 0; }
162   for(number_t k = rowPointer_[i - 1]; k < rowPointer_[i]; k++) // find in list of col index of row i
163     {
164       if(colIndex_[k] == j - 1) { return k + 1; }               // add 1 because values begin at address 1
165     }
166   return 0;
167 }
168 
169 /*!--------------------------------------------------------------------------------
170  access to submatrix adresses, useful for assembling matrices
171  rows and cols are vector of index (>0) of row and column, no index ordering is assumed !!
172  return the vector of adresses (relative number >0 in storage) in a row storage (as Matrix)
173  if a row or a col index is out of storage
174      an error is raised if errorOn is true (default)
175      position is set to 0 else
176  if sy!=_noSymmetry only positions of lower part are requested (not used here)
177  remark : since the vector storage indexCol_ is ordered for each line, if the indices of columns
178           of the submatrix were also, one could write a faster algorithm
179 --------------------------------------------------------------------------------*/
positions(const std::vector<number_t> & rows,const std::vector<number_t> & cols,std::vector<number_t> & adrs,bool errorOn,SymType sy) const180 void RowCsStorage::positions(const std::vector<number_t>& rows, const std::vector<number_t>& cols, std::vector<number_t>& adrs, bool errorOn, SymType sy) const
181 {
182   number_t nba = rows.size() * cols.size();
183   if(adrs.size() != nba) { adrs.resize(nba); }
184   std::vector<number_t>::iterator itp = adrs.begin();
185   std::vector<number_t>::const_iterator itr, itc, itb, ite;
186   for(itr = rows.begin(); itr != rows.end(); itr++)  // loop on row index
187     {
188       number_t i = *itr, rb = rowPointer_[i - 1], re = rowPointer_[i];
189       for(itc = cols.begin(); itc != cols.end(); itc++, itp++) // loop on col index
190         {
191           itb = colIndex_.begin() + rb;
192           ite = colIndex_.begin() + re;
193           *itp = 0;
194           number_t k=0;
195           while(itb != ite && *itp == 0) // find in list of col index of row i
196             {
197 
198               if(*itb == (*itc - 1)) { *itp = rb + k + 1; }
199               itb++; k++;
200             }
201           if(*itp == 0 && errorOn) { error("storage_outofstorage","RowCs", *itr, *itc); }
202         }
203     }
204 }
205 
206 //! get (col indices, adress) of row r in set [c1,c2] ## SymType not used ##
getRow(SymType s,number_t r,number_t c1,number_t c2) const207 std::vector<std::pair<number_t, number_t> > RowCsStorage::getRow(SymType s,number_t r, number_t c1, number_t c2) const
208 {
209   number_t nbc=c2;
210   if(nbc==0) nbc=nbCols_;
211   number_t rb=rowPointer_[r-1], re=rowPointer_[r];
212   number_t l=re-rb;
213   std::vector<std::pair<number_t, number_t> > cols(l);
214   std::vector<std::pair<number_t, number_t> >::iterator itcol=cols.begin();
215   l=0;
216   for(number_t k = rb; k < re; k++) // find in list of col index of row i
217     {
218       number_t c=colIndex_[k]+1;
219       if(c >= c1 && c<=nbc)
220         {
221           *itcol = std::make_pair(c,k+1);            // add 1 because values begin at address 1
222           l++; itcol++;
223         }
224     }
225   cols.resize(l);
226   return cols;
227 }
228 
229 //! get (row indices, adress) of col c in set [r1,r2] ## SymType not used ##
getCol(SymType s,number_t c,number_t r1,number_t r2) const230 std::vector<std::pair<number_t, number_t> > RowCsStorage::getCol(SymType s, number_t c, number_t r1, number_t r2) const
231 {
232   number_t nbr=r2;
233   if(nbr==0) nbr=nbRows_;
234   std::vector<std::pair<number_t, number_t> > rows(nbr-r1+1);
235   std::vector<std::pair<number_t, number_t> >::iterator itrow=rows.begin();
236   number_t l=0;
237   for(number_t i=r1; i<=nbr; i++)
238     {
239       number_t a=pos(i,c);
240       if(a!=0)
241         {
242           *itrow=std::make_pair(i,a);
243           l++; itrow++;
244         }
245     }
246   rows.resize(l);
247   return rows;
248 }
249 
250 //! get col indices of row r in set [c1,c2], specific CsRow algorithm (no getRows, use generic algorithm)
getCols(number_t r,number_t c1,number_t c2) const251 std::set<number_t> RowCsStorage::getCols(number_t r, number_t c1, number_t c2) const
252 {
253   std::set<number_t> colset;
254   number_t nbc=c2;
255   if(nbc==0) nbc=nbCols_;
256   if(nbc<c1) return colset;
257   number_t rb=rowPointer_[r-1], re=rowPointer_[r];
258   for(number_t k = rb; k < re; k++) // find in list of col index of row i
259     {
260       number_t c=colIndex_[k]+1;
261       if(c >= c1 && c<=nbc) colset.insert(c);
262     }
263   return colset;
264 }
265 
266 //! get col indices of row r in set [c1,c2], specific CsRow algorithm (no getRows, use generic algorithm)
267 // no allocation, no check (faster)
getColsV(std::vector<number_t> & colsv,number_t & nbcols,number_t r,number_t c1,number_t c2) const268 void RowCsStorage::getColsV(std::vector<number_t>& colsv, number_t& nbcols, number_t r, number_t c1, number_t c2) const
269 {
270   nbcols=0;
271   number_t nbc=c2;
272   if(nbc==0) nbc=nbCols_;
273   if(nbc<c1) return;
274   std::vector<number_t>::iterator itv=colsv.begin();
275   number_t rb=rowPointer_[r-1], re=rowPointer_[r];
276   for(number_t k = rb; k < re; k++) // find in list of col index of row i
277     {
278       number_t c=colIndex_[k]+1;
279       if(c >= c1 && c<=nbc) {*itv=c; itv++; nbcols++;}
280     }
281 }
282 
283 
284 
285 //! print storage pointers
print(std::ostream & os) const286 void RowCsStorage::print(std::ostream& os) const
287 {
288   printHeader(os);
289   os<<"row pointer = "<<rowPointer_<<eol;
290   os<<"column index = "<<colIndex_<<eol;
291 }
292 
293 /*!--------------------------------------------------------------------------------
294  print RowCs Storage matrix to output stream (sym is not used here)
295 --------------------------------------------------------------------------------*/
296 // print real scalar matrix
printEntries(std::ostream & os,const std::vector<real_t> & m,number_t vb,const SymType sym) const297 void RowCsStorage::printEntries(std::ostream& os, const std::vector<real_t>& m, number_t vb, const SymType sym) const
298 {
299   std::vector<real_t>::const_iterator itm = m.begin() + 1;
300   printEntriesAll(_scalar, itm, colIndex_, rowPointer_, entriesPerRow, entryWidth, entryPrec, "row", vb, os);
301 }
302 
303 //! print complex scalar matrix
printEntries(std::ostream & os,const std::vector<complex_t> & m,number_t vb,SymType sym) const304 void RowCsStorage::printEntries(std::ostream& os, const std::vector<complex_t>& m, number_t vb, SymType sym) const
305 {
306   std::vector<complex_t>::const_iterator itm = m.begin() + 1;
307   printEntriesAll(_scalar, itm, colIndex_, rowPointer_, entriesPerRow / 2, 2 * entryWidth + 1, entryPrec, "row", vb, os);
308 }
309 
310 //! large matrix of vectors are not available for the moment, use Matrix n x 1 or 1 x n
printEntries(std::ostream & os,const std::vector<Vector<real_t>> & m,number_t vb,SymType sym) const311 void RowCsStorage::printEntries(std::ostream& os, const std::vector< Vector<real_t> >& m, number_t vb, SymType sym) const
312 {error("storage_novector", "RowCsStorage::printEntries");}
313 
printEntries(std::ostream & os,const std::vector<Vector<complex_t>> & m,number_t vb,SymType sym) const314 void RowCsStorage::printEntries(std::ostream& os, const std::vector< Vector<complex_t> >& m, number_t vb, SymType sym) const
315 {error("storage_novector", "RowCsStorage::printEntries");}
316 
317 //! print matrix of real matrices
printEntries(std::ostream & os,const std::vector<Matrix<real_t>> & m,number_t vb,SymType sym) const318 void RowCsStorage::printEntries(std::ostream& os, const std::vector< Matrix<real_t> >& m, number_t vb, SymType sym) const
319 {
320   std::vector< Matrix<real_t> >::const_iterator itm = m.begin() + 1;
321   printEntriesAll(_matrix, itm, colIndex_, rowPointer_, entriesPerRow, entryWidth, entryPrec, "row", vb, os);
322 }
323 
324 //! print matrix of complex matrices
printEntries(std::ostream & os,const std::vector<Matrix<complex_t>> & m,number_t vb,SymType sym) const325 void RowCsStorage::printEntries(std::ostream& os, const std::vector< Matrix<complex_t> >& m, number_t vb, SymType sym) const
326 {
327   std::vector< Matrix<complex_t> >::const_iterator itm = m.begin() + 1;
328   printEntriesAll(_matrix, itm, colIndex_, rowPointer_, entriesPerRow / 2, 2 * entryWidth + 1, entryPrec, "row", vb, os);
329 }
330 
331 /*!
332 --------------------------------------------------------------------------------
333  print matrix to ostream in coordinate form : i j M_ij
334  according to type of values of matrix (overload the generic method in MatrixStorage)
335  sym is not used
336 --------------------------------------------------------------------------------
337 */
printCooMatrix(std::ostream & os,const std::vector<real_t> & m,SymType sym) const338 void RowCsStorage::printCooMatrix(std::ostream& os, const std::vector<real_t>& m, SymType sym) const
339 {
340   std::vector<real_t>::const_iterator itm = m.begin() + 1;
341   printCooTriangularPart(os, itm, colIndex_, rowPointer_, true);
342 }
343 
printCooMatrix(std::ostream & os,const std::vector<complex_t> & m,SymType sym) const344 void RowCsStorage::printCooMatrix(std::ostream& os, const std::vector<complex_t>& m, SymType sym) const
345 {
346   std::vector<complex_t>::const_iterator itm = m.begin() + 1;
347   printCooTriangularPart(os, itm, colIndex_, rowPointer_, true);
348 }
349 
printCooMatrix(std::ostream & os,const std::vector<Matrix<real_t>> & m,SymType sym) const350 void RowCsStorage::printCooMatrix(std::ostream& os, const std::vector< Matrix<real_t> >& m, SymType sym) const
351 {
352   std::vector< Matrix<real_t> >::const_iterator itm = m.begin() + 1;
353   printCooTriangularPart(os, itm, colIndex_, rowPointer_, true);
354 }
355 
printCooMatrix(std::ostream & os,const std::vector<Matrix<complex_t>> & m,SymType sym) const356 void RowCsStorage::printCooMatrix(std::ostream& os, const std::vector< Matrix<complex_t> >& m, SymType sym) const
357 {
358   std::vector< Matrix<complex_t> >::const_iterator itm = m.begin() + 1;
359   printCooTriangularPart(os, itm, colIndex_, rowPointer_, true);
360 }
361 
362 /*!--------------------------------------------------------------------------------
363  template Matrix x Vector & Vector x Matrix multiplications and specializations
364  result vector has to be sized before
365 --------------------------------------------------------------------------------*/
366 template<typename M, typename V, typename R>
multMatrixVector(const std::vector<M> & m,V * vp,R * rp) const367 void RowCsStorage::multMatrixVector(const std::vector<M>& m, V* vp, R* rp) const
368 {
369   trace_p->push("RowCsStorage::multMatrixVector (pointer form)");
370   typename std::vector<M>::const_iterator itm = m.begin() + 1;
371   rowMatrixVector(colIndex_, rowPointer_, itm, vp, rp);
372   trace_p->pop();
373 }
374 
375 template<typename M, typename V, typename R>
multMatrixVector(const std::vector<M> & m,const std::vector<V> & v,std::vector<R> & r) const376 void RowCsStorage::multMatrixVector(const std::vector<M>& m, const std::vector<V>& v, std::vector<R>& r) const
377 {
378   trace_p->push("RowCsStorage::multMatrixVector");
379   typename std::vector<M>::const_iterator itm = m.begin() + 1;
380   typename std::vector<V>::const_iterator itvb = v.begin();
381   typename std::vector<R>::iterator itrb = r.begin();
382   rowMatrixVector(colIndex_, rowPointer_, itm, itvb, itrb);
383   trace_p->pop();
384 }
385 
386 template<typename M, typename V, typename R>
multVectorMatrix(const std::vector<M> & m,V * vp,R * rp) const387 void RowCsStorage::multVectorMatrix(const std::vector<M>& m, V* vp, R* rp) const
388 {
389   trace_p->push("RowCsStorage::multVectorMatrix (pointer form)");
390   typename std::vector<M>::const_iterator itm = m.begin() + 1;
391   rowMatrixVector(colIndex_, rowPointer_, itm, vp, rp);
392   trace_p->pop();
393 }
394 
395 template<typename M, typename V, typename R>
multVectorMatrix(const std::vector<M> & m,const std::vector<V> & v,std::vector<R> & r) const396 void RowCsStorage::multVectorMatrix(const std::vector<M>& m, const std::vector<V>& v, std::vector<R>& r) const
397 {
398   trace_p->push("RowCsStorage::multVectorMatrix");
399   typename std::vector<M>::const_iterator itm = m.begin() + 1;
400   typename std::vector<V>::const_iterator itvb = v.begin();
401   typename std::vector<R>::iterator itrb = r.begin();
402   rowVectorMatrix(colIndex_, rowPointer_, itm, itvb, itrb);
403   trace_p->pop();
404 }
405 
406 /*!
407    Add two matrices
408    \param m1 vector values_ of first matrix
409    \param m2 vector values_ of second matrix
410    \param r vector values_ of result matrix
411  */
412 template<typename M1, typename M2, typename R>
addMatrixMatrix(const std::vector<M1> & m1,const std::vector<M2> & m2,std::vector<R> & r) const413 void RowCsStorage::addMatrixMatrix(const std::vector<M1>& m1, const std::vector<M2>& m2, std::vector<R>& r) const
414 {
415   trace_p->push("RowCsStorage::addMatrixMatrix");
416   typename std::vector<M1>::const_iterator itm1 = m1.begin() + 1;
417   typename std::vector<M2>::const_iterator itm2 = m2.begin() + 1;
418   typename std::vector<R>::iterator itrb = r.begin() + 1, itre = r.end();
419   sumMatrixMatrix(itm1, itm2, itrb, itre);
420   trace_p->pop();
421 }
422 
423 /*!
424    Extract and convert matrix storage to UMFPack format (Matlab sparse matrix)
425    \param m1 vector values_ current matrix
426    \param colPtUmf vector column Pointer of UMFPack format
427    \param rowIdxUmf vector row Index of UMFPack format
428    \param resultUmf vector values of UMFPack format
429  */
430 template<typename M1, typename Idx>
toUmfPack(const std::vector<M1> & m1,std::vector<Idx> & colPtUmf,std::vector<Idx> & rowIdxUmf,std::vector<M1> & resultUmf) const431 void RowCsStorage::toUmfPack(const std::vector<M1>& m1, std::vector<Idx>& colPtUmf, std::vector<Idx>& rowIdxUmf, std::vector<M1>& resultUmf) const
432 {
433   // Reserve memory for resultUmf and set its size to m1.size()-1 (we don't count for 0 in the first position)s
434   resultUmf.reserve(m1.size()-1);
435   resultUmf.clear();
436 
437   // Reserve memory for rowIdxUmf and set its size to 0
438   rowIdxUmf.reserve(m1.size()-1);
439   rowIdxUmf.clear();
440 
441   // Resize column pointer to nbCol+1
442   colPtUmf.clear();
443   colPtUmf.resize(nbCols_+1);
444 
445   // Because colPointer always begins with 0, so need to to count from the second position
446   typename std::vector<Idx>::iterator itColPtUmf = colPtUmf.begin()+1;
447   colPtUmf[0] = Idx(0);
448 
449   std::vector<number_t>::const_iterator itbColIdx = colIndex_.begin(), itColIdx = itbColIdx;
450   std::vector<number_t>::const_iterator iteColIdx = colIndex_.end();
451   std::vector<number_t>::const_iterator itRowPt = rowPointer_.begin();
452 
453   typename std::vector<M1>::const_iterator itm = m1.begin()+1;
454   typename std::vector<M1>::const_iterator itval;
455 
456   for(number_t colIdx = 0; colIdx < nbCols_; ++colIdx,++itColPtUmf)
457     {
458       itColIdx = itbColIdx;
459       Idx nzCol = Idx(0); // Number of non-zero in each "working" column
460       while(itColIdx != iteColIdx)
461         {
462           itColIdx = std::find(itColIdx,iteColIdx, colIdx);
463           if(itColIdx != iteColIdx)
464             {
465               itRowPt = std::find_if(rowPointer_.begin(), rowPointer_.end(),std::bind2nd(std::greater_equal<number_t>(), itColIdx - itbColIdx+1));
466 
467               // Update values
468               itval = (itColIdx-itbColIdx) + itm;
469               resultUmf.push_back(*itval);
470 
471               // Update colPtUmf with number of non-zero value
472               ++nzCol;
473 
474               // Update rowIdxUmf
475               rowIdxUmf.push_back(itRowPt-rowPointer_.begin()-1);
476 
477               // Increase iterator to make a search in new range
478               ++itColIdx;
479             }
480         }
481       // Update colPtUmf with number of non-zero value
482       *itColPtUmf += *(itColPtUmf-1) + nzCol;
483 
484 
485     }
486 }
487 /*!
488    incomplete factorization of matrix M stored as matrix F = L U where
489    - L is a lower triangular matrix with unit diagonal and is stored as
490    the strict lower triangular part of F
491    - U is a upper triangular matrix with diagonal stored as diagonal part of F
492    and strict upper triangular part stored as the strict upper triangular part of F :
493 
494   */
495 template<typename M>
ilu(std::vector<M> & m,std::vector<M> & f) const496 void RowCsStorage::ilu(std::vector<M>& m, std::vector<M>& f) const
497 {
498 
499   trace_p->push("RowCsStorage::ilu");
500   typename std::vector<M>::iterator f_ib=f.begin()+1;
501   std::vector<std::pair<number_t, number_t> > Cj;
502   std::vector<M> Diag(nbRows_);
503   number_t k;
504   Diag[0]=*f_ib;
505   number_t c,l;
506 
507   for (number_t j=0; j < nbRows_; j++) // boucle sur les colonnes
508   {
509        Cj=getCol(_noSymmetry,j+1,1,nbRows_);
510        for (number_t p=1; p < Cj.size(); p++)
511          {//Cj[p].first-1 ligne du peme coef non nul  col j
512               l=Cj[p].first-1;
513               c = rowPointer_[l];
514               k = 0;
515               while ( (Cj[k].first-1 < l) && (colIndex_[c] < j) )
516               {
517                   if (colIndex_[c] == Cj[k].first-1)
518                        {
519                           *(f_ib+Cj[p].second-1) -=*(f_ib+Cj[k].second-1) * (*(f_ib+c));
520                            c++;k++;
521                         }
522                   else if (colIndex_[c] < Cj[k].first-1)   c++;
523                   else /*if  (colIndex_[c] > Cj[k].first-1)  */   k++;
524               }
525             if (Cj[p].first-1 == j)
526               {
527                  Diag[j]=*(f_ib+Cj[p].second-1);
528                  if(std::abs(Diag[j]) < theZeroThreshold) {error("small_pivot") ; }
529                }
530             else if (Cj[p].first-1 > j) *(f_ib+Cj[p].second-1)/=Diag[j];
531          }
532    }
533   trace_p->pop();
534 }
535 
536 } // end of namespace xlifepp
537 
538