7 #if !defined(SG14_number_base_H) 8 #define SG14_number_base_H 1 10 #include <sg14/auxiliary/const_integer.h> 11 #include <sg14/bits/common.h> 12 #include <sg14/num_traits.h> 15 #include <type_traits> 19 template<
class Derived,
class Rep>
23 using _derived = Derived;
25 number_base() =
default;
27 constexpr number_base(
const rep& r)
31 number_base& operator=(
const T& r) {
33 return static_cast<Derived&
>(*this);
36 explicit constexpr
operator bool()
const 38 return static_cast<bool>(_rep);
41 constexpr
const rep& data()
const 46 #if (__cplusplus >= 201402L) 53 static constexpr Derived from_data(
const rep& r)
68 template<
class Derived,
class Enable =
void>
69 struct is_class_derived_from_number_base : std::false_type {};
71 template<
class Derived>
72 struct is_class_derived_from_number_base<
74 enable_if_t<
std::is_base_of<number_base<Derived, typename Derived::rep>, Derived>::value>>
81 template<
class T,
class Enable =
void>
82 struct is_derived_from_number_base : std::false_type {};
84 template<
class Derived>
85 struct is_derived_from_number_base<Derived, enable_if_t<std::is_class<Derived>::value>>
86 : is_class_derived_from_number_base<Derived> { };
91 template<
class Former,
class Latter>
93 static constexpr
bool value =
94 (std::is_floating_point<Former>::value && !std::is_floating_point<Latter>::value)
95 || (is_derived_from_number_base<Former>::value &&
96 !(is_derived_from_number_base<Latter>::value
97 || std::is_floating_point<Latter>::value));
105 class Operator,
class Lhs,
class RhsDerived,
class RhsRep,
106 enable_if_t <precedes<Lhs, RhsDerived>::value, std::nullptr_t> =
nullptr>
107 constexpr
auto operate(
const Lhs& lhs,
const number_base<RhsDerived, RhsRep>& rhs, Operator op)
108 -> decltype(op(lhs, static_cast<Lhs>(static_cast<const RhsDerived&>(rhs))))
110 return op(lhs, static_cast<Lhs>(static_cast<const RhsDerived&>(rhs)));
115 class Operator,
class LhsDerived,
class LhsRep,
class Rhs,
116 enable_if_t <precedes<Rhs, LhsDerived>::value, std::nullptr_t> =
nullptr>
117 constexpr
auto operate(
const number_base<LhsDerived, LhsRep>& lhs,
const Rhs& rhs, Operator op)
118 -> decltype(op(static_cast<Rhs>(static_cast<const LhsDerived&>(lhs)), rhs))
120 return op(static_cast<Rhs>(static_cast<const LhsDerived&>(lhs)), rhs);
125 class Operator,
class Lhs,
class RhsDerived,
class RhsRep,
126 enable_if_t <precedes<RhsDerived, Lhs>::value, std::nullptr_t> =
nullptr>
127 constexpr
auto operate(
const Lhs& lhs,
const number_base<RhsDerived, RhsRep>& rhs, Operator op)
128 -> decltype(op(_impl::from_value<RhsDerived>(lhs), static_cast<const RhsDerived&>(rhs))) {
129 return op(from_value<RhsDerived>(lhs), static_cast<const RhsDerived&>(rhs));
134 class Operator,
class LhsDerived,
class LhsRep,
class Rhs,
135 enable_if_t <precedes<LhsDerived, Rhs>::value, std::nullptr_t> =
nullptr>
136 constexpr
auto operate(
const number_base<LhsDerived, LhsRep>& lhs,
const Rhs& rhs, Operator op)
137 -> decltype(op(static_cast<const LhsDerived &>(lhs), from_value<LhsDerived>(rhs)))
139 return op(static_cast<const LhsDerived &>(lhs), from_value<LhsDerived>(rhs));
143 template<
class Operator,
class RhsDerived,
class RhsRep>
144 constexpr
auto operate(
const number_base<RhsDerived, RhsRep>& rhs, Operator op)
145 -> decltype(op(rhs.data()))
147 return op(rhs.data());
155 template<class Lhs, class Rhs, class = enable_if_t <is_derived_from_number_base<Lhs>::value>>
156 auto operator+=(Lhs& lhs,
const Rhs& rhs)
157 -> decltype(lhs = lhs + rhs)
159 return lhs = lhs + rhs;
162 template<class Lhs, class Rhs, class = enable_if_t <is_derived_from_number_base<Lhs>::value>>
163 auto operator-=(Lhs& lhs,
const Rhs& rhs)
164 -> decltype(lhs = lhs - rhs)
166 return lhs = lhs - rhs;
169 template<class Lhs, class Rhs, class = enable_if_t <is_derived_from_number_base<Lhs>::value>>
170 auto operator*=(Lhs& lhs,
const Rhs& rhs)
171 -> decltype(lhs = lhs * rhs)
173 return lhs = lhs * rhs;
176 template<class Lhs, class Rhs, class = enable_if_t <is_derived_from_number_base<Lhs>::value>>
177 auto operator/=(Lhs& lhs,
const Rhs& rhs)
178 -> decltype(lhs = lhs / rhs)
180 return lhs = lhs / rhs;
185 template<
class RhsDerived,
class RhsRep>
186 constexpr
auto operator+(
const number_base<RhsDerived, RhsRep>& rhs)
187 -> decltype(operate(rhs, plus_tag))
189 return operate(rhs, plus_tag);
192 template<
class RhsDerived,
class RhsRep>
193 constexpr
auto operator-(
const number_base<RhsDerived, RhsRep>& rhs)
194 -> decltype(operate(rhs, minus_tag))
196 return operate(rhs, minus_tag);
201 template<
class Lhs,
class Rhs>
202 constexpr
auto operator+(
const Lhs& lhs,
const Rhs& rhs)
203 -> decltype(operate(lhs, rhs, add_tag))
205 return operate(lhs, rhs, add_tag);
208 template<
class Lhs,
class Rhs>
209 constexpr
auto operator-(
const Lhs& lhs,
const Rhs& rhs)
210 -> decltype(operate(lhs, rhs, subtract_tag))
212 return operate(lhs, rhs, subtract_tag);
215 template<
class Lhs,
class Rhs>
216 constexpr
auto operator*(
const Lhs& lhs,
const Rhs& rhs)
217 -> decltype(operate(lhs, rhs, multiply_tag))
219 return operate(lhs, rhs, multiply_tag);
222 template<
class Lhs,
class Rhs>
223 constexpr
auto operator/(
const Lhs& lhs,
const Rhs& rhs)
224 -> decltype(operate(lhs, rhs, divide_tag))
226 return operate(lhs, rhs, divide_tag);
231 template<
class Lhs,
class Rhs>
232 constexpr
auto operator|(
const Lhs& lhs,
const Rhs& rhs)
233 -> decltype(operate(lhs, rhs, bitwise_or_tag))
235 return operate(lhs, rhs, bitwise_or_tag);
238 template<
class Lhs,
class Rhs>
239 constexpr
auto operator&(
const Lhs& lhs,
const Rhs& rhs)
240 -> decltype(operate(lhs, rhs, bitwise_and_tag))
242 return operate(lhs, rhs, bitwise_and_tag);
245 template<
class Lhs,
class Rhs>
246 constexpr
auto operator^(
const Lhs& lhs,
const Rhs& rhs)
247 -> decltype(operate(lhs, rhs, bitwise_xor_tag))
249 return operate(lhs, rhs, bitwise_xor_tag);
254 template<
class Lhs,
class Rhs>
255 constexpr
auto operator==(
const Lhs& lhs,
const Rhs& rhs)
256 -> decltype(operate(lhs, rhs, equal_tag))
258 return operate(lhs, rhs, equal_tag);
261 template<
class Lhs,
class Rhs>
262 constexpr
auto operator!=(
const Lhs& lhs,
const Rhs& rhs)
263 -> decltype(operate(lhs, rhs, not_equal_tag))
265 return operate(lhs, rhs, not_equal_tag);
268 template<
class Lhs,
class Rhs>
269 constexpr
auto operator<(
const Lhs& lhs,
const Rhs& rhs)
270 -> decltype(operate(lhs, rhs, less_than_tag))
272 return operate(lhs, rhs, less_than_tag);
275 template<
class Lhs,
class Rhs>
276 constexpr
auto operator>(
const Lhs& lhs,
const Rhs& rhs)
277 -> decltype(operate(lhs, rhs, greater_than_tag))
279 return operate(lhs, rhs, greater_than_tag);
282 template<
class Lhs,
class Rhs>
283 constexpr
auto operator<=(
const Lhs& lhs,
const Rhs& rhs)
284 -> decltype(operate(lhs, rhs, less_than_or_equal_tag))
286 return operate(lhs, rhs, less_than_or_equal_tag);
289 template<
class Lhs,
class Rhs>
290 constexpr
auto operator>=(
const Lhs& lhs,
const Rhs& rhs)
291 -> decltype(operate(lhs, rhs, greater_than_or_equal_tag))
293 return operate(lhs, rhs, greater_than_or_equal_tag);
300 template<
class Number>
301 struct is_composite<Number, _impl::enable_if_t<_impl::is_derived_from_number_base<Number>::value>> : std::true_type {
305 template<
class Number>
308 template<
class Number>
309 using get_rep_t =
typename get_rep<Number>::type;
313 template<
class Number,
class NewRep,
class Enable =
void>
316 template<
class Number,
class NewRep>
317 using set_rep_t =
typename set_rep<Number, NewRep>::type;
320 template<
class Number>
321 struct make_signed<Number, _impl::enable_if_t<_impl::is_derived_from_number_base<Number>::value>> {
322 using type = _impl::set_rep_t<Number, make_signed_t<_impl::get_rep_t<Number>>>;
325 template<
class Number>
326 struct make_unsigned<Number, _impl::enable_if_t<_impl::is_derived_from_number_base<Number>::value>> {
327 using type = _impl::set_rep_t<Number, make_unsigned_t<_impl::get_rep_t<Number>>>;
330 template<
class Number>
331 struct from_rep<Number, _impl::enable_if_t<_impl::is_derived_from_number_base<Number>::value>> {
333 constexpr
auto operator()(
const Rep &rep)
const -> Number {
334 return Number::from_data(static_cast<typename Number::rep>(rep));
338 template<
class Number>
339 struct to_rep<Number, _impl::enable_if_t<_impl::is_derived_from_number_base<Number>::value>> {
340 constexpr
auto operator()(
const typename Number::_derived& number)
const 341 -> decltype(number.data()){
342 return number.data();
346 template<
class Derived,
class Rep>
347 struct scale<_impl::number_base<Derived, Rep>> {
348 template<
class Input>
349 constexpr Rep operator()(
const Input &i,
int base,
int exp)
const {
351 ? _impl::to_rep(i) / _num_traits_impl::pow<Rep>(base, -exp)
352 : _impl::to_rep(i) * _num_traits_impl::pow<Rep>(base, exp);
361 template<
class Derived,
class Rep>
362 struct numeric_limits<
sg14::_impl::number_base<Derived, Rep>>
363 : numeric_limits<Rep> {
365 using _value_type = Derived;
366 using _rep =
typename _value_type::rep;
367 using _rep_numeric_limits = numeric_limits<_rep>;
371 static constexpr _value_type min() noexcept
373 return _value_type::from_data(_rep_numeric_limits::min());
376 static constexpr _value_type max() noexcept
378 return _value_type::from_data(_rep_numeric_limits::max());
381 static constexpr _value_type lowest() noexcept
383 return _value_type::from_data(_rep_numeric_limits::lowest());
386 static constexpr _value_type epsilon() noexcept
388 return _value_type::from_data(_rep_numeric_limits::round_error());
391 static constexpr _value_type round_error() noexcept
393 return static_cast<_value_type
>(_rep_numeric_limits::round_error());
396 static constexpr _value_type infinity() noexcept
398 return static_cast<_value_type
>(_rep_numeric_limits::infinity());
401 static constexpr _value_type quiet_NaN() noexcept
403 return static_cast<_value_type
>(_rep_numeric_limits::quiet_NaN());
406 static constexpr _value_type signaling_NaN() noexcept
408 return static_cast<_value_type
>(_rep_numeric_limits::signaling_NaN());
411 static constexpr _value_type denorm_min() noexcept
413 return static_cast<_value_type
>(_rep_numeric_limits::denorm_min());
418 #endif // SG14_NUMBER_BASE_H
study group 14 of the C++ working group
Definition: const_integer.h:22