| [658] | 1 | // $Id: tmatrix.cc,v 1.1.1.1 1999-11-26 16:37:12 ansari Exp $
 | 
|---|
 | 2 | //                         C.Magneville          04/99
 | 
|---|
 | 3 | #include "machdefs.h"
 | 
|---|
 | 4 | #include <stdio.h>
 | 
|---|
 | 5 | #include <stdlib.h>
 | 
|---|
 | 6 | #include <iostream.h>
 | 
|---|
 | 7 | #include <values.h>
 | 
|---|
 | 8 | #include <complex>
 | 
|---|
 | 9 | #include "pexceptions.h"
 | 
|---|
 | 10 | #include "tmatrix.h"
 | 
|---|
 | 11 | #include "objfio.h"
 | 
|---|
 | 12 | 
 | 
|---|
 | 13 | ////////////////////////////////////////////////////////////////
 | 
|---|
 | 14 | //**** Createur, Destructeur
 | 
|---|
 | 15 | 
 | 
|---|
 | 16 | template <class T>
 | 
|---|
 | 17 | TMatrix<T>::TMatrix()
 | 
|---|
 | 18 | // Constructeur par defaut.
 | 
|---|
 | 19 | : mNr(0), mNc(0), mNDBlock()
 | 
|---|
 | 20 | {
 | 
|---|
 | 21 | }
 | 
|---|
 | 22 | 
 | 
|---|
 | 23 | template <class T>
 | 
|---|
 | 24 | TMatrix<T>::TMatrix(uint_4 r,uint_4 c)
 | 
|---|
 | 25 | // Construit une matrice de r lignes et c colonnes.
 | 
|---|
 | 26 | : mNr(r), mNc(c), mNDBlock(r*c)
 | 
|---|
 | 27 | {
 | 
|---|
 | 28 | }
 | 
|---|
 | 29 | 
 | 
|---|
 | 30 | template <class T>
 | 
|---|
 | 31 | TMatrix<T>::TMatrix(uint_4 r,uint_4 c,T* values,Bridge* br)
 | 
|---|
 | 32 | // Construit une matrice de r lignes et c colonnes. On fournit
 | 
|---|
 | 33 | // le tableau des valeurs et eventuellement un Bridge.
 | 
|---|
 | 34 | : mNr(r), mNc(c), mNDBlock(r*c,values,br)
 | 
|---|
 | 35 | {
 | 
|---|
 | 36 | }
 | 
|---|
 | 37 | 
 | 
|---|
 | 38 | template <class T>
 | 
|---|
 | 39 | TMatrix<T>::TMatrix(const TMatrix<T>& a)
 | 
|---|
 | 40 | // Constructeur par copie (partage si "a" temporaire).
 | 
|---|
 | 41 | : mNr(a.mNr), mNc(a.mNc), mNDBlock(a.mNDBlock)
 | 
|---|
 | 42 | {
 | 
|---|
 | 43 | }
 | 
|---|
 | 44 | 
 | 
|---|
 | 45 | template <class T>
 | 
|---|
 | 46 | TMatrix<T>::TMatrix(const TMatrix<T>& a,bool share)
 | 
|---|
 | 47 | // Constructeur par copie avec possibilite de forcer le partage ou non.
 | 
|---|
 | 48 | : mNr(a.mNr), mNc(a.mNc), mNDBlock(a.mNDBlock,share)
 | 
|---|
 | 49 | {
 | 
|---|
 | 50 | }
 | 
|---|
 | 51 | 
 | 
|---|
 | 52 | template <class T>
 | 
|---|
 | 53 | TMatrix<T>::~TMatrix()
 | 
|---|
 | 54 | // Destructeur
 | 
|---|
 | 55 | {
 | 
|---|
 | 56 | }
 | 
|---|
 | 57 | 
 | 
|---|
 | 58 | ////////////////////////////////////////////////////////////////
 | 
|---|
 | 59 | // Operations matricielles
 | 
|---|
 | 60 | template <class T>
 | 
|---|
 | 61 | TMatrix<T> TMatrix<T>::Transpose(void) const
 | 
|---|
 | 62 | // Transposition
 | 
|---|
 | 63 | {
 | 
|---|
 | 64 | TMatrix<T> a; a.Clone(*this); a.SetTemp(true);
 | 
|---|
 | 65 | a.mNr = mNc; a.mNc = mNr;
 | 
|---|
 | 66 | {for(uint_4 i=0; i<mNr; i++)
 | 
|---|
 | 67 |   for(uint_4 j=0; j<mNc; j++) {
 | 
|---|
 | 68 |     a(j,i) = (*this)(i,j);
 | 
|---|
 | 69 | }}
 | 
|---|
 | 70 | return a;
 | 
|---|
 | 71 | }
 | 
|---|
 | 72 | 
 | 
|---|
 | 73 | ////////////////////////////////////////////////////////////////
 | 
|---|
 | 74 | //**** Impression
 | 
|---|
 | 75 | 
 | 
|---|
 | 76 | template <class T>
 | 
|---|
 | 77 | void TMatrix<T>::Print(ostream& os,int lp
 | 
|---|
 | 78 |                  ,uint_4 i0,uint_4 ni,uint_4 j0,uint_4 nj) const
 | 
|---|
 | 79 | // Impression de la sous-matrice (i:i+ni-1,i:j+nj-1)
 | 
|---|
 | 80 | {
 | 
|---|
 | 81 | os<<"TMatrix::Print("<<mNr<<","<<mNc<<")"<<endl;
 | 
|---|
 | 82 | if(lp>0)
 | 
|---|
 | 83 |   {os<<"       this="<<this<<endl; mNDBlock.Print(0,0);}
 | 
|---|
 | 84 | if(mNr==0 || mNc==0) return;
 | 
|---|
 | 85 | if(i0>=mNr || j0>=mNc || ni==0 || nj==0) return;
 | 
|---|
 | 86 | uint_4 i1 = i0+ni; if(i1>mNr) i1 = mNr;
 | 
|---|
 | 87 | uint_4 j1 = j0+nj; if(j1>mNc) j1 = mNc;
 | 
|---|
 | 88 | for(uint_4 i=i0;i<i1;i++) {
 | 
|---|
 | 89 |   for(uint_4 j=j0;j<j1;j++) cout<<" "<<(*this)(i,j);
 | 
|---|
 | 90 |   cout<<endl;
 | 
|---|
 | 91 | }
 | 
|---|
 | 92 | }
 | 
