Skip to content

Commit c3ab9c5

Browse files
committed
Added: Initial implementation of la-stack crate
Adds the initial implementation of the `la-stack` crate, providing stack-allocated linear algebra for fixed dimensions. Includes `Vector`, `Matrix`, and `Lu` types, along with basic functionality and examples. Also sets up `justfile` for development workflow and a license file.
1 parent 1989c3d commit c3ab9c5

File tree

9 files changed

+319
-23
lines changed

9 files changed

+319
-23
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
/target
2+
/.cspellcache

LICENSE

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# BSD 3-Clause License
2+
3+
Copyright (c) 2025, Adam Getchell
4+
5+
Redistribution and use in source and binary forms, with or without
6+
modification, are permitted provided that the following conditions are met:
7+
8+
1. Redistributions of source code must retain the above copyright notice, this
9+
list of conditions and the following disclaimer.
10+
11+
2. Redistributions in binary form must reproduce the above copyright notice,
12+
this list of conditions and the following disclaimer in the documentation
13+
and/or other materials provided with the distribution.
14+
15+
3. Neither the name of the copyright holder nor the names of its
16+
contributors may be used to endorse or promote products derived from
17+
this software without specific prior written permission.
18+
19+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

README.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# la-stack
2+
3+
[![Crates.io](https://img.shields.io/crates/v/la-stack.svg)](https://crates.io/crates/la-stack)
4+
[![Downloads](https://img.shields.io/crates/d/la-stack.svg)](https://crates.io/crates/la-stack)
5+
[![License](https://img.shields.io/crates/l/la-stack.svg)](LICENSE)
6+
[![Docs.rs](https://docs.rs/la-stack/badge.svg)](https://docs.rs/la-stack)
7+
[![CI](https://github.com/acgetchell/la-stack/actions/workflows/ci.yml/badge.svg)](https://github.com/acgetchell/la-stack/actions/workflows/ci.yml)
8+
[![rust-clippy analyze](https://github.com/acgetchell/la-stack/actions/workflows/rust-clippy.yml/badge.svg)](https://github.com/acgetchell/la-stack/actions/workflows/rust-clippy.yml)
9+
[![Audit dependencies](https://github.com/acgetchell/la-stack/actions/workflows/audit.yml/badge.svg)](https://github.com/acgetchell/la-stack/actions/workflows/audit.yml)
10+
11+
Fast, stack-allocated linear algebra for fixed dimensions in Rust.
12+
13+
This crate exists primarily to support the [`delaunay`](https://crates.io/crates/delaunay) crate’s needs while keeping the API intentionally small and explicit.
14+
15+
## 📐 Introduction
16+
17+
`la-stack` provides a handful of const-generic, stack-backed building blocks:
18+
19+
- `Vector<const D: usize>` for fixed-length vectors (`[f64; D]` today)
20+
- `Matrix<const D: usize>` for fixed-size square matrices (`[[f64; D]; D]` today)
21+
- `Lu<const D: usize>` for LU factorization with partial pivoting (solve + det)
22+
23+
## ✨ Design goals
24+
25+
- ✅ Const-generic dimensions (no dynamic sizes)
26+
- ✅ Stack storage only (no heap allocation in core types)
27+
-`Copy` types where possible
28+
- ✅ Explicit algorithms (LU, solve, determinant)
29+
-`unsafe` forbidden
30+
- ✅ No runtime dependencies (dev-dependencies are for contributors only)
31+
32+
## 🔢 Scalar types
33+
34+
Today, the core types are implemented for `f64`. The intent is to support `f32` and `f64` (and `f128` if/when Rust gains a stable primitive for it). Longer term, we may add optional arbitrary-precision support (e.g. via `rug`) depending on performance.
35+
36+
## 🚀 Quickstart
37+
38+
Add this to your `Cargo.toml`:
39+
40+
```toml
41+
[dependencies]
42+
la-stack = "0.1"
43+
```
44+
45+
Solve a 3×3 system via LU:
46+
47+
```rust
48+
use la_stack::{LaError, Matrix, Vector, DEFAULT_PIVOT_TOL};
49+
50+
fn main() -> Result<(), LaError> {
51+
// Requires pivoting (a[0][0] = 0), so it's a good LU demo.
52+
let a = Matrix::<3>::from_rows([[0.0, 1.0, 1.0], [1.0, 0.0, 1.0], [1.0, 1.0, 0.0]]);
53+
let b = Vector::<3>::new([5.0, 4.0, 3.0]);
54+
55+
let lu = a.lu(DEFAULT_PIVOT_TOL)?;
56+
let x = lu.solve_vec(b)?.into_array();
57+
58+
println!("x = {x:?}");
59+
Ok(())
60+
}
61+
```
62+
63+
## 🧩 API at a glance
64+
65+
| Type | Storage | Purpose | Key methods |
66+
|---|---|---|---|
67+
| `Vector<D>` | `[f64; D]` | Fixed-length vector | `new`, `zero`, `dot`, `norm2_sq` |
68+
| `Matrix<D>` | `[[f64; D]; D]` | Fixed-size square matrix | `from_rows`, `zero`, `identity`, `lu`, `det` |
69+
| `Lu<D>` | `Matrix<D>` + pivot array | Factorization for solves/det | `solve_vec`, `det` |
70+
71+
Storage shown above reflects the current `f64` implementation.
72+
73+
## 📋 Examples
74+
75+
The `examples/` directory contains small, runnable programs:
76+
77+
```bash
78+
just examples
79+
# or:
80+
cargo run --example solve_3x3
81+
cargo run --example det_3x3
82+
```
83+
84+
## 🤝 Contributing
85+
86+
A short contributor workflow:
87+
88+
```bash
89+
cargo install just
90+
just ci # lint + fast tests + bench compile
91+
just commit-check # lint + all tests + examples
92+
```
93+
94+
For the full set of developer commands, see `just --list` and `WARP.md`.
95+
96+
## 📄 License
97+
98+
BSD 3-Clause License. See [LICENSE](LICENSE).

WARP.md

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@ This file provides guidance to WARP (warp.dev) when working with code in this re
44

55
## Common commands
66

7-
- Build (debug): `cargo build`
8-
- Build (release): `cargo build --release`
9-
- Fast compile check (no binary produced): `cargo check`
10-
- Run tests: `cargo test`
7+
- Build (debug): `cargo build` (or `just build`)
8+
- Build (release): `cargo build --release` (or `just build-release`)
9+
- Fast compile check (no binary produced): `cargo check` (or `just check`)
10+
- Run tests: `cargo test` (or `just test`)
1111
- Run a single test (by name filter): `cargo test solve_2x2_basic` (or the full path: `cargo test lu::tests::solve_2x2_basic`)
12-
- Format: `cargo fmt`
13-
- Lint (Clippy): `cargo clippy --all-targets --all-features -- -D warnings`
14-
- Run benchmarks: `cargo bench`
12+
- Format: `cargo fmt` (or `just fmt`)
13+
- Lint (Clippy): `cargo clippy --all-targets --all-features -- -D warnings` (or `just clippy`)
14+
- Spell check: `just spell-check` (uses `cspell.json` at repo root; keep the `words` list sorted lexicographically)
15+
- Run benchmarks: `cargo bench` (or `just bench`)
16+
- Run examples: `just examples` (or `cargo run --example det_3x3`)
17+
- CI simulation (lint + tests + bench compile): `just ci`
18+
- Pre-commit validation: `just commit-check`
1519

1620
## Code structure (big picture)
1721

@@ -21,6 +25,7 @@ This file provides guidance to WARP (warp.dev) when working with code in this re
2125
- `src/vector.rs`: `Vector<const D: usize>` (`[f64; D]`)
2226
- `src/matrix.rs`: `Matrix<const D: usize>` (`[[f64; D]; D]`) + helpers (`get`, `set`, `inf_norm`, `det`)
2327
- `src/lu.rs`: `Lu<const D: usize>` factorization with partial pivoting (`solve_vec`, `det`)
28+
- A minimal `justfile` exists for common workflows (see `just --list`).
2429
- The public API re-exports these items from `src/lib.rs`.
2530
- Dev-only benchmarks live in `benches/vs_nalgebra.rs` (Criterion + nalgebra comparison).
2631

cspell.json

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"version": "0.2",
3+
"language": "en",
4+
"words": [
5+
"Clippy",
6+
"clippy",
7+
"const",
8+
"elif",
9+
"f128",
10+
"f32",
11+
"f64",
12+
"generics",
13+
"Getchell",
14+
"Justfile",
15+
"justfile",
16+
"lu",
17+
"MSRV",
18+
"msvc",
19+
"mult",
20+
"nalgebra",
21+
"pipefail",
22+
"pivoting",
23+
"println",
24+
"rug",
25+
"RUSTDOCFLAGS",
26+
"shellcheck",
27+
"usize"
28+
],
29+
"ignorePaths": [
30+
"target",
31+
"Cargo.lock"
32+
]
33+
}

examples/det_3x3.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//! Compute the determinant of a 3×3 matrix via explicit LU factorization.
2+
3+
use la_stack::{DEFAULT_PIVOT_TOL, LaError, Matrix};
4+
5+
fn main() -> Result<(), LaError> {
6+
let a = Matrix::<3>::from_rows([[1.0, 2.0, 3.0], [0.0, 4.0, 5.0], [1.0, 0.0, 6.0]]);
7+
8+
// Compute via explicit LU factorization.
9+
let lu = a.lu(DEFAULT_PIVOT_TOL)?;
10+
let det = lu.det();
11+
12+
println!("det = {det}");
13+
Ok(())
14+
}

examples/solve_3x3.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//! Solve a 3×3 linear system via LU factorization (with pivoting).
2+
3+
use la_stack::{DEFAULT_PIVOT_TOL, LaError, Matrix, Vector};
4+
5+
fn main() -> Result<(), LaError> {
6+
// This system requires pivoting (a[0][0] = 0), so it's a good LU demo.
7+
let a = Matrix::<3>::from_rows([[0.0, 1.0, 1.0], [1.0, 0.0, 1.0], [1.0, 1.0, 0.0]]);
8+
let b = Vector::<3>::new([5.0, 4.0, 3.0]);
9+
10+
let lu = a.lu(DEFAULT_PIVOT_TOL)?;
11+
let x = lu.solve_vec(b)?.into_array();
12+
13+
println!("x = [{:.6}, {:.6}, {:.6}]", x[0], x[1], x[2]);
14+
Ok(())
15+
}

justfile

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# shellcheck disable=SC2148
2+
# Justfile for la-stack development workflow
3+
# Install just: https://github.com/casey/just
4+
# Usage: just <command> or just --list
5+
6+
# Use bash with strict error handling for all recipes
7+
set shell := ["bash", "-euo", "pipefail", "-c"]
8+
9+
# Default recipe shows available commands
10+
default:
11+
@just --list
12+
13+
# Build commands
14+
build:
15+
cargo build
16+
17+
build-release:
18+
cargo build --release
19+
20+
check:
21+
cargo check
22+
23+
# Code quality and formatting
24+
fmt:
25+
cargo fmt
26+
27+
fmt-check:
28+
cargo fmt --check
29+
30+
clippy:
31+
cargo clippy --all-targets --all-features -- -D warnings
32+
33+
doc-check:
34+
RUSTDOCFLAGS='-D warnings' cargo doc --no-deps
35+
36+
# Lint groups (delaunay-style)
37+
lint: lint-code lint-docs lint-config
38+
39+
lint-code: fmt-check clippy doc-check
40+
41+
lint-docs: spell-check
42+
43+
lint-config: action-lint
44+
45+
# Testing (delaunay-style split)
46+
# - test: lib + doc tests (fast)
47+
# - test-integration: tests/ (if present)
48+
# - test-all: everything in Rust
49+
50+
test:
51+
cargo test --lib --verbose
52+
cargo test --doc --verbose
53+
54+
test-integration:
55+
cargo test --tests --verbose
56+
57+
test-all: test test-integration
58+
@echo "✅ All tests passed"
59+
60+
# Benchmarks
61+
bench:
62+
cargo bench
63+
64+
bench-compile:
65+
cargo bench --no-run
66+
67+
# Examples
68+
examples:
69+
cargo run --quiet --example det_3x3
70+
cargo run --quiet --example solve_3x3
71+
72+
# CI simulation (matches delaunay's `just ci` shape)
73+
ci: lint test test-integration bench-compile
74+
@echo "🎯 CI simulation complete!"
75+
76+
# Pre-commit workflow: comprehensive validation before committing
77+
# Runs: linting + all Rust tests (lib + doc + integration) + examples
78+
commit-check: lint test-all examples
79+
@echo "🚀 Ready to commit! All checks passed!"
80+
81+
# GitHub Actions workflow validation (optional)
82+
action-lint:
83+
#!/usr/bin/env bash
84+
set -euo pipefail
85+
if ! command -v actionlint >/dev/null; then
86+
echo "⚠️ 'actionlint' not found. Install: https://github.com/rhysd/actionlint"
87+
exit 0
88+
fi
89+
files=()
90+
while IFS= read -r -d '' file; do
91+
files+=("$file")
92+
done < <(git ls-files -z '.github/workflows/*.yml' '.github/workflows/*.yaml')
93+
if [ "${#files[@]}" -gt 0 ]; then
94+
printf '%s\0' "${files[@]}" | xargs -0 actionlint
95+
else
96+
echo "No workflow files found to lint."
97+
fi
98+
99+
# Spell check (cspell)
100+
#
101+
# Requires either:
102+
# - `cspell` on PATH (recommended: `npm i -g cspell`), or
103+
# - `npx` (will run cspell without a global install)
104+
spell-check:
105+
#!/usr/bin/env bash
106+
set -euo pipefail
107+
if command -v cspell >/dev/null; then
108+
cspell lint --config cspell.json --no-progress --gitignore --cache --exclude cspell.json .
109+
elif command -v npx >/dev/null; then
110+
npx cspell lint --config cspell.json --no-progress --gitignore --cache --exclude cspell.json .
111+
else
112+
echo "❌ cspell not found. Install via npm (recommended): npm i -g cspell"
113+
echo " Or ensure npx is available (Node.js)."
114+
exit 1
115+
fi
116+
117+
clean:
118+
cargo clean

src/cspell.json

Lines changed: 0 additions & 16 deletions
This file was deleted.

0 commit comments

Comments
 (0)