1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 
3 // Copyright (c) 2012 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2012 Bruno Lalande, Paris, France.
5 // Copyright (c) 2012 Mateusz Loskot, London, UK.
6 
7 // Use, modification and distribution is subject to the Boost Software License,
8 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10 
11 #ifndef BOOST_GEOMETRY_UTIL_CALCULATION_TYPE_HPP
12 #define BOOST_GEOMETRY_UTIL_CALCULATION_TYPE_HPP
13 
14 #include <boost/config.hpp>
15 #include <boost/mpl/if.hpp>
16 #include <boost/type_traits/is_floating_point.hpp>
17 #include <boost/type_traits/is_fundamental.hpp>
18 #include <boost/type_traits/is_void.hpp>
19 
20 #include <boost/geometry/util/select_coordinate_type.hpp>
21 #include <boost/geometry/util/select_most_precise.hpp>
22 
23 
24 namespace boost { namespace geometry
25 {
26 
27 namespace util
28 {
29 
30 namespace detail
31 {
32 
33 struct default_integral
34 {
35 #ifdef BOOST_HAS_LONG_LONG
36     typedef boost::long_long_type type;
37 #else
38     typedef int type;
39 #endif
40 };
41 
42 /*!
43 \details Selects the most appropriate:
44     - if calculation type is specified (not void), that one is used
45     - else if type is non-fundamental (user defined e.g. ttmath), that one
46     - else if type is floating point, the specified default FP is used
47     - else it is integral and the specified default integral is used
48  */
49 template
50 <
51     typename Type,
52     typename CalculationType,
53     typename DefaultFloatingPointCalculationType,
54     typename DefaultIntegralCalculationType
55 >
56 struct calculation_type
57 {
58     BOOST_STATIC_ASSERT((
59         boost::is_fundamental
60             <
61                 DefaultFloatingPointCalculationType
62             >::type::value
63         ));
64     BOOST_STATIC_ASSERT((
65         boost::is_fundamental
66             <
67                 DefaultIntegralCalculationType
68             >::type::value
69         ));
70 
71 
72     typedef typename boost::mpl::if_
73         <
74             boost::is_void<CalculationType>,
75             typename boost::mpl::if_
76                 <
77                     boost::is_floating_point<Type>,
78                     typename select_most_precise
79                         <
80                             DefaultFloatingPointCalculationType,
81                             Type
82                         >::type,
83                     typename select_most_precise
84                         <
85                             DefaultIntegralCalculationType,
86                             Type
87                         >::type
88                 >::type,
89             CalculationType
90         >::type type;
91 };
92 
93 } // namespace detail
94 
95 
96 namespace calculation_type
97 {
98 
99 namespace geometric
100 {
101 
102 template
103 <
104     typename Geometry,
105     typename CalculationType,
106     typename DefaultFloatingPointCalculationType = double,
107     typename DefaultIntegralCalculationType = detail::default_integral::type
108 >
109 struct unary
110 {
111     typedef typename detail::calculation_type
112         <
113             typename geometry::coordinate_type<Geometry>::type,
114             CalculationType,
115             DefaultFloatingPointCalculationType,
116             DefaultIntegralCalculationType
117         >::type type;
118 };
119 
120 template
121 <
122     typename Geometry1,
123     typename Geometry2,
124     typename CalculationType,
125     typename DefaultFloatingPointCalculationType = double,
126     typename DefaultIntegralCalculationType = detail::default_integral::type
127 >
128 struct binary
129 {
130     typedef typename detail::calculation_type
131         <
132             typename select_coordinate_type<Geometry1, Geometry2>::type,
133             CalculationType,
134             DefaultFloatingPointCalculationType,
135             DefaultIntegralCalculationType
136         >::type type;
137 };
138 
139 
140 /*!
141 \brief calculation type (ternary, for three geometry types)
142  */
143 template
144 <
145     typename Geometry1,
146     typename Geometry2,
147     typename Geometry3,
148     typename CalculationType,
149     typename DefaultFloatingPointCalculationType = double,
150     typename DefaultIntegralCalculationType = detail::default_integral::type
151 >
152 struct ternary
153 {
154     typedef typename detail::calculation_type
155         <
156             typename select_most_precise
157                 <
158                     typename coordinate_type<Geometry1>::type,
159                     typename select_coordinate_type
160                         <
161                             Geometry2,
162                             Geometry3
163                         >::type
164                 >::type,
165             CalculationType,
166             DefaultFloatingPointCalculationType,
167             DefaultIntegralCalculationType
168         >::type type;
169 };
170 
171 }} // namespace calculation_type::geometric
172 
173 } // namespace util
174 
175 }} // namespace boost::geometry
176 
177 
178 #endif // BOOST_GEOMETRY_UTIL_CALCULATION_TYPE_HPP
179