1 // Copyright John Maddock 2007.
2 // Use, modification and distribution are subject to the
3 // Boost Software License, Version 1.0. (See accompanying file
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6 #ifndef BOOST_MATH_TRUNC_HPP
7 #define BOOST_MATH_TRUNC_HPP
8
9 #ifdef _MSC_VER
10 #pragma once
11 #endif
12
13 #include <type_traits>
14 #include <boost/math/special_functions/math_fwd.hpp>
15 #include <boost/math/tools/config.hpp>
16 #include <boost/math/policies/error_handling.hpp>
17 #include <boost/math/special_functions/fpclassify.hpp>
18
19 namespace boost{ namespace math{ namespace detail{
20
21 template <class T, class Policy>
trunc(const T & v,const Policy & pol,const std::false_type &)22 inline typename tools::promote_args<T>::type trunc(const T& v, const Policy& pol, const std::false_type&)
23 {
24 BOOST_MATH_STD_USING
25 typedef typename tools::promote_args<T>::type result_type;
26 if(!(boost::math::isfinite)(v))
27 return policies::raise_rounding_error("boost::math::trunc<%1%>(%1%)", 0, static_cast<result_type>(v), static_cast<result_type>(v), pol);
28 return (v >= 0) ? static_cast<result_type>(floor(v)) : static_cast<result_type>(ceil(v));
29 }
30
31 template <class T, class Policy>
trunc(const T & v,const Policy &,const std::true_type &)32 inline typename tools::promote_args<T>::type trunc(const T& v, const Policy&, const std::true_type&)
33 {
34 return v;
35 }
36
37 }
38
39 template <class T, class Policy>
trunc(const T & v,const Policy & pol)40 inline typename tools::promote_args<T>::type trunc(const T& v, const Policy& pol)
41 {
42 return detail::trunc(v, pol, std::integral_constant<bool, detail::is_integer_for_rounding<T>::value>());
43 }
44 template <class T>
trunc(const T & v)45 inline typename tools::promote_args<T>::type trunc(const T& v)
46 {
47 return trunc(v, policies::policy<>());
48 }
49 //
50 // The following functions will not compile unless T has an
51 // implicit conversion to the integer types. For user-defined
52 // number types this will likely not be the case. In that case
53 // these functions should either be specialized for the UDT in
54 // question, or else overloads should be placed in the same
55 // namespace as the UDT: these will then be found via argument
56 // dependent lookup. See our concept archetypes for examples.
57 //
58 // Non-standard numeric limits syntax "(std::numeric_limits<int>::max)()"
59 // is to avoid macro substiution from MSVC
60 // https://stackoverflow.com/questions/27442885/syntax-error-with-stdnumeric-limitsmax
61 //
62 template <class T, class Policy>
itrunc(const T & v,const Policy & pol)63 inline int itrunc(const T& v, const Policy& pol)
64 {
65 BOOST_MATH_STD_USING
66 typedef typename tools::promote_args<T>::type result_type;
67 result_type r = boost::math::trunc(v, pol);
68 if(r > static_cast<result_type>((std::numeric_limits<int>::max)()) || r < static_cast<result_type>((std::numeric_limits<int>::min)()))
69 return static_cast<int>(policies::raise_rounding_error("boost::math::itrunc<%1%>(%1%)", 0, static_cast<result_type>(v), 0, pol));
70 return static_cast<int>(r);
71 }
72 template <class T>
itrunc(const T & v)73 inline int itrunc(const T& v)
74 {
75 return itrunc(v, policies::policy<>());
76 }
77
78 template <class T, class Policy>
ltrunc(const T & v,const Policy & pol)79 inline long ltrunc(const T& v, const Policy& pol)
80 {
81 BOOST_MATH_STD_USING
82 typedef typename tools::promote_args<T>::type result_type;
83 result_type r = boost::math::trunc(v, pol);
84 if(r > static_cast<result_type>((std::numeric_limits<long>::max)()) || r < static_cast<result_type>((std::numeric_limits<long>::min)()))
85 return static_cast<long>(policies::raise_rounding_error("boost::math::ltrunc<%1%>(%1%)", 0, static_cast<result_type>(v), 0L, pol));
86 return static_cast<long>(r);
87 }
88 template <class T>
ltrunc(const T & v)89 inline long ltrunc(const T& v)
90 {
91 return ltrunc(v, policies::policy<>());
92 }
93
94 template <class T, class Policy>
lltrunc(const T & v,const Policy & pol)95 inline long long lltrunc(const T& v, const Policy& pol)
96 {
97 BOOST_MATH_STD_USING
98 typedef typename tools::promote_args<T>::type result_type;
99 result_type r = boost::math::trunc(v, pol);
100 if(r > static_cast<result_type>((std::numeric_limits<long long>::max)()) ||
101 r < static_cast<result_type>((std::numeric_limits<long long>::min)()))
102 {
103 return static_cast<long long>(policies::raise_rounding_error("boost::math::lltrunc<%1%>(%1%)", 0, v, static_cast<long long>(0), pol));
104 }
105 return static_cast<long long>(r);
106 }
107 template <class T>
lltrunc(const T & v)108 inline long long lltrunc(const T& v)
109 {
110 return lltrunc(v, policies::policy<>());
111 }
112
113 template <class T, class Policy>
114 inline typename std::enable_if<std::is_constructible<int, T>::value, int>::type
iconvert(const T & v,const Policy &)115 iconvert(const T& v, const Policy&)
116 {
117 return static_cast<int>(v);
118 }
119
120 template <class T, class Policy>
121 inline typename std::enable_if<!std::is_constructible<int, T>::value, int>::type
iconvert(const T & v,const Policy & pol)122 iconvert(const T& v, const Policy& pol)
123 {
124 using boost::math::itrunc;
125 return itrunc(v, pol);
126 }
127
128 template <class T, class Policy>
129 inline typename std::enable_if<std::is_constructible<long, T>::value, long>::type
lconvert(const T & v,const Policy &)130 lconvert(const T& v, const Policy&)
131 {
132 return static_cast<long>(v);
133 }
134
135 template <class T, class Policy>
136 inline typename std::enable_if<!std::is_constructible<long, T>::value, long>::type
lconvert(const T & v,const Policy & pol)137 lconvert(const T& v, const Policy& pol)
138 {
139 using boost::math::ltrunc;
140 return ltrunc(v, pol);
141 }
142
143 template <class T, class Policy>
144 inline typename std::enable_if<std::is_constructible<long long, T>::value, long long>::type
llconvertert(const T & v,const Policy &)145 llconvertert(const T& v, const Policy&)
146 {
147 return static_cast<long long>(v);
148 }
149
150 template <class T, class Policy>
151 inline typename std::enable_if<!std::is_constructible<long long, T>::value, long long>::type
llconvertert(const T & v,const Policy & pol)152 llconvertert(const T& v, const Policy& pol)
153 {
154 using boost::math::lltrunc;
155 return lltrunc(v, pol);
156 }
157
158 }} // namespaces
159
160 #endif // BOOST_MATH_TRUNC_HPP
161