Chris@16
|
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
|
Chris@16
|
2
|
Chris@101
|
3 // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
Chris@101
|
4 // Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
Chris@101
|
5 // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
Chris@101
|
6
|
Chris@101
|
7 // This file was modified by Oracle on 2014, 2015.
|
Chris@101
|
8 // Modifications copyright (c) 2014-2015, Oracle and/or its affiliates.
|
Chris@101
|
9
|
Chris@101
|
10 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
Chris@101
|
11 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
Chris@16
|
12
|
Chris@16
|
13 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
Chris@16
|
14 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
Chris@16
|
15
|
Chris@16
|
16 // Use, modification and distribution is subject to the Boost Software License,
|
Chris@16
|
17 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
18 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
19
|
Chris@16
|
20 #ifndef BOOST_GEOMETRY_UTIL_MATH_HPP
|
Chris@16
|
21 #define BOOST_GEOMETRY_UTIL_MATH_HPP
|
Chris@16
|
22
|
Chris@16
|
23 #include <cmath>
|
Chris@16
|
24 #include <limits>
|
Chris@16
|
25
|
Chris@101
|
26 #include <boost/core/ignore_unused.hpp>
|
Chris@101
|
27
|
Chris@16
|
28 #include <boost/math/constants/constants.hpp>
|
Chris@101
|
29 #ifdef BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
|
Chris@101
|
30 #include <boost/math/special_functions/fpclassify.hpp>
|
Chris@101
|
31 #endif // BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
|
Chris@101
|
32 #include <boost/math/special_functions/round.hpp>
|
Chris@101
|
33 #include <boost/numeric/conversion/cast.hpp>
|
Chris@101
|
34 #include <boost/type_traits/is_fundamental.hpp>
|
Chris@16
|
35
|
Chris@16
|
36 #include <boost/geometry/util/select_most_precise.hpp>
|
Chris@16
|
37
|
Chris@16
|
38 namespace boost { namespace geometry
|
Chris@16
|
39 {
|
Chris@16
|
40
|
Chris@16
|
41 namespace math
|
Chris@16
|
42 {
|
Chris@16
|
43
|
Chris@16
|
44 #ifndef DOXYGEN_NO_DETAIL
|
Chris@16
|
45 namespace detail
|
Chris@16
|
46 {
|
Chris@16
|
47
|
Chris@101
|
48 template <typename T>
|
Chris@101
|
49 inline T const& greatest(T const& v1, T const& v2)
|
Chris@101
|
50 {
|
Chris@101
|
51 return (std::max)(v1, v2);
|
Chris@101
|
52 }
|
Chris@16
|
53
|
Chris@101
|
54 template <typename T>
|
Chris@101
|
55 inline T const& greatest(T const& v1, T const& v2, T const& v3)
|
Chris@101
|
56 {
|
Chris@101
|
57 return (std::max)(greatest(v1, v2), v3);
|
Chris@101
|
58 }
|
Chris@101
|
59
|
Chris@101
|
60 template <typename T>
|
Chris@101
|
61 inline T const& greatest(T const& v1, T const& v2, T const& v3, T const& v4)
|
Chris@101
|
62 {
|
Chris@101
|
63 return (std::max)(greatest(v1, v2, v3), v4);
|
Chris@101
|
64 }
|
Chris@101
|
65
|
Chris@101
|
66 template <typename T>
|
Chris@101
|
67 inline T const& greatest(T const& v1, T const& v2, T const& v3, T const& v4, T const& v5)
|
Chris@101
|
68 {
|
Chris@101
|
69 return (std::max)(greatest(v1, v2, v3, v4), v5);
|
Chris@101
|
70 }
|
Chris@101
|
71
|
Chris@101
|
72
|
Chris@101
|
73 template <typename T,
|
Chris@101
|
74 bool IsFloatingPoint = boost::is_floating_point<T>::value>
|
Chris@101
|
75 struct abs
|
Chris@101
|
76 {
|
Chris@101
|
77 static inline T apply(T const& value)
|
Chris@101
|
78 {
|
Chris@101
|
79 T const zero = T();
|
Chris@101
|
80 return value < zero ? -value : value;
|
Chris@101
|
81 }
|
Chris@101
|
82 };
|
Chris@101
|
83
|
Chris@101
|
84 template <typename T>
|
Chris@101
|
85 struct abs<T, true>
|
Chris@101
|
86 {
|
Chris@101
|
87 static inline T apply(T const& value)
|
Chris@101
|
88 {
|
Chris@101
|
89 return fabs(value);
|
Chris@101
|
90 }
|
Chris@101
|
91 };
|
Chris@101
|
92
|
Chris@101
|
93
|
Chris@101
|
94 struct equals_default_policy
|
Chris@101
|
95 {
|
Chris@101
|
96 template <typename T>
|
Chris@101
|
97 static inline T apply(T const& a, T const& b)
|
Chris@101
|
98 {
|
Chris@101
|
99 // See http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.17
|
Chris@101
|
100 return greatest(abs<T>::apply(a), abs<T>::apply(b), T(1));
|
Chris@101
|
101 }
|
Chris@101
|
102 };
|
Chris@101
|
103
|
Chris@101
|
104 template <typename T,
|
Chris@101
|
105 bool IsFloatingPoint = boost::is_floating_point<T>::value>
|
Chris@101
|
106 struct equals_factor_policy
|
Chris@101
|
107 {
|
Chris@101
|
108 equals_factor_policy()
|
Chris@101
|
109 : factor(1) {}
|
Chris@101
|
110 explicit equals_factor_policy(T const& v)
|
Chris@101
|
111 : factor(greatest(abs<T>::apply(v), T(1)))
|
Chris@101
|
112 {}
|
Chris@101
|
113 equals_factor_policy(T const& v0, T const& v1, T const& v2, T const& v3)
|
Chris@101
|
114 : factor(greatest(abs<T>::apply(v0), abs<T>::apply(v1),
|
Chris@101
|
115 abs<T>::apply(v2), abs<T>::apply(v3),
|
Chris@101
|
116 T(1)))
|
Chris@101
|
117 {}
|
Chris@101
|
118
|
Chris@101
|
119 T const& apply(T const&, T const&) const
|
Chris@101
|
120 {
|
Chris@101
|
121 return factor;
|
Chris@101
|
122 }
|
Chris@101
|
123
|
Chris@101
|
124 T factor;
|
Chris@101
|
125 };
|
Chris@101
|
126
|
Chris@101
|
127 template <typename T>
|
Chris@101
|
128 struct equals_factor_policy<T, false>
|
Chris@101
|
129 {
|
Chris@101
|
130 equals_factor_policy() {}
|
Chris@101
|
131 explicit equals_factor_policy(T const&) {}
|
Chris@101
|
132 equals_factor_policy(T const& , T const& , T const& , T const& ) {}
|
Chris@101
|
133
|
Chris@101
|
134 static inline T apply(T const&, T const&)
|
Chris@101
|
135 {
|
Chris@101
|
136 return T(1);
|
Chris@101
|
137 }
|
Chris@101
|
138 };
|
Chris@101
|
139
|
Chris@101
|
140 template <typename Type,
|
Chris@101
|
141 bool IsFloatingPoint = boost::is_floating_point<Type>::value>
|
Chris@16
|
142 struct equals
|
Chris@16
|
143 {
|
Chris@101
|
144 template <typename Policy>
|
Chris@101
|
145 static inline bool apply(Type const& a, Type const& b, Policy const&)
|
Chris@16
|
146 {
|
Chris@16
|
147 return a == b;
|
Chris@16
|
148 }
|
Chris@16
|
149 };
|
Chris@16
|
150
|
Chris@16
|
151 template <typename Type>
|
Chris@16
|
152 struct equals<Type, true>
|
Chris@16
|
153 {
|
Chris@101
|
154 template <typename Policy>
|
Chris@101
|
155 static inline bool apply(Type const& a, Type const& b, Policy const& policy)
|
Chris@16
|
156 {
|
Chris@101
|
157 boost::ignore_unused(policy);
|
Chris@16
|
158
|
Chris@16
|
159 if (a == b)
|
Chris@16
|
160 {
|
Chris@16
|
161 return true;
|
Chris@16
|
162 }
|
Chris@16
|
163
|
Chris@101
|
164 return abs<Type>::apply(a - b) <= std::numeric_limits<Type>::epsilon() * policy.apply(a, b);
|
Chris@16
|
165 }
|
Chris@16
|
166 };
|
Chris@16
|
167
|
Chris@101
|
168 template <typename T1, typename T2, typename Policy>
|
Chris@101
|
169 inline bool equals_by_policy(T1 const& a, T2 const& b, Policy const& policy)
|
Chris@101
|
170 {
|
Chris@101
|
171 return detail::equals
|
Chris@101
|
172 <
|
Chris@101
|
173 typename select_most_precise<T1, T2>::type
|
Chris@101
|
174 >::apply(a, b, policy);
|
Chris@101
|
175 }
|
Chris@101
|
176
|
Chris@101
|
177 template <typename Type,
|
Chris@101
|
178 bool IsFloatingPoint = boost::is_floating_point<Type>::value>
|
Chris@16
|
179 struct smaller
|
Chris@16
|
180 {
|
Chris@16
|
181 static inline bool apply(Type const& a, Type const& b)
|
Chris@16
|
182 {
|
Chris@16
|
183 return a < b;
|
Chris@16
|
184 }
|
Chris@16
|
185 };
|
Chris@16
|
186
|
Chris@16
|
187 template <typename Type>
|
Chris@16
|
188 struct smaller<Type, true>
|
Chris@16
|
189 {
|
Chris@16
|
190 static inline bool apply(Type const& a, Type const& b)
|
Chris@16
|
191 {
|
Chris@101
|
192 if (equals<Type, true>::apply(a, b, equals_default_policy()))
|
Chris@16
|
193 {
|
Chris@16
|
194 return false;
|
Chris@16
|
195 }
|
Chris@16
|
196 return a < b;
|
Chris@16
|
197 }
|
Chris@16
|
198 };
|
Chris@16
|
199
|
Chris@16
|
200
|
Chris@101
|
201 template <typename Type,
|
Chris@101
|
202 bool IsFloatingPoint = boost::is_floating_point<Type>::value>
|
Chris@101
|
203 struct equals_with_epsilon
|
Chris@101
|
204 : public equals<Type, IsFloatingPoint>
|
Chris@101
|
205 {};
|
Chris@101
|
206
|
Chris@101
|
207 template
|
Chris@101
|
208 <
|
Chris@101
|
209 typename T,
|
Chris@101
|
210 bool IsFundemantal = boost::is_fundamental<T>::value /* false */
|
Chris@101
|
211 >
|
Chris@101
|
212 struct square_root
|
Chris@101
|
213 {
|
Chris@101
|
214 typedef T return_type;
|
Chris@101
|
215
|
Chris@101
|
216 static inline T apply(T const& value)
|
Chris@101
|
217 {
|
Chris@101
|
218 // for non-fundamental number types assume that sqrt is
|
Chris@101
|
219 // defined either:
|
Chris@101
|
220 // 1) at T's scope, or
|
Chris@101
|
221 // 2) at global scope, or
|
Chris@101
|
222 // 3) in namespace std
|
Chris@101
|
223 using ::sqrt;
|
Chris@101
|
224 using std::sqrt;
|
Chris@101
|
225
|
Chris@101
|
226 return sqrt(value);
|
Chris@101
|
227 }
|
Chris@101
|
228 };
|
Chris@101
|
229
|
Chris@101
|
230 template <typename FundamentalFP>
|
Chris@101
|
231 struct square_root_for_fundamental_fp
|
Chris@101
|
232 {
|
Chris@101
|
233 typedef FundamentalFP return_type;
|
Chris@101
|
234
|
Chris@101
|
235 static inline FundamentalFP apply(FundamentalFP const& value)
|
Chris@101
|
236 {
|
Chris@101
|
237 #ifdef BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
|
Chris@101
|
238 // This is a workaround for some 32-bit platforms.
|
Chris@101
|
239 // For some of those platforms it has been reported that
|
Chris@101
|
240 // std::sqrt(nan) and/or std::sqrt(-nan) returns a finite value.
|
Chris@101
|
241 // For those platforms we need to define the macro
|
Chris@101
|
242 // BOOST_GEOMETRY_SQRT_CHECK_FINITENESS so that the argument
|
Chris@101
|
243 // to std::sqrt is checked appropriately before passed to std::sqrt
|
Chris@101
|
244 if (boost::math::isfinite(value))
|
Chris@101
|
245 {
|
Chris@101
|
246 return std::sqrt(value);
|
Chris@101
|
247 }
|
Chris@101
|
248 else if (boost::math::isinf(value) && value < 0)
|
Chris@101
|
249 {
|
Chris@101
|
250 return -std::numeric_limits<FundamentalFP>::quiet_NaN();
|
Chris@101
|
251 }
|
Chris@101
|
252 return value;
|
Chris@101
|
253 #else
|
Chris@101
|
254 // for fundamental floating point numbers use std::sqrt
|
Chris@101
|
255 return std::sqrt(value);
|
Chris@101
|
256 #endif // BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
|
Chris@101
|
257 }
|
Chris@101
|
258 };
|
Chris@101
|
259
|
Chris@101
|
260 template <>
|
Chris@101
|
261 struct square_root<float, true>
|
Chris@101
|
262 : square_root_for_fundamental_fp<float>
|
Chris@101
|
263 {
|
Chris@101
|
264 };
|
Chris@101
|
265
|
Chris@101
|
266 template <>
|
Chris@101
|
267 struct square_root<double, true>
|
Chris@101
|
268 : square_root_for_fundamental_fp<double>
|
Chris@101
|
269 {
|
Chris@101
|
270 };
|
Chris@101
|
271
|
Chris@101
|
272 template <>
|
Chris@101
|
273 struct square_root<long double, true>
|
Chris@101
|
274 : square_root_for_fundamental_fp<long double>
|
Chris@101
|
275 {
|
Chris@101
|
276 };
|
Chris@101
|
277
|
Chris@101
|
278 template <typename T>
|
Chris@101
|
279 struct square_root<T, true>
|
Chris@101
|
280 {
|
Chris@101
|
281 typedef double return_type;
|
Chris@101
|
282
|
Chris@101
|
283 static inline double apply(T const& value)
|
Chris@101
|
284 {
|
Chris@101
|
285 // for all other fundamental number types use also std::sqrt
|
Chris@101
|
286 //
|
Chris@101
|
287 // Note: in C++98 the only other possibility is double;
|
Chris@101
|
288 // in C++11 there are also overloads for integral types;
|
Chris@101
|
289 // this specialization works for those as well.
|
Chris@101
|
290 return square_root_for_fundamental_fp
|
Chris@101
|
291 <
|
Chris@101
|
292 double
|
Chris@101
|
293 >::apply(boost::numeric_cast<double>(value));
|
Chris@101
|
294 }
|
Chris@101
|
295 };
|
Chris@16
|
296
|
Chris@16
|
297
|
Chris@16
|
298 /*!
|
Chris@16
|
299 \brief Short construct to enable partial specialization for PI, currently not possible in Math.
|
Chris@16
|
300 */
|
Chris@16
|
301 template <typename T>
|
Chris@16
|
302 struct define_pi
|
Chris@16
|
303 {
|
Chris@16
|
304 static inline T apply()
|
Chris@16
|
305 {
|
Chris@16
|
306 // Default calls Boost.Math
|
Chris@16
|
307 return boost::math::constants::pi<T>();
|
Chris@16
|
308 }
|
Chris@16
|
309 };
|
Chris@16
|
310
|
Chris@16
|
311 template <typename T>
|
Chris@16
|
312 struct relaxed_epsilon
|
Chris@16
|
313 {
|
Chris@16
|
314 static inline T apply(const T& factor)
|
Chris@16
|
315 {
|
Chris@16
|
316 return factor * std::numeric_limits<T>::epsilon();
|
Chris@16
|
317 }
|
Chris@16
|
318 };
|
Chris@16
|
319
|
Chris@101
|
320 // ItoF ItoI FtoF
|
Chris@101
|
321 template <typename Result, typename Source,
|
Chris@101
|
322 bool ResultIsInteger = std::numeric_limits<Result>::is_integer,
|
Chris@101
|
323 bool SourceIsInteger = std::numeric_limits<Source>::is_integer>
|
Chris@101
|
324 struct round
|
Chris@101
|
325 {
|
Chris@101
|
326 static inline Result apply(Source const& v)
|
Chris@101
|
327 {
|
Chris@101
|
328 return boost::numeric_cast<Result>(v);
|
Chris@101
|
329 }
|
Chris@101
|
330 };
|
Chris@101
|
331
|
Chris@101
|
332 // FtoI
|
Chris@101
|
333 template <typename Result, typename Source>
|
Chris@101
|
334 struct round<Result, Source, true, false>
|
Chris@101
|
335 {
|
Chris@101
|
336 static inline Result apply(Source const& v)
|
Chris@101
|
337 {
|
Chris@101
|
338 namespace bmp = boost::math::policies;
|
Chris@101
|
339 // ignore rounding errors for backward compatibility
|
Chris@101
|
340 typedef bmp::policy< bmp::rounding_error<bmp::ignore_error> > policy;
|
Chris@101
|
341 return boost::numeric_cast<Result>(boost::math::round(v, policy()));
|
Chris@101
|
342 }
|
Chris@101
|
343 };
|
Chris@16
|
344
|
Chris@16
|
345 } // namespace detail
|
Chris@16
|
346 #endif
|
Chris@16
|
347
|
Chris@16
|
348
|
Chris@16
|
349 template <typename T>
|
Chris@16
|
350 inline T pi() { return detail::define_pi<T>::apply(); }
|
Chris@16
|
351
|
Chris@16
|
352 template <typename T>
|
Chris@16
|
353 inline T relaxed_epsilon(T const& factor)
|
Chris@16
|
354 {
|
Chris@16
|
355 return detail::relaxed_epsilon<T>::apply(factor);
|
Chris@16
|
356 }
|
Chris@16
|
357
|
Chris@16
|
358
|
Chris@16
|
359 // Maybe replace this by boost equals or boost ublas numeric equals or so
|
Chris@16
|
360
|
Chris@16
|
361 /*!
|
Chris@16
|
362 \brief returns true if both arguments are equal.
|
Chris@16
|
363 \ingroup utility
|
Chris@16
|
364 \param a first argument
|
Chris@16
|
365 \param b second argument
|
Chris@16
|
366 \return true if a == b
|
Chris@16
|
367 \note If both a and b are of an integral type, comparison is done by ==.
|
Chris@16
|
368 If one of the types is floating point, comparison is done by abs and
|
Chris@16
|
369 comparing with epsilon. If one of the types is non-fundamental, it might
|
Chris@16
|
370 be a high-precision number and comparison is done using the == operator
|
Chris@16
|
371 of that class.
|
Chris@16
|
372 */
|
Chris@16
|
373
|
Chris@16
|
374 template <typename T1, typename T2>
|
Chris@16
|
375 inline bool equals(T1 const& a, T2 const& b)
|
Chris@16
|
376 {
|
Chris@16
|
377 return detail::equals
|
Chris@16
|
378 <
|
Chris@101
|
379 typename select_most_precise<T1, T2>::type
|
Chris@101
|
380 >::apply(a, b, detail::equals_default_policy());
|
Chris@16
|
381 }
|
Chris@16
|
382
|
Chris@16
|
383 template <typename T1, typename T2>
|
Chris@16
|
384 inline bool equals_with_epsilon(T1 const& a, T2 const& b)
|
Chris@16
|
385 {
|
Chris@16
|
386 return detail::equals_with_epsilon
|
Chris@16
|
387 <
|
Chris@101
|
388 typename select_most_precise<T1, T2>::type
|
Chris@101
|
389 >::apply(a, b, detail::equals_default_policy());
|
Chris@16
|
390 }
|
Chris@16
|
391
|
Chris@16
|
392 template <typename T1, typename T2>
|
Chris@16
|
393 inline bool smaller(T1 const& a, T2 const& b)
|
Chris@16
|
394 {
|
Chris@16
|
395 return detail::smaller
|
Chris@16
|
396 <
|
Chris@101
|
397 typename select_most_precise<T1, T2>::type
|
Chris@16
|
398 >::apply(a, b);
|
Chris@16
|
399 }
|
Chris@16
|
400
|
Chris@16
|
401 template <typename T1, typename T2>
|
Chris@16
|
402 inline bool larger(T1 const& a, T2 const& b)
|
Chris@16
|
403 {
|
Chris@16
|
404 return detail::smaller
|
Chris@16
|
405 <
|
Chris@101
|
406 typename select_most_precise<T1, T2>::type
|
Chris@16
|
407 >::apply(b, a);
|
Chris@16
|
408 }
|
Chris@16
|
409
|
Chris@16
|
410
|
Chris@16
|
411
|
Chris@16
|
412 double const d2r = geometry::math::pi<double>() / 180.0;
|
Chris@16
|
413 double const r2d = 1.0 / d2r;
|
Chris@16
|
414
|
Chris@16
|
415 /*!
|
Chris@16
|
416 \brief Calculates the haversine of an angle
|
Chris@16
|
417 \ingroup utility
|
Chris@16
|
418 \note See http://en.wikipedia.org/wiki/Haversine_formula
|
Chris@16
|
419 haversin(alpha) = sin2(alpha/2)
|
Chris@16
|
420 */
|
Chris@16
|
421 template <typename T>
|
Chris@16
|
422 inline T hav(T const& theta)
|
Chris@16
|
423 {
|
Chris@16
|
424 T const half = T(0.5);
|
Chris@16
|
425 T const sn = sin(half * theta);
|
Chris@16
|
426 return sn * sn;
|
Chris@16
|
427 }
|
Chris@16
|
428
|
Chris@16
|
429 /*!
|
Chris@16
|
430 \brief Short utility to return the square
|
Chris@16
|
431 \ingroup utility
|
Chris@16
|
432 \param value Value to calculate the square from
|
Chris@16
|
433 \return The squared value
|
Chris@16
|
434 */
|
Chris@16
|
435 template <typename T>
|
Chris@16
|
436 inline T sqr(T const& value)
|
Chris@16
|
437 {
|
Chris@16
|
438 return value * value;
|
Chris@16
|
439 }
|
Chris@16
|
440
|
Chris@16
|
441 /*!
|
Chris@101
|
442 \brief Short utility to return the square root
|
Chris@101
|
443 \ingroup utility
|
Chris@101
|
444 \param value Value to calculate the square root from
|
Chris@101
|
445 \return The square root value
|
Chris@101
|
446 */
|
Chris@101
|
447 template <typename T>
|
Chris@101
|
448 inline typename detail::square_root<T>::return_type
|
Chris@101
|
449 sqrt(T const& value)
|
Chris@101
|
450 {
|
Chris@101
|
451 return detail::square_root
|
Chris@101
|
452 <
|
Chris@101
|
453 T, boost::is_fundamental<T>::value
|
Chris@101
|
454 >::apply(value);
|
Chris@101
|
455 }
|
Chris@101
|
456
|
Chris@101
|
457 /*!
|
Chris@16
|
458 \brief Short utility to workaround gcc/clang problem that abs is converting to integer
|
Chris@16
|
459 and that older versions of MSVC does not support abs of long long...
|
Chris@16
|
460 \ingroup utility
|
Chris@16
|
461 */
|
Chris@16
|
462 template<typename T>
|
Chris@16
|
463 inline T abs(T const& value)
|
Chris@16
|
464 {
|
Chris@101
|
465 return detail::abs<T>::apply(value);
|
Chris@16
|
466 }
|
Chris@16
|
467
|
Chris@16
|
468 /*!
|
Chris@16
|
469 \brief Short utility to calculate the sign of a number: -1 (negative), 0 (zero), 1 (positive)
|
Chris@16
|
470 \ingroup utility
|
Chris@16
|
471 */
|
Chris@16
|
472 template <typename T>
|
Chris@101
|
473 static inline int sign(T const& value)
|
Chris@16
|
474 {
|
Chris@16
|
475 T const zero = T();
|
Chris@16
|
476 return value > zero ? 1 : value < zero ? -1 : 0;
|
Chris@16
|
477 }
|
Chris@16
|
478
|
Chris@101
|
479 /*!
|
Chris@101
|
480 \brief Short utility to calculate the rounded value of a number.
|
Chris@101
|
481 \ingroup utility
|
Chris@101
|
482 \note If the source T is NOT an integral type and Result is an integral type
|
Chris@101
|
483 the value is rounded towards the closest integral value. Otherwise it's
|
Chris@101
|
484 casted.
|
Chris@101
|
485 */
|
Chris@101
|
486 template <typename Result, typename T>
|
Chris@101
|
487 inline Result round(T const& v)
|
Chris@101
|
488 {
|
Chris@101
|
489 return detail::round<Result, T>::apply(v);
|
Chris@101
|
490 }
|
Chris@16
|
491
|
Chris@16
|
492 } // namespace math
|
Chris@16
|
493
|
Chris@16
|
494
|
Chris@16
|
495 }} // namespace boost::geometry
|
Chris@16
|
496
|
Chris@16
|
497 #endif // BOOST_GEOMETRY_UTIL_MATH_HPP
|