|---|
 | 93 | 
 | 
|---|
 | 94 | ////////////////////////////////////////////////////////////////
 | 
|---|
 | 95 | //**** Surcharge de *= (INPLACE): TMatrix *= TMatrix;
 | 
|---|
 | 96 | 
 | 
|---|
 | 97 | template <class T>
 | 
|---|
 | 98 | TMatrix<T>& TMatrix<T>::operator *= (const TMatrix<T>& a)
 | 
|---|
 | 99 | // A = A*B  -> A(n,m) = A(n,m)*B(m,m)
 | 
|---|
 | 100 | {
 | 
|---|
 | 101 | uint_4 ndata = mNr*mNc;
 | 
|---|
 | 102 | if(ndata==0 || mNc!=a.mNr || a.mNr!=a.mNc)
 | 
|---|
 | 103 |   throw(SzMismatchError("TMatrix::operator*=A size mismatch"));
 | 
|---|
 | 104 | // A(i,j) = Sum(k) A(i,k)*B(k,j) ... il faut sauver la ligne "i" de A
 | 
|---|
 | 105 | // Vecteur oi   : vecteur ou est sauve la ligne i de la matrice *this
 | 
|---|
 | 106 | //                oi,oe = pointeur de debut et de fin du vecteur temporaire
 | 
|---|
 | 107 | //                oij   = pointeur parcourant le vecteur oi
 | 
|---|
 | 108 | // Matrice *this: i     = pointeur du debut de la ligne i
 | 
|---|
 | 109 | //                ij    = pointeur parcourant la ligne i
 | 
|---|
 | 110 | // Matrice a    : aj    = pointeur de debut de la colonne j
 | 
|---|
 | 111 | //                aji   = pointeur parcourant la colonne j
 | 
|---|
 | 112 | T* oi = new T[mNc]; T* oe = oi+mNc;
 | 
|---|
 | 113 | for(T *i=Data(); i<Data()+ndata; i+=mNc) {
 | 
|---|
 | 114 |   {for(T *oij=oi,*ij=i; oij<oe;) *oij++ = *ij++;}
 | 
|---|
 | 115 |   {for(T *ij=i,*aj=const_cast<T *>(a.Data()); aj<a.Data()+a.mNc; ij++,aj++) {
 | 
|---|
 | 116 |     T sum = 0;
 | 
|---|
 | 117 |     for(T *oij=oi,*aji=aj; oij<oe; oij++,aji+=a.mNc) sum += *oij * *aji;
 | 
|---|
 | 118 |     *ij = sum;
 | 
|---|
 | 119 |   }}
 | 
|---|
 | 120 | }
 | 
|---|
 | 121 | delete [] oi;
 | 
|---|
 | 122 | return *this;
 | 
|---|
 | 123 | }
 | 
|---|
 | 124 | 
 | 
|---|
 | 125 | ////////////////////////////////////////////////////////////////
 | 
|---|
 | 126 | //**** Pour surcharge d'operateurs C = A (+,-,*,/) B
 | 
|---|
 | 127 | 
 | 
|---|
 | 128 | template <class T> TMatrix<T> TMatrix<T>::Add(const TMatrix<T>& b) const
 | 
|---|
 | 129 | {
 | 
|---|
 | 130 | if(mNr!=b.mNr || mNc!=b.mNc)
 | 
|---|
 | 131 |     throw(SzMismatchError("TMatrix operator C=A+B size mismatch\n"));
 | 
|---|
 | 132 | TMatrix<T> result; result.SetTemp(true); result.mNr=mNr; result.mNc=mNc;
 | 
|---|
 | 133 | result.mNDBlock = mNDBlock+b.mNDBlock;
 | 
|---|
 | 134 | return result;
 | 
|---|
 | 135 | }
 | 
|---|
 | 136 | 
 | 
|---|
 | 137 | template <class T> TMatrix<T> TMatrix<T>::Sub(const TMatrix<T>& b) const
 | 
|---|
 | 138 | {
 | 
|---|
 | 139 | if(mNr!=b.mNr || mNc!=b.mNc)
 | 
|---|
 | 140 |     throw(SzMismatchError("TMatrix operator C=A-B size mismatch\n"));
 | 
|---|
 | 141 | TMatrix<T> result; result.SetTemp(true); result.mNr=mNr; result.mNc=mNc;
 | 
|---|
 | 142 | result.mNDBlock = mNDBlock-b.mNDBlock;
 | 
|---|
 | 143 | return result;
 | 
|---|
 | 144 | }
 | 
|---|
 | 145 | 
 | 
|---|
 | 146 | template <class T> TMatrix<T> TMatrix<T>::Mul(const TMatrix<T>& b) const
 | 
|---|
 | 147 | // C = A(this)*B : Cij = Aik Bkj (allocation forcee dans tous les cas)
 | 
|---|
 | 148 | {
 | 
|---|
 | 149 | if(mNr==0 || mNc==0 || b.mNc==0 || mNc!=b.mNr)
 | 
|---|
 | 150 |   throw(SzMismatchError("TMatrix operator C=A*B size mismatch\n"));
 | 
|---|
 | 151 | TMatrix<T> r; r.SetTemp(true); r.ReSize(mNr,b.mNc);
 | 
|---|
 | 152 | T *ai,*aik,*bj,*bkj,*ri,*rij;
 | 
|---|
 | 153 | for(ri=const_cast<T *>(r.Data()),ai=const_cast<T *>(Data());
 | 
|---|
 | 154 |     ri<r.Data()+r.mNr*r.mNc;ri+=r.mNc,ai+=mNc) {
 | 
|---|
 | 155 |   for(rij=ri,bj=const_cast<T *>(b.Data());rij<ri+r.mNc;rij++,bj++) {
 | 
|---|
 | 156 |     *rij = 0;
 | 
|---|
 | 157 |     for(aik=ai,bkj=bj;aik<ai+mNc;aik++,bkj+=b.mNc) *rij += *aik * *bkj;
 | 
|---|
 | 158 |   }
 | 
|---|
 | 159 | }
 | 
|---|
 | 160 | return r;
 | 
|---|
 | 161 | }
 | 
|---|
 | 162 | 
 | 
|---|
 | 163 | ////////////////////////////////////////////////////////////////
 | 
|---|
 | 164 | //**** Pour gestion des lignes et des colonnes
 | 
|---|
 | 165 | 
 | 
