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

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

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

Reza, 14/11/2011

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