use super::*;
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Float01;
impl Distribution<f32> for Float01 {
#[inline]
fn sample<R: Rng + ?Sized>(&self, rand: &mut Random<R>) -> f32 {
let exp = 126 - rand.next_u64().leading_zeros();
replace_exponent_f32(rand.next_f32(), exp)
}
}
impl Distribution<f64> for Float01 {
#[inline]
fn sample<R: Rng + ?Sized>(&self, rand: &mut Random<R>) -> f64 {
let exp = 1022 - rand.next_u64().leading_zeros();
replace_exponent_f64(rand.next_f64(), exp)
}
}
#[inline]
fn replace_exponent_f32(value: f32, exp: u32) -> f32 {
let mantissa = value.to_bits() & ((1 << f32::MANTISSA_DIGITS - 1) - 1);
f32::from_bits(exp << (f32::MANTISSA_DIGITS - 1) | mantissa)
}
#[inline]
fn replace_exponent_f64(value: f64, exp: u32) -> f64 {
let mantissa = value.to_bits() & ((1 << f64::MANTISSA_DIGITS - 1) - 1);
f64::from_bits((exp as u64) << (f64::MANTISSA_DIGITS - 1) | mantissa)
}
#[test]
fn test_yolo() {
for float in crate::new().samples(Float01).take(10000) {
let bits = f32::to_bits(float);
assert!(float > 0.0 && float < 1.0, "float({float}) bits({bits:#x})");
}
}
#[test]
fn test_edges() {
let mut rand = crate::rng::Mock::slice(&[0, 0, !0, !0]);
let low_float: f64 = rand.sample(&Float01);
let low_bits = low_float.to_bits();
let high_float: f64 = rand.sample(&Float01);
let high_bits = high_float.to_bits();
assert!(low_float > 0.0 && low_float < 1.0, "double({low_float}) bits({low_bits:#x})");
assert!(high_float > 0.0 && high_float < 1.0, "double({high_float}) bits({high_bits:#x})");
}