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

Last change on this file since 2915 was 2915, checked in by ansari, 20 years ago

Amelioration de la classe Range - permettant une valeur symbolique pour specifier le dernier index (last()) - Reza 22/02/2006

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