vyre 0.4.0

GPU compute intermediate representation with a standard operation library
Documentation
use crate::ir::{BufferDecl, DataType, Expr, Node, Program};
use crate::ops::AlgebraicLaw;
use crate::ops::{OpSpec, BYTES_TO_U32_OUTPUTS};

// WGSL lowering marker for `hash.crc32`.
//
// No special handling is needed. The generic Category A lowerer emits the
// IR composition from `kernel.rs`.

/// Spec-table check value: `crc32("123456789") == 0xCBF43926`.
pub const ASCII_123456789_CRC32: u32 = 0xCBF4_3926;

pub const CRC32_FINAL_XOR: u32 = 0xffff_ffff;

pub const CRC32_INITIAL: u32 = 0xffff_ffff;

pub const CRC32_POLY_REFLECTED: u32 = 0xEDB8_8320;

/// Build the canonical bitwise reflected CRC-32 program.
#[must_use]
pub fn crc32_program() -> Program {
    Program::new(
        vec![
            BufferDecl::read("input", 0, DataType::Bytes),
            BufferDecl::output("out", 1, DataType::U32),
        ],
        [1, 1, 1],
        vec![
            Node::let_bind("crc", Expr::u32(CRC32_INITIAL)),
            Node::loop_for(
                "pos",
                Expr::u32(0),
                Expr::buf_len("input"),
                vec![
                    Node::assign("crc", Expr::bitxor(Expr::var("crc"), input_byte())),
                    Node::loop_for(
                        "bit",
                        Expr::u32(0),
                        Expr::u32(8),
                        vec![Node::assign("crc", crc_bit_step())],
                    ),
                ],
            ),
            Node::assign(
                "crc",
                Expr::bitxor(Expr::var("crc"), Expr::u32(CRC32_FINAL_XOR)),
            ),
            Node::if_then(
                Expr::lt(Expr::u32(0), Expr::buf_len("out")),
                vec![Node::store("out", Expr::u32(0), Expr::var("crc"))],
            ),
        ],
    )
}

pub fn crc_bit_step() -> Expr {
    let shifted = Expr::shr(Expr::var("crc"), Expr::u32(1));
    Expr::select(
        Expr::ne(Expr::bitand(Expr::var("crc"), Expr::u32(1)), Expr::u32(0)),
        Expr::bitxor(shifted.clone(), Expr::u32(CRC32_POLY_REFLECTED)),
        shifted,
    )
}

/// Spec-table check value: `crc32(empty) == 0`.
pub const EMPTY_CRC32: u32 = 0;

pub fn input_byte() -> Expr {
    Expr::bitand(Expr::load("input", Expr::var("pos")), Expr::u32(0xff))
}

pub const INPUTS: &[DataType] = &[DataType::Bytes];

pub const LAWS: &[AlgebraicLaw] = &[AlgebraicLaw::Bounded {
    lo: 0,
    hi: u32::MAX,
}];

/// Declarative operation specification for `hash.crc32`.
pub const SPEC: OpSpec = OpSpec::composition(
    "hash.crc32",
    INPUTS,
    BYTES_TO_U32_OUTPUTS,
    LAWS,
    crc32_program,
);