williamr@2: // © Copyright Fernando Luis Cacciola Carballal 2000-2004 williamr@2: // Use, modification, and distribution is subject to the Boost Software williamr@2: // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at williamr@2: // http://www.boost.org/LICENSE_1_0.txt) williamr@2: williamr@2: // See library home page at http://www.boost.org/libs/numeric/conversion williamr@2: // williamr@2: // Contact the author at: fernando_cacciola@hotmail.com williamr@2: // williamr@2: #ifndef BOOST_NUMERIC_CONVERSION_DETAIL_IS_SUBRANGED_FLC_12NOV2002_HPP williamr@2: #define BOOST_NUMERIC_CONVERSION_DETAIL_IS_SUBRANGED_FLC_12NOV2002_HPP williamr@2: williamr@2: #include "boost/config.hpp" williamr@2: #include "boost/limits.hpp" williamr@2: williamr@2: #include "boost/mpl/int.hpp" williamr@2: #include "boost/mpl/multiplies.hpp" williamr@2: #include "boost/mpl/less.hpp" williamr@2: #include "boost/mpl/equal_to.hpp" williamr@2: williamr@2: #include "boost/type_traits/is_same.hpp" williamr@2: williamr@2: #include "boost/numeric/conversion/detail/meta.hpp" williamr@2: #include "boost/numeric/conversion/detail/int_float_mixture.hpp" williamr@2: #include "boost/numeric/conversion/detail/sign_mixture.hpp" williamr@2: #include "boost/numeric/conversion/detail/udt_builtin_mixture.hpp" williamr@2: williamr@2: namespace boost { namespace numeric { namespace convdetail williamr@2: { williamr@2: //--------------------------------------------------------------- williamr@2: // Implementations of the compile time predicate "T is subranged" williamr@2: //--------------------------------------------------------------- williamr@2: williamr@2: // for integral to integral conversions williamr@2: template williamr@2: struct subranged_Sig2Unsig williamr@2: { williamr@2: // Signed to unsigned conversions are 'subranged' because of possible loose williamr@2: // of negative values. williamr@2: typedef mpl::true_ type ; williamr@2: } ; williamr@2: williamr@2: // for unsigned integral to signed integral conversions williamr@2: template williamr@2: struct subranged_Unsig2Sig williamr@2: { williamr@2: // IMPORTANT NOTE: williamr@2: // williamr@2: // This code assumes that signed/unsigned integral values are represented williamr@2: // such that: williamr@2: // williamr@2: // numeric_limits::digits + 1 == numeric_limits::digits williamr@2: // williamr@2: // The '+1' is required since numeric_limits<>::digits gives 1 bit less for signed integral types. williamr@2: // williamr@2: // This fact is used by the following logic: williamr@2: // williamr@2: // if ( (numeric_limits::digits+1) < (2*numeric_limits::digits) ) williamr@2: // then the conversion is subranged. williamr@2: // williamr@2: williamr@2: typedef mpl::int_< ::std::numeric_limits::digits > S_digits ; williamr@2: typedef mpl::int_< ::std::numeric_limits::digits > T_digits ; williamr@2: williamr@2: // T is signed, so take digits+1 williamr@2: typedef typename T_digits::next u_T_digits ; williamr@2: williamr@2: typedef mpl::int_<2> Two ; williamr@2: williamr@2: typedef typename mpl::multiplies::type S_digits_times_2 ; williamr@2: williamr@2: typedef typename mpl::less::type type ; williamr@2: } ; williamr@2: williamr@2: // for integral to integral conversions of the same sign. williamr@2: template williamr@2: struct subranged_SameSign williamr@2: { williamr@2: // An integral conversion of the same sign is subranged if digits(T) < digits(S). williamr@2: williamr@2: typedef mpl::int_< ::std::numeric_limits::digits > S_digits ; williamr@2: typedef mpl::int_< ::std::numeric_limits::digits > T_digits ; williamr@2: williamr@2: typedef typename mpl::less::type type ; williamr@2: } ; williamr@2: williamr@2: // for integral to float conversions williamr@2: template williamr@2: struct subranged_Int2Float williamr@2: { williamr@2: typedef mpl::false_ type ; williamr@2: } ; williamr@2: williamr@2: // for float to integral conversions williamr@2: template williamr@2: struct subranged_Float2Int williamr@2: { williamr@2: typedef mpl::true_ type ; williamr@2: } ; williamr@2: williamr@2: // for float to float conversions williamr@2: template williamr@2: struct subranged_Float2Float williamr@2: { williamr@2: // If both T and S are floats, williamr@2: // compare exponent bits and if they match, mantisa bits. williamr@2: williamr@2: typedef mpl::int_< ::std::numeric_limits::digits > S_mantisa ; williamr@2: typedef mpl::int_< ::std::numeric_limits::digits > T_mantisa ; williamr@2: williamr@2: typedef mpl::int_< ::std::numeric_limits::max_exponent > S_exponent ; williamr@2: typedef mpl::int_< ::std::numeric_limits::max_exponent > T_exponent ; williamr@2: williamr@2: typedef typename mpl::less::type T_smaller_exponent ; williamr@2: williamr@2: typedef typename mpl::equal_to::type equal_exponents ; williamr@2: williamr@2: typedef mpl::less T_smaller_mantisa ; williamr@2: williamr@2: typedef mpl::eval_if not_bigger_exponent_case ; williamr@2: williamr@2: typedef typename williamr@2: mpl::eval_if::type williamr@2: type ; williamr@2: } ; williamr@2: williamr@2: // for Udt to built-in conversions williamr@2: template williamr@2: struct subranged_Udt2BuiltIn williamr@2: { williamr@2: typedef mpl::true_ type ; williamr@2: } ; williamr@2: williamr@2: // for built-in to Udt conversions williamr@2: template williamr@2: struct subranged_BuiltIn2Udt williamr@2: { williamr@2: typedef mpl::false_ type ; williamr@2: } ; williamr@2: williamr@2: // for Udt to Udt conversions williamr@2: template williamr@2: struct subranged_Udt2Udt williamr@2: { williamr@2: typedef mpl::false_ type ; williamr@2: } ; williamr@2: williamr@2: //------------------------------------------------------------------- williamr@2: // Selectors for the implementations of the subranged predicate williamr@2: //------------------------------------------------------------------- williamr@2: williamr@2: template williamr@2: struct get_subranged_Int2Int williamr@2: { williamr@2: typedef subranged_SameSign Sig2Sig ; williamr@2: typedef subranged_Sig2Unsig Sig2Unsig ; williamr@2: typedef subranged_Unsig2Sig Unsig2Sig ; williamr@2: typedef Sig2Sig Unsig2Unsig ; williamr@2: williamr@2: typedef typename get_sign_mixture::type sign_mixture ; williamr@2: williamr@2: typedef typename williamr@2: for_sign_mixture::type williamr@2: type ; williamr@2: } ; williamr@2: williamr@2: template williamr@2: struct get_subranged_BuiltIn2BuiltIn williamr@2: { williamr@2: typedef get_subranged_Int2Int Int2IntQ ; williamr@2: williamr@2: typedef subranged_Int2Float Int2Float ; williamr@2: typedef subranged_Float2Int Float2Int ; williamr@2: typedef subranged_Float2Float Float2Float ; williamr@2: williamr@2: typedef mpl::identity Int2FloatQ ; williamr@2: typedef mpl::identity Float2IntQ ; williamr@2: typedef mpl::identity Float2FloatQ ; williamr@2: williamr@2: typedef typename get_int_float_mixture::type int_float_mixture ; williamr@2: williamr@2: typedef for_int_float_mixture for_ ; williamr@2: williamr@2: typedef typename for_::type selected ; williamr@2: williamr@2: typedef typename selected::type type ; williamr@2: } ; williamr@2: williamr@2: template williamr@2: struct get_subranged williamr@2: { williamr@2: typedef get_subranged_BuiltIn2BuiltIn BuiltIn2BuiltInQ ; williamr@2: williamr@2: typedef subranged_BuiltIn2Udt BuiltIn2Udt ; williamr@2: typedef subranged_Udt2BuiltIn Udt2BuiltIn ; williamr@2: typedef subranged_Udt2Udt Udt2Udt ; williamr@2: williamr@2: typedef mpl::identity BuiltIn2UdtQ ; williamr@2: typedef mpl::identity Udt2BuiltInQ ; williamr@2: typedef mpl::identity Udt2UdtQ ; williamr@2: williamr@2: typedef typename get_udt_builtin_mixture::type udt_builtin_mixture ; williamr@2: williamr@2: typedef typename williamr@2: for_udt_builtin_mixture::type williamr@2: selected ; williamr@2: williamr@2: typedef typename selected::type selected2 ; williamr@2: williamr@2: typedef typename selected2::type type ; williamr@2: } ; williamr@2: williamr@2: williamr@2: //------------------------------------------------------------------- williamr@2: // Top level implementation selector. williamr@2: //------------------------------------------------------------------- williamr@2: template williamr@2: struct get_is_subranged williamr@2: { williamr@2: typedef get_subranged non_trivial_case ; williamr@2: typedef mpl::identity trivial_case ; williamr@2: williamr@2: typedef is_same is_trivial ; williamr@2: williamr@2: typedef typename mpl::if_::type selected ; williamr@2: williamr@2: typedef typename selected::type type ; williamr@2: } ; williamr@2: williamr@2: } } } // namespace boost::numeric::convdetail williamr@2: williamr@2: #endif williamr@2: williamr@2: