MatrixT.tcc 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056
  1. #include <string>
  2. #include <sstream>
  3. #include <stdexcept>
  4. #include <limits>
  5. #include "core/basics/Exception.h"
  6. #define _THROW_EMatrix(string) fthrow(Exception, string)
  7. #include "core/vector/ippwrapper.h"
  8. #include "core/vector/MatrixT.h"
  9. #include "vector"
  10. #include <algorithm>
  11. namespace NICE
  12. {
  13. template<typename ElementType>
  14. inline MatrixT<ElementType>::MatrixT()
  15. {
  16. setDataPointer(NULL, 0, 0, false);
  17. }
  18. template<typename ElementType>
  19. inline MatrixT<ElementType>::MatrixT(const size_t rows, const size_t cols)
  20. {
  21. setDataPointer(new ElementType[rows * cols], rows, cols, false);
  22. }
  23. #ifdef NICE_USELIB_LINAL
  24. template<typename ElementType>
  25. inline MatrixT<ElementType>::MatrixT(const LinAl::Matrix<ElementType>& m)
  26. {
  27. setDataPointer(new ElementType[m.rows() * m.cols()],
  28. m.rows(), m.cols(), false);
  29. for (unsigned int j = 0; j < cols(); j++)
  30. {
  31. for (unsigned int i = 0; i < rows(); i++)
  32. {
  33. (*this)(i, j) = m(i, j);
  34. }
  35. }
  36. }
  37. template<typename ElementType>
  38. inline MatrixT<ElementType>&
  39. MatrixT<ElementType>::operator=(const LinAl::Matrix<ElementType>& v)
  40. {
  41. if (rows() * cols() == 0 && !externalStorage && getDataPointer() == NULL)
  42. {
  43. setDataPointer(new ElementType[v.rows() * v.cols()],
  44. v.rows(), v.cols(), false);
  45. }
  46. else if (this->rows() != (unsigned int) v.rows()
  47. || this->cols() != (unsigned int) v.cols())
  48. {
  49. this->resize(v.rows(), v.cols());
  50. }
  51. for (unsigned int j = 0; j < cols(); j++)
  52. {
  53. for (unsigned int i = 0; i < rows(); i++)
  54. {
  55. (*this)(i, j) = v(i, j);
  56. }
  57. }
  58. return *this;
  59. }
  60. #endif // NICE_USELIB_LINAL
  61. template<typename ElementType>
  62. inline MatrixT<ElementType>::MatrixT(const size_t rows, const size_t cols,
  63. const ElementType& element)
  64. {
  65. setDataPointer(new ElementType[rows * cols], rows, cols, false);
  66. ippsSet(element, getDataPointer(), rows * cols);
  67. }
  68. template<typename ElementType>
  69. inline MatrixT<ElementType>::MatrixT(const ElementType* _data,
  70. const size_t rows, const size_t cols)
  71. {
  72. setDataPointer(new ElementType[rows * cols], rows, cols, false);
  73. ippsCopy(_data, getDataPointer(), rows * cols);
  74. }
  75. template<typename ElementType>
  76. inline MatrixT<ElementType>::MatrixT(ElementType* _data,
  77. const size_t rows, const size_t cols,
  78. const MatrixBase::Mode mode)
  79. {
  80. switch (mode)
  81. {
  82. case external:
  83. setDataPointer(_data, rows, cols, true);
  84. break;
  85. case copy:
  86. setDataPointer(new ElementType[rows * cols], rows, cols, false);
  87. ippsCopy(_data, getDataPointer(), rows * cols);
  88. break;
  89. default:
  90. setDataPointer(NULL, 0, 0, false);
  91. _THROW_EMatrix("Unknown Mode-enum.");
  92. }
  93. }
  94. //template <class ElementType>
  95. //inline MatrixT<ElementType>::MatrixT(std::istream& input) {
  96. // input >> dataSize;
  97. // setDataPointer(new ElementType[dataSize], dataSize, false);
  98. //
  99. // char c;
  100. // input >> c;
  101. // if (c != '<') {
  102. // _THROW_EMatrix("syntax error reading MatrixT");
  103. // }
  104. //
  105. // unsigned int i = -1;
  106. // while (true) {
  107. // std::string s;
  108. // input >> s;
  109. // if (s == ">") {
  110. // break;
  111. // }
  112. // i++;
  113. // if (i > dataSize) {
  114. // _THROW_EMatrix("syntax error reading MatrixT");
  115. // }
  116. // std::stringstream st(s);
  117. // ElementType x;
  118. // st >> x;
  119. // getDataPointer()[i] = x;
  120. // }
  121. //}
  122. template<typename ElementType>
  123. MatrixT<ElementType>::MatrixT(const MatrixT<ElementType>& v)
  124. {
  125. setDataPointer(new ElementType[v.rows() * v.cols()],
  126. v.rows(), v.cols(), false);
  127. ippsCopy(v.getDataPointer(), getDataPointer(), v.rows() * v.cols());
  128. }
  129. template<typename ElementType>
  130. inline MatrixT<ElementType>::~MatrixT()
  131. {
  132. if (!externalStorage && data != NULL)
  133. {
  134. delete[] data;
  135. setDataPointer(NULL, 0, 0, false);
  136. }
  137. }
  138. template<typename ElementType>
  139. void MatrixT<ElementType>::resize(size_t _rows, size_t _cols)
  140. {
  141. if (rows() * cols() == _rows * _cols)
  142. {
  143. m_rows = _rows;
  144. m_cols = _cols;
  145. return;
  146. }
  147. if (externalStorage)
  148. {
  149. if (_rows * _cols < rows() * cols())
  150. {
  151. m_rows = _rows;
  152. m_cols = _cols;
  153. return;
  154. }
  155. _THROW_EMatrix("Cannot resize MatrixT (external storage used)");
  156. }
  157. if (getDataPointer() != NULL)
  158. {
  159. size_t oldRows = rows();
  160. size_t oldCols = cols();
  161. ElementType* tmp = getDataPointer();
  162. setDataPointer(new ElementType[_rows * _cols], _rows, _cols, false);
  163. ippsCopy(tmp, getDataPointer(), std::min(_rows * _cols, oldRows * oldCols));
  164. delete[] tmp;
  165. }
  166. else
  167. {
  168. setDataPointer(new ElementType[_rows * _cols], _rows, _cols, false);
  169. }
  170. }
  171. template<class ElementType>
  172. inline const MatrixT<ElementType>*
  173. MatrixT<ElementType>::createConst(const ElementType* _data,
  174. const size_t rows, const size_t cols)
  175. {
  176. MatrixT<ElementType>* result = new MatrixT<ElementType>;
  177. result->setConstDataPointer(_data, rows, cols);
  178. return result;
  179. }
  180. template<class ElementType>
  181. inline const VectorT<ElementType> MatrixT<ElementType>::getColumnRef(uint i) const
  182. {
  183. const VectorT<ElementType> column(constData[i * rows()], rows(), VectorBase::external);
  184. return column;
  185. }
  186. template<class ElementType>
  187. inline VectorT<ElementType> MatrixT<ElementType>::getColumnRef(uint i)
  188. {
  189. VectorT<ElementType> column(data + (i * rows()), rows(), VectorBase::external);
  190. return column;
  191. }
  192. template<class ElementType>
  193. inline VectorT<ElementType> MatrixT<ElementType>::getColumn(uint i) const
  194. {
  195. VectorT<ElementType> column(constData + i * rows(), rows());
  196. return column;
  197. }
  198. template<class ElementType>
  199. inline VectorT<ElementType> MatrixT<ElementType>::getRow(uint i) const
  200. {
  201. VectorT<ElementType> row(cols());
  202. for (uint j = 0;j < cols();j++)
  203. {
  204. row(j) = (*this)(i, j);
  205. }
  206. return row;
  207. }
  208. template<class ElementType>
  209. inline ElementType MatrixT<ElementType>::Max() const
  210. {
  211. ElementType max = - std::numeric_limits<ElementType>::max();
  212. for (uint i = 0 ; i < rows(); i++)
  213. for (uint j = 0 ; j < cols(); j++)
  214. if ((*this)(i, j) > max)
  215. max = (*this)(i, j);
  216. return max;
  217. }
  218. template<class ElementType>
  219. inline ElementType MatrixT<ElementType>::Min() const
  220. {
  221. ElementType min = std::numeric_limits<ElementType>::max();
  222. for (uint i = 0 ; i < rows(); i++)
  223. for (uint j = 0 ; j < cols(); j++)
  224. if ((*this)(i, j) < min)
  225. min = (*this)(i, j);
  226. return min;
  227. }
  228. template<class ElementType>
  229. inline bool
  230. MatrixT<ElementType>::operator==(const MatrixT<ElementType>& v) const
  231. {
  232. if (this->rows() != v.rows() || this->cols() != v.cols())
  233. {
  234. throw std::invalid_argument(
  235. "MatrixT::operator==(): v.rows/cols() != rows/cols()");
  236. }
  237. else if (rows() == 0 || cols() == 0)
  238. {
  239. return true;
  240. }
  241. for (unsigned int j = 0; j < cols(); j++)
  242. {
  243. for (unsigned int i = 0; i < rows(); i++)
  244. {
  245. if (!(operator()(i, j) == v(i, j)))
  246. {
  247. return false;
  248. }
  249. }
  250. }
  251. return true;
  252. }
  253. template<class ElementType>
  254. inline bool
  255. MatrixT<ElementType>::operator!=(const MatrixT<ElementType>& v) const
  256. {
  257. if (this->rows() != v.rows() || this->cols() != v.cols())
  258. {
  259. throw std::invalid_argument(
  260. "MatrixT::operator==(): v.rows/cols() != rows/cols()");
  261. }
  262. else if (rows() == 0 || cols() == 0)
  263. {
  264. return false;
  265. }
  266. for (unsigned int j = 0; j < cols(); j++)
  267. {
  268. for (unsigned int i = 0; i < rows(); i++)
  269. {
  270. if (!(operator()(i, j) == v(i, j)))
  271. {
  272. return true;
  273. }
  274. }
  275. }
  276. return false;
  277. }
  278. template<typename ElementType>
  279. inline MatrixT<ElementType>&
  280. MatrixT<ElementType>::operator=(const MatrixT<ElementType>& v)
  281. {
  282. if (rows() * cols() == 0 && !externalStorage && getDataPointer() == NULL)
  283. {
  284. setDataPointer(new ElementType[v.rows() * v.cols()],
  285. v.rows(), v.cols(), false);
  286. }
  287. else if (this->rows() != v.rows() || this->cols() != v.cols())
  288. {
  289. this->resize(v.rows(), v.cols());
  290. }
  291. ippsCopy(v.getDataPointer(), getDataPointer(), v.rows() * v.cols());
  292. return *this;
  293. }
  294. template<typename ElementType>
  295. inline MatrixT<ElementType>&
  296. MatrixT<ElementType>::operator=(const ElementType& element)
  297. {
  298. ippsSet(element, getDataPointer(), this->rows() * this->cols());
  299. return *this;
  300. }
  301. template<typename ElementType>
  302. void MatrixT<ElementType>::transposeInplace()
  303. {
  304. if (rows() != cols())
  305. {
  306. _THROW_EMatrix("transposeInplace(): matrix has to be quadratic");
  307. }
  308. for (unsigned int j = 1; j < cols(); j++)
  309. {
  310. for (unsigned int i = 0; i < j; i++)
  311. {
  312. std::swap((*this)(i, j), (*this)(j, i));
  313. }
  314. }
  315. }
  316. template<typename ElementType>
  317. MatrixT<ElementType> MatrixT<ElementType>::transpose() const
  318. {
  319. MatrixT<ElementType> result(cols(), rows());
  320. // ifdef NICE_USELIB_IPP
  321. size_t tsize = sizeof(ElementType);
  322. IppStatus ret = ippmTranspose_m(getDataPointer(), tsize, rows() * tsize,
  323. cols(), rows(), result.getDataPointer(),
  324. tsize, cols() * tsize);
  325. if (ret != ippStsNoErr)
  326. {
  327. _THROW_EMatrix(ippGetStatusString(ret));
  328. }
  329. // #else
  330. // for (unsigned int j = 0; j < cols(); j++) {
  331. // for (unsigned int i = 0; i < rows(); i++) {
  332. // result(j, i) = (*this)(i, j);
  333. // }
  334. // }
  335. // #endif
  336. return result;
  337. }
  338. #define _DEFINE_EMATRIX_AUGMENTED_ASSIGNMENT(_Op, _Name) \
  339. template<class ElementType> \
  340. inline MatrixT<ElementType> & \
  341. MatrixT<ElementType>::operator _Op##= (const ElementType& v) { \
  342. ipps##_Name##C_I(v, getDataPointer(), this->rows() * this->cols()); \
  343. return *this; \
  344. }
  345. _DEFINE_EMATRIX_AUGMENTED_ASSIGNMENT( + , Add)
  346. _DEFINE_EMATRIX_AUGMENTED_ASSIGNMENT(-, Sub)
  347. _DEFINE_EMATRIX_AUGMENTED_ASSIGNMENT(*, Mul)
  348. _DEFINE_EMATRIX_AUGMENTED_ASSIGNMENT( / , Div)
  349. #define _DEFINE_EMATRIX_ASSIGNMENT(_Op, _Name) \
  350. template<class ElementType> \
  351. inline MatrixT<ElementType> & \
  352. MatrixT<ElementType>::operator _Op##= (const MatrixT<ElementType>& v) { \
  353. if(this->rows() != v.rows() || this->cols() != v. cols()) \
  354. _THROW_EMatrix("MatrixT: different data size"); \
  355. ipps##_Name##_I(v.getDataPointer(), getDataPointer(), \
  356. this->rows() * this->cols()); \
  357. return *this; \
  358. }
  359. _DEFINE_EMATRIX_ASSIGNMENT( + , Add)
  360. _DEFINE_EMATRIX_ASSIGNMENT(-, Sub)
  361. //_DEFINE_EMATRIX_ASSIGNMENT(*, Mul)
  362. //_DEFINE_EMATRIX_ASSIGNMENT(/, Div)
  363. template<typename ElementType>
  364. void MatrixT<ElementType>::setBlock(uint top, uint left,
  365. MatrixT<ElementType> m)
  366. {
  367. if (rows() < m.rows() + top || cols() < m.cols() + left)
  368. {
  369. _THROW_EMatrix("Matrix setBlock: target matrix too small.");
  370. }
  371. // FIXME use IPP?
  372. for (unsigned int j = 0; j < m.cols(); j++)
  373. {
  374. for (unsigned int i = 0; i < m.rows(); i++)
  375. {
  376. (*this)(i + top, j + left) = m(i, j);
  377. }
  378. }
  379. }
  380. template<typename ElementType>
  381. void MatrixT<ElementType>::setRow(const uint & row, const NICE::VectorT<ElementType> & v)
  382. {
  383. if (cols() < v.size() )
  384. {
  385. _THROW_EMatrix("Matrix setRow: target matrix too small.");
  386. }
  387. if (row >= rows() )
  388. {
  389. _THROW_EMatrix("Matrix setRow: row does not specify a proper row index.");
  390. }
  391. if ( cols() > v.size() )
  392. {
  393. cerr<<"Warning: Matrix setRow: row is longer than vector."<<endl;
  394. }
  395. // FIXME use IPP?
  396. for (unsigned int j = 0; j < v.size(); j++)
  397. {
  398. (*this)(row, j) = v[j];
  399. }
  400. }
  401. template<typename ElementType>
  402. void MatrixT<ElementType>::exchangeRows(const uint & r1, const uint & r2)
  403. {
  404. //is r1 a proper row index?
  405. if ( r1 > this->rows() )
  406. {
  407. _THROW_EMatrix("Matrix exchangeRows: r1 does not specify a proper row index.");
  408. }
  409. //is r2 a proper row index?
  410. if ( r2 > this->rows() )
  411. {
  412. _THROW_EMatrix("Matrix exchangeRows: r2 does not specify a proper row index.");
  413. }
  414. NICE::VectorT<ElementType> tmp (this->getRow(r1));
  415. this->setRow(r1, this->getRow(r2));
  416. this->setRow(r1, tmp);
  417. }
  418. template<typename ElementType>
  419. void MatrixT<ElementType>::addToBlock(uint top, uint left,
  420. MatrixT<ElementType> m)
  421. {
  422. if (rows() < m.rows() + top || cols() < m.cols() + left)
  423. {
  424. _THROW_EMatrix("Matrix setBlock: target matrix too small.");
  425. }
  426. // FIXME use IPP?
  427. for (unsigned int j = 0; j < m.cols(); j++)
  428. {
  429. for (unsigned int i = 0; i < m.rows(); i++)
  430. {
  431. (*this)(i + top, j + left) += m(i, j);
  432. }
  433. }
  434. }
  435. template<typename ElementType>
  436. void MatrixT<ElementType>::addIdentity(double scale)
  437. {
  438. unsigned int m = std::min(rows(), cols());
  439. for (unsigned int i = 0; i < m; i++)
  440. {
  441. (*this)(i, i) += scale;
  442. }
  443. }
  444. template<typename ElementType>
  445. void MatrixT<ElementType>::addDiagonal( const VectorT<ElementType> & D )
  446. {
  447. unsigned int m = std::min(rows(), cols());
  448. if ( D.size() != m )
  449. _THROW_EMatrix("Matrix addDiagonal: inconsistent size of vector and diagonal elements.");
  450. for (unsigned int i = 0; i < m; i++)
  451. {
  452. (*this)(i, i) += D[i];
  453. }
  454. }
  455. template<typename ElementType>
  456. void MatrixT<ElementType>::addScaledMatrix( const ElementType & scale , const MatrixT<ElementType>& m)
  457. {
  458. if ( (rows() != m.rows()) || (cols() != m.cols()) )
  459. {
  460. _THROW_EMatrix("Matrix addScaledMatrix: target matrix not of the same size.");
  461. }
  462. for (unsigned int j = 0; j < m.cols(); j++)
  463. {
  464. for (unsigned int i = 0; i < m.rows(); i++)
  465. {
  466. (*this)(i, j) += scale * m(i, j);
  467. }
  468. }
  469. }
  470. template<typename ElementType>
  471. void MatrixT<ElementType>::tensorProduct(const VectorT<ElementType>& v,
  472. const VectorT<ElementType>& w)
  473. {
  474. if (v.size() != w.size())
  475. {
  476. _THROW_EMatrix("Matrix tensorProduct: inconsistent sizes of factors.");
  477. }
  478. if (rows() == 0 && cols() == 0)
  479. {
  480. resize(v.size(), w.size());
  481. }
  482. if (rows() != v.size() || cols() != w.size())
  483. {
  484. _THROW_EMatrix("Matrix multiplication: inconsistent size of result matrix.");
  485. }
  486. // FIXME use IPP?
  487. for (unsigned int j = 0; j < cols(); j++)
  488. {
  489. for (unsigned int i = 0; i < rows(); i++)
  490. {
  491. (*this)(i, j) = v[i] * w[j];
  492. }
  493. }
  494. }
  495. template<typename ElementType>
  496. void MatrixT<ElementType>::addTensorProduct(double lambda, const VectorT<ElementType>& v,
  497. const VectorT<ElementType>& w)
  498. {
  499. if (v.size() != w.size())
  500. {
  501. _THROW_EMatrix("Matrix tensorProduct: inconsistent sizes of factors.");
  502. }
  503. if (rows() == 0 && cols() == 0)
  504. {
  505. resize(v.size(), w.size());
  506. set(0.0);
  507. }
  508. if (rows() != v.size() || cols() != w.size())
  509. {
  510. _THROW_EMatrix("Matrix multiplication: inconsistent size of result matrix.");
  511. }
  512. for (unsigned int j = 0; j < cols(); j++)
  513. {
  514. for (unsigned int i = 0; i < rows(); i++)
  515. {
  516. (*this)(i, j) += lambda * v[i] * w[j];
  517. }
  518. }
  519. }
  520. template<typename ElementType>
  521. void MatrixT<ElementType>::multiply(const MatrixT<ElementType>& a,
  522. const MatrixT<ElementType>& b,
  523. bool atranspose,
  524. bool btranspose)
  525. {
  526. if (this == &a || this == &b)
  527. {
  528. _THROW_EMatrix(
  529. "Matrix multiplication: a and b must not be the same object as this.");
  530. }
  531. size_t arows, acols;
  532. if (atranspose)
  533. {
  534. arows = a.cols();
  535. acols = a.rows();
  536. }
  537. else
  538. {
  539. arows = a.rows();
  540. acols = a.cols();
  541. }
  542. size_t brows, bcols;
  543. if (btranspose)
  544. {
  545. brows = b.cols();
  546. bcols = b.rows();
  547. }
  548. else
  549. {
  550. brows = b.rows();
  551. bcols = b.cols();
  552. }
  553. if (acols != brows)
  554. {
  555. _THROW_EMatrix("Matrix multiplication: inconsistent sizes of factors.");
  556. }
  557. if (rows() == 0 && cols() == 0)
  558. {
  559. resize(arows, bcols);
  560. }
  561. if (rows() != arows || cols() != bcols)
  562. {
  563. _THROW_EMatrix("Matrix multiplication: inconsistent size of result matrix.");
  564. }
  565. #ifdef NICE_USELIB_IPP
  566. size_t tsize = sizeof(ElementType);
  567. IppStatus ret;
  568. if (atranspose)
  569. {
  570. if (btranspose)
  571. {
  572. ret = ippmMul_tt(b.getDataPointer(), b.rows() * tsize, tsize, b.rows(), b.cols(),
  573. a.getDataPointer(), a.rows() * tsize, tsize, a.rows(), a.cols(),
  574. this->getDataPointer(), rows() * tsize, tsize);
  575. }
  576. else
  577. {
  578. ret = ippmMul_mt(b.getDataPointer(), b.rows() * tsize, tsize, b.rows(), b.cols(),
  579. a.getDataPointer(), a.rows() * tsize, tsize, a.rows(), a.cols(),
  580. this->getDataPointer(), rows() * tsize, tsize);
  581. }
  582. }
  583. else
  584. {
  585. if (btranspose)
  586. {
  587. ret = ippmMul_tm(b.getDataPointer(), b.rows() * tsize, tsize, b.rows(), b.cols(),
  588. a.getDataPointer(), a.rows() * tsize, tsize, a.rows(), a.cols(),
  589. this->getDataPointer(), rows() * tsize, tsize);
  590. }
  591. else
  592. {
  593. ret = ippmMul_mm(b.getDataPointer(), b.rows() * tsize, tsize, b.rows(), b.cols(),
  594. a.getDataPointer(), a.rows() * tsize, tsize, a.rows(), a.cols(),
  595. this->getDataPointer(), rows() * tsize, tsize);
  596. }
  597. }
  598. if (ret != ippStsNoErr)
  599. _THROW_EMatrix(ippGetStatusString(ret));
  600. #else
  601. // FIXME not very efficient
  602. ElementType ela, elb;
  603. for (unsigned int j = 0; j < cols(); j++)
  604. {
  605. for (unsigned int i = 0; i < rows(); i++)
  606. {
  607. ElementType sum = ElementType(0);
  608. for (unsigned int k = 0; k < acols; k++)
  609. {
  610. ela = atranspose ? a(k, i) : a(i, k);
  611. elb = btranspose ? b(j, k) : b(k, j);
  612. sum += ela * elb;
  613. }
  614. (*this)(i, j) = sum;
  615. }
  616. }
  617. #endif
  618. }
  619. template<typename ElementType>
  620. bool MatrixT<ElementType>::containsNaN() const
  621. {
  622. for (unsigned int c = 0; c < cols(); c++)
  623. {
  624. for (unsigned int r = 0; r < rows(); r++)
  625. {
  626. if (isNaN((*this)(r, c)))
  627. {
  628. return true;
  629. }
  630. }
  631. }
  632. return false;
  633. }
  634. template<typename ElementType>
  635. inline bool MatrixT<ElementType>::isEqual(const MatrixT<ElementType> &a, ElementType threshold) const
  636. {
  637. if (this->rows() != a.rows() || this->cols() != a.cols())
  638. _THROW_EMatrix("MatrixT: different data size");
  639. for (unsigned int j = 0; j < cols(); j++)
  640. {
  641. for (unsigned int i = 0; i < rows(); i++)
  642. {
  643. if (fabs((*this)(i, j) - a(i, j)) > threshold)
  644. return false;
  645. }
  646. }
  647. return true;
  648. }
  649. template<typename ElementType>
  650. ElementType MatrixT<ElementType>::squaredFrobeniusNorm() const
  651. {
  652. double sum = ElementType(0);
  653. for (unsigned int j = 0; j < cols(); j++)
  654. {
  655. for (unsigned int i = 0; i < rows(); i++)
  656. {
  657. sum += square((*this)(i, j));
  658. }
  659. }
  660. return static_cast<ElementType>(sum);
  661. }
  662. template<typename ElementType>
  663. ElementType MatrixT<ElementType>::trace() const
  664. {
  665. double sum = ElementType(0);
  666. for (unsigned int j = 0; j < std::min(cols(),rows()); j++)
  667. {
  668. sum += (*this)(j, j);
  669. }
  670. return static_cast<ElementType>(sum);
  671. }
  672. template<typename ElementType>
  673. ElementType MatrixT<ElementType>::bilinear(const VectorT<ElementType> & v) const
  674. {
  675. double sum = ElementType(0);
  676. if ((this->rows() != this->cols()) || (v.size() != this->rows()))
  677. _THROW_EMatrix("MatrixT: different data size");
  678. for (unsigned int j = 0; j < cols(); j++)
  679. {
  680. for (unsigned int i = 0; i < rows(); i++)
  681. {
  682. sum += (*this)(i, j) * v[i] * v[j];
  683. }
  684. }
  685. return static_cast<ElementType>(sum);
  686. }
  687. template<typename ElementType>
  688. void MatrixT<ElementType>::normalizeColumnsL1()
  689. {
  690. for (unsigned int j = 0 ; j < cols() ; j++)
  691. {
  692. ElementType sum = 0.0;
  693. for (unsigned int i = 0 ; i < rows() ; i++)
  694. sum += fabs((double)(*this)(i, j));
  695. if (sum > 1e-20)
  696. for (unsigned int i = 0 ; i < rows() ; i++)
  697. (*this)(i, j) /= sum;
  698. }
  699. }
  700. template<typename ElementType>
  701. void MatrixT<ElementType>::normalizeRowsL1()
  702. {
  703. for (unsigned int i = 0 ; i < rows() ; i++)
  704. {
  705. ElementType sum = 0.0;
  706. for (unsigned int j = 0 ; j < cols() ; j++)
  707. sum += fabs((double)(*this)(i, j));
  708. if (sum > 1e-20)
  709. for (unsigned int j = 0 ; j < cols() ; j++)
  710. (*this)(i, j) /= sum;
  711. }
  712. }
  713. /** get sub-matrix */
  714. template<class ElementType>
  715. MatrixT<ElementType> MatrixT<ElementType>::operator()(const uint row_tl,
  716. const uint col_tl,
  717. const uint row_br,
  718. const uint col_br) const
  719. {
  720. if ( (row_tl>row_br+1)||(row_br>=rows())||
  721. (col_tl>col_br+1)||(col_br>=cols()) )
  722. _THROW_EMatrix("MatrixT: wrong specification of sub-matrix");
  723. MatrixT<ElementType> tm(row_br-row_tl+1,col_br-col_tl+1);
  724. for (uint i=row_tl;i<=row_br;i++)
  725. for (uint j=col_tl;j<=col_br;j++) {
  726. tm(i-row_tl,j-col_tl) = (*this)(i,j);
  727. }
  728. return tm;
  729. }
  730. /** Matrix addition */
  731. template<class ElementType>
  732. MatrixT<ElementType> operator+(const MatrixT<ElementType> & a, const MatrixT<ElementType> & b)
  733. {
  734. MatrixT<ElementType> dst(a);
  735. dst += b;
  736. return dst;
  737. }
  738. /** Matrix substraction */
  739. template<class ElementType>
  740. MatrixT<ElementType> operator-(const MatrixT<ElementType> & a, const MatrixT<ElementType> & b)
  741. {
  742. MatrixT<ElementType> dst(a);
  743. dst -= b;
  744. return dst;
  745. }
  746. /** Matrix (right) multiplication with a scalar */
  747. template<class ElementType>
  748. MatrixT<ElementType> operator*(const MatrixT<ElementType> & a, const double s)
  749. {
  750. MatrixT<ElementType> dst(a);
  751. dst *= s;
  752. return dst;
  753. }
  754. /** Matrix (left) multiplication with a scalar */
  755. template<class ElementType>
  756. MatrixT<ElementType> operator*(const double s, const MatrixT<ElementType> & a)
  757. {
  758. MatrixT<ElementType> dst(a);
  759. dst *= s;
  760. return dst;
  761. }
  762. /** Matrix multiplication with a vector */
  763. template<class ElementType>
  764. VectorT<ElementType> operator*(const MatrixT<ElementType> & a, const VectorT<ElementType> & b)
  765. {
  766. VectorT<ElementType> dst;
  767. dst.multiply(a, b);
  768. return dst;
  769. }
  770. /** Matrix multiplication with a matrix */
  771. template<class ElementType>
  772. MatrixT<ElementType> operator*(const MatrixT<ElementType> & a, const MatrixT<ElementType> & b)
  773. {
  774. MatrixT<ElementType> dst;
  775. dst.multiply(a, b);
  776. return dst;
  777. }
  778. template<class ElementType>
  779. void kroneckerProduct (const MatrixT<ElementType>& A, const MatrixT<ElementType>& B, MatrixT<ElementType>& dst)
  780. {
  781. dst.resize ( A.rows() * B.rows(), A.cols() * B.cols() );
  782. for (uint iA = 0 ; iA < A.rows(); iA++ )
  783. for (uint jA = 0 ; jA < A.cols(); jA++ )
  784. for (uint iB = 0 ; iB < B.rows(); iB++ )
  785. for (uint jB = 0 ; jB < B.cols(); jB++ )
  786. dst( iA*B.rows() + iB, jA*B.cols() + jB ) = A(iA,jA) * B(iB,jB);
  787. }
  788. template <typename T>
  789. void kroneckerProductMultiplication ( const MatrixT<T> & A, const MatrixT<T> & B, const Vector & x, Vector & y )
  790. {
  791. if ( x.size() != A.cols() * B.cols() )
  792. fthrow(Exception, "The size of matrix A and B do not fit to the size of the given vector.");
  793. y.resize ( A.rows() * B.rows() );
  794. Matrix X ( A.cols(), B.cols() );
  795. uint k = 0;
  796. for ( uint i = 0 ; i < A.cols(); i++ )
  797. for ( uint j = 0 ; j < B.cols(); j++,k++ )
  798. X(i,j) = x[k];
  799. // result in matrix form Y^T = (B * X^T) * A^T
  800. // Y = A X B^T
  801. Matrix Y;
  802. Matrix XBt;
  803. XBt.multiply ( X, B, false, true );
  804. Y.multiply ( A, XBt );
  805. // Y has size B.rows() and A.rows()
  806. k = 0;
  807. for ( uint i = 0 ; i < A.rows(); i++ )
  808. for ( uint j = 0 ; j < B.rows(); j++,k++ )
  809. y[k] = Y(i,j);
  810. }
  811. template <typename T>
  812. void blockwiseMultiplication ( const MatrixT<T> & A, uint blockSize, const Vector & x, Vector & y )
  813. {
  814. if ( x.size() != A.cols() * blockSize )
  815. fthrow(Exception, "The size of matrix A and the block size do not fit to the size of the given vector.");
  816. y.resize ( A.rows() * blockSize );
  817. Matrix X ( A.cols(), blockSize );
  818. uint k = 0;
  819. for ( uint i = 0 ; i < A.cols(); i++ )
  820. for ( uint j = 0 ; j < blockSize; j++,k++ )
  821. X(i,j) = x[k];
  822. // result in matrix form Y^T = X^T * A^T
  823. // Y = A X
  824. Matrix Y;
  825. Y.multiply ( A, X );
  826. // Y has size blockSize and A.rows()
  827. k = 0;
  828. for ( uint i = 0 ; i < A.rows(); i++ )
  829. for ( uint j = 0 ; j < blockSize; j++,k++ )
  830. y[k] = Y(i,j);
  831. }
  832. /**
  833. * @brief Delete one specified row by copying every data but of this row to a temporal storage, resizing M and assigning the tmp data to the resized matrix
  834. * @author Alexander Lütz
  835. * @date 07/10/2011
  836. * @param int index of col which shall be deleted (const, reference)
  837. */
  838. template <typename T>
  839. void MatrixT<T>::deleteRow ( const int & index)
  840. {
  841. if ( (0 > index) || ((*this).rows() <= (uint)index))
  842. fthrow(Exception, "MatrixT::deleteRow -- The given index is not valid.");
  843. MatrixT<T> tmp((*this).rows()-1,(*this).cols());
  844. for (uint i = 0; i < (*this).rows(); i++)
  845. {
  846. for (uint j = 0; j < (*this).cols(); j++)
  847. {
  848. if (i < (uint) index)
  849. {
  850. tmp(i,j) = (*this)(i,j);
  851. } else if (i > (uint) index)
  852. {
  853. tmp(i-1,j) = (*this)(i,j);
  854. }
  855. }
  856. }
  857. (*this).resize(tmp.rows(), tmp.cols());
  858. (*this) = tmp;
  859. }
  860. /**
  861. * @brief Delete one specified col by copying every data but of this col to a temporal storage, resizing M and assigning the tmp data to the resized matrix
  862. * @author Alexander Lütz
  863. * @date 07/10/2011
  864. * @param int index of col which shall be deleted (const, reference)
  865. */
  866. template <typename T>
  867. void MatrixT<T>::deleteCol ( const int & index)
  868. {
  869. if ( (0 > index) || ((*this).cols() <= (uint) index))
  870. fthrow(Exception, "MatrixT::deleteCol -- The given index is not valid.");
  871. MatrixT<T> tmp((*this).rows(),(*this).cols()-1);
  872. for (uint i = 0; i < (*this).rows(); i++)
  873. {
  874. for (uint j = 0; j < (*this).cols(); j++)
  875. {
  876. if (j < (uint) index)
  877. {
  878. tmp(i,j) = (*this)(i,j);
  879. } else if (j > (uint) index)
  880. {
  881. tmp(i,j-1) = (*this)(i,j);
  882. }
  883. }
  884. }
  885. (*this).resize(tmp.rows(), tmp.cols());
  886. (*this) = tmp;
  887. }
  888. /**
  889. * @brief Delete multiple specified rows by copying every data but of this rows to a temporal storage, resizing M and assigning the tmp data to the resized matrix
  890. * @author Alexander Lütz
  891. * @date 07/10/2011
  892. * @param std::vector<int> indices of cols which shall be deleted (not const, reference, sorted afterwards)
  893. */
  894. //not const, because they get sorted
  895. template <typename T>
  896. void MatrixT<T>::deleteRows ( std::vector<int> & indices)
  897. {
  898. for (std::vector<int>::const_iterator it = indices.begin(); it != indices.end(); it++)
  899. {
  900. if ( (0 > *it) || ((*this).rows() <= (uint) *it))
  901. fthrow(Exception, "MatrixT::deleteRows -- The given indices are not valid.");
  902. }
  903. sort (indices.begin(), indices.begin() + indices.size());
  904. int row_counter(0);
  905. MatrixT<T> tmp((*this).rows()-indices.size(),(*this).cols());
  906. for (uint i = 0; i < (*this).rows(); i++)
  907. {
  908. for (uint j = 0; j < (*this).cols(); j++)
  909. {
  910. if (i == (uint) indices[row_counter])
  911. {
  912. row_counter++;
  913. break; //break inner j-loop
  914. }
  915. else
  916. tmp(i-row_counter,j) = (*this)(i,j);
  917. }
  918. }
  919. (*this).resize(tmp.rows(), tmp.cols());
  920. (*this) = tmp;
  921. }
  922. /**
  923. * @brief Delete multiple specified cols by copying every data but of this cols to a temporal storage, resizing M and assigning the tmp data to the resized matrix
  924. * @author Alexander Lütz
  925. * @date 07/10/2011
  926. * @param std::vector<int> indices of rows which shall be deleted (not const, reference, sorted afterwards)
  927. */
  928. //not const, because they get sorted
  929. template <typename T>
  930. void MatrixT<T>::deleteCols ( std::vector<int> & indices)
  931. {
  932. for (std::vector<int>::const_iterator it = indices.begin(); it != indices.end(); it++)
  933. {
  934. if ( (0 > *it) || ((*this).cols() <= (uint) *it))
  935. fthrow(Exception, "MatrixT::deleteCols -- The given indices are not valid.");
  936. }
  937. sort (indices.begin(), indices.begin() + indices.size());
  938. int col_counter(0);
  939. MatrixT<T> tmp((*this).rows(),(*this).cols()-indices.size());
  940. //TODO check wether this is sufficient according to the way we keep the matrices in the storage!
  941. for (uint j = 0; j < (*this).cols(); j++)
  942. {
  943. for (uint i = 0; i < (*this).rows(); i++)
  944. {
  945. if (j == (uint) indices[col_counter])
  946. {
  947. col_counter++;
  948. break; //break inner j-loop
  949. }
  950. else
  951. tmp(i,j-col_counter) = (*this)(i,j);
  952. }
  953. }
  954. (*this).resize(tmp.rows(), tmp.cols());
  955. (*this) = tmp;
  956. }
  957. } // namespace