demo_ode.cpp 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163
  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. dReal A[MSIZE4*MSIZE], B[MSIZE4*MSIZE], C[MSIZE4*MSIZE], diff;
  266. HEADER;
  267. dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
  268. dMultiply2 (B,A,A,MSIZE,MSIZE,MSIZE);
  269. memcpy (A,B,MSIZE4*MSIZE*sizeof(dReal));
  270. if (dFactorCholesky (B,MSIZE)) printf ("\tpassed (1)\n");
  271. else printf ("\tFAILED (1)\n");
  272. dClearUpperTriangle (B,MSIZE);
  273. dMultiply2 (C,B,B,MSIZE,MSIZE,MSIZE);
  274. diff = dMaxDifference(A,C,MSIZE,MSIZE);
  275. printf ("\tmaximum difference = %.6e - %s (2)\n",diff,
  276. diff > tol ? "FAILED" : "passed");
  277. }
  278. void testCholeskySolve()
  279. {
  280. dReal A[MSIZE4*MSIZE], L[MSIZE4*MSIZE], b[MSIZE],x[MSIZE],btest[MSIZE],diff;
  281. HEADER;
  282. // get A,L = PD matrix
  283. dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
  284. dMultiply2 (L,A,A,MSIZE,MSIZE,MSIZE);
  285. memcpy (A,L,MSIZE4*MSIZE*sizeof(dReal));
  286. // get b,x = right hand side
  287. dMakeRandomMatrix (b,MSIZE,1,1.0);
  288. memcpy (x,b,MSIZE*sizeof(dReal));
  289. // factor L
  290. if (dFactorCholesky (L,MSIZE)) printf ("\tpassed (1)\n");
  291. else printf ("\tFAILED (1)\n");
  292. dClearUpperTriangle (L,MSIZE);
  293. // solve A*x = b
  294. dSolveCholesky (L,x,MSIZE);
  295. // compute A*x and compare it with b
  296. dMultiply2 (btest,A,x,MSIZE,MSIZE,1);
  297. diff = dMaxDifference(b,btest,MSIZE,1);
  298. printf ("\tmaximum difference = %.6e - %s (2)\n",diff,
  299. diff > tol ? "FAILED" : "passed");
  300. }
  301. void testInvertPDMatrix()
  302. {
  303. int i,j,ok;
  304. dReal A[MSIZE4*MSIZE], Ainv[MSIZE4*MSIZE], I[MSIZE4*MSIZE];
  305. HEADER;
  306. dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
  307. dMultiply2 (Ainv,A,A,MSIZE,MSIZE,MSIZE);
  308. memcpy (A,Ainv,MSIZE4*MSIZE*sizeof(dReal));
  309. dSetZero (Ainv,MSIZE4*MSIZE);
  310. if (dInvertPDMatrix (A,Ainv,MSIZE))
  311. printf ("\tpassed (1)\n"); else printf ("\tFAILED (1)\n");
  312. dMultiply0 (I,A,Ainv,MSIZE,MSIZE,MSIZE);
  313. // compare with identity
  314. ok = 1;
  315. for (i=0; i<MSIZE; i++) {
  316. for (j=0; j<MSIZE; j++) {
  317. if (i != j) if (cmp (I[i*MSIZE4+j],0.0)==0) ok = 0;
  318. }
  319. }
  320. for (i=0; i<MSIZE; i++) {
  321. if (cmp (I[i*MSIZE4+i],1.0)==0) ok = 0;
  322. }
  323. if (ok) printf ("\tpassed (2)\n"); else printf ("\tFAILED (2)\n");
  324. }
  325. void testIsPositiveDefinite()
  326. {
  327. dReal A[MSIZE4*MSIZE], B[MSIZE4*MSIZE];
  328. HEADER;
  329. dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
  330. dMultiply2 (B,A,A,MSIZE,MSIZE,MSIZE);
  331. printf ("\t%s\n",dIsPositiveDefinite(A,MSIZE) ? "FAILED (1)":"passed (1)");
  332. printf ("\t%s\n",dIsPositiveDefinite(B,MSIZE) ? "passed (2)":"FAILED (2)");
  333. }
  334. void testFastLDLTFactorization()
  335. {
  336. int i,j;
  337. dReal A[MSIZE4*MSIZE], L[MSIZE4*MSIZE], DL[MSIZE4*MSIZE],
  338. ATEST[MSIZE4*MSIZE], d[MSIZE], diff;
  339. HEADER;
  340. dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
  341. dMultiply2 (L,A,A,MSIZE,MSIZE,MSIZE);
  342. memcpy (A,L,MSIZE4*MSIZE*sizeof(dReal));
  343. dFactorLDLT (L,d,MSIZE,MSIZE4);
  344. dClearUpperTriangle (L,MSIZE);
  345. for (i=0; i<MSIZE; i++) L[i*MSIZE4+i] = 1.0;
  346. dSetZero (DL,MSIZE4*MSIZE);
  347. for (i=0; i<MSIZE; i++) {
  348. for (j=0; j<MSIZE; j++) DL[i*MSIZE4+j] = L[i*MSIZE4+j] / d[j];
  349. }
  350. dMultiply2 (ATEST,L,DL,MSIZE,MSIZE,MSIZE);
  351. diff = dMaxDifference(A,ATEST,MSIZE,MSIZE);
  352. printf ("\tmaximum difference = %.6e - %s\n",diff,
  353. diff > tol ? "FAILED" : "passed");
  354. }
  355. void testSolveLDLT()
  356. {
  357. dReal A[MSIZE4*MSIZE], L[MSIZE4*MSIZE], d[MSIZE], x[MSIZE],
  358. b[MSIZE], btest[MSIZE], diff;
  359. HEADER;
  360. dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
  361. dMultiply2 (L,A,A,MSIZE,MSIZE,MSIZE);
  362. memcpy (A,L,MSIZE4*MSIZE*sizeof(dReal));
  363. dMakeRandomMatrix (b,MSIZE,1,1.0);
  364. memcpy (x,b,MSIZE*sizeof(dReal));
  365. dFactorLDLT (L,d,MSIZE,MSIZE4);
  366. dSolveLDLT (L,d,x,MSIZE,MSIZE4);
  367. dMultiply2 (btest,A,x,MSIZE,MSIZE,1);
  368. diff = dMaxDifference(b,btest,MSIZE,1);
  369. printf ("\tmaximum difference = %.6e - %s\n",diff,
  370. diff > tol ? "FAILED" : "passed");
  371. }
  372. void testLDLTAddTL()
  373. {
  374. int i,j;
  375. dReal A[MSIZE4*MSIZE], L[MSIZE4*MSIZE], d[MSIZE], a[MSIZE],
  376. DL[MSIZE4*MSIZE], ATEST[MSIZE4*MSIZE], diff;
  377. HEADER;
  378. dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
  379. dMultiply2 (L,A,A,MSIZE,MSIZE,MSIZE);
  380. memcpy (A,L,MSIZE4*MSIZE*sizeof(dReal));
  381. dFactorLDLT (L,d,MSIZE,MSIZE4);
  382. // delete first row and column of factorization
  383. for (i=0; i<MSIZE; i++) a[i] = -A[i*MSIZE4];
  384. a[0] += 1;
  385. dLDLTAddTL (L,d,a,MSIZE,MSIZE4);
  386. for (i=1; i<MSIZE; i++) L[i*MSIZE4] = 0;
  387. d[0] = 1;
  388. // get modified L*D*L'
  389. dClearUpperTriangle (L,MSIZE);
  390. for (i=0; i<MSIZE; i++) L[i*MSIZE4+i] = 1.0;
  391. dSetZero (DL,MSIZE4*MSIZE);
  392. for (i=0; i<MSIZE; i++) {
  393. for (j=0; j<MSIZE; j++) DL[i*MSIZE4+j] = L[i*MSIZE4+j] / d[j];
  394. }
  395. dMultiply2 (ATEST,L,DL,MSIZE,MSIZE,MSIZE);
  396. // compare it to A with its first row/column removed
  397. for (i=1; i<MSIZE; i++) A[i*MSIZE4] = A[i] = 0;
  398. A[0] = 1;
  399. diff = dMaxDifference(A,ATEST,MSIZE,MSIZE);
  400. printf ("\tmaximum difference = %.6e - %s\n",diff,
  401. diff > tol ? "FAILED" : "passed");
  402. }
  403. void testLDLTRemove()
  404. {
  405. int i,j,r,p[MSIZE];
  406. dReal A[MSIZE4*MSIZE], L[MSIZE4*MSIZE], d[MSIZE],
  407. L2[MSIZE4*MSIZE], d2[MSIZE], DL2[MSIZE4*MSIZE],
  408. Atest1[MSIZE4*MSIZE], Atest2[MSIZE4*MSIZE], diff, maxdiff;
  409. HEADER;
  410. // make array of A row pointers
  411. dReal *Arows[MSIZE];
  412. for (i=0; i<MSIZE; i++) Arows[i] = A+i*MSIZE4;
  413. // fill permutation vector
  414. for (i=0; i<MSIZE; i++) p[i]=i;
  415. dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
  416. dMultiply2 (L,A,A,MSIZE,MSIZE,MSIZE);
  417. memcpy (A,L,MSIZE4*MSIZE*sizeof(dReal));
  418. dFactorLDLT (L,d,MSIZE,MSIZE4);
  419. maxdiff = 1e10;
  420. for (r=0; r<MSIZE; r++) {
  421. // get Atest1 = A with row/column r removed
  422. memcpy (Atest1,A,MSIZE4*MSIZE*sizeof(dReal));
  423. dRemoveRowCol (Atest1,MSIZE,MSIZE4,r);
  424. // test that the row/column removal worked
  425. int bad = 0;
  426. for (i=0; i<MSIZE; i++) {
  427. for (j=0; j<MSIZE; j++) {
  428. if (i != r && j != r) {
  429. int ii = i;
  430. int jj = j;
  431. if (ii >= r) ii--;
  432. if (jj >= r) jj--;
  433. if (A[i*MSIZE4+j] != Atest1[ii*MSIZE4+jj]) bad = 1;
  434. }
  435. }
  436. }
  437. if (bad) printf ("\trow/col removal FAILED for row %d\n",r);
  438. // zero out last row/column of Atest1
  439. for (i=0; i<MSIZE; i++) {
  440. Atest1[(MSIZE-1)*MSIZE4+i] = 0;
  441. Atest1[i*MSIZE4+MSIZE-1] = 0;
  442. }
  443. // get L2*D2*L2' = adjusted factorization to remove that row
  444. memcpy (L2,L,MSIZE4*MSIZE*sizeof(dReal));
  445. memcpy (d2,d,MSIZE*sizeof(dReal));
  446. dLDLTRemove (/*A*/ Arows,p,L2,d2,MSIZE,MSIZE,r,MSIZE4);
  447. // get Atest2 = L2*D2*L2'
  448. dClearUpperTriangle (L2,MSIZE);
  449. for (i=0; i<(MSIZE-1); i++) L2[i*MSIZE4+i] = 1.0;
  450. for (i=0; i<MSIZE; i++) L2[(MSIZE-1)*MSIZE4+i] = 0;
  451. d2[MSIZE-1] = 1;
  452. dSetZero (DL2,MSIZE4*MSIZE);
  453. for (i=0; i<(MSIZE-1); i++) {
  454. for (j=0; j<MSIZE-1; j++) DL2[i*MSIZE4+j] = L2[i*MSIZE4+j] / d2[j];
  455. }
  456. dMultiply2 (Atest2,L2,DL2,MSIZE,MSIZE,MSIZE);
  457. diff = dMaxDifference(Atest1,Atest2,MSIZE,MSIZE);
  458. if (diff < maxdiff) maxdiff = diff;
  459. /*
  460. dPrintMatrix (Atest1,MSIZE,MSIZE);
  461. printf ("\n");
  462. dPrintMatrix (Atest2,MSIZE,MSIZE);
  463. printf ("\n");
  464. */
  465. }
  466. printf ("\tmaximum difference = %.6e - %s\n",maxdiff,
  467. maxdiff > tol ? "FAILED" : "passed");
  468. }
  469. //****************************************************************************
  470. // test mass stuff
  471. #define NUMP 10 // number of particles
  472. void printMassParams (dMass *m)
  473. {
  474. printf ("mass = %.4f\n",m->mass);
  475. printf ("com = (%.4f,%.4f,%.4f)\n",m->c[0],m->c[1],m->c[2]);
  476. printf ("I = [ %10.4f %10.4f %10.4f ]\n"
  477. " [ %10.4f %10.4f %10.4f ]\n"
  478. " [ %10.4f %10.4f %10.4f ]\n",
  479. m->_I(0,0),m->_I(0,1),m->_I(0,2),
  480. m->_I(1,0),m->_I(1,1),m->_I(1,2),
  481. m->_I(2,0),m->_I(2,1),m->_I(2,2));
  482. }
  483. void compareMassParams (dMass *m1, dMass *m2, const char *msg)
  484. {
  485. int i,j,ok = 1;
  486. if (!(cmp(m1->mass,m2->mass) && cmp(m1->c[0],m2->c[0]) &&
  487. cmp(m1->c[1],m2->c[1]) && cmp(m1->c[2],m2->c[2])))
  488. ok = 0;
  489. for (i=0; i<3; i++) for (j=0; j<3; j++)
  490. if (cmp (m1->_I(i,j),m2->_I(i,j))==0) ok = 0;
  491. if (ok) printf ("\tpassed (%s)\n",msg); else printf ("\tFAILED (%s)\n",msg);
  492. }
  493. // compute the mass parameters of a particle set
  494. void computeMassParams (dMass *m, dReal q[NUMP][3], dReal pm[NUMP])
  495. {
  496. int i,j;
  497. dMassSetZero (m);
  498. for (i=0; i<NUMP; i++) {
  499. m->mass += pm[i];
  500. for (j=0; j<3; j++) m->c[j] += pm[i]*q[i][j];
  501. m->_I(0,0) += pm[i]*(q[i][1]*q[i][1] + q[i][2]*q[i][2]);
  502. m->_I(1,1) += pm[i]*(q[i][0]*q[i][0] + q[i][2]*q[i][2]);
  503. m->_I(2,2) += pm[i]*(q[i][0]*q[i][0] + q[i][1]*q[i][1]);
  504. m->_I(0,1) -= pm[i]*(q[i][0]*q[i][1]);
  505. m->_I(0,2) -= pm[i]*(q[i][0]*q[i][2]);
  506. m->_I(1,2) -= pm[i]*(q[i][1]*q[i][2]);
  507. }
  508. for (j=0; j<3; j++) m->c[j] /= m->mass;
  509. m->_I(1,0) = m->_I(0,1);
  510. m->_I(2,0) = m->_I(0,2);
  511. m->_I(2,1) = m->_I(1,2);
  512. }
  513. void testMassFunctions()
  514. {
  515. dMass m;
  516. int i,j;
  517. dReal q[NUMP][3]; // particle positions
  518. dReal pm[NUMP]; // particle masses
  519. dMass m1,m2;
  520. dMatrix3 R;
  521. HEADER;
  522. printf ("\t");
  523. dMassSetZero (&m);
  524. TRAP_MESSAGE (dMassSetParameters (&m,10, 0,0,0, 1,2,3, 4,5,6),
  525. printf (" FAILED (1)\n"), printf (" passed (1)\n"));
  526. printf ("\t");
  527. dMassSetZero (&m);
  528. TRAP_MESSAGE (dMassSetParameters (&m,10, 0.1,0.2,0.15, 3,5,14, 3.1,3.2,4),
  529. printf ("passed (2)\n") , printf (" FAILED (2)\n"));
  530. if (m.mass==10 && m.c[0]==REAL(0.1) && m.c[1]==REAL(0.2) &&
  531. m.c[2]==REAL(0.15) && m._I(0,0)==3 && m._I(1,1)==5 && m._I(2,2)==14 &&
  532. m._I(0,1)==REAL(3.1) && m._I(0,2)==REAL(3.2) && m._I(1,2)==4 &&
  533. m._I(1,0)==REAL(3.1) && m._I(2,0)==REAL(3.2) && m._I(2,1)==4)
  534. printf ("\tpassed (3)\n"); else printf ("\tFAILED (3)\n");
  535. dMassSetZero (&m);
  536. dMassSetSphere (&m,1.4, 0.86);
  537. if (cmp(m.mass,3.73002719949386) && m.c[0]==0 && m.c[1]==0 && m.c[2]==0 &&
  538. cmp(m._I(0,0),1.10349124669826) &&
  539. cmp(m._I(1,1),1.10349124669826) &&
  540. cmp(m._I(2,2),1.10349124669826) &&
  541. m._I(0,1)==0 && m._I(0,2)==0 && m._I(1,2)==0 &&
  542. m._I(1,0)==0 && m._I(2,0)==0 && m._I(2,1)==0)
  543. printf ("\tpassed (4)\n"); else printf ("\tFAILED (4)\n");
  544. dMassSetZero (&m);
  545. dMassSetCapsule (&m,1.3,1,0.76,1.53);
  546. if (cmp(m.mass,5.99961928996029) && m.c[0]==0 && m.c[1]==0 && m.c[2]==0 &&
  547. cmp(m._I(0,0),1.59461986077384) &&
  548. cmp(m._I(1,1),4.21878433864904) &&
  549. cmp(m._I(2,2),4.21878433864904) &&
  550. m._I(0,1)==0 && m._I(0,2)==0 && m._I(1,2)==0 &&
  551. m._I(1,0)==0 && m._I(2,0)==0 && m._I(2,1)==0)
  552. printf ("\tpassed (5)\n"); else printf ("\tFAILED (5)\n");
  553. dMassSetZero (&m);
  554. dMassSetBox (&m,0.27,3,4,5);
  555. if (cmp(m.mass,16.2) && m.c[0]==0 && m.c[1]==0 && m.c[2]==0 &&
  556. cmp(m._I(0,0),55.35) && cmp(m._I(1,1),45.9) && cmp(m._I(2,2),33.75) &&
  557. m._I(0,1)==0 && m._I(0,2)==0 && m._I(1,2)==0 &&
  558. m._I(1,0)==0 && m._I(2,0)==0 && m._I(2,1)==0)
  559. printf ("\tpassed (6)\n"); else printf ("\tFAILED (6)\n");
  560. // test dMassAdjust?
  561. // make random particles and compute the mass, COM and inertia, then
  562. // translate and repeat.
  563. for (i=0; i<NUMP; i++) {
  564. pm[i] = dRandReal()+0.5;
  565. for (j=0; j<3; j++) {
  566. q[i][j] = 2.0*(dRandReal()-0.5);
  567. }
  568. }
  569. computeMassParams (&m1,q,pm);
  570. memcpy (&m2,&m1,sizeof(dMass));
  571. dMassTranslate (&m2,1,2,-3);
  572. for (i=0; i<NUMP; i++) {
  573. q[i][0] += 1;
  574. q[i][1] += 2;
  575. q[i][2] -= 3;
  576. }
  577. computeMassParams (&m1,q,pm);
  578. compareMassParams (&m1,&m2,"7");
  579. // rotate the masses
  580. _R(0,0) = -0.87919618797635;
  581. _R(0,1) = 0.15278881840384;
  582. _R(0,2) = -0.45129772879842;
  583. _R(1,0) = -0.47307856232664;
  584. _R(1,1) = -0.39258064912909;
  585. _R(1,2) = 0.78871864932708;
  586. _R(2,0) = -0.05666336483842;
  587. _R(2,1) = 0.90693771059546;
  588. _R(2,2) = 0.41743652473765;
  589. dMassRotate (&m2,R);
  590. for (i=0; i<NUMP; i++) {
  591. dReal a[3];
  592. dMultiply0 (a,&_R(0,0),&q[i][0],3,3,1);
  593. q[i][0] = a[0];
  594. q[i][1] = a[1];
  595. q[i][2] = a[2];
  596. }
  597. computeMassParams (&m1,q,pm);
  598. compareMassParams (&m1,&m2,"8");
  599. }
  600. //****************************************************************************
  601. // test rotation stuff
  602. void makeRandomRotation (dMatrix3 R)
  603. {
  604. dReal *u1 = R, *u2=R+4, *u3=R+8;
  605. dMakeRandomVector (u1,3,1.0);
  606. dNormalize3 (u1);
  607. dMakeRandomVector (u2,3,1.0);
  608. dReal d = dCalcVectorDot3(u1,u2);
  609. u2[0] -= d*u1[0];
  610. u2[1] -= d*u1[1];
  611. u2[2] -= d*u1[2];
  612. dNormalize3(u2);
  613. dCalcVectorCross3(u3,u1,u2);
  614. }
  615. void testRtoQandQtoR()
  616. {
  617. HEADER;
  618. dMatrix3 R,I,R2;
  619. dQuaternion q;
  620. int i;
  621. // test makeRandomRotation()
  622. makeRandomRotation (R);
  623. dMultiply2 (I,R,R,3,3,3);
  624. printf ("\tmakeRandomRotation() - %s (1)\n",
  625. cmpIdentityMat3(I) ? "passed" : "FAILED");
  626. // test QtoR() on random normalized quaternions
  627. int ok = 1;
  628. for (i=0; i<100; i++) {
  629. dMakeRandomVector (q,4,1.0);
  630. dNormalize4 (q);
  631. dQtoR (q,R);
  632. dMultiply2 (I,R,R,3,3,3);
  633. if (cmpIdentityMat3(I)==0) ok = 0;
  634. }
  635. printf ("\tQtoR() orthonormality %s (2)\n", ok ? "passed" : "FAILED");
  636. // test R -> Q -> R works
  637. dReal maxdiff=0;
  638. for (i=0; i<100; i++) {
  639. makeRandomRotation (R);
  640. dRtoQ (R,q);
  641. dQtoR (q,R2);
  642. dReal diff = dMaxDifference (R,R2,3,3);
  643. if (diff > maxdiff) maxdiff = diff;
  644. }
  645. printf ("\tmaximum difference = %e - %s (3)\n",maxdiff,
  646. (maxdiff > tol) ? "FAILED" : "passed");
  647. }
  648. void testQuaternionMultiply()
  649. {
  650. HEADER;
  651. dMatrix3 RA,RB,RC,Rtest;
  652. dQuaternion qa,qb,qc;
  653. dReal diff,maxdiff=0;
  654. for (int i=0; i<100; i++) {
  655. makeRandomRotation (RB);
  656. makeRandomRotation (RC);
  657. dRtoQ (RB,qb);
  658. dRtoQ (RC,qc);
  659. dMultiply0 (RA,RB,RC,3,3,3);
  660. dQMultiply0 (qa,qb,qc);
  661. dQtoR (qa,Rtest);
  662. diff = dMaxDifference (Rtest,RA,3,3);
  663. if (diff > maxdiff) maxdiff = diff;
  664. dMultiply1 (RA,RB,RC,3,3,3);
  665. dQMultiply1 (qa,qb,qc);
  666. dQtoR (qa,Rtest);
  667. diff = dMaxDifference (Rtest,RA,3,3);
  668. if (diff > maxdiff) maxdiff = diff;
  669. dMultiply2 (RA,RB,RC,3,3,3);
  670. dQMultiply2 (qa,qb,qc);
  671. dQtoR (qa,Rtest);
  672. diff = dMaxDifference (Rtest,RA,3,3);
  673. if (diff > maxdiff) maxdiff = diff;
  674. dMultiply0 (RA,RC,RB,3,3,3);
  675. transpose3x3 (RA);
  676. dQMultiply3 (qa,qb,qc);
  677. dQtoR (qa,Rtest);
  678. diff = dMaxDifference (Rtest,RA,3,3);
  679. if (diff > maxdiff) maxdiff = diff;
  680. }
  681. printf ("\tmaximum difference = %e - %s\n",maxdiff,
  682. (maxdiff > tol) ? "FAILED" : "passed");
  683. }
  684. void testRotationFunctions()
  685. {
  686. dMatrix3 R1;
  687. HEADER;
  688. printf ("\tdRSetIdentity - ");
  689. dMakeRandomMatrix (R1,3,3,1.0);
  690. dRSetIdentity (R1);
  691. if (cmpIdentityMat3(R1)) printf ("passed\n"); else printf ("FAILED\n");
  692. printf ("\tdRFromAxisAndAngle - ");
  693. printf ("\n");
  694. printf ("\tdRFromEulerAngles - ");
  695. printf ("\n");
  696. printf ("\tdRFrom2Axes - ");
  697. printf ("\n");
  698. }
  699. //****************************************************************************
  700. #include <assert.h>
  701. template<class T>
  702. class simplevector
  703. {
  704. private:
  705. int n;
  706. int max;
  707. T* data;
  708. public:
  709. simplevector() { initialize(); }
  710. ~simplevector() { finalize(); }
  711. T& operator[](int i) { assert(i>=0 && i<n); return data[i]; }
  712. const T& operator[](int i) const { assert(i>=0 && i<n); return data[i]; }
  713. void push_back(const T& elem)
  714. {
  715. if (n == max)
  716. {
  717. max *= 2;
  718. T* newdata = new T[max];
  719. memcpy(newdata, data, sizeof(T)*n);
  720. delete[] data;
  721. data = newdata;
  722. }
  723. data[n++] = elem;
  724. }
  725. int size() const { return n; }
  726. void clear() { finalize(); initialize(); }
  727. private:
  728. void finalize() { delete[] data; }
  729. void initialize() { data = new T[32]; max = 32; n = 0; }
  730. };
  731. // matrix header on the stack
  732. class dMatrixComparison {
  733. struct dMatInfo;
  734. simplevector<dMatInfo*> mat;
  735. int afterfirst,index;
  736. public:
  737. dMatrixComparison();
  738. ~dMatrixComparison();
  739. dReal nextMatrix (dReal *A, int n, int m, int lower_tri, const char *name, ...);
  740. // add a new n*m matrix A to the sequence. the name of the matrix is given
  741. // by the printf-style arguments (name,...). if this is the first sequence
  742. // then this object will simply record the matrices and return 0.
  743. // if this the second or subsequent sequence then this object will compare
  744. // the matrices with the first sequence, and report any differences.
  745. // the matrix error will be returned. if `lower_tri' is 1 then only the
  746. // lower triangle of the matrix (including the diagonal) will be compared
  747. // (the matrix must be square).
  748. void end();
  749. // end a sequence.
  750. void reset();
  751. // restarts the object, so the next sequence will be the first sequence.
  752. void dump();
  753. // print out info about all the matrices in the sequence
  754. };
  755. struct dMatrixComparison::dMatInfo {
  756. int n,m; // size of matrix
  757. char name[128]; // name of the matrix
  758. dReal *data; // matrix data
  759. int size; // size of `data'
  760. };
  761. dMatrixComparison::dMatrixComparison()
  762. {
  763. afterfirst = 0;
  764. index = 0;
  765. }
  766. dMatrixComparison::~dMatrixComparison()
  767. {
  768. reset();
  769. }
  770. dReal dMatrixComparison::nextMatrix (dReal *A, int n, int m, int lower_tri,
  771. const char *name, ...)
  772. {
  773. if (A==0 || n < 1 || m < 1 || name==0) dDebug (0,"bad args to nextMatrix");
  774. int num = n*dPAD(m);
  775. if (afterfirst==0) {
  776. dMatInfo *mi = (dMatInfo*) dAlloc (sizeof(dMatInfo));
  777. mi->n = n;
  778. mi->m = m;
  779. mi->size = num * sizeof(dReal);
  780. mi->data = (dReal*) dAlloc (mi->size);
  781. memcpy (mi->data,A,mi->size);
  782. va_list ap;
  783. va_start (ap,name);
  784. vsprintf (mi->name,name,ap);
  785. va_end (ap);
  786. if (strlen(mi->name) >= sizeof (mi->name)) dDebug (0,"name too long");
  787. mat.push_back(mi);
  788. return 0;
  789. }
  790. else {
  791. if (lower_tri && n != m)
  792. dDebug (0,"dMatrixComparison, lower triangular matrix must be square");
  793. if (index >= mat.size()) dDebug (0,"dMatrixComparison, too many matrices");
  794. dMatInfo *mp = mat[index];
  795. index++;
  796. dMatInfo mi;
  797. va_list ap;
  798. va_start (ap,name);
  799. vsprintf (mi.name,name,ap);
  800. va_end (ap);
  801. if (strlen(mi.name) >= sizeof (mi.name)) dDebug (0,"name too long");
  802. if (strcmp(mp->name,mi.name) != 0)
  803. dDebug (0,"dMatrixComparison, name mismatch (\"%s\" and \"%s\")",
  804. mp->name,mi.name);
  805. if (mp->n != n || mp->m != m)
  806. dDebug (0,"dMatrixComparison, size mismatch (%dx%d and %dx%d)",
  807. mp->n,mp->m,n,m);
  808. dReal maxdiff;
  809. if (lower_tri) {
  810. maxdiff = dMaxDifferenceLowerTriangle (A,mp->data,n);
  811. }
  812. else {
  813. maxdiff = dMaxDifference (A,mp->data,n,m);
  814. }
  815. if (maxdiff > tol)
  816. dDebug (0,"dMatrixComparison, matrix error (size=%dx%d, name=\"%s\", "
  817. "error=%.4e)",n,m,mi.name,maxdiff);
  818. return maxdiff;
  819. }
  820. }
  821. void dMatrixComparison::end()
  822. {
  823. if (mat.size() <= 0) dDebug (0,"no matrices in sequence");
  824. afterfirst = 1;
  825. index = 0;
  826. }
  827. void dMatrixComparison::reset()
  828. {
  829. for (int i=0; i<mat.size(); i++) {
  830. dFree (mat[i]->data,mat[i]->size);
  831. dFree (mat[i],sizeof(dMatInfo));
  832. }
  833. mat.clear();
  834. afterfirst = 0;
  835. index = 0;
  836. }
  837. void dMatrixComparison::dump()
  838. {
  839. for (int i=0; i<mat.size(); i++)
  840. printf ("%d: %s (%dx%d)\n",i,mat[i]->name,mat[i]->n,mat[i]->m);
  841. }
  842. //****************************************************************************
  843. // unit test
  844. #include <setjmp.h>
  845. // static jmp_buf jump_buffer;
  846. static void myDebug (int num, const char *msg, va_list ap)
  847. {
  848. // printf ("(Error %d: ",num);
  849. // vprintf (msg,ap);
  850. // printf (")\n");
  851. longjmp (jump_buffer,1);
  852. }
  853. extern "C" void dTestMatrixComparison()
  854. {
  855. volatile int i;
  856. printf ("dTestMatrixComparison()\n");
  857. dMessageFunction *orig_debug = dGetDebugHandler();
  858. dMatrixComparison mc;
  859. dReal A[50*50];
  860. // make first sequence
  861. unsigned long seed = dRandGetSeed();
  862. for (i=1; i<49; i++) {
  863. dMakeRandomMatrix (A,i,i+1,1.0);
  864. mc.nextMatrix (A,i,i+1,0,"A%d",i);
  865. }
  866. mc.end();
  867. //mc.dump();
  868. // test identical sequence
  869. dSetDebugHandler (&myDebug);
  870. dRandSetSeed (seed);
  871. if (setjmp (jump_buffer)) {
  872. printf ("\tFAILED (1)\n");
  873. }
  874. else {
  875. for (i=1; i<49; i++) {
  876. dMakeRandomMatrix (A,i,i+1,1.0);
  877. mc.nextMatrix (A,i,i+1,0,"A%d",i);
  878. }
  879. mc.end();
  880. printf ("\tpassed (1)\n");
  881. }
  882. dSetDebugHandler (orig_debug);
  883. // test broken sequences (with matrix error)
  884. dRandSetSeed (seed);
  885. volatile int passcount = 0;
  886. for (i=1; i<49; i++) {
  887. if (setjmp (jump_buffer)) {
  888. passcount++;
  889. }
  890. else {
  891. dSetDebugHandler (&myDebug);
  892. dMakeRandomMatrix (A,i,i+1,1.0);
  893. A[(i-1)*dPAD(i+1)+i] += REAL(0.01);
  894. mc.nextMatrix (A,i,i+1,0,"A%d",i);
  895. dSetDebugHandler (orig_debug);
  896. }
  897. }
  898. mc.end();
  899. printf ("\t%s (2)\n",(passcount == 48) ? "passed" : "FAILED");
  900. // test broken sequences (with name error)
  901. dRandSetSeed (seed);
  902. passcount = 0;
  903. for (i=1; i<49; i++) {
  904. if (setjmp (jump_buffer)) {
  905. passcount++;
  906. }
  907. else {
  908. dSetDebugHandler (&myDebug);
  909. dMakeRandomMatrix (A,i,i+1,1.0);
  910. mc.nextMatrix (A,i,i+1,0,"B%d",i);
  911. dSetDebugHandler (orig_debug);
  912. }
  913. }
  914. mc.end();
  915. printf ("\t%s (3)\n",(passcount == 48) ? "passed" : "FAILED");
  916. // test identical sequence again
  917. dSetDebugHandler (&myDebug);
  918. dRandSetSeed (seed);
  919. if (setjmp (jump_buffer)) {
  920. printf ("\tFAILED (4)\n");
  921. }
  922. else {
  923. for (i=1; i<49; i++) {
  924. dMakeRandomMatrix (A,i,i+1,1.0);
  925. mc.nextMatrix (A,i,i+1,0,"A%d",i);
  926. }
  927. mc.end();
  928. printf ("\tpassed (4)\n");
  929. }
  930. dSetDebugHandler (orig_debug);
  931. }
  932. //****************************************************************************
  933. // internal unit tests
  934. extern "C" void dTestDataStructures();
  935. extern "C" void dTestMatrixComparison();
  936. extern "C" int dTestSolveLCP();
  937. int main()
  938. {
  939. dInitODE();
  940. testRandomNumberGenerator();
  941. testInfinity();
  942. testPad();
  943. testCrossProduct();
  944. testSetZero();
  945. testNormalize3();
  946. //testReorthonormalize(); ... not any more
  947. testPlaneSpace();
  948. testMatrixMultiply();
  949. testSmallMatrixMultiply();
  950. testCholeskyFactorization();
  951. testCholeskySolve();
  952. testInvertPDMatrix();
  953. testIsPositiveDefinite();
  954. testFastLDLTFactorization();
  955. testSolveLDLT();
  956. testLDLTAddTL();
  957. testLDLTRemove();
  958. testMassFunctions();
  959. testRtoQandQtoR();
  960. testQuaternionMultiply();
  961. testRotationFunctions();
  962. dTestMatrixComparison();
  963. dTestSolveLCP();
  964. // dTestDataStructures();
  965. dCloseODE();
  966. return 0;
  967. }