Skip to content

Commit 620f308

Browse files
authored
Merge pull request ckormanyos#405 from ckormanyos/msvc_141
2 parents fb124fa + 55b5714 commit 620f308

File tree

4 files changed

+91
-98
lines changed

4 files changed

+91
-98
lines changed

README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ as shown in the [examples](./examples).
7171
- Clean header-only C++14 design.
7272
- Seamless portability to any modern C++14, 17, 20, 23 compiler and beyond.
7373
- Scalability with small memory footprint and efficiency suitable for both PC/workstation systems as well as _bare-metal_ embedded systems.
74-
- C++14 `constexpr`-_ness_.
74+
- C++14, 17, 20, 23 and beyond `constexpr`-ness.
7575

7676
## Quick start
7777

@@ -729,7 +729,7 @@ This optional macro can be used to switch `uintwide_t`'s
729729
data member access from _private_ to _public_. This allows the
730730
`uintwide_t` class to be used as a so-called _structured_ class,
731731
such as is needed for constant-valued template parameters
732-
in the sense of C++14's (and beyond) `constexpr`-ness.
732+
in a `constexpr` context.
733733
This preprocessor switch was invented based on the discussion in
734734
[issue 335](https://github.com/ckormanyos/wide-integer/issues/335)
735735

@@ -755,7 +755,7 @@ is not defined and CLZ-limb optimizations are default-_disabled_.
755755

756756
### C++14, 17, 20, 23 and beyond `constexpr` support
757757

758-
`uintwide_t` supports C++14 (and beyond) compile-time
758+
`uintwide_t` supports C++14, 17, 20, 23 and beyond compile-time
759759
`constexpr`-ness for all constructions, casts, operations,
760760
evaluation of function results, etc.
761761

@@ -849,8 +849,10 @@ in the wide-integer project.
849849
For sufficiently modern standards-conforming compilers,
850850
namespace-specific functions `to_chars()` and `from_chars()`
851851
are available. These each have the _usual_ `<charconv>`-like
852-
behavior, known from C++17. For motivational words to/from-chars,
853-
see also [issue 398](https://github.com/ckormanyos/wide-integer/issues/398).
852+
behavior, known from C++17. For motivational words on
853+
`to_chars()` and `from_chars()`,
854+
see also [issue 153](https://github.com/ckormanyos/wide-integer/issues/153)
855+
and [issue 398](https://github.com/ckormanyos/wide-integer/issues/398).
854856

855857
Support for importing and exporting bits is granted by the subroutines
856858
`import_bits()` and `export_bits()`. Their interfaces, input/output forms

boost/multiprecision/uintwide_t_backend.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#ifndef UINTWIDE_T_BACKEND_2019_12_15_HPP // NOLINT(llvm-header-guard)
99
#define UINTWIDE_T_BACKEND_2019_12_15_HPP
1010

11+
#include <algorithm>
1112
#include <cstdint>
1213
#include <limits>
1314
#include <string>

examples/example000_numeric_limits.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,30 @@ auto ::math::wide_integer::example000_numeric_limits() -> bool
6666
#endif
6767

6868
constexpr int256_t my_max ("0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
69-
constexpr int256_t my_min ("-57896044618658097711785492504343953926634992332820282019728792003956564819968");
70-
constexpr int256_t my_lowest("-57896044618658097711785492504343953926634992332820282019728792003956564819968");
69+
constexpr int256_t my_min ("0x8000000000000000000000000000000000000000000000000000000000000000");
70+
71+
#if (defined(_MSC_VER) && (_MSC_VER < 1920))
72+
#pragma warning(push)
73+
#pragma warning(disable : 4307)
74+
#endif
75+
constexpr int256_t my_min2 ("-57896044618658097711785492504343953926634992332820282019728792003956564819968");
76+
#if (defined(_MSC_VER) && (_MSC_VER < 1920))
77+
#pragma warning(pop)
78+
#endif
79+
80+
constexpr int256_t my_lowest = my_min2;
81+
82+
static_assert((std::numeric_limits<int256_t>::max) () == my_max, "Error: example000_numeric_limits signed not OK!");
83+
static_assert((std::numeric_limits<int256_t>::min) () == my_min, "Error: example000_numeric_limits signed not OK!");
84+
static_assert((std::numeric_limits<int256_t>::min) () == my_min2, "Error: example000_numeric_limits signed not OK!");
85+
static_assert( std::numeric_limits<int256_t>::lowest() == my_lowest, "Error: example000_numeric_limits signed not OK!");
86+
static_assert( std::numeric_limits<int256_t>::digits == static_cast<int>(INT32_C(255)), "Error: example000_numeric_limits signed not OK!");
87+
static_assert( std::numeric_limits<int256_t>::digits10 == static_cast<int>(INT32_C(76)), "Error: example000_numeric_limits signed not OK!");
7188

7289
constexpr bool result_int256_t_is_ok =
7390
((std::numeric_limits<int256_t>::max) () == my_max)
7491
&& ((std::numeric_limits<int256_t>::min) () == my_min)
92+
&& ((std::numeric_limits<int256_t>::min) () == my_min2)
7593
&& ( std::numeric_limits<int256_t>::lowest() == my_lowest)
7694
&& ( std::numeric_limits<int256_t>::digits == static_cast<int>(INT32_C(255)))
7795
&& ( std::numeric_limits<int256_t>::digits10 == static_cast<int>(INT32_C(76)))

math/wide_integer/uintwide_t.h

Lines changed: 63 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -2611,7 +2611,7 @@
26112611
}
26122612
else if(other.is_zero())
26132613
{
2614-
*this = limits_helper_max(IsSigned);
2614+
static_cast<void>(operator=(limits_helper_max<IsSigned>()));
26152615
}
26162616
else
26172617
{
@@ -2709,14 +2709,12 @@
27092709
{
27102710
if(this != &other) // LCOV_EXCL_LINE
27112711
{
2712-
auto bi = other.values.cbegin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto)
2712+
auto itr_b = other.values.cbegin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto)
27132713

27142714
// Perform bitwise OR.
2715-
for(auto& a : values)
2715+
for(auto itr_a = values.begin(); itr_a != values.end(); ++itr_a, ++itr_b) // NOLINT(altera-id-dependent-backward-branch,llvm-qualified-auto,readability-qualified-auto)
27162716
{
2717-
a = static_cast<limb_type>(a | *bi);
2718-
2719-
++bi;
2717+
*itr_a = static_cast<limb_type>(*itr_a | *itr_b);
27202718
}
27212719
}
27222720

@@ -2731,14 +2729,12 @@
27312729
}
27322730
else
27332731
{
2734-
auto bi = other.values.cbegin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto)
2732+
auto itr_b = other.values.cbegin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto)
27352733

27362734
// Perform bitwise XOR.
2737-
for(auto& a : values)
2735+
for(auto itr_a = values.begin(); itr_a != values.end(); ++itr_a, ++itr_b) // NOLINT(altera-id-dependent-backward-branch,llvm-qualified-auto,readability-qualified-auto)
27382736
{
2739-
a = static_cast<limb_type>(a ^ *bi);
2740-
2741-
++bi;
2737+
*itr_a = static_cast<limb_type>(*itr_a ^ *itr_b);
27422738
}
27432739
}
27442740

@@ -2749,14 +2745,12 @@
27492745
{
27502746
if(this != &other) // LCOV_EXCL_LINE
27512747
{
2752-
auto bi = other.values.cbegin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto)
2748+
auto itr_b = other.values.cbegin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto)
27532749

27542750
// Perform bitwise AND.
2755-
for(auto& a : values)
2751+
for(auto itr_a = values.begin(); itr_a != values.end(); ++itr_a, ++itr_b) // NOLINT(altera-id-dependent-backward-branch,llvm-qualified-auto,readability-qualified-auto)
27562752
{
2757-
a = static_cast<limb_type>(a & *bi);
2758-
2759-
++bi;
2753+
*itr_a = static_cast<limb_type>(*itr_a & *itr_b);
27602754
}
27612755
}
27622756

