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

Last change on this file since 3810 was 3751, checked in by ansari, 16 years ago

Prise en charge de float 128 bits (r_16, complex<r_16>) par TArray<T>,TMatrix<T>,TVector<T>. activation par le flag de compilation SO_LDBLE128

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