diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f81f669..e55979e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -40,6 +40,9 @@ jobs:
- name: Run tests
run: cargo test
+ - name: Run facade README doctests
+ run: cargo test -p strided-rs --doc
+
coverage:
name: coverage
runs-on: ubuntu-latest
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index b028f08..3cbbde3 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -34,7 +34,10 @@ jobs:
strided-rs docs
strided-rs
+ strided-rs
+ strided-traits
strided-view
+ strided-perm
strided-kernel
strided-einsum2
strided-opteinsum
diff --git a/Cargo.toml b/Cargo.toml
index 5df3331..cbcd5ad 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,3 +1,49 @@
[workspace]
-members = ["strided-traits", "strided-view", "strided-perm", "strided-kernel", "strided-einsum2", "strided-opteinsum", "mdarray-opteinsum", "ndarray-opteinsum"]
+members = [
+ "strided-rs",
+ "strided-traits",
+ "strided-view",
+ "strided-perm",
+ "strided-kernel",
+ "strided-einsum2",
+ "strided-opteinsum",
+ "mdarray-opteinsum",
+ "ndarray-opteinsum",
+]
resolver = "2"
+
+[workspace.package]
+version = "0.1.0"
+edition = "2021"
+license = "MIT OR Apache-2.0"
+authors = ["Satoshi Terasaki", "Hiroshi Shinaoka"]
+repository = "https://github.com/tensor4all/strided-rs"
+
+[workspace.dependencies]
+strided-rs = { version = "0.1.0", path = "strided-rs" }
+strided-traits = { version = "0.1.0", path = "strided-traits" }
+strided-view = { version = "0.1.0", path = "strided-view" }
+strided-perm = { version = "0.1.0", path = "strided-perm" }
+strided-kernel = { version = "0.1.0", path = "strided-kernel" }
+strided-einsum2 = { version = "0.1.0", path = "strided-einsum2", default-features = false }
+strided-opteinsum = { version = "0.1.0", path = "strided-opteinsum", default-features = false }
+mdarray-opteinsum = { version = "0.1.0", path = "mdarray-opteinsum", default-features = false }
+ndarray-opteinsum = { version = "0.1.0", path = "ndarray-opteinsum", default-features = false }
+
+approx = "0.5"
+cblas-inject = "0.1"
+cblas-sys = "0.2"
+criterion = "0.5"
+faer = "0.24"
+faer-traits = "0.24"
+mdarray = "0.8.0"
+ndarray = "0.17"
+num-complex = "0.4"
+num-traits = "0.2"
+omeco = "0.2"
+pulp = "0.22"
+rand = "0.8"
+rand_distr = "0.4"
+rayon = "1.10"
+smallvec = "1"
+thiserror = "1.0"
diff --git a/README.md b/README.md
index d6af150..5a07ad1 100644
--- a/README.md
+++ b/README.md
@@ -5,9 +5,17 @@ It is inspired by Julia's [Strided.jl](https://github.com/Jutho/Strided.jl),
[StridedViews.jl](https://github.com/Jutho/StridedViews.jl), and
[OMEinsum.jl](https://github.com/under-Peter/OMEinsum.jl).
+The recommended user-facing crate is [`strided-rs`](strided-rs/README.md).
+Use individual crates such as `strided-perm`, `strided-view`, or
+`strided-kernel` directly when you need a smaller dependency surface or a
+lower-level API.
+
## Workspace Layout
+- [`strided-rs`](strided-rs/README.md): facade crate that re-exports the main workspace APIs
+- [`strided-traits`](strided-traits/): shared scalar and element-operation traits
- [`strided-view`](strided-view/README.md): core dynamic-rank strided view/array types and metadata ops
+- [`strided-perm`](strided-perm/README.md): cache-efficient tensor permutation / transpose
- [`strided-kernel`](strided-kernel/README.md): cache-optimized elementwise/reduction kernels over strided views
- [`strided-einsum2`](strided-einsum2/README.md): binary einsum (`einsum2_into`) on strided tensors
- [`strided-opteinsum`](strided-opteinsum/README.md): N-ary einsum frontend with nested notation and contraction-order optimization
@@ -25,15 +33,20 @@ It is inspired by Julia's [Strided.jl](https://github.com/Jutho/Strided.jl),
## Installation
-These crates are currently **not published to crates.io** (`publish = false`).
-Use workspace path dependencies:
+These crates are being prepared for crates.io publication, but this repository
+does not publish them automatically. Until a release is published, use workspace
+path dependencies:
```toml
[dependencies]
-strided-view = { path = "../strided-rs/strided-view" }
-strided-kernel = { path = "../strided-rs/strided-kernel" }
-strided-einsum2 = { path = "../strided-rs/strided-einsum2" }
-strided-opteinsum = { path = "../strided-rs/strided-opteinsum" }
+strided-rs = { path = "../strided-rs/strided-rs" }
+```
+
+After publication, use:
+
+```toml
+[dependencies]
+strided-rs = "0.1"
```
## Documentation
@@ -54,22 +67,13 @@ CI also builds rustdoc on PRs and deploys workspace docs to GitHub Pages on `mai
## Quick Start
-```rust
-use strided_kernel::{StridedArray, map_into};
-
-// Create a row-major 2D array
-let src = StridedArray::::from_fn_row_major(&[2, 3], |idx| {
- (idx[0] * 10 + idx[1]) as f64
-});
-let mut dest = StridedArray::::row_major(&[2, 3]);
-
-// Element-wise map: dest[i] = src[i] * 2
-map_into(&mut dest.view_mut(), &src.view(), |x| x * 2.0).unwrap();
-assert_eq!(dest.get(&[1, 2]), 24.0); // (1*10 + 2) * 2
-```
+See the [`strided-rs` Quick Start](strided-rs/README.md#quick-start). The Rust
+example there is included in crate docs and verified by doctests in CI.
See each sub-crate README for detailed API examples and benchmarks:
+- [`strided-rs`](strided-rs/README.md) — recommended facade crate and executable Quick Start
- [`strided-view`](strided-view/README.md) — types, view operations
+- [`strided-perm`](strided-perm/README.md) — permutation and transpose kernels
- [`strided-kernel`](strided-kernel/README.md) — map/reduce/broadcast kernels, [benchmarks](strided-kernel/README.md#benchmarks)
- [`strided-einsum2`](strided-einsum2/README.md) — binary einsum with GEMM backend
- [`strided-opteinsum`](strided-opteinsum/README.md) — N-ary einsum, [benchmarks](strided-opteinsum/README.md#benchmarks)
diff --git a/docs/plans/2026-05-12-strided-rs-publish-prep.md b/docs/plans/2026-05-12-strided-rs-publish-prep.md
new file mode 100644
index 0000000..81d570f
--- /dev/null
+++ b/docs/plans/2026-05-12-strided-rs-publish-prep.md
@@ -0,0 +1,62 @@
+# strided-rs Publish Preparation Implementation Plan
+
+> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
+
+**Goal:** Add a user-facing `strided-rs` facade crate and prepare the workspace metadata, dependencies, README examples, and CI checks for a future crates.io release without publishing anything.
+
+**Architecture:** The workspace will continue to publish individual low-level crates, while `strided-rs` becomes the recommended entry point that re-exports the core APIs. README examples will live in `strided-rs/README.md` and be included in crate docs so `cargo test -p strided-rs --doc` verifies them.
+
+**Tech Stack:** Rust workspace, Cargo workspace metadata/dependencies, rustdoc doctests, GitHub Actions.
+
+---
+
+### Task 1: Add the Facade Crate
+
+**Files:**
+- Create: `strided-rs/Cargo.toml`
+- Create: `strided-rs/src/lib.rs`
+- Create: `strided-rs/README.md`
+- Modify: `Cargo.toml`
+
+**Steps:**
+1. Add `strided-rs` to `workspace.members`.
+2. Create a package named `strided-rs` with library crate `strided_rs`.
+3. Re-export core APIs from `strided-view`, `strided-kernel`, `strided-perm`, `strided-einsum2`, and `strided-opteinsum`.
+4. Add optional `mdarray` and `ndarray` features that re-export `mdarray-opteinsum` and `ndarray-opteinsum`.
+5. Include `README.md` as crate docs with `#![doc = include_str!("../README.md")]`.
+
+### Task 2: Centralize Cargo Metadata and Dependencies
+
+**Files:**
+- Modify: `Cargo.toml`
+- Modify: all workspace member `Cargo.toml` files
+
+**Steps:**
+1. Add `[workspace.package]` for version, authors, license, repository, and edition.
+2. Add `[workspace.dependencies]` for shared external dependencies and internal crates with `version + path`.
+3. Convert package metadata and dependency declarations to `workspace = true` where practical.
+4. Keep explicit `rust-version` where current crates already need different MSRV values.
+5. Do not run `cargo publish`.
+
+### Task 3: Make README Examples Executable
+
+**Files:**
+- Modify: `README.md`
+- Create/Modify: `strided-rs/README.md`
+- Modify: `.github/workflows/ci.yml`
+
+**Steps:**
+1. Move the user-facing Quick Start to `strided-rs/README.md`.
+2. Keep root README as workspace guidance and link to the facade crate README.
+3. Ensure Rust examples in `strided-rs/README.md` are complete doctests.
+4. Add an explicit CI step for `cargo test -p strided-rs --doc`.
+
+### Task 4: Verify
+
+**Commands:**
+- `cargo fmt --check`
+- `cargo test --workspace`
+- `cargo test -p strided-rs --doc`
+- `cargo publish --workspace --dry-run` only as a dry-run, never without `--dry-run`
+
+**Expected Result:** Formatting and tests pass. Publish dry-run either passes or reports only issues that require actual registry state or final release decisions.
diff --git a/mdarray-opteinsum/Cargo.toml b/mdarray-opteinsum/Cargo.toml
index 5e94fd6..89f7315 100644
--- a/mdarray-opteinsum/Cargo.toml
+++ b/mdarray-opteinsum/Cargo.toml
@@ -1,22 +1,21 @@
[package]
name = "mdarray-opteinsum"
-version = "0.1.0"
+version.workspace = true
edition = "2024"
rust-version = "1.89"
-license = "MIT OR Apache-2.0"
-authors = ["Satoshi Terasaki", "Hiroshi Shinaoka"]
-repository = "https://github.com/tensor4all/strided-rs"
+license.workspace = true
+authors.workspace = true
+repository.workspace = true
description = "N-ary einsum frontend for mdarray arrays, powered by strided-opteinsum."
-publish = false
[dependencies]
-mdarray = "0.8.0"
-strided-opteinsum = { path = "../strided-opteinsum", default-features = false }
-strided-view = { path = "../strided-view" }
-strided-kernel = { path = "../strided-kernel" }
-num-complex = "0.4"
-num-traits = "0.2"
-thiserror = "1.0"
+mdarray.workspace = true
+strided-opteinsum = { workspace = true, default-features = false }
+strided-view.workspace = true
+strided-kernel.workspace = true
+num-complex.workspace = true
+num-traits.workspace = true
+thiserror.workspace = true
[features]
default = ["faer"]
@@ -24,5 +23,5 @@ faer = ["strided-opteinsum/faer"]
blas = ["strided-opteinsum/blas"]
[dev-dependencies]
-approx = "0.5"
-num-complex = "0.4"
+approx.workspace = true
+num-complex.workspace = true
diff --git a/ndarray-opteinsum/Cargo.toml b/ndarray-opteinsum/Cargo.toml
index fd08cf2..c31a1d7 100644
--- a/ndarray-opteinsum/Cargo.toml
+++ b/ndarray-opteinsum/Cargo.toml
@@ -1,22 +1,21 @@
[package]
name = "ndarray-opteinsum"
-version = "0.1.0"
-edition = "2021"
+version.workspace = true
+edition.workspace = true
rust-version = "1.64"
-license = "MIT OR Apache-2.0"
-authors = ["Satoshi Terasaki", "Hiroshi Shinaoka"]
-repository = "https://github.com/tensor4all/strided-rs"
+license.workspace = true
+authors.workspace = true
+repository.workspace = true
description = "N-ary einsum frontend for ndarray arrays, powered by strided-opteinsum."
-publish = false
[dependencies]
-ndarray = "0.17"
-strided-opteinsum = { path = "../strided-opteinsum", default-features = false }
-strided-view = { path = "../strided-view" }
-strided-kernel = { path = "../strided-kernel" }
-num-complex = "0.4"
-num-traits = "0.2"
-thiserror = "1.0"
+ndarray.workspace = true
+strided-opteinsum = { workspace = true, default-features = false }
+strided-view.workspace = true
+strided-kernel.workspace = true
+num-complex.workspace = true
+num-traits.workspace = true
+thiserror.workspace = true
[features]
default = ["faer"]
@@ -24,5 +23,5 @@ faer = ["strided-opteinsum/faer"]
blas = ["strided-opteinsum/blas"]
[dev-dependencies]
-approx = "0.5"
-num-complex = "0.4"
+approx.workspace = true
+num-complex.workspace = true
diff --git a/strided-einsum2/Cargo.toml b/strided-einsum2/Cargo.toml
index 8968bb6..b32befc 100644
--- a/strided-einsum2/Cargo.toml
+++ b/strided-einsum2/Cargo.toml
@@ -1,37 +1,36 @@
[package]
name = "strided-einsum2"
-version = "0.1.0"
-edition = "2021"
-license = "MIT OR Apache-2.0"
-authors = ["Satoshi Terasaki", "Hiroshi Shinaoka"]
-repository = "https://github.com/tensor4all/strided-rs"
+version.workspace = true
+edition.workspace = true
+license.workspace = true
+authors.workspace = true
+repository.workspace = true
description = "Binary einsum (pairwise tensor contraction) on strided views."
-publish = false
[dependencies]
-strided-traits = { path = "../strided-traits" }
-strided-view = { path = "../strided-view" }
-strided-kernel = { path = "../strided-kernel" }
-strided-perm = { path = "../strided-perm" }
-num-traits = "0.2"
-thiserror = "1.0"
-faer = { version = "0.24", optional = true }
-faer-traits = { version = "0.24", optional = true }
-cblas-sys = { version = "0.2", optional = true }
-cblas-inject = { version = "0.1", optional = true }
-num-complex = { version = "0.4", optional = true }
-rayon = { version = "1.10", optional = true }
+strided-traits.workspace = true
+strided-view.workspace = true
+strided-kernel.workspace = true
+strided-perm.workspace = true
+num-traits.workspace = true
+thiserror.workspace = true
+faer = { workspace = true, optional = true }
+faer-traits = { workspace = true, optional = true }
+cblas-sys = { workspace = true, optional = true }
+cblas-inject = { workspace = true, optional = true }
+num-complex = { workspace = true, optional = true }
+rayon = { workspace = true, optional = true }
[features]
default = ["faer", "faer-traits"]
-parallel = ["rayon", "strided-kernel/parallel", "strided-perm/parallel"]
+parallel = ["dep:rayon", "strided-kernel/parallel", "strided-perm/parallel"]
blas = ["dep:cblas-sys", "dep:num-complex"]
blas-inject = ["dep:cblas-inject", "dep:num-complex"]
[dev-dependencies]
-approx = "0.5"
-num-complex = "0.4"
-rand = "0.8"
+approx.workspace = true
+num-complex.workspace = true
+rand.workspace = true
[lib]
bench = false
diff --git a/strided-einsum2/src/backend.rs b/strided-einsum2/src/backend.rs
index 5d0a6a0..0c35e90 100644
--- a/strided-einsum2/src/backend.rs
+++ b/strided-einsum2/src/backend.rs
@@ -1,7 +1,7 @@
//! Backend abstraction for batched GEMM dispatch.
//!
//! This module defines the [`Backend`] trait, marker structs for each backend,
-//! and the [`ActiveBackend`] type alias that serves as the single point of
+//! and the `ActiveBackend` type alias that serves as the single point of
//! backend selection based on Cargo features.
/// Trait for backends that can execute batched GEMM on contiguous operands.
@@ -95,10 +95,10 @@ impl Backend for NaiveBackend {
/// The active GEMM backend, selected by Cargo features.
///
-/// - `faer` (without blas/blas-inject) -> [`FaerBackend`]
-/// - `blas` or `blas-inject` (without faer) -> [`BlasBackend`]
-/// - no backend feature -> [`NaiveBackend`]
-/// - invalid combos -> [`NaiveBackend`] (placeholder; `compile_error!` fires first)
+/// - `faer` (without blas/blas-inject) -> `FaerBackend`
+/// - `blas` or `blas-inject` (without faer) -> `BlasBackend`
+/// - no backend feature -> `NaiveBackend`
+/// - invalid combos -> `NaiveBackend` (placeholder; `compile_error!` fires first)
#[cfg(all(feature = "faer", not(any(feature = "blas", feature = "blas-inject"))))]
pub type ActiveBackend = FaerBackend;
diff --git a/strided-kernel/Cargo.toml b/strided-kernel/Cargo.toml
index 37ce38c..caa449a 100644
--- a/strided-kernel/Cargo.toml
+++ b/strided-kernel/Cargo.toml
@@ -1,33 +1,32 @@
[package]
name = "strided-kernel"
-version = "0.1.0"
-edition = "2021"
-license = "MIT OR Apache-2.0"
-authors = ["Satoshi Terasaki", "Hiroshi Shinaoka"]
-repository = "https://github.com/tensor4all/strided-rs"
+version.workspace = true
+edition.workspace = true
+license.workspace = true
+authors.workspace = true
+repository.workspace = true
description = "Cache-optimized kernels for strided multidimensional array operations in Rust (ported from Julia Strided.jl/StridedViews.jl)."
-publish = false
[dependencies]
-strided-view = { path = "../strided-view" }
-strided-perm = { path = "../strided-perm" }
-num-traits = "0.2"
-num-complex = "0.4"
-rayon = { version = "1.10", optional = true }
-smallvec = { version = "1", optional = true }
-pulp = { version = "0.22", optional = true }
+strided-view.workspace = true
+strided-perm.workspace = true
+num-traits.workspace = true
+num-complex.workspace = true
+rayon = { workspace = true, optional = true }
+smallvec = { workspace = true, optional = true }
+pulp = { workspace = true, optional = true }
[features]
default = ["simd"]
-parallel = ["rayon", "smallvec", "strided-perm/parallel"]
+parallel = ["dep:rayon", "dep:smallvec", "strided-perm/parallel"]
simd = ["dep:pulp"]
[dev-dependencies]
-criterion = "0.5"
-approx = "0.5"
-rand = "0.8"
-rand_distr = "0.4"
-num-complex = "0.4"
+criterion.workspace = true
+approx.workspace = true
+rand.workspace = true
+rand_distr.workspace = true
+num-complex.workspace = true
[lib]
bench = false
diff --git a/strided-opteinsum/Cargo.toml b/strided-opteinsum/Cargo.toml
index aa2ad99..2e20e15 100644
--- a/strided-opteinsum/Cargo.toml
+++ b/strided-opteinsum/Cargo.toml
@@ -1,16 +1,21 @@
[package]
name = "strided-opteinsum"
-version = "0.1.0"
-edition = "2021"
+version.workspace = true
+edition.workspace = true
+license.workspace = true
+authors.workspace = true
+repository.workspace = true
+description = "N-ary einsum frontend with contraction-order optimization for strided tensors."
+readme = "README.md"
[dependencies]
-strided-view = { path = "../strided-view" }
-strided-kernel = { path = "../strided-kernel" }
-strided-einsum2 = { path = "../strided-einsum2", default-features = false }
-omeco = "0.2"
-num-complex = "0.4"
-num-traits = "0.2"
-thiserror = "1.0"
+strided-view.workspace = true
+strided-kernel.workspace = true
+strided-einsum2 = { workspace = true, default-features = false }
+omeco.workspace = true
+num-complex.workspace = true
+num-traits.workspace = true
+thiserror.workspace = true
[features]
default = ["faer"]
@@ -20,10 +25,10 @@ blas = ["strided-einsum2/blas"]
blas-inject = ["strided-einsum2/blas-inject"]
[dev-dependencies]
-approx = "0.5"
-num-complex = "0.4"
-rand = "0.8"
-strided-view = { path = "../strided-view" }
+approx.workspace = true
+num-complex.workspace = true
+rand.workspace = true
+strided-view.workspace = true
[lib]
bench = false
diff --git a/strided-perm/Cargo.toml b/strided-perm/Cargo.toml
index 79cdcdd..13a8021 100644
--- a/strided-perm/Cargo.toml
+++ b/strided-perm/Cargo.toml
@@ -1,25 +1,24 @@
[package]
name = "strided-perm"
-version = "0.1.0"
-edition = "2021"
-license = "MIT OR Apache-2.0"
-authors = ["Satoshi Terasaki", "Hiroshi Shinaoka"]
-repository = "https://github.com/tensor4all/strided-rs"
+version.workspace = true
+edition.workspace = true
+license.workspace = true
+authors.workspace = true
+repository.workspace = true
description = "Cache-efficient tensor permutation / transpose (HPTT-inspired)."
-publish = false
[dependencies]
-strided-view = { path = "../strided-view" }
-rayon = { version = "1.10", optional = true }
+strided-view.workspace = true
+rayon = { workspace = true, optional = true }
[features]
-parallel = ["rayon"]
+parallel = ["dep:rayon"]
[dev-dependencies]
-criterion = "0.5"
-rand = "0.8"
-rand_distr = "0.4"
-rayon = "1.10"
+criterion.workspace = true
+rand.workspace = true
+rand_distr.workspace = true
+rayon.workspace = true
[lib]
bench = false
diff --git a/strided-rs/Cargo.toml b/strided-rs/Cargo.toml
new file mode 100644
index 0000000..3046c35
--- /dev/null
+++ b/strided-rs/Cargo.toml
@@ -0,0 +1,53 @@
+[package]
+name = "strided-rs"
+version.workspace = true
+edition.workspace = true
+license.workspace = true
+authors.workspace = true
+repository.workspace = true
+description = "User-facing facade crate for the strided-rs workspace."
+readme = "README.md"
+
+[dependencies]
+strided-traits.workspace = true
+strided-view.workspace = true
+strided-perm.workspace = true
+strided-kernel.workspace = true
+strided-einsum2 = { workspace = true, default-features = false, optional = true }
+strided-opteinsum = { workspace = true, default-features = false, optional = true }
+mdarray-opteinsum = { workspace = true, default-features = false, optional = true }
+ndarray-opteinsum = { workspace = true, default-features = false, optional = true }
+
+[features]
+default = ["faer"]
+faer = [
+ "dep:strided-einsum2",
+ "dep:strided-opteinsum",
+ "strided-einsum2/faer",
+ "strided-einsum2/faer-traits",
+ "strided-opteinsum/faer",
+ "mdarray-opteinsum?/faer",
+ "ndarray-opteinsum?/faer",
+]
+parallel = [
+ "strided-perm/parallel",
+ "strided-kernel/parallel",
+ "strided-einsum2?/parallel",
+ "strided-opteinsum?/parallel",
+]
+blas = [
+ "dep:strided-einsum2",
+ "dep:strided-opteinsum",
+ "strided-einsum2/blas",
+ "strided-opteinsum/blas",
+ "mdarray-opteinsum?/blas",
+ "ndarray-opteinsum?/blas",
+]
+blas-inject = [
+ "dep:strided-einsum2",
+ "dep:strided-opteinsum",
+ "strided-einsum2/blas-inject",
+ "strided-opteinsum/blas-inject",
+]
+mdarray = ["dep:mdarray-opteinsum"]
+ndarray = ["dep:ndarray-opteinsum"]
diff --git a/strided-rs/README.md b/strided-rs/README.md
new file mode 100644
index 0000000..65df1ff
--- /dev/null
+++ b/strided-rs/README.md
@@ -0,0 +1,63 @@
+# strided-rs
+
+`strided-rs` is the recommended entry point for the strided-rs workspace. It
+re-exports the core strided view, kernel, permutation, and einsum crates so most
+users can depend on one package.
+
+## Installation
+
+```toml
+[dependencies]
+strided-rs = "0.1"
+```
+
+Use individual crates such as `strided-perm`, `strided-view`, or
+`strided-kernel` directly when you want a smaller dependency surface or a
+lower-level API.
+
+## Quick Start
+
+```rust
+use strided_rs::{map_into, StridedArray};
+
+let src = StridedArray::::from_fn_row_major(&[2, 3], |idx| {
+ (idx[0] * 10 + idx[1]) as f64
+});
+let mut dest = StridedArray::::row_major(&[2, 3]);
+
+map_into(&mut dest.view_mut(), &src.view(), |x| x * 2.0).unwrap();
+
+assert_eq!(dest.get(&[1, 2]), 24.0);
+```
+
+## Feature Flags
+
+- `faer` (default): enables the `faer` backend for einsum contractions.
+- `parallel`: enables Rayon-backed parallel kernels where available.
+- `blas`: enables the CBLAS backend for einsum contractions.
+- `blas-inject`: enables BLAS through `cblas-inject`.
+- `mdarray`: re-exports the `mdarray-opteinsum` frontend as `strided_rs::mdarray`.
+- `ndarray`: re-exports the `ndarray-opteinsum` frontend as `strided_rs::ndarray`.
+
+`faer`, `blas`, and `blas-inject` are mutually exclusive at the einsum backend
+level. Disable default features when selecting a BLAS backend. If default
+features are disabled, enable one backend feature when using einsum APIs or the
+`mdarray` / `ndarray` frontends:
+
+```toml
+[dependencies]
+strided-rs = { version = "0.1", default-features = false, features = ["blas"] }
+```
+
+## Namespaced APIs
+
+The facade exposes lower-level crates under modules:
+
+- `strided_rs::traits`
+- `strided_rs::view`
+- `strided_rs::perm`
+- `strided_rs::kernel`
+- `strided_rs::einsum2`
+- `strided_rs::opteinsum`
+
+The individual crates remain public and can be used directly.
diff --git a/strided-rs/src/lib.rs b/strided-rs/src/lib.rs
new file mode 100644
index 0000000..2b9aa6a
--- /dev/null
+++ b/strided-rs/src/lib.rs
@@ -0,0 +1,63 @@
+#![doc = include_str!("../README.md")]
+
+/// Shared scalar and element-operation traits.
+pub mod traits {
+ pub use strided_traits::*;
+}
+
+/// Strided view and owned strided array types.
+pub mod view {
+ pub use strided_view::*;
+}
+
+/// Cache-efficient tensor permutation and transpose routines.
+pub mod perm {
+ pub use strided_perm::*;
+}
+
+/// Cache-optimized map, reduce, and elementwise kernels.
+pub mod kernel {
+ pub use strided_kernel::*;
+}
+
+/// Binary einsum contractions on strided views.
+#[cfg(any(feature = "faer", feature = "blas", feature = "blas-inject"))]
+pub mod einsum2 {
+ pub use strided_einsum2::*;
+}
+
+/// N-ary optimized einsum frontend.
+#[cfg(any(feature = "faer", feature = "blas", feature = "blas-inject"))]
+pub mod opteinsum {
+ pub use strided_opteinsum::*;
+}
+
+/// `mdarray` einsum frontend.
+#[cfg(feature = "mdarray")]
+pub mod mdarray {
+ pub use mdarray_opteinsum::*;
+}
+
+/// `ndarray` einsum frontend.
+#[cfg(feature = "ndarray")]
+pub mod ndarray {
+ pub use ndarray_opteinsum::*;
+}
+
+pub use strided_kernel::{
+ add, axpy, copy_conj, copy_into, copy_into_col_major, copy_scale, copy_transpose_scale_into,
+ dot, fma, map_into, mul, reduce, reduce_axis, sum, symmetrize_conj_into, symmetrize_into,
+ zip_map2_into, zip_map3_into, zip_map4_into, MaybeSimdOps,
+};
+#[cfg(any(feature = "faer", feature = "blas", feature = "blas-inject"))]
+pub use strided_opteinsum::{
+ einsum, einsum_into, einsum_into_with_pool, einsum_with_pool, BufferPool, EinsumCode,
+ EinsumError, EinsumNode, EinsumOperand, EinsumScalar, StridedData, TypedTensor,
+};
+pub use strided_traits::{
+ Adjoint, ComposableElementOp, Compose, Conj, ElementOp, ElementOpApply, Identity, ScalarBase,
+ Transpose,
+};
+pub use strided_view::{
+ col_major_strides, row_major_strides, StridedArray, StridedError, StridedView, StridedViewMut,
+};
diff --git a/strided-traits/Cargo.toml b/strided-traits/Cargo.toml
index 8cb30b5..129eaa1 100644
--- a/strided-traits/Cargo.toml
+++ b/strided-traits/Cargo.toml
@@ -1,13 +1,12 @@
[package]
name = "strided-traits"
-version = "0.1.0"
-edition = "2021"
-license = "MIT OR Apache-2.0"
-authors = ["Satoshi Terasaki", "Hiroshi Shinaoka"]
-repository = "https://github.com/tensor4all/strided-rs"
+version.workspace = true
+edition.workspace = true
+license.workspace = true
+authors.workspace = true
+repository.workspace = true
description = "Shared traits for strided-rs: element operations, scalar bounds, and type-level composition."
-publish = false
[dependencies]
-num-traits = "0.2"
-num-complex = "0.4"
+num-traits.workspace = true
+num-complex.workspace = true
diff --git a/strided-traits/README.md b/strided-traits/README.md
new file mode 100644
index 0000000..37899ba
--- /dev/null
+++ b/strided-traits/README.md
@@ -0,0 +1,10 @@
+# strided-traits
+
+Shared traits for the strided-rs ecosystem.
+
+This crate contains scalar bounds and lazy element-operation traits used by
+`strided-view`, `strided-kernel`, `strided-einsum2`, and downstream extension
+crates. Most users should depend on the `strided-rs` facade crate instead.
+
+Depend on `strided-traits` directly when implementing custom scalar types or
+element operations for the lower-level crates.
diff --git a/strided-view/Cargo.toml b/strided-view/Cargo.toml
index bc389d0..bdcbc74 100644
--- a/strided-view/Cargo.toml
+++ b/strided-view/Cargo.toml
@@ -1,15 +1,14 @@
[package]
name = "strided-view"
-version = "0.1.0"
-edition = "2021"
-license = "MIT OR Apache-2.0"
-authors = ["Satoshi Terasaki", "Hiroshi Shinaoka"]
-repository = "https://github.com/tensor4all/strided-rs"
+version.workspace = true
+edition.workspace = true
+license.workspace = true
+authors.workspace = true
+repository.workspace = true
description = "Device-agnostic strided view types and metadata operations (ported from Julia StridedViews.jl)."
-publish = false
[dependencies]
-strided-traits = { path = "../strided-traits" }
-num-traits = "0.2"
-num-complex = "0.4"
-thiserror = "1.0"
+strided-traits.workspace = true
+num-traits.workspace = true
+num-complex.workspace = true
+thiserror.workspace = true