Skip to content

Commit 00eba67

Browse files
committed
Some docs and setup Index impls
Index is heavily overloaded for convenience.
1 parent 81b5e02 commit 00eba67

File tree

2 files changed

+105
-30
lines changed

2 files changed

+105
-30
lines changed

src/array.rs

Lines changed: 85 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,26 @@
1+
use std::ops::{Index, IndexMut};
12
use std::slice;
23
use std::vec;
34

45
use Dimension;
56

7+
/// A multi-dimensional array.
68
#[derive(Debug, PartialEq, Eq, Clone)]
79
pub struct Array<T> {
810
dims: Vec<Dimension>,
911
data: Vec<T>,
1012
}
1113

1214
impl<T> Array<T> {
15+
/// Creates a new `Array` from its underlying components.
16+
///
17+
/// The data array should be provided in the higher-dimensional equivalent
18+
/// of row-major order.
19+
///
20+
/// # Panics
21+
///
22+
/// Panics if the number of elements provided does not match the number of
23+
/// elements specified by the dimensions.
1324
pub fn from_parts(data: Vec<T>, dimensions: Vec<Dimension>) -> Array<T> {
1425
assert!((data.is_empty() && dimensions.is_empty()) ||
1526
data.len() == dimensions.iter().fold(1, |acc, i| acc * i.len),
@@ -20,6 +31,7 @@ impl<T> Array<T> {
2031
}
2132
}
2233

34+
/// Creates a new one-dimensional array.
2335
pub fn from_vec(data: Vec<T>, lower_bound: isize) -> Array<T> {
2436
Array {
2537
dims: vec![Dimension {
@@ -30,13 +42,30 @@ impl<T> Array<T> {
3042
}
3143
}
3244

45+
/// Wraps this array in a new dimension of size 1.
46+
///
47+
/// For example, the one dimensional array `[1, 2]` would turn into the
48+
/// two-dimensional array `[[1, 2]]`.
3349
pub fn wrap(&mut self, lower_bound: isize) {
3450
self.dims.insert(0, Dimension {
3551
len: 1,
3652
lower_bound: lower_bound,
3753
});
3854
}
3955

56+
/// Consumes another array, appending it to the top level dimension of this
57+
/// array.
58+
///
59+
/// The dimensions of the other array must be the same as the dimensions
60+
/// of this array with the first dimension removed. This includes lower
61+
/// bounds as well as lengths.
62+
///
63+
/// For example, if `[3, 4]` is pushed onto `[[1, 2]]`, the result is
64+
/// `[[1, 2], [3, 4]]`.
65+
///
66+
/// # Panics
67+
///
68+
/// Panics if the dimensions of the two arrays do not match.
4069
pub fn push(&mut self, other: Array<T>) {
4170
assert!(self.dims.len() - 1 == other.dims.len(),
4271
"cannot append differently shaped arrays");
@@ -47,20 +76,11 @@ impl<T> Array<T> {
4776
self.data.extend(other.data);
4877
}
4978

79+
/// Returns the dimensions of this array.
5080
pub fn dimensions(&self) -> &[Dimension] {
5181
&self.dims
5282
}
5383

54-
pub fn get(&self, indices: &[isize]) -> &T {
55-
let idx = self.shift_idx(indices);
56-
&self.data[idx]
57-
}
58-
59-
pub fn get_mut(&mut self, indices: &[isize]) -> &mut T {
60-
let idx = self.shift_idx(indices);
61-
&mut self.data[idx]
62-
}
63-
6484
fn shift_idx(&self, indices: &[isize]) -> usize {
6585
assert_eq!(self.dims.len(), indices.len());
6686
self.dims
@@ -86,6 +106,61 @@ impl<T> Array<T> {
86106
}
87107
}
88108

109+
pub trait ArrayIndex {
110+
fn index<T>(&self, array: &Array<T>) -> usize;
111+
}
112+
113+
impl<'a> ArrayIndex for &'a [isize] {
114+
fn index<T>(&self, array: &Array<T>) -> usize {
115+
array.shift_idx(*self)
116+
}
117+
}
118+
119+
impl ArrayIndex for isize {
120+
fn index<T>(&self, array: &Array<T>) -> usize {
121+
let slice: &[isize] = &[*self];
122+
ArrayIndex::index(&slice, array)
123+
}
124+
}
125+
126+
macro_rules! tuple_impl {
127+
($($name:ident : $t:ty),+) => {
128+
impl ArrayIndex for ($($t,)+) {
129+
fn index<T>(&self, array: &Array<T>) -> usize {
130+
let ($($name,)+) = *self;
131+
let slice: &[isize] = &[$($name),+];
132+
ArrayIndex::index(&slice, array)
133+
}
134+
}
135+
}
136+
}
137+
138+
tuple_impl!(a: isize);
139+
tuple_impl!(a: isize, b: isize);
140+
tuple_impl!(a: isize, b: isize, c: isize);
141+
tuple_impl!(a: isize, b: isize, c: isize, d: isize);
142+
tuple_impl!(a: isize, b: isize, c: isize, d: isize, e: isize);
143+
tuple_impl!(a: isize, b: isize, c: isize, d: isize, e: isize, f: isize);
144+
tuple_impl!(a: isize, b: isize, c: isize, d: isize, e: isize, f: isize, g: isize);
145+
tuple_impl!(a: isize, b: isize, c: isize, d: isize, e: isize, f: isize, g: isize, h: isize);
146+
tuple_impl!(a: isize, b: isize, c: isize, d: isize, e: isize, f: isize, g: isize, h: isize, i: isize);
147+
148+
impl<T, I: ArrayIndex> Index<I> for Array<T> {
149+
type Output = T;
150+
151+
fn index(&self, idx: I) -> &T {
152+
let idx = idx.index(self);
153+
&self.data[idx]
154+
}
155+
}
156+
157+
impl<T, I: ArrayIndex> IndexMut<I> for Array<T> {
158+
fn index_mut(&mut self, idx: I) -> &mut T {
159+
let idx = idx.index(self);
160+
&mut self.data[idx]
161+
}
162+
}
163+
89164
impl<'a, T: 'a> IntoIterator for &'a Array<T> {
90165
type Item = &'a T;
91166
type IntoIter = Iter<'a, T>;

src/lib.rs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,18 @@ mod tests {
3939
let a = Array::from_vec(vec!(0i32, 1, 2), -1);
4040
assert!(&[Dimension { len: 3, lower_bound: -1 }][..] ==
4141
a.dimensions());
42-
assert_eq!(&0, a.get(&[-1]));
43-
assert_eq!(&1, a.get(&[0]));
44-
assert_eq!(&2, a.get(&[1]));
42+
assert_eq!(0, a[-1]);
43+
assert_eq!(1, a[0]);
44+
assert_eq!(2, a[1]);
4545
}
4646

4747
#[test]
4848
fn test_2d_slice_get() {
4949
let mut a = Array::from_vec(vec!(0i32, 1, 2), -1);
5050
a.wrap(1);
51-
assert_eq!(&0, a.get(&[1, -1]));
52-
assert_eq!(&1, a.get(&[1, 0]));
53-
assert_eq!(&2, a.get(&[1, 1]));
51+
assert_eq!(0, a[(1, -1)]);
52+
assert_eq!(1, a[(1, 0)]);
53+
assert_eq!(2, a[(1, 1)]);
5454
}
5555

5656
#[test]
@@ -83,10 +83,10 @@ mod tests {
8383
let mut a = Array::from_vec(vec!(1i32, 2), 0);
8484
a.wrap(0);
8585
a.push(Array::from_vec(vec!(3, 4), 0));
86-
assert_eq!(&1, a.get(&[0, 0]));
87-
assert_eq!(&2, a.get(&[0, 1]));
88-
assert_eq!(&3, a.get(&[1, 0]));
89-
assert_eq!(&4, a.get(&[1, 1]));
86+
assert_eq!(1, a[(0, 0)]);
87+
assert_eq!(2, a[(0, 1)]);
88+
assert_eq!(3, a[(1, 0)]);
89+
assert_eq!(4, a[(1, 1)]);
9090
}
9191

9292
#[test]
@@ -99,21 +99,21 @@ mod tests {
9999
b.wrap(0);
100100
b.push(Array::from_vec(vec!(6, 7), 0));
101101
a.push(b);
102-
assert_eq!(&0, a.get(&[0, 0, 0]));
103-
assert_eq!(&1, a.get(&[0, 0, 1]));
104-
assert_eq!(&2, a.get(&[0, 1, 0]));
105-
assert_eq!(&3, a.get(&[0, 1, 1]));
106-
assert_eq!(&4, a.get(&[1, 0, 0]));
107-
assert_eq!(&5, a.get(&[1, 0, 1]));
108-
assert_eq!(&6, a.get(&[1, 1, 0]));
109-
assert_eq!(&7, a.get(&[1, 1, 1]));
102+
assert_eq!(0, a[(0, 0, 0)]);
103+
assert_eq!(1, a[(0, 0, 1)]);
104+
assert_eq!(2, a[(0, 1, 0)]);
105+
assert_eq!(3, a[(0, 1, 1)]);
106+
assert_eq!(4, a[(1, 0, 0)]);
107+
assert_eq!(5, a[(1, 0, 1)]);
108+
assert_eq!(6, a[(1, 1, 0)]);
109+
assert_eq!(7, a[(1, 1, 1)]);
110110
}
111111

112112
#[test]
113113
fn test_mut() {
114114
let mut a = Array::from_vec(vec!(1i32, 2), 0);
115115
a.wrap(0);
116-
*a.get_mut(&[0, 0]) = 3;
117-
assert_eq!(&3, a.get(&[0, 0]));
116+
a[(0, 0)] = 3;
117+
assert_eq!(3, a[(0, 0)]);
118118
}
119119
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy