vyre-conform 0.1.0

Conformance suite for vyre backends — proves byte-identical output to CPU reference
Documentation
use super::tensor::TensorValue;

/// A concrete value passed into or returned from the reference interpreter.
#[derive(Debug, Clone)]
pub enum Value {
    /// Unsigned 32-bit integer.
    U32(u32),
    /// Signed 32-bit integer.
    I32(i32),
    /// Unsigned 64-bit integer.
    U64(u64),
    /// Boolean value.
    Bool(bool),
    /// Raw little-endian bytes for storage, uniform, and byte buffers.
    Bytes(Vec<u8>),
    /// Floating-point value (F16, BF16, F32, F64 all share this variant).
    Float(f64),
    /// Multi-dimensional tensor.
    Tensor(TensorValue),
    /// Fixed-size array of values.
    Array(Vec<Value>),
}

impl PartialEq for Value {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (Self::U32(a), Self::U32(b)) => a == b,
            (Self::I32(a), Self::I32(b)) => a == b,
            (Self::U64(a), Self::U64(b)) => a == b,
            (Self::Bool(a), Self::Bool(b)) => a == b,
            (Self::Bytes(a), Self::Bytes(b)) => a == b,
            (Self::Float(a), Self::Float(b)) => a.to_bits() == b.to_bits(),
            (Self::Tensor(a), Self::Tensor(b)) => a == b,
            (Self::Array(a), Self::Array(b)) => a == b,
            _ => false,
        }
    }
}

impl Eq for Value {}

impl Value {
    /// Convert this conformance value into the reference interpreter value type.
    #[must_use]
    pub fn to_reference_value(&self) -> vyre_reference::value::Value {
        match self {
            Self::U32(value) => vyre_reference::value::Value::U32(*value),
            Self::I32(value) => vyre_reference::value::Value::I32(*value),
            Self::U64(value) => vyre_reference::value::Value::U64(*value),
            Self::Bool(value) => vyre_reference::value::Value::Bool(*value),
            Self::Bytes(bytes) => vyre_reference::value::Value::Bytes(bytes.clone()),
            Self::Float(value) => vyre_reference::value::Value::Float(*value),
            Self::Tensor(tensor) => vyre_reference::value::Value::Bytes(tensor.data.clone()),
            Self::Array(values) => vyre_reference::value::Value::Array(
                values.iter().map(Self::to_reference_value).collect(),
            ),
        }
    }

    /// Convert a reference interpreter value into the conformance value type.
    #[must_use]
    pub fn from_reference_value(value: vyre_reference::value::Value) -> Self {
        match value {
            vyre_reference::value::Value::U32(value) => Self::U32(value),
            vyre_reference::value::Value::I32(value) => Self::I32(value),
            vyre_reference::value::Value::U64(value) => Self::U64(value),
            vyre_reference::value::Value::Bool(value) => Self::Bool(value),
            vyre_reference::value::Value::Bytes(bytes) => Self::Bytes(bytes),
            vyre_reference::value::Value::Float(value) => Self::Float(value),
            vyre_reference::value::Value::Array(values) => {
                Self::Array(values.into_iter().map(Self::from_reference_value).collect())
            }
            other => Self::Bytes(other.to_bytes()),
        }
    }

    /// Convert a slice of conformance values into reference interpreter values.
    #[must_use]
    pub fn to_reference_values(values: &[Self]) -> Vec<vyre_reference::value::Value> {
        values.iter().map(Self::to_reference_value).collect()
    }

    /// Convert reference interpreter values into conformance values.
    #[must_use]
    pub fn from_reference_values(values: Vec<vyre_reference::value::Value>) -> Vec<Self> {
        values.into_iter().map(Self::from_reference_value).collect()
    }
}