tenferro-gpu 0.3.0

CubeCL-backed CUDA and WebGPU provider backends for tenferro tensors.
use cubecl::prelude::*;

use crate::kernels::helpers::{flat_to_tensor_index, multi_to_tensor_index, zero_value};

#[cube(launch_unchecked)]
pub fn extract_diagonal_kernel<E: CubePrimitive>(
    out: &mut Tensor<E>,
    input: &Tensor<E>,
    #[comptime] axis_a: usize,
    #[comptime] axis_b: usize,
    #[comptime] diag_output_axis: usize,
    #[comptime] input_rank: usize,
    #[comptime] output_rank: usize,
) {
    if ABSOLUTE_POS < out.len() {
        let out_idx = flat_to_tensor_index(ABSOLUTE_POS, out, output_rank);
        let mut input_idx = Array::<usize>::new(input_rank);
        let diag = out_idx[diag_output_axis];
        let mut out_axis = 0usize;
        #[unroll]
        for axis in 0..input_rank {
            if axis == axis_a || axis == axis_b {
                input_idx[axis] = diag;
            } else {
                input_idx[axis] = out_idx[out_axis];
                out_axis += 1;
            }
        }
        out[ABSOLUTE_POS] = input[multi_to_tensor_index(&input_idx, input, input_rank)];
    }
}

#[cube(launch_unchecked)]
pub fn embed_diagonal_copy_kernel<E: CubePrimitive>(
    out: &mut Tensor<E>,
    input: &Tensor<E>,
    #[comptime] axis_a: usize,
    #[comptime] axis_b: usize,
    #[comptime] input_rank: usize,
    #[comptime] output_rank: usize,
) {
    if ABSOLUTE_POS < input.len() {
        let input_idx = flat_to_tensor_index(ABSOLUTE_POS, input, input_rank);
        let mut output_idx = Array::<usize>::new(output_rank);
        let diag_val = input_idx[axis_a];
        let mut src_axis = 0usize;
        #[unroll]
        for out_axis in 0..output_rank {
            if out_axis == axis_b {
                output_idx[out_axis] = diag_val;
            } else {
                output_idx[out_axis] = input_idx[src_axis];
                src_axis += 1;
            }
        }
        let dst = multi_to_tensor_index(&output_idx, out, output_rank);
        out[dst] = input[ABSOLUTE_POS];
    }
}

#[cube(launch_unchecked)]
pub fn tril_kernel<E: CubePrimitive>(out: &mut Tensor<E>, input: &Tensor<E>, k: i64) {
    if ABSOLUTE_POS < out.len() {
        let row = out.coordinate(ABSOLUTE_POS, 0) as i64;
        let col = out.coordinate(ABSOLUTE_POS, 1) as i64;
        let boundary = col - k;
        out[ABSOLUTE_POS] = if row >= boundary {
            input[ABSOLUTE_POS]
        } else {
            zero_value::<E>()
        };
    }
}

#[cube(launch_unchecked)]
pub fn triu_kernel<E: CubePrimitive>(out: &mut Tensor<E>, input: &Tensor<E>, k: i64) {
    if ABSOLUTE_POS < out.len() {
        let row = out.coordinate(ABSOLUTE_POS, 0) as i64;
        let col = out.coordinate(ABSOLUTE_POS, 1) as i64;
        let boundary = col - k;
        out[ABSOLUTE_POS] = if row <= boundary {
            input[ABSOLUTE_POS]
        } else {
            zero_value::<E>()
        };
    }
}