一个可复用的C++ 3阶实方阵类和4阶实方阵类(兼容与扩展了DX中的4阶实方阵类)
部分DX矩阵函数的实现
namespace Han
{
FLOAT WINAPI D3DXMatrixDeterminant(CONST D3DXMATRIX *pM)
{
D3DXMATRIX mtx=*pM;
FLOAT ret=Bsdet(&mtx(0,0),4);//第一个参数是输入输出参数
return ret;
}
D3DXMATRIX* D3DXMatrixIdentity(D3DXMATRIX *pOut)
{
//identity matrix
memset(pOut,0,sizeof(D3DXMATRIX));
pOut->m[0][0]=1;
pOut->m[1][1]=1;
pOut->m[2][2]=1;
pOut->m[3][3]=1;
return pOut;
}
//Build a matrix which scales by (sx,sy,sz)
D3DXMATRIX* D3DXMatrixScaling(D3DXMATRIX *pOut,FLOAT sx,FLOAT sy,FLOAT sz)
{
//创建一个沿着X,Y和Z轴方向缩放矩阵
memset(pOut,0,sizeof(D3DXMATRIX));
pOut->m[0][0]=sx;
pOut->m[1][1]=sy;
pOut->m[2][2]=sz;
pOut->m[3][3]=1;
return pOut;
}
//Build a matrix which translates by (x,y,z)
D3DXMATRIX* D3DXMatrixTranslation(D3DXMATRIX *pOut,FLOAT x,FLOAT y,FLOAT z)
{
//创建一个沿着X,Y和Z轴方向平移矩阵
memset(pOut,0,sizeof(D3DXMATRIX));
pOut->m[0][0]=1;
pOut->m[1][1]=1;
pOut->m[2][2]=1;
pOut->m[3][3]=1;
pOut->m[3][0]=x;
pOut->m[3][1]=y;
pOut->m[3][2]=z;
return pOut;
}
//Build a matrix which rotates around the X axis
D3DXMATRIX* D3DXMatrixRotationX(D3DXMATRIX *pOut,FLOAT Angle)
{
//创建一个绕X轴旋转Angle弧度的旋转矩阵
memset(pOut,0,sizeof(D3DXMATRIX));
pOut->m[0][0]=1;
pOut->m[1][1]=cos(Angle);
pOut->m[2][2]=cos(Angle);
pOut->m[3][3]=1;
pOut->m[1][2]=sin(Angle);
pOut->m[2][1]=-sin(Angle);
return pOut;
}
//Build a matrix which rotates around the Y axis
D3DXMATRIX* D3DXMatrixRotationY(D3DXMATRIX *pOut,FLOAT Angle)
{
//创建一个绕Y轴旋转Angle弧度的旋转矩阵
memset(pOut,0,sizeof(D3DXMATRIX));
pOut->m[0][0]=cos(Angle);
pOut->m[1][1]=1;
pOut->m[2][2]=cos(Angle);
pOut->m[3][3]=1;
pOut->m[0][2]=-sin(Angle);
pOut->m[2][0]=sin(Angle);
return pOut;
}
//Build a matrix which rotates around the Z axis
D3DXMATRIX* D3DXMatrixRotationZ(D3DXMATRIX *pOut,FLOAT Angle)
{
//创建一个绕Z轴旋转Angle弧度的旋转矩阵
memset(pOut,0,sizeof(D3DXMATRIX));
pOut->m[0][0]=cos(Angle);
pOut->m[1][1]=cos(Angle);
pOut->m[2][2]=1;
pOut->m[3][3]=1;
pOut->m[0][1]=sin(Angle);
pOut->m[1][0]=-sin(Angle);
return pOut;
}
//Transform (x,y,z,1) by matrix
D3DXVECTOR4* D3DXVec3Transform(D3DXVECTOR4 *pOut,CONST D3DXVECTOR4 *pV,CONST D3DXMATRIX *pM)
{
#if 1
//MV
D3DXVECTOR4 v(pV->x,pV->y,pV->z,1);
pOut->x=(*pM)(0,0)*v.x+(*pM)(0,1)*v.y+(*pM)(0,2)*v.z+(*pM)(0,3)*v.w;
pOut->y=(*pM)(1,0)*v.x+(*pM)(1,1)*v.y+(*pM)(1,2)*v.z+(*pM)(1,3)*v.w;
pOut->z=(*pM)(2,0)*v.x+(*pM)(2,1)*v.y+(*pM)(2,2)*v.z+(*pM)(2,3)*v.w;
pOut->w=(*pM)(3,0)*v.x+(*pM)(3,1)*v.y+(*pM)(3,2)*v.z+(*pM)(3,3)*v.w;
return pOut;
#else
//VM
D3DXVECTOR4 v(pV->x,pV->y,pV->z,1);
pOut->x=(*pM)(0,0)*v.x+(*pM)(1,0)*v.y+(*pM)(2,0)*v.z+(*pM)(3,0)*v.w;
pOut->y=(*pM)(0,1)*v.x+(*pM)(1,1)*v.y+(*pM)(2,1)*v.z+(*pM)(3,1)*v.w;
pOut->z=(*pM)(0,2)*v.x+(*pM)(1,2)*v.y+(*pM)(2,2)*v.z+(*pM)(3,2)*v.w;
pOut->w=(*pM)(0,3)*v.x+(*pM)(1,3)*v.y+(*pM)(2,3)*v.z+(*pM)(3,3)*v.w;
return pOut;
#endif
return NULL;
}
};
----实矩阵乘法----
-3,1,-1,
-7,5,-1,
-6,6,-2,
-3,1,-1,
-7,5,-1,
-6,6,-2,
8,-4,4,
-8,12,4,
-12,12,4,
----实矩阵求逆----
-0.25,-0.25,0.25,
-0.5,3.47694e-008,0.25,
-0.75,0.75,-0.5,
-3,1,-1,
-7,5,-1,
-6,6,-2,
----实矩阵求行列式的值----
16
16
// 矩阵标准API(实矩阵相乘,Bsdet求实方阵的行列式值,求实方阵的逆)的C++封装,一个可复用的C++ 3阶方阵类
//
#include"stdafx.h"
#include<cmath>
#include<iostream>
using namespace std;
template<class T>
void __stdcall Brmul(T *a,T *b,int m,int n,int k,T *c)
{
int i,j,l,u;
for (i=0; i<=m-1; i++)
for (j=0; j<=k-1; j++)
{
u=i*k+j;
c[u]=0.0;
for(l=0; l<=n-1; l++)
c[u]=c[u]+a[i*n+l]*b[l*k+j];
}
return;
}
template<class T>
//第一个参数是输入输出参数
T __stdcall Bsdet(T *a,int n)
{
int i,j,k,is,js,l,u,v;
T f,det,q,d;
f=1.0; det=1.0;
for (k=0; k<=n-2; k++)
{
q=0.0;
for (i=k; i<=n-1; i++)
for (j=k; j<=n-1; j++)
{
l=i*n+j;
d=fabs(a[l]);
if (d>q)
{
q=d;
is=i;
js=j;
}
}
if(q+1.0==1.0)
{
det=0.0;
return(det);
}
if(is!=k)
{
f=-f;
for (j=k; j<=n-1; j++)
{
u=k*n+j;
v=is*n+j;
d=a[u];
a[u]=a[v];
a[v]=d;
}
}
if(js!=k)
{
f=-f;
for (i=k; i<=n-1; i++)
{
u=i*n+js;
v=i*n+k;
d=a[u];
a[u]=a[v];
a[v]=d;
}
}
l=k*n+k;
det=det*a[l];
for (i=k+1; i<=n-1; i++)
{
d=a[i*n+k]/a[l];
for (j=k+1; j<=n-1; j++)
{
u=i*n+j;
a[u]=a[u]-d*a[k*n+j];
}
}
}
det=f*det*a[n*n-1];
return(det);
}
template<class T>
int __stdcall Brinv(T *a,int n)
{
int *is,*js,i,j,k,l,u,v;
T d,p;
is=(int*)malloc(n*sizeof(int));
js=(int*)malloc(n*sizeof(int));
for (k=0; k<=n-1; k++)
{
d=0.0;
for (i=k; i<=n-1; i++)
for (j=k; j<=n-1; j++)
{
l=i*n+j;
p=fabs(a[l]);
if (p>d)
{
d=p;
is[k]=i;
js[k]=j;
}
}
if (d+1.0==1.0)
{
free(is);
free(js);
printf("err**not inv\n");
return(0);
}
if (is[k]!=k)
for (j=0; j<=n-1; j++)
{
u=k*n+j;
v=is[k]*n+j;
p=a[u];
a[u]=a[v];
a[v]=p;
}
if (js[k]!=k)
for (i=0; i<=n-1; i++)
{
u=i*n+k;
v=i*n+js[k];
p=a[u];
a[u]=a[v];
a[v]=p;
}
l=k*n+k;
a[l]=1.0/a[l];
for (j=0; j<=n-1; j++)
if (j!=k)
{
u=k*n+j;
a[u]=a[u]*a[l];
}
for (i=0; i<=n-1; i++)
if (i!=k)
for (j=0; j<=n-1; j++)
if (j!=k)
{
u=i*n+j;
a[u]=a[u]-a[i*n+k]*a[k*n+j];
}
for (i=0; i<=n-1; i++)
if (i!=k)
{
u=i*n+k;
a[u]=-a[u]*a[l];
}
}
for(k=n-1; k>=0; k--)
{
if (js[k]!=k)
for (j=0; j<=n-1; j++)
{
u=k*n+j;
v=js[k]*n+j;
p=a[u];
a[u]=a[v];
a[v]=p;
}
if (is[k]!=k)
for (i=0; i<=n-1; i++)
{
u=i*n+k;
v=i*n+is[k];
p=a[u];
a[u]=a[v];
a[v]=p;
}
}
free(is);
free(js);
return(1);
}
// From gamasutra. This file may follow different licence features.
// A floating point number
//
typedef float SCALAR;
//
// A 3D vector
//
class VECTOR
{
public:
SCALAR x,y,z; //x,y,z coordinates
public:
VECTOR() : x(0), y(0), z(0) {}
VECTOR( const SCALAR& a, const SCALAR& b, const SCALAR& c ) : x(a), y(b), z(c) {}
//index a component
//NOTE: returning a reference allows
//you to assign the indexed element
SCALAR& operator [] ( const long i )
{
return *((&x) + i);
}
//compare
const bool operator == ( const VECTOR& v ) const
{
return (v.x==x && v.y==y && v.z==z);
}
const bool operator != ( const VECTOR& v ) const
{
return !(v == *this);
}
//negate
const VECTOR operator - () const
{
return VECTOR( -x, -y, -z );
}
//assign
const VECTOR& operator = ( const VECTOR& v )
{
x = v.x;
y = v.y;
z = v.z;
return *this;
}
//increment
const VECTOR& operator += ( const VECTOR& v )
{
x+=v.x;
y+=v.y;
z+=v.z;
return *this;
}
//decrement
const VECTOR& operator -= ( const VECTOR& v )
{
x-=v.x;
y-=v.y;
z-=v.z;
return *this;
}
//self-multiply
const VECTOR& operator *= ( const SCALAR& s )
{
x*=s;
y*=s;
z*=s;
return *this;
}
//self-divide
const VECTOR& operator /= ( const SCALAR& s )
{
const SCALAR r = 1 / s;
x *= r;
y *= r;
z *= r;
return *this;
}
//add
const VECTOR operator + ( const VECTOR& v ) const
{
return VECTOR(x + v.x, y + v.y, z + v.z);
}
//subtract
const VECTOR operator - ( const VECTOR& v ) const
{
return VECTOR(x - v.x, y - v.y, z - v.z);
}
//post-multiply by a scalar
const VECTOR operator * ( const SCALAR& s ) const
{
return VECTOR( x*s, y*s, z*s );
}
//pre-multiply by a scalar
friend inline const VECTOR operator * ( const SCALAR& s, const VECTOR& v )
{
return v * s;
}
//divide
const VECTOR operator / (SCALAR s) const
{
s = 1/s;
return VECTOR( s*x, s*y, s*z );
}
//cross product
const VECTOR cross( const VECTOR& v ) const
{
//Davis, Snider, "Introduction to Vector Analysis", p. 44
return VECTOR( y*v.z - z*v.y, z*v.x - x*v.z, x*v.y - y*v.x );
}
//scalar dot product
const SCALAR dot( const VECTOR& v ) const
{
return x*v.x + y*v.y + z*v.z;
}
//length
const SCALAR length() const
{
return (SCALAR)sqrt( (double)this->dot(*this) );
}
//unit vector
const VECTOR unit() const
{
return (*this) / length();
}
//make this a unit vector
void normalize()
{
(*this) /= length();
}
//equal within an error 慹?
const bool nearlyEquals( const VECTOR& v, const SCALAR e ) const
{
return fabs(x-v.x)<e && fabs(y-v.y)<e && fabs(z-v.z)<e;
}
};
//
// A 3D position
//
//typedef VECTOR POINT;
// From gamasutra. This file may follow different licence features.
// A 3x3 matrix
//
class MATRIX
{
public:
VECTOR C[3]; //column vectors,应该是行向量或列向量,对象占用4*9=36字节的内存空间,内存顺序与真数组的内存顺序是一致的
public:
MATRIX()
{
//identity matrix
C[0].x = 1;
C[1].y = 1;
C[2].z = 1;
}
MATRIX( const VECTOR& c0, const VECTOR& c1, const VECTOR& c2 )
{
C[0] = c0;
C[1] = c1;
C[2] = c2;
}
//index a column, allow assignment
//NOTE: using this index operator along with the vector index
//gives you M[column][row], not the standard M[row][column]
VECTOR& operator [] ( long i )
{
return C[i];
}
//compare
const bool operator == ( const MATRIX& m ) const
{
return C[0]==m.C[0] && C[1]==m.C[1] && C[2]==m.C[2];
}
const bool operator != ( const MATRIX& m ) const
{
return !(m == *this);
}
//assign
const MATRIX& operator = ( const MATRIX& m )
{
C[0] = m.C[0];
C[1] = m.C[1];
C[2] = m.C[2];
return *this;
}
//increment
const MATRIX& operator +=( const MATRIX& m )
{
C[0] += m.C[0];
C[1] += m.C[1];
C[2] += m.C[2];
return *this;
}
//decrement
const MATRIX& operator -=( const MATRIX& m )
{
C[0] -= m.C[0];
C[1] -= m.C[1];
C[2] -= m.C[2];
return *this;
}
//self-multiply by a scalar
const MATRIX& operator *= ( const SCALAR& s )
{
C[0] *= s;
C[1] *= s;
C[2] *= s;
return *this;
}
//self-multiply by a matrix
const MATRIX& operator *= ( const MATRIX& m )
{
//NOTE: don抰 change the columns
//in the middle of the operation
MATRIX temp = (*this);
C[0] = temp * m.C[0];
C[1] = temp * m.C[1];
C[2] = temp * m.C[2];
return *this;
}
//add
const MATRIX operator + ( const MATRIX& m ) const
{
return MATRIX( C[0] + m.C[0], C[1] + m.C[1], C[2] + m.C[2] );
}
//subtract
const MATRIX operator - ( const MATRIX& m ) const
{
return MATRIX( C[0] - m.C[0], C[1] - m.C[1], C[2] - m.C[2] );
}
//post-multiply by a scalar
const MATRIX operator * ( const SCALAR& s ) const
{
return MATRIX( C[0]*s, C[1]*s, C[2]*s );
}
//pre-multiply by a scalar
friend inline const MATRIX operator * ( const SCALAR& s, const MATRIX& m )
{
return m * s;
}
//post-multiply by a vector
const VECTOR operator * ( const VECTOR& v ) const
{
return( C[0]*v.x + C[1]*v.y + C[2]*v.z );
}
//pre-multiply by a vector
inline friend const VECTOR operator * ( const VECTOR& v, const MATRIX& m )
{
return VECTOR( m.C[0].dot(v), m.C[1].dot(v), m.C[2].dot(v) );
}
//post-multiply by a matrix
const MATRIX operator * ( const MATRIX& m ) const
{
return MATRIX( (*this) * m.C[0], (*this) * m.C[1], (*this) * m.C[2] );
}
//transpose
MATRIX transpose() const
{
//turn columns on their side
return MATRIX( VECTOR( C[0].x, C[1].x, C[2].x ), //column 0
VECTOR( C[0].y, C[1].y, C[2].y ), //column 1
VECTOR( C[0].z, C[1].z, C[2].z ) //column 2
);
}
//scalar determinant
const SCALAR determinant() const
{
//Lang, "Linear Algebra", p. 143
return C[0].dot( C[1].cross(C[2]) );
}
//add by Ivan_han
const SCALAR det() const
{
MATRIX mtx=*this;
SCALAR ret=Bsdet(&mtx[0][0],3);//第一个参数是输入输出参数
return ret;
}
//matrix inverse,去掉返回值类型中的const
MATRIX inverse() const
{
MATRIX mtx=*this;
int i=Brinv((SCALAR *)&mtx[0][0],3);
if(i!=0)
return mtx;
return MATRIX();
}
//add by Ivan_han
friend ostream& operator<< (ostream& os,MATRIX& mtx);
};
//add by Ivan_han
ostream& operator<< (ostream& os,MATRIX& mtx)
{
for(int i=0;i<=2;i++)
{
for(int j=0;j<=2;j++)
os<<mtx[i][j]<<",";
os<<endl;
}
return os;
}
int main(void)
{
int i,j;
static float A[3][3]=
{
{-3,1,-1},
{-7,5,-1},
{-6,6,-2},
};
static float C[3][3],B[3][3]=
{
{-3,1,-1},
{-7,5,-1},
{-6,6,-2},
};
cout<<"----实矩阵乘法----"<<endl;
Brmul(&A[0][0],&B[0][0],3,3,3,&C[0][0]);
MATRIX mtxA,mtxB,mtxC;
memcpy(&mtxA,A,sizeof(A));
memcpy(&mtxB,B,sizeof(B));
memcpy(&mtxC,C,sizeof(C));
cout<<mtxA<<endl;
cout<<mtxB<<endl;
cout<<mtxC<<endl;
MATRIX mtxD=mtxA.inverse();
cout<<"----实矩阵求逆----"<<endl;
cout<<mtxD<<endl;
cout<<mtxD.inverse()<<endl;
cout<<"----实矩阵求行列式的值----"<<endl;
cout<<mtxA.determinant()<<endl;
cout<<mtxA.det()<<endl;
system("pause");
return 0;
}
----实矩阵乘法----
1,2,3,4,
5,6,7,8,
9,10,11,12,
13,14,15,16,
1,1,3,4,
1,2,3,2,
2,4,1,3,
5,7,1,4,
29,45,16,33,
65,101,48,85,
101,157,80,137,
137,213,112,189,
err**not inv
----实矩阵求逆----
1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1,
1,0,0,-0,
-0,1,0,-0,
0,-0,1,-0,
0,0,-0,1,
----实矩阵求行列式的值----
-0
// 矩阵标准API(实矩阵相乘,Bsdet求实方阵的行列式值,求实方阵的逆)的C++封装,一个可复用的C++ 4阶方阵类
//
#include"stdafx.h"
#include<cmath>
#include<iostream>
using namespace std;
template<class T>
void __stdcall Brmul(T *a,T *b,int m,int n,int k,T *c)
{
int i,j,l,u;
for (i=0; i<=m-1; i++)
for (j=0; j<=k-1; j++)
{
u=i*k+j;
c[u]=0.0;
for(l=0; l<=n-1; l++)
c[u]=c[u]+a[i*n+l]*b[l*k+j];
}
return;
}
template<class T>
//第一个参数是输入输出参数
T __stdcall Bsdet(T *a,int n)
{
int i,j,k,is,js,l,u,v;
T f,det,q,d;
f=1.0; det=1.0;
for (k=0; k<=n-2; k++)
{
q=0.0;
for (i=k; i<=n-1; i++)
for (j=k; j<=n-1; j++)
{
l=i*n+j;
d=fabs(a[l]);
if (d>q)
{
q=d;
is=i;
js=j;
}
}
if(q+1.0==1.0)
{
det=0.0;
return(det);
}
if(is!=k)
{
f=-f;
for (j=k; j<=n-1; j++)
{
u=k*n+j;
v=is*n+j;
d=a[u];
a[u]=a[v];
a[v]=d;
}
}
if(js!=k)
{
f=-f;
for (i=k; i<=n-1; i++)
{
u=i*n+js;
v=i*n+k;
d=a[u];
a[u]=a[v];
a[v]=d;
}
}
l=k*n+k;
det=det*a[l];
for (i=k+1; i<=n-1; i++)
{
d=a[i*n+k]/a[l];
for (j=k+1; j<=n-1; j++)
{
u=i*n+j;
a[u]=a[u]-d*a[k*n+j];
}
}
}
det=f*det*a[n*n-1];
return(det);
}
template<class T>
int __stdcall Brinv(T *a,int n)
{
int *is,*js,i,j,k,l,u,v;
T d,p;
is=(int*)malloc(n*sizeof(int));
js=(int*)malloc(n*sizeof(int));
for (k=0; k<=n-1; k++)
{
d=0.0;
for (i=k; i<=n-1; i++)
for (j=k; j<=n-1; j++)
{
l=i*n+j;
p=fabs(a[l]);
if (p>d)
{
d=p;
is[k]=i;
js[k]=j;
}
}
if (d+1.0==1.0)
{
free(is);
free(js);
printf("err**not inv\n");
return(0);
}
if (is[k]!=k)
for (j=0; j<=n-1; j++)
{
u=k*n+j;
v=is[k]*n+j;
p=a[u];
a[u]=a[v];
a[v]=p;
}
if (js[k]!=k)
for (i=0; i<=n-1; i++)
{
u=i*n+k;
v=i*n+js[k];
p=a[u];
a[u]=a[v];
a[v]=p;
}
l=k*n+k;
a[l]=1.0/a[l];
for (j=0; j<=n-1; j++)
if (j!=k)
{
u=k*n+j;
a[u]=a[u]*a[l];
}
for (i=0; i<=n-1; i++)
if (i!=k)
for (j=0; j<=n-1; j++)
if (j!=k)
{
u=i*n+j;
a[u]=a[u]-a[i*n+k]*a[k*n+j];
}
for (i=0; i<=n-1; i++)
if (i!=k)
{
u=i*n+k;
a[u]=-a[u]*a[l];
}
}
for(k=n-1; k>=0; k--)
{
if (js[k]!=k)
for (j=0; j<=n-1; j++)
{
u=k*n+j;
v=js[k]*n+j;
p=a[u];
a[u]=a[v];
a[v]=p;
}
if (is[k]!=k)
for (i=0; i<=n-1; i++)
{
u=i*n+k;
v=i*n+is[k];
p=a[u];
a[u]=a[v];
a[v]=p;
}
}
free(is);
free(js);
return(1);
}
// From gamasutra. This file may follow different licence features.
// A floating point number
//
typedef float SCALAR;
//
// A 4D vector
//
class VECTOR4
{
public:
SCALAR x,y,z,w; //x,y,z,w coordinates
public:
VECTOR4() : x(0), y(0), z(0),w(0) {}
VECTOR4( const SCALAR& a, const SCALAR& b, const SCALAR& c , const SCALAR& d) : x(a), y(b), z(c), w(d) {}
//index a component
//NOTE: returning a reference allows
//you to assign the indexed element
SCALAR& operator [] ( const long i )
{
return *((&x) + i);
}
//compare
const bool operator == ( const VECTOR4& v ) const
{
return (v.x==x && v.y==y && v.z==z && v.w==w);
}
const bool operator != ( const VECTOR4& v ) const
{
return !(v == *this);
}
//negate
const VECTOR4 operator - () const
{
return VECTOR4( -x, -y, -z ,-w);
}
//assign
const VECTOR4& operator = ( const VECTOR4& v )
{
x = v.x;
y = v.y;
z = v.z;
w = v.w;
return *this;
}
//increment
const VECTOR4& operator += ( const VECTOR4& v )
{
x+=v.x;
y+=v.y;
z+=v.z;
w+=v.w;
return *this;
}
//decrement
const VECTOR4& operator -= ( const VECTOR4& v )
{
x-=v.x;
y-=v.y;
z-=v.z;
w-=v.w;
return *this;
}
//self-multiply
const VECTOR4& operator *= ( const SCALAR& s )
{
x*=s;
y*=s;
z*=s;
w*=s;
return *this;
}
//self-divide
const VECTOR4& operator /= ( const SCALAR& s )
{
const SCALAR r = 1 / s;
x *= r;
y *= r;
z *= r;
w *= r;
return *this;
}
//add
const VECTOR4 operator + ( const VECTOR4& v ) const
{
return VECTOR4(x + v.x, y + v.y, z + v.z,w+v.w);
}
//subtract
const VECTOR4 operator - ( const VECTOR4& v ) const
{
return VECTOR4(x - v.x, y - v.y, z - v.z,w-v.w);
}
//post-multiply by a scalar
const VECTOR4 operator * ( const SCALAR& s ) const
{
return VECTOR4( x*s, y*s, z*s ,w*s);
}
//pre-multiply by a scalar
friend inline const VECTOR4 operator * ( const SCALAR& s, const VECTOR4& v )
{
return v * s;
}
//divide
const VECTOR4 operator / (SCALAR s) const
{
s = 1/s;
return VECTOR4( s*x, s*y, s*z ,s*w);
}
////cross product,没有4维叉积
//
// const VECTOR cross( const VECTOR& v ) const
// {
// //Davis, Snider, "Introduction to Vector Analysis", p. 44
// return VECTOR( y*v.z - z*v.y, z*v.x - x*v.z, x*v.y - y*v.x );
// }
//scalar dot product
const SCALAR dot( const VECTOR4& v ) const
{
return x*v.x + y*v.y + z*v.z+w*v.w;
}
//length
const SCALAR length() const
{
return (SCALAR)sqrt( (double)this->dot(*this) );
}
//unit vector
const VECTOR4 unit() const
{
return (*this) / length();
}
//make this a unit vector
void normalize()
{
(*this) /= length();
}
//equal within an error 慹?
const bool nearlyEquals( const VECTOR4& v, const SCALAR e ) const
{
return fabs(x-v.x)<e && fabs(y-v.y)<e && fabs(z-v.z)<e && fabs(w-v.w)<e;
}
};
//
// A 4D position
//
//typedef VECTOR4 POINT;
// From gamasutra. This file may follow different licence features.
// A 4x4 matrix
//
class MATRIX4
{
public:
VECTOR4 C[4]; //column vectors,应该是行向量或列向量,对象占用4*16=64字节的内存空间,内存顺序与真数组的内存顺序是一致的
public:
MATRIX4()
{
//identity matrix
C[0].x = 1;
C[1].y = 1;
C[2].z = 1;
C[3].w = 1;
}
MATRIX4( const VECTOR4& c0, const VECTOR4& c1, const VECTOR4& c2, const VECTOR4& c3 )
{
C[0] = c0;
C[1] = c1;
C[2] = c2;
C[3] = c3;
}
//index a column, allow assignment
//NOTE: using this index operator along with the vector index
//gives you M[column][row], not the standard M[row][column]
VECTOR4& operator [] ( long i )
{
return C[i];
}
//compare
const bool operator == ( const MATRIX4& m ) const
{
return C[0]==m.C[0] && C[1]==m.C[1] && C[2]==m.C[2] && C[3]==m.C[3];
}
const bool operator != ( const MATRIX4& m ) const
{
return !(m == *this);
}
//assign
const MATRIX4& operator = ( const MATRIX4& m )
{
C[0] = m.C[0];
C[1] = m.C[1];
C[2] = m.C[2];
C[3] = m.C[3];
return *this;
}
//increment
const MATRIX4& operator +=( const MATRIX4& m )
{
C[0] += m.C[0];
C[1] += m.C[1];
C[2] += m.C[2];
C[3] += m.C[3];
return *this;
}
//decrement
const MATRIX4& operator -=( const MATRIX4& m )
{
C[0] -= m.C[0];
C[1] -= m.C[1];
C[2] -= m.C[2];
C[3] -= m.C[3];
return *this;
}
//self-multiply by a scalar
const MATRIX4& operator *= ( const SCALAR& s )
{
C[0] *= s;
C[1] *= s;
C[2] *= s;
C[3] *= s;
return *this;
}
//self-multiply by a matrix
const MATRIX4& operator *= ( const MATRIX4& m )
{
//NOTE: don抰 change the columns
//in the middle of the operation
MATRIX4 temp = (*this);
C[0] = temp * m.C[0];
C[1] = temp * m.C[1];
C[2] = temp * m.C[2];
C[3] = temp * m.C[3];
return *this;
}
//add
const MATRIX4 operator + ( const MATRIX4& m ) const
{
return MATRIX4( C[0] + m.C[0], C[1] + m.C[1], C[2] + m.C[2], C[3] + m.C[3] );
}
//subtract
const MATRIX4 operator - ( const MATRIX4& m ) const
{
return MATRIX4( C[0] - m.C[0], C[1] - m.C[1], C[2] - m.C[2], C[3] - m.C[3]);
}
//post-multiply by a scalar
const MATRIX4 operator * ( const SCALAR& s ) const
{
return MATRIX4( C[0]*s, C[1]*s, C[2]*s, C[3]*s );
}
//pre-multiply by a scalar
friend inline const MATRIX4 operator * ( const SCALAR& s, const MATRIX4& m )
{
return m * s;
}
//post-multiply by a vector
const VECTOR4 operator * ( const VECTOR4& v ) const
{
return( C[0]*v.x + C[1]*v.y + C[2]*v.z+ C[3]*v.w );
}
//pre-multiply by a vector
inline friend const VECTOR4 operator * ( const VECTOR4& v, const MATRIX4& m )
{
return VECTOR4( m.C[0].dot(v), m.C[1].dot(v), m.C[2].dot(v), m.C[3].dot(v) );
}
//post-multiply by a matrix
const MATRIX4 operator * ( const MATRIX4& m ) const
{
return MATRIX4( (*this) * m.C[0], (*this) * m.C[1], (*this) * m.C[2], (*this) * m.C[3] );
}
//transpose
MATRIX4 transpose() const
{
//turn columns on their side
return MATRIX4( VECTOR4( C[0].x, C[1].x, C[2].x , C[3].x ), //column 0
VECTOR4( C[0].y, C[1].y, C[2].y, C[3].y ), //column 1
VECTOR4( C[0].z, C[1].z, C[2].z ,C[3].z), //column 2
VECTOR4( C[0].w, C[1].w, C[2].w, C[3].w ) //column 3
);
}
////scalar determinant,没有4维叉积
//const SCALAR determinant() const
//{
// //Lang, "Linear Algebra", p. 143
// return C[0].dot( C[1].cross(C[2]) );
//}
//add by Ivan_han
const SCALAR det() const
{
MATRIX4 mtx=*this;
SCALAR ret=Bsdet(&mtx[0][0],4);//第一个参数是输入输出参数
return ret;
}
//matrix inverse,去掉返回值类型中的const
MATRIX4 inverse() const
{
MATRIX4 mtx=*this;
int i=Brinv((SCALAR *)&mtx[0][0],4);
if(i!=0)
return mtx;
return MATRIX4();
}
//add by Ivan_han
friend ostream& operator<< (ostream& os,MATRIX4& mtx);
};
//add by Ivan_han
ostream& operator<< (ostream& os,MATRIX4& mtx)
{
for(int i=0;i<=3;i++)
{
for(int j=0;j<=3;j++)
os<<mtx[i][j]<<",";
os<<endl;
}
return os;
}
int main(void)
{
int i,j;
static float A[4][4]=
{
{1,2,3,4},
{5,6,7,8},
{9,10,11,12},
{13,14,15,16}
};
static float C[4][4],B[4][4]=
{
{1,1,3,4},
{1,2,3,2},
{2,4,1,3},
{5,7,1,4}
};
cout<<"----实矩阵乘法----"<<endl;
Brmul(&A[0][0],&B[0][0],4,4,4,&C[0][0]);
MATRIX4 mtxA,mtxB,mtxC;
memcpy(&mtxA,A,sizeof(A));
memcpy(&mtxB,B,sizeof(B));
memcpy(&mtxC,C,sizeof(C));
cout<<mtxA<<endl;
cout<<mtxB<<endl;
cout<<mtxC<<endl;
MATRIX4 mtxD=mtxA.inverse();
cout<<"----实矩阵求逆----"<<endl;
cout<<mtxD<<endl;
cout<<mtxD.inverse()<<endl;
cout<<"----实矩阵求行列式的值----"<<endl;
cout<<mtxA.det()<<endl;
system("pause");
return 0;
}
四元数(quaternion)模板类的使用
DX中的四元数D3DXQUATERNION和4维向量VECTOR4是兼容的,DX中四元数结构体的四个成员是:
FLOAT x,y,z,w;//w表示数量部分
D3DXQuaternionDot()函数将返回两个四元组的点积
D3DXQuaternionMultiply()函数则将两个四元组相乘。例如:
D3DXQUATERNION Qi(1,0,0,0),Qj(0,1,0,0),Qk(0,0,1,0),Q1(0,0,0,1),Q;
FLOAT fret=D3DXQuaternionDot(&Qi,&Qj);//0
FLOAT fret1=D3DXQuaternionDot(&Qi,&Qi);//1
D3DXQUATERNION* retQ=D3DXQuaternionMultiply(&Q,&Qj,&Qk);//Qk*Qj=-Q_i
D3DXQuaternionNormalize()计算一个单位长度的四元数
D3DXQuaternionLength()计算得到四元组的长度
D3DXQuaternionInverse()共轭变换并规格化四元数(其实就是求逆四元数)
D3DXQuaternionConjugate()求共轭四元数:数量部分w不变,向量部分x,y,z取相反数
例如:
D3DXQUATERNION q8(-1,2,3,2),Q8;
D3DXQUATERNION* retQ8=D3DXQuaternionNormalize(&Q8,&q8);
fret=D3DXQuaternionLength(&q8);//sqrt(18)
fret=D3DXQuaternionLength(&Q8);//1
retQ8=D3DXQuaternionInverse(&Q8,&q8);
retQ=D3DXQuaternionMultiply(&Q,&Q8,&q8);//q8*Q8=[2,(-1,2,3)][1/9,(1/18,-1/9,-1/6)]=[1,(0,0,0)]
retQ=D3DXQuaternionMultiply(&Q,&q8,&Q8);//Q8*q8=[1/9,(1/18,-1/9,-1/6)][2,(-1,2,3)]=[1,(0,0,0)]
retQ8=D3DXQuaternionConjugate(&Q8,&q8);
问题:对于四元数q,q^-1=~q的充要条件是?
四元数模板类的四个成员是:
private:
// [w, (x, y, z)],w表示数量部分
_Tp w, x, y, z;
cout<<Quaternion<float>(0,1,0,0)*Quaternion<float>(0,0,1,0)<<endl;//[0, (0, 0, 1)],ij=k
cout<<Quaternion<float>(0,0,1,0)*Quaternion<float>(0,0,0,1)<<endl;//[0, (1, 0, 0)],jk=i
cout<<Quaternion<float>(0,0,0,1)*Quaternion<float>(0,1,0,0)<<endl;//[0, (0, 1, 0)],ki=j
cout<<Quaternion<float>(0,0,1,0)*Quaternion<float>(0,1,0,0)<<endl;//[0, (0, 0, -1)],ji=-k
cout<<Quaternion<float>(0,0,0,1)*Quaternion<float>(0,0,1,0)<<endl;//[0, (-1, 0, 0)],kj=-i
cout<<Quaternion<float>(0,1,0,0)*Quaternion<float>(0,0,0,1)<<endl;//[0, (0, -1, 0)],ik=-j
cout<<Quaternion<float>(0,1,0,0)*Quaternion<float>(0,1,0,0)<<endl;//[-1, (0, 0, 0)],i^2=-1
cout<<Quaternion<float>(0,0,1,0)*Quaternion<float>(0,0,1,0)<<endl;//[-1, (0, 0, 0)],j^2=-1
cout<<Quaternion<float>(0,0,0,1)*Quaternion<float>(0,0,0,1)<<endl;//[-1, (0, 0, 0)],k^2=-1
cout<<Quaternion<float>(0,1,0,0)*Quaternion<float>(0,0,1,0)*Quaternion<float>(0,0,0,1)<<endl;//[-1, (0, 0, 0)],ijk=-1
四元数q_1,q_2的乘法:q_1q_2=Re(q_1)Re(q_2)-Im(q_1)·Im(q_2)+Re(q_1)Im(q_2)+Re(q_2)Im(q_1)+Im(q_1)×Im(q_2)
对任意两个四元数q_1,q_2,恒有Re(q_1q_2)=Re(q_2q_1)
对任意两个虚数四元数q_1,q_2(即数量部分为0:Re(q_1)=Re(q_2)=0),恒有q_1q_2+q_2q_1=-2Im(q_1)·Im(q_2)=2Re(q_1q_2)且q_1q_2-q_2q_1=2Im(q_1)×Im(q_2)=2Im(q_1q_2)
定义:四元数~q_1=Re(q_1)-Im(q_1)为四元数q_1=Re(q_1)+Im(q_1)的共轭,则有
Re(q_1)=Re(~q_1),Im(~q_1)=-Im(q_1)
~(~q_1)=q_1
~(q_1+q_2)=~q_1+~q_2,~(q_1q_2)=(~q_2)(~q_1)
~q_1+q_1=2Re(q_1)
当Re(q_1)=0时,~q_1=-q_1
用四元数概念描述3维空间里的旋转运动非常方便。有如下定理:
定理:设有四元数q_1及q_2,则
‖q_1q_2q_1^(-1)‖=‖q_2‖且Re(q_1q_2q_1^(-1))=Re(q_2)
设C^2是全体复数对(z_1,z_2)组成的二元复数集,定义C^2上的加法和乘法运算:
(z_1,z_2)+(z_1',z_2')=(z_1+z_1',z_2+z_2'),(z_1,z_2)(z_1',z_2')=(z_1z_1'-z_2z_2*,z_1z_2'+z_2z_1'*)
证明这样定义的环C^2与四元数除环同构。
1843年,爱尔兰人(19世纪的爱尔兰是英国的一部分)W.R.Hamilton在爱尔兰皇家科学院宣布了四元数的发现,这是历史上发现的第一种乘法交换律不成立的代数——四元数代数。两个三/七维空间中向量的叉积可以用对应的两个四元数的乘积(实部去掉)表示,三维空间中向量的叉积(向量积,三/七维空间特有,不满足交换性、不满足结合性)是一个向量而不是数。具有向量加法和叉积的R^3构成了一个Lie代数(非交换非结合)。
非交换的结合环在19世纪已经发现,那就是四元数(1843)与矩阵(1858),而19世纪末又发现了非结合环——Lie环(1870)。
1844年,Grassmann推演出更有一般性的几类代数。外代数是非交换(反交换、反对称性)、不可除、但结合的代数,外积/楔积a∧b适用于任何R^n,乘法结果是一个“扩张的量”。外代数一定是非交换结合代数;Lie代数不一定是非交换(反交换律)非结合代数。
1853年,(英)哈密顿(W.R.Hamilton,)的《四元数讲义》出版,系统地论述了四元数理论。
1857年,Cayley设计出另一种不可交换的代数——矩阵代数。
他们的研究打开代数的大门。
1870年,Kronecker给出了有限Abel群的抽象定义;
Dedekind开始使用“体”的说法,并研究了代数体;
1871年,哈密顿的学生(英)苏格兰理论物理学家、数学家麦克斯韦 (James Clerk Maxwell ,1831.6.13-1879)分开处理四元数的数量部分和向量部分,创立了向量分析(1871)。
1873年,麦克斯韦的《电磁学》出版,建立了磁场基本方程(麦克斯韦方程)。
1893年,韦伯(H.Weber)定义了抽象的体;
1910年,施坦尼茨展开了体的一般抽象理论;
Dedekind和Kronecker创立了环论;
1910年,施坦尼茨总结了包括群、代数、域等在内的代数体系的研究,开创了代数学。
1920年,埃米·诺特已引入“左模”、“右模”的概念。
1921年,埃米·诺特的《整环的理想理论》是交换代数发展的里程碑。建立了交换Noether环理论,证明了准素分解定理。后又引进交叉积的概念并用决定有限维Galois扩张的布饶尔群。
1927-1935年,Noether研究非交换代数与非交换算术。
1930年,毕尔霍夫建立格论,它源于1847年的bool代数;
二战后,出现了各种代数系统的理论和Bourbaki学派;
1955年,H.Cartan等建立了同调代数理论。
定理(Frobeuius,1878) :实数域R上的可除代数只能是实数域、复数域或四元数除环。
1878年,Frobenius证明基础域R的可除代数(是环,域或者广域上的代数)只有R、C(可交换的结合代数)及四元数体H(无限非交换除环,非交换的结合R-代数)三类,或者表述为:实数域上的所有有限维结合可除代数只有三个。如果去掉结合性要求,则实数域上还有一个可除代数Cayley-Dickson代数,即八卦代数O(非交换、非结合的R-代数)。小皮尔斯也独立得到证明(1881)。
实数域上有限维可除代数,连非结合可除代数也算在内,只有1,2,4,8这四种已知维数(1958)。实数域上有限维的交换可除代数只有实数及复数(1861-1884年K.Weierstrass,1870-1888年Dedekind)。
前苏联数学家盖尔范德的理论:
Banach代数一定是结合的,不一定是交换的,不一定有单位元。从这个意义上说,有单位元的Banach代数只有三种;有单位元的二维欧氏空间(包括实的R^2和复的C^2,后者一般称为酉空间)上的Banach代数本质上只有一种:(a,b)×(c,d)=(ac-bd,ad+bc)。高于四维的Banach代数(属结合代数)必定含有八元数(非结合非交换)
Hamilton的四元数理论与代数基本定理、代数数论的联系:
数强抽象为代数数:~就是满足代数方程(即有理系数多项式方程)的复数(又根据伽罗瓦理论,代数数不一定能用根式表示出来)。
例如,按定义,某些实数、某些复数是代数数,超越数和四元数i,j,k就不是代数数。
四元数除环H的定义:含有复数域C和i,j,k的除环。
x^2+1=0在H中有无穷多个根,四元数i,j,k显然是其根,但不是代数数。
整数[普通整数/有理整数:即正负自然数和零]弱抽象为代数整数[还是不简称为好]:如果一个代数数满足的多项式方程是首一的(即最高次项系数为1),系数是整数,则称为~。
与有限群论的联系:
在非阿贝尔群中,阶数为8的四元数群的所有子群是正规子群。
阶数为60的二十面体群不具有真正规子群。
威廉·罗文·哈密尔顿希望这种广义复数能用来表示三维空间的旋转,象复数能用来表示平面的旋转一样。
四元数就是1,i,j,k这四个单位的线性组合。这些新复数的确可以表示三维空间中的旋转(也可以表示四维空间中的旋转)。
因为三维空间中的旋转是非交换的。因此四元数单位是非交换的这个结果并不出人意外。
四元数群Q的8个元素是:1=I,-1=a^2,i=a,-i=a^3,j=b,-j=b^3,k=ab,-k=ba
抽象的哈密尔顿群的定义:任何非阿贝尔群如其所有子群都是正规子群就称为哈密尔顿群。
四元数群是阶数最小(8阶)的哈密尔顿群。
Quaternion class test
Constructors:
q1=[0, (0, 0, 0)]
q2=[1, (2, 3, 4)]
q3=[1, (2, 3, 4)]
q4=[5, (6, 7, 8)]
Operators:
Operator =
q5 = [1, (2, 3, 4)]
Operator +
q5 + q4 = [6, (8, 10, 12)]
Operator -
q5 - q4 = [-4, (-4, -4, -4)]
Operator *
q7 * q8 = [8, (-9, -2, 11)]
Operator /
q7/(q8.inverse) = [8, (-9, -2, 11)]
Operator +=
q4 += q5 is [6, (8, 10, 12)]
Operator -=
q5 -= q5 is [0, (0, 0, 0)]
Operator *=
q7 *= q8 is [8, (-9, -2, 11)]
Operator /=
q7 /= q8.inverse() is [8, (-9, -2, 11)]
Operator !=
works!
Operator ==
works!
Norm of q2 = 30
Magnitude of q2 = 5.47723
Scale of q2 by 2 = [2, (4, 6, 8)]
Inverse of q8 = [0.111111, (0.0555556, -0.111111, -0.166667)]
Conjugate of q8 = [2, (1, -2, -3)]
Unit Quaternion of q8 is [0.471405, (-0.235702, 0.471405, 0.707107)]
Rotate q8 by 1.1, 2.34, 7.65 = -1.71889, 7.02889, 3.58444
[-1.28978e-008, (-1.71889, 7.02889, 3.58444)]
#include "stdafx.h"
#include "quaternion.h"//四元数模板类的声明与定义都放在这个文件里
int main(int argc, char **argv)
{
// Quaternion test class
cout << "Quaternion class test" << endl;
cout << "Constructors:" << endl;
float vect[4] = { 5, 6, 7, 8 };
float v[3]= { 1.1, 2.34, 7.65 };
Quaternion<float> q1;
Quaternion<float> q2(1.0f, 2.0f, 3.0f, 4.0f);
Quaternion<float> q3(q2);
Quaternion<float> q4(vect);
Quaternion<float> q7(3.0f, 1.0f, -2.0f, 1.0f);
Quaternion<float> q8(2.0f, -1.0f, 2.0f, 3.0f);
Quaternion<float> q9(3.0f, 1.0f, -2.0f, 1.0f);
Quaternion<float> q16(0.0f, 1.1f, 2.34f, 7.65f);
//
cout << "q1=" << q1 << endl;
cout << "q2=" << q2 << endl;
cout << "q3=" << q3 << endl;
cout << "q4=" << q4 << endl;
cout << "Operators:" << endl;
cout << "Operator =" << endl;
Quaternion <float> q5 = q2;
cout << "q5 = " << q5 << endl;
cout << "Operator +" << endl;
Quaternion <float> q6 = q5 + q4;
cout << "q5 + q4 = " << q6 << endl; //should equal (6,8,10,12)
cout << "Operator -" << endl;
q6 = q5 - q4;
cout << "q5 - q4 = " << q6 << endl; //should equal (-4,-4,-4,-4)
cout << "Operator *" << endl;
q6 = q7 * q8;
cout << "q7 * q8 = " << q6 << endl; //should equal (8,-9,-2,11)
cout << "Operator /" << endl;
q6 = q8.inverse();
cout << "q7/(q8.inverse) = " << q7/q6 << endl;//should equal [8, (-9, -2, 11)]
cout << "Operator += " << endl;
q4 += q5;
cout << "q4 += q5 is " << q4 << endl;//should equal [6, (8, 10, 12)]
cout << "Operator -= " << endl;
q5 -= q5;
cout << "q5 -= q5 is " << q5 << endl;//should equal [0, (0, 0, 0)]
cout << "Operator *= " << endl;
q7 *= q8;
cout << "q7 *= q8 is " << q7 << endl;//should equal [8, (-9, -2, 11)]
cout << "Operator /= " << endl;
q7= q9;
q6 = q8.inverse();
q7/=q6;
cout << "q7 /= q8.inverse() is " << q7 << endl;//should equal [8, (-9, -2, 11)]
cout << "Operator != " << endl;
if (q2 != q2)
cout << "doesn't work:(" << endl;
else
cout << "works!" << endl;
cout << "Operator == " << endl;
if (q2 == q2)
cout << "works!" << endl;
else
cout << "doesn't work:(" << endl;
cout << "Norm of q2 = " << q2.norm() << endl; //30
cout << "Magnitude of q2 = " << q2.magnitude() << endl; //5.4772255....
q6 = q2.scale(2);
cout << "Scale of q2 by 2 = " << q6 << endl;//should equal [2, (4, 6, 8)]
cout << "Inverse of q8 = " << q8.inverse() << endl;//should equal [0.111..., (0.0555..., -0.111..., -0.1666...)]
cout << "Conjugate of q8 = " << q8.conjugate() <<endl; //should equal (2,1,-2,-3)
cout << "Unit Quaternion of q8 is " << q8.UnitQuaternion() << endl;
//QuatRot
q8.QuatRotation(v);
cout << "Rotate q8 by 1.1, 2.34, 7.65 = " << v[0] << ", " << v[1] << ", " << v[2] << endl;
//should get the same answer as QuatRot(v, q8) ignoring the w factor
q2=q8*q16;
q3=q2*(q8.inverse());
cout << q3 << endl;
#ifdef SHOEMAKE
float v1[3] = { 2.3f, 3.2f, 4.3f };
cout << "\nEuler -> Quaternion convertion test:" << endl;
cout << " -in vector: (" << v1[0] << ", " << v1[1] << ", " << v1[2] << ")" << endl;
Quaternion <float> q10(v1, EulOrdZYXs);
cout << " -out quaternion: " << q10 << endl;
cout << "Quaternion -> Euler convertion test:" << endl;
cout << " -in quaternion: " << q10 << endl;
q10.toEuler(v1, EulOrdZYXs);
cout << " -out vector: (" << v1[0] << ", " << v1[1] << ", " << v1[2] << ")" << endl;
#endif
system("pause");
return 0;
}