Chris@16: // Chris@16: // Copyright (c) 2000-2009 Chris@16: // Joerg Walter, Mathias Koch, Gunter Winkler Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // The authors gratefully acknowledge the support of Chris@16: // GeNeSys mbH & Co. KG in producing this work. Chris@16: // Chris@16: Chris@16: #ifndef _BOOST_UBLAS_FUNCTIONAL_ Chris@16: #define _BOOST_UBLAS_FUNCTIONAL_ Chris@16: Chris@16: #include Chris@16: Chris@101: #include Chris@101: Chris@16: #include Chris@16: #ifdef BOOST_UBLAS_USE_DUFF_DEVICE Chris@16: #include Chris@16: #endif Chris@16: #ifdef BOOST_UBLAS_USE_SIMD Chris@16: #include Chris@16: #else Chris@16: namespace boost { namespace numeric { namespace ublas { namespace raw { Chris@16: }}}} Chris@16: #endif Chris@16: #ifdef BOOST_UBLAS_HAVE_BINDINGS Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #endif Chris@16: Chris@16: #include Chris@16: Chris@16: Chris@16: Chris@16: namespace boost { namespace numeric { namespace ublas { Chris@16: Chris@16: // Scalar functors Chris@16: Chris@16: // Unary Chris@16: template Chris@16: struct scalar_unary_functor { Chris@16: typedef T value_type; Chris@16: typedef typename type_traits::const_reference argument_type; Chris@16: typedef typename type_traits::value_type result_type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct scalar_identity: Chris@16: public scalar_unary_functor { Chris@16: typedef typename scalar_unary_functor::argument_type argument_type; Chris@16: typedef typename scalar_unary_functor::result_type result_type; Chris@16: Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (argument_type t) { Chris@16: return t; Chris@16: } Chris@16: }; Chris@16: template Chris@16: struct scalar_negate: Chris@16: public scalar_unary_functor { Chris@16: typedef typename scalar_unary_functor::argument_type argument_type; Chris@16: typedef typename scalar_unary_functor::result_type result_type; Chris@16: Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (argument_type t) { Chris@16: return - t; Chris@16: } Chris@16: }; Chris@16: template Chris@16: struct scalar_conj: Chris@16: public scalar_unary_functor { Chris@16: typedef typename scalar_unary_functor::value_type value_type; Chris@16: typedef typename scalar_unary_functor::argument_type argument_type; Chris@16: typedef typename scalar_unary_functor::result_type result_type; Chris@16: Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (argument_type t) { Chris@16: return type_traits::conj (t); Chris@16: } Chris@16: }; Chris@16: Chris@16: // Unary returning real Chris@16: template Chris@16: struct scalar_real_unary_functor { Chris@16: typedef T value_type; Chris@16: typedef typename type_traits::const_reference argument_type; Chris@16: typedef typename type_traits::real_type result_type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct scalar_real: Chris@16: public scalar_real_unary_functor { Chris@16: typedef typename scalar_real_unary_functor::value_type value_type; Chris@16: typedef typename scalar_real_unary_functor::argument_type argument_type; Chris@16: typedef typename scalar_real_unary_functor::result_type result_type; Chris@16: Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (argument_type t) { Chris@16: return type_traits::real (t); Chris@16: } Chris@16: }; Chris@16: template Chris@16: struct scalar_imag: Chris@16: public scalar_real_unary_functor { Chris@16: typedef typename scalar_real_unary_functor::value_type value_type; Chris@16: typedef typename scalar_real_unary_functor::argument_type argument_type; Chris@16: typedef typename scalar_real_unary_functor::result_type result_type; Chris@16: Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (argument_type t) { Chris@16: return type_traits::imag (t); Chris@16: } Chris@16: }; Chris@16: Chris@16: // Binary Chris@16: template Chris@16: struct scalar_binary_functor { Chris@16: typedef typename type_traits::const_reference argument1_type; Chris@16: typedef typename type_traits::const_reference argument2_type; Chris@16: typedef typename promote_traits::promote_type result_type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct scalar_plus: Chris@16: public scalar_binary_functor { Chris@16: typedef typename scalar_binary_functor::argument1_type argument1_type; Chris@16: typedef typename scalar_binary_functor::argument2_type argument2_type; Chris@16: typedef typename scalar_binary_functor::result_type result_type; Chris@16: Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (argument1_type t1, argument2_type t2) { Chris@16: return t1 + t2; Chris@16: } Chris@16: }; Chris@16: template Chris@16: struct scalar_minus: Chris@16: public scalar_binary_functor { Chris@16: typedef typename scalar_binary_functor::argument1_type argument1_type; Chris@16: typedef typename scalar_binary_functor::argument2_type argument2_type; Chris@16: typedef typename scalar_binary_functor::result_type result_type; Chris@16: Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (argument1_type t1, argument2_type t2) { Chris@16: return t1 - t2; Chris@16: } Chris@16: }; Chris@16: template Chris@16: struct scalar_multiplies: Chris@16: public scalar_binary_functor { Chris@16: typedef typename scalar_binary_functor::argument1_type argument1_type; Chris@16: typedef typename scalar_binary_functor::argument2_type argument2_type; Chris@16: typedef typename scalar_binary_functor::result_type result_type; Chris@16: Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (argument1_type t1, argument2_type t2) { Chris@16: return t1 * t2; Chris@16: } Chris@16: }; Chris@16: template Chris@16: struct scalar_divides: Chris@16: public scalar_binary_functor { Chris@16: typedef typename scalar_binary_functor::argument1_type argument1_type; Chris@16: typedef typename scalar_binary_functor::argument2_type argument2_type; Chris@16: typedef typename scalar_binary_functor::result_type result_type; Chris@16: Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (argument1_type t1, argument2_type t2) { Chris@16: return t1 / t2; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct scalar_binary_assign_functor { Chris@16: // ISSUE Remove reference to avoid reference to reference problems Chris@16: typedef typename type_traits::type>::reference argument1_type; Chris@16: typedef typename type_traits::const_reference argument2_type; Chris@16: }; Chris@16: Chris@16: struct assign_tag {}; Chris@16: struct computed_assign_tag {}; Chris@16: Chris@16: template Chris@16: struct scalar_assign: Chris@16: public scalar_binary_assign_functor { Chris@16: typedef typename scalar_binary_assign_functor::argument1_type argument1_type; Chris@16: typedef typename scalar_binary_assign_functor::argument2_type argument2_type; Chris@16: #if BOOST_WORKAROUND( __IBMCPP__, <=600 ) Chris@16: static const bool computed ; Chris@16: #else Chris@16: static const bool computed = false ; Chris@16: #endif Chris@16: Chris@16: static BOOST_UBLAS_INLINE Chris@16: void apply (argument1_type t1, argument2_type t2) { Chris@16: t1 = t2; Chris@16: } Chris@16: Chris@16: template Chris@16: struct rebind { Chris@16: typedef scalar_assign other; Chris@16: }; Chris@16: }; Chris@16: Chris@16: #if BOOST_WORKAROUND( __IBMCPP__, <=600 ) Chris@16: template Chris@16: const bool scalar_assign::computed = false; Chris@16: #endif Chris@16: Chris@16: template Chris@16: struct scalar_plus_assign: Chris@16: public scalar_binary_assign_functor { Chris@16: typedef typename scalar_binary_assign_functor::argument1_type argument1_type; Chris@16: typedef typename scalar_binary_assign_functor::argument2_type argument2_type; Chris@16: #if BOOST_WORKAROUND( __IBMCPP__, <=600 ) Chris@16: static const bool computed ; Chris@16: #else Chris@16: static const bool computed = true ; Chris@16: #endif Chris@16: Chris@16: static BOOST_UBLAS_INLINE Chris@16: void apply (argument1_type t1, argument2_type t2) { Chris@16: t1 += t2; Chris@16: } Chris@16: Chris@16: template Chris@16: struct rebind { Chris@16: typedef scalar_plus_assign other; Chris@16: }; Chris@16: }; Chris@16: Chris@16: #if BOOST_WORKAROUND( __IBMCPP__, <=600 ) Chris@16: template Chris@16: const bool scalar_plus_assign::computed = true; Chris@16: #endif Chris@16: Chris@16: template Chris@16: struct scalar_minus_assign: Chris@16: public scalar_binary_assign_functor { Chris@16: typedef typename scalar_binary_assign_functor::argument1_type argument1_type; Chris@16: typedef typename scalar_binary_assign_functor::argument2_type argument2_type; Chris@16: #if BOOST_WORKAROUND( __IBMCPP__, <=600 ) Chris@16: static const bool computed ; Chris@16: #else Chris@16: static const bool computed = true ; Chris@16: #endif Chris@16: Chris@16: static BOOST_UBLAS_INLINE Chris@16: void apply (argument1_type t1, argument2_type t2) { Chris@16: t1 -= t2; Chris@16: } Chris@16: Chris@16: template Chris@16: struct rebind { Chris@16: typedef scalar_minus_assign other; Chris@16: }; Chris@16: }; Chris@16: Chris@16: #if BOOST_WORKAROUND( __IBMCPP__, <=600 ) Chris@16: template Chris@16: const bool scalar_minus_assign::computed = true; Chris@16: #endif Chris@16: Chris@16: template Chris@16: struct scalar_multiplies_assign: Chris@16: public scalar_binary_assign_functor { Chris@16: typedef typename scalar_binary_assign_functor::argument1_type argument1_type; Chris@16: typedef typename scalar_binary_assign_functor::argument2_type argument2_type; Chris@16: static const bool computed = true; Chris@16: Chris@16: static BOOST_UBLAS_INLINE Chris@16: void apply (argument1_type t1, argument2_type t2) { Chris@16: t1 *= t2; Chris@16: } Chris@16: Chris@16: template Chris@16: struct rebind { Chris@16: typedef scalar_multiplies_assign other; Chris@16: }; Chris@16: }; Chris@16: template Chris@16: struct scalar_divides_assign: Chris@16: public scalar_binary_assign_functor { Chris@16: typedef typename scalar_binary_assign_functor::argument1_type argument1_type; Chris@16: typedef typename scalar_binary_assign_functor::argument2_type argument2_type; Chris@16: static const bool computed ; Chris@16: Chris@16: static BOOST_UBLAS_INLINE Chris@16: void apply (argument1_type t1, argument2_type t2) { Chris@16: t1 /= t2; Chris@16: } Chris@16: Chris@16: template Chris@16: struct rebind { Chris@16: typedef scalar_divides_assign other; Chris@16: }; Chris@16: }; Chris@16: template Chris@16: const bool scalar_divides_assign::computed = true; Chris@16: Chris@16: template Chris@16: struct scalar_binary_swap_functor { Chris@16: typedef typename type_traits::type>::reference argument1_type; Chris@16: typedef typename type_traits::type>::reference argument2_type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct scalar_swap: Chris@16: public scalar_binary_swap_functor { Chris@16: typedef typename scalar_binary_swap_functor::argument1_type argument1_type; Chris@16: typedef typename scalar_binary_swap_functor::argument2_type argument2_type; Chris@16: Chris@16: static BOOST_UBLAS_INLINE Chris@16: void apply (argument1_type t1, argument2_type t2) { Chris@16: std::swap (t1, t2); Chris@16: } Chris@16: Chris@16: template Chris@16: struct rebind { Chris@16: typedef scalar_swap other; Chris@16: }; Chris@16: }; Chris@16: Chris@16: // Vector functors Chris@16: Chris@16: // Unary returning scalar Chris@16: template Chris@16: struct vector_scalar_unary_functor { Chris@16: typedef typename V::value_type value_type; Chris@16: typedef typename V::value_type result_type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct vector_sum: Chris@16: public vector_scalar_unary_functor { Chris@16: typedef typename vector_scalar_unary_functor::value_type value_type; Chris@16: typedef typename vector_scalar_unary_functor::result_type result_type; Chris@16: Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (const vector_expression &e) { Chris@16: result_type t = result_type (0); Chris@16: typedef typename E::size_type vector_size_type; Chris@16: vector_size_type size (e ().size ()); Chris@16: for (vector_size_type i = 0; i < size; ++ i) Chris@16: t += e () (i); Chris@16: return t; Chris@16: } Chris@16: // Dense case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (D size, I it) { Chris@16: result_type t = result_type (0); Chris@16: while (-- size >= 0) Chris@16: t += *it, ++ it; Chris@16: return t; Chris@16: } Chris@16: // Sparse case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (I it, const I &it_end) { Chris@16: result_type t = result_type (0); Chris@16: while (it != it_end) Chris@16: t += *it, ++ it; Chris@16: return t; Chris@16: } Chris@16: }; Chris@16: Chris@16: // Unary returning real scalar Chris@16: template Chris@16: struct vector_scalar_real_unary_functor { Chris@16: typedef typename V::value_type value_type; Chris@16: typedef typename type_traits::real_type real_type; Chris@16: typedef real_type result_type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct vector_norm_1: Chris@16: public vector_scalar_real_unary_functor { Chris@16: typedef typename vector_scalar_real_unary_functor::value_type value_type; Chris@16: typedef typename vector_scalar_real_unary_functor::real_type real_type; Chris@16: typedef typename vector_scalar_real_unary_functor::result_type result_type; Chris@16: Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (const vector_expression &e) { Chris@16: real_type t = real_type (); Chris@16: typedef typename E::size_type vector_size_type; Chris@16: vector_size_type size (e ().size ()); Chris@16: for (vector_size_type i = 0; i < size; ++ i) { Chris@16: real_type u (type_traits::type_abs (e () (i))); Chris@16: t += u; Chris@16: } Chris@16: return t; Chris@16: } Chris@16: // Dense case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (D size, I it) { Chris@16: real_type t = real_type (); Chris@16: while (-- size >= 0) { Chris@16: real_type u (type_traits::norm_1 (*it)); Chris@16: t += u; Chris@16: ++ it; Chris@16: } Chris@16: return t; Chris@16: } Chris@16: // Sparse case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (I it, const I &it_end) { Chris@16: real_type t = real_type (); Chris@16: while (it != it_end) { Chris@16: real_type u (type_traits::norm_1 (*it)); Chris@16: t += u; Chris@16: ++ it; Chris@16: } Chris@16: return t; Chris@16: } Chris@16: }; Chris@16: template Chris@16: struct vector_norm_2: Chris@16: public vector_scalar_real_unary_functor { Chris@16: typedef typename vector_scalar_real_unary_functor::value_type value_type; Chris@16: typedef typename vector_scalar_real_unary_functor::real_type real_type; Chris@16: typedef typename vector_scalar_real_unary_functor::result_type result_type; Chris@16: Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (const vector_expression &e) { Chris@16: #ifndef BOOST_UBLAS_SCALED_NORM Chris@16: real_type t = real_type (); Chris@16: typedef typename E::size_type vector_size_type; Chris@16: vector_size_type size (e ().size ()); Chris@16: for (vector_size_type i = 0; i < size; ++ i) { Chris@16: real_type u (type_traits::norm_2 (e () (i))); Chris@16: t += u * u; Chris@16: } Chris@16: return type_traits::type_sqrt (t); Chris@16: #else Chris@16: real_type scale = real_type (); Chris@16: real_type sum_squares (1); Chris@16: size_type size (e ().size ()); Chris@16: for (size_type i = 0; i < size; ++ i) { Chris@16: real_type u (type_traits::norm_2 (e () (i))); Chris@16: if ( real_type () /* zero */ == u ) continue; Chris@16: if (scale < u) { Chris@16: real_type v (scale / u); Chris@16: sum_squares = sum_squares * v * v + real_type (1); Chris@16: scale = u; Chris@16: } else { Chris@16: real_type v (u / scale); Chris@16: sum_squares += v * v; Chris@16: } Chris@16: } Chris@16: return scale * type_traits::type_sqrt (sum_squares); Chris@16: #endif Chris@16: } Chris@16: // Dense case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (D size, I it) { Chris@16: #ifndef BOOST_UBLAS_SCALED_NORM Chris@16: real_type t = real_type (); Chris@16: while (-- size >= 0) { Chris@16: real_type u (type_traits::norm_2 (*it)); Chris@16: t += u * u; Chris@16: ++ it; Chris@16: } Chris@16: return type_traits::type_sqrt (t); Chris@16: #else Chris@16: real_type scale = real_type (); Chris@16: real_type sum_squares (1); Chris@16: while (-- size >= 0) { Chris@16: real_type u (type_traits::norm_2 (*it)); Chris@16: if (scale < u) { Chris@16: real_type v (scale / u); Chris@16: sum_squares = sum_squares * v * v + real_type (1); Chris@16: scale = u; Chris@16: } else { Chris@16: real_type v (u / scale); Chris@16: sum_squares += v * v; Chris@16: } Chris@16: ++ it; Chris@16: } Chris@16: return scale * type_traits::type_sqrt (sum_squares); Chris@16: #endif Chris@16: } Chris@16: // Sparse case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (I it, const I &it_end) { Chris@16: #ifndef BOOST_UBLAS_SCALED_NORM Chris@16: real_type t = real_type (); Chris@16: while (it != it_end) { Chris@16: real_type u (type_traits::norm_2 (*it)); Chris@16: t += u * u; Chris@16: ++ it; Chris@16: } Chris@16: return type_traits::type_sqrt (t); Chris@16: #else Chris@16: real_type scale = real_type (); Chris@16: real_type sum_squares (1); Chris@16: while (it != it_end) { Chris@16: real_type u (type_traits::norm_2 (*it)); Chris@16: if (scale < u) { Chris@16: real_type v (scale / u); Chris@16: sum_squares = sum_squares * v * v + real_type (1); Chris@16: scale = u; Chris@16: } else { Chris@16: real_type v (u / scale); Chris@16: sum_squares += v * v; Chris@16: } Chris@16: ++ it; Chris@16: } Chris@16: return scale * type_traits::type_sqrt (sum_squares); Chris@16: #endif Chris@16: } Chris@16: }; Chris@16: template Chris@16: struct vector_norm_inf: Chris@16: public vector_scalar_real_unary_functor { Chris@16: typedef typename vector_scalar_real_unary_functor::value_type value_type; Chris@16: typedef typename vector_scalar_real_unary_functor::real_type real_type; Chris@16: typedef typename vector_scalar_real_unary_functor::result_type result_type; Chris@16: Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (const vector_expression &e) { Chris@16: real_type t = real_type (); Chris@16: typedef typename E::size_type vector_size_type; Chris@16: vector_size_type size (e ().size ()); Chris@16: for (vector_size_type i = 0; i < size; ++ i) { Chris@16: real_type u (type_traits::norm_inf (e () (i))); Chris@16: if (u > t) Chris@16: t = u; Chris@16: } Chris@16: return t; Chris@16: } Chris@16: // Dense case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (D size, I it) { Chris@16: real_type t = real_type (); Chris@16: while (-- size >= 0) { Chris@16: real_type u (type_traits::norm_inf (*it)); Chris@16: if (u > t) Chris@16: t = u; Chris@16: ++ it; Chris@16: } Chris@16: return t; Chris@16: } Chris@16: // Sparse case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (I it, const I &it_end) { Chris@16: real_type t = real_type (); Chris@16: while (it != it_end) { Chris@16: real_type u (type_traits::norm_inf (*it)); Chris@16: if (u > t) Chris@16: t = u; Chris@16: ++ it; Chris@16: } Chris@16: return t; Chris@16: } Chris@16: }; Chris@16: Chris@16: // Unary returning index Chris@16: template Chris@16: struct vector_scalar_index_unary_functor { Chris@16: typedef typename V::value_type value_type; Chris@16: typedef typename type_traits::real_type real_type; Chris@16: typedef typename V::size_type result_type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct vector_index_norm_inf: Chris@16: public vector_scalar_index_unary_functor { Chris@16: typedef typename vector_scalar_index_unary_functor::value_type value_type; Chris@16: typedef typename vector_scalar_index_unary_functor::real_type real_type; Chris@16: typedef typename vector_scalar_index_unary_functor::result_type result_type; Chris@16: Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (const vector_expression &e) { Chris@16: // ISSUE For CBLAS compatibility return 0 index in empty case Chris@16: result_type i_norm_inf (0); Chris@16: real_type t = real_type (); Chris@16: typedef typename E::size_type vector_size_type; Chris@16: vector_size_type size (e ().size ()); Chris@16: for (vector_size_type i = 0; i < size; ++ i) { Chris@16: real_type u (type_traits::norm_inf (e () (i))); Chris@16: if (u > t) { Chris@16: i_norm_inf = i; Chris@16: t = u; Chris@16: } Chris@16: } Chris@16: return i_norm_inf; Chris@16: } Chris@16: // Dense case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (D size, I it) { Chris@16: // ISSUE For CBLAS compatibility return 0 index in empty case Chris@16: result_type i_norm_inf (0); Chris@16: real_type t = real_type (); Chris@16: while (-- size >= 0) { Chris@16: real_type u (type_traits::norm_inf (*it)); Chris@16: if (u > t) { Chris@16: i_norm_inf = it.index (); Chris@16: t = u; Chris@16: } Chris@16: ++ it; Chris@16: } Chris@16: return i_norm_inf; Chris@16: } Chris@16: // Sparse case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (I it, const I &it_end) { Chris@16: // ISSUE For CBLAS compatibility return 0 index in empty case Chris@16: result_type i_norm_inf (0); Chris@16: real_type t = real_type (); Chris@16: while (it != it_end) { Chris@16: real_type u (type_traits::norm_inf (*it)); Chris@16: if (u > t) { Chris@16: i_norm_inf = it.index (); Chris@16: t = u; Chris@16: } Chris@16: ++ it; Chris@16: } Chris@16: return i_norm_inf; Chris@16: } Chris@16: }; Chris@16: Chris@16: // Binary returning scalar Chris@16: template Chris@16: struct vector_scalar_binary_functor { Chris@16: typedef TV value_type; Chris@16: typedef TV result_type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct vector_inner_prod: Chris@16: public vector_scalar_binary_functor { Chris@16: typedef typename vector_scalar_binary_functor::value_type value_type; Chris@16: typedef typename vector_scalar_binary_functor::result_type result_type; Chris@16: Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (const vector_container &c1, Chris@16: const vector_container &c2) { Chris@16: #ifdef BOOST_UBLAS_USE_SIMD Chris@16: using namespace raw; Chris@16: typedef typename C1::size_type vector_size_type; Chris@16: vector_size_type size (BOOST_UBLAS_SAME (c1 ().size (), c2 ().size ())); Chris@16: const typename V1::value_type *data1 = data_const (c1 ()); Chris@16: const typename V1::value_type *data2 = data_const (c2 ()); Chris@16: vector_size_type s1 = stride (c1 ()); Chris@16: vector_size_type s2 = stride (c2 ()); Chris@16: result_type t = result_type (0); Chris@16: if (s1 == 1 && s2 == 1) { Chris@16: for (vector_size_type i = 0; i < size; ++ i) Chris@16: t += data1 [i] * data2 [i]; Chris@16: } else if (s2 == 1) { Chris@16: for (vector_size_type i = 0, i1 = 0; i < size; ++ i, i1 += s1) Chris@16: t += data1 [i1] * data2 [i]; Chris@16: } else if (s1 == 1) { Chris@16: for (vector_size_type i = 0, i2 = 0; i < size; ++ i, i2 += s2) Chris@16: t += data1 [i] * data2 [i2]; Chris@16: } else { Chris@16: for (vector_size_type i = 0, i1 = 0, i2 = 0; i < size; ++ i, i1 += s1, i2 += s2) Chris@16: t += data1 [i1] * data2 [i2]; Chris@16: } Chris@16: return t; Chris@16: #elif defined(BOOST_UBLAS_HAVE_BINDINGS) Chris@16: return boost::numeric::bindings::atlas::dot (c1 (), c2 ()); Chris@16: #else Chris@16: return apply (static_cast > (c1), static_cast > (c2)); Chris@16: #endif Chris@16: } Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (const vector_expression &e1, Chris@16: const vector_expression &e2) { Chris@16: typedef typename E1::size_type vector_size_type; Chris@16: vector_size_type size (BOOST_UBLAS_SAME (e1 ().size (), e2 ().size ())); Chris@16: result_type t = result_type (0); Chris@16: #ifndef BOOST_UBLAS_USE_DUFF_DEVICE Chris@16: for (vector_size_type i = 0; i < size; ++ i) Chris@16: t += e1 () (i) * e2 () (i); Chris@16: #else Chris@16: vector_size_type i (0); Chris@16: DD (size, 4, r, (t += e1 () (i) * e2 () (i), ++ i)); Chris@16: #endif Chris@16: return t; Chris@16: } Chris@16: // Dense case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (D size, I1 it1, I2 it2) { Chris@16: result_type t = result_type (0); Chris@16: #ifndef BOOST_UBLAS_USE_DUFF_DEVICE Chris@16: while (-- size >= 0) Chris@16: t += *it1 * *it2, ++ it1, ++ it2; Chris@16: #else Chris@16: DD (size, 4, r, (t += *it1 * *it2, ++ it1, ++ it2)); Chris@16: #endif Chris@16: return t; Chris@16: } Chris@16: // Packed case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end) { Chris@16: result_type t = result_type (0); Chris@16: typedef typename I1::difference_type vector_difference_type; Chris@16: vector_difference_type it1_size (it1_end - it1); Chris@16: vector_difference_type it2_size (it2_end - it2); Chris@16: vector_difference_type diff (0); Chris@16: if (it1_size > 0 && it2_size > 0) Chris@16: diff = it2.index () - it1.index (); Chris@16: if (diff != 0) { Chris@16: vector_difference_type size = (std::min) (diff, it1_size); Chris@16: if (size > 0) { Chris@16: it1 += size; Chris@16: it1_size -= size; Chris@16: diff -= size; Chris@16: } Chris@16: size = (std::min) (- diff, it2_size); Chris@16: if (size > 0) { Chris@16: it2 += size; Chris@16: it2_size -= size; Chris@16: diff += size; Chris@16: } Chris@16: } Chris@16: vector_difference_type size ((std::min) (it1_size, it2_size)); Chris@16: while (-- size >= 0) Chris@16: t += *it1 * *it2, ++ it1, ++ it2; Chris@16: return t; Chris@16: } Chris@16: // Sparse case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end, sparse_bidirectional_iterator_tag) { Chris@16: result_type t = result_type (0); Chris@16: if (it1 != it1_end && it2 != it2_end) { Chris@16: while (true) { Chris@16: if (it1.index () == it2.index ()) { Chris@16: t += *it1 * *it2, ++ it1, ++ it2; Chris@16: if (it1 == it1_end || it2 == it2_end) Chris@16: break; Chris@16: } else if (it1.index () < it2.index ()) { Chris@16: increment (it1, it1_end, it2.index () - it1.index ()); Chris@16: if (it1 == it1_end) Chris@16: break; Chris@16: } else if (it1.index () > it2.index ()) { Chris@16: increment (it2, it2_end, it1.index () - it2.index ()); Chris@16: if (it2 == it2_end) Chris@16: break; Chris@16: } Chris@16: } Chris@16: } Chris@16: return t; Chris@16: } Chris@16: }; Chris@16: Chris@16: // Matrix functors Chris@16: Chris@16: // Binary returning vector Chris@16: template Chris@16: struct matrix_vector_binary_functor { Chris@16: typedef typename M1::size_type size_type; Chris@16: typedef typename M1::difference_type difference_type; Chris@16: typedef TV value_type; Chris@16: typedef TV result_type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct matrix_vector_prod1: Chris@16: public matrix_vector_binary_functor { Chris@16: typedef typename matrix_vector_binary_functor::size_type size_type; Chris@16: typedef typename matrix_vector_binary_functor::difference_type difference_type; Chris@16: typedef typename matrix_vector_binary_functor::value_type value_type; Chris@16: typedef typename matrix_vector_binary_functor::result_type result_type; Chris@16: Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (const matrix_container &c1, Chris@16: const vector_container &c2, Chris@16: size_type i) { Chris@16: #ifdef BOOST_UBLAS_USE_SIMD Chris@16: using namespace raw; Chris@16: size_type size = BOOST_UBLAS_SAME (c1 ().size2 (), c2 ().size ()); Chris@16: const typename M1::value_type *data1 = data_const (c1 ()) + i * stride1 (c1 ()); Chris@16: const typename M2::value_type *data2 = data_const (c2 ()); Chris@16: size_type s1 = stride2 (c1 ()); Chris@16: size_type s2 = stride (c2 ()); Chris@16: result_type t = result_type (0); Chris@16: if (s1 == 1 && s2 == 1) { Chris@16: for (size_type j = 0; j < size; ++ j) Chris@16: t += data1 [j] * data2 [j]; Chris@16: } else if (s2 == 1) { Chris@16: for (size_type j = 0, j1 = 0; j < size; ++ j, j1 += s1) Chris@16: t += data1 [j1] * data2 [j]; Chris@16: } else if (s1 == 1) { Chris@16: for (size_type j = 0, j2 = 0; j < size; ++ j, j2 += s2) Chris@16: t += data1 [j] * data2 [j2]; Chris@16: } else { Chris@16: for (size_type j = 0, j1 = 0, j2 = 0; j < size; ++ j, j1 += s1, j2 += s2) Chris@16: t += data1 [j1] * data2 [j2]; Chris@16: } Chris@16: return t; Chris@16: #elif defined(BOOST_UBLAS_HAVE_BINDINGS) Chris@16: return boost::numeric::bindings::atlas::dot (c1 ().row (i), c2 ()); Chris@16: #else Chris@16: return apply (static_cast > (c1), static_cast > (c2, i)); Chris@16: #endif Chris@16: } Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (const matrix_expression &e1, Chris@16: const vector_expression &e2, Chris@16: size_type i) { Chris@16: size_type size = BOOST_UBLAS_SAME (e1 ().size2 (), e2 ().size ()); Chris@16: result_type t = result_type (0); Chris@16: #ifndef BOOST_UBLAS_USE_DUFF_DEVICE Chris@16: for (size_type j = 0; j < size; ++ j) Chris@16: t += e1 () (i, j) * e2 () (j); Chris@16: #else Chris@16: size_type j (0); Chris@16: DD (size, 4, r, (t += e1 () (i, j) * e2 () (j), ++ j)); Chris@16: #endif Chris@16: return t; Chris@16: } Chris@16: // Dense case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (difference_type size, I1 it1, I2 it2) { Chris@16: result_type t = result_type (0); Chris@16: #ifndef BOOST_UBLAS_USE_DUFF_DEVICE Chris@16: while (-- size >= 0) Chris@16: t += *it1 * *it2, ++ it1, ++ it2; Chris@16: #else Chris@16: DD (size, 4, r, (t += *it1 * *it2, ++ it1, ++ it2)); Chris@16: #endif Chris@16: return t; Chris@16: } Chris@16: // Packed case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end) { Chris@16: result_type t = result_type (0); Chris@16: difference_type it1_size (it1_end - it1); Chris@16: difference_type it2_size (it2_end - it2); Chris@16: difference_type diff (0); Chris@16: if (it1_size > 0 && it2_size > 0) Chris@16: diff = it2.index () - it1.index2 (); Chris@16: if (diff != 0) { Chris@16: difference_type size = (std::min) (diff, it1_size); Chris@16: if (size > 0) { Chris@16: it1 += size; Chris@16: it1_size -= size; Chris@16: diff -= size; Chris@16: } Chris@16: size = (std::min) (- diff, it2_size); Chris@16: if (size > 0) { Chris@16: it2 += size; Chris@16: it2_size -= size; Chris@16: diff += size; Chris@16: } Chris@16: } Chris@16: difference_type size ((std::min) (it1_size, it2_size)); Chris@16: while (-- size >= 0) Chris@16: t += *it1 * *it2, ++ it1, ++ it2; Chris@16: return t; Chris@16: } Chris@16: // Sparse case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end, Chris@16: sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag) { Chris@16: result_type t = result_type (0); Chris@16: if (it1 != it1_end && it2 != it2_end) { Chris@16: size_type it1_index = it1.index2 (), it2_index = it2.index (); Chris@16: while (true) { Chris@16: difference_type compare = it1_index - it2_index; Chris@16: if (compare == 0) { Chris@16: t += *it1 * *it2, ++ it1, ++ it2; Chris@16: if (it1 != it1_end && it2 != it2_end) { Chris@16: it1_index = it1.index2 (); Chris@16: it2_index = it2.index (); Chris@16: } else Chris@16: break; Chris@16: } else if (compare < 0) { Chris@16: increment (it1, it1_end, - compare); Chris@16: if (it1 != it1_end) Chris@16: it1_index = it1.index2 (); Chris@16: else Chris@16: break; Chris@16: } else if (compare > 0) { Chris@16: increment (it2, it2_end, compare); Chris@16: if (it2 != it2_end) Chris@16: it2_index = it2.index (); Chris@16: else Chris@16: break; Chris@16: } Chris@16: } Chris@16: } Chris@16: return t; Chris@16: } Chris@16: // Sparse packed case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &/* it2_end */, Chris@16: sparse_bidirectional_iterator_tag, packed_random_access_iterator_tag) { Chris@16: result_type t = result_type (0); Chris@16: while (it1 != it1_end) { Chris@16: t += *it1 * it2 () (it1.index2 ()); Chris@16: ++ it1; Chris@16: } Chris@16: return t; Chris@16: } Chris@16: // Packed sparse case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (I1 it1, const I1 &/* it1_end */, I2 it2, const I2 &it2_end, Chris@16: packed_random_access_iterator_tag, sparse_bidirectional_iterator_tag) { Chris@16: result_type t = result_type (0); Chris@16: while (it2 != it2_end) { Chris@16: t += it1 () (it1.index1 (), it2.index ()) * *it2; Chris@16: ++ it2; Chris@16: } Chris@16: return t; Chris@16: } Chris@16: // Another dispatcher Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end, Chris@16: sparse_bidirectional_iterator_tag) { Chris@16: typedef typename I1::iterator_category iterator1_category; Chris@16: typedef typename I2::iterator_category iterator2_category; Chris@16: return apply (it1, it1_end, it2, it2_end, iterator1_category (), iterator2_category ()); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct matrix_vector_prod2: Chris@16: public matrix_vector_binary_functor { Chris@16: typedef typename matrix_vector_binary_functor::size_type size_type; Chris@16: typedef typename matrix_vector_binary_functor::difference_type difference_type; Chris@16: typedef typename matrix_vector_binary_functor::value_type value_type; Chris@16: typedef typename matrix_vector_binary_functor::result_type result_type; Chris@16: Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (const vector_container &c1, Chris@16: const matrix_container &c2, Chris@16: size_type i) { Chris@16: #ifdef BOOST_UBLAS_USE_SIMD Chris@16: using namespace raw; Chris@16: size_type size = BOOST_UBLAS_SAME (c1 ().size (), c2 ().size1 ()); Chris@16: const typename M1::value_type *data1 = data_const (c1 ()); Chris@16: const typename M2::value_type *data2 = data_const (c2 ()) + i * stride2 (c2 ()); Chris@16: size_type s1 = stride (c1 ()); Chris@16: size_type s2 = stride1 (c2 ()); Chris@16: result_type t = result_type (0); Chris@16: if (s1 == 1 && s2 == 1) { Chris@16: for (size_type j = 0; j < size; ++ j) Chris@16: t += data1 [j] * data2 [j]; Chris@16: } else if (s2 == 1) { Chris@16: for (size_type j = 0, j1 = 0; j < size; ++ j, j1 += s1) Chris@16: t += data1 [j1] * data2 [j]; Chris@16: } else if (s1 == 1) { Chris@16: for (size_type j = 0, j2 = 0; j < size; ++ j, j2 += s2) Chris@16: t += data1 [j] * data2 [j2]; Chris@16: } else { Chris@16: for (size_type j = 0, j1 = 0, j2 = 0; j < size; ++ j, j1 += s1, j2 += s2) Chris@16: t += data1 [j1] * data2 [j2]; Chris@16: } Chris@16: return t; Chris@16: #elif defined(BOOST_UBLAS_HAVE_BINDINGS) Chris@16: return boost::numeric::bindings::atlas::dot (c1 (), c2 ().column (i)); Chris@16: #else Chris@16: return apply (static_cast > (c1), static_cast > (c2, i)); Chris@16: #endif Chris@16: } Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (const vector_expression &e1, Chris@16: const matrix_expression &e2, Chris@16: size_type i) { Chris@16: size_type size = BOOST_UBLAS_SAME (e1 ().size (), e2 ().size1 ()); Chris@16: result_type t = result_type (0); Chris@16: #ifndef BOOST_UBLAS_USE_DUFF_DEVICE Chris@16: for (size_type j = 0; j < size; ++ j) Chris@16: t += e1 () (j) * e2 () (j, i); Chris@16: #else Chris@16: size_type j (0); Chris@16: DD (size, 4, r, (t += e1 () (j) * e2 () (j, i), ++ j)); Chris@16: #endif Chris@16: return t; Chris@16: } Chris@16: // Dense case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (difference_type size, I1 it1, I2 it2) { Chris@16: result_type t = result_type (0); Chris@16: #ifndef BOOST_UBLAS_USE_DUFF_DEVICE Chris@16: while (-- size >= 0) Chris@16: t += *it1 * *it2, ++ it1, ++ it2; Chris@16: #else Chris@16: DD (size, 4, r, (t += *it1 * *it2, ++ it1, ++ it2)); Chris@16: #endif Chris@16: return t; Chris@16: } Chris@16: // Packed case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end) { Chris@16: result_type t = result_type (0); Chris@16: difference_type it1_size (it1_end - it1); Chris@16: difference_type it2_size (it2_end - it2); Chris@16: difference_type diff (0); Chris@16: if (it1_size > 0 && it2_size > 0) Chris@16: diff = it2.index1 () - it1.index (); Chris@16: if (diff != 0) { Chris@16: difference_type size = (std::min) (diff, it1_size); Chris@16: if (size > 0) { Chris@16: it1 += size; Chris@16: it1_size -= size; Chris@16: diff -= size; Chris@16: } Chris@16: size = (std::min) (- diff, it2_size); Chris@16: if (size > 0) { Chris@16: it2 += size; Chris@16: it2_size -= size; Chris@16: diff += size; Chris@16: } Chris@16: } Chris@16: difference_type size ((std::min) (it1_size, it2_size)); Chris@16: while (-- size >= 0) Chris@16: t += *it1 * *it2, ++ it1, ++ it2; Chris@16: return t; Chris@16: } Chris@16: // Sparse case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end, Chris@16: sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag) { Chris@16: result_type t = result_type (0); Chris@16: if (it1 != it1_end && it2 != it2_end) { Chris@16: size_type it1_index = it1.index (), it2_index = it2.index1 (); Chris@16: while (true) { Chris@16: difference_type compare = it1_index - it2_index; Chris@16: if (compare == 0) { Chris@16: t += *it1 * *it2, ++ it1, ++ it2; Chris@16: if (it1 != it1_end && it2 != it2_end) { Chris@16: it1_index = it1.index (); Chris@16: it2_index = it2.index1 (); Chris@16: } else Chris@16: break; Chris@16: } else if (compare < 0) { Chris@16: increment (it1, it1_end, - compare); Chris@16: if (it1 != it1_end) Chris@16: it1_index = it1.index (); Chris@16: else Chris@16: break; Chris@16: } else if (compare > 0) { Chris@16: increment (it2, it2_end, compare); Chris@16: if (it2 != it2_end) Chris@16: it2_index = it2.index1 (); Chris@16: else Chris@16: break; Chris@16: } Chris@16: } Chris@16: } Chris@16: return t; Chris@16: } Chris@16: // Packed sparse case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (I1 it1, const I1 &/* it1_end */, I2 it2, const I2 &it2_end, Chris@16: packed_random_access_iterator_tag, sparse_bidirectional_iterator_tag) { Chris@16: result_type t = result_type (0); Chris@16: while (it2 != it2_end) { Chris@16: t += it1 () (it2.index1 ()) * *it2; Chris@16: ++ it2; Chris@16: } Chris@16: return t; Chris@16: } Chris@16: // Sparse packed case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &/* it2_end */, Chris@16: sparse_bidirectional_iterator_tag, packed_random_access_iterator_tag) { Chris@16: result_type t = result_type (0); Chris@16: while (it1 != it1_end) { Chris@16: t += *it1 * it2 () (it1.index (), it2.index2 ()); Chris@16: ++ it1; Chris@16: } Chris@16: return t; Chris@16: } Chris@16: // Another dispatcher Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end, Chris@16: sparse_bidirectional_iterator_tag) { Chris@16: typedef typename I1::iterator_category iterator1_category; Chris@16: typedef typename I2::iterator_category iterator2_category; Chris@16: return apply (it1, it1_end, it2, it2_end, iterator1_category (), iterator2_category ()); Chris@16: } Chris@16: }; Chris@16: Chris@16: // Binary returning matrix Chris@16: template Chris@16: struct matrix_matrix_binary_functor { Chris@16: typedef typename M1::size_type size_type; Chris@16: typedef typename M1::difference_type difference_type; Chris@16: typedef TV value_type; Chris@16: typedef TV result_type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct matrix_matrix_prod: Chris@16: public matrix_matrix_binary_functor { Chris@16: typedef typename matrix_matrix_binary_functor::size_type size_type; Chris@16: typedef typename matrix_matrix_binary_functor::difference_type difference_type; Chris@16: typedef typename matrix_matrix_binary_functor::value_type value_type; Chris@16: typedef typename matrix_matrix_binary_functor::result_type result_type; Chris@16: Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (const matrix_container &c1, Chris@16: const matrix_container &c2, Chris@16: size_type i, size_type j) { Chris@16: #ifdef BOOST_UBLAS_USE_SIMD Chris@16: using namespace raw; Chris@16: size_type size = BOOST_UBLAS_SAME (c1 ().size2 (), c2 ().sizc1 ()); Chris@16: const typename M1::value_type *data1 = data_const (c1 ()) + i * stride1 (c1 ()); Chris@16: const typename M2::value_type *data2 = data_const (c2 ()) + j * stride2 (c2 ()); Chris@16: size_type s1 = stride2 (c1 ()); Chris@16: size_type s2 = stride1 (c2 ()); Chris@16: result_type t = result_type (0); Chris@16: if (s1 == 1 && s2 == 1) { Chris@16: for (size_type k = 0; k < size; ++ k) Chris@16: t += data1 [k] * data2 [k]; Chris@16: } else if (s2 == 1) { Chris@16: for (size_type k = 0, k1 = 0; k < size; ++ k, k1 += s1) Chris@16: t += data1 [k1] * data2 [k]; Chris@16: } else if (s1 == 1) { Chris@16: for (size_type k = 0, k2 = 0; k < size; ++ k, k2 += s2) Chris@16: t += data1 [k] * data2 [k2]; Chris@16: } else { Chris@16: for (size_type k = 0, k1 = 0, k2 = 0; k < size; ++ k, k1 += s1, k2 += s2) Chris@16: t += data1 [k1] * data2 [k2]; Chris@16: } Chris@16: return t; Chris@16: #elif defined(BOOST_UBLAS_HAVE_BINDINGS) Chris@16: return boost::numeric::bindings::atlas::dot (c1 ().row (i), c2 ().column (j)); Chris@16: #else Chris@101: boost::ignore_unused(j); Chris@16: return apply (static_cast > (c1), static_cast > (c2, i)); Chris@16: #endif Chris@16: } Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (const matrix_expression &e1, Chris@16: const matrix_expression &e2, Chris@16: size_type i, size_type j) { Chris@16: size_type size = BOOST_UBLAS_SAME (e1 ().size2 (), e2 ().size1 ()); Chris@16: result_type t = result_type (0); Chris@16: #ifndef BOOST_UBLAS_USE_DUFF_DEVICE Chris@16: for (size_type k = 0; k < size; ++ k) Chris@16: t += e1 () (i, k) * e2 () (k, j); Chris@16: #else Chris@16: size_type k (0); Chris@16: DD (size, 4, r, (t += e1 () (i, k) * e2 () (k, j), ++ k)); Chris@16: #endif Chris@16: return t; Chris@16: } Chris@16: // Dense case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (difference_type size, I1 it1, I2 it2) { Chris@16: result_type t = result_type (0); Chris@16: #ifndef BOOST_UBLAS_USE_DUFF_DEVICE Chris@16: while (-- size >= 0) Chris@16: t += *it1 * *it2, ++ it1, ++ it2; Chris@16: #else Chris@16: DD (size, 4, r, (t += *it1 * *it2, ++ it1, ++ it2)); Chris@16: #endif Chris@16: return t; Chris@16: } Chris@16: // Packed case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end, packed_random_access_iterator_tag) { Chris@16: result_type t = result_type (0); Chris@16: difference_type it1_size (it1_end - it1); Chris@16: difference_type it2_size (it2_end - it2); Chris@16: difference_type diff (0); Chris@16: if (it1_size > 0 && it2_size > 0) Chris@16: diff = it2.index1 () - it1.index2 (); Chris@16: if (diff != 0) { Chris@16: difference_type size = (std::min) (diff, it1_size); Chris@16: if (size > 0) { Chris@16: it1 += size; Chris@16: it1_size -= size; Chris@16: diff -= size; Chris@16: } Chris@16: size = (std::min) (- diff, it2_size); Chris@16: if (size > 0) { Chris@16: it2 += size; Chris@16: it2_size -= size; Chris@16: diff += size; Chris@16: } Chris@16: } Chris@16: difference_type size ((std::min) (it1_size, it2_size)); Chris@16: while (-- size >= 0) Chris@16: t += *it1 * *it2, ++ it1, ++ it2; Chris@16: return t; Chris@16: } Chris@16: // Sparse case Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end, sparse_bidirectional_iterator_tag) { Chris@16: result_type t = result_type (0); Chris@16: if (it1 != it1_end && it2 != it2_end) { Chris@16: size_type it1_index = it1.index2 (), it2_index = it2.index1 (); Chris@16: while (true) { Chris@16: difference_type compare = difference_type (it1_index - it2_index); Chris@16: if (compare == 0) { Chris@16: t += *it1 * *it2, ++ it1, ++ it2; Chris@16: if (it1 != it1_end && it2 != it2_end) { Chris@16: it1_index = it1.index2 (); Chris@16: it2_index = it2.index1 (); Chris@16: } else Chris@16: break; Chris@16: } else if (compare < 0) { Chris@16: increment (it1, it1_end, - compare); Chris@16: if (it1 != it1_end) Chris@16: it1_index = it1.index2 (); Chris@16: else Chris@16: break; Chris@16: } else if (compare > 0) { Chris@16: increment (it2, it2_end, compare); Chris@16: if (it2 != it2_end) Chris@16: it2_index = it2.index1 (); Chris@16: else Chris@16: break; Chris@16: } Chris@16: } Chris@16: } Chris@16: return t; Chris@16: } Chris@16: }; Chris@16: Chris@16: // Unary returning scalar norm Chris@16: template Chris@16: struct matrix_scalar_real_unary_functor { Chris@16: typedef typename M::value_type value_type; Chris@16: typedef typename type_traits::real_type real_type; Chris@16: typedef real_type result_type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct matrix_norm_1: Chris@16: public matrix_scalar_real_unary_functor { Chris@16: typedef typename matrix_scalar_real_unary_functor::value_type value_type; Chris@16: typedef typename matrix_scalar_real_unary_functor::real_type real_type; Chris@16: typedef typename matrix_scalar_real_unary_functor::result_type result_type; Chris@16: Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (const matrix_expression &e) { Chris@16: real_type t = real_type (); Chris@16: typedef typename E::size_type matrix_size_type; Chris@16: matrix_size_type size2 (e ().size2 ()); Chris@16: for (matrix_size_type j = 0; j < size2; ++ j) { Chris@16: real_type u = real_type (); Chris@16: matrix_size_type size1 (e ().size1 ()); Chris@16: for (matrix_size_type i = 0; i < size1; ++ i) { Chris@16: real_type v (type_traits::norm_1 (e () (i, j))); Chris@16: u += v; Chris@16: } Chris@16: if (u > t) Chris@16: t = u; Chris@16: } Chris@16: return t; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct matrix_norm_frobenius: Chris@16: public matrix_scalar_real_unary_functor { Chris@16: typedef typename matrix_scalar_real_unary_functor::value_type value_type; Chris@16: typedef typename matrix_scalar_real_unary_functor::real_type real_type; Chris@16: typedef typename matrix_scalar_real_unary_functor::result_type result_type; Chris@16: Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (const matrix_expression &e) { Chris@16: real_type t = real_type (); Chris@16: typedef typename E::size_type matrix_size_type; Chris@16: matrix_size_type size1 (e ().size1 ()); Chris@16: for (matrix_size_type i = 0; i < size1; ++ i) { Chris@16: matrix_size_type size2 (e ().size2 ()); Chris@16: for (matrix_size_type j = 0; j < size2; ++ j) { Chris@16: real_type u (type_traits::norm_2 (e () (i, j))); Chris@16: t += u * u; Chris@16: } Chris@16: } Chris@16: return type_traits::type_sqrt (t); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct matrix_norm_inf: Chris@16: public matrix_scalar_real_unary_functor { Chris@16: typedef typename matrix_scalar_real_unary_functor::value_type value_type; Chris@16: typedef typename matrix_scalar_real_unary_functor::real_type real_type; Chris@16: typedef typename matrix_scalar_real_unary_functor::result_type result_type; Chris@16: Chris@16: template Chris@16: static BOOST_UBLAS_INLINE Chris@16: result_type apply (const matrix_expression &e) { Chris@16: real_type t = real_type (); Chris@16: typedef typename E::size_type matrix_size_type; Chris@16: matrix_size_type size1 (e ().size1 ()); Chris@16: for (matrix_size_type i = 0; i < size1; ++ i) { Chris@16: real_type u = real_type (); Chris@16: matrix_size_type size2 (e ().size2 ()); Chris@16: for (matrix_size_type j = 0; j < size2; ++ j) { Chris@16: real_type v (type_traits::norm_inf (e () (i, j))); Chris@16: u += v; Chris@16: } Chris@16: if (u > t) Chris@16: t = u; Chris@16: } Chris@16: return t; Chris@16: } Chris@16: }; Chris@16: Chris@16: // forward declaration Chris@16: template struct basic_column_major; Chris@16: Chris@16: // This functor defines storage layout and it's properties Chris@16: // matrix (i,j) -> storage [i * size_i + j] Chris@16: template Chris@16: struct basic_row_major { Chris@16: typedef Z size_type; Chris@16: typedef D difference_type; Chris@16: typedef row_major_tag orientation_category; Chris@16: typedef basic_column_major transposed_layout; Chris@16: Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type storage_size (size_type size_i, size_type size_j) { Chris@16: // Guard against size_type overflow Chris@16: BOOST_UBLAS_CHECK (size_j == 0 || size_i <= (std::numeric_limits::max) () / size_j, bad_size ()); Chris@16: return size_i * size_j; Chris@16: } Chris@16: Chris@16: // Indexing conversion to storage element Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type element (size_type i, size_type size_i, size_type j, size_type size_j) { Chris@16: BOOST_UBLAS_CHECK (i < size_i, bad_index ()); Chris@16: BOOST_UBLAS_CHECK (j < size_j, bad_index ()); Chris@16: detail::ignore_unused_variable_warning(size_i); Chris@16: // Guard against size_type overflow Chris@16: BOOST_UBLAS_CHECK (i <= ((std::numeric_limits::max) () - j) / size_j, bad_index ()); Chris@16: return i * size_j + j; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type address (size_type i, size_type size_i, size_type j, size_type size_j) { Chris@16: BOOST_UBLAS_CHECK (i <= size_i, bad_index ()); Chris@16: BOOST_UBLAS_CHECK (j <= size_j, bad_index ()); Chris@16: // Guard against size_type overflow - address may be size_j past end of storage Chris@16: BOOST_UBLAS_CHECK (size_j == 0 || i <= ((std::numeric_limits::max) () - j) / size_j, bad_index ()); Chris@16: detail::ignore_unused_variable_warning(size_i); Chris@16: return i * size_j + j; Chris@16: } Chris@16: Chris@16: // Storage element to index conversion Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: difference_type distance_i (difference_type k, size_type /* size_i */, size_type size_j) { Chris@16: return size_j != 0 ? k / size_j : 0; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: difference_type distance_j (difference_type k, size_type /* size_i */, size_type /* size_j */) { Chris@16: return k; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index_i (difference_type k, size_type /* size_i */, size_type size_j) { Chris@16: return size_j != 0 ? k / size_j : 0; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index_j (difference_type k, size_type /* size_i */, size_type size_j) { Chris@16: return size_j != 0 ? k % size_j : 0; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: bool fast_i () { Chris@16: return false; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: bool fast_j () { Chris@16: return true; Chris@16: } Chris@16: Chris@16: // Iterating storage elements Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: void increment_i (I &it, size_type /* size_i */, size_type size_j) { Chris@16: it += size_j; Chris@16: } Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: void increment_i (I &it, difference_type n, size_type /* size_i */, size_type size_j) { Chris@16: it += n * size_j; Chris@16: } Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: void decrement_i (I &it, size_type /* size_i */, size_type size_j) { Chris@16: it -= size_j; Chris@16: } Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: void decrement_i (I &it, difference_type n, size_type /* size_i */, size_type size_j) { Chris@16: it -= n * size_j; Chris@16: } Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: void increment_j (I &it, size_type /* size_i */, size_type /* size_j */) { Chris@16: ++ it; Chris@16: } Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: void increment_j (I &it, difference_type n, size_type /* size_i */, size_type /* size_j */) { Chris@16: it += n; Chris@16: } Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: void decrement_j (I &it, size_type /* size_i */, size_type /* size_j */) { Chris@16: -- it; Chris@16: } Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: void decrement_j (I &it, difference_type n, size_type /* size_i */, size_type /* size_j */) { Chris@16: it -= n; Chris@16: } Chris@16: Chris@16: // Triangular access Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type triangular_size (size_type size_i, size_type size_j) { Chris@16: size_type size = (std::max) (size_i, size_j); Chris@16: // Guard against size_type overflow - simplified Chris@16: BOOST_UBLAS_CHECK (size == 0 || size / 2 < (std::numeric_limits::max) () / size /* +1/2 */, bad_size ()); Chris@16: return ((size + 1) * size) / 2; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type lower_element (size_type i, size_type size_i, size_type j, size_type size_j) { Chris@16: BOOST_UBLAS_CHECK (i < size_i, bad_index ()); Chris@16: BOOST_UBLAS_CHECK (j < size_j, bad_index ()); Chris@16: BOOST_UBLAS_CHECK (i >= j, bad_index ()); Chris@16: detail::ignore_unused_variable_warning(size_i); Chris@16: detail::ignore_unused_variable_warning(size_j); Chris@16: // FIXME size_type overflow Chris@16: // sigma_i (i + 1) = (i + 1) * i / 2 Chris@16: // i = 0 1 2 3, sigma = 0 1 3 6 Chris@16: return ((i + 1) * i) / 2 + j; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type upper_element (size_type i, size_type size_i, size_type j, size_type size_j) { Chris@16: BOOST_UBLAS_CHECK (i < size_i, bad_index ()); Chris@16: BOOST_UBLAS_CHECK (j < size_j, bad_index ()); Chris@16: BOOST_UBLAS_CHECK (i <= j, bad_index ()); Chris@16: // FIXME size_type overflow Chris@16: // sigma_i (size - i) = size * i - i * (i - 1) / 2 Chris@16: // i = 0 1 2 3, sigma = 0 4 7 9 Chris@16: return (i * (2 * (std::max) (size_i, size_j) - i + 1)) / 2 + j - i; Chris@16: } Chris@16: Chris@16: // Major and minor indices Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index_M (size_type index1, size_type /* index2 */) { Chris@16: return index1; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index_m (size_type /* index1 */, size_type index2) { Chris@16: return index2; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type size_M (size_type size_i, size_type /* size_j */) { Chris@16: return size_i; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type size_m (size_type /* size_i */, size_type size_j) { Chris@16: return size_j; Chris@16: } Chris@16: }; Chris@16: Chris@16: // This functor defines storage layout and it's properties Chris@16: // matrix (i,j) -> storage [i + j * size_i] Chris@16: template Chris@16: struct basic_column_major { Chris@16: typedef Z size_type; Chris@16: typedef D difference_type; Chris@16: typedef column_major_tag orientation_category; Chris@16: typedef basic_row_major transposed_layout; Chris@16: Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type storage_size (size_type size_i, size_type size_j) { Chris@16: // Guard against size_type overflow Chris@16: BOOST_UBLAS_CHECK (size_i == 0 || size_j <= (std::numeric_limits::max) () / size_i, bad_size ()); Chris@16: return size_i * size_j; Chris@16: } Chris@16: Chris@16: // Indexing conversion to storage element Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type element (size_type i, size_type size_i, size_type j, size_type size_j) { Chris@16: BOOST_UBLAS_CHECK (i < size_i, bad_index ()); Chris@16: BOOST_UBLAS_CHECK (j < size_j, bad_index ()); Chris@16: detail::ignore_unused_variable_warning(size_j); Chris@16: // Guard against size_type overflow Chris@16: BOOST_UBLAS_CHECK (j <= ((std::numeric_limits::max) () - i) / size_i, bad_index ()); Chris@16: return i + j * size_i; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type address (size_type i, size_type size_i, size_type j, size_type size_j) { Chris@16: BOOST_UBLAS_CHECK (i <= size_i, bad_index ()); Chris@16: BOOST_UBLAS_CHECK (j <= size_j, bad_index ()); Chris@16: detail::ignore_unused_variable_warning(size_j); Chris@16: // Guard against size_type overflow - address may be size_i past end of storage Chris@16: BOOST_UBLAS_CHECK (size_i == 0 || j <= ((std::numeric_limits::max) () - i) / size_i, bad_index ()); Chris@16: return i + j * size_i; Chris@16: } Chris@16: Chris@16: // Storage element to index conversion Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: difference_type distance_i (difference_type k, size_type /* size_i */, size_type /* size_j */) { Chris@16: return k; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: difference_type distance_j (difference_type k, size_type size_i, size_type /* size_j */) { Chris@16: return size_i != 0 ? k / size_i : 0; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index_i (difference_type k, size_type size_i, size_type /* size_j */) { Chris@16: return size_i != 0 ? k % size_i : 0; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index_j (difference_type k, size_type size_i, size_type /* size_j */) { Chris@16: return size_i != 0 ? k / size_i : 0; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: bool fast_i () { Chris@16: return true; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: bool fast_j () { Chris@16: return false; Chris@16: } Chris@16: Chris@16: // Iterating Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: void increment_i (I &it, size_type /* size_i */, size_type /* size_j */) { Chris@16: ++ it; Chris@16: } Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: void increment_i (I &it, difference_type n, size_type /* size_i */, size_type /* size_j */) { Chris@16: it += n; Chris@16: } Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: void decrement_i (I &it, size_type /* size_i */, size_type /* size_j */) { Chris@16: -- it; Chris@16: } Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: void decrement_i (I &it, difference_type n, size_type /* size_i */, size_type /* size_j */) { Chris@16: it -= n; Chris@16: } Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: void increment_j (I &it, size_type size_i, size_type /* size_j */) { Chris@16: it += size_i; Chris@16: } Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: void increment_j (I &it, difference_type n, size_type size_i, size_type /* size_j */) { Chris@16: it += n * size_i; Chris@16: } Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: void decrement_j (I &it, size_type size_i, size_type /* size_j */) { Chris@16: it -= size_i; Chris@16: } Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: void decrement_j (I &it, difference_type n, size_type size_i, size_type /* size_j */) { Chris@16: it -= n* size_i; Chris@16: } Chris@16: Chris@16: // Triangular access Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type triangular_size (size_type size_i, size_type size_j) { Chris@16: size_type size = (std::max) (size_i, size_j); Chris@16: // Guard against size_type overflow - simplified Chris@16: BOOST_UBLAS_CHECK (size == 0 || size / 2 < (std::numeric_limits::max) () / size /* +1/2 */, bad_size ()); Chris@16: return ((size + 1) * size) / 2; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type lower_element (size_type i, size_type size_i, size_type j, size_type size_j) { Chris@16: BOOST_UBLAS_CHECK (i < size_i, bad_index ()); Chris@16: BOOST_UBLAS_CHECK (j < size_j, bad_index ()); Chris@16: BOOST_UBLAS_CHECK (i >= j, bad_index ()); Chris@16: // FIXME size_type overflow Chris@16: // sigma_j (size - j) = size * j - j * (j - 1) / 2 Chris@16: // j = 0 1 2 3, sigma = 0 4 7 9 Chris@16: return i - j + (j * (2 * (std::max) (size_i, size_j) - j + 1)) / 2; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type upper_element (size_type i, size_type size_i, size_type j, size_type size_j) { Chris@16: BOOST_UBLAS_CHECK (i < size_i, bad_index ()); Chris@16: BOOST_UBLAS_CHECK (j < size_j, bad_index ()); Chris@16: BOOST_UBLAS_CHECK (i <= j, bad_index ()); Chris@16: // FIXME size_type overflow Chris@16: // sigma_j (j + 1) = (j + 1) * j / 2 Chris@16: // j = 0 1 2 3, sigma = 0 1 3 6 Chris@16: return i + ((j + 1) * j) / 2; Chris@16: } Chris@16: Chris@16: // Major and minor indices Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index_M (size_type /* index1 */, size_type index2) { Chris@16: return index2; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index_m (size_type index1, size_type /* index2 */) { Chris@16: return index1; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type size_M (size_type /* size_i */, size_type size_j) { Chris@16: return size_j; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type size_m (size_type size_i, size_type /* size_j */) { Chris@16: return size_i; Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: template Chris@16: struct basic_full { Chris@16: typedef Z size_type; Chris@16: Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type packed_size (L, size_type size_i, size_type size_j) { Chris@16: return L::storage_size (size_i, size_j); Chris@16: } Chris@16: Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: bool zero (size_type /* i */, size_type /* j */) { Chris@16: return false; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: bool one (size_type /* i */, size_type /* j */) { Chris@16: return false; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: bool other (size_type /* i */, size_type /* j */) { Chris@16: return true; Chris@16: } Chris@16: // FIXME: this should not be used at all Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type restrict1 (size_type i, size_type /* j */) { Chris@16: return i; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type restrict2 (size_type /* i */, size_type j) { Chris@16: return j; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type mutable_restrict1 (size_type i, size_type /* j */) { Chris@16: return i; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type mutable_restrict2 (size_type /* i */, size_type j) { Chris@16: return j; Chris@16: } Chris@16: }; Chris@16: Chris@16: namespace detail { Chris@16: template < class L > Chris@16: struct transposed_structure { Chris@16: typedef typename L::size_type size_type; Chris@16: Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type packed_size (LAYOUT l, size_type size_i, size_type size_j) { Chris@16: return L::packed_size(l, size_j, size_i); Chris@16: } Chris@16: Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: bool zero (size_type i, size_type j) { Chris@16: return L::zero(j, i); Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: bool one (size_type i, size_type j) { Chris@16: return L::one(j, i); Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: bool other (size_type i, size_type j) { Chris@16: return L::other(j, i); Chris@16: } Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type element (LAYOUT /* l */, size_type i, size_type size_i, size_type j, size_type size_j) { Chris@16: return L::element(typename LAYOUT::transposed_layout(), j, size_j, i, size_i); Chris@16: } Chris@16: Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type restrict1 (size_type i, size_type j, size_type size1, size_type size2) { Chris@16: return L::restrict2(j, i, size2, size1); Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type restrict2 (size_type i, size_type j, size_type size1, size_type size2) { Chris@16: return L::restrict1(j, i, size2, size1); Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type mutable_restrict1 (size_type i, size_type j, size_type size1, size_type size2) { Chris@16: return L::mutable_restrict2(j, i, size2, size1); Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type mutable_restrict2 (size_type i, size_type j, size_type size1, size_type size2) { Chris@16: return L::mutable_restrict1(j, i, size2, size1); Chris@16: } Chris@16: Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type global_restrict1 (size_type index1, size_type size1, size_type index2, size_type size2) { Chris@16: return L::global_restrict2(index2, size2, index1, size1); Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type global_restrict2 (size_type index1, size_type size1, size_type index2, size_type size2) { Chris@16: return L::global_restrict1(index2, size2, index1, size1); Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type global_mutable_restrict1 (size_type index1, size_type size1, size_type index2, size_type size2) { Chris@16: return L::global_mutable_restrict2(index2, size2, index1, size1); Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type global_mutable_restrict2 (size_type index1, size_type size1, size_type index2, size_type size2) { Chris@16: return L::global_mutable_restrict1(index2, size2, index1, size1); Chris@16: } Chris@16: }; Chris@16: } Chris@16: Chris@16: template Chris@16: struct basic_lower { Chris@16: typedef Z size_type; Chris@16: typedef lower_tag triangular_type; Chris@16: Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type packed_size (L, size_type size_i, size_type size_j) { Chris@16: return L::triangular_size (size_i, size_j); Chris@16: } Chris@16: Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: bool zero (size_type i, size_type j) { Chris@16: return j > i; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: bool one (size_type /* i */, size_type /* j */) { Chris@16: return false; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: bool other (size_type i, size_type j) { Chris@16: return j <= i; Chris@16: } Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type element (L, size_type i, size_type size_i, size_type j, size_type size_j) { Chris@16: return L::lower_element (i, size_i, j, size_j); Chris@16: } Chris@16: Chris@16: // return nearest valid index in column j Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type restrict1 (size_type i, size_type j, size_type size1, size_type /* size2 */) { Chris@16: return (std::max)(j, (std::min) (size1, i)); Chris@16: } Chris@16: // return nearest valid index in row i Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type restrict2 (size_type i, size_type j, size_type /* size1 */, size_type /* size2 */) { Chris@16: return (std::max)(size_type(0), (std::min) (i+1, j)); Chris@16: } Chris@16: // return nearest valid mutable index in column j Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type mutable_restrict1 (size_type i, size_type j, size_type size1, size_type /* size2 */) { Chris@16: return (std::max)(j, (std::min) (size1, i)); Chris@16: } Chris@16: // return nearest valid mutable index in row i Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type mutable_restrict2 (size_type i, size_type j, size_type /* size1 */, size_type /* size2 */) { Chris@16: return (std::max)(size_type(0), (std::min) (i+1, j)); Chris@16: } Chris@16: Chris@16: // return an index between the first and (1+last) filled row Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type global_restrict1 (size_type index1, size_type size1, size_type /* index2 */, size_type /* size2 */) { Chris@16: return (std::max)(size_type(0), (std::min)(size1, index1) ); Chris@16: } Chris@16: // return an index between the first and (1+last) filled column Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type global_restrict2 (size_type /* index1 */, size_type /* size1 */, size_type index2, size_type size2) { Chris@16: return (std::max)(size_type(0), (std::min)(size2, index2) ); Chris@16: } Chris@16: Chris@16: // return an index between the first and (1+last) filled mutable row Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type global_mutable_restrict1 (size_type index1, size_type size1, size_type /* index2 */, size_type /* size2 */) { Chris@16: return (std::max)(size_type(0), (std::min)(size1, index1) ); Chris@16: } Chris@16: // return an index between the first and (1+last) filled mutable column Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type global_mutable_restrict2 (size_type /* index1 */, size_type /* size1 */, size_type index2, size_type size2) { Chris@16: return (std::max)(size_type(0), (std::min)(size2, index2) ); Chris@16: } Chris@16: }; Chris@16: Chris@16: // the first row only contains a single 1. Thus it is not stored. Chris@16: template Chris@16: struct basic_unit_lower : public basic_lower { Chris@16: typedef Z size_type; Chris@16: typedef unit_lower_tag triangular_type; Chris@16: Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type packed_size (L, size_type size_i, size_type size_j) { Chris@16: // Zero size strict triangles are bad at this point Chris@16: BOOST_UBLAS_CHECK (size_i != 0 && size_j != 0, bad_index ()); Chris@16: return L::triangular_size (size_i - 1, size_j - 1); Chris@16: } Chris@16: Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: bool one (size_type i, size_type j) { Chris@16: return j == i; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: bool other (size_type i, size_type j) { Chris@16: return j < i; Chris@16: } Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type element (L, size_type i, size_type size_i, size_type j, size_type size_j) { Chris@16: // Zero size strict triangles are bad at this point Chris@16: BOOST_UBLAS_CHECK (size_i != 0 && size_j != 0 && i != 0, bad_index ()); Chris@16: return L::lower_element (i-1, size_i - 1, j, size_j - 1); Chris@16: } Chris@16: Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type mutable_restrict1 (size_type i, size_type j, size_type size1, size_type /* size2 */) { Chris@16: return (std::max)(j+1, (std::min) (size1, i)); Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type mutable_restrict2 (size_type i, size_type j, size_type /* size1 */, size_type /* size2 */) { Chris@16: return (std::max)(size_type(0), (std::min) (i, j)); Chris@16: } Chris@16: Chris@16: // return an index between the first and (1+last) filled mutable row Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type global_mutable_restrict1 (size_type index1, size_type size1, size_type /* index2 */, size_type /* size2 */) { Chris@16: return (std::max)(size_type(1), (std::min)(size1, index1) ); Chris@16: } Chris@16: // return an index between the first and (1+last) filled mutable column Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type global_mutable_restrict2 (size_type /* index1 */, size_type /* size1 */, size_type index2, size_type size2) { Chris@16: BOOST_UBLAS_CHECK( size2 >= 1 , external_logic() ); Chris@16: return (std::max)(size_type(0), (std::min)(size2-1, index2) ); Chris@16: } Chris@16: }; Chris@16: Chris@16: // the first row only contains no element. Thus it is not stored. Chris@16: template Chris@16: struct basic_strict_lower : public basic_unit_lower { Chris@16: typedef Z size_type; Chris@16: typedef strict_lower_tag triangular_type; Chris@16: Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type packed_size (L, size_type size_i, size_type size_j) { Chris@16: // Zero size strict triangles are bad at this point Chris@16: BOOST_UBLAS_CHECK (size_i != 0 && size_j != 0, bad_index ()); Chris@16: return L::triangular_size (size_i - 1, size_j - 1); Chris@16: } Chris@16: Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: bool zero (size_type i, size_type j) { Chris@16: return j >= i; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: bool one (size_type /*i*/, size_type /*j*/) { Chris@16: return false; Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: bool other (size_type i, size_type j) { Chris@16: return j < i; Chris@16: } Chris@16: template Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type element (L, size_type i, size_type size_i, size_type j, size_type size_j) { Chris@16: // Zero size strict triangles are bad at this point Chris@16: BOOST_UBLAS_CHECK (size_i != 0 && size_j != 0 && i != 0, bad_index ()); Chris@16: return L::lower_element (i-1, size_i - 1, j, size_j - 1); Chris@16: } Chris@16: Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type restrict1 (size_type i, size_type j, size_type size1, size_type size2) { Chris@16: return basic_unit_lower::mutable_restrict1(i, j, size1, size2); Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type restrict2 (size_type i, size_type j, size_type size1, size_type size2) { Chris@16: return basic_unit_lower::mutable_restrict2(i, j, size1, size2); Chris@16: } Chris@16: Chris@16: // return an index between the first and (1+last) filled row Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type global_restrict1 (size_type index1, size_type size1, size_type index2, size_type size2) { Chris@16: return basic_unit_lower::global_mutable_restrict1(index1, size1, index2, size2); Chris@16: } Chris@16: // return an index between the first and (1+last) filled column Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type global_restrict2 (size_type index1, size_type size1, size_type index2, size_type size2) { Chris@16: return basic_unit_lower::global_mutable_restrict2(index1, size1, index2, size2); Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: template Chris@16: struct basic_upper : public detail::transposed_structure > Chris@16: { Chris@16: typedef upper_tag triangular_type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct basic_unit_upper : public detail::transposed_structure > Chris@16: { Chris@16: typedef unit_upper_tag triangular_type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct basic_strict_upper : public detail::transposed_structure > Chris@16: { Chris@16: typedef strict_upper_tag triangular_type; Chris@16: }; Chris@16: Chris@16: Chris@16: }}} Chris@16: Chris@16: #endif