8#ifndef UINTWIDE_T_2018_10_02_H
9#define UINTWIDE_T_2018_10_02_H
13#if defined(__GNUC__) || defined(__clang__)
14#if defined(WIDE_INTEGER_HAS_LIMB_TYPE_UINT64)
18#if !defined(WIDE_INTEGER_DISABLE_FLOAT_INTEROP)
25#include <initializer_list>
26#if !defined(WIDE_INTEGER_DISABLE_IOSTREAM)
32#if !defined(WIDE_INTEGER_DISABLE_IMPLEMENT_UTIL_DYNAMIC_ARRAY)
35#if !defined(WIDE_INTEGER_DISABLE_IOSTREAM)
41#if (defined(__clang__) && (__clang_major__ <= 9))
42#define WIDE_INTEGER_NUM_LIMITS_CLASS_TYPE struct
44#define WIDE_INTEGER_NUM_LIMITS_CLASS_TYPE class
48#if (_MSC_VER >= 1900) && defined(_HAS_CXX20) && (_HAS_CXX20 != 0)
49#define WIDE_INTEGER_CONSTEXPR constexpr
50#define WIDE_INTEGER_CONSTEXPR_IS_COMPILE_TIME_CONST 1
51#define WIDE_INTEGER_NODISCARD [[nodiscard]]
53#define WIDE_INTEGER_CONSTEXPR
54#define WIDE_INTEGER_CONSTEXPR_IS_COMPILE_TIME_CONST 0
55#define WIDE_INTEGER_NODISCARD
58#if (defined(__cplusplus) && (__cplusplus >= 201402L))
59#if defined(__AVR__) && (!defined(__GNUC__) || (defined(__GNUC__) && (__GNUC__ > 6)))
60#define WIDE_INTEGER_CONSTEXPR constexpr
61#define WIDE_INTEGER_CONSTEXPR_IS_COMPILE_TIME_CONST 1
62#define WIDE_INTEGER_NODISCARD [[nodiscard]]
63#elif (defined(__cpp_lib_constexpr_algorithms) && (__cpp_lib_constexpr_algorithms>=201806))
65#if (__clang_major__ > 9)
66#define WIDE_INTEGER_CONSTEXPR constexpr
67#define WIDE_INTEGER_CONSTEXPR_IS_COMPILE_TIME_CONST 1
68#define WIDE_INTEGER_NODISCARD [[nodiscard]]
70#define WIDE_INTEGER_CONSTEXPR
71#define WIDE_INTEGER_CONSTEXPR_IS_COMPILE_TIME_CONST 0
72#define WIDE_INTEGER_NODISCARD
75#define WIDE_INTEGER_CONSTEXPR constexpr
76#define WIDE_INTEGER_CONSTEXPR_IS_COMPILE_TIME_CONST 1
77#define WIDE_INTEGER_NODISCARD [[nodiscard]]
79#elif (defined(__clang__) && (__clang_major__ >= 10)) && (defined(__cplusplus) && (__cplusplus > 201703L))
80#if defined(__x86_64__)
81#define WIDE_INTEGER_CONSTEXPR constexpr
82#define WIDE_INTEGER_CONSTEXPR_IS_COMPILE_TIME_CONST 1
83#define WIDE_INTEGER_NODISCARD [[nodiscard]]
85#define WIDE_INTEGER_CONSTEXPR
86#define WIDE_INTEGER_CONSTEXPR_IS_COMPILE_TIME_CONST 0
87#define WIDE_INTEGER_NODISCARD
90#define WIDE_INTEGER_CONSTEXPR
91#define WIDE_INTEGER_CONSTEXPR_IS_COMPILE_TIME_CONST 0
92#define WIDE_INTEGER_NODISCARD
95#define WIDE_INTEGER_CONSTEXPR
96#define WIDE_INTEGER_CONSTEXPR_IS_COMPILE_TIME_CONST 0
97#define WIDE_INTEGER_NODISCARD
101#if defined(WIDE_INTEGER_NAMESPACE_BEGIN) || defined(WIDE_INTEGER_NAMESPACE_END)
102#error internal pre-processor macro already defined
105#if defined(WIDE_INTEGER_NAMESPACE)
106#define WIDE_INTEGER_NAMESPACE_BEGIN namespace WIDE_INTEGER_NAMESPACE {
107#define WIDE_INTEGER_NAMESPACE_END }
109#define WIDE_INTEGER_NAMESPACE_BEGIN
110#define WIDE_INTEGER_NAMESPACE_END
113#if !defined(WIDE_INTEGER_DISABLE_IMPLEMENT_UTIL_DYNAMIC_ARRAY)
115WIDE_INTEGER_NAMESPACE_BEGIN
119 template<
typename ValueType,
120 typename AllocatorType = std::allocator<ValueType>,
121 typename SizeType = std::size_t,
122 typename DiffType = std::ptrdiff_t>
125 template<
typename ValueType,
126 typename AllocatorType,
133 using allocator_type =
typename std::allocator_traits<AllocatorType>::template rebind_alloc<ValueType>;
134 using value_type =
typename allocator_type::value_type;
135 using reference = value_type &;
136 using const_reference =
const value_type &;
137 using iterator = value_type *;
138 using const_iterator =
const value_type*;
139 using pointer = value_type *;
140 using const_pointer =
const value_type*;
141 using size_type = SizeType;
142 using difference_type = DiffType;
143 using reverse_iterator = std::reverse_iterator<iterator>;
144 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
150 explicit WIDE_INTEGER_CONSTEXPR
dynamic_array(size_type count,
151 const_reference v = value_type(),
152 const allocator_type& a = allocator_type())
156 allocator_type my_a(a);
160 elems = std::allocator_traits<allocator_type>::allocate(my_a, elem_count);
163 iterator it = begin();
167 std::allocator_traits<allocator_type>::construct(my_a, it, v);
174 : elem_count(other.size()),
181 elems = std::allocator_traits<allocator_type>::allocate(my_a, elem_count);
184 std::copy(other.elems, other.elems + elem_count, elems);
187 template<
typename input_iterator>
190 const allocator_type& a = allocator_type())
191 : elem_count(
static_cast<size_type
>(std::distance(first, last))),
194 allocator_type my_a(a);
198 elems = std::allocator_traits<allocator_type>::allocate(my_a, elem_count);
201 std::copy(first, last, elems);
204 WIDE_INTEGER_CONSTEXPR
dynamic_array(std::initializer_list<value_type> lst,
205 const allocator_type& a = allocator_type())
206 : elem_count(lst.size()),
209 allocator_type my_a(a);
213 elems = std::allocator_traits<allocator_type>::allocate(my_a, elem_count);
216 std::copy(lst.begin(), lst.end(), elems);
223 other.elem_count = 0U;
224 other.elems =
nullptr;
232 using local_allocator_traits_type = std::allocator_traits<allocator_type>;
236 while (p != elems + elem_count)
238 local_allocator_traits_type::destroy(my_a, p);
244 local_allocator_traits_type::deallocate(my_a, elems, elem_count);
252 std::copy(other.elems,
253 other.elems + (std::min)(elem_count, other.elem_count),
266 using local_allocator_traits_type = std::allocator_traits<allocator_type>;
270 while (p != elems + elem_count)
272 local_allocator_traits_type::destroy(my_a, p);
277 local_allocator_traits_type::deallocate(my_a, elems, elem_count);
279 elem_count = other.elem_count;
282 other.elem_count = 0U;
283 other.elems =
nullptr;
289 WIDE_INTEGER_CONSTEXPR
auto begin() -> iterator {
return elems; }
290 WIDE_INTEGER_CONSTEXPR
auto end() -> iterator {
return elems + elem_count; }
291 WIDE_INTEGER_CONSTEXPR
auto begin()
const -> const_iterator {
return elems; }
292 WIDE_INTEGER_CONSTEXPR
auto end()
const -> const_iterator {
return elems + elem_count; }
293 WIDE_INTEGER_CONSTEXPR
auto cbegin()
const -> const_iterator {
return elems; }
294 WIDE_INTEGER_CONSTEXPR
auto cend()
const -> const_iterator {
return elems + elem_count; }
295 WIDE_INTEGER_CONSTEXPR
auto rbegin() -> reverse_iterator {
return reverse_iterator(elems + elem_count); }
296 WIDE_INTEGER_CONSTEXPR
auto rend() -> reverse_iterator {
return reverse_iterator(elems); }
297 WIDE_INTEGER_CONSTEXPR
auto rbegin()
const -> const_reverse_iterator {
return const_reverse_iterator(elems + elem_count); }
298 WIDE_INTEGER_CONSTEXPR
auto rend()
const -> const_reverse_iterator {
return const_reverse_iterator(elems); }
299 WIDE_INTEGER_CONSTEXPR
auto crbegin()
const -> const_reverse_iterator {
return const_reverse_iterator(elems + elem_count); }
300 WIDE_INTEGER_CONSTEXPR
auto crend()
const -> const_reverse_iterator {
return const_reverse_iterator(elems); }
303 WIDE_INTEGER_CONSTEXPR
auto data() -> pointer {
return elems; }
304 WIDE_INTEGER_CONSTEXPR
auto data()
const -> const_pointer {
return elems; }
307 constexpr auto size()
const -> size_type {
return elem_count; }
308 constexpr auto max_size()
const -> size_type {
return elem_count; }
309 constexpr auto empty()
const ->
bool {
return (elem_count == 0U); }
312 WIDE_INTEGER_CONSTEXPR
auto operator[](
const size_type i) -> reference {
return elems[i]; }
313 WIDE_INTEGER_CONSTEXPR
auto operator[](
const size_type i)
const -> const_reference {
return elems[i]; }
315 WIDE_INTEGER_CONSTEXPR
auto front() -> reference {
return elems[0U]; }
316 WIDE_INTEGER_CONSTEXPR
auto front()
const -> const_reference {
return elems[0U]; }
318 WIDE_INTEGER_CONSTEXPR
auto back() -> reference {
return ((elem_count >
static_cast<size_type
>(0U)) ? elems[elem_count - 1U] : elems[0U]); }
319 WIDE_INTEGER_CONSTEXPR
auto back()
const -> const_reference {
return ((elem_count >
static_cast<size_type
>(0U)) ? elems[elem_count - 1U] : elems[0U]); }
321 WIDE_INTEGER_CONSTEXPR
auto at(
const size_type i) -> reference {
return ((i < elem_count) ? elems[i] : elems[0U]); }
322 WIDE_INTEGER_CONSTEXPR
auto at(
const size_type i)
const -> const_reference {
return ((i < elem_count) ? elems[i] : elems[0U]); }
325 WIDE_INTEGER_CONSTEXPR
void fill(
const value_type& v)
327 std::fill_n(begin(), elem_count, v);
334 pointer tmp_elems = elems;
337 other.elems = tmp_elems;
339 std::swap(elem_count, other.elem_count);
345 pointer tmp_elems = elems;
348 other.elems = tmp_elems;
350 std::swap(elem_count, other.elem_count);
354 mutable size_type elem_count;
358 template<
typename ValueType,
typename AllocatorType>
362 bool left_and_right_are_equal =
false;
364 const bool sizes_are_equal = (lhs.size() == rhs.size());
368 using size_type =
typename dynamic_array<ValueType, AllocatorType>::size_type;
370 const bool size_of_left_is_zero = (lhs.size() ==
static_cast<size_type
>(0U));
372 left_and_right_are_equal =
373 (size_of_left_is_zero || std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin()));
380 return left_and_right_are_equal;
383 template<
typename ValueType,
typename AllocatorType>
384 WIDE_INTEGER_CONSTEXPR
auto operator<(
const dynamic_array<ValueType, AllocatorType>& lhs,
385 const dynamic_array<ValueType, AllocatorType>& rhs) ->
bool
387 using size_type =
typename dynamic_array<ValueType, AllocatorType>::size_type;
389 const bool size_of_left_is_zero = (lhs.size() ==
static_cast<size_type
>(0U));
393 if (size_of_left_is_zero)
395 const bool size_of_right_is_zero = (rhs.size() ==
static_cast<size_type
>(0U));
397 b_result = (!size_of_right_is_zero);
401 if (size_of_left_is_zero)
403 const bool size_of_right_is_zero = (rhs.size() ==
static_cast<size_type
>(0U));
405 b_result = (!size_of_right_is_zero);
409 const size_type count = (std::min)(lhs.size(), rhs.size());
411 b_result = std::lexicographical_compare(lhs.cbegin(),
412 lhs.cbegin() + count,
414 rhs.cbegin() + count);
421 template<
typename ValueType,
typename AllocatorType>
422 WIDE_INTEGER_CONSTEXPR
auto operator!=(
const dynamic_array<ValueType, AllocatorType>& lhs,
423 const dynamic_array<ValueType, AllocatorType>& rhs) ->
bool
425 return (!(lhs == rhs));
428 template<
typename ValueType,
typename AllocatorType>
429 WIDE_INTEGER_CONSTEXPR
auto operator>(
const dynamic_array<ValueType, AllocatorType>& lhs,
430 const dynamic_array<ValueType, AllocatorType>& rhs) ->
bool
435 template<
typename ValueType,
typename AllocatorType>
436 WIDE_INTEGER_CONSTEXPR
auto operator>=(
const dynamic_array<ValueType, AllocatorType>& lhs,
437 const dynamic_array<ValueType, AllocatorType>& rhs) ->
bool
439 return (!(lhs < rhs));
442 template<
typename ValueType,
typename AllocatorType>
443 WIDE_INTEGER_CONSTEXPR
auto operator<=(
const dynamic_array<ValueType, AllocatorType>& lhs,
444 const dynamic_array<ValueType, AllocatorType>& rhs) ->
bool
446 return (!(rhs < lhs));
449 template<
typename ValueType,
typename AllocatorType>
450 WIDE_INTEGER_CONSTEXPR
void swap(dynamic_array<ValueType, AllocatorType>& x,
451 dynamic_array<ValueType, AllocatorType>& y)
458WIDE_INTEGER_NAMESPACE_END
460WIDE_INTEGER_NAMESPACE_BEGIN
462#if(__cplusplus >= 201703L)
463namespace math::wide_integer::detail {
466 namespace wide_integer {
472#if(__cplusplus >= 201703L)
480WIDE_INTEGER_NAMESPACE_END
484#include <util/utility/util_dynamic_array.h>
486WIDE_INTEGER_NAMESPACE_BEGIN
488#if(__cplusplus >= 201703L)
489namespace math::wide_integer::detail {
492 namespace wide_integer {
498#if(__cplusplus >= 201703L)
506WIDE_INTEGER_NAMESPACE_END
510WIDE_INTEGER_NAMESPACE_BEGIN
512#if(__cplusplus >= 201703L)
513namespace math::wide_integer {
516 namespace wide_integer {
521 using size_t = std::uint32_t;
522 using ptrdiff_t = std::int32_t;
524 static_assert(((std::numeric_limits<size_t>::digits >= std::numeric_limits<std::uint16_t>::digits)
525 && (std::numeric_limits<ptrdiff_t>::digits + 1 >= std::numeric_limits<std::uint16_t>::digits)),
526 "Error: size type and pointer difference type must be at least 16 bits in width (or wider)");
531 static constexpr bool conditional_value =
532 (Width2 ==
static_cast<size_t>(1ULL << 0U)) || (Width2 ==
static_cast<size_t>(1ULL << 1U)) || (Width2 ==
static_cast<size_t>(1ULL << 2U)) || (Width2 ==
static_cast<size_t>(1ULL << 3U))
533 || (Width2 ==
static_cast<size_t>(1ULL << 4U)) || (Width2 ==
static_cast<size_t>(1ULL << 5U)) || (Width2 ==
static_cast<size_t>(1ULL << 6U)) || (Width2 ==
static_cast<size_t>(1ULL << 7U))
534 || (Width2 ==
static_cast<size_t>(1ULL << 8U)) || (Width2 ==
static_cast<size_t>(1ULL << 9U)) || (Width2 ==
static_cast<size_t>(1ULL << 10U)) || (Width2 ==
static_cast<size_t>(1ULL << 11U))
535 || (Width2 ==
static_cast<size_t>(1ULL << 12U)) || (Width2 ==
static_cast<size_t>(1ULL << 13U)) || (Width2 ==
static_cast<size_t>(1ULL << 14U)) || (Width2 ==
static_cast<size_t>(1ULL << 15U))
536 || (Width2 ==
static_cast<size_t>(1ULL << 16U)) || (Width2 ==
static_cast<size_t>(1ULL << 17U)) || (Width2 ==
static_cast<size_t>(1ULL << 18U)) || (Width2 ==
static_cast<size_t>(1ULL << 19U))
537 || (Width2 ==
static_cast<size_t>(1ULL << 20U)) || (Width2 ==
static_cast<size_t>(1ULL << 21U)) || (Width2 ==
static_cast<size_t>(1ULL << 22U)) || (Width2 ==
static_cast<size_t>(1ULL << 23U))
538 || (Width2 ==
static_cast<size_t>(1ULL << 24U)) || (Width2 ==
static_cast<size_t>(1ULL << 25U)) || (Width2 ==
static_cast<size_t>(1ULL << 26U)) || (Width2 ==
static_cast<size_t>(1ULL << 27U))
539 || (Width2 ==
static_cast<size_t>(1ULL << 28U)) || (Width2 ==
static_cast<size_t>(1ULL << 29U)) || (Width2 ==
static_cast<size_t>(1ULL << 30U)) || (Width2 ==
static_cast<size_t>(1ULL << 31U))
543 template<
const size_t BitCount,
544 typename EnableType =
void>
547#if defined(WIDE_INTEGER_HAS_LIMB_TYPE_UINT64)
548 static_assert((((BitCount >= 8U) && (BitCount <= 128U))
550 "Error: uint_type_helper is not intended to be used for this BitCount");
552 static_assert((((BitCount >= 8U) && (BitCount <= 64U))
554 "Error: uint_type_helper is not intended to be used for this BitCount");
557 using exact_unsigned_type = std::uintmax_t;
560 template<const
size_t BitCount>
struct uint_type_helper<BitCount, typename std::enable_if< (BitCount <= 8U)>::type> {
using exact_unsigned_type = std::uint8_t;
using fast_unsigned_type = std::uint_fast8_t;
using fast_signed_type = std::int_fast8_t; };
561 template<const
size_t BitCount>
struct uint_type_helper<BitCount, typename std::enable_if<(BitCount >= 9U) && (BitCount <= 16U)>::type> {
using exact_unsigned_type = std::uint16_t;
using fast_unsigned_type = std::uint_fast16_t;
using fast_signed_type = std::int_fast16_t; };
562 template<const
size_t BitCount>
struct uint_type_helper<BitCount, typename std::enable_if<(BitCount >= 17U) && (BitCount <= 32U)>::type> {
using exact_unsigned_type = std::uint32_t;
using fast_unsigned_type = std::uint_fast32_t;
using fast_signed_type = std::int_fast32_t; };
563 template<const
size_t BitCount>
struct uint_type_helper<BitCount, typename std::enable_if<(BitCount >= 33U) && (BitCount <= 64U)>::type> {
using exact_unsigned_type = std::uint64_t;
using fast_unsigned_type = std::uint_fast64_t;
using fast_signed_type = std::int_fast64_t; };
564#if defined(WIDE_INTEGER_HAS_LIMB_TYPE_UINT64)
565 template<const
size_t BitCount>
struct uint_type_helper<BitCount, typename std::enable_if<(BitCount >= 65U) && (BitCount <= 128U)>::type> {
using exact_unsigned_type =
unsigned __int128;
using fast_unsigned_type =
unsigned __int128;
using fast_signed_type =
signed __int128; };
568 using unsigned_fast_type =
typename uint_type_helper<static_cast<size_t>(std::numeric_limits<size_t >::digits + 0)>::fast_unsigned_type;
569 using signed_fast_type =
typename uint_type_helper<static_cast<size_t>(std::numeric_limits<ptrdiff_t>::digits + 1)>::fast_signed_type;
571#if !defined(WIDE_INTEGER_DISABLE_FLOAT_INTEROP)
574 template<
typename FloatingPo
intType> WIDE_INTEGER_CONSTEXPR
auto frexp(FloatingPointType x,
int* expptr) ->
typename std::enable_if<((std::is_floating_point<FloatingPointType>::value) && (std::numeric_limits<FloatingPointType>::is_iec559)), FloatingPointType>::type;
575 template<
typename FloatingPo
intType> WIDE_INTEGER_CONSTEXPR
auto frexp(FloatingPointType x,
int* expptr) ->
typename std::enable_if<((std::is_floating_point<FloatingPointType>::value) && (!std::numeric_limits<FloatingPointType>::is_iec559)), FloatingPointType>::type;
576 template<
typename FloatingPo
intType> WIDE_INTEGER_CONSTEXPR
auto isfinite(FloatingPointType x) ->
typename std::enable_if<((std::is_floating_point<FloatingPointType>::value) && (std::numeric_limits<FloatingPointType>::is_iec559)),
bool>::type;
577 template<
typename FloatingPo
intType> WIDE_INTEGER_CONSTEXPR
auto isfinite(FloatingPointType x) ->
typename std::enable_if<((std::is_floating_point<FloatingPointType>::value) && (!std::numeric_limits<FloatingPointType>::is_iec559)),
bool>::type;
584 using detail::size_t;
585 using detail::ptrdiff_t;
586 using detail::unsigned_fast_type;
587 using detail::signed_fast_type;
590 template<
const size_t Width2,
591 typename LimbType = std::uint32_t,
592 typename AllocatorType = void,
593 const bool IsSigned =
false>
597 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator+(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v)->uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
598 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator-(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v)->uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
599 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator*(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v)->uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
600 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator/(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v)->uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
601 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator%(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v)->uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
604 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator| (
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v)->uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
605 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator^ (
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v)->uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
606 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator& (
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v)->uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
609 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator+(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
610 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator-(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
611 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator*(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
612 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator/(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
614 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
615 constexpr auto operator%(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<((std::is_integral<IntegralType>::value)
616 && (!std::is_unsigned<IntegralType>::value)),
617 uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
619 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
620 WIDE_INTEGER_CONSTEXPR
auto operator%(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<((std::is_integral <IntegralType>::value)
621 && (std::is_unsigned <IntegralType>::value)
622 && (std::numeric_limits<IntegralType>::digits <= std::numeric_limits<LimbType>::digits)),
623 typename uintwide_t<Width2, LimbType, AllocatorType, IsSigned>::limb_type>::type;
625 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
626 constexpr auto operator%(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<((std::is_integral <IntegralType>::value)
627 && (std::is_unsigned <IntegralType>::value)
628 && (std::numeric_limits<IntegralType>::digits > std::numeric_limits<LimbType>::digits)),
629 uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
632 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator+(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
633 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator-(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
634 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator*(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
635 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator/(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
636 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator%(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
638#if !defined(WIDE_INTEGER_DISABLE_FLOAT_INTEROP)
640 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator+(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const FloatingPointType& f) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
641 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator-(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const FloatingPointType& f) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
642 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator*(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const FloatingPointType& f) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
643 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator/(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const FloatingPointType& f) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
644 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator%(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const FloatingPointType& f) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
647 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator+(
const FloatingPointType& f,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
648 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator-(
const FloatingPointType& f,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
649 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator*(
const FloatingPointType& f,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
650 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator/(
const FloatingPointType& f,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
651 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator%(
const FloatingPointType& f,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
655 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator|(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
656 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator^(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
657 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator&(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
660 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator|(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
661 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator^(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
662 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator&(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
665 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator<<(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType n) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
666 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator>>(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType n) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type;
669 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator==(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) -> bool;
670 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator!=(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) -> bool;
671 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator> (
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) -> bool;
672 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator< (
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) -> bool;
673 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator>=(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) -> bool;
674 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator<=(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) -> bool;
677 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator==(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type;
678 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator!=(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type;
679 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator> (
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type;
680 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator< (
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type;
681 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator>=(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type;
682 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator<=(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type;
685 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator==(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type;
686 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator!=(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type;
687 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator> (
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type;
688 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator< (
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type;
689 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator>=(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type;
690 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator<=(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type;
692#if !defined(WIDE_INTEGER_DISABLE_FLOAT_INTEROP)
694 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator==(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const FloatingPointType& f) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type;
695 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator!=(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const FloatingPointType& f) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type;
696 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator> (
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const FloatingPointType& f) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type;
697 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator< (
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const FloatingPointType& f) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type;
698 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator>=(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const FloatingPointType& f) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type;
699 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator<=(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const FloatingPointType& f) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type;
702 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator==(
const FloatingPointType& f,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type;
703 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator!=(
const FloatingPointType& f,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type;
704 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator> (
const FloatingPointType& f,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type;
705 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator< (
const FloatingPointType& f,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type;
706 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator>=(
const FloatingPointType& f,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type;
707 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator<=(
const FloatingPointType& f,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type;
710#if !defined(WIDE_INTEGER_DISABLE_IOSTREAM)
713 template<
typename char_type,
714 typename traits_type,
717 typename AllocatorType,
719 auto operator<<(std::basic_ostream<char_type, traits_type>& out,
720 const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& x)->std::basic_ostream<char_type, traits_type> &;
722 template<
typename char_type,
723 typename traits_type,
726 typename AllocatorType,
728 auto operator>>(std::basic_istream<char_type, traits_type>& in,
729 uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& x)->std::basic_istream<char_type, traits_type> &;
734 template<
const size_t Width2,
736 typename AllocatorType,
738 WIDE_INTEGER_CONSTEXPR
void swap(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& x,
739 uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& y);
741 template<
const size_t Width2,
743 typename AllocatorType,
745 WIDE_INTEGER_CONSTEXPR
auto lsb(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& x)->unsigned_fast_type;
747 template<
const size_t Width2,
749 typename AllocatorType,
751 WIDE_INTEGER_CONSTEXPR
auto msb(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& x)->unsigned_fast_type;
753 template<
const size_t Width2,
755 typename AllocatorType,
757 constexpr auto abs(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& x)->uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
759 template<
const size_t Width2,
761 typename AllocatorType,
763 WIDE_INTEGER_CONSTEXPR
auto sqrt(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& m)->uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
765 template<
const size_t Width2,
767 typename AllocatorType,
769 WIDE_INTEGER_CONSTEXPR
auto cbrt(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& m)->uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
771 template<
const size_t Width2,
773 typename AllocatorType,
775 WIDE_INTEGER_CONSTEXPR
auto rootk(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& m,
const std::uint_fast8_t k)->uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
777 template<
typename OtherUnsignedIntegralTypeP,
780 typename AllocatorType,
782 WIDE_INTEGER_CONSTEXPR
auto pow(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& b,
const OtherUnsignedIntegralTypeP& p)->uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
784 template<
typename OtherUnsignedIntegralTypeP,
785 typename OtherUnsignedIntegralTypeM,
788 typename AllocatorType,
790 WIDE_INTEGER_CONSTEXPR
auto powm(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& b,
791 const OtherUnsignedIntegralTypeP& p,
792 const OtherUnsignedIntegralTypeM& m)->uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
794 template<
const size_t Width2,
796 typename AllocatorType,
798 WIDE_INTEGER_CONSTEXPR
auto gcd(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& a,
799 const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& b)->uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
801 template<
typename Un
signedShortType>
802 WIDE_INTEGER_CONSTEXPR
auto gcd(
const UnsignedShortType& u,
const UnsignedShortType& v) ->
typename std::enable_if<((std::is_integral<UnsignedShortType>::value)
803 && (std::is_unsigned<UnsignedShortType>::value)), UnsignedShortType>::type;
805 template<
const size_t Width2,
807 typename AllocatorType,
809 WIDE_INTEGER_CONSTEXPR
auto lcm(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& a,
810 const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& b)->uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
812 template<
typename Un
signedShortType>
813 WIDE_INTEGER_CONSTEXPR
auto lcm(
const UnsignedShortType& a,
const UnsignedShortType& b) ->
typename std::enable_if<((std::is_integral<UnsignedShortType>::value)
814 && (std::is_unsigned<UnsignedShortType>::value)), UnsignedShortType>::type;
816 template<
const size_t Width2,
817 typename LimbType = std::uint32_t,
818 typename AllocatorType = void,
819 const bool IsSigned =
false>
822 template<
const size_t Width2,
823 typename LimbType = std::uint32_t,
824 typename AllocatorType = void,
825 const bool IsSigned =
false>
828 template<
const size_t Width2,
830 typename AllocatorType,
835 template<
const size_t Width2,
837 typename AllocatorType,
842 template<
typename DistributionType,
843 typename GeneratorType,
846 typename AllocatorType,
849 const unsigned_fast_type number_of_trials,
850 DistributionType& distribution,
851 GeneratorType& generator) -> bool;
853#if(__cplusplus >= 201703L)
860WIDE_INTEGER_NAMESPACE_END
865#if defined(WIDE_INTEGER_NAMESPACE)
866 template<
const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t Width2,
868 typename AllocatorType,
870 WIDE_INTEGER_NUM_LIMITS_CLASS_TYPE numeric_limits<WIDE_INTEGER_NAMESPACE::math::wide_integer::uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>;
872 template<const ::math::wide_integer::size_t Width2,
874 typename AllocatorType,
876 WIDE_INTEGER_NUM_LIMITS_CLASS_TYPE numeric_limits<::math::wide_integer::uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>;
880WIDE_INTEGER_NAMESPACE_BEGIN
882#if(__cplusplus >= 201703L)
883namespace math::wide_integer::detail {
886 namespace wide_integer {
890 template<
typename MyType,
899 static constexpr auto static_size() ->
typename base_class_type::size_type {
return MySize; }
901 explicit WIDE_INTEGER_CONSTEXPR
fixed_dynamic_array(
const typename base_class_type::size_type s = MySize,
902 const typename base_class_type::value_type& v =
typename base_class_type::value_type(),
903 const typename base_class_type::allocator_type& a =
typename base_class_type::allocator_type())
906 std::fill(base_class_type::begin(),
907 base_class_type::begin() + (std::min)(MySize,
static_cast<typename base_class_type::size_type
>(s)),
914 WIDE_INTEGER_CONSTEXPR
fixed_dynamic_array(std::initializer_list<typename base_class_type::value_type> lst)
917 std::copy(lst.begin(),
918 lst.begin() + (std::min)(
static_cast<typename base_class_type::size_type
>(lst.size()), MySize),
919 base_class_type::begin());
927 base_class_type::operator=(
static_cast<const base_class_type&
>(other_array));
934 base_class_type::operator=(
static_cast<base_class_type&&
>(other_array));
942 template<
typename MyType,
947 using base_class_type = std::array<MyType, static_cast<std::size_t>(MySize)>;
950 using size_type = size_t;
951 using value_type =
typename base_class_type::value_type;
953 static constexpr auto static_size() -> size_type {
return MySize; }
958 const value_type& v = value_type())
960 if (s < static_size())
962 std::fill(base_class_type::begin(), base_class_type::begin() + s, v);
963 std::fill(base_class_type::begin() + s, base_class_type::end(), value_type());
967 base_class_type::fill(v);
974 WIDE_INTEGER_CONSTEXPR
fixed_static_array(std::initializer_list<typename base_class_type::value_type> lst)
976 const auto size_to_copy =
977 (std::min)(
static_cast<size_type
>(lst.size()),
978 static_cast<size_type
>(MySize));
980 if (size_to_copy <
static_cast<size_type
>(base_class_type::size()))
982 std::copy(lst.begin(),
983 lst.begin() + size_to_copy,
984 base_class_type::begin());
986 std::fill(base_class_type::begin() + size_to_copy,
987 base_class_type::end(),
988 static_cast<typename base_class_type::value_type
>(0U));
992 std::copy(lst.begin(),
993 lst.begin() + size_to_copy,
994 base_class_type::begin());
1000 WIDE_INTEGER_CONSTEXPR
auto operator=(
const fixed_static_array& other_array)->fixed_static_array & =
default;
1001 WIDE_INTEGER_CONSTEXPR
auto operator=(
fixed_static_array&& other_array)
noexcept->fixed_static_array & =
default;
1003 WIDE_INTEGER_CONSTEXPR
auto operator[](
const size_type i) ->
typename base_class_type::reference {
return base_class_type::operator[](
static_cast<typename base_class_type::size_type
>(i)); }
1004 WIDE_INTEGER_CONSTEXPR
auto operator[](
const size_type i)
const ->
typename base_class_type::const_reference {
return base_class_type::operator[](
static_cast<typename base_class_type::size_type
>(i)); }
1010 static constexpr bool conditional_value =
1029 template<
typename Un
signedIntegralType>
1030 inline WIDE_INTEGER_CONSTEXPR
auto lsb_helper(
const UnsignedIntegralType& u)->unsigned_fast_type;
1032 template<
typename Un
signedIntegralType>
1033 inline WIDE_INTEGER_CONSTEXPR
auto msb_helper(
const UnsignedIntegralType& u)->unsigned_fast_type;
1036 inline WIDE_INTEGER_CONSTEXPR
auto msb_helper<std::uint32_t>(
const std::uint32_t& u)->unsigned_fast_type;
1039 inline WIDE_INTEGER_CONSTEXPR
auto msb_helper<std::uint16_t>(
const std::uint16_t& u)->unsigned_fast_type;
1042 inline WIDE_INTEGER_CONSTEXPR
auto msb_helper<std::uint8_t>(
const std::uint8_t& u)->unsigned_fast_type;
1045 inline WIDE_INTEGER_CONSTEXPR
auto strcpy_unsafe(
char* dst,
const char* src) ->
char*
1047 while ((*dst++ = *src++) !=
static_cast<char>(
'\0')) { ; }
1053 inline WIDE_INTEGER_CONSTEXPR
auto strlen_unsafe(
const char* p_str) -> unsigned_fast_type
1055 const char* p_str_copy{};
1057 for (p_str_copy = p_str; (*p_str_copy !=
static_cast<char>(
'\0')); ++p_str_copy) { ; }
1059 return static_cast<unsigned_fast_type
>(p_str_copy - p_str);
1062 template<
typename UnsignedShortType,
1063 typename UnsignedLargeType =
typename detail::uint_type_helper<static_cast<size_t>(std::numeric_limits<UnsignedShortType>::digits * 2)>::exact_unsigned_type>
1064 constexpr auto make_lo(
const UnsignedLargeType & u) -> UnsignedShortType
1070 using local_ushort_type = UnsignedShortType;
1071 using local_ularge_type = UnsignedLargeType;
1074#if defined(WIDE_INTEGER_HAS_LIMB_TYPE_UINT64)
1075 static_assert(((
sizeof(local_ushort_type) * 2U) ==
sizeof(local_ularge_type)),
1076 "Error: Please check the characteristics of the template parameters UnsignedShortType and UnsignedLargeType");
1078 static_assert(((std::numeric_limits<local_ushort_type>::is_integer)
1079 && (std::numeric_limits<local_ularge_type>::is_integer)
1080 && (!std::numeric_limits<local_ushort_type>::is_signed)
1081 && (!std::numeric_limits<local_ularge_type>::is_signed)
1082 && ((
sizeof(local_ushort_type) * 2U) ==
sizeof(local_ularge_type))),
1083 "Error: Please check the characteristics of the template parameters UnsignedShortType and UnsignedLargeType");
1086 return static_cast<local_ushort_type
>(u);
1089 template<
typename UnsignedShortType,
1090 typename UnsignedLargeType =
typename detail::uint_type_helper<static_cast<size_t>(std::numeric_limits<UnsignedShortType>::digits * 2)>::exact_unsigned_type>
1091 constexpr auto make_hi(
const UnsignedLargeType & u) -> UnsignedShortType
1097 using local_ushort_type = UnsignedShortType;
1098 using local_ularge_type = UnsignedLargeType;
1101#if defined(WIDE_INTEGER_HAS_LIMB_TYPE_UINT64)
1102 static_assert(((
sizeof(local_ushort_type) * 2U) ==
sizeof(local_ularge_type)),
1103 "Error: Please check the characteristics of the template parameters UnsignedShortType and UnsignedLargeType");
1105 static_assert(((std::numeric_limits<local_ushort_type>::is_integer)
1106 && (std::numeric_limits<local_ularge_type>::is_integer)
1107 && (!std::numeric_limits<local_ushort_type>::is_signed)
1108 && (!std::numeric_limits<local_ularge_type>::is_signed)
1109 && ((
sizeof(local_ushort_type) * 2U) ==
sizeof(local_ularge_type))),
1110 "Error: Please check the characteristics of the template parameters UnsignedShortType and UnsignedLargeType");
1113 return static_cast<local_ushort_type
>(u >>
static_cast<local_ushort_type
>(std::numeric_limits<local_ushort_type>::digits));
1116 template<
typename UnsignedShortType,
1117 typename UnsignedLargeType =
typename detail::uint_type_helper<static_cast<size_t>(std::numeric_limits<UnsignedShortType>::digits * 2)>::exact_unsigned_type>
1118 constexpr auto make_large(
const UnsignedShortType & lo,
const UnsignedShortType & hi) -> UnsignedLargeType
1124 using local_ushort_type = UnsignedShortType;
1125 using local_ularge_type = UnsignedLargeType;
1128#if defined(WIDE_INTEGER_HAS_LIMB_TYPE_UINT64)
1129 static_assert(((
sizeof(local_ushort_type) * 2U) ==
sizeof(local_ularge_type)),
1130 "Error: Please check the characteristics of the template parameters UnsignedShortType and UnsignedLargeType");
1132 static_assert(((std::numeric_limits<local_ushort_type>::is_integer)
1133 && (std::numeric_limits<local_ularge_type>::is_integer)
1134 && (!std::numeric_limits<local_ushort_type>::is_signed)
1135 && (!std::numeric_limits<local_ularge_type>::is_signed)
1136 && ((
sizeof(local_ushort_type) * 2U) ==
sizeof(local_ularge_type))),
1137 "Error: Please check the characteristics of the template parameters UnsignedShortType and UnsignedLargeType");
1140 return static_cast<local_ularge_type
>(
static_cast<local_ularge_type
>(
static_cast<local_ularge_type
>(hi) <<
static_cast<unsigned>(std::numeric_limits<UnsignedShortType>::digits)) | lo);
1143 template<
typename Un
signedIntegralType>
1144 constexpr auto negate(UnsignedIntegralType u) ->
typename std::enable_if< (std::is_integral<UnsignedIntegralType>::value)
1145 && (std::is_unsigned<UnsignedIntegralType>::value), UnsignedIntegralType>::type
1147 return static_cast<UnsignedIntegralType
>((
static_cast<UnsignedIntegralType
>(~u)) + 1U);
1150 template<
typename SignedIntegralType>
1151 constexpr auto negate(SignedIntegralType n) ->
typename std::enable_if< (std::is_integral<SignedIntegralType>::value)
1152 && (std::is_signed <SignedIntegralType>::value), SignedIntegralType>::type
1154 using local_unsigned_type =
1155 typename detail::uint_type_helper<static_cast<size_t>(std::numeric_limits<SignedIntegralType>::digits + 1)>::exact_unsigned_type;
1157 return static_cast<SignedIntegralType
>(negate(
static_cast<local_unsigned_type
>(n)));
1160#if !defined(WIDE_INTEGER_DISABLE_FLOAT_INTEROP)
1161 template<
typename FloatingPo
intType>
1169 : my_mantissa_part(0ULL),
1172 using native_float_type = FloatingPointType;
1174 static_assert(std::numeric_limits<native_float_type>::digits <= std::numeric_limits<unsigned long long>::digits,
1175 "Error: The width of the mantissa does not fit in unsigned long long");
1177 const native_float_type ff = ((f < static_cast<native_float_type>(0)) ? -f : f);
1179 if (ff < (std::numeric_limits<native_float_type>::min)())
1184 using my_own::frexp;
1187 auto man =
static_cast<native_float_type
>(frexp(f, &my_exponent_part));
1191 for (
auto i =
static_cast<std::uint_fast16_t
>(0U); i < static_cast<std::uint_fast16_t>(std::numeric_limits<native_float_type>::digits); ++i)
1197 n2 =
static_cast<unsigned>(man);
1198 man -=
static_cast<native_float_type
>(n2);
1200 if (n2 !=
static_cast<unsigned>(0U))
1202 my_mantissa_part |= 1U;
1205 if (i <
static_cast<unsigned>(std::numeric_limits<native_float_type>::digits - 1))
1207 my_mantissa_part <<= 1U;
1212 my_mantissa_part |=
static_cast<unsigned long long>(1ULL <<
static_cast<unsigned>(std::numeric_limits<native_float_type>::digits - 1));
1213 my_exponent_part -= 1;
1217 my_exponent_part(other.my_exponent_part) { }
1220 my_exponent_part(other.my_exponent_part) { }
1228 my_mantissa_part = other.my_mantissa_part;
1229 my_exponent_part = other.my_exponent_part;
1237 my_mantissa_part = other.my_mantissa_part;
1238 my_exponent_part = other.my_exponent_part;
1243 WIDE_INTEGER_NODISCARD WIDE_INTEGER_CONSTEXPR
auto get_mantissa()
const ->
unsigned long long {
return my_mantissa_part; }
1244 WIDE_INTEGER_NODISCARD WIDE_INTEGER_CONSTEXPR
auto get_exponent()
const ->
int {
return my_exponent_part; }
1249 unsigned long long my_mantissa_part;
1250 int my_exponent_part;
1254#if(__cplusplus >= 201703L)
1262#if(__cplusplus >= 201703L)
1263namespace math::wide_integer {
1266 namespace wide_integer {
1269 template<
const size_t Width2,
1271 typename AllocatorType,
1272 const bool IsSigned>
1276 template<
const size_t OtherWidth2,
1277 typename OtherLimbType,
1278 typename OtherAllocatorType,
1279 const bool OtherIsSigned>
1283 using limb_type = LimbType;
1285 using double_limb_type =
1290 using ushort_type = limb_type;
1291 using ularge_type = double_limb_type;
1294#if defined(WIDE_INTEGER_HAS_LIMB_TYPE_UINT64)
1295 static_assert(((
sizeof(limb_type) * 2U) ==
sizeof(double_limb_type)),
1296 "Error: Please check the characteristics of the template parameters UnsignedShortType and UnsignedLargeType");
1298 static_assert(((std::numeric_limits<limb_type>::is_integer)
1299 && (std::numeric_limits<double_limb_type>::is_integer)
1300 && (!std::numeric_limits<limb_type>::is_signed)
1301 && (!std::numeric_limits<double_limb_type>::is_signed)
1302 && ((
sizeof(limb_type) * 2U) ==
sizeof(double_limb_type))),
1303 "Error: Please check the characteristics of the template parameters UnsignedShortType and UnsignedLargeType");
1307 static constexpr size_t my_width2 = Width2;
1310 static constexpr size_t number_of_limbs =
1311 static_cast<size_t>(my_width2 /
static_cast<size_t>(std::numeric_limits<limb_type>::digits));
1313 static constexpr size_t number_of_limbs_karatsuba_threshold =
static_cast<size_t>(128U + 1U);
1320 && (my_width2 >= 16U)
1321 && (my_width2 == (number_of_limbs *
static_cast<size_t>(std::numeric_limits<limb_type>::digits))),
1322 "Error: Width2 must be 2^n times 1...63 (with n >= 3), while being 16, 24, 32 or larger, and exactly divisible by limb count");
1325 using representation_type =
1326 typename std::conditional
1327 <std::is_same<AllocatorType, void>::value,
1332 typename std::allocator_traits<typename std::conditional<std::is_same<AllocatorType, void>::value,
1333 std::allocator<void>,
1334 AllocatorType>::type>::template rebind_alloc<limb_type>>
1338 using iterator =
typename representation_type::iterator;
1339 using const_iterator =
typename representation_type::const_iterator;
1340 using reverse_iterator =
typename representation_type::reverse_iterator;
1341 using const_reverse_iterator =
typename representation_type::const_reverse_iterator;
1351 template<
typename Un
signedIntegralType>
1352 constexpr uintwide_t(
const UnsignedIntegralType v,
1353 typename std::enable_if<((std::is_integral <UnsignedIntegralType>::value)
1354 && (std::is_unsigned <UnsignedIntegralType>::value)
1355 && (std::numeric_limits<UnsignedIntegralType>::digits <= std::numeric_limits<limb_type>::digits))>::type* =
nullptr)
1361 template<
typename Un
signedIntegralType>
1362 WIDE_INTEGER_CONSTEXPR
uintwide_t(
const UnsignedIntegralType v,
1363 typename std::enable_if<((std::is_integral <UnsignedIntegralType>::value)
1364 && (std::is_unsigned <UnsignedIntegralType>::value)
1365 && (std::numeric_limits<UnsignedIntegralType>::digits > std::numeric_limits<limb_type>::digits))>::type* p_nullparam =
nullptr)
1367 static_cast<void>(p_nullparam ==
nullptr);
1369 auto right_shift_amount_v =
static_cast<unsigned_fast_type
>(0U);
1370 auto index_u =
static_cast<std::uint_fast8_t
> (0U);
1372 for (; ((index_u < values.size())
1373 && (right_shift_amount_v <
static_cast<unsigned_fast_type
>(std::numeric_limits<UnsignedIntegralType>::digits)));
1376 *(values.begin() +
static_cast<size_t>(index_u)) =
static_cast<limb_type
>(v >>
static_cast<unsigned>(right_shift_amount_v));
1378 right_shift_amount_v +=
static_cast<unsigned_fast_type
>(std::numeric_limits<limb_type>::digits);
1381 std::fill(values.begin() + index_u, values.end(),
static_cast<limb_type
>(0U));
1385 template<
typename SignedIntegralType>
1386 WIDE_INTEGER_CONSTEXPR
uintwide_t(
const SignedIntegralType v,
1387 typename std::enable_if<((std::is_integral<SignedIntegralType>::value)
1388 && (std::is_signed <SignedIntegralType>::value))>::type* p_nullparam =
nullptr)
1390 static_cast<void>(p_nullparam ==
nullptr);
1392 using local_signed_integral_type = SignedIntegralType;
1393 using local_unsigned_integral_type =
1396 const bool v_is_neg = (v < static_cast<local_signed_integral_type>(0));
1398 const local_unsigned_integral_type u =
1399 ((!v_is_neg) ?
static_cast<local_unsigned_integral_type
>(v)
1400 :
static_cast<local_unsigned_integral_type
>(detail::negate(v)));
1404 if (v_is_neg) { negate(); }
1407#if !defined(WIDE_INTEGER_DISABLE_FLOAT_INTEROP)
1408 template<
typename FloatingPointType,
1409 typename std::enable_if<(std::is_floating_point<FloatingPointType>::value)>::type
const* =
nullptr>
1410 WIDE_INTEGER_CONSTEXPR
uintwide_t(
const FloatingPointType f)
1412 using local_builtin_float_type = FloatingPointType;
1414 using detail::my_own::isfinite;
1422 const bool f_is_neg = (f < static_cast<local_builtin_float_type>(0.0F));
1424 const local_builtin_float_type a = ((!f_is_neg) ? f : -f);
1426 const bool a_is_zero = (a < static_cast<local_builtin_float_type>(1.0F));
1438 const int p2 = ld_parts.get_exponent() - (std::numeric_limits<FloatingPointType>::digits - 1);
1440 if (p2 < 0) { *
this >>=
static_cast<unsigned>(-p2); }
1441 else if (p2 == 0) { ; }
1442 else { *this <<= static_cast<unsigned>(p2); }
1458#if !defined(WIDE_INTEGER_DISABLE_TRIVIAL_COPY_AND_STD_LAYOUT_CHECKS)
1465 template<
const bool OtherIsSigned,
1466 typename std::enable_if<(OtherIsSigned != IsSigned)>::type
const* =
nullptr>
1468 : values(other.values) { }
1472 template<
const size_t OtherWidth2,
1473 const bool OtherIsSigned,
1474 typename std::enable_if<(Width2 < OtherWidth2)>::type
const* =
nullptr>
1479 const bool v_is_neg = (other_wide_integer_type::is_neg(v));
1481 constexpr auto sz =
static_cast<size_t>(number_of_limbs);
1485 std::copy(v.crepresentation().cbegin(),
1486 v.crepresentation().cbegin() + sz,
1491 const other_wide_integer_type uv(-v);
1493 std::copy(uv.crepresentation().cbegin(),
1494 uv.crepresentation().cbegin() + sz,
1503 template<
const size_t OtherWidth2,
1504 const bool OtherIsSigned,
1505 typename std::enable_if<(Width2 > OtherWidth2)>::type
const* =
nullptr>
1510 const bool v_is_neg = (other_wide_integer_type::is_neg(v));
1512 constexpr auto sz =
static_cast<size_t>(other_wide_integer_type::number_of_limbs);
1516 std::copy(v.crepresentation().cbegin(),
1517 v.crepresentation().cbegin() + sz,
1520 std::fill(values.begin() + sz, values.end(),
static_cast<limb_type
>(0U));
1524 const other_wide_integer_type uv(-v);
1526 std::copy(uv.crepresentation().cbegin(),
1527 uv.crepresentation().cbegin() + sz,
1530 std::fill(values.begin() + sz, values.end(),
static_cast<limb_type
>(0U));
1537 WIDE_INTEGER_CONSTEXPR
uintwide_t(
const char* str_input)
1539 if (!rd_string(str_input))
1541 std::fill(values.begin(), values.end(), (std::numeric_limits<limb_type>::max)());
1550 template<
const bool OtherIsSigned,
1551 typename std::enable_if<(IsSigned != OtherIsSigned)>::type
const* =
nullptr>
1553 : values(
static_cast<representation_type&&
>(other.values)) { }
1559 WIDE_INTEGER_CONSTEXPR
auto operator=(
const uintwide_t& other)->uintwide_t & =
default;
1562 template<
const bool OtherIsSigned,
1563 typename std::enable_if<(OtherIsSigned != IsSigned)>::type
const* =
nullptr>
1566 values = other.values;
1572 WIDE_INTEGER_CONSTEXPR
auto operator=(
uintwide_t&& other)
noexcept->uintwide_t & =
default;
1575 template<
const bool OtherIsSigned,
1576 typename std::enable_if<(IsSigned != OtherIsSigned)>::type
const* =
nullptr>
1579 values =
static_cast<representation_type&&
>(other.values);
1584#if !defined(WIDE_INTEGER_DISABLE_FLOAT_INTEROP)
1585 explicit constexpr operator long double()
const {
return extract_builtin_floating_point_type<long double>(); }
1586 explicit constexpr operator double()
const {
return extract_builtin_floating_point_type<double>(); }
1587 explicit constexpr operator float()
const {
return extract_builtin_floating_point_type<float>(); }
1590 template<
typename IntegralType,
1591 typename =
typename std::enable_if<std::is_integral<IntegralType>::value>::type>
1592 explicit constexpr operator IntegralType()
const
1594 using local_integral_type = IntegralType;
1596 return ((!is_neg(*
this))
1597 ? extract_builtin_integral_type<local_integral_type>()
1598 : detail::negate((-*
this).
template extract_builtin_integral_type<local_integral_type>()));
1602 explicit constexpr operator bool()
const {
return (!is_zero()); }
1606 template<
const size_t OtherWidth2,
1607 const bool OtherIsSigned,
1611 const bool this_is_neg = (is_neg(*
this));
1618 (Width2 < OtherWidth2) ? static_cast<size_t>(number_of_limbs)
1619 :
static_cast<size_t>(other_wide_integer_type::number_of_limbs)
1622 other_wide_integer_type other;
1626 std::copy(crepresentation().cbegin(),
1627 crepresentation().cbegin() + sz,
1628 other.values.begin());
1630 if (Width2 < OtherWidth2)
1632 std::fill(other.values.begin() + sz, other.values.end(),
static_cast<limb_type
>(0U));
1637 other_wide_integer_type uv(*
this);
1641 std::copy(uv.crepresentation().cbegin(),
1642 uv.crepresentation().cbegin() + sz,
1643 other.values.begin());
1645 if (Width2 < OtherWidth2)
1647 std::fill(other.values.begin() + sz, other.values.end(),
static_cast<limb_type
>(0U));
1658 template<
const bool OtherIsSigned,
1664 other_wide_integer_type other;
1666 std::copy(crepresentation().cbegin(),
1667 crepresentation().cend(),
1668 other.representation().begin());
1674 WIDE_INTEGER_CONSTEXPR
auto representation() -> representation_type & {
return values; }
1675 WIDE_INTEGER_NODISCARD WIDE_INTEGER_CONSTEXPR
auto representation()
const ->
const representation_type & {
return values; }
1676 WIDE_INTEGER_NODISCARD WIDE_INTEGER_CONSTEXPR
auto crepresentation()
const ->
const representation_type & {
return values; }
1679 WIDE_INTEGER_CONSTEXPR
auto operator+()
const ->
const uintwide_t & {
return *
this; }
1680 WIDE_INTEGER_CONSTEXPR
auto operator-()
const ->
uintwide_t {
uintwide_t tmp(*
this); tmp.negate();
return tmp; }
1689 const limb_type carry = eval_add_n(values.data(),
1692 static_cast<unsigned_fast_type
>(number_of_limbs),
1693 static_cast<limb_type
>(0U));
1695 static_cast<void>(carry);
1700 const limb_type carry = eval_add_n(values.data(),
1702 other.values.data(),
1703 static_cast<unsigned_fast_type
>(number_of_limbs),
1704 static_cast<limb_type
>(0U));
1706 static_cast<void>(carry);
1721 const limb_type has_borrow = eval_subtract_n(values.data(),
1723 other.values.data(),
1727 static_cast<void>(has_borrow);
1739 eval_mul_unary(*
this, other_as_self_copy);
1743 eval_mul_unary(*
this, other);
1749 WIDE_INTEGER_CONSTEXPR
auto mul_by_limb(
const limb_type v) ->
uintwide_t &
1751 if (v ==
static_cast<limb_type
>(0U))
1755 else if (v >
static_cast<limb_type
>(1U))
1757 static_cast<void>(eval_multiply_1d(values.data(),
1770 values.front() = 1U;
1772 std::fill(values.begin() + 1U, values.end(),
static_cast<limb_type
>(0U));
1774 else if (other.is_zero())
1776 *
this = limits_helper_max(IsSigned);
1782 const bool numererator_was_neg = is_neg(*
this);
1783 const bool denominator_was_neg = is_neg(other);
1785 if (numererator_was_neg || denominator_was_neg)
1789 local_unsigned_wide_type a(*
this);
1790 local_unsigned_wide_type b(other);
1792 if (numererator_was_neg) { a.negate(); }
1793 if (denominator_was_neg) { b.negate(); }
1795 a.eval_divide_knuth(b,
nullptr);
1797 if (numererator_was_neg != denominator_was_neg) { a.negate(); }
1803 eval_divide_knuth(other,
nullptr);
1814 std::fill(values.begin(), values.end(),
static_cast<limb_type
>(0U));
1819 const bool numererator_was_neg = is_neg(*
this);
1820 const bool denominator_was_neg = is_neg(other);
1822 if (numererator_was_neg || denominator_was_neg)
1826 local_unsigned_wide_type a(*
this);
1827 local_unsigned_wide_type b(other);
1829 if (numererator_was_neg) { a.negate(); }
1830 if (denominator_was_neg) { b.negate(); }
1832 local_unsigned_wide_type remainder;
1834 a.eval_divide_knuth(b, &remainder);
1837 if (numererator_was_neg) { remainder.negate(); }
1839 values = remainder.values;
1845 eval_divide_knuth(other, &remainder);
1847 values = remainder.values;
1855 WIDE_INTEGER_CONSTEXPR
auto operator++() ->
uintwide_t & { preincrement();
return *
this; }
1856 WIDE_INTEGER_CONSTEXPR
auto operator--() ->
uintwide_t & { predecrement();
return *
this; }
1859 WIDE_INTEGER_CONSTEXPR
auto operator++(
int) ->
uintwide_t {
const uintwide_t w(*
this); preincrement();
return w; }
1860 WIDE_INTEGER_CONSTEXPR
auto operator--(
int) ->
uintwide_t {
const uintwide_t w(*
this); predecrement();
return w; }
1862 WIDE_INTEGER_CONSTEXPR
auto operator~() ->
uintwide_t &
1875 for (
auto i =
static_cast<unsigned_fast_type
>(0U); i < number_of_limbs; ++i)
1877 *(values.begin() +
static_cast<size_t>(i)) =
static_cast<limb_type
>(*(values.cbegin() +
static_cast<size_t>(i)) | *(other.values.cbegin() +
static_cast<size_t>(i)));
1893 for (
auto i =
static_cast<unsigned_fast_type
>(0U); i < number_of_limbs; ++i)
1895 *(values.begin() +
static_cast<size_t>(i)) =
static_cast<limb_type
>(*(values.cbegin() +
static_cast<size_t>(i)) ^ *(other.values.cbegin() +
static_cast<size_t>(i)));
1907 for (
auto i =
static_cast<unsigned_fast_type
>(0U); i < number_of_limbs; ++i)
1909 *(values.begin() +
static_cast<size_t>(i)) =
static_cast<limb_type
>(*(values.cbegin() +
static_cast<size_t>(i)) & *(other.values.cbegin() +
static_cast<size_t>(i)));
1916 template<
typename SignedIntegralType>
1917 WIDE_INTEGER_CONSTEXPR
auto operator<<=(
const SignedIntegralType n) ->
typename std::enable_if<((std::is_integral<SignedIntegralType>::value)
1918 && (std::is_signed <SignedIntegralType>::value)),
uintwide_t>::type &
1923 using local_unsigned_type =
1926 operator>>=(
static_cast<local_unsigned_type
>(detail::negate(n)));
1932 else if (
static_cast<unsigned_fast_type
>(n) >= my_width2)
1934 std::fill(values.begin(), values.end(),
static_cast<limb_type
>(0U));
1938 const auto offset =
static_cast<unsigned_fast_type
>(
static_cast<unsigned_fast_type
>(n) /
static_cast<unsigned_fast_type
>(std::numeric_limits<limb_type>::digits));
1939 const auto left_shift_amount =
static_cast<std::uint_fast16_t
>(
static_cast<unsigned_fast_type
>(n) %
static_cast<unsigned_fast_type
>(std::numeric_limits<limb_type>::digits));
1941 shl(offset, left_shift_amount);
1947 template<
typename Un
signedIntegralType>
1948 WIDE_INTEGER_CONSTEXPR
auto operator<<=(
const UnsignedIntegralType n) ->
typename std::enable_if<((std::is_integral<UnsignedIntegralType>::value)
1949 && (!std::is_signed <UnsignedIntegralType>::value)),
uintwide_t>::type &
1956 else if (
static_cast<unsigned_fast_type
>(n) >= my_width2)
1958 std::fill(values.begin(), values.end(),
static_cast<limb_type
>(0U));
1962 const auto offset =
static_cast<unsigned_fast_type
>(
static_cast<unsigned_fast_type
>(n) /
static_cast<unsigned_fast_type
>(std::numeric_limits<limb_type>::digits));
1963 const auto left_shift_amount =
static_cast<std::uint_fast16_t
>(
static_cast<unsigned_fast_type
>(n) %
static_cast<unsigned_fast_type
>(std::numeric_limits<limb_type>::digits));
1965 shl(offset, left_shift_amount);
1971 template<
typename SignedIntegralType>
1972 WIDE_INTEGER_CONSTEXPR
auto operator>>=(
const SignedIntegralType n) ->
typename std::enable_if<((std::is_integral<SignedIntegralType>::value)
1973 && (std::is_signed <SignedIntegralType>::value)),
uintwide_t>::type &
1978 using local_unsigned_type =
1981 operator<<=(static_cast<local_unsigned_type>(detail::negate(n)));
1987 else if (
static_cast<unsigned_fast_type
>(n) >= my_width2)
1993 std::fill(values.begin(), values.end(),
static_cast<limb_type
>(0U));
1997 std::fill(values.begin(), values.end(), (std::numeric_limits<limb_type>::max)());
2002 const auto offset =
static_cast<unsigned_fast_type
>(
static_cast<unsigned_fast_type
>(n) /
static_cast<unsigned_fast_type
>(std::numeric_limits<limb_type>::digits));
2003 const auto right_shift_amount =
static_cast<std::uint_fast16_t
>(
static_cast<unsigned_fast_type
>(n) %
static_cast<unsigned_fast_type
>(std::numeric_limits<limb_type>::digits));
2005 shr(offset, right_shift_amount);
2011 template<
typename Un
signedIntegralType>
2012 WIDE_INTEGER_CONSTEXPR
auto operator>>=(
const UnsignedIntegralType n) ->
typename std::enable_if<((std::is_integral<UnsignedIntegralType>::value)
2013 && (!std::is_signed <UnsignedIntegralType>::value)),
uintwide_t>::type &
2020 else if (
static_cast<unsigned_fast_type
>(n) >= my_width2)
2022 std::fill(values.begin(), values.end(),
static_cast<limb_type
>(0U));
2026 const auto offset =
static_cast<unsigned_fast_type
>(
static_cast<unsigned_fast_type
>(n) /
static_cast<unsigned_fast_type
>(std::numeric_limits<limb_type>::digits));
2027 const auto right_shift_amount =
static_cast<std::uint_fast16_t
>(
static_cast<unsigned_fast_type
>(n) %
static_cast<unsigned_fast_type
>(std::numeric_limits<limb_type>::digits));
2029 shr(offset, right_shift_amount);
2036 constexpr auto operator==(
const uintwide_t& other)
const ->
bool {
return (compare(other) ==
static_cast<std::int_fast8_t
>(0)); }
2037 constexpr auto operator< (
const uintwide_t& other)
const ->
bool {
return (compare(other) ==
static_cast<std::int_fast8_t
>(-1)); }
2038 constexpr auto operator> (
const uintwide_t& other)
const ->
bool {
return (compare(other) ==
static_cast<std::int_fast8_t
>(1)); }
2039 constexpr auto operator!=(
const uintwide_t& other)
const ->
bool {
return (compare(other) !=
static_cast<std::int_fast8_t
>(0)); }
2040 constexpr auto operator<=(
const uintwide_t& other)
const ->
bool {
return (compare(other) <=
static_cast<std::int_fast8_t
>(0)); }
2041 constexpr auto operator>=(
const uintwide_t& other)
const ->
bool {
return (compare(other) >=
static_cast<std::int_fast8_t
>(0)); }
2044 static constexpr auto limits_helper_max(
bool is_signed) ->
uintwide_t
2052 number_of_limbs, (std::numeric_limits<limb_type>::max)()
2059 number_of_limbs, (std::numeric_limits<limb_type>::max)()
2065 static constexpr auto limits_helper_min(
bool is_signed) ->
uintwide_t
2073 number_of_limbs,
static_cast<limb_type
>(0U)
2080 number_of_limbs,
static_cast<limb_type
>(0U)
2086 static constexpr auto limits_helper_min() ->
uintwide_t
2088 return uintwide_t(representation_type(number_of_limbs,
static_cast<limb_type
>(0U)));
2091 static constexpr auto limits_helper_lowest(
bool is_signed) ->
uintwide_t
2099 number_of_limbs,
static_cast<limb_type
>(0U)
2106 number_of_limbs,
static_cast<limb_type
>(0U)
2114 static constexpr auto wr_string_max_buffer_size_oct =
2119 + (((my_width2 % 3U) != 0U) ? 1U : 0U)
2124 static constexpr auto wr_string_max_buffer_size_hex =
2129 + (((my_width2 % 4U) != 0U) ? 1U : 0U)
2134 static constexpr auto wr_string_max_buffer_size_dec =
2139 +
static_cast<size_t>((
static_cast<std::uintmax_t
>(my_width2) * UINTMAX_C(301)) / UINTMAX_C(1000))
2144 WIDE_INTEGER_CONSTEXPR
auto wr_string(
char* str_result,
2145 const std::uint_fast8_t base_rep = 0x10U,
2146 const bool show_base =
true,
2147 const bool show_pos =
false,
2148 const bool is_uppercase =
true,
2149 unsigned_fast_type field_width = 0U,
2150 const char fill_char =
static_cast<char>(
'0'))
const ->
bool
2152 bool wr_string_is_ok =
true;
2154 if (base_rep == UINT8_C(8))
2158 const auto mask =
static_cast<limb_type
>(
static_cast<std::uint8_t
>(0x7U));
2160 using string_storage_oct_type =
2161 typename std::conditional
2162 <my_width2 <= static_cast<size_t>(UINT32_C(2048)),
2164 wr_string_max_buffer_size_oct>,
2166 wr_string_max_buffer_size_oct,
2167 typename std::allocator_traits<typename std::conditional<std::is_same<AllocatorType, void>::value,
2168 std::allocator<void>,
2169 AllocatorType>::type>::template rebind_alloc<limb_type>>
2172 string_storage_oct_type str_temp;
2174 auto pos =
static_cast<unsigned_fast_type
>(str_temp.size() - 1U);
2180 str_temp[
static_cast<typename string_storage_oct_type::size_type
>(pos)] =
static_cast<char>(
'0');
2186 while (!t.is_zero())
2188 auto c =
static_cast<char>(*t.values.cbegin() & mask);
2190 if (c <=
static_cast<char>(INT8_C(8))) { c =
static_cast<char>(c +
static_cast<char>(INT8_C(0x30))); }
2194 str_temp[
static_cast<typename string_storage_oct_type::size_type
>(pos)] = c;
2203 while (!tu.is_zero())
2205 auto c =
static_cast<char>(*tu.values.cbegin() & mask);
2207 if (c <=
static_cast<char>(INT8_C(8))) { c =
static_cast<char>(c +
static_cast<char>(INT8_C(0x30))); }
2211 str_temp[
static_cast<typename string_storage_oct_type::size_type
>(pos)] = c;
2222 str_temp[
static_cast<typename string_storage_oct_type::size_type
>(pos)] =
static_cast<char>(
'0');
2229 str_temp[
static_cast<typename string_storage_oct_type::size_type
>(pos)] =
static_cast<char>(
'+');
2232 if (field_width != 0U)
2234 field_width = (std::min)(field_width,
static_cast<unsigned_fast_type
>(str_temp.size() - 1U));
2236 while (
static_cast<signed_fast_type
>(pos) >
static_cast<signed_fast_type
>((str_temp.size() - 1U) - field_width))
2240 str_temp[
static_cast<typename string_storage_oct_type::size_type
>(pos)] = fill_char;
2244 str_temp[
static_cast<typename string_storage_oct_type::size_type
>(str_temp.size() - 1U)] =
static_cast<char>(
'\0');
2246 detail::strcpy_unsafe(str_result, str_temp.data() + pos);
2248 else if (base_rep == UINT8_C(10))
2252 const bool str_has_neg_sign = is_neg(t);
2254 if (str_has_neg_sign)
2259 using string_storage_dec_type =
2260 typename std::conditional
2261 <my_width2 <= static_cast<size_t>(UINT32_C(2048)),
2263 wr_string_max_buffer_size_dec>,
2265 wr_string_max_buffer_size_dec,
2266 typename std::allocator_traits<typename std::conditional<std::is_same<AllocatorType, void>::value,
2267 std::allocator<void>,
2268 AllocatorType>::type>::template rebind_alloc<limb_type>>
2271 string_storage_dec_type str_temp;
2273 auto pos =
static_cast<unsigned_fast_type
>(str_temp.size() - 1U);
2279 str_temp[
static_cast<typename string_storage_dec_type::size_type
>(pos)] =
static_cast<char>(
'0');
2283 while (!t.is_zero())
2287 t.eval_divide_by_single_limb(
static_cast<limb_type
>(UINT8_C(10)), 0U,
nullptr);
2291 str_temp[
static_cast<typename string_storage_dec_type::size_type
>(pos)] =
2294 static_cast<limb_type
>
2296 tmp - (
uintwide_t(t).mul_by_limb(
static_cast<limb_type
>(UINT8_C(10))))
2303 if (show_pos && (!str_has_neg_sign))
2307 str_temp[
static_cast<typename string_storage_dec_type::size_type
>(pos)] =
static_cast<char>(
'+');
2309 else if (str_has_neg_sign)
2313 str_temp[
static_cast<typename string_storage_dec_type::size_type
>(pos)] =
static_cast<char>(
'-');
2316 if (field_width != 0U)
2318 field_width = (std::min)(field_width,
static_cast<unsigned_fast_type
>(str_temp.size() - 1U));
2320 while (
static_cast<signed_fast_type
>(pos) >
static_cast<signed_fast_type
>((str_temp.size() - 1U) - field_width))
2324 str_temp[
static_cast<typename string_storage_dec_type::size_type
>(pos)] = fill_char;
2328 str_temp[
static_cast<typename string_storage_dec_type::size_type
>(str_temp.size() - 1U)] =
static_cast<char>(
'\0');
2330 detail::strcpy_unsafe(str_result, str_temp.data() + pos);
2332 else if (base_rep == UINT8_C(16))
2336 const auto mask =
static_cast<limb_type
>(
static_cast<std::uint8_t
>(0xFU));
2338 using string_storage_hex_type =
2339 typename std::conditional
2340 <my_width2 <= static_cast<size_t>(UINT32_C(2048)),
2342 wr_string_max_buffer_size_hex>,
2344 wr_string_max_buffer_size_hex,
2345 typename std::allocator_traits<typename std::conditional<std::is_same<AllocatorType, void>::value,
2346 std::allocator<void>,
2347 AllocatorType>::type>::template rebind_alloc<limb_type>>
2350 string_storage_hex_type str_temp;
2352 auto pos =
static_cast<unsigned_fast_type
>(str_temp.size() - 1U);
2358 str_temp[
static_cast<typename string_storage_hex_type::size_type
>(pos)] =
static_cast<char>(
'0');
2364 while (!t.is_zero())
2366 char c(*t.values.cbegin() & mask);
2368 if (c <=
static_cast<char>(INT8_C(9))) { c =
static_cast<char>(c +
static_cast<char>(INT8_C(0x30))); }
2369 else if ((c >=
static_cast<char>(INT8_C(0xA))) && (c <=
static_cast<char>(INT8_C(0xF)))) { c =
static_cast<char>(c + (is_uppercase ?
static_cast<char>(INT8_C(55)) :
static_cast<char>(INT8_C(87)))); }
2373 str_temp[
static_cast<typename string_storage_hex_type::size_type
>(pos)] = c;
2382 while (!tu.is_zero())
2384 char c(*tu.values.cbegin() & mask);
2386 if (c <=
static_cast<char>(INT8_C(9))) { c =
static_cast<char>(c +
static_cast<char>(INT8_C(0x30))); }
2387 else if ((c >=
static_cast<char>(INT8_C(0xA))) && (c <=
static_cast<char>(INT8_C(0xF)))) { c =
static_cast<char>(c + (is_uppercase ?
static_cast<char>(INT8_C(55)) :
static_cast<char>(INT8_C(87)))); }
2391 str_temp[
static_cast<typename string_storage_hex_type::size_type
>(pos)] = c;
2402 str_temp[
static_cast<typename string_storage_hex_type::size_type
>(pos)] = (is_uppercase ?
static_cast<char>(
'X') :
static_cast<char>(
'x'));
2406 str_temp[
static_cast<typename string_storage_hex_type::size_type
>(pos)] =
static_cast<char>(
'0');
2413 str_temp[
static_cast<typename string_storage_hex_type::size_type
>(pos)] =
static_cast<char>(
'+');
2416 if (field_width != 0U)
2418 field_width = (std::min)(field_width,
static_cast<unsigned_fast_type
>(str_temp.size() - 1U));
2420 while (
static_cast<signed_fast_type
>(pos) >
static_cast<signed_fast_type
>((str_temp.size() - 1U) - field_width))
2424 str_temp[
static_cast<typename string_storage_hex_type::size_type
>(pos)] = fill_char;
2428 str_temp[
static_cast<typename string_storage_hex_type::size_type
>(str_temp.size() - 1U)] =
static_cast<char>(
'\0');
2430 detail::strcpy_unsafe(str_result, str_temp.data() + pos);
2434 wr_string_is_ok =
false;
2437 return wr_string_is_ok;
2440 template<
const bool RePhraseIsSigned = IsSigned,
2441 typename std::enable_if<(!RePhraseIsSigned)>::type
const* =
nullptr>
2444 return compare_ranges(values.data(),
2445 other.values.data(),
2449 template<
const bool RePhraseIsSigned = IsSigned,
2450 typename std::enable_if<(RePhraseIsSigned)>::type
const* =
nullptr>
2453 const bool other_is_neg = is_neg(other);
2459 : (other_is_neg ? INT8_C(1)
2464 WIDE_INTEGER_CONSTEXPR
void negate()
2471 WIDE_INTEGER_CONSTEXPR
void eval_divide_by_single_limb(
const limb_type short_denominator,
2472 const unsigned_fast_type u_offset,
2478 auto long_numerator =
static_cast<double_limb_type
>(0U);
2480 auto hi_part =
static_cast<limb_type
>(0U);
2482 for (
auto i =
static_cast<signed_fast_type
>(
static_cast<unsigned_fast_type
>(number_of_limbs - 1U) - u_offset);
static_cast<signed_fast_type
>(i) >= 0; --i)
2485 static_cast<double_limb_type
>
2487 static_cast<double_limb_type
>(*(values.cbegin() +
static_cast<size_t>(i)))
2488 +
static_cast<double_limb_type
>(
static_cast<double_limb_type
>(long_numerator -
static_cast<double_limb_type
>(
static_cast<double_limb_type
>(short_denominator) * hi_part)) <<
static_cast<unsigned>(std::numeric_limits<limb_type>::digits))
2491 *(values.begin() +
static_cast<size_t>(i)) =
2492 detail::make_lo<limb_type>(
static_cast<double_limb_type
>(long_numerator / short_denominator));
2494 hi_part = *(values.cbegin() +
static_cast<size_t>(i));
2497 if (remainder !=
nullptr)
2500 static_cast<double_limb_type
>
2502 static_cast<double_limb_type
>(*values.cbegin())
2503 +
static_cast<double_limb_type
>(
static_cast<double_limb_type
>(long_numerator -
static_cast<double_limb_type
>(
static_cast<double_limb_type
>(short_denominator) * hi_part)) <<
static_cast<unsigned>(std::numeric_limits<limb_type>::digits))
2506 *remainder =
static_cast<limb_type
>(long_numerator >>
static_cast<unsigned>(std::numeric_limits<limb_type>::digits));
2510 WIDE_INTEGER_NODISCARD WIDE_INTEGER_CONSTEXPR
auto is_zero()
const ->
bool
2512 auto it = values.cbegin();
2514 while ((it != values.cend()) && (*it ==
static_cast<limb_type
>(0U)))
2519 return (it == values.cend());
2522 template<
const bool RePhraseIsSigned = IsSigned,
2523 typename std::enable_if<(!RePhraseIsSigned)>::type
const* =
nullptr>
2529 template<
const bool RePhraseIsSigned = IsSigned,
2530 typename std::enable_if<(RePhraseIsSigned)>::type
const* =
nullptr>
2533 return (
static_cast<std::uint_fast8_t
>(
static_cast<std::uint_fast8_t
>(a.values.back() >>
static_cast<size_t>(std::numeric_limits<
typename uintwide_t<Width2, LimbType, AllocatorType, RePhraseIsSigned>::limb_type>::digits - 1)) & 1U) != 0U);
2536 static constexpr auto from_rep(
const representation_type& other_rep) ->
uintwide_t
2539 return uintwide_t(
static_cast<const representation_type&
>(other_rep));
2542 static constexpr auto from_rep(representation_type&& other_rep) ->
uintwide_t
2545 return uintwide_t(
static_cast<representation_type&&
>(other_rep));
2549 representation_type values{ };
2551 explicit constexpr uintwide_t(
const representation_type& other_rep)
2552 : values(
static_cast<const representation_type&
>(other_rep)) { }
2554 explicit constexpr uintwide_t(representation_type&& other_rep)
2555 : values(
static_cast<representation_type&&
>(other_rep)) { }
2557 template<
typename InputIteratorLeftType,
2558 typename InputIteratorRightType>
2559 static WIDE_INTEGER_CONSTEXPR
auto compare_ranges(InputIteratorLeftType a,
2560 InputIteratorRightType b,
2561 const unsigned_fast_type count) -> std::int_fast8_t
2563 std::int_fast8_t n_return = 0;
2565 std::reverse_iterator<InputIteratorLeftType> pa(a + count);
2566 std::reverse_iterator<InputIteratorRightType> pb(b + count);
2568 for (; pa != std::reverse_iterator<InputIteratorLeftType>(a); ++pa, ++pb)
2570 using value_left_type =
2571 typename std::iterator_traits<InputIteratorLeftType>::value_type;
2573 if (*pa >
static_cast<value_left_type
>(*pb)) { n_return = 1;
break; }
2574 if (*pa <
static_cast<value_left_type
>(*pb)) { n_return = -1;
break; }
2580 template<
typename UnknownBuiltInIntegralType>
2583 using local_unknown_builtin_integral_type = UnknownBuiltInIntegralType;
2585 using local_unsigned_conversion_type =
2587 std::numeric_limits<local_unknown_builtin_integral_type>::is_signed
2588 ?
static_cast<size_t>(std::numeric_limits<local_unknown_builtin_integral_type>::digits + 1)
2589 :
static_cast<size_t>(std::numeric_limits<local_unknown_builtin_integral_type>::digits + 0)>::exact_unsigned_type;
2591 static constexpr unsigned_fast_type value =
2592 static_cast<unsigned_fast_type
>(std::numeric_limits<local_unsigned_conversion_type>::digits
2593 / std::numeric_limits<limb_type>::digits);
2595 template<
typename InputIteratorLeft>
2596 static WIDE_INTEGER_CONSTEXPR
auto extract(InputIteratorLeft p_limb, unsigned_fast_type limb_count) -> local_unknown_builtin_integral_type
2598 using local_limb_type =
typename std::iterator_traits<InputIteratorLeft>::value_type;
2599 using left_difference_type =
typename std::iterator_traits<InputIteratorLeft>::difference_type;
2601 auto u =
static_cast<local_unsigned_conversion_type
>(0U);
2603 for (
auto i =
static_cast<unsigned_fast_type
>(0U); i < limb_count; ++i)
2606 static_cast<local_unsigned_conversion_type
>
2609 |
static_cast<local_unsigned_conversion_type
>(
static_cast<local_unsigned_conversion_type
>(*(p_limb +
static_cast<left_difference_type
>(i))) <<
static_cast<unsigned>(std::numeric_limits<local_limb_type>::digits *
static_cast<int>(i)))
2613 return static_cast<local_unknown_builtin_integral_type
>(u);
2618 template<
typename UnknownBuiltInIntegralType,
2619 typename =
typename std::enable_if<std::is_integral<UnknownBuiltInIntegralType>::value>::type>
2620 WIDE_INTEGER_NODISCARD WIDE_INTEGER_CONSTEXPR
auto extract_builtin_integral_type()
const -> UnknownBuiltInIntegralType
2622 using local_unknown_integral_type = UnknownBuiltInIntegralType;
2623 using digits_ratio_type = digits_ratio<local_unknown_integral_type>;
2625 const unsigned_fast_type ilim = (std::min)(
static_cast<unsigned_fast_type
>(digits_ratio_type::value),
2626 static_cast<unsigned_fast_type
>(values.size()));
2630 return ((digits_ratio_type::value < 2U)
2631 ?
static_cast<local_unknown_integral_type
>(*values.cbegin())
2632 : digits_ratio_type::extract(values.data(), ilim));
2635#if !defined(WIDE_INTEGER_DISABLE_FLOAT_INTEROP)
2637 template<
typename FloatingPointType,
2638 typename =
typename std::enable_if<std::is_floating_point<FloatingPointType>::value>::type>
2639 WIDE_INTEGER_NODISCARD WIDE_INTEGER_CONSTEXPR
auto extract_builtin_floating_point_type()
const -> FloatingPointType
2642 using local_builtin_float_type = FloatingPointType;
2644 const bool u_is_neg = is_neg(*
this);
2646 const local_unsigned_wide_integer_type u((!u_is_neg) ? *
this : -*
this);
2648 const auto my_msb =
static_cast<size_t>(msb(u));
2649 const auto ilim =
static_cast<size_t>
2651 static_cast<size_t>(
static_cast<size_t>(my_msb + 1U) /
static_cast<size_t>(std::numeric_limits<limb_type>::digits))
2652 +
static_cast<size_t>(((
static_cast<size_t>(my_msb + 1U) %
static_cast<size_t>(std::numeric_limits<limb_type>::digits)) != 0U) ?
static_cast<size_t>(1U) :
static_cast<size_t>(0U))
2655 auto a =
static_cast<local_builtin_float_type
>(0.0F);
2657 constexpr long double one_ldbl(1.0L);
2659 long double ldexp_runner(one_ldbl);
2661 for (
auto i =
static_cast<size_t>(0U); i < ilim; ++i)
2663 auto ld =
static_cast<long double>(0.0L);
2664 auto lm_mask =
static_cast<limb_type
>(1ULL);
2666 for (
auto j =
static_cast<size_t>(0U); j < static_cast<size_t>(std::numeric_limits<limb_type>::digits); ++j)
2668 if (
static_cast<limb_type
>(*(u.values.cbegin() +
static_cast<size_t>(i)) & lm_mask) !=
static_cast<limb_type
>(0U))
2670 ld =
static_cast<long double>(ld + ldexp_runner);
2673 constexpr long double two_ldbl(2.0L);
2675 lm_mask =
static_cast<limb_type
> (lm_mask << 1U);
2676 ldexp_runner =
static_cast<long double>(ldexp_runner * two_ldbl);
2679 a +=
static_cast<local_builtin_float_type
>(ld);
2682 return static_cast<local_builtin_float_type
>((!u_is_neg) ? a : -a);
2686 template<const
size_t OtherW
idth2>
2689 typename std::enable_if<((OtherWidth2 / std::numeric_limits<LimbType>::digits) < number_of_limbs_karatsuba_threshold)>::type* p_nullparam =
nullptr)
2691 static_cast<void>(p_nullparam ==
nullptr);
2697 constexpr size_t local_number_of_limbs =
2700 representation_type result{ };
2702 eval_multiply_n_by_n_to_lo_part(result.data(),
2705 local_number_of_limbs);
2707 std::copy(result.cbegin(),
2708 result.cbegin() + local_number_of_limbs,
2712 template<const
size_t OtherW
idth2>
2715 typename std::enable_if<((OtherWidth2 / std::numeric_limits<LimbType>::digits) >= number_of_limbs_karatsuba_threshold)>::type* p_nullparam =
nullptr)
2717 static_cast<void>(p_nullparam ==
nullptr);
2721 constexpr size_t local_number_of_limbs =
2727 using result_array_type =
2728 typename std::conditional<std::is_same<AllocatorType, void>::value,
2729 detail::fixed_static_array <limb_type, number_of_limbs * 2U>,
2731 number_of_limbs * 2U,
2732 typename std::allocator_traits<typename std::conditional<std::is_same<AllocatorType, void>::value,
2733 std::allocator<void>,
2734 AllocatorType>::type>::template rebind_alloc<limb_type>>>::type;
2736 using storage_array_type =
2737 typename std::conditional<std::is_same<AllocatorType, void>::value,
2738 detail::fixed_static_array <limb_type, number_of_limbs * 4U>,
2740 number_of_limbs * 4U,
2741 typename std::allocator_traits<typename std::conditional<std::is_same<AllocatorType, void>::value,
2742 std::allocator<void>,
2743 AllocatorType>::type>::template rebind_alloc<limb_type>>>::type;
2745 result_array_type result;
2746 storage_array_type t;
2748 eval_multiply_kara_n_by_n_to_2n(result.data(),
2751 local_number_of_limbs,
2754 std::copy(result.cbegin(),
2755 result.cbegin() + local_number_of_limbs,
2759 template<
typename ResultIterator,
2760 typename InputIteratorLeft,
2761 typename InputIteratorRight>
2762 static WIDE_INTEGER_CONSTEXPR
auto eval_add_n(ResultIterator r,
2763 InputIteratorLeft u,
2764 InputIteratorRight v,
2765 const unsigned_fast_type count,
2766 const limb_type carry_in =
static_cast<limb_type
>(0U)) -> limb_type
2768 auto carry_out =
static_cast<std::uint_fast8_t
>(carry_in);
2772 (std::numeric_limits<typename std::iterator_traits<ResultIterator>::value_type>::digits == std::numeric_limits<typename std::iterator_traits<InputIteratorLeft>::value_type>::digits)
2773 && (std::numeric_limits<
typename std::iterator_traits<ResultIterator>::value_type>::digits == std::numeric_limits<
typename std::iterator_traits<InputIteratorRight>::value_type>::digits),
2774 "Error: Internals require same widths for left-right-result limb_types at the moment"
2777 using local_limb_type =
typename std::iterator_traits<ResultIterator>::value_type;
2779 using local_double_limb_type =
2782 using result_difference_type =
typename std::iterator_traits<ResultIterator>::difference_type;
2783 using left_difference_type =
typename std::iterator_traits<InputIteratorLeft>::difference_type;
2784 using right_difference_type =
typename std::iterator_traits<InputIteratorRight>::difference_type;
2786 for (
auto i =
static_cast<unsigned_fast_type
>(0U); i < count; ++i)
2788 const auto uv_as_ularge =
2789 static_cast<local_double_limb_type
>(
static_cast<local_double_limb_type
>(
static_cast<local_double_limb_type
>(*(u +
static_cast<left_difference_type
>(i))) + *(v +
static_cast<right_difference_type
>(i))) + carry_out);
2791 carry_out =
static_cast<std::uint_fast8_t
>(detail::make_hi<local_limb_type>(uv_as_ularge));
2793 *(r +
static_cast<result_difference_type
>(i)) =
static_cast<local_limb_type
>(uv_as_ularge);
2796 return static_cast<limb_type
>(carry_out);
2799 template<
typename ResultIterator,
2800 typename InputIteratorLeft,
2801 typename InputIteratorRight>
2802 static WIDE_INTEGER_CONSTEXPR
auto eval_subtract_n(ResultIterator r,
2803 InputIteratorLeft u,
2804 InputIteratorRight v,
2805 const unsigned_fast_type count,
2806 const bool has_borrow_in =
false) ->
bool
2808 std::uint_fast8_t has_borrow_out = (has_borrow_in ? 1U : 0U);
2812 (std::numeric_limits<typename std::iterator_traits<ResultIterator>::value_type>::digits == std::numeric_limits<typename std::iterator_traits<InputIteratorLeft>::value_type>::digits)
2813 && (std::numeric_limits<
typename std::iterator_traits<ResultIterator>::value_type>::digits == std::numeric_limits<
typename std::iterator_traits<InputIteratorRight>::value_type>::digits),
2814 "Error: Internals require same widths for left-right-result limb_types at the moment"
2817 using local_limb_type =
typename std::iterator_traits<ResultIterator>::value_type;
2819 using local_double_limb_type =
2822 using result_difference_type =
typename std::iterator_traits<ResultIterator>::difference_type;
2823 using left_difference_type =
typename std::iterator_traits<InputIteratorLeft>::difference_type;
2824 using right_difference_type =
typename std::iterator_traits<InputIteratorRight>::difference_type;
2826 for (
auto i =
static_cast<unsigned_fast_type
>(0U); i < count; ++i)
2828 const auto uv_as_ularge =
static_cast<local_double_limb_type
>(
static_cast<local_double_limb_type
>(
static_cast<local_double_limb_type
>(*(u +
static_cast<left_difference_type
>(i))) - *(v +
static_cast<right_difference_type
>(i))) - has_borrow_out);
2830 has_borrow_out = (detail::make_hi<local_limb_type>(uv_as_ularge) !=
static_cast<local_limb_type
>(0U)) ? 1U : 0U;
2832 *(r +
static_cast<result_difference_type
>(i)) =
static_cast<local_limb_type
>(uv_as_ularge);
2835 return (has_borrow_out != 0U);
2838 template<
typename ResultIterator,
2839 typename InputIteratorLeft,
2840 typename InputIteratorRight,
2841 const size_t RePhraseWidth2 = Width2,
2843 static WIDE_INTEGER_CONSTEXPR
void eval_multiply_n_by_n_to_lo_part(ResultIterator r,
2844 InputIteratorLeft a,
2845 InputIteratorRight b,
2846 const unsigned_fast_type count)
2848 static_cast<void>(count);
2852 (std::numeric_limits<typename std::iterator_traits<ResultIterator>::value_type>::digits == std::numeric_limits<typename std::iterator_traits<InputIteratorLeft>::value_type>::digits)
2853 && (std::numeric_limits<
typename std::iterator_traits<ResultIterator>::value_type>::digits == std::numeric_limits<
typename std::iterator_traits<InputIteratorRight>::value_type>::digits),
2854 "Error: Internals require same widths for left-right-result limb_types at the moment"
2857 using local_limb_type =
typename std::iterator_traits<ResultIterator>::value_type;
2859 using local_double_limb_type =
2862 using result_difference_type =
typename std::iterator_traits<ResultIterator>::difference_type;
2863 using left_difference_type =
typename std::iterator_traits<InputIteratorLeft>::difference_type;
2864 using right_difference_type =
typename std::iterator_traits<InputIteratorRight>::difference_type;
2865 using result_value_type =
typename std::iterator_traits<ResultIterator>::value_type;
2888 local_double_limb_type r1;
2889 local_double_limb_type r2;
2891 const auto a0b0 =
static_cast<local_double_limb_type
>(*(a +
static_cast<left_difference_type
>(0)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(0))));
2892 const auto a0b1 =
static_cast<local_double_limb_type
>(*(a +
static_cast<left_difference_type
>(0)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(1))));
2893 const auto a1b0 =
static_cast<local_double_limb_type
>(*(a +
static_cast<left_difference_type
>(1)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(0))));
2894 const auto a1b1 =
static_cast<local_double_limb_type
>(*(a +
static_cast<left_difference_type
>(1)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(1))));
2900 if ((*(a +
static_cast<left_difference_type
>(2)) == 0U) && (*(b +
static_cast<right_difference_type
>(2)) == 0U)
2901 && (*(a +
static_cast<left_difference_type
>(3)) == 0U) && (*(b +
static_cast<right_difference_type
>(3)) == 0U))
2903 r1 =
static_cast<local_double_limb_type
>
2905 static_cast<local_double_limb_type
>
2907 detail::make_hi<local_limb_type>(a0b0)
2909 + detail::make_lo<local_limb_type>(a1b0)
2910 + detail::make_lo<local_limb_type>(a0b1)
2913 r2 =
static_cast<local_double_limb_type
>
2915 static_cast<local_double_limb_type
>
2917 detail::make_hi<local_limb_type>(r1)
2919 + detail::make_lo<local_limb_type>(a1b1)
2920 + detail::make_hi<local_limb_type>(a0b1)
2921 + detail::make_hi<local_limb_type>(a1b0)
2924 *(r +
static_cast<result_difference_type
>(3))
2925 =
static_cast<result_value_type
>
2927 detail::make_hi<local_limb_type>(r2)
2928 + detail::make_hi<local_limb_type>(a1b1)
2934 const auto a0b2 =
static_cast<local_double_limb_type
>(*(a +
static_cast<left_difference_type
>(0)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(2))));
2935 const auto a2b0 =
static_cast<local_double_limb_type
>(*(a +
static_cast<left_difference_type
>(2)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(0))));
2937 r1 =
static_cast<local_double_limb_type
>
2939 static_cast<local_double_limb_type
>
2941 detail::make_hi<local_limb_type>(a0b0)
2943 + detail::make_lo<local_limb_type>(a1b0)
2944 + detail::make_lo<local_limb_type>(a0b1)
2947 r2 =
static_cast<local_double_limb_type
>
2949 static_cast<local_double_limb_type
>
2951 detail::make_hi<local_limb_type>(r1)
2953 + detail::make_lo<local_limb_type>(a2b0)
2954 + detail::make_lo<local_limb_type>(a1b1)
2955 + detail::make_lo<local_limb_type>(a0b2)
2956 + detail::make_hi<local_limb_type>(a1b0)
2957 + detail::make_hi<local_limb_type>(a0b1)
2960 *(r +
static_cast<result_difference_type
>(3))
2961 =
static_cast<result_value_type
>
2963 detail::make_hi<local_limb_type>(r2)
2964 +
static_cast<local_limb_type
> (*(a +
static_cast<left_difference_type
>(3)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(0))))
2965 +
static_cast<local_limb_type
> (*(a +
static_cast<left_difference_type
>(2)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(1))))
2966 +
static_cast<local_limb_type
> (*(a +
static_cast<left_difference_type
>(1)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(2))))
2967 +
static_cast<local_limb_type
> (*(a +
static_cast<left_difference_type
>(0)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(3))))
2968 + detail::make_hi<local_limb_type>(a2b0)
2969 + detail::make_hi<local_limb_type>(a1b1)
2970 + detail::make_hi<local_limb_type>(a0b2)
2975 *(r +
static_cast<result_difference_type
>(0)) =
static_cast<local_limb_type
>(a0b0);
2976 *(r +
static_cast<result_difference_type
>(1)) =
static_cast<local_limb_type
>(r1);
2977 *(r +
static_cast<result_difference_type
>(2)) =
static_cast<local_limb_type
>(r2);
2980#if defined(WIDE_INTEGER_HAS_MUL_8_BY_8_UNROLL)
2981 template<
typename ResultIterator,
2982 typename InputIteratorLeft,
2983 typename InputIteratorRight,
2984 const size_t RePhraseWidth2 = Width2,
2986 static WIDE_INTEGER_CONSTEXPR
void eval_multiply_n_by_n_to_lo_part(ResultIterator r,
2987 InputIteratorLeft a,
2988 InputIteratorRight b,
2989 const unsigned_fast_type count)
2991 static_cast<void>(count);
2995 (std::numeric_limits<typename std::iterator_traits<ResultIterator>::value_type>::digits == std::numeric_limits<typename std::iterator_traits<InputIteratorLeft>::value_type>::digits)
2996 && (std::numeric_limits<
typename std::iterator_traits<ResultIterator>::value_type>::digits == std::numeric_limits<
typename std::iterator_traits<InputIteratorRight>::value_type>::digits),
2997 "Error: Internals require same widths for left-right-result limb_types at the moment"
3000 using local_limb_type =
typename std::iterator_traits<ResultIterator>::value_type;
3002 using local_double_limb_type =
3005 using result_difference_type =
typename std::iterator_traits<ResultIterator>::difference_type;
3006 using left_difference_type =
typename std::iterator_traits<InputIteratorLeft>::difference_type;
3007 using right_difference_type =
typename std::iterator_traits<InputIteratorRight>::difference_type;
3030 const local_double_limb_type a0b0 = *(a +
static_cast<left_difference_type
>(0)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(0)));
3032 const local_double_limb_type a1b0 = *(a +
static_cast<left_difference_type
>(1)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(0)));
3033 const local_double_limb_type a0b1 = *(a +
static_cast<left_difference_type
>(0)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(1)));
3035 const local_double_limb_type a2b0 = *(a +
static_cast<left_difference_type
>(2)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(0)));
3036 const local_double_limb_type a1b1 = *(a +
static_cast<left_difference_type
>(1)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(1)));
3037 const local_double_limb_type a0b2 = *(a +
static_cast<left_difference_type
>(0)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(2)));
3039 const local_double_limb_type a3b0 = *(a +
static_cast<left_difference_type
>(3)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(0)));
3040 const local_double_limb_type a2b1 = *(a +
static_cast<left_difference_type
>(2)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(1)));
3041 const local_double_limb_type a1b2 = *(a +
static_cast<left_difference_type
>(1)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(2)));
3042 const local_double_limb_type a0b3 = *(a +
static_cast<left_difference_type
>(0)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(3)));
3044 const local_double_limb_type a3b1 = *(a +
static_cast<left_difference_type
>(3)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(1)));
3045 const local_double_limb_type a2b2 = *(a +
static_cast<left_difference_type
>(2)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(2)));
3046 const local_double_limb_type a1b3 = *(a +
static_cast<left_difference_type
>(1)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(3)));
3048 const local_double_limb_type a3b2 = *(a +
static_cast<left_difference_type
>(3)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(2)));
3049 const local_double_limb_type a2b3 = *(a +
static_cast<left_difference_type
>(2)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(3)));
3051 const local_double_limb_type a3b3 = *(a +
static_cast<left_difference_type
>(3)) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(3)));
3053 local_double_limb_type rd1;
3054 local_double_limb_type rd2;
3055 local_double_limb_type rd3;
3056 local_double_limb_type rd4;
3057 local_double_limb_type rd5;
3058 local_double_limb_type rd6;
3064 if ((*(a +
static_cast<left_difference_type
>(INT32_C(7))) == 0U) && (*(b +
static_cast<right_difference_type
>(INT32_C(7))) == 0U)
3065 && (*(a +
static_cast<left_difference_type
>(INT32_C(6))) == 0U) && (*(b +
static_cast<right_difference_type
>(INT32_C(6))) == 0U)
3066 && (*(a +
static_cast<left_difference_type
>(INT32_C(5))) == 0U) && (*(b +
static_cast<right_difference_type
>(INT32_C(5))) == 0U)
3067 && (*(a +
static_cast<left_difference_type
>(INT32_C(4))) == 0U) && (*(b +
static_cast<right_difference_type
>(INT32_C(4))) == 0U))
3069 rd1 =
static_cast<local_double_limb_type
>
3071 detail::make_hi<local_limb_type>(a0b0)
3073 + detail::make_lo<local_limb_type>(a1b0)
3074 + detail::make_lo<local_limb_type>(a0b1)
3077 rd2 =
static_cast<local_double_limb_type
>
3079 detail::make_hi<local_limb_type>(rd1)
3081 + detail::make_lo<local_limb_type>(a2b0)
3082 + detail::make_lo<local_limb_type>(a1b1)
3083 + detail::make_lo<local_limb_type>(a0b2)
3084 + detail::make_hi<local_limb_type>(a1b0)
3085 + detail::make_hi<local_limb_type>(a0b1)
3088 rd3 =
static_cast<local_double_limb_type
>
3090 detail::make_hi<local_limb_type>(rd2)
3092 + detail::make_lo<local_limb_type>(a3b0)
3093 + detail::make_lo<local_limb_type>(a2b1)
3094 + detail::make_lo<local_limb_type>(a1b2)
3095 + detail::make_lo<local_limb_type>(a0b3)
3096 + detail::make_hi<local_limb_type>(a2b0)
3097 + detail::make_hi<local_limb_type>(a1b1)
3098 + detail::make_hi<local_limb_type>(a0b2)
3101 rd4 =
static_cast<local_double_limb_type
>
3103 detail::make_hi<local_limb_type>(rd3)
3105 + detail::make_lo<local_limb_type>(a3b1)
3106 + detail::make_lo<local_limb_type>(a2b2)
3107 + detail::make_lo<local_limb_type>(a1b3)
3108 + detail::make_hi<local_limb_type>(a3b0)
3109 + detail::make_hi<local_limb_type>(a2b1)
3110 + detail::make_hi<local_limb_type>(a1b2)
3111 + detail::make_hi<local_limb_type>(a0b3)
3114 rd5 =
static_cast<local_double_limb_type
>
3116 detail::make_hi<local_limb_type>(rd4)
3118 + detail::make_lo<local_limb_type>(a3b2)
3119 + detail::make_lo<local_limb_type>(a2b3)
3120 + detail::make_hi<local_limb_type>(a3b1)
3121 + detail::make_hi<local_limb_type>(a2b2)
3122 + detail::make_hi<local_limb_type>(a1b3)
3125 rd6 =
static_cast<local_double_limb_type
>
3127 detail::make_hi<local_limb_type>(rd5)
3129 + detail::make_lo<local_limb_type>(a3b3)
3130 + detail::make_hi<local_limb_type>(a3b2)
3131 + detail::make_hi<local_limb_type>(a2b3)
3134 *(r +
static_cast<result_difference_type
>(INT32_C(7)))
3135 =
static_cast<local_limb_type
>
3137 detail::make_hi<local_limb_type>(rd6)
3138 + detail::make_hi<local_limb_type>(a3b3)
3144 const local_double_limb_type a4b0 = *(a +
static_cast<left_difference_type
>(INT32_C(4))) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(INT32_C(0))));
3145 const local_double_limb_type a0b4 = *(a +
static_cast<left_difference_type
>(INT32_C(0))) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(INT32_C(4))));
3147 const local_double_limb_type a5b0 = *(a +
static_cast<left_difference_type
>(INT32_C(5))) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(INT32_C(0))));
3148 const local_double_limb_type a4b1 = *(a +
static_cast<left_difference_type
>(INT32_C(4))) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(INT32_C(1))));
3150 const local_double_limb_type a1b4 = *(a +
static_cast<left_difference_type
>(INT32_C(1))) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(INT32_C(4))));
3151 const local_double_limb_type a0b5 = *(a +
static_cast<left_difference_type
>(INT32_C(0))) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(INT32_C(5))));
3153 const local_double_limb_type a6b0 = *(a +
static_cast<left_difference_type
>(INT32_C(6))) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(INT32_C(0))));
3154 const local_double_limb_type a5b1 = *(a +
static_cast<left_difference_type
>(INT32_C(5))) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(INT32_C(1))));
3156 const local_double_limb_type a4b2 = *(a +
static_cast<left_difference_type
>(INT32_C(4))) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(INT32_C(2))));
3157 const local_double_limb_type a2b4 = *(a +
static_cast<left_difference_type
>(INT32_C(2))) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(INT32_C(4))));
3159 const local_double_limb_type a1b5 = *(a +
static_cast<left_difference_type
>(INT32_C(1))) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(INT32_C(5))));
3160 const local_double_limb_type a0b6 = *(a +
static_cast<left_difference_type
>(INT32_C(0))) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(INT32_C(6))));
3162 rd1 =
static_cast<local_double_limb_type
>
3164 detail::make_hi<local_limb_type>(a0b0)
3166 + detail::make_lo<local_limb_type>(a1b0)
3167 + detail::make_lo<local_limb_type>(a0b1)
3170 rd2 =
static_cast<local_double_limb_type
>
3172 detail::make_hi<local_limb_type>(rd1)
3174 + detail::make_lo<local_limb_type>(a2b0)
3175 + detail::make_lo<local_limb_type>(a1b1)
3176 + detail::make_lo<local_limb_type>(a0b2)
3177 + detail::make_hi<local_limb_type>(a1b0)
3178 + detail::make_hi<local_limb_type>(a0b1)
3181 rd3 =
static_cast<local_double_limb_type
>
3183 detail::make_hi<local_limb_type>(rd2)
3185 + detail::make_lo<local_limb_type>(a3b0)
3186 + detail::make_lo<local_limb_type>(a2b1)
3187 + detail::make_lo<local_limb_type>(a1b2)
3188 + detail::make_lo<local_limb_type>(a0b3)
3189 + detail::make_hi<local_limb_type>(a2b0)
3190 + detail::make_hi<local_limb_type>(a1b1)
3191 + detail::make_hi<local_limb_type>(a0b2)
3194 rd4 =
static_cast<local_double_limb_type
>
3196 detail::make_hi<local_limb_type>(rd3)
3198 + detail::make_lo<local_limb_type>(a4b0)
3199 + detail::make_lo<local_limb_type>(a3b1)
3200 + detail::make_lo<local_limb_type>(a2b2)
3201 + detail::make_lo<local_limb_type>(a1b3)
3202 + detail::make_lo<local_limb_type>(a0b4)
3203 + detail::make_hi<local_limb_type>(a3b0)
3204 + detail::make_hi<local_limb_type>(a2b1)
3205 + detail::make_hi<local_limb_type>(a1b2)
3206 + detail::make_hi<local_limb_type>(a0b3)
3209 rd5 =
static_cast<local_double_limb_type
>
3211 detail::make_hi<local_limb_type>(rd4)
3213 + detail::make_lo<local_limb_type>(a5b0)
3214 + detail::make_lo<local_limb_type>(a4b1)
3215 + detail::make_lo<local_limb_type>(a3b2)
3216 + detail::make_lo<local_limb_type>(a2b3)
3217 + detail::make_lo<local_limb_type>(a1b4)
3218 + detail::make_lo<local_limb_type>(a0b5)
3219 + detail::make_hi<local_limb_type>(a4b0)
3220 + detail::make_hi<local_limb_type>(a3b1)
3221 + detail::make_hi<local_limb_type>(a2b2)
3222 + detail::make_hi<local_limb_type>(a1b3)
3223 + detail::make_hi<local_limb_type>(a0b4)
3226 rd6 =
static_cast<local_double_limb_type
>
3228 detail::make_hi<local_limb_type>(rd5)
3230 + detail::make_lo<local_limb_type>(a6b0)
3231 + detail::make_lo<local_limb_type>(a5b1)
3232 + detail::make_lo<local_limb_type>(a4b2)
3233 + detail::make_lo<local_limb_type>(a3b3)
3234 + detail::make_lo<local_limb_type>(a2b4)
3235 + detail::make_lo<local_limb_type>(a1b5)
3236 + detail::make_lo<local_limb_type>(a0b6)
3237 + detail::make_hi<local_limb_type>(a5b0)
3238 + detail::make_hi<local_limb_type>(a4b1)
3239 + detail::make_hi<local_limb_type>(a3b2)
3240 + detail::make_hi<local_limb_type>(a2b3)
3241 + detail::make_hi<local_limb_type>(a1b4)
3242 + detail::make_hi<local_limb_type>(a0b5)
3245 *(r +
static_cast<result_difference_type
>(INT32_C(7)))
3246 =
static_cast<local_limb_type
>
3248 detail::make_hi<local_limb_type>(rd6)
3249 +
static_cast<local_limb_type
> (*(a +
static_cast<left_difference_type
>(INT32_C(7))) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(INT32_C(0)))))
3250 +
static_cast<local_limb_type
> (*(a +
static_cast<left_difference_type
>(INT32_C(6))) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(INT32_C(1)))))
3251 +
static_cast<local_limb_type
> (*(a +
static_cast<left_difference_type
>(INT32_C(5))) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(INT32_C(2)))))
3252 +
static_cast<local_limb_type
> (*(a +
static_cast<left_difference_type
>(INT32_C(4))) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(INT32_C(3)))))
3253 +
static_cast<local_limb_type
> (*(a +
static_cast<left_difference_type
>(INT32_C(3))) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(INT32_C(4)))))
3254 +
static_cast<local_limb_type
> (*(a +
static_cast<left_difference_type
>(INT32_C(2))) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(INT32_C(5)))))
3255 +
static_cast<local_limb_type
> (*(a +
static_cast<left_difference_type
>(INT32_C(1))) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(INT32_C(6)))))
3256 +
static_cast<local_limb_type
> (*(a +
static_cast<left_difference_type
>(INT32_C(0))) *
static_cast<local_double_limb_type
>(*(b +
static_cast<right_difference_type
>(INT32_C(7)))))
3257 + detail::make_hi<local_limb_type>(a6b0)
3258 + detail::make_hi<local_limb_type>(a5b1)
3259 + detail::make_hi<local_limb_type>(a4b2)
3260 + detail::make_hi<local_limb_type>(a3b3)
3261 + detail::make_hi<local_limb_type>(a2b4)
3262 + detail::make_hi<local_limb_type>(a1b5)
3263 + detail::make_hi<local_limb_type>(a0b6)
3268 *(r +
static_cast<result_difference_type
>(INT32_C(0))) =
static_cast<local_limb_type
>(a0b0);
3269 *(r +
static_cast<result_difference_type
>(INT32_C(1))) =
static_cast<local_limb_type
>(rd1);
3270 *(r +
static_cast<result_difference_type
>(INT32_C(2))) =
static_cast<local_limb_type
>(rd2);
3271 *(r +
static_cast<result_difference_type
>(INT32_C(3))) =
static_cast<local_limb_type
>(rd3);
3272 *(r +
static_cast<result_difference_type
>(INT32_C(4))) =
static_cast<local_limb_type
>(rd4);
3273 *(r +
static_cast<result_difference_type
>(INT32_C(5))) =
static_cast<local_limb_type
>(rd5);
3274 *(r +
static_cast<result_difference_type
>(INT32_C(6))) =
static_cast<local_limb_type
>(rd6);
3278 template<
typename ResultIterator,
3279 typename InputIteratorLeft,
3280 typename InputIteratorRight,
3281 const size_t RePhraseWidth2 = Width2,
3283#if defined(WIDE_INTEGER_HAS_MUL_8_BY_8_UNROLL)
3286 )>::type
const* =
nullptr>
3287 static WIDE_INTEGER_CONSTEXPR
void eval_multiply_n_by_n_to_lo_part(ResultIterator r,
3288 InputIteratorLeft a,
3289 InputIteratorRight b,
3290 const unsigned_fast_type count)
3294 (std::numeric_limits<typename std::iterator_traits<ResultIterator>::value_type>::digits == std::numeric_limits<typename std::iterator_traits<InputIteratorLeft>::value_type>::digits)
3295 && (std::numeric_limits<
typename std::iterator_traits<ResultIterator>::value_type>::digits == std::numeric_limits<
typename std::iterator_traits<InputIteratorRight>::value_type>::digits),
3296 "Error: Internals require same widths for left-right-result limb_types at the moment"
3299 using local_limb_type =
typename std::iterator_traits<ResultIterator>::value_type;
3301 using local_double_limb_type =
3304 using result_difference_type =
typename std::iterator_traits<ResultIterator>::difference_type;
3305 using left_difference_type =
typename std::iterator_traits<InputIteratorLeft>::difference_type;
3306 using right_difference_type =
typename std::iterator_traits<InputIteratorRight>::difference_type;
3308 std::fill_n(r, count,
static_cast<local_limb_type
>(0U));
3310 for (
auto i =
static_cast<unsigned_fast_type
>(0U); i < count; ++i)
3312 if (*(a +
static_cast<left_difference_type
>(i)) !=
static_cast<local_limb_type
>(0U))
3314 local_double_limb_type carry = 0U;
3316 for (
auto j =
static_cast<unsigned_fast_type
>(0U); j < static_cast<unsigned_fast_type>(count - i); ++j)
3318 carry =
static_cast<local_double_limb_type
>(carry +
static_cast<local_double_limb_type
>(
static_cast<local_double_limb_type
>(*(a +
static_cast<left_difference_type
>(i))) * *(b +
static_cast<right_difference_type
>(j))));
3319 carry =
static_cast<local_double_limb_type
>(carry + *(r +
static_cast<result_difference_type
>(i + j)));
3321 *(r +
static_cast<result_difference_type
>(i + j)) =
static_cast<local_limb_type
>(carry);
3322 carry = detail::make_hi<local_limb_type>(carry);
3328 template<
typename ResultIterator,
3329 typename InputIteratorLeft,
3330 typename InputIteratorRight>
3331 static WIDE_INTEGER_CONSTEXPR
void eval_multiply_n_by_n_to_2n(ResultIterator r,
3332 InputIteratorLeft a,
3333 InputIteratorRight b,
3334 const unsigned_fast_type count)
3338 (std::numeric_limits<typename std::iterator_traits<ResultIterator>::value_type>::digits == std::numeric_limits<typename std::iterator_traits<InputIteratorLeft>::value_type>::digits)
3339 && (std::numeric_limits<
typename std::iterator_traits<ResultIterator>::value_type>::digits == std::numeric_limits<
typename std::iterator_traits<InputIteratorRight>::value_type>::digits),
3340 "Error: Internals require same widths for left-right-result limb_types at the moment"
3343 using local_limb_type =
typename std::iterator_traits<ResultIterator>::value_type;
3345 using local_double_limb_type =
3348 using result_difference_type =
typename std::iterator_traits<ResultIterator>::difference_type;
3349 using left_difference_type =
typename std::iterator_traits<InputIteratorLeft>::difference_type;
3350 using right_difference_type =
typename std::iterator_traits<InputIteratorRight>::difference_type;
3352 std::fill_n(r, (count * 2U),
static_cast<local_limb_type
>(0U));
3354 for (
auto i =
static_cast<unsigned_fast_type
>(0U); i < count; ++i)
3356 if (*(a +
static_cast<left_difference_type
>(i)) !=
static_cast<local_limb_type
>(0U))
3358 unsigned_fast_type j = 0U;
3360 local_double_limb_type carry = 0U;
3362 for (; j < count; ++j)
3364 carry =
static_cast<local_double_limb_type
>(carry +
static_cast<local_double_limb_type
>(
static_cast<local_double_limb_type
>(*(a +
static_cast<left_difference_type
>(i))) * *(b +
static_cast<right_difference_type
>(j))));
3365 carry =
static_cast<local_double_limb_type
>(carry + *(r +
static_cast<result_difference_type
>(i + j)));
3367 *(r +
static_cast<result_difference_type
>(i + j)) =
static_cast<local_limb_type
>(carry);
3368 carry = detail::make_hi<local_limb_type>(carry);
3371 *(r +
static_cast<result_difference_type
>(i + j)) =
static_cast<local_limb_type
>(carry);
3376 template<
typename ResultIterator,
3377 typename InputIteratorLeft>
3378 static WIDE_INTEGER_CONSTEXPR
auto eval_multiply_1d(ResultIterator r,
3379 InputIteratorLeft a,
3380 const typename std::iterator_traits<InputIteratorLeft>::value_type b,
3381 const unsigned_fast_type count) -> limb_type
3385 (std::numeric_limits<typename std::iterator_traits<ResultIterator>::value_type>::digits == std::numeric_limits<typename std::iterator_traits<InputIteratorLeft>::value_type>::digits),
3386 "Error: Internals require same widths for left-right-result limb_types at the moment"
3389 using local_limb_type =
typename std::iterator_traits<ResultIterator>::value_type;
3391 using local_double_limb_type =
3394 using result_difference_type =
typename std::iterator_traits<ResultIterator>::difference_type;
3395 using left_difference_type =
typename std::iterator_traits<InputIteratorLeft>::difference_type;
3397 local_double_limb_type carry = 0U;
3401 std::fill(r, r + count,
static_cast<limb_type
>(0U));
3405 for (
auto i =
static_cast<unsigned_fast_type
>(0U); i < count; ++i)
3407 carry =
static_cast<local_double_limb_type
>(carry +
static_cast<local_double_limb_type
>(
static_cast<local_double_limb_type
>(*(a +
static_cast<left_difference_type
>(i))) * b));
3409 *(r +
static_cast<result_difference_type
>(i)) =
static_cast<local_limb_type
>(carry);
3410 carry = detail::make_hi<local_limb_type>(carry);
3414 return static_cast<local_limb_type
>(carry);
3417 template<
typename InputIteratorLeft>
3418 static WIDE_INTEGER_CONSTEXPR
3419 void eval_multiply_kara_propagate_carry(InputIteratorLeft t,
3420 const unsigned_fast_type n,
3421 const typename std::iterator_traits<InputIteratorLeft>::value_type carry)
3423 using local_limb_type =
typename std::iterator_traits<InputIteratorLeft>::value_type;
3425 using local_double_limb_type =
3428 using left_difference_type =
typename std::iterator_traits<InputIteratorLeft>::difference_type;
3430 unsigned_fast_type i = 0U;
3432 local_limb_type carry_out = carry;
3434 while ((i < n) && (carry_out !=
static_cast<local_limb_type
>(0U)))
3436 const local_double_limb_type uv_as_ularge =
static_cast<local_double_limb_type
>(*(t +
static_cast<left_difference_type
>(i))) + carry_out;
3438 carry_out = detail::make_hi<local_limb_type>(uv_as_ularge);
3440 *(t +
static_cast<left_difference_type
>(i)) =
static_cast<local_limb_type
>(uv_as_ularge);
3446 template<
typename InputIteratorLeft>
3447 static WIDE_INTEGER_CONSTEXPR
3448 void eval_multiply_kara_propagate_borrow(InputIteratorLeft t,
3449 const unsigned_fast_type n,
3450 const bool has_borrow)
3452 using local_limb_type =
typename std::iterator_traits<InputIteratorLeft>::value_type;
3454 using local_double_limb_type =
3457 using left_difference_type =
typename std::iterator_traits<InputIteratorLeft>::difference_type;
3459 unsigned_fast_type i = 0U;
3461 bool has_borrow_out = has_borrow;
3463 while ((i < n) && (has_borrow_out))
3465 auto uv_as_ularge =
static_cast<local_double_limb_type
>(*(t +
static_cast<left_difference_type
>(i)));
3472 has_borrow_out = (detail::make_hi<local_limb_type>(uv_as_ularge) !=
static_cast<local_limb_type
>(0U));
3474 *(t +
static_cast<left_difference_type
>(i)) =
static_cast<local_limb_type
>(uv_as_ularge);
3480 template<
typename ResultIterator,
3481 typename InputIteratorLeft,
3482 typename InputIteratorRight,
3483 typename InputIteratorTemp>
3484 static WIDE_INTEGER_CONSTEXPR
3485 void eval_multiply_kara_n_by_n_to_2n(ResultIterator r,
3486 const InputIteratorLeft a,
3487 const InputIteratorRight b,
3488 const unsigned_fast_type n,
3489 InputIteratorTemp t)
3491 if (n <=
static_cast<unsigned_fast_type
>(UINT32_C(48)))
3493 static_cast<void>(t);
3495 eval_multiply_n_by_n_to_2n(r, a, b, n);
3501 (std::numeric_limits<typename std::iterator_traits<ResultIterator>::value_type>::digits == std::numeric_limits<typename std::iterator_traits<InputIteratorLeft>::value_type>::digits)
3502 && (std::numeric_limits<
typename std::iterator_traits<ResultIterator>::value_type>::digits == std::numeric_limits<
typename std::iterator_traits<InputIteratorRight>::value_type>::digits)
3503 && (std::numeric_limits<typename std::iterator_traits<ResultIterator>::value_type>::digits == std::numeric_limits<typename std::iterator_traits<InputIteratorTemp>::value_type>::digits),
3504 "Error: Internals require same widths for left-right-result limb_types at the moment"
3507 using local_limb_type =
typename std::iterator_traits<ResultIterator>::value_type;
3509 using result_difference_type =
typename std::iterator_traits<ResultIterator>::difference_type;
3510 using left_difference_type =
typename std::iterator_traits<InputIteratorLeft>::difference_type;
3511 using right_difference_type =
typename std::iterator_traits<InputIteratorRight>::difference_type;
3512 using temp_difference_type =
typename std::iterator_traits<InputIteratorTemp>::difference_type;
3547 const unsigned_fast_type nh = n / 2U;
3549 const InputIteratorLeft a0 = a +
static_cast<left_difference_type
>(0);
3550 const InputIteratorLeft a1 = a +
static_cast<left_difference_type
>(nh);
3552 const InputIteratorRight b0 = b +
static_cast<right_difference_type
>(0);
3553 const InputIteratorRight b1 = b +
static_cast<right_difference_type
>(nh);
3555 ResultIterator r0 = r +
static_cast<result_difference_type
>(0);
3556 ResultIterator r1 = r +
static_cast<result_difference_type
>(nh);
3557 ResultIterator r2 = r +
static_cast<result_difference_type
>(n);
3558 ResultIterator r3 = r +
static_cast<result_difference_type
>(n + nh);
3560 InputIteratorTemp t0 = t +
static_cast<temp_difference_type
>(0);
3561 InputIteratorTemp t1 = t +
static_cast<temp_difference_type
>(nh);
3562 InputIteratorTemp t2 = t +
static_cast<temp_difference_type
>(n);
3563 InputIteratorTemp t4 = t +
static_cast<temp_difference_type
>(n + n);
3569 eval_multiply_kara_n_by_n_to_2n(r2, a1, b1, nh, t0);
3570 eval_multiply_kara_n_by_n_to_2n(r0, a0, b0, nh, t0);
3571 std::copy(r0, r0 + (2U * n), t0);
3573 local_limb_type carry;
3578 carry = eval_add_n(r1, r1, t2, n);
3579 eval_multiply_kara_propagate_carry(r3, nh, carry);
3580 carry = eval_add_n(r1, r1, t0, n);
3581 eval_multiply_kara_propagate_carry(r3, nh, carry);
3585 const std::int_fast8_t cmp_result_a1a0 = compare_ranges(a1, a0, nh);
3587 if (cmp_result_a1a0 == 1)
3589 static_cast<void>(eval_subtract_n(t0, a1, a0, nh));
3591 else if (cmp_result_a1a0 == -1)
3593 static_cast<void>(eval_subtract_n(t0, a0, a1, nh));
3598 const std::int_fast8_t cmp_result_b0b1 = compare_ranges(b0, b1, nh);
3600 if (cmp_result_b0b1 == 1)
3602 static_cast<void>(eval_subtract_n(t1, b0, b1, nh));
3604 else if (cmp_result_b0b1 == -1)
3606 static_cast<void>(eval_subtract_n(t1, b1, b0, nh));
3611 eval_multiply_kara_n_by_n_to_2n(t2, t0, t1, nh, t4);
3616 if ((cmp_result_a1a0 * cmp_result_b0b1) == 1)
3618 carry = eval_add_n(r1, r1, t2, n);
3620 eval_multiply_kara_propagate_carry(r3, nh, carry);
3622 else if ((cmp_result_a1a0 * cmp_result_b0b1) == -1)
3624 const bool has_borrow = eval_subtract_n(r1, r1, t2, n);
3626 eval_multiply_kara_propagate_borrow(r3, nh, has_borrow);
3631 WIDE_INTEGER_CONSTEXPR
void eval_divide_knuth(
const uintwide_t& other,
3645 using local_uint_index_type = unsigned_fast_type;
3647 auto u_offset =
static_cast<local_uint_index_type
>(0U);
3648 auto v_offset =
static_cast<local_uint_index_type
>(0U);
3651 for (
auto i =
static_cast<local_uint_index_type
>(0U); (i < number_of_limbs) && (*(values.cbegin() +
static_cast<size_t>(
static_cast<local_uint_index_type
>(number_of_limbs - 1U) - i)) ==
static_cast<limb_type
>(0U)); ++i) { ++u_offset; }
3652 for (
auto i =
static_cast<local_uint_index_type
>(0U); (i < number_of_limbs) && (*(other.values.cbegin() +
static_cast<size_t>(
static_cast<local_uint_index_type
>(number_of_limbs - 1U) - i)) ==
static_cast<limb_type
>(0U)); ++i) { ++v_offset; }
3654 if (v_offset ==
static_cast<local_uint_index_type
>(number_of_limbs))
3658 operator=(limits_helper_max(IsSigned));
3660 if (remainder !=
nullptr)
3662 *remainder =
uintwide_t(
static_cast<std::uint8_t
>(0U));
3665 else if (u_offset ==
static_cast<local_uint_index_type
>(number_of_limbs))
3669 if (remainder !=
nullptr)
3671 *remainder =
uintwide_t(
static_cast<std::uint8_t
>(0U));
3676 const auto result_of_compare_left_with_right = compare(other);
3678 const bool left_is_less_than_right = (result_of_compare_left_with_right == INT8_C(-1));
3679 const bool left_is_equal_to_right = (result_of_compare_left_with_right == INT8_C(0));
3681 if (left_is_less_than_right)
3685 if (remainder !=
nullptr)
3690 operator=(
static_cast<std::uint8_t
>(0U));
3692 else if (left_is_equal_to_right)
3696 operator=(
static_cast<std::uint8_t
>(1U));
3698 if (remainder !=
nullptr)
3700 *remainder =
uintwide_t(
static_cast<std::uint8_t
>(0U));
3703 else if (v_offset ==
static_cast<local_uint_index_type
>(number_of_limbs - 1U))
3707 const limb_type short_denominator = *other.values.cbegin();
3709 eval_divide_by_single_limb(short_denominator, u_offset, remainder);
3717 static_cast<limb_type
>(
static_cast<double_limb_type
>(
static_cast<double_limb_type
>(
static_cast<double_limb_type
>(1U) <<
static_cast<unsigned>(std::numeric_limits<limb_type>::digits))
3718 /
static_cast<double_limb_type
>(
static_cast<double_limb_type
>(*(other.values.cbegin() +
static_cast<size_t>(
static_cast<local_uint_index_type
>(number_of_limbs - 1U) - v_offset))) +
static_cast<limb_type
>(1U))));
3723 using uu_array_type =
3724 typename std::conditional<std::is_same<AllocatorType, void>::value,
3725 detail::fixed_static_array <limb_type, number_of_limbs + 1U>,
3727 number_of_limbs + 1U,
3728 typename std::allocator_traits<typename std::conditional<std::is_same<AllocatorType, void>::value,
3729 std::allocator<void>,
3730 AllocatorType>::type>::template rebind_alloc<limb_type>>>::type;
3733 representation_type vv;
3735 if (d >
static_cast<limb_type
>(1U))
3737 *(uu.begin() +
static_cast<size_t>(
static_cast<local_uint_index_type
>(number_of_limbs) - u_offset)) =
3738 eval_multiply_1d(uu.data(), values.data(), d, number_of_limbs - u_offset);
3740 static_cast<void>(eval_multiply_1d(vv.data(), other.values.data(), d, number_of_limbs - v_offset));
3744 std::copy(values.cbegin(), values.cend(), uu.begin());
3746 *(uu.begin() +
static_cast<size_t>(
static_cast<local_uint_index_type
>(number_of_limbs) - u_offset)) =
static_cast<limb_type
>(0U);
3754 const auto n =
static_cast<local_uint_index_type
> (number_of_limbs - v_offset);
3755 const auto m =
static_cast<local_uint_index_type
> (number_of_limbs - u_offset) - n;
3756 const auto vj0 =
static_cast<local_uint_index_type
>((number_of_limbs - 1U) - v_offset);
3758 for (
auto j =
static_cast<local_uint_index_type
>(0U); j <= m; ++j)
3766 const auto uj =
static_cast<local_uint_index_type
>(
static_cast<local_uint_index_type
>(
static_cast<local_uint_index_type
>(
static_cast<local_uint_index_type
>(number_of_limbs + 1U) - 1U) - u_offset) - j);
3767 const auto u_j_j1 =
static_cast<double_limb_type
>(
static_cast<double_limb_type
>(
static_cast<double_limb_type
>(*(uu.cbegin() +
static_cast<size_t>(uj))) <<
static_cast<unsigned>(std::numeric_limits<limb_type>::digits)) + *(uu.cbegin() +
static_cast<size_t>(uj - 1U)));
3769 limb_type q_hat = ((*(uu.cbegin() +
static_cast<size_t>(uj)) == *(vv.cbegin() +
static_cast<size_t>(vj0)))
3770 ? (std::numeric_limits<limb_type>::max)()
3771 :
static_cast<limb_type
>(u_j_j1 / *(vv.cbegin() +
static_cast<size_t>(vj0))));
3778 for (
auto t =
static_cast<double_limb_type
>(u_j_j1 -
static_cast<double_limb_type
>(q_hat *
static_cast<double_limb_type
>(*(vv.cbegin() +
static_cast<size_t>(vj0))))); ; --q_hat, t =
static_cast<double_limb_type
>(t + *(vv.cbegin() +
static_cast<size_t>(vj0))))
3780 if ((detail::make_hi<limb_type>(t) !=
static_cast<limb_type
>(0U))
3781 || (
static_cast<double_limb_type
>(
static_cast<double_limb_type
>(*(vv.cbegin() +
static_cast<size_t>(vj0 - 1U))) * q_hat)
3782 <=
static_cast<double_limb_type
>(
static_cast<double_limb_type
>(t << static_cast<unsigned>(std::numeric_limits<limb_type>::digits)) + *(uu.cbegin() +
static_cast<size_t>(uj - 2U)))))
3794 *(nv.begin() +
static_cast<size_t>(n)) = eval_multiply_1d(nv.data(), vv.data(), q_hat, n);
3796 const bool has_borrow =
3797 eval_subtract_n(uu.data() +
static_cast<size_t>(
static_cast<local_uint_index_type
>(uj - n)),
3798 uu.data() +
static_cast<size_t>(
static_cast<local_uint_index_type
>(uj - n)),
3804 *(values.begin() +
static_cast<size_t>(m - j)) =
static_cast<limb_type
>(q_hat - (has_borrow ? 1U : 0U));
3817 static_cast<void>(eval_add_n(uu.data() +
static_cast<size_t>(
static_cast<local_uint_index_type
>(uj - n)),
3818 uu.data() +
static_cast<size_t>(
static_cast<local_uint_index_type
>(uj - n)),
3826 std::fill(values.begin() +
static_cast<local_uint_index_type
>(m + 1U), values.end(),
static_cast<limb_type
>(0U));
3828 if (remainder !=
nullptr)
3832 std::copy(uu.cbegin(),
3833 uu.cbegin() +
static_cast<size_t>(
static_cast<local_uint_index_type
>(number_of_limbs - v_offset)),
3834 remainder->values.begin());
3838 auto previous_u =
static_cast<limb_type
>(0U);
3840 for (
auto rl =
static_cast<signed_fast_type
>(n - 1U), ul =
static_cast<signed_fast_type
>(number_of_limbs - (v_offset + 1U)); rl >= 0; --rl, --ul)
3843 static_cast<double_limb_type
>(*(uu.cbegin() +
static_cast<size_t>(ul))
3844 +
static_cast<double_limb_type
>(
static_cast<double_limb_type
>(previous_u) <<
static_cast<unsigned>(std::numeric_limits<limb_type>::digits)));
3846 *(remainder->values.begin() +
static_cast<size_t>(rl)) =
static_cast<limb_type
>(
static_cast<double_limb_type
>(t / d));
3847 previous_u =
static_cast<limb_type
>(
static_cast<double_limb_type
>(t -
static_cast<double_limb_type
>(
static_cast<double_limb_type
>(d) * *(remainder->values.cbegin() +
static_cast<size_t>(rl)))));
3851 std::fill(remainder->values.begin() +
static_cast<size_t>(n),
3852 remainder->values.end(),
3853 static_cast<limb_type
>(0U));
3859 WIDE_INTEGER_CONSTEXPR
void shl(
const unsigned_fast_type offset,
3860 const std::uint_fast16_t left_shift_amount)
3864 std::copy_backward(values.data(),
3865 values.data() +
static_cast<size_t>(number_of_limbs - offset),
3866 values.data() +
static_cast<size_t>(number_of_limbs));
3868 std::fill(values.begin(), values.begin() +
static_cast<size_t>(offset),
static_cast<limb_type
>(0U));
3871 using local_integral_type = unsigned_fast_type;
3873 if (left_shift_amount !=
static_cast<local_integral_type
>(0U))
3875 auto part_from_previous_value =
static_cast<limb_type
>(0U);
3877 for (unsigned_fast_type i = offset; i < static_cast<unsigned_fast_type>(number_of_limbs); ++i)
3879 const limb_type t = *(values.cbegin() +
static_cast<size_t>(i));
3881 *(values.begin() +
static_cast<size_t>(i)) =
3882 static_cast<limb_type
>(
static_cast<limb_type
>(t << static_cast<local_integral_type>(left_shift_amount)) | part_from_previous_value);
3884 part_from_previous_value =
3885 static_cast<limb_type
>(t >>
static_cast<local_integral_type
>(
static_cast<unsigned_fast_type
>(std::numeric_limits<limb_type>::digits - left_shift_amount)));
3890 WIDE_INTEGER_CONSTEXPR
void shr(
const unsigned_fast_type offset,
3891 const std::uint_fast16_t right_shift_amount)
3895 std::copy(values.begin() +
static_cast<size_t>(offset),
3896 values.begin() +
static_cast<size_t>(number_of_limbs),
3899 std::fill(values.end() -
static_cast<size_t>(offset),
3901 (!is_neg(*
this)) ?
static_cast<limb_type
>(0U) :
static_cast<limb_type
>((std::numeric_limits<limb_type>::max)()));
3904 using local_integral_type = unsigned_fast_type;
3906 if (right_shift_amount !=
static_cast<local_integral_type
>(0U))
3908 limb_type part_from_previous_value =
3910 ?
static_cast<limb_type
>(0U)
3911 :
static_cast<limb_type
>((std::numeric_limits<limb_type>::max)() <<
static_cast<std::uint_fast16_t
>(
static_cast<std::uint_fast16_t
>(std::numeric_limits<limb_type>::digits) - right_shift_amount));
3913 for (
auto i =
static_cast<signed_fast_type
>((number_of_limbs - 1U) - offset); i >=
static_cast<signed_fast_type
>(0); --i)
3915 const limb_type t = *(values.cbegin() +
static_cast<size_t>(i));
3917 *(values.begin() +
static_cast<size_t>(i)) =
static_cast<limb_type
>(
static_cast<limb_type
>(t >>
static_cast<local_integral_type
>(right_shift_amount)) | part_from_previous_value);
3919 part_from_previous_value =
static_cast<limb_type
>(t << static_cast<local_integral_type>(
static_cast<unsigned_fast_type
>(std::numeric_limits<limb_type>::digits - right_shift_amount)));
3925 WIDE_INTEGER_CONSTEXPR
auto rd_string(
const char* str_input) ->
bool
3927 std::fill(values.begin(), values.end(),
static_cast<limb_type
>(0U));
3929 const unsigned_fast_type str_length = detail::strlen_unsafe(str_input);
3931 std::uint_fast8_t base = UINT8_C(10);
3933 unsigned_fast_type pos = 0U;
3937 if ((str_length > 0U) && (str_input[0U] ==
static_cast<char>(
'+')))
3942 bool str_has_neg_sign =
false;
3946 if ((str_length > 0U) && (str_input[0U] ==
static_cast<char>(
'-')))
3948 str_has_neg_sign =
true;
3954 if (str_length > (pos + 0U))
3956 const bool might_be_oct_or_hex = ((str_input[pos + 0U] ==
static_cast<char>(
'0')) && (str_length > (pos + 1U)));
3958 if (might_be_oct_or_hex)
3960 if ((str_input[pos + 1U] >=
static_cast<char>(
'0')) && (str_input[pos + 1U] <=
static_cast<char>(
'8')))
3967 else if ((str_input[pos + 1U] ==
static_cast<char>(
'x')) || (str_input[pos + 1U] ==
static_cast<char>(
'X')))
3975 else if ((str_input[pos + 0U] >=
static_cast<char>(
'0')) && (str_input[pos + 0U] <=
static_cast<char>(
'9')))
3982 bool char_is_valid =
true;
3984 for (; ((pos < str_length) && char_is_valid); ++pos)
3986 const auto c =
static_cast<std::uint8_t
>(str_input[pos]);
3989 const bool char_is_apostrophe = (c ==
static_cast<char>(39));
3991 if (!char_is_apostrophe)
3993 if (base == UINT8_C(8))
3995 std::uint8_t uc_oct{ };
3997 if ((c >=
static_cast<char>(
'0')) && (c <=
static_cast<char>(
'8'))) { uc_oct =
static_cast<std::uint8_t
>(c -
static_cast<std::uint8_t
>(UINT8_C(0x30))); }
3998 else { uc_oct =
static_cast<std::uint8_t
>(
'\0'); char_is_valid =
false; }
4004 *values.begin() =
static_cast<limb_type
>(*values.begin() | uc_oct);
4007 else if (base == UINT8_C(10))
4009 std::uint8_t uc_dec{ };
4011 if ((c >=
static_cast<std::uint8_t
>(
'0')) && (c <= static_cast<std::uint8_t>(
'9'))) { uc_dec =
static_cast<std::uint8_t
>(c -
static_cast<std::uint8_t
>(UINT8_C(0x30))); }
4012 else { uc_dec =
static_cast<std::uint8_t
>(
'\0'); char_is_valid =
false; }
4016 mul_by_limb(
static_cast<limb_type
>(UINT8_C(10)));
4021 else if (base == UINT8_C(16))
4023 std::uint8_t uc_hex{ };
4025 if ((c >=
static_cast<std::uint8_t
>(
'a')) && (c <=
static_cast<std::uint8_t
>(
'f'))) { uc_hex =
static_cast<std::uint8_t
>(c -
static_cast<std::uint8_t
>(UINT8_C(87))); }
4026 else if ((c >=
static_cast<std::uint8_t
>(
'A')) && (c <=
static_cast<std::uint8_t
>(
'F'))) { uc_hex =
static_cast<std::uint8_t
>(c -
static_cast<std::uint8_t
>(UINT8_C(55))); }
4027 else if ((c >=
static_cast<std::uint8_t
>(
'0')) && (c <=
static_cast<std::uint8_t
>(
'9'))) { uc_hex =
static_cast<std::uint8_t
>(c -
static_cast<std::uint8_t
>(UINT8_C(0x30))); }
4028 else { uc_hex =
static_cast<std::uint8_t
>(
'\0'); char_is_valid =
false; }
4034 *values.begin() =
static_cast<limb_type
>(*values.begin() | uc_hex);
4040 if (str_has_neg_sign)
4045 return char_is_valid;
4048 WIDE_INTEGER_CONSTEXPR
void bitwise_not()
4050 for (
auto i =
static_cast<unsigned_fast_type
>(0U); i < number_of_limbs; ++i)
4052 *(values.begin() +
static_cast<size_t>(i)) =
static_cast<limb_type
>(~(*(values.cbegin() +
static_cast<size_t>(i))));
4056 WIDE_INTEGER_CONSTEXPR
void preincrement()
4059 unsigned_fast_type i = 0U;
4061 for (; (i < static_cast<unsigned_fast_type>(values.size() - 1U)) && (++(*(values.begin() +
static_cast<size_t>(i))) ==
static_cast<limb_type
>(0U)); ++i)
4066 if (i ==
static_cast<unsigned_fast_type
>(values.size() - 1U))
4068 ++(*(values.begin() +
static_cast<size_t>(i)));
4072 WIDE_INTEGER_CONSTEXPR
void predecrement()
4075 unsigned_fast_type i = 0U;
4077 for (; (i < static_cast<unsigned_fast_type>(values.size() - 1U)) && ((*(values.begin() +
static_cast<size_t>(i)))-- ==
static_cast<limb_type
>(0U)); ++i)
4082 if (i ==
static_cast<unsigned_fast_type
>(values.size() - 1U))
4084 --(*(values.begin() +
static_cast<size_t>(i)));
4102#if !defined(WIDE_INTEGER_DISABLE_TRIVIAL_COPY_AND_STD_LAYOUT_CHECKS)
4103 static_assert(std::is_trivially_copyable<uint64_t >::value,
"uintwide_t must be trivially copyable.");
4104 static_assert(std::is_trivially_copyable<uint128_t >::value,
"uintwide_t must be trivially copyable.");
4105 static_assert(std::is_trivially_copyable<uint256_t >::value,
"uintwide_t must be trivially copyable.");
4106 static_assert(std::is_trivially_copyable<uint512_t >::value,
"uintwide_t must be trivially copyable.");
4107 static_assert(std::is_trivially_copyable<uint1024_t >::value,
"uintwide_t must be trivially copyable.");
4108 static_assert(std::is_trivially_copyable<uint2048_t >::value,
"uintwide_t must be trivially copyable.");
4109 static_assert(std::is_trivially_copyable<uint4096_t >::value,
"uintwide_t must be trivially copyable.");
4110 static_assert(std::is_trivially_copyable<uint8192_t >::value,
"uintwide_t must be trivially copyable.");
4111 static_assert(std::is_trivially_copyable<uint16384_t>::value,
"uintwide_t must be trivially copyable.");
4112 static_assert(std::is_trivially_copyable<uint32768_t>::value,
"uintwide_t must be trivially copyable.");
4113 static_assert(std::is_trivially_copyable<uint65536_t>::value,
"uintwide_t must be trivially copyable.");
4115 static_assert(std::is_standard_layout<uint64_t >::value,
"uintwide_t must have standard layout.");
4116 static_assert(std::is_standard_layout<uint128_t >::value,
"uintwide_t must have standard layout.");
4117 static_assert(std::is_standard_layout<uint256_t >::value,
"uintwide_t must have standard layout.");
4118 static_assert(std::is_standard_layout<uint512_t >::value,
"uintwide_t must have standard layout.");
4119 static_assert(std::is_standard_layout<uint1024_t >::value,
"uintwide_t must have standard layout.");
4120 static_assert(std::is_standard_layout<uint2048_t >::value,
"uintwide_t must have standard layout.");
4121 static_assert(std::is_standard_layout<uint4096_t >::value,
"uintwide_t must have standard layout.");
4122 static_assert(std::is_standard_layout<uint8192_t >::value,
"uintwide_t must have standard layout.");
4123 static_assert(std::is_standard_layout<uint16384_t>::value,
"uintwide_t must have standard layout.");
4124 static_assert(std::is_standard_layout<uint32768_t>::value,
"uintwide_t must have standard layout.");
4125 static_assert(std::is_standard_layout<uint65536_t>::value,
"uintwide_t must have standard layout.");
4140#if !defined(WIDE_INTEGER_DISABLE_TRIVIAL_COPY_AND_STD_LAYOUT_CHECKS)
4141 static_assert(std::is_trivially_copyable<int64_t >::value,
"uintwide_t must be trivially copyable.");
4142 static_assert(std::is_trivially_copyable<int128_t >::value,
"uintwide_t must be trivially copyable.");
4143 static_assert(std::is_trivially_copyable<int256_t >::value,
"uintwide_t must be trivially copyable.");
4144 static_assert(std::is_trivially_copyable<int512_t >::value,
"uintwide_t must be trivially copyable.");
4145 static_assert(std::is_trivially_copyable<int1024_t >::value,
"uintwide_t must be trivially copyable.");
4146 static_assert(std::is_trivially_copyable<int2048_t >::value,
"uintwide_t must be trivially copyable.");
4147 static_assert(std::is_trivially_copyable<int4096_t >::value,
"uintwide_t must be trivially copyable.");
4148 static_assert(std::is_trivially_copyable<int8192_t >::value,
"uintwide_t must be trivially copyable.");
4149 static_assert(std::is_trivially_copyable<int16384_t>::value,
"uintwide_t must be trivially copyable.");
4150 static_assert(std::is_trivially_copyable<int32768_t>::value,
"uintwide_t must be trivially copyable.");
4151 static_assert(std::is_trivially_copyable<int65536_t>::value,
"uintwide_t must be trivially copyable.");
4153 static_assert(std::is_standard_layout<int64_t >::value,
"uintwide_t must have standard layout.");
4154 static_assert(std::is_standard_layout<int128_t >::value,
"uintwide_t must have standard layout.");
4155 static_assert(std::is_standard_layout<int256_t >::value,
"uintwide_t must have standard layout.");
4156 static_assert(std::is_standard_layout<int512_t >::value,
"uintwide_t must have standard layout.");
4157 static_assert(std::is_standard_layout<int1024_t >::value,
"uintwide_t must have standard layout.");
4158 static_assert(std::is_standard_layout<int2048_t >::value,
"uintwide_t must have standard layout.");
4159 static_assert(std::is_standard_layout<int4096_t >::value,
"uintwide_t must have standard layout.");
4160 static_assert(std::is_standard_layout<int8192_t >::value,
"uintwide_t must have standard layout.");
4161 static_assert(std::is_standard_layout<int16384_t>::value,
"uintwide_t must have standard layout.");
4162 static_assert(std::is_standard_layout<int32768_t>::value,
"uintwide_t must have standard layout.");
4163 static_assert(std::is_standard_layout<int65536_t>::value,
"uintwide_t must have standard layout.");
4170 template<
const size_t Width2,
4172 typename AllocatorType,
4173 const bool IsSigned>
4174 WIDE_INTEGER_NUM_LIMITS_CLASS_TYPE numeric_limits_uintwide_t_base
4175 :
public std::numeric_limits<
typename std::conditional<(!IsSigned),
unsigned int,
signed int>::type>
4181 static constexpr int digits = (!IsSigned)
4182 ?
static_cast<int>(local_wide_integer_type::my_width2)
4183 :
static_cast<int>(local_wide_integer_type::my_width2 - 1U);
4185 static constexpr int digits10 =
static_cast<int>((
static_cast<std::uintmax_t
>(digits) * UINTMAX_C(75257499)) / UINTMAX_C(250000000));
4186 static constexpr int max_digits10 = digits10;
4187 static constexpr int max_exponent = digits;
4188 static constexpr int max_exponent10 =
static_cast<int>((
static_cast<std::uintmax_t
>(max_exponent) * UINTMAX_C(75257499)) / UINTMAX_C(250000000));
4190 static constexpr auto (max)() -> local_wide_integer_type {
return local_wide_integer_type::limits_helper_max(IsSigned); }
4191 static constexpr auto (min)() -> local_wide_integer_type {
return local_wide_integer_type::limits_helper_min(IsSigned); }
4192 static constexpr auto lowest() -> local_wide_integer_type {
return local_wide_integer_type::limits_helper_lowest(IsSigned); }
4198 template<
const size_t Width2,
4200 typename AllocatorType,
4201 const bool IsSigned>
4203 :
public std::integral_constant<bool, true> { };
4205#if(__cplusplus >= 201703L)
4212WIDE_INTEGER_NAMESPACE_END
4217#if defined(WIDE_INTEGER_NAMESPACE)
4218 template<
const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t Width2,
4220 typename AllocatorType,
4221 const bool IsSigned>
4222 WIDE_INTEGER_NUM_LIMITS_CLASS_TYPE numeric_limits<WIDE_INTEGER_NAMESPACE::math::wide_integer::uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>
4223 :
public WIDE_INTEGER_NAMESPACE::math::wide_integer::numeric_limits_uintwide_t_base<Width2, LimbType, AllocatorType, IsSigned>{ };
4225 template<const ::math::wide_integer::size_t Width2,
4227 typename AllocatorType,
4228 const bool IsSigned>
4229 WIDE_INTEGER_NUM_LIMITS_CLASS_TYPE numeric_limits<::math::wide_integer::uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>
4230 : public ::math::wide_integer::numeric_limits_uintwide_t_base<Width2, LimbType, AllocatorType, IsSigned>{ };
4234WIDE_INTEGER_NAMESPACE_BEGIN
4236#if(__cplusplus >= 201703L)
4237namespace math::wide_integer {
4240 namespace wide_integer {
4244 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator+ (
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) -> uintwide_t<Width2, LimbType, AllocatorType, IsSigned> {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator+=(v); }
4245 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator- (
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) -> uintwide_t<Width2, LimbType, AllocatorType, IsSigned> {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator-=(v); }
4246 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator* (
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) -> uintwide_t<Width2, LimbType, AllocatorType, IsSigned> {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator*=(v); }
4247 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator/ (
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) -> uintwide_t<Width2, LimbType, AllocatorType, IsSigned> {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator/=(v); }
4248 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator% (
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) -> uintwide_t<Width2, LimbType, AllocatorType, IsSigned> {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator%=(v); }
4251 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator| (
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) -> uintwide_t<Width2, LimbType, AllocatorType, IsSigned> {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator|=(v); }
4252 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator^ (
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) -> uintwide_t<Width2, LimbType, AllocatorType, IsSigned> {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator^=(v); }
4253 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator& (
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) -> uintwide_t<Width2, LimbType, AllocatorType, IsSigned> {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator&=(v); }
4256 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator+(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator+=(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(v)); }
4257 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator-(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator-=(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(v)); }
4258 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator*(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator*=(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(v)); }
4259 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator/(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator/=(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(v)); }
4261 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
4262 constexpr auto operator%(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<((std::is_integral<IntegralType>::value)
4263 && (!std::is_unsigned<IntegralType>::value)),
4264 uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type
4265 {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator%=(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(v)); }
4267 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
4268 WIDE_INTEGER_CONSTEXPR
auto operator%(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<((std::is_integral<IntegralType>::value)
4269 && (std::is_unsigned<IntegralType>::value)
4270 && (std::numeric_limits<IntegralType>::digits <= std::numeric_limits<LimbType>::digits)),
4271 typename uintwide_t<Width2, LimbType, AllocatorType, IsSigned>::limb_type>::type
4273 using local_wide_integer_type = uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
4275 const bool u_is_neg = local_wide_integer_type::is_neg(u);
4277 local_wide_integer_type remainder;
4279 local_wide_integer_type((!u_is_neg) ? u : -u).eval_divide_by_single_limb(v, 0U, &remainder);
4281 using local_limb_type =
typename local_wide_integer_type::limb_type;
4283 auto u_rem =
static_cast<local_limb_type
>(remainder);
4285 return ((!u_is_neg) ? u_rem :
static_cast<local_limb_type
>(
static_cast<local_limb_type
>(~u_rem) + 1U));
4288 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
4289 constexpr auto operator%(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<((std::is_integral<IntegralType>::value)
4290 && (std::is_unsigned<IntegralType>::value)
4291 && (std::numeric_limits<IntegralType>::digits > std::numeric_limits<LimbType>::digits)),
4292 uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type
4293 {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator%=(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(v)); }
4296 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator+(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator+=(v); }
4297 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator-(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator-=(v); }
4298 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator*(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator*=(v); }
4299 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator/(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator/=(v); }
4300 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator%(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator%=(v); }
4302#if !defined(WIDE_INTEGER_DISABLE_FLOAT_INTEROP)
4304 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator+(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const FloatingPointType& f) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator+=(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(f)); }
4305 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator-(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const FloatingPointType& f) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator-=(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(f)); }
4306 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator*(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const FloatingPointType& f) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator*=(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(f)); }
4307 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator/(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const FloatingPointType& f) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator/=(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(f)); }
4308 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator%(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const FloatingPointType& f) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator%=(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(f)); }
4311 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator+(
const FloatingPointType& f,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(f).operator+=(v); }
4312 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator-(
const FloatingPointType& f,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(f).operator-=(v); }
4313 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator*(
const FloatingPointType& f,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(f).operator*=(v); }
4314 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator/(
const FloatingPointType& f,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(f).operator/=(v); }
4315 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator%(
const FloatingPointType& f,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(f).operator%=(v); }
4319 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator|(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator|=(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(v)); }
4320 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator^(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator^=(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(v)); }
4321 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator&(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator&=(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(v)); }
4324 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator|(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator|=(v); }
4325 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator^(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator^=(v); }
4326 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator&(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator&=(v); }
4329 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator<<(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType n) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator<<=(n); }
4330 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator>>(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType n) ->
typename std::enable_if<std::is_integral<IntegralType>::value, uintwide_t<Width2, LimbType, AllocatorType, IsSigned>>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator>>=(n); }
4333 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator==(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
bool {
return u.operator==(v); }
4334 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator!=(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
bool {
return u.operator!=(v); }
4335 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator> (
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
bool {
return u.operator> (v); }
4336 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator< (
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
bool {
return u.operator< (v); }
4337 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator>=(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
bool {
return u.operator>=(v); }
4338 template<const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator<=(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
bool {
return u.operator<=(v); }
4341 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator==(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type {
return u.operator==(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(v)); }
4342 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator!=(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type {
return u.operator!=(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(v)); }
4343 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator> (
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type {
return u.operator> (uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(v)); }
4344 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator< (
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type {
return u.operator< (uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(v)); }
4345 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator>=(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type {
return u.operator>=(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(v)); }
4346 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator<=(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const IntegralType& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type {
return u.operator<=(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(v)); }
4349 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator==(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator==(v); }
4350 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator!=(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator!=(v); }
4351 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator> (
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator> (v); }
4352 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator< (
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator< (v); }
4353 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator>=(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator>=(v); }
4354 template<
typename IntegralType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator<=(
const IntegralType& u,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_integral<IntegralType>::value,
bool>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(u).operator<=(v); }
4356#if !defined(WIDE_INTEGER_DISABLE_FLOAT_INTEROP)
4358 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator==(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const FloatingPointType& f) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type {
return u.operator==(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(f)); }
4359 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator!=(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const FloatingPointType& f) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type {
return u.operator!=(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(f)); }
4360 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator> (
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const FloatingPointType& f) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type {
return u.operator> (uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(f)); }
4361 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator< (
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const FloatingPointType& f) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type {
return u.operator< (uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(f)); }
4362 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator>=(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const FloatingPointType& f) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type {
return u.operator>=(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(f)); }
4363 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator<=(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& u,
const FloatingPointType& f) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type {
return u.operator<=(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(f)); }
4366 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator==(
const FloatingPointType& f,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(f).operator==(v); }
4367 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator!=(
const FloatingPointType& f,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(f).operator!=(v); }
4368 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator> (
const FloatingPointType& f,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(f).operator> (v); }
4369 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator< (
const FloatingPointType& f,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(f).operator< (v); }
4370 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator>=(
const FloatingPointType& f,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(f).operator>=(v); }
4371 template<
typename FloatingPo
intType, const
size_t W
idth2,
typename LimbType,
typename AllocatorType, const
bool IsSigned>
constexpr auto operator<=(
const FloatingPointType& f,
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& v) ->
typename std::enable_if<std::is_floating_point<FloatingPointType>::value,
bool>::type {
return uintwide_t<Width2, LimbType, AllocatorType, IsSigned>(f).operator<=(v); }
4374#if !defined(WIDE_INTEGER_DISABLE_IOSTREAM)
4377 template<
typename char_type,
4378 typename traits_type,
4379 const size_t Width2,
4381 typename AllocatorType,
4382 const bool IsSigned>
4383 auto operator<<(std::basic_ostream<char_type, traits_type>& out,
4384 const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& x) -> std::basic_ostream<char_type, traits_type> &
4386 std::basic_ostringstream<char_type, traits_type> ostr;
4388 const std::ios::fmtflags my_flags = out.flags();
4390 const bool show_pos = ((my_flags & std::ios::showpos) == std::ios::showpos);
4391 const bool show_base = ((my_flags & std::ios::showbase) == std::ios::showbase);
4392 const bool is_uppercase = ((my_flags & std::ios::uppercase) == std::ios::uppercase);
4394 std::uint_fast8_t base_rep{ };
4396 if ((my_flags & std::ios::oct) == std::ios::oct) { base_rep = UINT8_C(8); }
4397 else if ((my_flags & std::ios::hex) == std::ios::hex) { base_rep = UINT8_C(16); }
4398 else { base_rep = UINT8_C(10); }
4400 const auto field_width =
static_cast<unsigned_fast_type
>(out.width());
4401 const auto fill_char =
static_cast<char>(out.fill());
4403 using local_wide_integer_type = uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
4405 if (base_rep == UINT8_C(8))
4407 using string_storage_oct_type =
4408 typename std::conditional
4409 <local_wide_integer_type::my_width2 <= static_cast<size_t>(UINT32_C(2048)),
4410 detail::fixed_static_array <char,
4411 local_wide_integer_type::wr_string_max_buffer_size_oct>,
4412 detail::fixed_dynamic_array<char,
4413 local_wide_integer_type::wr_string_max_buffer_size_oct,
4414 typename std::allocator_traits<typename std::conditional<std::is_same<AllocatorType, void>::value,
4415 std::allocator<void>,
4416 AllocatorType>::type>::template rebind_alloc<typename local_wide_integer_type::limb_type>>
4421 string_storage_oct_type str_result;
4423 str_result.fill(
static_cast<char>(
'\0'));
4425 x.wr_string(str_result.data(), base_rep, show_base, show_pos, is_uppercase, field_width, fill_char);
4427 static_cast<void>(ostr << str_result.data());
4429 else if (base_rep == UINT8_C(10))
4431 using string_storage_dec_type =
4432 typename std::conditional
4433 <local_wide_integer_type::my_width2 <= static_cast<size_t>(UINT32_C(2048)),
4434 detail::fixed_static_array <char,
4435 local_wide_integer_type::wr_string_max_buffer_size_dec>,
4436 detail::fixed_dynamic_array<char,
4437 local_wide_integer_type::wr_string_max_buffer_size_dec,
4438 typename std::allocator_traits<typename std::conditional<std::is_same<AllocatorType, void>::value,
4439 std::allocator<void>,
4440 AllocatorType>::type>::template rebind_alloc<typename local_wide_integer_type::limb_type>>
4445 string_storage_dec_type str_result;
4447 str_result.fill(
static_cast<char>(
'\0'));
4449 x.wr_string(str_result.data(), base_rep, show_base, show_pos, is_uppercase, field_width, fill_char);
4451 static_cast<void>(ostr << str_result.data());
4453 else if (base_rep == UINT8_C(16))
4455 using string_storage_hex_type =
4456 typename std::conditional
4457 <local_wide_integer_type::my_width2 <= static_cast<size_t>(UINT32_C(2048)),
4458 detail::fixed_static_array <char,
4459 local_wide_integer_type::wr_string_max_buffer_size_hex>,
4460 detail::fixed_dynamic_array<char,
4461 local_wide_integer_type::wr_string_max_buffer_size_hex,
4462 typename std::allocator_traits<typename std::conditional<std::is_same<AllocatorType, void>::value,
4463 std::allocator<void>,
4464 AllocatorType>::type>::template rebind_alloc<typename local_wide_integer_type::limb_type>>
4469 string_storage_hex_type str_result;
4471 str_result.fill(
static_cast<char>(
'\0'));
4473 x.wr_string(str_result.data(), base_rep, show_base, show_pos, is_uppercase, field_width, fill_char);
4475 static_cast<void>(ostr << str_result.data());
4478 return (out << ostr.str());
4481 template<
typename char_type,
4482 typename traits_type,
4483 const size_t Width2,
4485 typename AllocatorType,
4486 const bool IsSigned>
4487 auto operator>>(std::basic_istream<char_type, traits_type>& in,
4488 uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& x) -> std::basic_istream<char_type, traits_type> &
4494 using local_wide_integer_type = uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
4496 x = local_wide_integer_type(str_in.c_str());
4503#if(__cplusplus >= 201703L)
4512#if(__cplusplus >= 201703L)
4513namespace math::wide_integer {
4516 namespace wide_integer {
4521#if !defined(WIDE_INTEGER_DISABLE_FLOAT_INTEROP)
4524 template<
typename FloatingPo
intType> WIDE_INTEGER_CONSTEXPR
auto frexp(FloatingPointType x,
int* expptr) ->
typename std::enable_if<((std::is_floating_point<FloatingPointType>::value) && (std::numeric_limits<FloatingPointType>::is_iec559)), FloatingPointType>::type
4526 using local_floating_point_type = FloatingPointType;
4528 const bool x_is_neg = (x < static_cast<local_floating_point_type>(0.0L));
4530 local_floating_point_type f = (x_is_neg ? -x : x);
4534 constexpr long double two_pow32 =
4535 static_cast<long double>(0x10000) *
static_cast<long double>(0x10000);
4537 while (f >=
static_cast<local_floating_point_type
>(two_pow32))
4542 f =
static_cast<local_floating_point_type
>(f /
static_cast<local_floating_point_type
>(two_pow32));
4543 e2 +=
static_cast<int>(INT32_C(32));
4546 constexpr long double one_ldbl(1.0L);
4548 while (f >=
static_cast<local_floating_point_type
>(one_ldbl))
4550 constexpr long double two_ldbl(2.0L);
4552 f =
static_cast<local_floating_point_type
>(f /
static_cast<local_floating_point_type
>(two_ldbl));
4557 if (expptr !=
nullptr)
4562 return ((!x_is_neg) ? f : -f);
4565 template<
typename FloatingPo
intType> WIDE_INTEGER_CONSTEXPR
auto frexp(FloatingPointType x,
int* expptr) ->
typename std::enable_if<((std::is_floating_point<FloatingPointType>::value) && (!std::numeric_limits<FloatingPointType>::is_iec559)), FloatingPointType>::type
4569 return frexp(x, expptr);
4572 template<
typename FloatingPo
intType> WIDE_INTEGER_CONSTEXPR
auto isfinite(FloatingPointType x) ->
typename std::enable_if<((std::is_floating_point<FloatingPointType>::value) && (std::numeric_limits<FloatingPointType>::is_iec559)),
bool>::type
4574 using local_floating_point_type = FloatingPointType;
4576 bool x_is_finite =
true;
4578 const bool x_is_nan = (x != x);
4582 x_is_finite =
false;
4586 const bool x_is_inf_pos = (x > (std::numeric_limits<local_floating_point_type>::max)());
4587 const bool x_is_inf_neg = (x < (std::numeric_limits<local_floating_point_type>::lowest)());
4589 if (x_is_inf_pos || x_is_inf_neg)
4591 x_is_finite =
false;
4598 template<
typename FloatingPo
intType> WIDE_INTEGER_CONSTEXPR
auto isfinite(FloatingPointType x) ->
typename std::enable_if<((std::is_floating_point<FloatingPointType>::value) && (!std::numeric_limits<FloatingPointType>::is_iec559)),
bool>::type
4600 using std::isfinite;
4607 template<
typename Un
signedIntegralType>
4608 inline WIDE_INTEGER_CONSTEXPR
auto lsb_helper(
const UnsignedIntegralType& u) -> unsigned_fast_type
4611 static_assert(((std::is_integral<UnsignedIntegralType>::value)
4612 && (std::is_unsigned<UnsignedIntegralType>::value)),
4613 "Error: Please check the characteristics of UnsignedIntegralType");
4615 unsigned_fast_type result = 0U;
4617 UnsignedIntegralType mask(u);
4625 while (
static_cast<std::uint_fast8_t
>(
static_cast<std::uint_fast8_t
>(mask) & UINT8_C(1)) == UINT8_C(0))
4635 template<
typename Un
signedIntegralType>
4636 inline WIDE_INTEGER_CONSTEXPR
auto msb_helper(
const UnsignedIntegralType& u) -> unsigned_fast_type
4639 static_assert(((std::is_integral<UnsignedIntegralType>::value)
4640 && (std::is_unsigned<UnsignedIntegralType>::value)),
4641 "Error: Please check the characteristics of UnsignedIntegralType");
4643 using local_unsigned_integral_type = UnsignedIntegralType;
4645 signed_fast_type i{ };
4650 for (i =
static_cast<signed_fast_type
>(std::numeric_limits<local_unsigned_integral_type>::digits - 1); i >= 0; --i)
4652 if ((u &
static_cast<local_unsigned_integral_type
>(
static_cast<local_unsigned_integral_type
>(1U) << i)) != 0U)
4658 return static_cast<unsigned_fast_type
>((std::max)(
static_cast<signed_fast_type
>(0), i));
4662 inline WIDE_INTEGER_CONSTEXPR
auto msb_helper<std::uint32_t>(
const std::uint32_t& u) -> unsigned_fast_type
4664 auto r =
static_cast<unsigned_fast_type
>(0U);
4665 auto x =
static_cast<std::uint_fast32_t
>(u);
4668 if ((x & UINT32_C(0xFFFF0000)) != UINT32_C(0)) { x =
static_cast<std::uint_fast32_t
>(x >>
static_cast<unsigned>(UINT8_C(16))); r =
static_cast<unsigned_fast_type
>(r | UINT32_C(16)); }
4669 if ((x & UINT32_C(0x0000FF00)) != UINT32_C(0)) { x =
static_cast<std::uint_fast32_t
>(x >>
static_cast<unsigned>(UINT8_C(8))); r =
static_cast<unsigned_fast_type
>(r | UINT32_C(8)); }
4670 if ((x & UINT32_C(0x000000F0)) != UINT32_C(0)) { x =
static_cast<std::uint_fast32_t
>(x >>
static_cast<unsigned>(UINT8_C(4))); r =
static_cast<unsigned_fast_type
>(r | UINT32_C(4)); }
4671 if ((x & UINT32_C(0x0000000C)) != UINT32_C(0)) { x =
static_cast<std::uint_fast32_t
>(x >>
static_cast<unsigned>(UINT8_C(2))); r =
static_cast<unsigned_fast_type
>(r | UINT32_C(2)); }
4672 if ((x & UINT32_C(0x00000002)) != UINT32_C(0)) { r =
static_cast<unsigned_fast_type
>(r | UINT32_C(1)); }
4678 inline WIDE_INTEGER_CONSTEXPR
auto msb_helper<std::uint16_t>(
const std::uint16_t& u) -> unsigned_fast_type
4680 auto r =
static_cast<unsigned_fast_type
>(0U);
4681 auto x =
static_cast<std::uint_fast16_t
>(u);
4684 if (
static_cast<std::uint_fast16_t
>(
static_cast<std::uint_fast32_t
>(x) & UINT32_C(0xFF00)) != UINT16_C(0)) { x =
static_cast<std::uint_fast16_t
>(x >>
static_cast<unsigned>(UINT8_C(8))); r =
static_cast<unsigned_fast_type
>(r | UINT32_C(8)); }
4685 if (
static_cast<std::uint_fast16_t
>(
static_cast<std::uint_fast32_t
>(x) & UINT32_C(0x00F0)) != UINT16_C(0)) { x =
static_cast<std::uint_fast16_t
>(x >>
static_cast<unsigned>(UINT8_C(4))); r =
static_cast<unsigned_fast_type
>(r | UINT32_C(4)); }
4686 if (
static_cast<std::uint_fast16_t
>(
static_cast<std::uint_fast32_t
>(x) & UINT32_C(0x000C)) != UINT16_C(0)) { x =
static_cast<std::uint_fast16_t
>(x >>
static_cast<unsigned>(UINT8_C(2))); r =
static_cast<unsigned_fast_type
>(r | UINT32_C(2)); }
4687 if (
static_cast<std::uint_fast16_t
>(
static_cast<std::uint_fast32_t
>(x) & UINT32_C(0x0002)) != UINT16_C(0)) { r =
static_cast<unsigned_fast_type
>(r | UINT32_C(1)); }
4693 inline WIDE_INTEGER_CONSTEXPR
auto msb_helper<std::uint8_t>(
const std::uint8_t& u) -> unsigned_fast_type
4695 auto r =
static_cast<unsigned_fast_type
>(0U);
4696 auto x =
static_cast<std::uint_fast8_t
>(u);
4699 if (
static_cast<std::uint_fast8_t
>(
static_cast<std::uint_fast32_t
>(x) & UINT32_C(0xF0)) != UINT8_C(0)) { x =
static_cast<std::uint_fast8_t
>(x >>
static_cast<unsigned>(UINT8_C(4))); r =
static_cast<unsigned_fast_type
>(r | UINT32_C(4)); }
4700 if (
static_cast<std::uint_fast8_t
>(
static_cast<std::uint_fast32_t
>(x) & UINT32_C(0x0C)) != UINT8_C(0)) { x =
static_cast<std::uint_fast8_t
>(x >>
static_cast<unsigned>(UINT8_C(2))); r =
static_cast<unsigned_fast_type
>(r | UINT32_C(2)); }
4701 if (
static_cast<std::uint_fast8_t
>(
static_cast<std::uint_fast32_t
>(x) & UINT32_C(0x02)) != UINT8_C(0)) { r =
static_cast<unsigned_fast_type
>(r | UINT32_C(1)); }
4708 template<
const size_t Width2,
4710 typename AllocatorType,
4711 const bool IsSigned>
4712 WIDE_INTEGER_CONSTEXPR
void swap(uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& x,
4713 uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& y)
4717 using local_wide_integer_type = uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
4719 const local_wide_integer_type tmp_x(x);
4726 template<
const size_t Width2,
4728 typename AllocatorType,
4729 const bool IsSigned>
4730 inline WIDE_INTEGER_CONSTEXPR
auto lsb(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& x) -> unsigned_fast_type
4735 using local_wide_integer_type = uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
4736 using local_value_type =
typename local_wide_integer_type::representation_type::value_type;
4738 auto bpos =
static_cast<unsigned_fast_type
>(0U);
4739 auto offset =
static_cast<unsigned_fast_type
>(0U);
4741 for (
auto it = x.crepresentation().cbegin(); it != x.crepresentation().cend(); ++it, ++offset)
4743 const auto vi =
static_cast<local_value_type
>(*it & (std::numeric_limits<local_value_type>::max)());
4745 if (vi !=
static_cast<local_value_type
>(0U))
4747 bpos =
static_cast<unsigned_fast_type
>
4749 detail::lsb_helper(*it)
4750 +
static_cast<unsigned_fast_type
>(
static_cast<unsigned_fast_type
>(std::numeric_limits<local_value_type>::digits) * offset)
4760 template<
const size_t Width2,
4762 typename AllocatorType,
4763 const bool IsSigned>
4764 WIDE_INTEGER_CONSTEXPR
auto msb(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& x) -> unsigned_fast_type
4769 using local_wide_integer_type = uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
4770 using local_value_type =
typename local_wide_integer_type::representation_type::value_type;
4772 auto bpos =
static_cast<unsigned_fast_type
>(0U);
4773 auto offset =
static_cast<unsigned_fast_type
>(x.crepresentation().size() - 1U);
4775 for (
auto ri = x.crepresentation().crbegin(); ri != x.crepresentation().crend(); ++ri, --offset)
4777 const auto vr =
static_cast<local_value_type
>(*ri & (std::numeric_limits<local_value_type>::max)());
4779 if (vr !=
static_cast<local_value_type
>(0U))
4781 bpos =
static_cast<unsigned_fast_type
>
4783 detail::msb_helper(*ri)
4784 +
static_cast<unsigned_fast_type
>(
static_cast<unsigned_fast_type
>(std::numeric_limits<local_value_type>::digits) * offset)
4794 template<
const size_t Width2,
4796 typename AllocatorType,
4797 const bool IsSigned>
4798 constexpr auto abs(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& x) -> uintwide_t<Width2, LimbType, AllocatorType, IsSigned>
4800 using local_wide_integer_type = uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
4802 return ((!local_wide_integer_type::is_neg(x)) ? x : -x);
4805 template<
const size_t Width2,
4807 typename AllocatorType,
4808 const bool IsSigned>
4809 WIDE_INTEGER_CONSTEXPR
auto sqrt(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& m) -> uintwide_t<Width2, LimbType, AllocatorType, IsSigned>
4813 using local_wide_integer_type = uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
4815 local_wide_integer_type s;
4817 if (m.is_zero() || local_wide_integer_type::is_neg(m))
4819 s = local_wide_integer_type(
static_cast<std::uint_fast8_t
>(0U));
4825 const unsigned_fast_type msb_pos = msb(m);
4828 const unsigned_fast_type left_shift_amount =
4829 ((
static_cast<unsigned_fast_type
>(msb_pos % 2U) == 0U)
4830 ?
static_cast<unsigned_fast_type
>(1U +
static_cast<unsigned_fast_type
>((msb_pos + 0U) / 2U))
4831 : static_cast<unsigned_fast_type>(1U + static_cast<unsigned_fast_type>((msb_pos + 1U) / 2U)));
4833 local_wide_integer_type
4836 local_wide_integer_type(
static_cast<std::uint_fast8_t
>(1U)) << left_shift_amount
4844 for (
auto i =
static_cast<unsigned_fast_type
>(0U); i < static_cast<unsigned_fast_type>(UINT8_C(64)); ++i)
4848 u = (s + (m / s)) >> 1;
4860 template<
const size_t Width2,
4862 typename AllocatorType,
4863 const bool IsSigned>
4864 WIDE_INTEGER_CONSTEXPR
auto cbrt(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& m) -> uintwide_t<Width2, LimbType, AllocatorType, IsSigned>
4868 using local_wide_integer_type = uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
4870 local_wide_integer_type s;
4872 if (local_wide_integer_type::is_neg(m))
4876 else if (m.is_zero())
4878 s = local_wide_integer_type(
static_cast<std::uint_fast8_t
>(0U));
4884 const unsigned_fast_type msb_pos = msb(m);
4887 const auto msb_pos_mod_3 =
static_cast<unsigned_fast_type
>(msb_pos % UINT8_C(3));
4889 const unsigned_fast_type left_shift_amount =
4890 ((msb_pos_mod_3 == 0U)
4891 ?
static_cast<unsigned_fast_type
>(1U +
static_cast<unsigned_fast_type
>((msb_pos + 0U) / 3U))
4892 :
static_cast<unsigned_fast_type
>(1U +
static_cast<unsigned_fast_type
>((msb_pos + (3U - msb_pos_mod_3)) / 3U)));
4894 local_wide_integer_type u(local_wide_integer_type(
static_cast<std::uint_fast8_t
>(1U)) << left_shift_amount);
4901 const auto three_minus_one =
static_cast<unsigned_fast_type
>(3U - 1U);
4903 for (
auto i =
static_cast<unsigned_fast_type
>(0U); i < static_cast<unsigned_fast_type>(UINT8_C(64)); ++i)
4907 local_wide_integer_type m_over_s_pow_3_minus_one = m;
4909 for (unsigned_fast_type j = 0U; j < 3U - 1U; ++j)
4914 m_over_s_pow_3_minus_one /= s;
4917 u = ((s * three_minus_one) + m_over_s_pow_3_minus_one) / 3U;
4929 template<
const size_t Width2,
4931 typename AllocatorType,
4932 const bool IsSigned>
4933 WIDE_INTEGER_CONSTEXPR
auto rootk(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& m,
const std::uint_fast8_t k) -> uintwide_t<Width2, LimbType, AllocatorType, IsSigned>
4937 using local_wide_integer_type = uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
4939 local_wide_integer_type s;
4955 if (m.is_zero() || local_wide_integer_type::is_neg(m))
4957 s = local_wide_integer_type(
static_cast<std::uint_fast8_t
>(0U));
4963 const unsigned_fast_type msb_pos = msb(m);
4966 const unsigned_fast_type msb_pos_mod_k = msb_pos % k;
4968 const unsigned_fast_type left_shift_amount =
4969 ((msb_pos_mod_k == 0U)
4970 ? 1U +
static_cast<unsigned_fast_type
>((msb_pos + 0U) / k)
4971 : 1U + static_cast<unsigned_fast_type>((msb_pos + (k - msb_pos_mod_k)) / k));
4973 local_wide_integer_type u(local_wide_integer_type(
static_cast<std::uint_fast8_t
>(1U)) << left_shift_amount);
4980 const unsigned_fast_type k_minus_one(k - 1U);
4982 for (
auto i =
static_cast<unsigned_fast_type
>(0U); i < static_cast<unsigned_fast_type>(UINT8_C(64)); ++i)
4986 local_wide_integer_type m_over_s_pow_k_minus_one = m;
4988 for (unsigned_fast_type j = 0U; j < k - 1U; ++j)
4993 m_over_s_pow_k_minus_one /= s;
4996 u = ((s * k_minus_one) + m_over_s_pow_k_minus_one) / k;
5009 template<
typename OtherIntegralTypeP,
5010 const size_t Width2,
5012 typename AllocatorType,
5013 const bool IsSigned>
5014 WIDE_INTEGER_CONSTEXPR
auto pow(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& b,
const OtherIntegralTypeP& p) -> uintwide_t<Width2, LimbType, AllocatorType, IsSigned>
5017 using local_wide_integer_type = uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
5018 using local_limb_type =
typename local_wide_integer_type::limb_type;
5020 local_wide_integer_type result;
5021 auto p0(
static_cast<local_limb_type
>(p));
5023 if ((p0 == 0U) && (p == OtherIntegralTypeP(0)))
5025 result = local_wide_integer_type(
static_cast<std::uint8_t
>(1U));
5027 else if ((p0 == 1U) && (p == OtherIntegralTypeP(1)))
5031 else if ((p0 == 2U) && (p == OtherIntegralTypeP(2)))
5038 result = local_wide_integer_type(
static_cast<std::uint8_t
>(1U));
5040 local_wide_integer_type y(b);
5041 local_wide_integer_type p_local(p);
5043 while (((p0 =
static_cast<local_limb_type
>(p_local)) != 0U) || (p_local != 0U))
5045 if ((p0 & 1U) != 0U)
5059 template<
typename OtherIntegralTypeP,
5060 typename OtherIntegralTypeM,
5061 const size_t Width2,
5063 typename AllocatorType,
5064 const bool IsSigned>
5065 WIDE_INTEGER_CONSTEXPR
auto powm(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& b,
5066 const OtherIntegralTypeP& p,
5067 const OtherIntegralTypeM& m) -> uintwide_t<Width2, LimbType, AllocatorType, IsSigned>
5071 using local_normal_width_type = uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
5072 using local_double_width_type =
typename local_normal_width_type::double_width_type;
5073 using local_limb_type =
typename local_normal_width_type::limb_type;
5075 local_normal_width_type result;
5076 local_double_width_type y(b);
5077 const local_double_width_type m_local(m);
5078 auto p0(
static_cast<local_limb_type
>(p));
5080 if ((p0 == 0U) && (p == OtherIntegralTypeP(0)))
5082 result = local_normal_width_type((m != 1U) ?
static_cast<std::uint8_t
>(1U) : static_cast<std::uint8_t>(0U));
5084 else if ((p0 == 1U) && (p == OtherIntegralTypeP(1)))
5088 else if ((p0 == 2U) && (p == OtherIntegralTypeP(2)))
5093 result = local_normal_width_type(y);
5097 local_double_width_type x(
static_cast<std::uint8_t
>(1U));
5098 OtherIntegralTypeP p_local(p);
5100 while (((p0 =
static_cast<local_limb_type
>(p_local)) != 0U) || (p_local != 0U))
5102 if ((p0 & 1U) != 0U)
5114 result = local_normal_width_type(x);
5122 template<
typename Un
signedShortType>
5123 WIDE_INTEGER_CONSTEXPR
auto integer_gcd_reduce_short(UnsignedShortType u, UnsignedShortType v) -> UnsignedShortType
5141 v >>= detail::lsb_helper(v);
5147 template<
typename Un
signedLargeType>
5148 WIDE_INTEGER_CONSTEXPR
auto integer_gcd_reduce_large(UnsignedLargeType u, UnsignedLargeType v) -> UnsignedLargeType
5153 using local_ularge_type = UnsignedLargeType;
5154 using local_ushort_type =
typename detail::uint_type_helper<static_cast<size_t>(std::numeric_limits<local_ularge_type>::digits / 2)>::exact_unsigned_type;
5168 if (v <=
static_cast<local_ularge_type
>((std::numeric_limits<local_ushort_type>::max)()))
5170 u = integer_gcd_reduce_short(
static_cast<local_ushort_type
>(v),
5171 static_cast<local_ushort_type
>(u));
5178 while (
static_cast<std::uint_fast8_t
>(
static_cast<std::uint_fast8_t
>(v) & UINT8_C(1)) == UINT8_C(0))
5189 template<
const size_t Width2,
5191 typename AllocatorType,
5192 const bool IsSigned>
5193 WIDE_INTEGER_CONSTEXPR
auto gcd(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& a,
5194 const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& b) -> uintwide_t<Width2, LimbType, AllocatorType, IsSigned>
5199 using local_wide_integer_type = uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
5200 using local_ushort_type =
typename local_wide_integer_type::limb_type;
5201 using local_ularge_type =
typename local_wide_integer_type::double_limb_type;
5203 const bool u_is_neg = local_wide_integer_type::is_neg(a);
5204 const bool v_is_neg = local_wide_integer_type::is_neg(b);
5206 local_wide_integer_type u((!u_is_neg) ? a : -a);
5207 local_wide_integer_type v((!v_is_neg) ? b : -b);
5209 local_wide_integer_type result;
5217 if ((
static_cast<local_ushort_type
>(v) == 0U) && (v == 0U))
5223 if ((
static_cast<local_ushort_type
>(u) == 0U) && (u == 0U))
5235 const unsigned_fast_type u_shift = lsb(u);
5236 const unsigned_fast_type v_shift = lsb(v);
5238 const unsigned_fast_type left_shift_amount = (std::min)(u_shift, v_shift);
5258 if (v <= (std::numeric_limits<local_ularge_type>::max)())
5260 if (v <= (std::numeric_limits<local_ushort_type>::max)())
5262 u = detail::integer_gcd_reduce_short(*(v.crepresentation().cbegin() + 0U),
5263 *(u.crepresentation().cbegin() + 0U));
5267 const auto my_v_hi =
5268 static_cast<local_ushort_type
>
5270 (v.crepresentation().size() >=
static_cast<typename local_wide_integer_type::representation_type::size_type
>(2U))
5271 ?
static_cast<local_ushort_type
>(*(v.crepresentation().cbegin() + 1U))
5272 :
static_cast<local_ushort_type
>(0U)
5275 const auto my_u_hi =
5276 static_cast<local_ushort_type
>
5278 (u.crepresentation().size() >=
static_cast<typename local_wide_integer_type::representation_type::size_type
>(2U))
5279 ?
static_cast<local_ushort_type
>(*(u.crepresentation().cbegin() + 1U))
5280 :
static_cast<local_ushort_type
>(0U)
5283 const local_ularge_type v_large = detail::make_large(*(v.crepresentation().cbegin() + 0U), my_v_hi);
5284 const local_ularge_type u_large = detail::make_large(*(u.crepresentation().cbegin() + 0U), my_u_hi);
5286 u = detail::integer_gcd_reduce_large(v_large, u_large);
5296 result = (u << left_shift_amount);
5299 return ((u_is_neg == v_is_neg) ? result : -result);
5302 template<
typename Un
signedShortType>
5303 WIDE_INTEGER_CONSTEXPR
auto gcd(
const UnsignedShortType& u,
const UnsignedShortType& v) ->
typename std::enable_if<((std::is_integral<UnsignedShortType>::value)
5304 && (std::is_unsigned<UnsignedShortType>::value)), UnsignedShortType>::type
5306 UnsignedShortType result;
5332 result = detail::integer_gcd_reduce_short(u, v);
5340 template<
typename IntegerType>
5341 WIDE_INTEGER_CONSTEXPR
auto lcm_impl(
const IntegerType& a,
const IntegerType& b) -> IntegerType
5343 using local_integer_type = IntegerType;
5347 const local_integer_type ap = abs(a);
5348 const local_integer_type bp = abs(b);
5350 const bool a_is_greater_than_b = (ap > bp);
5352 const local_integer_type gcd_of_ab = gcd(a, b);
5354 return (a_is_greater_than_b ? ap * (bp / gcd_of_ab)
5355 : bp * (ap / gcd_of_ab));
5360 template<
const size_t Width2,
5362 typename AllocatorType,
5363 const bool IsSigned>
5364 WIDE_INTEGER_CONSTEXPR
auto lcm(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& a,
5365 const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& b) -> uintwide_t<Width2, LimbType, AllocatorType, IsSigned>
5367 return detail::lcm_impl(a, b);
5370 template<
typename Un
signedShortType>
5371 WIDE_INTEGER_CONSTEXPR
auto lcm(
const UnsignedShortType& a,
const UnsignedShortType& b) ->
typename std::enable_if<((std::is_integral<UnsignedShortType>::value)
5372 && (std::is_unsigned<UnsignedShortType>::value)), UnsignedShortType>::type
5374 return detail::lcm_impl(a, b);
5377 template<
const size_t Width2,
5379 typename AllocatorType,
5380 const bool IsSigned>
5390 result_type p_b = (std::numeric_limits<result_type>::max)())
5391 : param_a(std::move(p_a)),
5392 param_b(std::move(p_b)) { }
5397 param_b(other_params.param_b) { }
5400 param_b(other_params.param_b) { }
5404 if (
this != &other_params)
5406 param_a = other_params.param_a;
5407 param_b = other_params.param_b;
5415 param_a = other_params.param_a;
5416 param_b = other_params.param_b;
5421 WIDE_INTEGER_NODISCARD
constexpr auto get_a()
const ->
result_type {
return param_a; }
5422 WIDE_INTEGER_NODISCARD
constexpr auto get_b()
const ->
result_type {
return param_b; }
5424 void set_a(
const result_type& p_a) { param_a = p_a; }
5425 void set_b(
const result_type& p_b) { param_b = p_b; }
5431 friend inline constexpr auto operator==(
const param_type& lhs,
5434 return ((lhs.param_a == rhs.param_a)
5435 && (lhs.param_b == rhs.param_b));
5438 friend inline constexpr auto operator!=(
const param_type& lhs,
5441 return ((lhs.param_a != rhs.param_a)
5442 || (lhs.param_b != rhs.param_b));
5449 const result_type& p_b = (std::numeric_limits<result_type>::max)())
5450 : my_params(param_type(p_a, p_b)) { }
5452 explicit uniform_int_distribution(
const param_type& other_params)
5453 : my_params(other_params) { }
5455 uniform_int_distribution(
const uniform_int_distribution& other_distribution) =
delete;
5457 uniform_int_distribution(uniform_int_distribution&& other) noexcept : my_params(other.my_params) { }
5459 ~uniform_int_distribution() =
default;
5461 auto operator=(
const uniform_int_distribution& other) -> uniform_int_distribution &
5465 my_params = other.my_params;
5471 auto operator=(uniform_int_distribution&& other)
noexcept -> uniform_int_distribution &
5473 my_params = other.my_params;
5478 void param(
const param_type& new_params)
5480 my_params = new_params;
5483 WIDE_INTEGER_NODISCARD
auto param() const -> const param_type & {
return my_params; }
5485 WIDE_INTEGER_NODISCARD
auto a() const -> result_type {
return my_params.get_a(); }
5486 WIDE_INTEGER_NODISCARD
auto b() const -> result_type {
return my_params.get_b(); }
5488 template<
typename GeneratorType,
5489 const int GeneratorResultBits = std::numeric_limits<typename GeneratorType::result_type>::digits>
5490 WIDE_INTEGER_CONSTEXPR
auto operator()(GeneratorType & generator) -> result_type
5492 return generate<GeneratorType, GeneratorResultBits>
5499 template<
typename GeneratorType,
5500 const int GeneratorResultBits = std::numeric_limits<typename GeneratorType::result_type>::digits>
5501 WIDE_INTEGER_CONSTEXPR
auto operator()(GeneratorType & input_generator,
5502 const param_type & input_params) -> result_type
5504 return generate<GeneratorType, GeneratorResultBits>
5512 param_type my_params;
5514 template<
typename GeneratorType,
5515 const int GeneratorResultBits = std::numeric_limits<typename GeneratorType::result_type>::digits>
5516 WIDE_INTEGER_CONSTEXPR
auto generate(GeneratorType & input_generator,
5517 const param_type & input_params)
const -> result_type
5521 auto result =
static_cast<result_type
>(
static_cast<std::uint8_t
>(0U));
5523 using local_limb_type =
typename result_type::limb_type;
5525 using generator_result_type =
typename GeneratorType::result_type;
5527 constexpr auto digits_generator_result_type =
static_cast<std::uint32_t
>(GeneratorResultBits);
5529 static_assert((digits_generator_result_type % UINT32_C(8)) == UINT32_C(0),
5530 "Error: Generator result type must have a multiple of 8 bits.");
5532 constexpr auto digits_limb_ratio =
5533 static_cast<std::uint32_t
>(std::numeric_limits<local_limb_type>::digits / 8U);
5535 constexpr auto digits_gtor_ratio =
static_cast<std::uint32_t
>(digits_generator_result_type / 8U);
5537 generator_result_type value = generator_result_type();
5539 auto it = result.representation().begin();
5541 unsigned_fast_type j = 0U;
5543 while (it != result.representation().end())
5545 if ((j % digits_gtor_ratio) == 0U)
5547 value = input_generator();
5550 const auto next_byte =
5551 static_cast<std::uint8_t
>(value >>
static_cast<unsigned>(
static_cast<unsigned_fast_type
>(j % digits_gtor_ratio) *
static_cast<unsigned_fast_type
>(UINT8_C(8))));
5554 static_cast<typename result_type::limb_type
>
5556 *it |
static_cast<local_limb_type
>(
static_cast<local_limb_type
>(next_byte) <<
static_cast<unsigned>(
static_cast<unsigned_fast_type
>(j % digits_limb_ratio) *
static_cast<unsigned_fast_type
>(UINT8_C(8))))
5561 if (
static_cast<unsigned_fast_type
>(j % digits_limb_ratio) ==
static_cast<unsigned_fast_type
>(0U))
5567 if ((input_params.get_a() != (std::numeric_limits<result_type>::min)())
5568 || (input_params.get_b() != (std::numeric_limits<result_type>::max)()))
5573 result_type range(input_params.get_b() - input_params.get_a());
5578 result += input_params.get_a();
5585 template<
const size_t Width2,
5587 typename AllocatorType,
5588 const bool IsSigned>
5589 constexpr auto operator==(
const uniform_int_distribution<Width2, LimbType, AllocatorType, IsSigned>& lhs,
5590 const uniform_int_distribution<Width2, LimbType, AllocatorType, IsSigned>& rhs) ->
bool
5592 return (lhs.param() == rhs.param());
5595 template<
const size_t Width2,
5597 typename AllocatorType,
5598 const bool IsSigned>
5599 constexpr auto operator!=(
const uniform_int_distribution<Width2, LimbType, AllocatorType, IsSigned>& lhs,
5600 const uniform_int_distribution<Width2, LimbType, AllocatorType, IsSigned>& rhs) ->
bool
5602 return (lhs.param() != rhs.param());
5605 template<
typename DistributionType,
5606 typename GeneratorType,
5607 const size_t Width2,
5609 typename AllocatorType,
5610 const bool IsSigned>
5611 auto miller_rabin(
const uintwide_t<Width2, LimbType, AllocatorType, IsSigned>& n,
5612 const unsigned_fast_type number_of_trials,
5613 DistributionType& distribution,
5614 GeneratorType& generator) ->
bool
5624 using local_wide_integer_type = uintwide_t<Width2, LimbType, AllocatorType, IsSigned>;
5625 using local_limb_type =
typename local_wide_integer_type::limb_type;
5627 const local_wide_integer_type np((!local_wide_integer_type::is_neg(n)) ? n : -n);
5630 const auto n0 =
static_cast<local_limb_type
>(np);
5632 if ((n0 & 1U) == 0U)
5638 if ((n0 <=
static_cast<local_limb_type
>(UINT8_C(227))) && (np <= static_cast<local_limb_type>(UINT8_C(227))))
5640 if ((n0 ==
static_cast<local_limb_type
>(UINT8_C(2))) && (np ==
static_cast<local_limb_type
>(UINT8_C(2))))
5659 constexpr std::array<local_limb_type, 48U> small_primes =
5661 UINT8_C(3), UINT8_C(5), UINT8_C(7), UINT8_C(11), UINT8_C(13), UINT8_C(17), UINT8_C(19), UINT8_C(23),
5662 UINT8_C(29), UINT8_C(31), UINT8_C(37), UINT8_C(41), UINT8_C(43), UINT8_C(47), UINT8_C(53), UINT8_C(59),
5663 UINT8_C(61), UINT8_C(67), UINT8_C(71), UINT8_C(73), UINT8_C(79), UINT8_C(83), UINT8_C(89), UINT8_C(97),
5664 UINT8_C(101), UINT8_C(103), UINT8_C(107), UINT8_C(109), UINT8_C(113), UINT8_C(127), UINT8_C(131), UINT8_C(137),
5665 UINT8_C(139), UINT8_C(149), UINT8_C(151), UINT8_C(157), UINT8_C(163), UINT8_C(167), UINT8_C(173), UINT8_C(179),
5666 UINT8_C(181), UINT8_C(191), UINT8_C(193), UINT8_C(197), UINT8_C(199), UINT8_C(211), UINT8_C(223), UINT8_C(227)
5669 return std::binary_search(small_primes.cbegin(),
5670 small_primes.cend(),
5681 constexpr std::uint64_t pp0 = UINT64_C(16294579238595022365);
5683 const auto m0 =
static_cast<std::uint64_t
>(np % pp0);
5685 if (detail::integer_gcd_reduce_large(m0, pp0) != 1U)
5695 constexpr std::uint64_t pp1 = UINT64_C(7145393598349078859);
5697 const auto m1 =
static_cast<std::uint64_t
>(np % pp1);
5699 if (detail::integer_gcd_reduce_large(m1, pp1) != 1U)
5709 constexpr std::uint64_t pp2 = UINT64_C(6408001374760705163);
5711 const auto m2 =
static_cast<std::uint64_t
>(np % pp2);
5713 if (detail::integer_gcd_reduce_large(m2, pp2) != 1U)
5723 constexpr std::uint64_t pp3 = UINT64_C(690862709424854779);
5725 const auto m3 =
static_cast<std::uint64_t
>(np % pp3);
5727 if (detail::integer_gcd_reduce_large(m3, pp3) != 1U)
5737 constexpr std::uint64_t pp4 = UINT64_C(80814592450549);
5739 const auto m4 =
static_cast<std::uint64_t
>(np % pp4);
5741 if (detail::integer_gcd_reduce_large(m4, pp4) != 1U)
5747 const local_wide_integer_type nm1(np - 1U);
5756 const local_wide_integer_type fn = powm(local_wide_integer_type(
static_cast<local_limb_type
>(228U)), nm1, np);
5758 const auto fn0 =
static_cast<local_limb_type
>(fn);
5760 if ((fn0 != 1U) && (fn != 1U))
5766 const unsigned_fast_type k = lsb(nm1);
5768 const local_wide_integer_type q = nm1 >> k;
5770 using local_param_type =
typename DistributionType::param_type;
5772 const local_param_type params(local_wide_integer_type(2U), np - 2U);
5774 bool is_probably_prime =
true;
5776 auto i =
static_cast<unsigned_fast_type
>(0U);
5778 local_wide_integer_type x;
5779 local_wide_integer_type y;
5784 x = distribution(generator, params);
5787 auto j =
static_cast<unsigned_fast_type
>(0U);
5791 const local_limb_type y0(y);
5793 if ((y0 == 1U) && (y == 1U))
5797 is_probably_prime =
false;
5810 is_probably_prime =
false;
5814 y = powm(y, 2U, np);
5820 }
while ((i < number_of_trials) && is_probably_prime);
5824 return is_probably_prime;
5827#if(__cplusplus >= 201703L)
5834WIDE_INTEGER_NAMESPACE_END
bool operator==(const Immediate &imm1, const Immediate &imm2)
Compares two Immediate.
std::ostream & operator<<(std::ostream &stream, BasicBlock &block)
Displays an BasicBlock.
bool operator!=(const Immediate &imm1, const Immediate &imm2)
Compares two Immediate.
bool operator<(const Immediate &imm1, const Immediate &imm2)
Compares two Immediate (needed for std::map)