vyre 0.4.0

GPU compute intermediate representation with a standard operation library
Documentation
use crate::ir::{Expr, Program};
use crate::ops::primitive;
use crate::ops::{OpSpec, F32_F32_F32_INPUTS, F32_OUTPUTS};

/// f32 element-wise clamp: max(min(x, max_val), min_val).
#[derive(Debug, Clone, Copy, Default)]
pub struct F32Clamp;

impl F32Clamp {
    pub const SPEC: OpSpec = OpSpec::composition_inlinable(
        "primitive.float.f32_clamp",
        F32_F32_F32_INPUTS,
        F32_OUTPUTS,
        &[],
        Self::program,
    );

    pub fn program() -> Program {
        primitive::ternary_f32_program(|x, min_val, max_val| {
            Expr::max(Expr::min(x, max_val), min_val)
        })
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::ir::{self, DataType};

    #[test]
    fn program_is_non_empty() {
        assert!(!F32Clamp::program().entry().is_empty());
    }

    #[test]
    fn program_validates() {
        let errors = ir::validate(&F32Clamp::program());
        assert!(errors.is_empty(), "validation failed: {errors:?}");
    }

    #[test]
    fn spec_id_is_correct() {
        assert_eq!(F32Clamp::SPEC.id(), "primitive.float.f32_clamp");
    }

    #[test]
    fn spec_signature_is_f32_f32_f32_to_f32() {
        assert_eq!(F32Clamp::SPEC.inputs(), &[DataType::F32, DataType::F32, DataType::F32]);
        assert_eq!(F32Clamp::SPEC.outputs(), &[DataType::F32]);
    }
}