Skip to content

Commit 81b5e02

Browse files
committed
Major rewrite
The old implementation was unsound in cases, so this is a significantly stripped down version with no unsafe code.
1 parent 2aa45dc commit 81b5e02

File tree

4 files changed

+251
-554
lines changed

4 files changed

+251
-554
lines changed

src/array.rs

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
use std::slice;
2+
use std::vec;
3+
4+
use Dimension;
5+
6+
#[derive(Debug, PartialEq, Eq, Clone)]
7+
pub struct Array<T> {
8+
dims: Vec<Dimension>,
9+
data: Vec<T>,
10+
}
11+
12+
impl<T> Array<T> {
13+
pub fn from_parts(data: Vec<T>, dimensions: Vec<Dimension>) -> Array<T> {
14+
assert!((data.is_empty() && dimensions.is_empty()) ||
15+
data.len() == dimensions.iter().fold(1, |acc, i| acc * i.len),
16+
"size mismatch");
17+
Array {
18+
dims: dimensions,
19+
data: data,
20+
}
21+
}
22+
23+
pub fn from_vec(data: Vec<T>, lower_bound: isize) -> Array<T> {
24+
Array {
25+
dims: vec![Dimension {
26+
len: data.len(),
27+
lower_bound: lower_bound
28+
}],
29+
data: data,
30+
}
31+
}
32+
33+
pub fn wrap(&mut self, lower_bound: isize) {
34+
self.dims.insert(0, Dimension {
35+
len: 1,
36+
lower_bound: lower_bound,
37+
});
38+
}
39+
40+
pub fn push(&mut self, other: Array<T>) {
41+
assert!(self.dims.len() - 1 == other.dims.len(),
42+
"cannot append differently shaped arrays");
43+
for (dim1, dim2) in self.dims.iter().skip(1).zip(other.dims.iter()) {
44+
assert!(dim1 == dim2, "cannot append differently shaped arrays");
45+
}
46+
self.dims[0].len += 1;
47+
self.data.extend(other.data);
48+
}
49+
50+
pub fn dimensions(&self) -> &[Dimension] {
51+
&self.dims
52+
}
53+
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+
64+
fn shift_idx(&self, indices: &[isize]) -> usize {
65+
assert_eq!(self.dims.len(), indices.len());
66+
self.dims
67+
.iter()
68+
.zip(indices.iter().cloned())
69+
.fold((0, 1), |(acc, stride), (dim, idx)| {
70+
let shifted = dim.shift(idx);
71+
(acc * stride + shifted, dim.len)
72+
})
73+
.0
74+
}
75+
76+
pub fn iter<'a>(&'a self) -> Iter<'a, T> {
77+
Iter {
78+
inner: self.data.iter(),
79+
}
80+
}
81+
82+
pub fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T> {
83+
IterMut {
84+
inner: self.data.iter_mut(),
85+
}
86+
}
87+
}
88+
89+
impl<'a, T: 'a> IntoIterator for &'a Array<T> {
90+
type Item = &'a T;
91+
type IntoIter = Iter<'a, T>;
92+
93+
fn into_iter(self) -> Iter<'a, T> {
94+
self.iter()
95+
}
96+
}
97+
98+
impl<'a, T: 'a> IntoIterator for &'a mut Array<T> {
99+
type Item = &'a mut T;
100+
type IntoIter = IterMut<'a, T>;
101+
102+
fn into_iter(self) -> IterMut<'a, T> {
103+
self.iter_mut()
104+
}
105+
}
106+
107+
impl<T> IntoIterator for Array<T> {
108+
type Item = T;
109+
type IntoIter = IntoIter<T>;
110+
111+
fn into_iter(self) -> IntoIter<T> {
112+
IntoIter {
113+
inner: self.data.into_iter()
114+
}
115+
}
116+
}
117+
118+
/// An iterator over references to values of an `ArrayBase` in the
119+
/// higher-dimensional equivalent of row-major order.
120+
pub struct Iter<'a, T: 'a> {
121+
inner: slice::Iter<'a, T>,
122+
}
123+
124+
impl<'a, T: 'a> Iterator for Iter<'a, T> {
125+
type Item = &'a T;
126+
127+
fn next(&mut self) -> Option<&'a T> {
128+
self.inner.next()
129+
}
130+
}
131+
132+
impl<'a, T: 'a> DoubleEndedIterator for Iter<'a, T> {
133+
fn next_back(&mut self) -> Option<&'a T> {
134+
self.inner.next_back()
135+
}
136+
}
137+
138+
/// An iterator over mutable references to values of an `ArrayBase` in the
139+
/// higher-dimensional equivalent of row-major order.
140+
pub struct IterMut<'a, T: 'a> {
141+
inner: slice::IterMut<'a, T>,
142+
}
143+
144+
impl<'a, T: 'a> Iterator for IterMut<'a, T> {
145+
type Item = &'a mut T;
146+
147+
fn next(&mut self) -> Option<&'a mut T> {
148+
self.inner.next()
149+
}
150+
}
151+
152+
impl<'a, T: 'a> DoubleEndedIterator for IterMut<'a, T> {
153+
fn next_back(&mut self) -> Option<&'a mut T> {
154+
self.inner.next_back()
155+
}
156+
}
157+
158+
/// An iterator over values of an `ArrayBase` in the higher-dimensional
159+
/// equivalent of row-major order.
160+
pub struct IntoIter<T> {
161+
inner: vec::IntoIter<T>,
162+
}
163+
164+
impl<T> Iterator for IntoIter<T> {
165+
type Item = T;
166+
167+
fn next(&mut self) -> Option<T> {
168+
self.inner.next()
169+
}
170+
}
171+
172+
impl<T> DoubleEndedIterator for IntoIter<T> {
173+
fn next_back(&mut self) -> Option<T> {
174+
self.inner.next_back()
175+
}
176+
}

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