diff --git a/Cargo.toml b/Cargo.toml index bee7dcad1..5207ba4c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,10 +4,7 @@ name = "ndarray" version = "0.17.2" edition = "2021" rust-version = "1.64" -authors = [ - "Ulrik Sverdrup \"bluss\"", - "Jim Turner" -] +authors = ["Ulrik Sverdrup \"bluss\"", "Jim Turner"] license = "MIT OR Apache-2.0" readme = "README-crates.io.md" @@ -20,12 +17,12 @@ keywords = ["array", "data-structure", "multidimensional", "matrix", "blas"] categories = ["data-structures", "science"] include = [ - "/src/**/*.rs", - "LICENSE-MIT", - "LICENSE-APACHE", - "RELEASES.md", - "README.rst", - "README-quick-start.md" + "/src/**/*.rs", + "LICENSE-MIT", + "LICENSE-APACHE", + "RELEASES.md", + "README.rst", + "README-quick-start.md", ] resolver = "2" @@ -46,9 +43,13 @@ rayon = { version = "1.10.0", optional = true } cblas-sys = { workspace = true, optional = true } libc = { version = "0.2.82", optional = true } -matrixmultiply = { version = "0.3.2", default-features = false, features=["cgemm"] } +matrixmultiply = { version = "0.3.2", default-features = false, features = [ + "cgemm", +] } -serde = { version = "1.0", optional = true, default-features = false, features = ["alloc"] } +serde = { version = "1.0", optional = true, default-features = false, features = [ + "alloc", +] } rawpointer = { version = "0.2" } [dev-dependencies] @@ -77,20 +78,17 @@ portable-atomic-critical-section = ["portable-atomic/critical-section"] [target.'cfg(not(target_has_atomic = "ptr"))'.dependencies] portable-atomic = { version = "1.6.0" } -portable-atomic-util = { version = "0.2.0", features = [ "alloc" ] } +portable-atomic-util = { version = "0.2.0", features = ["alloc"] } [workspace] -members = [ - "ndarray-rand", - "crates/*", -] +members = ["ndarray-rand", "crates/*"] default-members = [ - ".", - "ndarray-rand", - "crates/ndarray-gen", - "crates/numeric-tests", - "crates/serialization-tests", - # exclude blas-tests and blas-mock-tests that activate "blas" feature + ".", + "ndarray-rand", + "crates/ndarray-gen", + "crates/numeric-tests", + "crates/serialization-tests", + # exclude blas-tests and blas-mock-tests that activate "blas" feature ] [workspace.dependencies] @@ -105,7 +103,9 @@ approx = { version = "0.5", default-features = false } quickcheck = { version = "1.0", default-features = false } rand = { version = "0.9.0", features = ["small_rng"] } rand_distr = { version = "0.5.0" } -itertools = { version = "0.13.0", default-features = false, features = ["use_std"] } +itertools = { version = "0.13.0", default-features = false, features = [ + "use_std", +] } cblas-sys = { version = "0.1.4", default-features = false } [profile.bench] diff --git a/crates/blas-tests/Cargo.toml b/crates/blas-tests/Cargo.toml index 4b0209ac5..4cd3166b8 100644 --- a/crates/blas-tests/Cargo.toml +++ b/crates/blas-tests/Cargo.toml @@ -39,4 +39,3 @@ accelerate = ["blas-src", "blas-src/accelerate"] # Config for cargo-release [package.metadata.release] release = false - diff --git a/crates/ndarray-gen/Cargo.toml b/crates/ndarray-gen/Cargo.toml index 33394ccfc..7df1f0703 100644 --- a/crates/ndarray-gen/Cargo.toml +++ b/crates/ndarray-gen/Cargo.toml @@ -11,4 +11,3 @@ num-traits = { workspace = true } # Config for cargo-release [package.metadata.release] release = false - diff --git a/crates/numeric-tests/Cargo.toml b/crates/numeric-tests/Cargo.toml index 3e4014d25..5636fb1a9 100644 --- a/crates/numeric-tests/Cargo.toml +++ b/crates/numeric-tests/Cargo.toml @@ -18,8 +18,13 @@ approx = { workspace = true } rand = { workspace = true } rand_distr = { workspace = true } -blas-src = { optional = true, version = "0.10", default-features = false, features = ["openblas"] } -openblas-src = { optional = true, version = ">=0.10.11", default-features = false, features = ["cblas", "system"] } +blas-src = { optional = true, version = "0.10", default-features = false, features = [ + "openblas", +] } +openblas-src = { optional = true, version = ">=0.10.11", default-features = false, features = [ + "cblas", + "system", +] } [dev-dependencies] num-traits = { workspace = true } diff --git a/examples/sort-axis.rs b/examples/sort-axis.rs index 4da3a64d5..58bd07872 100644 --- a/examples/sort-axis.rs +++ b/examples/sort-axis.rs @@ -20,14 +20,10 @@ pub struct Permutation impl Permutation { /// Checks if the permutation is correct - pub fn from_indices(v: Vec) -> Result + pub fn from_indices(v: Vec) -> Option { let perm = Permutation { indices: v }; - if perm.correct() { - Ok(perm) - } else { - Err(()) - } + perm.correct().then_some(perm) } fn correct(&self) -> bool diff --git a/ndarray-rand/Cargo.toml b/ndarray-rand/Cargo.toml index b7169f304..ee1c6c165 100644 --- a/ndarray-rand/Cargo.toml +++ b/ndarray-rand/Cargo.toml @@ -14,11 +14,11 @@ description = "Constructors for randomized arrays. `rand` integration for `ndarr keywords = ["multidimensional", "matrix", "rand", "ndarray"] include = [ - "/src/**/*.rs", - "LICENSE-MIT", - "LICENSE-APACHE", - "RELEASES.md", - "README.rst" + "/src/**/*.rs", + "LICENSE-MIT", + "LICENSE-APACHE", + "RELEASES.md", + "README.rst", ] [dependencies] @@ -34,4 +34,3 @@ quickcheck = { workspace = true } [package.metadata.release] tag-name = "ndarray-rand-{{version}}" - diff --git a/rustfmt.toml b/rustfmt.toml index f3e376ccc..c178a2cfa 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -5,7 +5,7 @@ fn_call_width = 100 max_width = 120 brace_style = "AlwaysNextLine" control_brace_style = "AlwaysSameLine" -fn_params_layout = "Compressed" # ? +fn_params_layout = "Compressed" # ? format_macro_bodies = false imports_granularity = "Preserve" imports_indent = "Block" @@ -16,7 +16,7 @@ match_arm_blocks = false match_arm_leading_pipes = "Preserve" merge_derives = false overflow_delimited_expr = true -reorder_modules = false # impacts rustdoc order +reorder_modules = false # impacts rustdoc order short_array_element_width_threshold = 32 skip_macro_invocations = ["*"] unstable_features = true diff --git a/src/doc/crate_feature_flags.rs b/src/doc/crate_feature_flags.rs index fc2c2bd49..9cfe33313 100644 --- a/src/doc/crate_feature_flags.rs +++ b/src/doc/crate_feature_flags.rs @@ -14,9 +14,14 @@ //! ## `serde` //! - Enables serialization support for serde 1.x //! -//! ## `rayon` -//! - Enables parallel iterators, parallelized methods, the [`parallel`] module and [`par_azip!`]. -//! - Implies std +#![cfg_attr( + not(feature = "rayon"), + doc = "//! ## `rayon`\n//! - Enables parallel iterators, parallelized methods, and the `par_azip!` macro.\n//! - Implies std\n" +)] +#![cfg_attr( + feature = "rayon", + doc = "//! ## `rayon`\n//! - Enables parallel iterators, parallelized methods, the [`crate::parallel`] module and [`crate::parallel::par_azip`].\n//! - Implies std\n" +)] //! //! ## `approx` //! - Enables implementations of traits of the [`approx`] crate. @@ -28,8 +33,3 @@ //! //! ## `matrixmultiply-threading` //! - Enable the ``threading`` feature in the matrixmultiply package -//! -//! [`parallel`]: crate::parallel - -#[cfg(doc)] -use crate::parallel::par_azip; diff --git a/src/lib.rs b/src/lib.rs index 41e5ca350..91c2bb477 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -84,11 +84,18 @@ //! ## Crate Feature Flags //! //! The following crate feature flags are available. They are configured in your -//! `Cargo.toml`. See [`doc::crate_feature_flags`] for more information. +//! `Cargo.toml`. See [`crate::doc::crate_feature_flags`] for more information. //! //! - `std`: Rust standard library-using functionality (enabled by default) //! - `serde`: serialization support for serde 1.x -//! - `rayon`: Parallel iterators, parallelized methods, the [`parallel`] module and [`par_azip!`]. +#![cfg_attr( + not(feature = "rayon"), + doc = "//! - `rayon`: Parallel iterators, parallelized methods, and the `par_azip!` macro." +)] +#![cfg_attr( + feature = "rayon", + doc = "//! - `rayon`: Parallel iterators, parallelized methods, the [`parallel`] module and [`par_azip!`]." +)] //! - `approx` Implementations of traits from the [`approx`] crate. //! - `blas`: transparent BLAS support for matrix multiplication, needs configuration. //! - `matrixmultiply-threading`: Use threading from `matrixmultiply`. @@ -129,7 +136,7 @@ extern crate std; #[cfg(feature = "blas")] extern crate cblas_sys; -#[cfg(docsrs)] +#[cfg(any(doc, docsrs))] pub mod doc; use alloc::fmt::Debug; diff --git a/src/linalg/impl_linalg.rs b/src/linalg/impl_linalg.rs index 7dfe98578..81c942bc3 100644 --- a/src/linalg/impl_linalg.rs +++ b/src/linalg/impl_linalg.rs @@ -968,6 +968,63 @@ where is_blas_2d(a._dim(), a._strides(), BlasOrder::F) } +/// Dot product for dynamic-dimensional arrays (`ArrayD`). +/// +/// For one-dimensional arrays, computes the vector dot product, which is the sum +/// of the elementwise products (no conjugation of complex operands). +/// Both arrays must have the same length. +/// +/// For two-dimensional arrays, performs matrix multiplication. The array shapes +/// must be compatible in the following ways: +/// - If `self` is *M* × *N*, then `rhs` must be *N* × *K* for matrix-matrix multiplication +/// - If `self` is *M* × *N* and `rhs` is *N*, returns a vector of length *M* +/// - If `self` is *M* and `rhs` is *M* × *N*, returns a vector of length *N* +/// - If both arrays are one-dimensional of length *N*, returns a scalar +/// +/// **Panics** if: +/// - The arrays have dimensions other than 1 or 2 +/// - The array shapes are incompatible for the operation +/// - For vector dot product: the vectors have different lengths +impl Dot> for ArrayRef +where A: LinalgScalar +{ + type Output = Array; + + fn dot(&self, rhs: &ArrayRef) -> Self::Output + { + match (self.ndim(), rhs.ndim()) { + (1, 1) => { + let a = self.view().into_dimensionality::().unwrap(); + let b = rhs.view().into_dimensionality::().unwrap(); + let result = a.dot(&b); + ArrayD::from_elem(vec![], result) + } + (2, 2) => { + // Matrix-matrix multiplication + let a = self.view().into_dimensionality::().unwrap(); + let b = rhs.view().into_dimensionality::().unwrap(); + let result = a.dot(&b); + result.into_dimensionality::().unwrap() + } + (2, 1) => { + // Matrix-vector multiplication + let a = self.view().into_dimensionality::().unwrap(); + let b = rhs.view().into_dimensionality::().unwrap(); + let result = a.dot(&b); + result.into_dimensionality::().unwrap() + } + (1, 2) => { + // Vector-matrix multiplication + let a = self.view().into_dimensionality::().unwrap(); + let b = rhs.view().into_dimensionality::().unwrap(); + let result = a.dot(&b); + result.into_dimensionality::().unwrap() + } + _ => panic!("Dot product for ArrayD is only supported for 1D and 2D arrays"), + } + } +} + #[cfg(test)] #[cfg(feature = "blas")] mod blas_tests @@ -1083,60 +1140,3 @@ mod blas_tests } } } - -/// Dot product for dynamic-dimensional arrays (`ArrayD`). -/// -/// For one-dimensional arrays, computes the vector dot product, which is the sum -/// of the elementwise products (no conjugation of complex operands). -/// Both arrays must have the same length. -/// -/// For two-dimensional arrays, performs matrix multiplication. The array shapes -/// must be compatible in the following ways: -/// - If `self` is *M* × *N*, then `rhs` must be *N* × *K* for matrix-matrix multiplication -/// - If `self` is *M* × *N* and `rhs` is *N*, returns a vector of length *M* -/// - If `self` is *M* and `rhs` is *M* × *N*, returns a vector of length *N* -/// - If both arrays are one-dimensional of length *N*, returns a scalar -/// -/// **Panics** if: -/// - The arrays have dimensions other than 1 or 2 -/// - The array shapes are incompatible for the operation -/// - For vector dot product: the vectors have different lengths -impl Dot> for ArrayRef -where A: LinalgScalar -{ - type Output = Array; - - fn dot(&self, rhs: &ArrayRef) -> Self::Output - { - match (self.ndim(), rhs.ndim()) { - (1, 1) => { - let a = self.view().into_dimensionality::().unwrap(); - let b = rhs.view().into_dimensionality::().unwrap(); - let result = a.dot(&b); - ArrayD::from_elem(vec![], result) - } - (2, 2) => { - // Matrix-matrix multiplication - let a = self.view().into_dimensionality::().unwrap(); - let b = rhs.view().into_dimensionality::().unwrap(); - let result = a.dot(&b); - result.into_dimensionality::().unwrap() - } - (2, 1) => { - // Matrix-vector multiplication - let a = self.view().into_dimensionality::().unwrap(); - let b = rhs.view().into_dimensionality::().unwrap(); - let result = a.dot(&b); - result.into_dimensionality::().unwrap() - } - (1, 2) => { - // Vector-matrix multiplication - let a = self.view().into_dimensionality::().unwrap(); - let b = rhs.view().into_dimensionality::().unwrap(); - let result = a.dot(&b); - result.into_dimensionality::().unwrap() - } - _ => panic!("Dot product for ArrayD is only supported for 1D and 2D arrays"), - } - } -} diff --git a/src/partial.rs b/src/partial.rs index dbaa0e105..c579c36c6 100644 --- a/src/partial.rs +++ b/src/partial.rs @@ -37,6 +37,7 @@ impl Partial } #[cfg(feature = "rayon")] + #[allow(dead_code)] pub(crate) fn stub() -> Self { Self { @@ -46,6 +47,7 @@ impl Partial } #[cfg(feature = "rayon")] + #[allow(dead_code)] pub(crate) fn is_stub(&self) -> bool { self.ptr.is_null() @@ -60,6 +62,7 @@ impl Partial } #[cfg(feature = "rayon")] + #[allow(dead_code)] /// Merge if they are in order (left to right) and contiguous. /// Skips merge if T does not need drop. pub(crate) fn try_merge(mut left: Self, right: Self) -> Self diff --git a/src/zip/mod.rs b/src/zip/mod.rs index c481e481f..b01ae04ff 100644 --- a/src/zip/mod.rs +++ b/src/zip/mod.rs @@ -424,6 +424,7 @@ where D: Dimension } #[cfg(feature = "rayon")] + #[allow(dead_code)] pub(crate) fn uninitialized_for_current_layout(&self) -> Array, D> { let is_f = self.prefer_f(); diff --git a/tests/array.rs b/tests/array.rs index 512227bb6..391f88b95 100644 --- a/tests/array.rs +++ b/tests/array.rs @@ -4,6 +4,7 @@ )] use approx::assert_relative_eq; +use core::panic; use defmac::defmac; #[allow(deprecated)] use itertools::{zip, Itertools}; @@ -1005,7 +1006,7 @@ fn iter_size_hint() fn zero_axes() { let mut a = arr1::(&[]); - if let Some(_) = a.iter().next() { + if a.iter().next().is_some() { panic!(); } a.map(|_| panic!()); @@ -2080,7 +2081,7 @@ fn test_contiguous() assert!(c.as_slice_memory_order().is_some()); let v = c.slice(s![.., 0..1, ..]); assert!(!v.is_standard_layout()); - assert!(!v.as_slice_memory_order().is_some()); + assert!(v.as_slice_memory_order().is_none()); let v = c.slice(s![1..2, .., ..]); assert!(v.is_standard_layout()); diff --git a/tests/iterators.rs b/tests/iterators.rs index e8933a823..96b0673aa 100644 --- a/tests/iterators.rs +++ b/tests/iterators.rs @@ -195,7 +195,7 @@ fn inner_iter_corner_cases() assert_equal(a0.rows(), vec![aview1(&[0])]); let a2 = ArcArray::::zeros((0, 3)); - assert_equal(a2.rows(), vec![aview1(&[]); 0]); + assert_equal(a2.rows(), Vec::>::new()); let a2 = ArcArray::::zeros((3, 0)); assert_equal(a2.rows(), vec![aview1(&[]); 3]); @@ -359,11 +359,13 @@ fn axis_iter_zip_partially_consumed_discontiguous() } } +use ndarray::ArrayView1; + #[test] fn outer_iter_corner_cases() { let a2 = ArcArray::::zeros((0, 3)); - assert_equal(a2.outer_iter(), vec![aview1(&[]); 0]); + assert_equal(a2.outer_iter(), Vec::>::new()); let a2 = ArcArray::::zeros((3, 0)); assert_equal(a2.outer_iter(), vec![aview1(&[]); 3]); diff --git a/tests/numeric.rs b/tests/numeric.rs index 11a9fce76..b82a3561f 100644 --- a/tests/numeric.rs +++ b/tests/numeric.rs @@ -175,7 +175,7 @@ fn var_too_large_ddof() fn var_nan_ddof() { let a = Array2::::zeros((2, 3)); - let v = a.var(std::f64::NAN); + let v = a.var(f64::NAN); assert!(v.is_nan()); } diff --git a/tests/oper.rs b/tests/oper.rs index 4f68d27d3..a6d7054ba 100644 --- a/tests/oper.rs +++ b/tests/oper.rs @@ -19,20 +19,20 @@ fn test_oper(op: &str, a: &[f32], b: &[f32], c: &[f32]) let aa = CowArray::from(arr1(a)); let bb = CowArray::from(arr1(b)); let cc = CowArray::from(arr1(c)); - test_oper_arr::(op, aa.clone(), bb.clone(), cc.clone()); + test_oper_arr(op, aa.clone(), bb.clone(), cc.clone()); let dim = (2, 2); let aa = aa.to_shape(dim).unwrap(); let bb = bb.to_shape(dim).unwrap(); let cc = cc.to_shape(dim).unwrap(); - test_oper_arr::(op, aa.clone(), bb.clone(), cc.clone()); + test_oper_arr(op, aa.clone(), bb.clone(), cc.clone()); let dim = (1, 2, 1, 2); let aa = aa.to_shape(dim).unwrap(); let bb = bb.to_shape(dim).unwrap(); let cc = cc.to_shape(dim).unwrap(); - test_oper_arr::(op, aa.clone(), bb.clone(), cc.clone()); + test_oper_arr(op, aa.clone(), bb.clone(), cc.clone()); } -fn test_oper_arr(op: &str, mut aa: CowArray, bb: CowArray, cc: CowArray) +fn test_oper_arr(op: &str, mut aa: CowArray, bb: CowArray, cc: CowArray) where D: Dimension { match op {