From f9d9f8b764a703768ac976b749d29f356f36d57e Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 20 Feb 2024 01:26:26 +0000 Subject: [PATCH] Update documentation --- bi_8hpp_source.html | 775 +++++--------- bi__exceptions_8hpp_source.html | 62 +- classbi_1_1bi__t.html | 52 +- classbi_1_1division__by__zero-members.html | 2 +- classbi_1_1division__by__zero.html | 7 +- classbi_1_1exception-members.html | 2 +- classbi_1_1exception.html | 7 +- classbi_1_1overflow__error-members.html | 2 +- classbi_1_1overflow__error.html | 7 +- complexity.html | 38 +- dir_68267d1309a1af8e8297ef4c3efbcdba.html | 6 + doxygen_crawl.html | 2 +- h___8hpp_source.html | 1098 ++++++++++++++++++++ menudata.js | 4 +- 14 files changed, 1428 insertions(+), 636 deletions(-) create mode 100644 h___8hpp_source.html diff --git a/bi_8hpp_source.html b/bi_8hpp_source.html index bdc8529..74e9ad7 100644 --- a/bi_8hpp_source.html +++ b/bi_8hpp_source.html @@ -101,556 +101,263 @@
8
9#include <algorithm>
10#include <cassert>
-
11#include <compare>
-
12#include <iostream>
-
13#include <limits>
+
11#include <climits>
+
12#include <compare>
+
13#include <iostream>
14#include <span>
15#include <string>
16#include <utility>
17
-
18#include "bi_config.hpp"
-
19#include "bi_digit_vector.hpp"
-
20
-
21// TODO: modularize through the use of more files and separate implementation
-
22// from interface.
+
18#include "bi_digit_vector.impl.hpp"
+
19
+
20// NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers)
+
21static_assert(sizeof(double) * CHAR_BIT == 64, "64-bit double is assumed.");
+
22static_assert(-1 == ~0, "Two's complement representation assumed.");
23
-
24namespace bi {
-
25
-
26using bi_config::bi_base;
-
27using bi_config::bi_bitcount_t;
-
28using bi_config::bi_dbits;
-
29using bi_config::bi_dmax;
-
30using bi_config::bi_dwidth;
-
31using bi_config::dbl_max_int;
-
32using bi_config::ddigit;
-
33using bi_config::digit;
-
34
-
-
80class BI_API bi_t {
-
81 public:
-
82 // Constructors
-
83 bi_t() noexcept;
-
84 template <std::integral T>
-
85 bi_t(T); // NOLINT(runtime/explicit)
-
86 bi_t(const bi_t&);
-
87 bi_t(bi_t&& other) noexcept;
-
88 explicit bi_t(const std::string&);
-
89 explicit bi_t(const char*);
+
24#if defined(_WIN32)
+
25#if defined(BI_API_EXPORTS)
+
26#define BI_API __declspec(dllexport)
+
27#else
+
28#define BI_API __declspec(dllimport)
+
29#endif
+
30#else
+
31#define BI_API
+
32#endif
+
33
+
34#if defined(BI_FORCE_64_BIT) && defined(__SIZEOF_INT128__)
+
35#define BI_DIGIT_64_BIT
+
36#elif defined(BI_FORCE_32_BIT)
+
37#define BI_DIGIT_32_BIT
+
38#else
+
39#define BI_DIGIT_32_BIT
+
40#endif
+
41
+
42namespace bi {
+
43
+
44#if defined(BI_DIGIT_64_BIT)
+
45using digit = uint64_t;
+
46#else
+
47using digit = uint32_t;
+
48#endif
+
49
+
50using bi_bitcount_t = unsigned long;
+
51using dvector = digit_vector<digit, bi_bitcount_t>;
+
52
+
+
53class BI_API bi_t {
+
54 public:
+
55 // Constructors
+
56 bi_t() noexcept;
+
57 template <std::integral T>
+
58 bi_t(T); // NOLINT(runtime/explicit)
+
59 bi_t(const bi_t&);
+
60 bi_t(bi_t&& other) noexcept;
+
61 explicit bi_t(const std::string&);
+
62 explicit bi_t(const char*);
+
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
+
72 // Unary operators
+
73 bi_t operator+() const;
+
74 bi_t operator-() const;
+
75
+
76 // Increment and decrement
+
77 bi_t& operator++();
+
78 bi_t operator++(int);
+
79 bi_t& operator--();
+
80 bi_t operator--(int);
+
81
+
82 // Multiplicative operators
+
83 bi_t operator*(const bi_t&) const;
+
84 bi_t operator/(const bi_t&) const;
+
85 bi_t operator%(const bi_t&) const;
+
86 bi_t& operator*=(const bi_t&);
+
87 bi_t& operator/=(const bi_t&);
+
88 bi_t& operator%=(const bi_t&);
+
89 std::pair<bi_t, bi_t> div(const bi_t&) const;
90
-
91 ~bi_t() = default;
-
92
-
93 // Assignment operators
-
94 bi_t& operator=(const bi_t&);
-
95 bi_t& operator=(bi_t&& other) noexcept;
-
96 template <std::integral T>
-
97 bi_t& operator=(T);
-
98
-
99 // Unary operators
-
100 bi_t operator+() const;
-
101 bi_t operator-() const;
+
91 // Additive operators
+
92 bi_t operator+(const bi_t&) const;
+
93 bi_t operator-(const bi_t&) const;
+
94 bi_t& operator+=(const bi_t&);
+
95 bi_t& operator-=(const bi_t&);
+
96
+
97 // Shift operators
+
98 bi_t operator<<(bi_bitcount_t shift) const;
+
99 bi_t operator>>(bi_bitcount_t shift) const;
+
100 bi_t& operator<<=(bi_bitcount_t shift);
+
101 bi_t& operator>>=(bi_bitcount_t shift);
102
-
103 // Increment and decrement
-
104 bi_t& operator++();
-
105 bi_t operator++(int);
-
106 bi_t& operator--();
-
107 bi_t operator--(int);
-
108
-
109 // Multiplicative operators
-
110 bi_t operator*(const bi_t&) const;
-
111 bi_t operator/(const bi_t&) const;
-
112 bi_t operator%(const bi_t&) const;
-
113 bi_t& operator*=(const bi_t&);
-
114 bi_t& operator/=(const bi_t&);
-
115 bi_t& operator%=(const bi_t&);
-
116 std::pair<bi_t, bi_t> div(const bi_t&) const;
-
117
-
118 // Additive operators
-
119 bi_t operator+(const bi_t&) const;
-
120 bi_t operator-(const bi_t&) const;
-
121 bi_t& operator+=(const bi_t&);
-
122 bi_t& operator-=(const bi_t&);
-
123
-
124 // Shift operators
-
125 bi_t operator<<(bi_bitcount_t shift) const;
-
126 bi_t operator>>(bi_bitcount_t shift) const;
-
127 bi_t& operator<<=(bi_bitcount_t shift);
-
128 bi_t& operator>>=(bi_bitcount_t shift);
-
129
-
130 // Comparisons
-
131 std::strong_ordering operator<=>(const bi_t&) const noexcept;
-
132 bool operator==(const bi_t&) const noexcept;
-
133 template <std::integral T>
-
134 std::strong_ordering operator<=>(T) const noexcept;
-
135 template <std::integral T>
-
136 bool operator==(T) const noexcept;
-
137
-
138 // Bitwise operators
-
139 bi_t operator~() const;
-
140 bi_t operator&(const bi_t&) const;
-
141 bi_t operator|(const bi_t&) const;
-
142 bi_t operator^(const bi_t&) const;
-
143 bi_t& operator&=(const bi_t&);
-
144 bi_t& operator|=(const bi_t&);
-
145 bi_t& operator^=(const bi_t&);
-
146
-
147 // Conversion operators
-
148 explicit operator bool() const noexcept;
+
103 // Comparisons
+
104 std::strong_ordering operator<=>(const bi_t&) const noexcept;
+
105 bool operator==(const bi_t&) const noexcept;
+
106 template <std::integral T>
+
107 std::strong_ordering operator<=>(T) const noexcept;
+
108 template <std::integral T>
+
109 bool operator==(T) const noexcept;
+
110
+
111 // Bitwise operators
+
112 bi_t operator~() const;
+
113 bi_t operator&(const bi_t&) const;
+
114 bi_t operator|(const bi_t&) const;
+
115 bi_t operator^(const bi_t&) const;
+
116 bi_t& operator&=(const bi_t&);
+
117 bi_t& operator|=(const bi_t&);
+
118 bi_t& operator^=(const bi_t&);
+
119
+
120 // Conversion operators
+
121 explicit operator bool() const noexcept;
+
122
+
123 // Bits
+
124 bi_bitcount_t bit_length() const noexcept;
+
125 bool test_bit(bi_bitcount_t) const noexcept;
+
126 bi_t& set_bit(bi_bitcount_t);
+
127
+
128 // Accessors for internal representation
+
129 size_t capacity() const noexcept;
+
130 size_t size() const noexcept;
+
131 bool negative() const noexcept;
+
132 std::span<const digit> digits() const;
+
133 void print_internal(std::ostream& os = std::cout) const noexcept;
+
134
+
135 // Other
+
136 void swap(bi_t&) noexcept;
+
137 std::string to_string() const;
+
138 void negate() noexcept;
+
139 int sign() const noexcept;
+
140 bool odd() const noexcept;
+
141 bool even() const noexcept;
+
142
+
143 // Friends
+
144 BI_API friend std::ostream& operator<<(std::ostream& os, const bi_t& x);
+
145
+
146 private:
+
147 dvector vec_;
+
148 bool negative_;
149
-
150 // Bits
-
151 bi_bitcount_t bit_length() const noexcept;
-
152 bool test_bit(bi_bitcount_t) const noexcept;
-
153 bi_t& set_bit(bi_bitcount_t);
-
154
-
155 // Accessors for internal representation
-
156 size_t capacity() const noexcept;
-
157 size_t size() const noexcept;
-
158 bool negative() const noexcept;
-
159 std::span<const digit> digits() const;
-
160 void print_internal(std::ostream& os = std::cout) const noexcept;
-
161
-
162 // Other
-
163 void swap(bi_t&) noexcept;
-
164 std::string to_string() const;
-
165 void negate() noexcept;
-
166 int sign() const noexcept;
-
167 bool odd() const noexcept;
-
168 bool even() const noexcept;
-
169
-
170 // Friends
-
171 BI_API friend std::ostream& operator<<(std::ostream& os, const bi_t& x);
+
150 void reserve_(size_t new_capacity);
+
151 void resize_(size_t new_size);
+
152 digit& operator[](size_t index);
+
153 const digit& operator[](size_t index) const;
+
154 void resize_unsafe_(size_t new_size);
+
155 void trim_trailing_zeros() noexcept;
+
156
+
157 auto begin() noexcept { return vec_.begin(); }
+
158 auto begin() const noexcept { return vec_.begin(); }
+
159 auto end() noexcept { return vec_.end(); }
+
160 auto end() const noexcept { return vec_.end(); }
+
161 auto rbegin() noexcept { return vec_.rbegin(); }
+
162 auto rbegin() const noexcept { return vec_.rbegin(); }
+
163 auto rend() noexcept { return vec_.rend(); }
+
164 auto rend() const noexcept { return vec_.rend(); }
+
165
+
167 friend struct h_;
+
169};
+
+
170
+
171BI_API std::ostream& operator<<(std::ostream&, const bi_t&);
172
-
173 private:
-
174 digit_vector vec_;
-
175 bool negative_;
+
173BI_API void swap(bi_t& a, bi_t& b) noexcept;
+
174BI_API bi_t operator"" _bi(const char* str);
+
175BI_API bi_t abs(const bi_t& value);
176
-
177 // vector modifiers
-
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_trailing_zeros() noexcept;
+
181
+
183inline size_t bi_t::capacity() const noexcept { return vec_.capacity(); }
184
-
185 // vector iterators
-
186 auto begin() noexcept { return vec_.begin(); }
-
187 auto begin() const noexcept { return vec_.begin(); }
-
188 auto end() noexcept { return vec_.end(); }
-
189 auto end() const noexcept { return vec_.end(); }
-
190 auto rbegin() noexcept { return vec_.rbegin(); }
-
191 auto rbegin() const noexcept { return vec_.rbegin(); }
-
192 auto rend() noexcept { return vec_.rend(); }
-
193 auto rend() const noexcept { return vec_.rend(); }
-
194
-
195 // comparisons
-
196 static int cmp_abs(const bi_t&, const bi_t&) noexcept;
-
197 static int cmp(const bi_t&, const bi_t&) noexcept;
-
198 template <std::integral T>
-
199 static int cmp(const bi_t&, T) noexcept;
-
200
-
201 // initializing
-
202 template <std::integral T>
-
203 static void init_one_digit(bi_t&, T);
-
204 template <std::integral T>
-
205 static void init_atleast_one_digit(bi_t&, T);
-
206 void init_string(const std::string& str);
-
207
-
208 // arithmetic
-
209 static void sub_abs_gt(bi_t& result, const bi_t& a, const bi_t& b);
-
210 static void add_abs(bi_t& result, const bi_t& a, const bi_t& b);
-
211 static void sub_abs(bi_t& result, const bi_t& a, const bi_t& b);
-
212 static void add(bi_t& result, const bi_t& a, const bi_t& b);
-
213 static void sub(bi_t& result, const bi_t& a, const bi_t& b);
-
214 static void mul(bi_t& result, const bi_t& a, const bi_t& b);
-
215 void imul1add1(digit v, digit k);
-
216 static void left_shift(bi_t& result, const bi_t& a, bi_bitcount_t shift);
-
217 static void right_shift(bi_t& result, const bi_t& a, bi_bitcount_t shift);
-
218 static void div_algo_binary(bi_t& q, bi_t& r, const bi_t& n, const bi_t& d);
-
219 static void div_algo_single(bi_t& q, bi_t& r, const bi_t& n,
-
220 const bi_t& d) noexcept;
-
221 static void div_algo_knuth(bi_t& q, bi_t& r, const bi_t& n, const bi_t& d);
-
222 static void divide(bi_t& q, bi_t& r, const bi_t& n, const bi_t& d);
-
223
-
224 enum class BitwiseOperation { AND, OR, XOR };
-
225 template <BitwiseOperation Op>
-
226 static void bitwise_operation_impl(bi_t& res, const bi_t& a, const bi_t& b);
-
227 template <BitwiseOperation Op>
-
228 static bi_t bitwise_operation(const bi_t& a, const bi_t& b);
-
229 template <BitwiseOperation Op>
-
230 bi_t& ibitwise_operation(const bi_t& other);
-
231
-
232 // increment/decrement helpers
-
233 void increment_abs();
-
234 void decrement_abs();
-
235
-
236 // to_string() helpers
-
237 uint8_t idiv10() noexcept;
-
238 size_t decimal_length() const;
-
239
-
240 // misc.
-
241 template <DigitIterator InputIterator>
-
242 bi_t(InputIterator first, InputIterator last, bool negative = false);
-
243};
-
-
244
-
245BI_API std::ostream& operator<<(std::ostream&, const bi_t&);
-
246
-
247BI_API void swap(bi_t& a, bi_t& b) noexcept;
-
248BI_API bi_t operator"" _bi(const char* str);
-
249BI_API bi_t abs(const bi_t& value);
-
250
-
255
-
257inline size_t bi_t::capacity() const noexcept { return vec_.capacity(); }
-
258
-
260inline size_t bi_t::size() const noexcept { return vec_.size(); }
-
261
-
-
270inline std::span<const digit> bi_t::digits() const {
-
271 if (vec_.size() == 0) {
-
272 return std::span<const digit>();
-
273 }
-
274 return std::span<const digit>(vec_.data(), vec_.size());
-
275}
+
186inline size_t bi_t::size() const noexcept { return vec_.size(); }
+
187
+
189inline bool bi_t::negative() const noexcept { return negative_; }
+
190
+
+
199inline std::span<const digit> bi_t::digits() const {
+
200 if (vec_.size() == 0) {
+
201 return std::span<const digit>();
+
202 }
+
203 return std::span<const digit>(vec_.data(), vec_.size());
+
204}
-
276
-
278inline bool bi_t::negative() const noexcept { return negative_; }
-
279
-
281
-
286
-
287inline void bi_t::reserve_(size_t new_capacity) { vec_.reserve(new_capacity); }
-
288
-
289inline void bi_t::resize_(size_t new_size) { vec_.resize(new_size); }
-
290
-
291inline digit& bi_t::operator[](size_t index) { return vec_[index]; }
-
292
-
293inline const digit& bi_t::operator[](size_t index) const { return vec_[index]; }
-
294
-
295inline void bi_t::resize_unsafe_(size_t new_size) {
-
296 assert(new_size <= vec_.capacity());
-
297 vec_.resize_unsafe(new_size);
-
298}
-
299
-
300inline void bi_t::trim_trailing_zeros() noexcept {
-
301 size_t new_size = vec_.size();
-
302 while (new_size > 0 && vec_[new_size - 1] == 0) {
-
303 --new_size;
-
304 }
-
305 vec_.resize(new_size);
-
306 if (new_size == 0) {
-
307 negative_ = false;
-
308 }
-
309}
-
310
-
312
-
313template <std::integral T>
-
314void bi_t::init_one_digit(bi_t& x, T value) {
-
315 x.resize_(1);
-
316
-
317 if (value >= 0) {
-
318 x[0] = static_cast<digit>(value);
-
319 x.negative_ = false;
-
320 } else {
-
321 x[0] = static_cast<digit>(0) - static_cast<digit>(value);
-
322 x.negative_ = true;
-
323 }
-
324}
-
325
-
326template <std::integral T>
-
327void bi_t::init_atleast_one_digit(bi_t& x, T value) {
-
328 using UnsignedT = typename std::make_unsigned<T>::type;
-
329
-
330 size_t size = 1;
-
331 UnsignedT temp, uvalue;
-
332
-
333 if (value >= 0) {
-
334 uvalue = value;
-
335 x.negative_ = false;
-
336 } else {
-
337 uvalue = static_cast<UnsignedT>(0) - static_cast<UnsignedT>(value);
-
338 x.negative_ = true;
-
339 }
-
340
-
341 temp = uvalue;
-
342
-
343 while (temp >>= bi_dwidth) {
-
344 ++size;
-
345 }
-
346
-
347 x.resize_(size);
-
348
-
349 for (size_t i = 0; uvalue != 0; ++i) {
-
350 x[i] = static_cast<digit>(uvalue);
-
351 uvalue >>= bi_dwidth;
-
352 }
-
353}
-
354
-
358template <std::integral T>
-
-
359bi_t::bi_t(T value) {
-
360 using UnsignedT = typename std::make_unsigned<T>::type;
-
361
-
362 if (value == 0) {
-
363 vec_ = digit_vector();
-
364 negative_ = false;
-
365 return;
-
366 }
-
367
-
368 if constexpr (std::numeric_limits<T>::max() <= bi_dmax) {
-
369 bi_t::init_one_digit(*this, value);
-
370 } else {
-
371 bi_t::init_atleast_one_digit(*this, value);
-
372 }
-
373}
-
-
374
-
380template <DigitIterator InputIterator>
-
381bi_t::bi_t(InputIterator first, InputIterator last, bool negative)
-
382 : vec_(first, last), negative_(negative) {
-
383 trim_trailing_zeros();
-
384}
-
385
-
390
-
394template <std::integral T>
-
- -
396 using UnsignedT = typename std::make_unsigned<T>::type;
-
397
-
398 UnsignedT uvalue;
-
399 if (value == 0) {
-
400 resize_(0);
-
401 negative_ = false;
-
402 return *this;
-
403 } else if (value < 0) {
-
404 uvalue = static_cast<UnsignedT>(0) - static_cast<UnsignedT>(value);
-
405 negative_ = true;
-
406 } else {
-
407 uvalue = value;
-
408 negative_ = false;
-
409 }
-
410
-
411 if constexpr (std::numeric_limits<T>::max() <= bi_dmax) {
-
412 resize_(1);
-
413 vec_[0] = static_cast<digit>(uvalue);
-
414 } else {
-
415 UnsignedT temp = uvalue;
-
416
-
417 size_t n_digits = 1;
-
418 while (temp >>= bi_dwidth) {
-
419 ++n_digits;
-
420 }
-
421
-
422 resize_(n_digits);
-
423 for (size_t i = 0; uvalue != 0; ++i) {
-
424 vec_[i] = static_cast<digit>(uvalue);
-
425 uvalue >>= bi_dwidth;
-
426 }
-
427 }
-
428
-
429 return *this;
-
430}
-
-
431
-
433
-
434template <std::integral T>
-
435int bi_t::cmp(const bi_t& a, T b) noexcept {
-
436 if (b == 0) {
-
437 if (a.size() == 0) {
-
438 return 0; // a
-
439 }
-
440 return a.negative() ? -1 : 1; // b
-
441 }
-
442
-
443 using UnsignedT = typename std::make_unsigned<T>::type;
-
444 const bool b_negative = b < 0;
-
445 const UnsignedT unsigned_b =
-
446 b_negative ? -static_cast<UnsignedT>(b) : static_cast<UnsignedT>(b);
-
447
-
448 if (a.negative() && !b_negative) {
-
449 return -1; // c
-
450 }
-
451 if (!a.negative() && b_negative) {
-
452 return 1; // d
-
453 }
-
454
-
455 size_t n_b_digits = 0;
-
456 if constexpr (std::numeric_limits<UnsignedT>::max() <= bi_dmax) {
-
457 n_b_digits = (unsigned_b != 0) ? 1 : 0;
-
458 } else {
-
459 UnsignedT temp_b = unsigned_b;
-
460 while (temp_b != 0) {
-
461 temp_b >>= bi_dwidth;
-
462 n_b_digits++;
-
463 }
-
464 }
-
465
-
466 const size_t a_size = a.size();
-
467 if (a_size < n_b_digits) {
-
468 return a.negative() ? 1 : -1; // e
-
469 }
-
470
-
471 if (a_size > n_b_digits) {
-
472 return a.negative() ? -1 : 1; // f
-
473 }
-
474
-
475 for (size_t i = n_b_digits; i-- > 0;) {
-
476 const digit a_digit = a[i];
-
477 const digit b_digit = static_cast<digit>(unsigned_b >> (bi_dwidth * i));
-
478
-
479 if (a_digit < b_digit) {
-
480 return a.negative() ? 1 : -1; // g
-
481 }
-
482 if (a_digit > b_digit) {
-
483 return a.negative() ? -1 : 1; // h
-
484 }
-
485 }
-
486 return 0; // i
-
487}
-
488
-
496
-
497template <std::integral T>
-
498std::strong_ordering bi_t::operator<=>(T rhs) const noexcept {
-
499 return bi_t::cmp(*this, rhs) <=> 0;
-
500}
-
501
-
502template <std::integral T>
-
503bool bi_t::operator==(T rhs) const noexcept {
-
504 return bi_t::cmp(*this, rhs) == 0;
-
505}
-
506
-
508
-
513
-
-
518inline void bi_t::swap(bi_t& other) noexcept {
-
519 using std::swap;
-
520 swap(this->vec_, other.vec_);
-
521 swap(this->negative_, other.negative_);
-
522}
+
205
+
207
+
212
+
213inline void bi_t::reserve_(size_t new_capacity) { vec_.reserve(new_capacity); }
+
214
+
215inline void bi_t::resize_(size_t new_size) { vec_.resize(new_size); }
+
216
+
217inline digit& bi_t::operator[](size_t index) { return vec_[index]; }
+
218
+
219inline const digit& bi_t::operator[](size_t index) const { return vec_[index]; }
+
220
+
221inline void bi_t::resize_unsafe_(size_t new_size) {
+
222 assert(new_size <= vec_.capacity());
+
223 vec_.resize_unsafe(new_size);
+
224}
+
225
+
226inline void bi_t::trim_trailing_zeros() noexcept {
+
227 size_t new_size = vec_.size();
+
228 while (new_size > 0 && vec_[new_size - 1] == 0) {
+
229 --new_size;
+
230 }
+
231 vec_.resize(new_size);
+
232 if (new_size == 0) {
+
233 negative_ = false;
+
234 }
+
235}
+
236
+
238
+
243
+
+
248inline void bi_t::swap(bi_t& other) noexcept {
+
249 using std::swap;
+
250 swap(this->vec_, other.vec_);
+
251 swap(this->negative_, other.negative_);
+
252}
-
523
-
-
529inline int bi_t::sign() const noexcept {
-
530 if (size() == 0) {
-
531 return 0;
-
532 }
-
533 return negative_ ? -1 : 1;
-
534}
+
253
+
+
258inline void bi_t::negate() noexcept {
+
259 if (size() != 0) {
+
260 negative_ = !negative_;
+
261 }
+
262}
-
535
-
-
540inline void bi_t::negate() noexcept {
-
541 if (size() != 0) {
-
542 negative_ = !negative_;
-
543 }
-
544}
+
263
+
+
269inline int bi_t::sign() const noexcept {
+
270 if (size() == 0) {
+
271 return 0;
+
272 }
+
273 return negative_ ? -1 : 1;
+
274}
-
545
-
-
550inline bool bi_t::odd() const noexcept {
-
551 return size() == 0 ? false : (*this)[0] & 1;
-
552}
+
275
+
+
280inline bool bi_t::odd() const noexcept {
+
281 return size() == 0 ? false : (*this)[0] & 1;
+
282}
-
553
-
558inline bool bi_t::even() const noexcept { return !odd(); }
-
559
-
561
-
563inline digit_vector to_twos_complement(const digit_vector& vec) {
-
564 const size_t vec_size = vec.size();
-
565 digit_vector result;
-
566 result.resize(vec_size);
-
567
-
568 bool carry = true;
-
569 for (size_t i = 0; i < vec_size; ++i) {
-
570 const digit sum = ~vec[i] + carry;
-
571 carry = sum < static_cast<uint8_t>(carry);
-
572 result[i] = sum;
-
573 }
-
574
-
575 return result;
-
576}
-
577
-
579inline void to_twos_complement_in_place(digit_vector& vec) noexcept {
-
580 const size_t vec_size = vec.size();
-
581
-
582 bool carry = true;
-
583 for (size_t i = 0; i < vec_size; ++i) {
-
584 const digit sum = ~vec[i] + carry;
-
585 carry = sum < static_cast<uint8_t>(carry);
-
586 vec[i] = sum;
-
587 }
-
588}
-
589
-
591template <bi_t::BitwiseOperation Op>
-
592void bi_t::bitwise_operation_impl(bi_t& result, const bi_t& x, const bi_t& y) {
-
593 size_t max_size = std::max(x.size(), y.size());
-
594
-
595 const digit_vector& lhs_digits =
-
596 x.negative_ ? to_twos_complement(x.vec_) : x.vec_;
-
597 const digit_vector& rhs_digits =
-
598 y.negative_ ? to_twos_complement(y.vec_) : y.vec_;
-
599
-
600 bool result_negative; // NOLINT(cppcoreguidelines-init-variables)
-
601 if constexpr (Op == BitwiseOperation::AND) {
-
602 result_negative = x.negative_ && y.negative_;
-
603 } else if constexpr (Op == BitwiseOperation::OR) {
-
604 result_negative = x.negative_ || y.negative_;
-
605 } else if constexpr (Op == BitwiseOperation::XOR) {
-
606 result_negative = x.negative_ != y.negative_;
-
607 ++max_size;
-
608 }
-
609
-
610 result.resize_(max_size);
-
611
-
612 for (size_t i = 0; i < result.size(); ++i) {
-
613 const digit lhs_digit =
-
614 i < lhs_digits.size() ? lhs_digits[i] : (x.negative_ ? bi_dmax : 0);
-
615 const digit rhs_digit =
-
616 i < rhs_digits.size() ? rhs_digits[i] : (y.negative_ ? bi_dmax : 0);
-
617
-
618 if constexpr (Op == BitwiseOperation::AND) {
-
619 result[i] = lhs_digit & rhs_digit;
-
620 } else if constexpr (Op == BitwiseOperation::OR) {
-
621 result[i] = lhs_digit | rhs_digit;
-
622 } else if constexpr (Op == BitwiseOperation::XOR) {
-
623 result[i] = lhs_digit ^ rhs_digit;
-
624 }
-
625 }
-
626
-
627 result.negative_ = result_negative;
-
628
-
629 if (result.negative_) {
-
630 to_twos_complement_in_place(result.vec_);
-
631 }
-
632
-
633 result.trim_trailing_zeros();
-
634}
-
635
-
637template <bi_t::BitwiseOperation Op>
-
638bi_t bi_t::bitwise_operation(const bi_t& a, const bi_t& b) {
-
639 bi_t result;
-
640 bitwise_operation_impl<Op>(result, a, b);
-
641 return result;
-
642}
-
643
-
645template <bi_t::BitwiseOperation Op>
-
646bi_t& bi_t::ibitwise_operation(const bi_t& other) {
-
647 bitwise_operation_impl<Op>(*this, *this, other);
-
648 return *this;
-
649}
-
650
-
651} // namespace bi
-
652
-
653#endif // BI_INCLUDE_BI_HPP_
-
Arbitrary-precision integer type and related functions.
Definition bi.hpp:80
-
bi_t() noexcept
Default constructor. The integer is initialized to zero and no memory allocation occurs.
Definition bi.cpp:31
-
int sign() const noexcept
Return an int indicating the sign of the number: -1 for negative, 0 for zero, 1 for positive.
Definition bi.hpp:529
-
size_t capacity() const noexcept
Return the number of digits the allocated storage can hold.
Definition bi.hpp:257
-
size_t size() const noexcept
Return the number of digits used. Instance represents 0 iff size() == 0.
Definition bi.hpp:260
-
void negate() noexcept
Negates the integer in place.
Definition bi.hpp:540
-
void swap(bi_t &) noexcept
Swap the contents of this bi_t object with another bi_t object.
Definition bi.hpp:518
-
bool odd() const noexcept
Return true if this integer is odd, false otherwise.
Definition bi.hpp:550
-
std::span< const digit > digits() const
Return a read-only span of the digits stored in the internal digit vector, with least significant dig...
Definition bi.hpp:270
-
bi_t & operator=(const bi_t &)
Copy assignment operator.
Definition bi.cpp:92
-
bool negative() const noexcept
Reture true if the integer is (strictly) negative, false otherwise.
Definition bi.hpp:278
-
bool even() const noexcept
Return true if this integer is even, false otherwise.
Definition bi.hpp:558
+
283
+
288inline bool bi_t::even() const noexcept { return !odd(); }
+
289
+
291
+
292} // namespace bi
+
293
+
294#endif // BI_INCLUDE_BI_HPP_
+
Arbitrary-precision integer type and related functions.
Definition bi.hpp:53
+
int sign() const noexcept
Return an int indicating the sign of the number: -1 for negative, 0 for zero, 1 for positive.
Definition bi.hpp:269
+
size_t capacity() const noexcept
Return the number of digits the allocated storage can hold.
Definition bi.hpp:183
+
size_t size() const noexcept
Return the number of digits used. Instance represents 0 iff size() == 0.
Definition bi.hpp:186
+
void negate() noexcept
Negates the integer in place.
Definition bi.hpp:258
+
void swap(bi_t &) noexcept
Swap the contents of this bi_t object with another bi_t object.
Definition bi.hpp:248
+
bool odd() const noexcept
Return true if this integer is odd, false otherwise.
Definition bi.hpp:280
+
std::span< const digit > digits() const
Return a read-only span of the digits stored in the internal digit vector, with least significant dig...
Definition bi.hpp:199
+
bool negative() const noexcept
Reture true if the integer is (strictly) negative, false otherwise.
Definition bi.hpp:189
+
bool even() const noexcept
Return true if this integer is even, false otherwise.
Definition bi.hpp:288