const SIGN_MASK: u64 = 1 << 63;
#[inline(always)]
pub const fn encode_sortable_f64(val: f64) -> [u8; 8] {
let bits = val.to_bits();
let sortable = if bits & SIGN_MASK != 0 {
!bits
} else {
bits ^ SIGN_MASK
};
sortable.to_be_bytes()
}
#[inline(always)]
pub const fn decode_sortable_f64(bytes: [u8; 8]) -> f64 {
let bits = u64::from_be_bytes(bytes);
let orig = if bits & SIGN_MASK != 0 {
bits ^ SIGN_MASK
} else {
!bits
};
f64::from_bits(orig)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sortable_f64_special_cases() {
let neg_zero: f64 = -0.0;
let pos_zero: f64 = 0.0;
let neg_inf = f64::NEG_INFINITY;
let pos_inf = f64::INFINITY;
let enc_neg_inf = encode_sortable_f64(neg_inf);
let enc_neg_zero = encode_sortable_f64(neg_zero);
let enc_pos_zero = encode_sortable_f64(pos_zero);
let enc_pos_inf = encode_sortable_f64(pos_inf);
assert!(enc_neg_inf < enc_neg_zero);
assert!(enc_neg_zero < enc_pos_zero);
assert!(enc_pos_zero < enc_pos_inf);
assert_eq!(decode_sortable_f64(enc_neg_inf), neg_inf);
assert_eq!(decode_sortable_f64(enc_pos_inf), pos_inf);
assert_eq!(
decode_sortable_f64(enc_neg_zero).to_bits(),
neg_zero.to_bits()
);
assert_eq!(
decode_sortable_f64(enc_pos_zero).to_bits(),
pos_zero.to_bits()
);
}
}