1macro_rules! bint_as {
2 ($BInt: ident, $Digit: ident; $($int: ty), *) => {
3 $(
4 impl<const N: usize> CastFrom<$BInt<N>> for $int {
5 #[inline]
6 fn cast_from(from: $BInt<N>) -> Self {
7 if from.is_negative() {
8 let digits = from.bits.digits;
9 let mut out = !0;
10 let mut i = 0;
11 while i << digit::$Digit::BIT_SHIFT < <$int>::BITS as usize && i < N {
12 out &= !((!digits[i]) as $int << (i << digit::$Digit::BIT_SHIFT));
13 i += 1;
14 }
15 out
16 } else {
17 <$int>::cast_from(from.bits)
18 }
19 }
20 }
21 )*
22 };
23}
24
25macro_rules! as_bint {
26 ($BInt: ident, $BUint: ident; $($ty: ty), *) => {
27 $(
28 impl<const N: usize> CastFrom<$ty> for $BInt<N> {
29 #[inline]
30 fn cast_from(from: $ty) -> Self {
31 Self::from_bits($BUint::cast_from(from))
32 }
33 }
34 )*
35 }
36}
37
38macro_rules! bint_cast_from_float {
39 ($f: ty, $BUint: ident <$N: ident>) => {
40 #[inline]
41 fn cast_from(from: $f) -> Self {
42 if from.is_sign_negative() {
43 let u = $BUint::<$N>::cast_from(-from);
44 if u >= Self::MIN.to_bits() {
45 Self::MIN
46 } else {
47 -Self::from_bits(u)
48 }
49 } else {
50 let u = $BUint::<$N>::cast_from(from);
51 let i = Self::from_bits(u);
52 if i.is_negative() {
53 Self::MAX
54 } else {
55 i
56 }
57 }
58 }
59 };
60}
61
62pub(crate) use bint_cast_from_float;
63
64use crate::cast::CastFrom;
65use crate::digit;
66
67macro_rules! cast {
68 ($BUint: ident, $BInt: ident, $Digit: ident) => {
69 bint_as!($BInt, $Digit; u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
70
71 impl<const N: usize> CastFrom<$BInt<N>> for f32 {
72 #[inline]
73 fn cast_from(from: $BInt<N>) -> Self {
74 let f = f32::cast_from(from.unsigned_abs());
75 if from.is_negative() {
76 -f
77 } else {
78 f
79 }
80 }
81 }
82
83 impl<const N: usize> CastFrom<$BInt<N>> for f64 {
84 #[inline]
85 fn cast_from(from: $BInt<N>) -> Self {
86 let f = f64::cast_from(from.unsigned_abs());
87 if from.is_negative() {
88 -f
89 } else {
90 f
91 }
92 }
93 }
94
95 as_bint!($BInt, $BUint; u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, bool, char);
96
97 impl<const N: usize, const M: usize> CastFrom<$BUint<M>> for $BInt<N> {
98 #[inline]
99 fn cast_from(from: $BUint<M>) -> Self {
100 Self::from_bits($BUint::cast_from(from))
101 }
102 }
103
104 impl<const N: usize, const M: usize> CastFrom<$BInt<M>> for $BInt<N> {
105 #[inline]
106 fn cast_from(from: $BInt<M>) -> Self {
107 Self::from_bits($BUint::cast_from(from))
108 }
109 }
110
111 impl<const N: usize> CastFrom<f32> for $BInt<N> {
112 crate::bint::cast::bint_cast_from_float!(f32, $BUint<N>);
113 }
114
115 impl<const N: usize> CastFrom<f64> for $BInt<N> {
116 crate::bint::cast::bint_cast_from_float!(f64, $BUint<N>);
117 }
118 };
119}
120
121#[cfg(test)]
122crate::test::all_digit_tests! {
123 use crate::test::types::itest;
124
125 crate::int::cast::tests!(itest);
126}
127
128crate::macro_impl!(cast);
129
130macro_rules! bint_as_different_digit_bigint {
131 ($BUint: ident, $BInt: ident, $Digit: ident; $(($OtherBInt: ident, $OtherDigit: ident)), *) => {
132 $(
133 impl<const N: usize, const M: usize> crate::cast::CastFrom<$OtherBInt<M>> for $BUint<N> {
134 #[must_use = doc::must_use_op!()]
135 #[inline]
136 fn cast_from(from: $OtherBInt<M>) -> Self {
137 if !from.is_negative() || M * $OtherDigit::BITS as usize >= N * $Digit::BITS as usize { Self::cast_from(from.to_bits())
139 } else {
140 let mut out = Self::MAX;
141 if $Digit::BITS < $OtherDigit::BITS {
142 const DIVIDE_COUNT: usize = ($OtherDigit::BITS / $Digit::BITS) as usize;
143 let stop_index: usize = if <$OtherBInt<M>>::BITS > <$BUint<N>>::BITS {
144 N
145 } else {
146 M * DIVIDE_COUNT
147 };
148 let mut i = 0;
149 while i < stop_index {
150 let wider_digit = from.bits.digits[i / DIVIDE_COUNT];
151 let mini_shift = i % DIVIDE_COUNT;
152 let digit = (wider_digit >> (mini_shift << digit::$Digit::BIT_SHIFT)) as $Digit;
153 out.digits[i] = digit;
154 i += 1;
155 }
156 } else {
157 const DIVIDE_COUNT: usize = ($Digit::BITS / $OtherDigit::BITS) as usize;
158 let stop_index: usize = if <$OtherBInt<M>>::BITS > <$BUint<N>>::BITS {
159 N * DIVIDE_COUNT
160 } else {
161 M
162 };
163 let mut current_digit: $Digit = $Digit::MAX;
164 let mut i = 0;
165 while i < stop_index {
166 let mini_shift = i % DIVIDE_COUNT;
167 current_digit &= !((!from.bits.digits[i] as $Digit) << (mini_shift << digit::$OtherDigit::BIT_SHIFT));
168 if mini_shift == DIVIDE_COUNT - 1 || i == stop_index - 1 {
169 out.digits[i / DIVIDE_COUNT] = current_digit;
170 current_digit = $Digit::MAX;
171 }
172 i += 1;
173 }
174 }
175 out
176 }
177 }
178 }
179
180 impl<const N: usize, const M: usize> crate::cast::CastFrom<$OtherBInt<M>> for $BInt<N> {
181 #[must_use = doc::must_use_op!()]
182 #[inline]
183 fn cast_from(from: $OtherBInt<M>) -> Self {
184 Self::from_bits($BUint::<N>::cast_from(from))
185 }
186 }
187 )*
188 };
189}
190
191pub(crate) use bint_as_different_digit_bigint;