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

Last change on this file since 3113 was 3101, checked in by ansari, 19 years ago

Petits ajouts ds les commentaires pour doxygen TArray, TMatrix - Reza 02/11/2006

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