@@ -2884,82 +2878,60 @@
28842878
constexpr auto operator>=(const uintwide_t& other) const -> bool { return (compare(other) >= static_cast<std::int_fast8_t>( 0)); }
28852879

28862880
// Helper functions for supporting std::numeric_limits<>.
2887-
static constexpr auto limits_helper_max(bool is_signed) -> uintwide_t
2881+
template<const bool OtherIsSigned>
2882+
static constexpr auto limits_helper_max() -> std::enable_if_t<(!OtherIsSigned), uintwide_t>
28882883
{
2889-
return
2890-
(!is_signed)
2891-
? from_rep
2892-
(
2893-
representation_type
2894-
(
2895-
number_of_limbs, (std::numeric_limits<limb_type>::max)()
2896-
)
2897-
)
2898-
: from_rep
2899-
(
2900-
representation_type
2901-
(
2902-
number_of_limbs, (std::numeric_limits<limb_type>::max)() // LCOV_EXCL_LINE
2903-
)
2904-
)
2905-
^
2906-
(
2907-
uintwide_t(static_cast<std::uint8_t>(UINT8_C(1)))
2908-
<< static_cast<std::uint32_t>(my_width2 - static_cast<std::uint8_t>(UINT8_C(1)))
2909-
)
2910-
;
2884+
uintwide_t result_max { };
2885+
2886+
detail::fill_unsafe(result_max.values.begin(), result_max.values.end(), (std::numeric_limits<limb_type>::max)());
2887+
2888+
return result_max;
29112889
}
29122890

