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

Last change on this file since 3072 was 2927, checked in by ansari, 19 years ago

Instanciation explicite TArray/TMatrix/TVector <int_2> <uint_2> <unit_4> <uint_8> + enregistrement handler PPF - Reza 3/4/2006

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