source: Sophya/trunk/SophyaLib/TArray/tmatrix.cc@ 3810

Last change on this file since 3810 was 3751, checked in by ansari, 16 years ago

Prise en charge de float 128 bits (r_16, complex<r_16>) par TArray<T>,TMatrix<T>,TVector<T>. activation par le flag de compilation SO_LDBLE128

File size: 21.9 KB
RevLine 
[3751]1// $Id: tmatrix.cc,v 1.39 2010-03-03 20:46:07 ansari Exp $
[762]2// C.Magneville 04/99
[2615]3#include "sopnamsp.h"
[762]4#include "machdefs.h"
[2752]5#include <iostream>
6#include <iomanip>
[762]7#include <stdio.h>
8#include <stdlib.h>
9#include "pexceptions.h"
10#include "tmatrix.h"
11
[3751]12namespace SOPHYA {
13
[926]14/*!
[3751]15 \class TMatrix
[926]16 \ingroup TArray
[2267]17
18 The TMatrix class specializes the TArray class for representing
19 two dimensional arrays as matrices. Matrix and vector operations,
20 such as matrix multiplication or transposition is implemented.
[2917]21
22 Sub-matrices, in particular matrix rows and columns can easily and
23 efficiently be extracted and manipulated.
24 It should be noted that a significant memory overhead is associated with
25 small matrices (typically less than 10x10=100 elements).However,
26 higher dimension arrays (3D for examples) can be used to represent large
27 number of small matrices or vectors.
28
[3101]29 \warning Matrix row, column indices (r,c) correspond to array indices
30 (r=jy, c=ix) for CMemoryMapping and to (r=ix, c=jy) for FortranMemoryMapping.
31
[2267]32 \b Matrix is a typedef for double precision floating point matrix ( TMatrix<r_8> ).
33
34 \sa SOPHYA::TArray SOPHYA::TVector
[2917]35 \sa SOPHYA::Range SOPHYA::Sequence
36 \sa SOPHYA::MathArray SOPHYA::SimpleMatrixOperation
[2267]37
38 The following sample code illustrates vector-matrix multiplication
39 and matrix inversion, using simple gauss inversion.
40 \code
41 #include "array.h"
42 // ....
43 int n = 5; // Size of matrix and vectors here
44 Matrix a(n,n);
45 a = RandomSequence(RandomSequence::Gaussian, 0., 2.5);
46 Vector x(n);
47 x = RegularSequence(1.,3.);
48 Vector b = a*x;
49 cout << " ----- Vector x = \n " << x << endl;
50 cout << " ----- Vector b = a*x = \n " << b << endl;
51 SimpleMatrixOperation<r_8> smo;
52 Matrix inva = smo.Inverse(a);
53 cout << " ----- Matrix Inverse(a) = \n " << inva << endl;
54 cout << " ----- Matrix a*Inverse(a) = \n " << inva*a << endl;
55 cout << " ----- Matrix Inverse(a)*b (=Inv(a)*a*x) = \n " << inva*b << endl;
56 cout << " ----- Matrix x-Inverse(a)*b = (=0 ?)\n " << x-inva*b << endl;
57 \endcode
58
[926]59 */
[804]60
[762]61////////////////////////////////////////////////////////////////
62//**** Createur, Destructeur
[894]63//! Default constructor
[762]64template <class T>
65TMatrix<T>::TMatrix()
66// Constructeur par defaut.
[804]67 : TArray<T>()
[762]68{
[1099]69 arrtype_ = 1; // Type = Matrix
[762]70}
71
[894]72//! constructor of a matrix with r lines et c columns.
73/*!
74 \param r : number of rows
75 \param c : number of columns
76 \param mm : define the memory mapping type
[2575]77 \param fzero : if \b true , set matrix elements to zero
[894]78 \sa ReSize
79 */
[762]80template <class T>
[2575]81TMatrix<T>::TMatrix(sa_size_t r,sa_size_t c, short mm, bool fzero)
[762]82// Construit une matrice de r lignes et c colonnes.
[804]83 : TArray<T>()
[762]84{
[804]85 if ( (r == 0) || (c == 0) )
[1156]86 throw ParmError("TMatrix<T>::TMatrix(sa_size_t r,sa_size_t c) NRows or NCols = 0");
[1099]87 arrtype_ = 1; // Type = Matrix
[2575]88 ReSize(r, c, mm, fzero);
[762]89}
90
[967]91//! Constructor by copy
[976]92/*!
93 \warning datas are \b SHARED with \b a.
94 \sa NDataBlock::NDataBlock(const NDataBlock<T>&)
95*/
[762]96template <class T>
97TMatrix<T>::TMatrix(const TMatrix<T>& a)
[967]98// Constructeur par copie
[804]99 : TArray<T>(a)
[762]100{
[1099]101 arrtype_ = 1; // Type = Matrix
[1103]102 UpdateMemoryMapping(a, SameMemoryMapping);
[762]103}
104
[894]105//! Constructor by copy
106/*!
107 \param share : if true, share data. If false copy data
108 */
[762]109template <class T>
[804]110TMatrix<T>::TMatrix(const TMatrix<T>& a, bool share)
[762]111// Constructeur par copie avec possibilite de forcer le partage ou non.
[804]112: TArray<T>(a, share)
[762]113{
[1099]114 arrtype_ = 1; // Type = Matrix
[1103]115 UpdateMemoryMapping(a, SameMemoryMapping);
[762]116}
117
[894]118//! Constructor of a matrix from a TArray \b a
119/*!
120 \param a : TArray to be copied or shared
121 \param share : if true, share data. If false copy data
122 */
[762]123template <class T>
[2752]124TMatrix<T>::TMatrix(const TArray<T>& a, bool share)
[804]125: TArray<T>(a, share)
[762]126{
[813]127 if (a.NbDimensions() > 2)
128 throw SzMismatchError("TMatrix<T>::TMatrix(const TArray<T>& a, ...) a.NbDimensions()>2");
129 if (a.NbDimensions() == 1) {
130 size_[1] = 1;
131 step_[1] = size_[0]*step_[0];
132 ndim_ = 2;
133 }
[1099]134 arrtype_ = 1; // Type = Matrix
[2752]135 UpdateMemoryMapping(a, SameMemoryMapping);
[762]136}
137
[1099]138//! Constructor of a matrix from a TArray \b a , with a different data type
[1081]139template <class T>
140TMatrix<T>::TMatrix(const BaseArray& a)
141: TArray<T>()
142{
[1099]143 arrtype_ = 1; // Type = Matrix
[1103]144 UpdateMemoryMapping(a, SameMemoryMapping);
[1081]145 SetBA(a);
146}
147
148
149
[894]150//! Destructor
[762]151template <class T>
[804]152TMatrix<T>::~TMatrix()
[762]153{
154}
155
[976]156//! Set matrix equal to \b a and return *this
157/*!
158 \warning Datas are copied (cloned) from \b a.
159 \sa NDataBlock::operator=(const NDataBlock<T>&)
160*/
[804]161template <class T>
162TArray<T>& TMatrix<T>::Set(const TArray<T>& a)
[762]163{
[813]164 if (a.NbDimensions() > 2)
165 throw SzMismatchError("TMatrix<T>::Set(const TArray<T>& a) a.NbDimensions() > 2");
[1099]166 if ((arrtype_ == 2) && (a.NbDimensions() > 1) && (a.Size(0) > 1) && (a.Size(1) > 1) )
167 throw SzMismatchError("TMatrix<T>::Set(const TArray<T>& a) Size(0,1)>1 for Vector");
[813]168 TArray<T>::Set(a);
[970]169 if (NbDimensions() == 1) {
[813]170 size_[1] = 1;
171 step_[1] = size_[0]*step_[0];
172 ndim_ = 2;
173 }
[970]174 UpdateMemoryMapping(*this, SameMemoryMapping);
[813]175 return(*this);
[762]176}
177
[1081]178template <class T>
179TArray<T>& TMatrix<T>::SetBA(const BaseArray& a)
180{
181 if (a.NbDimensions() > 2)
182 throw SzMismatchError("TMatrix<T>::SetBA(const BaseArray& a) a.NbDimensions() > 2");
[1099]183 if ((arrtype_ == 2) && (a.NbDimensions() > 1) && (a.Size(0) > 1) && (a.Size(1) > 1) )
184 throw SzMismatchError("TMatrix<T>::Set(const TArray<T>& a) Size(0,1)>1 for Vector");
[1081]185 TArray<T>::SetBA(a);
186 if (NbDimensions() == 1) {
187 size_[1] = 1;
188 step_[1] = size_[0]*step_[0];
189 ndim_ = 2;
190 }
191 UpdateMemoryMapping(*this, SameMemoryMapping);
192 return(*this);
193}
194
195
196
[894]197//! Resize the matrix
198/*!
199 \param r : number of rows
200 \param c : number of columns
201 \param mm : define the memory mapping type
202 (SameMemoryMapping,CMemoryMapping
203 ,FortranMemoryMapping,DefaultMemoryMapping)
[2575]204 \param fzero : if \b true , set matrix elements to zero
[894]205 */
[804]206template <class T>
[2575]207void TMatrix<T>::ReSize(sa_size_t r, sa_size_t c, short mm, bool fzero)
[762]208{
[804]209 if(r==0||c==0)
210 throw(SzMismatchError("TMatrix::ReSize r or c==0 "));
[1099]211 if ((arrtype_ == 2) && (r > 1) && (c > 1))
212 throw(SzMismatchError("TMatrix::ReSize r>1&&c>1 for Vector "));
[1156]213 sa_size_t size[BASEARRAY_MAXNDIMS];
214 for(int_4 kk=0; kk<BASEARRAY_MAXNDIMS; kk++) size[kk] = 0;
[804]215 if (mm == SameMemoryMapping) mm = GetMemoryMapping();
[813]216 else if ( (mm != CMemoryMapping) && (mm != FortranMemoryMapping) )
217 mm = GetDefaultMemoryMapping();
218 if (mm == CMemoryMapping) {
219 size[0] = c; size[1] = r;
220 }
221 else {
222 size[0] = r; size[1] = c;
223 }
[2575]224 TArray<T>::ReSize(2, size, 1, fzero);
[813]225 UpdateMemoryMapping(mm);
[762]226}
227
[894]228//! Re-allocate space for the matrix
229/*!
230 \param r : number of rows
231 \param c : number of columns
232 \param mm : define the memory mapping type
233 \param force : if true re-allocation is forced, if not it occurs
234 only if the required space is greater than the old one.
235 \sa ReSize
236 */
[762]237template <class T>
[1156]238void TMatrix<T>::Realloc(sa_size_t r,sa_size_t c, short mm, bool force)
[762]239{
[804]240 if(r==0||c==0)
241 throw(SzMismatchError("TMatrix::Realloc r or c==0 "));
[1099]242 if ((arrtype_ == 2) && (r > 1) && (c > 1))
243 throw(SzMismatchError("TMatrix::Realloc r>1&&c>1 for Vector "));
[1156]244 sa_size_t size[BASEARRAY_MAXNDIMS];
245 for(int_4 kk=0; kk<BASEARRAY_MAXNDIMS; kk++) size[kk] = 0;
[813]246 if (mm == SameMemoryMapping) mm = GetMemoryMapping();
247 else if ( (mm != CMemoryMapping) && (mm != FortranMemoryMapping) )
248 mm = GetDefaultMemoryMapping();
249 if (mm == CMemoryMapping) {
250 size[0] = c; size[1] = r;
251 }
252 else {
253 size[0] = r; size[1] = c;
254 }
[804]255 TArray<T>::Realloc(2, size, 1, force);
[813]256 UpdateMemoryMapping(mm);
[762]257}
258
[804]259// $CHECK$ Reza 03/2000 Doit-on declarer cette methode const ?
[894]260//! Return a submatrix define by \b Range \b rline and \b rcol
[762]261template <class T>
[813]262TMatrix<T> TMatrix<T>::SubMatrix(Range rline, Range rcol) const
[762]263{
[2915]264 Range rx=Range::first();
265 Range ry=Range::first();
[813]266 short mm = GetMemoryMapping();
267 if (mm == CMemoryMapping) { rx = rcol; ry = rline; }
268 else { ry = rcol; rx = rline; }
[2917]269 TMatrix sm(SubArray(rx, ry, Range::first(), Range::first(), Range::first(), false), true);
[813]270 sm.UpdateMemoryMapping(mm);
271 return(sm);
[762]272}
273
[804]274////////////////////////////////////////////////////////////////
275// Transposition
[1412]276//! Transpose matrix in place, by changing the memory mapping
[762]277template <class T>
[1412]278TMatrix<T>& TMatrix<T>::TransposeSelf()
[804]279{
[813]280 short vt = (marowi_ == veceli_) ? ColumnVector : RowVector;
[1156]281 int_4 rci = macoli_;
[804]282 macoli_ = marowi_;
283 marowi_ = rci;
[813]284 veceli_ = (vt == ColumnVector ) ? marowi_ : macoli_;
[804]285 return(*this);
[762]286}
287
288
[1412]289//! Returns the transpose of the original matrix.
[894]290/*!
[1412]291 The data is shared between the two matrices
292 \return return a new matrix
293 */
294template <class T>
[2421]295TMatrix<T> TMatrix<T>::Transpose() const
[1412]296{
297 TMatrix<T> tm(*this);
298 tm.TransposeSelf();
299 return tm;
300}
301
302//! Returns a new matrix, corresponding to the transpose of the original matrix
303/*!
[894]304 \param mm : define the memory mapping type
305 (SameMemoryMapping,CMemoryMapping,FortranMemoryMapping)
306 \return return a new matrix
307 */
[762]308template <class T>
[2421]309TMatrix<T> TMatrix<T>::Transpose(short mm) const
[762]310{
[804]311 if (mm == SameMemoryMapping) mm = GetMemoryMapping();
312 TMatrix<T> tm(NCols(), NRows(), mm);
[1156]313 for(sa_size_t i=0; i<NRows(); i++)
314 for(sa_size_t j=0; j<NCols(); j++)
[804]315 tm(j,i) = (*this)(i,j);
316 return tm;
[762]317}
318
[1412]319//! Rearrange data in memory according to \b mm
[894]320/*!
321 \param mm : define the memory mapping type
322 (SameMemoryMapping,CMemoryMapping,FortranMemoryMapping)
323 \warning If identical, return a matrix that share the datas
324 */
[762]325template <class T>
[2421]326TMatrix<T> TMatrix<T>::Rearrange(short mm) const
[762]327{
[813]328 if ( mm == SameMemoryMapping) mm = GetMemoryMapping();
329 else if ( (mm != CMemoryMapping) && (mm != FortranMemoryMapping) )
330 mm = GetDefaultMemoryMapping();
331
332 if (mm == GetMemoryMapping())
333 return (TMatrix<T>(*this, true));
334
[804]335 TMatrix<T> tm(NRows(), NCols(), mm);
[1156]336 for(sa_size_t i=0; i<NRows(); i++)
337 for(sa_size_t j=0; j<NCols(); j++)
[804]338 tm(i,j) = (*this)(i,j);
339 return tm;
[762]340}
341
[894]342//! Set the matrix to the identity matrix \b imx
[762]343template <class T>
[804]344TMatrix<T>& TMatrix<T>::SetIdentity(IdentityMatrix imx)
[762]345{
[804]346 if (ndim_ == 0) {
[1156]347 sa_size_t sz = imx.Size();
[804]348 if (sz < 1) sz = 1;
349 ReSize(sz, sz);
350 }
351 T diag = (T)imx.Diag();
352 if (NRows() != NCols())
353 throw SzMismatchError("TMatrix::operator= (IdentityMatrix) NRows() != NCols()") ;
[996]354 *this = (T) 0;
[1156]355 for(sa_size_t i=0; i<NRows(); i++) (*this)(i,i) = diag;
[762]356
[804]357 return (*this);
[762]358}
359
[804]360
361
362////////////////////////////////////////////////////////////////
363//**** Impression
[894]364//! Return info on number of rows, column and type \b T
[762]365template <class T>
[813]366string TMatrix<T>::InfoString() const
367{
368 string rs = "TMatrix<";
369 rs += typeid(T).name();
370 char buff[64];
371 sprintf(buff, ">(NRows=%ld, NCols=%ld)", (long)NRows(), (long)NCols());
372 rs += buff;
373 return(rs);
374}
375
[894]376//! Print matrix
377/*!
[1554]378 \param os : output stream
[894]379 \param maxprt : maximum numer of print
380 \param si : if true, display attached DvList
[1554]381 \param ascd : if true, suppresses the display of line numbers,
382 suitable for ascii dump format.
[894]383 \sa SetMaxPrint
384 */
[813]385template <class T>
[1581]386void TMatrix<T>::Print(ostream& os, sa_size_t maxprt, bool si, bool ascd) const
[762]387{
[804]388 if (maxprt < 0) maxprt = max_nprt_;
[1156]389 sa_size_t npr = 0;
[2752]390
391 // keep stream's io flags
[2756]392 // ios_base::fmtflags ioflg = os.flags(); compil pas sur OSF-cxx
393 // os << right ; compile pas sur OSF-cxx
[2752]394
[804]395 Show(os, si);
[850]396 if (ndim_ < 1) return;
[2752]397 // Calcul de la largeur d'impression pour chaque element
398 int fprtw = os.precision()+7;
399 int prtw = 5;
400
401 if ( (typeid(T) == typeid( int_4 )) || (typeid(T) == typeid( uint_4 )) ) prtw = 8;
402 else if ( (typeid(T) == typeid( int_8 )) || (typeid(T) == typeid( uint_8 )) ) prtw = 11;
403 else if ( typeid(T) == typeid( r_4 ) ) prtw = fprtw;
404 else if ( typeid(T) == typeid( r_8 ) ) prtw = fprtw;
405 else if ( typeid(T) == typeid(complex<r_4>) ) prtw = fprtw;
406 else if ( typeid(T) == typeid(complex<r_8>) ) prtw = fprtw;
407
[1156]408 sa_size_t kc,kr;
[804]409 for(kr=0; kr<size_[marowi_]; kr++) {
[2788]410 if ( (size_[marowi_] > 1) && (size_[macoli_] > 10) && !ascd)
411 os << "----- Line= " << kr << endl;
[804]412 for(kc=0; kc<size_[macoli_]; kc++) {
[1554]413 if(kc > 0) os << " ";
[2752]414 os << setw(prtw) << (*this)(kr, kc); npr++;
[1156]415 if (npr >= (sa_size_t) maxprt) {
[804]416 if (npr < totsize_) os << "\n .... " << endl; return;
417 }
418 }
419 os << endl;
420 }
[813]421 os << endl;
[2756]422 //compile pas sur OSF-cxx os.flags(ioflg); // reset stream io flags
[762]423}
424
[2585]425//////////////////////////////////////////////////////////
426/////////////// Multiplication matricielle ///////////////
427//////////////////////////////////////////////////////////
[762]428
[894]429//! Return the matrix product C = (*this)*B
430/*!
431 \param mm : define the memory mapping type for the return matrix
432 */
[2574]433////////////// Routine de base sans optimisation //////////////
434/*
[804]435template <class T>
436TMatrix<T> TMatrix<T>::Multiply(const TMatrix<T>& b, short mm) const
437{
438 if (NCols() != b.NRows())
439 throw(SzMismatchError("TMatrix<T>::Multiply(b) NCols() != b.NRows() ") );
440 if (mm == SameMemoryMapping) mm = GetMemoryMapping();
441 TMatrix<T> rm(NRows(), b.NCols(), mm);
[762]442
[804]443 const T * pea;
444 const T * peb;
445 T sum;
[1156]446 sa_size_t r,c,k;
447 sa_size_t stepa = Step(ColsKA());
[1415]448 sa_size_t stepb = b.Step(b.RowsKA());
[804]449 // Calcul de C=rm = A*B (A=*this)
450 for(r=0; r<rm.NRows(); r++) // Boucle sur les lignes de A
451 for(c=0; c<rm.NCols(); c++) { // Boucle sur les colonnes de B
452 sum = 0;
453 pea = &((*this)(r,0)); // 1er element de la ligne r de A
454 peb = &(b(0,c)); // 1er element de la colonne c de B
455 for(k=0; k<NCols(); k++) sum += pea[k*stepa]*peb[k*stepb];
456 rm(r,c) = sum;
457 }
458
459 return rm;
460}
[2574]461*/
[804]462
[2574]463////////////// Routine optimisee //////////////
464template <class T>
465TMatrix<T> TMatrix<T>::Multiply(const TMatrix<T>& b, short mm) const
[2583]466// Calcul de C= rm = A*B (A=*this)
467// Remember: C-like matrices are column packed
468// Fortan-like matrices are line packed
[2574]469{
470 if (NCols() != b.NRows())
471 throw(SzMismatchError("TMatrix<T>::Multiply(b) NCols() != b.NRows() ") );
472
[2583]473 // Commentaire: pas de difference de vitesse notable selon le mapping de la matrice produit "rm"
[2585]474 if (mm == SameMemoryMapping) mm = GetMemoryMapping();
[2574]475 TMatrix<T> rm(NRows(), b.NCols(), mm);
476
477 // Les "steps" pour l'adressage des colonnes de A et des lignes de B
478 sa_size_t stepa = Step(ColsKA());
479 sa_size_t stepb = b.Step(b.RowsKA());
480
[2583]481 // Taille totale des matrices A et B
482 size_t totsiza = this->DataBlock().Size();
483 size_t totsizb = b.DataBlock().Size();
[2574]484
[2583]485
486 ///////////////////////////////////////////////////////////////////
487 // On decide si on optimise ou non selon les dimensions de A et B //
488 // (il semble que optimiser ou non ne degrade pas //
489 // beaucoup la vitesse pour les petites matrices) //
490 ////////////////////////////////////////////////////////////////////
491
492 uint_2 popt = GetMatProdOpt();
493 bool no_optim = false; // optimization demandee par default
494 if( (popt&(uint_2)1) == 0 ) { // pas d'optimization explicitement demande
495 no_optim = true;
496 } else if( (popt&(uint_2)2) == 0 ) { // pas d'optimization forcee, la methode decide
497 // On part sur une disponibilite dans le cache processeur de 100 ko
498 // (A et B peuvent etre stoquees dans le cache)
499 if((totsiza+totsizb)*sizeof(T)<100000) no_optim = true;
500 }
501
[2574]502 sa_size_t r,c,k;
503 T sum;
504 const T * pe;
505
[2583]506
507 /////////////////////////////////
508 // Pas d'optimisation demandee //
509 /////////////////////////////////
510
[2574]511 if( no_optim ) {
512 //cout<<"no_optim("<<no_optim<<") "<<stepa<<" "<<stepb<<endl;
513 const T * pea;
514 const T * peb;
515 for(r=0; r<rm.NRows(); r++) { // Boucle sur les lignes de A
516 for(c=0; c<rm.NCols(); c++) { // Boucle sur les colonnes de B
517 sum = 0;
518 pea = &((*this)(r,0));
519 peb = &(b(0,c));
520 // On gagne un peu en remplacant "pea[k*stepa]" par "pea+=stepa" pour les grosses matrices
521 //for(k=0; k<NCols(); k++) sum += pea[k*stepa]*peb[k*stepb];
522 for(k=0; k<NCols(); k++) {sum += (*pea)*(*peb); pea+=stepa; peb+=stepb;}
523 rm(r,c) = sum;
524 }
525 }
[2583]526 return rm;
[2574]527 }
[2583]528
529
530 //////////////////////////////////////////////////////////////////////////////////
531 // A.col est packed et B.row est packed (on a interet a optimiser quand meme) //
532 //////////////////////////////////////////////////////////////////////////////////
533
534 if(stepa==1 && stepb==1) {
[2585]535 //cout<<"A.col packed && B.row packed "<<stepa<<" "<<stepb<<endl;
536 T * pea = new T[NCols()];
[2574]537 const T * peb;
538 for(r=0; r<rm.NRows(); r++) { // Boucle sur les lignes de A
539 pe = &((*this)(r,0));
540 for(k=0; k<NCols(); k++) {pea[k] = *(pe++);}
541 for(c=0; c<rm.NCols(); c++) { // Boucle sur les colonnes de B
542 sum = 0;
543 peb = &(b(0,c));
544 for(k=0; k<NCols(); k++) sum += *(peb++)*pea[k];
545 rm(r,c) = sum;
546 }
547 }
548 delete [] pea;
[2583]549 return rm;
550 }
551
552
553 //////////////////////////////////////////////////
554 // A.col est packed et B.row n'est pas packed //
555 //////////////////////////////////////////////////
556
557 if(stepa==1 && stepb!=1) {
[2574]558 //cout<<"A.col packed && B.row not packed "<<stepa<<" "<<stepb<<endl;
559 const T * pea;
[2585]560 T * peb = new T[NCols()];
[2574]561 for(c=0; c<rm.NCols(); c++) { // Boucle sur les colonnes de B
562 pe = &(b(0,c));
563 for(k=0; k<NCols(); k++) {peb[k] = *pe; pe+=stepb;}
564 for(r=0; r<rm.NRows(); r++) { // Boucle sur les lignes de A
565 sum = 0;
566 pea = &((*this)(r,0));
567 for(k=0; k<NCols(); k++) sum += pea[k]*peb[k];
568 rm(r,c) = sum;
569 }
570 }
571 delete [] peb;
[2583]572 return rm;
[2574]573 }
[2583]574
575
576 //////////////////////////////////////////////////
577 // A.col n'est pas packed et B.row est packed //
578 //////////////////////////////////////////////////
579
580 if(stepa!=1 && stepb==1) {
[2574]581 //cout<<"A.col not packed && B.row packed "<<stepa<<" "<<stepb<<endl;
[2585]582 T * pea = new T[NCols()];
[2574]583 const T * peb;
584 for(r=0; r<rm.NRows(); r++) { // Boucle sur les lignes de A
585 pe = &((*this)(r,0));
586 for(k=0; k<NCols(); k++) {pea[k] = *pe; pe+=stepa;}
587 for(c=0; c<rm.NCols(); c++) { // Boucle sur les colonnes de B
588 sum = 0;
589 peb = &(b(0,c));
590 for(k=0; k<NCols(); k++) sum += pea[k]*peb[k];
591 rm(r,c) = sum;
592 }
593 }
594 delete [] pea;
[2583]595 return rm;
[2574]596 }
[2583]597
598
599 ////////////////////////////////////////////////////////
600 // A.col n'est pas packed et B.row n'est pas packed //
601 ////////////////////////////////////////////////////////
602
603 //---- On demande l'optimization par copie d'une des matrices
604
605 if( (popt&(uint_2)4) ) {
606 // On copie la plus petite
607 if(totsiza<totsizb) { // on copie A
608 //cout<<"A.col not packed && B.row not packed ==> copy A to optimize "<<stepa<<" "<<stepb<<endl;
609 // Acopy doit etre C-like pour etre column-packed
610 TMatrix<T> acopy(NRows(),NCols(),BaseArray::CMemoryMapping);
611 acopy = *this;
612 rm = acopy.Multiply(b,mm);
613 } else { // on copie B
614 //cout<<"A.col not packed && B.row not packed ==> copy B to optimize "<<stepa<<" "<<stepb<<endl;
615 // Bcopy doit etre Fortran-like pour etre column-packed
616 TMatrix<T> bcopy(b.NRows(),b.NCols(),BaseArray::FortranMemoryMapping);
617 bcopy = b;
618 rm = Multiply(bcopy,mm);
619 }
620 return rm;
621 }
622
623 //---- stepb>stepa
624
625 if(stepa!=1 && stepb!=1 && stepb>stepa) {
[2574]626 //cout<<"A.col not packed && B.row not packed ==> optimize on B "<<stepa<<" "<<stepb<<endl;
627 const T * pea;
[2585]628 T * peb = new T[NCols()];
[2574]629 for(c=0; c<rm.NCols(); c++) { // Boucle sur les colonnes de B
630 pe = &(b(0,c));
631 for(k=0; k<NCols(); k++) {peb[k] = *pe; pe+=stepb;}
632 for(r=0; r<rm.NRows(); r++) { // Boucle sur les lignes de A
633 sum = 0;
634 pea = &((*this)(r,0));
635 for(k=0; k<NCols(); k++) {sum += (*pea)*peb[k]; pea+=stepa;}
636 rm(r,c) = sum;
637 }
638 }
639 delete [] peb;
[2583]640 return rm;
[2574]641 }
[2583]642
643 //---- stepa>=stepb
644
645 if(stepa!=1 && stepb!=1) {
[2574]646 //cout<<"A.col not packed && B.row not packed ==> optimize on A "<<stepa<<" "<<stepb<<endl;
[2585]647 T * pea = new T[NCols()];
[2574]648 const T * peb;
649 for(r=0; r<rm.NRows(); r++) { // Boucle sur les lignes de A
650 pe = &((*this)(r,0));
651 for(k=0; k<NCols(); k++) {pea[k] = *pe; pe+=stepa;}
652 for(c=0; c<rm.NCols(); c++) { // Boucle sur les colonnes de B
653 sum = 0;
654 peb = &(b(0,c));
655 for(k=0; k<NCols(); k++) {sum += pea[k]*(*peb); peb+=stepb;}
656 rm(r,c) = sum;
657 }
658 }
659 delete [] pea;
[2583]660 return rm;
[2574]661 }
662
[2583]663
664 //////////////////////////////////////////////////
665 // Cas non prevu, on ne doit JAMAIS arriver ici //
666 //////////////////////////////////////////////////
667 cout<<"TMatrix<T>::Multiply(b) Optimize case not treated... Please report BUG !!! "<<endl;
668 throw(SzMismatchError("TMatrix<T>::Multiply(b) Optimize case not treated... Please report BUG !!! ") );
[2574]669 return rm;
[2585]670
[2574]671}
672
[2585]673
[762]674///////////////////////////////////////////////////////////////
675#ifdef __CXX_PRAGMA_TEMPLATES__
[3661]676#pragma define_template TMatrix<uint_1>
[762]677#pragma define_template TMatrix<uint_2>
[2927]678#pragma define_template TMatrix<uint_4>
[1543]679#pragma define_template TMatrix<uint_8>
[3661]680#pragma define_template TMatrix<int_1>
[2927]681#pragma define_template TMatrix<int_2>
[762]682#pragma define_template TMatrix<int_4>
683#pragma define_template TMatrix<int_8>
684#pragma define_template TMatrix<r_4>
[804]685#pragma define_template TMatrix<r_8>
[762]686#pragma define_template TMatrix< complex<r_4> >
687#pragma define_template TMatrix< complex<r_8> >
[3751]688#ifdef SO_LDBLE128
689#pragma define_template TMatrix<r_16>
690#pragma define_template TMatrix< complex<r_16> >
[762]691#endif
[3751]692#endif
[762]693
694#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
[3661]695template class TMatrix<uint_1>;
[762]696template class TMatrix<uint_2>;
[2927]697template class TMatrix<uint_4>;
[1543]698template class TMatrix<uint_8>;
[3661]699template class TMatrix<int_1>;
[2927]700template class TMatrix<int_2>;
[762]701template class TMatrix<int_4>;
702template class TMatrix<int_8>;
703template class TMatrix<r_4>;
704template class TMatrix<r_8>;
705template class TMatrix< complex<r_4> >;
706template class TMatrix< complex<r_8> >;
[3751]707#ifdef SO_LDBLE128
708template class TMatrix<r_16>;
709template class TMatrix< complex<r_16> >;
[762]710#endif
[3751]711#endif
712
713} // FIN namespace SOPHYA
Note: See TracBrowser for help on using the repository browser.