demo_ode.cpp 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234
  1. /*************************************************************************
  2. * *
  3. * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
  4. * All rights reserved. Email: [email protected] Web: www.q12.org *
  5. * *
  6. * This library is free software; you can redistribute it and/or *
  7. * modify it under the terms of EITHER: *
  8. * (1) The GNU Lesser General Public License as published by the Free *
  9. * Software Foundation; either version 2.1 of the License, or (at *
  10. * your option) any later version. The text of the GNU Lesser *
  11. * General Public License is included with this library in the *
  12. * file LICENSE.TXT. *
  13. * (2) The BSD-style license that is included with this library in *
  14. * the file LICENSE-BSD.TXT. *
  15. * *
  16. * This library is distributed in the hope that it will be useful, *
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
  19. * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
  20. * *
  21. *************************************************************************/
  22. #include <setjmp.h>
  23. #include <ode/ode.h>
  24. #ifdef _MSC_VER
  25. #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
  26. #endif
  27. //****************************************************************************
  28. // matrix accessors
  29. #define _A(i,j) A[(i)*4+(j)]
  30. #define _I(i,j) I[(i)*4+(j)]
  31. #define _R(i,j) R[(i)*4+(j)]
  32. //****************************************************************************
  33. // tolerances
  34. #ifdef dDOUBLE
  35. const double tol = 1e-10;
  36. #endif
  37. #ifdef dSINGLE
  38. const double tol = 1e-5;
  39. #endif
  40. //****************************************************************************
  41. // misc messages and error handling
  42. #ifdef __GNUC__
  43. #define HEADER printf ("%s()\n", __FUNCTION__);
  44. #else
  45. #define HEADER printf ("%s:%d\n",__FILE__,__LINE__);
  46. #endif
  47. static jmp_buf jump_buffer;
  48. void myMessageFunction (int num, const char *msg, va_list ap)
  49. {
  50. printf ("(Message %d: ",num);
  51. vprintf (msg,ap);
  52. printf (")");
  53. dSetMessageHandler (0);
  54. longjmp (jump_buffer,1);
  55. }
  56. #define TRAP_MESSAGE(do,ifnomsg,ifmsg) \
  57. dSetMessageHandler (&myMessageFunction); \
  58. if (setjmp (jump_buffer)) { \
  59. dSetMessageHandler (0); \
  60. ifmsg ; \
  61. } \
  62. else { \
  63. dSetMessageHandler (&myMessageFunction); \
  64. do ; \
  65. ifnomsg ; \
  66. } \
  67. dSetMessageHandler (0);
  68. //****************************************************************************
  69. // utility stuff
  70. // compare two numbers, within a threshhold, return 1 if approx equal
  71. int cmp (dReal a, dReal b)
  72. {
  73. return (fabs(a-b) < tol);
  74. }
  75. //****************************************************************************
  76. // matrix utility stuff
  77. // compare a 3x3 matrix with the identity
  78. int cmpIdentityMat3 (dMatrix3 A)
  79. {
  80. return
  81. (cmp(_A(0,0),1.0) && cmp(_A(0,1),0.0) && cmp(_A(0,2),0.0) &&
  82. cmp(_A(1,0),0.0) && cmp(_A(1,1),1.0) && cmp(_A(1,2),0.0) &&
  83. cmp(_A(2,0),0.0) && cmp(_A(2,1),0.0) && cmp(_A(2,2),1.0));
  84. }
  85. // transpose a 3x3 matrix in-line
  86. void transpose3x3 (dMatrix3 A)
  87. {
  88. dReal tmp;
  89. tmp=A[4]; A[4]=A[1]; A[1]=tmp;
  90. tmp=A[8]; A[8]=A[2]; A[2]=tmp;
  91. tmp=A[9]; A[9]=A[6]; A[6]=tmp;
  92. }
  93. //****************************************************************************
  94. // test miscellaneous math functions
  95. void testRandomNumberGenerator()
  96. {
  97. HEADER;
  98. if (dTestRand()) printf ("\tpassed\n");
  99. else printf ("\tFAILED\n");
  100. }
  101. void testInfinity()
  102. {
  103. HEADER;
  104. if (1e10 < dInfinity && -1e10 > -dInfinity && -dInfinity < dInfinity)
  105. printf ("\tpassed\n");
  106. else printf ("\tFAILED\n");
  107. }
  108. void testPad()
  109. {
  110. HEADER;
  111. char s[100];
  112. s[0]=0;
  113. for (int i=0; i<=16; i++) sprintf (s+strlen(s),"%d ",dPAD(i));
  114. printf ("\t%s\n", strcmp(s,"0 1 4 4 4 8 8 8 8 12 12 12 12 16 16 16 16 ") ?
  115. "FAILED" : "passed");
  116. }
  117. void testCrossProduct()
  118. {
  119. HEADER;
  120. dVector3 a1,a2,b,c;
  121. dMatrix3 B;
  122. dMakeRandomVector (b,3,1.0);
  123. dMakeRandomVector (c,3,1.0);
  124. dCalcVectorCross3(a1,b,c);
  125. dSetZero (B,12);
  126. dSetCrossMatrixPlus(B,b,4);
  127. dMultiply0 (a2,B,c,3,3,1);
  128. dReal diff = dMaxDifference(a1,a2,3,1);
  129. printf ("\t%s\n", diff > tol ? "FAILED" : "passed");
  130. }
  131. void testSetZero()
  132. {
  133. HEADER;
  134. dReal a[100];
  135. dMakeRandomVector (a,100,1.0);
  136. dSetZero (a,100);
  137. for (int i=0; i<100; i++) if (a[i] != 0.0) {
  138. printf ("\tFAILED\n");
  139. return;
  140. }
  141. printf ("\tpassed\n");
  142. }
  143. void testNormalize3()
  144. {
  145. HEADER;
  146. int i,j,bad=0;
  147. dVector3 n1,n2;
  148. for (i=0; i<1000; i++) {
  149. dMakeRandomVector (n1,3,1.0);
  150. for (j=0; j<3; j++) n2[j]=n1[j];
  151. dNormalize3 (n2);
  152. if (dFabs(dCalcVectorDot3(n2,n2) - 1.0) > tol) bad |= 1;
  153. if (dFabs(n2[0]/n1[0] - n2[1]/n1[1]) > tol) bad |= 2;
  154. if (dFabs(n2[0]/n1[0] - n2[2]/n1[2]) > tol) bad |= 4;
  155. if (dFabs(n2[1]/n1[1] - n2[2]/n1[2]) > tol) bad |= 8;
  156. if (dFabs(dCalcVectorDot3(n2,n1) - dSqrt(dCalcVectorDot3(n1,n1))) > tol) bad |= 16;
  157. if (bad) {
  158. printf ("\tFAILED (code=%x)\n",bad);
  159. return;
  160. }
  161. }
  162. printf ("\tpassed\n");
  163. }
  164. /*
  165. void testReorthonormalize()
  166. {
  167. HEADER;
  168. dMatrix3 R,I;
  169. dMakeRandomMatrix (R,3,3,1.0);
  170. for (int i=0; i<30; i++) dReorthonormalize (R);
  171. dMultiply2 (I,R,R,3,3,3);
  172. printf ("\t%s\n",cmpIdentityMat3 (I) ? "passed" : "FAILED");
  173. }
  174. */
  175. void testPlaneSpace()
  176. {
  177. HEADER;
  178. dVector3 n,p,q;
  179. int bad = 0;
  180. for (int i=0; i<1000; i++) {
  181. dMakeRandomVector (n,3,1.0);
  182. dNormalize3 (n);
  183. dPlaneSpace (n,p,q);
  184. if (fabs(dCalcVectorDot3(n,p)) > tol) bad = 1;
  185. if (fabs(dCalcVectorDot3(n,q)) > tol) bad = 1;
  186. if (fabs(dCalcVectorDot3(p,q)) > tol) bad = 1;
  187. if (fabs(dCalcVectorDot3(p,p)-1) > tol) bad = 1;
  188. if (fabs(dCalcVectorDot3(q,q)-1) > tol) bad = 1;
  189. }
  190. printf ("\t%s\n", bad ? "FAILED" : "passed");
  191. }
  192. //****************************************************************************
  193. // test matrix functions
  194. #define MSIZE 21
  195. #define MSIZE4 24 // MSIZE rounded up to 4
  196. void testMatrixMultiply()
  197. {
  198. // A is 2x3, B is 3x4, B2 is B except stored columnwise, C is 2x4
  199. dReal A[8],B[12],A2[12],B2[16],C[8];
  200. int i;
  201. HEADER;
  202. dSetZero (A,8);
  203. for (i=0; i<3; i++) A[i] = i+2;
  204. for (i=0; i<3; i++) A[i+4] = i+3+2;
  205. for (i=0; i<12; i++) B[i] = i+8;
  206. dSetZero (A2,12);
  207. for (i=0; i<6; i++) A2[i+2*(i/2)] = A[i+i/3];
  208. dSetZero (B2,16);
  209. for (i=0; i<12; i++) B2[i+i/3] = B[i];
  210. dMultiply0 (C,A,B,2,3,4);
  211. if (C[0] != 116 || C[1] != 125 || C[2] != 134 || C[3] != 143 ||
  212. C[4] != 224 || C[5] != 242 || C[6] != 260 || C[7] != 278)
  213. printf ("\tFAILED (1)\n"); else printf ("\tpassed (1)\n");
  214. dMultiply1 (C,A2,B,2,3,4);
  215. if (C[0] != 160 || C[1] != 172 || C[2] != 184 || C[3] != 196 ||
  216. C[4] != 196 || C[5] != 211 || C[6] != 226 || C[7] != 241)
  217. printf ("\tFAILED (2)\n"); else printf ("\tpassed (2)\n");
  218. dMultiply2 (C,A,B2,2,3,4);
  219. if (C[0] != 83 || C[1] != 110 || C[2] != 137 || C[3] != 164 ||
  220. C[4] != 164 || C[5] != 218 || C[6] != 272 || C[7] != 326)
  221. printf ("\tFAILED (3)\n"); else printf ("\tpassed (3)\n");
  222. }
  223. void testSmallMatrixMultiply()
  224. {
  225. dMatrix3 A,B,C,A2;
  226. dVector3 a,a2,x;
  227. HEADER;
  228. dMakeRandomMatrix (A,3,3,1.0);
  229. dMakeRandomMatrix (B,3,3,1.0);
  230. dMakeRandomMatrix (C,3,3,1.0);
  231. dMakeRandomMatrix (x,3,1,1.0);
  232. // dMultiply0_331()
  233. dMultiply0_331 (a,B,x);
  234. dMultiply0 (a2,B,x,3,3,1);
  235. printf ("\t%s (1)\n",(dMaxDifference (a,a2,3,1) > tol) ? "FAILED" :
  236. "passed");
  237. // dMultiply1_331()
  238. dMultiply1_331 (a,B,x);
  239. dMultiply1 (a2,B,x,3,3,1);
  240. printf ("\t%s (2)\n",(dMaxDifference (a,a2,3,1) > tol) ? "FAILED" :
  241. "passed");
  242. // dMultiply0_133
  243. dMultiply0_133 (a,x,B);
  244. dMultiply0 (a2,x,B,1,3,3);
  245. printf ("\t%s (3)\n",(dMaxDifference (a,a2,1,3) > tol) ? "FAILED" :
  246. "passed");
  247. // dMultiply0_333()
  248. dMultiply0_333 (A,B,C);
  249. dMultiply0 (A2,B,C,3,3,3);
  250. printf ("\t%s (4)\n",(dMaxDifference (A,A2,3,3) > tol) ? "FAILED" :
  251. "passed");
  252. // dMultiply1_333()
  253. dMultiply1_333 (A,B,C);
  254. dMultiply1 (A2,B,C,3,3,3);
  255. printf ("\t%s (5)\n",(dMaxDifference (A,A2,3,3) > tol) ? "FAILED" :
  256. "passed");
  257. // dMultiply2_333()
  258. dMultiply2_333 (A,B,C);
  259. dMultiply2 (A2,B,C,3,3,3);
  260. printf ("\t%s (6)\n",(dMaxDifference (A,A2,3,3) > tol) ? "FAILED" :
  261. "passed");
  262. }
  263. void testCholeskyFactorization()
  264. {
  265. size_t matrixSize = sizeof(dReal) * MSIZE4 * MSIZE;
  266. dReal *A = (dReal *)dAlloc(matrixSize), *B = (dReal *)dAlloc(matrixSize), *C = (dReal *)dAlloc(matrixSize), diff;
  267. HEADER;
  268. dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
  269. dMultiply2 (B,A,A,MSIZE,MSIZE,MSIZE);
  270. memcpy (A,B,MSIZE4*MSIZE*sizeof(dReal));
  271. if (dFactorCholesky (B,MSIZE)) printf ("\tpassed (1)\n");
  272. else printf ("\tFAILED (1)\n");
  273. dClearUpperTriangle (B,MSIZE);
  274. dMultiply2 (C,B,B,MSIZE,MSIZE,MSIZE);
  275. diff = dMaxDifference(A,C,MSIZE,MSIZE);
  276. printf ("\tmaximum difference = %.6e - %s (2)\n",diff,
  277. diff > tol ? "FAILED" : "passed");
  278. dFree(C, matrixSize);
  279. dFree(B, matrixSize);
  280. dFree(A, matrixSize);
  281. }
  282. void testCholeskySolve()
  283. {
  284. size_t matrixSize = sizeof(dReal) * MSIZE4 * MSIZE, vectorSize = sizeof(dReal) * MSIZE;
  285. dReal *A = (dReal *)dAlloc(matrixSize), *L = (dReal *)dAlloc(matrixSize);
  286. dReal *b = (dReal *)dAlloc(vectorSize), *x = (dReal *)dAlloc(vectorSize), *btest = (dReal *)dAlloc(vectorSize), diff;
  287. HEADER;
  288. // get A,L = PD matrix
  289. dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
  290. dMultiply2 (L,A,A,MSIZE,MSIZE,MSIZE);
  291. memcpy (A,L,MSIZE4*MSIZE*sizeof(dReal));
  292. // get b,x = right hand side
  293. dMakeRandomMatrix (b,MSIZE,1,1.0);
  294. memcpy (x,b,MSIZE*sizeof(dReal));
  295. // factor L
  296. if (dFactorCholesky (L,MSIZE)) printf ("\tpassed (1)\n");
  297. else printf ("\tFAILED (1)\n");
  298. dClearUpperTriangle (L,MSIZE);
  299. // solve A*x = b
  300. dSolveCholesky (L,x,MSIZE);
  301. // compute A*x and compare it with b
  302. dMultiply2 (btest,A,x,MSIZE,MSIZE,1);
  303. diff = dMaxDifference(b,btest,MSIZE,1);
  304. printf ("\tmaximum difference = %.6e - %s (2)\n",diff,
  305. diff > tol ? "FAILED" : "passed");
  306. dFree(btest, vectorSize);
  307. dFree(x, vectorSize);
  308. dFree(b, vectorSize);
  309. dFree(L, matrixSize);
  310. dFree(A, matrixSize);
  311. }
  312. void testInvertPDMatrix()
  313. {
  314. int i,j,ok;
  315. size_t matrixSize = sizeof(dReal) * MSIZE4 * MSIZE;
  316. dReal *A = (dReal *)dAlloc(matrixSize), *Ainv = (dReal *)dAlloc(matrixSize), *I = (dReal *)dAlloc(matrixSize);
  317. HEADER;
  318. dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
  319. dMultiply2 (Ainv,A,A,MSIZE,MSIZE,MSIZE);
  320. memcpy (A,Ainv,MSIZE4*MSIZE*sizeof(dReal));
  321. dSetZero (Ainv,MSIZE4*MSIZE);
  322. if (dInvertPDMatrix (A,Ainv,MSIZE))
  323. printf ("\tpassed (1)\n"); else printf ("\tFAILED (1)\n");
  324. dMultiply0 (I,A,Ainv,MSIZE,MSIZE,MSIZE);
  325. // compare with identity
  326. ok = 1;
  327. for (i=0; i<MSIZE; i++) {
  328. for (j=0; j<MSIZE; j++) {
  329. if (i != j) if (cmp (I[i*MSIZE4+j],0.0)==0) ok = 0;
  330. }
  331. }
  332. for (i=0; i<MSIZE; i++) {
  333. if (cmp (I[i*MSIZE4+i],1.0)==0) ok = 0;
  334. }
  335. if (ok) printf ("\tpassed (2)\n"); else printf ("\tFAILED (2)\n");
  336. dFree(I, matrixSize);
  337. dFree(Ainv, matrixSize);
  338. dFree(A, matrixSize);
  339. }
  340. void testIsPositiveDefinite()
  341. {
  342. size_t matrixSize = sizeof(dReal) * MSIZE4 * MSIZE;
  343. dReal *A = (dReal *)dAlloc(matrixSize), *B = (dReal *)dAlloc(matrixSize);
  344. HEADER;
  345. dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
  346. dMultiply2 (B,A,A,MSIZE,MSIZE,MSIZE);
  347. printf ("\t%s\n",dIsPositiveDefinite(A,MSIZE) ? "FAILED (1)":"passed (1)");
  348. printf ("\t%s\n",dIsPositiveDefinite(B,MSIZE) ? "passed (2)":"FAILED (2)");
  349. dFree(B, matrixSize);
  350. dFree(A, matrixSize);
  351. }
  352. void testFastLDLTFactorization()
  353. {
  354. int i,j;
  355. size_t matrixSize = sizeof(dReal) * MSIZE4 * MSIZE, vectorSize = sizeof(dReal) * MSIZE;
  356. dReal *A = (dReal *)dAlloc(matrixSize), *L = (dReal *)dAlloc(matrixSize), *DL = (dReal *)dAlloc(matrixSize),
  357. *ATEST = (dReal *)dAlloc(matrixSize), *d = (dReal *)dAlloc(vectorSize), diff;
  358. HEADER;
  359. dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
  360. dMultiply2 (L,A,A,MSIZE,MSIZE,MSIZE);
  361. memcpy (A,L,MSIZE4*MSIZE*sizeof(dReal));
  362. dFactorLDLT (L,d,MSIZE,MSIZE4);
  363. dClearUpperTriangle (L,MSIZE);
  364. for (i=0; i<MSIZE; i++) L[i*MSIZE4+i] = 1.0;
  365. dSetZero (DL,MSIZE4*MSIZE);
  366. for (i=0; i<MSIZE; i++) {
  367. for (j=0; j<MSIZE; j++) DL[i*MSIZE4+j] = L[i*MSIZE4+j] / d[j];
  368. }
  369. dMultiply2 (ATEST,L,DL,MSIZE,MSIZE,MSIZE);
  370. diff = dMaxDifference(A,ATEST,MSIZE,MSIZE);
  371. printf ("\tmaximum difference = %.6e - %s\n",diff,
  372. diff > tol ? "FAILED" : "passed");
  373. dFree(d, vectorSize);
  374. dFree(ATEST, matrixSize);
  375. dFree(DL, matrixSize);
  376. dFree(L, matrixSize);
  377. dFree(A, matrixSize);
  378. }
  379. void testSolveLDLT()
  380. {
  381. size_t matrixSize = sizeof(dReal) * MSIZE4 * MSIZE, vectorSize = sizeof(dReal) * MSIZE;
  382. dReal *A = (dReal *)dAlloc(matrixSize), *L = (dReal *)dAlloc(matrixSize),
  383. *d = (dReal *)dAlloc(vectorSize), *x = (dReal *)dAlloc(vectorSize),
  384. *b = (dReal *)dAlloc(vectorSize), *btest = (dReal *)dAlloc(vectorSize), diff;
  385. HEADER;
  386. dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
  387. dMultiply2 (L,A,A,MSIZE,MSIZE,MSIZE);
  388. memcpy (A,L,MSIZE4*MSIZE*sizeof(dReal));
  389. dMakeRandomMatrix (b,MSIZE,1,1.0);
  390. memcpy (x,b,MSIZE*sizeof(dReal));
  391. dFactorLDLT (L,d,MSIZE,MSIZE4);
  392. dSolveLDLT (L,d,x,MSIZE,MSIZE4);
  393. dMultiply2 (btest,A,x,MSIZE,MSIZE,1);
  394. diff = dMaxDifference(b,btest,MSIZE,1);
  395. printf ("\tmaximum difference = %.6e - %s\n",diff,
  396. diff > tol ? "FAILED" : "passed");
  397. dFree(btest, vectorSize);
  398. dFree(b, vectorSize);
  399. dFree(x, vectorSize);
  400. dFree(d, vectorSize);
  401. dFree(L, matrixSize);
  402. dFree(A, matrixSize);
  403. }
  404. void testLDLTAddTL()
  405. {
  406. int i,j;
  407. size_t matrixSize = sizeof(dReal) * MSIZE4 * MSIZE, vectorSize = sizeof(dReal) * MSIZE;
  408. dReal *A = (dReal *)dAlloc(matrixSize), *L = (dReal *)dAlloc(matrixSize),
  409. *DL = (dReal *)dAlloc(matrixSize), *ATEST = (dReal *)dAlloc(matrixSize),
  410. *d = (dReal *)dAlloc(vectorSize), *a = (dReal *)dAlloc(vectorSize), diff;
  411. HEADER;
  412. dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
  413. dMultiply2 (L,A,A,MSIZE,MSIZE,MSIZE);
  414. memcpy (A,L,MSIZE4*MSIZE*sizeof(dReal));
  415. dFactorLDLT (L,d,MSIZE,MSIZE4);
  416. // delete first row and column of factorization
  417. for (i=0; i<MSIZE; i++) a[i] = -A[i*MSIZE4];
  418. a[0] += 1;
  419. dLDLTAddTL (L,d,a,MSIZE,MSIZE4);
  420. for (i=1; i<MSIZE; i++) L[i*MSIZE4] = 0;
  421. d[0] = 1;
  422. // get modified L*D*L'
  423. dClearUpperTriangle (L,MSIZE);
  424. for (i=0; i<MSIZE; i++) L[i*MSIZE4+i] = 1.0;
  425. dSetZero (DL,MSIZE4*MSIZE);
  426. for (i=0; i<MSIZE; i++) {
  427. for (j=0; j<MSIZE; j++) DL[i*MSIZE4+j] = L[i*MSIZE4+j] / d[j];
  428. }
  429. dMultiply2 (ATEST,L,DL,MSIZE,MSIZE,MSIZE);
  430. // compare it to A with its first row/column removed
  431. for (i=1; i<MSIZE; i++) A[i*MSIZE4] = A[i] = 0;
  432. A[0] = 1;
  433. diff = dMaxDifference(A,ATEST,MSIZE,MSIZE);
  434. printf ("\tmaximum difference = %.6e - %s\n",diff,
  435. diff > tol ? "FAILED" : "passed");
  436. dFree(a, vectorSize);
  437. dFree(d, vectorSize);
  438. dFree(ATEST, matrixSize);
  439. dFree(DL, matrixSize);
  440. dFree(L, matrixSize);
  441. dFree(A, matrixSize);
  442. }
  443. void testLDLTRemove()
  444. {
  445. int i,j,r;
  446. size_t intVectorSize = sizeof(int) * MSIZE, matrixSize = sizeof(dReal) * MSIZE4 * MSIZE, vectorSize = sizeof(dReal) * MSIZE;
  447. int *p = (int *)dAlloc(intVectorSize);
  448. dReal *A = (dReal *)dAlloc(matrixSize), *L = (dReal *)dAlloc(matrixSize),
  449. *L2 = (dReal *)dAlloc(matrixSize), *DL2 = (dReal *)dAlloc(matrixSize),
  450. *Atest1 = (dReal *)dAlloc(matrixSize), *Atest2 = (dReal *)dAlloc(matrixSize),
  451. *d = (dReal *)dAlloc(vectorSize), *d2 = (dReal *)dAlloc(vectorSize), diff, maxdiff;
  452. HEADER;
  453. // make array of A row pointers
  454. dReal *Arows[MSIZE];
  455. for (i=0; i<MSIZE; i++) Arows[i] = A+i*MSIZE4;
  456. // fill permutation vector
  457. for (i=0; i<MSIZE; i++) p[i]=i;
  458. dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
  459. dMultiply2 (L,A,A,MSIZE,MSIZE,MSIZE);
  460. memcpy (A,L,MSIZE4*MSIZE*sizeof(dReal));
  461. dFactorLDLT (L,d,MSIZE,MSIZE4);
  462. maxdiff = 1e10;
  463. for (r=0; r<MSIZE; r++) {
  464. // get Atest1 = A with row/column r removed
  465. memcpy (Atest1,A,MSIZE4*MSIZE*sizeof(dReal));
  466. dRemoveRowCol (Atest1,MSIZE,MSIZE4,r);
  467. // test that the row/column removal worked
  468. int bad = 0;
  469. for (i=0; i<MSIZE; i++) {
  470. for (j=0; j<MSIZE; j++) {
  471. if (i != r && j != r) {
  472. int ii = i;
  473. int jj = j;
  474. if (ii >= r) ii--;
  475. if (jj >= r) jj--;
  476. if (A[i*MSIZE4+j] != Atest1[ii*MSIZE4+jj]) bad = 1;
  477. }
  478. }
  479. }
  480. if (bad) printf ("\trow/col removal FAILED for row %d\n",r);
  481. // zero out last row/column of Atest1
  482. for (i=0; i<MSIZE; i++) {
  483. Atest1[(MSIZE-1)*MSIZE4+i] = 0;
  484. Atest1[i*MSIZE4+MSIZE-1] = 0;
  485. }
  486. // get L2*D2*L2' = adjusted factorization to remove that row
  487. memcpy (L2,L,MSIZE4*MSIZE*sizeof(dReal));
  488. memcpy (d2,d,MSIZE*sizeof(dReal));
  489. dLDLTRemove (/*A*/ Arows,p,L2,d2,MSIZE,MSIZE,r,MSIZE4);
  490. // get Atest2 = L2*D2*L2'
  491. dClearUpperTriangle (L2,MSIZE);
  492. for (i=0; i<(MSIZE-1); i++) L2[i*MSIZE4+i] = 1.0;
  493. for (i=0; i<MSIZE; i++) L2[(MSIZE-1)*MSIZE4+i] = 0;
  494. d2[MSIZE-1] = 1;
  495. dSetZero (DL2,MSIZE4*MSIZE);
  496. for (i=0; i<(MSIZE-1); i++) {
  497. for (j=0; j<MSIZE-1; j++) DL2[i*MSIZE4+j] = L2[i*MSIZE4+j] / d2[j];
  498. }
  499. dMultiply2 (Atest2,L2,DL2,MSIZE,MSIZE,MSIZE);
  500. diff = dMaxDifference(Atest1,Atest2,MSIZE,MSIZE);
  501. if (diff < maxdiff) maxdiff = diff;
  502. /*
  503. dPrintMatrix (Atest1,MSIZE,MSIZE);
  504. printf ("\n");
  505. dPrintMatrix (Atest2,MSIZE,MSIZE);
  506. printf ("\n");
  507. */
  508. }
  509. printf ("\tmaximum difference = %.6e - %s\n",maxdiff,
  510. maxdiff > tol ? "FAILED" : "passed");
  511. dFree(d2, vectorSize);
  512. dFree(d, vectorSize);
  513. dFree(Atest2, matrixSize);
  514. dFree(Atest1, matrixSize);
  515. dFree(DL2, matrixSize);
  516. dFree(L2, matrixSize);
  517. dFree(L, matrixSize);
  518. dFree(A, matrixSize);
  519. }
  520. //****************************************************************************
  521. // test mass stuff
  522. #define NUMP 10 // number of particles
  523. void printMassParams (dMass *m)
  524. {
  525. printf ("mass = %.4f\n",m->mass);
  526. printf ("com = (%.4f,%.4f,%.4f)\n",m->c[0],m->c[1],m->c[2]);
  527. printf ("I = [ %10.4f %10.4f %10.4f ]\n"
  528. " [ %10.4f %10.4f %10.4f ]\n"
  529. " [ %10.4f %10.4f %10.4f ]\n",
  530. m->_I(0,0),m->_I(0,1),m->_I(0,2),
  531. m->_I(1,0),m->_I(1,1),m->_I(1,2),
  532. m->_I(2,0),m->_I(2,1),m->_I(2,2));
  533. }
  534. void compareMassParams (dMass *m1, dMass *m2, const char *msg)
  535. {
  536. int i,j,ok = 1;
  537. if (!(cmp(m1->mass,m2->mass) && cmp(m1->c[0],m2->c[0]) &&
  538. cmp(m1->c[1],m2->c[1]) && cmp(m1->c[2],m2->c[2])))
  539. ok = 0;
  540. for (i=0; i<3; i++) for (j=0; j<3; j++)
  541. if (cmp (m1->_I(i,j),m2->_I(i,j))==0) ok = 0;
  542. if (ok) printf ("\tpassed (%s)\n",msg); else printf ("\tFAILED (%s)\n",msg);
  543. }
  544. // compute the mass parameters of a particle set
  545. void computeMassParams (dMass *m, dReal q[NUMP][3], dReal pm[NUMP])
  546. {
  547. int i,j;
  548. dMassSetZero (m);
  549. for (i=0; i<NUMP; i++) {
  550. m->mass += pm[i];
  551. for (j=0; j<3; j++) m->c[j] += pm[i]*q[i][j];
  552. m->_I(0,0) += pm[i]*(q[i][1]*q[i][1] + q[i][2]*q[i][2]);
  553. m->_I(1,1) += pm[i]*(q[i][0]*q[i][0] + q[i][2]*q[i][2]);
  554. m->_I(2,2) += pm[i]*(q[i][0]*q[i][0] + q[i][1]*q[i][1]);
  555. m->_I(0,1) -= pm[i]*(q[i][0]*q[i][1]);
  556. m->_I(0,2) -= pm[i]*(q[i][0]*q[i][2]);
  557. m->_I(1,2) -= pm[i]*(q[i][1]*q[i][2]);
  558. }
  559. for (j=0; j<3; j++) m->c[j] /= m->mass;
  560. m->_I(1,0) = m->_I(0,1);
  561. m->_I(2,0) = m->_I(0,2);
  562. m->_I(2,1) = m->_I(1,2);
  563. }
  564. void testMassFunctions()
  565. {
  566. dMass m;
  567. int i,j;
  568. dReal q[NUMP][3]; // particle positions
  569. dReal pm[NUMP]; // particle masses
  570. dMass m1,m2;
  571. dMatrix3 R;
  572. HEADER;
  573. printf ("\t");
  574. dMassSetZero (&m);
  575. TRAP_MESSAGE (dMassSetParameters (&m,10, 0,0,0, 1,2,3, 4,5,6),
  576. printf (" FAILED (1)\n"), printf (" passed (1)\n"));
  577. printf ("\t");
  578. dMassSetZero (&m);
  579. TRAP_MESSAGE (dMassSetParameters (&m,10, 0.1,0.2,0.15, 3,5,14, 3.1,3.2,4),
  580. printf ("passed (2)\n") , printf (" FAILED (2)\n"));
  581. if (m.mass==10 && m.c[0]==REAL(0.1) && m.c[1]==REAL(0.2) &&
  582. m.c[2]==REAL(0.15) && m._I(0,0)==3 && m._I(1,1)==5 && m._I(2,2)==14 &&
  583. m._I(0,1)==REAL(3.1) && m._I(0,2)==REAL(3.2) && m._I(1,2)==4 &&
  584. m._I(1,0)==REAL(3.1) && m._I(2,0)==REAL(3.2) && m._I(2,1)==4)
  585. printf ("\tpassed (3)\n"); else printf ("\tFAILED (3)\n");
  586. dMassSetZero (&m);
  587. dMassSetSphere (&m,1.4, 0.86);
  588. if (cmp(m.mass,3.73002719949386) && m.c[0]==0 && m.c[1]==0 && m.c[2]==0 &&
  589. cmp(m._I(0,0),1.10349124669826) &&
  590. cmp(m._I(1,1),1.10349124669826) &&
  591. cmp(m._I(2,2),1.10349124669826) &&
  592. m._I(0,1)==0 && m._I(0,2)==0 && m._I(1,2)==0 &&
  593. m._I(1,0)==0 && m._I(2,0)==0 && m._I(2,1)==0)
  594. printf ("\tpassed (4)\n"); else printf ("\tFAILED (4)\n");
  595. dMassSetZero (&m);
  596. dMassSetCapsule (&m,1.3,1,0.76,1.53);
  597. if (cmp(m.mass,5.99961928996029) && m.c[0]==0 && m.c[1]==0 && m.c[2]==0 &&
  598. cmp(m._I(0,0),1.59461986077384) &&
  599. cmp(m._I(1,1),4.21878433864904) &&
  600. cmp(m._I(2,2),4.21878433864904) &&
  601. m._I(0,1)==0 && m._I(0,2)==0 && m._I(1,2)==0 &&
  602. m._I(1,0)==0 && m._I(2,0)==0 && m._I(2,1)==0)
  603. printf ("\tpassed (5)\n"); else printf ("\tFAILED (5)\n");
  604. dMassSetZero (&m);
  605. dMassSetBox (&m,0.27,3,4,5);
  606. if (cmp(m.mass,16.2) && m.c[0]==0 && m.c[1]==0 && m.c[2]==0 &&
  607. cmp(m._I(0,0),55.35) && cmp(m._I(1,1),45.9) && cmp(m._I(2,2),33.75) &&
  608. m._I(0,1)==0 && m._I(0,2)==0 && m._I(1,2)==0 &&
  609. m._I(1,0)==0 && m._I(2,0)==0 && m._I(2,1)==0)
  610. printf ("\tpassed (6)\n"); else printf ("\tFAILED (6)\n");
  611. // test dMassAdjust?
  612. // make random particles and compute the mass, COM and inertia, then
  613. // translate and repeat.
  614. for (i=0; i<NUMP; i++) {
  615. pm[i] = dRandReal()+0.5;
  616. for (j=0; j<3; j++) {
  617. q[i][j] = 2.0*(dRandReal()-0.5);
  618. }
  619. }
  620. computeMassParams (&m1,q,pm);
  621. memcpy (&m2,&m1,sizeof(dMass));
  622. dMassTranslate (&m2,1,2,-3);
  623. for (i=0; i<NUMP; i++) {
  624. q[i][0] += 1;
  625. q[i][1] += 2;
  626. q[i][2] -= 3;
  627. }
  628. computeMassParams (&m1,q,pm);
  629. compareMassParams (&m1,&m2,"7");
  630. // rotate the masses
  631. _R(0,0) = -0.87919618797635;
  632. _R(0,1) = 0.15278881840384;
  633. _R(0,2) = -0.45129772879842;
  634. _R(1,0) = -0.47307856232664;
  635. _R(1,1) = -0.39258064912909;
  636. _R(1,2) = 0.78871864932708;
  637. _R(2,0) = -0.05666336483842;
  638. _R(2,1) = 0.90693771059546;
  639. _R(2,2) = 0.41743652473765;
  640. dMassRotate (&m2,R);
  641. for (i=0; i<NUMP; i++) {
  642. dReal a[3];
  643. dMultiply0 (a,&_R(0,0),&q[i][0],3,3,1);
  644. q[i][0] = a[0];
  645. q[i][1] = a[1];
  646. q[i][2] = a[2];
  647. }
  648. computeMassParams (&m1,q,pm);
  649. compareMassParams (&m1,&m2,"8");
  650. }
  651. //****************************************************************************
  652. // test rotation stuff
  653. void makeRandomRotation (dMatrix3 R)
  654. {
  655. dReal *u1 = R, *u2=R+4, *u3=R+8;
  656. dMakeRandomVector (u1,3,1.0);
  657. dNormalize3 (u1);
  658. dMakeRandomVector (u2,3,1.0);
  659. dReal d = dCalcVectorDot3(u1,u2);
  660. u2[0] -= d*u1[0];
  661. u2[1] -= d*u1[1];
  662. u2[2] -= d*u1[2];
  663. dNormalize3(u2);
  664. dCalcVectorCross3(u3,u1,u2);
  665. }
  666. void testRtoQandQtoR()
  667. {
  668. HEADER;
  669. dMatrix3 R,I,R2;
  670. dQuaternion q;
  671. int i;
  672. // test makeRandomRotation()
  673. makeRandomRotation (R);
  674. dMultiply2 (I,R,R,3,3,3);
  675. printf ("\tmakeRandomRotation() - %s (1)\n",
  676. cmpIdentityMat3(I) ? "passed" : "FAILED");
  677. // test QtoR() on random normalized quaternions
  678. int ok = 1;
  679. for (i=0; i<100; i++) {
  680. dMakeRandomVector (q,4,1.0);
  681. dNormalize4 (q);
  682. dQtoR (q,R);
  683. dMultiply2 (I,R,R,3,3,3);
  684. if (cmpIdentityMat3(I)==0) ok = 0;
  685. }
  686. printf ("\tQtoR() orthonormality %s (2)\n", ok ? "passed" : "FAILED");
  687. // test R -> Q -> R works
  688. dReal maxdiff=0;
  689. for (i=0; i<100; i++) {
  690. makeRandomRotation (R);
  691. dRtoQ (R,q);
  692. dQtoR (q,R2);
  693. dReal diff = dMaxDifference (R,R2,3,3);
  694. if (diff > maxdiff) maxdiff = diff;
  695. }
  696. printf ("\tmaximum difference = %e - %s (3)\n",maxdiff,
  697. (maxdiff > tol) ? "FAILED" : "passed");
  698. }
  699. void testQuaternionMultiply()
  700. {
  701. HEADER;
  702. dMatrix3 RA,RB,RC,Rtest;
  703. dQuaternion qa,qb,qc;
  704. dReal diff,maxdiff=0;
  705. for (int i=0; i<100; i++) {
  706. makeRandomRotation (RB);
  707. makeRandomRotation (RC);
  708. dRtoQ (RB,qb);
  709. dRtoQ (RC,qc);
  710. dMultiply0 (RA,RB,RC,3,3,3);
  711. dQMultiply0 (qa,qb,qc);
  712. dQtoR (qa,Rtest);
  713. diff = dMaxDifference (Rtest,RA,3,3);
  714. if (diff > maxdiff) maxdiff = diff;
  715. dMultiply1 (RA,RB,RC,3,3,3);
  716. dQMultiply1 (qa,qb,qc);
  717. dQtoR (qa,Rtest);
  718. diff = dMaxDifference (Rtest,RA,3,3);
  719. if (diff > maxdiff) maxdiff = diff;
  720. dMultiply2 (RA,RB,RC,3,3,3);
  721. dQMultiply2 (qa,qb,qc);
  722. dQtoR (qa,Rtest);
  723. diff = dMaxDifference (Rtest,RA,3,3);
  724. if (diff > maxdiff) maxdiff = diff;
  725. dMultiply0 (RA,RC,RB,3,3,3);
  726. transpose3x3 (RA);
  727. dQMultiply3 (qa,qb,qc);
  728. dQtoR (qa,Rtest);
  729. diff = dMaxDifference (Rtest,RA,3,3);
  730. if (diff > maxdiff) maxdiff = diff;
  731. }
  732. printf ("\tmaximum difference = %e - %s\n",maxdiff,
  733. (maxdiff > tol) ? "FAILED" : "passed");
  734. }
  735. void testRotationFunctions()
  736. {
  737. dMatrix3 R1;
  738. HEADER;
  739. printf ("\tdRSetIdentity - ");
  740. dMakeRandomMatrix (R1,3,3,1.0);
  741. dRSetIdentity (R1);
  742. if (cmpIdentityMat3(R1)) printf ("passed\n"); else printf ("FAILED\n");
  743. printf ("\tdRFromAxisAndAngle - ");
  744. printf ("\n");
  745. printf ("\tdRFromEulerAngles - ");
  746. printf ("\n");
  747. printf ("\tdRFrom2Axes - ");
  748. printf ("\n");
  749. }
  750. //****************************************************************************
  751. #include <assert.h>
  752. template<class T>
  753. class simplevector
  754. {
  755. private:
  756. int n;
  757. int max;
  758. T* data;
  759. public:
  760. simplevector() { initialize(); }
  761. ~simplevector() { finalize(); }
  762. T& operator[](int i) { assert(i>=0 && i<n); return data[i]; }
  763. const T& operator[](int i) const { assert(i>=0 && i<n); return data[i]; }
  764. void push_back(const T& elem)
  765. {
  766. if (n == max)
  767. {
  768. max *= 2;
  769. T* newdata = new T[max];
  770. memcpy(newdata, data, sizeof(T)*n);
  771. delete[] data;
  772. data = newdata;
  773. }
  774. data[n++] = elem;
  775. }
  776. int size() const { return n; }
  777. void clear() { finalize(); initialize(); }
  778. private:
  779. void finalize() { delete[] data; }
  780. void initialize() { data = new T[32]; max = 32; n = 0; }
  781. };
  782. // matrix header on the stack
  783. class dMatrixComparison {
  784. struct dMatInfo;
  785. simplevector<dMatInfo*> mat;
  786. int afterfirst,index;
  787. public:
  788. dMatrixComparison();
  789. ~dMatrixComparison();
  790. dReal nextMatrix (dReal *A, int n, int m, int lower_tri, const char *name, ...);
  791. // add a new n*m matrix A to the sequence. the name of the matrix is given
  792. // by the printf-style arguments (name,...). if this is the first sequence
  793. // then this object will simply record the matrices and return 0.
  794. // if this the second or subsequent sequence then this object will compare
  795. // the matrices with the first sequence, and report any differences.
  796. // the matrix error will be returned. if `lower_tri' is 1 then only the
  797. // lower triangle of the matrix (including the diagonal) will be compared
  798. // (the matrix must be square).
  799. void end();
  800. // end a sequence.
  801. void reset();
  802. // restarts the object, so the next sequence will be the first sequence.
  803. void dump();
  804. // print out info about all the matrices in the sequence
  805. };
  806. struct dMatrixComparison::dMatInfo {
  807. int n,m; // size of matrix
  808. char name[128]; // name of the matrix
  809. dReal *data; // matrix data
  810. int size; // size of `data'
  811. };
  812. dMatrixComparison::dMatrixComparison()
  813. {
  814. afterfirst = 0;
  815. index = 0;
  816. }
  817. dMatrixComparison::~dMatrixComparison()
  818. {
  819. reset();
  820. }
  821. dReal dMatrixComparison::nextMatrix (dReal *A, int n, int m, int lower_tri,
  822. const char *name, ...)
  823. {
  824. if (A==0 || n < 1 || m < 1 || name==0) dDebug (0,"bad args to nextMatrix");
  825. int num = n*dPAD(m);
  826. if (afterfirst==0) {
  827. dMatInfo *mi = (dMatInfo*) dAlloc (sizeof(dMatInfo));
  828. mi->n = n;
  829. mi->m = m;
  830. mi->size = num * sizeof(dReal);
  831. mi->data = (dReal*) dAlloc (mi->size);
  832. memcpy (mi->data,A,mi->size);
  833. va_list ap;
  834. va_start (ap,name);
  835. vsprintf (mi->name,name,ap);
  836. va_end (ap);
  837. if (strlen(mi->name) >= sizeof (mi->name)) dDebug (0,"name too long");
  838. mat.push_back(mi);
  839. return 0;
  840. }
  841. else {
  842. if (lower_tri && n != m)
  843. dDebug (0,"dMatrixComparison, lower triangular matrix must be square");
  844. if (index >= mat.size()) dDebug (0,"dMatrixComparison, too many matrices");
  845. dMatInfo *mp = mat[index];
  846. index++;
  847. dMatInfo mi;
  848. va_list ap;
  849. va_start (ap,name);
  850. vsprintf (mi.name,name,ap);
  851. va_end (ap);
  852. if (strlen(mi.name) >= sizeof (mi.name)) dDebug (0,"name too long");
  853. if (strcmp(mp->name,mi.name) != 0)
  854. dDebug (0,"dMatrixComparison, name mismatch (\"%s\" and \"%s\")",
  855. mp->name,mi.name);
  856. if (mp->n != n || mp->m != m)
  857. dDebug (0,"dMatrixComparison, size mismatch (%dx%d and %dx%d)",
  858. mp->n,mp->m,n,m);
  859. dReal maxdiff;
  860. if (lower_tri) {
  861. maxdiff = dMaxDifferenceLowerTriangle (A,mp->data,n);
  862. }
  863. else {
  864. maxdiff = dMaxDifference (A,mp->data,n,m);
  865. }
  866. if (maxdiff > tol)
  867. dDebug (0,"dMatrixComparison, matrix error (size=%dx%d, name=\"%s\", "
  868. "error=%.4e)",n,m,mi.name,maxdiff);
  869. return maxdiff;
  870. }
  871. }
  872. void dMatrixComparison::end()
  873. {
  874. if (mat.size() <= 0) dDebug (0,"no matrices in sequence");
  875. afterfirst = 1;
  876. index = 0;
  877. }
  878. void dMatrixComparison::reset()
  879. {
  880. for (int i=0; i<mat.size(); i++) {
  881. dFree (mat[i]->data,mat[i]->size);
  882. dFree (mat[i],sizeof(dMatInfo));
  883. }
  884. mat.clear();
  885. afterfirst = 0;
  886. index = 0;
  887. }
  888. void dMatrixComparison::dump()
  889. {
  890. for (int i=0; i<mat.size(); i++)
  891. printf ("%d: %s (%dx%d)\n",i,mat[i]->name,mat[i]->n,mat[i]->m);
  892. }
  893. //****************************************************************************
  894. // unit test
  895. #include <setjmp.h>
  896. // static jmp_buf jump_buffer;
  897. static void myDebug (int /*num*/, const char* /*msg*/, va_list /*ap*/)
  898. {
  899. // printf ("(Error %d: ",num);
  900. // vprintf (msg,ap);
  901. // printf (")\n");
  902. longjmp (jump_buffer,1);
  903. }
  904. extern "C" void dTestMatrixComparison()
  905. {
  906. volatile int i;
  907. printf ("dTestMatrixComparison()\n");
  908. dMessageFunction *orig_debug = dGetDebugHandler();
  909. dMatrixComparison mc;
  910. dReal A[50*50];
  911. // make first sequence
  912. unsigned long seed = dRandGetSeed();
  913. for (i=1; i<49; i++) {
  914. dMakeRandomMatrix (A,i,i+1,1.0);
  915. mc.nextMatrix (A,i,i+1,0,"A%d",i);
  916. }
  917. mc.end();
  918. //mc.dump();
  919. // test identical sequence
  920. dSetDebugHandler (&myDebug);
  921. dRandSetSeed (seed);
  922. if (setjmp (jump_buffer)) {
  923. printf ("\tFAILED (1)\n");
  924. }
  925. else {
  926. for (i=1; i<49; i++) {
  927. dMakeRandomMatrix (A,i,i+1,1.0);
  928. mc.nextMatrix (A,i,i+1,0,"A%d",i);
  929. }
  930. mc.end();
  931. printf ("\tpassed (1)\n");
  932. }
  933. dSetDebugHandler (orig_debug);
  934. // test broken sequences (with matrix error)
  935. dRandSetSeed (seed);
  936. volatile int passcount = 0;
  937. for (i=1; i<49; i++) {
  938. if (setjmp (jump_buffer)) {
  939. passcount++;
  940. }
  941. else {
  942. dSetDebugHandler (&myDebug);
  943. dMakeRandomMatrix (A,i,i+1,1.0);
  944. A[(i-1)*dPAD(i+1)+i] += REAL(0.01);
  945. mc.nextMatrix (A,i,i+1,0,"A%d",i);
  946. dSetDebugHandler (orig_debug);
  947. }
  948. }
  949. mc.end();
  950. printf ("\t%s (2)\n",(passcount == 48) ? "passed" : "FAILED");
  951. // test broken sequences (with name error)
  952. dRandSetSeed (seed);
  953. passcount = 0;
  954. for (i=1; i<49; i++) {
  955. if (setjmp (jump_buffer)) {
  956. passcount++;
  957. }
  958. else {
  959. dSetDebugHandler (&myDebug);
  960. dMakeRandomMatrix (A,i,i+1,1.0);
  961. mc.nextMatrix (A,i,i+1,0,"B%d",i);
  962. dSetDebugHandler (orig_debug);
  963. }
  964. }
  965. mc.end();
  966. printf ("\t%s (3)\n",(passcount == 48) ? "passed" : "FAILED");
  967. // test identical sequence again
  968. dSetDebugHandler (&myDebug);
  969. dRandSetSeed (seed);
  970. if (setjmp (jump_buffer)) {
  971. printf ("\tFAILED (4)\n");
  972. }
  973. else {
  974. for (i=1; i<49; i++) {
  975. dMakeRandomMatrix (A,i,i+1,1.0);
  976. mc.nextMatrix (A,i,i+1,0,"A%d",i);
  977. }
  978. mc.end();
  979. printf ("\tpassed (4)\n");
  980. }
  981. dSetDebugHandler (orig_debug);
  982. }
  983. //****************************************************************************
  984. // internal unit tests
  985. extern "C" void dTestDataStructures();
  986. extern "C" void dTestMatrixComparison();
  987. extern "C" int dTestSolveLCP();
  988. int main()
  989. {
  990. dInitODE();
  991. testRandomNumberGenerator();
  992. testInfinity();
  993. testPad();
  994. testCrossProduct();
  995. testSetZero();
  996. testNormalize3();
  997. //testReorthonormalize(); ... not any more
  998. testPlaneSpace();
  999. testMatrixMultiply();
  1000. testSmallMatrixMultiply();
  1001. testCholeskyFactorization();
  1002. testCholeskySolve();
  1003. testInvertPDMatrix();
  1004. testIsPositiveDefinite();
  1005. testFastLDLTFactorization();
  1006. testSolveLDLT();
  1007. testLDLTAddTL();
  1008. testLDLTRemove();
  1009. testMassFunctions();
  1010. testRtoQandQtoR();
  1011. testQuaternionMultiply();
  1012. testRotationFunctions();
  1013. dTestMatrixComparison();
  1014. dTestSolveLCP();
  1015. // dTestDataStructures();
  1016. dCloseODE();
  1017. return 0;
  1018. }