runmat-runtime 0.6.0

Core runtime for RunMat with builtins, BLAS/LAPACK integration, and execution APIs
Documentation
#[cfg(target_arch = "wasm32")]
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
use runmat_builtins::{IntValue, IntegerStorage, Tensor, Value};

#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[test]
fn integer_scalar_variants_arithmetic() {
    let i8v = Value::Int(IntValue::I8(5));
    let i16v = Value::Int(IntValue::I16(-2));
    let u32v = Value::Int(IntValue::U32(7));
    let u64v = Value::Int(IntValue::U64(3));
    assert!(runmat_runtime::call_builtin("plus", &[i8v.clone(), i16v.clone()]).is_err());
    assert!(runmat_runtime::call_builtin("minus", &[u32v.clone(), u64v.clone()]).is_err());
    assert!(runmat_runtime::call_builtin("times", &[i8v.clone(), u32v.clone()]).is_err());
    assert!(runmat_runtime::call_builtin("rdivide", &[u32v.clone(), i16v.clone()]).is_err());
}

#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[test]
fn integer_promotion_with_double() {
    let i = Value::Int(IntValue::I32(4));
    let d = Value::Num(2.5);
    assert_eq!(
        runmat_runtime::call_builtin("plus", &[i.clone(), d.clone()]).unwrap(),
        Value::Int(IntValue::I32(7))
    );
    assert_eq!(
        runmat_runtime::call_builtin("times", &[d.clone(), i.clone()]).unwrap(),
        Value::Int(IntValue::I32(10))
    );
}

#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[test]
fn integer_array_elementwise_arithmetic_preserves_native_storage() {
    let signed = Value::Tensor(
        Tensor::new_integer(IntegerStorage::I8(vec![100, -100]), vec![1, 2]).expect("signed input"),
    );
    let signed_rhs = Value::Tensor(
        Tensor::new_integer(IntegerStorage::I8(vec![30, 30]), vec![1, 2]).expect("signed rhs"),
    );
    let unsigned = Value::Tensor(
        Tensor::new_integer(IntegerStorage::U64(vec![u64::MAX, 2]), vec![1, 2])
            .expect("unsigned input"),
    );
    let unsigned_rhs = Value::Tensor(
        Tensor::new_integer(IntegerStorage::U64(vec![1, 3]), vec![1, 2]).expect("unsigned rhs"),
    );

    assert_eq!(
        runmat_runtime::call_builtin("plus", &[signed.clone(), signed_rhs.clone()]).expect("plus"),
        Value::Tensor(
            Tensor::new_integer(IntegerStorage::I8(vec![127, -70]), vec![1, 2])
                .expect("plus expected"),
        )
    );
    assert_eq!(
        runmat_runtime::call_builtin("minus", &[signed.clone(), signed_rhs]).expect("minus"),
        Value::Tensor(
            Tensor::new_integer(IntegerStorage::I8(vec![70, -128]), vec![1, 2])
                .expect("minus expected"),
        )
    );
    assert_eq!(
        runmat_runtime::call_builtin("times", &[unsigned, unsigned_rhs]).expect("times"),
        Value::Tensor(
            Tensor::new_integer(IntegerStorage::U64(vec![u64::MAX, 6]), vec![1, 2])
                .expect("times expected"),
        )
    );
    assert_eq!(
        runmat_runtime::call_builtin("times", &[signed.clone(), Value::Num(2.6)])
            .expect("integer array with scalar double"),
        Value::Tensor(
            Tensor::new_integer(IntegerStorage::I8(vec![127, -128]), vec![1, 2])
                .expect("scalar double expected"),
        )
    );
}

#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[test]
fn integer_relations_keep_uint64_and_signed_values_exact() {
    let max_unsigned = Value::Int(IntValue::U64(u64::MAX));
    let max_signed = Value::Int(IntValue::I64(i64::MAX));
    assert_eq!(
        runmat_runtime::call_builtin("eq", &[max_unsigned.clone(), max_signed.clone()])
            .expect("eq"),
        Value::Bool(false)
    );
    assert_eq!(
        runmat_runtime::call_builtin("ne", &[max_unsigned.clone(), max_signed.clone()])
            .expect("ne"),
        Value::Bool(true)
    );
    assert_eq!(
        runmat_runtime::call_builtin("gt", &[max_unsigned.clone(), max_signed.clone()])
            .expect("gt"),
        Value::Bool(true)
    );
    assert_eq!(
        runmat_runtime::call_builtin("ge", &[max_unsigned, max_signed]).expect("ge"),
        Value::Bool(true)
    );
    assert_eq!(
        runmat_runtime::call_builtin(
            "lt",
            &[Value::Int(IntValue::I8(-1)), Value::Int(IntValue::U8(0))],
        )
        .expect("lt"),
        Value::Bool(true)
    );
    assert_eq!(
        runmat_runtime::call_builtin(
            "le",
            &[Value::Int(IntValue::I8(-1)), Value::Int(IntValue::U8(0))],
        )
        .expect("le"),
        Value::Bool(true)
    );
}

