1#![cfg(feature = "num-traits")]
3#![cfg_attr(docsrs, doc(cfg(feature = "num-traits")))]
4#![deny(unconditional_recursion)]
7use crate::Uint;
8use core::ops::{Shl, Shr};
9use num_traits::{
10 CheckedEuclid, Euclid, Inv, MulAdd, MulAddAssign, Num, NumCast,
11 bounds::Bounded,
12 cast::{FromPrimitive, ToPrimitive},
13 identities::{One, Zero},
14 int::PrimInt,
15 ops::{
16 bytes::{FromBytes, ToBytes},
17 checked::{
18 CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr,
19 CheckedSub,
20 },
21 overflowing::{OverflowingAdd, OverflowingMul, OverflowingSub},
22 saturating::{Saturating, SaturatingAdd, SaturatingMul, SaturatingSub},
23 wrapping::{WrappingAdd, WrappingMul, WrappingNeg, WrappingShl, WrappingShr, WrappingSub},
24 },
25 pow::Pow,
26 sign::Unsigned,
27};
28
29#[cfg(not(feature = "std"))]
30use alloc::vec::Vec;
31
32impl<const BITS: usize, const LIMBS: usize> Zero for Uint<BITS, LIMBS> {
38 #[inline(always)]
39 fn zero() -> Self {
40 Self::ZERO
41 }
42
43 #[inline(always)]
44 fn is_zero(&self) -> bool {
45 self.is_zero()
46 }
47}
48
49impl<const BITS: usize, const LIMBS: usize> One for Uint<BITS, LIMBS> {
50 #[inline(always)]
51 fn one() -> Self {
52 Self::ONE
53 }
54}
55
56impl<const BITS: usize, const LIMBS: usize> Bounded for Uint<BITS, LIMBS> {
57 #[inline(always)]
58 fn min_value() -> Self {
59 Self::ZERO
60 }
61
62 #[inline(always)]
63 fn max_value() -> Self {
64 Self::MAX
65 }
66}
67
68impl<const BITS: usize, const LIMBS: usize> FromBytes for Uint<BITS, LIMBS> {
69 type Bytes = [u8];
70
71 #[inline(always)]
72 fn from_le_bytes(bytes: &[u8]) -> Self {
73 Self::try_from_le_slice(bytes).unwrap()
74 }
75
76 #[inline(always)]
77 fn from_be_bytes(bytes: &[u8]) -> Self {
78 Self::try_from_be_slice(bytes).unwrap()
79 }
80}
81
82impl<const BITS: usize, const LIMBS: usize> ToBytes for Uint<BITS, LIMBS> {
83 type Bytes = Vec<u8>;
84
85 #[inline(always)]
86 fn to_le_bytes(&self) -> Self::Bytes {
87 self.to_le_bytes_vec()
88 }
89
90 #[inline(always)]
91 fn to_be_bytes(&self) -> Self::Bytes {
92 self.to_be_bytes_vec()
93 }
94}
95
96impl<const BITS: usize, const LIMBS: usize> CheckedAdd for Uint<BITS, LIMBS> {
97 #[inline(always)]
98 fn checked_add(&self, other: &Self) -> Option<Self> {
99 <Self>::checked_add(*self, *other)
100 }
101}
102
103impl<const BITS: usize, const LIMBS: usize> CheckedDiv for Uint<BITS, LIMBS> {
104 #[inline(always)]
105 fn checked_div(&self, other: &Self) -> Option<Self> {
106 <Self>::checked_div(*self, *other)
107 }
108}
109
110impl<const BITS: usize, const LIMBS: usize> CheckedMul for Uint<BITS, LIMBS> {
111 #[inline(always)]
112 fn checked_mul(&self, other: &Self) -> Option<Self> {
113 <Self>::checked_mul(*self, *other)
114 }
115}
116
117impl<const BITS: usize, const LIMBS: usize> CheckedNeg for Uint<BITS, LIMBS> {
118 #[inline(always)]
119 fn checked_neg(&self) -> Option<Self> {
120 <Self>::checked_neg(*self)
121 }
122}
123
124impl<const BITS: usize, const LIMBS: usize> CheckedRem for Uint<BITS, LIMBS> {
125 #[inline(always)]
126 fn checked_rem(&self, other: &Self) -> Option<Self> {
127 <Self>::checked_rem(*self, *other)
128 }
129}
130
131impl<const BITS: usize, const LIMBS: usize> CheckedShl for Uint<BITS, LIMBS> {
132 #[inline(always)]
133 fn checked_shl(&self, other: u32) -> Option<Self> {
134 <Self>::checked_shl(*self, other as usize)
135 }
136}
137
138impl<const BITS: usize, const LIMBS: usize> CheckedShr for Uint<BITS, LIMBS> {
139 #[inline(always)]
140 fn checked_shr(&self, other: u32) -> Option<Self> {
141 <Self>::checked_shr(*self, other as usize)
142 }
143}
144
145impl<const BITS: usize, const LIMBS: usize> CheckedSub for Uint<BITS, LIMBS> {
146 #[inline(always)]
147 fn checked_sub(&self, other: &Self) -> Option<Self> {
148 <Self>::checked_sub(*self, *other)
149 }
150}
151
152impl<const BITS: usize, const LIMBS: usize> CheckedEuclid for Uint<BITS, LIMBS> {
153 #[inline(always)]
154 fn checked_div_euclid(&self, v: &Self) -> Option<Self> {
155 <Self>::checked_div(*self, *v)
156 }
157
158 #[inline(always)]
159 fn checked_rem_euclid(&self, v: &Self) -> Option<Self> {
160 <Self>::checked_rem(*self, *v)
161 }
162}
163
164impl<const BITS: usize, const LIMBS: usize> Euclid for Uint<BITS, LIMBS> {
165 #[inline(always)]
166 fn div_euclid(&self, v: &Self) -> Self {
167 <Self>::wrapping_div(*self, *v)
168 }
169
170 #[inline(always)]
171 fn rem_euclid(&self, v: &Self) -> Self {
172 <Self>::wrapping_rem(*self, *v)
173 }
174}
175
176impl<const BITS: usize, const LIMBS: usize> Inv for Uint<BITS, LIMBS> {
177 type Output = Option<Self>;
178
179 #[inline(always)]
180 fn inv(self) -> Self::Output {
181 <Self>::inv_ring(self)
182 }
183}
184
185impl<const BITS: usize, const LIMBS: usize> MulAdd for Uint<BITS, LIMBS> {
186 type Output = Self;
187
188 #[inline(always)]
189 fn mul_add(self, a: Self, b: Self) -> Self::Output {
190 (self * a) + b
192 }
193}
194
195impl<const BITS: usize, const LIMBS: usize> MulAddAssign for Uint<BITS, LIMBS> {
196 #[inline(always)]
197 fn mul_add_assign(&mut self, a: Self, b: Self) {
198 *self *= a;
199 *self += b;
200 }
201}
202
203impl<const BITS: usize, const LIMBS: usize> Saturating for Uint<BITS, LIMBS> {
204 #[inline(always)]
205 fn saturating_add(self, v: Self) -> Self {
206 <Self>::saturating_add(self, v)
207 }
208
209 #[inline(always)]
210 fn saturating_sub(self, v: Self) -> Self {
211 <Self>::saturating_sub(self, v)
212 }
213}
214
215macro_rules! binary_op {
216 ($($trait:ident $fn:ident)*) => {$(
217 impl<const BITS: usize, const LIMBS: usize> $trait for Uint<BITS, LIMBS> {
218 #[inline(always)]
219 fn $fn(&self, v: &Self) -> Self {
220 <Self>::$fn(*self, *v)
221 }
222 }
223 )*};
224}
225
226binary_op! {
227 SaturatingAdd saturating_add
228 SaturatingSub saturating_sub
229 SaturatingMul saturating_mul
230 WrappingAdd wrapping_add
231 WrappingSub wrapping_sub
232 WrappingMul wrapping_mul
233}
234
235impl<const BITS: usize, const LIMBS: usize> WrappingNeg for Uint<BITS, LIMBS> {
236 #[inline(always)]
237 fn wrapping_neg(&self) -> Self {
238 <Self>::wrapping_neg(*self)
239 }
240}
241
242impl<const BITS: usize, const LIMBS: usize> WrappingShl for Uint<BITS, LIMBS> {
243 #[inline(always)]
244 fn wrapping_shl(&self, rhs: u32) -> Self {
245 <Self>::wrapping_shl(*self, rhs as usize)
246 }
247}
248
249impl<const BITS: usize, const LIMBS: usize> WrappingShr for Uint<BITS, LIMBS> {
250 #[inline(always)]
251 fn wrapping_shr(&self, rhs: u32) -> Self {
252 <Self>::wrapping_shr(*self, rhs as usize)
253 }
254}
255
256impl<const BITS: usize, const LIMBS: usize> OverflowingAdd for Uint<BITS, LIMBS> {
257 #[inline(always)]
258 fn overflowing_add(&self, v: &Self) -> (Self, bool) {
259 <Self>::overflowing_add(*self, *v)
260 }
261}
262
263impl<const BITS: usize, const LIMBS: usize> OverflowingSub for Uint<BITS, LIMBS> {
264 #[inline(always)]
265 fn overflowing_sub(&self, v: &Self) -> (Self, bool) {
266 <Self>::overflowing_sub(*self, *v)
267 }
268}
269
270impl<const BITS: usize, const LIMBS: usize> OverflowingMul for Uint<BITS, LIMBS> {
271 #[inline(always)]
272 fn overflowing_mul(&self, v: &Self) -> (Self, bool) {
273 <Self>::overflowing_mul(*self, *v)
274 }
275}
276
277impl<const BITS: usize, const LIMBS: usize> Num for Uint<BITS, LIMBS> {
278 type FromStrRadixErr = crate::ParseError;
279
280 #[inline(always)]
281 fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
282 #[allow(clippy::cast_lossless)]
283 <Self>::from_str_radix(str, radix as u64)
284 }
285}
286
287impl<const BITS: usize, const LIMBS: usize> Pow<Self> for Uint<BITS, LIMBS> {
288 type Output = Self;
289
290 #[inline(always)]
291 fn pow(self, rhs: Self) -> Self::Output {
292 <Self>::pow(self, rhs)
293 }
294}
295
296impl<const BITS: usize, const LIMBS: usize> Unsigned for Uint<BITS, LIMBS> {}
297
298impl<const BITS: usize, const LIMBS: usize> ToPrimitive for Uint<BITS, LIMBS> {
299 #[inline(always)]
300 fn to_i64(&self) -> Option<i64> {
301 self.try_into().ok()
302 }
303
304 #[inline(always)]
305 fn to_u64(&self) -> Option<u64> {
306 self.try_into().ok()
307 }
308
309 #[inline(always)]
310 fn to_i128(&self) -> Option<i128> {
311 self.try_into().ok()
312 }
313
314 #[inline(always)]
315 fn to_u128(&self) -> Option<u128> {
316 self.try_into().ok()
317 }
318}
319
320impl<const BITS: usize, const LIMBS: usize> FromPrimitive for Uint<BITS, LIMBS> {
321 #[inline(always)]
322 fn from_i64(n: i64) -> Option<Self> {
323 Self::try_from(n).ok()
324 }
325
326 #[inline(always)]
327 fn from_u64(n: u64) -> Option<Self> {
328 Self::try_from(n).ok()
329 }
330
331 #[inline(always)]
332 fn from_i128(n: i128) -> Option<Self> {
333 Self::try_from(n).ok()
334 }
335
336 #[inline(always)]
337 fn from_u128(n: u128) -> Option<Self> {
338 Self::try_from(n).ok()
339 }
340}
341
342impl<const BITS: usize, const LIMBS: usize> NumCast for Uint<BITS, LIMBS> {
343 #[inline(always)]
344 fn from<T: ToPrimitive>(n: T) -> Option<Self> {
345 <Self>::try_from(n.to_u128()?).ok()
346 }
347}
348
349impl<const BITS: usize, const LIMBS: usize> PrimInt for Uint<BITS, LIMBS> {
350 #[inline(always)]
351 #[allow(clippy::cast_possible_truncation)] fn count_ones(self) -> u32 {
353 <Self>::count_ones(&self) as u32
354 }
355
356 #[inline(always)]
357 #[allow(clippy::cast_possible_truncation)] fn count_zeros(self) -> u32 {
359 <Self>::count_zeros(&self) as u32
360 }
361
362 #[inline(always)]
363 #[allow(clippy::cast_possible_truncation)] fn leading_zeros(self) -> u32 {
365 <Self>::leading_zeros(&self) as u32
366 }
367
368 #[inline(always)]
369 #[allow(clippy::cast_possible_truncation)] fn leading_ones(self) -> u32 {
371 <Self>::leading_ones(&self) as u32
372 }
373
374 #[inline(always)]
375 #[allow(clippy::cast_possible_truncation)] fn trailing_zeros(self) -> u32 {
377 <Self>::trailing_zeros(&self) as u32
378 }
379 #[inline(always)]
380 #[allow(clippy::cast_possible_truncation)] fn trailing_ones(self) -> u32 {
382 <Self>::trailing_ones(&self) as u32
383 }
384
385 #[inline(always)]
386 fn rotate_left(self, n: u32) -> Self {
387 <Self>::rotate_left(self, n as usize)
388 }
389
390 #[inline(always)]
391 fn rotate_right(self, n: u32) -> Self {
392 <Self>::rotate_right(self, n as usize)
393 }
394
395 #[inline(always)]
396 fn signed_shl(self, n: u32) -> Self {
397 <Self>::shl(self, n as usize)
398 }
399
400 #[inline(always)]
401 fn signed_shr(self, n: u32) -> Self {
402 <Self>::arithmetic_shr(self, n as usize)
403 }
404
405 #[inline(always)]
406 fn unsigned_shl(self, n: u32) -> Self {
407 <Self>::shl(self, n as usize)
408 }
409
410 #[inline(always)]
411 fn unsigned_shr(self, n: u32) -> Self {
412 <Self>::shr(self, n as usize)
413 }
414
415 fn swap_bytes(self) -> Self {
417 let mut bytes = self.to_be_bytes_vec();
418 bytes.reverse();
419 Self::try_from_be_slice(&bytes).unwrap()
420 }
421
422 #[inline(always)]
423 fn reverse_bits(self) -> Self {
424 <Self>::reverse_bits(self)
425 }
426
427 #[inline(always)]
428 fn from_be(x: Self) -> Self {
429 if cfg!(target_endian = "big") {
430 x
431 } else {
432 x.swap_bytes()
433 }
434 }
435
436 #[inline(always)]
437 fn from_le(x: Self) -> Self {
438 if cfg!(target_endian = "little") {
439 x
440 } else {
441 x.swap_bytes()
442 }
443 }
444
445 #[inline(always)]
446 fn to_be(self) -> Self {
447 if cfg!(target_endian = "big") {
448 self
449 } else {
450 self.swap_bytes()
451 }
452 }
453
454 #[inline(always)]
455 fn to_le(self) -> Self {
456 if cfg!(target_endian = "little") {
457 self
458 } else {
459 self.swap_bytes()
460 }
461 }
462
463 #[inline(always)]
464 fn pow(self, exp: u32) -> Self {
465 self.pow(Self::from(exp))
466 }
467}
468
469#[cfg(test)]
470mod tests {
471 use super::*;
472 use crate::aliases::{U64, U256};
473 use num_traits::bounds::{LowerBounded, UpperBounded};
474
475 macro_rules! assert_impl{
476 ($type:ident, $($trait:tt),*) => {
477 $({
478 fn assert_impl<T: $trait>() {}
479 assert_impl::<$type>();
480 })*
481 }
482 }
483
484 #[test]
485 fn test_assert_impl() {
486 assert_impl!(U256, Bounded, LowerBounded, UpperBounded);
488 assert_impl!(U256, FromPrimitive, NumCast, ToPrimitive);
489 assert_impl!(U256, One, Zero);
490 assert_impl!(U256, PrimInt);
491 assert_impl!(U256, FromBytes, ToBytes);
492 assert_impl!(
493 U256, CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedSub,
494 CheckedShl, CheckedShr, CheckedSub
495 );
496 assert_impl!(U256, CheckedEuclid, Euclid);
497 assert_impl!(U256, Inv);
498 assert_impl!(U256, MulAdd, MulAddAssign);
499 assert_impl!(U256, OverflowingAdd, OverflowingMul, OverflowingSub);
500 assert_impl!(
501 U256,
502 Saturating,
503 SaturatingAdd,
504 SaturatingMul,
505 SaturatingSub
506 );
507 assert_impl!(
508 U256,
509 WrappingAdd,
510 WrappingMul,
511 WrappingNeg,
512 WrappingShl,
513 WrappingShr,
514 WrappingSub
515 );
516 assert_impl!(U256, (Pow<U256>));
517 assert_impl!(U256, Unsigned);
518 }
519
520 #[test]
521 fn test_signed_shl() {
522 let n = U64::from(0x0123456789abcdefu64);
524 let m = U64::from(0x3456789abcdef000u64);
525 assert_eq!(n.signed_shl(12), m);
526 }
527
528 #[test]
529 fn test_signed_shr() {
530 let n = U64::from(0xfedcba9876543210u64);
532 let m = U64::from(0xffffedcba9876543u64);
533 assert_eq!(n.signed_shr(12), m);
534 }
535}