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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
mod iterators;
mod nalgebra;
mod spatial;

use bitvec::bitvec;

use crate::errors::TpnTreeError;
pub use spatial::SpatialTree;
pub use spatial::Tree3D;

#[derive(Debug, Clone)]
pub struct TpnTree<T, const N: usize> {
    /// Coordinates of the N-dimensional hyperrectangle center.
    coordinates: [f64; N],
    /// Length of the normals from center of N-dimensional hyperrectangle to its faces.
    span: [f64; N],
    /// Height in tree.
    level: usize,
    /// There are zero or 2^N children, one times two per axis.
    children: Vec<Self>,
    /// Any potential data the tree might hold.
    data: Option<T>,
}

impl<T, const N: usize> TpnTree<T, N> {
    /// Creates a new TpnTree.
    ///
    /// Use this function if you need explicit control over the initial coordinates or a span with various length along different axis.
    /// Usually the [`TpnTree::root`] function should suffice and is simpler to use.
    ///
    /// # Examples
    ///
    /// Here we create a one dimensional tree, i.e. with one axis sitting on the center `[0.0]` with a span of 1.0 in each direction `[1.0]`.
    /// This is equal to a line segment spanning from -1.0 to 1.0 with its midpoint at 0.0.
    /// The `level` of the root is usually zero.
    /// ```
    /// # use tpntree::tpntree::TpnTree;
    ///
    /// let root = TpnTree::<(), 1>::new([0.0], [1.0], 0);
    /// ```
    ///
    /// Now lets create a two dimensional tree.
    /// The tree root corresponds to a square with its center sitting at the coordinates (1.0/1.0) with edges one edge being 4.0 the other being 1.0 units long.
    /// The edges equate to twice the span as it originates from the midpoint.
    /// ```
    /// # use tpntree::tpntree::TpnTree;
    /// let root = TpnTree::<(), 2>::new([1.0, 1.0], [2.0, 0.5], 0);
    /// ```
    pub fn new(coordinates: [f64; N], span: [f64; N], level: usize) -> Self {
        Self {
            coordinates,
            span,
            level,
            children: Vec::new(),
            data: None,
        }
    }

    /// Creates a new TpnTree with equal span in all dimension at the center of the space at level zero.
    ///
    /// Use this function if you want your TpnTree to represenst a centered N-dimensional hypercube.
    ///
    /// # Examples
    ///
    /// Here we create a three dimensional TpnTree with a span of 1.0 in ervery dimension.
    /// That is equal to a cube with edges of length 2.0.
    /// ```
    /// # use tpntree::tpntree::TpnTree;
    /// let root = TpnTree::<(), 3>::root(1.0);
    /// ```
    pub fn root(span: f64) -> Self {
        Self::new([0.0; N], [span; N], 0)
    }

    /// Divides the TpnTree into subregions creating new TpnTrees as children.
    ///
    /// Returns true if division happened, returns false when already divided.
    ///
    /// Each created child has its center moved by half the parents span up or down along the axis.
    /// Every child is equal to one unique combination of such half span moves.
    ///
    /// # Examples
    ///
    /// Dividing in the 2D case is creating four smaller squares.
    ///
    /// ```
    /// // +---+    +-+-+
    /// // |   | => +-+-+
    /// // +---+    +-+-+
    /// # use tpntree::tpntree::TpnTree;
    /// let mut root = TpnTree::<(), 2>::root(1.0);
    ///
    /// assert!(root.divide().is_ok());
    /// assert_eq!(root.child_count(), 4);
    /// ```
    pub fn divide(&mut self) -> Result<(), TpnTreeError> {
        if self.is_leaf() {
            let mut children = Vec::<Self>::new();
            let mut pattern = bitvec![0; self.coordinates.len()];

            // iterate for 2^N to generate all children
            for _ in 0..2usize.pow(self.coordinates.len() as u32) {
                let mut coordinates = self.coordinates;
                let mut span = self.span;
                // generate sign pattern from bits
                for i in 0..self.coordinates.len() {
                    span[i] = self.span[i] / 2.0;
                    coordinates[i] += span[i] - self.span[i] * pattern[i] as usize as f64;
                }

                children.push(Self::new(coordinates, span, self.level + 1));

                let mut carry = pattern.clone();
                carry.set_elements(0);
                let mut one = carry.clone();
                one.set(0, true);

                // "add one" to the pattern, loop to accomodate for carry
                while one.any() {
                    carry = pattern.clone() & one.clone();
                    pattern ^= one;
                    one = carry.clone();
                    // push so we can shift
                    one.push(false);
                    one.shift_right(1);
                    // pop to have an overflowing shift
                    one.pop();
                }
            }
            self.children = children;
            Ok(())
        } else {
            Err(TpnTreeError::CanNotDivide)
        }
    }

    /// Get a reference to a child TpnTree if it exists.
    pub fn get_child(&self, index: usize) -> Option<&Self> {
        self.children.get(index)
    }
    /// Get a mutable reference to a child TpnTree if it exists.
    pub fn get_child_mut(&mut self, index: usize) -> Option<&mut Self> {
        self.children.get_mut(index)
    }

    /// Returns the count of direct children.
    pub fn child_count(&self) -> usize {
        self.children.len()
    }

    /// Iterates all direct children by reference.
    pub fn iter_children(&self) -> impl Iterator<Item = &Self> {
        self.children.iter()
    }

