Gaussian elimination without result for acceleration - c
Good day,
I'm working on a C library (for myself, code: https://github.com/BattlestarSC/matrixLibrary.git) to handle matrix functions. This is mostly a learning/practice activity. One of my challenges is to take the determinant of a matrix efficiently. As my current attempts have failed, I wanted to take a different approach. I was reading though this method from MIT docs: http://web.mit.edu/18.06/www/Spring17/Determinants.pdf and it made a lot of sense. The issue I'm having is how to get to said point. As the Gaussian elimination method is good for multi-variable systems of equations, my matricies are not built from equations, and therefor are not part of a system. As in, each equation has no set result and does not fit into the form from this paper here:https://math.oregonstate.edu/home/programs/undergrad/CalculusQuestStudyGuides/vcalc/gauss/gauss.html
From this point, I'm at a loss as far as how to proceed with this method.
It makes a lot of sense to take the pivot point from each set of equations as described in the MIT paper, but how should I set up my matricies to make said result valid?
When you perform a Gaussian elimination, you swap rows and repeatedly subtract a multiple of one row from another to produce an upper triangular form.
When you do this on a system of equations or an "augmented matrix", you do not use any information from the result column. The decisions about which rows to swap and which to subtract with what multiplier would be exactly the same no matter what numbers are in the result column.
Because the "result column" is not used, you can perform the same procedure on a normal square matrix. Since the operations don't change the determinant (if you negate one row whenever you swap), you end up with an upper triangular matrix with the same det as the original.
The MIT author calls a function lu to do this in the example near the start. This does L-U decomposition on the matrix, which returns the Gaussian-eliminated matrix in the 'U' part: https://en.wikipedia.org/wiki/LU_decomposition.
L-U decomposition is pretty cool. It's like doing Gaussian elimination to solve all systems with the same "matrix part" all at once, which again you can do because the process doesn't need to see the result column at all.
Starting with a matrix M, you get L and U such that LU = M. That means, if you want to solve:
Mx = y
... where (x an y are column vectors), you have:
LUx = y
Solve Lv=y, which is easy (just substitution) because L is lower-triangular. Then you have:
Ux = v
... which is easy to solve because U is upper-triangular.
GEM is not very good for computers as it needs to reorder the rows so the algo leads to a valid result that adds relatively big overhead and potential instability (if ordered badly). The GEM is much better suited for humans and paper/pencil as we instinctively reorder/chose rows ...
So you should go with the (sub)Determinant approach as you wanted in the first place. Is faster and safer. I know its a bit tricky to learn it from papers. If it helps this is mine ancient matrix.h class (but in C++) I wrote when I was still a rookie (so there might be some hidden bugs I do not know of haven't use this for ages):
//--- matrix ver: 2.1 -------------------------------------------------------
#ifndef _matrix_h
#define _matrix_h
//---------------------------------------------------------------------------
double fabs(double x)
{
if (x<0) x=-x;
return x;
}
//---------------------------------------------------------------------------
class matrix
{
private:double **p;
int xs,ys;
double zeroacc;
public: matrix() { p=NULL; xs=0; ys=0; resize(1,1); zeroacc=1e-10; }
~matrix() { free(); }
void free();
int resize(int _xs,int _ys);
matrix& operator=(const matrix &b);
matrix& operator+();
matrix& operator-();
matrix& operator+(matrix &b);
matrix& operator-(matrix &b);
matrix& operator*(matrix &b);
matrix& operator+=(matrix &b);
matrix& operator-=(matrix &b);
matrix& operator*=(matrix &b);
matrix& operator!();
double& operator()(int y,int x);
double* operator[](int y) { return p[y]; }
void one();
int get_xs() { return xs; }
int get_ys() { return ys; }
double get_zeroacc() { return zeroacc; }
void set_zeroacc(double _zeroacc) { zeroacc=_zeroacc; if (zeroacc<0) zeroacc=-zeroacc; }
void ld(int y,double x0=0.0,double x1=0.0,double x2=0.0,double x3=0.0,double x4=0.0,double x5=0.0,double x6=0.0,double x7=0.0,double x8=0.0,double x9=0.0);
void prn(TCanvas *scr,int x0,int y0);
void lxch(int y1,int y2);
void lcom(int y1,int y2,double k);
void lmul(int y,double k);
void ldiv(int y,double k);
int gaus(matrix &b);
matrix& matrix::submatrix(int _x,int _y);
double determinant();
double subdeterminant();
matrix& inv_det();
matrix& inv_gaus();
};
//---------------------------------------------------------------------------
void matrix::free()
{
int y;
if (p!=NULL)
for (y=0;y<ys;y++)
delete[] p[y];
delete[] p;
p=NULL;
xs=0;
ys=0;
}
//---------------------------------------------------------------------------
int matrix::resize(int _xs,int _ys)
{
int y;
free();
if (_xs<1) _xs=1;
if (_ys<1) _ys=1;
xs=_xs;
ys=_ys;
p=new double*[ys];
if (p==NULL)
{
xs=0;
ys=0;
return 0;
}
for (y=0;y<ys;y++)
{
p[y]=new double[xs];
if (p[y]==NULL)
{
if (y>0)
for (y--;y>=0;y--)
delete p[y];
delete p;
p=NULL;
xs=0;
ys=0;
return 0;
}
}
return 1;
}
//---------------------------------------------------------------------------
matrix& matrix::operator=(const matrix &b)
{
int x,y;
if (!resize(b.get_xs(),b.get_ys())) return *this;
if (b.p)
for (y=0;y<ys;y++)
for (x=0;x<xs;x++)
p[y][x]=b.p[y][x];
return *this;
}
//---------------------------------------------------------------------------
matrix& matrix::operator+()
{
static matrix c;
int x,y;
c.resize(xs,ys);
for (y=0;y<ys;y++)
for (x=0;x<xs;x++)
c.p[y][x]= p[y][x];
return c;
}
//---------------------------------------------------------------------------
matrix& matrix::operator-()
{
static matrix c;
int x,y;
c.resize(xs,ys);
for (y=0;y<ys;y++)
for (x=0;x<xs;x++)
c.p[y][x]=-p[y][x];
return c;
}
//---------------------------------------------------------------------------
matrix& matrix::operator+(matrix &b)
{
static matrix c;
int x,y;
c.free();
if (xs!=b.get_xs()) return c;
if (ys!=b.get_ys()) return c;
c.resize(xs,ys);
for (y=0;y<ys;y++)
for (x=0;x<xs;x++)
c.p[y][x]=p[y][x]+b.p[y][x];
return c;
}
//---------------------------------------------------------------------------
matrix& matrix::operator-(matrix &b)
{
static matrix c;
int x,y;
c.free();
if (xs!=b.get_xs()) return c;
if (ys!=b.get_ys()) return c;
c.resize(xs,ys);
for (y=0;y<ys;y++)
for (x=0;x<xs;x++)
c.p[y][x]=p[y][x]-b.p[y][x];
return c;
}
//---------------------------------------------------------------------------
matrix& matrix::operator*(matrix &b)
{
static matrix c;
int i,j,k,ii,jj,kk;
c.free();
ii=ys;
jj=b.get_xs();
kk=b.get_ys();
if (kk!=xs) return c;
if (!c.resize(jj,ii)) return c;
for (i=0;i<ii;i++)
for (j=0;j<jj;j++)
c.p[i][j]=0.0;
for (i=0;i<ii;i++)
for (j=0;j<jj;j++)
for (k=0;k<kk;k++)
c.p[i][j]+=p[i][k]*b.p[k][j];
return c;
}
//---------------------------------------------------------------------------
matrix& matrix::operator+=(matrix &b)
{
int x,y;
if (xs!=b.get_xs()) { free(); return *this; }
if (ys!=b.get_ys()) { free(); return *this; }
for (y=0;y<ys;y++)
for (x=0;x<xs;x++)
p[y][x]+=b.p[y][x];
return *this;
}
//---------------------------------------------------------------------------
matrix& matrix::operator-=(matrix &b)
{
int x,y;
if (xs!=b.get_xs()) { free(); return *this; }
if (ys!=b.get_ys()) { free(); return *this; }
for (y=0;y<ys;y++)
for (x=0;x<xs;x++)
p[y][x]-=b.p[y][x];
return *this;
}
//---------------------------------------------------------------------------
matrix& matrix::operator*=(matrix &b)
{
matrix c;
int i,j,k,ii,jj,kk;
c.free();
ii=ys;
jj=b.get_xs();
kk=b.get_ys();
if (kk!=xs) { *this=c; return *this; }
if (!c.resize(jj,ii)) { *this=c; return *this; }
for (i=0;i<ii;i++)
for (j=0;j<jj;j++)
c.p[i][j]=0.0;
for (i=0;i<ii;i++)
for (j=0;j<jj;j++)
for (k=0;k<kk;k++)
c.p[i][j]+=p[i][k]*b.p[k][j];
*this=c; return *this;
}
//---------------------------------------------------------------------------
matrix& matrix::operator!()
{
// return inv_det();
return inv_gaus();
}
//---------------------------------------------------------------------------
double& matrix::operator()(int y,int x)
{
static double _null;
if (x<0) return _null;
if (y<0) return _null;
if (x>=xs) return _null;
if (y>=ys) return _null;
return p[y][x];
}
//---------------------------------------------------------------------------
void matrix::one()
{
int x,y;
for (y=0;y<ys;y++)
for (x=0;x<xs;x++)
if (x!=y) p[y][x]=0.0;
else p[y][x]=1.0;
}
//---------------------------------------------------------------------------
void matrix::ld(int y,double x0,double x1,double x2,double x3,double x4,double x5,double x6,double x7,double x8,double x9)
{
int x;
if (y<0) return;
if (y>=ys) return;
x=0;
if (x<xs) p[y][x]=x0; x++;
if (x<xs) p[y][x]=x1; x++;
if (x<xs) p[y][x]=x2; x++;
if (x<xs) p[y][x]=x3; x++;
if (x<xs) p[y][x]=x4; x++;
if (x<xs) p[y][x]=x5; x++;
if (x<xs) p[y][x]=x6; x++;
if (x<xs) p[y][x]=x7; x++;
if (x<xs) p[y][x]=x8; x++;
if (x<xs) p[y][x]=x9; x++;
}
//---------------------------------------------------------------------------
void matrix::prn(TCanvas *scr,int x0,int y0)
{
int x,y,xx,yy,dx,dy;
dx=50;
dy=13;
yy=y0;
for (y=0;y<ys;y++)
{
xx=x0;
for (x=0;x<xs;x++)
{
scr->TextOutA(xx,yy,AnsiString().sprintf("%.4lf",p[y][x]));
xx+=dx;
}
yy+=dy;
}
}
//---------------------------------------------------------------------------
void matrix::lxch(int y1,int y2)
{
int x;
double a;
if (y1<0) return;
if (y2<0) return;
if (y1>=ys) return;
if (y2>=ys) return;
for (x=0;x<xs;x++) { a=p[y1][x]; p[y1][x]=p[y2][x]; p[y2][x]=a; }
}
//---------------------------------------------------------------------------
void matrix::lcom(int y1,int y2,double k)
{
int x;
if (y1<0) return;
if (y2<0) return;
if (y1>=ys) return;
if (y2>=ys) return;
for (x=0;x<xs;x++) p[y1][x]+=p[y2][x]*k;
}
//---------------------------------------------------------------------------
void matrix::lmul(int y,double k)
{
int x;
if (y<0) return;
if (y>=ys) return;
for (x=0;x<xs;x++) p[y][x]*=k;
}
//---------------------------------------------------------------------------
void matrix::ldiv(int y,double k)
{
int x;
if (y<0) return;
if (y>=ys) return;
if ((k> zeroacc)||(k<-zeroacc)) k=1.0/k; else k=0.0;
for (x=0;x<xs;x++) p[y][x]*=k;
}
//---------------------------------------------------------------------------
int matrix::gaus(matrix &b)
{
int x,y;
double a;
if (xs!=ys) return 0;
if (ys!=b.ys) return 0;
for (x=0;x<xs;x++)
{
a=p[x][x]; // je aktualny prvok (x,x) na diagonale = 0 ?
if (a<0) a=-a;
if (a<=zeroacc)
for (y=0;y<ys;y++) // ak hej najdi nejaky nenulovy riadok v aktualnom stlpci (x)
if (x!=y)
{
a=p[y][x];
if (a<0) a=-a;
if (a>=zeroacc) // ak sa nasiel tak ho pripocitaj k aktualnemu riadku co zrusi tu nulu
{
b.lcom(x,y,1.0);
lcom(x,y,1.0);
break;
}
}
a=p[x][x]; // este raz otestuj ci na diagonale neni nula
if (a<0) a=-a;
if (a<=zeroacc) return 0; // ak je tak koniec
b.ldiv(x,p[x][x]); // sprav na diagonale 1-tku
ldiv(x,p[x][x]);
for (y=0;y<ys;y++) // a vynuluj zvysne riadky v stlpci(x)
if (y!=x)
{
b.lcom(y,x,-p[y][x]);
lcom(y,x,-p[y][x]);
}
}
return 1;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
matrix& matrix::submatrix(int _x,int _y)
{
static matrix c;
int x,y,xx,yy;
c.resize(xs-1,ys-1);
yy=0; for (y=0;y<ys;y++)
if (y!=_y)
{
xx=0; for (x=0;x<xs;x++)
if (x!=_x)
{
c.p[yy][xx]=p[y][x];
xx++;
}
yy++;
}
return c;
}
//---------------------------------------------------------------------------
double matrix::determinant()
{
double D;
matrix a;
int x,y,s;
D=0;
if (xs!=ys) return D;
if (xs==1) { D=p[0][0]; return D; }
y=0;
s=y&1;
for (x=0;x<xs;x++)
{
a=submatrix(x,y);
if (s) D-=a.determinant()*p[y][x];
else D+=a.determinant()*p[y][x];
s=!s;
}
return D;
}
//---------------------------------------------------------------------------
double matrix::subdeterminant()
{
double D;
matrix a,b;
int x,y,s;
D=0;
if (xs!=ys) return D;
if (xs==1) { D=p[0][0]; return D; }
b=this[0];
for (y=0;y<ys;y++)
for (x=0;x<xs;x++)
{
a=b.submatrix(x,y);
p[y][x]=a.determinant();
}
y=0;
s=y&1;
for (x=0;x<xs;x++)
{
if (s) D-=p[y][x]*b.p[y][x];
else D+=p[y][x]*b.p[y][x];
s=!s;
}
return D;
}
//---------------------------------------------------------------------------
matrix& matrix::inv_det()
{
int x,y,s;
double D;
static matrix a,b;
a=this[0];
b=this[0];
D=b.subdeterminant();
if (fabs(D)>zeroacc) D=1.0/D;
for (y=0;y<ys;y++)
for (x=0;x<xs;x++)
{
s=(x+y)&1;
if (s) a.p[y][x]=-b.p[x][y]*D;
else a.p[y][x]= b.p[x][y]*D;
}
return a;
}
//---------------------------------------------------------------------------
matrix& matrix::inv_gaus()
{
static matrix a,b;
a=*this;
b.resize(xs,ys);
b.one();
a.gaus(b);
return b;
}
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
Both GEM inv_gaus and (sub)determinant inv_det approaches are present so just extract/compare from it what you need.
BTW lately I needed some math stuff for N-dimensional space and once I was at it I also coded a square matrix as template where the (sub)Determinant approach is done as recursive template nd_math.h:
//--- N-Dimensional math ver: 1.002 -----------------------------------------
#ifndef _ND_math_h
#define _ND_math_h
//---------------------------------------------------------------------------
#include <math.h>
//---------------------------------------------------------------------------
#ifndef _rep4d_h
double divide(double a,double b) { if (fabs(b)<1e-30) return 0.0; return a/b; }
#endif
//---------------------------------------------------------------------------
template <const DWORD N> class vector
{
public:
double a[N];
vector() {}
vector(vector& a) { *this=a; }
~vector() {}
vector* operator = (const vector<N> *a) { *this=*a; return this; }
//vector* operator = (vector<N> &a) { ...copy... return this; }
double& operator [](const int i) { return a[i]; }
vector<N> operator + () { return *this; } // =+v0
vector<N> operator - () { int i; vector<N> q; for ( i=0;i<N;i++) q.a[i]= -a[i]; return q; } // =-v0
vector<N> operator + (vector<N> &v) { int i; vector<N> q; for ( i=0;i<N;i++) q.a[i]=a[i]+v.a[i]; return q; } // =v0+v1
vector<N> operator - (vector<N> &v) { int i; vector<N> q; for ( i=0;i<N;i++) q.a[i]=a[i]-v.a[i]; return q; } // =v0-v1
double operator * (vector<N> &v) { int i; double q; for (q=0.0,i=0;i<N;i++) q +=a[i]*v.a[i]; return q; } // =(v0.v1) dot product
vector<N> operator + (const double &c) { int i; vector<N> q; for ( i=0;i<N;i++) q.a[i]=a[i]+c; return q; } // =v0+(c,c,c,c,...)
vector<N> operator - (const double &c) { int i; vector<N> q; for ( i=0;i<N;i++) q.a[i]=a[i]-c; return q; } // =v0-(c,c,c,c,...)
vector<N> operator * (const double &c) { int i; vector<N> q; for ( i=0;i<N;i++) q.a[i]=a[i]*c; return q; } // =v0*c
vector<N> operator / ( double c) { int i; vector<N> q; c=divide(1.0,c); for ( i=0;i<N;i++) q.a[i]=a[i]*c; return q; } // =v0/c
vector<N> operator +=(vector<N> &v) { this[0]=this[0]+v; return *this; }; // v0+=v1
vector<N> operator -=(vector<N> &v) { this[0]=this[0]-v; return *this; }; // v0-=v1
vector<N> operator +=(const double &c) { this[0]=this[0]+c; return *this; }; // v0+=(c,c,c,c,...)
vector<N> operator -=(const double &c) { this[0]=this[0]-c; return *this; }; // v0-=(c,c,c,c,...)
vector<N> operator *=(const double &c) { this[0]=this[0]*c; return *this; }; // v0*=c
vector<N> operator /=(const double &c) { this[0]=this[0]/c; return *this; }; // v0/=c
AnsiString str() { int i; AnsiString q; for (q="( ",i=0;i<N;i++) q+=AnsiString().sprintf("%6.3lf ",a[i]); q+=")"; return q; }
double len() { int i; double l; for (l=0.0,i=0;i<N;i++) l+=a[i]*a[i]; return sqrt(l); } // get size
double len2() { int i; double l; for (l=0.0,i=0;i<N;i++) l+=a[i]*a[i]; return l; } // get size^2
void len(double l) { int i; l=divide(l,len()); for (i=0;i<N;i++) a[i]*=l; } // set size
void unit() { len(1.0); } // set unit size
void zero() { int i; for (i=0;i<N;i++) a[i]=0.0; } // set zero vector
void rnd() { int i; for (i=0;i<N;i++) a[i]=(2.0*Random())-1.0; } // set random unit vector
void set(double c) { int i; for (i=0;i<N;i++) a[i]=c; } // (c,c,c,c,...)
// i x j = k | | i j k |
// j x k = i | a x b = det | a0 a1 a2 | = + i*det | a1 a2 | - j*det | a0 a2 | + k*det | a0 a1 |
// k x i = j | | b0 b1 b2 | | b1 b2 | | b0 b2 | | b0 b1 |
void cross(const vector<N> *v)
{
int i,j;
matrix<N> m0;
matrix<N-1> m;
for (i=1;i<N;i++)
for (j=0;j<N;j++)
m0.a[i][j]=v[i-1].a[j];
for (j=0;j<N;j++)
{
m=m0.submatrix(0,j);
if (int(j&1)==0) a[j]=+m.det();
else a[j]=-m.det();
}
}
void cross(vector<N> **v)
{
int i,j;
matrix<N> m0;
matrix<N-1> m;
for (i=1;i<N;i++)
for (j=0;j<N;j++)
m0.a[i][j]=v[i-1]->a[j];
for (j=0;j<N;j++)
{
m=m0.submatrix(0,j);
if (int(j&1)==0) a[j]=+m.det();
else a[j]=-m.det();
}
}
void cross(vector<N> &v0) { vector<N> *v[ 1]={&v0}; cross(v); }
void cross(vector<N> &v0,vector<N> &v1) { vector<N> *v[ 2]={&v0,&v1}; cross(v); }
void cross(vector<N> &v0,vector<N> &v1,vector<N> &v2) { vector<N> *v[ 3]={&v0,&v1,&v2}; cross(v); }
void cross(vector<N> &v0,vector<N> &v1,vector<N> &v2,vector<N> &v3) { vector<N> *v[ 4]={&v0,&v1,&v2,&v3}; cross(v); }
void cross(vector<N> &v0,vector<N> &v1,vector<N> &v2,vector<N> &v3,vector<N> &v4) { vector<N> *v[ 5]={&v0,&v1,&v2,&v3,&v4}; cross(v); }
void cross(vector<N> &v0,vector<N> &v1,vector<N> &v2,vector<N> &v3,vector<N> &v4,vector<N> &v5) { vector<N> *v[ 6]={&v0,&v1,&v2,&v3,&v4,&v5}; cross(v); }
void cross(vector<N> &v0,vector<N> &v1,vector<N> &v2,vector<N> &v3,vector<N> &v4,vector<N> &v5,vector<N> &v6) { vector<N> *v[ 7]={&v0,&v1,&v2,&v3,&v4,&v5,&v6}; cross(v); }
void cross(vector<N> &v0,vector<N> &v1,vector<N> &v2,vector<N> &v3,vector<N> &v4,vector<N> &v5,vector<N> &v6,vector<N> &v7) { vector<N> *v[ 8]={&v0,&v1,&v2,&v3,&v4,&v5,&v6,&v7}; cross(v); }
void cross(vector<N> &v0,vector<N> &v1,vector<N> &v2,vector<N> &v3,vector<N> &v4,vector<N> &v5,vector<N> &v6,vector<N> &v7,vector<N> &v8) { vector<N> *v[ 9]={&v0,&v1,&v2,&v3,&v4,&v5,&v6,&v7,v8}; cross(v); }
void cross(vector<N> &v0,vector<N> &v1,vector<N> &v2,vector<N> &v3,vector<N> &v4,vector<N> &v5,vector<N> &v6,vector<N> &v7,vector<N> &v8,vector<N> &v9) { vector<N> *v[10]={&v0,&v1,&v2,&v3,&v4,&v5,&v6,&v7,v8,v9}; cross(v); }
void ld(const double &a0) { a[0]=a0; }
void ld(const double &a0,const double &a1) { a[0]=a0; a[1]=a1; }
void ld(const double &a0,const double &a1,const double &a2) { a[0]=a0; a[1]=a1; a[2]=a2; }
void ld(const double &a0,const double &a1,const double &a2,const double &a3) { a[0]=a0; a[1]=a1; a[2]=a2; a[3]=a3; }
void ld(const double &a0,const double &a1,const double &a2,const double &a3,const double &a4) { a[0]=a0; a[1]=a1; a[2]=a2; a[3]=a3; a[4]=a4; }
void ld(const double &a0,const double &a1,const double &a2,const double &a3,const double &a4,const double &a5) { a[0]=a0; a[1]=a1; a[2]=a2; a[3]=a3; a[4]=a4; a[5]=a5; }
void ld(const double &a0,const double &a1,const double &a2,const double &a3,const double &a4,const double &a5,const double &a6) { a[0]=a0; a[1]=a1; a[2]=a2; a[3]=a3; a[4]=a4; a[5]=a5; a[6]=a6; }
void ld(const double &a0,const double &a1,const double &a2,const double &a3,const double &a4,const double &a5,const double &a6,const double &a7) { a[0]=a0; a[1]=a1; a[2]=a2; a[3]=a3; a[4]=a4; a[5]=a5; a[6]=a6; a[7]=a7; }
void ld(const double &a0,const double &a1,const double &a2,const double &a3,const double &a4,const double &a5,const double &a6,const double &a7,const double &a8) { a[0]=a0; a[1]=a1; a[2]=a2; a[3]=a3; a[4]=a4; a[5]=a5; a[6]=a6; a[7]=a7; a[8]=a8; }
void ld(const double &a0,const double &a1,const double &a2,const double &a3,const double &a4,const double &a5,const double &a6,const double &a7,const double &a8,const double &a9) { a[0]=a0; a[1]=a1; a[2]=a2; a[3]=a3; a[4]=a4; a[5]=a5; a[6]=a6; a[7]=a7; a[8]=a8; a[9]=a9; }
};
//---------------------------------------------------------------------------
template <DWORD N> class matrix // square matrix
{
public:
vector<N> a[N];
matrix() {}
matrix(matrix& a) { *this=a; }
~matrix() {}
matrix* operator = (const matrix<N> *a) { *this=*a; return this; }
//matrix* operator = (matrix<N> &a) { ...copy... return this; }
vector<N>& operator [](const int i) { return a[i]; }
matrix<N> operator + () { return *this; }
matrix<N> operator - () { matrix<N> q; int i,j; for (i=0;i<M;i++) for (j=0;j<N;j++) q[i][j]=-a[i][j]; return q; } // = -m0
matrix<N> operator * (const matrix &m)
{
matrix<N> q;
int i,j,k;
for (i=0;i<N;i++)
for (j=0;j<N;j++)
for (q.a[i][j]=0.0,k=0;k<N;k++)
q.a[i].a[j]+=a[i].a[k]*m.a[k].a[j];
return q;
}
vector<N> operator * (vector<N> &v)
{
vector<N> q;
int i,j;
for (i=0;i<N;i++)
for (q.a[i]=0.0,j=0;j<N;j++)
q.a[i]+=a[i][j]*v.a[j];
return q;
}
matrix<N> operator * (const double &c)
{
matrix<N> q;
int i,j;
for (i=0;i<N;i++)
for (j=0;j<N;j++)
q.a[i].a[j]=a[i].a[j]*c;
return q;
}
matrix<N> operator / (const double &c)
{
return this[0]*divide(1.0,c);
}
matrix<N> operator *=(matrix<N> &m) { this[0]=this[0]*m; return *this; };
vector<N> operator *=(vector<N> &v) { this[0]=this[0]*v; return *this; };
matrix<N> operator *=(const double &c) { this[0]=this[0]*c; return *this; };
matrix<N> operator /=(const double &c) { this[0]=this[0]/c; return *this; };
AnsiString str() { int i,j; AnsiString q; for (q="",i=0;i<N;i++,q+="\r\n") { for (q+="( ",j=0;j<N;j++) q+=AnsiString().sprintf("%6.3lf ",a[i][j]); q+=")"; } return q; }
void unit() { int i,j; for (i=0;i<N;a[i][i]=1.0,i++) for (j=0;j<N;j++) a[i][j]=0.0; } // set unit matrix
void zero() { int i,j; for (i=0;i<N;i++) for (j=0;j<N;j++) a[i][j]=0.0; } // set zero matrix
void rnd() { int i,j; for (i=0;i<N;i++) for (j=0;j<N;j++) a[i][j]=(2.0*Random())-1.0; } // set random <-1,+1> matrix
void set(double c) { int i,j; for (i=0;i<N;i++) for (j=0;j<N;j++) a[i][j]=c; } // (c,c,c,c,...)
void orthonormal() // convert to orthonormal matrix
{
int i,j;
vector<N> *pV[N],*pp;
for (i=0;i<N;i++) { a[i].unit(); pV[i]=a+i; }
for (i=1;i<N;i++)
{
pV[0]->cross(pV+1);
pp=pV[0]; for (j=1;j<N;j++) pV[j-1]=pV[j]; pV[N-1]=pp;
}
}
matrix<N> transpose()
{
int i,j;
matrix<N> M;
for (i=0;i<N;i++)
for (j=0;j<N;j++)
M[i][j]=a[j][i];
return M;
}
matrix<N> inverse()
{
return adjugate()/det();
}
matrix<N> adjugate()
{
matrix<N> C;
double s;
int i,j;
for (i=0;i<N;i++)
for ((i&1)?s=-1.0:s=+1.0,j=0;j<N;j++,s=-s)
C[j][i]=minor(i,j)*s;
return C;
}
matrix<N> cofactor()
{
matrix<N> C;
double s;
int i,j;
for (i=0;i<N;i++)
for ((i&1)?s=+1.0:s=-1.0,j=0;j<N;j++,s=-s)
C[i][j]=minor(i,j)*s;
return C;
}
double minor(int i,int j)
{
return submatrix(i,j).det();
}
matrix<N-1> submatrix(int i,int j)
{
matrix<N-1> m;
int i0,i1,j0,j1;
for (i0=0,i1=0;i1<N;i1++)
if (i1!=i){ for (j0=0,j1=0;j1<N;j1++)
if (j1!=j){ m.a[i0][j0]=a[i1][j1]; j0++; } i0++; }
return m;
}
double det();
};
//---------------------------------------------------------------------------
double matrix<1>::det() { return a[0][0]; }
double matrix<2>::det() { return (a[0][0]*a[1][1])-(a[0][1]*a[1][0]); }
template <DWORD N> double matrix<N>::det()
{
double d=0.0; int j;
matrix<N-1> m;
for (j=0;j<N;j++)
{
m=submatrix(0,j);
if (int(j&1)==0) d+=a[0][j]*m.det();
else d-=a[0][j]*m.det();
}
return d;
}
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
But as you can see that code is a bit more complicated to follow as I am in a different coding level now (look for inverse)...
If you need also results then compute it as matrix equation:
A*X = Y
X = inv(A)*Y
Where X are unknowns (vector) , Y are knowns (vector) and A is the matrix.
Related
Tried Knap snap problem but its not working
#include<stdio.h> int max(int a,int b) { if(a>b) return a; return b; } void knacksnap(int n,int a[][n+1],int* val,int* weight,int maxweight) { if(n==0 || maxweight==0) { a[maxweight][n]=0; return; } if(a[maxweight][n]!=-1) return; if(weight[n-1]>maxweight) { knacksnap(n-1,a,val,weight,maxweight); a[maxweight][n]=a[maxweight][n-1]; } else { knacksnap(n-1,a,val,weight,maxweight-weight[n-1]); knacksnap(n-1,a,val,weight,maxweight); a[maxweight][n]=max(val[n-1]+a[maxweight-weight[n-1]][n-1],a[maxweight][n-1]); } } int main() { int n; scanf("%d",&n); int val[n],weight[n]; int i; for(i=0;i<n;i++) scanf("%d",&val[i]); for(i=0;i<n;i++) scanf("%d",&weight[i]); int maxweight; scanf("%d",&maxweight); int a[maxweight+1][n+1]; int j; for(i=0;i<maxweight+1;i++) { for(j=0;j<n+1;j++) { a[i][j]=-1; } } knacksnap(n,a,val,weight,maxweight); printf("\n"); printf("%d",a[maxweight][n]); } It not taking updated values by the knacksnap function. for example the inner knacksnap funtions are not generating correct values. eventhough their values are updated its not taking them. can someone please help
Heap Code Error
I am getting an error in the following code. I am building a heap and for that I use the buildup and move-up functions whereas for deleting the values I use move-down and deletion functions. And for inserting the values I use insert function. My output is showing error for the deletion part. #include<stdio.h> #include<stdlib.h> int a[100]; int size; void display(); void moveup(int); void insert(int); void buildup(); int deletion(); void movedown(int); int h; void main() { size=5; int i,j; printf("enter the elements\n"); for(i=1;i<=5;i++) { scanf("%d",&a[i]); } a[0]=32767; printf("\n"); buildup(); display(); insert(9); display(); printf("\n after deletion\n"); deletion(); display(); } void buildup() { int i; for(i=2;i<=size;i++) moveup(i); } void moveup(int i) { int p,temp; temp=a[i]; p=i/2; while(temp>a[p]) { a[i]=a[p]; i=p; p=i/2; } a[i]=temp; } void display() { int i; for(i=1;i<=size;i++) printf("%3d\n",a[i]); } void insert(int t) { printf("\n after insertion\n"); if(size==99) printf("insertion not possible"); a[++size]=t; moveup(size); } int deletion() { int t; t=a[1]; h=a[size--]; a[1]=h; movedown(1); return t; } void movedown(int i) { int l; int r; i=2*i; r=l+1; while(r<=size) { if(h>a[l]&&h>a[r]) { a[i]=h; return; } else { if(a[l]>a[r]) { a[i]=a[l]; i=l; } else { a[i]=a[r]; i=r; } } l=2*i; r=l+1; } if(l<=size&&a[l]>h) { a[i]=a[l]; i=l; } a[i]=h; }
Strassen multiplication - c program
We had to implement strassen's multiplication in a practical session , the code I wrote is given below , as you can see I have used a lot of intermediate matrices .I wanted to know how to return a 2d array from a function so that the code will look cleaner and more understandable , also it will give me some insights on pointers(a weak area for me )i.e say is use a double pointer as return type of sub function (int **sub(args list)) and since my strassen function has prototype strassen(int , int [],int[]..) When one argument of strassen function is a result of sub function , I get an error saying int (*)[] expected but returning int ** To resolve this I typecasted the result of sub function with int (*)[] but it does not work as expected Help please ? Thanks ! #include<stdio.h> #include<stdlib.h> void add(int n,int a[n][n],int b[n][n],int result[][n]) { printf("---add---\n"); int i,j; //int **result = (int **)malloc(n*sizeof(int *)); /*for(i=0;i<n;i++) result[i] = (int *)malloc(n*sizeof(int));*/ for(i=0;i<n;i++) { for(j=0;j<n;j++) { result[i][j] = a[i][j] + b[i][j]; printf("%d\t",result[i][j]); } printf("\n"); } //return result; } void sub(int n,int a[n][n],int b[n][n],int result[][n]) { printf("---sub---\n"); int i,j; /*int **result = (int **)malloc(n*sizeof(int *)); for(i=0;i<n;i++) result[i] = (int *)malloc(n*sizeof(int));*/ for(i=0;i<n;i++) { for(j=0;j<n;j++) { result[i][j] = a[i][j] - b[i][j]; printf("%d\t",result[i][j]); } } } void divide(int n,int a[n][n],int c[n/2][n/2],int i,int j) { int i1,i2,j1,j2; for(i1=0,i2=i;i1<n/2;i1++,i2++) { for(j1=0,j2=j;j1<n/2;j1++,j2++) { c[i1][j1] = a[i2][j2]; } } } void join(int n,int a[][n],int c[][n/2],int i,int j) { printf("join\n"); int i1,i2,j1,j2; for(i1=0,i2=i;i1<(n/2);i1++,i2++) { for(j1=0,j2=j;j1<(n/2);j1++,j2++) { a[i2][j2] = c[i1][j1]; printf("c[%d][%d] %d\n",i1,j1,c[i1][j1]); } } } void multiply(int n,int a[][n],int b[][n],int result[][n]) { int i,j; if(n==2) { //partial products printf("base case\n"); int p1 = (a[0][0]+a[1][1])*(b[0][0]+b[1][1]); int p2 = (a[1][0]+a[1][1])*b[0][0]; int p3 = a[0][0]*(b[0][1]-b[1][1]); int p4 = a[1][1]*(b[1][0]-b[0][0]); int p5 = (a[0][0]+a[0][1])*b[1][1]; int p6 = (a[1][0]-a[0][0])*(b[0][0]+b[0][1]); int p7 = (a[0][1]-a[1][1])*(b[1][0]+b[1][1]); int c11 = p1 + p4 - p5 + p7; int c12 = p3 + p5; int c21 = p2 + p4; int c22 = p1 + p3 - p2 + p6; result[0][0] = c11; result[0][1] = c12; result[1][0] = c21; result[1][1] = c22; for(i=0;i<2;i++) { for(j=0;j<2;j++) { printf("%d\t",result[i][j]); } printf("\n"); } } else { int a11[n/2][n/2]; int a12[n/2][n/2]; int a21[n/2][n/2]; int a22[n/2][n/2]; int b11[n/2][n/2]; int b12[n/2][n/2]; int b21[n/2][n/2]; int b22[n/2][n/2]; //divide matrices A & B into four parts divide(n,a,a11,0,0); divide(n,a,a12,0,n/2); divide(n,a,a21,n/2,0); divide(n,a,a22,n/2,n/2); divide(n,b,b11,0,0); divide(n,b,b12,0,n/2); divide(n,b,b21,n/2,0); divide(n,b,b22,n/2,n/2); //partial products int p1[n/2][n/2],p2[n/2][n/2],p3[n/2][n/2],p4[n/2][n/2],p5[n/2][n/2],p6[n/2][n/2],p7[n/2][n/2]; int c11[n/2][n/2],c12[n/2][n/2],c21[n/2][n/2],c22[n/2][n/2]; int i1[n/2][n/2],i2[n/2][n/2]; add(n/2,a11,a22,i1); add(n/2,b11,b22,i2); multiply(n/2,i1,i2,p1); int i3[n/2][n/2]; add(n/2,a21,a22,i3); multiply(n/2,i3,b11,p2); int i4[n/2][n/2]; sub(n/2,b12,b22,i4); multiply(n/2,a11,i4,p3); int i5[n/2][n/2]; sub(n/2,b21,b11,i5); multiply(n/2,a22,i5,p4); int i6[n/2][n/2]; add(n/2,a11,a12,i6); multiply(n/2,i6,b22,p5); int i7[n/2][n/2]; int i8[n/2][n/2]; sub(n/2,a21,a11,i7); add(n/2,b11,b12,i8); multiply(n/2,i7,i8,p6); int i9[n/2][n/2]; int i10[n/2][n/2]; sub(n/2,a12,a22,i9); add(n/2,b21,b22,i10); multiply(n/2,i9,i10,p7); //for c11 int r1[n/2][n/2]; int r2[n/2][n/2]; add(n/2,p1,p4,r1); //sub operation sub(n/2,r1,p5,r2); //sub operation add(n/2,r2,p7,c11); //main operation //for c12 add(n/2,p3,p5,c12); //for c21 add(n/2,p2,p4,c21); //for c22 int r3[n/2][n/2]; int r4[n/2][n/2]; add(n/2,p1,p3,r3); //sub operation sub(n/2,r3,p2,r4); //sub operation add(n/2,r4,p6,c22); //main operation join(n,result,c11,0,0); join(n,result,c12,0,n/2); join(n,result,c21,n/2,0); join(n,result,c22,n/2,n/2); printf("---c11---\n"); for(i=0;i<n/2;i++) { for(j=0;j<n/2;j++) { printf("%d\t",c11[i][j]); } printf("\n"); } printf("---c12---\n"); for(i=0;i<n/2;i++) { for(j=0;j<n/2;j++) { printf("%d\t",c12[i][j]); } printf("\n"); } printf("---c21---\n"); for(i=0;i<n/2;i++) { for(j=0;j<n/2;j++) { printf("%d\t",c21[i][j]); } printf("\n"); } printf("---c22---\n"); for(i=0;i<n/2;i++) { for(j=0;j<n/2;j++) { printf("%d\t",c22[i][j]); } printf("\n"); } /*for(i=0;i<n;i++) { for(j=0;j<n;j++) { printf("%d\t",result[i][j]); } printf("\n"); }*/ } } int main() { int n; printf("Enter the order of the matrices(power of 2)\n"); scanf("%d",&n); int i,j; int a[n][n],b[n][n]; printf("Enter first matrix\n"); for(i=0;i<n;i++) { for(j=0;j<n;j++) { scanf("%d",&a[i][j]); } } printf("Enter second matrix\n"); for(i=0;i<n;i++) { for(j=0;j<n;j++) { scanf("%d",&b[i][j]); } } printf("First matrix is \n"); for(i=0;i<n;i++) { for(j=0;j<n;j++) { printf("%d\t",a[i][j]); } printf("\n"); } printf("Second matrix is \n"); for(i=0;i<n;i++) { for(j=0;j<n;j++) { printf("%d\t",b[i][j]); } printf("\n"); } int r[n][n]; multiply(n,a,b,r); printf("---RESULT OF MULTIPLICATION---\n"); for(i=0;i<n;i++) { for(j=0;j<n;j++) { printf("%d\t",r[i][j]); } printf("\n"); } return 0; }
Function string_to_table is breaking on 3rd if c
I am trying to create program to add two matrixes. After typing input like [12 4] program crashes when function strcat starts. I have no idea what is wrong. func.h consists of stdio.h, _mingw.h,stdlib.h and string.h #include"func.h" void string_to_table(double **matrix, char inpt[])/*problematic function*/ { printf("convertion start"); int i=strlen(inpt); printf("%i",i); int j=1; int k=0,l=0; char num[128]; double converted=0; printf("breakpoint1"); while(j<(i-1)) { if(inpt[j]==' ') { printf("first if"); converted=atof(num); num[0]='\0'; matrix[k][l]=converted; ++l; printf("breakpoint2"); } else if(inpt[j]==';') { printf("second if"); converted=atof(num); num[0]='\0'; matrix[k][l]=converted; ++k; l=0; } else { printf("third if"); strcat(num,inpt[j]);/*place when everything crashes*/ } ++j; } printf("convert0 end"); } void add_matrix(double **matrix1, double **matrix2,int i,int j) { int k=0; int l=0; while(k<i) { while(l<j) { matrix1[k][l]+=matrix2[k][l]; ++l; } l=0; ++k; } int matrixproccesing(int *i,int *j, char m[])/*sprawdzanie poprawnosci wejscia*/ { printf("macro start"); int columnnum=0,rownum=0,x=0,piv=0,check=0; int textsize=strlen(m); printf("%i",i); printf("loop start"); printf("%i",textsize); while(x<(textsize-1)) { printf("%i",x); printf("\n"); if(x==0)/*czy poczatek to [*/ { if(m[x]!='[') return 0; } else if(x==(textsize-2))/*czy koniec to]*/ { printf("kohec"); if(m[x]==']') break; return 0; } else if((m[x]>47&&m[x]<58)||(m[x]==' ')||(m[x]=='.')||(m[x]==';')||(m[x]=='-'))/*czy liczba*/ { if(m[x]==';')/*czy ilosc liczb w rzedzie taka sama*/ { if(check==0) { check=columnnum; } else if(check!=columnnum) { return 0; } printf("colnum"); columnnum=0; rownum++; } else if(m[x]==' ')/*czy nowa liczba/kolumna */ { columnnum++; } } ++x; } *i=(check+1); *j=(columnnum+1); printf("macro end"); return 1; } int is_same_size(int a, int b,int c ,int d)/*test rozmiaru*/ { if((a==c)&(b==d)) return 1; return 0; } void print_da_matrix(double **matrix, int i, int j) { int k=0,l=0; printf("[ "); while(k<i) { while(l<j) { printf("%f",matrix[k][l]); printf(" "); } printf(";"); l=0; if(k<(i-1)) ++k; } printf("]"); } void release_the_memory(double **matrix, int i) { int k=0; while(k<i) { free(matrix[k]); ++k; } free(matrix); matrix=NULL; } } int main() { int i=0,j=0,m1=0,m2=0,tabcr=0; char matrix[512]; fgets(&matrix,511,stdin); double **matrix1; double **matrix2; if(!matrixproccesing(&i,&j,matrix)) { printf("zle wejscie"); return 0; } matrix1=(double**)malloc(i*sizeof(double *)); while(tabcr<j) { matrix1[tabcr]=(double*)malloc(j*sizeof(double)); ++tabcr; } string_to_table(matrix1,matrix); printf("\n"); printf("podaj druga macierz"); fgets(&matrix,511,stdin); if(!matrixproccesing(&m1,&m2,matrix)) { printf("zle wejscie"); return 0; } tabcr=0; if(!is_same_size(i,j,m1,m2)) { printf("matrixes have different size."); return 0; } matrix2=(double**)malloc(i*sizeof(double *)); while(tabcr<j) { matrix2[tabcr]=(double*)malloc(j*sizeof(double)); ++tabcr; } string_to_table(matrix2,matrix); add_matrix(matrix1,matrix2,i,j); /* print_da_matrix(matrix1,i,j); release_the_memory(matrix1,i); release_the_memory(matrix2,i);*/ return 0; }
Append does not work with mousepressed?
I am having an issue with my project, and cannot figure it out. Processing is telling me what I have is not an array, but I do not see how it is not. Also, this issue only occurs when I click the mouse in an attempt to make something else appear. int numParticles = 200; GenParticle [] p = new GenParticle[numParticles]; float r=170; float g=150; float b=85; float velX; float velY; void setup(){ size(500,500); noStroke(); smooth(); frameRate(30); for (int i=0; i<p.length; i++){ velX = random(-1,1); velY = -i; p[i]=new GenParticle(width/2,height/2,velX,velY,5.0,width/2,height/2); } } void draw(){ fill(0,20); rect(0,0,width,height); fill(255,60); for(int i=0; i<p.length; i++){ p[i].update(); p[i].regenerate(); p[i].display(); } } void mousePressed() { GenParticle gp = new GenParticle(mouseX,mouseY, velX, velY,5.0,mouseX,mouseY); p = (GenParticle[]) append(gp,p); } class GenParticle extends Particle{ float originX,originY; GenParticle(int xIn,int yIn,float vxIn,float vyIn,float r,float ox,float oy){ super(xIn, yIn, vxIn, vyIn, r); originX=ox; originY=oy; } void regenerate(){ if ((x>width+radius) || (x<-radius) || (y>height+radius) || (y<-radius)){ x=originX; y=originY; vx=random(-1.0,1.0); vy=random(-4.0,-2.0); } } } class Particle{ float x, y; float vx,vy; float radius; float gravity=0.1; float r=0; float g=0; float b=0; Particle(int xpos,int ypos,float velx,float vely,float r){ x=xpos; y=ypos; vx=velx; vy=vely; radius=r; } void update(){ vy=vy+gravity; y += vy; x += vx; } void display(){ fill(r,g,b); ellipse(x, y, radius*3,radius*3); if(mouseX>width/2){ r=r+9; }else{ g=g+6; } if(mouseY>height/2){ b=b+7; }else{ b=b-3; } if(keyPressed) { g=g+1; }else{ g=g-5; } r=constrain(r,0,255); g=constrain(g,0,255); b=constrain(b,0,255); } }
Syntax error: the array is the first parameter and the object you want to append is the second parameter of the append() function Your mousePressed should look like this: void mousePressed() { GenParticle gp = new GenParticle(mouseX,mouseY, velX, velY,5.0,mouseX,mouseY); p = (GenParticle[]) append(p,pg); } Notice the array p goes first, then the object (append to array p object pg).