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

Last change on this file since 4039 was 4035, checked in by ansari, 14 years ago

1/ modif mineure ds TArray<T>::::ReadASCII() au print level global de BaseArray
2/ Correction bug gestion memoire au niveau des constructeurs de copie TArray/TMatrix/TVector
avec un BaseArray en argument. Ajout argument optionnel bool pack a ces constructeurs
3/ On autorise desormais la creation des objets TArray/TMatrix/TVector par constructeur de
copie sur des objets non alloues

Reza, 14/11/2011

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