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

Last change on this file since 2585 was 2585, checked in by cmv, 21 years ago

Correction bug Multiply segment gault cmv 30/07/04

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