1use crate::{
17 helpers::IntHelper,
18 traits::LossyFrom,
19 types::extra::{
20 Diff, IsLessOrEqual, LeEqU128, LeEqU16, LeEqU32, LeEqU64, LeEqU8, True, U0, U1, U127, U128,
21 U15, U16, U31, U32, U63, U64, U7, U8,
22 },
23 FixedI128, FixedI16, FixedI32, FixedI64, FixedI8, FixedU128, FixedU16, FixedU32, FixedU64,
24 FixedU8,
25};
26use core::ops::Sub;
27#[cfg(feature = "f16")]
28use half::{bf16, f16};
29
30macro_rules! convert {
31 (
32 ($SrcU:ident, $SrcI:ident, $SrcBits:ident, $SrcLeEqU:ident) ->
33 ($DstU:ident, $DstI:ident, $DstBits:ident, $DstBitsM1:ident, $DstLeEqU:ident)
34 ) => {
35 impl<FracSrc: $SrcLeEqU, FracDst: $DstLeEqU> From<$SrcU<FracSrc>> for $DstU<FracDst>
36 where
37 FracSrc: IsLessOrEqual<FracDst, Output = True>,
38 $SrcBits: Sub<FracSrc>,
39 $DstBits: Sub<FracDst>,
40 Diff<$SrcBits, FracSrc>: IsLessOrEqual<Diff<$DstBits, FracDst>, Output = True>,
41 {
42 #[inline]
47 fn from(src: $SrcU<FracSrc>) -> Self {
48 let unshifted = Self::from_bits(src.to_bits().into()).to_bits();
49 let shift = FracDst::U32 - FracSrc::U32;
50 Self::from_bits(unshifted << shift)
51 }
52 }
53
54 impl<FracSrc: $SrcLeEqU, FracDst: $DstLeEqU> From<$SrcI<FracSrc>> for $DstI<FracDst>
55 where
56 FracSrc: IsLessOrEqual<FracDst, Output = True>,
57 $SrcBits: Sub<FracSrc>,
58 $DstBits: Sub<FracDst>,
59 Diff<$SrcBits, FracSrc>: IsLessOrEqual<Diff<$DstBits, FracDst>, Output = True>,
60 {
61 #[inline]
66 fn from(src: $SrcI<FracSrc>) -> Self {
67 let unshifted = Self::from_bits(src.to_bits().into()).to_bits();
68 let shift = FracDst::U32 - FracSrc::U32;
69 Self::from_bits(unshifted << shift)
70 }
71 }
72
73 impl<FracSrc: $SrcLeEqU, FracDst: $DstLeEqU> From<$SrcU<FracSrc>> for $DstI<FracDst>
74 where
75 FracSrc: IsLessOrEqual<FracDst, Output = True>,
76 $SrcBits: Sub<FracSrc>,
77 $DstBitsM1: Sub<FracDst>,
78 Diff<$SrcBits, FracSrc>: IsLessOrEqual<Diff<$DstBitsM1, FracDst>, Output = True>,
79 {
80 #[inline]
85 fn from(src: $SrcU<FracSrc>) -> Self {
86 let unshifted = Self::from_bits(src.to_bits().into()).to_bits();
87 let shift = FracDst::U32 - FracSrc::U32;
88 Self::from_bits(unshifted << shift)
89 }
90 }
91 };
92}
93
94macro_rules! convert_lossy {
95 (
96 ($SrcU:ident, $SrcI:ident, $SrcBits:ident, $SrcLeEqU:ident) ->
97 ($DstU:ident, $DstI:ident, $DstBits:ident, $DstBitsM1:ident, $DstLeEqU:ident)) => {
98 impl<FracSrc: $SrcLeEqU, FracDst: $DstLeEqU> LossyFrom<$SrcU<FracSrc>> for $DstU<FracDst>
99 where
100 $SrcBits: Sub<FracSrc>,
101 $DstBits: Sub<FracDst>,
102 Diff<$SrcBits, FracSrc>: IsLessOrEqual<Diff<$DstBits, FracDst>, Output = True>,
103 {
104 #[inline]
111 fn lossy_from(src: $SrcU<FracSrc>) -> Self {
112 src.to_num()
113 }
114 }
115
116 impl<FracSrc: $SrcLeEqU, FracDst: $DstLeEqU> LossyFrom<$SrcI<FracSrc>> for $DstI<FracDst>
117 where
118 $SrcBits: Sub<FracSrc>,
119 $DstBits: Sub<FracDst>,
120 Diff<$SrcBits, FracSrc>: IsLessOrEqual<Diff<$DstBits, FracDst>, Output = True>,
121 {
122 #[inline]
129 fn lossy_from(src: $SrcI<FracSrc>) -> Self {
130 src.to_num()
131 }
132 }
133
134 impl<FracSrc: $SrcLeEqU, FracDst: $DstLeEqU> LossyFrom<$SrcU<FracSrc>> for $DstI<FracDst>
135 where
136 $SrcBits: Sub<FracSrc>,
137 $DstBitsM1: Sub<FracDst>,
138 Diff<$SrcBits, FracSrc>: IsLessOrEqual<Diff<$DstBitsM1, FracDst>, Output = True>,
139 {
140 #[inline]
147 fn lossy_from(src: $SrcU<FracSrc>) -> Self {
148 src.to_num()
149 }
150 }
151 };
152 ($SrcU:ident, $SrcI:ident, $SrcBits:ident, $SrcLeEqU:ident) => {
153 convert_lossy! {
154 ($SrcU, $SrcI, $SrcBits, $SrcLeEqU) -> (FixedU8, FixedI8, U8, U7, LeEqU8)
155 }
156 convert_lossy! {
157 ($SrcU, $SrcI, $SrcBits, $SrcLeEqU) -> (FixedU16, FixedI16, U16, U15, LeEqU16)
158 }
159 convert_lossy! {
160 ($SrcU, $SrcI, $SrcBits, $SrcLeEqU) -> (FixedU32, FixedI32, U32, U31, LeEqU32)
161 }
162 convert_lossy! {
163 ($SrcU, $SrcI, $SrcBits, $SrcLeEqU) -> (FixedU64, FixedI64, U64, U63, LeEqU64)
164 }
165 convert_lossy! {
166 ($SrcU, $SrcI, $SrcBits, $SrcLeEqU) -> (FixedU128, FixedI128, U128, U127, LeEqU128)
167 }
168 };
169}
170
171convert! { (FixedU8, FixedI8, U8, LeEqU8) -> (FixedU16, FixedI16, U16, U15, LeEqU16) }
172convert! { (FixedU8, FixedI8, U8, LeEqU8) -> (FixedU32, FixedI32, U32, U31, LeEqU32) }
173convert! { (FixedU8, FixedI8, U8, LeEqU8) -> (FixedU64, FixedI64, U64, U63, LeEqU64) }
174convert! { (FixedU8, FixedI8, U8, LeEqU8) -> (FixedU128, FixedI128, U128, U127, LeEqU128) }
175
176convert! { (FixedU16, FixedI16, U16, LeEqU16) -> (FixedU32, FixedI32, U32, U31, LeEqU32) }
177convert! { (FixedU16, FixedI16, U16, LeEqU16) -> (FixedU64, FixedI64, U64, U63, LeEqU64) }
178convert! { (FixedU16, FixedI16, U16, LeEqU16) -> (FixedU128, FixedI128, U128, U127, LeEqU128) }
179
180convert! { (FixedU32, FixedI32, U32, LeEqU32) -> (FixedU64, FixedI64, U64, U63, LeEqU64) }
181convert! { (FixedU32, FixedI32, U32, LeEqU32) -> (FixedU128, FixedI128, U128, U127, LeEqU128) }
182
183convert! { (FixedU64, FixedI64, U64, LeEqU64) -> (FixedU128, FixedI128, U128, U127, LeEqU128) }
184
185convert_lossy! { FixedU8, FixedI8, U8, LeEqU8 }
186convert_lossy! { FixedU16, FixedI16, U16, LeEqU16 }
187convert_lossy! { FixedU32, FixedI32, U32, LeEqU32 }
188convert_lossy! { FixedU64, FixedI64, U64, LeEqU64 }
189convert_lossy! { FixedU128, FixedI128, U128, LeEqU128 }
190
191macro_rules! lossy {
192 ($Src:ty) => {
193 impl LossyFrom<$Src> for $Src {
194 #[inline]
199 fn lossy_from(src: $Src) -> Self {
200 src
201 }
202 }
203 };
204 ($Src:ty: Into $($Dst:ty),*) => { $(
205 impl LossyFrom<$Src> for $Dst {
206 #[inline]
211 fn lossy_from(src: $Src) -> Self {
212 src.into()
213 }
214 }
215 )* };
216}
217
218macro_rules! int_to_fixed {
219 (
220 ($SrcU:ident, $SrcI:ident, $SrcBits:ident, $SrcLeEqU:ident) ->
221 ($DstU:ident, $DstI:ident, $DstBits:ident, $DstBitsM1:ident, $DstLeEqU:ident)
222 ) => {
223 impl<FracDst: $DstLeEqU> From<$SrcU> for $DstU<FracDst>
224 where
225 $DstBits: Sub<FracDst>,
226 $SrcBits: IsLessOrEqual<Diff<$DstBits, FracDst>, Output = True>,
227 {
228 #[inline]
233 fn from(src: $SrcU) -> Self {
234 let unshifted = Self::from_bits(src.into()).to_bits();
235 let shift = FracDst::U32;
236 Self::from_bits(unshifted << shift)
237 }
238 }
239
240 impl<FracDst: $DstLeEqU> From<$SrcI> for $DstI<FracDst>
241 where
242 $DstBits: Sub<FracDst>,
243 $SrcBits: IsLessOrEqual<Diff<$DstBits, FracDst>, Output = True>,
244 {
245 #[inline]
250 fn from(src: $SrcI) -> Self {
251 let unshifted = Self::from_bits(src.into()).to_bits();
252 let shift = FracDst::U32;
253 Self::from_bits(unshifted << shift)
254 }
255 }
256
257 impl<FracDst: $DstLeEqU> From<$SrcU> for $DstI<FracDst>
258 where
259 $DstBitsM1: Sub<FracDst>,
260 $SrcBits: IsLessOrEqual<Diff<$DstBitsM1, FracDst>, Output = True>,
261 {
262 #[inline]
267 fn from(src: $SrcU) -> Self {
268 let unshifted = Self::from_bits(src.into()).to_bits();
269 let shift = FracDst::U32;
270 Self::from_bits(unshifted << shift)
271 }
272 }
273
274 impl<FracDst: $DstLeEqU> LossyFrom<$SrcU> for $DstU<FracDst>
275 where
276 $DstBits: Sub<FracDst>,
277 $SrcBits: IsLessOrEqual<Diff<$DstBits, FracDst>, Output = True>,
278 {
279 #[inline]
284 fn lossy_from(src: $SrcU) -> Self {
285 src.into()
286 }
287 }
288
289 impl<FracDst: $DstLeEqU> LossyFrom<$SrcI> for $DstI<FracDst>
290 where
291 $DstBits: Sub<FracDst>,
292 $SrcBits: IsLessOrEqual<Diff<$DstBits, FracDst>, Output = True>,
293 {
294 #[inline]
299 fn lossy_from(src: $SrcI) -> Self {
300 src.into()
301 }
302 }
303
304 impl<FracDst: $DstLeEqU> LossyFrom<$SrcU> for $DstI<FracDst>
305 where
306 $DstBitsM1: Sub<FracDst>,
307 $SrcBits: IsLessOrEqual<Diff<$DstBitsM1, FracDst>, Output = True>,
308 {
309 #[inline]
314 fn lossy_from(src: $SrcU) -> Self {
315 src.into()
316 }
317 }
318 };
319
320 (($SrcU:ident, $SrcI:ident) -> ($DstU:ident, $DstI:ident)) => {
321 impl From<$SrcU> for $DstU<U0> {
322 #[inline]
327 fn from(src: $SrcU) -> Self {
328 Self::from_bits(src)
329 }
330 }
331
332 impl From<$SrcI> for $DstI<U0> {
333 #[inline]
338 fn from(src: $SrcI) -> Self {
339 Self::from_bits(src)
340 }
341 }
342
343 lossy! { $SrcU: Into $DstU<U0> }
344 lossy! { $SrcI: Into $DstI<U0> }
345 };
346}
347
348int_to_fixed! { (u8, i8) -> (FixedU8, FixedI8) }
349int_to_fixed! { (u8, i8, U8, LeEqU8) -> (FixedU16, FixedI16, U16, U15, LeEqU16) }
350int_to_fixed! { (u8, i8, U8, LeEqU8) -> (FixedU32, FixedI32, U32, U31, LeEqU32) }
351int_to_fixed! { (u8, i8, U8, LeEqU8) -> (FixedU64, FixedI64, U64, U63, LeEqU64) }
352int_to_fixed! { (u8, i8, U8, LeEqU8) -> (FixedU128, FixedI128, U128, U127, LeEqU128) }
353
354int_to_fixed! { (u16, i16) -> (FixedU16, FixedI16) }
355int_to_fixed! { (u16, i16, U16, LeEqU16) -> (FixedU32, FixedI32, U32, U31, LeEqU32) }
356int_to_fixed! { (u16, i16, U16, LeEqU16) -> (FixedU64, FixedI64, U64, U63, LeEqU64) }
357int_to_fixed! { (u16, i16, U16, LeEqU16) -> (FixedU128, FixedI128, U128, U127, LeEqU128) }
358
359int_to_fixed! { (u32, i32) -> (FixedU32, FixedI32) }
360int_to_fixed! { (u32, i32, U32, LeEqU32) -> (FixedU64, FixedI64, U64, U63, LeEqU64) }
361int_to_fixed! { (u32, i32, U32, LeEqU32) -> (FixedU128, FixedI128, U128, U127, LeEqU128) }
362
363int_to_fixed! { (u64, i64) -> (FixedU64, FixedI64) }
364int_to_fixed! { (u64, i64, U64, LeEqU64) -> (FixedU128, FixedI128, U128, U127, LeEqU128) }
365
366int_to_fixed! { (u128, i128) -> (FixedU128, FixedI128) }
367
368macro_rules! bool_to_fixed {
369 ($DstU:ident, $DstI:ident, $DstBits:ident, $DstBitsM1:ident, $DstLeEqU:ident) => {
370 impl<FracDst: $DstLeEqU> From<bool> for $DstU<FracDst>
371 where
372 $DstBits: Sub<FracDst>,
373 U1: IsLessOrEqual<Diff<$DstBits, FracDst>, Output = True>,
374 {
375 #[inline]
382 fn from(src: bool) -> Self {
383 let unshifted = Self::from_bits(src.into()).to_bits();
384 let shift = FracDst::U32;
385 Self::from_bits(unshifted << shift)
386 }
387 }
388
389 impl<FracDst: $DstLeEqU> From<bool> for $DstI<FracDst>
390 where
391 $DstBitsM1: Sub<FracDst>,
392 U1: IsLessOrEqual<Diff<$DstBitsM1, FracDst>, Output = True>,
393 {
394 #[inline]
401 fn from(src: bool) -> Self {
402 let unshifted = Self::from_bits(src.into()).to_bits();
403 let shift = FracDst::U32;
404 Self::from_bits(unshifted << shift)
405 }
406 }
407
408 impl<FracDst: $DstLeEqU> LossyFrom<bool> for $DstU<FracDst>
409 where
410 $DstBits: Sub<FracDst>,
411 U1: IsLessOrEqual<Diff<$DstBits, FracDst>, Output = True>,
412 {
413 #[inline]
420 fn lossy_from(src: bool) -> Self {
421 src.into()
422 }
423 }
424
425 impl<FracDst: $DstLeEqU> LossyFrom<bool> for $DstI<FracDst>
426 where
427 $DstBitsM1: Sub<FracDst>,
428 U1: IsLessOrEqual<Diff<$DstBitsM1, FracDst>, Output = True>,
429 {
430 #[inline]
437 fn lossy_from(src: bool) -> Self {
438 src.into()
439 }
440 }
441 };
442}
443
444bool_to_fixed! { FixedU8, FixedI8, U8, U7, LeEqU8 }
445bool_to_fixed! { FixedU16, FixedI16, U16, U15, LeEqU16 }
446bool_to_fixed! { FixedU32, FixedI32, U32, U31, LeEqU32 }
447bool_to_fixed! { FixedU64, FixedI64, U64, U63, LeEqU64 }
448bool_to_fixed! { FixedU128, FixedI128, U128, U127, LeEqU128 }
449
450macro_rules! fixed_to_int {
451 (($SrcU:ident, $SrcI:ident) -> ($DstU:ident, $DstI:ident)) => {
452 impl From<$SrcU<U0>> for $DstU {
453 #[inline]
458 fn from(src: $SrcU<U0>) -> Self {
459 src.to_bits().into()
460 }
461 }
462
463 impl From<$SrcI<U0>> for $DstI {
464 #[inline]
469 fn from(src: $SrcI<U0>) -> Self {
470 src.to_bits().into()
471 }
472 }
473 };
474 (($SrcU:ident, $SrcI:ident) -> wider ($DstU:ident, $DstI:ident)) => {
475 fixed_to_int! { ($SrcU, $SrcI) -> ($DstU, $DstI) }
476
477 impl From<$SrcU<U0>> for $DstI {
478 #[inline]
483 fn from(src: $SrcU<U0>) -> Self {
484 src.to_bits().into()
485 }
486 }
487 };
488}
489
490fixed_to_int! { (FixedU8, FixedI8) -> (u8, i8) }
491fixed_to_int! { (FixedU8, FixedI8) -> wider (u16, i16) }
492fixed_to_int! { (FixedU8, FixedI8) -> wider (u32, i32) }
493fixed_to_int! { (FixedU8, FixedI8) -> wider (u64, i64) }
494fixed_to_int! { (FixedU8, FixedI8) -> wider (u128, i128) }
495fixed_to_int! { (FixedU8, FixedI8) -> wider (usize, isize) }
496
497fixed_to_int! { (FixedU16, FixedI16) -> (u16, i16) }
498fixed_to_int! { (FixedU16, FixedI16) -> wider (u32, i32) }
499fixed_to_int! { (FixedU16, FixedI16) -> wider (u64, i64) }
500fixed_to_int! { (FixedU16, FixedI16) -> wider (u128, i128) }
501fixed_to_int! { (FixedU16, FixedI16) -> (usize, isize) }
502
503fixed_to_int! { (FixedU32, FixedI32) -> (u32, i32) }
504fixed_to_int! { (FixedU32, FixedI32) -> wider (u64, i64) }
505fixed_to_int! { (FixedU32, FixedI32) -> wider (u128, i128) }
506
507fixed_to_int! { (FixedU64, FixedI64) -> (u64, i64) }
508fixed_to_int! { (FixedU64, FixedI64) -> wider (u128, i128) }
509
510fixed_to_int! { (FixedU128, FixedI128) -> (u128, i128) }
511
512macro_rules! fixed_to_int_lossy {
513 (
514 ($SrcU:ident, $SrcI:ident, $SrcBits:ident, $SrcLeEqU:ident) ->
515 ($DstU:ident, $DstI:ident, $DstBits:ident, $DstBitsM1:ident, $DstLeEqU:ident)
516 ) => {
517 impl<FracSrc: $SrcLeEqU> LossyFrom<$SrcU<FracSrc>> for $DstU
518 where
519 $SrcBits: Sub<FracSrc>,
520 Diff<$SrcBits, FracSrc>: IsLessOrEqual<$DstBits, Output = True>,
521 {
522 #[inline]
528 fn lossy_from(src: $SrcU<FracSrc>) -> Self {
529 src.to_num()
530 }
531 }
532
533 impl<FracSrc: $SrcLeEqU> LossyFrom<$SrcI<FracSrc>> for $DstI
534 where
535 $SrcBits: Sub<FracSrc>,
536 Diff<$SrcBits, FracSrc>: IsLessOrEqual<$DstBits, Output = True>,
537 {
538 #[inline]
544 fn lossy_from(src: $SrcI<FracSrc>) -> Self {
545 src.to_num()
546 }
547 }
548
549 impl<FracSrc: $SrcLeEqU> LossyFrom<$SrcU<FracSrc>> for $DstI
550 where
551 $SrcBits: Sub<FracSrc>,
552 Diff<$SrcBits, FracSrc>: IsLessOrEqual<$DstBitsM1, Output = True>,
553 {
554 #[inline]
560 fn lossy_from(src: $SrcU<FracSrc>) -> Self {
561 src.to_num()
562 }
563 }
564 };
565 ($SrcU:ident, $SrcI:ident, $SrcBits:ident, $SrcLeEqU:ident) => {
566 fixed_to_int_lossy! {
567 ($SrcU, $SrcI, $SrcBits, $SrcLeEqU) -> (u8, i8, U8, U7, LeEqU8)
568 }
569 fixed_to_int_lossy! {
570 ($SrcU, $SrcI, $SrcBits, $SrcLeEqU) -> (u16, i16, U16, U15, LeEqU16)
571 }
572 fixed_to_int_lossy! {
573 ($SrcU, $SrcI, $SrcBits, $SrcLeEqU) -> (u32, i32, U32, U31, LeEqU32)
574 }
575 fixed_to_int_lossy! {
576 ($SrcU, $SrcI, $SrcBits, $SrcLeEqU) -> (u64, i64, U64, U63, LeEqU64)
577 }
578 fixed_to_int_lossy! {
579 ($SrcU, $SrcI, $SrcBits, $SrcLeEqU) -> (u128, i128, U128, U127, LeEqU128)
580 }
581 fixed_to_int_lossy! {
582 ($SrcU, $SrcI, $SrcBits, $SrcLeEqU) -> (usize, isize, U16, U15, LeEqU16)
583 }
584 };
585}
586
587fixed_to_int_lossy! { FixedU8, FixedI8, U8, LeEqU8 }
588fixed_to_int_lossy! { FixedU16, FixedI16, U16, LeEqU16 }
589fixed_to_int_lossy! { FixedU32, FixedI32, U32, LeEqU32 }
590fixed_to_int_lossy! { FixedU64, FixedI64, U64, LeEqU64 }
591fixed_to_int_lossy! { FixedU128, FixedI128, U128, LeEqU128 }
592
593macro_rules! fixed_to_float {
594 ($Fixed:ident($LeEqU:ident) -> $Float:ident) => {
595 impl<Frac: $LeEqU> From<$Fixed<Frac>> for $Float {
596 #[inline]
601 fn from(src: $Fixed<Frac>) -> $Float {
602 src.to_num()
603 }
604 }
605 };
606}
607
608#[cfg(feature = "f16")]
609fixed_to_float! { FixedI8(LeEqU8) -> f16 }
610#[cfg(feature = "f16")]
611fixed_to_float! { FixedU8(LeEqU8) -> f16 }
612fixed_to_float! { FixedI8(LeEqU8) -> f32 }
613fixed_to_float! { FixedI16(LeEqU16) -> f32 }
614fixed_to_float! { FixedU8(LeEqU8) -> f32 }
615fixed_to_float! { FixedU16(LeEqU16) -> f32 }
616fixed_to_float! { FixedI8(LeEqU8) -> f64 }
617fixed_to_float! { FixedI16(LeEqU16) -> f64 }
618fixed_to_float! { FixedI32(LeEqU32) -> f64 }
619fixed_to_float! { FixedU8(LeEqU8) -> f64 }
620fixed_to_float! { FixedU16(LeEqU16) -> f64 }
621fixed_to_float! { FixedU32(LeEqU32) -> f64 }
622
623macro_rules! fixed_to_float_lossy {
624 ($Fixed:ident($LeEqU:ident) -> $Float:ident) => {
625 impl<Frac: $LeEqU> LossyFrom<$Fixed<Frac>> for $Float {
626 #[inline]
632 fn lossy_from(src: $Fixed<Frac>) -> $Float {
633 src.to_num()
634 }
635 }
636 };
637 ($Fixed:ident($LeEqU:ident)) => {
638 #[cfg(feature = "f16")]
639 fixed_to_float_lossy! { $Fixed($LeEqU) -> f16 }
640 #[cfg(feature = "f16")]
641 fixed_to_float_lossy! { $Fixed($LeEqU) -> bf16 }
642 fixed_to_float_lossy! { $Fixed($LeEqU) -> f32 }
643 fixed_to_float_lossy! { $Fixed($LeEqU) -> f64 }
644 };
645}
646
647fixed_to_float_lossy! { FixedI8(LeEqU8) }
648fixed_to_float_lossy! { FixedI16(LeEqU16) }
649fixed_to_float_lossy! { FixedI32(LeEqU32) }
650fixed_to_float_lossy! { FixedI64(LeEqU64) }
651fixed_to_float_lossy! { FixedI128(LeEqU128) }
652fixed_to_float_lossy! { FixedU8(LeEqU8) }
653fixed_to_float_lossy! { FixedU16(LeEqU16) }
654fixed_to_float_lossy! { FixedU32(LeEqU32) }
655fixed_to_float_lossy! { FixedU64(LeEqU64) }
656fixed_to_float_lossy! { FixedU128(LeEqU128) }
657
658macro_rules! int_to_float_lossy_lossless {
659 ($Int:ident -> $($Lossy:ident)*; $($Lossless:ident)*) => {
660 $(
661 impl LossyFrom<$Int> for $Lossy {
662 #[inline]
668 fn lossy_from(src: $Int) -> $Lossy {
669 src.to_repr_fixed().to_num()
670 }
671 }
672 )*
673 $(
674 impl LossyFrom<$Int> for $Lossless {
675 #[inline]
680 fn lossy_from(src: $Int) -> $Lossless {
681 src.to_repr_fixed().to_num()
682 }
683 }
684 )*
685 };
686}
687
688#[cfg(feature = "f16")]
689int_to_float_lossy_lossless! { i8 -> bf16; f16 }
690int_to_float_lossy_lossless! { i8 -> ; f32 f64 }
691#[cfg(feature = "f16")]
692int_to_float_lossy_lossless! { i16 -> bf16 f16; }
693int_to_float_lossy_lossless! { i16 -> ; f32 f64 }
694#[cfg(feature = "f16")]
695int_to_float_lossy_lossless! { i32 -> bf16 f16; }
696int_to_float_lossy_lossless! { i32 -> f32; f64 }
697#[cfg(feature = "f16")]
698int_to_float_lossy_lossless! { i64 -> bf16 f16; }
699int_to_float_lossy_lossless! { i64 -> f32 f64; }
700#[cfg(feature = "f16")]
701int_to_float_lossy_lossless! { i128 -> bf16 f16; }
702int_to_float_lossy_lossless! { i128 -> f32 f64; }
703#[cfg(feature = "f16")]
704int_to_float_lossy_lossless! { isize -> bf16 f16; }
705int_to_float_lossy_lossless! { isize -> f32 f64; }
706
707#[cfg(feature = "f16")]
708int_to_float_lossy_lossless! { u8 -> bf16; f16 }
709int_to_float_lossy_lossless! { u8 -> ; f32 f64 }
710#[cfg(feature = "f16")]
711int_to_float_lossy_lossless! { u16 -> bf16 f16; }
712int_to_float_lossy_lossless! { u16 -> ; f32 f64 }
713#[cfg(feature = "f16")]
714int_to_float_lossy_lossless! { u32 -> bf16 f16; }
715int_to_float_lossy_lossless! { u32 -> f32; f64 }
716#[cfg(feature = "f16")]
717int_to_float_lossy_lossless! { u64 -> bf16 f16; }
718int_to_float_lossy_lossless! { u64 -> f32 f64; }
719#[cfg(feature = "f16")]
720int_to_float_lossy_lossless! { u128 -> bf16 f16; }
721int_to_float_lossy_lossless! { u128 -> f32 f64; }
722#[cfg(feature = "f16")]
723int_to_float_lossy_lossless! { usize -> bf16 f16; }
724int_to_float_lossy_lossless! { usize -> f32 f64; }
725
726lossy! { bool }
727lossy! { bool: Into i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize }
728lossy! { i8 }
729lossy! { i8: Into i16, i32, i64, i128, isize }
730lossy! { i16 }
731lossy! { i16: Into i32, i64, i128, isize }
732lossy! { i32 }
733lossy! { i32: Into i64, i128 }
734lossy! { i64 }
735lossy! { i64: Into i128 }
736lossy! { i128 }
737lossy! { isize }
738lossy! { u8 }
739lossy! { u8: Into i16, i32, i64, i128, isize, u16, u32, u64, u128, usize }
740lossy! { u16 }
741lossy! { u16: Into i32, i64, i128, u32, u64, u128, usize }
742lossy! { u32 }
743lossy! { u32: Into i64, i128, u64, u128 }
744lossy! { u64 }
745lossy! { u64: Into i128, u128 }
746lossy! { u128 }
747lossy! { usize }
748
749#[cfg(feature = "f16")]
750lossy! { f16 }
751#[cfg(feature = "f16")]
752impl LossyFrom<f16> for bf16 {
753 #[inline]
754 fn lossy_from(src: f16) -> bf16 {
760 bf16::from_f32(src.into())
761 }
762}
763#[cfg(feature = "f16")]
764lossy! { f16: Into f32 }
765#[cfg(feature = "f16")]
766lossy! { f16: Into f64 }
767
768#[cfg(feature = "f16")]
769impl LossyFrom<bf16> for f16 {
770 #[inline]
771 fn lossy_from(src: bf16) -> f16 {
777 f16::from_f32(src.into())
778 }
779}
780#[cfg(feature = "f16")]
781lossy! { bf16 }
782#[cfg(feature = "f16")]
783lossy! { bf16: Into f32 }
784#[cfg(feature = "f16")]
785lossy! { bf16: Into f64 }
786
787#[cfg(feature = "f16")]
788impl LossyFrom<f32> for f16 {
789 #[inline]
790 fn lossy_from(src: f32) -> Self {
796 f16::from_f32(src)
797 }
798}
799#[cfg(feature = "f16")]
800impl LossyFrom<f32> for bf16 {
801 #[inline]
802 fn lossy_from(src: f32) -> Self {
808 bf16::from_f32(src)
809 }
810}
811lossy! { f32 }
812lossy! { f32: Into f64 }
813
814#[cfg(feature = "f16")]
815impl LossyFrom<f64> for f16 {
816 #[inline]
817 fn lossy_from(src: f64) -> Self {
823 f16::from_f64(src)
824 }
825}
826#[cfg(feature = "f16")]
827impl LossyFrom<f64> for bf16 {
828 #[inline]
829 fn lossy_from(src: f64) -> Self {
835 bf16::from_f64(src)
836 }
837}
838impl LossyFrom<f64> for f32 {
839 #[inline]
845 fn lossy_from(src: f64) -> Self {
846 src as f32
847 }
848}
849lossy! { f64 }
850
851fn _compile_fail_tests() {}
938
939#[cfg(test)]
940#[allow(clippy::float_cmp)]
941mod tests {
942 use crate::types::*;
943
944 #[test]
945 fn expanding_from_unsigned() {
946 type L8 = U8F0;
947 type LL16 = U16F0;
948 type LH16 = U8F8;
949 type LL128 = U128F0;
950 type LH128 = U8F120;
951
952 type H8 = U0F8;
953 type HL16 = U8F8;
954 type HH16 = U0F16;
955 type HL128 = U120F8;
956 type HH128 = U0F128;
957
958 let vals: &[u8] = &[0x00, 0x7f, 0x80, 0xff];
959 for &val in vals {
960 let val16 = u16::from(val);
961 let val128 = u128::from(val);
962
963 let l = L8::from_bits(val);
964 assert_eq!(l, L8::from(val));
965 assert_eq!(val, u8::from(l));
966 assert_eq!(LL16::from(l), LL16::from_bits(val16));
967 assert_eq!(LH16::from(l), LH16::from_bits(val16 << 8));
968 assert_eq!(LL128::from(l), LL128::from_bits(val128));
969 assert_eq!(LH128::from(l), LH128::from_bits(val128 << 120));
970
971 let h = H8::from_bits(val);
972 assert_eq!(HL16::from(h), HL16::from_bits(val16));
973 assert_eq!(HH16::from(h), HH16::from_bits(val16 << 8));
974 assert_eq!(HL128::from(h), HL128::from_bits(val128));
975 assert_eq!(HH128::from(h), HH128::from_bits(val128 << 120));
976 }
977 }
978
979 #[test]
980 fn expanding_from_signed() {
981 type L8 = I8F0;
982 type LL16 = I16F0;
983 type LH16 = I8F8;
984 type LL128 = I128F0;
985 type LH128 = I8F120;
986
987 type H8 = I0F8;
988 type HL16 = I8F8;
989 type HH16 = I0F16;
990 type HL128 = I120F8;
991 type HH128 = I0F128;
992
993 let vals: &[i8] = &[0x00, 0x7f, -0x80, -0x01];
994 for &val in vals {
995 let val16 = i16::from(val);
996 let val128 = i128::from(val);
997
998 let l = L8::from_bits(val);
999 assert_eq!(l, L8::from(val));
1000 assert_eq!(val, i8::from(l));
1001 assert_eq!(LL16::from(l), LL16::from_bits(val16));
1002 assert_eq!(LH16::from(l), LH16::from_bits(val16 << 8));
1003 assert_eq!(LL128::from(l), LL128::from_bits(val128));
1004 assert_eq!(LH128::from(l), LH128::from_bits(val128 << 120));
1005
1006 let h = H8::from_bits(val);
1007 assert_eq!(HL16::from(h), HL16::from_bits(val16));
1008 assert_eq!(HH16::from(h), HH16::from_bits(val16 << 8));
1009 assert_eq!(HL128::from(h), HL128::from_bits(val128));
1010 assert_eq!(HH128::from(h), HH128::from_bits(val128 << 120));
1011 }
1012 }
1013
1014 #[test]
1015 fn expanding_from_unsigned_to_signed() {
1016 type L8 = U8F0;
1017 type LL16 = I16F0;
1018 type LH16 = I9F7;
1019 type LL128 = I128F0;
1020 type LH128 = I9F119;
1021
1022 type H8 = U0F8;
1023 type HL16 = I8F8;
1024 type HH16 = I1F15;
1025 type HL128 = I120F8;
1026 type HH128 = I1F127;
1027
1028 let vals: &[u8] = &[0x00, 0x7f, 0x80, 0xff];
1029 for &val in vals {
1030 let val16 = i16::from(val);
1031 let val128 = i128::from(val);
1032
1033 let l = L8::from_bits(val);
1034 assert_eq!(l, L8::from(val));
1035 assert_eq!(val, u8::from(l));
1036 assert_eq!(LL16::from(l), LL16::from_bits(val16));
1037 assert_eq!(LH16::from(l), LH16::from_bits(val16 << 7));
1038 assert_eq!(LL128::from(l), LL128::from_bits(val128));
1039 assert_eq!(LH128::from(l), LH128::from_bits(val128 << 119));
1040
1041 let h = H8::from_bits(val);
1042 assert_eq!(HL16::from(h), HL16::from_bits(val16));
1043 assert_eq!(HH16::from(h), HH16::from_bits(val16 << 7));
1044 assert_eq!(HL128::from(h), HL128::from_bits(val128));
1045 assert_eq!(HH128::from(h), HH128::from_bits(val128 << 119));
1046 }
1047 }
1048
1049 #[test]
1050 fn from_bool() {
1051 assert_eq!(I2F6::from(true), 1);
1052 assert_eq!(I2F6::from(false), 0);
1053 assert_eq!(I64F64::from(true), 1);
1054 assert_eq!(U1F127::from(true), 1);
1055 }
1056
1057 #[test]
1058 fn to_size() {
1059 let min_i24 = I24F8::min_value();
1060 let max_i24 = I24F8::max_value();
1061 let max_u24 = U24F8::max_value();
1062 assert_eq!(min_i24.overflowing_to_num::<isize>(), (!0 << 23, false));
1063 assert_eq!(max_i24.overflowing_to_num::<isize>(), (!(!0 << 23), false));
1064 assert_eq!(max_u24.overflowing_to_num::<isize>(), (!(!0 << 24), false));
1065 assert_eq!(min_i24.overflowing_to_num::<usize>(), (!0 << 23, true));
1066 assert_eq!(max_i24.overflowing_to_num::<usize>(), (!(!0 << 23), false));
1067 assert_eq!(max_u24.overflowing_to_num::<usize>(), (!(!0 << 24), false));
1068
1069 let min_i56 = I56F8::min_value();
1070 let max_i56 = I56F8::max_value();
1071 let max_u56 = U56F8::max_value();
1072 #[cfg(target_pointer_width = "32")]
1073 {
1074 assert_eq!(min_i56.overflowing_to_num::<isize>(), (0, true));
1075 assert_eq!(max_i56.overflowing_to_num::<isize>(), (!0, true));
1076 assert_eq!(max_u56.overflowing_to_num::<isize>(), (!0, true));
1077 assert_eq!(min_i56.overflowing_to_num::<usize>(), (0, true));
1078 assert_eq!(max_i56.overflowing_to_num::<usize>(), (!0, true));
1079 assert_eq!(max_u56.overflowing_to_num::<usize>(), (!0, true));
1080 }
1081 #[cfg(target_pointer_width = "64")]
1082 {
1083 assert_eq!(min_i56.overflowing_to_num::<isize>(), (!0 << 55, false));
1084 assert_eq!(max_i56.overflowing_to_num::<isize>(), (!(!0 << 55), false));
1085 assert_eq!(max_u56.overflowing_to_num::<isize>(), (!(!0 << 56), false));
1086 assert_eq!(min_i56.overflowing_to_num::<usize>(), (!0 << 55, true));
1087 assert_eq!(max_i56.overflowing_to_num::<usize>(), (!(!0 << 55), false));
1088 assert_eq!(max_u56.overflowing_to_num::<usize>(), (!(!0 << 56), false));
1089 }
1090
1091 let min_i120 = I120F8::min_value();
1092 let max_i120 = I120F8::max_value();
1093 let max_u120 = U120F8::max_value();
1094 assert_eq!(min_i120.overflowing_to_num::<isize>(), (0, true));
1095 assert_eq!(max_i120.overflowing_to_num::<isize>(), (!0, true));
1096 assert_eq!(max_u120.overflowing_to_num::<isize>(), (!0, true));
1097 assert_eq!(min_i120.overflowing_to_num::<usize>(), (0, true));
1098 assert_eq!(max_i120.overflowing_to_num::<usize>(), (!0, true));
1099 assert_eq!(max_u120.overflowing_to_num::<usize>(), (!0, true));
1100 }
1101
1102 #[test]
1103 fn signed_from_float() {
1104 type Fix = I4F4;
1105 assert_eq!(Fix::from_num(3.0 / 2.0), Fix::from_bits(24));
1107 assert_eq!(Fix::from_num(3.0 / 4.0), Fix::from_bits(12));
1109 assert_eq!(Fix::from_num(3.0 / 8.0), Fix::from_bits(6));
1111 assert_eq!(Fix::from_num(3.0 / 16.0), Fix::from_bits(3));
1113 assert_eq!(Fix::from_num(3.0 / 32.0), Fix::from_bits(2));
1115 assert_eq!(Fix::from_num(5.0 / 32.0), Fix::from_bits(2));
1117 assert_eq!(Fix::from_num(3.0 / 64.0), Fix::from_bits(1));
1119 assert_eq!(Fix::from_num(1.0 / 32.0), Fix::from_bits(0));
1121
1122 assert_eq!(Fix::from_num(-3.0 / 2.0), Fix::from_bits(-24));
1124 assert_eq!(Fix::from_num(-3.0 / 4.0), Fix::from_bits(-12));
1126 assert_eq!(Fix::from_num(-3.0 / 8.0), Fix::from_bits(-6));
1128 assert_eq!(Fix::from_num(-3.0 / 16.0), Fix::from_bits(-3));
1130 assert_eq!(Fix::from_num(-3.0 / 32.0), Fix::from_bits(-2));
1132 assert_eq!(Fix::from_num(-5.0 / 32.0), Fix::from_bits(-2));
1134 assert_eq!(Fix::from_num(-3.0 / 64.0), Fix::from_bits(-1));
1136 assert_eq!(Fix::from_num(-1.0 / 32.0), Fix::from_bits(0));
1138
1139 assert_eq!(Fix::from_num(127.0 / 16.0), Fix::from_bits(127));
1141 assert_eq!(
1143 Fix::overflowing_from_num(255.0 / 32.0),
1144 (Fix::from_bits(-128), true)
1145 );
1146
1147 assert_eq!(Fix::from_num(-127.0 / 16.0), Fix::from_bits(-127));
1149 assert_eq!(Fix::from_num(-255.0 / 32.0), Fix::from_bits(-128));
1151 assert_eq!(Fix::from_num(-257.0 / 32.0), Fix::from_bits(-128));
1153 assert_eq!(
1155 Fix::overflowing_from_num(-129.0 / 16.0),
1156 (Fix::from_bits(127), true)
1157 );
1158 }
1159
1160 #[test]
1161 fn unsigned_from_num() {
1162 type Fix = U4F4;
1163 assert_eq!(Fix::from_num(3.0 / 2.0), Fix::from_bits(24));
1165 assert_eq!(Fix::from_num(3.0 / 4.0), Fix::from_bits(12));
1167 assert_eq!(Fix::from_num(3.0 / 8.0), Fix::from_bits(6));
1169 assert_eq!(Fix::from_num(3.0 / 16.0), Fix::from_bits(3));
1171 assert_eq!(Fix::from_num(3.0 / 32.0), Fix::from_bits(2));
1173 assert_eq!(Fix::from_num(5.0 / 32.0), Fix::from_bits(2));
1175 assert_eq!(Fix::from_num(3.0 / 64.0), Fix::from_bits(1));
1177 assert_eq!(Fix::from_num(1.0 / 32.0), Fix::from_bits(0));
1179 assert_eq!(Fix::from_num(-1.0 / 32.0), Fix::from_bits(0));
1181 assert_eq!(
1183 Fix::overflowing_from_num(-1.0 / 16.0),
1184 (Fix::from_bits(255), true)
1185 );
1186
1187 assert_eq!(Fix::from_num(255.0 / 16.0), Fix::from_bits(255));
1189 assert_eq!(
1191 Fix::overflowing_from_num(511.0 / 32.0),
1192 (Fix::from_bits(0), true)
1193 );
1194 }
1195
1196 #[cfg(feature = "f16")]
1197 #[test]
1198 fn to_f16() {
1199 use half::f16;
1200 for u in 0x00..=0xff {
1201 let fu = U1F7::from_bits(u);
1202 assert_eq!(fu.to_num::<f16>(), f16::from_f32(f32::from(u) / 128.0));
1203 let i = u as i8;
1204 let fi = I1F7::from_bits(i);
1205 assert_eq!(fi.to_num::<f16>(), f16::from_f32(f32::from(i) / 128.0));
1206
1207 for hi in &[
1208 0u32,
1209 0x0000_0100,
1210 0x7fff_ff00,
1211 0x8000_0000,
1212 0x8100_0000,
1213 0xffff_fe00,
1214 0xffff_ff00,
1215 ] {
1216 let uu = *hi | u32::from(u);
1217 let fuu = U25F7::from_bits(uu);
1218 assert_eq!(fuu.to_num::<f16>(), f16::from_f32(uu as f32 / 128.0));
1219 let ii = uu as i32;
1220 let fii = I25F7::from_bits(ii);
1221 assert_eq!(fii.to_num::<f16>(), f16::from_f32(ii as f32 / 128.0));
1222 }
1223
1224 for hi in &[
1225 0u128,
1226 0x0000_0000_0000_0000_0000_0000_0000_0100,
1227 0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
1228 0x8000_0000_0000_0000_0000_0000_0000_0000,
1229 0x8100_0000_0000_0000_0000_0000_0000_0000,
1230 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_fe00,
1231 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
1232 ] {
1233 let uu = *hi | u128::from(u);
1234 let fuu = U121F7::from_bits(uu);
1235 assert_eq!(fuu.to_num::<f16>(), f16::from_f64(uu as f64 / 128.0));
1236 let ii = uu as i128;
1237 let fii = I121F7::from_bits(ii);
1238 assert_eq!(fii.to_num::<f16>(), f16::from_f64(ii as f64 / 128.0));
1239 }
1240 }
1241 }
1242
1243 #[cfg(feature = "f16")]
1244 #[test]
1245 fn to_bf16() {
1246 use half::bf16;
1247 for u in 0x00..=0xff {
1248 let fu = U1F7::from_bits(u);
1249 assert_eq!(fu.to_num::<bf16>(), bf16::from_f32(f32::from(u) / 128.0));
1250 let i = u as i8;
1251 let fi = I1F7::from_bits(i);
1252 assert_eq!(fi.to_num::<bf16>(), bf16::from_f32(f32::from(i) / 128.0));
1253
1254 for hi in &[
1255 0u32,
1256 0x0000_0100,
1257 0x7fff_ff00,
1258 0x8000_0000,
1259 0x8100_0000,
1260 0xffff_fe00,
1261 0xffff_ff00,
1262 ] {
1263 let uu = *hi | u32::from(u);
1264 let fuu = U25F7::from_bits(uu);
1265 assert_eq!(fuu.to_num::<bf16>(), bf16::from_f32(uu as f32 / 128.0));
1266 let ii = uu as i32;
1267 let fii = I25F7::from_bits(ii);
1268 assert_eq!(fii.to_num::<bf16>(), bf16::from_f32(ii as f32 / 128.0));
1269 }
1270
1271 for hi in &[
1272 0u128,
1273 0x0000_0000_0000_0000_0000_0000_0000_0100,
1274 0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
1275 0x8000_0000_0000_0000_0000_0000_0000_0000,
1276 0x8100_0000_0000_0000_0000_0000_0000_0000,
1277 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_fe00,
1278 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
1279 ] {
1280 let uu = *hi | u128::from(u);
1281 let fuu = U121F7::from_bits(uu);
1282 assert_eq!(fuu.to_num::<bf16>(), bf16::from_f64(uu as f64 / 128.0));
1283 let ii = uu as i128;
1284 let fii = I121F7::from_bits(ii);
1285 assert_eq!(fii.to_num::<bf16>(), bf16::from_f64(ii as f64 / 128.0));
1286 }
1287 }
1288 }
1289
1290 #[test]
1291 fn to_f32() {
1292 for u in 0x00..=0xff {
1293 let fu = U1F7::from_bits(u);
1294 assert_eq!(fu.to_num::<f32>(), f32::from(u) / 128.0);
1295 let i = u as i8;
1296 let fi = I1F7::from_bits(i);
1297 assert_eq!(fi.to_num::<f32>(), f32::from(i) / 128.0);
1298
1299 for hi in &[
1300 0u32,
1301 0x0000_0100,
1302 0x7fff_ff00,
1303 0x8000_0000,
1304 0x8100_0000,
1305 0xffff_fe00,
1306 0xffff_ff00,
1307 ] {
1308 let uu = *hi | u32::from(u);
1309 let fuu = U25F7::from_bits(uu);
1310 assert_eq!(fuu.to_num::<f32>(), uu as f32 / 128.0);
1311 let ii = uu as i32;
1312 let fii = I25F7::from_bits(ii);
1313 assert_eq!(fii.to_num::<f32>(), ii as f32 / 128.0);
1314 }
1315
1316 for hi in &[
1317 0u128,
1318 0x0000_0000_0000_0000_0000_0000_0000_0100,
1319 0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
1320 0x8000_0000_0000_0000_0000_0000_0000_0000,
1321 0x8100_0000_0000_0000_0000_0000_0000_0000,
1322 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_fe00,
1323 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
1324 ] {
1325 let uu = *hi | u128::from(u);
1326 let fuu = U121F7::from_bits(uu);
1327 assert_eq!(fuu.to_num::<f32>(), (uu as f64 / 128.0) as f32);
1328 let ii = uu as i128;
1329 let fii = I121F7::from_bits(ii);
1330 assert_eq!(fii.to_num::<f32>(), (ii as f64 / 128.0) as f32);
1331 }
1332 }
1333 }
1334
1335 #[test]
1336 fn to_infinite_f32() {
1337 let too_large = U128F0::max_value();
1340 assert_eq!(too_large.count_ones(), 128);
1341 assert!(too_large.to_num::<f32>().is_infinite());
1342
1343 let still_too_large = too_large << 103u32;
1348 assert_eq!(still_too_large.count_ones(), 25);
1349 assert!(still_too_large.to_num::<f32>().is_infinite());
1350
1351 let not_too_large = still_too_large - U128F0::from_bits(1);
1354 assert_eq!(not_too_large.count_ones(), 127);
1355 assert!(!not_too_large.to_num::<f32>().is_infinite());
1356
1357 let min_i128 = I128F0::min_value();
1359 assert_eq!(min_i128.count_ones(), 1);
1360 assert_eq!(min_i128.to_num::<f32>(), -(127f32.exp2()));
1361 }
1362
1363 #[test]
1364 fn to_f64() {
1365 for u in 0x00..=0xff {
1366 let fu = U1F7::from_bits(u);
1367 assert_eq!(fu.to_num::<f64>(), f64::from(u) / 128.0);
1368 let i = u as i8;
1369 let fi = I1F7::from_bits(i);
1370 assert_eq!(fi.to_num::<f64>(), f64::from(i) / 128.0);
1371
1372 for hi in &[
1373 0u64,
1374 0x0000_0000_0000_0100,
1375 0x7fff_ffff_ffff_ff00,
1376 0x8000_0000_0000_0000,
1377 0x8100_0000_0000_0000,
1378 0xffff_ffff_ffff_fe00,
1379 0xffff_ffff_ffff_ff00,
1380 ] {
1381 let uu = *hi | u64::from(u);
1382 let fuu = U57F7::from_bits(uu);
1383 assert_eq!(fuu.to_num::<f64>(), uu as f64 / 128.0);
1384 let ii = uu as i64;
1385 let fii = I57F7::from_bits(ii);
1386 assert_eq!(fii.to_num::<f64>(), ii as f64 / 128.0);
1387 }
1388
1389 for hi in &[
1390 0u128,
1391 0x0000_0000_0000_0000_0000_0000_0000_0100,
1392 0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
1393 0x8000_0000_0000_0000_0000_0000_0000_0000,
1394 0x8100_0000_0000_0000_0000_0000_0000_0000,
1395 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_fe00,
1396 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
1397 ] {
1398 let uu = *hi | u128::from(u);
1399 let fuu = U121F7::from_bits(uu);
1400 assert_eq!(fuu.to_num::<f64>(), uu as f64 / 128.0);
1401 let ii = uu as i128;
1402 let fii = I121F7::from_bits(ii);
1403 assert_eq!(fii.to_num::<f64>(), ii as f64 / 128.0);
1404 }
1405 }
1406 }
1407
1408 #[cfg(feature = "f16")]
1409 #[test]
1410 fn lossy_f16() {
1411 use crate::traits::LossyFrom;
1412 use core::{f32, f64};
1413 use half::f16;
1414
1415 assert_eq!(f16::lossy_from(f32::NEG_INFINITY), f16::NEG_INFINITY);
1416 assert!(f16::lossy_from(f32::NAN).is_nan());
1417 assert_eq!(f16::lossy_from(1e-37f32), f16::from_bits(0));
1418 assert_eq!(f16::lossy_from(-32768f32 * 1.625), f16::from_bits(0xFA80));
1420 assert_eq!(f16::lossy_from(32768f32 * 2.), f16::INFINITY);
1421 assert_eq!(
1423 f16::lossy_from(f32::from(0x8020u16)),
1424 f16::from_bits(0x7801)
1425 );
1426 assert_eq!(
1428 f16::lossy_from(f32::from(0x8030u16)),
1429 f16::from_bits(0x7802)
1430 );
1431 assert_eq!(
1433 f16::lossy_from(f32::from(0x8050u16)),
1434 f16::from_bits(0x7802)
1435 );
1436 assert_eq!(f16::lossy_from((-24f32).exp2()), f16::from_bits(0x0001));
1438 assert_eq!(
1439 f16::lossy_from((-24f32).exp2() * 0.5001),
1440 f16::from_bits(0x0001)
1441 );
1442 assert_eq!(f16::lossy_from((-24f32).exp2() * 0.5), f16::from_bits(0));
1443
1444 assert_eq!(f16::lossy_from(f64::NEG_INFINITY), f16::NEG_INFINITY);
1445 assert!(f16::lossy_from(f64::NAN).is_nan());
1446 assert_eq!(f16::lossy_from(1e-37f64), f16::from_bits(0));
1447 assert_eq!(f16::lossy_from(-32768f64 * 1.625), f16::from_bits(0xFA80));
1449 assert_eq!(f16::lossy_from(32768f64 * 2.), f16::INFINITY);
1450 assert_eq!(
1452 f16::lossy_from(f64::from(0x8020u16)),
1453 f16::from_bits(0x7801)
1454 );
1455 assert_eq!(
1457 f16::lossy_from(f64::from(0x8030u16)),
1458 f16::from_bits(0x7802)
1459 );
1460 assert_eq!(
1462 f16::lossy_from(f64::from(0x8050u16)),
1463 f16::from_bits(0x7802)
1464 );
1465 assert_eq!(f16::lossy_from((-24f64).exp2()), f16::from_bits(0x0001));
1467 assert_eq!(
1468 f16::lossy_from((-24f64).exp2() * 0.5001),
1469 f16::from_bits(0x0001)
1470 );
1471 assert_eq!(f16::lossy_from((-24f32).exp2() * 0.5), f16::from_bits(0));
1472 }
1473
1474 #[cfg(feature = "f16")]
1475 #[test]
1476 fn lossy_bf16() {
1477 use crate::traits::LossyFrom;
1478 use core::{f32, f64};
1479 use half::bf16;
1480
1481 assert_eq!(bf16::lossy_from(f32::NEG_INFINITY), bf16::NEG_INFINITY);
1482 assert!(bf16::lossy_from(f32::NAN).is_nan());
1483 assert_eq!(bf16::lossy_from(f32::MIN_POSITIVE), bf16::MIN_POSITIVE);
1484 assert_eq!(
1486 bf16::lossy_from(127f32.exp2() * -1.625),
1487 bf16::from_bits(0xFF50)
1488 );
1489 assert_eq!(bf16::lossy_from(f32::MAX), bf16::INFINITY);
1491 assert_eq!(
1492 bf16::lossy_from(f32::from_bits(0x4175_7FFF)),
1493 bf16::from_bits(0x4175)
1494 );
1495 assert_eq!(
1496 bf16::lossy_from(f32::from_bits(0x4175_8000)),
1497 bf16::from_bits(0x4176)
1498 );
1499 assert_eq!(
1500 bf16::lossy_from(f32::from_bits(0x4175_8001)),
1501 bf16::from_bits(0x4176)
1502 );
1503 assert_eq!(
1504 bf16::lossy_from(f32::from_bits(0x4176_7FFF)),
1505 bf16::from_bits(0x4176)
1506 );
1507 assert_eq!(
1508 bf16::lossy_from(f32::from_bits(0x4176_8000)),
1509 bf16::from_bits(0x4176)
1510 );
1511 assert_eq!(
1512 bf16::lossy_from(f32::from_bits(0x4176_8001)),
1513 bf16::from_bits(0x4177)
1514 );
1515
1516 assert_eq!(bf16::lossy_from(f64::NEG_INFINITY), bf16::NEG_INFINITY);
1517 assert!(bf16::lossy_from(f64::NAN).is_nan());
1518 assert_eq!(bf16::lossy_from(1e-100f64), bf16::from_bits(0));
1519 assert_eq!(
1521 bf16::lossy_from(127f64.exp2() * -1.625),
1522 bf16::from_bits(0xFF50)
1523 );
1524 assert_eq!(bf16::lossy_from(128f64.exp2()), bf16::INFINITY);
1525 assert_eq!(bf16::lossy_from((-133f64).exp2()), bf16::from_bits(0x0001));
1527 assert_eq!(
1528 bf16::lossy_from((-133f64).exp2() * 0.5001),
1529 bf16::from_bits(0x0001)
1530 );
1531 assert_eq!(bf16::lossy_from((-133f32).exp2() * 0.5), bf16::from_bits(0));
1532 }
1533}