1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
4
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10
11 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.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15 ///original version written by Erwin Coumans, October 2013
16
17 #ifndef BT_MATRIX_X_H
18 #define BT_MATRIX_X_H
19
20 #include "LinearMath/btQuickprof.h"
21 #include "LinearMath/btAlignedObjectArray.h"
22 #include <stdio.h>
23
24 //#define BT_DEBUG_OSTREAM
25 #ifdef BT_DEBUG_OSTREAM
26 #include <iostream>
27 #include <iomanip> // std::setw
28 #endif //BT_DEBUG_OSTREAM
29
30 class btIntSortPredicate
31 {
32 public:
operator()33 bool operator() ( const int& a, const int& b ) const
34 {
35 return a < b;
36 }
37 };
38
39
40 template <typename T>
41 struct btVectorX
42 {
43 btAlignedObjectArray<T> m_storage;
44
btVectorXbtVectorX45 btVectorX()
46 {
47 }
btVectorXbtVectorX48 btVectorX(int numRows)
49 {
50 m_storage.resize(numRows);
51 }
52
resizebtVectorX53 void resize(int rows)
54 {
55 m_storage.resize(rows);
56 }
colsbtVectorX57 int cols() const
58 {
59 return 1;
60 }
rowsbtVectorX61 int rows() const
62 {
63 return m_storage.size();
64 }
sizebtVectorX65 int size() const
66 {
67 return rows();
68 }
69
nrm2btVectorX70 T nrm2() const
71 {
72 T norm = T(0);
73
74 int nn = rows();
75
76 {
77 if (nn == 1)
78 {
79 norm = btFabs((*this)[0]);
80 }
81 else
82 {
83 T scale = 0.0;
84 T ssq = 1.0;
85
86 /* The following loop is equivalent to this call to the LAPACK
87 auxiliary routine: CALL SLASSQ( N, X, INCX, SCALE, SSQ ) */
88
89 for (int ix=0;ix<nn;ix++)
90 {
91 if ((*this)[ix] != 0.0)
92 {
93 T absxi = btFabs((*this)[ix]);
94 if (scale < absxi)
95 {
96 T temp;
97 temp = scale / absxi;
98 ssq = ssq * (temp * temp) + BT_ONE;
99 scale = absxi;
100 }
101 else
102 {
103 T temp;
104 temp = absxi / scale;
105 ssq += temp * temp;
106 }
107 }
108 }
109 norm = scale * sqrt(ssq);
110 }
111 }
112 return norm;
113
114 }
setZerobtVectorX115 void setZero()
116 {
117 if (m_storage.size())
118 {
119 // for (int i=0;i<m_storage.size();i++)
120 // m_storage[i]=0;
121 //memset(&m_storage[0],0,sizeof(T)*m_storage.size());
122 btSetZero(&m_storage[0],m_storage.size());
123 }
124 }
125 const T& operator[] (int index) const
126 {
127 return m_storage[index];
128 }
129
130 T& operator[] (int index)
131 {
132 return m_storage[index];
133 }
134
getBufferPointerWritablebtVectorX135 T* getBufferPointerWritable()
136 {
137 return m_storage.size() ? &m_storage[0] : 0;
138 }
139
getBufferPointerbtVectorX140 const T* getBufferPointer() const
141 {
142 return m_storage.size() ? &m_storage[0] : 0;
143 }
144
145 };
146 /*
147 template <typename T>
148 void setElem(btMatrixX<T>& mat, int row, int col, T val)
149 {
150 mat.setElem(row,col,val);
151 }
152 */
153
154
155 template <typename T>
156 struct btMatrixX
157 {
158 int m_rows;
159 int m_cols;
160 int m_operations;
161 int m_resizeOperations;
162 int m_setElemOperations;
163
164 btAlignedObjectArray<T> m_storage;
165 mutable btAlignedObjectArray< btAlignedObjectArray<int> > m_rowNonZeroElements1;
166
getBufferPointerWritablebtMatrixX167 T* getBufferPointerWritable()
168 {
169 return m_storage.size() ? &m_storage[0] : 0;
170 }
171
getBufferPointerbtMatrixX172 const T* getBufferPointer() const
173 {
174 return m_storage.size() ? &m_storage[0] : 0;
175 }
btMatrixXbtMatrixX176 btMatrixX()
177 :m_rows(0),
178 m_cols(0),
179 m_operations(0),
180 m_resizeOperations(0),
181 m_setElemOperations(0)
182 {
183 }
btMatrixXbtMatrixX184 btMatrixX(int rows,int cols)
185 :m_rows(rows),
186 m_cols(cols),
187 m_operations(0),
188 m_resizeOperations(0),
189 m_setElemOperations(0)
190 {
191 resize(rows,cols);
192 }
resizebtMatrixX193 void resize(int rows, int cols)
194 {
195 m_resizeOperations++;
196 m_rows = rows;
197 m_cols = cols;
198 {
199 BT_PROFILE("m_storage.resize");
200 m_storage.resize(rows*cols);
201 }
202 }
colsbtMatrixX203 int cols() const
204 {
205 return m_cols;
206 }
rowsbtMatrixX207 int rows() const
208 {
209 return m_rows;
210 }
211 ///we don't want this read/write operator(), because we cannot keep track of non-zero elements, use setElem instead
212 /*T& operator() (int row,int col)
213 {
214 return m_storage[col*m_rows+row];
215 }
216 */
217
addElembtMatrixX218 void addElem(int row,int col, T val)
219 {
220 if (val)
221 {
222 if (m_storage[col+row*m_cols]==0.f)
223 {
224 setElem(row,col,val);
225 } else
226 {
227 m_storage[row*m_cols+col] += val;
228 }
229 }
230 }
231
232
setElembtMatrixX233 void setElem(int row,int col, T val)
234 {
235 m_setElemOperations++;
236 m_storage[row*m_cols+col] = val;
237 }
238
mulElembtMatrixX239 void mulElem(int row,int col, T val)
240 {
241 m_setElemOperations++;
242 //mul doesn't change sparsity info
243
244 m_storage[row*m_cols+col] *= val;
245 }
246
247
248
249
copyLowerToUpperTrianglebtMatrixX250 void copyLowerToUpperTriangle()
251 {
252 int count=0;
253 for (int row=0;row<rows();row++)
254 {
255 for (int col=0;col<row;col++)
256 {
257 setElem(col,row, (*this)(row,col));
258 count++;
259
260 }
261 }
262 //printf("copyLowerToUpperTriangle copied %d elements out of %dx%d=%d\n", count,rows(),cols(),cols()*rows());
263 }
264
operatorbtMatrixX265 const T& operator() (int row,int col) const
266 {
267 return m_storage[col+row*m_cols];
268 }
269
270
setZerobtMatrixX271 void setZero()
272 {
273 {
274 BT_PROFILE("storage=0");
275 btSetZero(&m_storage[0],m_storage.size());
276 //memset(&m_storage[0],0,sizeof(T)*m_storage.size());
277 //for (int i=0;i<m_storage.size();i++)
278 // m_storage[i]=0;
279 }
280 }
281
setIdentitybtMatrixX282 void setIdentity()
283 {
284 btAssert(rows() == cols());
285
286 setZero();
287 for (int row=0;row<rows();row++)
288 {
289 setElem(row,row,1);
290 }
291 }
292
293
294
printMatrixbtMatrixX295 void printMatrix(const char* msg)
296 {
297 printf("%s ---------------------\n",msg);
298 for (int i=0;i<rows();i++)
299 {
300 printf("\n");
301 for (int j=0;j<cols();j++)
302 {
303 printf("%2.1f\t",(*this)(i,j));
304 }
305 }
306 printf("\n---------------------\n");
307
308 }
309
310
rowComputeNonZeroElementsbtMatrixX311 void rowComputeNonZeroElements() const
312 {
313 m_rowNonZeroElements1.resize(rows());
314 for (int i=0;i<rows();i++)
315 {
316 m_rowNonZeroElements1[i].resize(0);
317 for (int j=0;j<cols();j++)
318 {
319 if ((*this)(i,j)!=0.f)
320 {
321 m_rowNonZeroElements1[i].push_back(j);
322 }
323 }
324 }
325 }
transposebtMatrixX326 btMatrixX transpose() const
327 {
328 //transpose is optimized for sparse matrices
329 btMatrixX tr(m_cols,m_rows);
330 tr.setZero();
331 for (int i=0;i<m_cols;i++)
332 for (int j=0;j<m_rows;j++)
333 {
334 T v = (*this)(j,i);
335 if (v)
336 {
337 tr.setElem(i,j,v);
338 }
339 }
340 return tr;
341 }
342
343
344 btMatrixX operator*(const btMatrixX& other)
345 {
346 //btMatrixX*btMatrixX implementation, brute force
347 btAssert(cols() == other.rows());
348
349 btMatrixX res(rows(),other.cols());
350 res.setZero();
351 // BT_PROFILE("btMatrixX mul");
352 for (int j=0; j < res.cols(); ++j)
353 {
354 {
355 for (int i=0; i < res.rows(); ++i)
356 {
357 T dotProd=0;
358 // T dotProd2=0;
359 //int waste=0,waste2=0;
360
361 {
362 // bool useOtherCol = true;
363 {
364 for (int v=0;v<rows();v++)
365 {
366 T w = (*this)(i,v);
367 if (other(v,j)!=0.f)
368 {
369 dotProd+=w*other(v,j);
370 }
371
372 }
373 }
374 }
375 if (dotProd)
376 res.setElem(i,j,dotProd);
377 }
378 }
379 }
380 return res;
381 }
382
383 // this assumes the 4th and 8th rows of B and C are zero.
multiplyAdd2_p8rbtMatrixX384 void multiplyAdd2_p8r (const btScalar *B, const btScalar *C, int numRows, int numRowsOther ,int row, int col)
385 {
386 const btScalar *bb = B;
387 for ( int i = 0;i<numRows;i++)
388 {
389 const btScalar *cc = C;
390 for ( int j = 0;j<numRowsOther;j++)
391 {
392 btScalar sum;
393 sum = bb[0]*cc[0];
394 sum += bb[1]*cc[1];
395 sum += bb[2]*cc[2];
396 sum += bb[4]*cc[4];
397 sum += bb[5]*cc[5];
398 sum += bb[6]*cc[6];
399 addElem(row+i,col+j,sum);
400 cc += 8;
401 }
402 bb += 8;
403 }
404 }
405
multiply2_p8rbtMatrixX406 void multiply2_p8r (const btScalar *B, const btScalar *C, int numRows, int numRowsOther, int row, int col)
407 {
408 btAssert (numRows>0 && numRowsOther>0 && B && C);
409 const btScalar *bb = B;
410 for ( int i = 0;i<numRows;i++)
411 {
412 const btScalar *cc = C;
413 for ( int j = 0;j<numRowsOther;j++)
414 {
415 btScalar sum;
416 sum = bb[0]*cc[0];
417 sum += bb[1]*cc[1];
418 sum += bb[2]*cc[2];
419 sum += bb[4]*cc[4];
420 sum += bb[5]*cc[5];
421 sum += bb[6]*cc[6];
422 setElem(row+i,col+j,sum);
423 cc += 8;
424 }
425 bb += 8;
426 }
427 }
428
setSubMatrixbtMatrixX429 void setSubMatrix(int rowstart,int colstart,int rowend,int colend,const T value)
430 {
431 int numRows = rowend+1-rowstart;
432 int numCols = colend+1-colstart;
433
434 for (int row=0;row<numRows;row++)
435 {
436 for (int col=0;col<numCols;col++)
437 {
438 setElem(rowstart+row,colstart+col,value);
439 }
440 }
441 }
442
setSubMatrixbtMatrixX443 void setSubMatrix(int rowstart,int colstart,int rowend,int colend,const btMatrixX& block)
444 {
445 btAssert(rowend+1-rowstart == block.rows());
446 btAssert(colend+1-colstart == block.cols());
447 for (int row=0;row<block.rows();row++)
448 {
449 for (int col=0;col<block.cols();col++)
450 {
451 setElem(rowstart+row,colstart+col,block(row,col));
452 }
453 }
454 }
setSubMatrixbtMatrixX455 void setSubMatrix(int rowstart,int colstart,int rowend,int colend,const btVectorX<T>& block)
456 {
457 btAssert(rowend+1-rowstart == block.rows());
458 btAssert(colend+1-colstart == block.cols());
459 for (int row=0;row<block.rows();row++)
460 {
461 for (int col=0;col<block.cols();col++)
462 {
463 setElem(rowstart+row,colstart+col,block[row]);
464 }
465 }
466 }
467
468
negativebtMatrixX469 btMatrixX negative()
470 {
471 btMatrixX neg(rows(),cols());
472 for (int i=0;i<rows();i++)
473 for (int j=0;j<cols();j++)
474 {
475 T v = (*this)(i,j);
476 neg.setElem(i,j,-v);
477 }
478 return neg;
479 }
480
481 };
482
483
484
485 typedef btMatrixX<float> btMatrixXf;
486 typedef btVectorX<float> btVectorXf;
487
488 typedef btMatrixX<double> btMatrixXd;
489 typedef btVectorX<double> btVectorXd;
490
491
492 #ifdef BT_DEBUG_OSTREAM
493 template <typename T>
494 std::ostream& operator<< (std::ostream& os, const btMatrixX<T>& mat)
495 {
496
497 os << " [";
498 //printf("%s ---------------------\n",msg);
499 for (int i=0;i<mat.rows();i++)
500 {
501 for (int j=0;j<mat.cols();j++)
502 {
503 os << std::setw(12) << mat(i,j);
504 }
505 if (i!=mat.rows()-1)
506 os << std::endl << " ";
507 }
508 os << " ]";
509 //printf("\n---------------------\n");
510
511 return os;
512 }
513 template <typename T>
514 std::ostream& operator<< (std::ostream& os, const btVectorX<T>& mat)
515 {
516
517 os << " [";
518 //printf("%s ---------------------\n",msg);
519 for (int i=0;i<mat.rows();i++)
520 {
521 os << std::setw(12) << mat[i];
522 if (i!=mat.rows()-1)
523 os << std::endl << " ";
524 }
525 os << " ]";
526 //printf("\n---------------------\n");
527
528 return os;
529 }
530
531 #endif //BT_DEBUG_OSTREAM
532
533
setElem(btMatrixXd & mat,int row,int col,double val)534 inline void setElem(btMatrixXd& mat, int row, int col, double val)
535 {
536 mat.setElem(row,col,val);
537 }
538
setElem(btMatrixXf & mat,int row,int col,float val)539 inline void setElem(btMatrixXf& mat, int row, int col, float val)
540 {
541 mat.setElem(row,col,val);
542 }
543
544 #ifdef BT_USE_DOUBLE_PRECISION
545 #define btVectorXu btVectorXd
546 #define btMatrixXu btMatrixXd
547 #else
548 #define btVectorXu btVectorXf
549 #define btMatrixXu btMatrixXf
550 #endif //BT_USE_DOUBLE_PRECISION
551
552
553
554 #endif//BT_MATRIX_H_H
555