1#![allow(deprecated)]
17
18use crate::int_helper::IntFixed;
19use crate::traits::{FromFixed, LosslessTryFrom, LossyFrom, ToFixed};
20use crate::types::extra::{
21 Diff, IsLessOrEqual, LeEqU8, LeEqU16, LeEqU32, LeEqU64, LeEqU128, True, U0, U1, U7, U8, U15,
22 U16, U24, U31, U32, U63, U64, U127, U128,
23};
24use crate::{
25 F128, F128Bits, FixedI8, FixedI16, FixedI32, FixedI64, FixedI128, FixedU8, FixedU16, FixedU32,
26 FixedU64, FixedU128,
27};
28use core::ops::Sub;
29use half::{bf16 as half_bf16, f16 as half_f16};
30
31macro_rules! convert {
32 (
33 ($SrcU:ident, $SrcI:ident, $SrcBits:ident, $SrcLeEqU:ident) ->
34 ($DstU:ident, $DstI:ident, $DstBits:ident, $DstBitsM1:ident, $DstLeEqU:ident)
35 ) => {
36 impl<FracSrc: $SrcLeEqU, FracDst: $DstLeEqU> From<$SrcU<FracSrc>> for $DstU<FracDst>
37 where
38 FracSrc: IsLessOrEqual<FracDst, Output = True>,
39 $SrcBits: Sub<FracSrc>,
40 $DstBits: Sub<FracDst>,
41 Diff<$SrcBits, FracSrc>: IsLessOrEqual<Diff<$DstBits, FracDst>, Output = True>,
42 {
43 #[inline]
48 fn from(src: $SrcU<FracSrc>) -> Self {
49 let unshifted = Self::from_bits(src.to_bits().into()).to_bits();
50 let shift = FracDst::U32 - FracSrc::U32;
51 Self::from_bits(unshifted << shift)
52 }
53 }
54
55 impl<FracSrc: $SrcLeEqU, FracDst: $DstLeEqU> From<$SrcI<FracSrc>> for $DstI<FracDst>
56 where
57 FracSrc: IsLessOrEqual<FracDst, Output = True>,
58 $SrcBits: Sub<FracSrc>,
59 $DstBits: Sub<FracDst>,
60 Diff<$SrcBits, FracSrc>: IsLessOrEqual<Diff<$DstBits, FracDst>, Output = True>,
61 {
62 #[inline]
67 fn from(src: $SrcI<FracSrc>) -> Self {
68 let unshifted = Self::from_bits(src.to_bits().into()).to_bits();
69 let shift = FracDst::U32 - FracSrc::U32;
70 Self::from_bits(unshifted << shift)
71 }
72 }
73
74 impl<FracSrc: $SrcLeEqU, FracDst: $DstLeEqU> From<$SrcU<FracSrc>> for $DstI<FracDst>
75 where
76 FracSrc: IsLessOrEqual<FracDst, Output = True>,
77 $SrcBits: Sub<FracSrc>,
78 $DstBitsM1: Sub<FracDst>,
79 Diff<$SrcBits, FracSrc>: IsLessOrEqual<Diff<$DstBitsM1, FracDst>, Output = True>,
80 {
81 #[inline]
86 fn from(src: $SrcU<FracSrc>) -> Self {
87 let unshifted = Self::from_bits(src.to_bits().into()).to_bits();
88 let shift = FracDst::U32 - FracSrc::U32;
89 Self::from_bits(unshifted << shift)
90 }
91 }
92 };
93}
94
95macro_rules! convert_lossless {
96 (
97 ($Src:ident, $SrcBits:ident, $SrcLeEqU:ident) ->
98 ($Dst:ident, $DstBits:ident, $DstLeEqU:ident)
99 ) => {
100 impl<FracSrc: $SrcLeEqU, FracDst: $DstLeEqU> LosslessTryFrom<$Src<FracSrc>>
102 for $Dst<FracDst>
103 where
104 FracSrc: IsLessOrEqual<FracDst, Output = True>,
105 {
106 #[inline]
111 fn lossless_try_from(src: $Src<FracSrc>) -> Option<Self> {
112 Self::checked_from_fixed(src)
113 }
114 }
115 };
116 ($Src:ident, $SrcBits:ident, $SrcLeEqU:ident) => {
117 convert_lossless! { ($Src, $SrcBits, $SrcLeEqU) -> (FixedI8, U8, LeEqU8) }
118 convert_lossless! { ($Src, $SrcBits, $SrcLeEqU) -> (FixedI16, U16, LeEqU16) }
119 convert_lossless! { ($Src, $SrcBits, $SrcLeEqU) -> (FixedI32, U32, LeEqU32) }
120 convert_lossless! { ($Src, $SrcBits, $SrcLeEqU) -> (FixedI64, U64, LeEqU64) }
121 convert_lossless! { ($Src, $SrcBits, $SrcLeEqU) -> (FixedI128, U128, LeEqU128) }
122 convert_lossless! { ($Src, $SrcBits, $SrcLeEqU) -> (FixedU8, U8, LeEqU8) }
123 convert_lossless! { ($Src, $SrcBits, $SrcLeEqU) -> (FixedU16, U16, LeEqU16) }
124 convert_lossless! { ($Src, $SrcBits, $SrcLeEqU) -> (FixedU32, U32, LeEqU32) }
125 convert_lossless! { ($Src, $SrcBits, $SrcLeEqU) -> (FixedU64, U64, LeEqU64) }
126 convert_lossless! { ($Src, $SrcBits, $SrcLeEqU) -> (FixedU128, U128, LeEqU128) }
127 };
128}
129
130macro_rules! convert_lossy {
131 (
132 ($SrcU:ident, $SrcI:ident, $SrcBits:ident, $SrcLeEqU:ident) ->
133 ($DstU:ident, $DstI:ident, $DstBits:ident, $DstBitsM1:ident, $DstLeEqU:ident)
134 ) => {
135 impl<FracSrc: $SrcLeEqU, FracDst: $DstLeEqU> LossyFrom<$SrcU<FracSrc>> for $DstU<FracDst>
137 where
138 $SrcBits: Sub<FracSrc>,
139 $DstBits: Sub<FracDst>,
140 Diff<$SrcBits, FracSrc>: IsLessOrEqual<Diff<$DstBits, FracDst>, Output = True>,
141 {
142 #[inline]
149 fn lossy_from(src: $SrcU<FracSrc>) -> Self {
150 src.to_num()
151 }
152 }
153
154 impl<FracSrc: $SrcLeEqU, FracDst: $DstLeEqU> LossyFrom<$SrcI<FracSrc>> for $DstI<FracDst>
156 where
157 $SrcBits: Sub<FracSrc>,
158 $DstBits: Sub<FracDst>,
159 Diff<$SrcBits, FracSrc>: IsLessOrEqual<Diff<$DstBits, FracDst>, Output = True>,
160 {
161 #[inline]
168 fn lossy_from(src: $SrcI<FracSrc>) -> Self {
169 src.to_num()
170 }
171 }
172
173 impl<FracSrc: $SrcLeEqU, FracDst: $DstLeEqU> LossyFrom<$SrcU<FracSrc>> for $DstI<FracDst>
175 where
176 $SrcBits: Sub<FracSrc>,
177 $DstBitsM1: Sub<FracDst>,
178 Diff<$SrcBits, FracSrc>: IsLessOrEqual<Diff<$DstBitsM1, FracDst>, Output = True>,
179 {
180 #[inline]
187 fn lossy_from(src: $SrcU<FracSrc>) -> Self {
188 src.to_num()
189 }
190 }
191 };
192 ($SrcU:ident, $SrcI:ident, $SrcBits:ident, $SrcLeEqU:ident) => {
193 convert_lossy! {
194 ($SrcU, $SrcI, $SrcBits, $SrcLeEqU) -> (FixedU8, FixedI8, U8, U7, LeEqU8)
195 }
196 convert_lossy! {
197 ($SrcU, $SrcI, $SrcBits, $SrcLeEqU) -> (FixedU16, FixedI16, U16, U15, LeEqU16)
198 }
199 convert_lossy! {
200 ($SrcU, $SrcI, $SrcBits, $SrcLeEqU) -> (FixedU32, FixedI32, U32, U31, LeEqU32)
201 }
202 convert_lossy! {
203 ($SrcU, $SrcI, $SrcBits, $SrcLeEqU) -> (FixedU64, FixedI64, U64, U63, LeEqU64)
204 }
205 convert_lossy! {
206 ($SrcU, $SrcI, $SrcBits, $SrcLeEqU) -> (FixedU128, FixedI128, U128, U127, LeEqU128)
207 }
208 };
209}
210
211convert! { (FixedU8, FixedI8, U8, LeEqU8) -> (FixedU16, FixedI16, U16, U15, LeEqU16) }
212convert! { (FixedU8, FixedI8, U8, LeEqU8) -> (FixedU32, FixedI32, U32, U31, LeEqU32) }
213convert! { (FixedU8, FixedI8, U8, LeEqU8) -> (FixedU64, FixedI64, U64, U63, LeEqU64) }
214convert! { (FixedU8, FixedI8, U8, LeEqU8) -> (FixedU128, FixedI128, U128, U127, LeEqU128) }
215
216convert! { (FixedU16, FixedI16, U16, LeEqU16) -> (FixedU32, FixedI32, U32, U31, LeEqU32) }
217convert! { (FixedU16, FixedI16, U16, LeEqU16) -> (FixedU64, FixedI64, U64, U63, LeEqU64) }
218convert! { (FixedU16, FixedI16, U16, LeEqU16) -> (FixedU128, FixedI128, U128, U127, LeEqU128) }
219
220convert! { (FixedU32, FixedI32, U32, LeEqU32) -> (FixedU64, FixedI64, U64, U63, LeEqU64) }
221convert! { (FixedU32, FixedI32, U32, LeEqU32) -> (FixedU128, FixedI128, U128, U127, LeEqU128) }
222
223convert! { (FixedU64, FixedI64, U64, LeEqU64) -> (FixedU128, FixedI128, U128, U127, LeEqU128) }
224
225convert_lossless! { FixedI8, U8, LeEqU8 }
226convert_lossless! { FixedI16, U16, LeEqU16 }
227convert_lossless! { FixedI32, U32, LeEqU32 }
228convert_lossless! { FixedI64, U64, LeEqU64 }
229convert_lossless! { FixedI128, U128, LeEqU128 }
230convert_lossless! { FixedU8, U8, LeEqU8 }
231convert_lossless! { FixedU16, U16, LeEqU16 }
232convert_lossless! { FixedU32, U32, LeEqU32 }
233convert_lossless! { FixedU64, U64, LeEqU64 }
234convert_lossless! { FixedU128, U128, LeEqU128 }
235
236convert_lossy! { FixedU8, FixedI8, U8, LeEqU8 }
237convert_lossy! { FixedU16, FixedI16, U16, LeEqU16 }
238convert_lossy! { FixedU32, FixedI32, U32, LeEqU32 }
239convert_lossy! { FixedU64, FixedI64, U64, LeEqU64 }
240convert_lossy! { FixedU128, FixedI128, U128, LeEqU128 }
241
242macro_rules! int_to_fixed {
243 ($Src:ident, $Dst:ident, $LeEqU:ident) => {
244 impl<Frac: $LeEqU> LosslessTryFrom<$Src> for $Dst<Frac> {
245 #[inline]
250 fn lossless_try_from(src: $Src) -> Option<Self> {
251 src.checked_to_fixed()
252 }
253 }
254 };
255
256 ($Src:ident $(, $Dst:ty)?) => {
257 $(impl From<$Src> for $Dst {
258 #[inline]
263 fn from(src: $Src) -> Self {
264 Self::from_bits(src)
265 }
266 })?
267
268 int_to_fixed! { $Src, FixedI8, LeEqU8 }
269 int_to_fixed! { $Src, FixedI16, LeEqU16 }
270 int_to_fixed! { $Src, FixedI32, LeEqU32 }
271 int_to_fixed! { $Src, FixedI64, LeEqU64 }
272 int_to_fixed! { $Src, FixedI128, LeEqU128 }
273 int_to_fixed! { $Src, FixedU8, LeEqU8 }
274 int_to_fixed! { $Src, FixedU16, LeEqU16 }
275 int_to_fixed! { $Src, FixedU32, LeEqU32 }
276 int_to_fixed! { $Src, FixedU64, LeEqU64 }
277 int_to_fixed! { $Src, FixedU128, LeEqU128 }
278
279 $(impl LossyFrom<$Src> for $Dst {
280 #[inline]
285 fn lossy_from(src: $Src) -> Self {
286 Self::from_bits(src)
287 }
288 })?
289 };
290}
291
292int_to_fixed! { bool }
293int_to_fixed! { i8, FixedI8<U0> }
294int_to_fixed! { i16, FixedI16<U0> }
295int_to_fixed! { i32, FixedI32<U0> }
296int_to_fixed! { i64, FixedI64<U0> }
297int_to_fixed! { i128, FixedI128<U0> }
298int_to_fixed! { isize }
299int_to_fixed! { u8, FixedU8<U0> }
300int_to_fixed! { u16, FixedU16<U0> }
301int_to_fixed! { u32, FixedU32<U0> }
302int_to_fixed! { u64, FixedU64<U0> }
303int_to_fixed! { u128, FixedU128<U0> }
304int_to_fixed! { usize }
305
306macro_rules! int_to_wider_fixed {
307 (
308 ($SrcU:ident, $SrcI:ident, $SrcBits:ident, $SrcLeEqU:ident) ->
309 ($DstU:ident, $DstI:ident, $DstBits:ident, $DstBitsM1:ident, $DstLeEqU:ident)
310 ) => {
311 impl<FracDst: $DstLeEqU> From<$SrcU> for $DstU<FracDst>
312 where
313 $DstBits: Sub<FracDst>,
314 $SrcBits: IsLessOrEqual<Diff<$DstBits, FracDst>, Output = True>,
315 {
316 #[inline]
321 fn from(src: $SrcU) -> Self {
322 let unshifted = Self::from_bits(src.into()).to_bits();
323 let shift = FracDst::U32;
324 Self::from_bits(unshifted << shift)
325 }
326 }
327
328 impl<FracDst: $DstLeEqU> From<$SrcI> for $DstI<FracDst>
329 where
330 $DstBits: Sub<FracDst>,
331 $SrcBits: IsLessOrEqual<Diff<$DstBits, FracDst>, Output = True>,
332 {
333 #[inline]
338 fn from(src: $SrcI) -> Self {
339 let unshifted = Self::from_bits(src.into()).to_bits();
340 let shift = FracDst::U32;
341 Self::from_bits(unshifted << shift)
342 }
343 }
344
345 impl<FracDst: $DstLeEqU> From<$SrcU> for $DstI<FracDst>
346 where
347 $DstBitsM1: Sub<FracDst>,
348 $SrcBits: IsLessOrEqual<Diff<$DstBitsM1, FracDst>, Output = True>,
349 {
350 #[inline]
355 fn from(src: $SrcU) -> Self {
356 let unshifted = Self::from_bits(src.into()).to_bits();
357 let shift = FracDst::U32;
358 Self::from_bits(unshifted << shift)
359 }
360 }
361
362 impl<FracDst: $DstLeEqU> LossyFrom<$SrcU> for $DstU<FracDst>
363 where
364 $DstBits: Sub<FracDst>,
365 $SrcBits: IsLessOrEqual<Diff<$DstBits, FracDst>, Output = True>,
366 {
367 #[inline]
372 fn lossy_from(src: $SrcU) -> Self {
373 src.into()
374 }
375 }
376
377 impl<FracDst: $DstLeEqU> LossyFrom<$SrcI> for $DstI<FracDst>
378 where
379 $DstBits: Sub<FracDst>,
380 $SrcBits: IsLessOrEqual<Diff<$DstBits, FracDst>, Output = True>,
381 {
382 #[inline]
387 fn lossy_from(src: $SrcI) -> Self {
388 src.into()
389 }
390 }
391
392 impl<FracDst: $DstLeEqU> LossyFrom<$SrcU> for $DstI<FracDst>
393 where
394 $DstBitsM1: Sub<FracDst>,
395 $SrcBits: IsLessOrEqual<Diff<$DstBitsM1, FracDst>, Output = True>,
396 {
397 #[inline]
402 fn lossy_from(src: $SrcU) -> Self {
403 src.into()
404 }
405 }
406 };
407}
408
409int_to_wider_fixed! { (u8, i8, U8, LeEqU8) -> (FixedU16, FixedI16, U16, U15, LeEqU16) }
410int_to_wider_fixed! { (u8, i8, U8, LeEqU8) -> (FixedU32, FixedI32, U32, U31, LeEqU32) }
411int_to_wider_fixed! { (u8, i8, U8, LeEqU8) -> (FixedU64, FixedI64, U64, U63, LeEqU64) }
412int_to_wider_fixed! { (u8, i8, U8, LeEqU8) -> (FixedU128, FixedI128, U128, U127, LeEqU128) }
413int_to_wider_fixed! { (u16, i16, U16, LeEqU16) -> (FixedU32, FixedI32, U32, U31, LeEqU32) }
414int_to_wider_fixed! { (u16, i16, U16, LeEqU16) -> (FixedU64, FixedI64, U64, U63, LeEqU64) }
415int_to_wider_fixed! { (u16, i16, U16, LeEqU16) -> (FixedU128, FixedI128, U128, U127, LeEqU128) }
416int_to_wider_fixed! { (u32, i32, U32, LeEqU32) -> (FixedU64, FixedI64, U64, U63, LeEqU64) }
417int_to_wider_fixed! { (u32, i32, U32, LeEqU32) -> (FixedU128, FixedI128, U128, U127, LeEqU128) }
418int_to_wider_fixed! { (u64, i64, U64, LeEqU64) -> (FixedU128, FixedI128, U128, U127, LeEqU128) }
419
420macro_rules! bool_to_fixed {
421 ($DstU:ident, $DstI:ident, $DstBits:ident, $DstBitsM1:ident, $DstLeEqU:ident) => {
422 impl<FracDst: $DstLeEqU> From<bool> for $DstU<FracDst>
423 where
424 $DstBits: Sub<FracDst>,
425 U1: IsLessOrEqual<Diff<$DstBits, FracDst>, Output = True>,
426 {
427 #[inline]
432 fn from(src: bool) -> Self {
433 let unshifted = Self::from_bits(src.into()).to_bits();
434 let shift = FracDst::U32;
435 Self::from_bits(unshifted << shift)
436 }
437 }
438
439 impl<FracDst: $DstLeEqU> From<bool> for $DstI<FracDst>
440 where
441 $DstBitsM1: Sub<FracDst>,
442 U1: IsLessOrEqual<Diff<$DstBitsM1, FracDst>, Output = True>,
443 {
444 #[inline]
449 fn from(src: bool) -> Self {
450 let unshifted = Self::from_bits(src.into()).to_bits();
451 let shift = FracDst::U32;
452 Self::from_bits(unshifted << shift)
453 }
454 }
455
456 impl<FracDst: $DstLeEqU> LossyFrom<bool> for $DstU<FracDst>
457 where
458 $DstBits: Sub<FracDst>,
459 U1: IsLessOrEqual<Diff<$DstBits, FracDst>, Output = True>,
460 {
461 #[inline]
466 fn lossy_from(src: bool) -> Self {
467 src.into()
468 }
469 }
470
471 impl<FracDst: $DstLeEqU> LossyFrom<bool> for $DstI<FracDst>
472 where
473 $DstBitsM1: Sub<FracDst>,
474 U1: IsLessOrEqual<Diff<$DstBitsM1, FracDst>, Output = True>,
475 {
476 #[inline]
481 fn lossy_from(src: bool) -> Self {
482 src.into()
483 }
484 }
485 };
486}
487
488bool_to_fixed! { FixedU8, FixedI8, U8, U7, LeEqU8 }
489bool_to_fixed! { FixedU16, FixedI16, U16, U15, LeEqU16 }
490bool_to_fixed! { FixedU32, FixedI32, U32, U31, LeEqU32 }
491bool_to_fixed! { FixedU64, FixedI64, U64, U63, LeEqU64 }
492bool_to_fixed! { FixedU128, FixedI128, U128, U127, LeEqU128 }
493
494macro_rules! fixed_to_int {
495 (($SrcU:ident, $SrcI:ident) -> ($DstU:ident, $DstI:ident)) => {
496 impl From<$SrcU<U0>> for $DstU {
497 #[inline]
502 fn from(src: $SrcU<U0>) -> Self {
503 src.to_bits().into()
504 }
505 }
506
507 impl From<$SrcI<U0>> for $DstI {
508 #[inline]
513 fn from(src: $SrcI<U0>) -> Self {
514 src.to_bits().into()
515 }
516 }
517 };
518 (($SrcU:ident, $SrcI:ident) -> wider ($DstU:ident, $DstI:ident)) => {
519 fixed_to_int! { ($SrcU, $SrcI) -> ($DstU, $DstI) }
520
521 impl From<$SrcU<U0>> for $DstI {
522 #[inline]
527 fn from(src: $SrcU<U0>) -> Self {
528 src.to_bits().into()
529 }
530 }
531 };
532}
533
534fixed_to_int! { (FixedU8, FixedI8) -> (u8, i8) }
535fixed_to_int! { (FixedU8, FixedI8) -> wider (u16, i16) }
536fixed_to_int! { (FixedU8, FixedI8) -> wider (u32, i32) }
537fixed_to_int! { (FixedU8, FixedI8) -> wider (u64, i64) }
538fixed_to_int! { (FixedU8, FixedI8) -> wider (u128, i128) }
539fixed_to_int! { (FixedU8, FixedI8) -> wider (usize, isize) }
540
541fixed_to_int! { (FixedU16, FixedI16) -> (u16, i16) }
542fixed_to_int! { (FixedU16, FixedI16) -> wider (u32, i32) }
543fixed_to_int! { (FixedU16, FixedI16) -> wider (u64, i64) }
544fixed_to_int! { (FixedU16, FixedI16) -> wider (u128, i128) }
545fixed_to_int! { (FixedU16, FixedI16) -> (usize, isize) }
546
547fixed_to_int! { (FixedU32, FixedI32) -> (u32, i32) }
548fixed_to_int! { (FixedU32, FixedI32) -> wider (u64, i64) }
549fixed_to_int! { (FixedU32, FixedI32) -> wider (u128, i128) }
550
551fixed_to_int! { (FixedU64, FixedI64) -> (u64, i64) }
552fixed_to_int! { (FixedU64, FixedI64) -> wider (u128, i128) }
553
554fixed_to_int! { (FixedU128, FixedI128) -> (u128, i128) }
555
556macro_rules! fixed_to_int_lossless {
557 ($Src:ty, $Dst:ident) => {
558 impl LosslessTryFrom<$Src> for $Dst {
559 #[inline]
564 fn lossless_try_from(src: $Src) -> Option<Self> {
565 $Dst::checked_from_fixed(src)
566 }
567 }
568 };
569
570 ($Src:ty) => {
571 fixed_to_int_lossless! { $Src, i8 }
572 fixed_to_int_lossless! { $Src, i16 }
573 fixed_to_int_lossless! { $Src, i32 }
574 fixed_to_int_lossless! { $Src, i64 }
575 fixed_to_int_lossless! { $Src, i128 }
576 fixed_to_int_lossless! { $Src, isize }
577 fixed_to_int_lossless! { $Src, u8 }
578 fixed_to_int_lossless! { $Src, u16 }
579 fixed_to_int_lossless! { $Src, u32 }
580 fixed_to_int_lossless! { $Src, u64 }
581 fixed_to_int_lossless! { $Src, u128 }
582 fixed_to_int_lossless! { $Src, usize }
583 };
584}
585
586fixed_to_int_lossless! { FixedI8<U0>}
587fixed_to_int_lossless! { FixedI16<U0>}
588fixed_to_int_lossless! { FixedI32<U0>}
589fixed_to_int_lossless! { FixedI64<U0>}
590fixed_to_int_lossless! { FixedI128<U0>}
591fixed_to_int_lossless! { FixedU8<U0>}
592fixed_to_int_lossless! { FixedU16<U0>}
593fixed_to_int_lossless! { FixedU32<U0>}
594fixed_to_int_lossless! { FixedU64<U0>}
595fixed_to_int_lossless! { FixedU128<U0>}
596
597macro_rules! fixed_to_int_lossy {
598 (
599 ($SrcU:ident, $SrcI:ident, $SrcBits:ident, $SrcLeEqU:ident) ->
600 ($DstU:ident, $DstI:ident, $DstBits:ident, $DstBitsM1:ident, $DstLeEqU:ident)
601 ) => {
602 impl<FracSrc: $SrcLeEqU> LossyFrom<$SrcU<FracSrc>> for $DstU
603 where
604 $SrcBits: Sub<FracSrc>,
605 Diff<$SrcBits, FracSrc>: IsLessOrEqual<$DstBits, Output = True>,
606 {
607 #[inline]
613 fn lossy_from(src: $SrcU<FracSrc>) -> Self {
614 src.to_num()
615 }
616 }
617
618 impl<FracSrc: $SrcLeEqU> LossyFrom<$SrcI<FracSrc>> for $DstI
619 where
620 $SrcBits: Sub<FracSrc>,
621 Diff<$SrcBits, FracSrc>: IsLessOrEqual<$DstBits, Output = True>,
622 {
623 #[inline]
629 fn lossy_from(src: $SrcI<FracSrc>) -> Self {
630 src.to_num()
631 }
632 }
633
634 impl<FracSrc: $SrcLeEqU> LossyFrom<$SrcU<FracSrc>> for $DstI
635 where
636 $SrcBits: Sub<FracSrc>,
637 Diff<$SrcBits, FracSrc>: IsLessOrEqual<$DstBitsM1, Output = True>,
638 {
639 #[inline]
645 fn lossy_from(src: $SrcU<FracSrc>) -> Self {
646 src.to_num()
647 }
648 }
649 };
650 ($SrcU:ident, $SrcI:ident, $SrcBits:ident, $SrcLeEqU:ident) => {
651 fixed_to_int_lossy! {
652 ($SrcU, $SrcI, $SrcBits, $SrcLeEqU) -> (u8, i8, U8, U7, LeEqU8)
653 }
654 fixed_to_int_lossy! {
655 ($SrcU, $SrcI, $SrcBits, $SrcLeEqU) -> (u16, i16, U16, U15, LeEqU16)
656 }
657 fixed_to_int_lossy! {
658 ($SrcU, $SrcI, $SrcBits, $SrcLeEqU) -> (u32, i32, U32, U31, LeEqU32)
659 }
660 fixed_to_int_lossy! {
661 ($SrcU, $SrcI, $SrcBits, $SrcLeEqU) -> (u64, i64, U64, U63, LeEqU64)
662 }
663 fixed_to_int_lossy! {
664 ($SrcU, $SrcI, $SrcBits, $SrcLeEqU) -> (u128, i128, U128, U127, LeEqU128)
665 }
666 fixed_to_int_lossy! {
667 ($SrcU, $SrcI, $SrcBits, $SrcLeEqU) -> (usize, isize, U16, U15, LeEqU16)
668 }
669 };
670}
671
672fixed_to_int_lossy! { FixedU8, FixedI8, U8, LeEqU8 }
673fixed_to_int_lossy! { FixedU16, FixedI16, U16, LeEqU16 }
674fixed_to_int_lossy! { FixedU32, FixedI32, U32, LeEqU32 }
675fixed_to_int_lossy! { FixedU64, FixedI64, U64, LeEqU64 }
676fixed_to_int_lossy! { FixedU128, FixedI128, U128, LeEqU128 }
677
678macro_rules! float_to_fixed {
686 ($Src:ident, $Dst:ident, $LeEqU:ident) => {
687 impl<Frac: $LeEqU> LosslessTryFrom<$Src> for $Dst<Frac>
688 where
689 U24: IsLessOrEqual<Frac, Output = True>,
690 {
691 #[inline]
697 fn lossless_try_from(src: $Src) -> Option<Self> {
698 src.checked_to_fixed()
699 }
700 }
701 };
702}
703
704float_to_fixed! { half_f16, FixedI32, LeEqU32 }
705float_to_fixed! { half_f16, FixedI64, LeEqU64 }
706float_to_fixed! { half_f16, FixedI128, LeEqU128 }
707
708macro_rules! fixed_to_float {
709 ($Fixed:ident($LeEqU:ident) -> $Float:ident) => {
710 impl<Frac: $LeEqU> From<$Fixed<Frac>> for $Float {
711 #[inline]
716 fn from(src: $Fixed<Frac>) -> $Float {
717 $Float::from_fixed(src)
718 }
719 }
720
721 impl<Frac: $LeEqU> LosslessTryFrom<$Fixed<Frac>> for $Float {
722 #[inline]
727 fn lossless_try_from(src: $Fixed<Frac>) -> Option<$Float> {
728 Some($Float::from_fixed(src))
729 }
730 }
731 };
732}
733
734fixed_to_float! { FixedI8(LeEqU8) -> half_f16 }
735fixed_to_float! { FixedU8(LeEqU8) -> half_f16 }
736fixed_to_float! { FixedI8(LeEqU8) -> f32 }
737fixed_to_float! { FixedI16(LeEqU16) -> f32 }
738fixed_to_float! { FixedU8(LeEqU8) -> f32 }
739fixed_to_float! { FixedU16(LeEqU16) -> f32 }
740fixed_to_float! { FixedI8(LeEqU8) -> f64 }
741fixed_to_float! { FixedI16(LeEqU16) -> f64 }
742fixed_to_float! { FixedI32(LeEqU32) -> f64 }
743fixed_to_float! { FixedU8(LeEqU8) -> f64 }
744fixed_to_float! { FixedU16(LeEqU16) -> f64 }
745fixed_to_float! { FixedU32(LeEqU32) -> f64 }
746fixed_to_float! { FixedI8(LeEqU8) -> F128 }
747fixed_to_float! { FixedI16(LeEqU16) -> F128 }
748fixed_to_float! { FixedI32(LeEqU32) -> F128 }
749fixed_to_float! { FixedI64(LeEqU64) -> F128 }
750fixed_to_float! { FixedU8(LeEqU8) -> F128 }
751fixed_to_float! { FixedU16(LeEqU16) -> F128 }
752fixed_to_float! { FixedU32(LeEqU32) -> F128 }
753fixed_to_float! { FixedU64(LeEqU64) -> F128 }
754fixed_to_float! { FixedI8(LeEqU8) -> F128Bits }
755fixed_to_float! { FixedI16(LeEqU16) -> F128Bits }
756fixed_to_float! { FixedI32(LeEqU32) -> F128Bits }
757fixed_to_float! { FixedI64(LeEqU64) -> F128Bits }
758fixed_to_float! { FixedU8(LeEqU8) -> F128Bits }
759fixed_to_float! { FixedU16(LeEqU16) -> F128Bits }
760fixed_to_float! { FixedU32(LeEqU32) -> F128Bits }
761fixed_to_float! { FixedU64(LeEqU64) -> F128Bits }
762
763macro_rules! fixed_to_float_lossy {
764 ($Fixed:ident($LeEqU:ident) -> $Float:ident) => {
765 impl<Frac: $LeEqU> LossyFrom<$Fixed<Frac>> for $Float {
766 #[inline]
772 fn lossy_from(src: $Fixed<Frac>) -> $Float {
773 src.to_num()
774 }
775 }
776 };
777 ($Fixed:ident($LeEqU:ident)) => {
778 #[cfg(feature = "nightly-float")]
779 fixed_to_float_lossy! { $Fixed($LeEqU) -> f16 }
780 fixed_to_float_lossy! { $Fixed($LeEqU) -> half_f16 }
781 fixed_to_float_lossy! { $Fixed($LeEqU) -> half_bf16 }
782 fixed_to_float_lossy! { $Fixed($LeEqU) -> f32 }
783 fixed_to_float_lossy! { $Fixed($LeEqU) -> f64 }
784 #[cfg(feature = "nightly-float")]
785 fixed_to_float_lossy! { $Fixed($LeEqU) -> f128 }
786 fixed_to_float_lossy! { $Fixed($LeEqU) -> F128 }
787 fixed_to_float_lossy! { $Fixed($LeEqU) -> F128Bits }
788 };
789}
790
791fixed_to_float_lossy! { FixedI8(LeEqU8) }
792fixed_to_float_lossy! { FixedI16(LeEqU16) }
793fixed_to_float_lossy! { FixedI32(LeEqU32) }
794fixed_to_float_lossy! { FixedI64(LeEqU64) }
795fixed_to_float_lossy! { FixedI128(LeEqU128) }
796fixed_to_float_lossy! { FixedU8(LeEqU8) }
797fixed_to_float_lossy! { FixedU16(LeEqU16) }
798fixed_to_float_lossy! { FixedU32(LeEqU32) }
799fixed_to_float_lossy! { FixedU64(LeEqU64) }
800fixed_to_float_lossy! { FixedU128(LeEqU128) }
801
802macro_rules! int_to_float_lossy_lossless {
803 ($Int:ident -> $($Lossy:ident)*; $($Lossless:ident)*) => {
804 $(
805 impl LossyFrom<$Int> for $Lossy {
806 #[inline]
812 fn lossy_from(src: $Int) -> $Lossy {
813 Self::from_fixed(IntFixed(src).fixed())
814 }
815 }
816 )*
817 $(
818 impl LosslessTryFrom<$Int> for $Lossless {
819 #[inline]
824 fn lossless_try_from(src: $Int) -> Option<$Lossless> {
825 Some(Self::from_fixed(IntFixed(src).fixed()))
826 }
827 }
828
829 impl LossyFrom<$Int> for $Lossless {
830 #[inline]
835 fn lossy_from(src: $Int) -> $Lossless {
836 Self::from_fixed(IntFixed(src).fixed())
837 }
838 }
839 )*
840 };
841}
842
843int_to_float_lossy_lossless! { i8 -> half_bf16; half_f16 f32 f64 F128 F128Bits }
844int_to_float_lossy_lossless! { i16 -> half_bf16 half_f16; f32 f64 F128 F128Bits }
845int_to_float_lossy_lossless! { i32 -> half_bf16 half_f16 f32; f64 F128 F128Bits }
846int_to_float_lossy_lossless! { i64 -> half_bf16 half_f16 f32 f64; F128 F128Bits }
847int_to_float_lossy_lossless! { i128 -> half_bf16 half_f16 f32 f64 F128 F128Bits; }
848int_to_float_lossy_lossless! { isize -> half_bf16 half_f16 f32 f64 F128 F128Bits; }
849
850int_to_float_lossy_lossless! { u8 -> half_bf16; half_f16 f32 f64 F128 F128Bits }
851int_to_float_lossy_lossless! { u16 -> half_bf16 half_f16; f32 f64 F128 F128Bits }
852int_to_float_lossy_lossless! { u32 -> half_bf16 half_f16 f32; f64 F128 F128Bits }
853int_to_float_lossy_lossless! { u64 -> half_bf16 half_f16 f32 f64; F128 F128Bits }
854int_to_float_lossy_lossless! { u128 -> half_bf16 half_f16 f32 f64 F128 F128Bits; }
855int_to_float_lossy_lossless! { usize -> half_bf16 half_f16 f32 f64 F128 F128Bits; }
856
857macro_rules! into {
858 ($Src:ty: $($Dst:ty),*) => { $(
859 impl LosslessTryFrom<$Src> for $Dst {
860 #[inline]
865 fn lossless_try_from(src: $Src) -> Option<Self> {
866 Some(Self::from(src))
867 }
868 }
869
870 impl LossyFrom<$Src> for $Dst {
871 #[inline]
876 fn lossy_from(src: $Src) -> Self {
877 Self::from(src)
878 }
879 }
880 )* };
881}
882
883macro_rules! try_into {
884 ($Src:ty: $($Dst:ty),*) => { $(
885 impl LosslessTryFrom<$Src> for $Dst {
886 #[inline]
891 fn lossless_try_from(src: $Src) -> Option<Self> {
892 Self::try_from(src).ok()
893 }
894 }
895 )* };
896}
897
898into! { bool: bool, i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize }
899
900into! { i8: i8, i16, i32, i64, i128, isize }
901try_into! { i8: u8, u16, u32, u64, u128, usize }
902into! { i16: i16, i32, i64, i128, isize }
903try_into! { i16: i8, u8, u16, u32, u64, u128, usize }
904into! { i32: i32, i64, i128 }
905try_into! { i32: i8, i16, isize, u8, u16, u32, u64, u128, usize }
906into! { i64: i64, i128 }
907try_into! { i64: i8, i16, i32, isize, u8, u16, u32, u64, u128, usize }
908into! { i128: i128 }
909try_into! { i128: i8, i16, i32, i64, isize, u8, u16, u32, u64, u128, usize }
910into! { isize: isize }
911try_into! { isize: i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, usize }
912
913into! { u8: i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize }
914try_into! { u8: i8 }
915into! { u16: i32, i64, i128, u16, u32, u64, u128, usize }
916try_into! { u16: i8, i16, isize, u8 }
917into! { u32: i64, i128, u32, u64, u128 }
918try_into! { u32: i8, i16, i32, isize, u8, u16, usize }
919into! { u64: i128, u64, u128 }
920try_into! { u64: i8, i16, i32, i64, isize, u8, u16, u32, usize }
921into! { u128: u128 }
922try_into! { u128: i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, usize }
923into! { usize: usize }
924try_into! { usize: i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128 }
925
926macro_rules! lossy {
927 ($Src:ty: $Dst:ty; $src:ident -> $conv:expr) => {
928 impl LossyFrom<$Src> for $Dst {
929 #[inline]
930 fn lossy_from($src: $Src) -> $Dst {
936 $conv
937 }
938 }
939 };
940}
941
942into! { half_f16: half_f16 }
943lossy! { half_f16: half_bf16; src -> half_bf16::from_f32(src.into()) }
944into! { half_f16: f32, f64 }
945
946lossy! { half_bf16: half_f16; src -> half_f16::from_f32(src.into()) }
947into! { half_bf16: half_bf16, f32, f64 }
948
949lossy! { f32: half_f16; src -> half_f16::from_f32(src) }
950lossy! { f32: half_bf16; src -> half_bf16::from_f32(src) }
951into! { f32: f32, f64 }
952
953lossy! { f64: half_f16; src -> half_f16::from_f64(src) }
954lossy! { f64: half_bf16; src -> half_bf16::from_f64(src) }
955lossy! { f64: f32; src -> src as f32 }
956into! { f64: f64 }
957
958#[cfg(feature = "nightly-float")]
959mod nightly_float {
960 use crate::int_helper::IntFixed;
961 use crate::traits::{FromFixed, LosslessTryFrom, LossyFrom, ToFixed};
962 use crate::types::extra::{
963 IsLessOrEqual, LeEqU8, LeEqU16, LeEqU32, LeEqU64, LeEqU128, True, U24,
964 };
965 use crate::{
966 FixedI8, FixedI16, FixedI32, FixedI64, FixedI128, FixedU8, FixedU16, FixedU32, FixedU64,
967 };
968
969 float_to_fixed! { f16, FixedI32, LeEqU32 }
970 float_to_fixed! { f16, FixedI64, LeEqU64 }
971 float_to_fixed! { f16, FixedI128, LeEqU128 }
972
973 fixed_to_float! { FixedI8(LeEqU8) -> f16 }
974 fixed_to_float! { FixedU8(LeEqU8) -> f16 }
975 fixed_to_float! { FixedI8(LeEqU8) -> f128 }
976 fixed_to_float! { FixedI16(LeEqU16) -> f128 }
977 fixed_to_float! { FixedI32(LeEqU32) -> f128 }
978 fixed_to_float! { FixedI64(LeEqU64) -> f128 }
979 fixed_to_float! { FixedU8(LeEqU8) -> f128 }
980 fixed_to_float! { FixedU16(LeEqU16) -> f128 }
981 fixed_to_float! { FixedU32(LeEqU32) -> f128 }
982 fixed_to_float! { FixedU64(LeEqU64) -> f128 }
983
984 int_to_float_lossy_lossless! { i8 -> ; f16 f128 }
985 int_to_float_lossy_lossless! { i16 -> f16; f128 }
986 int_to_float_lossy_lossless! { i32 -> f16; f128 }
987 int_to_float_lossy_lossless! { i64 -> f16; f128 }
988 int_to_float_lossy_lossless! { i128 -> f16 f128; }
989 int_to_float_lossy_lossless! { isize -> f16 f128; }
990
991 int_to_float_lossy_lossless! { u8 -> ; f16 f128 }
992 int_to_float_lossy_lossless! { u16 -> f16; f128 }
993 int_to_float_lossy_lossless! { u32 -> f16; f128 }
994 int_to_float_lossy_lossless! { u64 -> f16; f128 }
995 int_to_float_lossy_lossless! { u128 -> f16 f128; }
996 int_to_float_lossy_lossless! { usize -> f16 f128; }
997
998 into! { f16: f16, f64, f128 }
1000 into! { f32: f128 }
1001 into! { f64: f128 }
1002 into! { f128: f128 }
1003
1004 lossy! { f32: f16; src -> src as f16 }
1005 lossy! { f64: f16; src -> src as f16 }
1006 lossy! { f128: f16; src -> src as f16 }
1007 lossy! { f128: f32; src -> src as f32 }
1008 lossy! { f128: f64; src -> src as f64 }
1009}
1010
1011fn _compile_fail_tests() {}
1156
1157#[cfg(test)]
1158mod tests {
1159 use crate::types::*;
1160
1161 #[test]
1162 fn expanding_from_unsigned() {
1163 type L8 = U8F0;
1164 type Ll16 = U16F0;
1165 type Lh16 = U8F8;
1166 type Ll128 = U128F0;
1167 type Lh128 = U8F120;
1168
1169 type H8 = U0F8;
1170 type Hl16 = U8F8;
1171 type Hh16 = U0F16;
1172 type Hl128 = U120F8;
1173 type Hh128 = U0F128;
1174
1175 let vals: &[u8] = &[0x00, 0x7f, 0x80, 0xff];
1176 for &val in vals {
1177 let val16 = u16::from(val);
1178 let val128 = u128::from(val);
1179
1180 let l = L8::from_bits(val);
1181 assert_eq!(l, L8::from(val));
1182 assert_eq!(val, u8::from(l));
1183 assert_eq!(Ll16::from(l), Ll16::from_bits(val16));
1184 assert_eq!(Lh16::from(l), Lh16::from_bits(val16 << 8));
1185 assert_eq!(Ll128::from(l), Ll128::from_bits(val128));
1186 assert_eq!(Lh128::from(l), Lh128::from_bits(val128 << 120));
1187
1188 let h = H8::from_bits(val);
1189 assert_eq!(Hl16::from(h), Hl16::from_bits(val16));
1190 assert_eq!(Hh16::from(h), Hh16::from_bits(val16 << 8));
1191 assert_eq!(Hl128::from(h), Hl128::from_bits(val128));
1192 assert_eq!(Hh128::from(h), Hh128::from_bits(val128 << 120));
1193 }
1194 }
1195
1196 #[test]
1197 fn expanding_from_signed() {
1198 type L8 = I8F0;
1199 type Ll16 = I16F0;
1200 type Lh16 = I8F8;
1201 type Ll128 = I128F0;
1202 type Lh128 = I8F120;
1203
1204 type H8 = I0F8;
1205 type Hl16 = I8F8;
1206 type Hh16 = I0F16;
1207 type Hl128 = I120F8;
1208 type Hh128 = I0F128;
1209
1210 let vals: &[i8] = &[0x00, 0x7f, -0x80, -0x01];
1211 for &val in vals {
1212 let val16 = i16::from(val);
1213 let val128 = i128::from(val);
1214
1215 let l = L8::from_bits(val);
1216 assert_eq!(l, L8::from(val));
1217 assert_eq!(val, i8::from(l));
1218 assert_eq!(Ll16::from(l), Ll16::from_bits(val16));
1219 assert_eq!(Lh16::from(l), Lh16::from_bits(val16 << 8));
1220 assert_eq!(Ll128::from(l), Ll128::from_bits(val128));
1221 assert_eq!(Lh128::from(l), Lh128::from_bits(val128 << 120));
1222
1223 let h = H8::from_bits(val);
1224 assert_eq!(Hl16::from(h), Hl16::from_bits(val16));
1225 assert_eq!(Hh16::from(h), Hh16::from_bits(val16 << 8));
1226 assert_eq!(Hl128::from(h), Hl128::from_bits(val128));
1227 assert_eq!(Hh128::from(h), Hh128::from_bits(val128 << 120));
1228 }
1229 }
1230
1231 #[test]
1232 fn expanding_from_unsigned_to_signed() {
1233 type L8 = U8F0;
1234 type Ll16 = I16F0;
1235 type Lh16 = I9F7;
1236 type Ll128 = I128F0;
1237 type Lh128 = I9F119;
1238
1239 type H8 = U0F8;
1240 type Hl16 = I8F8;
1241 type Hh16 = I1F15;
1242 type Hl128 = I120F8;
1243 type Hh128 = I1F127;
1244
1245 let vals: &[u8] = &[0x00, 0x7f, 0x80, 0xff];
1246 for &val in vals {
1247 let val16 = i16::from(val);
1248 let val128 = i128::from(val);
1249
1250 let l = L8::from_bits(val);
1251 assert_eq!(l, L8::from(val));
1252 assert_eq!(val, u8::from(l));
1253 assert_eq!(Ll16::from(l), Ll16::from_bits(val16));
1254 assert_eq!(Lh16::from(l), Lh16::from_bits(val16 << 7));
1255 assert_eq!(Ll128::from(l), Ll128::from_bits(val128));
1256 assert_eq!(Lh128::from(l), Lh128::from_bits(val128 << 119));
1257
1258 let h = H8::from_bits(val);
1259 assert_eq!(Hl16::from(h), Hl16::from_bits(val16));
1260 assert_eq!(Hh16::from(h), Hh16::from_bits(val16 << 7));
1261 assert_eq!(Hl128::from(h), Hl128::from_bits(val128));
1262 assert_eq!(Hh128::from(h), Hh128::from_bits(val128 << 119));
1263 }
1264 }
1265
1266 #[test]
1267 fn from_bool() {
1268 assert_eq!(I2F6::from(true), 1);
1269 assert_eq!(I2F6::from(false), 0);
1270 assert_eq!(I64F64::from(true), 1);
1271 assert_eq!(U1F127::from(true), 1);
1272 }
1273
1274 #[test]
1275 fn to_size() {
1276 let min_i24 = I24F8::MIN;
1277 let max_i24 = I24F8::MAX;
1278 let max_u24 = U24F8::MAX;
1279 assert_eq!(min_i24.overflowing_to_num::<isize>(), (!0 << 23, false));
1280 assert_eq!(max_i24.overflowing_to_num::<isize>(), (!(!0 << 23), false));
1281 assert_eq!(max_u24.overflowing_to_num::<isize>(), (!(!0 << 24), false));
1282 assert_eq!(min_i24.overflowing_to_num::<usize>(), (!0 << 23, true));
1283 assert_eq!(max_i24.overflowing_to_num::<usize>(), (!(!0 << 23), false));
1284 assert_eq!(max_u24.overflowing_to_num::<usize>(), (!(!0 << 24), false));
1285
1286 let min_i56 = I56F8::MIN;
1287 let max_i56 = I56F8::MAX;
1288 let max_u56 = U56F8::MAX;
1289 #[cfg(target_pointer_width = "32")]
1290 {
1291 assert_eq!(min_i56.overflowing_to_num::<isize>(), (0, true));
1292 assert_eq!(max_i56.overflowing_to_num::<isize>(), (!0, true));
1293 assert_eq!(max_u56.overflowing_to_num::<isize>(), (!0, true));
1294 assert_eq!(min_i56.overflowing_to_num::<usize>(), (0, true));
1295 assert_eq!(max_i56.overflowing_to_num::<usize>(), (!0, true));
1296 assert_eq!(max_u56.overflowing_to_num::<usize>(), (!0, true));
1297 }
1298 #[cfg(target_pointer_width = "64")]
1299 {
1300 assert_eq!(min_i56.overflowing_to_num::<isize>(), (!0 << 55, false));
1301 assert_eq!(max_i56.overflowing_to_num::<isize>(), (!(!0 << 55), false));
1302 assert_eq!(max_u56.overflowing_to_num::<isize>(), (!(!0 << 56), false));
1303 assert_eq!(min_i56.overflowing_to_num::<usize>(), (!0 << 55, true));
1304 assert_eq!(max_i56.overflowing_to_num::<usize>(), (!(!0 << 55), false));
1305 assert_eq!(max_u56.overflowing_to_num::<usize>(), (!(!0 << 56), false));
1306 }
1307
1308 let min_i120 = I120F8::MIN;
1309 let max_i120 = I120F8::MAX;
1310 let max_u120 = U120F8::MAX;
1311 assert_eq!(min_i120.overflowing_to_num::<isize>(), (0, true));
1312 assert_eq!(max_i120.overflowing_to_num::<isize>(), (!0, true));
1313 assert_eq!(max_u120.overflowing_to_num::<isize>(), (!0, true));
1314 assert_eq!(min_i120.overflowing_to_num::<usize>(), (0, true));
1315 assert_eq!(max_i120.overflowing_to_num::<usize>(), (!0, true));
1316 assert_eq!(max_u120.overflowing_to_num::<usize>(), (!0, true));
1317 }
1318
1319 #[test]
1320 fn signed_from_float() {
1321 type Fix = I4F4;
1322 assert_eq!(Fix::from_num(3.0 / 2.0), Fix::from_bits(24));
1324 assert_eq!(Fix::from_num(3.0 / 4.0), Fix::from_bits(12));
1326 assert_eq!(Fix::from_num(3.0 / 8.0), Fix::from_bits(6));
1328 assert_eq!(Fix::from_num(3.0 / 16.0), Fix::from_bits(3));
1330 assert_eq!(Fix::from_num(3.0 / 32.0), Fix::from_bits(2));
1332 assert_eq!(Fix::from_num(5.0 / 32.0), Fix::from_bits(2));
1334 assert_eq!(Fix::from_num(3.0 / 64.0), Fix::DELTA);
1336 assert_eq!(Fix::from_num(1.0 / 32.0), Fix::ZERO);
1338
1339 assert_eq!(Fix::from_num(-3.0 / 2.0), Fix::from_bits(-24));
1341 assert_eq!(Fix::from_num(-3.0 / 4.0), Fix::from_bits(-12));
1343 assert_eq!(Fix::from_num(-3.0 / 8.0), Fix::from_bits(-6));
1345 assert_eq!(Fix::from_num(-3.0 / 16.0), Fix::from_bits(-3));
1347 assert_eq!(Fix::from_num(-3.0 / 32.0), Fix::from_bits(-2));
1349 assert_eq!(Fix::from_num(-5.0 / 32.0), Fix::from_bits(-2));
1351 assert_eq!(Fix::from_num(-3.0 / 64.0), Fix::from_bits(-1));
1353 assert_eq!(Fix::from_num(-1.0 / 32.0), Fix::ZERO);
1355
1356 assert_eq!(Fix::from_num(127.0 / 16.0), Fix::from_bits(127));
1358 assert_eq!(
1360 Fix::overflowing_from_num(255.0 / 32.0),
1361 (Fix::from_bits(-128), true)
1362 );
1363
1364 assert_eq!(Fix::from_num(-127.0 / 16.0), Fix::from_bits(-127));
1366 assert_eq!(Fix::from_num(-255.0 / 32.0), Fix::from_bits(-128));
1368 assert_eq!(Fix::from_num(-257.0 / 32.0), Fix::from_bits(-128));
1370 assert_eq!(
1372 Fix::overflowing_from_num(-129.0 / 16.0),
1373 (Fix::from_bits(127), true)
1374 );
1375 }
1376
1377 #[test]
1378 fn unsigned_from_num() {
1379 type Fix = U4F4;
1380 assert_eq!(Fix::from_num(3.0 / 2.0), Fix::from_bits(24));
1382 assert_eq!(Fix::from_num(3.0 / 4.0), Fix::from_bits(12));
1384 assert_eq!(Fix::from_num(3.0 / 8.0), Fix::from_bits(6));
1386 assert_eq!(Fix::from_num(3.0 / 16.0), Fix::from_bits(3));
1388 assert_eq!(Fix::from_num(3.0 / 32.0), Fix::from_bits(2));
1390 assert_eq!(Fix::from_num(5.0 / 32.0), Fix::from_bits(2));
1392 assert_eq!(Fix::from_num(3.0 / 64.0), Fix::DELTA);
1394 assert_eq!(Fix::from_num(1.0 / 32.0), Fix::ZERO);
1396 assert_eq!(Fix::from_num(-1.0 / 32.0), Fix::ZERO);
1398 assert_eq!(
1400 Fix::overflowing_from_num(-1.0 / 16.0),
1401 (Fix::from_bits(255), true)
1402 );
1403
1404 assert_eq!(Fix::from_num(255.0 / 16.0), Fix::from_bits(255));
1406 assert_eq!(Fix::overflowing_from_num(511.0 / 32.0), (Fix::ZERO, true));
1408 }
1409
1410 #[test]
1411 fn to_f16() {
1412 use half::f16 as half_f16;
1413 for u in 0x00..=0xff {
1414 let fu = U1F7::from_bits(u);
1415 assert_eq!(
1416 fu.to_num::<half_f16>(),
1417 half_f16::from_f32(f32::from(u) / 128.0)
1418 );
1419 let i = u as i8;
1420 let fi = I1F7::from_bits(i);
1421 assert_eq!(
1422 fi.to_num::<half_f16>(),
1423 half_f16::from_f32(f32::from(i) / 128.0)
1424 );
1425
1426 for hi in &[
1427 0u32,
1428 0x0000_0100,
1429 0x7fff_ff00,
1430 0x8000_0000,
1431 0x8100_0000,
1432 0xffff_fe00,
1433 0xffff_ff00,
1434 ] {
1435 let uu = *hi | u32::from(u);
1436 let fuu = U25F7::from_bits(uu);
1437 assert_eq!(
1438 fuu.to_num::<half_f16>(),
1439 half_f16::from_f32(uu as f32 / 128.0)
1440 );
1441 let ii = uu as i32;
1442 let fii = I25F7::from_bits(ii);
1443 assert_eq!(
1444 fii.to_num::<half_f16>(),
1445 half_f16::from_f32(ii as f32 / 128.0)
1446 );
1447 }
1448
1449 for hi in &[
1450 0u128,
1451 0x0000_0000_0000_0000_0000_0000_0000_0100,
1452 0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
1453 0x8000_0000_0000_0000_0000_0000_0000_0000,
1454 0x8100_0000_0000_0000_0000_0000_0000_0000,
1455 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_fe00,
1456 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
1457 ] {
1458 let uu = *hi | u128::from(u);
1459 let fuu = U121F7::from_bits(uu);
1460 assert_eq!(
1461 fuu.to_num::<half_f16>(),
1462 half_f16::from_f64(uu as f64 / 128.0)
1463 );
1464 let ii = uu as i128;
1465 let fii = I121F7::from_bits(ii);
1466 assert_eq!(
1467 fii.to_num::<half_f16>(),
1468 half_f16::from_f64(ii as f64 / 128.0)
1469 );
1470 }
1471 }
1472 }
1473
1474 #[test]
1475 fn to_half_bf16() {
1476 use half::bf16 as half_bf16;
1477 for u in 0x00..=0xff {
1478 let fu = U1F7::from_bits(u);
1479 assert_eq!(
1480 fu.to_num::<half_bf16>(),
1481 half_bf16::from_f32(f32::from(u) / 128.0)
1482 );
1483 let i = u as i8;
1484 let fi = I1F7::from_bits(i);
1485 assert_eq!(
1486 fi.to_num::<half_bf16>(),
1487 half_bf16::from_f32(f32::from(i) / 128.0)
1488 );
1489
1490 for hi in &[
1491 0u32,
1492 0x0000_0100,
1493 0x7fff_ff00,
1494 0x8000_0000,
1495 0x8100_0000,
1496 0xffff_fe00,
1497 0xffff_ff00,
1498 ] {
1499 let uu = *hi | u32::from(u);
1500 let fuu = U25F7::from_bits(uu);
1501 assert_eq!(
1502 fuu.to_num::<half_bf16>(),
1503 half_bf16::from_f32(uu as f32 / 128.0)
1504 );
1505 let ii = uu as i32;
1506 let fii = I25F7::from_bits(ii);
1507 assert_eq!(
1508 fii.to_num::<half_bf16>(),
1509 half_bf16::from_f32(ii as f32 / 128.0)
1510 );
1511 }
1512
1513 for hi in &[
1514 0u128,
1515 0x0000_0000_0000_0000_0000_0000_0000_0100,
1516 0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
1517 0x8000_0000_0000_0000_0000_0000_0000_0000,
1518 0x8100_0000_0000_0000_0000_0000_0000_0000,
1519 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_fe00,
1520 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
1521 ] {
1522 let uu = *hi | u128::from(u);
1523 let fuu = U121F7::from_bits(uu);
1524 assert_eq!(
1525 fuu.to_num::<half_bf16>(),
1526 half_bf16::from_f64(uu as f64 / 128.0)
1527 );
1528 let ii = uu as i128;
1529 let fii = I121F7::from_bits(ii);
1530 assert_eq!(
1531 fii.to_num::<half_bf16>(),
1532 half_bf16::from_f64(ii as f64 / 128.0)
1533 );
1534 }
1535 }
1536 }
1537
1538 #[test]
1539 fn to_f32() {
1540 for u in 0x00..=0xff {
1541 let fu = U1F7::from_bits(u);
1542 assert_eq!(fu.to_num::<f32>(), f32::from(u) / 128.0);
1543 let i = u as i8;
1544 let fi = I1F7::from_bits(i);
1545 assert_eq!(fi.to_num::<f32>(), f32::from(i) / 128.0);
1546
1547 for hi in &[
1548 0u32,
1549 0x0000_0100,
1550 0x7fff_ff00,
1551 0x8000_0000,
1552 0x8100_0000,
1553 0xffff_fe00,
1554 0xffff_ff00,
1555 ] {
1556 let uu = *hi | u32::from(u);
1557 let fuu = U25F7::from_bits(uu);
1558 assert_eq!(fuu.to_num::<f32>(), uu as f32 / 128.0);
1559 let ii = uu as i32;
1560 let fii = I25F7::from_bits(ii);
1561 assert_eq!(fii.to_num::<f32>(), ii as f32 / 128.0);
1562 }
1563
1564 for hi in &[
1565 0u128,
1566 0x0000_0000_0000_0000_0000_0000_0000_0100,
1567 0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
1568 0x8000_0000_0000_0000_0000_0000_0000_0000,
1569 0x8100_0000_0000_0000_0000_0000_0000_0000,
1570 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_fe00,
1571 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
1572 ] {
1573 let uu = *hi | u128::from(u);
1574 let fuu = U121F7::from_bits(uu);
1575 assert_eq!(fuu.to_num::<f32>(), (uu as f64 / 128.0) as f32);
1576 let ii = uu as i128;
1577 let fii = I121F7::from_bits(ii);
1578 assert_eq!(fii.to_num::<f32>(), (ii as f64 / 128.0) as f32);
1579 }
1580 }
1581 }
1582
1583 #[test]
1584 fn to_infinite_f32() {
1585 let too_large = U128F0::MAX;
1588 assert_eq!(too_large.count_ones(), 128);
1589 assert!(too_large.to_num::<f32>().is_infinite());
1590
1591 let still_too_large = too_large << 103u32;
1596 assert_eq!(still_too_large.count_ones(), 25);
1597 assert!(still_too_large.to_num::<f32>().is_infinite());
1598
1599 let not_too_large = still_too_large - U128F0::DELTA;
1602 assert_eq!(not_too_large.count_ones(), 127);
1603 assert!(!not_too_large.to_num::<f32>().is_infinite());
1604
1605 let min_i128 = I128F0::MIN;
1607 assert_eq!(min_i128.count_ones(), 1);
1608 assert_eq!(min_i128.to_num::<f32>(), -(127f32.exp2()));
1609 }
1610
1611 #[test]
1612 fn to_f64() {
1613 for u in 0x00..=0xff {
1614 let fu = U1F7::from_bits(u);
1615 assert_eq!(fu.to_num::<f64>(), f64::from(u) / 128.0);
1616 let i = u as i8;
1617 let fi = I1F7::from_bits(i);
1618 assert_eq!(fi.to_num::<f64>(), f64::from(i) / 128.0);
1619
1620 for hi in &[
1621 0u64,
1622 0x0000_0000_0000_0100,
1623 0x7fff_ffff_ffff_ff00,
1624 0x8000_0000_0000_0000,
1625 0x8100_0000_0000_0000,
1626 0xffff_ffff_ffff_fe00,
1627 0xffff_ffff_ffff_ff00,
1628 ] {
1629 let uu = *hi | u64::from(u);
1630 let fuu = U57F7::from_bits(uu);
1631 assert_eq!(fuu.to_num::<f64>(), uu as f64 / 128.0);
1632 let ii = uu as i64;
1633 let fii = I57F7::from_bits(ii);
1634 assert_eq!(fii.to_num::<f64>(), ii as f64 / 128.0);
1635 }
1636
1637 for hi in &[
1638 0u128,
1639 0x0000_0000_0000_0000_0000_0000_0000_0100,
1640 0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
1641 0x8000_0000_0000_0000_0000_0000_0000_0000,
1642 0x8100_0000_0000_0000_0000_0000_0000_0000,
1643 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_fe00,
1644 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
1645 ] {
1646 let uu = *hi | u128::from(u);
1647 let fuu = U121F7::from_bits(uu);
1648 assert_eq!(fuu.to_num::<f64>(), uu as f64 / 128.0);
1649 let ii = uu as i128;
1650 let fii = I121F7::from_bits(ii);
1651 assert_eq!(fii.to_num::<f64>(), ii as f64 / 128.0);
1652 }
1653 }
1654 }
1655
1656 #[test]
1657 fn to_f128() {
1658 use crate::F128;
1659 assert_eq!(
1661 I8F8::from_bits(-0x013A).to_num::<F128>(),
1662 F128::from_bits(0xBFFF_3A00_u128 << 96)
1663 );
1664 assert_eq!(I8F8::NEG_ONE.to_num::<F128>(), F128::NEG_ONE);
1665 assert_eq!(
1667 I8F8::from_num(-0.5).to_num::<F128>(),
1668 F128::from_bits(0xBFFE_u128 << 112)
1669 );
1670 assert_eq!(
1672 I0F128::from_bits(-1).to_num::<F128>(),
1673 F128::from_bits(0xBF7F_u128 << 112)
1674 );
1675 assert_eq!(I8F8::ZERO.to_num::<F128>(), F128::from_bits(0));
1677 assert_eq!(
1679 I0F128::DELTA.to_num::<F128>(),
1680 F128::from_bits(0x3F7F_u128 << 112)
1681 );
1682 assert_eq!(
1684 I8F8::from_num(0.5).to_num::<F128>(),
1685 F128::from_bits(0x3FFE_u128 << 112)
1686 );
1687 assert_eq!(I8F8::ONE.to_num::<F128>(), F128::ONE);
1688 assert_eq!(
1690 I8F8::from_bits(0x013A).to_num::<F128>(),
1691 F128::from_bits(0x3FFF_3A00_u128 << 96)
1692 );
1693 }
1694
1695 #[test]
1696 fn to_f128_bits() {
1697 use crate::F128Bits;
1698 assert_eq!(
1700 I8F8::from_bits(-0x013A).to_num::<F128Bits>(),
1701 F128Bits(0xBFFF_3A00_u128 << 96)
1702 );
1703 assert_eq!(
1705 I8F8::NEG_ONE.to_num::<F128Bits>(),
1706 F128Bits(0xBFFF_u128 << 112)
1707 );
1708 assert_eq!(
1710 I8F8::from_num(-0.5).to_num::<F128Bits>(),
1711 F128Bits(0xBFFE_u128 << 112)
1712 );
1713 assert_eq!(
1715 I0F128::from_bits(-1).to_num::<F128Bits>(),
1716 F128Bits(0xBF7F_u128 << 112)
1717 );
1718 assert_eq!(I8F8::ZERO.to_num::<F128Bits>(), F128Bits(0));
1720 assert_eq!(
1722 I0F128::DELTA.to_num::<F128Bits>(),
1723 F128Bits(0x3F7F_u128 << 112)
1724 );
1725 assert_eq!(
1727 I8F8::from_num(0.5).to_num::<F128Bits>(),
1728 F128Bits(0x3FFE_u128 << 112)
1729 );
1730 assert_eq!(I8F8::ONE.to_num::<F128Bits>(), F128Bits(0x3FFF_u128 << 112));
1732 assert_eq!(
1734 I8F8::from_bits(0x013A).to_num::<F128Bits>(),
1735 F128Bits(0x3FFF_3A00_u128 << 96)
1736 );
1737 }
1738
1739 #[test]
1740 fn lossy_f16() {
1741 use crate::traits::LossyFrom;
1742 use half::f16 as half_f16;
1743
1744 assert_eq!(
1745 half_f16::lossy_from(f32::NEG_INFINITY),
1746 half_f16::NEG_INFINITY
1747 );
1748 assert!(half_f16::lossy_from(f32::NAN).is_nan());
1749 assert_eq!(half_f16::lossy_from(1e-37f32), half_f16::ZERO);
1750 assert_eq!(
1752 half_f16::lossy_from(-32768f32 * 1.625),
1753 half_f16::from_bits(0xFA80)
1754 );
1755 assert_eq!(half_f16::lossy_from(32768f32 * 2.), half_f16::INFINITY);
1756 assert_eq!(
1758 half_f16::lossy_from(f32::from(0x8020u16)),
1759 half_f16::from_bits(0x7801)
1760 );
1761 assert_eq!(
1763 half_f16::lossy_from(f32::from(0x8030u16)),
1764 half_f16::from_bits(0x7802)
1765 );
1766 assert_eq!(
1768 half_f16::lossy_from(f32::from(0x8050u16)),
1769 half_f16::from_bits(0x7802)
1770 );
1771 assert_eq!(
1773 half_f16::lossy_from((-24f32).exp2()),
1774 half_f16::from_bits(0x0001)
1775 );
1776 assert_eq!(
1777 half_f16::lossy_from((-24f32).exp2() * 0.5001),
1778 half_f16::from_bits(0x0001)
1779 );
1780 assert_eq!(half_f16::lossy_from((-24f32).exp2() * 0.5), half_f16::ZERO);
1781
1782 assert_eq!(
1783 half_f16::lossy_from(f64::NEG_INFINITY),
1784 half_f16::NEG_INFINITY
1785 );
1786 assert!(half_f16::lossy_from(f64::NAN).is_nan());
1787 assert_eq!(half_f16::lossy_from(1e-37f64), half_f16::ZERO);
1788 assert_eq!(
1790 half_f16::lossy_from(-32768f64 * 1.625),
1791 half_f16::from_bits(0xFA80)
1792 );
1793 assert_eq!(half_f16::lossy_from(32768f64 * 2.), half_f16::INFINITY);
1794 assert_eq!(
1796 half_f16::lossy_from(f64::from(0x8020u16)),
1797 half_f16::from_bits(0x7801)
1798 );
1799 assert_eq!(
1801 half_f16::lossy_from(f64::from(0x8030u16)),
1802 half_f16::from_bits(0x7802)
1803 );
1804 assert_eq!(
1806 half_f16::lossy_from(f64::from(0x8050u16)),
1807 half_f16::from_bits(0x7802)
1808 );
1809 assert_eq!(
1811 half_f16::lossy_from((-24f64).exp2()),
1812 half_f16::from_bits(0x0001)
1813 );
1814 assert_eq!(
1815 half_f16::lossy_from((-24f64).exp2() * 0.5001),
1816 half_f16::from_bits(0x0001)
1817 );
1818 assert_eq!(half_f16::lossy_from((-24f32).exp2() * 0.5), half_f16::ZERO);
1819 }
1820
1821 #[test]
1822 fn lossy_half_bf16() {
1823 use crate::traits::LossyFrom;
1824 use half::bf16 as half_bf16;
1825
1826 assert_eq!(
1827 half_bf16::lossy_from(f32::NEG_INFINITY),
1828 half_bf16::NEG_INFINITY
1829 );
1830 assert!(half_bf16::lossy_from(f32::NAN).is_nan());
1831 assert_eq!(
1832 half_bf16::lossy_from(f32::MIN_POSITIVE),
1833 half_bf16::MIN_POSITIVE
1834 );
1835 assert_eq!(
1837 half_bf16::lossy_from(127f32.exp2() * -1.625),
1838 half_bf16::from_bits(0xFF50)
1839 );
1840 assert_eq!(half_bf16::lossy_from(f32::MAX), half_bf16::INFINITY);
1842 assert_eq!(
1843 half_bf16::lossy_from(f32::from_bits(0x4175_7FFF)),
1844 half_bf16::from_bits(0x4175)
1845 );
1846 assert_eq!(
1847 half_bf16::lossy_from(f32::from_bits(0x4175_8000)),
1848 half_bf16::from_bits(0x4176)
1849 );
1850 assert_eq!(
1851 half_bf16::lossy_from(f32::from_bits(0x4175_8001)),
1852 half_bf16::from_bits(0x4176)
1853 );
1854 assert_eq!(
1855 half_bf16::lossy_from(f32::from_bits(0x4176_7FFF)),
1856 half_bf16::from_bits(0x4176)
1857 );
1858 assert_eq!(
1859 half_bf16::lossy_from(f32::from_bits(0x4176_8000)),
1860 half_bf16::from_bits(0x4176)
1861 );
1862 assert_eq!(
1863 half_bf16::lossy_from(f32::from_bits(0x4176_8001)),
1864 half_bf16::from_bits(0x4177)
1865 );
1866
1867 assert_eq!(
1868 half_bf16::lossy_from(f64::NEG_INFINITY),
1869 half_bf16::NEG_INFINITY
1870 );
1871 assert!(half_bf16::lossy_from(f64::NAN).is_nan());
1872 assert_eq!(half_bf16::lossy_from(1e-100f64), half_bf16::ZERO);
1873 assert_eq!(
1875 half_bf16::lossy_from(127f64.exp2() * -1.625),
1876 half_bf16::from_bits(0xFF50)
1877 );
1878 assert_eq!(half_bf16::lossy_from(128f64.exp2()), half_bf16::INFINITY);
1879 assert_eq!(
1881 half_bf16::lossy_from((-133f64).exp2()),
1882 half_bf16::from_bits(0x0001)
1883 );
1884 assert_eq!(
1885 half_bf16::lossy_from((-133f64).exp2() * 0.5001),
1886 half_bf16::from_bits(0x0001)
1887 );
1888 assert_eq!(
1889 half_bf16::lossy_from((-133f32).exp2() * 0.5),
1890 half_bf16::ZERO
1891 );
1892 }
1893
1894 #[test]
1895 fn keep_nothing() {
1896 assert_eq!(I32F0::from_num(I0F32::MIN), -1);
1897 assert_eq!(I32F0::from_num(I0F32::MAX), 0);
1898 assert_eq!(I32F0::from_num(U0F32::MIN), 0);
1899 assert_eq!(I32F0::from_num(U0F32::MAX), 0);
1900 assert_eq!(U32F0::checked_from_num(I0F32::MIN), None);
1901 assert_eq!(U32F0::from_num(I0F32::MAX), 0);
1902 assert_eq!(U32F0::from_num(U0F32::MIN), 0);
1903 assert_eq!(U32F0::from_num(U0F32::MAX), 0);
1904
1905 assert_eq!(I0F32::from_num(I32F0::ZERO), 0);
1906 assert_eq!(I0F32::from_num(U32F0::ZERO), 0);
1907 assert_eq!(U0F32::from_num(I32F0::ZERO), 0);
1908 assert_eq!(U0F32::from_num(U32F0::ZERO), 0);
1909
1910 assert_eq!(I128F0::from_num(I0F128::MIN), -1);
1911 assert_eq!(I128F0::from_num(I0F128::MAX), 0);
1912 assert_eq!(I128F0::from_num(U0F128::MIN), 0);
1913 assert_eq!(I128F0::from_num(U0F128::MAX), 0);
1914 assert_eq!(U128F0::checked_from_num(I0F128::MIN), None);
1915 assert_eq!(U128F0::from_num(I0F128::MAX), 0);
1916 assert_eq!(U128F0::from_num(U0F128::MIN), 0);
1917 assert_eq!(U128F0::from_num(U0F128::MAX), 0);
1918
1919 assert_eq!(I0F128::from_num(I128F0::ZERO), 0);
1920 assert_eq!(I0F128::from_num(U128F0::ZERO), 0);
1921 assert_eq!(U0F128::from_num(I128F0::ZERO), 0);
1922 assert_eq!(U0F128::from_num(U128F0::ZERO), 0);
1923 }
1924}