Lattice is a small scientific computing language aimed at reproducible numerics and statistical workflows. It ships a REPL and embeddable library with:
- Arithmetic expressions with identifiers, unary minus, calls, assignments, and blocks.
- Control flow via
if/elsestatements, nested blocks,whileloops,forloops, andbreak/continue. - Strict typing with optional annotations and a numeric tower (ints, floats, complex, decimals, rationals) plus tensors.
- GPU backends: OpenCL, CUDA, HIP, and Metal with BLAS/MPS/CLBlast matmul and dense add/sub paths when available (kernels are used for non-BLAS ops only).
- Built-in constants
pi,e,gamma,infand math helperspow,gcd,lcm,abs,sign,mod,floor,ceil,round,clamp,min,max,sum,mean,var,std,transpose,matmul,conv2d,max_pool2d,fft1d. - Typed constructors/casts:
int(),float(),complex(),decimal(),rational(),tensor(),tensor_values(),tensor_sparse_csr(),tensor_sparse_coo(),tensor_ragged(),to_dense(),to_sparse_csr(),to_sparse_coo(). The project is organized with headers ininclude/and sources insrc/.
include/– public headers (lexer/,parser/,runtime/,repl/,builtin/,util/)src/– implementation (lexer/,parser/,runtime/,repl/,builtin/,main.cpp)tests/– modular tests undertests/{lexer,parser,runtime,builtin,util,repl}with shared helpers attests/test_util.*and entry intests/main.cppCMakeLists.txt– build configuration.clang-format– formatting rules.gitignore– repository hygiene
cmake -S . -B build
cmake --build build./build/latticeExample session (typed values, complex/tensors):
lattice> x = 3
3
lattice> x + 2
5
lattice> complex(1, -2)
1+-2i
lattice> t = tensor(2, 2, 1)
tensor[dense][2x2]<f64>
lattice> tensor_values((1,2,3))
tensor[dense][3]<i32>
lattice> tensor_values(((1,2),(3,4)))
tensor[dense][2x2]<i32>
lattice> matmul(tensor_values(((1,2),(3,4))), tensor_values(((1,),(1,))))
tensor[dense][2x1]<f64>
lattice> var(tensor_values((1,3)))
1
lattice> fft1d(tensor_values((1,0,1,0)))
(tensor[dense][4]<f64>, tensor[dense][4]<f64>)
lattice> exit
LATTICE_BACKEND=auto ./build/lattice
LATTICE_BACKEND=cuda ./build/lattice
LATTICE_BACKEND=hip ./build/lattice
LATTICE_BACKEND=metal ./build/lattice
LATTICE_BACKEND=opencl ./build/lattice
LATTICE_GPU_SMOKE_TEST=1 ctest --test-dir build -R lattice_testsMicrobenchmarks are available via ./build/lattice_bench. For R vs Lattice
matmul comparisons, see benchmarks/scripts/compare_r_lattice_matmul.sh.
Host: macOS (Intel Core i5 2.4 GHz, Intel Iris Plus Graphics 655).
Command:
./build/lattice_bench --backend cpu --ops matmul --matmul-size 1024 --warmup 1 --iters 2Results:
| Tool/Backend | Latency (s) | Bandwidth (GB/s) | GFLOP/s | Notes |
|---|---|---|---|---|
R (base %*%) |
0.0185 | N/A | 116.080 | Median over 2 iterations, warmup 1. |
| Lattice CPU | 0.0146 | 1.72778 | 147.437 | Same parameters as above. |
| Lattice Metal | N/A | N/A | N/A | Metal backend unavailable on this host (fell back to OpenCL CPU device). |
- Creation:
- Dense:
tensor(d0, d1, ..., fill)for row-major dense;tensor_values((1,2,3))for 1D; nested tuples for nD (e.g.,tensor_values(((1,2),(3,4)))). Square-bracket list literals are not supported; tuples are the only literal collection. - Sparse:
tensor_sparse_csr((rows, cols), indptr_tuple, indices_tuple, values_tuple),tensor_sparse_coo((rows, cols), rows_tuple, cols_tuple, values_tuple). - Ragged:
tensor_ragged(row_splits_tuple, values_tuple). - Conversion:
to_dense,to_sparse_csr,to_sparse_coo.
- Dense:
- Elementwise ops:
+ - * /support dense⊕dense (broadcast), dense⊕sparse (densifies sparse), sparse⊕sparse (same format/shape), ragged⊕ragged (matchingrow_splits). Other mixes error with guidance. - Reductions:
sum,mean,var,stdreduce all elements; missing sparse entries count as zero; ragged reduces flat values. Results are cast to the tensor element dtype. - Linear algebra:
matmul(2D only, requires BLAS/MPS/CLBlast) andtranspose(2D only) on dense tensors; sparse inputs are densified first. More ops (solve/QR/LU/SVD) are not implemented yet. - Convolution/pooling:
conv2d(input2d, kernel2d)with valid padding only;max_pool2d(input2d, kh, kw)with integer kernel sizes, no stride/dilation options yet. - FFT:
fft1dreturns a tuple(real_tensor, imag_tensor); implementation is naive O(n^2) and dense-only.
if/else:if (condition) { expr_or_stmt } else { other_stmt }. Conditions must bebool.- Comparisons:
==,!=,>,<,>=,<=yield booleans (true/false). - Boolean literals:
true,false; arithmetic on bools is allowed (1/0) but control-flow requiresbool. while:while (condition) body. Condition re-evaluated each iteration.for:for (init; condition; increment) body. Any of the three clauses may be empty (e.g.,for (; cond; )).break/continue: only valid inside loops;continueskips to the next iteration;breakexits the nearest loop. At the REPL top level they print an error.- Blocks:
{ stmt1; stmt2; ... }with optional semicolons after statements. - Functions:
func name(param1, param2) { ... }defines a function;return expr;exits with a value. Withoutreturn, the last statement value is used if present, otherwise0. Functions may carry type annotations on params/returns; annotated boundaries are enforced, unannotated code remains dynamic.
- Numeric tower:
i8/i16/i32/i64/u8/u16/u32/u64,f16/bfloat16/f32/f64,complex64/complex128,decimal,rational,bool. - Aggregates:
tensor(dense/sparse CSR/COO/ragged) with shape/row-major strides and element dtype (defaultf64), tuples, records, strings. - Constructors/casts:
int,float,complex,decimal,rational,tensor,tensor_values, sparse/ragged tensor constructors,to_dense,to_sparse_*. - Promotion: complex > float > int; signed/unsigned width-aware; decimal↔decimal and rational↔rational only; tensor ops promote element dtype; implicit narrowing is rejected (use
cast/constructors). - Math builtins enforce dtype expectations (e.g.,
gcd/lcmrequire integers,abshandles complex/decimal/rational,powsupports complex).
cmake --build build
ctest --test-dir buildTests exercise parsing and evaluation (arithmetic, identifiers, constants, builtins, and error paths).
Use clang-format with the provided configuration:
find include src CUDA HIP OpenCL Metal \( -name '*.h' -o -name '*.hpp' -o -name '*.hh' -o -name '*.hxx' -o -name '*.c' -o -name '*.cc' -o -name '*.cpp' -o -name '*.cxx' -o -name '*.mm' -o -name '*.cu' -o -name '*.hip' -o -name '*.cl' -o -name '*.metal' \) -print0 | xargs -0 clang-format -i