|---|
 | 166 | template <class T> TMatrixRC<T> TMatrix<T>::Row(uint_4 r) const
 | 
|---|
 | 167 | {
 | 
|---|
 | 168 | TMatrixRC<T> rc((TMatrix<T>&)*this, TmatrixRow, r);
 | 
|---|
 | 169 | return rc;
 | 
|---|
 | 170 | }
 | 
|---|
 | 171 | 
 | 
|---|
 | 172 | template <class T> TMatrixRC<T> TMatrix<T>::Col(uint_4 c) const
 | 
|---|
 | 173 | {
 | 
|---|
 | 174 | TMatrixRC<T> rc((TMatrix<T>&)*this, TmatrixCol, c);
 | 
|---|
 | 175 | return rc;
 | 
|---|
 | 176 | }
 | 
|---|
 | 177 | 
 | 
|---|
 | 178 | template <class T> TMatrixRC<T> TMatrix<T>::Diag() const
 | 
|---|
 | 179 | {
 | 
|---|
 | 180 | TMatrixRC<T> rc((TMatrix<T>&)*this, TmatrixDiag);
 | 
|---|
 | 181 | return rc;
 | 
|---|
 | 182 | }
 | 
|---|
 | 183 | 
 | 
|---|
 | 184 | ////////////////////////////////////////////////////////////////
 | 
|---|
 | 185 | //**** Pour inversion
 | 
|---|
 | 186 | #ifndef M_LN2
 | 
|---|
 | 187 | #define M_LN2 0.69314718055994530942
 | 
|---|
 | 188 | #endif
 | 
|---|
 | 189 | #ifndef LN_MINDOUBLE
 | 
|---|
 | 190 | #define LN_MINDOUBLE  (M_LN2 * (DMINEXP - 1))
 | 
|---|
 | 191 | #endif
 | 
|---|
 | 192 | #ifndef LN_MAXDOUBLE
 | 
|---|
 | 193 | #define LN_MAXDOUBLE  (M_LN2 * DMAXEXP)
 | 
|---|
 | 194 | #endif
 | 
|---|
 | 195 | 
 | 
|---|
 | 196 | r_8 TMatrix<r_8>::GausPiv(TMatrix<r_8>& a, TMatrix<r_8>& b)
 | 
|---|
 | 197 | // Pivot de Gauss
 | 
|---|
 | 198 | // * Attention: egcs impose que cette fonction soit mise dans le .cc
 | 
|---|
 | 199 | //              avant ::Inverse() (car Inverse() l'utilise)
 | 
|---|
 | 200 | // {TMatrix A(a); TMatrix B(b); return (r_8) TMatrix::GausPiv(A,B);}
 | 
|---|
 | 201 | {
 | 
|---|
 | 202 | uint_4 n = a.NRows();
 | 
|---|
 | 203 | if(n!=b.NRows())
 | 
|---|
 | 204 |   throw(SzMismatchError("TMatrix::GausPiv size mismatch\n"));
 | 
|---|
 | 205 | // On fait une normalisation un peu brutale...
 | 
|---|
 | 206 | double vmin=MAXDOUBLE;
 | 
|---|
 | 207 | double vmax=0;
 | 
|---|
 | 208 | for(uint_4 iii=0; iii<a.NRows(); iii++)
 | 
|---|
 | 209 |   for(uint_4 jjj=0; jjj<a.NCols(); jjj++) {
 | 
|---|
 | 210 |     double v = TMatrixRC<r_8>::Abs_Value(a(iii,jjj));
 | 
|---|
 | 211 |     if(v>vmax) vmax = v;
 | 
|---|
 | 212 |     if(v<vmin && v>0) vmin = v;
 | 
|---|
 | 213 | }
 | 
|---|
 | 214 | double nrm = sqrt(vmin*vmax);
 | 
|---|
 | 215 | if(nrm > 1.e5 || nrm < 1.e-5) {
 | 
|---|
 | 216 |   a /= nrm;
 | 
|---|
 | 217 |   b /= nrm;
 | 
|---|
 | 218 |   //cout << "normalisation matrice " << nrm << endl;
 | 
|---|
 | 219 | } else nrm=1;
 | 
|---|
 | 220 | 
 | 
|---|
 | 221 | double det = 1.0;
 | 
|---|
 | 222 | if(nrm != 1) {
 | 
|---|
 | 223 |   double ld = a.NRows() * log(nrm);
 | 
|---|
 | 224 |   if (ld <= LN_MINDOUBLE || ld >= LN_MAXDOUBLE) {
 | 
|---|
 | 225 |    // cerr << "TMatrix warning, overflow for det" << endl;
 | 
|---|
 | 226 |   } else {
 | 
|---|
 | 227 |     det = exp(ld);
 | 
|---|
 | 228 |   }
 | 
|---|
 | 229 | }
 | 
|---|
 | 230 | 
 | 
|---|
 | 231 | TMatrixRC<r_8> pivRowa(a,TmatrixRow);
 | 
|---|
 | 232 | TMatrixRC<r_8> pivRowb(b,TmatrixRow);
 | 
|---|
 | 233 | 
 | 
|---|
 | 234 | for(uint_4 k=0; k<n-1; k++) {
 | 
|---|
 | 235 |   uint_4 iPiv = a.Col(k).IMaxAbs(k);
 | 
|---|
 | 236 |   if(iPiv != k) {
 | 
|---|
 | 237 |     TMatrixRC<r_8> aIPiv(a.Row(iPiv));
 | 
|---|
 | 238 |     TMatrixRC<r_8> aK(a.Row(k));
 | 
|---|
 | 239 |     TMatrixRC<r_8>::Swap(aIPiv,aK);
 | 
|---|
 | 240 |     TMatrixRC<r_8> bIPiv(b.Row(iPiv));
 | 
|---|
 | 241 |     TMatrixRC<r_8> bK(b.Row(k));
 | 
|---|
 | 242 |     TMatrixRC<r_8>::Swap(bIPiv,bK);
 | 
|---|
 | 243 |   }
 | 
|---|
 | 244 |   double pivot = a(k,k);
 | 
|---|
 | 245 |   if (fabs(pivot) < 1.e-50) return 0.0;
 | 
|---|
 | 246 |   //det *= pivot;
 | 
|---|
 | 247 |   pivRowa.SetRow(k); // to avoid constructors
 | 
|---|
 | 248 |   pivRowb.SetRow(k);
 | 
|---|
 | 249 |   for (uint_4 i=k+1; i<n; i++) {
 | 
|---|
 | 250 |     double r = -a(i,k)/pivot;
 | 
|---|
 | 251 |     a.Row(i).LinComb(r, pivRowa); // + rapide que -= r * pivRowa
 | 
|---|
 | 252 |     b.Row(i).LinComb(r, pivRowb);
 | 
|---|
 | 253 |   }
 | 
|---|
 | 254 | }
 | 
|---|
 | 255 | det *= a(n-1, n-1);
 | 
|---|
 | 256 | 
 | 
|---|
 | 257 | // on remonte
 | 
|---|
 | 258 | for(uint_4 kk=n-1; kk>0; kk--) {
 | 
|---|
 | 259 |   double pivot = a(kk,kk);
 | 
|---|
 | 260 |   if (fabs(pivot) <= 1.e-50) return 0.0;
 | 
|---|
 | 261 |   pivRowa.SetRow(kk); // to avoid constructors
 | 
|---|
 | 262 |   pivRowb.SetRow(kk);
 | 
|---|
 | 263 |   for(uint_4 jj=0; jj<kk; jj++) {
 | 
|---|
 | 264 |     double r = -a(jj,kk)/pivot;
 | 
|---|
 | 265 |     a.Row(jj).LinComb(r, pivRowa);
 | 
|---|
 | 266 |     b.Row(jj).LinComb(r, pivRowb);
 | 
|---|
 | 267 |   }
 | 
|---|
 | 268 | }
 | 
|---|
 | 269 | 
 | 
|---|
 | 270 | for(uint_4 l=0; l<n; l++) {
 | 
|---|
 | 271 |   if (fabs(a(l,l)) <= 1.e-50) return 0.0;
 | 
|---|
 | 272 |   b.Row(l) /= a(l,l);
 | 
|---|
 | 273 | }
 | 
|---|
 | 274 | 
 | 
|---|
 | 275 | return det;
 | 
|---|
 | 276 | }
 | 
