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
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							2284 lines
						
					
					
						
							87 KiB
						
					
					
				| /* -*- c++ -*- (enables emacs c++ mode) */ | |
| /*=========================================================================== | |
|   | |
|  Copyright (C) 2002-2012 Yves Renard | |
|   | |
|  This file is a part of GETFEM++ | |
|   | |
|  Getfem++  is  free software;  you  can  redistribute  it  and/or modify it | |
|  under  the  terms  of the  GNU  Lesser General Public License as published | |
|  by  the  Free Software Foundation;  either version 3 of the License,  or | |
|  (at your option) any later version along with the GCC Runtime Library | |
|  Exception either version 3.1 or (at your option) any later version. | |
|  This program  is  distributed  in  the  hope  that it will be useful,  but | |
|  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
|  or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public | |
|  License and GCC Runtime Library Exception for more details. | |
|  You  should  have received a copy of the GNU Lesser General Public License | |
|  along  with  this program;  if not, write to the Free Software Foundation, | |
|  Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA. | |
|   | |
|  As a special exception, you  may use  this file  as it is a part of a free | |
|  software  library  without  restriction.  Specifically,  if   other  files | |
|  instantiate  templates  or  use macros or inline functions from this file, | |
|  or  you compile this  file  and  link  it  with other files  to produce an | |
|  executable, this file  does  not  by itself cause the resulting executable | |
|  to be covered  by the GNU Lesser General Public License.  This   exception | |
|  does not  however  invalidate  any  other  reasons why the executable file | |
|  might be covered by the GNU Lesser General Public License. | |
|   | |
| ===========================================================================*/ | |
| 
 | |
| /**@file gmm_blas.h | |
|    @author  Yves Renard <Yves.Renard@insa-lyon.fr> | |
|    @date October 13, 2002. | |
|    @brief Basic linear algebra functions. | |
| */ | |
| 
 | |
