/***************************************************************************** * * * FOX Controller Library, Version 1.3.3. * * * * Copyright (C) 1998,1999,2000 Russell Smith (rl.smith@auckland.ac.nz) * * * * The FOX Controller Library is free software; you can redistribute it * * and/or modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either version * * 2 of the License, or (at your option) any later version. * * * * The FOX Controller Library is distributed in the hope that it will be * * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with the Fox Controller Library; see the file COPYING.LIB. * * If not, write to the Free Software Foundation, Inc., 59 Temple Place - * * Suite 330, Boston, MA 02111-1307, USA. * * * *****************************************************************************/ #include #include #include "atoi.h" //*************************************************************************** // Matrix inversion class Matrix { int n; // matrix is n*n - n=0 if constructor failed int size; // size = n*n cftype *data; // n*n matrix elements int LUDecompose (int perm[]); void Solve (cftype *b, int perm[]); public: Matrix (int _n, cftype *_data); void SetInverse (Matrix &a); }; //........................................................................... // Debugging macros to test pointer bounds // #define CHECKIT #ifdef CHECKIT #define CHECK(pointer) if ((pointer)=(data+size)) \ ZFatalError ("Pointer check failed at " __FILE__ ":%d",__LINE__); #define CHECK2(pointer,obj,limit) \ if ((pointer)<(obj) || (pointer)>=((obj)+limit)) \ ZFatalError ("Pointer check failed at " __FILE__ ":%d",__LINE__); #define CHECK3(num) \ if ((num)<0 || (num)>=n) \ ZFatalError ("Range check failed at " __FILE__ ":%d",__LINE__); #define CHECK_MESSAGE printf ("Matrix checking turned on\n"); #else #define CHECK(pointer) /**/ #define CHECK2(pointer,obj,limit) /**/ #define CHECK3(num) /**/ #define CHECK_MESSAGE /**/ #endif //........................................................................... // This is based on the ludcmp routine from NRC #2.3. int Matrix::LUDecompose (int perm[]) { int i,imax,j,k,swaps; // swaps = num row interchanges cftype big,dum,sum,temp; cftype *Aptr,*rptr,*cptr; // row & col pointers for Crout's method if (n==0) return 0; cftype vv [n]; // vv = the implicit scaling of each row swaps = 1; imax = 0; // to prevent "possibly unused" warning // loop over rows to get the implicit scaling information Aptr = data; for (i=0; i big) big = temp; } checkthat2 (big != 0.0,"Singular matrix in Matrix::LUDecompose"); CHECK3(i) vv[i] = 1.0/big; } for (j=0; j= big) { big=dum; imax=i; } Aptr += n; // jump to next row } if (j != imax) { // do we need to swap rows? Aptr = data + n*imax; rptr = data + n*j; for (k=n; k; k--) { // row swap CHECK(Aptr) CHECK(rptr) dum = *Aptr; *Aptr++ = *rptr; *rptr++ = dum; } swaps=-swaps; // record row swap parity CHECK3(imax) CHECK3(j) vv[imax] = vv[j]; // also interchange scale factor } CHECK3(j) perm[j] = imax; Aptr = data + (n+1)*j; // Aptr = pivot element CHECK(Aptr) if ((*Aptr) == 0.0) { *Aptr = 1.0e-20; // Cheating! } if (j != (n-1)) { // divide by the pivot element dum = 1.0/(*Aptr); Aptr += n; for (i=j+1; i=0, ii=index of 1st nonzero ip = perm[i]; // element of b sum = b[ip]; b[ip] = b[i]; if (ii>=0) { Aptr = data + i*n+ii; bptr = b + ii; for (j=ii; j 1) { for (i=n-2; i>=0; i--) { sum = b[i]; Aptr = data + (n+1)*i+1; bptr = b + i + 1; for (j=i+1; j #include cftype frandom() { return cftype(random()) / cftype(RAND_MAX); } int main() { cftype Adata[16],Ainvdata[16]; Matrix A(4,Adata),Ainv(4,Ainvdata); srandom (time(NULL)); for (int i=0; i<16; i++) Adata[i] = frandom(); FILE *f = fopen ("z1","w"); for (int i=0; i<4; i++) { for (int j=0; j<4; j++) fprintf (f,"%.15f ",Adata[i*4+j]); fprintf (f,"\n"); } fclose (f); Ainv.SetInverse (A); f = fopen ("z2","w"); for (int i=0; i<4; i++) { for (int j=0; j<4; j++) fprintf (f,"%.15f ",Ainvdata[i*4+j]); fprintf (f,"\n"); } fclose (f); } */ //*************************************************************************** // GetAtoi GetAtoi::GetAtoi (int _ny, cftype *A, int _n) { int i,j,k,l; valid = 0; Atoi = NULL; invAtoi = NULL; ny = _ny; ny2 = ny*ny; n = _n; checkthat (ny <= MAX_NY,"ny > %d in GetAtoi ctor",MAX_NY); checkthat (n >= 1,"bad n in Atoi ctor"); checkmemptr (Atoi = new cftype [ny2 * n]); checkmemptr (invAtoi = new cftype [ny2 * n]); // get inverse of A cftype Adata[ny2],invAdata [ny2]; memcpy (Adata,A,ny2*sizeof(cftype)); Matrix matA (ny,Adata); Matrix invA (ny,invAdata); invA.SetInverse (matA); // get X1 = X2 = identity cftype X1 [MAX_NY * MAX_NY]; cftype X2 [MAX_NY * MAX_NY]; for (i=0; i