|---|
 | 277 | 
 | 
|---|
 | 278 | TMatrix<r_8> TMatrix<r_8>::Inverse() const
 | 
|---|
 | 279 | // Inversion
 | 
|---|
 | 280 | {
 | 
|---|
 | 281 | TMatrix<r_8> b(mNc,mNr); TMatrix<r_8> a(*this); b = 1.;
 | 
|---|
 | 282 | if(fabs(TMatrix<r_8>::GausPiv(a,b)) < 1.e-50)
 | 
|---|
 | 283 |   throw(MathExc("TMatrix Inverse() Singular OMatrix"));
 | 
|---|
 | 284 | return b;
 | 
|---|
 | 285 | }
 | 
|---|
 | 286 | 
 | 
|---|
 | 287 | #include "generalfit.h"
 | 
|---|
 | 288 | //////////////////////////////////////////////////////////
 | 
|---|
 | 289 | //**** Residus des fits
 | 
|---|
 | 290 | TMatrix<r_8> TMatrix<r_8>::FitResidus(GeneralFit& gfit
 | 
|---|
 | 291 |             ,double xorg,double yorg,double dx,double dy)
 | 
|---|
 | 292 | // Retourne une classe contenant les residus du fit ``gfit''.
 | 
|---|
 | 293 | // On suppose que x=j (colonnes) et y=i (lignes) pour m(i,j).
 | 
|---|
 | 294 | // Les coordonnees de l'element (i,j) sont :
 | 
|---|
 | 295 | //    (i,j) -> x = xorg+j*dx , y = yorg+i*dy
 | 
|---|
 | 296 | {
 | 
|---|
 | 297 | if(NCols()<=0||NRows()<=0)
 | 
|---|
 | 298 |   throw(SzMismatchError("TMatrix::FitResidus size mismatch\n"));
 | 
|---|
 | 299 | GeneralFunction* f = gfit.GetFunction();
 | 
|---|
 | 300 | if(f==NULL)
 | 
|---|
 | 301 |   throw(NullPtrError("TMatrix::FitResidus GeneraFit==NULL\n"));
 | 
|---|
 | 302 | int npar =  gfit.GetNPar();
 | 
|---|
 | 303 | if(npar==0)
 | 
|---|
 | 304 |   throw(SzMismatchError("TMatrix::FitResidus GeneraFit 0 parametre\n"));
 | 
|---|
 | 305 | double* par = new double[npar];
 | 
|---|
 | 306 | {for(int i=0;i<npar;i++) par[i] = gfit.GetParm(i);}
 | 
|---|
 | 307 | TMatrix<r_8> m(*this);
 | 
|---|
 | 308 | for(uint_4 i=0;i<NRows();i++) for(uint_4 j=0;j<NCols();j++) {
 | 
|---|
 | 309 |   double x[2] = {xorg+j*dx,yorg+i*dy};
 | 
|---|
 | 310 |   m(i,j) -= f->Value(x,par);
 | 
|---|
 | 311 | }
 | 
|---|
 | 312 | delete [] par;
 | 
|---|
 | 313 | return m;
 | 
|---|
 | 314 | }
 | 
|---|
 | 315 | 
 | 
|---|
 | 316 | TMatrix<r_8> TMatrix<r_8>::FitFunction(GeneralFit& gfit
 | 
|---|
 | 317 |             ,double xorg,double yorg,double dx,double dy)
 | 
|---|
 | 318 | // Retourne une classe contenant la fonction du fit ``gfit''.
 | 
|---|
 | 319 | // On suppose que x=j (colonnes) et y=i (lignes) pour m(i,j).
 | 
|---|
 | 320 | // Les coordonnees de l'element (i,j) sont :
 | 
|---|
 | 321 | //    (i,j) -> x = xorg + j*dx , y = yorg + i*dy
 | 
|---|
 | 322 | {
 | 
|---|
 | 323 | if(NCols()<=0||NRows()<=0)
 | 
|---|
 | 324 |   throw(SzMismatchError("TMatrix::FitFunction size mismatch\n"));
 | 
|---|
 | 325 | GeneralFunction* f = gfit.GetFunction();
 | 
|---|
 | 326 | if(f==NULL)
 | 
|---|
 | 327 |   throw(NullPtrError("TMatrix::FitFunction GeneraFit==NULL\n"));
 | 
|---|
 | 328 | int npar =  gfit.GetNPar();
 | 
|---|
 | 329 | if(npar==0)
 | 
|---|
 | 330 |   throw(SzMismatchError("TMatrix::FitFunction GeneraFit 0 parametre\n"));
 | 
|---|
 | 331 | double* par = new double[npar];
 | 
|---|
 | 332 | {for(int i=0;i<npar;i++) par[i] = gfit.GetParm(i);}
 | 
|---|
 | 333 | TMatrix<r_8> m(*this);
 | 
|---|
 | 334 | for(uint_4 i=0;i<NRows();i++) for(uint_4 j=0;j<NCols();j++) {
 | 
|---|
 | 335 |   double x[2] = {xorg+j*dx,yorg+i*dy};
 | 
|---|
 | 336 |   m(i,j) = f->Value(x,par);
 | 
|---|
 | 337 | }
 | 
|---|
 | 338 | delete [] par;
 | 
|---|
 | 339 | return m;
 | 
|---|
 | 340 | }
 | 
|---|
 | 341 | 
 | 
|---|
 | 342 | ///////////////////////////////////////////////////////////
 | 
|---|
 | 343 | // --------------------------------------------------------
 | 
|---|
 | 344 | //   Les objets delegues pour la gestion de persistance 
 | 
|---|
 | 345 | // --------------------------------------------------------
 | 
|---|
 | 346 | ///////////////////////////////////////////////////////////
 | 
|---|
 | 347 | 
 | 
|---|
 | 348 | template <class T>
 | 
|---|
 | 349 | FIO_TMatrix<T>::FIO_TMatrix()
 | 
|---|
 | 350 | {
 | 
|---|
 | 351 | dobj=new TMatrix<T>;
 | 
|---|
 | 352 | ownobj=true;
 | 
|---|
 | 353 | }
 | 
|---|
 | 354 | 
 | 
|---|
 | 355 | template <class T>
 | 
|---|
 | 356 | FIO_TMatrix<T>::FIO_TMatrix(string const & filename) 
 | 
|---|
 | 357 | {
 | 
|---|
 | 358 | dobj=new TMatrix<T>;
 | 
|---|
 | 359 | ownobj=true; 
 | 
|---|
 | 360 | Read(filename);
 | 
|---|
 | 361 | }
 | 
|---|
 | 362 | 
 | 
|---|
 | 363 | template <class T>
 | 
|---|
 | 364 | FIO_TMatrix<T>::FIO_TMatrix(const TMatrix<T> & obj) 
 | 
|---|
 | 365 | { 
 | 
|---|
 | 366 | dobj = new TMatrix<T>(obj);
 | 
|---|
 | 367 | ownobj=true; 
 | 
|---|
 | 368 | }
 | 
|---|
 | 369 | 
 | 
|---|
 | 370 | template <class T>
 | 
|---|
 | 371 | FIO_TMatrix<T>::FIO_TMatrix(TMatrix<T> * obj) 
 | 
|---|
 | 372 | { 
 | 
|---|
 | 373 | dobj = obj;
 | 
|---|
 | 374 | ownobj=false; 
 | 
|---|
 | 375 | }
 | 
|---|
 | 376 | 
 | 
|---|
 | 377 | template <class T>
 | 
|---|
 | 378 | FIO_TMatrix<T>::~FIO_TMatrix()
 | 
|---|
 | 379 | {
 | 
|---|
 | 380 | if (ownobj && dobj) delete dobj;
 | 
|---|
 | 381 | }
 | 
|---|
 | 382 | 
 | 
|---|
 | 383 | template <class T>
 | 
|---|
 | 384 | AnyDataObj* FIO_TMatrix<T>::DataObj()
 | 
|---|
 | 385 | {
 | 
|---|
 | 386 | return(dobj);
 | 
|---|
 | 387 | }
 | 
|---|
 | 388 | 
 | 
|---|
 | 389 | template <class T>
 | 
|---|
 | 390 | void FIO_TMatrix<T>::ReadSelf(PInPersist& is)
 | 
|---|
 | 391 | {
 | 
|---|
 | 392 | // On lit les 3 premiers uint_4
 | 
|---|
 | 393 | //  0: Numero de version,  1 : NRows,  2 : NCol
 | 
|---|
 | 394 | uint_4 itab[3];
 | 
|---|
 | 395 | is.Get(itab,3);
 | 
|---|
 | 396 | if (dobj == NULL) dobj = new TMatrix<T>(itab[1],itab[2]);
 | 
|---|
 | 397 | else dobj->ReSize(itab[1],itab[2]);
 | 
|---|
 | 398 | // On lit le NDataBlock
 | 
|---|
 | 399 | FIO_NDataBlock<T> fio_nd(&dobj->DataBlock());
 | 
|---|
 | 400 | fio_nd.Read(is);
 | 
|---|
 | 401 | }
 | 
|---|
 | 402 | 
 | 
|---|
 | 403 | template <class T>
 | 
|---|
 | 404 | void FIO_TMatrix<T>::WriteSelf(POutPersist& os) const
 | 
|---|
 | 405 | {
 | 
|---|
 | 406 | if (dobj == NULL)   return;
 | 
|---|
 | 407 | //  On ecrit 3 uint_4 .... 
 | 
|---|
 | 408 | //  0: Numero de version,  1 : NRows,  2 : NCol
 | 
|---|
 | 409 | uint_4 itab[3];
 | 
|---|
 | 410 |  itab[0] = 1;  // Numero de version a 1
 | 
|---|
 | 411 | itab[1] = dobj->NRows();
 | 
|---|
 | 412 | itab[2] = dobj->NCols();
 | 
|---|
 | 413 | os.Put(itab,3);
 | 
|---|
 | 414 | // On ecrit le NDataBlock
 | 
|---|
 | 415 | FIO_NDataBlock<T> fio_nd(&dobj->DataBlock());
 | 
|---|
 | 416 | fio_nd.Write(os);
 | 
|---|
 | 417 | }
 | 
|---|
 | 418 | 
 | 
|---|
 | 419 | ////////////////////////////////////////////////////////////////
 | 
|---|
 | 420 | // -------------------------------------------------------------
 | 
|---|
 | 421 | //   La classe de gestion des lignes et colonnes d'une matrice
 | 
|---|
 | 422 | // -------------------------------------------------------------
 | 
|---|
 | 423 | ////////////////////////////////////////////////////////////////
 | 
|---|
 | 424 | #include "tvector.h"
 | 
|---|
 | 425 | 
 | 
