Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ by Accelerate.

This package should provide small, explicit Swift APIs for selecting high-volume
row submatrices from tall dense matrices. The first implementation target is a
real-valued `Double` path using Accelerate BLAS/LAPACK, with `Float` support
following the same shape once the API is settled.
real-valued `Double` and `Float` path using Accelerate BLAS/LAPACK without
deprecated compatibility shims.

## Implementation Plan

Expand All @@ -17,11 +17,11 @@ following the same shape once the API is settled.
- Keep dimensions explicit and validate shape before calling Accelerate.
- Return descriptive errors for non-tall, rank-deficient, or malformed input.

2. Implement square MaxVol for `Double`.
2. Implement square MaxVol for `Double` and `Float`.
- Accept an `N x r` matrix where `N >= r`.
- Initialize pivots with `dgetrf`.
- Initialize pivots with `dgetrf` / `sgetrf`.
- Solve for expansion coefficients with triangular solves.
- Iterate row swaps using the standard rank-one update with `dger`.
- Iterate row swaps using the standard rank-one update with `dger` / `sger`.
- Return selected row indices, coefficient matrix, iteration count, and
whether the coefficient tolerance was reached.

Expand All @@ -41,7 +41,8 @@ following the same shape once the API is settled.
5. Add performance-focused refinements only after the behavior is stable.
- Avoid repeated temporary allocations in the swap loop.
- Reuse workspace buffers.
- Add `Float` variants mapped to `sgetrf`, `strsm`, and `sger`.
- Keep `Double` and `Float` paths mapped to the matching Accelerate entry
points.
- Consider complex support only after real-valued APIs are stable.

## Non-Goals For The First Pass
Expand Down
53 changes: 28 additions & 25 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,44 @@

## Current Focus

- Build from `v0.5.0` toward `v1.0.0` with real-valued `Double` algorithms
backed by modern Accelerate BLAS/LAPACK.
- Build from `v0.7.0` toward `v1.0.0` with real-valued `Double` and `Float`
algorithms backed by modern Accelerate BLAS/LAPACK.
- Keep Swift Testing as the package test surface and require reference fixtures
before broadening the algorithm surface.
- Treat public API compatibility as pre-1.0 until RectMaxVol, Float support, and
reference parity are complete.
- Treat public API compatibility as pre-1.0 until reference parity,
performance behavior, and documentation are complete enough to support a
stable contract.

## Algorithm Milestones

1. Implement square MaxVol for `Double`.
- Accept a tall or square `DenseColumnMajorMatrix<Double>` where
1. Implement square MaxVol for `Double` and `Float`.
- Accept a tall or square `DenseColumnMajorMatrix<Double>` or
`DenseColumnMajorMatrix<Float>` where
`rows >= columns`.
- Initialize pivots with Accelerate LAPACK LU factorization.
- Solve expansion coefficients with Accelerate triangular solve routines.
- Iterate row swaps with BLAS rank-one updates.
- Return selected row indices, coefficient matrix, iteration count, and
convergence status.

2. Add RectMaxVol for `Double`.
2. Add RectMaxVol for `Double` and `Float`.
- Start from square MaxVol selected rows.
- Append rows while coefficient row norms exceed tolerance.
- Support explicit `minRows` and `maxRows` bounds.
- Reuse coefficient-update primitives from square MaxVol where practical.

3. Add `Float` support after the `Double` API is stable.
- Mirror the `Double` API shape.
- Map to the matching single-precision Accelerate entry points.
- Keep shared validation and result semantics identical.

4. Add reference-parity fixtures for each supported algorithm.
3. Add reference-parity fixtures for each supported algorithm.
- Keep small deterministic fixtures generated from `maxvolpy`, `Maxvol.jl`,
or an R implementation.
- Record selected rows, coefficients, iteration counts, and convergence
status for fixture matrices that require zero, one, and multiple swaps.
- Include independent reconstruction checks for every fixture.

4. Add performance-focused refinements.
- Reduce temporary allocations in square row swaps and rectangular appends.
- Reuse workspace buffers where it improves measured throughput.
- Add benchmark coverage for representative row counts and ranks.

## Test Coverage

- Cover matrix storage, checked access, shape validation, and result invariants.
Expand All @@ -47,8 +49,9 @@
maximum-iteration cases.
- Keep reference fixtures generated from upstream Python, Julia, or R
implementations when algorithm behavior changes.
- Add randomized orthonormal-matrix tests similar to `Maxvol.jl` before `1.0.0`.
- Add Release-mode validation once behavior depends on optimization-sensitive
- Keep randomized orthonormal-matrix tests similar to `Maxvol.jl` across
supported scalar types.
- Keep Release-mode validation in the release path for optimization-sensitive
Accelerate calls.
- Keep validation clean under the modern Accelerate `ACCELERATE_NEW_LAPACK` and
`ACCELERATE_LAPACK_ILP64` import surface.
Expand All @@ -61,8 +64,8 @@
- Document square MaxVol and RectMaxVol usage with small examples.
- Keep algorithm limitations and non-goals visible before `1.0.0`.
- Keep public API docs aligned with tested behavior.
- Add a DocC article that explains tolerance, convergence status, and
iteration-limited partial results before `1.0.0`.
- Expand DocC with algorithm notes, limitations, and reference-fixture
provenance before `1.0.0`.

## Swift Package Index

Expand All @@ -81,14 +84,14 @@

## Before `1.0.0`

