mirror of
https://github.com/bulletphysics/bullet3
synced 2024-12-16 06:30:05 +00:00
153 lines
4.3 KiB
C++
153 lines
4.3 KiB
C++
//
|
|
// Big Vector and Sparse Matrix Classes
|
|
//
|
|
|
|
#include <float.h>
|
|
|
|
#include "vec3n.h"
|
|
|
|
|
|
float conjgrad_lasterror;
|
|
float conjgrad_epsilon = 0.1f;
|
|
int conjgrad_loopcount;
|
|
int conjgrad_looplimit = 100;
|
|
|
|
/*EXPORTVAR(conjgrad_lasterror);
|
|
EXPORTVAR(conjgrad_epsilon );
|
|
EXPORTVAR(conjgrad_loopcount);
|
|
EXPORTVAR(conjgrad_looplimit);
|
|
*/
|
|
|
|
int ConjGradient(float3N &X, float3Nx3N &A, float3N &B)
|
|
{
|
|
// Solves for unknown X in equation AX=B
|
|
conjgrad_loopcount=0;
|
|
int n=B.count;
|
|
float3N q(n),d(n),tmp(n),r(n);
|
|
r = B - Mul(tmp,A,X); // just use B if X known to be zero
|
|
d = r;
|
|
float s = dot(r,r);
|
|
float starget = s * squared(conjgrad_epsilon);
|
|
while( s>starget && conjgrad_loopcount++ < conjgrad_looplimit)
|
|
{
|
|
Mul(q,A,d); // q = A*d;
|
|
float a = s/dot(d,q);
|
|
X = X + d*a;
|
|
if(conjgrad_loopcount%50==0)
|
|
{
|
|
r = B - Mul(tmp,A,X);
|
|
}
|
|
else
|
|
{
|
|
r = r - q*a;
|
|
}
|
|
float s_prev = s;
|
|
s = dot(r,r);
|
|
d = r+d*(s/s_prev);
|
|
}
|
|
conjgrad_lasterror = s;
|
|
return conjgrad_loopcount<conjgrad_looplimit; // true means we reached desired accuracy in given time - ie stable
|
|
}
|
|
|
|
|
|
int ConjGradientMod(float3N &X, float3Nx3N &A, float3N &B,int3 hack)
|
|
{
|
|
// obsolete!!!
|
|
// Solves for unknown X in equation AX=B
|
|
conjgrad_loopcount=0;
|
|
int n=B.count;
|
|
float3N q(n),d(n),tmp(n),r(n);
|
|
r = B - Mul(tmp,A,X); // just use B if X known to be zero
|
|
r[hack[0]] = r[hack[1]] = r[hack[2]] = float3(0,0,0);
|
|
d = r;
|
|
float s = dot(r,r);
|
|
float starget = s * squared(conjgrad_epsilon);
|
|
while( s>starget && conjgrad_loopcount++ < conjgrad_looplimit)
|
|
{
|
|
Mul(q,A,d); // q = A*d;
|
|
q[hack[0]] = q[hack[1]] = q[hack[2]] = float3(0,0,0);
|
|
float a = s/dot(d,q);
|
|
X = X + d*a;
|
|
if(conjgrad_loopcount%50==0)
|
|
{
|
|
r = B - Mul(tmp,A,X);
|
|
r[hack[0]] = r[hack[1]] = r[hack[2]] = float3(0,0,0);
|
|
}
|
|
else
|
|
{
|
|
r = r - q*a;
|
|
}
|
|
float s_prev = s;
|
|
s = dot(r,r);
|
|
d = r+d*(s/s_prev);
|
|
d[hack[0]] = d[hack[1]] = d[hack[2]] = float3(0,0,0);
|
|
}
|
|
conjgrad_lasterror = s;
|
|
return conjgrad_loopcount<conjgrad_looplimit; // true means we reached desired accuracy in given time - ie stable
|
|
}
|
|
|
|
|
|
|
|
static inline void filter(float3N &V,const float3Nx3N &S)
|
|
{
|
|
for(int i=0;i<S.blocks.count;i++)
|
|
{
|
|
V[S.blocks[i].r] = V[S.blocks[i].r]*S.blocks[i].m;
|
|
}
|
|
}
|
|
|
|
int ConjGradientFiltered(float3N &X, const float3Nx3N &A, const float3N &B,const float3Nx3N &S)
|
|
{
|
|
// Solves for unknown X in equation AX=B
|
|
conjgrad_loopcount=0;
|
|
int n=B.count;
|
|
float3N q(n),d(n),tmp(n),r(n);
|
|
r = B - Mul(tmp,A,X); // just use B if X known to be zero
|
|
filter(r,S);
|
|
d = r;
|
|
float s = dot(r,r);
|
|
float starget = s * squared(conjgrad_epsilon);
|
|
while( s>starget && conjgrad_loopcount++ < conjgrad_looplimit)
|
|
{
|
|
Mul(q,A,d); // q = A*d;
|
|
filter(q,S);
|
|
float a = s/dot(d,q);
|
|
X = X + d*a;
|
|
if(conjgrad_loopcount%50==0)
|
|
{
|
|
r = B - Mul(tmp,A,X);
|
|
filter(r,S);
|
|
}
|
|
else
|
|
{
|
|
r = r - q*a;
|
|
}
|
|
float s_prev = s;
|
|
s = dot(r,r);
|
|
d = r+d*(s/s_prev);
|
|
filter(d,S);
|
|
}
|
|
conjgrad_lasterror = s;
|
|
return conjgrad_loopcount<conjgrad_looplimit; // true means we reached desired accuracy in given time - ie stable
|
|
}
|
|
|
|
|
|
|
|
|
|
// test big vector math library:
|
|
static void testfloat3N()
|
|
{
|
|
float3N a(2),b(2),c(2);
|
|
a[0] = float3(1,2,3);
|
|
a[1] = float3(4,5,6);
|
|
b[0] = float3(10,20,30);
|
|
b[1] = float3(40,50,60);
|
|
// c = a+b+b * 10.0f;
|
|
// float d = dot(a+b,-b);
|
|
int k;
|
|
k=0;
|
|
}
|
|
class dotest{public:dotest(){testfloat3N();}}do_test_at_program_startup;
|
|
|
|
|