|---|
 | 426 | template <class T> TMatrixRC<T>::TMatrixRC()
 | 
|---|
 | 427 | : matrix(NULL), data(NULL), index(0), step(0)
 | 
|---|
 | 428 | {}
 | 
|---|
 | 429 | 
 | 
|---|
 | 430 | template <class T> TMatrixRC<T>::TMatrixRC(TMatrix<T>& m,TRCKind rckind,uint_4 ind)
 | 
|---|
 | 431 | : matrix(&m), data(Org(m,rckind,ind)),
 | 
|---|
 | 432 |   index(ind), step(Step(m,rckind)), kind(rckind)
 | 
|---|
 | 433 | {
 | 
|---|
 | 434 | if (kind == TmatrixDiag && m.mNc != m.mNr)
 | 
|---|
 | 435 |   throw(SzMismatchError("TMatrixRC::TMatrixRC(...,TmatrixDiag,...) size mismatch\n"));
 | 
|---|
 | 436 | }
 | 
|---|
 | 437 | 
 | 
|---|
 | 438 | template <class T> int_4 TMatrixRC<T>::Next()
 | 
|---|
 | 439 | {
 | 
|---|
 | 440 | if (!matrix || kind==TmatrixDiag) return -1;
 | 
|---|
 | 441 | index++;
 | 
|---|
 | 442 | if(kind == TmatrixRow) {
 | 
|---|
 | 443 |   if(index > (int_4)matrix->mNr) {index = (int_4)matrix->mNr; return -1;}
 | 
|---|
 | 444 |   data += matrix->mNc;
 | 
|---|
 | 445 | } else {
 | 
|---|
 | 446 |   if (index > (int_4)matrix->mNc) {index = (int_4)matrix->mNc; return -1;}
 | 
|---|
 | 447 |   data++;
 | 
|---|
 | 448 | }
 | 
|---|
 | 449 | return index;
 | 
|---|
 | 450 | }
 | 
|---|
 | 451 | 
 | 
|---|
 | 452 | template <class T> int_4 TMatrixRC<T>::Prev()
 | 
|---|
 | 453 | {
 | 
|---|
 | 454 | if (!matrix || kind == TmatrixDiag) return -1;
 | 
|---|
 | 455 | index--;
 | 
|---|
 | 456 | if(index < 0) {index = 0; return -1;}
 | 
|---|
 | 457 | if(kind == TmatrixRow) data -= matrix->mNc;
 | 
|---|
 | 458 | else data--;
 | 
|---|
 | 459 | return index;
 | 
|---|
 | 460 | }
 | 
|---|
 | 461 | 
 | 
|---|
 | 462 | template <class T> int_4 TMatrixRC<T>::SetCol(int_4 c)
 | 
|---|
 | 463 | {
 | 
|---|
 | 464 | if(!matrix) return -1;
 | 
|---|
 | 465 | if(c<0 || c>(int_4)matrix->mNc) return -1;
 | 
|---|
 | 466 | kind = TmatrixCol;
 | 
|---|
 | 467 | index = c;
 | 
|---|
 | 468 | step = Step(*matrix, TmatrixCol);
 | 
|---|
 | 469 | data = Org(*matrix, TmatrixCol, c);
 | 
|---|
 | 470 | return c;
 | 
|---|
 | 471 | }
 | 
|---|
 | 472 | 
 | 
|---|
 | 473 | template <class T> int_4 TMatrixRC<T>::SetRow(int_4 r)
 | 
|---|
 | 474 | {
 | 
|---|
 | 475 | if(!matrix) return -1;
 | 
|---|
 | 476 | if(r<0 && r>(int_4)matrix->mNr) return -1;
 | 
|---|
 | 477 | kind = TmatrixRow;
 | 
|---|
 | 478 | index = r;
 | 
|---|
 | 479 | step = Step(*matrix, TmatrixRow);
 | 
|---|
 | 480 | data = Org(*matrix, TmatrixRow, r);
 | 
|---|
 | 481 | return r;
 | 
|---|
 | 482 | }
 | 
|---|
 | 483 | 
 | 
|---|
 | 484 | template <class T> int_4 TMatrixRC<T>::SetDiag()
 | 
|---|
 | 485 | {
 | 
|---|
 | 486 | if (!matrix) return -1;
 | 
|---|
 | 487 | if (matrix->mNc != matrix->mNr)
 | 
|---|
 | 488 |   throw(SzMismatchError("TMatrixRC::SetDiag size mismatch\n"));
 | 
|---|
 | 489 | kind = TmatrixDiag;
 | 
|---|
 | 490 | index = 0;
 | 
|---|
 | 491 | step = Step(*matrix, TmatrixDiag);
 | 
|---|
 | 492 | data = Org(*matrix, TmatrixDiag);
 | 
|---|
 | 493 | return 0;
 | 
|---|
 | 494 | }
 | 
|---|
 | 495 | 
 | 
|---|
 | 496 | 
 | 
|---|
 | 497 | template <class T> TMatrixRC<T>& TMatrixRC<T>::operator = (const TMatrixRC<T>& rc)
 | 
|---|
 | 498 | {
 | 
|---|
 | 499 | matrix = rc.matrix;
 | 
|---|
 | 500 | data   = rc.data;
 | 
|---|
 | 501 | index  = rc.index;
 | 
|---|
 | 502 | step   = rc.step;
 | 
|---|
 | 503 | kind   = rc.kind;
 | 
|---|
 | 504 | return *this;
 | 
|---|
 | 505 | }
 | 
|---|
 | 506 | 
 | 
|---|
 | 507 | template <class T> TVector<T> TMatrixRC<T>::GetVect() const
 | 
|---|
 | 508 | {
 | 
|---|
 | 509 | TVector<T> v(NElts());
 | 
|---|
 | 510 | for (uint_4 i=0; i<NElts(); i++) v(i) = (*this)(i);
 | 
|---|
 | 511 | return v;
 | 
|---|
 | 512 | }
 | 
|---|
 | 513 | 
 | 
|---|
 | 514 | template <class T> TMatrixRC<T>& TMatrixRC<T>::operator += (const TMatrixRC<T>& rc)
 | 
