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