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

Last change on this file since 4033 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
Line 
1// $Id: tmatrix.cc,v 1.40 2010-08-05 12:16:19 ansari Exp $
2// C.Magneville 04/99
3#include "sopnamsp.h"
4#include "machdefs.h"
5#include <iostream>
6#include <iomanip>
7#include <stdio.h>
8#include <stdlib.h>
9#include "pexceptions.h"
10
11#define TMATRIX_CC_BFILE // avoid extern template declarations
12#include "tmatrix.h"
13
14namespace SOPHYA {
15
16/*!
17 \class TMatrix
18 \ingroup TArray
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.
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
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
34 \b Matrix is a typedef for double precision floating point matrix ( TMatrix<r_8> ).
35
36 \sa SOPHYA::TArray SOPHYA::TVector
37 \sa SOPHYA::Range SOPHYA::Sequence
38 \sa SOPHYA::MathArray SOPHYA::SimpleMatrixOperation
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
61 */
62
63////////////////////////////////////////////////////////////////
64//**** Createur, Destructeur
65//! Default constructor
66template <class T>
67TMatrix<T>::TMatrix()
68// Constructeur par defaut.
69 : TArray<T>()
70{
71 arrtype_ = 1; // Type = Matrix
72}
73
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
79 \param fzero : if \b true , set matrix elements to zero
80 \sa ReSize
81 */
82template <class T>
83TMatrix<T>::TMatrix(sa_size_t r,sa_size_t c, short mm, bool fzero)
84// Construit une matrice de r lignes et c colonnes.
85 : TArray<T>()
86{
87 if ( (r == 0) || (c == 0) )
88 throw ParmError("TMatrix<T>::TMatrix(sa_size_t r,sa_size_t c) NRows or NCols = 0");
89 arrtype_ = 1; // Type = Matrix
90 ReSize(r, c, mm, fzero);
91}
92
93//! Constructor by copy
94/*!
95 \warning datas are \b SHARED with \b a.
96 \sa NDataBlock::NDataBlock(const NDataBlock<T>&)
97*/
98template <class T>
99TMatrix<T>::TMatrix(const TMatrix<T>& a)
100// Constructeur par copie
101 : TArray<T>(a)
102{
103 arrtype_ = 1; // Type = Matrix
104 UpdateMemoryMapping(a, SameMemoryMapping);
105}
106
107//! Constructor by copy
108/*!
109 \param share : if true, share data. If false copy data
110 */
111template <class T>
112TMatrix<T>::TMatrix(const TMatrix<T>& a, bool share)
113// Constructeur par copie avec possibilite de forcer le partage ou non.
114: TArray<T>(a, share)
115{
116 arrtype_ = 1; // Type = Matrix
117 UpdateMemoryMapping(a, SameMemoryMapping);
118}
119
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 */
125template <class T>
126TMatrix<T>::TMatrix(const TArray<T>& a, bool share)
127: TArray<T>(a, share)
128{
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 }
136 arrtype_ = 1; // Type = Matrix
137 UpdateMemoryMapping(a, SameMemoryMapping);
138}
139
140//! Constructor of a matrix from a TArray \b a , with a different data type
141template <class T>
142TMatrix<T>::TMatrix(const BaseArray& a)
143: TArray<T>()
144{
145 arrtype_ = 1; // Type = Matrix
146 UpdateMemoryMapping(a, SameMemoryMapping);
147 SetBA(a);
148}
149
150
151
152//! Destructor
153template <class T>
154TMatrix<T>::~TMatrix()
155{
156}
157
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*/
163template <class T>
164TArray<T>& TMatrix<T>::Set(const TArray<T>& a)
165{
166 if (a.NbDimensions() > 2)
167 throw SzMismatchError("TMatrix<T>::Set(const TArray<T>& a) a.NbDimensions() > 2");
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");
170 TArray<T>::Set(a);
171 if (NbDimensions() == 1) {
172 size_[1] = 1;
173 step_[1] = size_[0]*step_[0];
174 ndim_ = 2;
175 }
176 UpdateMemoryMapping(*this, SameMemoryMapping);
177 return(*this);
178}
179
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");
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");
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
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)
206 \param fzero : if \b true , set matrix elements to zero
207 */
208template <class T>
209void TMatrix<T>::ReSize(sa_size_t r, sa_size_t c, short mm, bool fzero)
210{
211 if(r==0||c==0)
212 throw(SzMismatchError("TMatrix::ReSize r or c==0 "));
213 if ((arrtype_ == 2) && (r > 1) && (c > 1))
214 throw(SzMismatchError("TMatrix::ReSize r>1&&c>1 for Vector "));
215 sa_size_t size[BASEARRAY_MAXNDIMS];
216 for(int_4 kk=0; kk<BASEARRAY_MAXNDIMS; kk++) size[kk] = 0;
217 if (mm == SameMemoryMapping) mm = GetMemoryMapping();
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 }
226 TArray<T>::ReSize(2, size, 1, fzero);
227 UpdateMemoryMapping(mm);
228}
229
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 */
239template <class T>
240void TMatrix<T>::Realloc(sa_size_t r,sa_size_t c, short mm, bool force)
241{
242 if(r==0||c==0)
243 throw(SzMismatchError("TMatrix::Realloc r or c==0 "));
244 if ((arrtype_ == 2) && (r > 1) && (c > 1))
245 throw(SzMismatchError("TMatrix::Realloc r>1&&c>1 for Vector "));
246 sa_size_t size[BASEARRAY_MAXNDIMS];
247 for(int_4 kk=0; kk<BASEARRAY_MAXNDIMS; kk++) size[kk] = 0;
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 }
257 TArray<T>::Realloc(2, size, 1, force);
258 UpdateMemoryMapping(mm);
259}
260
261// $CHECK$ Reza 03/2000 Doit-on declarer cette methode const ?
262//! Return a submatrix define by \b Range \b rline and \b rcol
263template <class T>
264TMatrix<T> TMatrix<T>::SubMatrix(Range rline, Range rcol) const
265{
266 Range rx=Range::first();
267 Range ry=Range::first();
268 short mm = GetMemoryMapping();
269 if (mm == CMemoryMapping) { rx = rcol; ry = rline; }
270 else { ry = rcol; rx = rline; }
271 TMatrix sm(SubArray(rx, ry, Range::first(), Range::first(), Range::first(), false), true);
272 sm.UpdateMemoryMapping(mm);
273 return(sm);
274}
275
276////////////////////////////////////////////////////////////////
277// Transposition
278//! Transpose matrix in place, by changing the memory mapping
279template <class T>
280TMatrix<T>& TMatrix<T>::TransposeSelf()
281{
282 short vt = (marowi_ == veceli_) ? ColumnVector : RowVector;
283 int_4 rci = macoli_;
284 macoli_ = marowi_;
285 marowi_ = rci;
286 veceli_ = (vt == ColumnVector ) ? marowi_ : macoli_;
287 return(*this);
288}
289
290
291//! Returns the transpose of the original matrix.
292/*!
293 The data is shared between the two matrices
294 \return return a new matrix
295 */
296template <class T>
297TMatrix<T> TMatrix<T>::Transpose() const
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/*!
306 \param mm : define the memory mapping type
307 (SameMemoryMapping,CMemoryMapping,FortranMemoryMapping)
308 \return return a new matrix
309 */
310template <class T>
311TMatrix<T> TMatrix<T>::Transpose(short mm) const
312{
313 if (mm == SameMemoryMapping) mm = GetMemoryMapping();
314 TMatrix<T> tm(NCols(), NRows(), mm);
315 for(sa_size_t i=0; i<NRows(); i++)
316 for(sa_size_t j=0; j<NCols(); j++)
317 tm(j,i) = (*this)(i,j);
318 return tm;
319}
320
321//! Rearrange data in memory according to \b mm
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 */
327template <class T>
328TMatrix<T> TMatrix<T>::Rearrange(short mm) const
329{
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
337 TMatrix<T> tm(NRows(), NCols(), mm);
338 for(sa_size_t i=0; i<NRows(); i++)
339 for(sa_size_t j=0; j<NCols(); j++)
340 tm(i,j) = (*this)(i,j);
341 return tm;
342}
343
344//! Set the matrix to the identity matrix \b imx
345template <class T>
346TMatrix<T>& TMatrix<T>::SetIdentity(IdentityMatrix imx)
347{
348 if (ndim_ == 0) {
349 sa_size_t sz = imx.Size();
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()") ;
356 *this = (T) 0;
357 for(sa_size_t i=0; i<NRows(); i++) (*this)(i,i) = diag;
358
359 return (*this);
360}
361
362
363
364////////////////////////////////////////////////////////////////
365//**** Impression
366//! Return info on number of rows, column and type \b T
367template <class T>
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
378//! Print matrix
379/*!
380 \param os : output stream
381 \param maxprt : maximum numer of print
382 \param si : if true, display attached DvList
383 \param ascd : if true, suppresses the display of line numbers,
384 suitable for ascii dump format.
385 \sa SetMaxPrint
386 */
387template <class T>
388void TMatrix<T>::Print(ostream& os, sa_size_t maxprt, bool si, bool ascd) const
389{
390 if (maxprt < 0) maxprt = max_nprt_;
391 sa_size_t npr = 0;
392
393 // keep stream's io flags
394 // ios_base::fmtflags ioflg = os.flags(); compil pas sur OSF-cxx
395 // os << right ; compile pas sur OSF-cxx
396
397 Show(os, si);
398 if (ndim_ < 1) return;
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
410 sa_size_t kc,kr;
411 for(kr=0; kr<size_[marowi_]; kr++) {
412 if ( (size_[marowi_] > 1) && (size_[macoli_] > 10) && !ascd)
413 os << "----- Line= " << kr << endl;
414 for(kc=0; kc<size_[macoli_]; kc++) {
415 if(kc > 0) os << " ";
416 os << setw(prtw) << (*this)(kr, kc); npr++;
417 if (npr >= (sa_size_t) maxprt) {
418 if (npr < totsize_) os << "\n .... " << endl; return;
419 }
420 }
421 os << endl;
422 }
423 os << endl;
424 //compile pas sur OSF-cxx os.flags(ioflg); // reset stream io flags
425}
426
427//////////////////////////////////////////////////////////
428/////////////// Multiplication matricielle ///////////////
429//////////////////////////////////////////////////////////
430
431//! Return the matrix product C = (*this)*B
432/*!
433 \param mm : define the memory mapping type for the return matrix
434 */
435////////////// Routine de base sans optimisation //////////////
436/*
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);
444
445 const T * pea;
446 const T * peb;
447 T sum;
448 sa_size_t r,c,k;
449 sa_size_t stepa = Step(ColsKA());
450 sa_size_t stepb = b.Step(b.RowsKA());
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}
463*/
464
465////////////// Routine optimisee //////////////
466template <class T>
467TMatrix<T> TMatrix<T>::Multiply(const TMatrix<T>& b, short mm) const
468// Calcul de C= rm = A*B (A=*this)
469// Remember: C-like matrices are column packed
470// Fortan-like matrices are line packed
471{
472 if (NCols() != b.NRows())
473 throw(SzMismatchError("TMatrix<T>::Multiply(b) NCols() != b.NRows() ") );
474
475 // Commentaire: pas de difference de vitesse notable selon le mapping de la matrice produit "rm"
476 if (mm == SameMemoryMapping) mm = GetMemoryMapping();
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
483 // Taille totale des matrices A et B
484 size_t totsiza = this->DataBlock().Size();
485 size_t totsizb = b.DataBlock().Size();
486
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
504 sa_size_t r,c,k;
505 T sum;
506 const T * pe;
507
508
509 /////////////////////////////////
510 // Pas d'optimisation demandee //
511 /////////////////////////////////
512
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 }
528 return rm;
529 }
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) {
537 //cout<<"A.col packed && B.row packed "<<stepa<<" "<<stepb<<endl;
538 T * pea = new T[NCols()];
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;
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) {
560 //cout<<"A.col packed && B.row not packed "<<stepa<<" "<<stepb<<endl;
561 const T * pea;
562 T * peb = new T[NCols()];
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;
574 return rm;
575 }
576
577
578 //////////////////////////////////////////////////
579 // A.col n'est pas packed et B.row est packed //
580 //////////////////////////////////////////////////
581
582 if(stepa!=1 && stepb==1) {
583 //cout<<"A.col not packed && B.row packed "<<stepa<<" "<<stepb<<endl;
584 T * pea = new T[NCols()];
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;
597 return rm;
598 }
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) {
628 //cout<<"A.col not packed && B.row not packed ==> optimize on B "<<stepa<<" "<<stepb<<endl;
629 const T * pea;
630 T * peb = new T[NCols()];
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;
642 return rm;
643 }
644
645 //---- stepa>=stepb
646
647 if(stepa!=1 && stepb!=1) {
648 //cout<<"A.col not packed && B.row not packed ==> optimize on A "<<stepa<<" "<<stepb<<endl;
649 T * pea = new T[NCols()];
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;
662 return rm;
663 }
664
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 !!! ") );
671 return rm;
672
673}
674
675
676///////////////////////////////////////////////////////////////
677#ifdef __CXX_PRAGMA_TEMPLATES__
678#pragma define_template TMatrix<uint_1>
679#pragma define_template TMatrix<uint_2>
680#pragma define_template TMatrix<uint_4>
681#pragma define_template TMatrix<uint_8>
682#pragma define_template TMatrix<int_1>
683#pragma define_template TMatrix<int_2>
684#pragma define_template TMatrix<int_4>
685#pragma define_template TMatrix<int_8>
686#pragma define_template TMatrix<r_4>
687#pragma define_template TMatrix<r_8>
688#pragma define_template TMatrix< complex<r_4> >
689#pragma define_template TMatrix< complex<r_8> >
690#ifdef SO_LDBLE128
691#pragma define_template TMatrix<r_16>
692#pragma define_template TMatrix< complex<r_16> >
693#endif
694#endif
695
696#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
697template class TMatrix<uint_1>;
698template class TMatrix<uint_2>;
699template class TMatrix<uint_4>;
700template class TMatrix<uint_8>;
701template class TMatrix<int_1>;
702template class TMatrix<int_2>;
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> >;
709#ifdef SO_LDBLE128
710template class TMatrix<r_16>;
711template class TMatrix< complex<r_16> >;
712#endif
713#endif
714
715} // FIN namespace SOPHYA
Note: See TracBrowser for help on using the repository browser.