My aggregated monorepo of OCaml code, automaintained

tessera-linalg: initial scaffold with matrix helpers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

+144
+11
tessera-linalg/dune-project
··· 1 + (lang dune 3.17) 2 + (name tessera-linalg) 3 + (generate_opam_files true) 4 + (license ISC) 5 + (package 6 + (name tessera-linalg) 7 + (synopsis "PCA and kNN for float32 Bigarray data") 8 + (description "Portable OCaml implementations of PCA dimensionality reduction and k-nearest-neighbors classification. Operates on flat float32 Bigarray data with explicit shapes.") 9 + (depends 10 + (ocaml (>= 5.2)) 11 + (alcotest (and :with-test (>= 0.8)))))
+5
tessera-linalg/lib/dune
··· 1 + (library 2 + (name linalg) 3 + (public_name tessera-linalg) 4 + (ocamlopt_flags (:standard -w -69)) 5 + (ocamlc_flags (:standard -w -69)))
+51
tessera-linalg/lib/linalg.ml
··· 1 + type vec = (float, Bigarray.float32_elt, Bigarray.c_layout) Bigarray.Array1.t 2 + 3 + type mat = { 4 + data : vec; 5 + rows : int; 6 + cols : int; 7 + } 8 + 9 + let create_mat ~rows ~cols = 10 + let data = Bigarray.Array1.create Bigarray.float32 Bigarray.c_layout (rows * cols) in 11 + Bigarray.Array1.fill data 0.0; 12 + { data; rows; cols } 13 + 14 + let mat_get m i j = 15 + Bigarray.Array1.get m.data (i * m.cols + j) 16 + 17 + let mat_set m i j v = 18 + Bigarray.Array1.set m.data (i * m.cols + j) v 19 + 20 + (* ---- PCA (stub) ---- *) 21 + 22 + type pca_model = { 23 + mean : float array; 24 + components : float array array; 25 + } 26 + 27 + let pca_fit ?(max_samples = 100_000) _mat ~n_components = 28 + ignore max_samples; 29 + { mean = [||]; components = Array.make n_components [||] } 30 + 31 + let pca_transform _model mat = 32 + create_mat ~rows:mat.rows ~cols:0 33 + 34 + (* ---- kNN (stub) ---- *) 35 + 36 + type knn_model = { 37 + embeddings : mat; 38 + labels : int array; 39 + } 40 + 41 + let knn_fit ~embeddings ~labels = 42 + { embeddings; labels } 43 + 44 + type knn_result = { 45 + predictions : int array; 46 + confidences : float array; 47 + } 48 + 49 + let knn_predict _model ~k:_ query = 50 + { predictions = Array.make query.rows 0; 51 + confidences = Array.make query.rows 0.0 }
+27
tessera-linalg/lib/linalg.mli
··· 1 + type vec = (float, Bigarray.float32_elt, Bigarray.c_layout) Bigarray.Array1.t 2 + 3 + type mat = { 4 + data : vec; 5 + rows : int; 6 + cols : int; 7 + } 8 + 9 + val create_mat : rows:int -> cols:int -> mat 10 + val mat_get : mat -> int -> int -> float 11 + val mat_set : mat -> int -> int -> float -> unit 12 + 13 + type pca_model 14 + 15 + val pca_fit : ?max_samples:int -> mat -> n_components:int -> pca_model 16 + val pca_transform : pca_model -> mat -> mat 17 + 18 + type knn_model 19 + 20 + val knn_fit : embeddings:mat -> labels:int array -> knn_model 21 + 22 + type knn_result = { 23 + predictions : int array; 24 + confidences : float array; 25 + } 26 + 27 + val knn_predict : knn_model -> k:int -> mat -> knn_result
+3
tessera-linalg/test/dune
··· 1 + (test 2 + (name test_linalg) 3 + (libraries tessera-linalg alcotest))
+47
tessera-linalg/test/test_linalg.ml
··· 1 + open Linalg 2 + 3 + (* Helper to create a mat from a float array array (row-major) *) 4 + let mat_of_arrays rows_data = 5 + let rows = Array.length rows_data in 6 + let cols = if rows > 0 then Array.length rows_data.(0) else 0 in 7 + let m = create_mat ~rows ~cols in 8 + for i = 0 to rows - 1 do 9 + for j = 0 to cols - 1 do 10 + mat_set m i j rows_data.(i).(j) 11 + done 12 + done; 13 + m 14 + 15 + let _ = mat_of_arrays 16 + 17 + (* ---- Matrix tests ---- *) 18 + 19 + let test_create_mat_dims () = 20 + let m = create_mat ~rows:3 ~cols:4 in 21 + Alcotest.(check int) "rows" 3 m.rows; 22 + Alcotest.(check int) "cols" 4 m.cols; 23 + Alcotest.(check int) "data length" 12 (Bigarray.Array1.dim m.data) 24 + 25 + let test_mat_get_set_roundtrip () = 26 + let m = create_mat ~rows:2 ~cols:3 in 27 + mat_set m 0 0 1.5; 28 + mat_set m 1 2 42.0; 29 + let v1 = mat_get m 0 0 in 30 + let v2 = mat_get m 1 2 in 31 + Alcotest.(check (float 1e-3)) "get(0,0)" 1.5 v1; 32 + Alcotest.(check (float 1e-3)) "get(1,2)" 42.0 v2 33 + 34 + let test_mat_zero_init () = 35 + let m = create_mat ~rows:2 ~cols:2 in 36 + Alcotest.(check (float 1e-6)) "zero init" 0.0 (mat_get m 0 0) 37 + 38 + (* ---- Test runner ---- *) 39 + 40 + let () = 41 + Alcotest.run "tessera-linalg" [ 42 + "matrix", [ 43 + Alcotest.test_case "create_mat dimensions" `Quick test_create_mat_dims; 44 + Alcotest.test_case "get/set roundtrip" `Quick test_mat_get_set_roundtrip; 45 + Alcotest.test_case "zero initialization" `Quick test_mat_zero_init; 46 + ]; 47 + ]