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::{AlgebraicLaw, OpSpec, U32_INPUTS, U32_OUTPUTS};

// Absolute value under signed i32 interpretation, returned as u32.
// abs(0x8000_0000) = 0x8000_0000 (wrapping i32 abs).

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

/// Absolute value operation (signed interpretation).
#[derive(Debug, Clone, Copy, Default)]
pub struct Abs;

impl Abs {
    /// Declarative operation specification.
    ///
    /// Laws are declared as explicit `AlgebraicLaw` values on `SPEC`.
    pub const SPEC: OpSpec = OpSpec::composition_inlinable(
        "primitive.math.abs",
        U32_INPUTS,
        U32_OUTPUTS,
        LAWS,
        Self::program,
    );

    /// Build the canonical IR program.
    ///
    /// # Examples
    ///
    /// ```
    /// use vyre::ir::Expr;
    /// use vyre::ops::primitive::abs::Abs;
    ///
    /// let _expr = Expr::negate(Expr::u32(7));
    /// let program = Abs::program();
    /// assert!(!program.entry().is_empty());
    /// ```
    #[must_use]
    pub fn program() -> Program {
        primitive::unary_u32_program(|a| {
            let is_neg = Expr::ne(
                Expr::bitand(a.clone(), Expr::u32(0x8000_0000)),
                Expr::u32(0),
            );
            Expr::select(is_neg, Expr::negate(a.clone()), a)
        })
    }
}