Start implementations of basic arithmatic operators
All checks were successful
timw4mail/rusty-numbers/pipeline/head This commit looks good
All checks were successful
timw4mail/rusty-numbers/pipeline/head This commit looks good
This commit is contained in:
parent
fce5d42be2
commit
94f39fff07
178
src/bigint.rs
178
src/bigint.rs
@ -1,18 +1,15 @@
|
|||||||
//! \[WIP\] Arbitrarily large integers
|
//! \[WIP\] Arbitrarily large integers
|
||||||
//!
|
//!
|
||||||
//! Traits to implement:
|
//! Traits to implement:
|
||||||
//! * Add
|
|
||||||
//! * AddAssign
|
|
||||||
//! * Div
|
|
||||||
//! * DivAssign
|
|
||||||
//! * Mul
|
|
||||||
//! * MulAssign
|
|
||||||
//! * Neg
|
//! * Neg
|
||||||
//! * Rem
|
//! * Rem
|
||||||
//! * RemAssign
|
//! * RemAssign
|
||||||
//! * Sub
|
//! * Sub
|
||||||
//! * SubAssign
|
//! * SubAssign
|
||||||
use crate::num::*;
|
use crate::num::*;
|
||||||
|
use core::ops::{
|
||||||
|
Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Sub, SubAssign,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct BigInt {
|
pub struct BigInt {
|
||||||
@ -37,27 +34,71 @@ macro_rules! impl_from_smaller {
|
|||||||
|
|
||||||
#[cfg(target_pointer_width = "16")]
|
#[cfg(target_pointer_width = "16")]
|
||||||
impl_from_smaller!(u8, u16);
|
impl_from_smaller!(u8, u16);
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "16")]
|
#[cfg(target_pointer_width = "16")]
|
||||||
static BITS:usize = 16;
|
static BITS:usize = 16;
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
impl_from_smaller!(u8, u16, u32);
|
impl_from_smaller!(u8, u16, u32);
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
static BITS:usize = 32;
|
static BITS:usize = 32;
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
impl_from_smaller!(u8, u16, u32, u64);
|
impl_from_smaller!(u8, u16, u32, u64);
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
static BITS:usize = 64;
|
static BITS:usize = 64;
|
||||||
|
|
||||||
fn add(u: BigInt, v: BigInt) -> BigInt {
|
impl Default for BigInt {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
inner: vec![0],
|
||||||
|
sign: Sign::Positive,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<usize> for BigInt {
|
||||||
|
fn from(n: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
inner: vec![n],
|
||||||
|
sign: Sign::Positive,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for BigInt {
|
||||||
|
fn from(s: &str) -> Self {
|
||||||
|
Self::from_str_radix(s, 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<String> for BigInt {
|
||||||
|
fn from(s: String) -> Self {
|
||||||
|
Self::from_str_radix(s, 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BigInt {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shrink_to_fit(&mut self) {
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_str_radix<T: ToString>(s: T, radix: usize) -> BigInt {
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add for BigInt {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn add(self, rhs: Self) -> Self::Output {
|
||||||
let mut out = BigInt::default();
|
let mut out = BigInt::default();
|
||||||
|
|
||||||
let u_digits = u.inner.len();
|
let u_digits = self.inner.len();
|
||||||
let v_digits = v.inner.len();
|
let v_digits = rhs.inner.len();
|
||||||
|
|
||||||
let digits = if v_digits > u_digits {
|
let digits = if v_digits > u_digits {
|
||||||
v_digits
|
v_digits
|
||||||
@ -67,8 +108,8 @@ fn add(u: BigInt, v: BigInt) -> BigInt {
|
|||||||
|
|
||||||
let mut carry = 0usize;
|
let mut carry = 0usize;
|
||||||
for i in 0..=digits {
|
for i in 0..=digits {
|
||||||
let a = *u.inner.get(i).unwrap_or(&0usize);
|
let a = *self.inner.get(i).unwrap_or(&0usize);
|
||||||
let b = *v.inner.get(i).unwrap_or(&0usize);
|
let b = *rhs.inner.get(i).unwrap_or(&0usize);
|
||||||
|
|
||||||
let (res, overflowed) = a.overflowing_add(b);
|
let (res, overflowed) = a.overflowing_add(b);
|
||||||
// assert!(!overflowed, "Expected to overflow: {:#?}", (res, overflowed));
|
// assert!(!overflowed, "Expected to overflow: {:#?}", (res, overflowed));
|
||||||
@ -93,49 +134,79 @@ fn add(u: BigInt, v: BigInt) -> BigInt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
out
|
out
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for BigInt {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
inner: vec![0],
|
|
||||||
sign: Sign::Positive,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<usize> for BigInt {
|
impl Sub for BigInt {
|
||||||
fn from(n: usize) -> Self {
|
type Output = Self;
|
||||||
Self {
|
|
||||||
inner: vec![n],
|
|
||||||
sign: Sign::Positive,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&str> for BigInt {
|
fn sub(self, rhs: Self) -> Self::Output {
|
||||||
fn from(_: &str) -> Self {
|
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<String> for BigInt {
|
impl Mul for BigInt {
|
||||||
fn from(_: String) -> Self {
|
type Output = Self;
|
||||||
|
|
||||||
|
fn mul(self, rhs: Self) -> Self::Output {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BigInt {
|
impl Div for BigInt {
|
||||||
pub fn new() -> Self {
|
type Output = Self;
|
||||||
Self::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn shrink_to_fit(&mut self) {
|
fn div(self, rhs: Self) -> Self::Output {
|
||||||
todo!();
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_str_radix<T: ToString>(s: T, radix: usize) {
|
impl Rem for BigInt {
|
||||||
todo!();
|
type Output = Self;
|
||||||
|
|
||||||
|
fn rem(self, rhs: Self) -> Self::Output {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddAssign for BigInt {
|
||||||
|
fn add_assign(&mut self, rhs: Self) {
|
||||||
|
*self = self.clone() + rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SubAssign for BigInt {
|
||||||
|
fn sub_assign(&mut self, rhs: Self) {
|
||||||
|
*self = self.clone() - rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MulAssign for BigInt {
|
||||||
|
fn mul_assign(&mut self, rhs: Self) {
|
||||||
|
*self = self.clone() * rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DivAssign for BigInt {
|
||||||
|
fn div_assign(&mut self, rhs: Self) {
|
||||||
|
*self = self.clone() / rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RemAssign for BigInt {
|
||||||
|
fn rem_assign(&mut self, rhs: Self) {
|
||||||
|
*self = self.clone() % rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Neg for BigInt {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn neg(self) -> Self::Output {
|
||||||
|
let mut output = self.clone();
|
||||||
|
output.sign = !output.sign;
|
||||||
|
|
||||||
|
output
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,11 +229,28 @@ mod tests {
|
|||||||
let a = BigInt::from(core::usize::MAX);
|
let a = BigInt::from(core::usize::MAX);
|
||||||
let b = BigInt::from(core::usize::MAX);
|
let b = BigInt::from(core::usize::MAX);
|
||||||
|
|
||||||
let sum = add(a, b);
|
let sum = a + b;
|
||||||
|
|
||||||
assert_eq!(sum.inner[0], core::usize::MAX - 1, "least significant place should be MAX - 1");
|
assert_eq!(
|
||||||
|
sum.inner[0],
|
||||||
|
core::usize::MAX - 1,
|
||||||
|
"least significant place should be MAX - 1"
|
||||||
|
);
|
||||||
assert_eq!(sum.inner[1], 1usize, "most significant place should be 1");
|
assert_eq!(sum.inner[1], 1usize, "most significant place should be 1");
|
||||||
|
}
|
||||||
|
|
||||||
// assert!(false, "{:#?} should have inner equal to {:?}", sum, core::u64::MAX as u128 + core::u64::MAX as u128);
|
#[test]
|
||||||
|
fn test_add_assign() {
|
||||||
|
let mut a = BigInt::from(core::usize::MAX);
|
||||||
|
let b = BigInt::from(core::usize::MAX);
|
||||||
|
|
||||||
|
a += b;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
a.inner[0],
|
||||||
|
core::usize::MAX - 1,
|
||||||
|
"least significant place should be MAX - 1"
|
||||||
|
);
|
||||||
|
assert_eq!(a.inner[1], 1usize, "most significant place should be 1");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user