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
37 changes: 19 additions & 18 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ env:
# `LazyLock<Tier>` detection means one binary, all ISAs. Jobs that
# specifically need a higher target-cpu can opt in via per-job env.
RUSTFLAGS: "-D warnings"
MSRV: 1.97.1
BLAS_MSRV: 1.97.1
MSRV: 1.98.1
BLAS_MSRV: 1.98.1

jobs:
pass-msrv:
Expand All @@ -41,18 +41,19 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
# Pinned to 1.97.1 to match `rust-toolchain.toml`. The workspace
# bumped from 1.94.1 → 1.97.1 in commit
# https://github.com/AdaWorldAPI/ndarray (this PR) to align with
# bevy (edition 2024 → 1.95 MSRV) and lance-graph. 1.95 added the
# `clippy::manual_checked_ops` lint which fires on
# `impl_owned_array.rs::into_scalar` — fixed in this same PR.
# Must equal `rust-toolchain.toml`'s channel. The version is NOT
# restated in this comment on purpose: CI here does NOT read the
# toolchain file (it uses `dtolnay/rust-toolchain@<version>`), so the
# number lives in three places — the `MSRV`/`BLAS_MSRV` env above, the
# matrix entry below, and each `dtolnay/rust-toolchain@` step. All of
# them move together with the toolchain file, and its bump log is the
# one place that records WHY each move happened.
rust:
- "1.97.1"
- "1.98.1"
name: clippy/${{ matrix.rust }}
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.97.1
- uses: dtolnay/rust-toolchain@1.98.1
with:
components: clippy
- uses: Swatinem/rust-cache@v2
Expand All @@ -74,10 +75,10 @@ jobs:
# That state no longer exists; the band-aid is removed in this PR.
steps:
- uses: actions/checkout@v4
# Stable rustfmt 1.97.1 — pinned in `rust-toolchain.toml`. No
# nightly dependency since rustfmt.toml is stable-clean post-PR
# #133.
- uses: dtolnay/rust-toolchain@1.97.1
# Stable rustfmt on the pinned channel (see `rust-toolchain.toml`;
# version deliberately not restated here). No nightly dependency since
# rustfmt.toml is stable-clean post-PR #133.
- uses: dtolnay/rust-toolchain@1.98.1
with:
components: rustfmt
- run: cargo fmt --all --check
Expand All @@ -99,7 +100,7 @@ jobs:
with:
toolchain: ${{ matrix.rust }}
targets: ${{ matrix.target }}
# rust-toolchain.toml pins 1.97.1 — install the cross-compile target
# rust-toolchain.toml pins the channel — install the cross-compile target
# for that toolchain too, since dtolnay/rust-toolchain only installs
# for the matrix value which may differ from the pinned version.
- run: rustup target add ${{ matrix.target }}
Expand All @@ -126,7 +127,7 @@ jobs:
- uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-unknown-unknown
# rust-toolchain.toml pins 1.97.1 — install the wasm target for the pinned
# rust-toolchain.toml pins the channel — install the wasm target for the pinned
# toolchain too (dtolnay installs for `stable`, which may differ).
- run: rustup target add wasm32-unknown-unknown
- uses: actions/setup-node@v4
Expand Down Expand Up @@ -155,7 +156,7 @@ jobs:
- uses: dtolnay/rust-toolchain@stable
with:
targets: aarch64-unknown-linux-gnu
# rust-toolchain.toml pins 1.97.1 — install the aarch64 target for the
# rust-toolchain.toml pins the channel — install the aarch64 target for the
# pinned toolchain too (dtolnay installs for `stable`, which may differ).
- run: rustup target add aarch64-unknown-linux-gnu
- name: install aarch64 cross toolchain + qemu-user
Expand Down Expand Up @@ -210,7 +211,7 @@ jobs:
name: hpc-stream-parallel/rayon
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.97.1
- uses: dtolnay/rust-toolchain@1.98.1
- uses: Swatinem/rust-cache@v2
- uses: taiki-e/install-action@nextest
- name: cargo check (no rayon — scalar path unchanged)
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ edition = "2021"
# of the contract crate happens to still succeed today — a coincidence, not a
# guarantee, and exactly what an untested MSRV declaration buys. Declare what is
# actually verified.
rust-version = "1.97"
rust-version = "1.98"
authors = [
"Ulrik Sverdrup \"bluss\"",
"Jim Turner"
Expand Down
9 changes: 4 additions & 5 deletions crates/numeric-tests/tests/accuracy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,18 +269,17 @@ fn accurate_mul_with_column_f64() {
let a = gen::<f64, _>(Ix2(m, k), rng);
let b_owner = gen::<f64, _>(Ix2(k, k), rng);
let b_row_col;
let b_sq;

// pick dense square or broadcasted to square matrix
match i {
0..=3 => b_sq = b_owner.view(),
let b_sq = match i {
0..=3 => b_owner.view(),
4..=7 => {
b_row_col = b_owner.column(0);
b_sq = b_row_col.broadcast((k, k)).unwrap();
b_row_col.broadcast((k, k)).unwrap()
}
_otherwise => {
b_row_col = b_owner.row(0);
b_sq = b_row_col.broadcast((k, k)).unwrap();
b_row_col.broadcast((k, k)).unwrap()
}
};

Expand Down
2 changes: 1 addition & 1 deletion examples/morton_cascade_probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ impl Pyramid {
for l in 1..=k as usize {
let prev = &levels[l - 1];
let mut cur = Vec::with_capacity(prev.len() / 4);
for node in prev.chunks_exact(4) {
for node in prev.as_chunks::<4>().0 {
let mn = node.iter().map(|p| p.0).fold(f32::INFINITY, f32::min);
let mx = node.iter().map(|p| p.1).fold(f32::NEG_INFINITY, f32::max);
cur.push((mn, mx));
Expand Down
2 changes: 1 addition & 1 deletion examples/onebrc_cascade_probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ impl Pyramid {
for l in 1..=k as usize {
let prev = &levels[l - 1];
let mut cur = Vec::with_capacity(prev.len() / 4);
for q in prev.chunks_exact(4) {
for q in prev.as_chunks::<4>().0 {
cur.push(Node {
min: q.iter().map(|n| n.min).fold(f32::INFINITY, f32::min),
max: q.iter().map(|n| n.max).fold(f32::NEG_INFINITY, f32::max),
Expand Down
31 changes: 20 additions & 11 deletions rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
[toolchain]
channel = "1.97.1"
# Pinned to 1.97.1 (2026-08-05). Aligns ndarray with the rest of the
# AdaWorldAPI stack — lance-graph, OGAR, ruff, MedCare-rs, woa-rs, a2ui-rs and
# stockfish-rs are all on 1.97.1; ndarray was the last sibling still declaring
# 1.95, so a consumer path-dep'ing both it and lance-graph-contract saw two
# different MSRVs.
channel = "1.98.1"
# The pinned version is the `channel` line ABOVE — deliberately not restated
# here. This comment used to open "Pinned to 1.97.1", and this file's own
# warning explains why that is a trap: "A stale comment on a version pin is how
# the next reader learns the wrong number." A bump edits `channel` and leaves
# prose behind, so the prose keeps only the rationale.
#
# Rationale: ndarray moves in lockstep with the rest of the AdaWorldAPI stack —
# lance-graph, OGAR, ruff, MedCare-rs, woa-rs, a2ui-rs, stockfish-rs — because a
# consumer path-dep'ing both ndarray and lance-graph-contract otherwise sees two
# different MSRVs. ndarray was once the last sibling still declaring 1.95.
#
# The channel here and `Cargo.toml`'s `rust-version` must move TOGETHER. They
# were out of step between the 1.95 → 1.97.1 channel bump and 2026-08-05: this
# file said 1.97.1 while the manifest still declared 1.95, and the comment below
# still described the 1.95 rationale. A stale comment on a version pin is how the
# next reader learns the wrong number.
# file named one version while the manifest declared another.
#
# Bump log (append one line per bump):
# 1.95 → 1.97.1 stack alignment (2026-08-05); the 1.95 bump had introduced
# `clippy::manual_checked_ops`, fixed in `impl_owned_array.rs`
# 1.97.1 → 1.98.1 current stable (1.98.0 2026-08-20, 1.98.1 2026-09-01);
# workspace-wide sweep. The 1.98 delta measured across the
# stack is ONE lint, `clippy::chunks_exact_to_as_chunks`
# (new, default-on STYLE group) — zero sites in this repo.
#
# (Historical: the 1.95 bump introduced `clippy::manual_checked_ops`, which fired
# on `impl_owned_array.rs::into_scalar` and was fixed in that same commit.)
# Never auto-track `stable` — bump explicitly when a future version is
# reviewed and the workspace clippy passes clean.
components = ["clippy", "rustfmt"]
10 changes: 6 additions & 4 deletions src/backend/kernels_avx512.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,13 @@ pub fn scal_f64(alpha: f64, x: &mut [f64]) {
#[cfg(target_arch = "x86_64")]
#[target_feature(enable = "avx512f")]
pub fn asum_f32(x: &[f32]) -> f32 {
let (chunks, remainder) = x.as_chunks::<16>();
let mut acc = F32x16::splat(0.0);
for chunk in x.chunks_exact(16) {
for chunk in chunks {
acc += F32x16::from_slice(chunk).abs();
}
let mut sum = acc.reduce_sum();
for &v in x.chunks_exact(16).remainder() {
for &v in remainder {
sum += v.abs();
}
sum
Expand All @@ -190,12 +191,13 @@ pub fn asum_f32(x: &[f32]) -> f32 {
#[cfg(target_arch = "x86_64")]
#[target_feature(enable = "avx512f")]
pub fn asum_f64(x: &[f64]) -> f64 {
let (chunks, remainder) = x.as_chunks::<8>();
let mut acc = F64x8::splat(0.0);
for chunk in x.chunks_exact(8) {
for chunk in chunks {
acc += F64x8::from_slice(chunk).abs();
}
let mut sum = acc.reduce_sum();
for &v in x.chunks_exact(8).remainder() {
for &v in remainder {
sum += v.abs();
}
sum
Expand Down
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
clippy::deref_addrof,
clippy::manual_map, // is not an error
clippy::while_let_on_iterator, // is not an error
clippy::from_iter_instead_of_collect, // using from_iter is good style
clippy::incompatible_msrv, // false positive PointerExt::offset
)]
#![doc(test(attr(deny(warnings))))]
Expand Down
7 changes: 6 additions & 1 deletion src/simd_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,12 @@ pub fn bf16_tile_gemm_16x16(a_bf16: &[u16], b_bf16: &[u16], c: &mut [f32], k: us
*slot = b_f32[kk * 16 + j];
}
let mut acc = F32x16::splat(0.0);
for (ra, rb) in a_row.chunks_exact(16).zip(col.chunks_exact(16)) {
for (ra, rb) in a_row
.as_chunks::<16>()
.0
.iter()
.zip(col.as_chunks::<16>().0)
{
acc = F32x16::from_slice(ra).mul_add(F32x16::from_slice(rb), acc);
}
c[i * 16 + j] += acc.reduce_sum();
Expand Down
Loading