bi
An arbitrary precision integer library for C++.
Loading...
Searching...
No Matches
bi.hpp
1/*
2Copyright 2024 Owain Davies
3SPDX-License-Identifier: Apache-2.0
4*/
5
6#ifndef BI_INCLUDE_BI_HPP_
7#define BI_INCLUDE_BI_HPP_
8
9#include <climits>
10#include <compare>
11#include <iostream>
12#include <span>
13#include <string>
14#include <utility>
15
16#include "impl-bi_digit_vector.hpp"
17
18// NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers)
19
20static_assert(sizeof(double) * CHAR_BIT == 64, "64-bit double is assumed.");
21static_assert(-1 == ~0, "Two's complement representation assumed.");
22
23#if defined(_WIN32)
24#if defined(BI_API_EXPORTS)
25#define BI_API __declspec(dllexport)
26#else
27#define BI_API __declspec(dllimport)
28#endif
29#else
30#define BI_API
31#endif
32
33#if defined(BI_FORCE_64_BIT) && defined(__SIZEOF_INT128__)
34#define BI_DIGIT_64_BIT
35#elif defined(BI_FORCE_32_BIT)
36#define BI_DIGIT_32_BIT
37#else
38#define BI_DIGIT_32_BIT
39#endif
40
41namespace bi {
42
43#if defined(BI_DIGIT_64_BIT)
44using digit = uint64_t;
45#else
46using digit = uint32_t;
47#endif
48
49using bi_bitcount_t = unsigned long;
50using dvector = digit_vector<digit, bi_bitcount_t>;
51
52class BI_API bi_t {
53 public:
54 // Constructors
55 bi_t() noexcept;
56 template <std::integral T>
57 bi_t(T); // NOLINT(runtime/explicit)
58 bi_t(const bi_t&);
59 bi_t(bi_t&& other) noexcept;
60 explicit bi_t(const std::string&, int base = 10);
61 explicit bi_t(const char*, int base = 10);
62 bi_t(double); // NOLINT(runtime/explicit)
63
64 ~bi_t() = default;
65
66 // Assignment operators
67 bi_t& operator=(const bi_t&);
68 bi_t& operator=(bi_t&& other) noexcept;
69 template <std::integral T>
70 bi_t& operator=(T);
71 bi_t& operator=(const std::string&);
72 bi_t& operator=(const char*);
73 bi_t& operator=(double);
74
75 // Unary operators
76 bi_t operator+() const;
77 bi_t operator-() const;
78
79 // Increment and decrement
80 bi_t& operator++();
81 bi_t operator++(int);
82 bi_t& operator--();
83 bi_t operator--(int);
84
85 // Multiplicative operators
86 bi_t operator*(const bi_t&) const;
87 bi_t operator/(const bi_t&) const;
88 bi_t operator%(const bi_t&) const;
89 bi_t& operator*=(const bi_t&);
90 bi_t& operator/=(const bi_t&);
91 bi_t& operator%=(const bi_t&);
92 std::pair<bi_t, bi_t> div(const bi_t&) const;
93
94 // Additive operators
95 bi_t operator+(const bi_t&) const;
96 bi_t operator-(const bi_t&) const;
97 bi_t& operator+=(const bi_t&);
98 bi_t& operator-=(const bi_t&);
99
100 // Shift operators
101 bi_t operator<<(bi_bitcount_t shift) const;
102 bi_t operator>>(bi_bitcount_t shift) const;
103 bi_t& operator<<=(bi_bitcount_t shift);
104 bi_t& operator>>=(bi_bitcount_t shift);
105
106 // Comparisons
107 std::strong_ordering operator<=>(const bi_t&) const noexcept;
108 bool operator==(const bi_t&) const noexcept;
109
110 template <std::integral T>
111 std::strong_ordering operator<=>(T) const noexcept;
112 template <std::integral T>
113 bool operator==(T) const noexcept;
114
115 bool operator==(double) const noexcept;
116 bool operator!=(double) const noexcept;
117 bool operator<(double) const noexcept;
118 bool operator<=(double) const noexcept;
119 bool operator>(double) const noexcept;
120 bool operator>=(double) const noexcept;
121
122 // Bitwise operators
123 bi_t operator~() const;
124 bi_t operator&(const bi_t&) const;
125 bi_t operator|(const bi_t&) const;
126 bi_t operator^(const bi_t&) const;
127 bi_t& operator&=(const bi_t&);
128 bi_t& operator|=(const bi_t&);
129 bi_t& operator^=(const bi_t&);
130
131 // Conversion operators
132 explicit operator bool() const noexcept;
133 template <std::integral T>
134 explicit operator T() const noexcept;
135 explicit operator double() const noexcept;
136
137 // Bits
138 bi_bitcount_t bit_length() const noexcept;
139 bool test_bit(bi_bitcount_t) const noexcept;
140 bi_t& set_bit(bi_bitcount_t);
141
142 // Accessors for internal representation
143 size_t capacity() const noexcept;
144 size_t size() const noexcept;
145 bool negative() const noexcept;
146 std::span<const digit> digits() const;
147 void print_internal(std::ostream& os = std::cout) const noexcept;
148
149 // Other
150 void swap(bi_t&) noexcept;
151 std::string to_string(int base = 10) const;
152 void negate() noexcept;
153 int sign() const noexcept;
154 bool odd() const noexcept;
155 bool even() const noexcept;
156 template <std::integral T>
157 bool within() const noexcept;
158
159 // Friends
160 BI_API friend std::ostream& operator<<(std::ostream& os, const bi_t& x);
161
162 friend bool operator==(double lhs, const bi_t& rhs) noexcept;
163 friend bool operator!=(double lhs, const bi_t& rhs) noexcept;
164 friend bool operator<(double lhs, const bi_t& rhs) noexcept;
165 friend bool operator<=(double lhs, const bi_t& rhs) noexcept;
166 friend bool operator>(double lhs, const bi_t& rhs) noexcept;
167 friend bool operator>=(double lhs, const bi_t& rhs) noexcept;
168
169 /* Static */
170 // Exponentiation
171 static bi_t pow(const bi_t& base, bi_bitcount_t exp);
172 static bi_t pow(const bi_t& base, const bi_t& exp);
173
174 private:
175 dvector vec_;
176 bool negative_;
177
178 void reserve_(size_t new_capacity);
179 void resize_(size_t new_size);
180 digit& operator[](size_t index);
181 const digit& operator[](size_t index) const;
182 void resize_unsafe_(size_t new_size);
183 void trim() noexcept;
184
185 auto begin() noexcept;
186 auto begin() const noexcept;
187 auto end() noexcept;
188 auto end() const noexcept;
189 auto rbegin() noexcept;
190 auto rbegin() const noexcept;
191 auto rend() noexcept;
192 auto rend() const noexcept;
193
195 friend struct h_;
197};
198
199BI_API std::ostream& operator<<(std::ostream&, const bi_t&);
200
201BI_API void swap(bi_t& a, bi_t& b) noexcept;
202BI_API bi_t operator"" _bi(const char* str);
203BI_API bi_t abs(const bi_t& value);
204
205} // namespace bi
206
207// NOLINTEND(cppcoreguidelines-avoid-magic-numbers)
208
209#endif // BI_INCLUDE_BI_HPP_
210
211#include "impl-bi.inl"
Arbitrary-precision integer type and related functions.
Definition bi.hpp:52
size_t capacity() const noexcept
Return the number of digits the allocated storage can hold.