cubek-interpolate 0.3.0

CubeK: Interpolation
mod bicubic;
mod bilinear;
mod lanczos3;
mod nearest;

pub(crate) use bicubic::reference_bicubic;
pub(crate) use bilinear::reference_bilinear;
pub(crate) use lanczos3::reference_lanczos3;
pub(crate) use nearest::reference_nearest;

use super::{f32_elem_type, make_random_f32_host, make_zero_handle};
use crate::{
    InterpolateStrategy,
    definition::{InterpolateForwardProblem, InterpolateMode, InterpolateOptions},
    interpolate,
};
use cubecl::client::Client;
use cubek_test_utils::{
    ExecutionOutcome, HostData, HostDataType, Progress, launch_and_capture_outcome,
};

pub fn kernel_result(
    client: Client,
    problem: InterpolateForwardProblem,
    strategy: InterpolateStrategy,
    seed: u64,
) -> Result<HostData, String> {
    let dtype = f32_elem_type();
    let input_shape = problem.input_shape().to_vec();
    let (input_handle, _input_host) = make_random_f32_host(&client, input_shape, seed);

    let output_handle = make_zero_handle(&client, problem.output_shape().to_vec(), dtype);

    let outcome = launch_and_capture_outcome(&client, &[&output_handle.handle], |c| {
        interpolate(
            c,
            input_handle.clone().binding(),
            output_handle.clone().binding(),
            problem.options,
            strategy,
            dtype,
        )
        .into()
    });

    match outcome {
        ExecutionOutcome::CompileError(e) => Err(format!("compile error: {e}")),
        ExecutionOutcome::Executed => Ok(HostData::from_tensor_handle(
            &client,
            output_handle,
            HostDataType::F32,
        )),
    }
}

pub fn cpu_reference_result(
    client: Client,
    problem: InterpolateForwardProblem,
    seed: u64,
    progress: Option<&Progress>,
) -> Result<HostData, String> {
    let out_shape = problem.output_shape();

    if let Some(p) = progress {
        let total: usize = out_shape.iter().product();
        p.set_total(total as u64);
    }

    let (_input_handle, input_host) =
        make_random_f32_host(&client, problem.input_shape().to_vec(), seed);

    Ok(reference_for_interpolation_mode(
        &input_host,
        &out_shape,
        &problem.options,
        progress,
    ))
}

pub fn reference_for_interpolation_mode(
    input: &HostData,
    output_shape: &[usize],
    options: &InterpolateOptions,
    progress: Option<&Progress>,
) -> HostData {
    match options.mode {
        InterpolateMode::Nearest(nearest_mode) => {
            reference_nearest(input, output_shape, nearest_mode, progress)
        }
        InterpolateMode::Bilinear => {
            reference_bilinear(input, output_shape, options.align_corners, progress)
        }
        InterpolateMode::Bicubic => {
            reference_bicubic(input, output_shape, options.align_corners, progress)
        }
        InterpolateMode::Lanczos3 => {
            reference_lanczos3(input, output_shape, options.align_corners, progress)
        }
    }
}