use std::cmp::max; use std::convert::TryFrom; use std::num::TryFromIntError; use std::ops::{Add, Mul}; #[derive(Clone)] pub struct Number { // least significant first pub integer_part: Vec, } macro_rules! int_conv { ($($t:ty),*) => {$( impl From<$t> for Number { fn from(x: $t) -> Number { Number { integer_part: vec![x as usize], } } } impl TryFrom for $t { type Error = TryFromIntError; fn try_from(x: Number) -> Result<$t, TryFromIntError> { if x.integer_part.len() > 1 { ::try_from(-1).map(|_| 0) } else { <$t>::try_from(x.integer_part[0]).map_err(|_| ::try_from(-1).unwrap_err()) } } } )*}; } int_conv!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize); impl Add for Number { type Output = Number; fn add(self, rhs: Self) -> Self::Output { let longest_ipart_len = max(self.integer_part.len(), rhs.integer_part.len()); let mut result_ipart = vec![]; let mut carry: usize = 0; for i in 0..longest_ipart_len { let self_part = self.integer_part.get(i).copied().unwrap_or(0); let rhs_part = rhs.integer_part.get(i).copied().unwrap_or(0); let (half_sum, early_carry) = self_part.overflowing_add(rhs_part); let (full_sum, late_carry) = half_sum.overflowing_add(carry); carry = if early_carry || late_carry { 1 } else { 0 }; result_ipart.push(full_sum); } Number { integer_part: result_ipart, } } } impl Mul for Number { type Output = Number; fn mul(self, rhs: Self) -> Self::Output { if self.integer_part.len() > 1 || rhs.integer_part.len() > 1 { todo!() } else { Number { integer_part: vec![self.integer_part[0] * rhs.integer_part[0]] } } } }