10 #if !defined(SG14_SAFE_INTEGER_H) 11 #define SG14_SAFE_INTEGER_H 1 13 #include <sg14/bits/number_base.h> 14 #include <sg14/fixed_point> 22 #define SG14_INTEGER_BIT_SHIFT_DEFINE(OP) \ 23 template <class LhsRep, class LhsOverflowTag, class RhsRep, class RhsOverflowTag> \ 24 constexpr auto operator OP (const safe_integer<LhsRep, LhsOverflowTag>& lhs, const safe_integer<RhsRep, RhsOverflowTag>& rhs) \ 25 -> safe_integer<LhsRep, LhsOverflowTag> { \ 26 return lhs.data() OP rhs.data(); } \ 28 template <class Lhs, class RhsRep, class RhsOverflowTag, _impl::enable_if_t<std::is_fundamental<Lhs>::value, int> dummy = 0> \ 29 constexpr auto operator OP (const Lhs& lhs, const safe_integer<RhsRep, RhsOverflowTag>& rhs) \ 31 return lhs OP rhs.data(); } \ 33 template <class LhsRep, class LhsOverflowTag, class Rhs, _impl::enable_if_t<std::is_fundamental<Rhs>::value, int> dummy = 0> \ 34 constexpr auto operator OP (const safe_integer<LhsRep, LhsOverflowTag>& lhs, const Rhs& rhs) \ 35 -> safe_integer<LhsRep, LhsOverflowTag> { \ 36 return safe_integer<LhsRep, LhsOverflowTag>(lhs.data() OP rhs); } 41 template<
class Rep,
class OverflowTag>
44 namespace _integer_impl {
49 struct is_safe_integer
53 template<
class Rep,
class OverflowTag>
54 struct is_safe_integer<safe_integer<Rep, OverflowTag>>
62 template<
class Lhs,
class Rhs>
63 struct are_integer_class_operands {
64 static constexpr
int integer_class = is_safe_integer<Lhs>::value + is_safe_integer<Rhs>::value;
65 static constexpr
int integer_or_float = _impl::is_integer_or_float<Lhs>::value + _impl::is_integer_or_float<Rhs>::value;
66 static constexpr
bool value = (integer_class >= 1) && (integer_or_float == 2);
72 template<
class,
class,
class =
void>
76 template<
class LhsRep,
class RhsRep,
class OverflowTag>
78 safe_integer<LhsRep, OverflowTag>,
79 safe_integer<RhsRep, OverflowTag>> {
80 using type = safe_integer<
81 typename std::common_type<LhsRep, RhsRep>::type,
87 template<
class LhsRep,
class LhsOverflowTag,
class RhsInteger>
89 safe_integer<LhsRep, LhsOverflowTag>, RhsInteger,
91 !_integer_impl::is_safe_integer<RhsInteger>::value && std::is_integral<RhsInteger>::value>> {
92 using type =
typename sg14::safe_integer<typename std::common_type<LhsRep, RhsInteger>::type, LhsOverflowTag>;
97 template<
class LhsRep,
class LhsOverflowTag,
class Float>
99 safe_integer<LhsRep, LhsOverflowTag>, Float,
100 _impl::enable_if_t<std::is_floating_point<Float>::value>> {
101 using type =
typename std::common_type<LhsRep, Float>::type;
105 template<
class Lhs,
class RhsRep,
class RhsOverflowTag>
106 struct common_type<Lhs, safe_integer<RhsRep, RhsOverflowTag>>
107 : common_type<safe_integer<RhsRep, RhsOverflowTag>, Lhs> {
116 template<
class Rep =
int,
class OverflowTag = throwing_overflow_tag>
117 class safe_integer :
public _impl::number_base<safe_integer<Rep, OverflowTag>, Rep> {
118 using _base = _impl::number_base<safe_integer<Rep, OverflowTag>, Rep>;
124 using overflow_tag = OverflowTag;
129 constexpr safe_integer() =
delete;
131 template<
class RhsRep,
class RhsOverflowTag>
132 constexpr safe_integer(
const safe_integer<RhsRep, RhsOverflowTag>& rhs)
133 :safe_integer(rhs.data())
137 template<class Rhs, _impl::enable_if_t<!_integer_impl::is_safe_integer<Rhs>::value,
int> dummy = 0>
138 constexpr safe_integer(
const Rhs& rhs)
139 :_base(convert<rep>(overflow_tag{}, rhs))
144 template<
class Integral, Integral Value,
int Digits,
int Exponent>
145 constexpr safe_integer(const_integer<Integral, Value, Digits, Exponent>)
146 : _base(static_cast<rep>(Value))
148 static_assert(Value <= std::numeric_limits<rep>::max(),
"initialization by out-of-range value");
149 static_assert(!std::numeric_limits<Integral>::is_signed || Value >= std::numeric_limits<rep>::lowest(),
"initialization by out-of-range value");
153 constexpr
explicit operator T()
const 155 return static_cast<T
>(_base::data());
163 template<
class Rep,
class OverflowTag>
164 struct get_rep<safe_integer<Rep, OverflowTag>> {
168 template<
class OldRep,
class OverflowTag,
class NewRep>
169 struct set_rep<safe_integer<OldRep, OverflowTag>, NewRep> {
170 using type = safe_integer<NewRep, OverflowTag>;
177 template<
class Rep,
class OverflowTag>
178 struct digits<safe_integer<Rep, OverflowTag>> : digits<Rep> {
181 template<
class Rep,
class OverflowTag, _digits_type MinNumBits>
182 struct set_digits<safe_integer<Rep, OverflowTag>, MinNumBits> {
183 using type = safe_integer<set_digits_t<Rep, MinNumBits>, OverflowTag>;
186 template<
class Rep,
class OverflowTag,
class Value>
187 struct from_value<safe_integer<Rep, OverflowTag>, Value> {
188 using type = safe_integer<Value, OverflowTag>;
191 template<
class Rep,
class OverflowTag>
192 struct scale<safe_integer<Rep, OverflowTag>> {
193 using value_type = safe_integer<Rep, OverflowTag>;
194 constexpr
auto operator()(
const value_type &i,
int base,
int exp)
const 195 -> decltype(_impl::to_rep(i) * _num_traits_impl::pow<value_type>(base, exp)) {
197 ? _impl::to_rep(i) / _num_traits_impl::pow<value_type>(base, -exp)
198 : _impl::to_rep(i) * _num_traits_impl::pow<value_type>(base, exp);
205 template<
class OverflowTag,
class Rep>
206 constexpr
auto make_safe_integer(Rep
const& value)
207 -> safe_integer<Rep, OverflowTag>
220 template<
class OverflowTag,
class OperatorTag,
class LhsRep,
class RhsRep,
class = enable_if_t<OperatorTag::is_arithmetic>>
221 constexpr
auto operate_common_tag(
224 const safe_integer<LhsRep, OverflowTag>& lhs,
225 const safe_integer<RhsRep, OverflowTag>& rhs)
226 -> decltype(make_safe_integer<OverflowTag>(_overflow_impl::operate<OverflowTag, OperatorTag>()(lhs.data(), rhs.data())))
228 return make_safe_integer<OverflowTag>(_overflow_impl::operate<OverflowTag, OperatorTag>()(lhs.data(), rhs.data()));
232 template<
class OverflowTag,
class OperatorTag,
class LhsRep,
class RhsRep,
class = enable_if_t<OperatorTag::is_comparison>>
233 constexpr
auto operate_common_tag(
236 const safe_integer<LhsRep, OverflowTag>& lhs,
237 const safe_integer<RhsRep, OverflowTag>& rhs)
238 -> decltype(_overflow_impl::operate<OverflowTag, OperatorTag>()(lhs.data(), rhs.data()))
240 return _overflow_impl::operate<OverflowTag, OperatorTag>()(lhs.data(), rhs.data());
244 template<
class OperatorTag,
class LhsRep,
class LhsTag,
class RhsRep,
class RhsTag>
245 constexpr
auto operate(
246 const safe_integer<LhsRep, LhsTag>& lhs,
247 const safe_integer<RhsRep, RhsTag>& rhs,
248 OperatorTag operator_tag)
249 -> decltype(operate_common_tag(common_type_t<LhsTag, RhsTag>{}, operator_tag, lhs, rhs))
251 return operate_common_tag(common_type_t<LhsTag, RhsTag>{}, operator_tag, lhs, rhs);
258 SG14_INTEGER_BIT_SHIFT_DEFINE(>>);
260 SG14_INTEGER_BIT_SHIFT_DEFINE(<<);
267 class RhsRep,
class RhsOverflowTag>
270 sg14::safe_integer<RhsRep, RhsOverflowTag>>
271 : sg14::_integer_impl::common_type<
273 sg14::safe_integer<RhsRep, RhsOverflowTag>> {
278 class LhsRep,
class LhsOverflowTag,
281 sg14::safe_integer<LhsRep, LhsOverflowTag>,
283 : sg14::_integer_impl::common_type<
284 sg14::safe_integer<LhsRep, LhsOverflowTag>,
290 class LhsRep,
class LhsOverflowTag,
291 class RhsRep,
int RhsExponent>
293 sg14::safe_integer<LhsRep, LhsOverflowTag>,
296 sg14::fixed_point<sg14::safe_integer<LhsRep, LhsOverflowTag>, 0>,
297 sg14::fixed_point<RhsRep, RhsExponent>> {
302 class LhsRep,
int LhsExponent,
303 class RhsRep,
class RhsOverflowTag>
305 sg14::fixed_point<LhsRep, LhsExponent>,
306 sg14::safe_integer<RhsRep, RhsOverflowTag>>
308 sg14::fixed_point<LhsRep, LhsExponent>,
309 sg14::fixed_point<sg14::safe_integer<RhsRep, RhsOverflowTag>, 0>> {
314 class LhsRep,
class LhsOverflowTag,
315 class RhsRep,
class RhsOverflowTag>
317 sg14::safe_integer<LhsRep, LhsOverflowTag>,
318 sg14::safe_integer<RhsRep, RhsOverflowTag>>
319 : sg14::_integer_impl::common_type<
320 sg14::safe_integer<LhsRep, LhsOverflowTag>,
321 sg14::safe_integer<RhsRep, RhsOverflowTag>> {
327 template<
class Rep,
class OverflowTag>
328 struct numeric_limits<sg14::safe_integer<Rep, OverflowTag>>
329 : numeric_limits<sg14::_impl::number_base<sg14::safe_integer<Rep, OverflowTag>, Rep>> {};
332 #endif // SG14_SAFE_INTEGER_H
literal real number approximation that uses fixed-point arithmetic
Definition: fixed_point_type.h:20
study group 14 of the C++ working group
Definition: const_integer.h:22