demo_ode.cpp 40 KB

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