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
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use int::Int;
use int::LargeInt;

trait UAddSub: LargeInt {
    fn uadd(self, other: Self) -> Self {
        let (low, carry) = self.low().overflowing_add(other.low());
        let high = self.high().wrapping_add(other.high());
        let carry = if carry {
            Self::HighHalf::ONE
        } else {
            Self::HighHalf::ZERO
        };
        Self::from_parts(low, high.wrapping_add(carry))
    }
    fn uadd_one(self) -> Self {
        let (low, carry) = self.low().overflowing_add(Self::LowHalf::ONE);
        let carry = if carry {
            Self::HighHalf::ONE
        } else {
            Self::HighHalf::ZERO
        };
        Self::from_parts(low, self.high().wrapping_add(carry))
    }
    fn usub(self, other: Self) -> Self {
        let uneg = (!other).uadd_one();
        self.uadd(uneg)
    }
}

impl UAddSub for u128 {}

trait AddSub: Int
where
    <Self as Int>::UnsignedInt: UAddSub,
{
    fn add(self, other: Self) -> Self {
        Self::from_unsigned(self.unsigned().uadd(other.unsigned()))
    }
    fn sub(self, other: Self) -> Self {
        Self::from_unsigned(self.unsigned().usub(other.unsigned()))
    }
}

impl AddSub for u128 {}
impl AddSub for i128 {}

trait Addo: AddSub
where
    <Self as Int>::UnsignedInt: UAddSub,
{
    fn addo(self, other: Self, overflow: &mut i32) -> Self {
        *overflow = 0;
        let result = AddSub::add(self, other);
        if other >= Self::ZERO {
            if result < self {
                *overflow = 1;
            }
        } else {
            if result >= self {
                *overflow = 1;
            }
        }
        result
    }
}

impl Addo for i128 {}
impl Addo for u128 {}

trait Subo: AddSub
where
    <Self as Int>::UnsignedInt: UAddSub,
{
    fn subo(self, other: Self, overflow: &mut i32) -> Self {
        *overflow = 0;
        let result = AddSub::sub(self, other);
        if other >= Self::ZERO {
            if result > self {
                *overflow = 1;
            }
        } else {
            if result <= self {
                *overflow = 1;
            }
        }
        result
    }
}

impl Subo for i128 {}
impl Subo for u128 {}

intrinsics! {
    pub extern "C" fn __rust_i128_add(a: i128, b: i128) -> i128 {
        __rust_u128_add(a as _, b as _) as _
    }

    pub extern "C" fn __rust_i128_addo(a: i128, b: i128) -> (i128, bool) {
        let mut oflow = 0;
        let r = a.addo(b, &mut oflow);
        (r, oflow != 0)
    }

    pub extern "C" fn __rust_u128_add(a: u128, b: u128) -> u128 {
        a.add(b)
    }

    pub extern "C" fn __rust_u128_addo(a: u128, b: u128) -> (u128, bool) {
        let mut oflow = 0;
        let r = a.addo(b, &mut oflow);
        (r, oflow != 0)
    }


    pub extern "C" fn __rust_i128_sub(a: i128, b: i128) -> i128 {
        __rust_u128_sub(a as _, b as _) as _
    }

    pub extern "C" fn __rust_i128_subo(a: i128, b: i128) -> (i128, bool) {
        let mut oflow = 0;
        let r = a.subo(b, &mut oflow);
        (r, oflow != 0)
    }

    pub extern "C" fn __rust_u128_sub(a: u128, b: u128) -> u128 {
        a.sub(b)
    }

    pub extern "C" fn __rust_u128_subo(a: u128, b: u128) -> (u128, bool) {
        let mut oflow = 0;
        let r = a.subo(b, &mut oflow);
        (r, oflow != 0)
    }
}