bi
An arbitrary precision integer library for C++.
|
Arbitrary-precision integer type and related functions. More...
#include "bi.hpp"
Public Member Functions | |||
bi_t () noexcept | |||
Default constructor. The integer is initialized to zero and no memory allocation occurs. | |||
template<std::integral T> | |||
bi_t (T) | |||
Constructor for integral types. | |||
bi_t (const bi_t &) | |||
Copy constructor. | |||
bi_t (bi_t &&other) noexcept | |||
Move constructor. After the move, other is left in a valid state representing the integer 0. | |||
Construct from a string | |||
Construct an integer from a string representing a base-
Allows leading whitespace and/or a plus/minus sign before the first base- Examples: bi_t() noexcept Default constructor. The integer is initialized to zero and no memory allocation occurs. Definition bi.cpp:81 | |||
bi_t (const std::string &, int base=10) | |||
bi_t (const char *, int base=10) | |||
bi_t (double) | |||
Assignment operators | |||
bi_t & | operator= (const bi_t &) | ||
Copy assignment operator. | |||
bi_t & | operator= (bi_t &&other) noexcept | ||
Move assignment operator. After the move, other is left in a valid state representing the integer 0. | |||
template<std::integral T> | |||
bi_t & | operator= (T) | ||
Assign a builtin integral type value to a bi_t . | |||
bi_t & | operator= (const std::string &) | ||
bi_t & | operator= (const char *) | ||
bi_t & | operator= (double) | ||
Unary operators | |||
bi_t | operator+ () const | ||
bi_t | operator- () const | ||
Increment and decrement | |||
bi_t & | operator++ () | ||
bi_t | operator++ (int) | ||
bi_t & | operator-- () | ||
bi_t | operator-- (int) | ||
Multiplicative operators | |||
| |||
bi_t | operator* (const bi_t &) const | ||
bi_t | operator/ (const bi_t &) const | ||
bi_t | operator% (const bi_t &) const | ||
bi_t & | operator*= (const bi_t &) | ||
bi_t & | operator/= (const bi_t &) | ||
bi_t & | operator%= (const bi_t &) | ||
std::pair< bi_t, bi_t > | div (const bi_t &) const | ||
Computes both the quotient and remainder of division of this bi_t object by another bi_t object and returns both the quotient and the remainder as a pair. | |||
Additive operators | |||
bi_t | operator+ (const bi_t &) const | ||
bi_t | operator- (const bi_t &) const | ||
bi_t & | operator+= (const bi_t &) | ||
bi_t & | operator-= (const bi_t &) | ||
Shift operators | |||
| |||
bi_t | operator<< (bi_bitcount_t shift) const | ||
Return a new integer representing the integer left-shifted shift bit positions with vacated bits zero-filled. | |||
bi_t | operator>> (bi_bitcount_t shift) const | ||
Return a new integer representing the integer right-shifted shift bit positions. This is an arithmetic right shift with sign extension. | |||
bi_t & | operator<<= (bi_bitcount_t shift) | ||
bi_t & | operator>>= (bi_bitcount_t shift) | ||
Comparisons | |||
std::strong_ordering | operator<=> (const bi_t &) const noexcept | ||
bool | operator== (const bi_t &) const noexcept | ||
Comparisons with integral types | |||
template<std::integral T> | |||
std::strong_ordering | operator<=> (T) const noexcept | ||
template<std::integral T> | |||
bool | operator== (T) const noexcept | ||
Comparisons with floats | |||
Compare a These member functions handle the case where a These comparisons are designed to be consistent with IEEE 754, handling special cases like NaNs and infinities. NaN:
Infinities:
| |||
bool | operator== (double) const noexcept | ||
bool | operator!= (double) const noexcept | ||
bool | operator< (double) const noexcept | ||
bool | operator<= (double) const noexcept | ||
bool | operator> (double) const noexcept | ||
bool | operator>= (double) const noexcept | ||
Bitwise operators | |||
| |||
bi_t | operator~ () const | ||
Unary complement operator. Return a new integer representing the ones' complement of this integer. | |||
bi_t | operator& (const bi_t &) const | ||
bi_t | operator| (const bi_t &) const | ||
bi_t | operator^ (const bi_t &) const | ||
bi_t & | operator&= (const bi_t &) | ||
bi_t & | operator|= (const bi_t &) | ||
bi_t & | operator^= (const bi_t &) | ||
Conversion operators | |||
operator bool () const noexcept | |||
true if and only if this integer is nonzero. | |||
template<std::integral T> | |||
operator T () const noexcept | |||
Converts a bi_t object to an integral type T. | |||
operator double () const noexcept | |||
Bits | |||
bi_bitcount_t | bit_length () const noexcept | ||
If nonzero, return the number of bits required to represent its absolute value. Otherwise (i.e. the integer is zero), return 0 . | |||
bool | test_bit (bi_bitcount_t) const noexcept | ||
Test bit i , acting as if the integer is nonnegative. | |||
bi_t & | set_bit (bi_bitcount_t) | ||
Set bit i , acting as if the integer is nonnegative, but preserving its original sign in the result. | |||
Accessors for internal representation | |||
size_t | capacity () const noexcept | ||
Return the number of digits the allocated storage can hold. | |||
size_t | size () const noexcept | ||
Return the number of digits used. Instance represents 0 iff size() == 0 . | |||
bool | negative () const noexcept | ||
Return true if the integer is (strictly) negative, false otherwise. | |||
std::span< const digit > | digits () const | ||
Return a read-only span of the digits stored in the internal digit vector, with least significant digits first. If the integer is zero, an empty span is returned. | |||
void | print_internal (std::ostream &os=std::cout) const noexcept | ||
Other | |||
void | swap (bi_t &) noexcept | ||
Swap the contents of this bi_t object with another bi_t object. | |||
std::string | to_string (int base=10) const | ||
Return a string containing the base-base representation of the integer, where base must be an integer in \( [2, 36] \) (by default, base is 10 ). | |||
void | negate () noexcept | ||
Negates the integer in place. | |||
int | sign () const noexcept | ||
Return an int indicating the sign of the number: -1 for negative, 0 for zero, 1 for positive. | |||
bool | odd () const noexcept | ||
Return true if this integer is odd, false otherwise. | |||
bool | even () const noexcept | ||
Return true if this integer is even, false otherwise. | |||
template<std::integral T> | |||
bool | within () const noexcept | ||
Return true if this integer fits in an integral type T, false otherwise. | |||
Static Public Member Functions | |
Exponentiation | |
static bi_t | pow (const bi_t &base, bi_bitcount_t exp) |
static bi_t | pow (const bi_t &base, const bi_t &exp) |
Friends | |
std::ostream & | operator<< (std::ostream &os, const bi_t &x) |
Outputs the base-10 (decimal) representation of a bi_t object to a standard output stream. | |
bool | operator== (double lhs, const bi_t &rhs) noexcept |
bool | operator!= (double lhs, const bi_t &rhs) noexcept |
bool | operator< (double lhs, const bi_t &rhs) noexcept |
bool | operator<= (double lhs, const bi_t &rhs) noexcept |
bool | operator> (double lhs, const bi_t &rhs) noexcept |
bool | operator>= (double lhs, const bi_t &rhs) noexcept |
Related Symbols | |
(Note that these are not member symbols.) | |
void | swap (bi_t &a, bi_t &b) noexcept |
Swap the contents of a with b . | |
bi_t | operator""_bi (const char *s) |
User-defined literal (UDL) operator for creating bi_t objects. | |
bi_t | abs (const bi_t &value) |
Return a new integer representing the absolute value of the argument integer. | |
Arbitrary-precision integer type and related functions.
An instance of bi_t
represents an arbitrary precision integer.
The implementation has several design goals, including, but not limited to:
std::bad_alloc | Throws in case of memory allocation failure. |
bi::overflow_error | Throws if an operation expects the result to require a digit vector with size() exceeding max_size() . See internals below. |
bi::division_by_zero | Throws if a division by zero attempt is detected. |
bi::from_float | Throws when attempting to convert a NaN or infinity to a bi_t . |
std::invalid_argument | Throws in a string constructor if an invalid string or argument is provided. |
The custom exception classes derive from std::runtime_error
. To catch and handle these specific exceptions, #include
the "bi_exceptions.hpp"
header (in addition to "bi.hpp"
).
The representation of a bi_t
consists of a digit vector and a boolean indicating if the integer is negative. The integer is represented internally as a base \( 2^{n} \) integer where \( n \) is typically 32 bits. An element of the digit vector, i.e. a digit, is typically a uint32_t
. The digit vector stores the magnitude of the integer, with least significant digits first. Counts of bits are represented by the bi_bitcount_t
type, which is an unsigned long
. Counts of bytes for dynamically allocated memory expects a size_t
type. Thus, the digit vector is theoretically constrained to be less than or equal to SIZE_MAX / sizeof(digit)
. Additionally, because counts of bits use the unsigned long
type, we also constrain the maximum size of the vector to be less than or equal to ULONG_MAX / (CHAR_BIT * sizeof(digit))
, where the denominator is the number of bits in the digit data type (typically 32). Together, these constraints determine max_size()
for the internal digit vector. An operation that expects a result to exceed max_size()
throws bi::overflow_error
.
|
noexcept |
Default constructor. The integer is initialized to zero and no memory allocation occurs.
|
noexcept |
Return the number of digits the allocated storage can hold.
std::span< const digit > bi::bi_t::digits | ( | ) | const |
Return a read-only span of the digits stored in the internal digit vector, with least significant digits first. If the integer is zero, an empty span is returned.
Computes both the quotient and remainder of division of this bi_t
object by another bi_t
object and returns both the quotient and the remainder as a pair.
other | The divisor. |
bi_t
objects where the first
element is the quotient and the second
element is the remainder. size()
of the dividend and \( n \) is the size()
of the divisor.
|
noexcept |
Return true
if this integer is even, false
otherwise.
|
noexcept |
Negates the integer in place.
|
noexcept |
Return true
if the integer is (strictly) negative, false otherwise.
|
noexcept |
Return true
if this integer is odd, false
otherwise.
|
explicitnoexcept |
true
if and only if this integer is nonzero.
Example:
The output is
|
explicitnoexcept |
Converts a bi_t
object to an integral type T.
As with the C++20 Standard (7.3.8, p. 93):
[T]he result is the unique value of the destination type that is congruent to the source integer modulo \( 2^{N} \), where \( N \) is the width of the destination type.
|
noexcept |
Mathematically, given two integers \( x, y \) with coefficients \( x_{i}, y_{i} \) of their binary representation, the result of \( x \; \& \; y \) (bitwise AND) is an integer \( r \) with base-2 coefficients \( r_{i} \) such that
\[ r_{i} = 1 \Longleftrightarrow x_{i} = 1 \wedge y_{i} = 1 \]
|
noexcept |
bi_t bi::bi_t::operator<< | ( | bi_bitcount_t | shift | ) | const |
Return a new integer representing the integer left-shifted shift
bit positions with vacated bits zero-filled.
Mathematically, the value of the resulting integer is
\[ x \times 2^{\text{shift}} \]
where \( x \) is the big integer.
|
noexcept |
|
noexcept |
|
noexcept |
|
noexcept |
bi_t bi::bi_t::operator>> | ( | bi_bitcount_t | shift | ) | const |
Return a new integer representing the integer right-shifted shift
bit positions. This is an arithmetic right shift with sign extension.
Mathematically, the value of the resulting integer is \( \frac{x}{2^{\text{shift}}} \), rounded down:
\[ \left\lfloor \frac{x}{2^{\text{shift}}} \right\rfloor \]
where \( x \) is the big integer.
Mathematically, given two integers \( x, y \) with coefficients \( x_{i}, y_{i} \) of their binary representation, the result of \( x \; ^\wedge \; y \) (bitwise exclusive OR) is an integer \( r \) with base-2 coefficients \( r_{i} \) such that
\[ r_{i} = 1 \Longleftrightarrow (x_{i} = 1 \wedge y_{i} = 0) \lor (x_{i} = 0 \wedge y_{i} = 1) \]
Mathematically, given two integers \( x, y \) with coefficients \( x_{i}, y_{i} \) of their binary representation, the result of \( x \; | \; y \) (bitwise inclusive OR) is an integer \( r \) with base-2 coefficients \( r_{i} \) such that
\[ r_{i} = 1 \Longleftrightarrow x_{i} = 1 \lor y_{i} = 1 \]
|
noexcept |
Prints the integer in the form
followed by a newline. Outputs to the specified std::ostream
or to standard output (std::cout
) by default. If the integer is negative, the output will be preceded by a minus sign (-
). bi_dbits
is typically 32.
Useful for understanding the internal representation of the integer.
os | The output stream to which the internal representation is printed. If not specified, defaults to standard output (std::cout ). |
|
noexcept |
Return an int
indicating the sign of the number: -1
for negative, 0
for zero, 1
for positive.
|
noexcept |
Return the number of digits used. Instance represents 0
iff size() == 0
.
|
noexcept |
Swap the contents of this bi_t
object with another bi_t
object.
std::string bi::bi_t::to_string | ( | int | base = 10 | ) | const |
Return a string
containing the base-base
representation of the integer, where base
must be an integer in \( [2, 36] \) (by default, base
is 10
).
Examples:
|
noexcept |
Return true
if this integer fits in an integral type T, false
otherwise.
For bi_t
object x
and integral type T
, x.within<T>()
evaluates to
Example:
|
related |
|
friend |
Outputs the base-10 (decimal) representation of a bi_t
object to a standard output stream.
This overload of the stream insertion operator allows instances of bi_t
to be sent to standard output streams like std::cout
. The bi_t
object is converted to a string via to_string()
before being output.
os | The output stream to which the data is sent. |
x | The bi_t object to be output. |
<<
operators. Swap the contents of a
with b
.