7 #if !defined(SG14_PRECISE_INTEGER_H) 8 #define SG14_PRECISE_INTEGER_H 1 10 #include <sg14/bits/number_base.h> 11 #include <sg14/bits/limits.h> 15 struct closest_rounding_tag {
16 template<
class To,
class From>
17 static constexpr To convert(
const From& from)
19 return static_cast<To
>(std::intmax_t(from+((from>=0) ? .5 : -.5)));
23 template<
class Rep =
int,
class RoundingTag = closest_rounding_tag>
24 class precise_integer :
public _impl::number_base<precise_integer<Rep, RoundingTag>, Rep> {
25 using super = _impl::number_base<precise_integer<Rep, RoundingTag>, Rep>;
27 using rounding = RoundingTag;
29 constexpr precise_integer() =
default;
31 template<class T, _impl::enable_if_t<std::numeric_limits<T>::is_integer,
int> Dummy = 0>
32 constexpr precise_integer(
const T& v)
33 : super(static_cast<Rep>(v)) { }
35 template<class T, _impl::enable_if_t<!std::numeric_limits<T>::is_integer,
int> Dummy = 0>
36 constexpr precise_integer(
const T& v)
37 : super(rounding::template convert<Rep>(v)) { }
40 constexpr
explicit operator T()
const 42 return static_cast<T
>(super::data());
49 template<
class Rep,
class RoundingTag>
50 struct digits<precise_integer<Rep, RoundingTag>> : digits<Rep> {
53 template<
class Rep,
class RoundingTag, _digits_type MinNumBits>
54 struct set_digits<precise_integer<Rep, RoundingTag>, MinNumBits> {
55 using type = precise_integer<set_digits_t<Rep, MinNumBits>, RoundingTag>;
59 template<
class Rep,
class RoundingTag>
60 struct get_rep<precise_integer<Rep, RoundingTag>> {
64 template<
class OldRep,
class RoundingTag,
class NewRep>
65 struct set_rep<precise_integer<OldRep, RoundingTag>, NewRep> {
66 using type = precise_integer<NewRep, RoundingTag>;
70 template<
class Rep,
class RoundingTag,
class Value>
71 struct from_value<precise_integer<Rep, RoundingTag>, Value> {
72 using type = precise_integer<Value, RoundingTag>;
75 template<
class Rep,
class RoundingTag>
76 struct scale<precise_integer<Rep, RoundingTag>>
77 : scale<_impl::number_base<precise_integer<Rep, RoundingTag>, Rep>> {
80 namespace _precise_integer_impl {
85 struct is_precise_integer : std::false_type {
88 template<
class Rep,
class RoundingTag>
89 struct is_precise_integer<precise_integer<Rep, RoundingTag>> : std::true_type {
98 template<
class Operator,
class RoundingTag,
class LhsRep,
class RhsRep,
class = enable_if_t<Operator::is_arithmetic>>
99 constexpr
auto operate_common_tag(
100 const precise_integer<LhsRep, RoundingTag>& lhs,
101 const precise_integer<RhsRep, RoundingTag>& rhs)
102 -> decltype(from_rep<precise_integer<op_result<Operator, LhsRep, RhsRep>, RoundingTag>>(Operator()(lhs.data(), rhs.data())))
104 using result_type = precise_integer<op_result<Operator, LhsRep, RhsRep>, RoundingTag>;
105 return from_rep<result_type>(Operator()(lhs.data(), rhs.data()));
109 template<
class Operator,
class RoundingTag,
class LhsRep,
class RhsRep, enable_if_t<Operator::is_comparison,
int> = 0>
110 constexpr
auto operate_common_tag(
111 const precise_integer<LhsRep, RoundingTag>& lhs,
112 const precise_integer<RhsRep, RoundingTag>& rhs)
113 -> decltype(Operator()(lhs.data(), rhs.data()))
115 return Operator()(lhs.data(), rhs.data());
119 template<
class Operator,
class LhsRep,
class LhsRoundingTag,
class RhsRep,
class RhsRoundingTag>
120 constexpr
auto operate(
121 const precise_integer<LhsRep, LhsRoundingTag>& lhs,
122 const precise_integer<RhsRep, RhsRoundingTag>& rhs,
124 -> decltype(operate_common_tag<Operator, common_type_t<LhsRoundingTag, RhsRoundingTag>>(lhs, rhs))
126 return operate_common_tag<Operator, common_type_t<LhsRoundingTag, RhsRoundingTag>>(lhs, rhs);
133 template<
class LhsRep,
class LhsRoundingTag,
class RhsInteger>
134 constexpr
auto operator<<(
135 const precise_integer<LhsRep, LhsRoundingTag>& lhs,
136 const RhsInteger& rhs)
137 -> decltype(from_rep<precise_integer<decltype(_impl::to_rep(lhs) << rhs), LhsRoundingTag>>(_impl::to_rep(lhs) << rhs))
139 return from_rep<precise_integer<
140 decltype(_impl::to_rep(lhs) << rhs),
141 LhsRoundingTag>>(_impl::to_rep(lhs) << rhs);
149 template<
class Rep,
class RoundingTag>
150 struct numeric_limits<
sg14::precise_integer<Rep, RoundingTag>>
151 : numeric_limits<sg14::_impl::number_base<sg14::precise_integer<Rep, RoundingTag>, Rep>> {};
study group 14 of the C++ working group
Definition: const_integer.h:22