From dc833d8bab93a060dead7e5004aba1428daa65cd Mon Sep 17 00:00:00 2001 From: Vivian Date: Tue, 27 Jan 2026 17:49:07 +0100 Subject: [PATCH 1/8] Add `linspace_exclusive` function. Add a `linspace_exclusive` function which creates a `Linspace` iterator which is exclusive at its upper bound. This is essentially the same as `linspace(endpoint=False)` in numpy. --- src/lib.rs | 2 +- src/linspace.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 41e5ca350..c26877434 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -201,7 +201,7 @@ mod layout; mod linalg_traits; mod linspace; #[cfg(feature = "std")] -pub use crate::linspace::{linspace, range, Linspace}; +pub use crate::linspace::{linspace, linspace_exclusive, range, Linspace}; mod logspace; #[cfg(feature = "std")] pub use crate::logspace::{logspace, Logspace}; diff --git a/src/linspace.rs b/src/linspace.rs index 411c480db..38fdf9f59 100644 --- a/src/linspace.rs +++ b/src/linspace.rs @@ -90,6 +90,32 @@ where F: Float } } +/// Return an iterator of evenly spaced floats. +/// +/// The `Linspace` has `n` elements from `a` to `b` (exclusive). +/// +/// The iterator element type is `F`, where `F` must implement [`Float`], e.g. +/// [`f32`] or [`f64`]. +/// +/// **Panics** if converting `n` to type `F` fails. +#[inline] +pub fn linspace_exclusive(a: F, b: F, n: usize) -> Linspace +where F: Float +{ + let step = if n > 1 { + let num_steps = F::from(n).expect("Converting number of steps to `A` must not fail."); + (b - a) / num_steps + } else { + F::zero() + }; + Linspace { + start: a, + step, + index: 0, + len: n, + } +} + /// Return an iterator of floats from `a` to `b` (exclusive), /// incrementing by `step`. /// From 7ae478c52ab63ade71ffdcb7fcc0ca21d3e85f88 Mon Sep 17 00:00:00 2001 From: Vivian Date: Thu, 29 Jan 2026 11:44:19 +0100 Subject: [PATCH 2/8] Add range implementations of linspace and logspace --- benches/construct.rs | 4 +-- src/impl_constructors.rs | 54 +++++++++++++++++-------------- src/lib.rs | 2 +- src/linspace.rs | 70 +++++++++++++++++----------------------- src/logspace.rs | 34 +++++++++++++------ 5 files changed, 86 insertions(+), 78 deletions(-) diff --git a/benches/construct.rs b/benches/construct.rs index 71a4fb905..958eaa3b6 100644 --- a/benches/construct.rs +++ b/benches/construct.rs @@ -21,7 +21,7 @@ fn zeros_f64(bench: &mut Bencher) #[bench] fn map_regular(bench: &mut test::Bencher) { - let a = Array::linspace(0., 127., 128) + let a = Array::linspace(0.0..=127.0, 128) .into_shape_with_order((8, 16)) .unwrap(); bench.iter(|| a.map(|&x| 2. * x)); @@ -31,7 +31,7 @@ fn map_regular(bench: &mut test::Bencher) #[bench] fn map_stride(bench: &mut test::Bencher) { - let a = Array::linspace(0., 127., 256) + let a = Array::linspace(0.0..=127.0, 256) .into_shape_with_order((8, 32)) .unwrap(); let av = a.slice(s![.., ..;2]); diff --git a/src/impl_constructors.rs b/src/impl_constructors.rs index ba01e2ca3..f1a9b57ed 100644 --- a/src/impl_constructors.rs +++ b/src/impl_constructors.rs @@ -44,7 +44,8 @@ use rawpointer::PointerExt; /// /// ## Constructor methods for one-dimensional arrays. impl ArrayBase -where S: DataOwned +where + S: DataOwned, { /// Create a one-dimensional array from a vector (no copying needed). /// @@ -55,13 +56,9 @@ where S: DataOwned /// /// let array = Array::from_vec(vec![1., 2., 3., 4.]); /// ``` - pub fn from_vec(v: Vec) -> Self - { + pub fn from_vec(v: Vec) -> Self { if mem::size_of::() == 0 { - assert!( - v.len() <= isize::MAX as usize, - "Length must fit in `isize`.", - ); + assert!(v.len() <= isize::MAX as usize, "Length must fit in `isize`.",); } unsafe { Self::from_shape_vec_unchecked(v.len() as Ix, v) } } @@ -76,8 +73,7 @@ where S: DataOwned /// let array = Array::from_iter(0..10); /// ``` #[allow(clippy::should_implement_trait)] - pub fn from_iter>(iterable: I) -> Self - { + pub fn from_iter>(iterable: I) -> Self { Self::from_vec(iterable.into_iter().collect()) } @@ -99,10 +95,12 @@ where S: DataOwned /// assert!(array == arr1(&[0.0, 0.25, 0.5, 0.75, 1.0])) /// ``` #[cfg(feature = "std")] - pub fn linspace(start: A, end: A, n: usize) -> Self - where A: Float + pub fn linspace(range: R, n: usize) -> Self + where + R: std::ops::RangeBounds, + A: Float, { - Self::from(to_vec(linspace::linspace(start, end, n))) + Self::from(to_vec(linspace::linspace(range, n))) } /// Create a one-dimensional array with elements from `start` to `end` @@ -118,7 +116,8 @@ where S: DataOwned /// ``` #[cfg(feature = "std")] pub fn range(start: A, end: A, step: A) -> Self - where A: Float + where + A: Float, { Self::from(to_vec(linspace::range(start, end, step))) } @@ -145,10 +144,12 @@ where S: DataOwned /// # } /// ``` #[cfg(feature = "std")] - pub fn logspace(base: A, start: A, end: A, n: usize) -> Self - where A: Float + pub fn logspace(base: A, range: R, n: usize) -> Self + where + R: std::ops::RangeBounds, + A: Float, { - Self::from(to_vec(logspace::logspace(base, start, end, n))) + Self::from(to_vec(logspace::logspace(base, range, n))) } /// Create a one-dimensional array with `n` geometrically spaced elements @@ -180,7 +181,8 @@ where S: DataOwned /// ``` #[cfg(feature = "std")] pub fn geomspace(start: A, end: A, n: usize) -> Option - where A: Float + where + A: Float, { Some(Self::from(to_vec(geomspace::geomspace(start, end, n)?))) } @@ -188,7 +190,8 @@ where S: DataOwned /// ## Constructor methods for two-dimensional arrays. impl ArrayBase -where S: DataOwned +where + S: DataOwned, { /// Create an identity matrix of size `n` (square 2D array). /// @@ -470,14 +473,14 @@ where /// ); /// ``` pub fn from_shape_vec(shape: Sh, v: Vec) -> Result - where Sh: Into> + where + Sh: Into>, { // eliminate the type parameter Sh as soon as possible Self::from_shape_vec_impl(shape.into(), v) } - fn from_shape_vec_impl(shape: StrideShape, v: Vec) -> Result - { + fn from_shape_vec_impl(shape: StrideShape, v: Vec) -> Result { let dim = shape.dim; let is_custom = shape.strides.is_custom(); dimension::can_index_slice_with_strides(&v, &dim, &shape.strides, dimension::CanIndexCheckMode::OwnedMutable)?; @@ -513,7 +516,8 @@ where /// 5. The strides must not allow any element to be referenced by two different /// indices. pub unsafe fn from_shape_vec_unchecked(shape: Sh, v: Vec) -> Self - where Sh: Into> + where + Sh: Into>, { let shape = shape.into(); let dim = shape.dim; @@ -521,8 +525,7 @@ where Self::from_vec_dim_stride_unchecked(dim, strides, v) } - unsafe fn from_vec_dim_stride_unchecked(dim: D, strides: D, mut v: Vec) -> Self - { + unsafe fn from_vec_dim_stride_unchecked(dim: D, strides: D, mut v: Vec) -> Self { // debug check for issues that indicates wrong use of this constructor debug_assert!(dimension::can_index_slice(&v, &dim, &strides, CanIndexCheckMode::OwnedMutable).is_ok()); @@ -595,7 +598,8 @@ where /// # let _ = shift_by_two; /// ``` pub fn uninit(shape: Sh) -> ArrayBase - where Sh: ShapeBuilder + where + Sh: ShapeBuilder, { unsafe { let shape = shape.into_shape_with_order(); diff --git a/src/lib.rs b/src/lib.rs index c26877434..41e5ca350 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -201,7 +201,7 @@ mod layout; mod linalg_traits; mod linspace; #[cfg(feature = "std")] -pub use crate::linspace::{linspace, linspace_exclusive, range, Linspace}; +pub use crate::linspace::{linspace, range, Linspace}; mod logspace; #[cfg(feature = "std")] pub use crate::logspace::{logspace, Logspace}; diff --git a/src/linspace.rs b/src/linspace.rs index 38fdf9f59..8f2db1257 100644 --- a/src/linspace.rs +++ b/src/linspace.rs @@ -6,13 +6,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. #![cfg(feature = "std")] + +use std::ops::{Bound, RangeBounds}; + use num_traits::Float; /// An iterator of a sequence of evenly spaced floats. /// /// Iterator element type is `F`. -pub struct Linspace -{ +pub struct Linspace { start: F, step: F, index: usize, @@ -20,13 +22,13 @@ pub struct Linspace } impl Iterator for Linspace -where F: Float +where + F: Float, { type Item = F; #[inline] - fn next(&mut self) -> Option - { + fn next(&mut self) -> Option { if self.index >= self.len { None } else { @@ -38,19 +40,18 @@ where F: Float } #[inline] - fn size_hint(&self) -> (usize, Option) - { + fn size_hint(&self) -> (usize, Option) { let n = self.len - self.index; (n, Some(n)) } } impl DoubleEndedIterator for Linspace -where F: Float +where + F: Float, { #[inline] - fn next_back(&mut self) -> Option - { + fn next_back(&mut self) -> Option { if self.index >= self.len { None } else { @@ -71,43 +72,31 @@ impl ExactSizeIterator for Linspace where Linspace: Iterator {} /// The iterator element type is `F`, where `F` must implement [`Float`], e.g. /// [`f32`] or [`f64`]. /// -/// **Panics** if converting `n - 1` to type `F` fails. +/// ## Panics +/// - If called with a range type other than `a..b` or `a..=b`. +/// - If converting `n` to type `F` fails. #[inline] -pub fn linspace(a: F, b: F, n: usize) -> Linspace -where F: Float +pub fn linspace(range: R, n: usize) -> Linspace +where + R: RangeBounds, + F: Float, { - let step = if n > 1 { - let num_steps = F::from(n - 1).expect("Converting number of steps to `A` must not fail."); - (b - a) / num_steps - } else { - F::zero() + let (a, b, num_steps) = match (range.start_bound(), range.end_bound()) { + (Bound::Included(a), Bound::Included(b)) => { + (*a, *b, F::from(n - 1).expect("Converting number of steps to `A` must not fail.")) + } + (Bound::Included(a), Bound::Excluded(b)) => { + (*a, *b, F::from(n).expect("Converting number of steps to `A` must not fail.")) + } + _ => panic!("Only a..b and a..=b ranges are supported."), }; - Linspace { - start: a, - step, - index: 0, - len: n, - } -} -/// Return an iterator of evenly spaced floats. -/// -/// The `Linspace` has `n` elements from `a` to `b` (exclusive). -/// -/// The iterator element type is `F`, where `F` must implement [`Float`], e.g. -/// [`f32`] or [`f64`]. -/// -/// **Panics** if converting `n` to type `F` fails. -#[inline] -pub fn linspace_exclusive(a: F, b: F, n: usize) -> Linspace -where F: Float -{ - let step = if n > 1 { - let num_steps = F::from(n).expect("Converting number of steps to `A` must not fail."); + let step = if num_steps > F::zero() { (b - a) / num_steps } else { F::zero() }; + Linspace { start: a, step, @@ -127,7 +116,8 @@ where F: Float /// **Panics** if converting `((b - a) / step).ceil()` to type `F` fails. #[inline] pub fn range(a: F, b: F, step: F) -> Linspace -where F: Float +where + F: Float, { let len = b - a; let steps = F::ceil(len / step); diff --git a/src/logspace.rs b/src/logspace.rs index 463012018..a62ba4263 100644 --- a/src/logspace.rs +++ b/src/logspace.rs @@ -6,6 +6,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. #![cfg(feature = "std")] + +use std::ops::{Bound, RangeBounds}; use num_traits::Float; /// An iterator of a sequence of logarithmically spaced number. @@ -79,15 +81,27 @@ impl ExactSizeIterator for Logspace where Logspace: Iterator {} /// /// **Panics** if converting `n - 1` to type `F` fails. #[inline] -pub fn logspace(base: F, a: F, b: F, n: usize) -> Logspace -where F: Float +pub fn logspace(base: F, range: R, n: usize) -> Logspace +where + R: RangeBounds, + F: Float, { - let step = if n > 1 { - let num_steps = F::from(n - 1).expect("Converting number of steps to `A` must not fail."); + let (a, b, num_steps) = match (range.start_bound(), range.end_bound()) { + (Bound::Included(a), Bound::Included(b)) => { + (*a, *b, F::from(n - 1).expect("Converting number of steps to `A` must not fail.")) + } + (Bound::Included(a), Bound::Excluded(b)) => { + (*a, *b, F::from(n).expect("Converting number of steps to `A` must not fail.")) + } + _ => panic!("Only a..b and a..=b ranges are supported."), + }; + + let step = if num_steps > F::zero() { (b - a) / num_steps } else { F::zero() }; + Logspace { sign: base.signum(), base: base.abs(), @@ -110,23 +124,23 @@ mod tests use crate::{arr1, Array1}; use approx::assert_abs_diff_eq; - let array: Array1<_> = logspace(10.0, 0.0, 3.0, 4).collect(); + let array: Array1<_> = logspace(10.0, 0.0..=3.0, 4).collect(); assert_abs_diff_eq!(array, arr1(&[1e0, 1e1, 1e2, 1e3]), epsilon = 1e-12); - let array: Array1<_> = logspace(10.0, 3.0, 0.0, 4).collect(); + let array: Array1<_> = logspace(10.0, 3.0..=0.0, 4).collect(); assert_abs_diff_eq!(array, arr1(&[1e3, 1e2, 1e1, 1e0]), epsilon = 1e-12); - let array: Array1<_> = logspace(-10.0, 3.0, 0.0, 4).collect(); + let array: Array1<_> = logspace(-10.0, 3.0..=0.0, 4).collect(); assert_abs_diff_eq!(array, arr1(&[-1e3, -1e2, -1e1, -1e0]), epsilon = 1e-12); - let array: Array1<_> = logspace(-10.0, 0.0, 3.0, 4).collect(); + let array: Array1<_> = logspace(-10.0, 0.0..=3.0, 4).collect(); assert_abs_diff_eq!(array, arr1(&[-1e0, -1e1, -1e2, -1e3]), epsilon = 1e-12); } #[test] fn iter_forward() { - let mut iter = logspace(10.0f64, 0.0, 3.0, 4); + let mut iter = logspace(10.0f64, 0.0..=3.0, 4); assert!(iter.size_hint() == (4, Some(4))); @@ -142,7 +156,7 @@ mod tests #[test] fn iter_backward() { - let mut iter = logspace(10.0f64, 0.0, 3.0, 4); + let mut iter = logspace(10.0f64, 0.0..=3.0, 4); assert!(iter.size_hint() == (4, Some(4))); From 3dfe1146f48bdac8cae6a0080e2c3316a6163e88 Mon Sep 17 00:00:00 2001 From: Vivian Date: Mon, 2 Feb 2026 10:32:51 +0100 Subject: [PATCH 3/8] nightly fmt --- src/impl_constructors.rs | 33 +++++++++++++++------------------ src/linspace.rs | 31 +++++++++++++++---------------- src/logspace.rs | 14 ++++++-------- 3 files changed, 36 insertions(+), 42 deletions(-) diff --git a/src/impl_constructors.rs b/src/impl_constructors.rs index f1a9b57ed..18cdca921 100644 --- a/src/impl_constructors.rs +++ b/src/impl_constructors.rs @@ -44,8 +44,7 @@ use rawpointer::PointerExt; /// /// ## Constructor methods for one-dimensional arrays. impl ArrayBase -where - S: DataOwned, +where S: DataOwned { /// Create a one-dimensional array from a vector (no copying needed). /// @@ -56,7 +55,8 @@ where /// /// let array = Array::from_vec(vec![1., 2., 3., 4.]); /// ``` - pub fn from_vec(v: Vec) -> Self { + pub fn from_vec(v: Vec) -> Self + { if mem::size_of::() == 0 { assert!(v.len() <= isize::MAX as usize, "Length must fit in `isize`.",); } @@ -73,7 +73,8 @@ where /// let array = Array::from_iter(0..10); /// ``` #[allow(clippy::should_implement_trait)] - pub fn from_iter>(iterable: I) -> Self { + pub fn from_iter>(iterable: I) -> Self + { Self::from_vec(iterable.into_iter().collect()) } @@ -116,8 +117,7 @@ where /// ``` #[cfg(feature = "std")] pub fn range(start: A, end: A, step: A) -> Self - where - A: Float, + where A: Float { Self::from(to_vec(linspace::range(start, end, step))) } @@ -181,8 +181,7 @@ where /// ``` #[cfg(feature = "std")] pub fn geomspace(start: A, end: A, n: usize) -> Option - where - A: Float, + where A: Float { Some(Self::from(to_vec(geomspace::geomspace(start, end, n)?))) } @@ -190,8 +189,7 @@ where /// ## Constructor methods for two-dimensional arrays. impl ArrayBase -where - S: DataOwned, +where S: DataOwned { /// Create an identity matrix of size `n` (square 2D array). /// @@ -473,14 +471,14 @@ where /// ); /// ``` pub fn from_shape_vec(shape: Sh, v: Vec) -> Result - where - Sh: Into>, + where Sh: Into> { // eliminate the type parameter Sh as soon as possible Self::from_shape_vec_impl(shape.into(), v) } - fn from_shape_vec_impl(shape: StrideShape, v: Vec) -> Result { + fn from_shape_vec_impl(shape: StrideShape, v: Vec) -> Result + { let dim = shape.dim; let is_custom = shape.strides.is_custom(); dimension::can_index_slice_with_strides(&v, &dim, &shape.strides, dimension::CanIndexCheckMode::OwnedMutable)?; @@ -516,8 +514,7 @@ where /// 5. The strides must not allow any element to be referenced by two different /// indices. pub unsafe fn from_shape_vec_unchecked(shape: Sh, v: Vec) -> Self - where - Sh: Into>, + where Sh: Into> { let shape = shape.into(); let dim = shape.dim; @@ -525,7 +522,8 @@ where Self::from_vec_dim_stride_unchecked(dim, strides, v) } - unsafe fn from_vec_dim_stride_unchecked(dim: D, strides: D, mut v: Vec) -> Self { + unsafe fn from_vec_dim_stride_unchecked(dim: D, strides: D, mut v: Vec) -> Self + { // debug check for issues that indicates wrong use of this constructor debug_assert!(dimension::can_index_slice(&v, &dim, &strides, CanIndexCheckMode::OwnedMutable).is_ok()); @@ -598,8 +596,7 @@ where /// # let _ = shift_by_two; /// ``` pub fn uninit(shape: Sh) -> ArrayBase - where - Sh: ShapeBuilder, + where Sh: ShapeBuilder { unsafe { let shape = shape.into_shape_with_order(); diff --git a/src/linspace.rs b/src/linspace.rs index 8f2db1257..a8498a483 100644 --- a/src/linspace.rs +++ b/src/linspace.rs @@ -14,7 +14,8 @@ use num_traits::Float; /// An iterator of a sequence of evenly spaced floats. /// /// Iterator element type is `F`. -pub struct Linspace { +pub struct Linspace +{ start: F, step: F, index: usize, @@ -22,13 +23,13 @@ pub struct Linspace { } impl Iterator for Linspace -where - F: Float, +where F: Float { type Item = F; #[inline] - fn next(&mut self) -> Option { + fn next(&mut self) -> Option + { if self.index >= self.len { None } else { @@ -40,18 +41,19 @@ where } #[inline] - fn size_hint(&self) -> (usize, Option) { + fn size_hint(&self) -> (usize, Option) + { let n = self.len - self.index; (n, Some(n)) } } impl DoubleEndedIterator for Linspace -where - F: Float, +where F: Float { #[inline] - fn next_back(&mut self) -> Option { + fn next_back(&mut self) -> Option + { if self.index >= self.len { None } else { @@ -82,12 +84,10 @@ where F: Float, { let (a, b, num_steps) = match (range.start_bound(), range.end_bound()) { - (Bound::Included(a), Bound::Included(b)) => { - (*a, *b, F::from(n - 1).expect("Converting number of steps to `A` must not fail.")) - } - (Bound::Included(a), Bound::Excluded(b)) => { - (*a, *b, F::from(n).expect("Converting number of steps to `A` must not fail.")) - } + (Bound::Included(a), Bound::Included(b)) => + (*a, *b, F::from(n - 1).expect("Converting number of steps to `A` must not fail.")), + (Bound::Included(a), Bound::Excluded(b)) => + (*a, *b, F::from(n).expect("Converting number of steps to `A` must not fail.")), _ => panic!("Only a..b and a..=b ranges are supported."), }; @@ -116,8 +116,7 @@ where /// **Panics** if converting `((b - a) / step).ceil()` to type `F` fails. #[inline] pub fn range(a: F, b: F, step: F) -> Linspace -where - F: Float, +where F: Float { let len = b - a; let steps = F::ceil(len / step); diff --git a/src/logspace.rs b/src/logspace.rs index a62ba4263..7e4437407 100644 --- a/src/logspace.rs +++ b/src/logspace.rs @@ -7,8 +7,8 @@ // except according to those terms. #![cfg(feature = "std")] -use std::ops::{Bound, RangeBounds}; use num_traits::Float; +use std::ops::{Bound, RangeBounds}; /// An iterator of a sequence of logarithmically spaced number. /// @@ -82,17 +82,15 @@ impl ExactSizeIterator for Logspace where Logspace: Iterator {} /// **Panics** if converting `n - 1` to type `F` fails. #[inline] pub fn logspace(base: F, range: R, n: usize) -> Logspace -where +where R: RangeBounds, F: Float, { let (a, b, num_steps) = match (range.start_bound(), range.end_bound()) { - (Bound::Included(a), Bound::Included(b)) => { - (*a, *b, F::from(n - 1).expect("Converting number of steps to `A` must not fail.")) - } - (Bound::Included(a), Bound::Excluded(b)) => { - (*a, *b, F::from(n).expect("Converting number of steps to `A` must not fail.")) - } + (Bound::Included(a), Bound::Included(b)) => + (*a, *b, F::from(n - 1).expect("Converting number of steps to `A` must not fail.")), + (Bound::Included(a), Bound::Excluded(b)) => + (*a, *b, F::from(n).expect("Converting number of steps to `A` must not fail.")), _ => panic!("Only a..b and a..=b ranges are supported."), }; From 4d0bbc0773d3277936b819a2acd1529f1c1bab19 Mon Sep 17 00:00:00 2001 From: Vivian Date: Mon, 2 Feb 2026 10:51:21 +0100 Subject: [PATCH 4/8] Use `FiniteBounds` to only allow `a..b` and `a..=b` ranges. --- benches/iter.rs | 12 ++++++------ src/finite_bounds.rs | 38 ++++++++++++++++++++++++++++++++++++ src/impl_constructors.rs | 4 ++-- src/lib.rs | 2 ++ src/linspace.rs | 32 ++++++++++++++---------------- src/logspace.rs | 42 ++++++++++++++++------------------------ 6 files changed, 79 insertions(+), 51 deletions(-) create mode 100644 src/finite_bounds.rs diff --git a/benches/iter.rs b/benches/iter.rs index bc483c8c2..0e18f1230 100644 --- a/benches/iter.rs +++ b/benches/iter.rs @@ -47,7 +47,7 @@ fn iter_sum_2d_transpose(bench: &mut Bencher) #[bench] fn iter_filter_sum_2d_u32(bench: &mut Bencher) { - let a = Array::linspace(0., 1., 256) + let a = Array::linspace(0.0..=1.0, 256) .into_shape_with_order((16, 16)) .unwrap(); let b = a.mapv(|x| (x * 100.) as u32); @@ -58,7 +58,7 @@ fn iter_filter_sum_2d_u32(bench: &mut Bencher) #[bench] fn iter_filter_sum_2d_f32(bench: &mut Bencher) { - let a = Array::linspace(0., 1., 256) + let a = Array::linspace(0.0..=1.0, 256) .into_shape_with_order((16, 16)) .unwrap(); let b = a * 100.; @@ -69,7 +69,7 @@ fn iter_filter_sum_2d_f32(bench: &mut Bencher) #[bench] fn iter_filter_sum_2d_stride_u32(bench: &mut Bencher) { - let a = Array::linspace(0., 1., 256) + let a = Array::linspace(0.0..=1.0, 256) .into_shape_with_order((16, 16)) .unwrap(); let b = a.mapv(|x| (x * 100.) as u32); @@ -81,7 +81,7 @@ fn iter_filter_sum_2d_stride_u32(bench: &mut Bencher) #[bench] fn iter_filter_sum_2d_stride_f32(bench: &mut Bencher) { - let a = Array::linspace(0., 1., 256) + let a = Array::linspace(0.0..=1.0, 256) .into_shape_with_order((16, 16)) .unwrap(); let b = a * 100.; @@ -93,7 +93,7 @@ fn iter_filter_sum_2d_stride_f32(bench: &mut Bencher) #[bench] fn iter_rev_step_by_contiguous(bench: &mut Bencher) { - let a = Array::linspace(0., 1., 512); + let a = Array::linspace(0.0..=1.0, 512); bench.iter(|| { a.iter().rev().step_by(2).for_each(|x| { black_box(x); @@ -105,7 +105,7 @@ fn iter_rev_step_by_contiguous(bench: &mut Bencher) #[bench] fn iter_rev_step_by_discontiguous(bench: &mut Bencher) { - let mut a = Array::linspace(0., 1., 1024); + let mut a = Array::linspace(0.0..=1.0, 1024); a.slice_axis_inplace(Axis(0), Slice::new(0, None, 2)); bench.iter(|| { a.iter().rev().step_by(2).for_each(|x| { diff --git a/src/finite_bounds.rs b/src/finite_bounds.rs new file mode 100644 index 000000000..b2cd2aa68 --- /dev/null +++ b/src/finite_bounds.rs @@ -0,0 +1,38 @@ +use num_traits::Float; + +pub enum Bound { + Included(F), + Excluded(F), +} + +/// A version of std::ops::RangeBounds that only implements a..b and a..=b ranges. +pub trait FiniteBounds { + fn start_bound(&self) -> F; + fn end_bound(&self) -> Bound; +} + +impl FiniteBounds for std::ops::Range +where + F: Float, +{ + fn start_bound(&self) -> F { + self.start + } + + fn end_bound(&self) -> Bound { + Bound::Excluded(self.end) + } +} + +impl FiniteBounds for std::ops::RangeInclusive +where + F: Float, +{ + fn start_bound(&self) -> F { + *self.start() + } + + fn end_bound(&self) -> Bound { + Bound::Included(*self.end()) + } +} diff --git a/src/impl_constructors.rs b/src/impl_constructors.rs index 18cdca921..846223f26 100644 --- a/src/impl_constructors.rs +++ b/src/impl_constructors.rs @@ -98,7 +98,7 @@ where S: DataOwned #[cfg(feature = "std")] pub fn linspace(range: R, n: usize) -> Self where - R: std::ops::RangeBounds, + R: crate::finite_bounds::FiniteBounds, A: Float, { Self::from(to_vec(linspace::linspace(range, n))) @@ -146,7 +146,7 @@ where S: DataOwned #[cfg(feature = "std")] pub fn logspace(base: A, range: R, n: usize) -> Self where - R: std::ops::RangeBounds, + R: crate::finite_bounds::FiniteBounds, A: Float, { Self::from(to_vec(logspace::logspace(base, range, n))) diff --git a/src/lib.rs b/src/lib.rs index 41e5ca350..970c3f126 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -199,6 +199,8 @@ mod indexes; mod iterators; mod layout; mod linalg_traits; +#[cfg(feature = "std")] +mod finite_bounds; mod linspace; #[cfg(feature = "std")] pub use crate::linspace::{linspace, range, Linspace}; diff --git a/src/linspace.rs b/src/linspace.rs index a8498a483..f2331888b 100644 --- a/src/linspace.rs +++ b/src/linspace.rs @@ -7,15 +7,14 @@ // except according to those terms. #![cfg(feature = "std")] -use std::ops::{Bound, RangeBounds}; +use crate::finite_bounds::{Bound, FiniteBounds}; use num_traits::Float; /// An iterator of a sequence of evenly spaced floats. /// /// Iterator element type is `F`. -pub struct Linspace -{ +pub struct Linspace { start: F, step: F, index: usize, @@ -23,13 +22,13 @@ pub struct Linspace } impl Iterator for Linspace -where F: Float +where + F: Float, { type Item = F; #[inline] - fn next(&mut self) -> Option - { + fn next(&mut self) -> Option { if self.index >= self.len { None } else { @@ -41,19 +40,18 @@ where F: Float } #[inline] - fn size_hint(&self) -> (usize, Option) - { + fn size_hint(&self) -> (usize, Option) { let n = self.len - self.index; (n, Some(n)) } } impl DoubleEndedIterator for Linspace -where F: Float +where + F: Float, { #[inline] - fn next_back(&mut self) -> Option - { + fn next_back(&mut self) -> Option { if self.index >= self.len { None } else { @@ -80,15 +78,12 @@ impl ExactSizeIterator for Linspace where Linspace: Iterator {} #[inline] pub fn linspace(range: R, n: usize) -> Linspace where - R: RangeBounds, + R: FiniteBounds, F: Float, { let (a, b, num_steps) = match (range.start_bound(), range.end_bound()) { - (Bound::Included(a), Bound::Included(b)) => - (*a, *b, F::from(n - 1).expect("Converting number of steps to `A` must not fail.")), - (Bound::Included(a), Bound::Excluded(b)) => - (*a, *b, F::from(n).expect("Converting number of steps to `A` must not fail.")), - _ => panic!("Only a..b and a..=b ranges are supported."), + (a, Bound::Included(b)) => (a, b, F::from(n - 1).expect("Converting number of steps to `A` must not fail.")), + (a, Bound::Excluded(b)) => (a, b, F::from(n).expect("Converting number of steps to `A` must not fail.")), }; let step = if num_steps > F::zero() { @@ -116,7 +111,8 @@ where /// **Panics** if converting `((b - a) / step).ceil()` to type `F` fails. #[inline] pub fn range(a: F, b: F, step: F) -> Linspace -where F: Float +where + F: Float, { let len = b - a; let steps = F::ceil(len / step); diff --git a/src/logspace.rs b/src/logspace.rs index 7e4437407..fa0192446 100644 --- a/src/logspace.rs +++ b/src/logspace.rs @@ -7,14 +7,14 @@ // except according to those terms. #![cfg(feature = "std")] +use crate::finite_bounds::{Bound, FiniteBounds}; + use num_traits::Float; -use std::ops::{Bound, RangeBounds}; /// An iterator of a sequence of logarithmically spaced number. /// /// Iterator element type is `F`. -pub struct Logspace -{ +pub struct Logspace { sign: F, base: F, start: F, @@ -24,13 +24,13 @@ pub struct Logspace } impl Iterator for Logspace -where F: Float +where + F: Float, { type Item = F; #[inline] - fn next(&mut self) -> Option - { + fn next(&mut self) -> Option { if self.index >= self.len { None } else { @@ -43,19 +43,18 @@ where F: Float } #[inline] - fn size_hint(&self) -> (usize, Option) - { + fn size_hint(&self) -> (usize, Option) { let n = self.len - self.index; (n, Some(n)) } } impl DoubleEndedIterator for Logspace -where F: Float +where + F: Float, { #[inline] - fn next_back(&mut self) -> Option - { + fn next_back(&mut self) -> Option { if self.index >= self.len { None } else { @@ -83,15 +82,12 @@ impl ExactSizeIterator for Logspace where Logspace: Iterator {} #[inline] pub fn logspace(base: F, range: R, n: usize) -> Logspace where - R: RangeBounds, + R: FiniteBounds, F: Float, { let (a, b, num_steps) = match (range.start_bound(), range.end_bound()) { - (Bound::Included(a), Bound::Included(b)) => - (*a, *b, F::from(n - 1).expect("Converting number of steps to `A` must not fail.")), - (Bound::Included(a), Bound::Excluded(b)) => - (*a, *b, F::from(n).expect("Converting number of steps to `A` must not fail.")), - _ => panic!("Only a..b and a..=b ranges are supported."), + (a, Bound::Included(b)) => (a, b, F::from(n - 1).expect("Converting number of steps to `A` must not fail.")), + (a, Bound::Excluded(b)) => (a, b, F::from(n).expect("Converting number of steps to `A` must not fail.")), }; let step = if num_steps > F::zero() { @@ -111,14 +107,12 @@ where } #[cfg(test)] -mod tests -{ +mod tests { use super::logspace; #[test] #[cfg(feature = "approx")] - fn valid() - { + fn valid() { use crate::{arr1, Array1}; use approx::assert_abs_diff_eq; @@ -136,8 +130,7 @@ mod tests } #[test] - fn iter_forward() - { + fn iter_forward() { let mut iter = logspace(10.0f64, 0.0..=3.0, 4); assert!(iter.size_hint() == (4, Some(4))); @@ -152,8 +145,7 @@ mod tests } #[test] - fn iter_backward() - { + fn iter_backward() { let mut iter = logspace(10.0f64, 0.0..=3.0, 4); assert!(iter.size_hint() == (4, Some(4))); From e750399492acfe52c9cdde1b9a42bd0dd8b9dcf0 Mon Sep 17 00:00:00 2001 From: Vivian Date: Mon, 2 Feb 2026 10:51:32 +0100 Subject: [PATCH 5/8] nightly fmt --- src/finite_bounds.rs | 24 ++++++++++++++---------- src/linspace.rs | 21 +++++++++++---------- src/logspace.rs | 30 ++++++++++++++++++------------ 3 files changed, 43 insertions(+), 32 deletions(-) diff --git a/src/finite_bounds.rs b/src/finite_bounds.rs index b2cd2aa68..565fe2bcb 100644 --- a/src/finite_bounds.rs +++ b/src/finite_bounds.rs @@ -1,38 +1,42 @@ use num_traits::Float; -pub enum Bound { +pub enum Bound +{ Included(F), Excluded(F), } /// A version of std::ops::RangeBounds that only implements a..b and a..=b ranges. -pub trait FiniteBounds { +pub trait FiniteBounds +{ fn start_bound(&self) -> F; fn end_bound(&self) -> Bound; } impl FiniteBounds for std::ops::Range -where - F: Float, +where F: Float { - fn start_bound(&self) -> F { + fn start_bound(&self) -> F + { self.start } - fn end_bound(&self) -> Bound { + fn end_bound(&self) -> Bound + { Bound::Excluded(self.end) } } impl FiniteBounds for std::ops::RangeInclusive -where - F: Float, +where F: Float { - fn start_bound(&self) -> F { + fn start_bound(&self) -> F + { *self.start() } - fn end_bound(&self) -> Bound { + fn end_bound(&self) -> Bound + { Bound::Included(*self.end()) } } diff --git a/src/linspace.rs b/src/linspace.rs index f2331888b..099cf2aa6 100644 --- a/src/linspace.rs +++ b/src/linspace.rs @@ -14,7 +14,8 @@ use num_traits::Float; /// An iterator of a sequence of evenly spaced floats. /// /// Iterator element type is `F`. -pub struct Linspace { +pub struct Linspace +{ start: F, step: F, index: usize, @@ -22,13 +23,13 @@ pub struct Linspace { } impl Iterator for Linspace -where - F: Float, +where F: Float { type Item = F; #[inline] - fn next(&mut self) -> Option { + fn next(&mut self) -> Option + { if self.index >= self.len { None } else { @@ -40,18 +41,19 @@ where } #[inline] - fn size_hint(&self) -> (usize, Option) { + fn size_hint(&self) -> (usize, Option) + { let n = self.len - self.index; (n, Some(n)) } } impl DoubleEndedIterator for Linspace -where - F: Float, +where F: Float { #[inline] - fn next_back(&mut self) -> Option { + fn next_back(&mut self) -> Option + { if self.index >= self.len { None } else { @@ -111,8 +113,7 @@ where /// **Panics** if converting `((b - a) / step).ceil()` to type `F` fails. #[inline] pub fn range(a: F, b: F, step: F) -> Linspace -where - F: Float, +where F: Float { let len = b - a; let steps = F::ceil(len / step); diff --git a/src/logspace.rs b/src/logspace.rs index fa0192446..dd1b7ae19 100644 --- a/src/logspace.rs +++ b/src/logspace.rs @@ -14,7 +14,8 @@ use num_traits::Float; /// An iterator of a sequence of logarithmically spaced number. /// /// Iterator element type is `F`. -pub struct Logspace { +pub struct Logspace +{ sign: F, base: F, start: F, @@ -24,13 +25,13 @@ pub struct Logspace { } impl Iterator for Logspace -where - F: Float, +where F: Float { type Item = F; #[inline] - fn next(&mut self) -> Option { + fn next(&mut self) -> Option + { if self.index >= self.len { None } else { @@ -43,18 +44,19 @@ where } #[inline] - fn size_hint(&self) -> (usize, Option) { + fn size_hint(&self) -> (usize, Option) + { let n = self.len - self.index; (n, Some(n)) } } impl DoubleEndedIterator for Logspace -where - F: Float, +where F: Float { #[inline] - fn next_back(&mut self) -> Option { + fn next_back(&mut self) -> Option + { if self.index >= self.len { None } else { @@ -107,12 +109,14 @@ where } #[cfg(test)] -mod tests { +mod tests +{ use super::logspace; #[test] #[cfg(feature = "approx")] - fn valid() { + fn valid() + { use crate::{arr1, Array1}; use approx::assert_abs_diff_eq; @@ -130,7 +134,8 @@ mod tests { } #[test] - fn iter_forward() { + fn iter_forward() + { let mut iter = logspace(10.0f64, 0.0..=3.0, 4); assert!(iter.size_hint() == (4, Some(4))); @@ -145,7 +150,8 @@ mod tests { } #[test] - fn iter_backward() { + fn iter_backward() + { let mut iter = logspace(10.0f64, 0.0..=3.0, 4); assert!(iter.size_hint() == (4, Some(4))); From 4a6364721aede2fc106e7e27bd873c66df14a8d2 Mon Sep 17 00:00:00 2001 From: Vivian Date: Mon, 2 Feb 2026 10:55:11 +0100 Subject: [PATCH 6/8] remove panic from comment --- src/linspace.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/linspace.rs b/src/linspace.rs index 099cf2aa6..ff52bf0c1 100644 --- a/src/linspace.rs +++ b/src/linspace.rs @@ -74,9 +74,7 @@ impl ExactSizeIterator for Linspace where Linspace: Iterator {} /// The iterator element type is `F`, where `F` must implement [`Float`], e.g. /// [`f32`] or [`f64`]. /// -/// ## Panics -/// - If called with a range type other than `a..b` or `a..=b`. -/// - If converting `n` to type `F` fails. +/// **Panics** if converting `n` to type `F` fails. #[inline] pub fn linspace(range: R, n: usize) -> Linspace where From 3557a8d0977a2acf44601ad18eca2d2bc273bcea Mon Sep 17 00:00:00 2001 From: Vivian Date: Thu, 5 Feb 2026 14:59:33 +0100 Subject: [PATCH 7/8] Update syntax everywhere --- README-quick-start.md | 2 +- benches/bench1.rs | 2 +- benches/higher-order.rs | 10 +++++----- benches/numeric.rs | 2 +- examples/sort-axis.rs | 2 +- src/doc/ndarray_for_numpy_users/mod.rs | 4 ++-- src/impl_constructors.rs | 6 +++--- src/parallel/mod.rs | 4 ++-- tests/par_azip.rs | 2 +- tests/par_rayon.rs | 4 ++-- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/README-quick-start.md b/README-quick-start.md index ad13acc72..19decb859 100644 --- a/README-quick-start.md +++ b/README-quick-start.md @@ -91,7 +91,7 @@ fn main() { use ndarray::prelude::*; use ndarray::{Array, Ix3}; fn main() { - let a = Array::::linspace(0., 5., 11); + let a = Array::::linspace(0.0..5.0, 11); println!("{:?}", a); } ``` diff --git a/benches/bench1.rs b/benches/bench1.rs index ea527cd35..3b00b41e9 100644 --- a/benches/bench1.rs +++ b/benches/bench1.rs @@ -984,7 +984,7 @@ const MEAN_SUM_N: usize = 127; fn range_mat(m: Ix, n: Ix) -> Array2 { assert!(m * n != 0); - Array::linspace(0., (m * n - 1) as f32, m * n) + Array::linspace(0.0..(m * n - 1) as f32, m * n) .into_shape_with_order((m, n)) .unwrap() } diff --git a/benches/higher-order.rs b/benches/higher-order.rs index 5eb009566..9c4b64434 100644 --- a/benches/higher-order.rs +++ b/benches/higher-order.rs @@ -14,7 +14,7 @@ const Y: usize = 16; #[bench] fn map_regular(bench: &mut Bencher) { - let a = Array::linspace(0., 127., N) + let a = Array::linspace(0.0..127.0, N) .into_shape_with_order((X, Y)) .unwrap(); bench.iter(|| a.map(|&x| 2. * x)); @@ -29,7 +29,7 @@ pub fn double_array(mut a: ArrayViewMut2<'_, f64>) #[bench] fn map_stride_double_f64(bench: &mut Bencher) { - let mut a = Array::linspace(0., 127., N * 2) + let mut a = Array::linspace(0.0..127.0, N * 2) .into_shape_with_order([X, Y * 2]) .unwrap(); let mut av = a.slice_mut(s![.., ..;2]); @@ -42,7 +42,7 @@ fn map_stride_double_f64(bench: &mut Bencher) #[bench] fn map_stride_f64(bench: &mut Bencher) { - let a = Array::linspace(0., 127., N * 2) + let a = Array::linspace(0.0..127.0, N * 2) .into_shape_with_order([X, Y * 2]) .unwrap(); let av = a.slice(s![.., ..;2]); @@ -53,7 +53,7 @@ fn map_stride_f64(bench: &mut Bencher) #[bench] fn map_stride_u32(bench: &mut Bencher) { - let a = Array::linspace(0., 127., N * 2) + let a = Array::linspace(0.0..127.0, N * 2) .into_shape_with_order([X, Y * 2]) .unwrap(); let b = a.mapv(|x| x as u32); @@ -65,7 +65,7 @@ fn map_stride_u32(bench: &mut Bencher) #[bench] fn fold_axis(bench: &mut Bencher) { - let a = Array::linspace(0., 127., N * 2) + let a = Array::linspace(0.0..127.0, N * 2) .into_shape_with_order([X, Y * 2]) .unwrap(); bench.iter(|| a.fold_axis(Axis(0), 0., |&acc, &elt| acc + elt)); diff --git a/benches/numeric.rs b/benches/numeric.rs index ceb57fbd7..e447ddf77 100644 --- a/benches/numeric.rs +++ b/benches/numeric.rs @@ -13,7 +13,7 @@ const Y: usize = 16; #[bench] fn clip(bench: &mut Bencher) { - let mut a = Array::linspace(0., 127., N * 2) + let mut a = Array::linspace(0.0..127.0, N * 2) .into_shape_with_order([X, Y * 2]) .unwrap(); let min = 2.; diff --git a/examples/sort-axis.rs b/examples/sort-axis.rs index 4da3a64d5..26292bad8 100644 --- a/examples/sort-axis.rs +++ b/examples/sort-axis.rs @@ -169,7 +169,7 @@ where D: Dimension #[cfg(feature = "std")] fn main() { - let a = Array::linspace(0., 63., 64) + let a = Array::linspace(0.0..63.0, 64) .into_shape_with_order((8, 8)) .unwrap(); let strings = a.map(|x| x.to_string()); diff --git a/src/doc/ndarray_for_numpy_users/mod.rs b/src/doc/ndarray_for_numpy_users/mod.rs index bb6b7ae83..a9400211d 100644 --- a/src/doc/ndarray_for_numpy_users/mod.rs +++ b/src/doc/ndarray_for_numpy_users/mod.rs @@ -195,8 +195,8 @@ //! ------|-----------|------ //! `np.array([[1.,2.,3.], [4.,5.,6.]])` | [`array![[1.,2.,3.], [4.,5.,6.]]`][array!] or [`arr2(&[[1.,2.,3.], [4.,5.,6.]])`][arr2()] | 2×3 floating-point array literal //! `np.arange(0., 10., 0.5)` or `np.r_[:10.:0.5]` | [`Array::range(0., 10., 0.5)`][::range()] | create a 1-D array with values `0.`, `0.5`, …, `9.5` -//! `np.linspace(0., 10., 11)` or `np.r_[:10.:11j]` | [`Array::linspace(0., 10., 11)`][::linspace()] | create a 1-D array with 11 elements with values `0.`, …, `10.` -//! `np.logspace(2.0, 3.0, num=4, base=10.0)` | [`Array::logspace(10.0, 2.0, 3.0, 4)`][::logspace()] | create a 1-D array with 4 elements with values `100.`, `215.4`, `464.1`, `1000.` +//! `np.linspace(0., 10., 11)` or `np.r_[:10.:11j]` | [`Array::linspace(0.0..=10.0, 11)`][::linspace()] | create a 1-D array with 11 elements with values `0.`, …, `10.` +//! `np.logspace(2.0, 3.0, num=4, base=10.0)` | [`Array::logspace(10.0, 2.0..=3.0, 4)`][::logspace()] | create a 1-D array with 4 elements with values `100.`, `215.4`, `464.1`, `1000.` //! `np.geomspace(1., 1000., num=4)` | [`Array::geomspace(1e0, 1e3, 4)`][::geomspace()] | create a 1-D array with 4 elements with values `1.`, `10.`, `100.`, `1000.` //! `np.ones((3, 4, 5))` | [`Array::ones((3, 4, 5))`][::ones()] | create a 3×4×5 array filled with ones (inferring the element type) //! `np.zeros((3, 4, 5))` | [`Array::zeros((3, 4, 5))`][::zeros()] | create a 3×4×5 array filled with zeros (inferring the element type) diff --git a/src/impl_constructors.rs b/src/impl_constructors.rs index 846223f26..7f71cca5b 100644 --- a/src/impl_constructors.rs +++ b/src/impl_constructors.rs @@ -92,7 +92,7 @@ where S: DataOwned /// ```rust /// use ndarray::{Array, arr1}; /// - /// let array = Array::linspace(0., 1., 5); + /// let array = Array::linspace(0.0..=1.0, 5); /// assert!(array == arr1(&[0.0, 0.25, 0.5, 0.75, 1.0])) /// ``` #[cfg(feature = "std")] @@ -136,10 +136,10 @@ where S: DataOwned /// use approx::assert_abs_diff_eq; /// use ndarray::{Array, arr1}; /// - /// let array = Array::logspace(10.0, 0.0, 3.0, 4); + /// let array = Array::logspace(10.0, 0.0..=3.0, 4); /// assert_abs_diff_eq!(array, arr1(&[1e0, 1e1, 1e2, 1e3]), epsilon = 1e-12); /// - /// let array = Array::logspace(-10.0, 3.0, 0.0, 4); + /// let array = Array::logspace(-10.0, 3.0..=0.0, 4); /// assert_abs_diff_eq!(array, arr1(&[-1e3, -1e2, -1e1, -1e0]), epsilon = 1e-12); /// # } /// ``` diff --git a/src/parallel/mod.rs b/src/parallel/mod.rs index 2eef69307..f99177c3a 100644 --- a/src/parallel/mod.rs +++ b/src/parallel/mod.rs @@ -65,7 +65,7 @@ //! use ndarray::Axis; //! use ndarray::parallel::prelude::*; //! -//! let a = Array::linspace(0., 63., 64).into_shape_with_order((4, 16)).unwrap(); +//! let a = Array::linspace(0.0..63.0, 64).into_shape_with_order((4, 16)).unwrap(); //! let mut sums = Vec::new(); //! a.axis_iter(Axis(0)) //! .into_par_iter() @@ -84,7 +84,7 @@ //! use ndarray::Axis; //! use ndarray::parallel::prelude::*; //! -//! let a = Array::linspace(0., 63., 64).into_shape_with_order((4, 16)).unwrap(); +//! let a = Array::linspace(0.0..63.0, 64).into_shape_with_order((4, 16)).unwrap(); //! let mut shapes = Vec::new(); //! a.axis_chunks_iter(Axis(0), 3) //! .into_par_iter() diff --git a/tests/par_azip.rs b/tests/par_azip.rs index 41011d495..dd00059c1 100644 --- a/tests/par_azip.rs +++ b/tests/par_azip.rs @@ -41,7 +41,7 @@ fn test_par_azip3() *a += b / 10.; *c = a.sin(); }); - let res = Array::linspace(0., 3.1, 32).mapv_into(f32::sin); + let res = Array::linspace(0.0..3.1, 32).mapv_into(f32::sin); assert_abs_diff_eq!(res, ArrayView::from(&c), epsilon = 1e-4); } diff --git a/tests/par_rayon.rs b/tests/par_rayon.rs index 13669763f..3dbf9bd9c 100644 --- a/tests/par_rayon.rs +++ b/tests/par_rayon.rs @@ -26,7 +26,7 @@ fn test_axis_iter() fn test_axis_iter_mut() { use approx::assert_abs_diff_eq; - let mut a = Array::linspace(0., 1.0f64, M * N) + let mut a = Array::linspace(0.0..1.0f64, M * N) .into_shape_with_order((M, N)) .unwrap(); let b = a.mapv(|x| x.exp()); @@ -82,7 +82,7 @@ fn test_axis_chunks_iter() fn test_axis_chunks_iter_mut() { use approx::assert_abs_diff_eq; - let mut a = Array::linspace(0., 1.0f64, M * N) + let mut a = Array::linspace(0.0..1.0f64, M * N) .into_shape_with_order((M, N)) .unwrap(); let b = a.mapv(|x| x.exp()); From ad4acbe3b06eb31eea03e5322d4dd9e06611c805 Mon Sep 17 00:00:00 2001 From: Vivian Date: Thu, 5 Feb 2026 15:22:17 +0100 Subject: [PATCH 8/8] *in*clusive range syntax --- README-quick-start.md | 2 +- benches/bench1.rs | 2 +- benches/higher-order.rs | 10 +++++----- benches/numeric.rs | 2 +- examples/sort-axis.rs | 2 +- src/parallel/mod.rs | 4 ++-- tests/par_azip.rs | 2 +- tests/par_rayon.rs | 4 ++-- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/README-quick-start.md b/README-quick-start.md index 19decb859..84e968744 100644 --- a/README-quick-start.md +++ b/README-quick-start.md @@ -91,7 +91,7 @@ fn main() { use ndarray::prelude::*; use ndarray::{Array, Ix3}; fn main() { - let a = Array::::linspace(0.0..5.0, 11); + let a = Array::::linspace(0.0..=5.0, 11); println!("{:?}", a); } ``` diff --git a/benches/bench1.rs b/benches/bench1.rs index 3b00b41e9..3b5405329 100644 --- a/benches/bench1.rs +++ b/benches/bench1.rs @@ -984,7 +984,7 @@ const MEAN_SUM_N: usize = 127; fn range_mat(m: Ix, n: Ix) -> Array2 { assert!(m * n != 0); - Array::linspace(0.0..(m * n - 1) as f32, m * n) + Array::linspace(0.0..=(m * n - 1) as f32, m * n) .into_shape_with_order((m, n)) .unwrap() } diff --git a/benches/higher-order.rs b/benches/higher-order.rs index 9c4b64434..6356687fb 100644 --- a/benches/higher-order.rs +++ b/benches/higher-order.rs @@ -14,7 +14,7 @@ const Y: usize = 16; #[bench] fn map_regular(bench: &mut Bencher) { - let a = Array::linspace(0.0..127.0, N) + let a = Array::linspace(0.0..=127.0, N) .into_shape_with_order((X, Y)) .unwrap(); bench.iter(|| a.map(|&x| 2. * x)); @@ -29,7 +29,7 @@ pub fn double_array(mut a: ArrayViewMut2<'_, f64>) #[bench] fn map_stride_double_f64(bench: &mut Bencher) { - let mut a = Array::linspace(0.0..127.0, N * 2) + let mut a = Array::linspace(0.0..=127.0, N * 2) .into_shape_with_order([X, Y * 2]) .unwrap(); let mut av = a.slice_mut(s![.., ..;2]); @@ -42,7 +42,7 @@ fn map_stride_double_f64(bench: &mut Bencher) #[bench] fn map_stride_f64(bench: &mut Bencher) { - let a = Array::linspace(0.0..127.0, N * 2) + let a = Array::linspace(0.0..=127.0, N * 2) .into_shape_with_order([X, Y * 2]) .unwrap(); let av = a.slice(s![.., ..;2]); @@ -53,7 +53,7 @@ fn map_stride_f64(bench: &mut Bencher) #[bench] fn map_stride_u32(bench: &mut Bencher) { - let a = Array::linspace(0.0..127.0, N * 2) + let a = Array::linspace(0.0..=127.0, N * 2) .into_shape_with_order([X, Y * 2]) .unwrap(); let b = a.mapv(|x| x as u32); @@ -65,7 +65,7 @@ fn map_stride_u32(bench: &mut Bencher) #[bench] fn fold_axis(bench: &mut Bencher) { - let a = Array::linspace(0.0..127.0, N * 2) + let a = Array::linspace(0.0..=127.0, N * 2) .into_shape_with_order([X, Y * 2]) .unwrap(); bench.iter(|| a.fold_axis(Axis(0), 0., |&acc, &elt| acc + elt)); diff --git a/benches/numeric.rs b/benches/numeric.rs index e447ddf77..5dcde52d4 100644 --- a/benches/numeric.rs +++ b/benches/numeric.rs @@ -13,7 +13,7 @@ const Y: usize = 16; #[bench] fn clip(bench: &mut Bencher) { - let mut a = Array::linspace(0.0..127.0, N * 2) + let mut a = Array::linspace(0.0..=127.0, N * 2) .into_shape_with_order([X, Y * 2]) .unwrap(); let min = 2.; diff --git a/examples/sort-axis.rs b/examples/sort-axis.rs index 26292bad8..112abfc77 100644 --- a/examples/sort-axis.rs +++ b/examples/sort-axis.rs @@ -169,7 +169,7 @@ where D: Dimension #[cfg(feature = "std")] fn main() { - let a = Array::linspace(0.0..63.0, 64) + let a = Array::linspace(0.0..=63.0, 64) .into_shape_with_order((8, 8)) .unwrap(); let strings = a.map(|x| x.to_string()); diff --git a/src/parallel/mod.rs b/src/parallel/mod.rs index f99177c3a..3ac0d4b04 100644 --- a/src/parallel/mod.rs +++ b/src/parallel/mod.rs @@ -65,7 +65,7 @@ //! use ndarray::Axis; //! use ndarray::parallel::prelude::*; //! -//! let a = Array::linspace(0.0..63.0, 64).into_shape_with_order((4, 16)).unwrap(); +//! let a = Array::linspace(0.0..=63.0, 64).into_shape_with_order((4, 16)).unwrap(); //! let mut sums = Vec::new(); //! a.axis_iter(Axis(0)) //! .into_par_iter() @@ -84,7 +84,7 @@ //! use ndarray::Axis; //! use ndarray::parallel::prelude::*; //! -//! let a = Array::linspace(0.0..63.0, 64).into_shape_with_order((4, 16)).unwrap(); +//! let a = Array::linspace(0.0..=63.0, 64).into_shape_with_order((4, 16)).unwrap(); //! let mut shapes = Vec::new(); //! a.axis_chunks_iter(Axis(0), 3) //! .into_par_iter() diff --git a/tests/par_azip.rs b/tests/par_azip.rs index dd00059c1..7dd233e5e 100644 --- a/tests/par_azip.rs +++ b/tests/par_azip.rs @@ -41,7 +41,7 @@ fn test_par_azip3() *a += b / 10.; *c = a.sin(); }); - let res = Array::linspace(0.0..3.1, 32).mapv_into(f32::sin); + let res = Array::linspace(0.0..=3.1, 32).mapv_into(f32::sin); assert_abs_diff_eq!(res, ArrayView::from(&c), epsilon = 1e-4); } diff --git a/tests/par_rayon.rs b/tests/par_rayon.rs index 3dbf9bd9c..1b6b2b794 100644 --- a/tests/par_rayon.rs +++ b/tests/par_rayon.rs @@ -26,7 +26,7 @@ fn test_axis_iter() fn test_axis_iter_mut() { use approx::assert_abs_diff_eq; - let mut a = Array::linspace(0.0..1.0f64, M * N) + let mut a = Array::linspace(0.0..=1.0f64, M * N) .into_shape_with_order((M, N)) .unwrap(); let b = a.mapv(|x| x.exp()); @@ -82,7 +82,7 @@ fn test_axis_chunks_iter() fn test_axis_chunks_iter_mut() { use approx::assert_abs_diff_eq; - let mut a = Array::linspace(0.0..1.0f64, M * N) + let mut a = Array::linspace(0.0..=1.0f64, M * N) .into_shape_with_order((M, N)) .unwrap(); let b = a.mapv(|x| x.exp());