Chris@16: // Boost.Geometry (aka GGL, Generic Geometry Library) Chris@16: Chris@16: // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. Chris@16: // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. Chris@16: // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. Chris@16: Chris@101: // This file was modified by Oracle on 2014. Chris@101: // Modifications copyright (c) 2014 Oracle and/or its affiliates. Chris@101: Chris@101: // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle Chris@101: Chris@16: // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library Chris@16: // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. Chris@16: Chris@16: // Use, modification and distribution is subject to the Boost Software License, Chris@16: // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP Chris@16: #define BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: Chris@16: namespace boost { namespace geometry Chris@16: { Chris@16: Chris@16: #ifndef DOXYGEN_NO_DETAIL Chris@16: Chris@16: namespace detail { namespace select_most_precise Chris@16: { Chris@16: Chris@16: Chris@16: // At least one of the types is non-fundamental. Take that one. Chris@16: // if both are non-fundamental, the type-to-be-selected Chris@16: // is unknown, it should be defined by explicit specialization. Chris@16: template Chris@16: struct select_non_fundamental Chris@16: { Chris@16: typedef T1 type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct select_non_fundamental Chris@16: { Chris@16: typedef T2 type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct select_non_fundamental Chris@16: { Chris@16: typedef T1 type; Chris@16: }; Chris@16: Chris@16: Chris@16: // Selection of largest type (e.g. int of Chris@16: // It defaults takes the first one, if second is larger, take the second one Chris@16: template Chris@16: struct select_largest Chris@16: { Chris@16: typedef T1 type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct select_largest Chris@16: { Chris@16: typedef T2 type; Chris@16: }; Chris@16: Chris@16: Chris@16: Chris@16: // Selection of floating point and specializations: Chris@16: // both FP or both !FP does never occur... Chris@16: template Chris@16: struct select_floating_point Chris@16: { Chris@16: typedef char type; Chris@16: }; Chris@16: Chris@16: Chris@16: // ... so if ONE but not both of these types is floating point, take that one Chris@16: template Chris@16: struct select_floating_point Chris@16: { Chris@16: typedef T1 type; Chris@16: }; Chris@16: Chris@16: Chris@16: template Chris@16: struct select_floating_point Chris@16: { Chris@16: typedef T2 type; Chris@16: }; Chris@16: Chris@16: Chris@16: }} // namespace detail::select_most_precise Chris@16: #endif // DOXYGEN_NO_DETAIL Chris@16: Chris@16: Chris@16: /*! Chris@16: \brief Meta-function to select, of two types, the most accurate type for Chris@16: calculations Chris@16: \ingroup utility Chris@16: \details select_most_precise classes, compares two types on compile time. Chris@16: For example, if an addition must be done with a double and an integer, the Chris@16: result must be a double. Chris@16: If both types are integer, the result can be an integer. Chris@16: \note It is different from the "promote" class, already in boost. That Chris@16: class promotes e.g. a (one) float to a double. This class selects a Chris@16: type from two types. It takes the most accurate, but does not promote Chris@16: afterwards. Chris@16: \note This traits class is completely independant from GGL and might be a Chris@16: separate addition to Boost Chris@16: \note If the input is a non-fundamental type, it might be a calculation Chris@16: type such as a GMP-value or another high precision value. Therefore, Chris@16: if one is non-fundamental, that one is chosen. Chris@16: \note If both types are non-fundamental, the result is indeterminate and Chris@16: currently the first one is chosen. Chris@16: */ Chris@101: template Chris@101: struct select_most_precise Chris@101: { Chris@101: typedef typename select_most_precise Chris@101: < Chris@101: typename select_most_precise::type, Chris@101: T3 Chris@101: >::type type; Chris@101: }; Chris@101: Chris@16: template Chris@101: struct select_most_precise Chris@16: { Chris@16: static const bool second_larger = sizeof(T2) > sizeof(T1); Chris@16: static const bool one_not_fundamental = ! Chris@16: (boost::is_fundamental::type::value Chris@16: && boost::is_fundamental::type::value); Chris@16: Chris@16: static const bool both_same = Chris@16: boost::is_floating_point::type::value Chris@16: == boost::is_floating_point::type::value; Chris@16: Chris@16: typedef typename boost::mpl::if_c Chris@16: < Chris@16: one_not_fundamental, Chris@16: typename detail::select_most_precise::select_non_fundamental Chris@16: < Chris@16: boost::is_fundamental::type::value, Chris@16: boost::is_fundamental::type::value, Chris@16: T1, Chris@16: T2 Chris@16: >::type, Chris@16: typename boost::mpl::if_c Chris@16: < Chris@16: both_same, Chris@16: typename detail::select_most_precise::select_largest Chris@16: < Chris@16: second_larger, Chris@16: T1, Chris@16: T2 Chris@16: >::type, Chris@16: typename detail::select_most_precise::select_floating_point Chris@16: < Chris@16: boost::is_floating_point::type::value, Chris@16: boost::is_floating_point::type::value, Chris@16: T1, Chris@16: T2 Chris@16: >::type Chris@16: >::type Chris@16: >::type type; Chris@16: }; Chris@16: Chris@101: template Chris@101: struct select_most_precise Chris@101: { Chris@101: typedef T1 type; Chris@101: }; Chris@16: Chris@16: }} // namespace boost::geometry Chris@16: Chris@16: #endif // BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP