use crate::ir::{Expr, Program};
use crate::ops::primitive;
use crate::ops::{AlgebraicLaw, OpSpec, F32_F32_INPUTS, F32_OUTPUTS};
pub const LAWS: &[AlgebraicLaw] = &[AlgebraicLaw::Commutative];
#[derive(Debug, Clone, Copy, Default)]
pub struct F32Add;
impl F32Add {
pub const SPEC: OpSpec = OpSpec::composition_inlinable(
"primitive.float.f32_add",
F32_F32_INPUTS,
F32_OUTPUTS,
LAWS,
Self::program,
);
#[must_use]
pub fn program() -> Program {
primitive::binary_f32_program(Expr::add)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ir::{self, DataType};
#[test]
pub(crate) fn program_is_non_empty() {
let program = F32Add::program();
assert!(!program.entry().is_empty());
}
#[test]
pub(crate) fn program_validates() {
let program = F32Add::program();
let errors = ir::validate(&program);
assert!(errors.is_empty(), "validation failed: {errors:?}");
}
#[test]
pub(crate) fn program_lowers_to_wgsl_with_add() {
let program = F32Add::program();
let wgsl =
crate::lower::wgsl::lower_anonymous(&program).expect("F32Add must lower to WGSL");
assert!(wgsl.contains(" + "), "F32Add WGSL must contain '+'");
}
#[test]
pub(crate) fn spec_id_is_correct() {
assert_eq!(F32Add::SPEC.id(), "primitive.float.f32_add");
}
#[test]
pub(crate) fn spec_signature_is_f32_f32_to_f32() {
assert_eq!(F32Add::SPEC.inputs(), &[DataType::F32, DataType::F32]);
assert_eq!(F32Add::SPEC.outputs(), &[DataType::F32]);
}
}