fast_posit/posit/convert/
posit.rs1use super::*;
2use crate::underlying::const_as;
3
4impl<
5 const N1: u32,
6 const ES1: u32,
7 Int1: crate::Int,
8> Posit<N1, ES1, Int1> {
9 fn round_from_fast<
11 const N2: u32,
12 const ES2: u32,
13 Int2: crate::Int,
14 >(self) -> Posit<N2, ES2, Int2> {
15 if const { ES1 != ES2 } { unimplemented!() }
16 if const { N1 <= N2 } {
17 let bits = const_as::<Int1, Int2>(self.to_bits()) << (N2 - N1);
19 unsafe { Posit::from_bits_unchecked(bits) }
22 } else {
23 let sticky: Int2 = Int2::from(self.to_bits().mask_lsb(N1 - N2 - 1) != Int1::ZERO);
27 let round: Int2 = const_as(self.to_bits() >> (N1 - N2 - 1));
28 let bits = const_as::<Int1, Int2>(self.to_bits() >> (N1 - N2));
41 let round_up = round & (bits | sticky) & Int2::ONE;
42 let is_special = Posit::<N2, ES2, Int2>::from_bits(bits).is_special();
50 let round_up = round_up | ((round | sticky) & Int2::from(is_special));
51 let bits_rounded = Posit::<N2, ES2, Int2>::sign_extend(bits.wrapping_add(round_up));
52 let overflow = !(bits_rounded ^ bits).is_positive();
53 Posit::from_bits(bits_rounded.wrapping_sub(Int2::from(overflow)))
54 }
55 }
56
57 fn round_from_slow<
59 const N2: u32,
60 const ES2: u32,
61 Int2: crate::Int,
62 >(self) -> Posit<N2, ES2, Int2> {
63 if self == Self::ZERO {
64 Posit::ZERO
65 } else if self == Self::NAR {
66 Posit::NAR
67 } else {
68 let decoded = unsafe { self.decode_regular() };
70 let shift_right = if const { Int1::BITS <= Int2::BITS } {0} else {Int1::BITS - Int2::BITS};
72 let shift_left = if const { Int1::BITS >= Int2::BITS } {0} else {Int2::BITS - Int1::BITS};
73 let frac = const_as::<Int1, Int2>(decoded.frac >> shift_right) << shift_left;
74 let exp = const_as::<Int1, Int2>(decoded.exp);
75 let sticky = Int2::from(decoded.frac.mask_lsb(shift_right) != Int1::ZERO);
77 if Int1::BITS > Int2::BITS
80 && Self::MAX_EXP >= const_as(Decoded::<N2, ES2, Int2>::FRAC_DENOM)
81 && decoded.exp.abs() >= const_as(Decoded::<N2, ES2, Int2>::FRAC_DENOM) {
82 let exp = Decoded::<N2, ES2, Int2>::FRAC_DENOM - Int2::ONE;
84 let exp = if decoded.exp.is_positive() {exp} else {-exp};
85 return unsafe { Decoded{frac, exp}.encode_regular() }
88 }
89 unsafe { Decoded{frac, exp}.encode_regular_round(sticky) }
93 }
94 }
95}
96
97impl<
108 const N: u32,
109 const ES: u32,
110 Int: crate::Int,
111> Posit<N, ES, Int> {
112 pub fn convert<
130 const N2: u32,
131 const ES2: u32,
132 Int2: crate::Int,
133 >(self) -> Posit<N2, ES2, Int2> {
134 if const { ES == ES2 } {
135 self.round_from_fast()
138 } else {
139 self.round_from_slow()
141 }
142 }
143}
144
145#[cfg(test)]
146#[allow(non_camel_case_types)]
147mod tests {
148 use super::*;
149 use malachite::rational::Rational;
150 use proptest::prelude::*;
151
152 macro_rules! test_exhaustive {
153 ($name: ident, $src:ty, $dst:ty) => {
154 #[test]
155 fn $name() {
156 for src in <$src>::cases_exhaustive_all() {
157 let dst: $dst = src.convert();
158 assert!(super::rational::try_is_correct_rounded(Rational::try_from(src), dst))
159 }
160 }
161 };
162 }
163
164 macro_rules! test_proptest {
165 ($name: ident, $src:ty, $dst:ty) => {
166 proptest!{
167 #![proptest_config(ProptestConfig::with_cases(crate::PROPTEST_CASES))]
168 #[test]
169 fn $name(src in <$src>::cases_proptest_all()) {
170 let dst: $dst = src.convert();
171 assert!(super::rational::try_is_correct_rounded(Rational::try_from(src), dst))
172 }
173 }
174 };
175 }
176
177 macro_rules! make_suite {
178 ($macro_name: ident, $name_src:ident, $src:ty) => {
179 mod $name_src {
180 use super::*;
181 $macro_name!{posit_10_0, $src, Posit<10, 0, i16>}
182 $macro_name!{posit_10_1, $src, Posit<10, 1, i16>}
183 $macro_name!{posit_10_2, $src, Posit<10, 2, i16>}
184 $macro_name!{posit_10_3, $src, Posit<10, 3, i16>}
185 $macro_name!{posit_8_0, $src, Posit<8, 0, i8>}
186 $macro_name!{posit_20_4, $src, Posit<20, 4, i32>}
187 $macro_name!{p8, $src, crate::p8}
188 $macro_name!{p16, $src, crate::p16}
189 $macro_name!{p32, $src, crate::p32}
190 $macro_name!{p64, $src, crate::p64}
191 $macro_name!{posit_3_0, $src, Posit<3, 0, i8>}
192 $macro_name!{posit_4_0, $src, Posit<4, 0, i8>}
193 $macro_name!{posit_4_1, $src, Posit<4, 1, i8>}
194 }
195 };
196 }
197
198 make_suite!{test_proptest, posit_10_0, Posit<10, 0, i16>}
199 make_suite!{test_proptest, posit_10_1, Posit<10, 1, i16>}
200 make_suite!{test_proptest, posit_10_2, Posit<10, 2, i16>}
201 make_suite!{test_proptest, posit_10_3, Posit<10, 3, i16>}
202
203 make_suite!{test_proptest, posit_8_0, Posit<8, 0, i8>}
204 make_suite!{test_proptest, posit_20_4, Posit<20, 4, i32>}
205
206 make_suite!{test_proptest, p8, crate::p8}
207 make_suite!{test_proptest, p16, crate::p16}
208 make_suite!{test_proptest, p32, crate::p32}
209 make_suite!{test_proptest, p64, crate::p64}
210
211 make_suite!{test_proptest, posit_3_0, Posit<3, 0, i8>}
212 make_suite!{test_proptest, posit_4_0, Posit<4, 0, i8>}
213 make_suite!{test_proptest, posit_4_1, Posit<4, 1, i8>}
214}