home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume21
/
newmat02
/
part03
/
newmat8.cxx
< prev
next >
Wrap
C/C++ Source or Header
|
1991-08-01
|
7KB
|
310 lines
//$$ newmat8.cxx Advanced matrix functions, scalar functions
// Copyright (C) 1991: R B Davies and DSIR
#include "include.hxx"
#include "boolean.hxx"
typedef double real; // all floating point double
#include "newmat.hxx"
#include "newmatap.hxx"
#include "newmatrc.hxx"
//#define REPORT { static ExeCounter ExeCount(__LINE__,8); ExeCount++; }
#define REPORT {}
/********************** householder triangularisation *********************/
inline real square(real x) { return x*x; }
void HHDecompose(Matrix& X, LowerTriangularMatrix& L)
{
int n = X.Ncols(); int s = X.Nrows(); L.ReDimension(s);
real* xi = X.Store(); int k;
for (int i=0; i<s; i++)
{
real sum = 0.0;
real* xi0=xi; k=n; while(k--) { sum += square(*xi++); }
sum = sqrt(sum);
L.element(i,i) = sum;
real* xj0=xi0; k=n; while(k--) { *xj0++ /= sum; }
for (int j=i+1; j<s; j++)
{
sum=0.0;
xi=xi0; real* xj=xj0; k=n; while(k--) { sum += *xi++ * *xj++; }
xi=xi0; k=n; while(k--) { *xj0++ -= sum * *xi++; }
L.element(j,i) = sum;
}
}
}
void HHDecompose(const Matrix& X, Matrix& Y, Matrix& M)
{
int n = X.Ncols(); int s = X.Nrows(); int t = Y.Nrows();
if (Y.Ncols() != n) MatrixError("Incompatible dimensions in HHDecompose");
M.ReDimension(t,s);
real* xi = X.Store(); int k;
for (int i=0; i<s; i++)
{
real* xj0 = Y.Store(); real* xi0 = xi;
for (int j=0; j<t; j++)
{
real sum=0.0;
xi=xi0; real* xj=xj0; k=n; while(k--) { sum += *xi++ * *xj++; }
xi=xi0; k=n; while(k--) { *xj0++ -= sum * *xi++; }
M.element(j,i) = sum;
}
}
}
/********* Cholesky decomposition of a positive definite matrix *************/
// Suppose S is symmetrix and positive definite. Then there exists a unique
// lower triangular matrix L such that L L.t() = S;
LowerTriangularMatrix Cholesky(const SymmetricMatrix& S)
{
int nr = S.Nrows();
LowerTriangularMatrix T(nr);
real* s = S.Store(); real* t = T.Store(); real* tk = t;
for (int i=0; i<nr; i++)
{
real* tj = t; real* ti = tk;
for (int j=0; j<=i; j++)
{
tk = ti; real sum = 0.0; int k = j;
while (k--) { sum += *tj++ * *tk++; }
if (i==j) *tk++ = sqrt(*s++ - sum);
else *tk++ = (*s++ - sum) / *tj++;
}
}
#ifndef __ZTC__
T.Release(); // not wanted if routine avoids return init
#endif
return T;
}
/************************** LU transformation ****************************/
inline real fabs(real f) { return (f>0.0) ? f : -f; }
void CroutMatrix::ludcmp()
// LU decomposition - from numerical recipes in C
{
REPORT
int i,j;
real* vv=new real [nrows]; MatrixErrorNoSpace(vv);
real* a;
a=store;
for (i=0;i<nrows;i++)
{
real big=0.0;
j=nrows; while (j--) { real temp=fabs(*a++); if (temp > big) big=temp; }
if (big == 0.0) MatrixError("Singular matrix");
vv[i]=1.0/big;
}
real* aj=store;
for (j=0;j<nrows;j++)
{
real* ai=store;
for (i=0;i<j;i++)
{
real sum=*(ai+j); real* aix=ai; real* ajx=aj;
int k=i; while (k--) { sum -= *aix++ * *ajx; ajx += nrows; }
*ajx = sum; ai += nrows;
}
real big=0.0; int imax;
for (i=j;i<nrows;i++)
{
real sum=*(ai+j); real* aix=ai; real* ajx=aj;
int k=j; while (k--) { sum -= *aix++ * *ajx; ajx += nrows; }
*aix = sum; ai += nrows;
real dum=vv[i]*fabs(sum); if (dum >= big) { big=dum; imax=i; }
}
if (j != imax)
{
real* amax=store+imax*nrows; real* ajx=store+j*nrows;
int k=nrows; while(k--) { real dum=*amax; *amax++=*ajx; *ajx++=dum; }
d=!d; vv[imax]=vv[j];
}
indx[j]=imax; ai=aj+j*nrows;
if (*ai == 0.0) MatrixError("Singular matrix");
real dum=1.0/(*ai);
i=nrows-j; while (--i) { ai += nrows; *ai *= dum; }
aj++;
}
delete [nrows] vv;
}
void CroutMatrix::lubksb(real* B, int mini)
{
REPORT
int i,j; int ii=-1; real* ai=store;
for (i=0;i<nrows;i++)
{
int ip=indx[i]; real sum=B[ip]; B[ip]=B[i];
if (ii>=0)
{
real* aij=ai+ii; real* bj=B+ii; j=i-ii;
while (j--) { sum -= *aij++ * *bj; bj++; }
}
else if (sum) ii=i;
B[i]=sum; ai += nrows;
}
for (i=nrows-1;i>=mini;i--)
{
real* bj=B+i; ai -= nrows; real* ajx=ai+i; real sum=*bj; bj++;
j=nrows-i; while(--j) { sum -= *(++ajx) * *bj; bj++; }
B[i]=sum/(*(ai+i));
}
}
/****************************** scalar functions ****************************/
real GeneralMatrix::SumSquare()
{
REPORT
real sum = 0.0; int i = storage; real* s = store;
while (i--) sum += square(*s++);
tDelete(); return sum;
}
real SymmetricMatrix::SumSquare()
{
REPORT
real sum1 = 0.0; real sum2 = 0.0; real* s = store; int nr = nrows;
for (int i = 0; i<nr; i++)
{
int j = i;
while (j--) sum2 += square(*s++);
sum1 += square(*s++);
}
tDelete(); return sum1 + 2.0 * sum2;
}
real BaseMatrix::SumSquare()
{
REPORT GeneralMatrix* gm = Evaluate();
real s = gm->SumSquare(); return s;
}
real Matrix::Trace()
{
REPORT
int i = nrows; int d = i+1;
if (i != ncols) MatrixError("trace of non-square matrix");
real sum = 0.0; real* s = store;
while (i--) { sum += *s; s += d; }
tDelete(); return sum;
}
real DiagonalMatrix::Trace()
{
REPORT
int i = nrows; real sum = 0.0; real* s = store;
while (i--) sum += *s++;
tDelete(); return sum;
}
real SymmetricMatrix::Trace()
{
REPORT
int i = nrows; real sum = 0.0; real* s = store; int j = 2;
while (i--) { sum += *s; s += j++; }
tDelete(); return sum;
}
real LowerTriangularMatrix::Trace()
{
REPORT
int i = nrows; real sum = 0.0; real* s = store; int j = 2;
while (i--) { sum += *s; s += j++; }
tDelete(); return sum;
}
real UpperTriangularMatrix::Trace()
{
REPORT
int i = nrows; real sum = 0.0; real* s = store;
while (i) { sum += *s; s += i--; }
tDelete(); return sum;
}
real BaseMatrix::Trace()
{
REPORT
GeneralMatrix* gm = Evaluate(MatrixType::Diag);
real sum = gm->Trace(); return sum;
}
void LogAndSign::operator*=(real x)
{
if (x > 0.0) { log_value += log(x); }
else if (x < 0.0) { log_value += log(-x); sign = -sign; }
else sign = 0;
}
real LogAndSign::Value() { return sign * exp(log_value); }
LogAndSign DiagonalMatrix::LogDeterminant()
{
REPORT
int i = nrows; LogAndSign sum; real* s = store;
while (i--) sum *= *s++;
tDelete(); return sum;
}
LogAndSign LowerTriangularMatrix::LogDeterminant()
{
REPORT
int i = nrows; LogAndSign sum; real* s = store; int j = 2;
while (i--) { sum *= *s; s += j++; }
tDelete(); return sum;
}
LogAndSign UpperTriangularMatrix::LogDeterminant()
{
REPORT
int i = nrows; LogAndSign sum; real* s = store;
while (i) { sum *= *s; s += i--; }
tDelete(); return sum;
}
LogAndSign BaseMatrix::LogDeterminant()
{
REPORT GeneralMatrix* gm = Evaluate();
LogAndSign sum = gm->LogDeterminant(); return sum;
}
LogAndSign GeneralMatrix::LogDeterminant()
{
REPORT
if (nrows != ncols) MatrixError("determinant of non-square matrix");
CroutMatrix C(*this); return C.LogDeterminant();
}
LogAndSign CroutMatrix::LogDeterminant()
{
REPORT
int i = nrows; int dd = i+1; LogAndSign sum; real* s = store;
while (i--) { sum *= *s; s += dd; }
if (!d) sum.ChangeSign(); return sum;
}