ink_primitives/
arithmetic.rs1use core::ops::{
18 Add,
19 AddAssign,
20 Div,
21 DivAssign,
22 Mul,
23 MulAssign,
24 Sub,
25 SubAssign,
26};
27use num_traits::{
28 checked_pow,
29 Bounded,
30 CheckedMul,
31 One,
32 Unsigned,
33 Zero,
34};
35
36pub trait BaseArithmetic:
42 Sized
43 + From<u8>
44 + Bounded
45 + Ord
46 + PartialOrd<Self>
47 + Zero
48 + One
49 + Bounded
50 + Add<Self, Output = Self>
51 + AddAssign<Self>
52 + Sub<Self, Output = Self>
53 + SubAssign<Self>
54 + Mul<Self, Output = Self>
55 + MulAssign<Self>
56 + Div<Self, Output = Self>
57 + DivAssign<Self>
58 + CheckedMul
59 + Saturating
60 + TryFrom<u16>
61 + TryFrom<u32>
62 + TryFrom<u64>
63 + TryFrom<u128>
64 + TryFrom<usize>
65 + TryInto<u16>
66 + TryInto<u32>
67 + TryInto<u64>
68 + TryInto<u128>
69 + TryInto<usize>
70{
89}
90
91impl<T> BaseArithmetic for T where
92 T: Sized
93 + From<u8>
94 + Bounded
95 + Ord
96 + PartialOrd<Self>
97 + Zero
98 + One
99 + Add<Self, Output = Self>
100 + AddAssign<Self>
101 + Sub<Self, Output = Self>
102 + SubAssign<Self>
103 + Mul<Self, Output = Self>
104 + MulAssign<Self>
105 + Div<Self, Output = Self>
106 + DivAssign<Self>
107 + CheckedMul
108 + Saturating
109 + TryFrom<u16>
110 + TryFrom<u32>
111 + TryFrom<u64>
112 + TryFrom<u128>
113 + TryFrom<usize>
114 + TryInto<u16>
115 + TryInto<u32>
116 + TryInto<u64>
117 + TryInto<u128>
118 + TryInto<usize>
119{
120}
121
122pub trait AtLeast32Bit: BaseArithmetic + From<u16> + From<u32> {}
128
129impl<T> AtLeast32Bit for T where T: BaseArithmetic + From<u16> + From<u32> {}
130
131pub trait AtLeast32BitUnsigned: AtLeast32Bit + Unsigned {}
134
135impl<T> AtLeast32BitUnsigned for T where T: AtLeast32Bit + Unsigned {}
136
137#[allow(dead_code)]
140pub trait Saturating {
141 fn saturating_add(self, rhs: Self) -> Self;
144
145 fn saturating_sub(self, rhs: Self) -> Self;
148
149 fn saturating_mul(self, rhs: Self) -> Self;
152
153 fn saturating_pow(self, exp: usize) -> Self;
156}
157
158impl<T> Saturating for T
159where
160 T: Clone + Zero + One + PartialOrd + CheckedMul + Bounded + num_traits::Saturating,
161{
162 fn saturating_add(self, o: Self) -> Self {
163 <Self as num_traits::Saturating>::saturating_add(self, o)
164 }
165
166 fn saturating_sub(self, o: Self) -> Self {
167 <Self as num_traits::Saturating>::saturating_sub(self, o)
168 }
169
170 fn saturating_mul(self, o: Self) -> Self {
171 self.checked_mul(&o).unwrap_or_else(|| {
172 if (self < T::zero()) != (o < T::zero()) {
173 Bounded::min_value()
174 } else {
175 Bounded::max_value()
176 }
177 })
178 }
179
180 fn saturating_pow(self, exp: usize) -> Self {
181 let neg = self < T::zero() && exp % 2 != 0;
182 checked_pow(self, exp).unwrap_or_else(|| {
183 if neg {
184 Bounded::min_value()
185 } else {
186 Bounded::max_value()
187 }
188 })
189 }
190}
191
192#[cfg(test)]
193mod tests {
194 use super::Saturating;
195
196 #[test]
197 fn saturating_add() {
198 assert_eq!(u64::MAX, Saturating::saturating_add(u64::MAX, 1))
199 }
200
201 #[test]
202 fn saturatiung_sub() {
203 assert_eq!(u64::MIN, Saturating::saturating_sub(u64::MIN, 1))
204 }
205
206 #[test]
207 fn saturating_mul() {
208 assert_eq!(u64::MAX, Saturating::saturating_mul(u64::MAX, 2));
209 assert_eq!(i64::MAX, Saturating::saturating_mul(i64::MAX, 2));
210 assert_eq!(i64::MIN, Saturating::saturating_mul(i64::MIN, 2));
211 assert_eq!(i64::MIN, Saturating::saturating_mul(2, i64::MIN));
212 }
213
214 #[test]
215 fn saturating_pow() {
216 assert_eq!(u64::MAX, Saturating::saturating_pow(u64::MAX, 2));
217 assert_eq!(i64::MAX, Saturating::saturating_pow(i64::MIN, 2));
218 assert_eq!(i64::MIN, Saturating::saturating_pow(i64::MIN, 3));
219 }
220}