First shot at adding bigints
Some checks failed
timw4mail/rusty-numbers/pipeline/head There was a failure building this commit
Some checks failed
timw4mail/rusty-numbers/pipeline/head There was a failure building this commit
This commit is contained in:
parent
096373789b
commit
d5d9730607
103
src/bigint.rs
103
src/bigint.rs
@ -20,24 +20,96 @@ pub struct BigInt {
|
|||||||
sign: Sign,
|
sign: Sign,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_from_smaller {
|
||||||
|
($($Type: ty),* ) => {
|
||||||
|
$(
|
||||||
|
impl From<$Type> for BigInt {
|
||||||
|
fn from(n: $Type) -> Self {
|
||||||
|
let mut new = Self::default();
|
||||||
|
new.inner[0] = n as usize;
|
||||||
|
|
||||||
|
new
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_pointer_width = "16")]
|
||||||
|
impl_from_smaller!(u8, u16);
|
||||||
|
|
||||||
|
#[cfg(target_pointer_width = "32")]
|
||||||
|
impl_from_smaller!(u8, u16, u32);
|
||||||
|
|
||||||
|
#[cfg(target_pointer_width = "64")]
|
||||||
|
impl_from_smaller!(u8, u16, u32, u64);
|
||||||
|
|
||||||
|
#[cfg(target_pointer_width = "16")]
|
||||||
|
static BITS:usize = 16;
|
||||||
|
|
||||||
|
#[cfg(target_pointer_width = "32")]
|
||||||
|
static BITS:usize = 32;
|
||||||
|
|
||||||
|
#[cfg(target_pointer_width = "64")]
|
||||||
|
static BITS:usize = 64;
|
||||||
|
|
||||||
|
fn add(u: BigInt, v: BigInt) -> BigInt {
|
||||||
|
let mut out = BigInt::default();
|
||||||
|
|
||||||
|
let u_digits = u.inner.len();
|
||||||
|
let v_digits = v.inner.len();
|
||||||
|
|
||||||
|
let digits = if v_digits > u_digits {
|
||||||
|
v_digits
|
||||||
|
} else {
|
||||||
|
u_digits
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut carry = 0usize;
|
||||||
|
for i in 0..=digits {
|
||||||
|
let a = *u.inner.get(i).unwrap_or(&0usize);
|
||||||
|
let b = *v.inner.get(i).unwrap_or(&0usize);
|
||||||
|
|
||||||
|
let (res, overflowed) = a.overflowing_add(b);
|
||||||
|
// assert!(!overflowed, "Expected to overflow: {:#?}", (res, overflowed));
|
||||||
|
if overflowed {
|
||||||
|
if i == 0 {
|
||||||
|
out.inner[i] = res;
|
||||||
|
} else {
|
||||||
|
out.inner.push(res);
|
||||||
|
}
|
||||||
|
carry = core::usize::MAX - res + 1;
|
||||||
|
} else {
|
||||||
|
if res < core::usize::MAX {
|
||||||
|
out.inner.push(res + carry);
|
||||||
|
carry = 0;
|
||||||
|
} else {
|
||||||
|
out.inner.push(0usize);
|
||||||
|
carry = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
carry = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for BigInt {
|
impl Default for BigInt {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: vec![],
|
inner: vec![0],
|
||||||
sign: Sign::Positive,
|
sign: Sign::Positive,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Unsigned> From<T> for BigInt {
|
impl From<usize> for BigInt {
|
||||||
fn from(n: T) -> Self {
|
fn from(n: usize) -> Self {
|
||||||
let mut new = Self::default();
|
Self {
|
||||||
|
inner: vec![n],
|
||||||
if n > T::max_value() {
|
sign: Sign::Positive,
|
||||||
new.split(n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,6 +156,17 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn sanity_checks() {
|
fn sanity_checks() {
|
||||||
|
let int = BigInt::from(45u8);
|
||||||
|
assert_eq!(int.inner[0], 45usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* #[test]
|
||||||
|
fn test_add() {
|
||||||
|
let a = BigInt::from(core::u64::MAX);
|
||||||
|
let b = BigInt::from(core::u64::MAX);
|
||||||
|
|
||||||
|
let sum = add(a, b);
|
||||||
|
|
||||||
|
assert!(false, "{:#?} should have inner equal to {:?}", sum, core::u64::MAX as u128 + core::u64::MAX as u128);
|
||||||
|
} */
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user