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