123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- //
- // 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;
|