/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library 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 files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include // misc defines #define ALLOCA dALLOCA16 void dSetZero (dReal *a, int n) { dAASSERT (a && n >= 0); while (n > 0) { *(a++) = 0; n--; } } void dSetValue (dReal *a, int n, dReal value) { dAASSERT (a && n >= 0); while (n > 0) { *(a++) = value; n--; } } void dMultiply0 (dReal *A, const dReal *B, const dReal *C, int p, int q, int r) { int i,j,k,qskip,rskip,rpad; dAASSERT (A && B && C && p>0 && q>0 && r>0); qskip = dPAD(q); rskip = dPAD(r); rpad = rskip - r; dReal sum; const dReal *b,*c,*bb; bb = B; for (i=p; i; i--) { for (j=0 ; j0 && q>0 && r>0); pskip = dPAD(p); rskip = dPAD(r); for (i=0; i0 && q>0 && r>0); rpad = dPAD(r) - r; qskip = dPAD(q); bb = B; for (i=p; i; i--) { cc = C; for (j=r; j; j--) { z = 0; sum = 0; for (k=q; k; k--,z++) sum += bb[z] * cc[z]; *(A++) = sum; cc += qskip; } A += rpad; bb += qskip; } } int dFactorCholesky (dReal *A, int n) { int i,j,k,nskip; dReal sum,*a,*b,*aa,*bb,*cc,*recip; dAASSERT (n > 0 && A); nskip = dPAD (n); recip = (dReal*) ALLOCA (n * sizeof(dReal)); aa = A; for (i=0; i 0 && L && b); nskip = dPAD (n); y = (dReal*) ALLOCA (n*sizeof(dReal)); for (i=0; i= 0; i--) { sum = 0; for (k=i+1; k < n; k++) sum += L[k*nskip+i]*b[k]; b[i] = (y[i]-sum)/L[i*nskip+i]; } } int dInvertPDMatrix (const dReal *A, dReal *Ainv, int n) { int i,j,nskip; dReal *L,*x; dAASSERT (n > 0 && A && Ainv); nskip = dPAD (n); L = (dReal*) ALLOCA (nskip*n*sizeof(dReal)); memcpy (L,A,nskip*n*sizeof(dReal)); x = (dReal*) ALLOCA (n*sizeof(dReal)); if (dFactorCholesky (L,n)==0) return 0; dSetZero (Ainv,n*nskip); // make sure all padding elements set to 0 for (i=0; i 0 && A); int nskip = dPAD (n); Acopy = (dReal*) ALLOCA (nskip*n * sizeof(dReal)); memcpy (Acopy,A,nskip*n * sizeof(dReal)); return dFactorCholesky (Acopy,n); } /***** this has been replaced by a faster version void dSolveL1T (const dReal *L, dReal *b, int n, int nskip) { int i,j; dAASSERT (L && b && n >= 0 && nskip >= n); dReal sum; for (i=n-2; i>=0; i--) { sum = 0; for (j=i+1; j= 0); for (int i=0; i 0 && nskip >= n); dSolveL1 (L,b,n,nskip); dVectorScale (b,d,n); dSolveL1T (L,b,n,nskip); } void dLDLTAddTL (dReal *L, dReal *d, const dReal *a, int n, int nskip) { int j,p; dReal *W1,*W2,W11,W21,alpha1,alpha2,alphanew,gamma1,gamma2,k1,k2,Wp,ell,dee; dAASSERT (L && d && a && n > 0 && nskip >= n); if (n < 2) return; W1 = (dReal*) ALLOCA (n*sizeof(dReal)); W2 = (dReal*) ALLOCA (n*sizeof(dReal)); W1[0] = 0; W2[0] = 0; for (j=1; j j) ? _GETA(i,j) : _GETA(j,i)) void dLDLTRemove (dReal **A, const int *p, dReal *L, dReal *d, int n1, int n2, int r, int nskip) { int i; dAASSERT(A && p && L && d && n1 > 0 && n2 > 0 && r >= 0 && r < n2 && n1 >= n2 && nskip >= n1); #ifndef dNODEBUG for (i=0; i= 0 && p[i] < n1); #endif if (r==n2-1) { return; // deleting last row/col is easy } else if (r==0) { dReal *a = (dReal*) ALLOCA (n2 * sizeof(dReal)); for (i=0; i 0 && nskip >= n && r >= 0 && r < n); if (r >= n-1) return; if (r > 0) { for (i=0; i