Skip to content

Implement scalar functions in linalg - #123

Open
imlvts wants to merge 5 commits into
trueagi-io:mainfrom
imlvts:linalg-flat
Open

Implement scalar functions in linalg#123
imlvts wants to merge 5 commits into
trueagi-io:mainfrom
imlvts:linalg-flat

Conversation

@imlvts

@imlvts imlvts commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

This implements in-place implementations for scalar (element-wise) functions for linalg tensors.
The operations are applied in-place, modifying the tensor.

Example

use linalg::dense::Dense;
use linalg::scalar::ScalarTransform;

let mut a = Dense::<f32>::zeros(vec![2, 2]);
a.fill_from(&[-1.0, 4.0, 9.0, -16.0]);
a.abs();   // |x|
a.sqrt();  // √x
assert_eq!(a.data, vec![1.0, 2.0, 3.0, 4.0]);

For sparse matrix implementation, only elements which store a value are touched. This means the result is mathematically not correct for functions which don't follow f(0) = 0. If you want a mathematically correct result, the chain of applied functions needs to have zero as a fix point (f(0) = 0).

imlvts and others added 5 commits June 25, 2026 22:53
New `linalg::scalar` module with a `ScalarTransform` trait providing
in-place element-wise math: abs, min, max, clamp, sin, cos, tan, asin,
acos, atan, atan2, sqrt, cbrt, ln, exp, powf, powi. Implemented for
`Dense` and `Csr` (which transform their contiguous value slice; Csr
touches stored non-zeros only, preserving sparsity).

Per-element work is delegated to a macro-generated `MathScalar` backend
for f32/f64. The new `intel-mkl` feature dispatches the unary
transcendentals and powf to MKL's VML batch kernels (vsSin, vdExp,
vsPowx, …); the default build uses std math.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Me5wnJCyjtrsKu3qfUhSs
The required method exposed a single `&mut [T]`, which assumed every
implementor stores its elements in one contiguous buffer. That excludes
`Blocked`, whose elements live in many per-block `Box<[f32; N*N]>`
allocations (and would exclude strided views or tiled layouts).

Replace `values_mut() -> &mut [T]` with `for_each_chunk(f)`, which hands
the callback each contiguous run of stored elements. Single-buffer types
(Dense, Csr) yield one chunk, so MKL still batches the whole array.

Implement it for `Blocked` to validate the generalization: it emits one
chunk per valid row-run, skipping edge-block padding so zero-changing
transforms (exp, cos) don't turn padding into spurious non-zeros. Tested.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Me5wnJCyjtrsKu3qfUhSs
`benches/scalar.rs` times the full ScalarTransform op surface on a large
Dense array for f32/f64, reporting net Melem/s and GB/s. The per-iter
in-place buffer refresh is measured and subtracted to isolate the math.

Runs on both backends: `--bench scalar` for std math,
`--bench scalar --features intel-mkl` for the MKL VML path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Me5wnJCyjtrsKu3qfUhSs
Add benches/SCALAR_BENCH.md: how to run the scalar throughput bench on
both backends, how to obtain MKL via uv wheels (link symlink + env), and
representative f32/f64 numbers comparing std vs MKL (single- and
multi-threaded VML).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Me5wnJCyjtrsKu3qfUhSs
Replace the manual link setup (env RUSTFLAGS / LD_LIBRARY_PATH / symlink)
with the `intel-mkl-src` build dependency, gated behind the `intel-mkl`
feature. It downloads a redistributable MKL and statically links it, so
`--features intel-mkl` builds, tests, and benches with zero system setup.

Pin `mkl-static-lp64-iomp`: static is required for intel-mkl-src's
auto-download (dynamic configs expect a system MKL on the loader path),
and LP64 keeps MKL_INT 32-bit to match the VML FFI declarations. Drop the
`#[link(name = "mkl_rt")]` attribute in favour of `use intel_mkl_src as _`
for linkage. Tests pass with the feature on; bench confirms VML dispatch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Me5wnJCyjtrsKu3qfUhSs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant