1const EXPONENT_MASK_OFFSET: usize = 48;
4const SIGN_MASK: u64 = 1 << 63;
5const EXPONENT_MASK: u64 = 0x7ffc << EXPONENT_MASK_OFFSET;
6const PAYLOAD_MASK: u64 = !(0xfffc << EXPONENT_MASK_OFFSET);
7
8#[inline]
10pub const fn box_unsigned(payload: u64) -> u64 {
11 EXPONENT_MASK | payload
12}
13
14#[inline]
16pub const fn unbox_unsigned(number: u64) -> Option<u64> {
17 if is_boxed(number) {
18 Some(unbox_unsigned_unchecked(number))
19 } else {
20 None
21 }
22}
23
24#[inline]
26pub const fn unbox_unsigned_unchecked(number: u64) -> u64 {
27 number & PAYLOAD_MASK
28}
29
30#[inline]
32pub const fn box_signed(payload: i64) -> u64 {
33 (if payload < 0 { SIGN_MASK } else { 0 }) | box_unsigned(payload.unsigned_abs())
34}
35
36#[inline]
38pub const fn unbox_signed(number: u64) -> Option<i64> {
39 if let Some(value) = unbox_unsigned(number) {
40 Some((if number & SIGN_MASK == 0 { 1 } else { -1 }) * value as i64)
41 } else {
42 None
43 }
44}
45
46#[inline]
48pub const fn is_boxed(number: u64) -> bool {
49 number & EXPONENT_MASK == EXPONENT_MASK
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 const MAXIMUM: i64 = 1 << 50;
57
58 #[test]
59 fn check_mask() {
60 assert_ne!(EXPONENT_MASK, f64::NAN.to_bits());
61 assert!(f64::from_bits(EXPONENT_MASK).is_nan());
62 }
63
64 #[test]
65 fn unbox_nan() {
66 assert_eq!(unbox_signed(f64::NAN.to_bits()), None);
67 assert_eq!(unbox_signed(f64::INFINITY.to_bits()), None);
68 assert_eq!(unbox_signed(f64::NEG_INFINITY.to_bits()), None);
69 }
70
71 #[test]
72 fn box_unsigned_value() {
73 fn box_to_f64(payload: u64) -> f64 {
74 f64::from_bits(box_unsigned(payload))
75 }
76
77 assert!(box_to_f64(0).is_nan());
78 assert!(box_to_f64(1).is_nan());
79 assert!(box_to_f64(7).is_nan());
80 assert!(box_to_f64(42).is_nan());
81 }
82
83 #[test]
84 fn unbox_unsigned_value() {
85 assert_eq!(unbox_unsigned(42.0f64.to_bits()), None);
86 assert_eq!(unbox_unsigned(box_unsigned(0)), Some(0));
87 assert_eq!(unbox_unsigned(box_unsigned(1)), Some(1));
88 assert_eq!(unbox_unsigned(box_unsigned(7)), Some(7));
89 assert_eq!(unbox_unsigned(box_unsigned(42)), Some(42));
90 }
91
92 #[test]
93 fn unsigned_maximum() {
94 let x = MAXIMUM as _;
95
96 assert_eq!(unbox_unsigned(box_unsigned(x - 1)), Some(x - 1));
97 assert_eq!(unbox_unsigned(box_unsigned(x)), Some(0));
98 }
99
100 #[test]
101 fn box_signed_value() {
102 fn box_to_f64(payload: i64) -> f64 {
103 f64::from_bits(box_signed(payload))
104 }
105
106 assert!(box_to_f64(0).is_nan());
107 assert!(box_to_f64(1).is_nan());
108 assert!(box_to_f64(7).is_nan());
109 assert!(box_to_f64(42).is_nan());
110 assert!(box_to_f64(-1).is_nan());
111 assert!(box_to_f64(-7).is_nan());
112 assert!(box_to_f64(-42).is_nan());
113 }
114
115 #[test]
116 fn unbox_signed_value() {
117 assert_eq!(unbox_signed(42.0f64.to_bits()), None);
118 assert_eq!(unbox_signed(box_signed(0)), Some(0));
119 assert_eq!(unbox_signed(box_signed(1)), Some(1));
120 assert_eq!(unbox_signed(box_signed(7)), Some(7));
121 assert_eq!(unbox_signed(box_signed(42)), Some(42));
122 assert_eq!(unbox_signed(box_signed(-1)), Some(-1));
123 assert_eq!(unbox_signed(box_signed(-7)), Some(-7));
124 assert_eq!(unbox_signed(box_signed(-42)), Some(-42));
125 }
126
127 #[test]
128 fn signed_maximum() {
129 assert_eq!(unbox_signed(box_signed(MAXIMUM - 1)), Some(MAXIMUM - 1));
130 assert_eq!(unbox_signed(box_signed(MAXIMUM)), Some(0));
131 }
132
133 #[test]
134 fn signed_minimum() {
135 assert_eq!(unbox_signed(box_signed(1 - MAXIMUM)), Some(1 - MAXIMUM));
136 assert_eq!(unbox_signed(box_signed(-MAXIMUM)), Some(0));
137 }
138
139 #[test]
140 fn unbox_f64_value() {
141 fn unbox_from_f64(number: f64) -> Option<u64> {
142 unbox_unsigned(number.to_bits())
143 }
144
145 assert_eq!(unbox_from_f64(0.0), None);
146 assert_eq!(unbox_from_f64(-1.0), None);
147 assert_eq!(unbox_from_f64(1.0), None);
148 assert_eq!(unbox_from_f64(42.0), None);
149 }
150}