2913-
static constexpr auto limits_helper_min(bool is_signed) -> uintwide_t
2891+
template<const bool OtherIsSigned>
2892+
static constexpr auto limits_helper_max() -> std::enable_if_t<OtherIsSigned, uintwide_t>
29142893
{
2915-
return
2916-
(!is_signed)
2917-
? from_rep
2918-
(
2919-
representation_type
2920-
(
2921-
number_of_limbs, static_cast<limb_type>(UINT8_C(0))
2922-
)
2923-
)
2924-
: from_rep
2925-
(
2926-
representation_type
2927-
(
2928-
number_of_limbs, static_cast<limb_type>(UINT8_C(0)) // LCOV_EXCL_LINE
2929-
)
2930-
)
2931-
|
2932-
(
2933-
uintwide_t(static_cast<std::uint8_t>(UINT8_C(1)))
2934-
<< static_cast<std::uint32_t>(my_width2 - static_cast<std::uint8_t>(UINT8_C(1)))
2935-
)
2936-
;
2894+
uintwide_t result_max { };
2895+
2896+
detail::fill_unsafe(result_max.values.begin(), result_max.values.end(), (std::numeric_limits<limb_type>::max)());
2897+
2898+
constexpr auto high_bit_limb =
2899+
static_cast<limb_type>
2900+
(
2901+
static_cast<limb_type>(UINT8_C(1)) << static_cast<unsigned>(std::numeric_limits<limb_type>::digits - static_cast<int>(INT8_C(1)))
2902+
);
2903+
2904+
result_max.values.back() ^= high_bit_limb;
2905+
2906+
return result_max;
29372907
}
29382908