|---|
 | 515 | {
 | 
|---|
 | 516 | if ( NElts() != rc.NElts() )
 | 
|---|
 | 517 |   throw(SzMismatchError("TMatrixRC::operator+= size mismatch\n"));
 | 
|---|
 | 518 | if ( kind != rc.kind )
 | 
|---|
 | 519 |   throw(SzMismatchError("TMatrixRC::operator+= type mismatch\n"));
 | 
|---|
 | 520 | for (uint_4 i=0; i<NElts(); i++) (*this)(i) += rc(i);
 | 
|---|
 | 521 | return *this;
 | 
|---|
 | 522 | }
 | 
|---|
 | 523 | 
 | 
|---|
 | 524 | template <class T> TMatrixRC<T>& TMatrixRC<T>::operator -= (const TMatrixRC<T>& rc)
 | 
|---|
 | 525 | {
 | 
|---|
 | 526 | if( NElts() != rc.NElts() )
 | 
|---|
 | 527 |   throw(SzMismatchError("TMatrixRC::operator-= size mismatch\n"));
 | 
|---|
 | 528 | if( kind != rc.kind )
 | 
|---|
 | 529 |   throw(SzMismatchError("TMatrixRC::operator-= type mismatch\n"));
 | 
|---|
 | 530 | for(uint_4 i=0; i<NElts(); i++) (*this)(i) -= rc(i);
 | 
|---|
 | 531 | return *this;
 | 
|---|
 | 532 | }
 | 
|---|
 | 533 | 
 | 
|---|
 | 534 | 
 | 
|---|
 | 535 | template <class T> TMatrixRC<T>& TMatrixRC<T>::operator *= (T x)
 | 
|---|
 | 536 | {
 | 
|---|
 | 537 | for(uint_4 i=0; i<NElts(); i++) (*this)(i) *= x;
 | 
|---|
 | 538 | return *this;
 | 
|---|
 | 539 | }
 | 
|---|
 | 540 | 
 | 
|---|
 | 541 | template <class T> TMatrixRC<T>& TMatrixRC<T>::operator /= (T x)
 | 
|---|
 | 542 | {
 | 
|---|
 | 543 | for(uint_4 i=0; i<NElts(); i++) (*this)(i) /= x;
 | 
|---|
 | 544 | return *this;
 | 
|---|
 | 545 | }
 | 
|---|
 | 546 | 
 | 
|---|
 | 547 | 
 | 
|---|
 | 548 | template <class T> TMatrixRC<T>& TMatrixRC<T>::operator -= (T x)
 | 
|---|
 | 549 | {
 | 
|---|
 | 550 | for(uint_4 i=0; i<NElts(); i++) (*this)(i) -= x;
 | 
|---|
 | 551 | return *this;
 | 
|---|
 | 552 | }
 | 
|---|
 | 553 | 
 | 
|---|
 | 554 | template <class T> TMatrixRC<T>& TMatrixRC<T>::operator += (T x)
 | 
|---|
 | 555 | {
 | 
|---|
 | 556 | for(uint_4 i=0; i<NElts(); i++) (*this)(i) += x;
 | 
|---|
 | 557 | return *this;
 | 
|---|
 | 558 | }
 | 
|---|
 | 559 | 
 | 
|---|
 | 560 | template <class T>
 | 
|---|
 | 561 | TMatrixRC<T>& TMatrixRC<T>::LinComb(T a, T b, const TMatrixRC<T>& rc, uint_4 first)
 | 
|---|
 | 562 | {
 | 
|---|
 | 563 | if ( NElts() != rc.NElts() )
 | 
|---|
 | 564 |   throw(SzMismatchError("TMatrixRC::LinComb size mismatch\n"));
 | 
|---|
 | 565 | if ( kind != rc.kind )
 | 
|---|
 | 566 |   throw(SzMismatchError("TMatrixRC::LinComb type mismatch\n"));
 | 
|---|
 | 567 | for(uint_4 i=first; i<NElts(); i++) (*this)(i) = (*this)(i)*a + rc(i)*b;
 | 
|---|
 | 568 | return *this;
 | 
|---|
 | 569 | }
 | 
|---|
 | 570 | 
 | 
|---|
 | 571 | template <class T>
 | 
|---|
 | 572 | TMatrixRC<T>& TMatrixRC<T>::LinComb(T b, const TMatrixRC<T>& rc, uint_4 first)
 | 
|---|
 | 573 | {
 | 
|---|
 | 574 | if ( NElts() != rc.NElts() )
 | 
|---|
 | 575 |   throw(SzMismatchError("TMatrixRC::LinComb size mismatch\n"));
 | 
|---|
 | 576 | if ( kind != rc.kind )
 | 
|---|
 | 577 |   throw(SzMismatchError("TMatrixRC::LinComb type mismatch\n"));
 | 
|---|
 | 578 | for(uint_4 i=first; i<NElts(); i++) (*this)(i) += rc(i)*b;
 | 
|---|
 | 579 | return *this;
 | 
|---|
 | 580 | }
 | 
|---|
 | 581 | 
 | 
|---|
 | 582 | template <class T> uint_4 TMatrixRC<T>::IMaxAbs(uint_4 first)
 | 
|---|
 | 583 | {
 | 
|---|
 | 584 | if (first>NElts())
 | 
|---|
 | 585 |   throw(SzMismatchError("TMatrixRC::IMaxAbs size mismatch\n"));
 | 
|---|
 | 586 | uint_4 imax = first;
 | 
|---|
 | 587 | double vmax = Abs_Value((*this)(first));
 | 
|---|
 | 588 | for(uint_4 i=first+1; i<NElts(); i++) {
 | 
|---|
 | 589 |   double v = Abs_Value((*this)(i));
 | 
|---|
 | 590 |   if(v > vmax) {vmax = v; imax = i;}
 | 
|---|
 | 591 | }
 | 
|---|
 | 592 | return imax;
 | 
|---|
 | 593 | }
 | 
|---|
 | 594 | 
 | 
|---|
 | 595 | template <class T>
 | 
|---|
 | 596 | void TMatrixRC<T>::Swap(TMatrixRC<T>& rc1, TMatrixRC<T>& rc2)
 | 
|---|
 | 597 | {
 | 
|---|
 | 598 | if(rc1.NElts() != rc2.NElts())
 | 
|---|
 | 599 |   throw(SzMismatchError("TMatrixRC::Swap size mismatch\n"));
 | 
|---|
 | 600 | if(rc1.kind != rc2.kind)
 | 
|---|
 | 601 |   throw(SzMismatchError("TMatrixRC::Swap type mismatch\n"));
 | 
|---|
 | 602 | if(rc1.data == rc2.data) return;
 | 
|---|
 | 603 | for(uint_4 i=0; i<rc1.NElts(); i++)
 | 
|---|
 | 604 |   {T tmp = rc1(i); rc1(i) = rc2(i); rc2(i) = tmp;}
 | 
|---|
 | 605 | }
 | 
