RowMatrixT.tcc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. #include <string>
  2. #include <sstream>
  3. #include <stdexcept>
  4. #include "core/basics/Exception.h"
  5. #define _THROW_ERowMatrix(string) fthrow(Exception, string)
  6. #include "core/vector/ippwrapper.h"
  7. #include "core/vector/RowMatrixT.h"
  8. namespace NICE {
  9. template<typename ElementType>
  10. inline RowMatrixT<ElementType>::RowMatrixT() {
  11. setDataPointer(NULL, 0, 0, false);
  12. }
  13. template<typename ElementType>
  14. inline RowMatrixT<ElementType>::RowMatrixT(const size_t rows, const size_t cols) {
  15. setDataPointer(new ElementType[rows * cols], rows, cols, false);
  16. }
  17. #ifdef NICE_USELIB_LINAL
  18. template<typename ElementType>
  19. inline RowMatrixT<ElementType>::RowMatrixT(const LinAl::Matrix<ElementType>& m) {
  20. setDataPointer(new ElementType[m.rows() * m.cols()],
  21. m.rows(), m.cols(), false);
  22. for (unsigned int i = 0; i < rows(); i++) {
  23. for (unsigned int j = 0; j < cols(); j++) {
  24. (*this)(i, j) = m(i, j);
  25. }
  26. }
  27. }
  28. #endif // NICE_USELIB_LINAL
  29. template<typename ElementType>
  30. inline RowMatrixT<ElementType>::RowMatrixT(const size_t rows, const size_t cols,
  31. const ElementType& element) {
  32. setDataPointer(new ElementType[rows * cols], rows, cols, false);
  33. ippsSet(element, getDataPointer(), rows * cols);
  34. }
  35. template<typename ElementType>
  36. inline RowMatrixT<ElementType>::RowMatrixT(const ElementType* _data,
  37. const size_t rows, const size_t cols) {
  38. setDataPointer(new ElementType[rows * cols], rows, cols, false);
  39. ippsCopy(_data, getDataPointer(), rows * cols);
  40. }
  41. template<typename ElementType>
  42. inline RowMatrixT<ElementType>::RowMatrixT(ElementType* _data,
  43. const size_t rows, const size_t cols,
  44. const MatrixBase::Mode mode) {
  45. switch (mode) {
  46. case external:
  47. setDataPointer(_data, rows, cols, true);
  48. break;
  49. case copy:
  50. setDataPointer(new ElementType[rows * cols], rows, cols, false);
  51. ippsCopy(_data, getDataPointer(), rows * cols);
  52. break;
  53. default:
  54. setDataPointer(NULL, 0, 0, false);
  55. _THROW_ERowMatrix("Unknown Mode-enum.");
  56. }
  57. }
  58. //template <class ElementType>
  59. //inline RowMatrixT<ElementType>::RowMatrixT(std::istream& input) {
  60. // input >> dataSize;
  61. // setDataPointer(new ElementType[dataSize], dataSize, false);
  62. //
  63. // char c;
  64. // input >> c;
  65. // if (c != '<') {
  66. // _THROW_ERowMatrix("syntax error reading RowMatrixT");
  67. // }
  68. //
  69. // unsigned int i = -1;
  70. // while (true) {
  71. // std::string s;
  72. // input >> s;
  73. // if (s == ">") {
  74. // break;
  75. // }
  76. // i++;
  77. // if (i > dataSize) {
  78. // _THROW_ERowMatrix("syntax error reading RowMatrixT");
  79. // }
  80. // std::stringstream st(s);
  81. // ElementType x;
  82. // st >> x;
  83. // getDataPointer()[i] = x;
  84. // }
  85. //}
  86. template<typename ElementType>
  87. RowMatrixT<ElementType>::RowMatrixT(const RowMatrixT<ElementType>& v) {
  88. setDataPointer(new ElementType[v.rows() * v.cols()],
  89. v.rows(), v.cols(), false);
  90. ippsCopy(v.getDataPointer(), getDataPointer(), v.rows() * v.cols());
  91. }
  92. template<typename ElementType>
  93. inline RowMatrixT<ElementType>::~RowMatrixT() {
  94. if (!externalStorage && data != NULL) {
  95. delete[] data;
  96. setDataPointer(NULL, 0, 0, false);
  97. }
  98. }
  99. template<typename ElementType>
  100. void RowMatrixT<ElementType>::resize(size_t _rows, size_t _cols) {
  101. if (rows() * cols() == _rows * _cols) {
  102. m_rows = _rows;
  103. m_cols = _cols;
  104. return;
  105. }
  106. if (externalStorage) {
  107. if (_rows * _cols < rows() * cols()) {
  108. m_rows = _rows;
  109. m_cols = _cols;
  110. return;
  111. }
  112. _THROW_ERowMatrix("Cannot resize RowMatrixT (external storage used)");
  113. }
  114. if (getDataPointer() != NULL) {
  115. size_t oldRows = rows();
  116. size_t oldCols = cols();
  117. ElementType* tmp = getDataPointer();
  118. setDataPointer(new ElementType[_rows * _cols], _rows, _cols, false);
  119. ippsCopy(tmp, getDataPointer(), std::min(_rows * _cols, oldRows * oldCols));
  120. delete[] tmp;
  121. } else {
  122. setDataPointer(new ElementType[_rows * _cols], _rows, _cols, false);
  123. }
  124. }
  125. template<class ElementType>
  126. inline const RowMatrixT<ElementType>*
  127. RowMatrixT<ElementType>::createConst(const ElementType* _data,
  128. const size_t rows, const size_t cols) {
  129. RowMatrixT<ElementType>* result = new RowMatrixT<ElementType>;
  130. result->setConstDataPointer(_data, rows, cols);
  131. return result;
  132. }
  133. template<class ElementType>
  134. inline const VectorT<ElementType> RowMatrixT<ElementType>::getRowRef(uint i) const
  135. {
  136. const VectorT<ElementType> row(constData[i * cols()],cols(),VectorBase::external);
  137. return row;
  138. }
  139. template<class ElementType>
  140. inline VectorT<ElementType> RowMatrixT<ElementType>::getRowRef(uint i)
  141. {
  142. VectorT<ElementType> row(data[i * cols()],cols(),VectorBase::external);
  143. return row;
  144. }
  145. template<class ElementType>
  146. inline VectorT<ElementType> RowMatrixT<ElementType>::getRow(uint i) const
  147. {
  148. VectorT<ElementType> row(constData[i * cols()],cols());
  149. return row;
  150. }
  151. template<class ElementType>
  152. inline VectorT<ElementType> RowMatrixT<ElementType>::getColumn(uint i) const
  153. {
  154. VectorT<ElementType> column(rows());
  155. for(int j=0;j<rows();j++) {
  156. column(j)=(*this)(j, i);
  157. }
  158. return column;
  159. }
  160. template<class ElementType>
  161. inline bool
  162. RowMatrixT<ElementType>::operator==(const RowMatrixT<ElementType>& v) const {
  163. if (this->rows() != v.rows() || this->cols() != v.cols()) {
  164. throw std::invalid_argument(
  165. "RowMatrixT::operator==(): v.rows/cols() != rows/cols()");
  166. } else if (rows() == 0 || cols() == 0) {
  167. return true;
  168. }
  169. for (unsigned int i = 0; i < rows(); i++) {
  170. for (unsigned int j = 0; j < cols(); j++) {
  171. if (!(operator()(i, j) == v(i, j))) {
  172. return false;
  173. }
  174. }
  175. }
  176. return true;
  177. }
  178. template<class ElementType>
  179. inline bool
  180. RowMatrixT<ElementType>::operator!=(const RowMatrixT<ElementType>& v) const {
  181. if (this->rows() != v.rows() || this->cols() != v.cols()) {
  182. throw std::invalid_argument(
  183. "RowMatrixT::operator!=(): v.rows/cols() != rows/cols()");
  184. } else if (rows() == 0 || cols() == 0) {
  185. return false;
  186. }
  187. for (unsigned int i = 0; i < rows(); i++) {
  188. for (unsigned int j = 0; j < cols(); j++) {
  189. if (!(operator()(i, j) == v(i, j))) {
  190. return true;
  191. }
  192. }
  193. }
  194. return false;
  195. }
  196. template<typename ElementType>
  197. inline RowMatrixT<ElementType>&
  198. RowMatrixT<ElementType>::operator=(const RowMatrixT<ElementType>& v) {
  199. if (rows() * cols() == 0 && !externalStorage && getDataPointer() == NULL) {
  200. setDataPointer(new ElementType[v.rows() * v.cols()],
  201. v.rows(), v.cols(), false);
  202. } else if (this->rows() != v.rows() || this->cols() != v.cols()) {
  203. this->resize(v.rows(),v.cols());
  204. }
  205. ippsCopy(v.getDataPointer(), getDataPointer(), v.rows() * v.cols());
  206. return *this;
  207. }
  208. template<typename ElementType>
  209. inline RowMatrixT<ElementType>&
  210. RowMatrixT<ElementType>::operator=(const ElementType& element) {
  211. ippsSet(element, getDataPointer(), this->rows() * this->cols());
  212. return *this;
  213. }
  214. template<typename ElementType>
  215. void RowMatrixT<ElementType>::transposeInplace() {
  216. if (rows() != cols()) {
  217. _THROW_ERowMatrix("transposeInplace(): matrix has to be quadratic");
  218. }
  219. for (unsigned int j = 1; j < cols(); j++) {
  220. for (unsigned int i = 0; i < j; i++) {
  221. std::swap((*this)(i, j), (*this)(j, i));
  222. }
  223. }
  224. }
  225. template<typename ElementType>
  226. RowMatrixT<ElementType> RowMatrixT<ElementType>::transpose() {
  227. RowMatrixT<ElementType> result(cols(),rows());
  228. // #ifdef NICE_USELIB_IPP
  229. size_t tsize = sizeof(ElementType);
  230. IppStatus ret = ippmTranspose_m(getDataPointer(), cols()*tsize, tsize,
  231. cols(), rows(),
  232. result.getDataPointer(), rows()*tsize, tsize);
  233. if (ret!=ippStsNoErr) {
  234. _THROW_ERowMatrix(ippGetStatusString(ret));
  235. }
  236. // #else
  237. // for (unsigned int i = 0; i < rows(); i++) {
  238. // for (unsigned int j = 0; j < cols(); j++) {
  239. // result(j, i) = (*this)(i, j);
  240. // }
  241. // }
  242. // #endif
  243. return result;
  244. }
  245. #define _DEFINE_ERowMatrix_AUGMENTED_ASSIGNMENT(_Op, _Name) \
  246. template<class ElementType> \
  247. inline RowMatrixT<ElementType> & \
  248. RowMatrixT<ElementType>::operator _Op##= (const ElementType& v) { \
  249. ipps##_Name##C_I(v, getDataPointer(), this->rows() * this->cols()); \
  250. return *this; \
  251. }
  252. _DEFINE_ERowMatrix_AUGMENTED_ASSIGNMENT(+, Add)
  253. _DEFINE_ERowMatrix_AUGMENTED_ASSIGNMENT(-, Sub)
  254. _DEFINE_ERowMatrix_AUGMENTED_ASSIGNMENT(*, Mul)
  255. _DEFINE_ERowMatrix_AUGMENTED_ASSIGNMENT(/, Div)
  256. #define _DEFINE_ERowMatrix_ASSIGNMENT(_Op, _Name) \
  257. template<class ElementType> \
  258. inline RowMatrixT<ElementType> & \
  259. RowMatrixT<ElementType>::operator _Op##= (const RowMatrixT<ElementType>& v) { \
  260. if(this->rows() != v.rows() || this->cols() != v. cols()) \
  261. _THROW_ERowMatrix("RowMatrixT: different data size"); \
  262. ipps##_Name##_I(v.getDataPointer(), getDataPointer(), \
  263. this->rows() * this->cols()); \
  264. return *this; \
  265. }
  266. _DEFINE_ERowMatrix_ASSIGNMENT(+, Add)
  267. _DEFINE_ERowMatrix_ASSIGNMENT(-, Sub)
  268. //_DEFINE_ERowMatrix_ASSIGNMENT(*, Mul)
  269. //_DEFINE_ERowMatrix_ASSIGNMENT(/, Div)
  270. template<typename ElementType>
  271. void RowMatrixT<ElementType>::multiply(const RowMatrixT<ElementType>& a,
  272. const RowMatrixT<ElementType>& b,
  273. bool atranspose,
  274. bool btranspose) {
  275. if (this == &a || this == &b) {
  276. _THROW_ERowMatrix(
  277. "Matrix multiplication: a and b must not be the same object as this.");
  278. }
  279. size_t arows, acols;
  280. if(atranspose) {
  281. arows=a.cols();
  282. acols=a.rows();
  283. } else {
  284. arows=a.rows();
  285. acols=a.cols();
  286. }
  287. size_t brows, bcols;
  288. if(btranspose) {
  289. brows=b.cols();
  290. bcols=b.rows();
  291. } else {
  292. brows=b.rows();
  293. bcols=b.cols();
  294. }
  295. if (acols != brows) {
  296. _THROW_ERowMatrix("Matrix multiplication: inconsistent sizes of factors.");
  297. }
  298. if (rows() == 0 && cols() == 0) {
  299. resize(arows, bcols);
  300. }
  301. if (rows() != arows || cols() != bcols) {
  302. _THROW_ERowMatrix("Matrix multiplication: inconsistent size of result matriq.");
  303. }
  304. #ifdef NICE_USELIB_IPP
  305. size_t tsize=sizeof(ElementType);
  306. IppStatus ret;
  307. if(atranspose) {
  308. if(btranspose) {
  309. ret = ippmMul_tt(a.getDataPointer(), a.cols()*tsize, tsize, a.cols(), a.rows(),
  310. b.getDataPointer(), b.cols()*tsize, tsize, b.cols(), b.rows(),
  311. this->getDataPointer(), cols()*tsize, tsize);
  312. } else {
  313. ret = ippmMul_tm(a.getDataPointer(), a.cols()*tsize, tsize, a.cols(), a.rows(),
  314. b.getDataPointer(), b.cols()*tsize, tsize, b.cols(), b.rows(),
  315. this->getDataPointer(), cols()*tsize, tsize);
  316. }
  317. } else {
  318. if(btranspose) {
  319. ret = ippmMul_mt(a.getDataPointer(), a.cols()*tsize, tsize, a.cols(), a.rows(),
  320. b.getDataPointer(), b.cols()*tsize, tsize, b.cols(), b.rows(),
  321. this->getDataPointer(), cols()*tsize, tsize);
  322. } else {
  323. ret = ippmMul_mm(a.getDataPointer(), a.cols()*tsize, tsize, a.cols(), a.rows(),
  324. b.getDataPointer(), b.cols()*tsize, tsize, b.cols(), b.rows(),
  325. this->getDataPointer(), cols()*tsize, tsize);
  326. }
  327. }
  328. if(ret!=ippStsNoErr)
  329. _THROW_ERowMatrix(ippGetStatusString(ret));
  330. #else
  331. // FIXME not very efficient
  332. ElementType ela, elb;
  333. for (unsigned int i = 0; i < rows(); i++) {
  334. for (unsigned int j = 0; j < cols(); j++) {
  335. ElementType sum = ElementType(0);
  336. for (unsigned int k = 0; k < acols; k++) {
  337. ela = atranspose ? a(k, i) : a(i, k);
  338. elb = btranspose ? b(j, k) : b(k, j);
  339. sum += ela * elb;
  340. }
  341. (*this)(i, j) = sum;
  342. }
  343. }
  344. #endif
  345. }
  346. template<typename ElementType>
  347. bool RowMatrixT<ElementType>::containsNaN() const {
  348. for (unsigned int r = 0; r < rows(); r++) {
  349. for (unsigned int c = 0; c < cols(); c++) {
  350. if (NICE::isNaN((*this)(r, c))) {
  351. return true;
  352. }
  353. }
  354. }
  355. return false;
  356. }
  357. template<typename ElementType>
  358. inline bool RowMatrixT<ElementType>::isEqual(const RowMatrixT<ElementType> &a, ElementType threshold) const
  359. {
  360. if(this->rows() != a.rows() || this->cols() != a.cols())
  361. _THROW_ERowMatrix("RowMatrixT: different data size");
  362. for (unsigned int i = 0; i < rows(); i++) {
  363. for (unsigned int j = 0; j < cols(); j++) {
  364. if(abs((*this)(i, j)-a(i,j))>threshold)
  365. return false;
  366. }
  367. }
  368. return true;
  369. }
  370. template<typename ElementType>
  371. ElementType RowMatrixT<ElementType>::squaredFrobeniusNorm() const {
  372. double sum = ElementType(0);
  373. for (unsigned int i = 0; i < rows(); i++) {
  374. for (unsigned int j = 0; j < cols(); j++) {
  375. sum += square((*this)(i, j));
  376. }
  377. }
  378. return sum;
  379. }
  380. }