1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//! Heap-allocated array implementation of Grid3.

use crate::{
    range::Range0To,
    grid3::*,
};
use mint::Vector3;

/// Heap-allocated array implementation of Grid3.
pub struct ArrayGrid3<T> {
    alloc: Box<[T]>,
    x_len: i32,
    y_len: i32,
    z_len: i32,
}

impl<T> ArrayGrid3<T> {
    pub fn new<I, F>(x_len: i32, y_len: i32, z_len: i32, mut startval: F) -> Self
    where
        I: From<Vector3<i32>>,
        F: FnMut(I) -> T
    {
        assert!(x_len >= 0);
        assert!(y_len >= 0);
        assert!(z_len >= 0);
        
        let len = x_len * y_len * z_len;
        let mut v: Vec<T> = Vec::with_capacity(len as usize);
        for z in 0..z_len {
            for y in 0..y_len {
                for x in 0..x_len {
                    let item = startval(I::from(Vector3 { x, y, z }));
                    v.push(item);
                }
            }
        }
        ArrayGrid3 {
            alloc: v.into_boxed_slice(),
            x_len,
            y_len,
            z_len,
        }
    }
    
    pub fn broadcast(x_len: i32, y_len: i32, z_len: i32, startval: T) -> Self
    where
        T: Clone 
    {
        Self::new(x_len, y_len, z_len, |_: Vector3<i32>| startval.clone())
    }
    
    fn inner_index(&self, x: i32, y: i32, z: i32) -> Option<i32> {
        if x < 0 || x >= self.x_len || y < 0 || y >= self.y_len || z < 0 || z >= self.z_len {
            None
        } else {
            Some(z * self.x_len * self.y_len + y * self.x_len + x)
        }
    }
}

impl<T> Grid3 for ArrayGrid3<T> {
    type Item = T;
    type XBound = Range0To;
    type YBound = Range0To;
    type ZBound = Range0To;
    
    fn x_bound(&self) -> Range0To {
        Range0To { end: self.x_len }
    }
    
    fn y_bound(&self) -> Range0To {
        Range0To { end: self.y_len }
    }
    
    fn z_bound(&self) -> Range0To {
        Range0To { end: self.z_len }
    }
}

impl<T> Grid3Len for ArrayGrid3<T> {}

impl<T> Grid3Ref for ArrayGrid3<T> {
    fn idx<I>(&self, coord: I) -> &Self::Item
    where
        I: Into<Vector3<i32>>
    {
        let coord = coord.into();
        let Vector3 { x, y, z } = coord;
        let option = self
            .inner_index(x, y, z)
            .map(|i| &self.alloc[i as usize]);
        match option {
            Some(o) => o,
            None => panic!("invalid index {:?}", coord),
        }
    }
}

impl<T> Grid3Mut for ArrayGrid3<T> {
    fn midx<I>(&mut self, coord: I) -> &mut Self::Item
    where
        I: Into<Vector3<i32>>
    {
        let coord = coord.into();
        let Vector3 { x, y, z } = coord;
        let option = self
            .inner_index(x, y, z)
            .map(move |i| &mut self.alloc[i as usize]);
        match option {
            Some(o) => o,
            None => panic!("invalid index {:?}", coord),
        }
    }
}

impl<T: Clone> Grid3Get for ArrayGrid3<T> {
    fn get<I: Into<Vector3<i32>>>(&self, coord: I) -> Self::Item 
    { self.idx(coord).clone() }
}

impl<T> Grid3Set for ArrayGrid3<T> {
    fn set<I: Into<Vector3<i32>>>(&mut self, coord: I, elem: Self::Item) 
    { *self.midx(coord) = elem; }
}