|---|
 | 606 | 
 | 
|---|
 | 607 | ///////////////////////////////////////////////////////////////
 | 
|---|
 | 608 | #ifdef __CXX_PRAGMA_TEMPLATES__
 | 
|---|
 | 609 | #pragma define_template TMatrix<uint_1>
 | 
|---|
 | 610 | #pragma define_template TMatrix<uint_2>
 | 
|---|
 | 611 | #pragma define_template TMatrix<int_2>
 | 
|---|
 | 612 | #pragma define_template TMatrix<int_4>
 | 
|---|
 | 613 | #pragma define_template TMatrix<int_8>
 | 
|---|
 | 614 | #pragma define_template TMatrix<uint_4>
 | 
|---|
 | 615 | #pragma define_template TMatrix<uint_8>
 | 
|---|
 | 616 | #pragma define_template TMatrix<r_4>
 | 
|---|
 | 617 | #pragma define_template TMatrix<r_8>
 | 
|---|
 | 618 | #pragma define_template TMatrix< complex<float> > 
 | 
|---|
 | 619 | #pragma define_template TMatrix< complex<double> > 
 | 
|---|
 | 620 | // Instances des delegues FileIO (PPersist)
 | 
|---|
 | 621 | #pragma define_template FIO_TMatrix<uint_1>
 | 
|---|
 | 622 | #pragma define_template FIO_TMatrix<uint_2>
 | 
|---|
 | 623 | #pragma define_template FIO_TMatrix<int_2>
 | 
|---|
 | 624 | #pragma define_template FIO_TMatrix<int_4>
 | 
|---|
 | 625 | #pragma define_template FIO_TMatrix<int_8>
 | 
|---|
 | 626 | #pragma define_template FIO_TMatrix<uint_4>
 | 
|---|
 | 627 | #pragma define_template FIO_TMatrix<uint_8>
 | 
|---|
 | 628 | #pragma define_template FIO_TMatrix<r_8>
 | 
|---|
 | 629 | #pragma define_template FIO_TMatrix<r_4>
 | 
|---|
 | 630 | #pragma define_template FIO_TMatrix< complex<float> >
 | 
|---|
 | 631 | #pragma define_template FIO_TMatrix< complex<double> >
 | 
|---|
 | 632 | // Instances gestion lignes/colonnes
 | 
|---|
 | 633 | #pragma define_template TMatrixRC<uint_1>
 | 
|---|
 | 634 | #pragma define_template TMatrixRC<uint_2>
 | 
|---|
 | 635 | #pragma define_template TMatrixRC<int_2>
 | 
|---|
 | 636 | #pragma define_template TMatrixRC<int_4>
 | 
|---|
 | 637 | #pragma define_template TMatrixRC<int_8>
 | 
|---|
 | 638 | #pragma define_template TMatrixRC<uint_4>
 | 
|---|
 | 639 | #pragma define_template TMatrixRC<uint_8>
 | 
|---|
 | 640 | #pragma define_template TMatrixRC<r_4>
 | 
|---|
 | 641 | #pragma define_template TMatrixRC<r_8>
 | 
|---|
 | 642 | #pragma define_template TMatrixRC< complex<float> > 
 | 
|---|
 | 643 | #pragma define_template TMatrixRC< complex<double> >
 | 
|---|
 | 644 | #endif
 | 
|---|
 | 645 | 
 | 
|---|
 | 646 | #if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
 | 
|---|
 | 647 | template class TMatrix<uint_1>;
 | 
|---|
 | 648 | template class TMatrix<uint_2>;
 | 
|---|
 | 649 | template class TMatrix<int_2>;
 | 
|---|
 | 650 | template class TMatrix<int_4>;
 | 
|---|
 | 651 | template class TMatrix<int_8>;
 | 
|---|
 | 652 | template class TMatrix<uint_4>;
 | 
|---|
 | 653 | template class TMatrix<uint_8>;
 | 
|---|
 | 654 | template class TMatrix<r_4>;
 | 
|---|
 | 655 | template class TMatrix<r_8>;
 | 
|---|
 | 656 | template class TMatrix< complex<float> >;
 | 
|---|
 | 657 | template class TMatrix< complex<double> >;
 | 
|---|
 | 658 | // Instances des delegues FileIO (PPersist)
 | 
|---|
 | 659 | template class FIO_TMatrix<uint_1>;
 | 
|---|
 | 660 | template class FIO_TMatrix<uint_2>;
 | 
|---|
 | 661 | template class FIO_TMatrix<int_2>;
 | 
|---|
 | 662 | template class FIO_TMatrix<int_4>;
 | 
|---|
 | 663 | template class FIO_TMatrix<int_8>;
 | 
|---|
 | 664 | template class FIO_TMatrix<uint_4>;
 | 
|---|
 | 665 | template class FIO_TMatrix<uint_8>;
 | 
|---|
 | 666 | template class FIO_TMatrix<r_8>;
 | 
|---|
 | 667 | template class FIO_TMatrix<r_4>;
 | 
|---|
 | 668 | template class FIO_TMatrix< complex<float> >;
 | 
|---|
 | 669 | template class FIO_TMatrix< complex<double> >;
 | 
|---|
 | 670 | // Instances gestion lignes/colonnes
 | 
|---|
 | 671 | template class TMatrixRC<uint_1>;
 | 
|---|
 | 672 | template class TMatrixRC<uint_2>;
 | 
|---|
 | 673 | template class TMatrixRC<int_2>;
 | 
|---|
 | 674 | template class TMatrixRC<int_4>;
 | 
|---|
 | 675 | template class TMatrixRC<int_8>;
 | 
|---|
 | 676 | template class TMatrixRC<uint_4>;
 | 
|---|
 | 677 | template class TMatrixRC<uint_8>;
 | 
|---|
 | 678 | template class TMatrixRC<r_4>;
 | 
|---|
 | 679 | template class TMatrixRC<r_8>;
 | 
|---|
 | 680 | template class TMatrixRC< complex<float> >;
 | 
|---|
 | 681 | template class TMatrixRC< complex<double> >;
 | 
|---|
 | 682 | #endif
 | 
|---|