| #ifndef GMM_BLAS_H__ | |
| #define GMM_BLAS_H__ | |
|  | |
| #include "gmm_scaled.h" | |
| #include "gmm_transposed.h" | |
| #include "gmm_conjugated.h" | |
|  | |
| namespace gmm { | |
| 
 | |
|   /* ******************************************************************** */ | |
|   /*		                                         		  */ | |
|   /*		Generic algorithms                           		  */ | |
|   /*		                                         		  */ | |
|   /* ******************************************************************** */ | |
| 
 | |
| 
 | |
|   /* ******************************************************************** */ | |
|   /*		Miscellaneous                           		  */ | |
|   /* ******************************************************************** */ | |
| 
 | |
|   /** clear (fill with zeros) a vector or matrix. */ | |
|   template <typename L> inline void clear(L &l) | |
|   { linalg_traits<L>::do_clear(l); } | |
|   /** @cond DOXY_SHOW_ALL_FUNCTIONS  | |
|       skip all these redundant definitions in doxygen documentation.. | |
|    */ | |
|   template <typename L> inline void clear(const L &l) | |
|   { linalg_traits<L>::do_clear(linalg_const_cast(l)); } | |
| 
 | |
|   ///@endcond | |
|   /** count the number of non-zero entries of a vector or matrix. */  template <typename L> inline size_type nnz(const L& l) | |
|   { return nnz(l, typename linalg_traits<L>::linalg_type()); } | |
| 
 | |
|   ///@cond DOXY_SHOW_ALL_FUNCTIONS | |
|   template <typename L> inline size_type nnz(const L& l, abstract_vector) {  | |
|     typename linalg_traits<L>::const_iterator it = vect_const_begin(l), | |
|       ite = vect_const_end(l); | |
|     size_type res(0); | |
|     for (; it != ite; ++it) ++res; | |
|     return res; | |
|   } | |
| 
 | |
|   template <typename L> inline size_type nnz(const L& l, abstract_matrix) { | |
|     return nnz(l,  typename principal_orientation_type<typename | |
| 	       linalg_traits<L>::sub_orientation>::potype()); | |
|   } | |
| 
 | |
|   template <typename L> inline size_type nnz(const L& l, row_major) { | |
|     size_type res(0); | |
|     for (size_type i = 0; i < mat_nrows(l); ++i) | |
|       res += nnz(mat_const_row(l, i)); | |
|     return res; | |
|   }  | |
| 
 | |
|   template <typename L> inline size_type nnz(const L& l, col_major) { | |
|     size_type res(0); | |
|     for (size_type i = 0; i < mat_ncols(l); ++i) | |
|       res += nnz(mat_const_col(l, i)); | |
|     return res; | |
|   } | |
| 
 | |
|   ///@endcond | |
|  | |
| 
 | |
|   /** fill a vector or matrix with x. */ | |
|   template <typename L> inline | |
|   void fill(L& l, typename gmm::linalg_traits<L>::value_type x) { | |
|     typedef typename gmm::linalg_traits<L>::value_type T; | |
|     if (x == T(0)) gmm::clear(l); | |
|     fill(l, x, typename linalg_traits<L>::linalg_type()); | |
|   } | |
| 
 | |
|   template <typename L> inline | |
|   void fill(const L& l, typename gmm::linalg_traits<L>::value_type x) { | |
|     fill(linalg_const_cast(l), x); | |
|   } | |
| 
 | |
|   template <typename L> inline // to be optimized for dense vectors ... | |
|   void fill(L& l,  typename gmm::linalg_traits<L>::value_type x, | |
| 		   abstract_vector) { | |
|     for (size_type i = 0; i < vect_size(l); ++i) l[i] = x; | |
|   } | |
| 
 | |
|   template <typename L> inline // to be optimized for dense matrices ... | |
|   void fill(L& l, typename gmm::linalg_traits<L>::value_type x, | |
| 		   abstract_matrix) { | |
|     for (size_type i = 0; i < mat_nrows(l); ++i) | |
|       for (size_type j = 0; j < mat_ncols(l); ++j) | |
| 	l(i,j) = x; | |
|   } | |
| 
 | |
|   /** fill a vector or matrix with random value (uniform [-1,1]). */ | |
|   template <typename L> inline void fill_random(L& l) | |
|   { fill_random(l, typename linalg_traits<L>::linalg_type()); } | |
| 
 | |
|   ///@cond DOXY_SHOW_ALL_FUNCTIONS | |
|   template <typename L> inline void fill_random(const L& l) { | |
|     fill_random(linalg_const_cast(l), | |
| 		typename linalg_traits<L>::linalg_type()); | |
|   } | |
| 
 | |
|   template <typename L> inline void fill_random(L& l, abstract_vector) { | |
|     for (size_type i = 0; i < vect_size(l); ++i) | |
|       l[i] = gmm::random(typename linalg_traits<L>::value_type()); | |
|   } | |
| 
 | |
|   template <typename L> inline void fill_random(L& l, abstract_matrix) { | |
|     for (size_type i = 0; i < mat_nrows(l); ++i) | |
|       for (size_type j = 0; j < mat_ncols(l); ++j) | |
| 	l(i,j) = gmm::random(typename linalg_traits<L>::value_type()); | |
|   } | |
| 
 | |
|   ///@endcond | |
|   /** fill a vector or matrix with random value. | |
|       @param l a vector or matrix. | |
|       @param cfill probability of a non-zero value. | |
|   */ | |
|   template <typename L> inline void fill_random(L& l, double cfill) | |
|   { fill_random(l, cfill, typename linalg_traits<L>::linalg_type()); } | |
|   ///@cond DOXY_SHOW_ALL_FUNCTIONS | |
|  | |
|   template <typename L> inline void fill_random(const L& l, double cfill) { | |
|     fill_random(linalg_const_cast(l), cfill, | |
| 		typename linalg_traits<L>::linalg_type()); | |
|   } | |
| 
 | |
|   template <typename L> inline | |
|   void fill_random(L& l, double cfill, abstract_vector) { | |
|     typedef typename linalg_traits<L>::value_type T; | |
|     size_type ntot = std::min(vect_size(l), | |
| 			      size_type(double(vect_size(l))*cfill) + 1); | |
|     for (size_type nb = 0; nb < ntot;) { | |
|       size_type i = gmm::irandom(vect_size(l)); | |
|       if (l[i] == T(0)) {  | |
| 	l[i] = gmm::random(typename linalg_traits<L>::value_type()); | |
| 	++nb; | |
|       } | |
|     } | |
|   } | |
| 
 | |
|   template <typename L> inline | |
|   void fill_random(L& l, double cfill, abstract_matrix) { | |
|     fill_random(l, cfill, typename principal_orientation_type<typename | |
| 		linalg_traits<L>::sub_orientation>::potype()); | |
|   } | |
| 
 | |
|   template <typename L> inline | |
|   void fill_random(L& l, double cfill, row_major) { | |
|     for (size_type i=0; i < mat_nrows(l); ++i) fill_random(mat_row(l,i),cfill); | |
|   } | |
| 
 | |
|   template <typename L> inline | |
|   void fill_random(L& l, double cfill, col_major) { | |
|     for (size_type j=0; j < mat_ncols(l); ++j) fill_random(mat_col(l,j),cfill); | |
|   } | |
| 
 | |
|   /* resize a vector */ | |
|   template <typename V> inline | |
|   void resize(V &v, size_type n, linalg_false) | |
|   { linalg_traits<V>::resize(v, n); } | |
| 
 | |
|   template <typename V> inline | |
|   void resize(V &, size_type , linalg_modifiable) | |
|   { GMM_ASSERT1(false, "You cannot resize a reference"); } | |
| 
 | |
|   template <typename V> inline | |
|   void resize(V &, size_type , linalg_const) | |
|   { GMM_ASSERT1(false, "You cannot resize a reference"); } | |
| 
 | |
|   ///@endcond | |
|   /** resize a vector. */ | |
|    template <typename V> inline | |
|   void resize(V &v, size_type n) { | |
|     resize(v, n, typename linalg_traits<V>::is_reference()); | |
|   } | |
|   ///@cond DOXY_SHOW_ALL_FUNCTIONS | |
|  | |
|   /** resize a matrix **/ | |
|   template <typename M> inline | |
|   void resize(M &v, size_type m, size_type n, linalg_false) { | |
|     linalg_traits<M>::resize(v, m, n); | |
|   } | |
| 
 | |
|   template <typename M> inline | |
|   void resize(M &, size_type, size_type, linalg_modifiable) | |
|   { GMM_ASSERT1(false, "You cannot resize a reference"); } | |
| 
 | |
|   template <typename M> inline | |
|   void resize(M &, size_type, size_type, linalg_const) | |
|   { GMM_ASSERT1(false, "You cannot resize a reference"); } | |
| 
 | |
|   ///@endcond  | |
|   /** resize a matrix */ | |
|   template <typename M> inline | |
|   void resize(M &v, size_type m, size_type n) | |
|   { resize(v, m, n, typename linalg_traits<M>::is_reference()); } | |
|   ///@cond | |
|  | |
|   template <typename M> inline | |
|   void reshape(M &v, size_type m, size_type n, linalg_false) | |
|   { linalg_traits<M>::reshape(v, m, n); } | |
| 
 | |
|   template <typename M> inline | |
|   void reshape(M &, size_type, size_type, linalg_modifiable) | |
|   { GMM_ASSERT1(false, "You cannot reshape a reference"); } | |
| 
 | |
|   template <typename M> inline | |
|   void reshape(M &, size_type, size_type, linalg_const) | |
|   { GMM_ASSERT1(false, "You cannot reshape a reference"); } | |
| 
 | |
|   ///@endcond  | |
|   /** reshape a matrix */ | |
|   template <typename M> inline | |
|   void reshape(M &v, size_type m, size_type n) | |
|   { reshape(v, m, n, typename linalg_traits<M>::is_reference()); } | |
|   ///@cond DOXY_SHOW_ALL_FUNCTIONS | |
|    | |
| 
 | |
|   /* ******************************************************************** */ | |
|   /*		Scalar product                             		  */ | |
|   /* ******************************************************************** */ | |
| 
 | |
|   ///@endcond | |
|   /** scalar product between two vectors */ | |
|   template <typename V1, typename V2> inline | |
|   typename strongest_value_type<V1,V2>::value_type | |
|     vect_sp(const V1 &v1, const V2 &v2) { | |
|     GMM_ASSERT2(vect_size(v1) == vect_size(v2), "dimensions mismatch"); | |
|     return vect_sp(v1, v2, | |
| 		   typename linalg_traits<V1>::storage_type(),  | |
| 		   typename linalg_traits<V2>::storage_type()); | |
|   } | |
| 
 | |
|   /** scalar product between two vectors, using a matrix. | |
|       @param ps the matrix of the scalar product. | |
|       @param v1 the first vector | |
|       @param v2 the second vector | |
|   */ | |
|   template <typename MATSP, typename V1, typename V2> inline | |
|   typename strongest_value_type3<V1,V2,MATSP>::value_type | |
|     vect_sp(const MATSP &ps, const V1 &v1, const V2 &v2) { | |
|     return vect_sp_with_mat(ps, v1, v2, | |
| 			    typename linalg_traits<MATSP>::sub_orientation()); | |
|   } | |
|   ///@cond DOXY_SHOW_ALL_FUNCTIONS | |
|  | |
|   template <typename MATSP, typename V1, typename V2> inline | |
|     typename strongest_value_type3<V1,V2,MATSP>::value_type | |
|     vect_sp_with_mat(const MATSP &ps, const V1 &v1, const V2 &v2, row_major) { | |
|     return vect_sp_with_matr(ps, v1, v2,  | |
| 			     typename linalg_traits<V2>::storage_type()); | |
|   } | |
| 
 | |
|   template <typename MATSP, typename V1, typename V2> inline  | |
|     typename strongest_value_type3<V1,V2,MATSP>::value_type | |
|     vect_sp_with_matr(const MATSP &ps, const V1 &v1, const V2 &v2, | |
| 		      abstract_sparse) { | |
|     GMM_ASSERT2(vect_size(v1) == mat_ncols(ps) && | |
| 		vect_size(v2) == mat_nrows(ps), "dimensions mismatch"); | |
|     size_type nr = mat_nrows(ps); | |
|     typename linalg_traits<V2>::const_iterator | |
|       it = vect_const_begin(v2), ite = vect_const_end(v2); | |
|     typename strongest_value_type3<V1,V2,MATSP>::value_type res(0); | |
|     for (; it != ite; ++it) | |
|       res += vect_sp(mat_const_row(ps, it.index()), v1)* (*it); | |
|     return res; | |
|   } | |
| 
 | |
|   template <typename MATSP, typename V1, typename V2> inline | |
|     typename strongest_value_type3<V1,V2,MATSP>::value_type | |
|     vect_sp_with_matr(const MATSP &ps, const V1 &v1, const V2 &v2, | |
| 		      abstract_skyline) | |
|   { return vect_sp_with_matr(ps, v1, v2, abstract_sparse()); } | |
| 
 | |
|   template <typename MATSP, typename V1, typename V2> inline | |
|     typename strongest_value_type3<V1,V2,MATSP>::value_type | |
|     vect_sp_with_matr(const MATSP &ps, const V1 &v1, const V2 &v2, | |
| 		      abstract_dense) { | |
|     GMM_ASSERT2(vect_size(v1) == mat_ncols(ps) && | |
| 		vect_size(v2) == mat_nrows(ps), "dimensions mismatch"); | |
|     typename linalg_traits<V2>::const_iterator | |
|       it = vect_const_begin(v2), ite = vect_const_end(v2); | |
|     typename strongest_value_type3<V1,V2,MATSP>::value_type res(0); | |
|     for (size_type i = 0; it != ite; ++i, ++it) | |
|       res += vect_sp(mat_const_row(ps, i), v1) * (*it); | |
|     return res; | |
|   } | |
| 
 | |
|   template <typename MATSP, typename V1, typename V2> inline | |
|   typename strongest_value_type3<V1,V2,MATSP>::value_type | |
|   vect_sp_with_mat(const MATSP &ps, const V1 &v1,const V2 &v2,row_and_col) | |
|   { return vect_sp_with_mat(ps, v1, v2, row_major()); } | |
| 
 | |
|   template <typename MATSP, typename V1, typename V2> inline | |
|   typename strongest_value_type3<V1,V2,MATSP>::value_type | |
|   vect_sp_with_mat(const MATSP &ps, const V1 &v1, const V2 &v2,col_major){ | |
|     return vect_sp_with_matc(ps, v1, v2, | |
| 			     typename linalg_traits<V1>::storage_type()); | |
|   } | |
| 
 | |
|   template <typename MATSP, typename V1, typename V2> inline | |
|     typename strongest_value_type3<V1,V2,MATSP>::value_type | |
|     vect_sp_with_matc(const MATSP &ps, const V1 &v1, const V2 &v2, | |
| 		      abstract_sparse) { | |
|     GMM_ASSERT2(vect_size(v1) == mat_ncols(ps) && | |
| 		vect_size(v2) == mat_nrows(ps),"dimensions mismatch"); | |
|     typename linalg_traits<V1>::const_iterator | |
|       it = vect_const_begin(v1), ite = vect_const_end(v1); | |
|     typename strongest_value_type3<V1,V2,MATSP>::value_type res(0); | |
|     for (; it != ite; ++it) | |
|       res += vect_sp(mat_const_col(ps, it.index()), v2) * (*it); | |
|     return res; | |
|   } | |
| 
 | |
|   template <typename MATSP, typename V1, typename V2> inline | |
|     typename strongest_value_type3<V1,V2,MATSP>::value_type | |
|     vect_sp_with_matc(const MATSP &ps, const V1 &v1, const V2 &v2, | |
| 		      abstract_skyline) | |
|   { return vect_sp_with_matc(ps, v1, v2, abstract_sparse()); } | |
| 
 | |
|   template <typename MATSP, typename V1, typename V2> inline | |
|     typename strongest_value_type3<V1,V2,MATSP>::value_type | |
|     vect_sp_with_matc(const MATSP &ps, const V1 &v1, const V2 &v2, | |
| 		      abstract_dense) { | |
|     GMM_ASSERT2(vect_size(v1) == mat_ncols(ps) && | |
| 		vect_size(v2) == mat_nrows(ps), "dimensions mismatch"); | |
|     typename linalg_traits<V1>::const_iterator | |
|       it = vect_const_begin(v1), ite = vect_const_end(v1); | |
|     typename strongest_value_type3<V1,V2,MATSP>::value_type res(0); | |
|     for (size_type i = 0; it != ite; ++i, ++it) | |
|       res += vect_sp(mat_const_col(ps, i), v2) * (*it); | |
|     return res; | |
|   } | |
| 
 | |
|   template <typename MATSP, typename V1, typename V2> inline | |
|   typename strongest_value_type3<V1,V2,MATSP>::value_type | |
|   vect_sp_with_mat(const MATSP &ps, const V1 &v1,const V2 &v2,col_and_row) | |
|   { return vect_sp_with_mat(ps, v1, v2, col_major()); } | |
| 
 | |
|   template <typename MATSP, typename V1, typename V2> inline | |
|   typename strongest_value_type3<V1,V2,MATSP>::value_type | |
|   vect_sp_with_mat(const MATSP &ps, const V1 &v1, const V2 &v2, | |
| 		   abstract_null_type) { | |
|     typename temporary_vector<V1>::vector_type w(mat_nrows(ps)); | |
|     GMM_WARNING2("Warning, a temporary is used in scalar product\n"); | |
|     mult(ps, v1, w);  | |
|     return vect_sp(w, v2); | |
|   } | |
| 
 | |
|   template <typename IT1, typename IT2> inline | |
|   typename strongest_numeric_type<typename std::iterator_traits<IT1>::value_type, | |
| 				  typename std::iterator_traits<IT2>::value_type>::T | |
|   vect_sp_dense_(IT1 it, IT1 ite, IT2 it2) { | |
|     typename strongest_numeric_type<typename std::iterator_traits<IT1>::value_type, | |
|       typename std::iterator_traits<IT2>::value_type>::T res(0); | |
|     for (; it != ite; ++it, ++it2) res += (*it) * (*it2); | |
|     return res; | |
|   } | |
|    | |
|   template <typename IT1, typename V> inline | |
|     typename strongest_numeric_type<typename std::iterator_traits<IT1>::value_type, | |
| 				    typename linalg_traits<V>::value_type>::T | |
|     vect_sp_sparse_(IT1 it, IT1 ite, const V &v) { | |
|       typename strongest_numeric_type<typename std::iterator_traits<IT1>::value_type, | |
| 	typename linalg_traits<V>::value_type>::T res(0); | |
|     for (; it != ite; ++it) res += (*it) * v[it.index()]; | |
|     return res; | |
|   } | |
| 
 | |
|   template <typename V1, typename V2> inline | |
|   typename strongest_value_type<V1,V2>::value_type | |
|     vect_sp(const V1 &v1, const V2 &v2, abstract_dense, abstract_dense) { | |
|     return vect_sp_dense_(vect_const_begin(v1), vect_const_end(v1), | |
| 			  vect_const_begin(v2)); | |
|   } | |
| 
 | |
|   template <typename V1, typename V2> inline | |
|     typename strongest_value_type<V1,V2>::value_type | |
|     vect_sp(const V1 &v1, const V2 &v2, abstract_skyline, abstract_dense) { | |
|     typename linalg_traits<V1>::const_iterator it1 = vect_const_begin(v1), | |
|       ite =  vect_const_end(v1); | |
|     typename linalg_traits<V2>::const_iterator it2 = vect_const_begin(v2); | |
|     return vect_sp_dense_(it1, ite, it2 + it1.index()); | |
|   } | |
| 
 | |
|   template <typename V1, typename V2> inline | |
|     typename strongest_value_type<V1,V2>::value_type | |
|     vect_sp(const V1 &v1, const V2 &v2, abstract_dense, abstract_skyline) { | |
|     typename linalg_traits<V2>::const_iterator it1 = vect_const_begin(v2), | |
|       ite =  vect_const_end(v2); | |
|     typename linalg_traits<V1>::const_iterator it2 = vect_const_begin(v1); | |
|     return vect_sp_dense_(it1, ite, it2 + it1.index()); | |
|   } | |
| 
 | |
|   template <typename V1, typename V2> inline | |
|     typename strongest_value_type<V1,V2>::value_type | |
|     vect_sp(const V1 &v1, const V2 &v2, abstract_skyline, abstract_skyline) { | |
|     typedef typename strongest_value_type<V1,V2>::value_type T; | |
|     typename linalg_traits<V1>::const_iterator it1 = vect_const_begin(v1), | |
|       ite1 =  vect_const_end(v1); | |
|     typename linalg_traits<V2>::const_iterator it2 = vect_const_begin(v2), | |
|       ite2 =  vect_const_end(v2); | |
|     size_type n = std::min(ite1.index(), ite2.index()); | |
|     size_type l = std::max(it1.index(), it2.index()); | |
| 
 | |
|     if (l < n) { | |
|       size_type m = l - it1.index(), p = l - it2.index(), q = m + n - l; | |
|       return vect_sp_dense_(it1+m, it1+q, it2 + p); | |
|     } | |
|     return T(0); | |
|   } | |
| 
 | |
|   template <typename V1, typename V2> inline | |
|     typename strongest_value_type<V1,V2>::value_type | |
|   vect_sp(const V1 &v1, const V2 &v2,abstract_sparse,abstract_dense) { | |
|     return vect_sp_sparse_(vect_const_begin(v1), vect_const_end(v1), v2); | |
|   } | |
| 
 | |
|   template <typename V1, typename V2> inline | |
|     typename strongest_value_type<V1,V2>::value_type | |
|     vect_sp(const V1 &v1, const V2 &v2, abstract_sparse, abstract_skyline) { | |
|     return vect_sp_sparse_(vect_const_begin(v1), vect_const_end(v1), v2); | |
|   } | |
| 
 | |
|   template <typename V1, typename V2> inline | |
|     typename strongest_value_type<V1,V2>::value_type | |
|     vect_sp(const V1 &v1, const V2 &v2, abstract_skyline, abstract_sparse) { | |
|     return vect_sp_sparse_(vect_const_begin(v2), vect_const_end(v2), v1); | |
|   } | |
| 
 | |
|   template <typename V1, typename V2> inline | |
|     typename strongest_value_type<V1,V2>::value_type | |
|     vect_sp(const V1 &v1, const V2 &v2, abstract_dense,abstract_sparse) { | |
|     return vect_sp_sparse_(vect_const_begin(v2), vect_const_end(v2), v1); | |
|   } | |
| 
 | |
| 
 | |
|   template <typename V1, typename V2> inline | |
|   typename strongest_value_type<V1,V2>::value_type | |
|   vect_sp_sparse_sparse(const V1 &v1, const V2 &v2, linalg_true) { | |
|     typename linalg_traits<V1>::const_iterator it1 = vect_const_begin(v1), | |
|       ite1 = vect_const_end(v1); | |
|     typename linalg_traits<V2>::const_iterator it2 = vect_const_begin(v2), | |
|       ite2 = vect_const_end(v2); | |
|     typename strongest_value_type<V1,V2>::value_type res(0); | |
|      | |
|     while (it1 != ite1 && it2 != ite2) { | |
|       if (it1.index() == it2.index()) | |
| 	{ res += (*it1) * *it2; ++it1; ++it2; } | |
|       else if (it1.index() < it2.index()) ++it1; else ++it2; | |
|     } | |
|     return res; | |
|   } | |
| 
 | |
|   template <typename V1, typename V2> inline | |
|   typename strongest_value_type<V1,V2>::value_type | |
|   vect_sp_sparse_sparse(const V1 &v1, const V2 &v2, linalg_false) { | |
|     return vect_sp_sparse_(vect_const_begin(v1), vect_const_end(v1), v2); | |
|   } | |
| 
 | |
|   template <typename V1, typename V2> inline | |
|     typename strongest_value_type<V1,V2>::value_type | |
|     vect_sp(const V1 &v1, const V2 &v2,abstract_sparse,abstract_sparse) { | |
|     return vect_sp_sparse_sparse(v1, v2, | |
| 	    typename linalg_and<typename linalg_traits<V1>::index_sorted, | |
| 	    typename linalg_traits<V2>::index_sorted>::bool_type()); | |
|   } | |
|    | |
|   /* ******************************************************************** */ | |
|   /*		Hermitian product                             		  */ | |
|   /* ******************************************************************** */ | |
|   ///@endcond | |
|   /** Hermitian product. */ | |
|   template <typename V1, typename V2> | |
|   inline typename strongest_value_type<V1,V2>::value_type | |
|   vect_hp(const V1 &v1, const V2 &v2) | |
|   { return vect_sp(v1, conjugated(v2)); } | |
| 
 | |
|   /** Hermitian product with a matrix. */ | |
|   template <typename MATSP, typename V1, typename V2> inline | |
|   typename strongest_value_type3<V1,V2,MATSP>::value_type | |
|     vect_hp(const MATSP &ps, const V1 &v1, const V2 &v2) { | |
|     return vect_sp(ps, v1, gmm::conjugated(v2)); | |
|   } | |
| 
 | |
|   /* ******************************************************************** */ | |
|   /*		Trace of a matrix                             		  */ | |
|   /* ******************************************************************** */ | |
|    | |
|   /** Trace of a matrix */ | |
|    template <typename M> | |
|    typename linalg_traits<M>::value_type | |
|    mat_trace(const M &m) { | |
|      typedef typename linalg_traits<M>::value_type T; | |
|      T res(0); | |
|      for (size_type i = 0; i < std::min(mat_nrows(m), mat_ncols(m)); ++i) | |
|        res += m(i,i); | |
|      return res; | |
|   } | |
| 
 | |
|   /* ******************************************************************** */ | |
|   /*		Euclidean norm                             		  */ | |
|   /* ******************************************************************** */ | |
| 
 | |
|   /** Euclidean norm of a vector. */ | |
|   template <typename V> | |
|   typename number_traits<typename linalg_traits<V>::value_type> | |
|   ::magnitude_type | |
|   vect_norm2_sqr(const V &v) { | |
|     typedef typename linalg_traits<V>::value_type T; | |
|     typedef typename number_traits<T>::magnitude_type R; | |
|     typename linalg_traits<V>::const_iterator | |
|       it = vect_const_begin(v), ite = vect_const_end(v); | |
|     R res(0); | |
|     for (; it != ite; ++it) res += gmm::abs_sqr(*it); | |
|     return res; | |
|   } | |
| 
 | |
|   /** squared Euclidean norm of a vector. */ | |
|   template <typename V> inline | |
|    typename number_traits<typename linalg_traits<V>::value_type> | |
|    ::magnitude_type  | |
|   vect_norm2(const V &v) | |
|   { return sqrt(vect_norm2_sqr(v)); } | |
|    | |
| 
 | |
|   /** squared Euclidean distance between two vectors */ | |
|   template <typename V1, typename V2> inline | |
|    typename number_traits<typename linalg_traits<V1>::value_type> | |
|    ::magnitude_type | |
|   vect_dist2_sqr(const V1 &v1, const V2 &v2) { // not fully optimized  | |
|     typedef typename linalg_traits<V1>::value_type T; | |
|     typedef typename number_traits<T>::magnitude_type R; | |
|     typename linalg_traits<V1>::const_iterator | |
|       it1 = vect_const_begin(v1), ite1 = vect_const_end(v1); | |
|     typename linalg_traits<V2>::const_iterator | |
|       it2 = vect_const_begin(v2), ite2 = vect_const_end(v2); | |
|     size_type k1(0), k2(0); | |
|     R res(0); | |
|     while (it1 != ite1 && it2 != ite2) { | |
|       size_type i1 = index_of_it(it1, k1, | |
| 				 typename linalg_traits<V1>::storage_type()); | |
|       size_type i2 = index_of_it(it2, k2, | |
| 				 typename linalg_traits<V2>::storage_type()); | |
| 
 | |
|       if (i1 == i2) { | |
| 	res += gmm::abs_sqr(*it2 - *it1); ++it1; ++k1; ++it2; ++k2; | |
|       } | |
|       else if (i1 < i2) { | |
| 	res += gmm::abs_sqr(*it1); ++it1; ++k1;  | |
|       } | |
|       else  { | |
| 	res += gmm::abs_sqr(*it2); ++it2; ++k2;  | |
|       } | |
|     } | |
|     while (it1 != ite1) { res += gmm::abs_sqr(*it1); ++it1; } | |
|     while (it2 != ite2) { res += gmm::abs_sqr(*it2); ++it2; } | |
|     return res; | |
|   } | |
|   | |
|   /** Euclidean distance between two vectors */ | |
|   template <typename V1, typename V2> inline | |
|    typename number_traits<typename linalg_traits<V1>::value_type> | |
|    ::magnitude_type | |
|   vect_dist2(const V1 &v1, const V2 &v2) | |
|   { return sqrt(vect_dist2_sqr(v1, v2)); } | |
|   ///@cond DOXY_SHOW_ALL_FUNCTIONS | |
|   template <typename M> | |
|    typename number_traits<typename linalg_traits<M>::value_type> | |
|    ::magnitude_type | |
|    mat_euclidean_norm_sqr(const M &m, row_major) { | |
|     typename number_traits<typename linalg_traits<M>::value_type> | |
|       ::magnitude_type res(0); | |
|     for (size_type i = 0; i < mat_nrows(m); ++i) | |
|       res += vect_norm2_sqr(mat_const_row(m, i)); | |
|     return res; | |
|   } | |
| 
 | |
|   template <typename M> | |
|    typename number_traits<typename linalg_traits<M>::value_type> | |
|    ::magnitude_type | |
|    mat_euclidean_norm_sqr(const M &m, col_major) { | |
|     typename number_traits<typename linalg_traits<M>::value_type> | |
|       ::magnitude_type res(0); | |
|     for (size_type i = 0; i < mat_ncols(m); ++i) | |
|       res += vect_norm2_sqr(mat_const_col(m, i)); | |
|     return res; | |
|   } | |
|   ///@endcond | |
|   /** squared Euclidean norm of a matrix. */ | |
|   template <typename M> inline | |
|    typename number_traits<typename linalg_traits<M>::value_type> | |
|    ::magnitude_type | |
|    mat_euclidean_norm_sqr(const M &m) { | |
|     return mat_euclidean_norm_sqr(m, | |
| 		     typename principal_orientation_type<typename | |
| 		     linalg_traits<M>::sub_orientation>::potype()); | |
|   } | |
| 
 | |
|   /** Euclidean norm of a matrix. */ | |
|   template <typename M> inline | |
|    typename number_traits<typename linalg_traits<M>::value_type> | |
|    ::magnitude_type | |
|    mat_euclidean_norm(const M &m) | |
|   { return gmm::sqrt(mat_euclidean_norm_sqr(m)); } | |
| 
 | |
|   /* ******************************************************************** */ | |
|   /*		vector norm1                                    	  */ | |
|   /* ******************************************************************** */ | |
|   /** 1-norm of a vector */ | |
|   template <typename V> | |
|   typename number_traits<typename linalg_traits<V>::value_type> | |
|   ::magnitude_type | |
|   vect_norm1(const V &v) { | |
|     typename linalg_traits<V>::const_iterator | |
|       it = vect_const_begin(v), ite = vect_const_end(v); | |
|     typename number_traits<typename linalg_traits<V>::value_type> | |
| 	::magnitude_type res(0); | |
|     for (; it != ite; ++it) res += gmm::abs(*it); | |
|     return res; | |
|   } | |
| 
 | |
|   /* ******************************************************************** */ | |
|   /*		vector Infinity norm                              	  */ | |
|   /* ******************************************************************** */ | |
|   /** Infinity norm of a vector. */ | |
|   template <typename V> | |
|   typename number_traits<typename linalg_traits<V>::value_type> | |
|   ::magnitude_type  | |
|   vect_norminf(const V &v) { | |
|     typename linalg_traits<V>::const_iterator | |
|       it = vect_const_begin(v), ite = vect_const_end(v); | |
|       typename number_traits<typename linalg_traits<V>::value_type> | |
| 	::magnitude_type res(0); | |
|     for (; it != ite; ++it) res = std::max(res, gmm::abs(*it)); | |
|     return res; | |
|   } | |
| 
 | |
|   /* ******************************************************************** */ | |
|   /*		matrix norm1                                    	  */ | |
|   /* ******************************************************************** */ | |
|   ///@cond DOXY_SHOW_ALL_FUNCTIONS | |
|   template <typename M> | |
|    typename number_traits<typename linalg_traits<M>::value_type> | |
|    ::magnitude_type | |
|    mat_norm1(const M &m, col_major) { | |
|     typename number_traits<typename linalg_traits<M>::value_type> | |
|       ::magnitude_type res(0); | |
|     for (size_type i = 0; i < mat_ncols(m); ++i) | |
|       res = std::max(res, vect_norm1(mat_const_col(m,i))); | |
|     return res; | |
|   } | |
| 
 | |
|   template <typename M> | |
|    typename number_traits<typename linalg_traits<M>::value_type> | |
|    ::magnitude_type | |
|    mat_norm1(const M &m, row_major) { | |
|     typedef typename linalg_traits<M>::value_type T; | |
|     typedef typename number_traits<T>::magnitude_type R; | |
|     typedef typename linalg_traits<M>::storage_type store_type; | |
|      | |
|     std::vector<R> aux(mat_ncols(m)); | |
|     for (size_type i = 0; i < mat_nrows(m); ++i) { | |
|       typedef typename linalg_traits<M>::const_sub_row_type row_type; | |
|       row_type row = mat_const_row(m, i); | |
|       typename linalg_traits<row_type>::const_iterator | |
| 	it = vect_const_begin(row), ite = vect_const_end(row); | |
|       for (size_type k = 0; it != ite; ++it, ++k) | |
| 	aux[index_of_it(it, k, store_type())] += gmm::abs(*it); | |
|     } | |
|     return vect_norminf(aux); | |
|   } | |
| 
 | |
|   template <typename M> | |
|    typename number_traits<typename linalg_traits<M>::value_type> | |
|    ::magnitude_type | |
|    mat_norm1(const M &m, col_and_row) | |
|   { return mat_norm1(m, col_major()); } | |
| 
 | |
|   template <typename M> | |
|    typename number_traits<typename linalg_traits<M>::value_type> | |
|    ::magnitude_type | |
|    mat_norm1(const M &m, row_and_col) | |
|   { return mat_norm1(m, col_major()); } | |
|   ///@endcond | |
|   /** 1-norm of a matrix */ | |
|   template <typename M> | |
|    typename number_traits<typename linalg_traits<M>::value_type> | |
|    ::magnitude_type | |
|    mat_norm1(const M &m) { | |
|     return mat_norm1(m, typename linalg_traits<M>::sub_orientation()); | |
|   } | |
| 
 | |
| 
 | |
|   /* ******************************************************************** */ | |
|   /*		matrix Infinity norm                              	  */ | |
|   /* ******************************************************************** */ | |
|   ///@cond DOXY_SHOW_ALL_FUNCTIONS | |
|   template <typename M> | |
|    typename number_traits<typename linalg_traits<M>::value_type> | |
|    ::magnitude_type | |
|    mat_norminf(const M &m, row_major) { | |
|     typename number_traits<typename linalg_traits<M>::value_type> | |
|       ::magnitude_type res(0); | |
|     for (size_type i = 0; i < mat_nrows(m); ++i) | |
|       res = std::max(res, vect_norm1(mat_const_row(m,i))); | |
|     return res; | |
|   } | |
| 
 | |
|   template <typename M> | |
|    typename number_traits<typename linalg_traits<M>::value_type> | |
|    ::magnitude_type | |
|    mat_norminf(const M &m, col_major) { | |
|     typedef typename linalg_traits<M>::value_type T; | |
|     typedef typename number_traits<T>::magnitude_type R; | |
|     typedef typename linalg_traits<M>::storage_type store_type; | |
|      | |
|     std::vector<R> aux(mat_nrows(m)); | |
|     for (size_type i = 0; i < mat_ncols(m); ++i) { | |
|       typedef typename linalg_traits<M>::const_sub_col_type col_type; | |
|       col_type col = mat_const_col(m, i); | |
|       typename linalg_traits<col_type>::const_iterator | |
| 	it = vect_const_begin(col), ite = vect_const_end(col); | |
|       for (size_type k = 0; it != ite; ++it, ++k) | |
| 	aux[index_of_it(it, k, store_type())] += gmm::abs(*it); | |
|     } | |
|     return vect_norminf(aux); | |
|   } | |
| 
 | |
|   template <typename M> | |
|    typename number_traits<typename linalg_traits<M>::value_type> | |
|    ::magnitude_type | |
|    mat_norminf(const M &m, col_and_row) | |
|   { return mat_norminf(m, row_major()); } | |
| 
 | |
|   template <typename M> | |
|    typename number_traits<typename linalg_traits<M>::value_type> | |
|    ::magnitude_type | |
|    mat_norminf(const M &m, row_and_col) | |
|   { return mat_norminf(m, row_major()); } | |
|   ///@endcond | |
|   /** infinity-norm of a matrix.*/ | |
|   template <typename M> | |
|    typename number_traits<typename linalg_traits<M>::value_type> | |
|    ::magnitude_type | |
|    mat_norminf(const M &m) { | |
|     return mat_norminf(m, typename linalg_traits<M>::sub_orientation()); | |
|   } | |
| 
 | |
|   /* ******************************************************************** */ | |
|   /*		Max norm for matrices                              	  */ | |
|   /* ******************************************************************** */ | |
|   ///@cond DOXY_SHOW_ALL_FUNCTIONS | |
|   template <typename M> | |
|    typename number_traits<typename linalg_traits<M>::value_type> | |
|    ::magnitude_type | |
|    mat_maxnorm(const M &m, row_major) { | |
|     typename number_traits<typename linalg_traits<M>::value_type> | |
|       ::magnitude_type res(0); | |
|     for (size_type i = 0; i < mat_nrows(m); ++i) | |
|       res = std::max(res, vect_norminf(mat_const_row(m,i))); | |
|     return res; | |
|   } | |
| 
 | |
|   template <typename M> | |
|    typename number_traits<typename linalg_traits<M>::value_type> | |
|    ::magnitude_type | |
|    mat_maxnorm(const M &m, col_major) { | |
|     typename number_traits<typename linalg_traits<M>::value_type> | |
|       ::magnitude_type res(0); | |
|     for (size_type i = 0; i < mat_ncols(m); ++i) | |
|       res = std::max(res, vect_norminf(mat_const_col(m,i))); | |
|     return res; | |
|   } | |
|   ///@endcond | |
|   /** max-norm of a matrix. */ | |
|   template <typename M> | |
|    typename number_traits<typename linalg_traits<M>::value_type> | |
|    ::magnitude_type | |
|    mat_maxnorm(const M &m) { | |
|     return mat_maxnorm(m, | |
| 		     typename principal_orientation_type<typename | |
| 		     linalg_traits<M>::sub_orientation>::potype()); | |
|   } | |
| 
 | |
|   /* ******************************************************************** */ | |
|   /*		Clean                                    		  */ | |
|   /* ******************************************************************** */ | |
|   /** Clean a vector or matrix (replace near-zero entries with zeroes).   */ | |
|    | |
|   template <typename L> inline void clean(L &l, double threshold); | |
| 
 | |
|   ///@cond DOXY_SHOW_ALL_FUNCTIONS | |
|  | |
|   template <typename L, typename T> | |
|   void clean(L &l, double threshold, abstract_dense, T) { | |
|     typedef typename number_traits<T>::magnitude_type R; | |
|     typename linalg_traits<L>::iterator it = vect_begin(l), ite = vect_end(l); | |
|     for (; it != ite; ++it) | |
|       if (gmm::abs(*it) < R(threshold)) *it = T(0); | |
|   } | |
| 
 | |
|   template <typename L, typename T> | |
|   void clean(L &l, double threshold, abstract_skyline, T) | |
|   { gmm::clean(l, threshold, abstract_dense(), T()); } | |
| 
 | |
|   template <typename L, typename T> | |
|   void clean(L &l, double threshold, abstract_sparse, T) { | |
|     typedef typename number_traits<T>::magnitude_type R; | |
|     typename linalg_traits<L>::iterator it = vect_begin(l), ite = vect_end(l); | |
|     std::vector<size_type> ind; | |
|     for (; it != ite; ++it) | |
|       if (gmm::abs(*it) < R(threshold)) ind.push_back(it.index()); | |
|     for (size_type i = 0; i < ind.size(); ++i) l[ind[i]] = T(0); | |
|   } | |
|    | |
|   template <typename L, typename T> | |
|   void clean(L &l, double threshold, abstract_dense, std::complex<T>) { | |
|     typename linalg_traits<L>::iterator it = vect_begin(l), ite = vect_end(l); | |
|     for (; it != ite; ++it){ | |
|       if (gmm::abs((*it).real()) < T(threshold)) | |
| 	*it = std::complex<T>(T(0), (*it).imag()); | |
|       if (gmm::abs((*it).imag()) < T(threshold)) | |
| 	*it = std::complex<T>((*it).real(), T(0)); | |
|     } | |
|   } | |
| 
 | |
|   template <typename L, typename T> | |
|   void clean(L &l, double threshold, abstract_skyline, std::complex<T>) | |
|   { gmm::clean(l, threshold, abstract_dense(), std::complex<T>()); } | |
| 
 | |
|   template <typename L, typename T> | |
|   void clean(L &l, double threshold, abstract_sparse, std::complex<T>) { | |
|     typename linalg_traits<L>::iterator it = vect_begin(l), ite = vect_end(l); | |
|     std::vector<size_type> ind; | |
|     for (; it != ite; ++it) { | |
|       bool r = (gmm::abs((*it).real()) < T(threshold)); | |
|       bool i = (gmm::abs((*it).imag()) < T(threshold)); | |
|       if (r && i) ind.push_back(it.index()); | |
|       else if (r) (*it).real() = T(0); | |
|       else if (i) (*it).imag() = T(0); | |
|     } | |
|     for (size_type i = 0; i < ind.size(); ++i) | |
|       l[ind[i]] = std::complex<T>(T(0),T(0)); | |
|   } | |
| 
 | |
|   template <typename L> inline void clean(L &l, double threshold, | |
| 					  abstract_vector) { | |
|     gmm::clean(l, threshold, typename linalg_traits<L>::storage_type(), | |
| 	       typename linalg_traits<L>::value_type()); | |
|   } | |
| 
 | |
|   template <typename L> inline void clean(const L &l, double threshold); | |
| 
 | |
|   template <typename L> void clean(L &l, double threshold, row_major) { | |
|     for (size_type i = 0; i < mat_nrows(l); ++i) | |
|       gmm::clean(mat_row(l, i), threshold); | |
|   } | |
| 
 | |
|   template <typename L> void clean(L &l, double threshold, col_major) { | |
|     for (size_type i = 0; i < mat_ncols(l); ++i) | |
|       gmm::clean(mat_col(l, i), threshold); | |
|   } | |
| 
 | |
|   template <typename L> inline void clean(L &l, double threshold, | |
| 					  abstract_matrix) { | |
|     gmm::clean(l, threshold, | |
| 	       typename principal_orientation_type<typename | |
| 	       linalg_traits<L>::sub_orientation>::potype()); | |
|   } | |
| 
 | |
|   template <typename L> inline void clean(L &l, double threshold) | |
|   { clean(l, threshold, typename linalg_traits<L>::linalg_type()); } | |
|   | |
|   template <typename L> inline void clean(const L &l, double threshold) | |
|   { gmm::clean(linalg_const_cast(l), threshold); } | |
| 
 | |
|   /* ******************************************************************** */ | |
|   /*		Copy                                    		  */ | |
|   /* ******************************************************************** */ | |
|   ///@endcond | |
|   /** Copy vectors or matrices.  | |
|       @param l1 source vector or matrix. | |
|       @param l2 destination. | |
|   */ | |
|   template <typename L1, typename L2> inline | |
|   void copy(const L1& l1, L2& l2) {  | |
|     if ((const void *)(&l1) != (const void *)(&l2)) { | |
|       if (same_origin(l1,l2)) | |
| 	GMM_WARNING2("Warning : a conflict is possible in copy\n"); | |
|       | |
|       copy(l1, l2, typename linalg_traits<L1>::linalg_type(), | |
| 	   typename linalg_traits<L2>::linalg_type()); | |
|     } | |
|   } | |
|   ///@cond DOXY_SHOW_ALL_FUNCTIONS | |
|  | |
|   template <typename L1, typename L2> inline | |
|   void copy(const L1& l1, const L2& l2) { copy(l1, linalg_const_cast(l2)); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void copy(const L1& l1, L2& l2, abstract_vector, abstract_vector) { | |
|     GMM_ASSERT2(vect_size(l1) == vect_size(l2), "dimensions mismatch"); | |
|     copy_vect(l1, l2, typename linalg_traits<L1>::storage_type(), | |
| 	      typename linalg_traits<L2>::storage_type()); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void copy(const L1& l1, L2& l2, abstract_matrix, abstract_matrix) { | |
|     size_type m = mat_nrows(l1), n = mat_ncols(l1); | |
|     if (!m || !n) return; | |
|     GMM_ASSERT2(n==mat_ncols(l2) && m==mat_nrows(l2), "dimensions mismatch"); | |
|     copy_mat(l1, l2, typename linalg_traits<L1>::sub_orientation(), | |
| 	     typename linalg_traits<L2>::sub_orientation()); | |
|   } | |
| 
 | |
|   template <typename V1, typename V2, typename C1, typename C2> inline  | |
|   void copy_vect(const V1 &v1, const V2 &v2, C1, C2) | |
|   { copy_vect(v1, const_cast<V2 &>(v2), C1(), C2()); } | |
|    | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void copy_mat_by_row(const L1& l1, L2& l2) { | |
|     size_type nbr = mat_nrows(l1); | |
|     for (size_type i = 0; i < nbr; ++i) | |
|       copy_vect(mat_const_row(l1, i), mat_row(l2, i), | |
|       		typename linalg_traits<L1>::storage_type(), | |
| 		typename linalg_traits<L2>::storage_type()); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void copy_mat_by_col(const L1 &l1, L2 &l2) { | |
|     size_type nbc = mat_ncols(l1); | |
|     for (size_type i = 0; i < nbc; ++i) { | |
|       copy_vect(mat_const_col(l1, i), mat_col(l2, i), | |
|       		typename linalg_traits<L1>::storage_type(), | |
| 		typename linalg_traits<L2>::storage_type()); | |
|     } | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void copy_mat(const L1& l1, L2& l2, row_major, row_major) | |
|   { copy_mat_by_row(l1, l2); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void copy_mat(const L1& l1, L2& l2, row_major, row_and_col) | |
|   { copy_mat_by_row(l1, l2); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void copy_mat(const L1& l1, L2& l2, row_and_col, row_and_col) | |
|   { copy_mat_by_row(l1, l2); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void copy_mat(const L1& l1, L2& l2, row_and_col, row_major) | |
|   { copy_mat_by_row(l1, l2); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void copy_mat(const L1& l1, L2& l2, col_and_row, row_major) | |
|   { copy_mat_by_row(l1, l2); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void copy_mat(const L1& l1, L2& l2, row_major, col_and_row) | |
|   { copy_mat_by_row(l1, l2); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void copy_mat(const L1& l1, L2& l2, col_and_row, row_and_col) | |
|   { copy_mat_by_row(l1, l2); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void copy_mat(const L1& l1, L2& l2, row_and_col, col_and_row) | |
|   { copy_mat_by_row(l1, l2); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void copy_mat(const L1& l1, L2& l2, col_major, col_major) | |
|   { copy_mat_by_col(l1, l2); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void copy_mat(const L1& l1, L2& l2, col_major, col_and_row) | |
|   { copy_mat_by_col(l1, l2); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void copy_mat(const L1& l1, L2& l2, col_major, row_and_col) | |
|   { copy_mat_by_col(l1, l2); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void copy_mat(const L1& l1, L2& l2, row_and_col, col_major) | |
|   { copy_mat_by_col(l1, l2); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void copy_mat(const L1& l1, L2& l2, col_and_row, col_major) | |
|   { copy_mat_by_col(l1, l2); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void copy_mat(const L1& l1, L2& l2, col_and_row, col_and_row) | |
|   { copy_mat_by_col(l1, l2); } | |
|    | |
|   template <typename L1, typename L2> inline | |
|   void copy_mat_mixed_rc(const L1& l1, L2& l2, size_type i) { | |
|     copy_mat_mixed_rc(l1, l2, i, typename linalg_traits<L1>::storage_type()); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void copy_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_sparse) { | |
|     typename linalg_traits<L1>::const_iterator | |
|       it  = vect_const_begin(l1), ite = vect_const_end(l1); | |
|     for (; it != ite; ++it) | |
|       l2(i, it.index()) = *it; | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void copy_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_skyline) { | |
|     typename linalg_traits<L1>::const_iterator | |
|       it  = vect_const_begin(l1), ite = vect_const_end(l1); | |
|     for (; it != ite; ++it) | |
|       l2(i, it.index()) = *it; | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void copy_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_dense) { | |
|     typename linalg_traits<L1>::const_iterator | |
|       it  = vect_const_begin(l1), ite = vect_const_end(l1); | |
|     for (size_type j = 0; it != ite; ++it, ++j) l2(i, j) = *it; | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void copy_mat_mixed_cr(const L1& l1, L2& l2, size_type i) { | |
|     copy_mat_mixed_cr(l1, l2, i, typename linalg_traits<L1>::storage_type()); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void copy_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_sparse) { | |
|     typename linalg_traits<L1>::const_iterator | |
|       it  = vect_const_begin(l1), ite = vect_const_end(l1); | |
|     for (; it != ite; ++it) l2(it.index(), i) = *it; | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void copy_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_skyline) { | |
|     typename linalg_traits<L1>::const_iterator | |
|       it  = vect_const_begin(l1), ite = vect_const_end(l1); | |
|     for (; it != ite; ++it) l2(it.index(), i) = *it; | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void copy_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_dense) { | |
|     typename linalg_traits<L1>::const_iterator | |
|       it  = vect_const_begin(l1), ite = vect_const_end(l1); | |
|     for (size_type j = 0; it != ite; ++it, ++j) l2(j, i) = *it; | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void copy_mat(const L1& l1, L2& l2, row_major, col_major) { | |
|     clear(l2); | |
|     size_type nbr = mat_nrows(l1); | |
|     for (size_type i = 0; i < nbr; ++i) | |
|       copy_mat_mixed_rc(mat_const_row(l1, i), l2, i); | |
|   } | |
|    | |
|   template <typename L1, typename L2> | |
|   void copy_mat(const L1& l1, L2& l2, col_major, row_major) { | |
|     clear(l2); | |
|     size_type nbc = mat_ncols(l1); | |
|     for (size_type i = 0; i < nbc; ++i) | |
|       copy_mat_mixed_cr(mat_const_col(l1, i), l2, i); | |
|   } | |
|    | |
|   template <typename L1, typename L2> inline | |
|   void copy_vect(const L1 &l1, L2 &l2, abstract_dense, abstract_dense) { | |
|     std::copy(vect_const_begin(l1), vect_const_end(l1), vect_begin(l2)); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> inline // to be optimised ? | |
|   void copy_vect(const L1 &l1, L2 &l2, abstract_skyline, abstract_skyline) { | |
|     typename linalg_traits<L1>::const_iterator it1 = vect_const_begin(l1), | |
|       ite1 = vect_const_end(l1); | |
|     while (it1 != ite1 && *it1 == typename linalg_traits<L1>::value_type(0)) | |
|       ++it1; | |
| 
 | |
|     if (ite1 - it1 > 0) { | |
|       clear(l2); | |
|       typename linalg_traits<L2>::iterator it2 = vect_begin(l2),  | |
| 	ite2 = vect_end(l2); | |
|       while (*(ite1-1) == typename linalg_traits<L1>::value_type(0)) ite1--; | |
| 
 | |
|       if (it2 == ite2) { | |
| 	l2[it1.index()] = *it1; ++it1; | |
| 	l2[ite1.index()-1] = *(ite1-1); --ite1; | |
| 	if (it1 < ite1) | |
| 	  { it2 = vect_begin(l2); ++it2; std::copy(it1, ite1, it2); } | |
|       } | |
|       else { | |
| 	ptrdiff_t m = it1.index() - it2.index(); | |
| 	if (m >= 0 && ite1.index() <= ite2.index()) | |
| 	  std::copy(it1, ite1, it2 + m); | |
| 	else { | |
| 	  if (m < 0) l2[it1.index()] = *it1; | |
| 	  if (ite1.index() > ite2.index()) l2[ite1.index()-1] = *(ite1-1); | |
| 	  it2 = vect_begin(l2); ite2 = vect_end(l2); | |
| 	  m = it1.index() - it2.index(); | |
| 	  std::copy(it1, ite1, it2 + m); | |
| 	} | |
|       } | |
|     } | |
|   } | |
|    | |
|   template <typename L1, typename L2> | |
|   void copy_vect(const L1& l1, L2& l2, abstract_sparse, abstract_dense) { | |
|     clear(l2); | |
|     typename linalg_traits<L1>::const_iterator | |
|       it  = vect_const_begin(l1), ite = vect_const_end(l1); | |
|     for (; it != ite; ++it) { l2[it.index()] = *it; } | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void copy_vect(const L1& l1, L2& l2, abstract_sparse, abstract_skyline) { | |
|     clear(l2); | |
|     typename linalg_traits<L1>::const_iterator | |
|       it  = vect_const_begin(l1), ite = vect_const_end(l1); | |
|     for (; it != ite; ++it) l2[it.index()] = *it; | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void copy_vect(const L1& l1, L2& l2, abstract_skyline, abstract_dense) { | |
|     typedef typename linalg_traits<L1>::value_type T; | |
|     typedef typename linalg_traits<L1>::const_iterator l1_const_iterator; | |
|     typedef typename linalg_traits<L2>::iterator l2_iterator; | |
|     l1_const_iterator it = vect_const_begin(l1), ite = vect_const_end(l1); | |
|     if (it == ite) | |
|       gmm::clear(l2); | |
|     else { | |
|       l2_iterator it2 = vect_begin(l2), ite2 = vect_end(l2); | |
|        | |
|       size_type i = it.index(), j; | |
|       for (j = 0; j < i; ++j, ++it2) *it2 = T(0); | |
|       for (; it != ite; ++it, ++it2) *it2 = *it; | |
|       for (; it2 != ite2; ++it2) *it2 = T(0); | |
|     } | |
|   } | |
|      | |
|   template <typename L1, typename L2> | |
|   void copy_vect(const L1& l1, L2& l2, abstract_sparse, abstract_sparse) { | |
|     typename linalg_traits<L1>::const_iterator | |
|       it  = vect_const_begin(l1), ite = vect_const_end(l1); | |
|     clear(l2); | |
|     for (; it != ite; ++it) | |
|       if (*it != (typename linalg_traits<L1>::value_type)(0)) | |
| 	l2[it.index()] = *it; | |
|   } | |
|    | |
|   template <typename L1, typename L2> | |
|   void copy_vect(const L1& l1, L2& l2, abstract_dense, abstract_sparse) { | |
|     clear(l2); | |
|     typename linalg_traits<L1>::const_iterator | |
|       it  = vect_const_begin(l1), ite = vect_const_end(l1); | |
|     for (size_type i = 0; it != ite; ++it, ++i) | |
|       if (*it != (typename linalg_traits<L1>::value_type)(0)) | |
| 	l2[i] = *it; | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> // to be optimised ... | |
|   void copy_vect(const L1& l1, L2& l2, abstract_dense, abstract_skyline) { | |
|     clear(l2); | |
|     typename linalg_traits<L1>::const_iterator | |
|       it  = vect_const_begin(l1), ite = vect_const_end(l1); | |
|     for (size_type i = 0; it != ite; ++it, ++i) | |
|       if (*it != (typename linalg_traits<L1>::value_type)(0)) | |
| 	l2[i] = *it; | |
|   } | |
| 
 | |
|    | |
|   template <typename L1, typename L2> | |
|   void copy_vect(const L1& l1, L2& l2, abstract_skyline, abstract_sparse) { | |
|     clear(l2); | |
|     typename linalg_traits<L1>::const_iterator | |
|       it  = vect_const_begin(l1), ite = vect_const_end(l1); | |
|     for (; it != ite; ++it) | |
|       if (*it != (typename linalg_traits<L1>::value_type)(0)) | |
| 	l2[it.index()] = *it; | |
|   } | |
| 
 | |
|   /* ******************************************************************** */ | |
|   /*		Matrix and vector addition                             	  */ | |
|   /*   algorithms are built in order to avoid some conflicts whith        */ | |
|   /*   repeated arguments or with overlapping part of a same object.      */ | |
|   /*   In the latter case, conflicts are still possible.                  */ | |
|   /* ******************************************************************** */ | |
|   ///@endcond | |
|   /** Add two vectors or matrices | |
|       @param l1 | |
|       @param l2 contains on output, l2+l1. | |
|   */ | |
|   template <typename L1, typename L2> inline | |
|     void add(const L1& l1, L2& l2) { | |
|       add_spec(l1, l2, typename linalg_traits<L2>::linalg_type()); | |
|   } | |
|   ///@cond | |
|  | |
|   template <typename L1, typename L2> inline | |
|   void add(const L1& l1, const L2& l2) { add(l1, linalg_const_cast(l2)); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|     void add_spec(const L1& l1, L2& l2, abstract_vector) { | |
|     GMM_ASSERT2(vect_size(l1) == vect_size(l2), "dimensions mismatch"); | |
|     add(l1, l2, typename linalg_traits<L1>::storage_type(), | |
| 	typename linalg_traits<L2>::storage_type()); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|     void add_spec(const L1& l1, L2& l2, abstract_matrix) { | |
|     size_type m = mat_nrows(l1), n = mat_ncols(l1); | |
|     GMM_ASSERT2(m==mat_nrows(l2) && n==mat_ncols(l2), "dimensions mismatch"); | |
|     add(l1, l2, typename linalg_traits<L1>::sub_orientation(), | |
| 	typename linalg_traits<L2>::sub_orientation()); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void add(const L1& l1, L2& l2, row_major, row_major) { | |
|     typename linalg_traits<L1>::const_row_iterator it1 = mat_row_begin(l1), | |
|       ite = mat_row_end(l1); | |
|     typename linalg_traits<L2>::row_iterator it2 = mat_row_begin(l2); | |
|     for ( ; it1 != ite; ++it1, ++it2) | |
|       add(linalg_traits<L1>::row(it1), linalg_traits<L2>::row(it2)); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void add(const L1& l1, L2& l2, col_major, col_major) { | |
|     typename linalg_traits<L1>::const_col_iterator | |
|       it1 = mat_col_const_begin(l1), | |
|       ite = mat_col_const_end(l1); | |
|     typename linalg_traits<L2>::col_iterator it2 = mat_col_begin(l2); | |
|     for ( ; it1 != ite; ++it1, ++it2) | |
|       add(linalg_traits<L1>::col(it1),  linalg_traits<L2>::col(it2)); | |
|   } | |
|    | |
|     template <typename L1, typename L2> inline | |
|   void add_mat_mixed_rc(const L1& l1, L2& l2, size_type i) { | |
|     add_mat_mixed_rc(l1, l2, i, typename linalg_traits<L1>::storage_type()); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void add_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_sparse) { | |
|     typename linalg_traits<L1>::const_iterator | |
|       it  = vect_const_begin(l1), ite = vect_const_end(l1); | |
|     for (; it != ite; ++it) l2(i, it.index()) += *it; | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void add_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_skyline) { | |
|     typename linalg_traits<L1>::const_iterator | |
|       it  = vect_const_begin(l1), ite = vect_const_end(l1); | |
|     for (; it != ite; ++it) l2(i, it.index()) += *it; | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void add_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_dense) { | |
|     typename linalg_traits<L1>::const_iterator | |
|       it  = vect_const_begin(l1), ite = vect_const_end(l1); | |
|     for (size_type j = 0; it != ite; ++it, ++j) l2(i, j) += *it; | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void add_mat_mixed_cr(const L1& l1, L2& l2, size_type i) { | |
|     add_mat_mixed_cr(l1, l2, i, typename linalg_traits<L1>::storage_type()); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void add_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_sparse) { | |
|     typename linalg_traits<L1>::const_iterator | |
|       it  = vect_const_begin(l1), ite = vect_const_end(l1); | |
|     for (; it != ite; ++it) l2(it.index(), i) += *it; | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void add_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_skyline) { | |
|     typename linalg_traits<L1>::const_iterator | |
|       it  = vect_const_begin(l1), ite = vect_const_end(l1); | |
|     for (; it != ite; ++it) l2(it.index(), i) += *it; | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void add_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_dense) { | |
|     typename linalg_traits<L1>::const_iterator | |
|       it  = vect_const_begin(l1), ite = vect_const_end(l1); | |
|     for (size_type j = 0; it != ite; ++it, ++j) l2(j, i) += *it; | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void add(const L1& l1, L2& l2, row_major, col_major) { | |
|     size_type nbr = mat_nrows(l1); | |
|     for (size_type i = 0; i < nbr; ++i) | |
|       add_mat_mixed_rc(mat_const_row(l1, i), l2, i); | |
|   } | |
|    | |
|   template <typename L1, typename L2> | |
|   void add(const L1& l1, L2& l2, col_major, row_major) { | |
|     size_type nbc = mat_ncols(l1); | |
|     for (size_type i = 0; i < nbc; ++i) | |
|       add_mat_mixed_cr(mat_const_col(l1, i), l2, i); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void add(const L1& l1, L2& l2, row_and_col, row_major) | |
|   { add(l1, l2, row_major(), row_major()); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void add(const L1& l1, L2& l2, row_and_col, row_and_col) | |
|   { add(l1, l2, row_major(), row_major()); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void add(const L1& l1, L2& l2, row_and_col, col_and_row) | |
|   { add(l1, l2, row_major(), row_major()); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void add(const L1& l1, L2& l2, col_and_row, row_and_col) | |
|   { add(l1, l2, row_major(), row_major()); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void add(const L1& l1, L2& l2, row_major, row_and_col) | |
|   { add(l1, l2, row_major(), row_major()); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void add(const L1& l1, L2& l2, col_and_row, row_major) | |
|   { add(l1, l2, row_major(), row_major()); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void add(const L1& l1, L2& l2, row_major, col_and_row) | |
|   { add(l1, l2, row_major(), row_major()); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void add(const L1& l1, L2& l2, row_and_col, col_major) | |
|   { add(l1, l2, col_major(), col_major()); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void add(const L1& l1, L2& l2, col_major, row_and_col) | |
|   { add(l1, l2, col_major(), col_major()); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void add(const L1& l1, L2& l2, col_and_row, col_major) | |
|   { add(l1, l2, col_major(), col_major()); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void add(const L1& l1, L2& l2, col_and_row, col_and_row) | |
|   { add(l1, l2, col_major(), col_major()); } | |
| 
 | |
|   template <typename L1, typename L2> inline | |
|   void add(const L1& l1, L2& l2, col_major, col_and_row) | |
|   { add(l1, l2, col_major(), col_major()); } | |
| 
 | |
|   ///@endcond | |
|   /** Addition of two vectors/matrices | |
|       @param l1 | |
|       @param l2 | |
|       @param l3 contains l1+l2 on output | |
|   */ | |
|   template <typename L1, typename L2, typename L3> inline | |
|   void add(const L1& l1, const L2& l2, L3& l3) { | |
|     add_spec(l1, l2, l3, typename linalg_traits<L2>::linalg_type()); | |
|   } | |
|   ///@cond DOXY_SHOW_ALL_FUNCTIONS | |
|  | |
|   template <typename L1, typename L2, typename L3> inline | |
|   void add(const L1& l1, const L2& l2, const L3& l3) | |
|   { add(l1, l2, linalg_const_cast(l3)); } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> inline | |
|     void add_spec(const L1& l1, const L2& l2, L3& l3, abstract_matrix) | |
|   { copy(l2, l3); add(l1, l3); } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> inline | |
|     void add_spec(const L1& l1, const L2& l2, L3& l3, abstract_vector) { | |
|     GMM_ASSERT2(vect_size(l1) == vect_size(l2) && | |
| 		vect_size(l1) == vect_size(l3), "dimensions mismatch"); | |
|     if ((const void *)(&l1) == (const void *)(&l3)) | |
|       add(l2, l3); | |
|     else if ((const void *)(&l2) == (const void *)(&l3)) | |
|       add(l1, l3); | |
|     else | |
|       add(l1, l2, l3, typename linalg_traits<L1>::storage_type(), | |
| 	  typename linalg_traits<L2>::storage_type(), | |
| 	  typename linalg_traits<L3>::storage_type()); | |
|   } | |
| 
 | |
|   template <typename IT1, typename IT2, typename IT3> | |
|     void add_full_(IT1 it1, IT2 it2, IT3 it3, IT3 ite) { | |
|     for (; it3 != ite; ++it3, ++it2, ++it1) *it3 = *it1 + *it2; | |
|   } | |
| 
 | |
|   template <typename IT1, typename IT2, typename IT3> | |
|     void add_almost_full_(IT1 it1, IT1 ite1, IT2 it2, IT3 it3, IT3 ite3) { | |
|     IT3 it = it3; | |
|     for (; it != ite3; ++it, ++it2) *it = *it2; | |
|     for (; it1 != ite1; ++it1) | |
|       *(it3 + it1.index()) += *it1; | |
|   } | |
| 
 | |
|   template <typename IT1, typename IT2, typename IT3> | |
|   void add_to_full_(IT1 it1, IT1 ite1, IT2 it2, IT2 ite2, | |
| 		    IT3 it3, IT3 ite3) { | |
|     typedef typename std::iterator_traits<IT3>::value_type T; | |
|     IT3 it = it3; | |
|     for (; it != ite3; ++it) *it = T(0); | |
|     for (; it1 != ite1; ++it1) *(it3 + it1.index()) = *it1; | |
|     for (; it2 != ite2; ++it2) *(it3 + it2.index()) += *it2;     | |
|   } | |
|    | |
|   template <typename L1, typename L2, typename L3> inline | |
|   void add(const L1& l1, const L2& l2, L3& l3, | |
| 	   abstract_dense, abstract_dense, abstract_dense) { | |
|     add_full_(vect_const_begin(l1), vect_const_begin(l2), | |
| 	      vect_begin(l3), vect_end(l3)); | |
|   } | |
|    | |
|   // generic function for add(v1, v2, v3). | |
|   // Need to be specialized to optimize particular additions. | |
|   template <typename L1, typename L2, typename L3, | |
| 	    typename ST1, typename ST2, typename ST3> | |
|   inline void add(const L1& l1, const L2& l2, L3& l3, ST1, ST2, ST3) | |
|   { copy(l2, l3); add(l1, l3, ST1(), ST3()); } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> inline | |
|   void add(const L1& l1, const L2& l2, L3& l3, | |
| 	   abstract_sparse, abstract_dense, abstract_dense) { | |
|     add_almost_full_(vect_const_begin(l1), vect_const_end(l1), | |
| 		     vect_const_begin(l2), vect_begin(l3), vect_end(l3)); | |
|   } | |
|    | |
|   template <typename L1, typename L2, typename L3> inline | |
|   void add(const L1& l1, const L2& l2, L3& l3, | |
| 	   abstract_dense, abstract_sparse, abstract_dense) | |
|   { add(l2, l1, l3, abstract_sparse(), abstract_dense(), abstract_dense()); } | |
|    | |
|   template <typename L1, typename L2, typename L3> inline | |
|   void add(const L1& l1, const L2& l2, L3& l3, | |
| 	   abstract_sparse, abstract_sparse, abstract_dense) { | |
|     add_to_full_(vect_const_begin(l1), vect_const_end(l1), | |
| 		 vect_const_begin(l2), vect_const_end(l2), | |
| 		 vect_begin(l3), vect_end(l3)); | |
|   } | |
| 
 | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void add_spspsp(const L1& l1, const L2& l2, L3& l3, linalg_true) { | |
|     typename linalg_traits<L1>::const_iterator | |
|       it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); | |
|     typename linalg_traits<L2>::const_iterator | |
|       it2 = vect_const_begin(l2), ite2 = vect_const_end(l2); | |
|     clear(l3); | |
|     while (it1 != ite1 && it2 != ite2) { | |
|       ptrdiff_t d = it1.index() - it2.index(); | |
|       if (d < 0) | |
| 	{ l3[it1.index()] += *it1; ++it1; } | |
|       else if (d > 0) | |
| 	{ l3[it2.index()] += *it2; ++it2; } | |
|       else | |
| 	{ l3[it1.index()] = *it1 + *it2; ++it1; ++it2; } | |
|     } | |
|     for (; it1 != ite1; ++it1) l3[it1.index()] += *it1; | |
|     for (; it2 != ite2; ++it2) l3[it2.index()] += *it2;    | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void add_spspsp(const L1& l1, const L2& l2, L3& l3, linalg_false) | |
|   { copy(l2, l3); add(l2, l3); } | |
|    | |
|   template <typename L1, typename L2, typename L3> | |
|   void add(const L1& l1, const L2& l2, L3& l3, | |
| 	   abstract_sparse, abstract_sparse, abstract_sparse) { | |
|     add_spspsp(l1, l2, l3, typename linalg_and<typename | |
| 	       linalg_traits<L1>::index_sorted, | |
| 	       typename linalg_traits<L2>::index_sorted>::bool_type()); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void add(const L1& l1, L2& l2, abstract_dense, abstract_dense) { | |
|     typename linalg_traits<L1>::const_iterator it1 = vect_const_begin(l1);  | |
|     typename linalg_traits<L2>::iterator | |
|              it2 = vect_begin(l2), ite = vect_end(l2); | |
|     for (; it2 != ite; ++it2, ++it1) *it2 += *it1; | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void add(const L1& l1, L2& l2, abstract_dense, abstract_skyline) { | |
|     typedef typename linalg_traits<L1>::const_iterator const_l1_iterator; | |
|     typedef typename linalg_traits<L2>::iterator l2_iterator; | |
|     typedef typename linalg_traits<L1>::value_type T; | |
| 
 | |
|     const_l1_iterator it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);  | |
|     size_type i1 = 0, ie1 = vect_size(l1); | |
|     while (it1 != ite1 && *it1 == T(0)) { ++it1; ++i1; } | |
|     if (it1 != ite1) { | |
|       l2_iterator it2 = vect_begin(l2), ite2 = vect_end(l2); | |
|       while (ie1 && *(ite1-1) == T(0)) { ite1--; --ie1; } | |
| 
 | |
|       if (it2 == ite2 || i1 < it2.index()) { | |
| 	l2[i1] = *it1; ++i1; ++it1; | |
| 	if (it1 == ite1) return; | |
| 	it2 = vect_begin(l2); ite2 = vect_end(l2); | |
|       } | |
|       if (ie1 > ite2.index()) { | |
| 	--ite1; l2[ie1 - 1] = *ite1; | |
| 	it2 = vect_begin(l2); | |
|       } | |
|       it2 += i1 - it2.index(); | |
|       for (; it1 != ite1; ++it1, ++it2) { *it2 += *it1; } | |
|     } | |
|   } | |
| 
 | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void add(const L1& l1, L2& l2, abstract_skyline, abstract_dense) { | |
|     typename linalg_traits<L1>::const_iterator it1 = vect_const_begin(l1), | |
|       ite1 = vect_const_end(l1); | |
|     if (it1 != ite1) { | |
|       typename linalg_traits<L2>::iterator it2 = vect_begin(l2); | |
|       it2 += it1.index(); | |
|       for (; it1 != ite1; ++it2, ++it1) *it2 += *it1; | |
|     } | |
|   } | |
| 
 | |
|    | |
|   template <typename L1, typename L2> | |
|   void add(const L1& l1, L2& l2, abstract_sparse, abstract_dense) { | |
|     typename linalg_traits<L1>::const_iterator | |
|       it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); | |
|     for (; it1 != ite1; ++it1) l2[it1.index()] += *it1; | |
|   } | |
|    | |
|   template <typename L1, typename L2> | |
|   void add(const L1& l1, L2& l2, abstract_sparse, abstract_sparse) { | |
|     typename linalg_traits<L1>::const_iterator | |
|       it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); | |
|     for (; it1 != ite1; ++it1) l2[it1.index()] += *it1; | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void add(const L1& l1, L2& l2, abstract_sparse, abstract_skyline) { | |
|     typename linalg_traits<L1>::const_iterator | |
|       it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); | |
|     for (; it1 != ite1; ++it1) l2[it1.index()] += *it1; | |
|   } | |
| 
 | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void add(const L1& l1, L2& l2, abstract_skyline, abstract_sparse) { | |
|     typename linalg_traits<L1>::const_iterator | |
|       it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); | |
|     for (; it1 != ite1; ++it1) | |
|       if (*it1 != typename linalg_traits<L1>::value_type(0)) | |
| 	l2[it1.index()] += *it1; | |
|   } | |
| 
 | |
|   template <typename L1, typename L2> | |
|   void add(const L1& l1, L2& l2, abstract_skyline, abstract_skyline) { | |
|     typedef typename linalg_traits<L1>::const_iterator const_l1_iterator; | |
|     typedef typename linalg_traits<L2>::iterator l2_iterator; | |
|     typedef typename linalg_traits<L1>::value_type T1; | |
|     typedef typename linalg_traits<L2>::value_type T2; | |
| 
 | |
|     const_l1_iterator it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); | |
|      | |
|     while (it1 != ite1 && *it1 == T1(0)) ++it1; | |
|     if (ite1 != it1) { | |
|       l2_iterator it2 = vect_begin(l2), ite2 = vect_end(l2); | |
|       while (*(ite1-1) == T1(0)) ite1--; | |
|       if (it2 == ite2 || it1.index() < it2.index()) { | |
| 	l2[it1.index()] = T2(0); | |
| 	it2 = vect_begin(l2); ite2 = vect_end(l2); | |
|       } | |
|       if (ite1.index() > ite2.index()) { | |
| 	l2[ite1.index() - 1] = T2(0); | |
| 	it2 = vect_begin(l2);  | |
|       } | |
|       it2 += it1.index() - it2.index(); | |
|       for (; it1 != ite1; ++it1, ++it2) *it2 += *it1; | |
|     } | |
|   } | |
|    | |
|   template <typename L1, typename L2> | |
|   void add(const L1& l1, L2& l2, abstract_dense, abstract_sparse) { | |
|     typename linalg_traits<L1>::const_iterator | |
|       it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); | |
|     for (size_type i = 0; it1 != ite1; ++it1, ++i) | |
|       if (*it1 != typename linalg_traits<L1>::value_type(0)) l2[i] += *it1; | |
|   }  | |
| 
 | |
|   /* ******************************************************************** */ | |
|   /*		Matrix-vector mult                                    	  */ | |
|   /* ******************************************************************** */ | |
|   ///@endcond | |
|   /** matrix-vector or matrix-matrix product. | |
|       @param l1 a matrix. | |
|       @param l2 a vector or matrix. | |
|       @param l3 the product l1*l2. | |
|   */ | |
|   template <typename L1, typename L2, typename L3> inline | |
|   void mult(const L1& l1, const L2& l2, L3& l3) { | |
|     mult_dispatch(l1, l2, l3, typename linalg_traits<L2>::linalg_type()); | |
|   } | |
|   ///@cond DOXY_SHOW_ALL_FUNCTIONS | |
|  | |
|   template <typename L1, typename L2, typename L3> inline | |
|   void mult(const L1& l1, const L2& l2, const L3& l3) | |
|   { mult(l1, l2, linalg_const_cast(l3)); } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> inline | |
|   void mult_dispatch(const L1& l1, const L2& l2, L3& l3, abstract_vector) { | |
|     size_type m = mat_nrows(l1), n = mat_ncols(l1); | |
|     if (!m || !n) { gmm::clear(l3); return; } | |
|     GMM_ASSERT2(n==vect_size(l2) && m==vect_size(l3), "dimensions mismatch"); | |
|     if (!same_origin(l2, l3)) | |
|       mult_spec(l1, l2, l3, typename principal_orientation_type<typename | |
| 		linalg_traits<L1>::sub_orientation>::potype()); | |
|     else { | |
|       GMM_WARNING2("Warning, A temporary is used for mult\n"); | |
|       typename temporary_vector<L3>::vector_type temp(vect_size(l3)); | |
|       mult_spec(l1, l2, temp, typename principal_orientation_type<typename | |
| 		linalg_traits<L1>::sub_orientation>::potype()); | |
|       copy(temp, l3); | |
|     } | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_by_row(const L1& l1, const L2& l2, L3& l3, abstract_sparse) { | |
|     typedef typename  linalg_traits<L3>::value_type T; | |
|     clear(l3); | |
|     size_type nr = mat_nrows(l1); | |
|     for (size_type i = 0; i < nr; ++i) { | |
|       T aux = vect_sp(mat_const_row(l1, i), l2); | |
|       if (aux != T(0)) l3[i] = aux; | |
|     } | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_by_row(const L1& l1, const L2& l2, L3& l3, abstract_skyline) { | |
|     typedef typename  linalg_traits<L3>::value_type T; | |
|     clear(l3);  | |
|     size_type nr = mat_nrows(l1); | |
|     for (size_type i = 0; i < nr; ++i) { | |
|       T aux = vect_sp(mat_const_row(l1, i), l2); | |
|       if (aux != T(0)) l3[i] = aux; | |
|     } | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_by_row(const L1& l1, const L2& l2, L3& l3, abstract_dense) { | |
|     typename linalg_traits<L3>::iterator it=vect_begin(l3), ite=vect_end(l3); | |
|     typename linalg_traits<L1>::const_row_iterator | |
|       itr = mat_row_const_begin(l1);  | |
|     for (; it != ite; ++it, ++itr) | |
|       *it = vect_sp(linalg_traits<L1>::row(itr), l2, | |
| 		    typename linalg_traits<L1>::storage_type(), | |
| 		    typename linalg_traits<L2>::storage_type()); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_by_col(const L1& l1, const L2& l2, L3& l3, abstract_dense) { | |
|     clear(l3); | |
|     size_type nc = mat_ncols(l1); | |
|     for (size_type i = 0; i < nc; ++i) | |
|       add(scaled(mat_const_col(l1, i), l2[i]), l3); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_by_col(const L1& l1, const L2& l2, L3& l3, abstract_sparse) { | |
|     typedef typename linalg_traits<L2>::value_type T; | |
|     clear(l3); | |
|     typename linalg_traits<L2>::const_iterator it = vect_const_begin(l2), | |
|       ite = vect_const_end(l2); | |
|     for (; it != ite; ++it) | |
|       if (*it != T(0)) add(scaled(mat_const_col(l1, it.index()), *it), l3); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_by_col(const L1& l1, const L2& l2, L3& l3, abstract_skyline) { | |
|     typedef typename linalg_traits<L2>::value_type T; | |
|     clear(l3);  | |
|     typename linalg_traits<L2>::const_iterator it = vect_const_begin(l2), | |
|       ite = vect_const_end(l2); | |
|     for (; it != ite; ++it) | |
|       if (*it != T(0)) add(scaled(mat_const_col(l1, it.index()), *it), l3); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> inline | |
|   void mult_spec(const L1& l1, const L2& l2, L3& l3, row_major) | |
|   { mult_by_row(l1, l2, l3, typename linalg_traits<L3>::storage_type()); } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> inline | |
|   void mult_spec(const L1& l1, const L2& l2, L3& l3, col_major) | |
|   { mult_by_col(l1, l2, l3, typename linalg_traits<L2>::storage_type()); } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> inline | |
|   void mult_spec(const L1& l1, const L2& l2, L3& l3, abstract_null_type) | |
|   { mult_ind(l1, l2, l3, typename linalg_traits<L1>::storage_type()); } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_ind(const L1& l1, const L2& l2, L3& l3, abstract_indirect) { | |
|     GMM_ASSERT1(false, "gmm::mult(m, ., .) undefined for this kind of matrix"); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3, typename L4> inline | |
|   void mult(const L1& l1, const L2& l2, const L3& l3, L4& l4) { | |
|     size_type m = mat_nrows(l1), n = mat_ncols(l1); | |
|     copy(l3, l4); | |
|     if (!m || !n) { gmm::copy(l3, l4); return; } | |
|     GMM_ASSERT2(n==vect_size(l2) && m==vect_size(l4), "dimensions mismatch"); | |
|     if (!same_origin(l2, l4)) { | |
|       mult_add_spec(l1, l2, l4, typename principal_orientation_type<typename | |
| 		    linalg_traits<L1>::sub_orientation>::potype()); | |
|     } | |
|     else { | |
|       GMM_WARNING2("Warning, A temporary is used for mult\n"); | |
|       typename temporary_vector<L2>::vector_type temp(vect_size(l2)); | |
|       copy(l2, temp); | |
|       mult_add_spec(l1,temp, l4, typename principal_orientation_type<typename | |
| 		linalg_traits<L1>::sub_orientation>::potype()); | |
|     } | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3, typename L4> inline | |
|   void mult(const L1& l1, const L2& l2, const L3& l3, const L4& l4) | |
|   { mult(l1, l2, l3, linalg_const_cast(l4)); }  | |
| 
 | |
|   ///@endcond | |
|   /** Multiply-accumulate. l3 += l1*l2; */ | |
|   template <typename L1, typename L2, typename L3> inline | |
|   void mult_add(const L1& l1, const L2& l2, L3& l3) { | |
|     size_type m = mat_nrows(l1), n = mat_ncols(l1); | |
|     if (!m || !n) return; | |
|     GMM_ASSERT2(n==vect_size(l2) && m==vect_size(l3), "dimensions mismatch"); | |
|     if (!same_origin(l2, l3)) { | |
|       mult_add_spec(l1, l2, l3, typename principal_orientation_type<typename | |
| 		    linalg_traits<L1>::sub_orientation>::potype()); | |
|     } | |
|     else { | |
|       GMM_WARNING2("Warning, A temporary is used for mult\n"); | |
|       typename temporary_vector<L3>::vector_type temp(vect_size(l2)); | |
|       copy(l2, temp); | |
|       mult_add_spec(l1,temp, l3, typename principal_orientation_type<typename | |
| 		linalg_traits<L1>::sub_orientation>::potype()); | |
|     } | |
|   } | |
|   ///@cond DOXY_SHOW_ALL_FUNCTIONS | |
|  | |
|   template <typename L1, typename L2, typename L3> inline | |
|   void mult_add(const L1& l1, const L2& l2, const L3& l3) | |
|   { mult_add(l1, l2, linalg_const_cast(l3)); }  | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_add_by_row(const L1& l1, const L2& l2, L3& l3, abstract_sparse) { | |
|     typedef typename linalg_traits<L3>::value_type T; | |
|     size_type nr = mat_nrows(l1); | |
|     for (size_type i = 0; i < nr; ++i) { | |
|       T aux = vect_sp(mat_const_row(l1, i), l2); | |
|       if (aux != T(0)) l3[i] += aux; | |
|     } | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_add_by_row(const L1& l1, const L2& l2, L3& l3, abstract_skyline) { | |
|     typedef typename linalg_traits<L3>::value_type T; | |
|     size_type nr = mat_nrows(l1); | |
|     for (size_type i = 0; i < nr; ++i) { | |
|       T aux = vect_sp(mat_const_row(l1, i), l2); | |
|       if (aux != T(0)) l3[i] += aux; | |
|     } | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_add_by_row(const L1& l1, const L2& l2, L3& l3, abstract_dense) { | |
|     typename linalg_traits<L3>::iterator it=vect_begin(l3), ite=vect_end(l3); | |
|     typename linalg_traits<L1>::const_row_iterator | |
|       itr = mat_row_const_begin(l1); | |
|     for (; it != ite; ++it, ++itr) | |
|       *it += vect_sp(linalg_traits<L1>::row(itr), l2); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_add_by_col(const L1& l1, const L2& l2, L3& l3, abstract_dense) { | |
|     size_type nc = mat_ncols(l1); | |
|     for (size_type i = 0; i < nc; ++i) | |
|       add(scaled(mat_const_col(l1, i), l2[i]), l3); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_add_by_col(const L1& l1, const L2& l2, L3& l3, abstract_sparse) { | |
|     typename linalg_traits<L2>::const_iterator it = vect_const_begin(l2), | |
|       ite = vect_const_end(l2); | |
|     for (; it != ite; ++it) | |
|       if (*it != typename linalg_traits<L2>::value_type(0)) | |
| 	add(scaled(mat_const_col(l1, it.index()), *it), l3); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_add_by_col(const L1& l1, const L2& l2, L3& l3, abstract_skyline) { | |
|     typename linalg_traits<L2>::const_iterator it = vect_const_begin(l2), | |
|       ite = vect_const_end(l2); | |
|     for (; it != ite; ++it) | |
|       if (*it != typename linalg_traits<L2>::value_type(0)) | |
| 	add(scaled(mat_const_col(l1, it.index()), *it), l3); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> inline | |
|   void mult_add_spec(const L1& l1, const L2& l2, L3& l3, row_major) | |
|   { mult_add_by_row(l1, l2, l3, typename linalg_traits<L3>::storage_type()); } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> inline | |
|   void mult_add_spec(const L1& l1, const L2& l2, L3& l3, col_major) | |
|   { mult_add_by_col(l1, l2, l3, typename linalg_traits<L2>::storage_type()); } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> inline | |
|   void mult_add_spec(const L1& l1, const L2& l2, L3& l3, abstract_null_type) | |
|   { mult_ind(l1, l2, l3, typename linalg_traits<L1>::storage_type()); } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void transposed_mult(const L1& l1, const L2& l2, const L3& l3) | |
|   { mult(gmm::transposed(l1), l2, l3); } | |
| 
 | |
| 
 | |
|   /* ******************************************************************** */ | |
|   /*		Matrix-matrix mult                                    	  */ | |
|   /* ******************************************************************** */ | |
|    | |
| 
 | |
|   struct g_mult {};  // generic mult, less optimized | |
|   struct c_mult {};  // col x col -> col mult | |
|   struct r_mult {};  // row x row -> row mult | |
|   struct rcmult {};  // row x col -> col mult | |
|   struct crmult {};  // col x row -> row mult | |
|  | |
| 
 | |
|   template<typename SO1, typename SO2, typename SO3> struct mult_t; | |
|   #define DEFMU__ template<> struct mult_t | |
|   DEFMU__<row_major  , row_major  , row_major  > { typedef r_mult t; }; | |
|   DEFMU__<row_major  , row_major  , col_major  > { typedef g_mult t; }; | |
|   DEFMU__<row_major  , row_major  , col_and_row> { typedef r_mult t; }; | |
|   DEFMU__<row_major  , row_major  , row_and_col> { typedef r_mult t; }; | |
|   DEFMU__<row_major  , col_major  , row_major  > { typedef rcmult t; }; | |
|   DEFMU__<row_major  , col_major  , col_major  > { typedef rcmult t; }; | |
|   DEFMU__<row_major  , col_major  , col_and_row> { typedef rcmult t; }; | |
|   DEFMU__<row_major  , col_major  , row_and_col> { typedef rcmult t; }; | |
|   DEFMU__<row_major  , col_and_row, row_major  > { typedef r_mult t; }; | |
|   DEFMU__<row_major  , col_and_row, col_major  > { typedef rcmult t; }; | |
|   DEFMU__<row_major  , col_and_row, col_and_row> { typedef rcmult t; }; | |
|   DEFMU__<row_major  , col_and_row, row_and_col> { typedef rcmult t; }; | |
|   DEFMU__<row_major  , row_and_col, row_major  > { typedef r_mult t; }; | |
|   DEFMU__<row_major  , row_and_col, col_major  > { typedef rcmult t; }; | |
|   DEFMU__<row_major  , row_and_col, col_and_row> { typedef r_mult t; }; | |
|   DEFMU__<row_major  , row_and_col, row_and_col> { typedef r_mult t; }; | |
|   DEFMU__<col_major  , row_major  , row_major  > { typedef crmult t; }; | |
|   DEFMU__<col_major  , row_major  , col_major  > { typedef g_mult t; }; | |
|   DEFMU__<col_major  , row_major  , col_and_row> { typedef crmult t; }; | |
|   DEFMU__<col_major  , row_major  , row_and_col> { typedef crmult t; }; | |
|   DEFMU__<col_major  , col_major  , row_major  > { typedef g_mult t; }; | |
|   DEFMU__<col_major  , col_major  , col_major  > { typedef c_mult t; }; | |
|   DEFMU__<col_major  , col_major  , col_and_row> { typedef c_mult t; }; | |
|   DEFMU__<col_major  , col_major  , row_and_col> { typedef c_mult t; }; | |
|   DEFMU__<col_major  , col_and_row, row_major  > { typedef crmult t; }; | |
|   DEFMU__<col_major  , col_and_row, col_major  > { typedef c_mult t; }; | |
|   DEFMU__<col_major  , col_and_row, col_and_row> { typedef c_mult t; }; | |
|   DEFMU__<col_major  , col_and_row, row_and_col> { typedef c_mult t; }; | |
|   DEFMU__<col_major  , row_and_col, row_major  > { typedef crmult t; }; | |
|   DEFMU__<col_major  , row_and_col, col_major  > { typedef c_mult t; }; | |
|   DEFMU__<col_major  , row_and_col, col_and_row> { typedef c_mult t; }; | |
|   DEFMU__<col_major  , row_and_col, row_and_col> { typedef c_mult t; }; | |
|   DEFMU__<col_and_row, row_major  , row_major  > { typedef r_mult t; }; | |
|   DEFMU__<col_and_row, row_major  , col_major  > { typedef c_mult t; }; | |
|   DEFMU__<col_and_row, row_major  , col_and_row> { typedef r_mult t; }; | |
|   DEFMU__<col_and_row, row_major  , row_and_col> { typedef r_mult t; }; | |
|   DEFMU__<col_and_row, col_major  , row_major  > { typedef rcmult t; }; | |
|   DEFMU__<col_and_row, col_major  , col_major  > { typedef c_mult t; }; | |
|   DEFMU__<col_and_row, col_major  , col_and_row> { typedef c_mult t; }; | |
|   DEFMU__<col_and_row, col_major  , row_and_col> { typedef c_mult t; }; | |
|   DEFMU__<col_and_row, col_and_row, row_major  > { typedef r_mult t; }; | |
|   DEFMU__<col_and_row, col_and_row, col_major  > { typedef c_mult t; }; | |
|   DEFMU__<col_and_row, col_and_row, col_and_row> { typedef c_mult t; }; | |
|   DEFMU__<col_and_row, col_and_row, row_and_col> { typedef c_mult t; }; | |
|   DEFMU__<col_and_row, row_and_col, row_major  > { typedef r_mult t; }; | |
|   DEFMU__<col_and_row, row_and_col, col_major  > { typedef c_mult t; }; | |
|   DEFMU__<col_and_row, row_and_col, col_and_row> { typedef c_mult t; }; | |
|   DEFMU__<col_and_row, row_and_col, row_and_col> { typedef r_mult t; }; | |
|   DEFMU__<row_and_col, row_major  , row_major  > { typedef r_mult t; }; | |
|   DEFMU__<row_and_col, row_major  , col_major  > { typedef c_mult t; }; | |
|   DEFMU__<row_and_col, row_major  , col_and_row> { typedef r_mult t; }; | |
|   DEFMU__<row_and_col, row_major  , row_and_col> { typedef r_mult t; }; | |
|   DEFMU__<row_and_col, col_major  , row_major  > { typedef rcmult t; }; | |
|   DEFMU__<row_and_col, col_major  , col_major  > { typedef c_mult t; }; | |
|   DEFMU__<row_and_col, col_major  , col_and_row> { typedef c_mult t; }; | |
|   DEFMU__<row_and_col, col_major  , row_and_col> { typedef c_mult t; }; | |
|   DEFMU__<row_and_col, col_and_row, row_major  > { typedef rcmult t; }; | |
|   DEFMU__<row_and_col, col_and_row, col_major  > { typedef rcmult t; }; | |
|   DEFMU__<row_and_col, col_and_row, col_and_row> { typedef rcmult t; }; | |
|   DEFMU__<row_and_col, col_and_row, row_and_col> { typedef rcmult t; }; | |
|   DEFMU__<row_and_col, row_and_col, row_major  > { typedef r_mult t; }; | |
|   DEFMU__<row_and_col, row_and_col, col_major  > { typedef c_mult t; }; | |
|   DEFMU__<row_and_col, row_and_col, col_and_row> { typedef r_mult t; }; | |
|   DEFMU__<row_and_col, row_and_col, row_and_col> { typedef r_mult t; }; | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_dispatch(const L1& l1, const L2& l2, L3& l3, abstract_matrix) { | |
|     typedef typename temporary_matrix<L3>::matrix_type temp_mat_type; | |
|     size_type m = mat_nrows(l1), n = mat_ncols(l1), k = mat_ncols(l2); | |
|     if (n == 0) { gmm::clear(l3); return; } | |
|     GMM_ASSERT2(n == mat_nrows(l2) && m == mat_nrows(l3) && k == mat_ncols(l3), | |
| 		"dimensions mismatch"); | |
| 
 | |
|     if (same_origin(l2, l3) || same_origin(l1, l3)) { | |
|       GMM_WARNING2("A temporary is used for mult"); | |
|       temp_mat_type temp(mat_nrows(l3), mat_ncols(l3)); | |
|       mult_spec(l1, l2, temp, typename mult_t< | |
| 		typename linalg_traits<L1>::sub_orientation, | |
| 		typename linalg_traits<L2>::sub_orientation, | |
| 		typename linalg_traits<temp_mat_type>::sub_orientation>::t()); | |
|       copy(temp, l3); | |
|     } | |
|     else | |
|       mult_spec(l1, l2, l3, typename mult_t< | |
| 		typename linalg_traits<L1>::sub_orientation, | |
| 		typename linalg_traits<L2>::sub_orientation, | |
| 		typename linalg_traits<L3>::sub_orientation>::t()); | |
|   } | |
| 
 | |
|   // Completely generic but inefficient | |
|  | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_spec(const L1& l1, const L2& l2, L3& l3, g_mult) { | |
|     typedef typename linalg_traits<L3>::value_type T; | |
|     GMM_WARNING2("Inefficient generic matrix-matrix mult is used"); | |
|     for (size_type i = 0; i < mat_nrows(l3) ; ++i) | |
|       for (size_type j = 0; j < mat_ncols(l3) ; ++j) { | |
| 	T a(0); | |
| 	for (size_type k = 0; k < mat_nrows(l2) ; ++k) a += l1(i, k)*l2(k, j); | |
| 	l3(i, j) = a; | |
|       } | |
|   } | |
| 
 | |
|   // row x col matrix-matrix mult | |
|  | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_row_col_with_temp(const L1& l1, const L2& l2, L3& l3, col_major) { | |
|     typedef typename temporary_col_matrix<L1>::matrix_type temp_col_mat; | |
|     temp_col_mat temp(mat_nrows(l1), mat_ncols(l1)); | |
|     copy(l1, temp); | |
|     mult(temp, l2, l3); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_row_col_with_temp(const L1& l1, const L2& l2, L3& l3, row_major) { | |
|     typedef typename temporary_row_matrix<L2>::matrix_type temp_row_mat; | |
|     temp_row_mat temp(mat_nrows(l2), mat_ncols(l2)); | |
|     copy(l2, temp); | |
|     mult(l1, temp, l3); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_spec(const L1& l1, const L2& l2, L3& l3, rcmult) { | |
|     if (is_sparse(l1) && is_sparse(l2)) { | |
|       GMM_WARNING3("Inefficient row matrix - col matrix mult for " | |
| 		  "sparse matrices, using temporary"); | |
|       mult_row_col_with_temp(l1, l2, l3,  | |
| 			     typename principal_orientation_type<typename | |
| 			     linalg_traits<L3>::sub_orientation>::potype()); | |
|     } | |
|     else { | |
|       typename linalg_traits<L2>::const_col_iterator | |
| 	it2b = linalg_traits<L2>::col_begin(l2), it2, | |
| 	ite = linalg_traits<L2>::col_end(l2); | |
|       size_type i,j, k = mat_nrows(l1); | |
|        | |
|       for (i = 0; i < k; ++i) { | |
| 	typename linalg_traits<L1>::const_sub_row_type r1=mat_const_row(l1, i); | |
| 	for (it2 = it2b, j = 0; it2 != ite; ++it2, ++j) | |
| 	  l3(i,j) = vect_sp(r1, linalg_traits<L2>::col(it2)); | |
|       } | |
|     } | |
|   } | |
| 
 | |
|   // row - row matrix-matrix mult | |
|  | |
|   template <typename L1, typename L2, typename L3> inline | |
|   void mult_spec(const L1& l1, const L2& l2, L3& l3, r_mult) { | |
|     mult_spec(l1, l2, l3,r_mult(),typename linalg_traits<L1>::storage_type()); | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_spec(const L1& l1, const L2& l2, L3& l3, r_mult, abstract_dense) { | |
|     // optimizable | |
|     clear(l3); | |
|     size_type nn = mat_nrows(l3), mm = mat_nrows(l2); | |
|     for (size_type i = 0; i < nn; ++i) { | |
|       for (size_type j = 0; j < mm; ++j) { | |
| 	add(scaled(mat_const_row(l2, j), l1(i, j)), mat_row(l3, i)); | |
|       } | |
|     } | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_spec(const L1& l1, const L2& l2, L3& l3, r_mult, abstract_sparse) { | |
|     // optimizable | |
|     clear(l3); | |
|     size_type nn = mat_nrows(l3); | |
|     for (size_type i = 0; i < nn; ++i) { | |
|       typename linalg_traits<L1>::const_sub_row_type rl1=mat_const_row(l1, i); | |
|       typename linalg_traits<typename linalg_traits<L1>::const_sub_row_type>:: | |
| 	const_iterator it = vect_const_begin(rl1), ite = vect_const_end(rl1); | |
|       for (; it != ite; ++it) | |
| 	add(scaled(mat_const_row(l2, it.index()), *it), mat_row(l3, i)); | |
|     } | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_spec(const L1& l1, const L2& l2, L3& l3, r_mult, abstract_skyline) | |
|   { mult_spec(l1, l2, l3, r_mult(), abstract_sparse()); } | |
| 
 | |
|   // col - col matrix-matrix mult | |
|  | |
|   template <typename L1, typename L2, typename L3> inline | |
|   void mult_spec(const L1& l1, const L2& l2, L3& l3, c_mult) { | |
|     mult_spec(l1, l2,l3,c_mult(),typename linalg_traits<L2>::storage_type(), | |
| 	      typename linalg_traits<L2>::sub_orientation()); | |
|   } | |
| 
 | |
| 
 | |
|   template <typename L1, typename L2, typename L3, typename ORIEN> | |
|   void mult_spec(const L1& l1, const L2& l2, L3& l3, c_mult, | |
| 		 abstract_dense, ORIEN) { | |
|     typedef typename linalg_traits<L2>::value_type T; | |
|     size_type nn = mat_ncols(l3), mm = mat_ncols(l1); | |
| 
 | |
|     for (size_type i = 0; i < nn; ++i) { | |
|       clear(mat_col(l3, i)); | |
|       for (size_type j = 0; j < mm; ++j) { | |
| 	T b = l2(j, i); | |
| 	if (b != T(0)) add(scaled(mat_const_col(l1, j), b), mat_col(l3, i)); | |
|       } | |
|     } | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3, typename ORIEN> | |
|   void mult_spec(const L1& l1, const L2& l2, L3& l3, c_mult, | |
| 		 abstract_sparse, ORIEN) { | |
|     // optimizable | |
|     clear(l3); | |
|     size_type nn = mat_ncols(l3); | |
|     for (size_type i = 0; i < nn; ++i) { | |
|       typename linalg_traits<L2>::const_sub_col_type rc2=mat_const_col(l2, i); | |
|       typename linalg_traits<typename linalg_traits<L2>::const_sub_col_type>:: | |
| 	const_iterator it = vect_const_begin(rc2), ite = vect_const_end(rc2); | |
|       for (; it != ite; ++it) | |
| 	add(scaled(mat_const_col(l1, it.index()), *it), mat_col(l3, i)); | |
|     } | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_spec(const L1& l1, const L2& l2, L3& l3, c_mult, | |
| 		 abstract_sparse, row_major) { | |
|      typedef typename linalg_traits<L2>::value_type T; | |
|      GMM_WARNING3("Inefficient matrix-matrix mult for sparse matrices"); | |
|      clear(l3); | |
|      size_type mm = mat_nrows(l2), nn = mat_ncols(l3); | |
|      for (size_type i = 0; i < nn; ++i) | |
|        for (size_type j = 0; j < mm; ++j) { | |
| 	 T a = l2(i,j); | |
| 	 if (a != T(0)) add(scaled(mat_const_col(l1, j), a), mat_col(l3, i)); | |
|        } | |
|    } | |
| 
 | |
|   template <typename L1, typename L2, typename L3, typename ORIEN> inline | |
|   void mult_spec(const L1& l1, const L2& l2, L3& l3, c_mult, | |
| 		 abstract_skyline, ORIEN) | |
|   { mult_spec(l1, l2, l3, c_mult(), abstract_sparse(), ORIEN()); } | |
| 
 | |
|    | |
|   // col - row matrix-matrix mult | |
|  | |
|   template <typename L1, typename L2, typename L3> inline | |
|   void mult_spec(const L1& l1, const L2& l2, L3& l3, crmult) | |
|   { mult_spec(l1,l2,l3,crmult(), typename linalg_traits<L1>::storage_type()); } | |
| 
 | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_spec(const L1& l1, const L2& l2, L3& l3, crmult, abstract_dense) { | |
|     // optimizable | |
|     clear(l3); | |
|     size_type nn = mat_ncols(l1), mm = mat_nrows(l1); | |
|     for (size_type i = 0; i < nn; ++i) { | |
|       for (size_type j = 0; j < mm; ++j) | |
|       add(scaled(mat_const_row(l2, i), l1(j, i)), mat_row(l3, j)); | |
|     } | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> | |
|   void mult_spec(const L1& l1, const L2& l2, L3& l3, crmult, abstract_sparse) { | |
|     // optimizable | |
|     clear(l3); | |
|     size_type nn = mat_ncols(l1); | |
|     for (size_type i = 0; i < nn; ++i) { | |
|       typename linalg_traits<L1>::const_sub_col_type rc1=mat_const_col(l1, i); | |
|       typename linalg_traits<typename linalg_traits<L1>::const_sub_col_type>:: | |
| 	const_iterator it = vect_const_begin(rc1), ite = vect_const_end(rc1); | |
|       for (; it != ite; ++it) | |
| 	add(scaled(mat_const_row(l2, i), *it), mat_row(l3, it.index())); | |
|     } | |
|   } | |
| 
 | |
|   template <typename L1, typename L2, typename L3> inline | |
|   void mult_spec(const L1& l1, const L2& l2, L3& l3, crmult, abstract_skyline) | |
|   { mult_spec(l1, l2, l3, crmult(), abstract_sparse()); } | |
|    | |
| 
 | |
|   /* ******************************************************************** */ | |
|   /*		Symmetry test.                                     	  */ | |
|   /* ******************************************************************** */ | |
| 
 | |
|   ///@endcond | |
|   /** test if A is symmetric. | |
|       @param A a matrix. | |
|       @param tol a threshold. | |
|   */ | |
|   template <typename MAT> inline | |
|   bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol | |
| 		    = magnitude_of_linalg(MAT)(-1)) { | |
|     typedef magnitude_of_linalg(MAT) R; | |
|     if (tol < R(0)) tol = default_tol(R()) * mat_maxnorm(A); | |
|     if (mat_nrows(A) != mat_ncols(A)) return false; | |
|     return is_symmetric(A, tol, typename linalg_traits<MAT>::storage_type()); | |
|   } | |
|   ///@cond DOXY_SHOW_ALL_FUNCTIONS | |
|  | |
|   template <typename MAT>  | |
|   bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol,  | |
| 		    abstract_dense) { | |
|     size_type m = mat_nrows(A); | |
|     for (size_type i = 1; i < m; ++i) | |
|       for (size_type j = 0; j < i; ++j) | |
| 	if (gmm::abs(A(i, j)-A(j, i)) > tol) return false; | |
|     return true; | |
|   } | |
| 
 | |
|   template <typename MAT>  | |
|   bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol,  | |
| 		    abstract_sparse) { | |
|     return is_symmetric(A, tol, typename principal_orientation_type<typename | |
| 			linalg_traits<MAT>::sub_orientation>::potype()); | |
|   } | |
| 
 | |
|   template <typename MAT>  | |
|   bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol,  | |
| 		    row_major) { | |
|     for (size_type i = 0; i < mat_nrows(A); ++i) { | |
|       typedef typename linalg_traits<MAT>::const_sub_row_type row_type; | |
|       row_type row = mat_const_row(A, i); | |
|       typename linalg_traits<row_type>::const_iterator | |
| 	it = vect_const_begin(row), ite = vect_const_end(row); | |
|       for (; it != ite; ++it) | |
| 	if (gmm::abs(*it - A(it.index(), i)) > tol) return false; | |
|     } | |
|     return true; | |
|   } | |
| 
 | |
|   template <typename MAT>  | |
|   bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol,  | |
| 		    col_major) { | |
|     for (size_type i = 0; i < mat_ncols(A); ++i) { | |
|       typedef typename linalg_traits<MAT>::const_sub_col_type col_type; | |
|       col_type col = mat_const_col(A, i); | |
|       typename linalg_traits<col_type>::const_iterator | |
| 	it = vect_const_begin(col), ite = vect_const_end(col); | |
|       for (; it != ite; ++it) | |
| 	if (gmm::abs(*it - A(i, it.index())) > tol) return false; | |
|     } | |
|     return true; | |
|   } | |
| 
 | |
|   template <typename MAT>  | |
|   bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol,  | |
| 		    abstract_skyline) | |
|   { return is_symmetric(A, tol, abstract_sparse()); } | |
| 
 | |
|   ///@endcond | |
|   /** test if A is Hermitian. | |
|       @param A a matrix. | |
|       @param tol a threshold. | |
|   */ | |
|   template <typename MAT> inline | |
|   bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol | |
| 		    = magnitude_of_linalg(MAT)(-1)) { | |
|     typedef magnitude_of_linalg(MAT) R; | |
|     if (tol < R(0)) tol = default_tol(R()) * mat_maxnorm(A); | |
|     if (mat_nrows(A) != mat_ncols(A)) return false; | |
|     return is_hermitian(A, tol, typename linalg_traits<MAT>::storage_type()); | |
|   } | |
|   ///@cond DOXY_SHOW_ALL_FUNCTIONS | |
|  | |
|   template <typename MAT>  | |
|   bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol, | |
| 		    abstract_dense) { | |
|     size_type m = mat_nrows(A); | |
|     for (size_type i = 1; i < m; ++i) | |
|       for (size_type j = 0; j < i; ++j) | |
| 	if (gmm::abs(A(i, j)-gmm::conj(A(j, i))) > tol) return false; | |
|     return true; | |
|   } | |
| 
 | |
|   template <typename MAT>  | |
|   bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol,  | |
| 		    abstract_sparse) { | |
|     return is_hermitian(A, tol, typename principal_orientation_type<typename | |
| 			linalg_traits<MAT>::sub_orientation>::potype()); | |
|   } | |
| 
 | |
|   template <typename MAT>  | |
|   bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol,  | |
| 		    row_major) { | |
|     for (size_type i = 0; i < mat_nrows(A); ++i) { | |
|       typedef typename linalg_traits<MAT>::const_sub_row_type row_type; | |
|       row_type row = mat_const_row(A, i); | |
|       typename linalg_traits<row_type>::const_iterator | |
| 	it = vect_const_begin(row), ite = vect_const_end(row); | |
|       for (; it != ite; ++it) | |
| 	if (gmm::abs(gmm::conj(*it) - A(it.index(), i)) > tol) return false; | |
|     } | |
|     return true; | |
|   } | |
| 
 | |
|   template <typename MAT>  | |
|   bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol,  | |
| 		    col_major) { | |
|     for (size_type i = 0; i < mat_ncols(A); ++i) { | |
|       typedef typename linalg_traits<MAT>::const_sub_col_type col_type; | |
|       col_type col = mat_const_col(A, i); | |
|       typename linalg_traits<col_type>::const_iterator | |
| 	it = vect_const_begin(col), ite = vect_const_end(col); | |
|       for (; it != ite; ++it) | |
| 	if (gmm::abs(gmm::conj(*it) - A(i, it.index())) > tol) return false; | |
|     } | |
|     return true; | |
|   } | |
| 
 | |
|   template <typename MAT>  | |
|   bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol,  | |
| 		    abstract_skyline) | |
|   { return is_hermitian(A, tol, abstract_sparse()); } | |
|   ///@endcond | |
| } | |
| 
 | |
| 
 | |
| #endif //  GMM_BLAS_H__
 |