|
18 | 18 | use crate::arith::derive_arith; |
19 | 19 | use crate::bigint::div::div_rem; |
20 | 20 | use num_bigint::BigInt; |
21 | | -use num_traits::{FromPrimitive, ToPrimitive, cast::AsPrimitive}; |
| 21 | +use num_traits::{ |
| 22 | + Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedSub, FromPrimitive, |
| 23 | + Num, One, Signed, ToPrimitive, WrappingAdd, WrappingMul, WrappingNeg, WrappingSub, Zero, |
| 24 | + cast::AsPrimitive, |
| 25 | +}; |
22 | 26 | use std::cmp::Ordering; |
23 | 27 | use std::num::ParseIntError; |
24 | 28 | use std::ops::{BitAnd, BitOr, BitXor, Neg, Shl, Shr}; |
@@ -869,6 +873,137 @@ impl ToPrimitive for i256 { |
869 | 873 | } |
870 | 874 | } |
871 | 875 |
|
| 876 | +// num_traits checked implementations |
| 877 | + |
| 878 | +impl CheckedNeg for i256 { |
| 879 | + fn checked_neg(&self) -> Option<Self> { |
| 880 | + (*self).checked_neg() |
| 881 | + } |
| 882 | +} |
| 883 | + |
| 884 | +impl CheckedAdd for i256 { |
| 885 | + fn checked_add(&self, v: &i256) -> Option<Self> { |
| 886 | + (*self).checked_add(*v) |
| 887 | + } |
| 888 | +} |
| 889 | + |
| 890 | +impl CheckedSub for i256 { |
| 891 | + fn checked_sub(&self, v: &i256) -> Option<Self> { |
| 892 | + (*self).checked_sub(*v) |
| 893 | + } |
| 894 | +} |
| 895 | + |
| 896 | +impl CheckedDiv for i256 { |
| 897 | + fn checked_div(&self, v: &i256) -> Option<Self> { |
| 898 | + (*self).checked_div(*v) |
| 899 | + } |
| 900 | +} |
| 901 | + |
| 902 | +impl CheckedMul for i256 { |
| 903 | + fn checked_mul(&self, v: &i256) -> Option<Self> { |
| 904 | + (*self).checked_mul(*v) |
| 905 | + } |
| 906 | +} |
| 907 | + |
| 908 | +impl CheckedRem for i256 { |
| 909 | + fn checked_rem(&self, v: &i256) -> Option<Self> { |
| 910 | + (*self).checked_rem(*v) |
| 911 | + } |
| 912 | +} |
| 913 | + |
| 914 | +impl WrappingAdd for i256 { |
| 915 | + fn wrapping_add(&self, v: &Self) -> Self { |
| 916 | + (*self).wrapping_add(*v) |
| 917 | + } |
| 918 | +} |
| 919 | + |
| 920 | +impl WrappingSub for i256 { |
| 921 | + fn wrapping_sub(&self, v: &Self) -> Self { |
| 922 | + (*self).wrapping_sub(*v) |
| 923 | + } |
| 924 | +} |
| 925 | + |
| 926 | +impl WrappingMul for i256 { |
| 927 | + fn wrapping_mul(&self, v: &Self) -> Self { |
| 928 | + (*self).wrapping_mul(*v) |
| 929 | + } |
| 930 | +} |
| 931 | + |
| 932 | +impl WrappingNeg for i256 { |
| 933 | + fn wrapping_neg(&self) -> Self { |
| 934 | + (*self).wrapping_neg() |
| 935 | + } |
| 936 | +} |
| 937 | + |
| 938 | +impl Zero for i256 { |
| 939 | + fn zero() -> Self { |
| 940 | + i256::ZERO |
| 941 | + } |
| 942 | + |
| 943 | + fn is_zero(&self) -> bool { |
| 944 | + *self == i256::ZERO |
| 945 | + } |
| 946 | +} |
| 947 | + |
| 948 | +impl One for i256 { |
| 949 | + fn one() -> Self { |
| 950 | + i256::ONE |
| 951 | + } |
| 952 | + |
| 953 | + fn is_one(&self) -> bool { |
| 954 | + *self == i256::ONE |
| 955 | + } |
| 956 | +} |
| 957 | + |
| 958 | +impl Num for i256 { |
| 959 | + type FromStrRadixErr = ParseI256Error; |
| 960 | + |
| 961 | + fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> { |
| 962 | + if radix == 10 { |
| 963 | + str.parse() |
| 964 | + } else { |
| 965 | + // Parsing from non-10 baseseeÎ is not supported |
| 966 | + Err(ParseI256Error {}) |
| 967 | + } |
| 968 | + } |
| 969 | +} |
| 970 | + |
| 971 | +impl Signed for i256 { |
| 972 | + fn abs(&self) -> Self { |
| 973 | + self.wrapping_abs() |
| 974 | + } |
| 975 | + |
| 976 | + fn abs_sub(&self, other: &Self) -> Self { |
| 977 | + if self > other { |
| 978 | + self.wrapping_sub(other) |
| 979 | + } else { |
| 980 | + i256::ZERO |
| 981 | + } |
| 982 | + } |
| 983 | + |
| 984 | + fn signum(&self) -> Self { |
| 985 | + (*self).signum() |
| 986 | + } |
| 987 | + |
| 988 | + fn is_positive(&self) -> bool { |
| 989 | + (*self).is_positive() |
| 990 | + } |
| 991 | + |
| 992 | + fn is_negative(&self) -> bool { |
| 993 | + (*self).is_negative() |
| 994 | + } |
| 995 | +} |
| 996 | + |
| 997 | +impl Bounded for i256 { |
| 998 | + fn min_value() -> Self { |
| 999 | + i256::MIN |
| 1000 | + } |
| 1001 | + |
| 1002 | + fn max_value() -> Self { |
| 1003 | + i256::MAX |
| 1004 | + } |
| 1005 | +} |
| 1006 | + |
872 | 1007 | #[cfg(all(test, not(miri)))] // llvm.x86.subborrow.64 not supported by MIRI |
873 | 1008 | mod tests { |
874 | 1009 | use super::*; |
@@ -1337,6 +1472,83 @@ mod tests { |
1337 | 1472 | assert!(out.is_finite() && out.is_sign_negative()); |
1338 | 1473 | } |
1339 | 1474 |
|
| 1475 | + #[test] |
| 1476 | + fn test_num_traits() { |
| 1477 | + let value = i256::from_i128(-5); |
| 1478 | + assert_eq!( |
| 1479 | + <i256 as CheckedNeg>::checked_neg(&value), |
| 1480 | + Some(i256::from(5)) |
| 1481 | + ); |
| 1482 | + |
| 1483 | + assert_eq!( |
| 1484 | + <i256 as CheckedAdd>::checked_add(&value, &value), |
| 1485 | + Some(i256::from(-10)) |
| 1486 | + ); |
| 1487 | + |
| 1488 | + assert_eq!( |
| 1489 | + <i256 as CheckedSub>::checked_sub(&value, &value), |
| 1490 | + Some(i256::from(0)) |
| 1491 | + ); |
| 1492 | + |
| 1493 | + assert_eq!( |
| 1494 | + <i256 as CheckedMul>::checked_mul(&value, &value), |
| 1495 | + Some(i256::from(25)) |
| 1496 | + ); |
| 1497 | + |
| 1498 | + assert_eq!( |
| 1499 | + <i256 as CheckedDiv>::checked_div(&value, &value), |
| 1500 | + Some(i256::from(1)) |
| 1501 | + ); |
| 1502 | + |
| 1503 | + assert_eq!( |
| 1504 | + <i256 as CheckedRem>::checked_rem(&value, &value), |
| 1505 | + Some(i256::from(0)) |
| 1506 | + ); |
| 1507 | + |
| 1508 | + assert_eq!( |
| 1509 | + <i256 as WrappingAdd>::wrapping_add(&value, &value), |
| 1510 | + i256::from(-10) |
| 1511 | + ); |
| 1512 | + |
| 1513 | + assert_eq!( |
| 1514 | + <i256 as WrappingSub>::wrapping_sub(&value, &value), |
| 1515 | + i256::from(0) |
| 1516 | + ); |
| 1517 | + |
| 1518 | + assert_eq!( |
| 1519 | + <i256 as WrappingMul>::wrapping_mul(&value, &value), |
| 1520 | + i256::from(25) |
| 1521 | + ); |
| 1522 | + |
| 1523 | + assert_eq!(<i256 as WrappingNeg>::wrapping_neg(&value), i256::from(5)); |
| 1524 | + |
| 1525 | + // A single check for wrapping behavior, rely on trait implementation for others |
| 1526 | + let result = <i256 as WrappingAdd>::wrapping_add(&i256::MAX, &i256::ONE); |
| 1527 | + assert_eq!(result, i256::MIN); |
| 1528 | + |
| 1529 | + assert_eq!(<i256 as Signed>::abs(&value), i256::from(5)); |
| 1530 | + |
| 1531 | + assert_eq!(<i256 as One>::one(), i256::from(1)); |
| 1532 | + assert_eq!(<i256 as Zero>::zero(), i256::from(0)); |
| 1533 | + |
| 1534 | + assert_eq!(<i256 as Bounded>::min_value(), i256::MIN); |
| 1535 | + assert_eq!(<i256 as Bounded>::max_value(), i256::MAX); |
| 1536 | + } |
| 1537 | + |
| 1538 | + #[test] |
| 1539 | + fn test_numtraits_from_str_radix() { |
| 1540 | + assert_eq!( |
| 1541 | + i256::from_str_radix("123456789", 10).expect("parsed"), |
| 1542 | + i256::from(123456789) |
| 1543 | + ); |
| 1544 | + assert_eq!( |
| 1545 | + i256::from_str_radix("0", 10).expect("parsed"), |
| 1546 | + i256::from(0) |
| 1547 | + ); |
| 1548 | + assert!(i256::from_str_radix("abc", 10).is_err()); |
| 1549 | + assert!(i256::from_str_radix("0", 16).is_err()); |
| 1550 | + } |
| 1551 | + |
1340 | 1552 | #[test] |
1341 | 1553 | fn test_leading_zeros() { |
1342 | 1554 | // Without high part |
|
0 commit comments