2939-
static constexpr auto limits_helper_lowest(bool is_signed) -> uintwide_t
2909+
template<const bool OtherIsSigned>
2910+
static constexpr auto limits_helper_min() -> std::enable_if_t<(!OtherIsSigned), uintwide_t>
29402911
{
2941-
return
2942-
(!is_signed)
2943-
? from_rep
2944-
(
2945-
representation_type
2946-
(
2947-
number_of_limbs, static_cast<limb_type>(UINT8_C(0))
2948-
)
2949-
)
2950-
: from_rep
2951-
(
2952-
representation_type
2953-
(
2954-
number_of_limbs, static_cast<limb_type>(UINT8_C(0))
2955-
)
2956-
)
2957-
|
2958-
(
2959-
uintwide_t(static_cast<std::uint8_t>(UINT8_C(1)))
2960-
<< static_cast<std::uint32_t>(my_width2 - static_cast<std::uint8_t>(UINT8_C(1)))
2961-
)
2962-
;
2912+
return uintwide_t { };
2913+
}
2914+
2915+
template<const bool OtherIsSigned>
2916+
static constexpr auto limits_helper_min() -> std::enable_if_t<OtherIsSigned, uintwide_t>
2917+
{
2918+
uintwide_t result_min { };
2919+
2920+
constexpr auto high_bit_limb =
2921+
static_cast<limb_type>
2922+
(
2923+
static_cast<limb_type>(UINT8_C(1)) << static_cast<unsigned>(std::numeric_limits<limb_type>::digits - static_cast<int>(INT8_C(1)))
2924+
);
2925+
2926+
result_min.values.back() |= high_bit_limb;
2927+
2928+
return result_min;
2929+
}
2930+
2931+
template<const bool OtherIsSigned>
2932+
static constexpr auto limits_helper_lowest() -> uintwide_t
2933+
{
2934+
return limits_helper_min<OtherIsSigned>();
29632935
}
29642936

29652937
// Write string function.
@@ -4531,14 +4503,14 @@
45314503
);
45324504

45334505
*r++ = static_cast<local_limb_type>(carry);
4534-
carry = detail::make_hi<local_limb_type>(carry);
4506+
carry = static_cast<local_double_limb_type>(detail::make_hi<local_limb_type>(carry));
45354507
}
45364508

45374509
#if defined(WIDE_INTEGER_HAS_CLZ_LIMB_OPTIMIZATIONS)
45384510
for( ; i < count; ++i)
45394511
{
45404512
*r++ = static_cast<local_limb_type>(carry);
4541-
carry = detail::make_hi<local_limb_type>(static_cast<local_double_limb_type>(UINT8_C(0)));
4513+
carry = static_cast<local_double_limb_type>(UINT8_C(0));
45424514
}
45434515
#endif
45444516
}
@@ -4798,7 +4770,7 @@
47984770
{
47994771
// The denominator is zero. Set the maximum value and return.
48004772
// This also catches (0 / 0) and sets the maximum value for it.
4801-
static_cast<void>(operator=(limits_helper_max(IsSigned))); // LCOV_EXCL_LINE
4773+
static_cast<void>(operator=(limits_helper_max<IsSigned>())); // LCOV_EXCL_LINE
48024774

48034775
if(remainder != nullptr) // LCOV_EXCL_LINE
48044776
{
@@ -5535,9 +5507,9 @@
55355507
static constexpr int max_exponent = digits;
55365508
static constexpr int max_exponent10 = static_cast<int>((static_cast<std::uintmax_t>(max_exponent) * UINTMAX_C(75257499)) / UINTMAX_C(250000000));
55375509

5538-
static constexpr auto (max) () -> local_wide_integer_type { return local_wide_integer_type::limits_helper_max (IsSigned); }
5539-
static constexpr auto (min) () -> local_wide_integer_type { return local_wide_integer_type::limits_helper_min (IsSigned); }
5540-
static constexpr auto lowest() -> local_wide_integer_type { return local_wide_integer_type::limits_helper_lowest(IsSigned); }
5510+
static constexpr auto (max) () -> local_wide_integer_type { return local_wide_integer_type::template limits_helper_max <IsSigned>(); }
5511+
static constexpr auto (min) () -> local_wide_integer_type { return local_wide_integer_type::template limits_helper_min <IsSigned>(); }
5512+
static constexpr auto lowest() -> local_wide_integer_type { return local_wide_integer_type::template limits_helper_lowest<IsSigned>(); }
55415513
};
55425514

55435515
template<class T>

0 commit comments

Comments
 (0)