14 unstable releases (3 breaking)
new 0.4.1 | Dec 17, 2024 |
---|---|
0.4.0 | Dec 13, 2024 |
0.3.0 | Dec 7, 2024 |
0.2.6 | Dec 5, 2024 |
0.1.2 | Nov 30, 2024 |
#123 in Algorithms
1,358 downloads per month
415KB
9K
SLoC
arbi
arbi
implements an Arbitrary Precision Integer type: Arbi
.
Features
-
No dependencies.
Empty dependencies section in
Cargo.toml
. -
no_std
.This crate is
no_std
and utilizes thealloc
crate for dynamic memory allocation. -
forbid(unsafe_code)
.Statically guarantees that crate code does not use
unsafe
Rust. -
Pure Rust implementation.
Usage
Construct an Arbi
integer
The following are equivalent and return an Arbi
integer with value 0
(no memory allocation occurs):
Arbi::default()
also returns zero, but it is not const
.
use arbi::Arbi;
let a = Arbi::new();
let b = Arbi::default();
let c = Arbi::zero();
assert_eq!(a, 0);
assert_eq!(a, b);
assert_eq!(b, c);
Construct an Arbi
integer from any primitive integer type value,
any f64
(except for infinities and NaNs), or any string containing a
base-base
representation of an integer, where base
must be in [2, 36].
use arbi::{base::DEC, Arbi};
// From any primitive integer type
let a = Arbi::from(u128::MAX);
assert_eq!(a, u128::MAX);
// From any f64 (except for infinities and NaNs)
let b = Arbi::from(f64::MAX);
assert_eq!(b, f64::MAX);
// From a string
let c = Arbi::from_str_radix("123456789", 10).unwrap();
let d = Arbi::from_str_base("123456789", DEC).unwrap();
assert_eq!(c, 123456789);
assert_eq!(c, d);
use core::str::FromStr;
// Currently, FromStr assumes base 10.
let e = Arbi::from_str("-987654321").unwrap();
assert_eq!(e, -987654321);
let f = "123456789".parse::<Arbi>().unwrap();
assert_eq!(f, 123456789);
Use Arbi::with_capacity_bits()
or Arbi::with_capacity()
to construct an
integer representing zero with at least a specified capacity:
use arbi::{Arbi, Assign};
let mut a = Arbi::with_capacity_bits(128);
let initial_capacity = a.capacity_bits();
assert_eq!(a, 0);
assert!(initial_capacity >= 128);
a.assign(u128::MAX);
assert_eq!(a.capacity_bits(), initial_capacity); // no memory allocation needed
assert_eq!(a, u128::MAX);
Assign to an Arbi
integer
Assign
to an Arbi
any primitive integer type value, a floating-point
value, a string, or another Arbi
integer.
The main benefit of assigning is that if there is already enough capacity,
memory allocation need not occur. In contrast, from
methods typically involve
memory allocation.
use arbi::{Arbi, Assign};
let mut a = Arbi::with_capacity(10);
let mut capacity = a.capacity();
// From integer
a.assign(u128::MAX);
assert_eq!(a, u128::MAX);
assert_eq!(a.capacity(), capacity); // no memory allocation occurred
// From float
a.assign(f64::MAX);
assert_eq!(a, f64::MAX);
assert!(a.capacity() > capacity); // memory allocation occured because we needed
// more capacity to represent the value
capacity = a.capacity();
// From string (no need for the Assign trait)
if let Err(e) = a.assign_str_radix("123456789", 10) {
panic!("Parsing error: {}", e);
}
assert_eq!(a, 123456789);
assert_eq!(a.capacity(), capacity); // no memory allocation occurred
// From another Arbi integer
let b = Arbi::from(987654321);
a.assign(&b);
assert_eq!(a.capacity(), capacity); // no memory allocation occurred
Comparisons
Compare an Arbi
to another Arbi
, a primitive integer type value, or a
floating-point value.
All equality and comparison operators are supported ==
, !=
, <
, <=
, >
,
>=
.
Comparisons with floating-point values are designed to be consistent with IEEE
754. SeePartialOrd<f64> for Arbi
for a description of the semantics of
comparing an Arbi
to a floating-point value.
use arbi::{Arbi, Assign};
let mut a;
// Float
a = Arbi::one();
a <<= 2000_usize;
assert_ne!(a, f64::MAX);
assert!(a < f64::INFINITY);
assert!(a > f64::MAX);
// Integer
a.assign(u64::MAX);
assert_eq!(a, u64::MAX);
assert!(u128::MAX > a);
assert!(a > u32::MAX);
// Arbi
let b = Arbi::one();
assert!(a > b);
assert!(b < a);
To and From a String
In what follows, base
must be an integer in [2, 36]
. Moreover, the
*_radix()
and *_base()
string-related functions are equivalent, except that
*_radix()
functions panic on an invalid base and *_base()
functions cannot
panic due to an invalid base.
Convert any Arbi
integer to a String
containing the base-base
representation of the integer.
Arbi::to_string_radix()
Arbi::to_string_base()
Arbi::to_string()
(usesArbi::to_string_base()
, assuming base10
).
Convert any string containing the base-base
representation of an integer to
an Arbi
.
Arbi::from_str_radix()
Arbi::from_str_base()
Arbi::from_str()
(same asfrom_str_base()
but assumes base10
and needscore::str::FromStr
in scope).
Assign any string containing the base-base
representation of an integer to
an Arbi
.
use arbi::{base::OCT, Arbi};
use core::str::FromStr; // needed for from_str() alone
let mut a = Arbi::from(u128::MAX);
// To string
assert_eq!(a.to_string(), u128::MAX.to_string()); // assumes base-10
assert_eq!(a.to_string_radix(16), "ffffffffffffffffffffffffffffffff");
assert_eq!(
a.to_string_base(OCT),
"3777777777777777777777777777777777777777777"
);
// From string
assert_eq!(
Arbi::from_str("340282366920938463463374607431768211455").unwrap(),
u128::MAX
); // assumes base-10
assert_eq!(
Arbi::from_str_radix("ffffffffffffffffffffffffffffffff", 16).unwrap(),
u128::MAX
);
assert_eq!(
Arbi::from_str_base("3777777777777777777777777777777777777777777", OCT)
.unwrap(),
u128::MAX
);
// Assign string
a.assign_str_radix("573c0ff2cce44d2025e04db43", 16);
assert_eq!(a, 0x573c0ff2cce44d2025e04db43_u128);
a.assign_str_base("1772555052337322416757226463207030", OCT);
assert_eq!(a, 0o1772555052337322416757226463207030_u128);
Arithmetic
All standard arithmetic operations are implemented:
- Binary operators:
+
,-
,*
,/
,%
,+=
,-=
,*=
,/=
,%=
- Unary operators:
-
.
Bitwise Operations
All standard bitwise operations are implemented. These operators perform bitwise operations on integers using two's complement representation (with sign extension).
- Shift operators:
<<
,>>
,<<=
,>>=
. - Bitwise complement:
!
. - Bitwise AND, OR, and XOR:
&
,|
,^
,&=
,|=
,^=
.
Test or set a bit at a specified index (zero-based) on the absolute value of an
Arbi
integer:
Obtain the number of bits needed to represent the absolute value of an Arbi
integer using Arbi::size_bits()
:
use arbi::Arbi;
let mut a = Arbi::zero();
assert_eq!(a.size_bits(), 0);
a.incr(); // 1
assert_eq!(a.size_bits(), 1);
a.incr(); // 10
assert_eq!(a.size_bits(), 2);
a.incr(); // 11
assert_eq!(a.size_bits(), 2);
To Built-In Integer
In what follows, let *
denote any primitive integer type name:
i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize
.
Methods
-
wrapping_to_*()
: convert thisArbi
integer to a primitive integer type value. This is “wrapping”. -
checked_to_*()
: try to convert thisArbi
integer to a primitive integer type value. If thisArbi
integer does not fit in the target primitive integer type, returnsNone
. -
fits_*()
: test if thisArbi
integer fits in a primitive integer type. TheFits
trait can also be used to do the same thing.See
Arbi::fits_i32()
and also theFits
trait.
To Floating-Point Value
Convert an Arbi
integer to a floating-point value using the Arbi::to_f64()
method:
use arbi::{Arbi, Pow};
let a = Arbi::from(-987654321);
assert_eq!(a.to_f64(), -987654321.0);
let b = Arbi::from(1_u64 << 32);
assert_ne!((&b).pow(31_usize).to_f64(), f64::INFINITY);
assert_eq!((&b).pow(32_usize).to_f64(), f64::INFINITY);
Increment/Decrement
Increment or decrement an Arbi
integer in-place by one using the
Arbi::incr()
and Arbi::decr()
methods (+=
and -=
can also be used).
use arbi::Arbi;
let mut a = Arbi::zero();
a.incr();
assert_eq!(a, 1);
a.decr();
assert_eq!(a, 0);
a.decr();
assert_eq!(a, -1);
Exponentiation
Raise an Arbi
integer to the power of a usize
, u128
, or another
Arbi
integer using the Pow
trait.
use arbi::{Arbi, Pow};
let mut a = Arbi::from(2);
a = a.pow(128_usize);
assert_eq!(
a,
Arbi::from_str_radix("100000000000000000000000000000000", 16).unwrap()
);
Display
The core::fmt::Display
implementation uses the base-10 representation of the
Arbi
integer and by extension, so does Arbi::to_string()
.
use arbi::Arbi;
let a = Arbi::from(12345);
assert_eq!(format!("{}", a), "12345");
assert_eq!(a.to_string(), "12345");
License
This project is dual-licensed under either the Apache License, Version 2.0 or the MIT License, at your option.
Contributing
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you shall be dual-licensed as above, without any additional terms or conditions.