You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2284 lines
87 KiB

  1. /* -*- c++ -*- (enables emacs c++ mode) */
  2. /*===========================================================================
  3. Copyright (C) 2002-2012 Yves Renard
  4. This file is a part of GETFEM++
  5. Getfem++ is free software; you can redistribute it and/or modify it
  6. under the terms of the GNU Lesser General Public License as published
  7. by the Free Software Foundation; either version 3 of the License, or
  8. (at your option) any later version along with the GCC Runtime Library
  9. Exception either version 3.1 or (at your option) any later version.
  10. This program is distributed in the hope that it will be useful, but
  11. WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  12. or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
  13. License and GCC Runtime Library Exception for more details.
  14. You should have received a copy of the GNU Lesser General Public License
  15. along with this program; if not, write to the Free Software Foundation,
  16. Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
  17. As a special exception, you may use this file as it is a part of a free
  18. software library without restriction. Specifically, if other files
  19. instantiate templates or use macros or inline functions from this file,
  20. or you compile this file and link it with other files to produce an
  21. executable, this file does not by itself cause the resulting executable
  22. to be covered by the GNU Lesser General Public License. This exception
  23. does not however invalidate any other reasons why the executable file
  24. might be covered by the GNU Lesser General Public License.
  25. ===========================================================================*/
  26. /**@file gmm_blas.h
  27. @author Yves Renard <Yves.Renard@insa-lyon.fr>
  28. @date October 13, 2002.
  29. @brief Basic linear algebra functions.
  30. */
  31. #ifndef GMM_BLAS_H__
  32. #define GMM_BLAS_H__
  33. #include "gmm_scaled.h"
  34. #include "gmm_transposed.h"
  35. #include "gmm_conjugated.h"
  36. namespace gmm {
  37. /* ******************************************************************** */
  38. /* */
  39. /* Generic algorithms */
  40. /* */
  41. /* ******************************************************************** */
  42. /* ******************************************************************** */
  43. /* Miscellaneous */
  44. /* ******************************************************************** */
  45. /** clear (fill with zeros) a vector or matrix. */
  46. template <typename L> inline void clear(L &l)
  47. { linalg_traits<L>::do_clear(l); }
  48. /** @cond DOXY_SHOW_ALL_FUNCTIONS
  49. skip all these redundant definitions in doxygen documentation..
  50. */
  51. template <typename L> inline void clear(const L &l)
  52. { linalg_traits<L>::do_clear(linalg_const_cast(l)); }
  53. ///@endcond
  54. /** count the number of non-zero entries of a vector or matrix. */ template <typename L> inline size_type nnz(const L& l)
  55. { return nnz(l, typename linalg_traits<L>::linalg_type()); }
  56. ///@cond DOXY_SHOW_ALL_FUNCTIONS
  57. template <typename L> inline size_type nnz(const L& l, abstract_vector) {
  58. typename linalg_traits<L>::const_iterator it = vect_const_begin(l),
  59. ite = vect_const_end(l);
  60. size_type res(0);
  61. for (; it != ite; ++it) ++res;
  62. return res;
  63. }
  64. template <typename L> inline size_type nnz(const L& l, abstract_matrix) {
  65. return nnz(l, typename principal_orientation_type<typename
  66. linalg_traits<L>::sub_orientation>::potype());
  67. }
  68. template <typename L> inline size_type nnz(const L& l, row_major) {
  69. size_type res(0);
  70. for (size_type i = 0; i < mat_nrows(l); ++i)
  71. res += nnz(mat_const_row(l, i));
  72. return res;
  73. }
  74. template <typename L> inline size_type nnz(const L& l, col_major) {
  75. size_type res(0);
  76. for (size_type i = 0; i < mat_ncols(l); ++i)
  77. res += nnz(mat_const_col(l, i));
  78. return res;
  79. }
  80. ///@endcond
  81. /** fill a vector or matrix with x. */
  82. template <typename L> inline
  83. void fill(L& l, typename gmm::linalg_traits<L>::value_type x) {
  84. typedef typename gmm::linalg_traits<L>::value_type T;
  85. if (x == T(0)) gmm::clear(l);
  86. fill(l, x, typename linalg_traits<L>::linalg_type());
  87. }
  88. template <typename L> inline
  89. void fill(const L& l, typename gmm::linalg_traits<L>::value_type x) {
  90. fill(linalg_const_cast(l), x);
  91. }
  92. template <typename L> inline // to be optimized for dense vectors ...
  93. void fill(L& l, typename gmm::linalg_traits<L>::value_type x,
  94. abstract_vector) {
  95. for (size_type i = 0; i < vect_size(l); ++i) l[i] = x;
  96. }
  97. template <typename L> inline // to be optimized for dense matrices ...
  98. void fill(L& l, typename gmm::linalg_traits<L>::value_type x,
  99. abstract_matrix) {
  100. for (size_type i = 0; i < mat_nrows(l); ++i)
  101. for (size_type j = 0; j < mat_ncols(l); ++j)
  102. l(i,j) = x;
  103. }
  104. /** fill a vector or matrix with random value (uniform [-1,1]). */
  105. template <typename L> inline void fill_random(L& l)
  106. { fill_random(l, typename linalg_traits<L>::linalg_type()); }
  107. ///@cond DOXY_SHOW_ALL_FUNCTIONS
  108. template <typename L> inline void fill_random(const L& l) {
  109. fill_random(linalg_const_cast(l),
  110. typename linalg_traits<L>::linalg_type());
  111. }
  112. template <typename L> inline void fill_random(L& l, abstract_vector) {
  113. for (size_type i = 0; i < vect_size(l); ++i)
  114. l[i] = gmm::random(typename linalg_traits<L>::value_type());
  115. }
  116. template <typename L> inline void fill_random(L& l, abstract_matrix) {
  117. for (size_type i = 0; i < mat_nrows(l); ++i)
  118. for (size_type j = 0; j < mat_ncols(l); ++j)
  119. l(i,j) = gmm::random(typename linalg_traits<L>::value_type());
  120. }
  121. ///@endcond
  122. /** fill a vector or matrix with random value.
  123. @param l a vector or matrix.
  124. @param cfill probability of a non-zero value.
  125. */
  126. template <typename L> inline void fill_random(L& l, double cfill)
  127. { fill_random(l, cfill, typename linalg_traits<L>::linalg_type()); }
  128. ///@cond DOXY_SHOW_ALL_FUNCTIONS
  129. template <typename L> inline void fill_random(const L& l, double cfill) {
  130. fill_random(linalg_const_cast(l), cfill,
  131. typename linalg_traits<L>::linalg_type());
  132. }
  133. template <typename L> inline
  134. void fill_random(L& l, double cfill, abstract_vector) {
  135. typedef typename linalg_traits<L>::value_type T;
  136. size_type ntot = std::min(vect_size(l),
  137. size_type(double(vect_size(l))*cfill) + 1);
  138. for (size_type nb = 0; nb < ntot;) {
  139. size_type i = gmm::irandom(vect_size(l));
  140. if (l[i] == T(0)) {
  141. l[i] = gmm::random(typename linalg_traits<L>::value_type());
  142. ++nb;
  143. }
  144. }
  145. }
  146. template <typename L> inline
  147. void fill_random(L& l, double cfill, abstract_matrix) {
  148. fill_random(l, cfill, typename principal_orientation_type<typename
  149. linalg_traits<L>::sub_orientation>::potype());
  150. }
  151. template <typename L> inline
  152. void fill_random(L& l, double cfill, row_major) {
  153. for (size_type i=0; i < mat_nrows(l); ++i) fill_random(mat_row(l,i),cfill);
  154. }
  155. template <typename L> inline
  156. void fill_random(L& l, double cfill, col_major) {
  157. for (size_type j=0; j < mat_ncols(l); ++j) fill_random(mat_col(l,j),cfill);
  158. }
  159. /* resize a vector */
  160. template <typename V> inline
  161. void resize(V &v, size_type n, linalg_false)
  162. { linalg_traits<V>::resize(v, n); }
  163. template <typename V> inline
  164. void resize(V &, size_type , linalg_modifiable)
  165. { GMM_ASSERT1(false, "You cannot resize a reference"); }
  166. template <typename V> inline
  167. void resize(V &, size_type , linalg_const)
  168. { GMM_ASSERT1(false, "You cannot resize a reference"); }
  169. ///@endcond
  170. /** resize a vector. */
  171. template <typename V> inline
  172. void resize(V &v, size_type n) {
  173. resize(v, n, typename linalg_traits<V>::is_reference());
  174. }
  175. ///@cond DOXY_SHOW_ALL_FUNCTIONS
  176. /** resize a matrix **/
  177. template <typename M> inline
  178. void resize(M &v, size_type m, size_type n, linalg_false) {
  179. linalg_traits<M>::resize(v, m, n);
  180. }
  181. template <typename M> inline
  182. void resize(M &, size_type, size_type, linalg_modifiable)
  183. { GMM_ASSERT1(false, "You cannot resize a reference"); }
  184. template <typename M> inline
  185. void resize(M &, size_type, size_type, linalg_const)
  186. { GMM_ASSERT1(false, "You cannot resize a reference"); }
  187. ///@endcond
  188. /** resize a matrix */
  189. template <typename M> inline
  190. void resize(M &v, size_type m, size_type n)
  191. { resize(v, m, n, typename linalg_traits<M>::is_reference()); }
  192. ///@cond
  193. template <typename M> inline
  194. void reshape(M &v, size_type m, size_type n, linalg_false)
  195. { linalg_traits<M>::reshape(v, m, n); }
  196. template <typename M> inline
  197. void reshape(M &, size_type, size_type, linalg_modifiable)
  198. { GMM_ASSERT1(false, "You cannot reshape a reference"); }
  199. template <typename M> inline
  200. void reshape(M &, size_type, size_type, linalg_const)
  201. { GMM_ASSERT1(false, "You cannot reshape a reference"); }
  202. ///@endcond
  203. /** reshape a matrix */
  204. template <typename M> inline
  205. void reshape(M &v, size_type m, size_type n)
  206. { reshape(v, m, n, typename linalg_traits<M>::is_reference()); }
  207. ///@cond DOXY_SHOW_ALL_FUNCTIONS
  208. /* ******************************************************************** */
  209. /* Scalar product */
  210. /* ******************************************************************** */
  211. ///@endcond
  212. /** scalar product between two vectors */
  213. template <typename V1, typename V2> inline
  214. typename strongest_value_type<V1,V2>::value_type
  215. vect_sp(const V1 &v1, const V2 &v2) {
  216. GMM_ASSERT2(vect_size(v1) == vect_size(v2), "dimensions mismatch");
  217. return vect_sp(v1, v2,
  218. typename linalg_traits<V1>::storage_type(),
  219. typename linalg_traits<V2>::storage_type());
  220. }
  221. /** scalar product between two vectors, using a matrix.
  222. @param ps the matrix of the scalar product.
  223. @param v1 the first vector
  224. @param v2 the second vector
  225. */
  226. template <typename MATSP, typename V1, typename V2> inline
  227. typename strongest_value_type3<V1,V2,MATSP>::value_type
  228. vect_sp(const MATSP &ps, const V1 &v1, const V2 &v2) {
  229. return vect_sp_with_mat(ps, v1, v2,
  230. typename linalg_traits<MATSP>::sub_orientation());
  231. }
  232. ///@cond DOXY_SHOW_ALL_FUNCTIONS
  233. template <typename MATSP, typename V1, typename V2> inline
  234. typename strongest_value_type3<V1,V2,MATSP>::value_type
  235. vect_sp_with_mat(const MATSP &ps, const V1 &v1, const V2 &v2, row_major) {
  236. return vect_sp_with_matr(ps, v1, v2,
  237. typename linalg_traits<V2>::storage_type());
  238. }
  239. template <typename MATSP, typename V1, typename V2> inline
  240. typename strongest_value_type3<V1,V2,MATSP>::value_type
  241. vect_sp_with_matr(const MATSP &ps, const V1 &v1, const V2 &v2,
  242. abstract_sparse) {
  243. GMM_ASSERT2(vect_size(v1) == mat_ncols(ps) &&
  244. vect_size(v2) == mat_nrows(ps), "dimensions mismatch");
  245. size_type nr = mat_nrows(ps);
  246. typename linalg_traits<V2>::const_iterator
  247. it = vect_const_begin(v2), ite = vect_const_end(v2);
  248. typename strongest_value_type3<V1,V2,MATSP>::value_type res(0);
  249. for (; it != ite; ++it)
  250. res += vect_sp(mat_const_row(ps, it.index()), v1)* (*it);
  251. return res;
  252. }
  253. template <typename MATSP, typename V1, typename V2> inline
  254. typename strongest_value_type3<V1,V2,MATSP>::value_type
  255. vect_sp_with_matr(const MATSP &ps, const V1 &v1, const V2 &v2,
  256. abstract_skyline)
  257. { return vect_sp_with_matr(ps, v1, v2, abstract_sparse()); }
  258. template <typename MATSP, typename V1, typename V2> inline
  259. typename strongest_value_type3<V1,V2,MATSP>::value_type
  260. vect_sp_with_matr(const MATSP &ps, const V1 &v1, const V2 &v2,
  261. abstract_dense) {
  262. GMM_ASSERT2(vect_size(v1) == mat_ncols(ps) &&
  263. vect_size(v2) == mat_nrows(ps), "dimensions mismatch");
  264. typename linalg_traits<V2>::const_iterator
  265. it = vect_const_begin(v2), ite = vect_const_end(v2);
  266. typename strongest_value_type3<V1,V2,MATSP>::value_type res(0);
  267. for (size_type i = 0; it != ite; ++i, ++it)
  268. res += vect_sp(mat_const_row(ps, i), v1) * (*it);
  269. return res;
  270. }
  271. template <typename MATSP, typename V1, typename V2> inline
  272. typename strongest_value_type3<V1,V2,MATSP>::value_type
  273. vect_sp_with_mat(const MATSP &ps, const V1 &v1,const V2 &v2,row_and_col)
  274. { return vect_sp_with_mat(ps, v1, v2, row_major()); }
  275. template <typename MATSP, typename V1, typename V2> inline
  276. typename strongest_value_type3<V1,V2,MATSP>::value_type
  277. vect_sp_with_mat(const MATSP &ps, const V1 &v1, const V2 &v2,col_major){
  278. return vect_sp_with_matc(ps, v1, v2,
  279. typename linalg_traits<V1>::storage_type());
  280. }
  281. template <typename MATSP, typename V1, typename V2> inline
  282. typename strongest_value_type3<V1,V2,MATSP>::value_type
  283. vect_sp_with_matc(const MATSP &ps, const V1 &v1, const V2 &v2,
  284. abstract_sparse) {
  285. GMM_ASSERT2(vect_size(v1) == mat_ncols(ps) &&
  286. vect_size(v2) == mat_nrows(ps),"dimensions mismatch");
  287. typename linalg_traits<V1>::const_iterator
  288. it = vect_const_begin(v1), ite = vect_const_end(v1);
  289. typename strongest_value_type3<V1,V2,MATSP>::value_type res(0);
  290. for (; it != ite; ++it)
  291. res += vect_sp(mat_const_col(ps, it.index()), v2) * (*it);
  292. return res;
  293. }
  294. template <typename MATSP, typename V1, typename V2> inline
  295. typename strongest_value_type3<V1,V2,MATSP>::value_type
  296. vect_sp_with_matc(const MATSP &ps, const V1 &v1, const V2 &v2,
  297. abstract_skyline)
  298. { return vect_sp_with_matc(ps, v1, v2, abstract_sparse()); }
  299. template <typename MATSP, typename V1, typename V2> inline
  300. typename strongest_value_type3<V1,V2,MATSP>::value_type
  301. vect_sp_with_matc(const MATSP &ps, const V1 &v1, const V2 &v2,
  302. abstract_dense) {
  303. GMM_ASSERT2(vect_size(v1) == mat_ncols(ps) &&
  304. vect_size(v2) == mat_nrows(ps), "dimensions mismatch");
  305. typename linalg_traits<V1>::const_iterator
  306. it = vect_const_begin(v1), ite = vect_const_end(v1);
  307. typename strongest_value_type3<V1,V2,MATSP>::value_type res(0);
  308. for (size_type i = 0; it != ite; ++i, ++it)
  309. res += vect_sp(mat_const_col(ps, i), v2) * (*it);
  310. return res;
  311. }
  312. template <typename MATSP, typename V1, typename V2> inline
  313. typename strongest_value_type3<V1,V2,MATSP>::value_type
  314. vect_sp_with_mat(const MATSP &ps, const V1 &v1,const V2 &v2,col_and_row)
  315. { return vect_sp_with_mat(ps, v1, v2, col_major()); }
  316. template <typename MATSP, typename V1, typename V2> inline
  317. typename strongest_value_type3<V1,V2,MATSP>::value_type
  318. vect_sp_with_mat(const MATSP &ps, const V1 &v1, const V2 &v2,
  319. abstract_null_type) {
  320. typename temporary_vector<V1>::vector_type w(mat_nrows(ps));
  321. GMM_WARNING2("Warning, a temporary is used in scalar product\n");
  322. mult(ps, v1, w);
  323. return vect_sp(w, v2);
  324. }
  325. template <typename IT1, typename IT2> inline
  326. typename strongest_numeric_type<typename std::iterator_traits<IT1>::value_type,
  327. typename std::iterator_traits<IT2>::value_type>::T
  328. vect_sp_dense_(IT1 it, IT1 ite, IT2 it2) {
  329. typename strongest_numeric_type<typename std::iterator_traits<IT1>::value_type,
  330. typename std::iterator_traits<IT2>::value_type>::T res(0);
  331. for (; it != ite; ++it, ++it2) res += (*it) * (*it2);
  332. return res;
  333. }
  334. template <typename IT1, typename V> inline
  335. typename strongest_numeric_type<typename std::iterator_traits<IT1>::value_type,
  336. typename linalg_traits<V>::value_type>::T
  337. vect_sp_sparse_(IT1 it, IT1 ite, const V &v) {
  338. typename strongest_numeric_type<typename std::iterator_traits<IT1>::value_type,
  339. typename linalg_traits<V>::value_type>::T res(0);
  340. for (; it != ite; ++it) res += (*it) * v[it.index()];
  341. return res;
  342. }
  343. template <typename V1, typename V2> inline
  344. typename strongest_value_type<V1,V2>::value_type
  345. vect_sp(const V1 &v1, const V2 &v2, abstract_dense, abstract_dense) {
  346. return vect_sp_dense_(vect_const_begin(v1), vect_const_end(v1),
  347. vect_const_begin(v2));
  348. }
  349. template <typename V1, typename V2> inline
  350. typename strongest_value_type<V1,V2>::value_type
  351. vect_sp(const V1 &v1, const V2 &v2, abstract_skyline, abstract_dense) {
  352. typename linalg_traits<V1>::const_iterator it1 = vect_const_begin(v1),
  353. ite = vect_const_end(v1);
  354. typename linalg_traits<V2>::const_iterator it2 = vect_const_begin(v2);
  355. return vect_sp_dense_(it1, ite, it2 + it1.index());
  356. }
  357. template <typename V1, typename V2> inline
  358. typename strongest_value_type<V1,V2>::value_type
  359. vect_sp(const V1 &v1, const V2 &v2, abstract_dense, abstract_skyline) {
  360. typename linalg_traits<V2>::const_iterator it1 = vect_const_begin(v2),
  361. ite = vect_const_end(v2);
  362. typename linalg_traits<V1>::const_iterator it2 = vect_const_begin(v1);
  363. return vect_sp_dense_(it1, ite, it2 + it1.index());
  364. }
  365. template <typename V1, typename V2> inline
  366. typename strongest_value_type<V1,V2>::value_type
  367. vect_sp(const V1 &v1, const V2 &v2, abstract_skyline, abstract_skyline) {
  368. typedef typename strongest_value_type<V1,V2>::value_type T;
  369. typename linalg_traits<V1>::const_iterator it1 = vect_const_begin(v1),
  370. ite1 = vect_const_end(v1);
  371. typename linalg_traits<V2>::const_iterator it2 = vect_const_begin(v2),
  372. ite2 = vect_const_end(v2);
  373. size_type n = std::min(ite1.index(), ite2.index());
  374. size_type l = std::max(it1.index(), it2.index());
  375. if (l < n) {
  376. size_type m = l - it1.index(), p = l - it2.index(), q = m + n - l;
  377. return vect_sp_dense_(it1+m, it1+q, it2 + p);
  378. }
  379. return T(0);
  380. }
  381. template <typename V1, typename V2> inline
  382. typename strongest_value_type<V1,V2>::value_type
  383. vect_sp(const V1 &v1, const V2 &v2,abstract_sparse,abstract_dense) {
  384. return vect_sp_sparse_(vect_const_begin(v1), vect_const_end(v1), v2);
  385. }
  386. template <typename V1, typename V2> inline
  387. typename strongest_value_type<V1,V2>::value_type
  388. vect_sp(const V1 &v1, const V2 &v2, abstract_sparse, abstract_skyline) {
  389. return vect_sp_sparse_(vect_const_begin(v1), vect_const_end(v1), v2);
  390. }
  391. template <typename V1, typename V2> inline
  392. typename strongest_value_type<V1,V2>::value_type
  393. vect_sp(const V1 &v1, const V2 &v2, abstract_skyline, abstract_sparse) {
  394. return vect_sp_sparse_(vect_const_begin(v2), vect_const_end(v2), v1);
  395. }
  396. template <typename V1, typename V2> inline
  397. typename strongest_value_type<V1,V2>::value_type
  398. vect_sp(const V1 &v1, const V2 &v2, abstract_dense,abstract_sparse) {
  399. return vect_sp_sparse_(vect_const_begin(v2), vect_const_end(v2), v1);
  400. }
  401. template <typename V1, typename V2> inline
  402. typename strongest_value_type<V1,V2>::value_type
  403. vect_sp_sparse_sparse(const V1 &v1, const V2 &v2, linalg_true) {
  404. typename linalg_traits<V1>::const_iterator it1 = vect_const_begin(v1),
  405. ite1 = vect_const_end(v1);
  406. typename linalg_traits<V2>::const_iterator it2 = vect_const_begin(v2),
  407. ite2 = vect_const_end(v2);
  408. typename strongest_value_type<V1,V2>::value_type res(0);
  409. while (it1 != ite1 && it2 != ite2) {
  410. if (it1.index() == it2.index())
  411. { res += (*it1) * *it2; ++it1; ++it2; }
  412. else if (it1.index() < it2.index()) ++it1; else ++it2;
  413. }
  414. return res;
  415. }
  416. template <typename V1, typename V2> inline
  417. typename strongest_value_type<V1,V2>::value_type
  418. vect_sp_sparse_sparse(const V1 &v1, const V2 &v2, linalg_false) {
  419. return vect_sp_sparse_(vect_const_begin(v1), vect_const_end(v1), v2);
  420. }
  421. template <typename V1, typename V2> inline
  422. typename strongest_value_type<V1,V2>::value_type
  423. vect_sp(const V1 &v1, const V2 &v2,abstract_sparse,abstract_sparse) {
  424. return vect_sp_sparse_sparse(v1, v2,
  425. typename linalg_and<typename linalg_traits<V1>::index_sorted,
  426. typename linalg_traits<V2>::index_sorted>::bool_type());
  427. }
  428. /* ******************************************************************** */
  429. /* Hermitian product */
  430. /* ******************************************************************** */
  431. ///@endcond
  432. /** Hermitian product. */
  433. template <typename V1, typename V2>
  434. inline typename strongest_value_type<V1,V2>::value_type
  435. vect_hp(const V1 &v1, const V2 &v2)
  436. { return vect_sp(v1, conjugated(v2)); }
  437. /** Hermitian product with a matrix. */
  438. template <typename MATSP, typename V1, typename V2> inline
  439. typename strongest_value_type3<V1,V2,MATSP>::value_type
  440. vect_hp(const MATSP &ps, const V1 &v1, const V2 &v2) {
  441. return vect_sp(ps, v1, gmm::conjugated(v2));
  442. }
  443. /* ******************************************************************** */
  444. /* Trace of a matrix */
  445. /* ******************************************************************** */
  446. /** Trace of a matrix */
  447. template <typename M>
  448. typename linalg_traits<M>::value_type
  449. mat_trace(const M &m) {
  450. typedef typename linalg_traits<M>::value_type T;
  451. T res(0);
  452. for (size_type i = 0; i < std::min(mat_nrows(m), mat_ncols(m)); ++i)
  453. res += m(i,i);
  454. return res;
  455. }
  456. /* ******************************************************************** */
  457. /* Euclidean norm */
  458. /* ******************************************************************** */
  459. /** Euclidean norm of a vector. */
  460. template <typename V>
  461. typename number_traits<typename linalg_traits<V>::value_type>
  462. ::magnitude_type
  463. vect_norm2_sqr(const V &v) {
  464. typedef typename linalg_traits<V>::value_type T;
  465. typedef typename number_traits<T>::magnitude_type R;
  466. typename linalg_traits<V>::const_iterator
  467. it = vect_const_begin(v), ite = vect_const_end(v);
  468. R res(0);
  469. for (; it != ite; ++it) res += gmm::abs_sqr(*it);
  470. return res;
  471. }
  472. /** squared Euclidean norm of a vector. */
  473. template <typename V> inline
  474. typename number_traits<typename linalg_traits<V>::value_type>
  475. ::magnitude_type
  476. vect_norm2(const V &v)
  477. { return sqrt(vect_norm2_sqr(v)); }
  478. /** squared Euclidean distance between two vectors */
  479. template <typename V1, typename V2> inline
  480. typename number_traits<typename linalg_traits<V1>::value_type>
  481. ::magnitude_type
  482. vect_dist2_sqr(const V1 &v1, const V2 &v2) { // not fully optimized
  483. typedef typename linalg_traits<V1>::value_type T;
  484. typedef typename number_traits<T>::magnitude_type R;
  485. typename linalg_traits<V1>::const_iterator
  486. it1 = vect_const_begin(v1), ite1 = vect_const_end(v1);
  487. typename linalg_traits<V2>::const_iterator
  488. it2 = vect_const_begin(v2), ite2 = vect_const_end(v2);
  489. size_type k1(0), k2(0);
  490. R res(0);
  491. while (it1 != ite1 && it2 != ite2) {
  492. size_type i1 = index_of_it(it1, k1,
  493. typename linalg_traits<V1>::storage_type());
  494. size_type i2 = index_of_it(it2, k2,
  495. typename linalg_traits<V2>::storage_type());
  496. if (i1 == i2) {
  497. res += gmm::abs_sqr(*it2 - *it1); ++it1; ++k1; ++it2; ++k2;
  498. }
  499. else if (i1 < i2) {
  500. res += gmm::abs_sqr(*it1); ++it1; ++k1;
  501. }
  502. else {
  503. res += gmm::abs_sqr(*it2); ++it2; ++k2;
  504. }
  505. }
  506. while (it1 != ite1) { res += gmm::abs_sqr(*it1); ++it1; }
  507. while (it2 != ite2) { res += gmm::abs_sqr(*it2); ++it2; }
  508. return res;
  509. }
  510. /** Euclidean distance between two vectors */
  511. template <typename V1, typename V2> inline
  512. typename number_traits<typename linalg_traits<V1>::value_type>
  513. ::magnitude_type
  514. vect_dist2(const V1 &v1, const V2 &v2)
  515. { return sqrt(vect_dist2_sqr(v1, v2)); }
  516. ///@cond DOXY_SHOW_ALL_FUNCTIONS
  517. template <typename M>
  518. typename number_traits<typename linalg_traits<M>::value_type>
  519. ::magnitude_type
  520. mat_euclidean_norm_sqr(const M &m, row_major) {
  521. typename number_traits<typename linalg_traits<M>::value_type>
  522. ::magnitude_type res(0);
  523. for (size_type i = 0; i < mat_nrows(m); ++i)
  524. res += vect_norm2_sqr(mat_const_row(m, i));
  525. return res;
  526. }
  527. template <typename M>
  528. typename number_traits<typename linalg_traits<M>::value_type>
  529. ::magnitude_type
  530. mat_euclidean_norm_sqr(const M &m, col_major) {
  531. typename number_traits<typename linalg_traits<M>::value_type>
  532. ::magnitude_type res(0);
  533. for (size_type i = 0; i < mat_ncols(m); ++i)
  534. res += vect_norm2_sqr(mat_const_col(m, i));
  535. return res;
  536. }
  537. ///@endcond
  538. /** squared Euclidean norm of a matrix. */
  539. template <typename M> inline
  540. typename number_traits<typename linalg_traits<M>::value_type>
  541. ::magnitude_type
  542. mat_euclidean_norm_sqr(const M &m) {
  543. return mat_euclidean_norm_sqr(m,
  544. typename principal_orientation_type<typename
  545. linalg_traits<M>::sub_orientation>::potype());
  546. }
  547. /** Euclidean norm of a matrix. */
  548. template <typename M> inline
  549. typename number_traits<typename linalg_traits<M>::value_type>
  550. ::magnitude_type
  551. mat_euclidean_norm(const M &m)
  552. { return gmm::sqrt(mat_euclidean_norm_sqr(m)); }
  553. /* ******************************************************************** */
  554. /* vector norm1 */
  555. /* ******************************************************************** */
  556. /** 1-norm of a vector */
  557. template <typename V>
  558. typename number_traits<typename linalg_traits<V>::value_type>
  559. ::magnitude_type
  560. vect_norm1(const V &v) {
  561. typename linalg_traits<V>::const_iterator
  562. it = vect_const_begin(v), ite = vect_const_end(v);
  563. typename number_traits<typename linalg_traits<V>::value_type>
  564. ::magnitude_type res(0);
  565. for (; it != ite; ++it) res += gmm::abs(*it);
  566. return res;
  567. }
  568. /* ******************************************************************** */
  569. /* vector Infinity norm */
  570. /* ******************************************************************** */
  571. /** Infinity norm of a vector. */
  572. template <typename V>
  573. typename number_traits<typename linalg_traits<V>::value_type>
  574. ::magnitude_type
  575. vect_norminf(const V &v) {
  576. typename linalg_traits<V>::const_iterator
  577. it = vect_const_begin(v), ite = vect_const_end(v);
  578. typename number_traits<typename linalg_traits<V>::value_type>
  579. ::magnitude_type res(0);
  580. for (; it != ite; ++it) res = std::max(res, gmm::abs(*it));
  581. return res;
  582. }
  583. /* ******************************************************************** */
  584. /* matrix norm1 */
  585. /* ******************************************************************** */
  586. ///@cond DOXY_SHOW_ALL_FUNCTIONS
  587. template <typename M>
  588. typename number_traits<typename linalg_traits<M>::value_type>
  589. ::magnitude_type
  590. mat_norm1(const M &m, col_major) {
  591. typename number_traits<typename linalg_traits<M>::value_type>
  592. ::magnitude_type res(0);
  593. for (size_type i = 0; i < mat_ncols(m); ++i)
  594. res = std::max(res, vect_norm1(mat_const_col(m,i)));
  595. return res;
  596. }
  597. template <typename M>
  598. typename number_traits<typename linalg_traits<M>::value_type>
  599. ::magnitude_type
  600. mat_norm1(const M &m, row_major) {
  601. typedef typename linalg_traits<M>::value_type T;
  602. typedef typename number_traits<T>::magnitude_type R;
  603. typedef typename linalg_traits<M>::storage_type store_type;
  604. std::vector<R> aux(mat_ncols(m));
  605. for (size_type i = 0; i < mat_nrows(m); ++i) {
  606. typedef typename linalg_traits<M>::const_sub_row_type row_type;
  607. row_type row = mat_const_row(m, i);
  608. typename linalg_traits<row_type>::const_iterator
  609. it = vect_const_begin(row), ite = vect_const_end(row);
  610. for (size_type k = 0; it != ite; ++it, ++k)
  611. aux[index_of_it(it, k, store_type())] += gmm::abs(*it);
  612. }
  613. return vect_norminf(aux);
  614. }
  615. template <typename M>
  616. typename number_traits<typename linalg_traits<M>::value_type>
  617. ::magnitude_type
  618. mat_norm1(const M &m, col_and_row)
  619. { return mat_norm1(m, col_major()); }
  620. template <typename M>
  621. typename number_traits<typename linalg_traits<M>::value_type>
  622. ::magnitude_type
  623. mat_norm1(const M &m, row_and_col)
  624. { return mat_norm1(m, col_major()); }
  625. ///@endcond
  626. /** 1-norm of a matrix */
  627. template <typename M>
  628. typename number_traits<typename linalg_traits<M>::value_type>
  629. ::magnitude_type
  630. mat_norm1(const M &m) {
  631. return mat_norm1(m, typename linalg_traits<M>::sub_orientation());
  632. }
  633. /* ******************************************************************** */
  634. /* matrix Infinity norm */
  635. /* ******************************************************************** */
  636. ///@cond DOXY_SHOW_ALL_FUNCTIONS
  637. template <typename M>
  638. typename number_traits<typename linalg_traits<M>::value_type>
  639. ::magnitude_type
  640. mat_norminf(const M &m, row_major) {
  641. typename number_traits<typename linalg_traits<M>::value_type>
  642. ::magnitude_type res(0);
  643. for (size_type i = 0; i < mat_nrows(m); ++i)
  644. res = std::max(res, vect_norm1(mat_const_row(m,i)));
  645. return res;
  646. }
  647. template <typename M>
  648. typename number_traits<typename linalg_traits<M>::value_type>
  649. ::magnitude_type
  650. mat_norminf(const M &m, col_major) {
  651. typedef typename linalg_traits<M>::value_type T;
  652. typedef typename number_traits<T>::magnitude_type R;
  653. typedef typename linalg_traits<M>::storage_type store_type;
  654. std::vector<R> aux(mat_nrows(m));
  655. for (size_type i = 0; i < mat_ncols(m); ++i) {
  656. typedef typename linalg_traits<M>::const_sub_col_type col_type;
  657. col_type col = mat_const_col(m, i);
  658. typename linalg_traits<col_type>::const_iterator
  659. it = vect_const_begin(col), ite = vect_const_end(col);
  660. for (size_type k = 0; it != ite; ++it, ++k)
  661. aux[index_of_it(it, k, store_type())] += gmm::abs(*it);
  662. }
  663. return vect_norminf(aux);
  664. }
  665. template <typename M>
  666. typename number_traits<typename linalg_traits<M>::value_type>
  667. ::magnitude_type
  668. mat_norminf(const M &m, col_and_row)
  669. { return mat_norminf(m, row_major()); }
  670. template <typename M>
  671. typename number_traits<typename linalg_traits<M>::value_type>
  672. ::magnitude_type
  673. mat_norminf(const M &m, row_and_col)
  674. { return mat_norminf(m, row_major()); }
  675. ///@endcond
  676. /** infinity-norm of a matrix.*/
  677. template <typename M>
  678. typename number_traits<typename linalg_traits<M>::value_type>
  679. ::magnitude_type
  680. mat_norminf(const M &m) {
  681. return mat_norminf(m, typename linalg_traits<M>::sub_orientation());
  682. }
  683. /* ******************************************************************** */
  684. /* Max norm for matrices */
  685. /* ******************************************************************** */
  686. ///@cond DOXY_SHOW_ALL_FUNCTIONS
  687. template <typename M>
  688. typename number_traits<typename linalg_traits<M>::value_type>
  689. ::magnitude_type
  690. mat_maxnorm(const M &m, row_major) {
  691. typename number_traits<typename linalg_traits<M>::value_type>
  692. ::magnitude_type res(0);
  693. for (size_type i = 0; i < mat_nrows(m); ++i)
  694. res = std::max(res, vect_norminf(mat_const_row(m,i)));
  695. return res;
  696. }
  697. template <typename M>
  698. typename number_traits<typename linalg_traits<M>::value_type>
  699. ::magnitude_type
  700. mat_maxnorm(const M &m, col_major) {
  701. typename number_traits<typename linalg_traits<M>::value_type>
  702. ::magnitude_type res(0);
  703. for (size_type i = 0; i < mat_ncols(m); ++i)
  704. res = std::max(res, vect_norminf(mat_const_col(m,i)));
  705. return res;
  706. }
  707. ///@endcond
  708. /** max-norm of a matrix. */
  709. template <typename M>
  710. typename number_traits<typename linalg_traits<M>::value_type>
  711. ::magnitude_type
  712. mat_maxnorm(const M &m) {
  713. return mat_maxnorm(m,
  714. typename principal_orientation_type<typename
  715. linalg_traits<M>::sub_orientation>::potype());
  716. }
  717. /* ******************************************************************** */
  718. /* Clean */
  719. /* ******************************************************************** */
  720. /** Clean a vector or matrix (replace near-zero entries with zeroes). */
  721. template <typename L> inline void clean(L &l, double threshold);
  722. ///@cond DOXY_SHOW_ALL_FUNCTIONS
  723. template <typename L, typename T>
  724. void clean(L &l, double threshold, abstract_dense, T) {
  725. typedef typename number_traits<T>::magnitude_type R;
  726. typename linalg_traits<L>::iterator it = vect_begin(l), ite = vect_end(l);
  727. for (; it != ite; ++it)
  728. if (gmm::abs(*it) < R(threshold)) *it = T(0);
  729. }
  730. template <typename L, typename T>
  731. void clean(L &l, double threshold, abstract_skyline, T)
  732. { gmm::clean(l, threshold, abstract_dense(), T()); }
  733. template <typename L, typename T>
  734. void clean(L &l, double threshold, abstract_sparse, T) {
  735. typedef typename number_traits<T>::magnitude_type R;
  736. typename linalg_traits<L>::iterator it = vect_begin(l), ite = vect_end(l);
  737. std::vector<size_type> ind;
  738. for (; it != ite; ++it)
  739. if (gmm::abs(*it) < R(threshold)) ind.push_back(it.index());
  740. for (size_type i = 0; i < ind.size(); ++i) l[ind[i]] = T(0);
  741. }
  742. template <typename L, typename T>
  743. void clean(L &l, double threshold, abstract_dense, std::complex<T>) {
  744. typename linalg_traits<L>::iterator it = vect_begin(l), ite = vect_end(l);
  745. for (; it != ite; ++it){
  746. if (gmm::abs((*it).real()) < T(threshold))
  747. *it = std::complex<T>(T(0), (*it).imag());
  748. if (gmm::abs((*it).imag()) < T(threshold))
  749. *it = std::complex<T>((*it).real(), T(0));
  750. }
  751. }
  752. template <typename L, typename T>
  753. void clean(L &l, double threshold, abstract_skyline, std::complex<T>)
  754. { gmm::clean(l, threshold, abstract_dense(), std::complex<T>()); }
  755. template <typename L, typename T>
  756. void clean(L &l, double threshold, abstract_sparse, std::complex<T>) {
  757. typename linalg_traits<L>::iterator it = vect_begin(l), ite = vect_end(l);
  758. std::vector<size_type> ind;
  759. for (; it != ite; ++it) {
  760. bool r = (gmm::abs((*it).real()) < T(threshold));
  761. bool i = (gmm::abs((*it).imag()) < T(threshold));
  762. if (r && i) ind.push_back(it.index());
  763. else if (r) (*it).real() = T(0);
  764. else if (i) (*it).imag() = T(0);
  765. }
  766. for (size_type i = 0; i < ind.size(); ++i)
  767. l[ind[i]] = std::complex<T>(T(0),T(0));
  768. }
  769. template <typename L> inline void clean(L &l, double threshold,
  770. abstract_vector) {
  771. gmm::clean(l, threshold, typename linalg_traits<L>::storage_type(),
  772. typename linalg_traits<L>::value_type());
  773. }
  774. template <typename L> inline void clean(const L &l, double threshold);
  775. template <typename L> void clean(L &l, double threshold, row_major) {
  776. for (size_type i = 0; i < mat_nrows(l); ++i)
  777. gmm::clean(mat_row(l, i), threshold);
  778. }
  779. template <typename L> void clean(L &l, double threshold, col_major) {
  780. for (size_type i = 0; i < mat_ncols(l); ++i)
  781. gmm::clean(mat_col(l, i), threshold);
  782. }
  783. template <typename L> inline void clean(L &l, double threshold,
  784. abstract_matrix) {
  785. gmm::clean(l, threshold,
  786. typename principal_orientation_type<typename
  787. linalg_traits<L>::sub_orientation>::potype());
  788. }
  789. template <typename L> inline void clean(L &l, double threshold)
  790. { clean(l, threshold, typename linalg_traits<L>::linalg_type()); }
  791. template <typename L> inline void clean(const L &l, double threshold)
  792. { gmm::clean(linalg_const_cast(l), threshold); }
  793. /* ******************************************************************** */
  794. /* Copy */
  795. /* ******************************************************************** */
  796. ///@endcond
  797. /** Copy vectors or matrices.
  798. @param l1 source vector or matrix.
  799. @param l2 destination.
  800. */
  801. template <typename L1, typename L2> inline
  802. void copy(const L1& l1, L2& l2) {
  803. if ((const void *)(&l1) != (const void *)(&l2)) {
  804. if (same_origin(l1,l2))
  805. GMM_WARNING2("Warning : a conflict is possible in copy\n");
  806. copy(l1, l2, typename linalg_traits<L1>::linalg_type(),
  807. typename linalg_traits<L2>::linalg_type());
  808. }
  809. }
  810. ///@cond DOXY_SHOW_ALL_FUNCTIONS
  811. template <typename L1, typename L2> inline
  812. void copy(const L1& l1, const L2& l2) { copy(l1, linalg_const_cast(l2)); }
  813. template <typename L1, typename L2> inline
  814. void copy(const L1& l1, L2& l2, abstract_vector, abstract_vector) {
  815. GMM_ASSERT2(vect_size(l1) == vect_size(l2), "dimensions mismatch");
  816. copy_vect(l1, l2, typename linalg_traits<L1>::storage_type(),
  817. typename linalg_traits<L2>::storage_type());
  818. }
  819. template <typename L1, typename L2> inline
  820. void copy(const L1& l1, L2& l2, abstract_matrix, abstract_matrix) {
  821. size_type m = mat_nrows(l1), n = mat_ncols(l1);
  822. if (!m || !n) return;
  823. GMM_ASSERT2(n==mat_ncols(l2) && m==mat_nrows(l2), "dimensions mismatch");
  824. copy_mat(l1, l2, typename linalg_traits<L1>::sub_orientation(),
  825. typename linalg_traits<L2>::sub_orientation());
  826. }
  827. template <typename V1, typename V2, typename C1, typename C2> inline
  828. void copy_vect(const V1 &v1, const V2 &v2, C1, C2)
  829. { copy_vect(v1, const_cast<V2 &>(v2), C1(), C2()); }
  830. template <typename L1, typename L2>
  831. void copy_mat_by_row(const L1& l1, L2& l2) {
  832. size_type nbr = mat_nrows(l1);
  833. for (size_type i = 0; i < nbr; ++i)
  834. copy_vect(mat_const_row(l1, i), mat_row(l2, i),
  835. typename linalg_traits<L1>::storage_type(),
  836. typename linalg_traits<L2>::storage_type());
  837. }
  838. template <typename L1, typename L2>
  839. void copy_mat_by_col(const L1 &l1, L2 &l2) {
  840. size_type nbc = mat_ncols(l1);
  841. for (size_type i = 0; i < nbc; ++i) {
  842. copy_vect(mat_const_col(l1, i), mat_col(l2, i),
  843. typename linalg_traits<L1>::storage_type(),
  844. typename linalg_traits<L2>::storage_type());
  845. }
  846. }
  847. template <typename L1, typename L2> inline
  848. void copy_mat(const L1& l1, L2& l2, row_major, row_major)
  849. { copy_mat_by_row(l1, l2); }
  850. template <typename L1, typename L2> inline
  851. void copy_mat(const L1& l1, L2& l2, row_major, row_and_col)
  852. { copy_mat_by_row(l1, l2); }
  853. template <typename L1, typename L2> inline
  854. void copy_mat(const L1& l1, L2& l2, row_and_col, row_and_col)
  855. { copy_mat_by_row(l1, l2); }
  856. template <typename L1, typename L2> inline
  857. void copy_mat(const L1& l1, L2& l2, row_and_col, row_major)
  858. { copy_mat_by_row(l1, l2); }
  859. template <typename L1, typename L2> inline
  860. void copy_mat(const L1& l1, L2& l2, col_and_row, row_major)
  861. { copy_mat_by_row(l1, l2); }
  862. template <typename L1, typename L2> inline
  863. void copy_mat(const L1& l1, L2& l2, row_major, col_and_row)
  864. { copy_mat_by_row(l1, l2); }
  865. template <typename L1, typename L2> inline
  866. void copy_mat(const L1& l1, L2& l2, col_and_row, row_and_col)
  867. { copy_mat_by_row(l1, l2); }
  868. template <typename L1, typename L2> inline
  869. void copy_mat(const L1& l1, L2& l2, row_and_col, col_and_row)
  870. { copy_mat_by_row(l1, l2); }
  871. template <typename L1, typename L2> inline
  872. void copy_mat(const L1& l1, L2& l2, col_major, col_major)
  873. { copy_mat_by_col(l1, l2); }
  874. template <typename L1, typename L2> inline
  875. void copy_mat(const L1& l1, L2& l2, col_major, col_and_row)
  876. { copy_mat_by_col(l1, l2); }
  877. template <typename L1, typename L2> inline
  878. void copy_mat(const L1& l1, L2& l2, col_major, row_and_col)
  879. { copy_mat_by_col(l1, l2); }
  880. template <typename L1, typename L2> inline
  881. void copy_mat(const L1& l1, L2& l2, row_and_col, col_major)
  882. { copy_mat_by_col(l1, l2); }
  883. template <typename L1, typename L2> inline
  884. void copy_mat(const L1& l1, L2& l2, col_and_row, col_major)
  885. { copy_mat_by_col(l1, l2); }
  886. template <typename L1, typename L2> inline
  887. void copy_mat(const L1& l1, L2& l2, col_and_row, col_and_row)
  888. { copy_mat_by_col(l1, l2); }
  889. template <typename L1, typename L2> inline
  890. void copy_mat_mixed_rc(const L1& l1, L2& l2, size_type i) {
  891. copy_mat_mixed_rc(l1, l2, i, typename linalg_traits<L1>::storage_type());
  892. }
  893. template <typename L1, typename L2>
  894. void copy_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_sparse) {
  895. typename linalg_traits<L1>::const_iterator
  896. it = vect_const_begin(l1), ite = vect_const_end(l1);
  897. for (; it != ite; ++it)
  898. l2(i, it.index()) = *it;
  899. }
  900. template <typename L1, typename L2>
  901. void copy_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_skyline) {
  902. typename linalg_traits<L1>::const_iterator
  903. it = vect_const_begin(l1), ite = vect_const_end(l1);
  904. for (; it != ite; ++it)
  905. l2(i, it.index()) = *it;
  906. }
  907. template <typename L1, typename L2>
  908. void copy_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_dense) {
  909. typename linalg_traits<L1>::const_iterator
  910. it = vect_const_begin(l1), ite = vect_const_end(l1);
  911. for (size_type j = 0; it != ite; ++it, ++j) l2(i, j) = *it;
  912. }
  913. template <typename L1, typename L2> inline
  914. void copy_mat_mixed_cr(const L1& l1, L2& l2, size_type i) {
  915. copy_mat_mixed_cr(l1, l2, i, typename linalg_traits<L1>::storage_type());
  916. }
  917. template <typename L1, typename L2>
  918. void copy_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_sparse) {
  919. typename linalg_traits<L1>::const_iterator
  920. it = vect_const_begin(l1), ite = vect_const_end(l1);
  921. for (; it != ite; ++it) l2(it.index(), i) = *it;
  922. }
  923. template <typename L1, typename L2>
  924. void copy_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_skyline) {
  925. typename linalg_traits<L1>::const_iterator
  926. it = vect_const_begin(l1), ite = vect_const_end(l1);
  927. for (; it != ite; ++it) l2(it.index(), i) = *it;
  928. }
  929. template <typename L1, typename L2>
  930. void copy_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_dense) {
  931. typename linalg_traits<L1>::const_iterator
  932. it = vect_const_begin(l1), ite = vect_const_end(l1);
  933. for (size_type j = 0; it != ite; ++it, ++j) l2(j, i) = *it;
  934. }
  935. template <typename L1, typename L2>
  936. void copy_mat(const L1& l1, L2& l2, row_major, col_major) {
  937. clear(l2);
  938. size_type nbr = mat_nrows(l1);
  939. for (size_type i = 0; i < nbr; ++i)
  940. copy_mat_mixed_rc(mat_const_row(l1, i), l2, i);
  941. }
  942. template <typename L1, typename L2>
  943. void copy_mat(const L1& l1, L2& l2, col_major, row_major) {
  944. clear(l2);
  945. size_type nbc = mat_ncols(l1);
  946. for (size_type i = 0; i < nbc; ++i)
  947. copy_mat_mixed_cr(mat_const_col(l1, i), l2, i);
  948. }
  949. template <typename L1, typename L2> inline
  950. void copy_vect(const L1 &l1, L2 &l2, abstract_dense, abstract_dense) {
  951. std::copy(vect_const_begin(l1), vect_const_end(l1), vect_begin(l2));
  952. }
  953. template <typename L1, typename L2> inline // to be optimised ?
  954. void copy_vect(const L1 &l1, L2 &l2, abstract_skyline, abstract_skyline) {
  955. typename linalg_traits<L1>::const_iterator it1 = vect_const_begin(l1),
  956. ite1 = vect_const_end(l1);
  957. while (it1 != ite1 && *it1 == typename linalg_traits<L1>::value_type(0))
  958. ++it1;
  959. if (ite1 - it1 > 0) {
  960. clear(l2);
  961. typename linalg_traits<L2>::iterator it2 = vect_begin(l2),
  962. ite2 = vect_end(l2);
  963. while (*(ite1-1) == typename linalg_traits<L1>::value_type(0)) ite1--;
  964. if (it2 == ite2) {
  965. l2[it1.index()] = *it1; ++it1;
  966. l2[ite1.index()-1] = *(ite1-1); --ite1;
  967. if (it1 < ite1)
  968. { it2 = vect_begin(l2); ++it2; std::copy(it1, ite1, it2); }
  969. }
  970. else {
  971. ptrdiff_t m = it1.index() - it2.index();
  972. if (m >= 0 && ite1.index() <= ite2.index())
  973. std::copy(it1, ite1, it2 + m);
  974. else {
  975. if (m < 0) l2[it1.index()] = *it1;
  976. if (ite1.index() > ite2.index()) l2[ite1.index()-1] = *(ite1-1);
  977. it2 = vect_begin(l2); ite2 = vect_end(l2);
  978. m = it1.index() - it2.index();
  979. std::copy(it1, ite1, it2 + m);
  980. }
  981. }
  982. }
  983. }
  984. template <typename L1, typename L2>
  985. void copy_vect(const L1& l1, L2& l2, abstract_sparse, abstract_dense) {
  986. clear(l2);
  987. typename linalg_traits<L1>::const_iterator
  988. it = vect_const_begin(l1), ite = vect_const_end(l1);
  989. for (; it != ite; ++it) { l2[it.index()] = *it; }
  990. }
  991. template <typename L1, typename L2>
  992. void copy_vect(const L1& l1, L2& l2, abstract_sparse, abstract_skyline) {
  993. clear(l2);
  994. typename linalg_traits<L1>::const_iterator
  995. it = vect_const_begin(l1), ite = vect_const_end(l1);
  996. for (; it != ite; ++it) l2[it.index()] = *it;
  997. }
  998. template <typename L1, typename L2>
  999. void copy_vect(const L1& l1, L2& l2, abstract_skyline, abstract_dense) {
  1000. typedef typename linalg_traits<L1>::value_type T;
  1001. typedef typename linalg_traits<L1>::const_iterator l1_const_iterator;
  1002. typedef typename linalg_traits<L2>::iterator l2_iterator;
  1003. l1_const_iterator it = vect_const_begin(l1), ite = vect_const_end(l1);
  1004. if (it == ite)
  1005. gmm::clear(l2);
  1006. else {
  1007. l2_iterator it2 = vect_begin(l2), ite2 = vect_end(l2);
  1008. size_type i = it.index(), j;
  1009. for (j = 0; j < i; ++j, ++it2) *it2 = T(0);
  1010. for (; it != ite; ++it, ++it2) *it2 = *it;
  1011. for (; it2 != ite2; ++it2) *it2 = T(0);
  1012. }
  1013. }
  1014. template <typename L1, typename L2>
  1015. void copy_vect(const L1& l1, L2& l2, abstract_sparse, abstract_sparse) {
  1016. typename linalg_traits<L1>::const_iterator
  1017. it = vect_const_begin(l1), ite = vect_const_end(l1);
  1018. clear(l2);
  1019. for (; it != ite; ++it)
  1020. if (*it != (typename linalg_traits<L1>::value_type)(0))
  1021. l2[it.index()] = *it;
  1022. }
  1023. template <typename L1, typename L2>
  1024. void copy_vect(const L1& l1, L2& l2, abstract_dense, abstract_sparse) {
  1025. clear(l2);
  1026. typename linalg_traits<L1>::const_iterator
  1027. it = vect_const_begin(l1), ite = vect_const_end(l1);
  1028. for (size_type i = 0; it != ite; ++it, ++i)
  1029. if (*it != (typename linalg_traits<L1>::value_type)(0))
  1030. l2[i] = *it;
  1031. }
  1032. template <typename L1, typename L2> // to be optimised ...
  1033. void copy_vect(const L1& l1, L2& l2, abstract_dense, abstract_skyline) {
  1034. clear(l2);
  1035. typename linalg_traits<L1>::const_iterator
  1036. it = vect_const_begin(l1), ite = vect_const_end(l1);
  1037. for (size_type i = 0; it != ite; ++it, ++i)
  1038. if (*it != (typename linalg_traits<L1>::value_type)(0))
  1039. l2[i] = *it;
  1040. }
  1041. template <typename L1, typename L2>
  1042. void copy_vect(const L1& l1, L2& l2, abstract_skyline, abstract_sparse) {
  1043. clear(l2);
  1044. typename linalg_traits<L1>::const_iterator
  1045. it = vect_const_begin(l1), ite = vect_const_end(l1);
  1046. for (; it != ite; ++it)
  1047. if (*it != (typename linalg_traits<L1>::value_type)(0))
  1048. l2[it.index()] = *it;
  1049. }
  1050. /* ******************************************************************** */
  1051. /* Matrix and vector addition */
  1052. /* algorithms are built in order to avoid some conflicts whith */
  1053. /* repeated arguments or with overlapping part of a same object. */
  1054. /* In the latter case, conflicts are still possible. */
  1055. /* ******************************************************************** */
  1056. ///@endcond
  1057. /** Add two vectors or matrices
  1058. @param l1
  1059. @param l2 contains on output, l2+l1.
  1060. */
  1061. template <typename L1, typename L2> inline
  1062. void add(const L1& l1, L2& l2) {
  1063. add_spec(l1, l2, typename linalg_traits<L2>::linalg_type());
  1064. }
  1065. ///@cond
  1066. template <typename L1, typename L2> inline
  1067. void add(const L1& l1, const L2& l2) { add(l1, linalg_const_cast(l2)); }
  1068. template <typename L1, typename L2> inline
  1069. void add_spec(const L1& l1, L2& l2, abstract_vector) {
  1070. GMM_ASSERT2(vect_size(l1) == vect_size(l2), "dimensions mismatch");
  1071. add(l1, l2, typename linalg_traits<L1>::storage_type(),
  1072. typename linalg_traits<L2>::storage_type());
  1073. }
  1074. template <typename L1, typename L2> inline
  1075. void add_spec(const L1& l1, L2& l2, abstract_matrix) {
  1076. size_type m = mat_nrows(l1), n = mat_ncols(l1);
  1077. GMM_ASSERT2(m==mat_nrows(l2) && n==mat_ncols(l2), "dimensions mismatch");
  1078. add(l1, l2, typename linalg_traits<L1>::sub_orientation(),
  1079. typename linalg_traits<L2>::sub_orientation());
  1080. }
  1081. template <typename L1, typename L2>
  1082. void add(const L1& l1, L2& l2, row_major, row_major) {
  1083. typename linalg_traits<L1>::const_row_iterator it1 = mat_row_begin(l1),
  1084. ite = mat_row_end(l1);
  1085. typename linalg_traits<L2>::row_iterator it2 = mat_row_begin(l2);
  1086. for ( ; it1 != ite; ++it1, ++it2)
  1087. add(linalg_traits<L1>::row(it1), linalg_traits<L2>::row(it2));
  1088. }
  1089. template <typename L1, typename L2>
  1090. void add(const L1& l1, L2& l2, col_major, col_major) {
  1091. typename linalg_traits<L1>::const_col_iterator
  1092. it1 = mat_col_const_begin(l1),
  1093. ite = mat_col_const_end(l1);
  1094. typename linalg_traits<L2>::col_iterator it2 = mat_col_begin(l2);
  1095. for ( ; it1 != ite; ++it1, ++it2)
  1096. add(linalg_traits<L1>::col(it1), linalg_traits<L2>::col(it2));
  1097. }
  1098. template <typename L1, typename L2> inline
  1099. void add_mat_mixed_rc(const L1& l1, L2& l2, size_type i) {
  1100. add_mat_mixed_rc(l1, l2, i, typename linalg_traits<L1>::storage_type());
  1101. }
  1102. template <typename L1, typename L2>
  1103. void add_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_sparse) {
  1104. typename linalg_traits<L1>::const_iterator
  1105. it = vect_const_begin(l1), ite = vect_const_end(l1);
  1106. for (; it != ite; ++it) l2(i, it.index()) += *it;
  1107. }
  1108. template <typename L1, typename L2>
  1109. void add_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_skyline) {
  1110. typename linalg_traits<L1>::const_iterator
  1111. it = vect_const_begin(l1), ite = vect_const_end(l1);
  1112. for (; it != ite; ++it) l2(i, it.index()) += *it;
  1113. }
  1114. template <typename L1, typename L2>
  1115. void add_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_dense) {
  1116. typename linalg_traits<L1>::const_iterator
  1117. it = vect_const_begin(l1), ite = vect_const_end(l1);
  1118. for (size_type j = 0; it != ite; ++it, ++j) l2(i, j) += *it;
  1119. }
  1120. template <typename L1, typename L2> inline
  1121. void add_mat_mixed_cr(const L1& l1, L2& l2, size_type i) {
  1122. add_mat_mixed_cr(l1, l2, i, typename linalg_traits<L1>::storage_type());
  1123. }
  1124. template <typename L1, typename L2>
  1125. void add_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_sparse) {
  1126. typename linalg_traits<L1>::const_iterator
  1127. it = vect_const_begin(l1), ite = vect_const_end(l1);
  1128. for (; it != ite; ++it) l2(it.index(), i) += *it;
  1129. }
  1130. template <typename L1, typename L2>
  1131. void add_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_skyline) {
  1132. typename linalg_traits<L1>::const_iterator
  1133. it = vect_const_begin(l1), ite = vect_const_end(l1);
  1134. for (; it != ite; ++it) l2(it.index(), i) += *it;
  1135. }
  1136. template <typename L1, typename L2>
  1137. void add_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_dense) {
  1138. typename linalg_traits<L1>::const_iterator
  1139. it = vect_const_begin(l1), ite = vect_const_end(l1);
  1140. for (size_type j = 0; it != ite; ++it, ++j) l2(j, i) += *it;
  1141. }
  1142. template <typename L1, typename L2>
  1143. void add(const L1& l1, L2& l2, row_major, col_major) {
  1144. size_type nbr = mat_nrows(l1);
  1145. for (size_type i = 0; i < nbr; ++i)
  1146. add_mat_mixed_rc(mat_const_row(l1, i), l2, i);
  1147. }
  1148. template <typename L1, typename L2>
  1149. void add(const L1& l1, L2& l2, col_major, row_major) {
  1150. size_type nbc = mat_ncols(l1);
  1151. for (size_type i = 0; i < nbc; ++i)
  1152. add_mat_mixed_cr(mat_const_col(l1, i), l2, i);
  1153. }
  1154. template <typename L1, typename L2> inline
  1155. void add(const L1& l1, L2& l2, row_and_col, row_major)
  1156. { add(l1, l2, row_major(), row_major()); }
  1157. template <typename L1, typename L2> inline
  1158. void add(const L1& l1, L2& l2, row_and_col, row_and_col)
  1159. { add(l1, l2, row_major(), row_major()); }
  1160. template <typename L1, typename L2> inline
  1161. void add(const L1& l1, L2& l2, row_and_col, col_and_row)
  1162. { add(l1, l2, row_major(), row_major()); }
  1163. template <typename L1, typename L2> inline
  1164. void add(const L1& l1, L2& l2, col_and_row, row_and_col)
  1165. { add(l1, l2, row_major(), row_major()); }
  1166. template <typename L1, typename L2> inline
  1167. void add(const L1& l1, L2& l2, row_major, row_and_col)
  1168. { add(l1, l2, row_major(), row_major()); }
  1169. template <typename L1, typename L2> inline
  1170. void add(const L1& l1, L2& l2, col_and_row, row_major)
  1171. { add(l1, l2, row_major(), row_major()); }
  1172. template <typename L1, typename L2> inline
  1173. void add(const L1& l1, L2& l2, row_major, col_and_row)
  1174. { add(l1, l2, row_major(), row_major()); }
  1175. template <typename L1, typename L2> inline
  1176. void add(const L1& l1, L2& l2, row_and_col, col_major)
  1177. { add(l1, l2, col_major(), col_major()); }
  1178. template <typename L1, typename L2> inline
  1179. void add(const L1& l1, L2& l2, col_major, row_and_col)
  1180. { add(l1, l2, col_major(), col_major()); }
  1181. template <typename L1, typename L2> inline
  1182. void add(const L1& l1, L2& l2, col_and_row, col_major)
  1183. { add(l1, l2, col_major(), col_major()); }
  1184. template <typename L1, typename L2> inline
  1185. void add(const L1& l1, L2& l2, col_and_row, col_and_row)
  1186. { add(l1, l2, col_major(), col_major()); }
  1187. template <typename L1, typename L2> inline
  1188. void add(const L1& l1, L2& l2, col_major, col_and_row)
  1189. { add(l1, l2, col_major(), col_major()); }
  1190. ///@endcond
  1191. /** Addition of two vectors/matrices
  1192. @param l1
  1193. @param l2
  1194. @param l3 contains l1+l2 on output
  1195. */
  1196. template <typename L1, typename L2, typename L3> inline
  1197. void add(const L1& l1, const L2& l2, L3& l3) {
  1198. add_spec(l1, l2, l3, typename linalg_traits<L2>::linalg_type());
  1199. }
  1200. ///@cond DOXY_SHOW_ALL_FUNCTIONS
  1201. template <typename L1, typename L2, typename L3> inline
  1202. void add(const L1& l1, const L2& l2, const L3& l3)
  1203. { add(l1, l2, linalg_const_cast(l3)); }
  1204. template <typename L1, typename L2, typename L3> inline
  1205. void add_spec(const L1& l1, const L2& l2, L3& l3, abstract_matrix)
  1206. { copy(l2, l3); add(l1, l3); }
  1207. template <typename L1, typename L2, typename L3> inline
  1208. void add_spec(const L1& l1, const L2& l2, L3& l3, abstract_vector) {
  1209. GMM_ASSERT2(vect_size(l1) == vect_size(l2) &&
  1210. vect_size(l1) == vect_size(l3), "dimensions mismatch");
  1211. if ((const void *)(&l1) == (const void *)(&l3))
  1212. add(l2, l3);
  1213. else if ((const void *)(&l2) == (const void *)(&l3))
  1214. add(l1, l3);
  1215. else
  1216. add(l1, l2, l3, typename linalg_traits<L1>::storage_type(),
  1217. typename linalg_traits<L2>::storage_type(),
  1218. typename linalg_traits<L3>::storage_type());
  1219. }
  1220. template <typename IT1, typename IT2, typename IT3>
  1221. void add_full_(IT1 it1, IT2 it2, IT3 it3, IT3 ite) {
  1222. for (; it3 != ite; ++it3, ++it2, ++it1) *it3 = *it1 + *it2;
  1223. }
  1224. template <typename IT1, typename IT2, typename IT3>
  1225. void add_almost_full_(IT1 it1, IT1 ite1, IT2 it2, IT3 it3, IT3 ite3) {
  1226. IT3 it = it3;
  1227. for (; it != ite3; ++it, ++it2) *it = *it2;
  1228. for (; it1 != ite1; ++it1)
  1229. *(it3 + it1.index()) += *it1;
  1230. }
  1231. template <typename IT1, typename IT2, typename IT3>
  1232. void add_to_full_(IT1 it1, IT1 ite1, IT2 it2, IT2 ite2,
  1233. IT3 it3, IT3 ite3) {
  1234. typedef typename std::iterator_traits<IT3>::value_type T;
  1235. IT3 it = it3;
  1236. for (; it != ite3; ++it) *it = T(0);
  1237. for (; it1 != ite1; ++it1) *(it3 + it1.index()) = *it1;
  1238. for (; it2 != ite2; ++it2) *(it3 + it2.index()) += *it2;
  1239. }
  1240. template <typename L1, typename L2, typename L3> inline
  1241. void add(const L1& l1, const L2& l2, L3& l3,
  1242. abstract_dense, abstract_dense, abstract_dense) {
  1243. add_full_(vect_const_begin(l1), vect_const_begin(l2),
  1244. vect_begin(l3), vect_end(l3));
  1245. }
  1246. // generic function for add(v1, v2, v3).
  1247. // Need to be specialized to optimize particular additions.
  1248. template <typename L1, typename L2, typename L3,
  1249. typename ST1, typename ST2, typename ST3>
  1250. inline void add(const L1& l1, const L2& l2, L3& l3, ST1, ST2, ST3)
  1251. { copy(l2, l3); add(l1, l3, ST1(), ST3()); }
  1252. template <typename L1, typename L2, typename L3> inline
  1253. void add(const L1& l1, const L2& l2, L3& l3,
  1254. abstract_sparse, abstract_dense, abstract_dense) {
  1255. add_almost_full_(vect_const_begin(l1), vect_const_end(l1),
  1256. vect_const_begin(l2), vect_begin(l3), vect_end(l3));
  1257. }
  1258. template <typename L1, typename L2, typename L3> inline
  1259. void add(const L1& l1, const L2& l2, L3& l3,
  1260. abstract_dense, abstract_sparse, abstract_dense)
  1261. { add(l2, l1, l3, abstract_sparse(), abstract_dense(), abstract_dense()); }
  1262. template <typename L1, typename L2, typename L3> inline
  1263. void add(const L1& l1, const L2& l2, L3& l3,
  1264. abstract_sparse, abstract_sparse, abstract_dense) {
  1265. add_to_full_(vect_const_begin(l1), vect_const_end(l1),
  1266. vect_const_begin(l2), vect_const_end(l2),
  1267. vect_begin(l3), vect_end(l3));
  1268. }
  1269. template <typename L1, typename L2, typename L3>
  1270. void add_spspsp(const L1& l1, const L2& l2, L3& l3, linalg_true) {
  1271. typename linalg_traits<L1>::const_iterator
  1272. it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
  1273. typename linalg_traits<L2>::const_iterator
  1274. it2 = vect_const_begin(l2), ite2 = vect_const_end(l2);
  1275. clear(l3);
  1276. while (it1 != ite1 && it2 != ite2) {
  1277. ptrdiff_t d = it1.index() - it2.index();
  1278. if (d < 0)
  1279. { l3[it1.index()] += *it1; ++it1; }
  1280. else if (d > 0)
  1281. { l3[it2.index()] += *it2; ++it2; }
  1282. else
  1283. { l3[it1.index()] = *it1 + *it2; ++it1; ++it2; }
  1284. }
  1285. for (; it1 != ite1; ++it1) l3[it1.index()] += *it1;
  1286. for (; it2 != ite2; ++it2) l3[it2.index()] += *it2;
  1287. }
  1288. template <typename L1, typename L2, typename L3>
  1289. void add_spspsp(const L1& l1, const L2& l2, L3& l3, linalg_false)
  1290. { copy(l2, l3); add(l2, l3); }
  1291. template <typename L1, typename L2, typename L3>
  1292. void add(const L1& l1, const L2& l2, L3& l3,
  1293. abstract_sparse, abstract_sparse, abstract_sparse) {
  1294. add_spspsp(l1, l2, l3, typename linalg_and<typename
  1295. linalg_traits<L1>::index_sorted,
  1296. typename linalg_traits<L2>::index_sorted>::bool_type());
  1297. }
  1298. template <typename L1, typename L2>
  1299. void add(const L1& l1, L2& l2, abstract_dense, abstract_dense) {
  1300. typename linalg_traits<L1>::const_iterator it1 = vect_const_begin(l1);
  1301. typename linalg_traits<L2>::iterator
  1302. it2 = vect_begin(l2), ite = vect_end(l2);
  1303. for (; it2 != ite; ++it2, ++it1) *it2 += *it1;
  1304. }
  1305. template <typename L1, typename L2>
  1306. void add(const L1& l1, L2& l2, abstract_dense, abstract_skyline) {
  1307. typedef typename linalg_traits<L1>::const_iterator const_l1_iterator;
  1308. typedef typename linalg_traits<L2>::iterator l2_iterator;
  1309. typedef typename linalg_traits<L1>::value_type T;
  1310. const_l1_iterator it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
  1311. size_type i1 = 0, ie1 = vect_size(l1);
  1312. while (it1 != ite1 && *it1 == T(0)) { ++it1; ++i1; }
  1313. if (it1 != ite1) {
  1314. l2_iterator it2 = vect_begin(l2), ite2 = vect_end(l2);
  1315. while (ie1 && *(ite1-1) == T(0)) { ite1--; --ie1; }
  1316. if (it2 == ite2 || i1 < it2.index()) {
  1317. l2[i1] = *it1; ++i1; ++it1;
  1318. if (it1 == ite1) return;
  1319. it2 = vect_begin(l2); ite2 = vect_end(l2);
  1320. }
  1321. if (ie1 > ite2.index()) {
  1322. --ite1; l2[ie1 - 1] = *ite1;
  1323. it2 = vect_begin(l2);
  1324. }
  1325. it2 += i1 - it2.index();
  1326. for (; it1 != ite1; ++it1, ++it2) { *it2 += *it1; }
  1327. }
  1328. }
  1329. template <typename L1, typename L2>
  1330. void add(const L1& l1, L2& l2, abstract_skyline, abstract_dense) {
  1331. typename linalg_traits<L1>::const_iterator it1 = vect_const_begin(l1),
  1332. ite1 = vect_const_end(l1);
  1333. if (it1 != ite1) {
  1334. typename linalg_traits<L2>::iterator it2 = vect_begin(l2);
  1335. it2 += it1.index();
  1336. for (; it1 != ite1; ++it2, ++it1) *it2 += *it1;
  1337. }
  1338. }
  1339. template <typename L1, typename L2>
  1340. void add(const L1& l1, L2& l2, abstract_sparse, abstract_dense) {
  1341. typename linalg_traits<L1>::const_iterator
  1342. it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
  1343. for (; it1 != ite1; ++it1) l2[it1.index()] += *it1;
  1344. }
  1345. template <typename L1, typename L2>
  1346. void add(const L1& l1, L2& l2, abstract_sparse, abstract_sparse) {
  1347. typename linalg_traits<L1>::const_iterator
  1348. it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
  1349. for (; it1 != ite1; ++it1) l2[it1.index()] += *it1;
  1350. }
  1351. template <typename L1, typename L2>
  1352. void add(const L1& l1, L2& l2, abstract_sparse, abstract_skyline) {
  1353. typename linalg_traits<L1>::const_iterator
  1354. it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
  1355. for (; it1 != ite1; ++it1) l2[it1.index()] += *it1;
  1356. }
  1357. template <typename L1, typename L2>
  1358. void add(const L1& l1, L2& l2, abstract_skyline, abstract_sparse) {
  1359. typename linalg_traits<L1>::const_iterator
  1360. it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
  1361. for (; it1 != ite1; ++it1)
  1362. if (*it1 != typename linalg_traits<L1>::value_type(0))
  1363. l2[it1.index()] += *it1;
  1364. }
  1365. template <typename L1, typename L2>
  1366. void add(const L1& l1, L2& l2, abstract_skyline, abstract_skyline) {
  1367. typedef typename linalg_traits<L1>::const_iterator const_l1_iterator;
  1368. typedef typename linalg_traits<L2>::iterator l2_iterator;
  1369. typedef typename linalg_traits<L1>::value_type T1;
  1370. typedef typename linalg_traits<L2>::value_type T2;
  1371. const_l1_iterator it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
  1372. while (it1 != ite1 && *it1 == T1(0)) ++it1;
  1373. if (ite1 != it1) {
  1374. l2_iterator it2 = vect_begin(l2), ite2 = vect_end(l2);
  1375. while (*(ite1-1) == T1(0)) ite1--;
  1376. if (it2 == ite2 || it1.index() < it2.index()) {
  1377. l2[it1.index()] = T2(0);
  1378. it2 = vect_begin(l2); ite2 = vect_end(l2);
  1379. }
  1380. if (ite1.index() > ite2.index()) {
  1381. l2[ite1.index() - 1] = T2(0);
  1382. it2 = vect_begin(l2);
  1383. }
  1384. it2 += it1.index() - it2.index();
  1385. for (; it1 != ite1; ++it1, ++it2) *it2 += *it1;
  1386. }
  1387. }
  1388. template <typename L1, typename L2>
  1389. void add(const L1& l1, L2& l2, abstract_dense, abstract_sparse) {
  1390. typename linalg_traits<L1>::const_iterator
  1391. it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
  1392. for (size_type i = 0; it1 != ite1; ++it1, ++i)
  1393. if (*it1 != typename linalg_traits<L1>::value_type(0)) l2[i] += *it1;
  1394. }
  1395. /* ******************************************************************** */
  1396. /* Matrix-vector mult */
  1397. /* ******************************************************************** */
  1398. ///@endcond
  1399. /** matrix-vector or matrix-matrix product.
  1400. @param l1 a matrix.
  1401. @param l2 a vector or matrix.
  1402. @param l3 the product l1*l2.
  1403. */
  1404. template <typename L1, typename L2, typename L3> inline
  1405. void mult(const L1& l1, const L2& l2, L3& l3) {
  1406. mult_dispatch(l1, l2, l3, typename linalg_traits<L2>::linalg_type());
  1407. }
  1408. ///@cond DOXY_SHOW_ALL_FUNCTIONS
  1409. template <typename L1, typename L2, typename L3> inline
  1410. void mult(const L1& l1, const L2& l2, const L3& l3)
  1411. { mult(l1, l2, linalg_const_cast(l3)); }
  1412. template <typename L1, typename L2, typename L3> inline
  1413. void mult_dispatch(const L1& l1, const L2& l2, L3& l3, abstract_vector) {
  1414. size_type m = mat_nrows(l1), n = mat_ncols(l1);
  1415. if (!m || !n) { gmm::clear(l3); return; }
  1416. GMM_ASSERT2(n==vect_size(l2) && m==vect_size(l3), "dimensions mismatch");
  1417. if (!same_origin(l2, l3))
  1418. mult_spec(l1, l2, l3, typename principal_orientation_type<typename
  1419. linalg_traits<L1>::sub_orientation>::potype());
  1420. else {
  1421. GMM_WARNING2("Warning, A temporary is used for mult\n");
  1422. typename temporary_vector<L3>::vector_type temp(vect_size(l3));
  1423. mult_spec(l1, l2, temp, typename principal_orientation_type<typename
  1424. linalg_traits<L1>::sub_orientation>::potype());
  1425. copy(temp, l3);
  1426. }
  1427. }
  1428. template <typename L1, typename L2, typename L3>
  1429. void mult_by_row(const L1& l1, const L2& l2, L3& l3, abstract_sparse) {
  1430. typedef typename linalg_traits<L3>::value_type T;
  1431. clear(l3);
  1432. size_type nr = mat_nrows(l1);
  1433. for (size_type i = 0; i < nr; ++i) {
  1434. T aux = vect_sp(mat_const_row(l1, i), l2);
  1435. if (aux != T(0)) l3[i] = aux;
  1436. }
  1437. }
  1438. template <typename L1, typename L2, typename L3>
  1439. void mult_by_row(const L1& l1, const L2& l2, L3& l3, abstract_skyline) {
  1440. typedef typename linalg_traits<L3>::value_type T;
  1441. clear(l3);
  1442. size_type nr = mat_nrows(l1);
  1443. for (size_type i = 0; i < nr; ++i) {
  1444. T aux = vect_sp(mat_const_row(l1, i), l2);
  1445. if (aux != T(0)) l3[i] = aux;
  1446. }
  1447. }
  1448. template <typename L1, typename L2, typename L3>
  1449. void mult_by_row(const L1& l1, const L2& l2, L3& l3, abstract_dense) {
  1450. typename linalg_traits<L3>::iterator it=vect_begin(l3), ite=vect_end(l3);
  1451. typename linalg_traits<L1>::const_row_iterator
  1452. itr = mat_row_const_begin(l1);
  1453. for (; it != ite; ++it, ++itr)
  1454. *it = vect_sp(linalg_traits<L1>::row(itr), l2,
  1455. typename linalg_traits<L1>::storage_type(),
  1456. typename linalg_traits<L2>::storage_type());
  1457. }
  1458. template <typename L1, typename L2, typename L3>
  1459. void mult_by_col(const L1& l1, const L2& l2, L3& l3, abstract_dense) {
  1460. clear(l3);
  1461. size_type nc = mat_ncols(l1);
  1462. for (size_type i = 0; i < nc; ++i)
  1463. add(scaled(mat_const_col(l1, i), l2[i]), l3);
  1464. }
  1465. template <typename L1, typename L2, typename L3>
  1466. void mult_by_col(const L1& l1, const L2& l2, L3& l3, abstract_sparse) {
  1467. typedef typename linalg_traits<L2>::value_type T;
  1468. clear(l3);
  1469. typename linalg_traits<L2>::const_iterator it = vect_const_begin(l2),
  1470. ite = vect_const_end(l2);
  1471. for (; it != ite; ++it)
  1472. if (*it != T(0)) add(scaled(mat_const_col(l1, it.index()), *it), l3);
  1473. }
  1474. template <typename L1, typename L2, typename L3>
  1475. void mult_by_col(const L1& l1, const L2& l2, L3& l3, abstract_skyline) {
  1476. typedef typename linalg_traits<L2>::value_type T;
  1477. clear(l3);
  1478. typename linalg_traits<L2>::const_iterator it = vect_const_begin(l2),
  1479. ite = vect_const_end(l2);
  1480. for (; it != ite; ++it)
  1481. if (*it != T(0)) add(scaled(mat_const_col(l1, it.index()), *it), l3);
  1482. }
  1483. template <typename L1, typename L2, typename L3> inline
  1484. void mult_spec(const L1& l1, const L2& l2, L3& l3, row_major)
  1485. { mult_by_row(l1, l2, l3, typename linalg_traits<L3>::storage_type()); }
  1486. template <typename L1, typename L2, typename L3> inline
  1487. void mult_spec(const L1& l1, const L2& l2, L3& l3, col_major)
  1488. { mult_by_col(l1, l2, l3, typename linalg_traits<L2>::storage_type()); }
  1489. template <typename L1, typename L2, typename L3> inline
  1490. void mult_spec(const L1& l1, const L2& l2, L3& l3, abstract_null_type)
  1491. { mult_ind(l1, l2, l3, typename linalg_traits<L1>::storage_type()); }
  1492. template <typename L1, typename L2, typename L3>
  1493. void mult_ind(const L1& l1, const L2& l2, L3& l3, abstract_indirect) {
  1494. GMM_ASSERT1(false, "gmm::mult(m, ., .) undefined for this kind of matrix");
  1495. }
  1496. template <typename L1, typename L2, typename L3, typename L4> inline
  1497. void mult(const L1& l1, const L2& l2, const L3& l3, L4& l4) {
  1498. size_type m = mat_nrows(l1), n = mat_ncols(l1);
  1499. copy(l3, l4);
  1500. if (!m || !n) { gmm::copy(l3, l4); return; }
  1501. GMM_ASSERT2(n==vect_size(l2) && m==vect_size(l4), "dimensions mismatch");
  1502. if (!same_origin(l2, l4)) {
  1503. mult_add_spec(l1, l2, l4, typename principal_orientation_type<typename
  1504. linalg_traits<L1>::sub_orientation>::potype());
  1505. }
  1506. else {
  1507. GMM_WARNING2("Warning, A temporary is used for mult\n");
  1508. typename temporary_vector<L2>::vector_type temp(vect_size(l2));
  1509. copy(l2, temp);
  1510. mult_add_spec(l1,temp, l4, typename principal_orientation_type<typename
  1511. linalg_traits<L1>::sub_orientation>::potype());
  1512. }
  1513. }
  1514. template <typename L1, typename L2, typename L3, typename L4> inline
  1515. void mult(const L1& l1, const L2& l2, const L3& l3, const L4& l4)
  1516. { mult(l1, l2, l3, linalg_const_cast(l4)); }
  1517. ///@endcond
  1518. /** Multiply-accumulate. l3 += l1*l2; */
  1519. template <typename L1, typename L2, typename L3> inline
  1520. void mult_add(const L1& l1, const L2& l2, L3& l3) {
  1521. size_type m = mat_nrows(l1), n = mat_ncols(l1);
  1522. if (!m || !n) return;
  1523. GMM_ASSERT2(n==vect_size(l2) && m==vect_size(l3), "dimensions mismatch");
  1524. if (!same_origin(l2, l3)) {
  1525. mult_add_spec(l1, l2, l3, typename principal_orientation_type<typename
  1526. linalg_traits<L1>::sub_orientation>::potype());
  1527. }
  1528. else {
  1529. GMM_WARNING2("Warning, A temporary is used for mult\n");
  1530. typename temporary_vector<L3>::vector_type temp(vect_size(l2));
  1531. copy(l2, temp);
  1532. mult_add_spec(l1,temp, l3, typename principal_orientation_type<typename
  1533. linalg_traits<L1>::sub_orientation>::potype());
  1534. }
  1535. }
  1536. ///@cond DOXY_SHOW_ALL_FUNCTIONS
  1537. template <typename L1, typename L2, typename L3> inline
  1538. void mult_add(const L1& l1, const L2& l2, const L3& l3)
  1539. { mult_add(l1, l2, linalg_const_cast(l3)); }
  1540. template <typename L1, typename L2, typename L3>
  1541. void mult_add_by_row(const L1& l1, const L2& l2, L3& l3, abstract_sparse) {
  1542. typedef typename linalg_traits<L3>::value_type T;
  1543. size_type nr = mat_nrows(l1);
  1544. for (size_type i = 0; i < nr; ++i) {
  1545. T aux = vect_sp(mat_const_row(l1, i), l2);
  1546. if (aux != T(0)) l3[i] += aux;
  1547. }
  1548. }
  1549. template <typename L1, typename L2, typename L3>
  1550. void mult_add_by_row(const L1& l1, const L2& l2, L3& l3, abstract_skyline) {
  1551. typedef typename linalg_traits<L3>::value_type T;
  1552. size_type nr = mat_nrows(l1);
  1553. for (size_type i = 0; i < nr; ++i) {
  1554. T aux = vect_sp(mat_const_row(l1, i), l2);
  1555. if (aux != T(0)) l3[i] += aux;
  1556. }
  1557. }
  1558. template <typename L1, typename L2, typename L3>
  1559. void mult_add_by_row(const L1& l1, const L2& l2, L3& l3, abstract_dense) {
  1560. typename linalg_traits<L3>::iterator it=vect_begin(l3), ite=vect_end(l3);
  1561. typename linalg_traits<L1>::const_row_iterator
  1562. itr = mat_row_const_begin(l1);
  1563. for (; it != ite; ++it, ++itr)
  1564. *it += vect_sp(linalg_traits<L1>::row(itr), l2);
  1565. }
  1566. template <typename L1, typename L2, typename L3>
  1567. void mult_add_by_col(const L1& l1, const L2& l2, L3& l3, abstract_dense) {
  1568. size_type nc = mat_ncols(l1);
  1569. for (size_type i = 0; i < nc; ++i)
  1570. add(scaled(mat_const_col(l1, i), l2[i]), l3);
  1571. }
  1572. template <typename L1, typename L2, typename L3>
  1573. void mult_add_by_col(const L1& l1, const L2& l2, L3& l3, abstract_sparse) {
  1574. typename linalg_traits<L2>::const_iterator it = vect_const_begin(l2),
  1575. ite = vect_const_end(l2);
  1576. for (; it != ite; ++it)
  1577. if (*it != typename linalg_traits<L2>::value_type(0))
  1578. add(scaled(mat_const_col(l1, it.index()), *it), l3);
  1579. }
  1580. template <typename L1, typename L2, typename L3>
  1581. void mult_add_by_col(const L1& l1, const L2& l2, L3& l3, abstract_skyline) {
  1582. typename linalg_traits<L2>::const_iterator it = vect_const_begin(l2),
  1583. ite = vect_const_end(l2);
  1584. for (; it != ite; ++it)
  1585. if (*it != typename linalg_traits<L2>::value_type(0))
  1586. add(scaled(mat_const_col(l1, it.index()), *it), l3);
  1587. }
  1588. template <typename L1, typename L2, typename L3> inline
  1589. void mult_add_spec(const L1& l1, const L2& l2, L3& l3, row_major)
  1590. { mult_add_by_row(l1, l2, l3, typename linalg_traits<L3>::storage_type()); }
  1591. template <typename L1, typename L2, typename L3> inline
  1592. void mult_add_spec(const L1& l1, const L2& l2, L3& l3, col_major)
  1593. { mult_add_by_col(l1, l2, l3, typename linalg_traits<L2>::storage_type()); }
  1594. template <typename L1, typename L2, typename L3> inline
  1595. void mult_add_spec(const L1& l1, const L2& l2, L3& l3, abstract_null_type)
  1596. { mult_ind(l1, l2, l3, typename linalg_traits<L1>::storage_type()); }
  1597. template <typename L1, typename L2, typename L3>
  1598. void transposed_mult(const L1& l1, const L2& l2, const L3& l3)
  1599. { mult(gmm::transposed(l1), l2, l3); }
  1600. /* ******************************************************************** */
  1601. /* Matrix-matrix mult */
  1602. /* ******************************************************************** */
  1603. struct g_mult {}; // generic mult, less optimized
  1604. struct c_mult {}; // col x col -> col mult
  1605. struct r_mult {}; // row x row -> row mult
  1606. struct rcmult {}; // row x col -> col mult
  1607. struct crmult {}; // col x row -> row mult
  1608. template<typename SO1, typename SO2, typename SO3> struct mult_t;
  1609. #define DEFMU__ template<> struct mult_t
  1610. DEFMU__<row_major , row_major , row_major > { typedef r_mult t; };
  1611. DEFMU__<row_major , row_major , col_major > { typedef g_mult t; };
  1612. DEFMU__<row_major , row_major , col_and_row> { typedef r_mult t; };
  1613. DEFMU__<row_major , row_major , row_and_col> { typedef r_mult t; };
  1614. DEFMU__<row_major , col_major , row_major > { typedef rcmult t; };
  1615. DEFMU__<row_major , col_major , col_major > { typedef rcmult t; };
  1616. DEFMU__<row_major , col_major , col_and_row> { typedef rcmult t; };
  1617. DEFMU__<row_major , col_major , row_and_col> { typedef rcmult t; };
  1618. DEFMU__<row_major , col_and_row, row_major > { typedef r_mult t; };
  1619. DEFMU__<row_major , col_and_row, col_major > { typedef rcmult t; };
  1620. DEFMU__<row_major , col_and_row, col_and_row> { typedef rcmult t; };
  1621. DEFMU__<row_major , col_and_row, row_and_col> { typedef rcmult t; };
  1622. DEFMU__<row_major , row_and_col, row_major > { typedef r_mult t; };
  1623. DEFMU__<row_major , row_and_col, col_major > { typedef rcmult t; };
  1624. DEFMU__<row_major , row_and_col, col_and_row> { typedef r_mult t; };
  1625. DEFMU__<row_major , row_and_col, row_and_col> { typedef r_mult t; };
  1626. DEFMU__<col_major , row_major , row_major > { typedef crmult t; };
  1627. DEFMU__<col_major , row_major , col_major > { typedef g_mult t; };
  1628. DEFMU__<col_major , row_major , col_and_row> { typedef crmult t; };
  1629. DEFMU__<col_major , row_major , row_and_col> { typedef crmult t; };
  1630. DEFMU__<col_major , col_major , row_major > { typedef g_mult t; };
  1631. DEFMU__<col_major , col_major , col_major > { typedef c_mult t; };
  1632. DEFMU__<col_major , col_major , col_and_row> { typedef c_mult t; };
  1633. DEFMU__<col_major , col_major , row_and_col> { typedef c_mult t; };
  1634. DEFMU__<col_major , col_and_row, row_major > { typedef crmult t; };
  1635. DEFMU__<col_major , col_and_row, col_major > { typedef c_mult t; };
  1636. DEFMU__<col_major , col_and_row, col_and_row> { typedef c_mult t; };
  1637. DEFMU__<col_major , col_and_row, row_and_col> { typedef c_mult t; };
  1638. DEFMU__<col_major , row_and_col, row_major > { typedef crmult t; };
  1639. DEFMU__<col_major , row_and_col, col_major > { typedef c_mult t; };
  1640. DEFMU__<col_major , row_and_col, col_and_row> { typedef c_mult t; };
  1641. DEFMU__<col_major , row_and_col, row_and_col> { typedef c_mult t; };
  1642. DEFMU__<col_and_row, row_major , row_major > { typedef r_mult t; };
  1643. DEFMU__<col_and_row, row_major , col_major > { typedef c_mult t; };
  1644. DEFMU__<col_and_row, row_major , col_and_row> { typedef r_mult t; };
  1645. DEFMU__<col_and_row, row_major , row_and_col> { typedef r_mult t; };
  1646. DEFMU__<col_and_row, col_major , row_major > { typedef rcmult t; };
  1647. DEFMU__<col_and_row, col_major , col_major > { typedef c_mult t; };
  1648. DEFMU__<col_and_row, col_major , col_and_row> { typedef c_mult t; };
  1649. DEFMU__<col_and_row, col_major , row_and_col> { typedef c_mult t; };
  1650. DEFMU__<col_and_row, col_and_row, row_major > { typedef r_mult t; };
  1651. DEFMU__<col_and_row, col_and_row, col_major > { typedef c_mult t; };
  1652. DEFMU__<col_and_row, col_and_row, col_and_row> { typedef c_mult t; };
  1653. DEFMU__<col_and_row, col_and_row, row_and_col> { typedef c_mult t; };
  1654. DEFMU__<col_and_row, row_and_col, row_major > { typedef r_mult t; };
  1655. DEFMU__<col_and_row, row_and_col, col_major > { typedef c_mult t; };
  1656. DEFMU__<col_and_row, row_and_col, col_and_row> { typedef c_mult t; };
  1657. DEFMU__<col_and_row, row_and_col, row_and_col> { typedef r_mult t; };
  1658. DEFMU__<row_and_col, row_major , row_major > { typedef r_mult t; };
  1659. DEFMU__<row_and_col, row_major , col_major > { typedef c_mult t; };
  1660. DEFMU__<row_and_col, row_major , col_and_row> { typedef r_mult t; };
  1661. DEFMU__<row_and_col, row_major , row_and_col> { typedef r_mult t; };
  1662. DEFMU__<row_and_col, col_major , row_major > { typedef rcmult t; };
  1663. DEFMU__<row_and_col, col_major , col_major > { typedef c_mult t; };
  1664. DEFMU__<row_and_col, col_major , col_and_row> { typedef c_mult t; };
  1665. DEFMU__<row_and_col, col_major , row_and_col> { typedef c_mult t; };
  1666. DEFMU__<row_and_col, col_and_row, row_major > { typedef rcmult t; };
  1667. DEFMU__<row_and_col, col_and_row, col_major > { typedef rcmult t; };
  1668. DEFMU__<row_and_col, col_and_row, col_and_row> { typedef rcmult t; };
  1669. DEFMU__<row_and_col, col_and_row, row_and_col> { typedef rcmult t; };
  1670. DEFMU__<row_and_col, row_and_col, row_major > { typedef r_mult t; };
  1671. DEFMU__<row_and_col, row_and_col, col_major > { typedef c_mult t; };
  1672. DEFMU__<row_and_col, row_and_col, col_and_row> { typedef r_mult t; };
  1673. DEFMU__<row_and_col, row_and_col, row_and_col> { typedef r_mult t; };
  1674. template <typename L1, typename L2, typename L3>
  1675. void mult_dispatch(const L1& l1, const L2& l2, L3& l3, abstract_matrix) {
  1676. typedef typename temporary_matrix<L3>::matrix_type temp_mat_type;
  1677. size_type m = mat_nrows(l1), n = mat_ncols(l1), k = mat_ncols(l2);
  1678. if (n == 0) { gmm::clear(l3); return; }
  1679. GMM_ASSERT2(n == mat_nrows(l2) && m == mat_nrows(l3) && k == mat_ncols(l3),
  1680. "dimensions mismatch");
  1681. if (same_origin(l2, l3) || same_origin(l1, l3)) {
  1682. GMM_WARNING2("A temporary is used for mult");
  1683. temp_mat_type temp(mat_nrows(l3), mat_ncols(l3));
  1684. mult_spec(l1, l2, temp, typename mult_t<
  1685. typename linalg_traits<L1>::sub_orientation,
  1686. typename linalg_traits<L2>::sub_orientation,
  1687. typename linalg_traits<temp_mat_type>::sub_orientation>::t());
  1688. copy(temp, l3);
  1689. }
  1690. else
  1691. mult_spec(l1, l2, l3, typename mult_t<
  1692. typename linalg_traits<L1>::sub_orientation,
  1693. typename linalg_traits<L2>::sub_orientation,
  1694. typename linalg_traits<L3>::sub_orientation>::t());
  1695. }
  1696. // Completely generic but inefficient
  1697. template <typename L1, typename L2, typename L3>
  1698. void mult_spec(const L1& l1, const L2& l2, L3& l3, g_mult) {
  1699. typedef typename linalg_traits<L3>::value_type T;
  1700. GMM_WARNING2("Inefficient generic matrix-matrix mult is used");
  1701. for (size_type i = 0; i < mat_nrows(l3) ; ++i)
  1702. for (size_type j = 0; j < mat_ncols(l3) ; ++j) {
  1703. T a(0);
  1704. for (size_type k = 0; k < mat_nrows(l2) ; ++k) a += l1(i, k)*l2(k, j);
  1705. l3(i, j) = a;
  1706. }
  1707. }
  1708. // row x col matrix-matrix mult
  1709. template <typename L1, typename L2, typename L3>
  1710. void mult_row_col_with_temp(const L1& l1, const L2& l2, L3& l3, col_major) {
  1711. typedef typename temporary_col_matrix<L1>::matrix_type temp_col_mat;
  1712. temp_col_mat temp(mat_nrows(l1), mat_ncols(l1));
  1713. copy(l1, temp);
  1714. mult(temp, l2, l3);
  1715. }
  1716. template <typename L1, typename L2, typename L3>
  1717. void mult_row_col_with_temp(const L1& l1, const L2& l2, L3& l3, row_major) {
  1718. typedef typename temporary_row_matrix<L2>::matrix_type temp_row_mat;
  1719. temp_row_mat temp(mat_nrows(l2), mat_ncols(l2));
  1720. copy(l2, temp);
  1721. mult(l1, temp, l3);
  1722. }
  1723. template <typename L1, typename L2, typename L3>
  1724. void mult_spec(const L1& l1, const L2& l2, L3& l3, rcmult) {
  1725. if (is_sparse(l1) && is_sparse(l2)) {
  1726. GMM_WARNING3("Inefficient row matrix - col matrix mult for "
  1727. "sparse matrices, using temporary");
  1728. mult_row_col_with_temp(l1, l2, l3,
  1729. typename principal_orientation_type<typename
  1730. linalg_traits<L3>::sub_orientation>::potype());
  1731. }
  1732. else {
  1733. typename linalg_traits<L2>::const_col_iterator
  1734. it2b = linalg_traits<L2>::col_begin(l2), it2,
  1735. ite = linalg_traits<L2>::col_end(l2);
  1736. size_type i,j, k = mat_nrows(l1);
  1737. for (i = 0; i < k; ++i) {
  1738. typename linalg_traits<L1>::const_sub_row_type r1=mat_const_row(l1, i);
  1739. for (it2 = it2b, j = 0; it2 != ite; ++it2, ++j)
  1740. l3(i,j) = vect_sp(r1, linalg_traits<L2>::col(it2));
  1741. }
  1742. }
  1743. }
  1744. // row - row matrix-matrix mult
  1745. template <typename L1, typename L2, typename L3> inline
  1746. void mult_spec(const L1& l1, const L2& l2, L3& l3, r_mult) {
  1747. mult_spec(l1, l2, l3,r_mult(),typename linalg_traits<L1>::storage_type());
  1748. }
  1749. template <typename L1, typename L2, typename L3>
  1750. void mult_spec(const L1& l1, const L2& l2, L3& l3, r_mult, abstract_dense) {
  1751. // optimizable
  1752. clear(l3);
  1753. size_type nn = mat_nrows(l3), mm = mat_nrows(l2);
  1754. for (size_type i = 0; i < nn; ++i) {
  1755. for (size_type j = 0; j < mm; ++j) {
  1756. add(scaled(mat_const_row(l2, j), l1(i, j)), mat_row(l3, i));
  1757. }
  1758. }
  1759. }
  1760. template <typename L1, typename L2, typename L3>
  1761. void mult_spec(const L1& l1, const L2& l2, L3& l3, r_mult, abstract_sparse) {
  1762. // optimizable
  1763. clear(l3);
  1764. size_type nn = mat_nrows(l3);
  1765. for (size_type i = 0; i < nn; ++i) {
  1766. typename linalg_traits<L1>::const_sub_row_type rl1=mat_const_row(l1, i);
  1767. typename linalg_traits<typename linalg_traits<L1>::const_sub_row_type>::
  1768. const_iterator it = vect_const_begin(rl1), ite = vect_const_end(rl1);
  1769. for (; it != ite; ++it)
  1770. add(scaled(mat_const_row(l2, it.index()), *it), mat_row(l3, i));
  1771. }
  1772. }
  1773. template <typename L1, typename L2, typename L3>
  1774. void mult_spec(const L1& l1, const L2& l2, L3& l3, r_mult, abstract_skyline)
  1775. { mult_spec(l1, l2, l3, r_mult(), abstract_sparse()); }
  1776. // col - col matrix-matrix mult
  1777. template <typename L1, typename L2, typename L3> inline
  1778. void mult_spec(const L1& l1, const L2& l2, L3& l3, c_mult) {
  1779. mult_spec(l1, l2,l3,c_mult(),typename linalg_traits<L2>::storage_type(),
  1780. typename linalg_traits<L2>::sub_orientation());
  1781. }
  1782. template <typename L1, typename L2, typename L3, typename ORIEN>
  1783. void mult_spec(const L1& l1, const L2& l2, L3& l3, c_mult,
  1784. abstract_dense, ORIEN) {
  1785. typedef typename linalg_traits<L2>::value_type T;
  1786. size_type nn = mat_ncols(l3), mm = mat_ncols(l1);
  1787. for (size_type i = 0; i < nn; ++i) {
  1788. clear(mat_col(l3, i));
  1789. for (size_type j = 0; j < mm; ++j) {
  1790. T b = l2(j, i);
  1791. if (b != T(0)) add(scaled(mat_const_col(l1, j), b), mat_col(l3, i));
  1792. }
  1793. }
  1794. }
  1795. template <typename L1, typename L2, typename L3, typename ORIEN>
  1796. void mult_spec(const L1& l1, const L2& l2, L3& l3, c_mult,
  1797. abstract_sparse, ORIEN) {
  1798. // optimizable
  1799. clear(l3);
  1800. size_type nn = mat_ncols(l3);
  1801. for (size_type i = 0; i < nn; ++i) {
  1802. typename linalg_traits<L2>::const_sub_col_type rc2=mat_const_col(l2, i);
  1803. typename linalg_traits<typename linalg_traits<L2>::const_sub_col_type>::
  1804. const_iterator it = vect_const_begin(rc2), ite = vect_const_end(rc2);
  1805. for (; it != ite; ++it)
  1806. add(scaled(mat_const_col(l1, it.index()), *it), mat_col(l3, i));
  1807. }
  1808. }
  1809. template <typename L1, typename L2, typename L3>
  1810. void mult_spec(const L1& l1, const L2& l2, L3& l3, c_mult,
  1811. abstract_sparse, row_major) {
  1812. typedef typename linalg_traits<L2>::value_type T;
  1813. GMM_WARNING3("Inefficient matrix-matrix mult for sparse matrices");
  1814. clear(l3);
  1815. size_type mm = mat_nrows(l2), nn = mat_ncols(l3);
  1816. for (size_type i = 0; i < nn; ++i)
  1817. for (size_type j = 0; j < mm; ++j) {
  1818. T a = l2(i,j);
  1819. if (a != T(0)) add(scaled(mat_const_col(l1, j), a), mat_col(l3, i));
  1820. }
  1821. }
  1822. template <typename L1, typename L2, typename L3, typename ORIEN> inline
  1823. void mult_spec(const L1& l1, const L2& l2, L3& l3, c_mult,
  1824. abstract_skyline, ORIEN)
  1825. { mult_spec(l1, l2, l3, c_mult(), abstract_sparse(), ORIEN()); }
  1826. // col - row matrix-matrix mult
  1827. template <typename L1, typename L2, typename L3> inline
  1828. void mult_spec(const L1& l1, const L2& l2, L3& l3, crmult)
  1829. { mult_spec(l1,l2,l3,crmult(), typename linalg_traits<L1>::storage_type()); }
  1830. template <typename L1, typename L2, typename L3>
  1831. void mult_spec(const L1& l1, const L2& l2, L3& l3, crmult, abstract_dense) {
  1832. // optimizable
  1833. clear(l3);
  1834. size_type nn = mat_ncols(l1), mm = mat_nrows(l1);
  1835. for (size_type i = 0; i < nn; ++i) {
  1836. for (size_type j = 0; j < mm; ++j)
  1837. add(scaled(mat_const_row(l2, i), l1(j, i)), mat_row(l3, j));
  1838. }
  1839. }
  1840. template <typename L1, typename L2, typename L3>
  1841. void mult_spec(const L1& l1, const L2& l2, L3& l3, crmult, abstract_sparse) {
  1842. // optimizable
  1843. clear(l3);
  1844. size_type nn = mat_ncols(l1);
  1845. for (size_type i = 0; i < nn; ++i) {
  1846. typename linalg_traits<L1>::const_sub_col_type rc1=mat_const_col(l1, i);
  1847. typename linalg_traits<typename linalg_traits<L1>::const_sub_col_type>::
  1848. const_iterator it = vect_const_begin(rc1), ite = vect_const_end(rc1);
  1849. for (; it != ite; ++it)
  1850. add(scaled(mat_const_row(l2, i), *it), mat_row(l3, it.index()));
  1851. }
  1852. }
  1853. template <typename L1, typename L2, typename L3> inline
  1854. void mult_spec(const L1& l1, const L2& l2, L3& l3, crmult, abstract_skyline)
  1855. { mult_spec(l1, l2, l3, crmult(), abstract_sparse()); }
  1856. /* ******************************************************************** */
  1857. /* Symmetry test. */
  1858. /* ******************************************************************** */
  1859. ///@endcond
  1860. /** test if A is symmetric.
  1861. @param A a matrix.
  1862. @param tol a threshold.
  1863. */
  1864. template <typename MAT> inline
  1865. bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol
  1866. = magnitude_of_linalg(MAT)(-1)) {
  1867. typedef magnitude_of_linalg(MAT) R;
  1868. if (tol < R(0)) tol = default_tol(R()) * mat_maxnorm(A);
  1869. if (mat_nrows(A) != mat_ncols(A)) return false;
  1870. return is_symmetric(A, tol, typename linalg_traits<MAT>::storage_type());
  1871. }
  1872. ///@cond DOXY_SHOW_ALL_FUNCTIONS
  1873. template <typename MAT>
  1874. bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol,
  1875. abstract_dense) {
  1876. size_type m = mat_nrows(A);
  1877. for (size_type i = 1; i < m; ++i)
  1878. for (size_type j = 0; j < i; ++j)
  1879. if (gmm::abs(A(i, j)-A(j, i)) > tol) return false;
  1880. return true;
  1881. }
  1882. template <typename MAT>
  1883. bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol,
  1884. abstract_sparse) {
  1885. return is_symmetric(A, tol, typename principal_orientation_type<typename
  1886. linalg_traits<MAT>::sub_orientation>::potype());
  1887. }
  1888. template <typename MAT>
  1889. bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol,
  1890. row_major) {
  1891. for (size_type i = 0; i < mat_nrows(A); ++i) {
  1892. typedef typename linalg_traits<MAT>::const_sub_row_type row_type;
  1893. row_type row = mat_const_row(A, i);
  1894. typename linalg_traits<row_type>::const_iterator
  1895. it = vect_const_begin(row), ite = vect_const_end(row);
  1896. for (; it != ite; ++it)
  1897. if (gmm::abs(*it - A(it.index(), i)) > tol) return false;
  1898. }
  1899. return true;
  1900. }
  1901. template <typename MAT>
  1902. bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol,
  1903. col_major) {
  1904. for (size_type i = 0; i < mat_ncols(A); ++i) {
  1905. typedef typename linalg_traits<MAT>::const_sub_col_type col_type;
  1906. col_type col = mat_const_col(A, i);
  1907. typename linalg_traits<col_type>::const_iterator
  1908. it = vect_const_begin(col), ite = vect_const_end(col);
  1909. for (; it != ite; ++it)
  1910. if (gmm::abs(*it - A(i, it.index())) > tol) return false;
  1911. }
  1912. return true;
  1913. }
  1914. template <typename MAT>
  1915. bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol,
  1916. abstract_skyline)
  1917. { return is_symmetric(A, tol, abstract_sparse()); }
  1918. ///@endcond
  1919. /** test if A is Hermitian.
  1920. @param A a matrix.
  1921. @param tol a threshold.
  1922. */
  1923. template <typename MAT> inline
  1924. bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol
  1925. = magnitude_of_linalg(MAT)(-1)) {
  1926. typedef magnitude_of_linalg(MAT) R;
  1927. if (tol < R(0)) tol = default_tol(R()) * mat_maxnorm(A);
  1928. if (mat_nrows(A) != mat_ncols(A)) return false;
  1929. return is_hermitian(A, tol, typename linalg_traits<MAT>::storage_type());
  1930. }
  1931. ///@cond DOXY_SHOW_ALL_FUNCTIONS
  1932. template <typename MAT>
  1933. bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol,
  1934. abstract_dense) {
  1935. size_type m = mat_nrows(A);
  1936. for (size_type i = 1; i < m; ++i)
  1937. for (size_type j = 0; j < i; ++j)
  1938. if (gmm::abs(A(i, j)-gmm::conj(A(j, i))) > tol) return false;
  1939. return true;
  1940. }
  1941. template <typename MAT>
  1942. bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol,
  1943. abstract_sparse) {
  1944. return is_hermitian(A, tol, typename principal_orientation_type<typename
  1945. linalg_traits<MAT>::sub_orientation>::potype());
  1946. }
  1947. template <typename MAT>
  1948. bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol,
  1949. row_major) {
  1950. for (size_type i = 0; i < mat_nrows(A); ++i) {
  1951. typedef typename linalg_traits<MAT>::const_sub_row_type row_type;
  1952. row_type row = mat_const_row(A, i);
  1953. typename linalg_traits<row_type>::const_iterator
  1954. it = vect_const_begin(row), ite = vect_const_end(row);
  1955. for (; it != ite; ++it)
  1956. if (gmm::abs(gmm::conj(*it) - A(it.index(), i)) > tol) return false;
  1957. }
  1958. return true;
  1959. }
  1960. template <typename MAT>
  1961. bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol,
  1962. col_major) {
  1963. for (size_type i = 0; i < mat_ncols(A); ++i) {
  1964. typedef typename linalg_traits<MAT>::const_sub_col_type col_type;
  1965. col_type col = mat_const_col(A, i);
  1966. typename linalg_traits<col_type>::const_iterator
  1967. it = vect_const_begin(col), ite = vect_const_end(col);
  1968. for (; it != ite; ++it)
  1969. if (gmm::abs(gmm::conj(*it) - A(i, it.index())) > tol) return false;
  1970. }
  1971. return true;
  1972. }
  1973. template <typename MAT>
  1974. bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol,
  1975. abstract_skyline)
  1976. { return is_hermitian(A, tol, abstract_sparse()); }
  1977. ///@endcond
  1978. }
  1979. #endif // GMM_BLAS_H__