From 3902ad88aa4ceedc60763d988585442ef876cdb0 Mon Sep 17 00:00:00 2001 From: "riseproject-dev[bot]" <330740410+riseproject-dev[bot]@users.noreply.github.com> Date: Thu, 22 Oct 2026 12:02:55 +0000 Subject: [PATCH 01/10] lance-context: Add versions 0.6.6, 0.6.7 Signed-off-by: riseproject-dev[bot] <330740410+riseproject-dev[bot]@users.noreply.github.com> --- docs/packages/lance-context.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/packages/lance-context.yaml b/docs/packages/lance-context.yaml index 2d30330f8a70..595efbc03092 100644 --- a/docs/packages/lance-context.yaml +++ b/docs/packages/lance-context.yaml @@ -9,3 +9,5 @@ versions: - filename: lance_context-0.6.5-cp39-abi3-manylinux_2_39_riscv64.whl sha256: 92d24bb5ae04b93a78c2a04c35b8718f2dd1befa470916b8bb733d24959b1065 requires-python: '>=3.11, <3.14' +- version: 0.6.6 +- version: 0.6.7 From d0714daa9f1594cf6062f457a080b99401cd99d5 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Fri, 23 Oct 2026 12:19:18 +0800 Subject: [PATCH 02/10] lance-context: drop the unused lance-graph dependency for 0.6.6 --- ...remove-unused-lance-graph-dependency.patch | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 patches/lance-context/0.6.6/0001-remove-unused-lance-graph-dependency.patch diff --git a/patches/lance-context/0.6.6/0001-remove-unused-lance-graph-dependency.patch b/patches/lance-context/0.6.6/0001-remove-unused-lance-graph-dependency.patch new file mode 100644 index 000000000000..3551258942e1 --- /dev/null +++ b/patches/lance-context/0.6.6/0001-remove-unused-lance-graph-dependency.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ludovic Henry +Date: Mon, 06 Oct 2026 00:00:00 +0000 +Subject: [PATCH] lance-context-core: drop the unused lance-graph dependency + +crates/lance-context-core/Cargo.toml depends on `lance-graph = "0.5.4"`, +but no Rust source file in this workspace imports `lance_graph` +(`grep -rln lance_graph crates/ python/` matches nothing). lance-graph's +own Cargo.toml pins `lance`/`lance-core`/`lance-linalg` at an incompatible +`1.x` line, which Cargo resolves as a third, parallel copy of the whole +lance-core/lance-linalg family next to the `7.0.0` one lancedb pulls in +and the `9.0.0` one `crates/lance-context-core` depends on directly. +Cargo's `[patch]` table needs one entry per semver-incompatible line of a +crate that is to be redirected, and the riscv64 SIMD fallbacks (see +0003-cargo-patch-lance-crates-for-riscv64.patch) only exist for the 7.x +and 9.x lines, so removing the dead dependency drops the 1.x copy from +resolution instead. + +Upstream-Status: To upstream [not yet submitted to lance-format/lance-context] + +Signed-off-by: Ludovic Henry +--- + crates/lance-context-core/Cargo.toml | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/crates/lance-context-core/Cargo.toml b/crates/lance-context-core/Cargo.toml +index 55f7dce..9c2311a 100644 +--- a/crates/lance-context-core/Cargo.toml ++++ b/crates/lance-context-core/Cargo.toml +@@ -31,7 +31,6 @@ lance-context-api = { version = "0.6.6", path = "../lance-context-api" } + lance-index = "9.0.0" + lance-namespace = "9.0.0" + lancedb = "0.30.0" +-lance-graph = "0.5.4" + # Version-matched with lance-context-server/-master so one process-wide recorder + # serves every crate. + metrics = { version = "0.24", optional = true } +-- +2.43.0 From 0ab7d8815e5ef40ae1bb9fe7adafe17f9eea7e1d Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Fri, 23 Oct 2026 12:19:23 +0800 Subject: [PATCH 03/10] lance-context: drop the unused lance-graph dependency for 0.6.7 --- ...remove-unused-lance-graph-dependency.patch | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 patches/lance-context/0.6.7/0001-remove-unused-lance-graph-dependency.patch diff --git a/patches/lance-context/0.6.7/0001-remove-unused-lance-graph-dependency.patch b/patches/lance-context/0.6.7/0001-remove-unused-lance-graph-dependency.patch new file mode 100644 index 000000000000..456f2e7afd42 --- /dev/null +++ b/patches/lance-context/0.6.7/0001-remove-unused-lance-graph-dependency.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ludovic Henry +Date: Mon, 06 Oct 2026 00:00:00 +0000 +Subject: [PATCH] lance-context-core: drop the unused lance-graph dependency + +crates/lance-context-core/Cargo.toml depends on `lance-graph = "0.5.4"`, +but no Rust source file in this workspace imports `lance_graph` +(`grep -rln lance_graph crates/ python/` matches nothing). lance-graph's +own Cargo.toml pins `lance`/`lance-core`/`lance-linalg` at an incompatible +`1.x` line, which Cargo resolves as a third, parallel copy of the whole +lance-core/lance-linalg family next to the `7.0.0` one lancedb pulls in +and the `9.0.0` one `crates/lance-context-core` depends on directly. +Cargo's `[patch]` table needs one entry per semver-incompatible line of a +crate that is to be redirected, and the riscv64 SIMD fallbacks (see +0003-cargo-patch-lance-crates-for-riscv64.patch) only exist for the 7.x +and 9.x lines, so removing the dead dependency drops the 1.x copy from +resolution instead. + +Upstream-Status: To upstream [not yet submitted to lance-format/lance-context] + +Signed-off-by: Ludovic Henry +--- + crates/lance-context-core/Cargo.toml | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/crates/lance-context-core/Cargo.toml b/crates/lance-context-core/Cargo.toml +index a5d0f25..928c52a 100644 +--- a/crates/lance-context-core/Cargo.toml ++++ b/crates/lance-context-core/Cargo.toml +@@ -31,7 +31,6 @@ lance-context-api = { version = "0.6.7", path = "../lance-context-api" } + lance-index = "9.0.0" + lance-namespace = "9.0.0" + lancedb = "0.30.0" +-lance-graph = "0.5.4" + # Version-matched with lance-context-server/-master so one process-wide recorder + # serves every crate. + metrics = { version = "0.24", optional = true } +-- +2.43.0 From 551779f04ce20e67ec288a65a7f34572355ccbe9 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Fri, 23 Oct 2026 12:19:27 +0800 Subject: [PATCH 04/10] lance-context: carry the lance-core riscv64 SIMD fallback to 0.6.6 --- ...002-lance-core-riscv64-simd-fallback.patch | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 patches/lance-context/0.6.6/0002-lance-core-riscv64-simd-fallback.patch diff --git a/patches/lance-context/0.6.6/0002-lance-core-riscv64-simd-fallback.patch b/patches/lance-context/0.6.6/0002-lance-core-riscv64-simd-fallback.patch new file mode 100644 index 000000000000..58c2f4f76bd5 --- /dev/null +++ b/patches/lance-context/0.6.6/0002-lance-core-riscv64-simd-fallback.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ludovic Henry +Date: Mon, 06 Oct 2026 00:00:00 +0000 +Subject: [PATCH] lance-core: add a portable riscv64 SIMD-tier fallback + +lance-core's SIMD_SUPPORT static (src/utils/cpu.rs) picks a SIMD tier +via a `cfg`-gated closure with arms for aarch64, x86_64 and loongarch64 +only; none of them match riscv64, so the closure's block has no +trailing expression there and the crate fails to compile with "expected +`SimdSupport`, found `()`". Add a `None`-tier fallback arm beside the +existing ones for every architecture without a dedicated tier. + +Applied (via patches/lance-context/0.6.5/0003-cargo-patch-lance-crates-for-riscv64.patch) +to a local copy of this crate's 7.0.0 crates.io release, which +crates/lance-context-core's `lance = "7.0.0"` pulls in transitively +and cannot be patched in place (CLAUDE.md gotcha 300). + +Upstream-Status: To upstream [not yet submitted to lance-format/lance] + +Signed-off-by: Ludovic Henry +--- +diff --git a/src/utils/cpu.rs b/src/utils/cpu.rs +index 4e7ab01..34ed3a0 100644 +--- a/src/utils/cpu.rs ++++ b/src/utils/cpu.rs +@@ -58,6 +58,17 @@ pub static SIMD_SUPPORT: LazyLock = LazyLock::new(|| { + SimdSupport::None + } + } ++ // riscv64 (and any other architecture without a dedicated tier above) has ++ // no SIMD kernels in lance yet; upstream's cfg arms have no catch-all, so ++ // this closure otherwise evaluates to `()` here instead of `SimdSupport`. ++ #[cfg(not(any( ++ target_arch = "aarch64", ++ target_arch = "x86_64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ SimdSupport::None ++ } + }); + + #[cfg(target_arch = "x86_64")] +-- +2.43.0 From 25bbd19cf4ab33ebf29b721934350ae356f9ccb8 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Fri, 23 Oct 2026 12:19:32 +0800 Subject: [PATCH 05/10] lance-context: carry the lance-core riscv64 SIMD fallback to 0.6.7 --- ...002-lance-core-riscv64-simd-fallback.patch | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 patches/lance-context/0.6.7/0002-lance-core-riscv64-simd-fallback.patch diff --git a/patches/lance-context/0.6.7/0002-lance-core-riscv64-simd-fallback.patch b/patches/lance-context/0.6.7/0002-lance-core-riscv64-simd-fallback.patch new file mode 100644 index 000000000000..58c2f4f76bd5 --- /dev/null +++ b/patches/lance-context/0.6.7/0002-lance-core-riscv64-simd-fallback.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ludovic Henry +Date: Mon, 06 Oct 2026 00:00:00 +0000 +Subject: [PATCH] lance-core: add a portable riscv64 SIMD-tier fallback + +lance-core's SIMD_SUPPORT static (src/utils/cpu.rs) picks a SIMD tier +via a `cfg`-gated closure with arms for aarch64, x86_64 and loongarch64 +only; none of them match riscv64, so the closure's block has no +trailing expression there and the crate fails to compile with "expected +`SimdSupport`, found `()`". Add a `None`-tier fallback arm beside the +existing ones for every architecture without a dedicated tier. + +Applied (via patches/lance-context/0.6.5/0003-cargo-patch-lance-crates-for-riscv64.patch) +to a local copy of this crate's 7.0.0 crates.io release, which +crates/lance-context-core's `lance = "7.0.0"` pulls in transitively +and cannot be patched in place (CLAUDE.md gotcha 300). + +Upstream-Status: To upstream [not yet submitted to lance-format/lance] + +Signed-off-by: Ludovic Henry +--- +diff --git a/src/utils/cpu.rs b/src/utils/cpu.rs +index 4e7ab01..34ed3a0 100644 +--- a/src/utils/cpu.rs ++++ b/src/utils/cpu.rs +@@ -58,6 +58,17 @@ pub static SIMD_SUPPORT: LazyLock = LazyLock::new(|| { + SimdSupport::None + } + } ++ // riscv64 (and any other architecture without a dedicated tier above) has ++ // no SIMD kernels in lance yet; upstream's cfg arms have no catch-all, so ++ // this closure otherwise evaluates to `()` here instead of `SimdSupport`. ++ #[cfg(not(any( ++ target_arch = "aarch64", ++ target_arch = "x86_64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ SimdSupport::None ++ } + }); + + #[cfg(target_arch = "x86_64")] +-- +2.43.0 From 32865521449ac0c62e7cd3aa574d1d0bfc5c1ac0 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Fri, 23 Oct 2026 12:19:46 +0800 Subject: [PATCH 06/10] lance-context: redirect lance-core/lance-linalg to riscv64-patched copies for 0.6.6 --- ...cargo-patch-lance-crates-for-riscv64.patch | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 patches/lance-context/0.6.6/0003-cargo-patch-lance-crates-for-riscv64.patch diff --git a/patches/lance-context/0.6.6/0003-cargo-patch-lance-crates-for-riscv64.patch b/patches/lance-context/0.6.6/0003-cargo-patch-lance-crates-for-riscv64.patch new file mode 100644 index 000000000000..e7bb17b0861e --- /dev/null +++ b/patches/lance-context/0.6.6/0003-cargo-patch-lance-crates-for-riscv64.patch @@ -0,0 +1,88 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ludovic Henry +Date: Mon, 06 Oct 2026 00:00:00 +0000 +Subject: [PATCH] cargo: redirect lance-core/lance-linalg to riscv64-patched + checkouts + +lance-core's SIMD_SUPPORT static (src/utils/cpu.rs) and lance-linalg's +f32x8/f32x16/i32x8/f64x4/f64x8 SIMD types (src/simd/{f32,i32,f64}.rs) +are compiled for x86_64/aarch64/loongarch64 only, with no fallback arm +for any other architecture (CLAUDE.md gotcha 300). + +Cargo.lock holds two semver-incompatible lines of both crates once +lance-graph is gone: 7.0.0 (pulled in by lancedb 0.30.0) and 9.0.0 +(`lance = "9.0.0"` in crates/lance-context-core). `[patch.crates-io]` +redirects one version per crate name, so the 9.0.0 pair uses the plain +name and the 7.0.0 pair an aliased entry (`package = "lance-core"`). +Both are redirected to the riscv64-patched copies the workflow +materializes at build time from the pinned crates.io releases (see +0002/0004, applied to both lines); only the `source`/ +`checksum` lines of those four Cargo.lock entries change. + +Upstream-Status: Inappropriate [redirects a pinned dependency to a local checkout materialized at build time; the fix itself belongs in lance-format/lance] + +Signed-off-by: Ludovic Henry +--- +diff --git a/Cargo.lock b/Cargo.lock +index ac263f7..d87b7b3 100644 +--- a/Cargo.lock ++++ b/Cargo.lock +@@ -6491,8 +6491,6 @@ dependencies = [ + [[package]] + name = "lance-core" + version = "7.0.0" +-source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "13f84020da5a484e2f07dd1796e09785ed7cd889857ebc4cb77e32ef214ee594" + dependencies = [ + "arrow-array 58.3.0", + "arrow-buffer 58.3.0", +@@ -6528,8 +6526,6 @@ dependencies = [ + [[package]] + name = "lance-core" + version = "9.0.0" +-source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "238c8a58308e7718d6bd96b53494eb7953fa299778bc4911cc571c3576e9446d" + dependencies = [ + "arrow-array 58.3.0", + "arrow-buffer 58.3.0", +@@ -7387,8 +7383,6 @@ dependencies = [ + [[package]] + name = "lance-linalg" + version = "7.0.0" +-source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "6b4c51cad0ac780b02dc4da48528479e7693c03e8d05390510bbc69ca2a9a1f1" + dependencies = [ + "arrow-array 58.3.0", + "arrow-buffer 58.3.0", +@@ -7405,8 +7399,6 @@ dependencies = [ + [[package]] + name = "lance-linalg" + version = "9.0.0" +-source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "0e5a9b99bd1f49bc2fe5afb81323141abc506c818f589de95dbab4f6143d9a88" + dependencies = [ + "arrow-array 58.3.0", + "arrow-buffer 58.3.0", +diff --git a/Cargo.toml b/Cargo.toml +index 2efab19..07f2f68 100644 +--- a/Cargo.toml ++++ b/Cargo.toml +@@ -17,3 +17,16 @@ license = "Apache-2.0" + + [workspace.metadata] + # reserved for future use ++ ++# lance-core's SIMD_SUPPORT static and lance-linalg's f32x8/f32x16/i32x8/ ++# f64x4/f64x8 SIMD types compile only for x86_64/aarch64/loongarch64 ++# upstream (CLAUDE.md gotcha 300); the riscv64-patched copies below are ++# materialized from the pinned crates.io releases by the workflow at ++# build time. Cargo.lock pins two semver-incompatible lines of each crate ++# (7.0.0 via lancedb, 9.0.0 via lance-context-core), and [patch] can only ++# redirect one per name, so the second is patched through an aliased entry. ++[patch.crates-io] ++lance-core = { path = "lance-core-9.0.0-riscv64" } ++lance-linalg = { path = "lance-linalg-9.0.0-riscv64" } ++lance-core-7 = { path = "lance-core-7.0.0-riscv64", package = "lance-core" } ++lance-linalg-7 = { path = "lance-linalg-7.0.0-riscv64", package = "lance-linalg" } +-- +2.43.0 From dee461b5549bb4151608efc2b0a7a1e203001182 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Fri, 23 Oct 2026 12:19:56 +0800 Subject: [PATCH 07/10] lance-context: redirect lance-core/lance-linalg to riscv64-patched copies for 0.6.7 --- ...cargo-patch-lance-crates-for-riscv64.patch | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 patches/lance-context/0.6.7/0003-cargo-patch-lance-crates-for-riscv64.patch diff --git a/patches/lance-context/0.6.7/0003-cargo-patch-lance-crates-for-riscv64.patch b/patches/lance-context/0.6.7/0003-cargo-patch-lance-crates-for-riscv64.patch new file mode 100644 index 000000000000..c584b6a055a0 --- /dev/null +++ b/patches/lance-context/0.6.7/0003-cargo-patch-lance-crates-for-riscv64.patch @@ -0,0 +1,88 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ludovic Henry +Date: Mon, 06 Oct 2026 00:00:00 +0000 +Subject: [PATCH] cargo: redirect lance-core/lance-linalg to riscv64-patched + checkouts + +lance-core's SIMD_SUPPORT static (src/utils/cpu.rs) and lance-linalg's +f32x8/f32x16/i32x8/f64x4/f64x8 SIMD types (src/simd/{f32,i32,f64}.rs) +are compiled for x86_64/aarch64/loongarch64 only, with no fallback arm +for any other architecture (CLAUDE.md gotcha 300). + +Cargo.lock holds two semver-incompatible lines of both crates once +lance-graph is gone: 7.0.0 (pulled in by lancedb 0.30.0) and 9.0.0 +(`lance = "9.0.0"` in crates/lance-context-core). `[patch.crates-io]` +redirects one version per crate name, so the 9.0.0 pair uses the plain +name and the 7.0.0 pair an aliased entry (`package = "lance-core"`). +Both are redirected to the riscv64-patched copies the workflow +materializes at build time from the pinned crates.io releases (see +0002/0004, applied to both lines); only the `source`/ +`checksum` lines of those four Cargo.lock entries change. + +Upstream-Status: Inappropriate [redirects a pinned dependency to a local checkout materialized at build time; the fix itself belongs in lance-format/lance] + +Signed-off-by: Ludovic Henry +--- +diff --git a/Cargo.lock b/Cargo.lock +index ae51867..517dc44 100644 +--- a/Cargo.lock ++++ b/Cargo.lock +@@ -6491,8 +6491,6 @@ dependencies = [ + [[package]] + name = "lance-core" + version = "7.0.0" +-source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "13f84020da5a484e2f07dd1796e09785ed7cd889857ebc4cb77e32ef214ee594" + dependencies = [ + "arrow-array 58.3.0", + "arrow-buffer 58.3.0", +@@ -6528,8 +6526,6 @@ dependencies = [ + [[package]] + name = "lance-core" + version = "9.0.0" +-source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "238c8a58308e7718d6bd96b53494eb7953fa299778bc4911cc571c3576e9446d" + dependencies = [ + "arrow-array 58.3.0", + "arrow-buffer 58.3.0", +@@ -7387,8 +7383,6 @@ dependencies = [ + [[package]] + name = "lance-linalg" + version = "7.0.0" +-source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "6b4c51cad0ac780b02dc4da48528479e7693c03e8d05390510bbc69ca2a9a1f1" + dependencies = [ + "arrow-array 58.3.0", + "arrow-buffer 58.3.0", +@@ -7405,8 +7399,6 @@ dependencies = [ + [[package]] + name = "lance-linalg" + version = "9.0.0" +-source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "0e5a9b99bd1f49bc2fe5afb81323141abc506c818f589de95dbab4f6143d9a88" + dependencies = [ + "arrow-array 58.3.0", + "arrow-buffer 58.3.0", +diff --git a/Cargo.toml b/Cargo.toml +index 2efab19..07f2f68 100644 +--- a/Cargo.toml ++++ b/Cargo.toml +@@ -17,3 +17,16 @@ license = "Apache-2.0" + + [workspace.metadata] + # reserved for future use ++ ++# lance-core's SIMD_SUPPORT static and lance-linalg's f32x8/f32x16/i32x8/ ++# f64x4/f64x8 SIMD types compile only for x86_64/aarch64/loongarch64 ++# upstream (CLAUDE.md gotcha 300); the riscv64-patched copies below are ++# materialized from the pinned crates.io releases by the workflow at ++# build time. Cargo.lock pins two semver-incompatible lines of each crate ++# (7.0.0 via lancedb, 9.0.0 via lance-context-core), and [patch] can only ++# redirect one per name, so the second is patched through an aliased entry. ++[patch.crates-io] ++lance-core = { path = "lance-core-9.0.0-riscv64" } ++lance-linalg = { path = "lance-linalg-9.0.0-riscv64" } ++lance-core-7 = { path = "lance-core-7.0.0-riscv64", package = "lance-core" } ++lance-linalg-7 = { path = "lance-linalg-7.0.0-riscv64", package = "lance-linalg" } +-- +2.43.0 From a26e5a3b725b276fcaad54e24c62b13ec43cdcb9 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Fri, 23 Oct 2026 12:21:09 +0800 Subject: [PATCH 08/10] lance-context: carry the lance-linalg riscv64 SIMD fallback to 0.6.6 --- ...4-lance-linalg-riscv64-simd-fallback.patch | 1400 +++++++++++++++++ 1 file changed, 1400 insertions(+) create mode 100644 patches/lance-context/0.6.6/0004-lance-linalg-riscv64-simd-fallback.patch diff --git a/patches/lance-context/0.6.6/0004-lance-linalg-riscv64-simd-fallback.patch b/patches/lance-context/0.6.6/0004-lance-linalg-riscv64-simd-fallback.patch new file mode 100644 index 000000000000..03a3ed39625f --- /dev/null +++ b/patches/lance-context/0.6.6/0004-lance-linalg-riscv64-simd-fallback.patch @@ -0,0 +1,1400 @@ +Upstream-Status: To upstream [lance-linalg's per-arch SIMD structs (f32x8/f32x16/f64x4/f64x8/i32x8) have no fallback for architectures without a dedicated tier (riscv64 included); not filed upstream per this session's policy against opening external issues/PRs] + +--- lance-linalg-orig/src/simd/f32.rs 2006-07-24 03:21:28 ++++ lance-linalg-9.0.0-riscv64/src/simd/f32.rs 2026-09-07 02:16:55 +@@ -35,6 +35,17 @@ + #[derive(Clone, Copy)] + pub struct f32x8(v8f32); + ++/// 8 of 32-bit `f32` values. Portable scalar fallback for architectures with ++/// no dedicated SIMD tier above (riscv64 included) -- CLAUDE.md gotcha 300. ++#[allow(non_camel_case_types)] ++#[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++)))] ++#[derive(Clone, Copy)] ++pub struct f32x8([f32; 8]); ++ + impl std::fmt::Debug for f32x8 { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let mut arr = [0.0_f32; 8]; +@@ -119,6 +130,27 @@ + ]; + Self::load_unaligned(values.as_ptr()) + } ++ ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ unsafe { ++ let ptr = slice.as_ptr(); ++ ++ let values = [ ++ *ptr.add(indices[0] as usize), ++ *ptr.add(indices[1] as usize), ++ *ptr.add(indices[2] as usize), ++ *ptr.add(indices[3] as usize), ++ *ptr.add(indices[4] as usize), ++ *ptr.add(indices[5] as usize), ++ *ptr.add(indices[6] as usize), ++ *ptr.add(indices[7] as usize), ++ ]; ++ Self::load_unaligned(values.as_ptr()) ++ } + } + } + +@@ -172,6 +204,14 @@ + unsafe { + Self(transmute(lasx_xvreplgr2vr_w(transmute(val)))) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self([val; 8]) ++ } + } + + fn zeros() -> Self { +@@ -186,6 +226,14 @@ + #[cfg(target_arch = "loongarch64")] + { + Self::splat(0.0) ++ } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self([0.0; 8]) + } + } + +@@ -203,6 +251,14 @@ + { + Self(transmute(lasx_xvld::<0>(transmute(ptr)))) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self::load_unaligned(ptr) ++ } + } + + #[inline] +@@ -219,6 +275,18 @@ + { + Self(transmute(lasx_xvld::<0>(transmute(ptr)))) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f32; 8]; ++ for (i, r) in result.iter_mut().enumerate() { ++ *r = unsafe { *ptr.add(i) }; ++ } ++ Self(result) ++ } + } + + unsafe fn store(&self, ptr: *mut f32) { +@@ -234,6 +302,14 @@ + unsafe { + lasx_xvst::<0>(transmute(self.0), transmute(ptr)); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ unsafe { ++ self.store_unaligned(ptr); ++ } + } + + unsafe fn store_unaligned(&self, ptr: *mut f32) { +@@ -249,6 +325,16 @@ + unsafe { + lasx_xvst::<0>(transmute(self.0), transmute(ptr)); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ unsafe { ++ for (i, v) in self.0.iter().enumerate() { ++ *ptr.add(i) = *v; ++ } ++ } + } + + #[inline] +@@ -277,6 +363,14 @@ + { + self.as_array().iter().sum() + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ self.0.iter().sum() ++ } + } + + fn reduce_min(&self) -> f32 { +@@ -311,6 +405,14 @@ + let m2 = lasx_xvfmin_s(transmute(m1), transmute(m2)); + transmute(lasx_xvpickve2gr_w::<0>(transmute(m2))) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ self.0.iter().copied().fold(f32::INFINITY, f32::min) ++ } + } + + fn min(&self, rhs: &Self) -> Self { +@@ -329,6 +431,18 @@ + unsafe { + Self(lasx_xvfmin_s(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f32; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i].min(rhs.0[i]); ++ } ++ Self(result) ++ } + } + + fn find(&self, val: f32) -> Option { +@@ -362,6 +476,18 @@ + } + } + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..8 { ++ if self.0[i] == val { ++ return Some(i as i32); ++ } ++ } ++ } + None + } + } +@@ -380,6 +506,16 @@ + #[cfg(target_arch = "loongarch64")] + unsafe { + self.0 = lasx_xvfmadd_s(a.0, b.0, self.0); ++ } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..8 { ++ self.0[i] += a.0[i] * b.0[i]; ++ } + } + } + } +@@ -404,6 +540,18 @@ + unsafe { + Self(lasx_xvfadd_s(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f32; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i] + rhs.0[i]; ++ } ++ Self(result) ++ } + } + } + +@@ -423,6 +571,16 @@ + unsafe { + self.0 = lasx_xvfadd_s(self.0, rhs.0); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..8 { ++ self.0[i] += rhs.0[i]; ++ } ++ } + } + } + +@@ -446,6 +604,18 @@ + unsafe { + Self(lasx_xvfsub_s(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f32; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i] - rhs.0[i]; ++ } ++ Self(result) ++ } + } + } + +@@ -465,6 +635,16 @@ + unsafe { + self.0 = lasx_xvfsub_s(self.0, rhs.0); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..8 { ++ self.0[i] -= rhs.0[i]; ++ } ++ } + } + } + +@@ -488,6 +668,18 @@ + unsafe { + Self(lasx_xvfmul_s(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f32; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i] * rhs.0[i]; ++ } ++ Self(result) ++ } + } + } + +@@ -516,6 +708,16 @@ + #[derive(Clone, Copy)] + pub struct f32x16(v8f32, v8f32); + ++/// 16 of 32-bit `f32` values. Portable scalar fallback -- CLAUDE.md gotcha 300. ++#[allow(non_camel_case_types)] ++#[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++)))] ++#[derive(Clone, Copy)] ++pub struct f32x16([f32; 16]); ++ + impl std::fmt::Debug for f32x16 { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let mut arr = [0.0_f32; 16]; +@@ -561,6 +763,14 @@ + transmute(lasx_xvreplgr2vr_w(transmute(val))), + ) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self([val; 16]) ++ } + } + + #[inline] +@@ -577,6 +787,14 @@ + { + Self::splat(0.0) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self([0.0; 16]) ++ } + } + + #[inline] +@@ -596,6 +814,14 @@ + transmute(lasx_xvld::<32>(transmute(ptr))), + ) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self::load_unaligned(ptr) ++ } + } + + #[inline] +@@ -614,6 +840,18 @@ + transmute(lasx_xvld::<0>(transmute(ptr))), + transmute(lasx_xvld::<32>(transmute(ptr))), + ) ++ } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f32; 16]; ++ for (i, r) in result.iter_mut().enumerate() { ++ *r = unsafe { *ptr.add(i) }; ++ } ++ Self(result) + } + } + +@@ -633,6 +871,14 @@ + lasx_xvst::<0>(transmute(self.0), transmute(ptr)); + lasx_xvst::<32>(transmute(self.1), transmute(ptr)); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ unsafe { ++ self.store_unaligned(ptr); ++ } + } + + #[inline] +@@ -651,6 +897,16 @@ + lasx_xvst::<0>(transmute(self.0), transmute(ptr)); + lasx_xvst::<32>(transmute(self.1), transmute(ptr)); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ unsafe { ++ for (i, v) in self.0.iter().enumerate() { ++ *ptr.add(i) = *v; ++ } ++ } + } + + #[inline] +@@ -681,6 +937,14 @@ + { + self.as_array().iter().sum() + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ self.0.iter().sum() ++ } + } + + #[inline] +@@ -715,6 +979,14 @@ + let m1 = lasx_xvfmin_s(transmute(m1), transmute(m2)); + transmute(lasx_xvpickve2gr_w::<0>(transmute(m1))) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ self.0.iter().copied().fold(f32::INFINITY, f32::min) ++ } + } + + #[inline] +@@ -736,6 +1008,18 @@ + unsafe { + Self(lasx_xvfmin_s(self.0, rhs.0), lasx_xvfmin_s(self.1, rhs.1)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f32; 16]; ++ for i in 0..16 { ++ result[i] = self.0[i].min(rhs.0[i]); ++ } ++ Self(result) ++ } + } + + #[inline] +@@ -782,6 +1066,19 @@ + } + None + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..16 { ++ if self.0[i] == val { ++ return Some(i as i32); ++ } ++ } ++ None ++ } + } + } + +@@ -805,6 +1102,16 @@ + self.0 = lasx_xvfmadd_s(a.0, b.0, self.0); + self.1 = lasx_xvfmadd_s(a.1, b.1, self.1); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..16 { ++ self.0[i] += a.0[i] * b.0[i]; ++ } ++ } + } + } + +@@ -829,6 +1136,18 @@ + #[cfg(target_arch = "loongarch64")] + unsafe { + Self(lasx_xvfadd_s(self.0, rhs.0), lasx_xvfadd_s(self.1, rhs.1)) ++ } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f32; 16]; ++ for i in 0..16 { ++ result[i] = self.0[i] + rhs.0[i]; ++ } ++ Self(result) + } + } + } +@@ -853,6 +1172,16 @@ + self.0 = lasx_xvfadd_s(self.0, rhs.0); + self.1 = lasx_xvfadd_s(self.1, rhs.1); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..16 { ++ self.0[i] += rhs.0[i]; ++ } ++ } + } + } + +@@ -877,6 +1206,18 @@ + #[cfg(target_arch = "loongarch64")] + unsafe { + Self(lasx_xvfmul_s(self.0, rhs.0), lasx_xvfmul_s(self.1, rhs.1)) ++ } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f32; 16]; ++ for i in 0..16 { ++ result[i] = self.0[i] * rhs.0[i]; ++ } ++ Self(result) + } + } + } +@@ -903,6 +1244,18 @@ + unsafe { + Self(lasx_xvfsub_s(self.0, rhs.0), lasx_xvfsub_s(self.1, rhs.1)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f32; 16]; ++ for i in 0..16 { ++ result[i] = self.0[i] - rhs.0[i]; ++ } ++ Self(result) ++ } + } + } + +@@ -926,6 +1279,16 @@ + self.0 = lasx_xvfsub_s(self.0, rhs.0); + self.1 = lasx_xvfsub_s(self.1, rhs.1); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..16 { ++ self.0[i] -= rhs.0[i]; ++ } ++ } + } + } + +--- lance-linalg-orig/src/simd/f64.rs 2006-07-24 03:21:28 ++++ lance-linalg-9.0.0-riscv64/src/simd/f64.rs 2026-09-07 02:18:45 +@@ -33,6 +33,17 @@ + #[derive(Clone, Copy)] + pub struct f64x4(v4f64); + ++/// Portable scalar fallback for architectures with no dedicated SIMD tier ++/// above (riscv64 included) -- CLAUDE.md gotcha 300. ++#[allow(non_camel_case_types)] ++#[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++)))] ++#[derive(Clone, Copy)] ++pub struct f64x4([f64; 4]); ++ + impl std::fmt::Debug for f64x4 { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let mut arr = [0.0_f64; 4]; +@@ -69,6 +80,14 @@ + unsafe { + Self(transmute(lasx_xvreplgr2vr_d(transmute(val)))) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self([val; 4]) ++ } + } + + fn zeros() -> Self { +@@ -84,6 +103,14 @@ + { + Self::splat(0.0) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self([0.0; 4]) ++ } + } + + #[inline] +@@ -100,6 +127,14 @@ + { + Self(transmute(lasx_xvld::<0>(transmute(ptr)))) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self::load_unaligned(ptr) ++ } + } + + #[inline] +@@ -116,6 +151,18 @@ + { + Self(transmute(lasx_xvld::<0>(transmute(ptr)))) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f64; 4]; ++ for (i, r) in result.iter_mut().enumerate() { ++ *r = unsafe { *ptr.add(i) }; ++ } ++ Self(result) ++ } + } + + unsafe fn store(&self, ptr: *mut f64) { +@@ -131,6 +178,14 @@ + unsafe { + lasx_xvst::<0>(transmute(self.0), transmute(ptr)); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ unsafe { ++ self.store_unaligned(ptr); ++ } + } + + unsafe fn store_unaligned(&self, ptr: *mut f64) { +@@ -146,6 +201,16 @@ + unsafe { + lasx_xvst::<0>(transmute(self.0), transmute(ptr)); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ unsafe { ++ for (i, v) in self.0.iter().enumerate() { ++ *ptr.add(i) = *v; ++ } ++ } + } + + #[inline] +@@ -169,6 +234,14 @@ + { + self.as_array().iter().sum() + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ self.0.iter().sum() ++ } + } + + fn reduce_min(&self) -> f64 { +@@ -194,6 +267,14 @@ + .copied() + .fold(f64::INFINITY, f64::min) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ self.0.iter().copied().fold(f64::INFINITY, f64::min) ++ } + } + + fn min(&self, rhs: &Self) -> Self { +@@ -212,6 +293,18 @@ + unsafe { + Self(lasx_xvfmin_d(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f64; 4]; ++ for i in 0..4 { ++ result[i] = self.0[i].min(rhs.0[i]); ++ } ++ Self(result) ++ } + } + + fn find(&self, val: f64) -> Option { +@@ -241,6 +334,16 @@ + unsafe { + self.0 = lasx_xvfmadd_d(a.0, b.0, self.0); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..4 { ++ self.0[i] += a.0[i] * b.0[i]; ++ } ++ } + } + } + +@@ -264,6 +367,18 @@ + unsafe { + Self(lasx_xvfadd_d(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f64; 4]; ++ for i in 0..4 { ++ result[i] = self.0[i] + rhs.0[i]; ++ } ++ Self(result) ++ } + } + } + +@@ -283,6 +398,16 @@ + unsafe { + self.0 = lasx_xvfadd_d(self.0, rhs.0); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..4 { ++ self.0[i] += rhs.0[i]; ++ } ++ } + } + } + +@@ -306,6 +431,18 @@ + unsafe { + Self(lasx_xvfsub_d(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f64; 4]; ++ for i in 0..4 { ++ result[i] = self.0[i] - rhs.0[i]; ++ } ++ Self(result) ++ } + } + } + +@@ -325,6 +462,16 @@ + unsafe { + self.0 = lasx_xvfsub_d(self.0, rhs.0); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..4 { ++ self.0[i] -= rhs.0[i]; ++ } ++ } + } + } + +@@ -348,6 +495,18 @@ + unsafe { + Self(lasx_xvfmul_d(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f64; 4]; ++ for i in 0..4 { ++ result[i] = self.0[i] * rhs.0[i]; ++ } ++ Self(result) ++ } + } + } + +@@ -377,6 +536,16 @@ + #[derive(Clone, Copy)] + pub struct f64x8(v4f64, v4f64); + ++/// Portable scalar fallback -- CLAUDE.md gotcha 300. ++#[allow(non_camel_case_types)] ++#[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++)))] ++#[derive(Clone, Copy)] ++pub struct f64x8([f64; 8]); ++ + impl std::fmt::Debug for f64x8 { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let mut arr = [0.0_f64; 8]; +@@ -416,6 +585,14 @@ + let v = transmute(lasx_xvreplgr2vr_d(transmute(val))); + Self(v, v) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self([val; 8]) ++ } + } + + #[inline] +@@ -432,6 +609,14 @@ + { + Self::splat(0.0) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self([0.0; 8]) ++ } + } + + #[inline] +@@ -451,6 +636,14 @@ + transmute(lasx_xvld::<32>(transmute(ptr))), + ) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self::load_unaligned(ptr) ++ } + } + + #[inline] +@@ -470,6 +663,18 @@ + transmute(lasx_xvld::<32>(transmute(ptr))), + ) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f64; 8]; ++ for (i, r) in result.iter_mut().enumerate() { ++ *r = unsafe { *ptr.add(i) }; ++ } ++ Self(result) ++ } + } + + #[inline] +@@ -489,6 +694,14 @@ + lasx_xvst::<0>(transmute(self.0), transmute(ptr)); + lasx_xvst::<32>(transmute(self.1), transmute(ptr)); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ unsafe { ++ self.store_unaligned(ptr); ++ } + } + + #[inline] +@@ -508,6 +721,16 @@ + lasx_xvst::<0>(transmute(self.0), transmute(ptr)); + lasx_xvst::<32>(transmute(self.1), transmute(ptr)); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ unsafe { ++ for (i, v) in self.0.iter().enumerate() { ++ *ptr.add(i) = *v; ++ } ++ } + } + + #[inline] +@@ -531,6 +754,14 @@ + { + self.as_array().iter().sum() + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ self.0.iter().sum() ++ } + } + + #[inline] +@@ -557,6 +788,14 @@ + .iter() + .copied() + .fold(f64::INFINITY, f64::min) ++ } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ self.0.iter().copied().fold(f64::INFINITY, f64::min) + } + } + +@@ -577,6 +816,18 @@ + unsafe { + Self(lasx_xvfmin_d(self.0, rhs.0), lasx_xvfmin_d(self.1, rhs.1)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f64; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i].min(rhs.0[i]); ++ } ++ Self(result) ++ } + } + + #[inline] +@@ -612,6 +863,16 @@ + self.0 = lasx_xvfmadd_d(a.0, b.0, self.0); + self.1 = lasx_xvfmadd_d(a.1, b.1, self.1); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..8 { ++ self.0[i] += a.0[i] * b.0[i]; ++ } ++ } + } + } + +@@ -635,6 +896,18 @@ + unsafe { + Self(lasx_xvfadd_d(self.0, rhs.0), lasx_xvfadd_d(self.1, rhs.1)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f64; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i] + rhs.0[i]; ++ } ++ Self(result) ++ } + } + } + +@@ -657,6 +930,16 @@ + unsafe { + self.0 = lasx_xvfadd_d(self.0, rhs.0); + self.1 = lasx_xvfadd_d(self.1, rhs.1); ++ } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..8 { ++ self.0[i] += rhs.0[i]; ++ } + } + } + } +@@ -681,6 +964,18 @@ + unsafe { + Self(lasx_xvfmul_d(self.0, rhs.0), lasx_xvfmul_d(self.1, rhs.1)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f64; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i] * rhs.0[i]; ++ } ++ Self(result) ++ } + } + } + +@@ -704,6 +999,18 @@ + unsafe { + Self(lasx_xvfsub_d(self.0, rhs.0), lasx_xvfsub_d(self.1, rhs.1)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f64; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i] - rhs.0[i]; ++ } ++ Self(result) ++ } + } + } + +@@ -727,6 +1034,16 @@ + self.0 = lasx_xvfsub_d(self.0, rhs.0); + self.1 = lasx_xvfsub_d(self.1, rhs.1); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..8 { ++ self.0[i] -= rhs.0[i]; ++ } ++ } + } + } + +--- lance-linalg-orig/src/simd/i32.rs 2006-07-24 03:21:28 ++++ lance-linalg-9.0.0-riscv64/src/simd/i32.rs 2026-09-07 02:19:36 +@@ -30,6 +30,17 @@ + #[derive(Clone, Copy)] + pub struct i32x8(v8i32); + ++/// Portable scalar fallback for architectures with no dedicated SIMD tier ++/// above (riscv64 included) -- CLAUDE.md gotcha 300. ++#[allow(non_camel_case_types)] ++#[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++)))] ++#[derive(Clone, Copy)] ++pub struct i32x8(pub(crate) [i32; 8]); ++ + impl std::fmt::Debug for i32x8 { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let mut arr = [0; 8]; +@@ -67,6 +78,14 @@ + unsafe { + Self(lasx_xvreplgr2vr_w(val)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self([val; 8]) ++ } + } + + #[inline] +@@ -83,6 +102,14 @@ + { + Self::splat(0) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self([0; 8]) ++ } + } + + #[inline] +@@ -99,6 +126,14 @@ + { + Self(transmute(lasx_xvld::<0>(transmute(ptr)))) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self::load_unaligned(ptr) ++ } + } + + #[inline] +@@ -115,6 +150,18 @@ + { + Self(transmute(lasx_xvld::<0>(transmute(ptr)))) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0i32; 8]; ++ for (i, r) in result.iter_mut().enumerate() { ++ *r = unsafe { *ptr.add(i) }; ++ } ++ Self(result) ++ } + } + + #[inline] +@@ -135,6 +182,16 @@ + unsafe { + lasx_xvst::<0>(transmute(self.0), transmute(ptr)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ unsafe { ++ for (i, v) in self.0.iter().enumerate() { ++ *ptr.add(i) = *v; ++ } ++ } + } + + fn reduce_sum(&self) -> i32 { +@@ -151,6 +208,14 @@ + { + self.as_array().iter().sum() + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ self.0.iter().sum() ++ } + } + + fn reduce_min(&self) -> i32 { +@@ -173,6 +238,18 @@ + unsafe { + Self(lasx_xvmin_w(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0i32; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i].min(rhs.0[i]); ++ } ++ Self(result) ++ } + } + + fn find(&self, val: i32) -> Option { +@@ -206,6 +283,18 @@ + } + } + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..8 { ++ if self.0[i] == val { ++ return Some(i as i32); ++ } ++ } ++ } + None + } + } +@@ -230,6 +319,18 @@ + unsafe { + Self(lasx_xvadd_w(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0i32; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i].wrapping_add(rhs.0[i]); ++ } ++ Self(result) ++ } + } + } + +@@ -249,6 +350,16 @@ + unsafe { + self.0 = lasx_xvadd_w(self.0, rhs.0); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..8 { ++ self.0[i] = self.0[i].wrapping_add(rhs.0[i]); ++ } ++ } + } + } + +@@ -272,6 +383,18 @@ + unsafe { + Self(lasx_xvsub_w(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0i32; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i].wrapping_sub(rhs.0[i]); ++ } ++ Self(result) ++ } + } + } + +@@ -291,6 +414,16 @@ + unsafe { + self.0 = lasx_xvsub_w(self.0, rhs.0); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..8 { ++ self.0[i] = self.0[i].wrapping_sub(rhs.0[i]); ++ } ++ } + } + } + +@@ -314,6 +447,18 @@ + unsafe { + Self(lasx_xvmul_w(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0i32; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i].wrapping_mul(rhs.0[i]); ++ } ++ Self(result) ++ } + } + } + From bad1c21050de61458f1fd44572874306b5e24f80 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Fri, 23 Oct 2026 12:22:27 +0800 Subject: [PATCH 09/10] lance-context: carry the lance-linalg riscv64 SIMD fallback to 0.6.7 --- ...4-lance-linalg-riscv64-simd-fallback.patch | 1400 +++++++++++++++++ 1 file changed, 1400 insertions(+) create mode 100644 patches/lance-context/0.6.7/0004-lance-linalg-riscv64-simd-fallback.patch diff --git a/patches/lance-context/0.6.7/0004-lance-linalg-riscv64-simd-fallback.patch b/patches/lance-context/0.6.7/0004-lance-linalg-riscv64-simd-fallback.patch new file mode 100644 index 000000000000..03a3ed39625f --- /dev/null +++ b/patches/lance-context/0.6.7/0004-lance-linalg-riscv64-simd-fallback.patch @@ -0,0 +1,1400 @@ +Upstream-Status: To upstream [lance-linalg's per-arch SIMD structs (f32x8/f32x16/f64x4/f64x8/i32x8) have no fallback for architectures without a dedicated tier (riscv64 included); not filed upstream per this session's policy against opening external issues/PRs] + +--- lance-linalg-orig/src/simd/f32.rs 2006-07-24 03:21:28 ++++ lance-linalg-9.0.0-riscv64/src/simd/f32.rs 2026-09-07 02:16:55 +@@ -35,6 +35,17 @@ + #[derive(Clone, Copy)] + pub struct f32x8(v8f32); + ++/// 8 of 32-bit `f32` values. Portable scalar fallback for architectures with ++/// no dedicated SIMD tier above (riscv64 included) -- CLAUDE.md gotcha 300. ++#[allow(non_camel_case_types)] ++#[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++)))] ++#[derive(Clone, Copy)] ++pub struct f32x8([f32; 8]); ++ + impl std::fmt::Debug for f32x8 { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let mut arr = [0.0_f32; 8]; +@@ -119,6 +130,27 @@ + ]; + Self::load_unaligned(values.as_ptr()) + } ++ ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ unsafe { ++ let ptr = slice.as_ptr(); ++ ++ let values = [ ++ *ptr.add(indices[0] as usize), ++ *ptr.add(indices[1] as usize), ++ *ptr.add(indices[2] as usize), ++ *ptr.add(indices[3] as usize), ++ *ptr.add(indices[4] as usize), ++ *ptr.add(indices[5] as usize), ++ *ptr.add(indices[6] as usize), ++ *ptr.add(indices[7] as usize), ++ ]; ++ Self::load_unaligned(values.as_ptr()) ++ } + } + } + +@@ -172,6 +204,14 @@ + unsafe { + Self(transmute(lasx_xvreplgr2vr_w(transmute(val)))) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self([val; 8]) ++ } + } + + fn zeros() -> Self { +@@ -186,6 +226,14 @@ + #[cfg(target_arch = "loongarch64")] + { + Self::splat(0.0) ++ } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self([0.0; 8]) + } + } + +@@ -203,6 +251,14 @@ + { + Self(transmute(lasx_xvld::<0>(transmute(ptr)))) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self::load_unaligned(ptr) ++ } + } + + #[inline] +@@ -219,6 +275,18 @@ + { + Self(transmute(lasx_xvld::<0>(transmute(ptr)))) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f32; 8]; ++ for (i, r) in result.iter_mut().enumerate() { ++ *r = unsafe { *ptr.add(i) }; ++ } ++ Self(result) ++ } + } + + unsafe fn store(&self, ptr: *mut f32) { +@@ -234,6 +302,14 @@ + unsafe { + lasx_xvst::<0>(transmute(self.0), transmute(ptr)); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ unsafe { ++ self.store_unaligned(ptr); ++ } + } + + unsafe fn store_unaligned(&self, ptr: *mut f32) { +@@ -249,6 +325,16 @@ + unsafe { + lasx_xvst::<0>(transmute(self.0), transmute(ptr)); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ unsafe { ++ for (i, v) in self.0.iter().enumerate() { ++ *ptr.add(i) = *v; ++ } ++ } + } + + #[inline] +@@ -277,6 +363,14 @@ + { + self.as_array().iter().sum() + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ self.0.iter().sum() ++ } + } + + fn reduce_min(&self) -> f32 { +@@ -311,6 +405,14 @@ + let m2 = lasx_xvfmin_s(transmute(m1), transmute(m2)); + transmute(lasx_xvpickve2gr_w::<0>(transmute(m2))) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ self.0.iter().copied().fold(f32::INFINITY, f32::min) ++ } + } + + fn min(&self, rhs: &Self) -> Self { +@@ -329,6 +431,18 @@ + unsafe { + Self(lasx_xvfmin_s(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f32; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i].min(rhs.0[i]); ++ } ++ Self(result) ++ } + } + + fn find(&self, val: f32) -> Option { +@@ -362,6 +476,18 @@ + } + } + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..8 { ++ if self.0[i] == val { ++ return Some(i as i32); ++ } ++ } ++ } + None + } + } +@@ -380,6 +506,16 @@ + #[cfg(target_arch = "loongarch64")] + unsafe { + self.0 = lasx_xvfmadd_s(a.0, b.0, self.0); ++ } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..8 { ++ self.0[i] += a.0[i] * b.0[i]; ++ } + } + } + } +@@ -404,6 +540,18 @@ + unsafe { + Self(lasx_xvfadd_s(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f32; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i] + rhs.0[i]; ++ } ++ Self(result) ++ } + } + } + +@@ -423,6 +571,16 @@ + unsafe { + self.0 = lasx_xvfadd_s(self.0, rhs.0); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..8 { ++ self.0[i] += rhs.0[i]; ++ } ++ } + } + } + +@@ -446,6 +604,18 @@ + unsafe { + Self(lasx_xvfsub_s(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f32; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i] - rhs.0[i]; ++ } ++ Self(result) ++ } + } + } + +@@ -465,6 +635,16 @@ + unsafe { + self.0 = lasx_xvfsub_s(self.0, rhs.0); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..8 { ++ self.0[i] -= rhs.0[i]; ++ } ++ } + } + } + +@@ -488,6 +668,18 @@ + unsafe { + Self(lasx_xvfmul_s(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f32; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i] * rhs.0[i]; ++ } ++ Self(result) ++ } + } + } + +@@ -516,6 +708,16 @@ + #[derive(Clone, Copy)] + pub struct f32x16(v8f32, v8f32); + ++/// 16 of 32-bit `f32` values. Portable scalar fallback -- CLAUDE.md gotcha 300. ++#[allow(non_camel_case_types)] ++#[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++)))] ++#[derive(Clone, Copy)] ++pub struct f32x16([f32; 16]); ++ + impl std::fmt::Debug for f32x16 { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let mut arr = [0.0_f32; 16]; +@@ -561,6 +763,14 @@ + transmute(lasx_xvreplgr2vr_w(transmute(val))), + ) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self([val; 16]) ++ } + } + + #[inline] +@@ -577,6 +787,14 @@ + { + Self::splat(0.0) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self([0.0; 16]) ++ } + } + + #[inline] +@@ -596,6 +814,14 @@ + transmute(lasx_xvld::<32>(transmute(ptr))), + ) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self::load_unaligned(ptr) ++ } + } + + #[inline] +@@ -614,6 +840,18 @@ + transmute(lasx_xvld::<0>(transmute(ptr))), + transmute(lasx_xvld::<32>(transmute(ptr))), + ) ++ } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f32; 16]; ++ for (i, r) in result.iter_mut().enumerate() { ++ *r = unsafe { *ptr.add(i) }; ++ } ++ Self(result) + } + } + +@@ -633,6 +871,14 @@ + lasx_xvst::<0>(transmute(self.0), transmute(ptr)); + lasx_xvst::<32>(transmute(self.1), transmute(ptr)); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ unsafe { ++ self.store_unaligned(ptr); ++ } + } + + #[inline] +@@ -651,6 +897,16 @@ + lasx_xvst::<0>(transmute(self.0), transmute(ptr)); + lasx_xvst::<32>(transmute(self.1), transmute(ptr)); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ unsafe { ++ for (i, v) in self.0.iter().enumerate() { ++ *ptr.add(i) = *v; ++ } ++ } + } + + #[inline] +@@ -681,6 +937,14 @@ + { + self.as_array().iter().sum() + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ self.0.iter().sum() ++ } + } + + #[inline] +@@ -715,6 +979,14 @@ + let m1 = lasx_xvfmin_s(transmute(m1), transmute(m2)); + transmute(lasx_xvpickve2gr_w::<0>(transmute(m1))) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ self.0.iter().copied().fold(f32::INFINITY, f32::min) ++ } + } + + #[inline] +@@ -736,6 +1008,18 @@ + unsafe { + Self(lasx_xvfmin_s(self.0, rhs.0), lasx_xvfmin_s(self.1, rhs.1)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f32; 16]; ++ for i in 0..16 { ++ result[i] = self.0[i].min(rhs.0[i]); ++ } ++ Self(result) ++ } + } + + #[inline] +@@ -782,6 +1066,19 @@ + } + None + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..16 { ++ if self.0[i] == val { ++ return Some(i as i32); ++ } ++ } ++ None ++ } + } + } + +@@ -805,6 +1102,16 @@ + self.0 = lasx_xvfmadd_s(a.0, b.0, self.0); + self.1 = lasx_xvfmadd_s(a.1, b.1, self.1); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..16 { ++ self.0[i] += a.0[i] * b.0[i]; ++ } ++ } + } + } + +@@ -829,6 +1136,18 @@ + #[cfg(target_arch = "loongarch64")] + unsafe { + Self(lasx_xvfadd_s(self.0, rhs.0), lasx_xvfadd_s(self.1, rhs.1)) ++ } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f32; 16]; ++ for i in 0..16 { ++ result[i] = self.0[i] + rhs.0[i]; ++ } ++ Self(result) + } + } + } +@@ -853,6 +1172,16 @@ + self.0 = lasx_xvfadd_s(self.0, rhs.0); + self.1 = lasx_xvfadd_s(self.1, rhs.1); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..16 { ++ self.0[i] += rhs.0[i]; ++ } ++ } + } + } + +@@ -877,6 +1206,18 @@ + #[cfg(target_arch = "loongarch64")] + unsafe { + Self(lasx_xvfmul_s(self.0, rhs.0), lasx_xvfmul_s(self.1, rhs.1)) ++ } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f32; 16]; ++ for i in 0..16 { ++ result[i] = self.0[i] * rhs.0[i]; ++ } ++ Self(result) + } + } + } +@@ -903,6 +1244,18 @@ + unsafe { + Self(lasx_xvfsub_s(self.0, rhs.0), lasx_xvfsub_s(self.1, rhs.1)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f32; 16]; ++ for i in 0..16 { ++ result[i] = self.0[i] - rhs.0[i]; ++ } ++ Self(result) ++ } + } + } + +@@ -926,6 +1279,16 @@ + self.0 = lasx_xvfsub_s(self.0, rhs.0); + self.1 = lasx_xvfsub_s(self.1, rhs.1); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..16 { ++ self.0[i] -= rhs.0[i]; ++ } ++ } + } + } + +--- lance-linalg-orig/src/simd/f64.rs 2006-07-24 03:21:28 ++++ lance-linalg-9.0.0-riscv64/src/simd/f64.rs 2026-09-07 02:18:45 +@@ -33,6 +33,17 @@ + #[derive(Clone, Copy)] + pub struct f64x4(v4f64); + ++/// Portable scalar fallback for architectures with no dedicated SIMD tier ++/// above (riscv64 included) -- CLAUDE.md gotcha 300. ++#[allow(non_camel_case_types)] ++#[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++)))] ++#[derive(Clone, Copy)] ++pub struct f64x4([f64; 4]); ++ + impl std::fmt::Debug for f64x4 { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let mut arr = [0.0_f64; 4]; +@@ -69,6 +80,14 @@ + unsafe { + Self(transmute(lasx_xvreplgr2vr_d(transmute(val)))) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self([val; 4]) ++ } + } + + fn zeros() -> Self { +@@ -84,6 +103,14 @@ + { + Self::splat(0.0) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self([0.0; 4]) ++ } + } + + #[inline] +@@ -100,6 +127,14 @@ + { + Self(transmute(lasx_xvld::<0>(transmute(ptr)))) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self::load_unaligned(ptr) ++ } + } + + #[inline] +@@ -116,6 +151,18 @@ + { + Self(transmute(lasx_xvld::<0>(transmute(ptr)))) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f64; 4]; ++ for (i, r) in result.iter_mut().enumerate() { ++ *r = unsafe { *ptr.add(i) }; ++ } ++ Self(result) ++ } + } + + unsafe fn store(&self, ptr: *mut f64) { +@@ -131,6 +178,14 @@ + unsafe { + lasx_xvst::<0>(transmute(self.0), transmute(ptr)); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ unsafe { ++ self.store_unaligned(ptr); ++ } + } + + unsafe fn store_unaligned(&self, ptr: *mut f64) { +@@ -146,6 +201,16 @@ + unsafe { + lasx_xvst::<0>(transmute(self.0), transmute(ptr)); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ unsafe { ++ for (i, v) in self.0.iter().enumerate() { ++ *ptr.add(i) = *v; ++ } ++ } + } + + #[inline] +@@ -169,6 +234,14 @@ + { + self.as_array().iter().sum() + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ self.0.iter().sum() ++ } + } + + fn reduce_min(&self) -> f64 { +@@ -194,6 +267,14 @@ + .copied() + .fold(f64::INFINITY, f64::min) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ self.0.iter().copied().fold(f64::INFINITY, f64::min) ++ } + } + + fn min(&self, rhs: &Self) -> Self { +@@ -212,6 +293,18 @@ + unsafe { + Self(lasx_xvfmin_d(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f64; 4]; ++ for i in 0..4 { ++ result[i] = self.0[i].min(rhs.0[i]); ++ } ++ Self(result) ++ } + } + + fn find(&self, val: f64) -> Option { +@@ -241,6 +334,16 @@ + unsafe { + self.0 = lasx_xvfmadd_d(a.0, b.0, self.0); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..4 { ++ self.0[i] += a.0[i] * b.0[i]; ++ } ++ } + } + } + +@@ -264,6 +367,18 @@ + unsafe { + Self(lasx_xvfadd_d(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f64; 4]; ++ for i in 0..4 { ++ result[i] = self.0[i] + rhs.0[i]; ++ } ++ Self(result) ++ } + } + } + +@@ -283,6 +398,16 @@ + unsafe { + self.0 = lasx_xvfadd_d(self.0, rhs.0); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..4 { ++ self.0[i] += rhs.0[i]; ++ } ++ } + } + } + +@@ -306,6 +431,18 @@ + unsafe { + Self(lasx_xvfsub_d(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f64; 4]; ++ for i in 0..4 { ++ result[i] = self.0[i] - rhs.0[i]; ++ } ++ Self(result) ++ } + } + } + +@@ -325,6 +462,16 @@ + unsafe { + self.0 = lasx_xvfsub_d(self.0, rhs.0); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..4 { ++ self.0[i] -= rhs.0[i]; ++ } ++ } + } + } + +@@ -348,6 +495,18 @@ + unsafe { + Self(lasx_xvfmul_d(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f64; 4]; ++ for i in 0..4 { ++ result[i] = self.0[i] * rhs.0[i]; ++ } ++ Self(result) ++ } + } + } + +@@ -377,6 +536,16 @@ + #[derive(Clone, Copy)] + pub struct f64x8(v4f64, v4f64); + ++/// Portable scalar fallback -- CLAUDE.md gotcha 300. ++#[allow(non_camel_case_types)] ++#[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++)))] ++#[derive(Clone, Copy)] ++pub struct f64x8([f64; 8]); ++ + impl std::fmt::Debug for f64x8 { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let mut arr = [0.0_f64; 8]; +@@ -416,6 +585,14 @@ + let v = transmute(lasx_xvreplgr2vr_d(transmute(val))); + Self(v, v) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self([val; 8]) ++ } + } + + #[inline] +@@ -432,6 +609,14 @@ + { + Self::splat(0.0) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self([0.0; 8]) ++ } + } + + #[inline] +@@ -451,6 +636,14 @@ + transmute(lasx_xvld::<32>(transmute(ptr))), + ) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self::load_unaligned(ptr) ++ } + } + + #[inline] +@@ -470,6 +663,18 @@ + transmute(lasx_xvld::<32>(transmute(ptr))), + ) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f64; 8]; ++ for (i, r) in result.iter_mut().enumerate() { ++ *r = unsafe { *ptr.add(i) }; ++ } ++ Self(result) ++ } + } + + #[inline] +@@ -489,6 +694,14 @@ + lasx_xvst::<0>(transmute(self.0), transmute(ptr)); + lasx_xvst::<32>(transmute(self.1), transmute(ptr)); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ unsafe { ++ self.store_unaligned(ptr); ++ } + } + + #[inline] +@@ -508,6 +721,16 @@ + lasx_xvst::<0>(transmute(self.0), transmute(ptr)); + lasx_xvst::<32>(transmute(self.1), transmute(ptr)); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ unsafe { ++ for (i, v) in self.0.iter().enumerate() { ++ *ptr.add(i) = *v; ++ } ++ } + } + + #[inline] +@@ -531,6 +754,14 @@ + { + self.as_array().iter().sum() + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ self.0.iter().sum() ++ } + } + + #[inline] +@@ -557,6 +788,14 @@ + .iter() + .copied() + .fold(f64::INFINITY, f64::min) ++ } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ self.0.iter().copied().fold(f64::INFINITY, f64::min) + } + } + +@@ -577,6 +816,18 @@ + unsafe { + Self(lasx_xvfmin_d(self.0, rhs.0), lasx_xvfmin_d(self.1, rhs.1)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f64; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i].min(rhs.0[i]); ++ } ++ Self(result) ++ } + } + + #[inline] +@@ -612,6 +863,16 @@ + self.0 = lasx_xvfmadd_d(a.0, b.0, self.0); + self.1 = lasx_xvfmadd_d(a.1, b.1, self.1); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..8 { ++ self.0[i] += a.0[i] * b.0[i]; ++ } ++ } + } + } + +@@ -635,6 +896,18 @@ + unsafe { + Self(lasx_xvfadd_d(self.0, rhs.0), lasx_xvfadd_d(self.1, rhs.1)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f64; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i] + rhs.0[i]; ++ } ++ Self(result) ++ } + } + } + +@@ -657,6 +930,16 @@ + unsafe { + self.0 = lasx_xvfadd_d(self.0, rhs.0); + self.1 = lasx_xvfadd_d(self.1, rhs.1); ++ } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..8 { ++ self.0[i] += rhs.0[i]; ++ } + } + } + } +@@ -681,6 +964,18 @@ + unsafe { + Self(lasx_xvfmul_d(self.0, rhs.0), lasx_xvfmul_d(self.1, rhs.1)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f64; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i] * rhs.0[i]; ++ } ++ Self(result) ++ } + } + } + +@@ -704,6 +999,18 @@ + unsafe { + Self(lasx_xvfsub_d(self.0, rhs.0), lasx_xvfsub_d(self.1, rhs.1)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0.0f64; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i] - rhs.0[i]; ++ } ++ Self(result) ++ } + } + } + +@@ -727,6 +1034,16 @@ + self.0 = lasx_xvfsub_d(self.0, rhs.0); + self.1 = lasx_xvfsub_d(self.1, rhs.1); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..8 { ++ self.0[i] -= rhs.0[i]; ++ } ++ } + } + } + +--- lance-linalg-orig/src/simd/i32.rs 2006-07-24 03:21:28 ++++ lance-linalg-9.0.0-riscv64/src/simd/i32.rs 2026-09-07 02:19:36 +@@ -30,6 +30,17 @@ + #[derive(Clone, Copy)] + pub struct i32x8(v8i32); + ++/// Portable scalar fallback for architectures with no dedicated SIMD tier ++/// above (riscv64 included) -- CLAUDE.md gotcha 300. ++#[allow(non_camel_case_types)] ++#[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++)))] ++#[derive(Clone, Copy)] ++pub struct i32x8(pub(crate) [i32; 8]); ++ + impl std::fmt::Debug for i32x8 { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let mut arr = [0; 8]; +@@ -67,6 +78,14 @@ + unsafe { + Self(lasx_xvreplgr2vr_w(val)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self([val; 8]) ++ } + } + + #[inline] +@@ -83,6 +102,14 @@ + { + Self::splat(0) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self([0; 8]) ++ } + } + + #[inline] +@@ -99,6 +126,14 @@ + { + Self(transmute(lasx_xvld::<0>(transmute(ptr)))) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ Self::load_unaligned(ptr) ++ } + } + + #[inline] +@@ -115,6 +150,18 @@ + { + Self(transmute(lasx_xvld::<0>(transmute(ptr)))) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0i32; 8]; ++ for (i, r) in result.iter_mut().enumerate() { ++ *r = unsafe { *ptr.add(i) }; ++ } ++ Self(result) ++ } + } + + #[inline] +@@ -135,6 +182,16 @@ + unsafe { + lasx_xvst::<0>(transmute(self.0), transmute(ptr)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ unsafe { ++ for (i, v) in self.0.iter().enumerate() { ++ *ptr.add(i) = *v; ++ } ++ } + } + + fn reduce_sum(&self) -> i32 { +@@ -151,6 +208,14 @@ + { + self.as_array().iter().sum() + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ self.0.iter().sum() ++ } + } + + fn reduce_min(&self) -> i32 { +@@ -173,6 +238,18 @@ + unsafe { + Self(lasx_xvmin_w(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0i32; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i].min(rhs.0[i]); ++ } ++ Self(result) ++ } + } + + fn find(&self, val: i32) -> Option { +@@ -206,6 +283,18 @@ + } + } + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..8 { ++ if self.0[i] == val { ++ return Some(i as i32); ++ } ++ } ++ } + None + } + } +@@ -230,6 +319,18 @@ + unsafe { + Self(lasx_xvadd_w(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0i32; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i].wrapping_add(rhs.0[i]); ++ } ++ Self(result) ++ } + } + } + +@@ -249,6 +350,16 @@ + unsafe { + self.0 = lasx_xvadd_w(self.0, rhs.0); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..8 { ++ self.0[i] = self.0[i].wrapping_add(rhs.0[i]); ++ } ++ } + } + } + +@@ -272,6 +383,18 @@ + unsafe { + Self(lasx_xvsub_w(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0i32; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i].wrapping_sub(rhs.0[i]); ++ } ++ Self(result) ++ } + } + } + +@@ -291,6 +414,16 @@ + unsafe { + self.0 = lasx_xvsub_w(self.0, rhs.0); + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ for i in 0..8 { ++ self.0[i] = self.0[i].wrapping_sub(rhs.0[i]); ++ } ++ } + } + } + +@@ -314,6 +447,18 @@ + unsafe { + Self(lasx_xvmul_w(self.0, rhs.0)) + } ++ #[cfg(not(any( ++ target_arch = "x86_64", ++ target_arch = "aarch64", ++ target_arch = "loongarch64" ++ )))] ++ { ++ let mut result = [0i32; 8]; ++ for i in 0..8 { ++ result[i] = self.0[i].wrapping_mul(rhs.0[i]); ++ } ++ Self(result) ++ } + } + } + From e30810067c344ccc3c08c4edb762be2b22078abf Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Fri, 23 Oct 2026 12:23:02 +0800 Subject: [PATCH 10/10] lance-context: vendor riscv64-fixed lance 9.0.0 crates next to the 7.0.0 ones --- .github/workflows/build-lance-context.yml | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-lance-context.yml b/.github/workflows/build-lance-context.yml index 525c7df9c62f..60b774e52197 100644 --- a/.github/workflows/build-lance-context.yml +++ b/.github/workflows/build-lance-context.yml @@ -95,8 +95,8 @@ jobs: # i32x8/f64x4/f64x8 SIMD types compile only for x86_64/aarch64/ # loongarch64 upstream (CLAUDE.md gotcha 300); both are pulled in from # crates.io at a pinned `lance = "7.0.0"` (crates/lance-context-core/ - # Cargo.toml), so riscv64-fixed copies are vendored here and wired in - # via `[patch.crates-io]`. + # Cargo.toml; "9.0.0" from 0.6.6, see below), so riscv64-fixed copies are + # vendored here and wired in via `[patch.crates-io]`. - name: Vendor riscv64-fixed lance-core and lance-linalg run: | curl -fsSL -A "python-wheels (https://github.com/riseproject-dev/python-wheels)" -o lance-core.tar.gz "https://crates.io/api/v1/crates/lance-core/7.0.0/download" @@ -111,6 +111,21 @@ jobs: rm lance-linalg.tar.gz patch -p1 -d lance-linalg-7.0.0-riscv64 < python-wheels/patches/lance-context/${{ env.LANCE_CONTEXT_VERSION }}/0004-lance-linalg-riscv64-simd-fallback.patch + # From 0.6.6 on, crates/lance-context-core depends on `lance = "9.0.0"` + # while lancedb 0.30.0 still pulls in the 7.0.0 line, so Cargo.lock holds + # both and each needs its own riscv64-fixed copy. + patches="$PWD/python-wheels/patches/lance-context/${LANCE_CONTEXT_VERSION}" + if grep -q 'lance-core-9.0.0-riscv64' "$patches/0003-cargo-patch-lance-crates-for-riscv64.patch"; then + for crate in lance-core lance-linalg; do + curl -fsSL -A "python-wheels (https://github.com/riseproject-dev/python-wheels)" -o "$crate.tar.gz" "https://crates.io/api/v1/crates/$crate/9.0.0/download" + mkdir "$crate-9.0.0-riscv64" + tar xzf "$crate.tar.gz" -C "$crate-9.0.0-riscv64" --strip-components=1 + rm "$crate.tar.gz" + done + patch -p1 -d lance-core-9.0.0-riscv64 < "$patches/0002-lance-core-riscv64-simd-fallback.patch" + patch -p1 -d lance-linalg-9.0.0-riscv64 < "$patches/0004-lance-linalg-riscv64-simd-fallback.patch" + fi + git apply python-wheels/patches/lance-context/${{ env.LANCE_CONTEXT_VERSION }}/0003-cargo-patch-lance-crates-for-riscv64.patch - name: Free disk space