use crate::intrinsics::matrix_kernels;
use crate::marshal::register_typed_fn_2;
use crate::module_exports::ModuleExports;
use crate::typed_module_exports::{ConcreteReturn, ConcreteType, TypedReturn};
use shape_value::aligned_vec::AlignedVec;
use shape_value::heap_value::{HeapValue, MatrixData};
use std::sync::Arc;
pub fn create_matrix_intrinsics_module() -> ModuleExports {
let mut module = ModuleExports::new("std::core::intrinsics::matrix");
module.description =
"Matrix intrinsics (matmul_vec, matmul_mat, mat_add, mat_sub)".to_string();
register_typed_fn_2::<_, Vec<Arc<HeapValue>>, Arc<Vec<f64>>>(
&mut module,
"__intrinsic_matmul_vec",
"Matrix-vector multiplication: `Mat<number> * Vec<number> -> Vec<number>`",
[("matrix", "Array<Array<number>>"), ("vector", "Array<number>")],
ConcreteType::ArrayNumber,
|matrix, vector, _ctx| {
let (a, rows, inner) = extract_matrix(&matrix, "Left matrix")?;
let b = vector.as_slice();
if inner != b.len() {
return Err(format!(
"Matrix/vector dimension mismatch: matrix is {}x{}, vector is length {}",
rows,
inner,
b.len()
));
}
let mut out = vec![0.0; rows];
for i in 0..rows {
let row_base = i * inner;
let mut acc = 0.0;
for k in 0..inner {
acc += a[row_base + k] * b[k];
}
out[i] = acc;
}
Ok(TypedReturn::Concrete(ConcreteReturn::ArrayF64(out)))
},
);
register_typed_fn_2::<_, Vec<Arc<HeapValue>>, Vec<Arc<HeapValue>>>(
&mut module,
"__intrinsic_matmul_mat",
"Matrix-matrix multiplication: `Mat<number> * Mat<number> -> Mat<number>`",
[
("a", "Array<Array<number>>"),
("b", "Array<Array<number>>"),
],
ConcreteType::ArrayHeapValue("Array<Array<number>>".to_string()),
|a_rows_arc, b_rows_arc, _ctx| {
let (a, a_rows, a_cols) = extract_matrix(&a_rows_arc, "Left matrix")?;
let (b, b_rows, b_cols) = extract_matrix(&b_rows_arc, "Right matrix")?;
if a_cols != b_rows {
return Err(format!(
"Matrix dimension mismatch: left is {}x{}, right is {}x{}",
a_rows, a_cols, b_rows, b_cols
));
}
if a_rows == 0 || b_cols == 0 {
return Ok(TypedReturn::Concrete(ConcreteReturn::ArrayHeapValue(
matrix_to_heap_value_vec(&[], a_rows, b_cols),
)));
}
let mut out = vec![0.0; a_rows * b_cols];
for i in 0..a_rows {
let a_row_base = i * a_cols;
let out_row_base = i * b_cols;
for k in 0..a_cols {
let a_ik = a[a_row_base + k];
let b_row_base = k * b_cols;
for j in 0..b_cols {
out[out_row_base + j] += a_ik * b[b_row_base + j];
}
}
}
Ok(TypedReturn::Concrete(ConcreteReturn::ArrayHeapValue(
matrix_to_heap_value_vec(&out, a_rows, b_cols),
)))
},
);
register_typed_fn_2::<_, Vec<Arc<HeapValue>>, Vec<Arc<HeapValue>>>(
&mut module,
"__intrinsic_mat_add",
"Element-wise matrix addition: `Mat<number> + Mat<number>`",
[
("a", "Array<Array<number>>"),
("b", "Array<Array<number>>"),
],
ConcreteType::ArrayHeapValue("Array<Array<number>>".to_string()),
|a_rows_arc, b_rows_arc, _ctx| {
let a = matrix_data_from_heap_value_vec(&a_rows_arc, "Left matrix")?;
let b = matrix_data_from_heap_value_vec(&b_rows_arc, "Right matrix")?;
let out = matrix_kernels::matrix_add(&a, &b)?;
Ok(TypedReturn::Concrete(ConcreteReturn::ArrayHeapValue(
matrix_data_to_heap_value_vec(&out),
)))
},
);
register_typed_fn_2::<_, Vec<Arc<HeapValue>>, Vec<Arc<HeapValue>>>(
&mut module,
"__intrinsic_mat_sub",
"Element-wise matrix subtraction: `Mat<number> - Mat<number>`",
[
("a", "Array<Array<number>>"),
("b", "Array<Array<number>>"),
],
ConcreteType::ArrayHeapValue("Array<Array<number>>".to_string()),
|a_rows_arc, b_rows_arc, _ctx| {
let a = matrix_data_from_heap_value_vec(&a_rows_arc, "Left matrix")?;
let b = matrix_data_from_heap_value_vec(&b_rows_arc, "Right matrix")?;
let out = matrix_kernels::matrix_sub(&a, &b)?;
Ok(TypedReturn::Concrete(ConcreteReturn::ArrayHeapValue(
matrix_data_to_heap_value_vec(&out),
)))
},
);
module
}
fn row_to_f64_vec(_hv: &Arc<HeapValue>, label: &str, row_idx: usize) -> Result<Vec<f64>, String> {
Err(format!(
"{label} row {row_idx}: SURFACE — matrix row-extract reached a \
`HeapValue::TypedArray(Arc<TypedArrayData>)` carrier whose inner \
enum was DELETED at V3-S5 ckpt-1 (2026-05-15). Production target \
is the v2-raw `TypedArray<f64>` / `TypedArray<i64>` flat-struct \
carrier per W12-typed-array-data-deletion audit §1.2 + §3.1 \
scalar recipe + ADR-006 §2.7.24 Q25.A SUPERSEDED. The \
`HeapValue::TypedArray` variant migration to v2-raw rows is \
ckpt-4 territory (`heap_variants.rs:476`). Cascade-broken \
surface; UNREACHABLE until ckpt-4 + ckpt-5 land the row-carrier \
cascade.",
label = label,
row_idx = row_idx,
))
}
fn extract_matrix(
rows: &[Arc<HeapValue>],
label: &str,
) -> Result<(Vec<f64>, usize, usize), String> {
if rows.is_empty() {
return Ok((Vec::new(), 0, 0));
}
let mut cols: Option<usize> = None;
let mut flat = Vec::new();
for (row_idx, hv) in rows.iter().enumerate() {
let row = row_to_f64_vec(hv, label, row_idx)?;
match cols {
Some(expected) if row.len() != expected => {
return Err(format!(
"{} has non-rectangular rows: expected {}, got {} at row {}",
label,
expected,
row.len(),
row_idx
));
}
None => cols = Some(row.len()),
_ => {}
}
flat.extend_from_slice(&row);
}
Ok((flat, rows.len(), cols.unwrap_or(0)))
}
fn matrix_data_from_heap_value_vec(
rows: &[Arc<HeapValue>],
label: &str,
) -> Result<MatrixData, String> {
let (flat, num_rows, cols) = extract_matrix(rows, label)?;
let aligned = if flat.is_empty() {
AlignedVec::new()
} else {
AlignedVec::from_vec(flat)
};
Ok(MatrixData::from_flat(aligned, num_rows as u32, cols as u32))
}
fn matrix_to_heap_value_vec(_flat: &[f64], rows: usize, cols: usize) -> Vec<Arc<HeapValue>> {
if rows == 0 {
return Vec::new();
}
debug_assert!(
cols > 0,
"matrix_to_heap_value_vec ckpt-2 broken-state: \
non-empty rows={} requested but row-carrier rebuild path \
cascade-broken (TypedArrayData DELETED at ckpt-1; \
HeapValue::TypedArray arm migration is ckpt-4 territory). \
W12-typed-array-data-deletion audit §1.2 + §3.1 production \
target = v2-raw TypedArray<f64>.",
rows,
);
let _ = (cols,);
Vec::new()
}
fn matrix_data_to_heap_value_vec(mat: &MatrixData) -> Vec<Arc<HeapValue>> {
matrix_to_heap_value_vec(mat.data.as_slice(), mat.rows as usize, mat.cols as usize)
}