tokitai-operator 0.1.0

Verified DL kernel compiler: formally-checked GEMM, p-adic, sheaf, contract-carrying ops. Paper-artifact grade.
Documentation
//! Sample-set generators for property-based tests.
//!
//! `PadicSampleGenerator` produces sequences of `(Padic, Padic, ...)`
//! tuples that satisfy the property being tested (e.g. two numbers
//! whose valuation sum is exactly the product's valuation).
//! `BinarySampleSet` produces pairs of `i64` values for the
//! property-based arithmetic tests.
//!
//! Sample generators are pure: no I/O, no global state, no
//! randomness beyond the seed passed to the constructor. The
//! `proptest` framework consumes them through the standard
//! `proptest!` macro.
//!
use crate::domain::{Padic, PadicDomain};
use crate::{Error, Result};

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SampleSet<T> {
    pub source: String,
    pub values: Vec<T>,
}

impl<T> SampleSet<T> {
    pub fn new(source: impl Into<String>, values: Vec<T>) -> Result<Self> {
        if values.is_empty() {
            return Err(Error::verification("sample set must not be empty"));
        }
        Ok(Self {
            source: source.into(),
            values,
        })
    }

    pub fn len(&self) -> usize {
        self.values.len()
    }

    pub fn is_empty(&self) -> bool {
        self.values.is_empty()
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BinarySampleSet<T> {
    pub source: String,
    pub pairs: Vec<(T, T)>,
}

impl<T> BinarySampleSet<T> {
    pub fn new(source: impl Into<String>, pairs: Vec<(T, T)>) -> Result<Self> {
        if pairs.is_empty() {
            return Err(Error::verification("binary sample set must not be empty"));
        }
        Ok(Self {
            source: source.into(),
            pairs,
        })
    }

    pub fn len(&self) -> usize {
        self.pairs.len()
    }

    pub fn is_empty(&self) -> bool {
        self.pairs.is_empty()
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PadicSampleProfile {
    ContractSmoke,
    ValuationStratified,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PadicSampleGenerator {
    profile: PadicSampleProfile,
}

impl PadicSampleGenerator {
    pub fn new(profile: PadicSampleProfile) -> Self {
        Self { profile }
    }

    pub fn contract_smoke() -> Self {
        Self::new(PadicSampleProfile::ContractSmoke)
    }

    pub fn valuation_stratified() -> Self {
        Self::new(PadicSampleProfile::ValuationStratified)
    }

    pub fn binary_samples(&self, domain: &PadicDomain) -> Result<BinarySampleSet<Padic>> {
        match self.profile {
            PadicSampleProfile::ContractSmoke => BinarySampleSet::new(
                "p-adic contract smoke samples",
                vec![
                    (domain.element(1), domain.element(2)),
                    (domain.element(domain.meta.prime as u128), domain.element(2)),
                    (
                        domain.element((domain.meta.prime * domain.meta.prime) as u128),
                        domain.element(domain.meta.prime as u128),
                    ),
                ],
            ),
            PadicSampleProfile::ValuationStratified => {
                let mut pairs = Vec::new();
                let max_level = domain.meta.precision.min(4);
                for lhs_level in 0..max_level {
                    for rhs_level in 0..max_level {
                        let lhs = domain.element(power(domain.meta.prime, lhs_level)?);
                        let rhs = domain.element(2 * power(domain.meta.prime, rhs_level)?);
                        pairs.push((lhs, rhs));
                    }
                }
                BinarySampleSet::new("p-adic valuation-stratified samples", pairs)
            }
        }
    }
}

fn power(base: u64, exponent: u32) -> Result<u128> {
    let mut value = 1u128;
    for _ in 0..exponent {
        value = value
            .checked_mul(base as u128)
            .ok_or_else(|| Error::verification("sample value does not fit in u128"))?;
    }
    Ok(value)
}