Skip to content

Commit fd67f70

Browse files
authored
Change linspace to take a range argument. (#1580)
This is a breaking change, since it alters the arguments of `linspace` rather than adding a new function. Closes #1169
1 parent 1daa82f commit fd67f70

File tree

16 files changed

+117
-52
lines changed

16 files changed

+117
-52
lines changed

README-quick-start.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ fn main() {
9191
use ndarray::prelude::*;
9292
use ndarray::{Array, Ix3};
9393
fn main() {
94-
let a = Array::<f64, _>::linspace(0., 5., 11);
94+
let a = Array::<f64, _>::linspace(0.0..=5.0, 11);
9595
println!("{:?}", a);
9696
}
9797
```

benches/bench1.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -984,7 +984,7 @@ const MEAN_SUM_N: usize = 127;
984984
fn range_mat(m: Ix, n: Ix) -> Array2<f32>
985985
{
986986
assert!(m * n != 0);
987-
Array::linspace(0., (m * n - 1) as f32, m * n)
987+
Array::linspace(0.0..=(m * n - 1) as f32, m * n)
988988
.into_shape_with_order((m, n))
989989
.unwrap()
990990
}

benches/construct.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ fn zeros_f64(bench: &mut Bencher)
2121
#[bench]
2222
fn map_regular(bench: &mut test::Bencher)
2323
{
24-
let a = Array::linspace(0., 127., 128)
24+
let a = Array::linspace(0.0..=127.0, 128)
2525
.into_shape_with_order((8, 16))
2626
.unwrap();
2727
bench.iter(|| a.map(|&x| 2. * x));
@@ -31,7 +31,7 @@ fn map_regular(bench: &mut test::Bencher)
3131
#[bench]
3232
fn map_stride(bench: &mut test::Bencher)
3333
{
34-
let a = Array::linspace(0., 127., 256)
34+
let a = Array::linspace(0.0..=127.0, 256)
3535
.into_shape_with_order((8, 32))
3636
.unwrap();
3737
let av = a.slice(s![.., ..;2]);

benches/higher-order.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const Y: usize = 16;
1414
#[bench]
1515
fn map_regular(bench: &mut Bencher)
1616
{
17-
let a = Array::linspace(0., 127., N)
17+
let a = Array::linspace(0.0..=127.0, N)
1818
.into_shape_with_order((X, Y))
1919
.unwrap();
2020
bench.iter(|| a.map(|&x| 2. * x));
@@ -29,7 +29,7 @@ pub fn double_array(mut a: ArrayViewMut2<'_, f64>)
2929
#[bench]
3030
fn map_stride_double_f64(bench: &mut Bencher)
3131
{
32-
let mut a = Array::linspace(0., 127., N * 2)
32+
let mut a = Array::linspace(0.0..=127.0, N * 2)
3333
.into_shape_with_order([X, Y * 2])
3434
.unwrap();
3535
let mut av = a.slice_mut(s![.., ..;2]);
@@ -42,7 +42,7 @@ fn map_stride_double_f64(bench: &mut Bencher)
4242
#[bench]
4343
fn map_stride_f64(bench: &mut Bencher)
4444
{
45-
let a = Array::linspace(0., 127., N * 2)
45+
let a = Array::linspace(0.0..=127.0, N * 2)
4646
.into_shape_with_order([X, Y * 2])
4747
.unwrap();
4848
let av = a.slice(s![.., ..;2]);
@@ -53,7 +53,7 @@ fn map_stride_f64(bench: &mut Bencher)
5353
#[bench]
5454
fn map_stride_u32(bench: &mut Bencher)
5555
{
56-
let a = Array::linspace(0., 127., N * 2)
56+
let a = Array::linspace(0.0..=127.0, N * 2)
5757
.into_shape_with_order([X, Y * 2])
5858
.unwrap();
5959
let b = a.mapv(|x| x as u32);
@@ -65,7 +65,7 @@ fn map_stride_u32(bench: &mut Bencher)
6565
#[bench]
6666
fn fold_axis(bench: &mut Bencher)
6767
{
68-
let a = Array::linspace(0., 127., N * 2)
68+
let a = Array::linspace(0.0..=127.0, N * 2)
6969
.into_shape_with_order([X, Y * 2])
7070
.unwrap();
7171
bench.iter(|| a.fold_axis(Axis(0), 0., |&acc, &elt| acc + elt));

benches/iter.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ fn iter_sum_2d_transpose(bench: &mut Bencher)
4747
#[bench]
4848
fn iter_filter_sum_2d_u32(bench: &mut Bencher)
4949
{
50-
let a = Array::linspace(0., 1., 256)
50+
let a = Array::linspace(0.0..=1.0, 256)
5151
.into_shape_with_order((16, 16))
5252
.unwrap();
5353
let b = a.mapv(|x| (x * 100.) as u32);
@@ -58,7 +58,7 @@ fn iter_filter_sum_2d_u32(bench: &mut Bencher)
5858
#[bench]
5959
fn iter_filter_sum_2d_f32(bench: &mut Bencher)
6060
{
61-
let a = Array::linspace(0., 1., 256)
61+
let a = Array::linspace(0.0..=1.0, 256)
6262
.into_shape_with_order((16, 16))
6363
.unwrap();
6464
let b = a * 100.;
@@ -69,7 +69,7 @@ fn iter_filter_sum_2d_f32(bench: &mut Bencher)
6969
#[bench]
7070
fn iter_filter_sum_2d_stride_u32(bench: &mut Bencher)
7171
{
72-
let a = Array::linspace(0., 1., 256)
72+
let a = Array::linspace(0.0..=1.0, 256)
7373
.into_shape_with_order((16, 16))
7474
.unwrap();
7575
let b = a.mapv(|x| (x * 100.) as u32);
@@ -81,7 +81,7 @@ fn iter_filter_sum_2d_stride_u32(bench: &mut Bencher)
8181
#[bench]
8282
fn iter_filter_sum_2d_stride_f32(bench: &mut Bencher)
8383
{
84-
let a = Array::linspace(0., 1., 256)
84+
let a = Array::linspace(0.0..=1.0, 256)
8585
.into_shape_with_order((16, 16))
8686
.unwrap();
8787
let b = a * 100.;
@@ -93,7 +93,7 @@ fn iter_filter_sum_2d_stride_f32(bench: &mut Bencher)
9393
#[bench]
9494
fn iter_rev_step_by_contiguous(bench: &mut Bencher)
9595
{
96-
let a = Array::linspace(0., 1., 512);
96+
let a = Array::linspace(0.0..=1.0, 512);
9797
bench.iter(|| {
9898
a.iter().rev().step_by(2).for_each(|x| {
9999
black_box(x);
@@ -105,7 +105,7 @@ fn iter_rev_step_by_contiguous(bench: &mut Bencher)
105105
#[bench]
106106
fn iter_rev_step_by_discontiguous(bench: &mut Bencher)
107107
{
108-
let mut a = Array::linspace(0., 1., 1024);
108+
let mut a = Array::linspace(0.0..=1.0, 1024);
109109
a.slice_axis_inplace(Axis(0), Slice::new(0, None, 2));
110110
bench.iter(|| {
111111
a.iter().rev().step_by(2).for_each(|x| {

benches/numeric.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const Y: usize = 16;
1313
#[bench]
1414
fn clip(bench: &mut Bencher)
1515
{
16-
let mut a = Array::linspace(0., 127., N * 2)
16+
let mut a = Array::linspace(0.0..=127.0, N * 2)
1717
.into_shape_with_order([X, Y * 2])
1818
.unwrap();
1919
let min = 2.;

examples/sort-axis.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ where D: Dimension
169169
#[cfg(feature = "std")]
170170
fn main()
171171
{
172-
let a = Array::linspace(0., 63., 64)
172+
let a = Array::linspace(0.0..=63.0, 64)
173173
.into_shape_with_order((8, 8))
174174
.unwrap();
175175
let strings = a.map(|x| x.to_string());

src/doc/ndarray_for_numpy_users/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,8 @@
195195
//! ------|-----------|------
196196
//! `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
197197
//! `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`
198-
//! `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.`
199-
//! `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.`
198+
//! `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.`
199+
//! `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.`
200200
//! `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.`
201201
//! `np.ones((3, 4, 5))` | [`Array::ones((3, 4, 5))`][::ones()] | create a 3×4×5 array filled with ones (inferring the element type)
202202
//! `np.zeros((3, 4, 5))` | [`Array::zeros((3, 4, 5))`][::zeros()] | create a 3×4×5 array filled with zeros (inferring the element type)

src/finite_bounds.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use num_traits::Float;
2+
3+
pub enum Bound<F>
4+
{
5+
Included(F),
6+
Excluded(F),
7+
}
8+
9+
/// A version of std::ops::RangeBounds that only implements a..b and a..=b ranges.
10+
pub trait FiniteBounds<F>
11+
{
12+
fn start_bound(&self) -> F;
13+
fn end_bound(&self) -> Bound<F>;
14+
}
15+
16+
impl<F> FiniteBounds<F> for std::ops::Range<F>
17+
where F: Float
18+
{
19+
fn start_bound(&self) -> F
20+
{
21+
self.start
22+
}
23+
24+
fn end_bound(&self) -> Bound<F>
25+
{
26+
Bound::Excluded(self.end)
27+
}
28+
}
29+
30+
impl<F> FiniteBounds<F> for std::ops::RangeInclusive<F>
31+
where F: Float
32+
{
33+
fn start_bound(&self) -> F
34+
{
35+
*self.start()
36+
}
37+
38+
fn end_bound(&self) -> Bound<F>
39+
{
40+
Bound::Included(*self.end())
41+
}
42+
}

src/impl_constructors.rs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,7 @@ where S: DataOwned<Elem = A>
5858
pub fn from_vec(v: Vec<A>) -> Self
5959
{
6060
if mem::size_of::<A>() == 0 {
61-
assert!(
62-
v.len() <= isize::MAX as usize,
63-
"Length must fit in `isize`.",
64-
);
61+
assert!(v.len() <= isize::MAX as usize, "Length must fit in `isize`.",);
6562
}
6663
unsafe { Self::from_shape_vec_unchecked(v.len() as Ix, v) }
6764
}
@@ -95,14 +92,16 @@ where S: DataOwned<Elem = A>
9592
/// ```rust
9693
/// use ndarray::{Array, arr1};
9794
///
98-
/// let array = Array::linspace(0., 1., 5);
95+
/// let array = Array::linspace(0.0..=1.0, 5);
9996
/// assert!(array == arr1(&[0.0, 0.25, 0.5, 0.75, 1.0]))
10097
/// ```
10198
#[cfg(feature = "std")]
102-
pub fn linspace(start: A, end: A, n: usize) -> Self
103-
where A: Float
99+
pub fn linspace<R>(range: R, n: usize) -> Self
100+
where
101+
R: crate::finite_bounds::FiniteBounds<A>,
102+
A: Float,
104103
{
105-
Self::from(to_vec(linspace::linspace(start, end, n)))
104+
Self::from(to_vec(linspace::linspace(range, n)))
106105
}
107106

108107
/// Create a one-dimensional array with elements from `start` to `end`
@@ -137,18 +136,20 @@ where S: DataOwned<Elem = A>
137136
/// use approx::assert_abs_diff_eq;
138137
/// use ndarray::{Array, arr1};
139138
///
140-
/// let array = Array::logspace(10.0, 0.0, 3.0, 4);
139+
/// let array = Array::logspace(10.0, 0.0..=3.0, 4);
141140
/// assert_abs_diff_eq!(array, arr1(&[1e0, 1e1, 1e2, 1e3]), epsilon = 1e-12);
142141
///
143-
/// let array = Array::logspace(-10.0, 3.0, 0.0, 4);
142+
/// let array = Array::logspace(-10.0, 3.0..=0.0, 4);
144143
/// assert_abs_diff_eq!(array, arr1(&[-1e3, -1e2, -1e1, -1e0]), epsilon = 1e-12);
145144
/// # }
146145
/// ```
147146
#[cfg(feature = "std")]
148-
pub fn logspace(base: A, start: A, end: A, n: usize) -> Self
149-
where A: Float
147+
pub fn logspace<R>(base: A, range: R, n: usize) -> Self
148+
where
149+
R: crate::finite_bounds::FiniteBounds<A>,
150+
A: Float,
150151
{
151-
Self::from(to_vec(logspace::logspace(base, start, end, n)))
152+
Self::from(to_vec(logspace::logspace(base, range, n)))
152153
}
153154

154155
/// Create a one-dimensional array with `n` geometrically spaced elements

0 commit comments

Comments
 (0)