compiler_builtins/int/
addsub.rs

1use crate::int::{DInt, Int, MinInt};
2
3trait UAddSub: DInt + Int {
4    fn uadd(self, other: Self) -> Self {
5        let (lo, carry) = self.lo().overflowing_add(other.lo());
6        let hi = self.hi().wrapping_add(other.hi());
7        let carry = if carry { Self::H::ONE } else { Self::H::ZERO };
8        Self::from_lo_hi(lo, hi.wrapping_add(carry))
9    }
10    fn uadd_one(self) -> Self {
11        let (lo, carry) = self.lo().overflowing_add(Self::H::ONE);
12        let carry = if carry { Self::H::ONE } else { Self::H::ZERO };
13        Self::from_lo_hi(lo, self.hi().wrapping_add(carry))
14    }
15    fn usub(self, other: Self) -> Self {
16        let uneg = (!other).uadd_one();
17        self.uadd(uneg)
18    }
19}
20
21impl UAddSub for u128 {}
22
23trait AddSub: Int
24where
25    <Self as MinInt>::UnsignedInt: UAddSub,
26{
27    fn add(self, other: Self) -> Self {
28        Self::from_unsigned(self.unsigned().uadd(other.unsigned()))
29    }
30    fn sub(self, other: Self) -> Self {
31        Self::from_unsigned(self.unsigned().usub(other.unsigned()))
32    }
33}
34
35impl AddSub for u128 {}
36impl AddSub for i128 {}
37
38trait Addo: AddSub
39where
40    <Self as MinInt>::UnsignedInt: UAddSub,
41{
42    fn addo(self, other: Self) -> (Self, bool) {
43        let sum = AddSub::add(self, other);
44        (sum, (other < Self::ZERO) != (sum < self))
45    }
46}
47
48impl Addo for i128 {}
49impl Addo for u128 {}
50
51trait Subo: AddSub
52where
53    <Self as MinInt>::UnsignedInt: UAddSub,
54{
55    fn subo(self, other: Self) -> (Self, bool) {
56        let sum = AddSub::sub(self, other);
57        (sum, (other < Self::ZERO) != (self < sum))
58    }
59}
60
61impl Subo for i128 {}
62impl Subo for u128 {}
63
64intrinsics! {
65    pub extern "C" fn __rust_i128_add(a: i128, b: i128) -> i128 {
66        AddSub::add(a,b)
67    }
68
69    pub extern "C" fn __rust_i128_addo(a: i128, b: i128, oflow: &mut i32) -> i128 {
70        let (add, o) = a.addo(b);
71        *oflow = o.into();
72        add
73    }
74
75    pub extern "C" fn __rust_u128_add(a: u128, b: u128) -> u128 {
76        AddSub::add(a,b)
77    }
78
79    pub extern "C" fn __rust_u128_addo(a: u128, b: u128, oflow: &mut i32) -> u128 {
80        let (add, o) = a.addo(b);
81        *oflow = o.into();
82        add
83    }
84
85    pub extern "C" fn __rust_i128_sub(a: i128, b: i128) -> i128 {
86        AddSub::sub(a,b)
87    }
88
89    pub extern "C" fn __rust_i128_subo(a: i128, b: i128, oflow: &mut i32) -> i128 {
90        let (sub, o) = a.subo(b);
91        *oflow = o.into();
92        sub
93    }
94
95    pub extern "C" fn __rust_u128_sub(a: u128, b: u128) -> u128 {
96        AddSub::sub(a,b)
97    }
98
99    pub extern "C" fn __rust_u128_subo(a: u128, b: u128, oflow: &mut i32) -> u128 {
100        let (sub, o) = a.subo(b);
101        *oflow = o.into();
102        sub
103    }
104}