btMatrixX.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  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 "LinearMath/btQuickprof.h"
  17. #include "LinearMath/btAlignedObjectArray.h"
  18. #include <stdio.h>
  19. //#define BT_DEBUG_OSTREAM
  20. #ifdef BT_DEBUG_OSTREAM
  21. #include <iostream>
  22. #include <iomanip> // std::setw
  23. #endif //BT_DEBUG_OSTREAM
  24. class btIntSortPredicate
  25. {
  26. public:
  27. bool operator()(const int& a, const int& b) const
  28. {
  29. return a < b;
  30. }
  31. };
  32. template <typename T>
  33. struct btVectorX
  34. {
  35. btAlignedObjectArray<T> m_storage;
  36. btVectorX()
  37. {
  38. }
  39. btVectorX(int numRows)
  40. {
  41. m_storage.resize(numRows);
  42. }
  43. void resize(int rows)
  44. {
  45. m_storage.resize(rows);
  46. }
  47. int cols() const
  48. {
  49. return 1;
  50. }
  51. int rows() const
  52. {
  53. return m_storage.size();
  54. }
  55. int size() const
  56. {
  57. return rows();
  58. }
  59. T nrm2() const
  60. {
  61. T norm = T(0);
  62. int nn = rows();
  63. {
  64. if (nn == 1)
  65. {
  66. norm = btFabs((*this)[0]);
  67. }
  68. else
  69. {
  70. T scale = 0.0;
  71. T ssq = 1.0;
  72. /* The following loop is equivalent to this call to the LAPACK
  73. auxiliary routine: CALL SLASSQ( N, X, INCX, SCALE, SSQ ) */
  74. for (int ix = 0; ix < nn; ix++)
  75. {
  76. if ((*this)[ix] != 0.0)
  77. {
  78. T absxi = btFabs((*this)[ix]);
  79. if (scale < absxi)
  80. {
  81. T temp;
  82. temp = scale / absxi;
  83. ssq = ssq * (temp * temp) + BT_ONE;
  84. scale = absxi;
  85. }
  86. else
  87. {
  88. T temp;
  89. temp = absxi / scale;
  90. ssq += temp * temp;
  91. }
  92. }
  93. }
  94. norm = scale * sqrt(ssq);
  95. }
  96. }
  97. return norm;
  98. }
  99. void setZero()
  100. {
  101. if (m_storage.size())
  102. {
  103. // for (int i=0;i<m_storage.size();i++)
  104. // m_storage[i]=0;
  105. //memset(&m_storage[0],0,sizeof(T)*m_storage.size());
  106. btSetZero(&m_storage[0], m_storage.size());
  107. }
  108. }
  109. const T& operator[](int index) const
  110. {
  111. return m_storage[index];
  112. }
  113. T& operator[](int index)
  114. {
  115. return m_storage[index];
  116. }
  117. T* getBufferPointerWritable()
  118. {
  119. return m_storage.size() ? &m_storage[0] : 0;
  120. }
  121. const T* getBufferPointer() const
  122. {
  123. return m_storage.size() ? &m_storage[0] : 0;
  124. }
  125. };
  126. /*
  127. template <typename T>
  128. void setElem(btMatrixX<T>& mat, int row, int col, T val)
  129. {
  130. mat.setElem(row,col,val);
  131. }
  132. */
  133. template <typename T>
  134. struct btMatrixX
  135. {
  136. int m_rows;
  137. int m_cols;
  138. int m_operations;
  139. int m_resizeOperations;
  140. int m_setElemOperations;
  141. btAlignedObjectArray<T> m_storage;
  142. mutable btAlignedObjectArray<btAlignedObjectArray<int> > m_rowNonZeroElements1;
  143. T* getBufferPointerWritable()
  144. {
  145. return m_storage.size() ? &m_storage[0] : 0;
  146. }
  147. const T* getBufferPointer() const
  148. {
  149. return m_storage.size() ? &m_storage[0] : 0;
  150. }
  151. btMatrixX()
  152. : m_rows(0),
  153. m_cols(0),
  154. m_operations(0),
  155. m_resizeOperations(0),
  156. m_setElemOperations(0)
  157. {
  158. }
  159. btMatrixX(int rows, int cols)
  160. : m_rows(rows),
  161. m_cols(cols),
  162. m_operations(0),
  163. m_resizeOperations(0),
  164. m_setElemOperations(0)
  165. {
  166. resize(rows, cols);
  167. }
  168. void resize(int rows, int cols)
  169. {
  170. m_resizeOperations++;
  171. m_rows = rows;
  172. m_cols = cols;
  173. {
  174. BT_PROFILE("m_storage.resize");
  175. m_storage.resize(rows * cols);
  176. }
  177. }
  178. int cols() const
  179. {
  180. return m_cols;
  181. }
  182. int rows() const
  183. {
  184. return m_rows;
  185. }
  186. ///we don't want this read/write operator(), because we cannot keep track of non-zero elements, use setElem instead
  187. /*T& operator() (int row,int col)
  188. {
  189. return m_storage[col*m_rows+row];
  190. }
  191. */
  192. void addElem(int row, int col, T val)
  193. {
  194. if (val)
  195. {
  196. if (m_storage[col + row * m_cols] == 0.f)
  197. {
  198. setElem(row, col, val);
  199. }
  200. else
  201. {
  202. m_storage[row * m_cols + col] += val;
  203. }
  204. }
  205. }
  206. void setElem(int row, int col, T val)
  207. {
  208. m_setElemOperations++;
  209. m_storage[row * m_cols + col] = val;
  210. }
  211. void mulElem(int row, int col, T val)
  212. {
  213. m_setElemOperations++;
  214. //mul doesn't change sparsity info
  215. m_storage[row * m_cols + col] *= val;
  216. }
  217. void copyLowerToUpperTriangle()
  218. {
  219. int count = 0;
  220. for (int row = 0; row < rows(); row++)
  221. {
  222. for (int col = 0; col < row; col++)
  223. {
  224. setElem(col, row, (*this)(row, col));
  225. count++;
  226. }
  227. }
  228. //printf("copyLowerToUpperTriangle copied %d elements out of %dx%d=%d\n", count,rows(),cols(),cols()*rows());
  229. }
  230. const T& operator()(int row, int col) const
  231. {
  232. return m_storage[col + row * m_cols];
  233. }
  234. void setZero()
  235. {
  236. {
  237. BT_PROFILE("storage=0");
  238. if (m_storage.size())
  239. {
  240. btSetZero(&m_storage[0], m_storage.size());
  241. }
  242. //memset(&m_storage[0],0,sizeof(T)*m_storage.size());
  243. //for (int i=0;i<m_storage.size();i++)
  244. // m_storage[i]=0;
  245. }
  246. }
  247. void setIdentity()
  248. {
  249. btAssert(rows() == cols());
  250. setZero();
  251. for (int row = 0; row < rows(); row++)
  252. {
  253. setElem(row, row, 1);
  254. }
  255. }
  256. void printMatrix(const char* msg) const
  257. {
  258. printf("%s ---------------------\n", msg);
  259. for (int i = 0; i < rows(); i++)
  260. {
  261. printf("\n");
  262. for (int j = 0; j < cols(); j++)
  263. {
  264. printf("%2.1f\t", (*this)(i, j));
  265. }
  266. }
  267. printf("\n---------------------\n");
  268. }
  269. void rowComputeNonZeroElements() const
  270. {
  271. m_rowNonZeroElements1.resize(rows());
  272. for (int i = 0; i < rows(); i++)
  273. {
  274. m_rowNonZeroElements1[i].resize(0);
  275. for (int j = 0; j < cols(); j++)
  276. {
  277. if ((*this)(i, j) != 0.f)
  278. {
  279. m_rowNonZeroElements1[i].push_back(j);
  280. }
  281. }
  282. }
  283. }
  284. btMatrixX transpose() const
  285. {
  286. //transpose is optimized for sparse matrices
  287. btMatrixX tr(m_cols, m_rows);
  288. tr.setZero();
  289. for (int i = 0; i < m_cols; i++)
  290. for (int j = 0; j < m_rows; j++)
  291. {
  292. T v = (*this)(j, i);
  293. if (v)
  294. {
  295. tr.setElem(i, j, v);
  296. }
  297. }
  298. return tr;
  299. }
  300. btMatrixX operator*(const btMatrixX& other)
  301. {
  302. //btMatrixX*btMatrixX implementation, brute force
  303. btAssert(cols() == other.rows());
  304. btMatrixX res(rows(), other.cols());
  305. res.setZero();
  306. // BT_PROFILE("btMatrixX mul");
  307. for (int i = 0; i < rows(); ++i)
  308. {
  309. {
  310. for (int j = 0; j < other.cols(); ++j)
  311. {
  312. T dotProd = 0;
  313. {
  314. {
  315. int c = cols();
  316. for (int k = 0; k < c; k++)
  317. {
  318. T w = (*this)(i, k);
  319. if (other(k, j) != 0.f)
  320. {
  321. dotProd += w * other(k, 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. void setSubMatrix(int rowstart, int colstart, int rowend, int colend, const T value)
  378. {
  379. int numRows = rowend + 1 - rowstart;
  380. int numCols = colend + 1 - colstart;
  381. for (int row = 0; row < numRows; row++)
  382. {
  383. for (int col = 0; col < numCols; col++)
  384. {
  385. setElem(rowstart + row, colstart + col, value);
  386. }
  387. }
  388. }
  389. void setSubMatrix(int rowstart, int colstart, int rowend, int colend, const btMatrixX& block)
  390. {
  391. btAssert(rowend + 1 - rowstart == block.rows());
  392. btAssert(colend + 1 - colstart == block.cols());
  393. for (int row = 0; row < block.rows(); row++)
  394. {
  395. for (int col = 0; col < block.cols(); col++)
  396. {
  397. setElem(rowstart + row, colstart + col, block(row, col));
  398. }
  399. }
  400. }
  401. void setSubMatrix(int rowstart, int colstart, int rowend, int colend, const btVectorX<T>& block)
  402. {
  403. btAssert(rowend + 1 - rowstart == block.rows());
  404. btAssert(colend + 1 - colstart == block.cols());
  405. for (int row = 0; row < block.rows(); row++)
  406. {
  407. for (int col = 0; col < block.cols(); col++)
  408. {
  409. setElem(rowstart + row, colstart + col, block[row]);
  410. }
  411. }
  412. }
  413. btMatrixX negative()
  414. {
  415. btMatrixX neg(rows(), cols());
  416. for (int i = 0; i < rows(); i++)
  417. for (int j = 0; j < cols(); j++)
  418. {
  419. T v = (*this)(i, j);
  420. neg.setElem(i, j, -v);
  421. }
  422. return neg;
  423. }
  424. };
  425. typedef btMatrixX<float> btMatrixXf;
  426. typedef btVectorX<float> btVectorXf;
  427. typedef btMatrixX<double> btMatrixXd;
  428. typedef btVectorX<double> btVectorXd;
  429. #ifdef BT_DEBUG_OSTREAM
  430. template <typename T>
  431. std::ostream& operator<<(std::ostream& os, const btMatrixX<T>& mat)
  432. {
  433. os << " [";
  434. //printf("%s ---------------------\n",msg);
  435. for (int i = 0; i < mat.rows(); i++)
  436. {
  437. for (int j = 0; j < mat.cols(); j++)
  438. {
  439. os << std::setw(12) << mat(i, j);
  440. }
  441. if (i != mat.rows() - 1)
  442. os << std::endl
  443. << " ";
  444. }
  445. os << " ]";
  446. //printf("\n---------------------\n");
  447. return os;
  448. }
  449. template <typename T>
  450. std::ostream& operator<<(std::ostream& os, const btVectorX<T>& mat)
  451. {
  452. os << " [";
  453. //printf("%s ---------------------\n",msg);
  454. for (int i = 0; i < mat.rows(); i++)
  455. {
  456. os << std::setw(12) << mat[i];
  457. if (i != mat.rows() - 1)
  458. os << std::endl
  459. << " ";
  460. }
  461. os << " ]";
  462. //printf("\n---------------------\n");
  463. return os;
  464. }
  465. #endif //BT_DEBUG_OSTREAM
  466. inline void setElem(btMatrixXd& mat, int row, int col, double val)
  467. {
  468. mat.setElem(row, col, val);
  469. }
  470. inline void setElem(btMatrixXf& mat, int row, int col, float val)
  471. {
  472. mat.setElem(row, col, val);
  473. }
  474. #ifdef BT_USE_DOUBLE_PRECISION
  475. #define btVectorXu btVectorXd
  476. #define btMatrixXu btMatrixXd
  477. #else
  478. #define btVectorXu btVectorXf
  479. #define btMatrixXu btMatrixXf
  480. #endif //BT_USE_DOUBLE_PRECISION
  481. #endif //BT_MATRIX_H_H