1use crate::{fbig::FBig, round::Round};
4use dashu_base::{Abs, DivEuclid, ParseError, RemEuclid, Sign};
5use dashu_int::{IBig, Word};
6use num_traits_v02 as num_traits;
7
8impl<R: Round, const B: Word> num_traits::Zero for FBig<R, B> {
9 #[inline]
10 fn zero() -> Self {
11 FBig::ZERO
12 }
13 #[inline]
14 fn is_zero(&self) -> bool {
15 self.repr.is_zero()
16 }
17}
18
19impl<R: Round, const B: Word> num_traits::One for FBig<R, B> {
20 #[inline]
21 fn one() -> Self {
22 FBig::ONE
23 }
24 #[inline]
25 fn is_one(&self) -> bool {
26 self.repr.is_one()
27 }
28}
29
30macro_rules! impl_from_primitive_int {
31 ($t:ty, $method:ident) => {
32 #[inline]
33 fn $method(n: $t) -> Option<Self> {
34 Some(FBig::from(n))
35 }
36 };
37}
38
39impl<R: Round, const B: Word> num_traits::FromPrimitive for FBig<R, B> {
40 impl_from_primitive_int!(i8, from_i8);
41 impl_from_primitive_int!(i16, from_i16);
42 impl_from_primitive_int!(i32, from_i32);
43 impl_from_primitive_int!(i64, from_i64);
44 impl_from_primitive_int!(i128, from_i128);
45 impl_from_primitive_int!(isize, from_isize);
46 impl_from_primitive_int!(u8, from_u8);
47 impl_from_primitive_int!(u16, from_u16);
48 impl_from_primitive_int!(u32, from_u32);
49 impl_from_primitive_int!(u64, from_u64);
50 impl_from_primitive_int!(u128, from_u128);
51 impl_from_primitive_int!(usize, from_usize);
52
53 #[inline]
54 fn from_f32(f: f32) -> Option<Self> {
55 match FBig::<R, 2>::try_from(f) {
56 Ok(val) => Some(val.with_base::<B>().value()),
57 Err(_) => None,
58 }
59 }
60 #[inline]
61 fn from_f64(f: f64) -> Option<Self> {
62 match FBig::<R, 2>::try_from(f) {
63 Ok(val) => Some(val.with_base::<B>().value()),
64 Err(_) => None,
65 }
66 }
67}
68
69macro_rules! impl_to_primitive_int {
70 ($t:ty, $method:ident) => {
71 #[inline]
72 fn $method(&self) -> Option<$t> {
73 num_traits::ToPrimitive::$method(&self.to_int().value())
74 }
75 };
76}
77
78impl<R: Round, const B: Word> num_traits::ToPrimitive for FBig<R, B> {
79 impl_to_primitive_int!(i8, to_i8);
80 impl_to_primitive_int!(i16, to_i16);
81 impl_to_primitive_int!(i32, to_i32);
82 impl_to_primitive_int!(i64, to_i64);
83 impl_to_primitive_int!(i128, to_i128);
84 impl_to_primitive_int!(isize, to_isize);
85 impl_to_primitive_int!(u8, to_u8);
86 impl_to_primitive_int!(u16, to_u16);
87 impl_to_primitive_int!(u32, to_u32);
88 impl_to_primitive_int!(u64, to_u64);
89 impl_to_primitive_int!(u128, to_u128);
90 impl_to_primitive_int!(usize, to_usize);
91
92 #[inline]
93 fn to_f32(&self) -> Option<f32> {
94 Some(self.to_f32().value())
95 }
96 #[inline]
97 fn to_f64(&self) -> Option<f64> {
98 Some(self.to_f64().value())
99 }
100}
101
102impl<R: Round, const B: Word> num_traits::Pow<IBig> for FBig<R, B> {
103 type Output = FBig<R, B>;
104
105 fn pow(self, rhs: IBig) -> Self {
106 self.powi(rhs)
107 }
108}
109impl<R: Round, const B: Word> num_traits::Pow<IBig> for &FBig<R, B> {
110 type Output = FBig<R, B>;
111
112 fn pow(self, rhs: IBig) -> FBig<R, B> {
113 self.powi(rhs)
114 }
115}
116impl<R: Round, const B: Word> num_traits::Pow<&FBig<R, B>> for FBig<R, B> {
117 type Output = FBig<R, B>;
118
119 fn pow(self, rhs: &Self) -> Self {
120 self.powf(rhs)
121 }
122}
123impl<R: Round, const B: Word> num_traits::Pow<&FBig<R, B>> for &FBig<R, B> {
124 type Output = FBig<R, B>;
125
126 fn pow(self, rhs: &FBig<R, B>) -> FBig<R, B> {
127 self.powf(rhs)
128 }
129}
130
131impl<R: Round, const B: Word> num_traits::Num for FBig<R, B> {
132 type FromStrRadixErr = ParseError;
133 #[inline]
134 fn from_str_radix(s: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
135 #[allow(clippy::unnecessary_fallible_conversions)]
137 let r: Word = radix.try_into().map_err(|_| ParseError::UnsupportedRadix)?;
138 if r == B {
139 #[allow(deprecated)] Self::from_str_native(s)
141 } else {
142 Err(ParseError::UnsupportedRadix)
143 }
144 }
145}
146
147impl<R: Round, const B: Word> num_traits::Euclid for FBig<R, B> {
148 #[inline]
149 fn div_euclid(&self, v: &Self) -> Self {
150 DivEuclid::div_euclid(self, v).into()
151 }
152 #[inline]
153 fn rem_euclid(&self, v: &Self) -> Self {
154 RemEuclid::rem_euclid(self, v)
155 }
156}
157
158impl<R: Round, const B: Word> num_traits::Signed for FBig<R, B> {
159 #[inline]
160 fn abs(&self) -> Self {
161 Abs::abs(self.clone())
162 }
163
164 #[inline]
165 fn abs_sub(&self, other: &Self) -> Self {
166 Abs::abs(self - other)
167 }
168
169 #[inline]
170 fn signum(&self) -> Self {
171 FBig::signum(self)
172 }
173
174 #[inline]
175 fn is_positive(&self) -> bool {
176 !self.repr.is_zero() && self.repr.sign() == Sign::Positive
177 }
178
179 #[inline]
180 fn is_negative(&self) -> bool {
181 self.repr.sign() == Sign::Negative
182 }
183}
184
185#[cfg(test)]
186mod tests {
187 use super::num_traits::{FromPrimitive, One, Zero};
188 use crate::DBig;
189
190 #[test]
191 fn test_01() {
192 assert_eq!(DBig::from(0), DBig::zero());
193 assert_eq!(DBig::from(1), DBig::one());
194
195 assert!(DBig::from(0).is_zero());
196 assert!(!DBig::from(0).is_one());
197 assert!(!DBig::from(1).is_zero());
198 assert!(DBig::from(1).is_one());
199 }
200
201 #[test]
202 fn test_from() {
203 assert_eq!(DBig::from_usize(1), Some(DBig::one()));
204 assert_eq!(DBig::from_isize(-1), Some(-DBig::one()));
205 }
206}