#![cfg_attr(not(feature = "cpu"), allow(dead_code))]
#![allow(unused_imports)]
use std::sync::Arc;
use rlx_ir::{DType, Graph, Node, NodeId, Op, OpExtension, Shape, VjpContext, register_op};
#[cfg(feature = "cpu")]
use rlx_cpu::op_registry::{CpuKernel, CpuTensorMut, CpuTensorRef, register_cpu_kernel};
use super::*;
pub(crate) struct SparseValuesGradExt;
impl OpExtension for SparseValuesGradExt {
fn name(&self) -> &str {
SPARSE_VALUES_GRAD
}
fn num_inputs(&self) -> usize {
4
}
fn infer_shape(&self, inputs: &[&Shape], _attrs: &[u8]) -> Shape {
let col_idx = inputs[0];
assert_eq!(
col_idx.dtype(),
DType::I32,
"values_grad: col_idx must be I32"
);
let nnz = col_idx
.num_elements()
.expect("values_grad: col_idx must have static shape");
Shape::new(&[nnz], DType::F64)
}
}
#[cfg(feature = "cpu")]
pub(crate) struct SparseValuesGradCpu;
#[cfg(feature = "cpu")]
impl CpuKernel for SparseValuesGradCpu {
fn name(&self) -> &str {
SPARSE_VALUES_GRAD
}
fn execute(
&self,
inputs: &[CpuTensorRef<'_>],
output: CpuTensorMut<'_>,
_attrs: &[u8],
) -> Result<(), String> {
let col_idx = inputs[0].expect_i32("values_grad col_idx")?;
let row_ptr = inputs[1].expect_i32("values_grad row_ptr")?;
let u = inputs[2].expect_f64("values_grad u")?;
let v = inputs[3].expect_f64("values_grad v")?;
let out = output.expect_f64_mut("values_grad out")?;
algos::values_grad(col_idx, row_ptr, u, v, out)
}
}