1macro_rules! decode_float {
2 ($name: ident, $f: ty, $u: ty) => {
3 pub fn $name(f: $f) -> ($u, i16) {
4 const BITS: u32 = core::mem::size_of::<$f>() as u32 * 8;
5 const MANT_MASK: $u = <$u>::MAX >> (BITS - (<$f>::MANTISSA_DIGITS - 1));
6 const EXP_MASK: $u = <$u>::MAX >> 1;
7 const BIAS: i16 = <$f>::MAX_EXP as i16 - 1;
8
9 let bits = f.to_bits();
10 let exp = ((bits & EXP_MASK) >> (<$f>::MANTISSA_DIGITS - 1)) as i16;
11 let mut mant = bits & MANT_MASK;
12 if exp != 0 {
13 mant |= (1 << (<$f>::MANTISSA_DIGITS - 1));
14 }
15 (mant, exp - (BIAS + <$f>::MANTISSA_DIGITS as i16 - 1))
16 }
17 };
18}
19
20decode_float!(decode_f32, f32, u32);
21decode_float!(decode_f64, f64, u64);
22
23macro_rules! buint_as_int {
24 ($BUint: ident, $Digit: ident; $($int: ty), *) => {
25 $(
26 impl<const N: usize> CastFrom<$BUint<N>> for $int {
27 #[must_use = doc::must_use_op!()]
28 #[inline]
29 fn cast_from(from: $BUint<N>) -> Self {
30 let mut out = 0;
31 let mut i = 0;
32 while i << crate::digit::$Digit::BIT_SHIFT < <$int>::BITS as usize && i < N {
33 out |= from.digits[i] as $int << (i << crate::digit::$Digit::BIT_SHIFT);
34 i += 1;
35 }
36 out
37 }
38 }
39 )*
40 };
41}
42
43macro_rules! buint_as_float {
44 ($BUint: ident, $f: ty) => {
45 impl<const N: usize> CastFrom<$BUint<N>> for $f {
46 #[must_use = doc::must_use_op!()]
47 #[inline]
48 fn cast_from(value: $BUint<N>) -> Self {
49 crate::cast::float::cast_float_from_uint(value)
50 }
51 }
52 };
53}
54
55macro_rules! as_buint {
56 ($BUint: ident, $Digit: ident; $($ty: ty), *) => {
57 $(
58 impl<const N: usize> CastFrom<$ty> for $BUint<N> {
59 #[must_use = doc::must_use_op!()]
60 #[inline]
61 fn cast_from(mut from: $ty) -> Self {
62 #[allow(unused_comparisons)]
63 let mut out = if from < 0 {
64 Self::MAX
65 } else {
66 Self::MIN
67 };
68 let mut i = 0;
69 while from != 0 && i < N {
70 let masked = from as $Digit & $Digit::MAX;
71 out.digits[i] = masked;
72 if <$ty>::BITS <= $Digit::BITS {
73 from = 0;
74 } else {
75 from = from.wrapping_shr($Digit::BITS);
76 }
77 i += 1;
78 }
79 out
80 }
81 }
82 )*
83 };
84}
85
86use crate::cast::CastFrom;
87use crate::doc;
88use crate::ExpType;
89#[allow(unused_imports)]
90use crate::cast::float::{FloatMantissa, CastUintFromFloatHelper, CastFloatFromUintHelper};
91
92macro_rules! cast {
93 ($BUint: ident, $BInt: ident, $Digit: ident) => {
94 impl<const N: usize> CastUintFromFloatHelper for $BUint<N> {
118 const MAX: Self = Self::MAX;
119 const MIN: Self = Self::MIN;
120 }
121
122 impl<const N: usize> CastFloatFromUintHelper for $BUint<N> {
123 fn trailing_zeros(self) -> ExpType {
124 Self::trailing_zeros(self)
125 }
126 }
127
128 impl<const N: usize> $BUint<N> {
129 #[inline]
130 const fn cast_up<const M: usize>(self, digit: $Digit) -> $BUint<M> {
131 let mut digits = [digit; M];
132 let mut i = M - N;
133 while i < M {
134 let index = i - (M - N);
135 digits[index] = self.digits[index];
136 i += 1;
137 }
138 $BUint::from_digits(digits)
139 }
140
141 #[inline]
142 const fn cast_down<const M: usize>(self) -> $BUint<M> {
143 let mut out = $BUint::ZERO;
144 let mut i = 0;
145 while i < M {
146 out.digits[i] = self.digits[i];
147 i += 1;
148 }
149 out
150 }
151 }
152
153 buint_as_int!($BUint, $Digit; u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
154
155 buint_as_float!($BUint, f32);
156 buint_as_float!($BUint, f64);
157
158 as_buint!($BUint, $Digit; u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
159
160 impl<const N: usize> CastFrom<bool> for $BUint<N> {
161 #[must_use = doc::must_use_op!()]
162 #[inline]
163 fn cast_from(from: bool) -> Self {
164 if from {
165 Self::ONE
166 } else {
167 Self::ZERO
168 }
169 }
170 }
171
172 impl<const N: usize> CastFrom<char> for $BUint<N> {
173 #[must_use = doc::must_use_op!()]
174 #[inline]
175 fn cast_from(from: char) -> Self {
176 Self::cast_from(from as u32)
177 }
178 }
179
180 impl<const N: usize, const M: usize> CastFrom<$BUint<M>> for $BUint<N> {
181 #[must_use = doc::must_use_op!()]
182 #[inline]
183 fn cast_from(from: $BUint<M>) -> Self {
184 if M < N {
185 from.cast_up(0)
186 } else {
187 from.cast_down()
188 }
189 }
190 }
191
192 impl<const N: usize, const M: usize> CastFrom<$BInt<M>> for $BUint<N> {
193 #[must_use = doc::must_use_op!()]
194 #[inline]
195 fn cast_from(from: $BInt<M>) -> Self {
196 if M < N {
197 let padding_digit = if from.is_negative() {
198 $Digit::MAX
199 } else {
200 0
201 };
202 from.to_bits().cast_up(padding_digit)
203 } else {
204 from.to_bits().cast_down()
205 }
206 }
207 }
208
209 impl<const N: usize> CastFrom<f32> for $BUint<N> {
210 #[must_use = doc::must_use_op!()]
211 #[inline]
212 fn cast_from(value: f32) -> Self {
213 crate::cast::float::cast_uint_from_float(value)
214 }
215 }
216
217 impl<const N: usize> CastFrom<f64> for $BUint<N> {
218 #[must_use = doc::must_use_op!()]
219 #[inline]
220 fn cast_from(value: f64) -> Self {
221 crate::cast::float::cast_uint_from_float(value)
222 }
223 }
224 };
225}
226
227#[cfg(test)]
228crate::test::all_digit_tests! {
229 crate::int::cast::tests!(utest);
230}
231
232crate::macro_impl!(cast);
233
234macro_rules! buint_as_different_digit_bigint {
235 ($BUint: ident, $BInt: ident, $Digit: ident; $(($OtherBUint: ident, $OtherDigit: ident)), *) => {
236 $(
237 impl<const N: usize, const M: usize> crate::cast::CastFrom<$OtherBUint<M>> for $BUint<N> {
238 #[must_use = doc::must_use_op!()]
239 #[inline]
240 fn cast_from(from: $OtherBUint<M>) -> Self {
241 let mut out = Self::ZERO;
242 if $Digit::BITS < $OtherDigit::BITS {
243 const DIVIDE_COUNT: usize = ($OtherDigit::BITS / $Digit::BITS) as usize;
244 let stop_index: usize = if <$OtherBUint<M>>::BITS > <$BUint<N>>::BITS {
245 N
246 } else {
247 M * DIVIDE_COUNT
248 };
249 let mut i = 0;
250 while i < stop_index {
251 let wider_digit = from.digits[i / DIVIDE_COUNT];
252 let mini_shift = i % DIVIDE_COUNT;
253 let digit = (wider_digit >> (mini_shift << digit::$Digit::BIT_SHIFT)) as $Digit;
254 out.digits[i] = digit;
255 i += 1;
256 }
257 } else {
258 const DIVIDE_COUNT: usize = ($Digit::BITS / $OtherDigit::BITS) as usize;
259 let stop_index: usize = if <$OtherBUint<M>>::BITS > <$BUint<N>>::BITS {
260 N * DIVIDE_COUNT
261 } else {
262 M
263 };
264 let mut current_digit: $Digit = 0;
265 let mut i = 0;
266 while i < stop_index {
267 let mini_shift = i % DIVIDE_COUNT;
268 current_digit |= (from.digits[i] as $Digit) << (mini_shift << digit::$OtherDigit::BIT_SHIFT);
269 if mini_shift == DIVIDE_COUNT - 1 || i == stop_index - 1 {
270 out.digits[i / DIVIDE_COUNT] = current_digit;
271 current_digit = 0;
272 }
273 i += 1;
274 }
275 }
276 out
277 }
278 }
279
280 impl<const N: usize, const M: usize> crate::cast::CastFrom<$OtherBUint<M>> for $BInt<N> {
281 #[must_use = doc::must_use_op!()]
282 #[inline]
283 fn cast_from(from: $OtherBUint<M>) -> Self {
284 Self::from_bits($BUint::cast_from(from))
285 }
286 }
287 )*
288 }
289}
290
291pub(crate) use buint_as_different_digit_bigint;