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