1///////////////////////////////////////////////////////////////
2// Copyright 2012 - 2021 John Maddock.
3// Copyright 2021 Matt Borland.
4// Distributed under the Boost Software License, Version 1.0.
5// See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
6
7#ifndef BOOST_MP_CPP_INT_CONFIG_HPP
8#define BOOST_MP_CPP_INT_CONFIG_HPP
9
10#include <cstdint>
11#include <type_traits>
12#include <limits>
13#include <boost/multiprecision/detail/standalone_config.hpp>
14#include <boost/multiprecision/detail/assert.hpp>
15
16namespace boost {
17namespace multiprecision {
18
19namespace detail {
20
21//
22// These traits calculate the largest type in the list
23// [unsigned] long long, long, int, which has the specified number
24// of bits. Note that int_t and uint_t find the first
25// member of the above list, not the last. We want the last in the
26// list to ensure that mixed arithmetic operations are as efficient
27// as possible.
28//
29
30template <std::size_t Bits>
31struct int_t
32{
33 using exact = typename std::conditional<Bits <= sizeof(signed char) * CHAR_BIT, signed char,
34 typename std::conditional<Bits <= sizeof(short) * CHAR_BIT, short,
35 typename std::conditional<Bits <= sizeof(int) * CHAR_BIT, int,
36 typename std::conditional<Bits <= sizeof(long) * CHAR_BIT, long,
37 typename std::conditional<Bits <= sizeof(long long) * CHAR_BIT, long long, void
38 >::type>::type>::type>::type>::type;
39
40 using least = typename std::conditional<Bits-1 <= std::numeric_limits<signed char>::digits, signed char,
41 typename std::conditional<Bits-1 <= std::numeric_limits<short>::digits, short,
42 typename std::conditional<Bits-1 <= std::numeric_limits<int>::digits, int,
43 typename std::conditional<Bits-1 <= std::numeric_limits<long>::digits, long,
44 typename std::conditional<Bits-1 <= std::numeric_limits<long long>::digits, long long, void
45 >::type>::type>::type>::type>::type;
46
47 static_assert(!std::is_same<void, exact>::value && !std::is_same<void, least>::value, "Number of bits does not match any standard data type. \
48 Please file an issue at https://github.com/boostorg/multiprecision/ referencing this error from cpp_int_config.hpp");
49};
50
51template <std::size_t Bits>
52struct uint_t
53{
54 using exact = typename std::conditional<Bits <= sizeof(unsigned char) * CHAR_BIT, unsigned char,
55 typename std::conditional<Bits <= sizeof(unsigned short) * CHAR_BIT, unsigned short,
56 typename std::conditional<Bits <= sizeof(unsigned int) * CHAR_BIT, unsigned int,
57 typename std::conditional<Bits <= sizeof(unsigned long) * CHAR_BIT, unsigned long,
58 typename std::conditional<Bits <= sizeof(unsigned long long) * CHAR_BIT, unsigned long long, void
59 >::type>::type>::type>::type>::type;
60
61 using least = typename std::conditional<Bits <= std::numeric_limits<unsigned char>::digits, unsigned char,
62 typename std::conditional<Bits <= std::numeric_limits<unsigned short>::digits, unsigned short,
63 typename std::conditional<Bits <= std::numeric_limits<unsigned int>::digits, unsigned int,
64 typename std::conditional<Bits <= std::numeric_limits<unsigned long>::digits, unsigned long,
65 typename std::conditional<Bits <= std::numeric_limits<unsigned long long>::digits, unsigned long long, void
66 >::type>::type>::type>::type>::type;
67
68 static_assert(!std::is_same<void, exact>::value && !std::is_same<void, least>::value, "Number of bits does not match any standard data type. \
69 Please file an issue at https://github.com/boostorg/multiprecision/ referencing this error from cpp_int_config.hpp");
70};
71
72template <std::size_t N>
73struct largest_signed_type
74{
75 using type = typename std::conditional<
76 1 + std::numeric_limits<long long>::digits == N,
77 long long,
78 typename std::conditional<
79 1 + std::numeric_limits<long>::digits == N,
80 long,
81 typename std::conditional<
82 1 + std::numeric_limits<int>::digits == N,
83 int,
84 typename int_t<N>::exact>::type>::type>::type;
85};
86
87template <std::size_t N>
88struct largest_unsigned_type
89{
90 using type = typename std::conditional<
91 std::numeric_limits<unsigned long long>::digits == N,
92 unsigned long long,
93 typename std::conditional<
94 std::numeric_limits<unsigned long>::digits == N,
95 unsigned long,
96 typename std::conditional<
97 std::numeric_limits<unsigned int>::digits == N,
98 unsigned int,
99 typename uint_t<N>::exact>::type>::type>::type;
100};
101
102} // namespace detail
103
104#if defined(BOOST_HAS_INT128)
105
106using limb_type = detail::largest_unsigned_type<64>::type;
107using signed_limb_type = detail::largest_signed_type<64>::type;
108using double_limb_type = boost::multiprecision::uint128_type;
109using signed_double_limb_type = boost::multiprecision::int128_type;
110constexpr limb_type max_block_10 = 1000000000000000000uLL;
111constexpr limb_type digits_per_block_10 = 18;
112
113inline BOOST_MP_CXX14_CONSTEXPR limb_type block_multiplier(std::size_t count)
114{
115 constexpr limb_type values[digits_per_block_10] = {10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000, 10000000000000000, 100000000000000000, 1000000000000000000};
116 BOOST_MP_ASSERT(count < digits_per_block_10);
117 return values[count];
118}
119
120// Can't do formatted IO on an __int128
121#define BOOST_MP_NO_DOUBLE_LIMB_TYPE_IO
122
123#else
124
125using limb_type = detail::largest_unsigned_type<32>::type;
126using signed_limb_type = detail::largest_signed_type<32>::type ;
127using double_limb_type = detail::largest_unsigned_type<64>::type;
128using signed_double_limb_type = detail::largest_signed_type<64>::type ;
129constexpr limb_type max_block_10 = 1000000000;
130constexpr limb_type digits_per_block_10 = 9;
131
132inline limb_type block_multiplier(std::size_t count)
133{
134 constexpr limb_type values[digits_per_block_10] = {10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
135 BOOST_MP_ASSERT(count < digits_per_block_10);
136 return values[count];
137}
138
139#endif
140
141constexpr std::size_t bits_per_limb = sizeof(limb_type) * CHAR_BIT;
142
143template <class T>
144inline BOOST_MP_CXX14_CONSTEXPR void minmax(const T& a, const T& b, T& aa, T& bb)
145{
146 if (a < b)
147 {
148 aa = a;
149 bb = b;
150 }
151 else
152 {
153 aa = b;
154 bb = a;
155 }
156}
157
158} // namespace multiprecision
159} // namespace boost
160
161#endif // BOOST_MP_CPP_INT_CONFIG_HPP
162

source code of boost/libs/multiprecision/include/boost/multiprecision/cpp_int/cpp_int_config.hpp