1use crate::{
17 types::extra::{LeEqU128, LeEqU16, LeEqU32, LeEqU64, LeEqU8},
18 FixedI128, FixedI16, FixedI32, FixedI64, FixedI8, FixedU128, FixedU16, FixedU32, FixedU64,
19 FixedU8,
20};
21use az::{Cast, CheckedCast, OverflowingCast, SaturatingCast, StaticCast, WrappingCast};
22use core::mem;
23#[cfg(feature = "f16")]
24use half::{bf16, f16};
25
26macro_rules! run_time {
27 ($Src:ident($LeEqUSrc:ident); $Dst:ident($LeEqUDst:ident)) => {
28 impl<FracSrc: $LeEqUSrc, FracDst: $LeEqUDst> Cast<$Dst<FracDst>> for $Src<FracSrc> {
29 #[inline]
30 fn cast(self) -> $Dst<FracDst> {
31 self.to_num()
32 }
33 }
34
35 impl<FracSrc: $LeEqUSrc, FracDst: $LeEqUDst> CheckedCast<$Dst<FracDst>> for $Src<FracSrc> {
36 #[inline]
37 fn checked_cast(self) -> Option<$Dst<FracDst>> {
38 self.checked_to_num()
39 }
40 }
41
42 impl<FracSrc: $LeEqUSrc, FracDst: $LeEqUDst> SaturatingCast<$Dst<FracDst>>
43 for $Src<FracSrc>
44 {
45 #[inline]
46 fn saturating_cast(self) -> $Dst<FracDst> {
47 self.saturating_to_num()
48 }
49 }
50
51 impl<FracSrc: $LeEqUSrc, FracDst: $LeEqUDst> WrappingCast<$Dst<FracDst>> for $Src<FracSrc> {
52 #[inline]
53 fn wrapping_cast(self) -> $Dst<FracDst> {
54 self.wrapping_to_num()
55 }
56 }
57
58 impl<FracSrc: $LeEqUSrc, FracDst: $LeEqUDst> OverflowingCast<$Dst<FracDst>>
59 for $Src<FracSrc>
60 {
61 #[inline]
62 fn overflowing_cast(self) -> ($Dst<FracDst>, bool) {
63 self.overflowing_to_num()
64 }
65 }
66 };
67
68 ($Fixed:ident($LeEqU:ident); $Dst:ident) => {
69 impl<Frac: $LeEqU> Cast<$Dst> for $Fixed<Frac> {
70 #[inline]
71 fn cast(self) -> $Dst {
72 self.to_num()
73 }
74 }
75
76 impl<Frac: $LeEqU> CheckedCast<$Dst> for $Fixed<Frac> {
77 #[inline]
78 fn checked_cast(self) -> Option<$Dst> {
79 self.checked_to_num()
80 }
81 }
82
83 impl<Frac: $LeEqU> SaturatingCast<$Dst> for $Fixed<Frac> {
84 #[inline]
85 fn saturating_cast(self) -> $Dst {
86 self.saturating_to_num()
87 }
88 }
89
90 impl<Frac: $LeEqU> WrappingCast<$Dst> for $Fixed<Frac> {
91 #[inline]
92 fn wrapping_cast(self) -> $Dst {
93 self.wrapping_to_num()
94 }
95 }
96
97 impl<Frac: $LeEqU> OverflowingCast<$Dst> for $Fixed<Frac> {
98 #[inline]
99 fn overflowing_cast(self) -> ($Dst, bool) {
100 self.overflowing_to_num()
101 }
102 }
103 };
104
105 ($Src:ident; $Fixed:ident($LeEqU:ident)) => {
106 impl<Frac: $LeEqU> Cast<$Fixed<Frac>> for $Src {
107 #[inline]
108 fn cast(self) -> $Fixed<Frac> {
109 <$Fixed<Frac>>::from_num(self)
110 }
111 }
112
113 impl<Frac: $LeEqU> CheckedCast<$Fixed<Frac>> for $Src {
114 #[inline]
115 fn checked_cast(self) -> Option<$Fixed<Frac>> {
116 <$Fixed<Frac>>::checked_from_num(self)
117 }
118 }
119
120 impl<Frac: $LeEqU> SaturatingCast<$Fixed<Frac>> for $Src {
121 #[inline]
122 fn saturating_cast(self) -> $Fixed<Frac> {
123 <$Fixed<Frac>>::saturating_from_num(self)
124 }
125 }
126
127 impl<Frac: $LeEqU> WrappingCast<$Fixed<Frac>> for $Src {
128 #[inline]
129 fn wrapping_cast(self) -> $Fixed<Frac> {
130 <$Fixed<Frac>>::wrapping_from_num(self)
131 }
132 }
133
134 impl<Frac: $LeEqU> OverflowingCast<$Fixed<Frac>> for $Src {
135 #[inline]
136 fn overflowing_cast(self) -> ($Fixed<Frac>, bool) {
137 <$Fixed<Frac>>::overflowing_from_num(self)
138 }
139 }
140 };
141}
142
143macro_rules! compile_time {
144 (
145 impl<$FracSrc:ident: $LeEqUSrc:ident, $FracDst:ident: $LeEqUDst:ident> StaticCast<$Dst:ty>
146 for $Src:ty
147 {
148 $cond:expr
149 }
150 ) => {
151 impl<$FracSrc: $LeEqUSrc, $FracDst: $LeEqUDst> StaticCast<$Dst> for $Src {
152 #[inline]
153 fn static_cast(self) -> Option<$Dst> {
154 if $cond {
155 Some(az::cast(self))
156 } else {
157 None
158 }
159 }
160 }
161 };
162
163 (impl<$Frac:ident: $LeEqU:ident> StaticCast<$Dst:ty> for $Src:ty { $cond:expr }) => {
164 impl<$Frac: $LeEqU> StaticCast<$Dst> for $Src {
165 #[inline]
166 fn static_cast(self) -> Option<$Dst> {
167 if $cond {
168 Some(az::cast(self))
169 } else {
170 None
171 }
172 }
173 }
174 };
175
176 ($SrcI:ident, $SrcU:ident($LeEqUSrc:ident); $DstI:ident, $DstU:ident($LeEqUDst:ident)) => {
177 compile_time! {
178 impl<FracSrc: $LeEqUSrc, FracDst: $LeEqUDst> StaticCast<$DstI<FracDst>>
179 for $SrcI<FracSrc>
180 {
181 <$DstI<FracDst>>::INT_NBITS >= <$SrcI<FracSrc>>::INT_NBITS
182 }
183 }
184
185 compile_time! {
186 impl<FracSrc: $LeEqUSrc, FracDst: $LeEqUDst> StaticCast<$DstU<FracDst>>
187 for $SrcI<FracSrc>
188 {
189 false
190 }
191 }
192
193 compile_time! {
194 impl<FracSrc: $LeEqUSrc, FracDst: $LeEqUDst> StaticCast<$DstI<FracDst>>
195 for $SrcU<FracSrc>
196 {
197 <$DstI<FracDst>>::INT_NBITS > <$SrcU<FracSrc>>::INT_NBITS
198 }
199 }
200
201 compile_time! {
202 impl<FracSrc: $LeEqUSrc, FracDst: $LeEqUDst> StaticCast<$DstU<FracDst>>
203 for $SrcU<FracSrc>
204 {
205 <$DstU<FracDst>>::INT_NBITS >= <$SrcU<FracSrc>>::INT_NBITS
206 }
207 }
208 };
209
210 ($FixedI:ident, $FixedU:ident($LeEqU:ident); int $DstI:ident, $DstU:ident) => {
211 compile_time! {
212 impl<Frac: $LeEqU> StaticCast<$DstI> for $FixedI<Frac> {
213 8 * mem::size_of::<$DstI>() as u32 >= <$FixedI<Frac>>::INT_NBITS
214 }
215 }
216
217 compile_time! {
218 impl<Frac: $LeEqU> StaticCast<$DstI> for $FixedU<Frac> {
219 8 * mem::size_of::<$DstI>() as u32 > <$FixedU<Frac>>::INT_NBITS
220 }
221 }
222
223 compile_time! {
224 impl<Frac: $LeEqU> StaticCast<$DstU> for $FixedI<Frac> {
225 false
226 }
227 }
228
229 compile_time! {
230 impl<Frac: $LeEqU> StaticCast<$DstU> for $FixedU<Frac> {
231 8 * mem::size_of::<$DstU>() as u32 >= <$FixedU<Frac>>::INT_NBITS
232 }
233 }
234 };
235
236 (int $SrcI:ident, $SrcU:ident; $FixedI:ident, $FixedU:ident($LeEqU:ident)) => {
237 compile_time! {
238 impl<Frac: $LeEqU> StaticCast<$FixedI<Frac>> for $SrcI {
239 <$FixedI<Frac>>::INT_NBITS >= 8 * mem::size_of::<$SrcI>() as u32
240 }
241 }
242
243 compile_time! {
244 impl<Frac: $LeEqU> StaticCast<$FixedU<Frac>> for $SrcI {
245 false
246 }
247 }
248
249 compile_time! {
250 impl<Frac: $LeEqU> StaticCast<$FixedI<Frac>> for $SrcU {
251 <$FixedI<Frac>>::INT_NBITS > 8 * mem::size_of::<$SrcU>() as u32
252 }
253 }
254
255 compile_time! {
256 impl<Frac: $LeEqU> StaticCast<$FixedU<Frac>> for $SrcU {
257 <$FixedU<Frac>>::INT_NBITS >= 8 * mem::size_of::<$SrcU>() as u32
258 }
259 }
260 };
261
262 ($Fixed:ident($LeEqU:ident); float $Dst:ident) => {
263 compile_time! {
264 impl<Frac: $LeEqU> StaticCast<$Dst> for $Fixed<Frac> {
265 true
266 }
267 }
268 };
269
270 (float $Src:ident; $Fixed:ident($LeEqU:ident)) => {
271 compile_time! {
272 impl<Frac: $LeEqU> StaticCast<$Fixed<Frac>> for $Src {
273 false
274 }
275 }
276 };
277}
278
279macro_rules! run_time_num {
280 ($Src:ident($LeEqUSrc:ident); $($Dst:ident($LeEqUDst:ident),)*) => { $(
281 run_time! { $Src($LeEqUSrc); $Dst($LeEqUDst) }
282 )* };
283 ($Fixed:ident($LeEqU:ident); $($Num:ident,)*) => { $(
284 run_time! { $Fixed($LeEqU); $Num }
285 run_time! { $Num; $Fixed($LeEqU) }
286 )* };
287 ($($Fixed:ident($LeEqU:ident),)*) => { $(
288 run_time_num! {
289 $Fixed($LeEqU);
290 FixedI8(LeEqU8), FixedI16(LeEqU16), FixedI32(LeEqU32), FixedI64(LeEqU64),
291 FixedI128(LeEqU128),
292 FixedU8(LeEqU8), FixedU16(LeEqU16), FixedU32(LeEqU32), FixedU64(LeEqU64),
293 FixedU128(LeEqU128),
294 }
295 run_time! { bool; $Fixed($LeEqU) }
296 run_time_num! {
297 $Fixed($LeEqU);
298 i8, i16, i32, i64, i128, isize,
299 u8, u16, u32, u64, u128, usize,
300 f32, f64,
301 }
302 #[cfg(feature = "f16")]
303 run_time_num! {
304 $Fixed($LeEqU);
305 f16, bf16,
306 }
307 )* };
308}
309
310run_time_num! {
311 FixedI8(LeEqU8), FixedI16(LeEqU16), FixedI32(LeEqU32), FixedI64(LeEqU64), FixedI128(LeEqU128),
312 FixedU8(LeEqU8), FixedU16(LeEqU16), FixedU32(LeEqU32), FixedU64(LeEqU64), FixedU128(LeEqU128),
313}
314
315macro_rules! compile_time_fixed {
316 (
317 $SrcI:ident, $SrcU:ident($LeEqUSrc:ident); $(($DstI:ident, $DstU:ident($LeEqUDst:ident)),)*
318 ) => { $(
319 compile_time! { $SrcI, $SrcU($LeEqUSrc); $DstI, $DstU($LeEqUDst) }
320 )* };
321 ($($FixedI:ident, $FixedU:ident($LeEqU:ident),)*) => { $(
322 compile_time_fixed! {
323 $FixedI, $FixedU($LeEqU);
324 (FixedI8, FixedU8(LeEqU8)),
325 (FixedI16, FixedU16(LeEqU16)),
326 (FixedI32, FixedU32(LeEqU32)),
327 (FixedI64, FixedU64(LeEqU64)),
328 (FixedI128, FixedU128(LeEqU128)),
329 }
330 )* };
331}
332
333compile_time_fixed! {
334 FixedI8, FixedU8(LeEqU8),
335 FixedI16, FixedU16(LeEqU16),
336 FixedI32, FixedU32(LeEqU32),
337 FixedI64, FixedU64(LeEqU64),
338 FixedI128, FixedU128(LeEqU128),
339}
340
341macro_rules! compile_time_int {
342 ($FixedI:ident, $FixedU:ident($LeEqU:ident); $(($IntI:ident, $IntU:ident),)*) => { $(
343 compile_time! { $FixedI, $FixedU($LeEqU); int $IntI, $IntU }
344 compile_time! { int $IntI, $IntU; $FixedI, $FixedU($LeEqU) }
345 )* };
346 ($($FixedI:ident, $FixedU:ident($LeEqU:ident),)*) => { $(
347 compile_time! {
348 impl<Frac: $LeEqU> StaticCast<$FixedI<Frac>> for bool {
349 <$FixedI<Frac>>::INT_NBITS > 1
350 }
351 }
352
353 compile_time! {
354 impl<Frac: $LeEqU> StaticCast<$FixedU<Frac>> for bool {
355 <$FixedU<Frac>>::INT_NBITS >= 1
356 }
357 }
358
359 compile_time_int! {
360 $FixedI, $FixedU($LeEqU);
361 (i8, u8),
362 (i16, u16),
363 (i32, u32),
364 (i64, u64),
365 (i128, u128),
366 (isize, usize),
367 }
368 )* };
369}
370
371compile_time_int! {
372 FixedI8, FixedU8(LeEqU8),
373 FixedI16, FixedU16(LeEqU16),
374 FixedI32, FixedU32(LeEqU32),
375 FixedI64, FixedU64(LeEqU64),
376 FixedI128, FixedU128(LeEqU128),
377}
378
379macro_rules! compile_time_float {
380 ($Fixed:ident($LeEqU:ident); $($Float:ident,)*) => { $(
381 compile_time! { $Fixed($LeEqU); float $Float }
382 compile_time! { float $Float; $Fixed($LeEqU) }
383 )* };
384 ($($Fixed:ident($LeEqU:ident),)*) => { $(
385 compile_time_float! {
386 $Fixed($LeEqU);
387 f32, f64,
388 }
389 #[cfg(feature = "f16")]
390 compile_time_float! {
391 $Fixed($LeEqU);
392 f16, bf16,
393 }
394 )* };
395}
396
397compile_time_float! {
398 FixedI8(LeEqU8), FixedI16(LeEqU16), FixedI32(LeEqU32), FixedI64(LeEqU64), FixedI128(LeEqU128),
399 FixedU8(LeEqU8), FixedU16(LeEqU16), FixedU32(LeEqU32), FixedU64(LeEqU64), FixedU128(LeEqU128),
400}