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

Last change on this file since 2806 was 2788, checked in by ansari, 20 years ago

corrections pour impression/dump ascii des tableaux/matrices - Reza 30 Mai 2005

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