    /// Iterates all direct children by mutable reference.
    pub fn iter_children_mut(&mut self) -> impl Iterator<Item = &mut Self> {
        self.children.iter_mut()
    }

    /// Returns the coordinates of the center of the TpnTree.
    pub fn coordinates(&self) -> [f64; N] {
        self.coordinates
    }

    /// Returns the span of the TpnTree.
    pub fn span(&self) -> [f64; N] {
        self.span
    }

    /// Returns the data by reference of the TpnTree.
    pub fn data(&self) -> Option<&T> {
        self.data.as_ref()
    }

    /// Returns the data by mutable reference of the TpnTree.
    pub fn data_mut(&mut self) -> &mut Option<T> {
        &mut self.data
    }

    /// Returns the level of the TpnTree.
    pub fn level(&self) -> usize {
        self.level
    }

    /// Returns wheter the tree is a root.
    pub fn is_root(&self) -> bool {
        self.level == 0
    }

    /// Returns wheter the tree is a leaf.
    pub fn is_leaf(&self) -> bool {
        self.children.is_empty()
    }

    /// Returns a list of adjacent trees along each dimension.
    ///
    /// The trees appear in order of dimension and that first the tree above self, then the one below.
    /// Thereby there will be dimension times two TpnTrees returned.
    pub fn adjacent_trees(&self) -> Vec<Self> {
        let mut adjacent_trees = Vec::new();
        for i in 0..self.coordinates.len() {
            let mut coordinates_above = self.coordinates;
            coordinates_above[i] += self.span[i] * 2.0;
            let tree_above = Self::new(coordinates_above, self.span, 0);

            let mut coordinates_below = self.coordinates;
            coordinates_below[i] -= self.span[i] * 2.0;
            let tree_below = Self::new(coordinates_below, self.span, 0);

            adjacent_trees.push(tree_above);
            adjacent_trees.push(tree_below);
        }
        adjacent_trees
    }
}

#[cfg(test)]
#[allow(clippy::float_cmp)]
mod tests {
    use super::TpnTree;

    #[test]
    pub fn divide_into_subregions_dim_1() {
        let mut root = TpnTree::<(), 1>::root(2.0);

        assert!(root.divide().is_ok());
        assert_eq!(root.child_count(), 2);

        assert_eq!(root.get_child(0).map(|c| c.coordinates()), Some([1.0]));
        assert_eq!(root.get_child(1).map(|c| c.coordinates()), Some([-1.0]));

        assert!(root.divide().is_err());
    }

    #[test]
    pub fn divide_into_subregions_dim_2() {
        let mut root = TpnTree::<(), 2>::root(1.0);

        assert!(root.divide().is_ok());
        assert_eq!(root.child_count(), 4);

        assert!(root.iter_children().any(|c| c.coordinates() == [0.5, 0.5]));
        assert!(root.iter_children().any(|c| c.coordinates() == [0.5, -0.5]));
        assert!(root.iter_children().any(|c| c.coordinates() == [-0.5, 0.5]));
        assert!(root
            .iter_children()
            .any(|c| c.coordinates() == [-0.5, -0.5]));

        assert!(root.divide().is_err());
    }

    #[test]
    pub fn divide_into_subregions_dim_3() {
        let mut root = TpnTree::<(), 3>::root(1.0);

        assert!(root.divide().is_ok());
        assert_eq!(root.child_count(), 8);

        assert!(root
            .iter_children()
            .any(|c| c.coordinates() == [0.5, 0.5, 0.5]));
        assert!(root
            .iter_children()
            .any(|c| c.coordinates() == [0.5, 0.5, -0.5]));
        assert!(root
            .iter_children()
            .any(|c| c.coordinates() == [0.5, -0.5, 0.5]));
        assert!(root
            .iter_children()
            .any(|c| c.coordinates() == [0.5, -0.5, -0.5]));
        assert!(root
            .iter_children()
            .any(|c| c.coordinates() == [-0.5, 0.5, 0.5]));
        assert!(root
            .iter_children()
            .any(|c| c.coordinates() == [-0.5, 0.5, -0.5]));
        assert!(root
            .iter_children()
            .any(|c| c.coordinates() == [-0.5, -0.5, 0.5]));
        assert!(root
            .iter_children()
            .any(|c| c.coordinates() == [-0.5, -0.5, -0.5]));

        assert!(root.divide().is_err());
    }

    #[test]
    pub fn get_adjacent_trees_dimension_one() {
        let root = TpnTree::<(), 1>::root(1.0);

        let adjacent_trees = root.adjacent_trees();

        assert!(adjacent_trees.iter().any(|c| c.coordinates() == [2.0]));
        assert!(adjacent_trees.iter().any(|c| c.coordinates() == [-2.0]));
    }

    #[test]
    pub fn get_adjacent_trees_dimension_two() {
        let root = TpnTree::<(), 2>::root(1.0);

        let adjacent_trees = root.adjacent_trees();

        assert!(adjacent_trees.iter().any(|c| c.coordinates() == [0.0, 2.0]));
        assert!(adjacent_trees
            .iter()
            .any(|c| c.coordinates() == [0.0, -2.0]));

        assert!(adjacent_trees.iter().any(|c| c.coordinates() == [2.0, 0.0]));
        assert!(adjacent_trees
            .iter()
            .any(|c| c.coordinates() == [-2.0, 0.0]));
    }
}