#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[test]
fn integer_relation_size_errors_keep_builtin_identifier() {
    let lhs = Value::Tensor(
        Tensor::new_integer(IntegerStorage::U8(vec![1, 2]), vec![1, 2]).expect("lhs"),
    );
    let rhs = Value::Tensor(
        Tensor::new_integer(IntegerStorage::U8(vec![1, 2, 3]), vec![1, 3]).expect("rhs"),
    );
    let error = runmat_runtime::call_builtin("eq", &[lhs, rhs]).expect_err("size mismatch");
    assert_eq!(error.identifier(), Some("RunMat:eq:SizeMismatch"));
}

#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[test]
fn sum_native_preserves_exact_integer_storage_while_default_is_double() {
    let input = Value::Tensor(
        Tensor::new_integer(IntegerStorage::U64(vec![u64::MAX, 1, 5, 7]), vec![2, 2])
            .expect("input"),
    );
    assert_eq!(
        runmat_runtime::call_builtin("sum", &[input.clone(), Value::from("native")])
            .expect("native sum"),
        Value::Tensor(
            Tensor::new_integer(IntegerStorage::U64(vec![u64::MAX, 12]), vec![1, 2])
                .expect("native output"),
        )
    );
    assert_eq!(
        runmat_runtime::call_builtin(
            "sum",
            &[input.clone(), Value::Num(2.0), Value::from("native")],
        )
        .expect("native row sum"),
        Value::Tensor(
            Tensor::new_integer(IntegerStorage::U64(vec![u64::MAX, 8]), vec![2, 1])
                .expect("native row output"),
        )
    );
    assert_eq!(
        runmat_runtime::call_builtin(
            "sum",
            &[Value::Int(IntValue::U64(u64::MAX)), Value::from("native")],
        )
        .expect("native scalar sum"),
        Value::Int(IntValue::U64(u64::MAX))
    );
    match runmat_runtime::call_builtin("sum", &[input]).expect("default sum") {
        Value::Tensor(tensor) => {
            assert!(tensor.integer_storage().is_none());
            assert_eq!(tensor.shape, vec![1, 2]);
        }
        other => panic!("expected double tensor, got {other:?}"),
    }
}

#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[test]
fn prod_native_preserves_integer_storage_while_default_is_double() {
    let input = Value::Tensor(
        Tensor::new_integer(IntegerStorage::U8(vec![2, 200, 3, 2]), vec![2, 2]).expect("input"),
    );
    assert_eq!(
        runmat_runtime::call_builtin("prod", &[input.clone(), Value::from("native")])
            .expect("native product"),
        Value::Tensor(
            Tensor::new_integer(IntegerStorage::U8(vec![255, 6]), vec![1, 2])
                .expect("native output"),
        )
    );
    assert_eq!(
        runmat_runtime::call_builtin(
            "prod",
            &[Value::Int(IntValue::I64(i64::MIN)), Value::from("native")],
        )
        .expect("native scalar product"),
        Value::Int(IntValue::I64(i64::MIN))
    );
    match runmat_runtime::call_builtin("prod", &[input]).expect("default product") {
        Value::Tensor(tensor) => assert!(tensor.integer_storage().is_none()),
        other => panic!("expected double tensor, got {other:?}"),
    }
}

#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[test]
fn integer_class_and_string() {
    let i = Value::Int(IntValue::U16(42));
    let cls = runmat_runtime::call_builtin("class", [i.clone()].as_slice()).unwrap();
    if let Value::String(s) = cls {
        assert_eq!(s, "uint16");
    } else {
        panic!();
    }
    let s = runmat_runtime::call_builtin("string", [i].as_slice()).unwrap();
    if let Value::StringArray(sa) = s {
        assert_eq!(sa.data[0], "42");
    } else {
        panic!();
    }
}

#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[test]
fn uint16_builtin_dispatches_and_casts_array() {
    let input = Value::Tensor(Tensor::new(vec![3.49, -2.0, 70000.0], vec![1, 3]).unwrap());
    let output = runmat_runtime::call_builtin("uint16", &[input]).expect("uint16 builtin");
    match output {
        Value::Tensor(tensor) => {
            assert_eq!(tensor.shape, vec![1, 3]);
            assert_eq!(tensor.data, vec![3.0, 0.0, u16::MAX as f64]);
        }
        other => panic!("expected tensor output, got {other:?}"),
    }
}