sl@0: // sl@0: // Copyright (c) 2000-2002 sl@0: // Joerg Walter, Mathias Koch sl@0: // sl@0: // Permission to use, copy, modify, distribute and sell this software sl@0: // and its documentation for any purpose is hereby granted without fee, sl@0: // provided that the above copyright notice appear in all copies and sl@0: // that both that copyright notice and this permission notice appear sl@0: // in supporting documentation. The authors make no representations sl@0: // about the suitability of this software for any purpose. sl@0: // It is provided "as is" without express or implied warranty. sl@0: // sl@0: // The authors gratefully acknowledge the support of sl@0: // GeNeSys mbH & Co. KG in producing this work. sl@0: // sl@0: sl@0: #ifndef _BOOST_UBLAS_TRAITS_ sl@0: #define _BOOST_UBLAS_TRAITS_ sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: sl@0: namespace boost { namespace numeric { namespace ublas { sl@0: sl@0: // Use Joel de Guzman's return type deduction sl@0: // uBLAS assumes a common return type for all binary arithmetic operators sl@0: template sl@0: struct promote_traits { sl@0: typedef type_deduction_detail::base_result_of base_type; sl@0: static typename base_type::x_type x; sl@0: static typename base_type::y_type y; sl@0: static const std::size_t size = sizeof ( sl@0: type_deduction_detail::test< sl@0: typename base_type::x_type sl@0: , typename base_type::y_type sl@0: >(x + y) // Use x+y to stand of all the arithmetic actions sl@0: ); sl@0: sl@0: static const std::size_t index = (size / sizeof (char)) - 1; sl@0: typedef typename mpl::at_c< sl@0: typename base_type::types, index>::type id; sl@0: typedef typename id::type promote_type; sl@0: }; sl@0: sl@0: sl@0: // Type traits - generic numeric properties and functions sl@0: template sl@0: struct type_traits; sl@0: sl@0: // Define properties for a generic scalar type sl@0: template sl@0: struct scalar_traits { sl@0: typedef scalar_traits self_type; sl@0: typedef T value_type; sl@0: typedef const T &const_reference; sl@0: typedef T &reference; sl@0: sl@0: typedef T real_type; sl@0: typedef real_type precision_type; // we do not know what type has more precision then the real_type sl@0: sl@0: static const unsigned plus_complexity = 1; sl@0: static const unsigned multiplies_complexity = 1; sl@0: sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: real_type real (const_reference t) { sl@0: return t; sl@0: } sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: real_type imag (const_reference /*t*/) { sl@0: return 0; sl@0: } sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: value_type conj (const_reference t) { sl@0: return t; sl@0: } sl@0: sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: real_type type_abs (const_reference t) { sl@0: return std::abs (t); // must use explict std:: as bultin types are not in std namespace sl@0: } sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: value_type type_sqrt (const_reference t) { sl@0: // force a type conversion back to value_type for intgral types sl@0: return value_type (std::sqrt (t)); // must use explict std:: as bultin types are not in std namespace sl@0: } sl@0: sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: real_type norm_1 (const_reference t) { sl@0: return self_type::type_abs (t); sl@0: } sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: real_type norm_2 (const_reference t) { sl@0: return self_type::type_abs (t); sl@0: } sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: real_type norm_inf (const_reference t) { sl@0: return self_type::type_abs (t); sl@0: } sl@0: sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: bool equals (const_reference t1, const_reference t2) { sl@0: return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON * sl@0: (std::max) ((std::max) (self_type::norm_inf (t1), sl@0: self_type::norm_inf (t2)), sl@0: BOOST_UBLAS_TYPE_CHECK_MIN); sl@0: } sl@0: }; sl@0: sl@0: // Define default type traits, assume T is a scalar type sl@0: template sl@0: struct type_traits : scalar_traits { sl@0: typedef type_traits self_type; sl@0: typedef T value_type; sl@0: typedef const T &const_reference; sl@0: typedef T &reference; sl@0: sl@0: typedef T real_type; sl@0: typedef real_type precision_type; sl@0: static const unsigned multiplies_complexity = 1; sl@0: sl@0: }; sl@0: sl@0: // Define real type traits sl@0: template<> sl@0: struct type_traits : scalar_traits { sl@0: typedef type_traits self_type; sl@0: typedef float value_type; sl@0: typedef const value_type &const_reference; sl@0: typedef value_type &reference; sl@0: typedef value_type real_type; sl@0: typedef double precision_type; sl@0: }; sl@0: template<> sl@0: struct type_traits : scalar_traits { sl@0: typedef type_traits self_type; sl@0: typedef double value_type; sl@0: typedef const value_type &const_reference; sl@0: typedef value_type &reference; sl@0: typedef value_type real_type; sl@0: typedef long double precision_type; sl@0: }; sl@0: template<> sl@0: struct type_traits : scalar_traits { sl@0: typedef type_traits self_type; sl@0: typedef long double value_type; sl@0: typedef const value_type &const_reference; sl@0: typedef value_type &reference; sl@0: typedef value_type real_type; sl@0: typedef value_type precision_type; sl@0: }; sl@0: sl@0: // Define properties for a generic complex type sl@0: template sl@0: struct complex_traits { sl@0: typedef complex_traits self_type; sl@0: typedef T value_type; sl@0: typedef const T &const_reference; sl@0: typedef T &reference; sl@0: sl@0: typedef typename T::value_type real_type; sl@0: typedef real_type precision_type; // we do not know what type has more precision then the real_type sl@0: sl@0: static const unsigned plus_complexity = 2; sl@0: static const unsigned multiplies_complexity = 6; sl@0: sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: real_type real (const_reference t) { sl@0: return std::real (t); sl@0: } sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: real_type imag (const_reference t) { sl@0: return std::imag (t); sl@0: } sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: value_type conj (const_reference t) { sl@0: return std::conj (t); sl@0: } sl@0: sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: real_type type_abs (const_reference t) { sl@0: return abs (t); sl@0: } sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: value_type type_sqrt (const_reference t) { sl@0: return sqrt (t); sl@0: } sl@0: sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: real_type norm_1 (const_reference t) { sl@0: return type_traits::type_abs (self_type::real (t)) + sl@0: type_traits::type_abs (self_type::imag (t)); sl@0: } sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: real_type norm_2 (const_reference t) { sl@0: return self_type::type_abs (t); sl@0: } sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: real_type norm_inf (const_reference t) { sl@0: return (std::max) (type_traits::type_abs (self_type::real (t)), sl@0: type_traits::type_abs (self_type::imag (t))); sl@0: } sl@0: sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: bool equals (const_reference t1, const_reference t2) { sl@0: return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON * sl@0: (std::max) ((std::max) (self_type::norm_inf (t1), sl@0: self_type::norm_inf (t2)), sl@0: BOOST_UBLAS_TYPE_CHECK_MIN); sl@0: } sl@0: }; sl@0: sl@0: // Define complex type traits sl@0: template<> sl@0: struct type_traits > : complex_traits >{ sl@0: typedef type_traits > self_type; sl@0: typedef std::complex value_type; sl@0: typedef const value_type &const_reference; sl@0: typedef value_type &reference; sl@0: typedef float real_type; sl@0: typedef std::complex precision_type; sl@0: sl@0: }; sl@0: template<> sl@0: struct type_traits > : complex_traits >{ sl@0: typedef type_traits > self_type; sl@0: typedef std::complex value_type; sl@0: typedef const value_type &const_reference; sl@0: typedef value_type &reference; sl@0: typedef double real_type; sl@0: typedef std::complex precision_type; sl@0: }; sl@0: template<> sl@0: struct type_traits > : complex_traits > { sl@0: typedef type_traits > self_type; sl@0: typedef std::complex value_type; sl@0: typedef const value_type &const_reference; sl@0: typedef value_type &reference; sl@0: typedef long double real_type; sl@0: typedef value_type precision_type; sl@0: }; sl@0: sl@0: #ifdef BOOST_UBLAS_USE_INTERVAL sl@0: // Define properties for a generic scalar interval type sl@0: template sl@0: struct scalar_interval_type_traits : scalar_type_traits { sl@0: typedef scalar_interval_type_traits self_type; sl@0: typedef boost::numeric::interval value_type; sl@0: typedef const value_type &const_reference; sl@0: typedef value_type &reference; sl@0: typedef value_type real_type; sl@0: typedef real_type precision_type; // we do not know what type has more precision then the real_type sl@0: sl@0: static const unsigned plus_complexity = 1; sl@0: static const unsigned multiplies_complexity = 1; sl@0: sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: real_type type_abs (const_reference t) { sl@0: return abs (t); sl@0: } sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: value_type type_sqrt (const_reference t) { sl@0: return sqrt (t); sl@0: } sl@0: sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: real_type norm_1 (const_reference t) { sl@0: return self_type::type_abs (t); sl@0: } sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: real_type norm_2 (const_reference t) { sl@0: return self_type::type_abs (t); sl@0: } sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: real_type norm_inf (const_reference t) { sl@0: return self_type::type_abs (t); sl@0: } sl@0: sl@0: static sl@0: BOOST_UBLAS_INLINE sl@0: bool equals (const_reference t1, const_reference t2) { sl@0: return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON * sl@0: (std::max) ((std::max) (self_type::norm_inf (t1), sl@0: self_type::norm_inf (t2)), sl@0: BOOST_UBLAS_TYPE_CHECK_MIN); sl@0: } sl@0: }; sl@0: sl@0: // Define scalar interval type traits sl@0: template<> sl@0: struct type_traits > : scalar_interval_type_traits > { sl@0: typedef type_traits > self_type; sl@0: typedef boost::numeric::interval value_type; sl@0: typedef const value_type &const_reference; sl@0: typedef value_type &reference; sl@0: typedef value_type real_type; sl@0: typedef boost::numeric::interval precision_type; sl@0: sl@0: }; sl@0: template<> sl@0: struct type_traits > : scalar_interval_type_traits > { sl@0: typedef type_traits > self_type; sl@0: typedef boost::numeric::interval value_type; sl@0: typedef const value_type &const_reference; sl@0: typedef value_type &reference; sl@0: typedef value_type real_type; sl@0: typedef boost::numeric::interval precision_type; sl@0: }; sl@0: template<> sl@0: struct type_traits > : scalar_interval_type_traits > { sl@0: typedef type_traits > self_type; sl@0: typedef boost::numeric::interval value_type; sl@0: typedef const value_type &const_reference; sl@0: typedef value_type &reference; sl@0: typedef value_type real_type; sl@0: typedef value_type precision_type; sl@0: }; sl@0: sl@0: #endif sl@0: sl@0: sl@0: // Storage tags -- hierarchical definition of storage characteristics sl@0: sl@0: struct unknown_storage_tag {}; sl@0: struct sparse_proxy_tag: public unknown_storage_tag {}; sl@0: struct sparse_tag: public sparse_proxy_tag {}; sl@0: struct packed_proxy_tag: public sparse_proxy_tag {}; sl@0: struct packed_tag: public packed_proxy_tag {}; sl@0: struct dense_proxy_tag: public packed_proxy_tag {}; sl@0: struct dense_tag: public dense_proxy_tag {}; sl@0: sl@0: template sl@0: struct storage_restrict_traits { sl@0: typedef S1 storage_category; sl@0: }; sl@0: sl@0: template<> sl@0: struct storage_restrict_traits { sl@0: typedef sparse_proxy_tag storage_category; sl@0: }; sl@0: template<> sl@0: struct storage_restrict_traits { sl@0: typedef sparse_proxy_tag storage_category; sl@0: }; sl@0: template<> sl@0: struct storage_restrict_traits { sl@0: typedef sparse_proxy_tag storage_category; sl@0: }; sl@0: sl@0: template<> sl@0: struct storage_restrict_traits { sl@0: typedef packed_proxy_tag storage_category; sl@0: }; sl@0: template<> sl@0: struct storage_restrict_traits { sl@0: typedef packed_proxy_tag storage_category; sl@0: }; sl@0: template<> sl@0: struct storage_restrict_traits { sl@0: typedef sparse_proxy_tag storage_category; sl@0: }; sl@0: sl@0: template<> sl@0: struct storage_restrict_traits { sl@0: typedef sparse_proxy_tag storage_category; sl@0: }; sl@0: sl@0: template<> sl@0: struct storage_restrict_traits { sl@0: typedef dense_proxy_tag storage_category; sl@0: }; sl@0: template<> sl@0: struct storage_restrict_traits { sl@0: typedef packed_proxy_tag storage_category; sl@0: }; sl@0: template<> sl@0: struct storage_restrict_traits { sl@0: typedef sparse_proxy_tag storage_category; sl@0: }; sl@0: sl@0: template<> sl@0: struct storage_restrict_traits { sl@0: typedef packed_proxy_tag storage_category; sl@0: }; sl@0: template<> sl@0: struct storage_restrict_traits { sl@0: typedef sparse_proxy_tag storage_category; sl@0: }; sl@0: sl@0: sl@0: // Iterator tags -- hierarchical definition of storage characteristics sl@0: sl@0: struct sparse_bidirectional_iterator_tag : public std::bidirectional_iterator_tag {}; sl@0: struct packed_random_access_iterator_tag : public std::random_access_iterator_tag {}; sl@0: struct dense_random_access_iterator_tag : public packed_random_access_iterator_tag {}; sl@0: sl@0: // Thanks to Kresimir Fresl for convincing Comeau with iterator_base_traits ;-) sl@0: template sl@0: struct iterator_base_traits {}; sl@0: sl@0: template<> sl@0: struct iterator_base_traits { sl@0: template sl@0: struct iterator_base { sl@0: typedef forward_iterator_base type; sl@0: }; sl@0: }; sl@0: sl@0: template<> sl@0: struct iterator_base_traits { sl@0: template sl@0: struct iterator_base { sl@0: typedef bidirectional_iterator_base type; sl@0: }; sl@0: }; sl@0: template<> sl@0: struct iterator_base_traits { sl@0: template sl@0: struct iterator_base { sl@0: typedef bidirectional_iterator_base type; sl@0: }; sl@0: }; sl@0: sl@0: template<> sl@0: struct iterator_base_traits { sl@0: template sl@0: struct iterator_base { sl@0: typedef random_access_iterator_base type; sl@0: }; sl@0: }; sl@0: template<> sl@0: struct iterator_base_traits { sl@0: template sl@0: struct iterator_base { sl@0: typedef random_access_iterator_base type; sl@0: }; sl@0: }; sl@0: template<> sl@0: struct iterator_base_traits { sl@0: template sl@0: struct iterator_base { sl@0: typedef random_access_iterator_base type; sl@0: }; sl@0: }; sl@0: sl@0: template sl@0: struct iterator_restrict_traits { sl@0: typedef I1 iterator_category; sl@0: }; sl@0: sl@0: template<> sl@0: struct iterator_restrict_traits { sl@0: typedef sparse_bidirectional_iterator_tag iterator_category; sl@0: }; sl@0: template<> sl@0: struct iterator_restrict_traits { sl@0: typedef sparse_bidirectional_iterator_tag iterator_category; sl@0: }; sl@0: sl@0: template<> sl@0: struct iterator_restrict_traits { sl@0: typedef sparse_bidirectional_iterator_tag iterator_category; sl@0: }; sl@0: template<> sl@0: struct iterator_restrict_traits { sl@0: typedef sparse_bidirectional_iterator_tag iterator_category; sl@0: }; sl@0: sl@0: template<> sl@0: struct iterator_restrict_traits { sl@0: typedef packed_random_access_iterator_tag iterator_category; sl@0: }; sl@0: template<> sl@0: struct iterator_restrict_traits { sl@0: typedef packed_random_access_iterator_tag iterator_category; sl@0: }; sl@0: sl@0: template sl@0: BOOST_UBLAS_INLINE sl@0: void increment (I &it, const I &it_end, typename I::difference_type compare, packed_random_access_iterator_tag) { sl@0: it += (std::min) (compare, it_end - it); sl@0: } sl@0: template sl@0: BOOST_UBLAS_INLINE sl@0: void increment (I &it, const I &/* it_end */, typename I::difference_type /* compare */, sparse_bidirectional_iterator_tag) { sl@0: ++ it; sl@0: } sl@0: template sl@0: BOOST_UBLAS_INLINE sl@0: void increment (I &it, const I &it_end, typename I::difference_type compare) { sl@0: increment (it, it_end, compare, typename I::iterator_category ()); sl@0: } sl@0: sl@0: template sl@0: BOOST_UBLAS_INLINE sl@0: void increment (I &it, const I &it_end) { sl@0: #if BOOST_UBLAS_TYPE_CHECK sl@0: I cit (it); sl@0: while (cit != it_end) { sl@0: BOOST_UBLAS_CHECK (*cit == typename I::value_type/*zero*/(), internal_logic ()); sl@0: ++ cit; sl@0: } sl@0: #endif sl@0: it = it_end; sl@0: } sl@0: sl@0: }}} sl@0: sl@0: #endif