- Complete RectMaxVol for `Double` with reference-parity fixtures.
- Add `Float` support with the same API shape and reference fixtures.
- Decide whether complex-valued matrices are in scope for `1.0.0` or explicitly
post-1.0.
- Add broader randomized numerical tests, including orthonormal tall matrices
and near-rank-deficient cases.
- Add Release-mode validation for optimization-sensitive Accelerate behavior.
- Add performance benchmarks for allocation count and row-swap throughput.
- Expand DocC with algorithm notes, limitations, and reference-fixture
provenance.
- Add broader randomized numerical tests, including stress cases for larger
ranks, wider condition-number ranges, and deterministic tie behavior.
- Add performance benchmarks for allocation count, row-swap throughput, and
rectangular append throughput.
- Profile whether reusable workspaces are worth adding to the public API or
should remain an internal optimization.
- Expand DocC with reference-fixture provenance and a short comparison with
Python, Julia, and R implementations.
- Verify Swift Package Index renders the tagged `v1.0.0` documentation cleanly.
20 changes: 14 additions & 6 deletions Sources/MaxVol/MaxVol.docc/MaxVol.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Accelerate.
## Overview

MaxVol provides Swift-native APIs for selecting representative rows from tall
dense matrices. The first implementation path supports real-valued `Double`
dense matrices. The implementation supports real-valued `Double` and `Float`
matrices stored in column-major order so the package can call Accelerate BLAS
and LAPACK routines directly.

Expand All @@ -26,7 +26,12 @@ let matrix = try DenseColumnMajorMatrix(
)
```

Call ``maxVol(_:options:)`` to select a square basis from a tall matrix:
Use `DenseColumnMajorMatrix<Float>` for the single-precision path; the public
algorithm calls keep the same shape.

Call ``maxVol(_:options:)->MaxVolResult<Double>`` or
``maxVol(_:options:)->MaxVolResult<Float>`` to select a square basis from a
tall matrix:

```swift
let result = try maxVol(matrix)
Expand All @@ -44,8 +49,9 @@ rows:
let coefficients = result.coefficients
```

Call ``rectMaxVol(_:options:)`` when the basis may contain more rows than the
matrix column count:
Call ``rectMaxVol(_:options:)->MaxVolResult<Double>`` or
``rectMaxVol(_:options:)->MaxVolResult<Float>`` when the basis may contain more
rows than the matrix column count:

```swift
let rectangular = try rectMaxVol(matrix, options: RectMaxVolOptions(minRows: 3))
Expand All @@ -59,8 +65,10 @@ let rectangular = try rectMaxVol(matrix, options: RectMaxVolOptions(minRows: 3))

### MaxVol

- ``maxVol(_:options:)``
- ``rectMaxVol(_:options:)``
- ``maxVol(_:options:)->MaxVolResult<Double>``
- ``maxVol(_:options:)->MaxVolResult<Float>``
- ``rectMaxVol(_:options:)->MaxVolResult<Double>``
- ``rectMaxVol(_:options:)->MaxVolResult<Float>``
- ``MaxVolOptions``
- ``RectMaxVolOptions``
- ``MaxVolResult``
Expand Down
26 changes: 17 additions & 9 deletions Sources/MaxVol/MaxVol.docc/ToleranceAndConvergence.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ let coefficients = result.coefficients

## Square MaxVol

``maxVol(_:options:)`` selects exactly one row per matrix column. The square
algorithm starts from an LU-pivoted basis, computes expansion coefficients, and
swaps rows while any coefficient magnitude is larger than
``maxVol(_:options:)->MaxVolResult<Double>`` and
``maxVol(_:options:)->MaxVolResult<Float>`` select exactly one row per matrix
column. The square algorithm starts from an LU-pivoted basis, computes expansion
coefficients, and swaps rows while any coefficient magnitude is larger than
``MaxVolOptions/tolerance``.

The square tolerance must be at least `1.0`. Values closer to `1.0` usually do
Expand All @@ -37,10 +38,11 @@ validated and reconstructs through its current selected rows, but

## RectMaxVol

``rectMaxVol(_:options:)`` starts from square MaxVol, then appends extra rows.
The rectangular stopping test uses coefficient row norms instead of individual
coefficient magnitudes: unselected rows are appended while their coefficient row
norm exceeds ``RectMaxVolOptions/tolerance``.
``rectMaxVol(_:options:)->MaxVolResult<Double>`` and
``rectMaxVol(_:options:)->MaxVolResult<Float>`` start from square MaxVol, then
append extra rows. The rectangular stopping test uses coefficient row norms
instead of individual coefficient magnitudes: unselected rows are appended while
their coefficient row norm exceeds ``RectMaxVolOptions/tolerance``.

``RectMaxVolOptions/minRows`` can force extra rows even when the tolerance is
already satisfied. ``RectMaxVolOptions/maxRows`` can stop the append loop before
Expand All @@ -57,12 +59,18 @@ stronger square basis matters. For rectangular selection, set
basis size, and set ``RectMaxVolOptions/maxRows`` when runtime or storage must
be bounded.

The same option types apply to both `Double` and `Float` overloads. Tolerances
are expressed as `Double` values so callers can keep one configuration surface
while the numerical work uses the matrix scalar type.

## Topics

### Related APIs

- ``maxVol(_:options:)``
- ``rectMaxVol(_:options:)``
- ``maxVol(_:options:)->MaxVolResult<Double>``
- ``maxVol(_:options:)->MaxVolResult<Float>``
- ``rectMaxVol(_:options:)->MaxVolResult<Double>``
- ``rectMaxVol(_:options:)->MaxVolResult<Float>``
- ``MaxVolOptions``
- ``RectMaxVolOptions``
- ``MaxVolResult``
Expand Down
Loading
Loading