1use crate::int_helper;
17use crate::types::extra::{LeEqU8, LeEqU16, LeEqU32, LeEqU64, LeEqU128};
18use crate::{
19 FixedI8, FixedI16, FixedI32, FixedI64, FixedI128, FixedU8, FixedU16, FixedU32, FixedU64,
20 FixedU128,
21};
22use core::cmp::Ordering;
23
24pub enum Widest {
27 Unsigned(u128),
28 Negative(i128),
29}
30
31pub struct ToFixedHelper {
32 pub(crate) bits: Widest,
33 pub(crate) dir: Ordering,
34 pub(crate) overflow: bool,
35}
36
37pub struct ToFloatHelper {
38 pub(crate) neg: bool,
39 pub(crate) abs: u128,
40}
41
42pub struct FromFloatHelper {
43 pub(crate) kind: FloatKind,
44}
45pub enum FloatKind {
46 NaN,
47 Infinite { neg: bool },
48 Finite { neg: bool, conv: ToFixedHelper },
49}
50
51pub struct Private;
52
53pub trait Sealed: Copy {
54 fn to_fixed_helper(self, _: Private, dst_frac_nbits: u32, dst_int_nbits: u32) -> ToFixedHelper;
55 fn to_float_helper(self, _: Private) -> ToFloatHelper;
56 fn saturating_from_float_helper(_: Private, src: FromFloatHelper) -> Self;
57 fn overflowing_from_float_helper(_: Private, src: FromFloatHelper) -> (Self, bool);
58}
59macro_rules! impl_sealed {
60 ($Fixed:ident($LeEqU:ident, $Signedness:ident, $Inner:ident)) => {
61 impl<Frac: $LeEqU> Sealed for $Fixed<Frac> {
62 #[inline]
63 fn to_fixed_helper(
64 self,
65 _: Private,
66 dst_frac_nbits: u32,
67 dst_int_nbits: u32,
68 ) -> ToFixedHelper {
69 int_helper::$Inner::to_fixed_helper(
70 self.to_bits(),
71 Self::FRAC_NBITS as i32,
72 dst_frac_nbits,
73 dst_int_nbits,
74 )
75 }
76 #[inline]
77 fn to_float_helper(self, _: Private) -> ToFloatHelper {
78 let (neg, abs) = int_helper::$Inner::neg_abs(self.to_bits());
79 let abs = abs.into();
80 ToFloatHelper { neg, abs }
81 }
82 #[inline]
83 fn saturating_from_float_helper(_: Private, src: FromFloatHelper) -> Self {
84 let neg = match src.kind {
85 FloatKind::NaN => panic!("NaN"),
86 FloatKind::Infinite { neg } => neg,
87 FloatKind::Finite { neg, .. } => neg,
88 };
89 let saturated = if neg { Self::MIN } else { Self::MAX };
90 let FloatKind::Finite { conv, .. } = src.kind else {
91 return saturated;
92 };
93 if conv.overflow {
94 return saturated;
95 }
96 let bits = if_signed_unsigned!(
97 $Signedness,
98 match conv.bits {
99 Widest::Unsigned(bits) => {
100 let bits = bits as _;
101 if bits < 0 {
102 return Self::MAX;
103 }
104 bits
105 }
106 Widest::Negative(bits) => bits as _,
107 },
108 match conv.bits {
109 Widest::Unsigned(bits) => bits as _,
110 Widest::Negative(_) => return Self::MIN,
111 },
112 );
113 Self::from_bits(bits)
114 }
115 #[inline]
116 #[track_caller]
117 fn overflowing_from_float_helper(_: Private, src: FromFloatHelper) -> (Self, bool) {
118 let conv = match src.kind {
119 FloatKind::NaN => panic!("NaN"),
120 FloatKind::Infinite { .. } => panic!("infinite"),
121 FloatKind::Finite { conv, .. } => conv,
122 };
123 let mut new_overflow = false;
124 let bits = if_signed_unsigned!(
125 $Signedness,
126 match conv.bits {
127 Widest::Unsigned(bits) => {
128 let bits = bits as _;
129 if bits < 0 {
130 new_overflow = true;
131 }
132 bits
133 }
134 Widest::Negative(bits) => bits as _,
135 },
136 match conv.bits {
137 Widest::Unsigned(bits) => bits as _,
138 Widest::Negative(bits) => {
139 new_overflow = true;
140 bits as _
141 }
142 },
143 );
144 (Self::from_bits(bits), conv.overflow || new_overflow)
145 }
146 }
147 };
148}
149
150impl_sealed! { FixedI8(LeEqU8, Signed, i8) }
151impl_sealed! { FixedI16(LeEqU16, Signed, i16) }
152impl_sealed! { FixedI32(LeEqU32, Signed, i32) }
153impl_sealed! { FixedI64(LeEqU64, Signed, i64) }
154impl_sealed! { FixedI128(LeEqU128, Signed, i128) }
155impl_sealed! { FixedU8(LeEqU8, Unsigned, u8) }
156impl_sealed! { FixedU16(LeEqU16, Unsigned, u16) }
157impl_sealed! { FixedU32(LeEqU32, Unsigned, u32) }
158impl_sealed! { FixedU64(LeEqU64, Unsigned, u64) }
159impl_sealed! { FixedU128(LeEqU128, Unsigned, u128) }