use crate::ir::{BufferDecl, DataType, Expr, Node, Program};
use crate::ops::{OpSpec, F32_F32_INPUTS, BOOL_OUTPUTS};
#[derive(Debug, Clone, Copy, Default)]
pub struct F32Lt;
impl F32Lt {
pub const SPEC: OpSpec = OpSpec::composition_inlinable(
"primitive.float.f32_lt",
F32_F32_INPUTS,
BOOL_OUTPUTS,
&[],
Self::program,
);
pub fn program() -> Program {
let idx = Expr::var("idx");
Program::new(
vec![
BufferDecl::read("a", 0, DataType::F32),
BufferDecl::read("b", 1, DataType::F32),
BufferDecl::output("out", 2, DataType::Bool),
],
crate::ops::primitive::WORKGROUP_SIZE,
vec![
Node::let_bind("idx", Expr::gid_x()),
Node::if_then(
Expr::lt(idx.clone(), Expr::buf_len("out")),
vec![Node::store(
"out",
idx.clone(),
Expr::lt(Expr::load("a", idx.clone()), Expr::load("b", idx)),
)],
),
],
)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ir::{self, DataType};
#[test]
fn program_is_non_empty() {
assert!(!F32Lt::program().entry().is_empty());
}
#[test]
fn program_validates() {
let errors = ir::validate(&F32Lt::program());
assert!(errors.is_empty(), "validation failed: {errors:?}");
}
#[test]
fn spec_id_is_correct() {
assert_eq!(F32Lt::SPEC.id(), "primitive.float.f32_lt");
}
#[test]
fn spec_signature_is_f32_f32_to_bool() {
assert_eq!(F32Lt::SPEC.inputs(), &[DataType::F32, DataType::F32]);
assert_eq!(F32Lt::SPEC.outputs(), &[DataType::Bool]);
}
}