1
+ use std:: ops:: { Index , IndexMut } ;
1
2
use std:: slice;
2
3
use std:: vec;
3
4
4
5
use Dimension ;
5
6
7
+ /// A multi-dimensional array.
6
8
#[ derive( Debug , PartialEq , Eq , Clone ) ]
7
9
pub struct Array < T > {
8
10
dims : Vec < Dimension > ,
9
11
data : Vec < T > ,
10
12
}
11
13
12
14
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.
13
24
pub fn from_parts ( data : Vec < T > , dimensions : Vec < Dimension > ) -> Array < T > {
14
25
assert ! ( ( data. is_empty( ) && dimensions. is_empty( ) ) ||
15
26
data. len( ) == dimensions. iter( ) . fold( 1 , |acc, i| acc * i. len) ,
@@ -20,6 +31,7 @@ impl<T> Array<T> {
20
31
}
21
32
}
22
33
34
+ /// Creates a new one-dimensional array.
23
35
pub fn from_vec ( data : Vec < T > , lower_bound : isize ) -> Array < T > {
24
36
Array {
25
37
dims : vec ! [ Dimension {
@@ -30,13 +42,30 @@ impl<T> Array<T> {
30
42
}
31
43
}
32
44
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]]`.
33
49
pub fn wrap ( & mut self , lower_bound : isize ) {
34
50
self . dims . insert ( 0 , Dimension {
35
51
len : 1 ,
36
52
lower_bound : lower_bound,
37
53
} ) ;
38
54
}
39
55
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.
40
69
pub fn push ( & mut self , other : Array < T > ) {
41
70
assert ! ( self . dims. len( ) - 1 == other. dims. len( ) ,
42
71
"cannot append differently shaped arrays" ) ;
@@ -47,20 +76,11 @@ impl<T> Array<T> {
47
76
self . data . extend ( other. data ) ;
48
77
}
49
78
79
+ /// Returns the dimensions of this array.
50
80
pub fn dimensions ( & self ) -> & [ Dimension ] {
51
81
& self . dims
52
82
}
53
83
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
84
fn shift_idx ( & self , indices : & [ isize ] ) -> usize {
65
85
assert_eq ! ( self . dims. len( ) , indices. len( ) ) ;
66
86
self . dims
@@ -86,6 +106,61 @@ impl<T> Array<T> {
86
106
}
87
107
}
88
108
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
+
89
164
impl < ' a , T : ' a > IntoIterator for & ' a Array < T > {
90
165
type Item = & ' a T ;
91
166
type IntoIter = Iter < ' a , T > ;
0 commit comments