blob: 2ac0de87d983851d5167a394ab0bba06f6b8879d [file] [log] [blame]
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2012 Bruno Lalande, Paris, France.
// Copyright (c) 2012 Mateusz Loskot, London, UK.
// 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_CALCULATION_TYPE_HPP
#define BOOST_GEOMETRY_UTIL_CALCULATION_TYPE_HPP
#include <boost/config.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
namespace util
{
namespace detail
{
struct default_integral
{
#ifdef BOOST_HAS_LONG_LONG
typedef boost::long_long_type type;
#else
typedef int type;
#endif
};
/*!
\details Selects the most appropriate:
- if calculation type is specified (not void), that one is used
- else if type is non-fundamental (user defined e.g. ttmath), that one
- else if type is floating point, the specified default FP is used
- else it is integral and the specified default integral is used
*/
template
<
typename Type,
typename CalculationType,
typename DefaultFloatingPointCalculationType,
typename DefaultIntegralCalculationType
>
struct calculation_type
{
BOOST_STATIC_ASSERT((
boost::is_fundamental
<
DefaultFloatingPointCalculationType
>::type::value
));
BOOST_STATIC_ASSERT((
boost::is_fundamental
<
DefaultIntegralCalculationType
>::type::value
));
typedef typename boost::mpl::if_
<
boost::is_void<CalculationType>,
typename boost::mpl::if_
<
boost::is_floating_point<Type>,
typename select_most_precise
<
DefaultFloatingPointCalculationType,
Type
>::type,
typename select_most_precise
<
DefaultIntegralCalculationType,
Type
>::type
>::type,
CalculationType
>::type type;
};
} // namespace detail
namespace calculation_type
{
namespace geometric
{
template
<
typename Geometry,
typename CalculationType,
typename DefaultFloatingPointCalculationType = double,
typename DefaultIntegralCalculationType = detail::default_integral::type
>
struct unary
{
typedef typename detail::calculation_type
<
typename geometry::coordinate_type<Geometry>::type,
CalculationType,
DefaultFloatingPointCalculationType,
DefaultIntegralCalculationType
>::type type;
};
template
<
typename Geometry1,
typename Geometry2,
typename CalculationType,
typename DefaultFloatingPointCalculationType = double,
typename DefaultIntegralCalculationType = detail::default_integral::type
>
struct binary
{
typedef typename detail::calculation_type
<
typename select_coordinate_type<Geometry1, Geometry2>::type,
CalculationType,
DefaultFloatingPointCalculationType,
DefaultIntegralCalculationType
>::type type;
};
/*!
\brief calculation type (ternary, for three geometry types)
*/
template
<
typename Geometry1,
typename Geometry2,
typename Geometry3,
typename CalculationType,
typename DefaultFloatingPointCalculationType = double,
typename DefaultIntegralCalculationType = detail::default_integral::type
>
struct ternary
{
typedef typename detail::calculation_type
<
typename select_most_precise
<
typename coordinate_type<Geometry1>::type,
typename select_coordinate_type
<
Geometry2,
Geometry3
>::type
>::type,
CalculationType,
DefaultFloatingPointCalculationType,
DefaultIntegralCalculationType
>::type type;
};
}} // namespace calculation_type::geometric
} // namespace util
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_CALCULATION_TYPE_HPP