btMatrixX.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. /*
  2. Bullet Continuous Collision Detection and Physics Library
  3. Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
  4. This software is provided 'as-is', without any express or implied warranty.
  5. In no event will the authors be held liable for any damages arising from the use of this software.
  6. Permission is granted to anyone to use this software for any purpose,
  7. including commercial applications, and to alter it and redistribute it freely,
  8. subject to the following restrictions:
  9. 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
  10. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  11. 3. This notice may not be removed or altered from any source distribution.
  12. */
  13. ///original version written by Erwin Coumans, October 2013
  14. #ifndef BT_MATRIX_X_H
  15. #define BT_MATRIX_X_H
  16. #include "bullet/LinearMath/btQuickprof.h"
  17. #include "bullet/LinearMath/btAlignedObjectArray.h"
  18. class btIntSortPredicate
  19. {
  20. public:
  21. bool operator() ( const int& a, const int& b ) const
  22. {
  23. return a < b;
  24. }
  25. };
  26. template <typename T>
  27. struct btMatrixX
  28. {
  29. int m_rows;
  30. int m_cols;
  31. int m_operations;
  32. int m_resizeOperations;
  33. int m_setElemOperations;
  34. btAlignedObjectArray<T> m_storage;
  35. btAlignedObjectArray< btAlignedObjectArray<int> > m_rowNonZeroElements1;
  36. btAlignedObjectArray< btAlignedObjectArray<int> > m_colNonZeroElements;
  37. T* getBufferPointerWritable()
  38. {
  39. return m_storage.size() ? &m_storage[0] : 0;
  40. }
  41. const T* getBufferPointer() const
  42. {
  43. return m_storage.size() ? &m_storage[0] : 0;
  44. }
  45. btMatrixX()
  46. :m_rows(0),
  47. m_cols(0),
  48. m_operations(0),
  49. m_resizeOperations(0),
  50. m_setElemOperations(0)
  51. {
  52. }
  53. btMatrixX(int rows,int cols)
  54. :m_rows(rows),
  55. m_cols(cols),
  56. m_operations(0),
  57. m_resizeOperations(0),
  58. m_setElemOperations(0)
  59. {
  60. resize(rows,cols);
  61. }
  62. void resize(int rows, int cols)
  63. {
  64. m_resizeOperations++;
  65. m_rows = rows;
  66. m_cols = cols;
  67. {
  68. BT_PROFILE("m_storage.resize");
  69. m_storage.resize(rows*cols);
  70. }
  71. clearSparseInfo();
  72. }
  73. int cols() const
  74. {
  75. return m_cols;
  76. }
  77. int rows() const
  78. {
  79. return m_rows;
  80. }
  81. ///we don't want this read/write operator(), because we cannot keep track of non-zero elements, use setElem instead
  82. /*T& operator() (int row,int col)
  83. {
  84. return m_storage[col*m_rows+row];
  85. }
  86. */
  87. void addElem(int row,int col, T val)
  88. {
  89. if (val)
  90. {
  91. if (m_storage[col+row*m_cols]==0.f)
  92. {
  93. setElem(row,col,val);
  94. } else
  95. {
  96. m_storage[row*m_cols+col] += val;
  97. }
  98. }
  99. }
  100. void copyLowerToUpperTriangle()
  101. {
  102. int count=0;
  103. for (int row=0;row<m_rowNonZeroElements1.size();row++)
  104. {
  105. for (int j=0;j<m_rowNonZeroElements1[row].size();j++)
  106. {
  107. int col = m_rowNonZeroElements1[row][j];
  108. setElem(col,row, (*this)(row,col));
  109. count++;
  110. }
  111. }
  112. //printf("copyLowerToUpperTriangle copied %d elements out of %dx%d=%d\n", count,rows(),cols(),cols()*rows());
  113. }
  114. void setElem(int row,int col, T val)
  115. {
  116. m_setElemOperations++;
  117. if (val)
  118. {
  119. if (m_storage[col+row*m_cols]==0.f)
  120. {
  121. m_rowNonZeroElements1[row].push_back(col);
  122. m_colNonZeroElements[col].push_back(row);
  123. }
  124. m_storage[row*m_cols+col] = val;
  125. }
  126. }
  127. const T& operator() (int row,int col) const
  128. {
  129. return m_storage[col+row*m_cols];
  130. }
  131. void clearSparseInfo()
  132. {
  133. BT_PROFILE("clearSparseInfo=0");
  134. m_rowNonZeroElements1.resize(m_rows);
  135. m_colNonZeroElements.resize(m_cols);
  136. for (int i=0;i<m_rows;i++)
  137. m_rowNonZeroElements1[i].resize(0);
  138. for (int j=0;j<m_cols;j++)
  139. m_colNonZeroElements[j].resize(0);
  140. }
  141. void setZero()
  142. {
  143. {
  144. BT_PROFILE("storage=0");
  145. btSetZero(&m_storage[0],m_storage.size());
  146. //memset(&m_storage[0],0,sizeof(T)*m_storage.size());
  147. //for (int i=0;i<m_storage.size();i++)
  148. // m_storage[i]=0;
  149. }
  150. {
  151. BT_PROFILE("clearSparseInfo=0");
  152. clearSparseInfo();
  153. }
  154. }
  155. void printMatrix(const char* msg)
  156. {
  157. printf("%s ---------------------\n",msg);
  158. for (int i=0;i<rows();i++)
  159. {
  160. printf("\n");
  161. for (int j=0;j<cols();j++)
  162. {
  163. printf("%2.1f\t",(*this)(i,j));
  164. }
  165. }
  166. printf("\n---------------------\n");
  167. }
  168. void printNumZeros(const char* msg)
  169. {
  170. printf("%s: ",msg);
  171. int numZeros = 0;
  172. for (int i=0;i<m_storage.size();i++)
  173. if (m_storage[i]==0)
  174. numZeros++;
  175. int total = m_cols*m_rows;
  176. int computedNonZero = total-numZeros;
  177. int nonZero = 0;
  178. for (int i=0;i<m_colNonZeroElements.size();i++)
  179. nonZero += m_colNonZeroElements[i].size();
  180. btAssert(computedNonZero==nonZero);
  181. if(computedNonZero!=nonZero)
  182. {
  183. printf("Error: computedNonZero=%d, but nonZero=%d\n",computedNonZero,nonZero);
  184. }
  185. //printf("%d numZeros out of %d (%f)\n",numZeros,m_cols*m_rows,numZeros/(m_cols*m_rows));
  186. printf("total %d, %d rows, %d cols, %d non-zeros (%f %)\n", total, rows(),cols(), nonZero,100.f*(T)nonZero/T(total));
  187. }
  188. /*
  189. void rowComputeNonZeroElements()
  190. {
  191. m_rowNonZeroElements1.resize(rows());
  192. for (int i=0;i<rows();i++)
  193. {
  194. m_rowNonZeroElements1[i].resize(0);
  195. for (int j=0;j<cols();j++)
  196. {
  197. if ((*this)(i,j)!=0.f)
  198. {
  199. m_rowNonZeroElements1[i].push_back(j);
  200. }
  201. }
  202. }
  203. }
  204. */
  205. btMatrixX transpose() const
  206. {
  207. //transpose is optimized for sparse matrices
  208. btMatrixX tr(m_cols,m_rows);
  209. tr.setZero();
  210. #if 0
  211. for (int i=0;i<m_cols;i++)
  212. for (int j=0;j<m_rows;j++)
  213. {
  214. T v = (*this)(j,i);
  215. if (v)
  216. {
  217. tr.setElem(i,j,v);
  218. }
  219. }
  220. #else
  221. for (int i=0;i<m_colNonZeroElements.size();i++)
  222. for (int h=0;h<m_colNonZeroElements[i].size();h++)
  223. {
  224. int j = m_colNonZeroElements[i][h];
  225. T v = (*this)(j,i);
  226. tr.setElem(i,j,v);
  227. }
  228. #endif
  229. return tr;
  230. }
  231. void sortRowIndexArrays()
  232. {
  233. for (int i=0;i<m_rowNonZeroElements1[i].size();i++)
  234. {
  235. m_rowNonZeroElements1[i].quickSort(btIntSortPredicate());
  236. }
  237. }
  238. void sortColIndexArrays()
  239. {
  240. for (int i=0;i<m_colNonZeroElements[i].size();i++)
  241. {
  242. m_colNonZeroElements[i].quickSort(btIntSortPredicate());
  243. }
  244. }
  245. btMatrixX operator*(const btMatrixX& other)
  246. {
  247. //btMatrixX*btMatrixX implementation, optimized for sparse matrices
  248. btAssert(cols() == other.rows());
  249. btMatrixX res(rows(),other.cols());
  250. res.setZero();
  251. // BT_PROFILE("btMatrixX mul");
  252. for (int j=0; j < res.cols(); ++j)
  253. {
  254. //int numZero=other.m_colNonZeroElements[j].size();
  255. //if (numZero)
  256. {
  257. for (int i=0; i < res.rows(); ++i)
  258. //for (int g = 0;g<m_colNonZeroElements[j].size();g++)
  259. {
  260. T dotProd=0;
  261. T dotProd2=0;
  262. int waste=0,waste2=0;
  263. bool doubleWalk = false;
  264. if (doubleWalk)
  265. {
  266. int numRows = m_rowNonZeroElements1[i].size();
  267. int numOtherCols = other.m_colNonZeroElements[j].size();
  268. for (int ii=0;ii<numRows;ii++)
  269. {
  270. int vThis=m_rowNonZeroElements1[i][ii];
  271. }
  272. for (int ii=0;ii<numOtherCols;ii++)
  273. {
  274. int vOther = other.m_colNonZeroElements[j][ii];
  275. }
  276. int indexRow = 0;
  277. int indexOtherCol = 0;
  278. while (indexRow < numRows && indexOtherCol < numOtherCols)
  279. {
  280. int vThis=m_rowNonZeroElements1[i][indexRow];
  281. int vOther = other.m_colNonZeroElements[j][indexOtherCol];
  282. if (vOther==vThis)
  283. {
  284. dotProd += (*this)(i,vThis) * other(vThis,j);
  285. }
  286. if (vThis<vOther)
  287. {
  288. indexRow++;
  289. } else
  290. {
  291. indexOtherCol++;
  292. }
  293. }
  294. } else
  295. {
  296. bool useOtherCol = true;
  297. if (other.m_colNonZeroElements[j].size() <m_rowNonZeroElements1[i].size())
  298. {
  299. useOtherCol=true;
  300. }
  301. if (!useOtherCol )
  302. {
  303. for (int q=0;q<other.m_colNonZeroElements[j].size();q++)
  304. {
  305. int v = other.m_colNonZeroElements[j][q];
  306. T w = (*this)(i,v);
  307. if (w!=0.f)
  308. {
  309. dotProd+=w*other(v,j);
  310. }
  311. }
  312. }
  313. else
  314. {
  315. for (int q=0;q<m_rowNonZeroElements1[i].size();q++)
  316. {
  317. int v=m_rowNonZeroElements1[i][q];
  318. T w = (*this)(i,v);
  319. if (other(v,j)!=0.f)
  320. {
  321. dotProd+=w*other(v,j);
  322. }
  323. }
  324. }
  325. }
  326. if (dotProd)
  327. res.setElem(i,j,dotProd);
  328. }
  329. }
  330. }
  331. return res;
  332. }
  333. // this assumes the 4th and 8th rows of B and C are zero.
  334. void multiplyAdd2_p8r (const btScalar *B, const btScalar *C, int numRows, int numRowsOther ,int row, int col)
  335. {
  336. const btScalar *bb = B;
  337. for ( int i = 0;i<numRows;i++)
  338. {
  339. const btScalar *cc = C;
  340. for ( int j = 0;j<numRowsOther;j++)
  341. {
  342. btScalar sum;
  343. sum = bb[0]*cc[0];
  344. sum += bb[1]*cc[1];
  345. sum += bb[2]*cc[2];
  346. sum += bb[4]*cc[4];
  347. sum += bb[5]*cc[5];
  348. sum += bb[6]*cc[6];
  349. addElem(row+i,col+j,sum);
  350. cc += 8;
  351. }
  352. bb += 8;
  353. }
  354. }
  355. void multiply2_p8r (const btScalar *B, const btScalar *C, int numRows, int numRowsOther, int row, int col)
  356. {
  357. btAssert (numRows>0 && numRowsOther>0 && B && C);
  358. const btScalar *bb = B;
  359. for ( int i = 0;i<numRows;i++)
  360. {
  361. const btScalar *cc = C;
  362. for ( int j = 0;j<numRowsOther;j++)
  363. {
  364. btScalar sum;
  365. sum = bb[0]*cc[0];
  366. sum += bb[1]*cc[1];
  367. sum += bb[2]*cc[2];
  368. sum += bb[4]*cc[4];
  369. sum += bb[5]*cc[5];
  370. sum += bb[6]*cc[6];
  371. setElem(row+i,col+j,sum);
  372. cc += 8;
  373. }
  374. bb += 8;
  375. }
  376. }
  377. };
  378. template <typename T>
  379. struct btVectorX
  380. {
  381. btAlignedObjectArray<T> m_storage;
  382. btVectorX()
  383. {
  384. }
  385. btVectorX(int numRows)
  386. {
  387. m_storage.resize(numRows);
  388. }
  389. void resize(int rows)
  390. {
  391. m_storage.resize(rows);
  392. }
  393. int cols() const
  394. {
  395. return 1;
  396. }
  397. int rows() const
  398. {
  399. return m_storage.size();
  400. }
  401. int size() const
  402. {
  403. return rows();
  404. }
  405. void setZero()
  406. {
  407. // for (int i=0;i<m_storage.size();i++)
  408. // m_storage[i]=0;
  409. //memset(&m_storage[0],0,sizeof(T)*m_storage.size());
  410. btSetZero(&m_storage[0],m_storage.size());
  411. }
  412. const T& operator[] (int index) const
  413. {
  414. return m_storage[index];
  415. }
  416. T& operator[] (int index)
  417. {
  418. return m_storage[index];
  419. }
  420. T* getBufferPointerWritable()
  421. {
  422. return m_storage.size() ? &m_storage[0] : 0;
  423. }
  424. const T* getBufferPointer() const
  425. {
  426. return m_storage.size() ? &m_storage[0] : 0;
  427. }
  428. };
  429. /*
  430. template <typename T>
  431. void setElem(btMatrixX<T>& mat, int row, int col, T val)
  432. {
  433. mat.setElem(row,col,val);
  434. }
  435. */
  436. typedef btMatrixX<float> btMatrixXf;
  437. typedef btVectorX<float> btVectorXf;
  438. typedef btMatrixX<double> btMatrixXd;
  439. typedef btVectorX<double> btVectorXd;
  440. inline void setElem(btMatrixXd& mat, int row, int col, double val)
  441. {
  442. mat.setElem(row,col,val);
  443. }
  444. inline void setElem(btMatrixXf& mat, int row, int col, float val)
  445. {
  446. mat.setElem(row,col,val);
  447. }
  448. #ifdef BT_USE_DOUBLE_PRECISION
  449. #define btVectorXu btVectorXd
  450. #define btMatrixXu btMatrixXd
  451. #else
  452. #define btVectorXu btVectorXf
  453. #define btMatrixXu btMatrixXf
  454. #endif //BT_USE_DOUBLE_PRECISION
  455. #endif//BT_MATRIX_H_H