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 $(impl_const! {
26 impl<const N: usize> const 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(from: $BUint<N>) -> Self {
49 crate::buint::as_float::cast_float_from_uint(from)
50 }
89 }
90 };
91}
92
93macro_rules! as_buint {
94 ($BUint: ident, $Digit: ident; $($ty: ty), *) => {
95 $(crate::nightly::const_impl! {
96 impl<const N: usize> const CastFrom<$ty> for $BUint<N> {
97 #[must_use = doc::must_use_op!()]
98 #[inline]
99 fn cast_from(mut from: $ty) -> Self {
100 #[allow(unused_comparisons)]
101 let mut out = if from < 0 {
102 Self::MAX
103 } else {
104 Self::MIN
105 };
106 let mut i = 0;
107 while from != 0 && i < N {
108 let masked = from as $Digit & $Digit::MAX;
109 out.digits[i] = masked;
110 if <$ty>::BITS <= $Digit::BITS {
111 from = 0;
112 } else {
113 from = from.wrapping_shr($Digit::BITS);
114 }
115 i += 1;
116 }
117 out
118 }
119 }
120 })*
121 };
122}
123
124use crate::cast::CastFrom;
125use crate::doc;
126use crate::nightly::impl_const;
127macro_rules! cast {
130 ($BUint: ident, $BInt: ident, $Digit: ident) => {
131 impl<const N: usize> $BUint<N> {
132 crate::nightly::const_fn! {
133 #[inline]
134 const fn cast_up<const M: usize>(self, digit: $Digit) -> $BUint<M> {
135 let mut digits = [digit; M];
136 let mut i = M - N;
137 while i < M {
138 let index = i - (M - N);
139 digits[index] = self.digits[index];
140 i += 1;
141 }
142 $BUint::from_digits(digits)
143 }
144 }
145 crate::nightly::const_fn! {
146 #[inline]
147 const fn cast_down<const M: usize>(self) -> $BUint<M> {
148 let mut out = $BUint::ZERO;
149 let mut i = 0;
150 while i < M {
151 out.digits[i] = self.digits[i];
152 i += 1;
153 }
154 out
155 }
156 }
157 }
158
159 buint_as_int!($BUint, $Digit; u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
160
161 buint_as_float!($BUint, f32);
162 buint_as_float!($BUint, f64);
163
164 as_buint!($BUint, $Digit; u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
165
166 impl_const! {
167 impl<const N: usize> const CastFrom<bool> for $BUint<N> {
168 #[must_use = doc::must_use_op!()]
169 #[inline]
170 fn cast_from(from: bool) -> Self {
171 if from {
172 Self::ONE
173 } else {
174 Self::ZERO
175 }
176 }
177 }
178 }
179
180 impl_const! {
181 impl<const N: usize> const CastFrom<char> for $BUint<N> {
182 #[must_use = doc::must_use_op!()]
183 #[inline]
184 fn cast_from(from: char) -> Self {
185 Self::cast_from(from as u32)
186 }
187 }
188 }
189
190 impl_const! {
191 impl<const N: usize, const M: usize> const CastFrom<$BUint<M>> for $BUint<N> {
192 #[must_use = doc::must_use_op!()]
193 #[inline]
194 fn cast_from(from: $BUint<M>) -> Self {
195 if M < N {
196 from.cast_up(0)
197 } else {
198 from.cast_down()
199 }
200 }
201 }
202 }
203
204 impl_const! {
205 impl<const N: usize, const M: usize> const CastFrom<$BInt<M>> for $BUint<N> {
206 #[must_use = doc::must_use_op!()]
207 #[inline]
208 fn cast_from(from: $BInt<M>) -> Self {
209 if M < N {
210 let padding_digit = if from.is_negative() {
211 $Digit::MAX
212 } else {
213 0
214 };
215 from.to_bits().cast_up(padding_digit)
216 } else {
217 from.to_bits().cast_down()
218 }
219 }
220 }
221 }
222
223 impl<const N: usize> CastFrom<f32> for $BUint<N> {
224 #[must_use = doc::must_use_op!()]
225 #[inline]
226 fn cast_from(from: f32) -> Self {
227 crate::buint::float_as::uint_cast_from_float(from)
228 }
229 }
230
231 impl<const N: usize> CastFrom<f64> for $BUint<N> {
232 #[must_use = doc::must_use_op!()]
233 #[inline]
234 fn cast_from(from: f64) -> Self {
235 crate::buint::float_as::uint_cast_from_float(from)
236 }
237 }
238
239 };
240}
241
242crate::macro_impl!(cast);
243
244macro_rules! buint_as_different_digit_bigint {
245 ($BUint: ident, $BInt: ident, $Digit: ident; $(($OtherBUint: ident, $OtherDigit: ident)), *) => {
246 $(
247 crate::nightly::const_impl! {
248 impl<const N: usize, const M: usize> const crate::cast::CastFrom<$OtherBUint<M>> for $BUint<N> {
249 #[must_use = doc::must_use_op!()]
250 #[inline]
251 fn cast_from(from: $OtherBUint<M>) -> Self {
252 let mut out = Self::ZERO;
253 if $Digit::BITS < $OtherDigit::BITS {
254 const DIVIDE_COUNT: usize = ($OtherDigit::BITS / $Digit::BITS) as usize;
255 let stop_index: usize = if <$OtherBUint<M>>::BITS > <$BUint<N>>::BITS {
256 N
257 } else {
258 M * DIVIDE_COUNT
259 };
260 let mut i = 0;
261 while i < stop_index {
262 let wider_digit = from.digits[i / DIVIDE_COUNT];
263 let mini_shift = i % DIVIDE_COUNT;
264 let digit = (wider_digit >> (mini_shift << digit::$Digit::BIT_SHIFT)) as $Digit;
265 out.digits[i] = digit;
266 i += 1;
267 }
268 } else {
269 const DIVIDE_COUNT: usize = ($Digit::BITS / $OtherDigit::BITS) as usize;
270 let stop_index: usize = if <$OtherBUint<M>>::BITS > <$BUint<N>>::BITS {
271 N * DIVIDE_COUNT
272 } else {
273 M
274 };
275 let mut current_digit: $Digit = 0;
276 let mut i = 0;
277 while i < stop_index {
278 let mini_shift = i % DIVIDE_COUNT;
279 current_digit |= (from.digits[i] as $Digit) << (mini_shift << digit::$OtherDigit::BIT_SHIFT);
280 if mini_shift == DIVIDE_COUNT - 1 || i == stop_index - 1 {
281 out.digits[i / DIVIDE_COUNT] = current_digit;
282 current_digit = 0;
283 }
284 i += 1;
285 }
286 }
287 out
288 }
289 }
290 }
291
292 crate::nightly::const_impl! {
293 impl<const N: usize, const M: usize> const crate::cast::CastFrom<$OtherBUint<M>> for $BInt<N> {
294 #[must_use = doc::must_use_op!()]
295 #[inline]
296 fn cast_from(from: $OtherBUint<M>) -> Self {
297 Self::from_bits($BUint::cast_from(from))
298 }
299 }
300 }
301 )*
302 }
303}
304
305pub(crate) use buint_as_different_digit_bigint;