aboutsummaryrefslogtreecommitdiff
path: root/src/number.rs
blob: d40e50abadd4edd2e2da58a4170fc73527df9def (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
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<usize>,
}

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<Number> for $t {
            type Error = TryFromIntError;

            fn try_from(x: Number) -> Result<$t, TryFromIntError> {
                if x.integer_part.len() > 1 {
                    <u8>::try_from(-1).map(|_| 0)
                } else {
                    <$t>::try_from(x.integer_part[0]).map_err(|_| <u8>::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]]
            }
        }
    }
}