cubek-random 0.3.0

CubeK: Random Number Generation
use cubecl::{
    CubeDim,    prelude::{BufferArg, *},
};
use cubek_random::*;

#[test]
fn values_open_interval() {
    let client = cubecl::test_device().client();

    let input = client.create_from_slice(u32::as_bytes(&[0, u32::MAX]));
    let output = client.empty(input.size() as usize);

    kernel_to_unit_interval_oo::launch(
        &client,
        CubeCount::Static(1, 1, 1),
        CubeDim::new_1d(2),
        unsafe { BufferArg::from_raw_parts(input, 2) },
        unsafe { BufferArg::from_raw_parts(output.clone(), 2) },
    );

    let actual = client.read_one(output).unwrap();
    let actual = f32::from_bytes(&actual);

    assert!(
        actual[0] > 0.0,
        "Expected 0 to map to a value strictly greater than 0.0, but got {}",
        actual[0]
    );

    assert!(
        actual[1] < 1.0,
        "Expected u32::MAX to map to a value strictly less than 1.0, but got {}",
        actual[1]
    );

    assert!(
        actual[1] >= 0.9999999,
        "Expected u32::MAX to map close to 1.0, but got {}",
        actual[1]
    );
}

#[cube(launch)]
pub(crate) fn kernel_to_unit_interval_co(input: &[u32], output: &mut [f32]) {
    let value = Vector::<u32, Const<1>>::new(input[ABSOLUTE_POS]);
    output[ABSOLUTE_POS] = to_unit_interval_closed_open(value).extract(0usize);
}

#[cube(launch)]
pub(crate) fn kernel_to_unit_interval_oo(input: &[u32], output: &mut [f32]) {
    let value = Vector::<u32, Const<1>>::new(input[ABSOLUTE_POS]);
    output[ABSOLUTE_POS] = to_unit_interval_open(value).extract(0usize);
}

#[test]
fn values_closed_open_interval() {
    let client = cubecl::test_device().client();

    let input = client.create_from_slice(u32::as_bytes(&[0, u32::MAX]));
    let output = client.empty(input.size() as usize);

    kernel_to_unit_interval_co::launch(
        &client,
        CubeCount::Static(1, 1, 1),
        CubeDim::new_1d(2),
        unsafe { BufferArg::from_raw_parts(input, 2) },
        unsafe { BufferArg::from_raw_parts(output.clone(), 2) },
    );

    let actual = client.read_one(output).unwrap();
    let actual = f32::from_bytes(&actual);

    // Previous implementation would map to `[0, 1]` but the interval should be half open `[0, 1)`
    assert_eq!(
        actual[0], 0.0,
        "Expected 0 to map to 0.0, but got {}",
        actual[0]
    );

    assert!(
        actual[1] < 1.0,
        "Expected u32::MAX to map to a value strictly less than 1.0, but got {}",
        actual[1]
    );

    assert!(
        actual[1] >= 0.9999999,
        "Expected u32::MAX to map close to 1.0, but got {}",
        actual[1]
    );
}