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

Last change on this file since 3468 was 3101, checked in by ansari, 19 years ago

Petits ajouts ds les commentaires pour doxygen TArray, TMatrix - Reza 02/11/2006

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