/* Copyright 2002 Ben Blum, Christian Shelton * * This file is part of GameTracer. * * GameTracer is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * GameTracer 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GameTracer; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "cmatrix.h" #include "math.h" #include "float.h" cvector::~cvector() { delete []x; } // adopted from NRiC, pg 45 cmatrix::~cmatrix() { delete []x; } int cvector::num_vec_cons = 0; cmatrix cmatrix::inv(bool &worked) const { if (m!=n) { cerr << "invalid cmatrix inverse" << endl; exit(1); } cmatrix temp(n,n); int *ix = new int[n]; if (!LUdecomp(temp,ix)) { worked = false; delete []ix; return cmatrix(n,n,0,false); } worked = true; cmatrix ret(n,n); int i,j; double *col = new double[n]; for(j=0;j=big) { big = dum; imax = i; } } if (j!=imax) { for(k=0;k=0;i--) { sum = b[i]; for(int j=i+1;j<=n-1;j++) sum -= x[i*n+j]*b[j]; b[i] = sum/x[i*n+i]; } } bool cmatrix::solve(cvector &b, cvector &ret) { if (m!=n) { cerr << "invalid cmatrix in solve" << endl; exit(1); } for(int i=0;iabsb) { double sqr = absb/absa; return absa*sqrt(1.0+sqr*sqr); } else { if (absb==0.0) return 0; double sqr = absa/absb; return absb*sqrt(1.0+sqr*sqr); } } #define SIGN(a,b) ((b) > 0.0 ? fabs(a) : -fabs(a)) // adopted from pg 67 of NRiC void cmatrix::svd(cmatrix &u, cmatrix &v, double *w) { u = *this; if (v.n!=n || v.m!=n) { delete []v.x; v.n = n; v.m = n; v.s = n*n; v.x = new double[v.s]; } int flag,i,its,j,jj,k,l,nm; double anorm,c,f,g,h,s,scale,x,y,z,*rv1; rv1 = new double[n]; g=scale=anorm=(double)0; for(i=0;itemp ? anorm : temp; } for(i=n-1;i>=0;i--) { if (in?n-1:m-1;i>=0;i--) { l=i+1; g=w[i]; for(j=l;j=0;k--) { for(its=1;its<=30;its++) { flag = 1; for(l=k;l>=0;l--) { nm = l-1; if ((double)(fabs(rv1[l])+anorm)==anorm) { flag = 0; break; } if ((double)(fabs(w[nm])+anorm)==anorm) break; } if (flag) { c = (double)0; s = (double)1; for(i=l;i<=k;i++) { f = s*rv1[i]; rv1[i] = c*rv1[i]; if ((double)(fabs(f)+anorm)==anorm) break; g = w[i]; h = pythag(f,g); w[i] = h; h = 1/h; c = g*h; s = -f*h; for(j=0;j max) { max = fabs(retval[i][j]); maxi = i; } } if(j != lastj && max == 0.0) { if(lastj >= 0) return DBL_MAX; lastj = j; if(j != m-1) continue; } if(maxi == -1) { cout << "oops"; return DBL_MAX; } i = maxi; pivot = retval[i][j]; for(i0 = 0; i0 < m; i0++) { if(i0 != i) { for(j0 = 0; j0 < m; j0++) { if(j0 != j) { retval[i0][j0] *= pivot; retval[i0][j0] -= retval[i0][j] * retval[i][j0]; retval[i0][j0] /= D; } } } } for(i0 = 0; i0 < m; i0++) { retval[i0][j] = -retval[i0][j]; } retval[i][j] = D; D = pivot; r[i] = j; c[j] = i; if(j == lastj) break; if(j == m-1 && lastj >= 0) j = lastj - 1; } // cout << retval << endl << endl; int s=0; i = 0; memcpy(r2, r, m * sizeof(int)); while(i < m-1) { j = r2[i]; if(i != j) { s++; r2[i] = r2[j]; r2[j] = j; } else i++; } for(i = 0; i < m; i++) for(j = 0; j < m; j++) x[i*n+j] = retval[c[i]][r[j]]; if(s%2 == 1) { negate(); D = -D; } // cout << *this << endl << endl; return D; } double cmatrix::testAdjoint() //returns the characteristic polynomial and adjoint cmatrix { cmatrix c(n,n,1.0,1), p(n,n); int i = 0, j; double det,b; for (;;) { i++; if (i == n) break; p = *this * c; c = p; b = - c.trace() / i; for (j = 0; j < n; j++) c[j][j] += b; } p = m * c; det = - p.trace() / n; b = 1 - 2*((n - 1) % 2); *this = c * b; return det; } double cmatrix::trace() { assert(n == m); double sum = 0.0; for(int i = 0; i < n; i++) { sum += x[i*n+i]; } return sum; }