fera_array/
nested.rs

1use {Array, DynamicArray};
2
3use std::marker::PhantomData;
4use std::ops::{Index, IndexMut};
5
6/// An `Array` implemented as an array of arrays.
7///
8/// It contains a main `Array` of type `M`. Each element (nested array) of the main array is an
9/// `Array` of type `N`. The type of the elements of the nested arrays is `T`.
10///
11/// This type offers a flatted view of the elements in the nested arrays. Each time an element at a
12/// specified index is accessed, the index is decomposed in two indices (using `S: Split`), the
13/// first one is used to index the main array and the second one to index the nested array.
14///
15/// This type is interesting to implemented copy on write arrays. See `CowNestedArray`.
16#[derive(Clone)]
17pub struct NestedArray<T, S, M, N> {
18    len: usize,
19    cap: usize,
20    data: M,
21    split: S,
22    _marker: PhantomData<(T, N)>,
23}
24
25impl<T, S, M, N> NestedArray<T, S, M, N>
26where
27    S: Split,
28    M: Array<N>,
29    N: Array<T>,
30{
31    #[inline]
32    fn max_nested(&self) -> usize {
33        self.split.max_nested()
34    }
35
36    #[inline]
37    fn split(&self, i: usize) -> (usize, usize) {
38        self.split.split(i)
39    }
40
41    #[cfg(test)]
42    fn compute_len(&self) -> usize {
43        self.data.iter().map(|d| d.len()).sum()
44    }
45}
46
47impl<T, S, M, N> Index<usize> for NestedArray<T, S, M, N>
48where
49    S: Split,
50    M: Array<N>,
51    N: Array<T> + Clone,
52{
53    type Output = T;
54
55    #[inline]
56    fn index(&self, index: usize) -> &Self::Output {
57        assert!(index < self.len);
58        unsafe { self.get_unchecked(index) }
59    }
60}
61
62impl<T, S, M, N> IndexMut<usize> for NestedArray<T, S, M, N>
63where
64    S: Split,
65    M: Array<N>,
66    N: Array<T> + Clone,
67{
68    #[inline]
69    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
70        assert!(index < self.len);
71        unsafe { self.get_unchecked_mut(index) }
72    }
73}
74
75impl<T, S, M, N> Array<T> for NestedArray<T, S, M, N>
76where
77    S: Split,
78    M: Array<N>,
79    N: Array<T> + Clone,
80{
81    fn with_value(value: T, n: usize) -> Self
82    where
83        T: Clone,
84    {
85        let s = S::new(n);
86        let max = s.max_nested();
87        let (div, rem) = div_rem(n, max);
88
89        let data = {
90            if n == 0 {
91                M::with_value(N::with_value(value, 0), 0)
92            } else if n < s.max_nested() {
93                M::with_value(N::with_value(value, n), 1)
94            } else if rem == 0 {
95                M::with_value(N::with_value(value, max), div)
96            } else {
97                // FIXME: N is being cloned one extra time
98                let mut data = M::with_value(N::with_value(value.clone(), max), div + 1);
99                // Fix the last element of data which should have rem elements but have max
100                data[div] = N::with_value(value, rem);
101                data
102            }
103        };
104
105        NestedArray {
106            len: n,
107            cap: n,
108            data: data,
109            split: s,
110            _marker: PhantomData,
111        }
112    }
113
114    #[inline]
115    fn len(&self) -> usize {
116        self.len
117    }
118
119    #[inline]
120    unsafe fn get_unchecked(&self, index: usize) -> &T {
121        let (i, j) = self.split(index);
122        self.data.get_unchecked(i).get_unchecked(j)
123    }
124
125    #[inline]
126    unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
127        let (i, j) = self.split(index);
128        self.data.get_unchecked_mut(i).get_unchecked_mut(j)
129    }
130}
131
132impl<T, S, M, N> DynamicArray<T> for NestedArray<T, S, M, N>
133where
134    S: Split,
135    M: DynamicArray<N>,
136    N: DynamicArray<T> + Clone,
137{
138    fn with_capacity(capacity: usize) -> Self
139    where
140        Self: Sized,
141    {
142        let s = S::new(capacity);
143        let max = s.max_nested();
144        let (div, rem) = div_rem(capacity, max);
145
146        let mut data = if rem == 0 {
147            M::with_capacity(div)
148        } else {
149            M::with_capacity(div + 1)
150        };
151
152        let mut cap = 0;
153
154        while cap + max <= capacity {
155            cap += max;
156            data.push(N::with_capacity(max));
157        }
158
159        if rem != 0 {
160            data.push(N::with_capacity(rem));
161        }
162
163        NestedArray {
164            len: 0,
165            cap: capacity,
166            data: data,
167            split: s,
168            _marker: PhantomData,
169        }
170    }
171
172    // TODO: implement reserve
173
174    fn capacity(&self) -> usize {
175        self.cap
176    }
177
178    unsafe fn set_len(&mut self, len: usize) {
179        if self.len == len {
180            return;
181        }
182
183        let (i, j) = self.split(len);
184        let max = self.max_nested();
185        let old = self.data.len();
186
187        if j == 0 {
188            self.data.set_len(i);
189            if i != 0 {
190                self.data[i - 1].set_len(max);
191            }
192        } else {
193            self.data.set_len(i + 1);
194            self.data[i].set_len(j);
195        }
196
197        let new = self.data.len();
198
199        if new != 0 && old < new - 1 {
200            for i in old..new - 1 {
201                self.data[i].set_len(max)
202            }
203        }
204
205        self.len = len;
206    }
207}
208
209/// Describe how to split the indices for a `NestedArray`.
210pub trait Split {
211    /// Creates a new `Split` for a `NestedArray` with `n` elements.
212    fn new(n: usize) -> Self;
213
214    /// Split `index` in two indices (main array, nested array).
215    fn split(&self, index: usize) -> (usize, usize);
216
217    /// Returns the maximum index that can be produced to be used in a nested arrays.
218    fn max_nested(&self) -> usize;
219}
220
221#[derive(Copy, Clone)]
222pub struct SqrtSplit(usize);
223
224impl Split for SqrtSplit {
225    fn new(n: usize) -> Self {
226        SqrtSplit(::std::cmp::max(1, (n as f64).sqrt() as usize))
227    }
228
229    fn split(&self, index: usize) -> (usize, usize) {
230        div_rem(index, self.0)
231    }
232
233    fn max_nested(&self) -> usize {
234        self.0
235    }
236}
237
238#[derive(Copy, Clone)]
239pub struct BalancedShiftSplit(usize);
240
241impl Split for BalancedShiftSplit {
242    fn new(n: usize) -> Self {
243        let mut s = 1;
244
245        while (1 << s) * (1 << s) < n {
246            s += 1;
247        }
248
249        BalancedShiftSplit(s)
250    }
251
252    fn split(&self, index: usize) -> (usize, usize) {
253        (index >> self.0, index & (self.max_nested() - 1))
254    }
255
256    fn max_nested(&self) -> usize {
257        1 << self.0
258    }
259}
260
261fn div_rem(a: usize, b: usize) -> (usize, usize) {
262    (a / b, a % b)
263}
264
265/// Implementations of `Split` using bit shift.
266pub mod shift {
267    use super::Split;
268    macro_rules! def_shift {
269        ($name:ident, $num:expr) => {
270            #[allow(missing_docs)]
271            #[derive(Clone)]
272            pub struct $name;
273
274            impl Split for $name {
275                #[inline]
276                fn new(_n: usize) -> Self {
277                    $name
278                }
279
280                #[inline]
281                fn split(&self, index: usize) -> (usize, usize) {
282                    (index >> $num, index & (self.max_nested() - 1))
283                }
284
285                #[inline]
286                fn max_nested(&self) -> usize {
287                    (1 << $num)
288                }
289            }
290        };
291    }
292
293    macro_rules! def_shifts {
294        ($($name:ident $num:expr)+) => (
295            $(def_shift!{$name, $num})+
296        )
297    }
298
299    def_shifts!{
300        Shift1   1 Shift2   2 Shift3   3 Shift4   4 Shift5   5 Shift6   6 Shift7   7
301        Shift8   8 Shift9   9 Shift10 10 Shift11 11 Shift12 12 Shift13 13 Shift14 14
302        Shift15 15 Shift16 16 Shift17 17 Shift18 18 Shift19 19 Shift20 20 Shift21 21
303        Shift22 22 Shift23 23 Shift24 24 Shift25 25 Shift26 26 Shift27 27 Shift28 28
304        Shift29 29 Shift30 30 Shift31 31
305    }
306
307    #[cfg(target_pointer_width = "64")]
308    def_shifts!{
309        Shift32 32 Shift33 33 Shift34 34 Shift35 35
310        Shift36 36 Shift37 37 Shift38 38 Shift39 39 Shift40 40 Shift41 41 Shift42 42
311        Shift43 43 Shift44 44 Shift45 45 Shift46 46 Shift47 47 Shift48 48 Shift49 49
312        Shift50 50 Shift51 51 Shift52 52 Shift53 53 Shift54 54 Shift55 55 Shift56 56
313        Shift57 57 Shift58 58 Shift59 59 Shift60 60 Shift61 61 Shift62 62 Shift63 63
314    }
315}
316
317#[cfg(test)]
318mod tests {
319    use super::*;
320    use {ArrayTests, BalancedShiftSplit, DynamicArray, DynamicArrayTests, VecArray};
321
322    #[test]
323    fn sqrt_split() {
324        let s = SqrtSplit::new(10);
325        assert_eq!(3, s.max_nested());
326        assert_eq!((0, 0), s.split(0));
327        assert_eq!((0, 1), s.split(1));
328        assert_eq!((0, 2), s.split(2));
329        assert_eq!((1, 0), s.split(3));
330        assert_eq!((1, 1), s.split(4));
331        assert_eq!((2, 0), s.split(6));
332        assert_eq!((3, 0), s.split(9));
333    }
334
335    #[test]
336    fn sqrt_split_zero() {
337        let s = SqrtSplit::new(0);
338        assert_eq!(1, s.max_nested());
339        assert_eq!((0, 0), s.split(0));
340        assert_eq!((1024, 0), s.split(1024));
341    }
342
343    #[test]
344    fn shift_split_zero() {
345        let s = BalancedShiftSplit::new(0);
346        assert_eq!(2, s.max_nested());
347        assert_eq!((0, 0), s.split(0));
348        assert_eq!((512, 0), s.split(1024));
349    }
350
351    #[test]
352    fn shift_split() {
353        let s = BalancedShiftSplit::new(10);
354        assert_eq!(4, s.max_nested());
355        assert_eq!((0, 0), s.split(0));
356        assert_eq!((0, 3), s.split(3));
357        assert_eq!((1, 0), s.split(4));
358        assert_eq!((1, 1), s.split(5));
359        assert_eq!((2, 0), s.split(8));
360        assert_eq!((2, 1), s.split(9));
361    }
362
363    #[test]
364    fn set_len() {
365        let mut v: NestedArray<
366            usize,
367            BalancedShiftSplit,
368            VecArray<VecArray<usize>>,
369            VecArray<usize>,
370        > = NestedArray::with_capacity(14);
371
372        assert_eq!(0, v.len());
373        assert_eq!(0, v.compute_len());
374
375        for i in 0..15 {
376            unsafe {
377                v.set_len(i);
378            }
379            assert_eq!(i, v.len());
380            assert_eq!(i, v.compute_len());
381        }
382
383        for i in 0..15 {
384            unsafe {
385                v.set_len(14 - i);
386            }
387            assert_eq!(14 - i, v.len());
388            assert_eq!(14 - i, v.compute_len());
389        }
390
391        unsafe {
392            v.set_len(13);
393        }
394        assert_eq!(13, v.len());
395        assert_eq!(13, v.compute_len());
396
397        unsafe {
398            v.set_len(5);
399        }
400
401        assert_eq!(5, v.len());
402        assert_eq!(5, v.compute_len());
403    }
404
405    struct T;
406
407    impl ArrayTests for T {
408        type A = NestedArray<usize, BalancedShiftSplit, VecArray<VecArray<usize>>, VecArray<usize>>;
409    }
410
411    delegate_tests!{
412        T,
413        basic_0,
414        basic_001k,
415        basic_100k,
416        clone_001k,
417        clone_100k
418    }
419
420    impl DynamicArrayTests for T {}
421
422    delegate_tests!{
423        T,
424        capacity,
425        push_1k,
426        clone_push
427    }
428
429    #[cfg(all(feature = "nightly", test))]
430    mod benchs {
431        use super::T;
432        use test::Bencher;
433        use ArrayBenchs;
434
435        impl ArrayBenchs for T {}
436
437        delegate_benchs!{
438            T,
439            fold_xor_0001k,
440            fold_xor_0010k,
441            fold_xor_0100k,
442            fold_xor_1000k,
443            clone_change_0001k,
444            clone_change_0010k,
445            clone_change_0100k,
446            clone_change_1000k
447        }
448    }
449}