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

Last change on this file since 3072 was 2927, checked in by ansari, 19 years ago

Instanciation explicite TArray/TMatrix/TVector <int_2> <uint_2> <unit_4> <uint_8> + enregistrement handler PPF - Reza 3/4/2006

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