use core::panic;
use std::{fmt, ops};
#[derive(Clone)]
pub struct InfInt(pub Vec<u128>);
impl InfInt {
pub fn new(var: u128) -> Self {
InfInt(vec![var])
}
pub fn add_destroy(&mut self, other: &InfInt) {
if self.0.len() == 0 {
panic!("Empty InfInt object should never exist.");
}
let mut carry = false;
let mut idx = 0;
while idx < other.0.len() {
if idx > self.0.len() - 1 {
self.0.push(0);
}
let (res_temp, car_temp1) = u128::add_and_carry(self.0[idx], other.0[idx]);
(self.0[idx], carry) = u128::add_and_carry(res_temp, carry as u128);
carry = car_temp1 || carry;
idx += 1;
}
while carry {
if idx >= self.0.len() {
self.0.push(1);
break;
}
(self.0[idx], carry) = u128::add_and_carry(self.0[idx], 1);
idx += 1;
}
}
pub fn subtract_destroy(&mut self, other: &InfInt) {
if other.0.len() > self.0.len() {
self.0 = vec![0];
}
let mut carry = false;
let mut idx = 0;
while idx < other.0.len() {
let mut temp_carry = self.0[idx] < other.0[idx];
self.0[idx] = self.0[idx].wrapping_sub(other.0[idx]);
temp_carry = temp_carry || (self.0[idx] == 0);
self.0[idx] = self.0[idx].wrapping_sub(carry as u128);
carry = temp_carry;
idx += 1;
}
if carry {
loop {
if idx >= self.0.len() {
self.0 = vec![0];
break;
} else if self.0[idx] == 0 {
self.0[idx] = u128::MAX;
} else {
self.0[idx] -= 1;
break;
}
idx += 1;
}
}
while self.0.len() > 1 && *self.0.last().unwrap() == 0 {
self.0.pop();
}
}
pub fn multiply_destroy(&mut self, other: &InfInt) {
if self.0.len() == 0 || other.0.len() == 0 {
panic!("Empty InfInt object should never exist.");
}
if (other.0.len() == 1 && other.0[0] == 0) || (self.0.len() == 1 && self.0[0] == 0) {
self.0 = vec![0];
return; }
let mut other_idxs: Vec<u128> = vec![];
for i in 0..other.0.len() {
if other.0[i] != 0 {
other_idxs.push(0);
}
}
inc_list_idx(&mut other_idxs); let self_adder = self.clone();
while other_idxs != other.0 {
self.add_destroy(&self_adder);
inc_list_idx(&mut other_idxs);
}
}
pub fn to_base_10_array(&self) -> Vec<u8> {
let mut array_out = vec![0];
for i in 0..self.0.len() {
for j in 0..128 {
if ((self.0[i] >> j) & 1) == 1 {
let mut new_value = vec![1];
for _ in 0..((i * 128) + j) {
let (mut res, mut carry) =
base_10_add_and_carry(new_value[0], new_value[0]);
new_value[0] = res;
for k in 1..new_value.len() {
let temp_carry = carry;
(res, carry) = base_10_add_and_carry(new_value[k], new_value[k]);
new_value[k] = res + temp_carry as u8;
}
if carry {
new_value.push(1);
}
}
let mut carry = false;
let mut k = 0;
while k < new_value.len() {
if k > array_out.len() - 1 {
array_out.push(0);
}
let (res, car_temp) = base_10_add_and_carry(array_out[k], new_value[k]);
(array_out[k], carry) = base_10_add_and_carry(res, carry as u8);
carry = car_temp || carry;
k += 1;
}
while carry {
if k > array_out.len() - 1 {
array_out.push(0);
}
(array_out[k], carry) = base_10_add_and_carry(array_out[k], 1);
k += 1;
}
}
}
}
array_out
}
}
fn inc_list_idx(list_idx: &mut Vec<u128>) {
let mut idx = 0;
let mut carry = true;
while idx < list_idx.len() {
(list_idx[idx], carry) = u128::add_and_carry(list_idx[idx], carry as u128);
if !carry {
break;
}
idx += 1;
}
}
pub trait AddAndCarry<T, Output = (T, bool)> {
fn add_and_carry(a: T, b: T) -> Output;
}
impl AddAndCarry<u128> for u128 {
fn add_and_carry(a: u128, b: u128) -> (u128, bool) {
let result = a.wrapping_add(b);
let carry = result < a || result < b;
(result, carry)
}
}
impl AddAndCarry<u8> for u8 {
fn add_and_carry(a: u8, b: u8) -> (u8, bool) {
let result = a.wrapping_add(b);
let carry = result < a || result < b;
(result, carry)
}
}
fn base_10_add_and_carry(a: u8, b: u8) -> (u8, bool) {
let result = a + b;
let carry = result > 9;
(result % 10, carry)
}
impl fmt::Debug for InfInt {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut result = String::new();
let base_10_version = self.to_base_10_array();
for number in base_10_version.iter().rev() {
result.push_str(&number.to_string());
}
write!(f, "{}", result)
}
}
impl fmt::Display for InfInt {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut result = String::new();
let base_10_version = self.to_base_10_array();
for number in base_10_version.iter().rev() {
result.push_str(&number.to_string());
}
write!(f, "{}", result)
}
}
impl ops::Add<InfInt> for InfInt {
type Output = InfInt;
fn add(self, other: InfInt) -> InfInt {
let mut result = self.clone();
result.add_destroy(&other);
result
}
}
impl ops::Add<u128> for InfInt {
type Output = InfInt;
fn add(self, other: u128) -> InfInt {
let mut result = self.clone();
result.add_destroy(&InfInt::new(other));
result
}
}
impl PartialEq for InfInt {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add_and_carry() {
let (result, carry) = u128::add_and_carry(1, 2);
assert_eq!(result, 3);
assert!(!carry);
let (result, carry) = u128::add_and_carry(u128::MAX, 1);
assert_eq!(result, 0);
assert!(carry);
}
#[test]
fn test_add_destroy() {
let mut a = InfInt::new(1);
let b = InfInt::new(2);
a.add_destroy(&b);
assert_eq!(a, InfInt::new(3));
}
#[test]
fn add_new_item() {
let mut a = InfInt::new(1);
a.add_destroy(&InfInt::new(u128::MAX));
let mut answer = InfInt::new(0);
answer.0.push(1);
println!("a: {:?}", a);
println!("answer: {:?}", answer);
assert_eq!(a, answer);
}
#[test]
fn add_two_items() {
let mut a = InfInt::new(5);
a.add_destroy(&InfInt::new(u128::MAX));
a.add_destroy(&InfInt::new(u128::MAX));
let mut b = InfInt::new(3);
b.0.push(2);
assert_eq!(a, b);
}
#[test]
fn add_with_long_carry() {
let mut a = InfInt::new(u128::MAX);
a.0.push(u128::MAX);
a.0.push(u128::MAX);
a.add_destroy(&InfInt::new(1));
let mut answer = InfInt::new(0);
answer.0.push(0);
answer.0.push(0);
answer.0.push(1);
assert_eq!(a, answer);
}
#[test]
fn test_subtract_destroy() {
let mut a = InfInt::new(5);
let b = InfInt::new(2);
a.subtract_destroy(&b);
assert_eq!(a, InfInt::new(3));
}
#[test]
fn test_subtract_bigger() {
let mut a = InfInt::new(5);
let b = InfInt::new(10);
a.subtract_destroy(&b);
assert_eq!(a, InfInt::new(0)); }
#[test]
fn test_to_base_10_array() {
let a = InfInt::new(123456789);
let base_10_array = a.to_base_10_array();
assert_eq!(base_10_array, vec![9, 8, 7, 6, 5, 4, 3, 2, 1]); }
#[test]
fn test_small_to_base_10_array() {
let a = InfInt::new(5);
let base_10_array = a.to_base_10_array();
assert_eq!(base_10_array, vec![5]);
}
#[test]
fn test_carry_to_base_10_array() {
let a = InfInt::new(10);
let base_10_array = a.to_base_10_array();
assert_eq!(base_10_array, vec![0, 1]);
}
#[test]
fn test_subtract_carry() {
let mut a = InfInt::new(0);
a.0.push(1);
let b = InfInt::new(1);
a.subtract_destroy(&b);
assert_eq!(a, InfInt::new(u128::MAX));
assert_eq!(a.0.len(), InfInt::new(u128::MAX).0.len());
}
#[test]
fn test_add_and_subtract() {
let mut a = InfInt::new(10);
a.add_destroy(&InfInt::new(5));
assert_eq!(a, InfInt::new(15));
a.subtract_destroy(&InfInt::new(12));
assert_eq!(a, InfInt::new(3));
}
#[test]
fn test_multiply_destroy() {
let mut a = InfInt::new(3);
let b = InfInt::new(4);
a.multiply_destroy(&b);
assert_eq!(a, InfInt::new(12));
let mut c = InfInt::new(0);
c.multiply_destroy(&b);
assert_eq!(c, InfInt::new(0)); }
}