cubek-interpolate 0.3.0

CubeK: Interpolation
mod backward;
mod forward;

use crate::{
    InterpolateStrategy,
    definition::{InterpolateOptions, InterpolateProblem},
};
use cubecl::std::tensor::TensorHandle;
use cubecl::{client::Client, prelude::*, zspace::Strides};
use cubek_test_utils::{HostData, Progress, TestInput};

pub(crate) fn f32_elem_type() -> ElemType {
    f32::elem_type_native()
}

pub(crate) fn make_random_f32_host(
    client: &Client,
    shape: Vec<usize>,
    seed: u64,
) -> (TensorHandle, HostData) {
    TestInput::builder(client.clone(), shape)
        .uniform(seed, -1., 1.)
        .generate_with_f32_host_data()
}

pub(crate) fn make_zero_handle(
    client: &Client,
    shape: Vec<usize>,
    dtype: ElemType,
) -> TensorHandle {
    TestInput::builder(client.clone(), shape)
        .dtype(dtype)
        .zeros()
        .generate_without_host_data()
}

pub fn kernel_result(
    client: Client,
    problem: InterpolateProblem,
    strategy: InterpolateStrategy,
    seed: u64,
) -> Result<HostData, String> {
    match problem {
        InterpolateProblem::Forward(prob) => forward::kernel_result(client, prob, strategy, seed),
        InterpolateProblem::Backward(prob) => backward::kernel_result(client, prob, seed),
    }
}

pub fn cpu_reference_result(
    client: Client,
    problem: InterpolateProblem,
    seed: u64,
    progress: Option<&Progress>,
) -> Result<HostData, String> {
    match problem {
        InterpolateProblem::Forward(prob) => {
            forward::cpu_reference_result(client, prob, seed, progress)
        }
        InterpolateProblem::Backward(prob) => {
            backward::cpu_reference_result(client, prob, seed, progress)
        }
    }
}

pub fn cpu_reference_interpolate_from_host(
    input: &HostData,
    output_shape: &[usize],
    options: &InterpolateOptions,
) -> HostData {
    forward::reference_for_interpolation_mode(input, output_shape, options, None)
}

pub fn cpu_reference_interpolate_backward_from_host(
    out_grad: &HostData,
    output_shape: &[usize],
    options: &InterpolateOptions,
) -> HostData {
    backward::reference_for_backward_interpolation_mode(out_grad, output_shape, options, None)
}

pub(crate) fn for_each_output_coord(output_shape: &[usize], mut f: impl FnMut(usize, &[usize])) {
    let rank = output_shape.len();
    if rank == 0 {
        f(0, &[]);
        return;
    }
    let num: usize = output_shape.iter().product();
    let mut coord = vec![0usize; rank];
    for linear in 0..num {
        let mut rem = linear;
        for d in (0..rank).rev() {
            coord[d] = rem % output_shape[d];
            rem /= output_shape[d];
        }
        f(linear, &coord);
    }
}

pub(crate) fn contiguous_strides(shape: &[usize]) -> Strides {
    let n = shape.len();
    if n == 0 {
        return Strides::new(&[] as &[usize]);
    }
    let mut s = vec![0usize; n];
    s[n - 1] = 1;
    for i in (0..n - 1).rev() {
        s[i] = s[i + 1] * shape[i + 1];
    }
    Strides::new(&s)
}