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

Last change on this file since 3831 was 3831, checked in by ansari, 15 years ago

Introduction et gestion du flag preprocesseur NEED_EXT_DECL_TEMP pour declaration extern des classes template avec instantiation explicite (pb dynamic_cast sur Mac OS 10.6), Reza 05/08/2010

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