1use core::num::FpCategory;
6
7use crate::{
8 Approximation::{self, *},
9 Sign::{self, *},
10};
11
12pub trait BitTest {
33 fn bit_len(&self) -> usize;
47
48 fn bit(&self, n: usize) -> bool;
50}
51
52pub trait PowerOfTwo {
63 fn is_power_of_two(&self) -> bool;
65 fn next_power_of_two(self) -> Self;
67}
68
69macro_rules! impl_bit_ops_for_uint {
70 ($($T:ty)*) => {$(
71 impl BitTest for $T {
72 #[inline]
73 fn bit_len(&self) -> usize {
74 (<$T>::BITS - self.leading_zeros()) as usize
75 }
76 #[inline]
77 fn bit(&self, position: usize) -> bool {
78 if position >= <$T>::BITS as usize {
79 return false;
80 } else {
81 self & (1 << position) > 0
82 }
83 }
84 }
85
86 impl PowerOfTwo for $T {
87 #[inline]
88 fn is_power_of_two(&self) -> bool {
89 <$T>::is_power_of_two(*self)
90 }
91 #[inline]
92 fn next_power_of_two(self) -> $T {
93 <$T>::next_power_of_two(self)
94 }
95 }
96 )*}
97}
98impl_bit_ops_for_uint!(u8 u16 u32 u64 u128 usize);
99
100macro_rules! impl_bit_ops_for_int {
101 ($($T:ty)*) => {$(
102 impl BitTest for $T {
103 #[inline]
104 fn bit_len(&self) -> usize {
105 self.unsigned_abs().bit_len()
106 }
107 #[inline]
108 fn bit(&self, position: usize) -> bool {
109 if position >= <$T>::BITS as usize {
110 return self < &0;
111 } else {
112 self & (1 << position) > 0
113 }
114 }
115 }
116 )*}
117}
118impl_bit_ops_for_int!(i8 i16 i32 i64 i128 isize);
119
120pub trait FloatEncoding {
139 type Mantissa;
141 type Exponent;
143
144 fn decode(self) -> Result<(Self::Mantissa, Self::Exponent), FpCategory>;
149
150 fn encode(mantissa: Self::Mantissa, exponent: Self::Exponent) -> Approximation<Self, Sign>
161 where
162 Self: Sized;
163}
164
165#[inline]
168fn round_to_even_adjustment(bits: u8) -> bool {
169 bits >= 0b110 || bits == 0b011
170}
171
172impl FloatEncoding for f32 {
173 type Mantissa = i32;
174 type Exponent = i16;
175
176 #[inline]
177 fn decode(self) -> Result<(i32, i16), FpCategory> {
178 let bits: u32 = self.to_bits();
179 let sign_bit = bits >> 31;
180 let mantissa_bits = bits & 0x7fffff;
181
182 let mut exponent = ((bits >> 23) & 0xff) as i16;
184 if exponent == 0xff {
185 return if mantissa_bits != 0 {
186 Err(FpCategory::Nan)
187 } else {
188 Err(FpCategory::Infinite)
189 };
190 }
191
192 let mantissa = if exponent == 0 {
194 exponent = -126 - 23;
196 mantissa_bits
197 } else {
198 exponent -= 127 + 23; mantissa_bits | 0x800000
201 } as i32;
202
203 let sign = Sign::from(sign_bit > 0);
204 Ok((mantissa * sign, exponent))
205 }
206
207 #[inline]
208 fn encode(mantissa: i32, exponent: i16) -> Approximation<Self, Sign> {
209 if mantissa == 0 {
210 return Exact(0f32);
211 }
212
213 let sign = (mantissa < 0) as u32;
215 let mut mantissa = mantissa.unsigned_abs();
216
217 let zeros = mantissa.leading_zeros();
218 let top_bit = (u32::BITS - zeros) as i16 + exponent;
219
220 if top_bit > 128 {
221 return if sign == 0 {
223 Inexact(f32::INFINITY, Sign::Positive)
224 } else {
225 Inexact(f32::NEG_INFINITY, Sign::Negative)
226 };
227 } else if top_bit < -125 - 23 {
228 return if sign == 0 {
230 Inexact(0f32, Sign::Negative)
231 } else {
232 Inexact(-0f32, Sign::Positive)
233 };
234 };
235
236 let bits; let round_bits; if top_bit <= -125 {
239 let shift = exponent + 126 + 23;
244 if shift >= 0 {
245 round_bits = 0; mantissa <<= shift as u32;
247 } else {
248 let shifted = mantissa << (30 + shift) as u32;
249 round_bits = (shifted >> 28 & 0b110) as u8 | ((shifted & 0xfffffff) != 0) as u8;
250 mantissa >>= (-shift) as u32;
251 }
252
253 bits = (sign << 31) | mantissa;
255 } else {
256 if mantissa == 1 {
259 mantissa = 0; } else {
261 mantissa <<= zeros + 1;
262 }
263
264 let exponent = (exponent + 127 + u32::BITS as i16) as u32 - zeros - 1;
266
267 bits = (sign << 31) | (exponent << 23) | (mantissa >> 9);
269
270 round_bits = ((mantissa >> 7) & 0b110) as u8 | ((mantissa & 0x7f) != 0) as u8;
272 };
273
274 if round_bits & 0b11 == 0 {
275 Exact(f32::from_bits(bits))
277 } else {
278 let sign = Sign::from(sign > 0);
279 if round_to_even_adjustment(round_bits) {
280 Inexact(f32::from_bits(bits + 1), Positive * sign)
283 } else {
284 Inexact(f32::from_bits(bits), Negative * sign)
285 }
286 }
287 }
288}
289
290impl FloatEncoding for f64 {
291 type Mantissa = i64;
292 type Exponent = i16;
293
294 #[inline]
295 fn decode(self) -> Result<(i64, i16), FpCategory> {
296 let bits: u64 = self.to_bits();
297 let sign_bit = bits >> 63;
298 let mantissa_bits = bits & 0xfffffffffffff;
299
300 let mut exponent = ((bits >> 52) & 0x7ff) as i16;
302 if exponent == 0x7ff {
303 return if mantissa_bits != 0 {
304 Err(FpCategory::Nan)
305 } else {
306 Err(FpCategory::Infinite)
307 };
308 }
309
310 let mantissa = if exponent == 0 {
312 exponent = -1022 - 52;
314 mantissa_bits
315 } else {
316 exponent -= 1023 + 52; mantissa_bits | 0x10000000000000
319 } as i64;
320
321 if sign_bit == 0 {
322 Ok((mantissa, exponent))
323 } else {
324 Ok((-mantissa, exponent))
325 }
326 }
327
328 #[inline]
329 fn encode(mantissa: i64, exponent: i16) -> Approximation<Self, Sign> {
330 if mantissa == 0 {
331 return Exact(0f64);
332 }
333
334 let sign = (mantissa < 0) as u64;
336 let mut mantissa = mantissa.unsigned_abs();
337
338 let zeros = mantissa.leading_zeros();
339 let top_bit = (u64::BITS - zeros) as i16 + exponent;
340
341 if top_bit > 1024 {
342 return if sign == 0 {
344 Inexact(f64::INFINITY, Sign::Positive)
345 } else {
346 Inexact(f64::NEG_INFINITY, Sign::Negative)
347 };
348 } else if top_bit < -1022 - 52 {
349 return if sign == 0 {
351 Inexact(0f64, Sign::Negative)
352 } else {
353 Inexact(-0f64, Sign::Positive)
354 };
355 };
356
357 let bits; let round_bits; if top_bit <= -1022 {
360 let shift = exponent + 1022 + 52;
365 if shift >= 0 {
366 round_bits = 0; mantissa <<= shift as u32;
368 } else {
369 let shifted = mantissa << (62 + shift) as u64;
370 round_bits =
371 (shifted >> 60 & 0b110) as u8 | ((shifted & 0xfffffffffffffff) != 0) as u8;
372 mantissa >>= (-shift) as u32;
373 }
374
375 bits = (sign << 63) | mantissa;
377 } else {
378 if mantissa == 1 {
381 mantissa = 0; } else {
383 mantissa <<= zeros + 1;
384 }
385
386 let exponent = (exponent + 1023 + u64::BITS as i16) as u64 - zeros as u64 - 1;
388
389 bits = (sign << 63) | (exponent << 52) | (mantissa >> 12);
391
392 round_bits = ((mantissa >> 10) & 0b110) as u8 | ((mantissa & 0x3ff) != 0) as u8;
394 };
395
396 if round_bits & 0b11 == 0 {
397 Exact(f64::from_bits(bits))
399 } else {
400 let sign = Sign::from(sign > 0);
401 if round_to_even_adjustment(round_bits) {
402 Inexact(f64::from_bits(bits + 1), Positive * sign)
405 } else {
406 Inexact(f64::from_bits(bits), Negative * sign)
407 }
408 }
409 }
410}
411
412#[cfg(test)]
413mod tests {
414 use super::*;
415
416 #[test]
417 fn test_float_encoding() {
418 assert_eq!(f32::INFINITY.decode(), Err(FpCategory::Infinite));
420 assert_eq!(f32::NEG_INFINITY.decode(), Err(FpCategory::Infinite));
421 assert_eq!(f32::NAN.decode(), Err(FpCategory::Nan));
422 assert_eq!(f64::INFINITY.decode(), Err(FpCategory::Infinite));
423 assert_eq!(f64::NEG_INFINITY.decode(), Err(FpCategory::Infinite));
424 assert_eq!(f64::NAN.decode(), Err(FpCategory::Nan));
425
426 let f32_cases = [
428 0.,
429 -1.,
430 1.,
431 f32::MIN,
432 f32::MAX,
433 f32::MIN_POSITIVE,
434 -f32::MIN_POSITIVE,
435 f32::EPSILON,
436 f32::from_bits(0x1), f32::from_bits(0x7ff), f32::from_bits(0x7fffff), f32::from_bits(0x800000), -123.4567,
441 core::f32::consts::PI,
442 ];
443 for f in f32_cases {
444 let (man, exp) = f.decode().unwrap();
445 assert_eq!(f32::encode(man, exp), Exact(f));
446 }
447
448 let f64_cases = [
449 0.,
450 -1.,
451 1.,
452 f64::MIN,
453 f64::MAX,
454 f64::MIN_POSITIVE,
455 -f64::MIN_POSITIVE,
456 f64::EPSILON,
457 f64::from_bits(0x1), f64::from_bits(0x7fffff), f64::from_bits(0xfffffffffffff), f64::from_bits(0x10000000000000), -123456.789012345,
462 core::f64::consts::PI,
463 ];
464 for f in f64_cases {
465 let (man, exp) = f.decode().unwrap();
466 assert_eq!(f64::encode(man, exp), Exact(f));
467 }
468
469 assert_eq!(f32::encode(1, 128), Inexact(f32::INFINITY, Sign::Positive));
471 assert_eq!(f32::encode(-1, 128), Inexact(f32::NEG_INFINITY, Sign::Negative));
472 assert_eq!(f32::encode(1, -150), Inexact(0f32, Sign::Negative));
473 assert_eq!(f32::encode(-1, -150), Inexact(-0f32, Sign::Positive));
474 assert_eq!(f64::encode(1, 1024), Inexact(f64::INFINITY, Sign::Positive));
475 assert_eq!(f64::encode(-1, 1024), Inexact(f64::NEG_INFINITY, Sign::Negative));
476 assert_eq!(f64::encode(1, -1075), Inexact(0f64, Sign::Negative));
477 assert_eq!(f64::encode(-1, -1075), Inexact(-0f64, Sign::Positive));
478
479 assert_eq!(f32::encode(3, -150), Inexact(f32::from_bits(0x00000002), Sign::Positive));
481 assert_eq!(f32::encode(-5, -150), Inexact(f32::from_bits(0x80000002), Sign::Positive));
482 assert_eq!(f32::encode(i32::MAX, 50), Inexact(f32::from_bits(0x68000000), Sign::Positive));
483 assert_eq!(
484 f32::encode(i32::MAX, -150),
485 Inexact(f32::from_bits(0x04000000), Sign::Positive)
486 );
487 assert_eq!(
488 f32::encode(i32::MAX, -160),
489 Inexact(f32::from_bits(0x00100000), Sign::Positive)
490 );
491 assert_eq!(
492 f32::encode(i32::MAX, -170),
493 Inexact(f32::from_bits(0x00000400), Sign::Positive)
494 );
495 assert_eq!(
496 f64::encode(3, -1075),
497 Inexact(f64::from_bits(0x0000000000000002), Sign::Positive)
498 );
499 assert_eq!(
500 f64::encode(-5, -1075),
501 Inexact(f64::from_bits(0x8000000000000002), Sign::Positive)
502 );
503 assert_eq!(
504 f64::encode(i64::MAX, 500),
505 Inexact(f64::from_bits(0x6320000000000000), Sign::Positive)
506 );
507 assert_eq!(
508 f64::encode(i64::MAX, -1075),
509 Inexact(f64::from_bits(0x00b0000000000000), Sign::Positive)
510 );
511 assert_eq!(
512 f64::encode(i64::MAX, -1095),
513 Inexact(f64::from_bits(0x0000040000000000), Sign::Positive)
514 );
515 assert_eq!(f64::encode(i64::MAX, -1115), Inexact(f64::from_bits(0x400000), Sign::Positive));
516
517 assert_eq!(f32::encode(1, 0), Exact(1f32));
519 assert_eq!(f64::encode(1, 0), Exact(1f64));
520 assert_eq!(f32::encode(0x1000000, -173), Exact(f32::from_bits(0x1)));
521 assert_eq!(f64::encode(0x40000000000000, -1128), Exact(f64::from_bits(0x1)));
522 }
523}