// Rascal, the Advanced Scientific CALculator
// Copyright (C) 2001, Sebastian Ritterbusch (Rascal@Ritterbusch.de)
//
// This program 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.
//
// This program 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 detauls.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
#ifndef MATRIX_HPP_INCLUDED
#define MATRIX_HPP_INCLUDED
// #define INDCHECK
#include <iostream.h>
template <class T>
class mmatrix
{
public:
T **a;
int N,M;
public:
mmatrix(int aN,int aM) : N(aN),M(aM)
{
a=new T *[N];
int i;
for(i=0;i<N;i++)
a[i]=new T[M];
}
mmatrix(int aN,int aM,const T & x,const T & y) : N(aN),M(aM)
{
a=new T *[N];
int i;
for(i=0;i<N;i++)
a[i]=new T[M];
int j;
for(i=0;i<N;i++)
for(j=0;j<M;j++)
a[i][j]=(i==j)?x:y;
}
mmatrix(const T & b) : N(1),M(1)
{
a=new T *[1];
a[0]=new T[1];
a[0][0]=b;
}
mmatrix(const mmatrix<T> &b) : N(b.N),M(b.M)
{
int i,j;
a=new T *[N];
for(i=0;i<N;i++)
{
a[i]=new T[M];
for(j=0;j<M;j++)
a[i][j]=b.a[i][j];
}
}
~mmatrix(void) { int i; for(i=0;i<N;i++) delete [] a[i]; delete [] a; }
mmatrix<T> & operator =(const mmatrix<T> & b)
{
int i,j;
if(N!=b.N || M!=b.M)
{
for(i=0;i<N;i++) delete [] a[i]; delete [] a; // what if self-assigment ?!??
N=b.N;M=b.M;
a=new T *[N];
for(i=0;i<N;i++)
a[i]=new T[M];
}
for(i=0;i<N;i++)
for(j=0;j<M;j++)
a[i][j]=b.a[i][j];
return *this;
}
inline mmatrix<T> & operator +=(const mmatrix<T> & b)
{
int i,j;
int iN(b.N<N?b.N:N),iM(b.M<M?b.M:M);
for(i=0;i<iN;i++)
for(j=0;j<iM;j++)
a[i][j]=a[i][j]+b.a[i][j];
return *this;
}
inline mmatrix<T> & operator -=(const mmatrix<T> & b)
{
int i,j;
int iN(b.N<N?b.N:N),iM(b.M<M?b.M:M);
for(i=0;i<iN;i++)
for(j=0;j<iM;j++)
a[i][j]=a[i][j]-b.a[i][j];
return *this;
}
inline mmatrix<T> & foreach(T (*f)(const T &))
{
int i,j;
for(i=0;i<N;i++)
for(j=0;j<M;j++)
a[i][j]=f(a[i][j]);
return *this;
}
inline mmatrix<T> foreach(T (*f)(const T &)) const
{
int i,j;
mmatrix<T> temp(N,M);
for(i=0;i<N;i++)
for(j=0;j<M;j++)
temp.a[i][j]=f(a[i][j]);
return temp;
}
inline mmatrix<T> & foreach(T (*f)(T))
{
int i,j;
for(i=0;i<N;i++)
for(j=0;j<M;j++)
a[i][j]=f(a[i][j]);
return *this;
}
inline mmatrix<T> & foreach(T (*f)(T)) const
{
int i,j;
mmatrix<T> temp(N,M);
for(i=0;i<N;i++)
for(j=0;j<M;j++)
temp.a[i][j]=f(a[i][j]);
return *this;
}
friend inline mmatrix<T> operator +(mmatrix<T> a,const mmatrix<T> & b) { return a+=b; }
friend inline mmatrix<T> operator -(mmatrix<T> a,const mmatrix<T> & b) { return a-=b; }
T & operator ()(int i,int j)
{
#ifndef INDCHECK
return a[i][j];
#else
if(i>=0 && i<N && j>=0 && j<M)
return a[i][j];
else
throw(new int);
#endif
}
T & Y(int i,int j) {
#ifndef INDCHECK
return a[i][j];
#else
if(i>=0 && i<N && j>=0 && j<M)
return a[i][j];
else
throw(new int);
#endif
}
T operator ()(int i,int j) const {
#ifndef INDCHECK
return a[i][j];
#else
if(i>=0 && i<N && j>=0 && j<M)
return a[i][j];
else
throw(new int);
#endif
}
T y(int i,int j) const {
#ifndef INDCHECK
return a[i][j];
#else
if(i>=0 && i<N && j>=0 && j<M)
return a[i][j];
else
throw(new int);
#endif
}
mmatrix<T> row(int i) const
{
if(i>=0 && i<N)
{
mmatrix<T> r(1,M);
for(int j=0;j<M;j++)
r.a[0][j]=a[i][j];
return r;
} else
return mmatrix<T>(0,M);
}
friend ostream & operator <<(ostream & o,const mmatrix<T> & x)
{
int i,j;
for(i=0;i<x.N;i++)
{
for(j=0;j<x.M-1;j++)
o << x.a[i][j] << '\t';
o << x.a[i][j] << endl;
}
return o;
}
};
template <class S>
inline mmatrix<S> operator *(const mmatrix<S> & x,const mmatrix<S> & y)
{
int i,j,k;
int iB(x.M<y.N?x.M:y.N);
mmatrix<S> z(x.N,y.M);
for(i=0;i<x.N;i++)
for(j=0;j<y.M;j++)
{
if(0<iB)
z(i,j)=x(i,0)*y(0,j);
for(k=1;k<iB;k++)
z(i,j)=z(i,j)+x(i,k)*y(k,j);
}
return z;
}
template <class S>
inline int operator ==(const mmatrix<S> & x,const mmatrix<S> & y)
{
int i,j,k;
if(x.M!=y.M || x.N!=y.N)
return 0;
for(i=0;i<x.N;i++)
for(j=0;j<x.M;j++)
if(x(i,j)!=y(i,j))
return 0;
return 1;
}
template <class S>
inline int operator !=(const mmatrix<S> & x,const mmatrix<S> & y)
{
int i,j,k;
if(x.M!=y.M || x.N!=y.N)
return 1;
for(i=0;i<x.N;i++)
for(j=0;j<x.M;j++)
if(x(i,j)!=y(i,j))
return 1;
return 0;
}
template <class S>
inline mmatrix<S> operator *(const S & x,const mmatrix<S> & y)
{
int i,j,k;
mmatrix<S> z(y.N,y.M);
for(i=0;i<y.N;i++)
for(j=0;j<y.M;j++)
z(i,j)=x*y(i,j);
return z;
}
template <class S>
inline mmatrix<S> operator -(const mmatrix<S> & y)
{
int i,j,k;
mmatrix<S> z(y.N,y.M);
for(i=0;i<y.N;i++)
for(j=0;j<y.M;j++)
z(i,j)=-y(i,j);
return z;
}
template <class T>
mmatrix<T> trans(const mmatrix<T> & A)
{
mmatrix<T> B(A.M,A.N);
int i,j;
for(i=0;i<B.N;i++)
for(j=0;j<B.M;j++)
B(i,j)=A(j,i);
return B;
}
template <class T>
mmatrix<T> appendcol(const mmatrix<T> & A,const mmatrix<T> & c) // append col
{
int maxN(A.N>c.N?A.N:c.N);
mmatrix<T> B(maxN,A.M+c.M);
int i,j;
for(i=0;i<A.N;i++)
for(j=0;j<A.M;j++)
B(i,j)=A(i,j);
for(i=0;i<c.N;i++)
for(j=0;j<c.M;j++)
B(i,j+A.M)=c(i,j);
return B;
}
template <class T>
mmatrix<T> appendline(const mmatrix<T> & A,const mmatrix<T> & l) // append line
{
int maxM(A.M>l.M?A.M:l.M);
mmatrix<T> B(A.N+l.N,maxM);
int i,j;
for(i=0;i<A.N;i++)
for(j=0;j<A.M;j++)
B(i,j)=A(i,j);
for(i=0;i<l.N;i++)
for(j=0;j<l.M;j++)
B(i+A.N,j)=l(i,j);
return B;
}
template <class T>
mmatrix<T> inv(mmatrix<T> A)
{
int N(A.N<A.M?A.N:A.M);
mmatrix<T> B(N,N);
int i,j,k;
for(i=0;i<N;i++)
for(j=0;j<N;j++)
B(i,j)=(i==j)?1:0;
for(i=0;i<N;i++)
{
if(A(i,i)==T(0)) // trouble...
{
for(k=i+1;k<N && (k==i || A(k,i)==T(0));k++);
if(k<N) // okay, found a better row
{
T swap;
for(j=0;j<N;j++)
{
swap=A(k,j);A(k,j)=A(i,j);A(i,j)=swap;
}
} else
{
return mmatrix<T>(0,0); // Sorry, inversion not possible.
}
}
for(j=0;j<N;j++)
if(i!=j)
{
T quot=A(j,i)/A(i,i);
for(k=0;k<i+1;k++)
{
B(j,k)=B(j,k)-quot*B(i,k);
}
for(k=i+1;k<N;k++)
A(j,k)=A(j,k)-quot*A(i,k);
}
}
for(i=0;i<N;i++)
for(j=0;j<N;j++)
B(i,j)=B(i,j)/A(i,i);
return B;
}
template <class T>
T det(mmatrix<T> A)
{
if((A.N==1 && A.M>0) || (A.M==1 && A.N>0))
return A(0,0);
int N(A.N<A.M?A.N:A.M);
mmatrix<T> B(N-1,N-1);
T res;
int i,j,k;
for(i=0;i<N;i++)
{
for(j=0;j<i;j++)
for(k=1;k<N;k++)
B(j,k-1)=A(j,k);
j++;
for(;j<N;j++)
for(k=1;k<N;k++)
B(j-1,k-1)=A(j,k);
if(i==0)
res=A(i,0)*det(B);
else if(i&1)
res=res-A(i,0)*det(B);
else
res=res+A(i,0)*det(B);
}
return res;
}
template<class T>
mmatrix<T> pow(mmatrix<T> A,int p)
{
mmatrix<T> b(A.N,A.M,1,0);
if(p<0)
{
A=inv(A);
p=-p;
}
while(p!=0)
{
if(p&1)
b=b*A;
p=p/2;
if(p)
A=A*A;
}
return b;
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1