10 #if !defined(SG14_NUMERIC_TRAITS)    11 #define SG14_NUMERIC_TRAITS 1    13 #if !defined(SG14_GODBOLT_ORG)    15 #include "bits/limits.h"    16 #include "bits/type_traits.h"    25     using _digits_type = int;
    30     template<
class T, 
class Enable = 
void>
    31     struct is_composite : std::false_type {
    32         static_assert(!std::is_reference<T>::value, 
"T is a reference");
    33         static_assert(!std::is_const<T>::value, 
"T is const");
    34         static_assert(!std::is_volatile<T>::value, 
"T is volatile");
    37 #if (__cplusplus > 201402L)    39     constexpr 
auto is_composite_v = is_composite<T>::value;
    42     namespace _num_traits_impl {
    46         template<
class ... Args>
    50         struct are_composite<> : std::false_type {
    53         template<
class ArgHead, 
class ... ArgTail>
    54         struct are_composite<ArgHead, ArgTail...>
    55                 : std::integral_constant<bool, is_composite<typename std::decay<ArgHead>::type>::value || are_composite<ArgTail...>::value> {
    61         template<_digits_type MinNumDigits, 
class Smaller, 
class T>
    62         struct enable_for_range
    63                 : std::enable_if<MinNumDigits <= std::numeric_limits<T>::digits &&
    64                                  std::numeric_limits<Smaller>::digits < MinNumDigits> {
    67         template<_digits_type MinNumDigits, class Smallest>
    68         struct enable_for_range<MinNumDigits, void, Smallest>
    69                 : std::enable_if<MinNumDigits <= std::numeric_limits<Smallest>::digits> {
    72         template<_digits_type MinNumDigits, class Smaller, class T>
    73         using enable_for_range_t = typename enable_for_range<MinNumDigits, Smaller, T>::type;
    78         template<_digits_type MinNumDigits, class Enable = void>
    79         struct set_digits_signed;
    81         template<_digits_type MinNumDigits>
    82         struct set_digits_signed<MinNumDigits, enable_for_range_t<MinNumDigits, void, std::int8_t>> {
    83             using type = std::int8_t;
    86         template<_digits_type MinNumDigits>
    87         struct set_digits_signed<MinNumDigits, enable_for_range_t<MinNumDigits, std::int8_t, std::int16_t>> {
    88             using type = std::int16_t;
    91         template<_digits_type MinNumDigits>
    92         struct set_digits_signed<MinNumDigits, enable_for_range_t<MinNumDigits, std::int16_t, std::int32_t>> {
    93             using type = std::int32_t;
    96         template<_digits_type MinNumDigits>
    97         struct set_digits_signed<MinNumDigits, enable_for_range_t<MinNumDigits, std::int32_t, std::int64_t>> {
    98             using type = std::int64_t;
   101 #if defined(SG14_INT128_ENABLED)
   102         template<_digits_type MinNumDigits>
   103         struct set_digits_signed<MinNumDigits, enable_for_range_t<MinNumDigits, std::int64_t, SG14_INT128>> {
   104             using type = SG14_INT128;
   111         template<_digits_type MinNumDigits, class Enable = void>
   112         struct set_digits_unsigned;
   114         template<_digits_type MinNumDigits>
   115         struct set_digits_unsigned<MinNumDigits, enable_for_range_t<MinNumDigits, void, std::uint8_t>> {
   116             using type = std::uint8_t;
   119         template<_digits_type MinNumDigits>
   120         struct set_digits_unsigned<MinNumDigits, enable_for_range_t<MinNumDigits, std::uint8_t, std::uint16_t>> {
   121             using type = std::uint16_t;
   124         template<_digits_type MinNumDigits>
   125         struct set_digits_unsigned<MinNumDigits, enable_for_range_t<MinNumDigits, std::uint16_t, std::uint32_t>> {
   126             using type = std::uint32_t;
   129         template<_digits_type MinNumDigits>
   130         struct set_digits_unsigned<MinNumDigits, enable_for_range_t<MinNumDigits, std::uint32_t, std::uint64_t>> {
   131             using type = std::uint64_t;
   134 #if defined(SG14_INT128_ENABLED)
   135         template<_digits_type MinNumDigits>
   136         struct set_digits_unsigned<MinNumDigits, enable_for_range_t<MinNumDigits, std::uint64_t, SG14_UINT128>> {
   137             using type = SG14_UINT128;
   144         template<class Integer, _digits_type MinNumDigits>
   145         using set_digits_integer = typename std::conditional<
   146                 std::numeric_limits<Integer>::is_signed,
   147                 set_digits_signed<MinNumDigits>,
   148                 set_digits_unsigned<MinNumDigits>>::type;
   154     template<class T, class Enable = void>
   155     struct digits : std::integral_constant<_digits_type, std::numeric_limits<T>::digits> {
   158 #if (__cplusplus > 201402L)
   160     constexpr _digits_type digits_v = digits<T>::value;
   166     template<class T, _digits_type Digits, class Enable = void>
   169     template<class T, _digits_type Digits>
   170     struct set_digits<T, Digits, _impl::enable_if_t<std::is_integral<T>::value>>
   171             : _num_traits_impl::set_digits_integer<T, Digits> {
   174 #if defined(SG14_INT128_ENABLED)
   175     template<_digits_type Digits>
   176     struct set_digits<SG14_INT128, Digits>
   177             : _num_traits_impl::set_digits_integer<signed, Digits> {
   180     template<_digits_type Digits>
   181     struct set_digits<SG14_UINT128, Digits>
   182             : _num_traits_impl::set_digits_integer<unsigned, Digits> {
   186     template<class T, _digits_type Digits>
   187     using set_digits_t = typename set_digits<T, Digits>::type;
   193     struct is_signed : std::integral_constant<bool, std::numeric_limits<T>::is_signed> {
   199     template<class, class = void>
   203     struct make_signed<T, _impl::enable_if_t<std::is_integral<T>::value>> : std::make_signed<T> {
   207     using make_signed_t = typename make_signed<T>::type;
   212     template<class, class = void>
   213     struct make_unsigned;
   216     struct make_unsigned<T, _impl::enable_if_t<std::is_integral<T>::value>> : std::make_unsigned<T> {
   219 #if defined(SG14_INT128_ENABLED)
   222     struct make_unsigned<SG14_INT128> {
   223         using type = SG14_UINT128;
   226     struct make_unsigned<SG14_UINT128> {
   227         using type = SG14_UINT128;
   231     struct make_signed<SG14_INT128> {
   232         using type = SG14_INT128;
   235     struct make_signed<SG14_UINT128> {
   236         using type = SG14_INT128;
   241     using make_unsigned_t = typename make_unsigned<T>::type;
   247         template<class T, bool IsSigned = true>
   251         struct make_signed<T, true> : ::sg14::make_signed<T> {
   255         struct make_signed<T, false> : ::sg14::make_unsigned<T> {
   258         template<class T, bool IsSigned>
   259         using make_signed_t = typename make_signed<T, IsSigned>::type;
   264         template<class T1, class T2>
   265         struct common_signedness {
   266             static constexpr bool _are_signed = std::numeric_limits<T1>::is_signed | std::numeric_limits<T2>::is_signed;
   268             using type = typename std::common_type<make_signed_t<T1, _are_signed>,
   269                     make_signed_t<T2, _are_signed>>::type;
   272         template<class T1, class T2>
   273         using common_signedness_t = typename common_signedness<T1, T2>::type;
   278         template<class T, class Enable = void>
   279         struct unsigned_or_float;
   282         struct unsigned_or_float<T, enable_if_t<std::numeric_limits<T>::is_iec559>> {
   287         struct unsigned_or_float<T, enable_if_t<!std::numeric_limits<T>::is_iec559>> : make_unsigned<T> {
   291         using unsigned_or_float_t = typename unsigned_or_float<T>::type;
   293         template<class Encompasser, class Encompassed, class Enable = void>
   294         struct encompasses_lower;
   296         template<class Encompasser, class Encompassed>
   297         struct encompasses_lower<Encompasser, Encompassed,
   298                 enable_if_t<std::numeric_limits<Encompasser>::is_signed
   299                             && std::numeric_limits<Encompassed>::is_signed>> {
   300             static constexpr bool value = std::numeric_limits<Encompasser>::lowest()
   301                                           <= std::numeric_limits<Encompassed>::lowest();
   304         template<class Encompasser, class Encompassed>
   305         struct encompasses_lower<Encompasser, Encompassed,
   306                 enable_if_t<!std::numeric_limits<Encompassed>::is_signed>> : std::true_type {
   309         template<class Encompasser, class Encompassed>
   310         struct encompasses_lower<Encompasser, Encompassed,
   311                 enable_if_t<!std::numeric_limits<Encompasser>::is_signed
   312                             && std::numeric_limits<Encompassed>::is_signed>> : std::false_type {
   316         template<class Encompasser, class Encompassed>
   318             static constexpr bool _lower = encompasses_lower<Encompasser, Encompassed>::value;
   319             static constexpr bool _upper =
   320                     static_cast<unsigned_or_float_t<Encompasser>>(std::numeric_limits<Encompasser>::max())
   321                     >= static_cast<unsigned_or_float_t<Encompassed>>(std::numeric_limits<Encompassed>::max());
   323             static constexpr bool value = _lower && _upper;
   330         struct is_integer_or_float : std::integral_constant<
   332                 std::numeric_limits<T>::is_integer || std::numeric_limits<T>::is_iec559> {
   339     template<class Number, class Enable = void>
   341         constexpr Number operator()(const Number &number) const {
   348         template<class Number, class Enable = void>
   349         constexpr auto to_rep(const Number &number)
   350         -> decltype(sg14::to_rep<Number>()(number)) {
   351             return sg14::to_rep<Number>()(number);
   358     template<class Number, class Enable = void>
   361         constexpr Number operator()(const Rep &rep) const {
   363             return static_cast<Number>(rep);
   368         template<class Number, class Rep>
   369         constexpr auto from_rep(const Rep &rep)
   370         -> decltype(sg14::from_rep<Number>()(rep)) {
   371             return sg14::from_rep<Number>()(rep);
   379     template<
class Result, 
class F, 
class ... Args,
   380             _impl::enable_if_t<!_num_traits_impl::are_composite<Args ...>::value, 
int> dummy = 0>
   381     constexpr Result for_rep(F f, Args &&...args) {
   382         return f(std::forward<Args>(args)...);
   385     template<
class Result, 
class F, 
class ... Args,
   386             _impl::enable_if_t<_num_traits_impl::are_composite<Args ...>::value, 
int> dummy = 0>
   387     constexpr Result for_rep(F f, Args &&...args) {
   388         return for_rep<Result>(f, _impl::to_rep<typename std::decay<Args>::type>(std::forward<Args>(args))...);
   395     template<
class Number, 
class Value, 
class Enable = 
void>
   398     template<
class Number, 
class Value>
   399     struct from_value<Number, Value, _impl::enable_if_t<std::is_integral<Number>::value>> {
   403     template<
class Number, 
class Value>
   404     using from_value_t = 
typename from_value<Number, Value>::type;
   407         template<
class Number, 
class Value>
   408         constexpr 
auto from_value(
const Value &value)
   409         -> sg14::from_value_t<Number, Value> {
   417     namespace _num_traits_impl {
   419         using scale_result_type = decltype(std::declval<T>() * std::declval<T>());
   422         constexpr scale_result_type<T> pown(
int base, 
int exp) {
   424                    ? pown<T>(base, exp - 1) * 
static_cast<scale_result_type<T>
>(base)
   425                    : static_cast<scale_result_type<T>>(1);
   429         constexpr scale_result_type<T> pow2(
int exp) {
   430             return scale_result_type<T>{1} << exp;
   434         constexpr scale_result_type<T> pow(
int base, 
int exp) {
   435             return (base == 2) ? pow2<T>(exp) : pown<T>(base, exp);
   441         constexpr 
auto operator()(
const T &i, 
int base, 
int exp) 
const   442         -> _num_traits_impl::scale_result_type<T> {
   443             return _impl::from_rep<_num_traits_impl::scale_result_type<T>>(
   445                     ? _impl::to_rep<T>(i) / _num_traits_impl::pow<T>(base, -exp)
   446                     : _impl::to_rep<T>(i) * _num_traits_impl::pow<T>(base, exp));
   452         constexpr 
auto scale(
const T &i, 
int base, 
int exp)
   453         -> decltype(sg14::scale<T>()(i, base, exp)) {
   454             return sg14::scale<T>()(i, base, exp);
   459 #endif    // SG14_NUMERIC_TRAITS study group 14 of the C++ working group 
Definition: const_integer.h:22