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

Last change on this file since 2585 was 2585, checked in by cmv, 21 years ago

Correction bug Multiply segment gault cmv 30/07/04

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