├── .gitignore ├── .github └── workflows │ └── rust.yml ├── Cargo.toml ├── LICENSE ├── HOWITWORKS.md ├── README.md └── src ├── lib.rs ├── tree ├── iterators.rs ├── mod.rs └── datastore.rs ├── error.rs └── matrix.rs /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | 12 | # Code coverage files 13 | *.profraw 14 | -------------------------------------------------------------------------------- /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: build & tests 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Build 20 | run: cargo build --verbose 21 | - name: Run tests 22 | run: cargo test --verbose 23 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "k2_tree" 3 | version = "0.5.3" 4 | authors = ["GGabi "] 5 | readme = "README.md" 6 | edition = "2018" 7 | description = "A space-efficient representation of sparsely populated bit-matrices." 8 | license = "MIT" 9 | repository = "https://github.com/GGabi/k2_tree" 10 | documentation = "https://docs.rs/k2_tree/" 11 | keywords = ["collection", "tree", "matrix", "bit", "bit-matrix"] 12 | categories = ["compression", "data-structures"] 13 | 14 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 15 | 16 | [dependencies] 17 | bitvec = "0.17.4" 18 | serde = { version = "1.0.119", features = ["derive"] } 19 | 20 | [dev-dependencies] 21 | rand = "0.7.3" 22 | serde_json = "1.0" 23 | serde_yaml = "0.8" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Gabriel Roels 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /HOWITWORKS.md: -------------------------------------------------------------------------------- 1 | # How it Works: 2 | ## Original Bit-Matrix: 3 | ``` 4 | 00|00||10|10 5 | 00|00||00|11 6 | ------------ 7 | 00|00||00|00 8 | 00|00||00|10 9 | ============ 10 | 10|10||00|11 11 | 10|00||00|00 12 | ------------ 13 | 00|00||00|00 14 | 00|00||00|00 15 | ``` 16 | As shown above, the 8x8 bit-matrix is sub-divided into sub-matrices where: 17 | * The smallest is width `k`. 18 | * All others are `k * child_width`. 19 | ## Modified Matrix 20 | Then, all sub-matrices containing only zeroes are substituted by a single zero, like so: 21 | ``` 22 | 0 ||10|10 23 | ||00|11 24 | ||----- 25 | ||0 |00 26 | || |10 27 | ============ 28 | 10|10||0 |11 29 | 10|00|| |00 30 | ------------ 31 | 0 |0 ||0 |0 32 | | || | 33 | ``` 34 | ## `K2Tree` Representation of Modified Matrix 35 | And then the `K2Tree` is built from this modified matrix: 36 | ``` 37 | 0111 38 | ____|||_________ 39 | | | | 40 | 1101 1100 0100 41 | |----|----| |----| | 42 | 1000 1011 0010 1010 1000 1100 43 | 44 | ``` 45 | In the first layer of the tree, each bit refers to one of the 4 largest quadrants in the modified matrix in the order: 46 | * The top-left contains nothing. 47 | * The top-right contains something. 48 | * The bottom-left contains something. 49 | * The bottom-right contains something. 50 | 51 | Then, for the second layer each block refers to the sub-matrices of each quadrant: 52 | * The top-right quadrant contains the following sub-quadrants: 53 | * The top-left, top-right and bottom-right contain something. 54 | * The bottom-left contains nothing. 55 | * The bottom-left qudrant contains the following: 56 | * Top-left and top-right contains something. 57 | * Bottom-left and bottom-right contains nothing. 58 | * And so on for the final quadrant. 59 | 60 | The final layer is referred to as the leaf-layer and contains the actual data in the matrix: 61 | * The top-left sub-quadrant of the top-right quadrant contains the bits: `1000` 62 | * Etc. 63 | ## Bit Representation of K2Tree 64 | The above `K2Tree` is stored as a series of bits: 65 | `[0111; 1101, 1100, 0100; 1000, 1011, 0010, 1010, 1000, 1100]` 66 | (Where `;` separates layers and `,` separates blocks) 67 | ## Final `K2Tree`: 68 | Finally, the bit representation of the K2Tree is stored alongside various metadata; so that the original matrix can be recovered and to greatly optimise various operations. 69 | ```rust 70 | K2Tree { 71 | stem_k: 2, 72 | leaf_k: 2, 73 | max_slayers: 2, 74 | stems: [0111110111000100], 75 | leaves: [100010110010101010001100], 76 | } 77 | ``` 78 | 79 | \- GGabi -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | [![Build Status](https://github.com/GGabi/k2_tree/workflows/build%20&%20tests/badge.svg)](https://github.com/GGabi/k2_tree/actions) 3 | [![](http://meritbadge.herokuapp.com/k2_tree)](https://crates.io/crates/k2_tree) 4 | [![API](https://docs.rs/k2_tree/badge.svg)](https://docs.rs/k2_tree) 5 | 6 | # k2_tree 7 | A collection designed to efficiently compress sparsely-populated bit-matrices. 8 | 9 | See the original proposal [here](https://users.dcc.uchile.cl/~gnavarro/ps/spire09.1.pdf). 10 | 11 | **Note:** This library heavily relies upon [bitvec](https://docs.rs/bitvec/0.17.4/bitvec/) to optimally store its data, which is very slow when compiled without optimisations! 12 | 13 | ## Usage 14 | Add `k2_tree` into your project dependencies: 15 | ```toml 16 | [dependencies] 17 | k2_tree = "0.5.2" 18 | ``` 19 | 20 | # When `K2Tree`s are Useful: 21 | `K2Tree`s are extremely efficient at representing data that can be encoded as a two-dimensional bit-matrix, especially if said matrix is sparsely populated. 22 | 23 | Take a real-world example: representing Web-Graphs. 24 | 25 | Hyperlinks between webpages can be encoded as a 2-d bit-matrix, where each column/row corresponds to a specific page and each bit denotes whether two pages are joined via a hyperlink; 1 if yes, 0 if not. 26 | 27 | These adjacency-matrices tend to be extremely sparse ***most of the time***, making the `K2Tree` the perfect structure for encoding them! 28 | 29 | Another example is representing Triple-Stores, which [this repo](https://github.com/GGabi/RippleDB) demonstrates is effective. 30 | 31 | # Example: 32 | ## Original Bit-Matrix: 33 | ``` 34 | 00|00||10|10 35 | 00|00||00|11 36 | ------------ 37 | 00|00||00|00 38 | 00|00||00|10 39 | ============ 40 | 10|10||00|11 41 | 10|00||00|00 42 | ------------ 43 | 00|00||00|00 44 | 00|00||00|00 45 | ``` 46 | ## Bit-Representation: 47 | `[0111; 1101, 1100, 0100; 1000, 1011, 0010, 1010, 1000, 1100]` 48 | 49 | (Where `;` separates layers and `,` separates blocks) 50 | ## Final `K2Tree`: 51 | ```rust 52 | K2Tree { 53 | stem_k: 2, // usize 54 | leaf_k: 2, // usize 55 | max_slayers: 2, // usize 56 | stems: [0111110111000100], // BitVec 57 | leaves: [100010110010101010001100], // BitVec 58 | } 59 | ``` 60 | For a more in-depth explanation of the compression process, [check this out](HOWITWORKS.md). 61 | # The Road to 1.0: 62 | - [x] Make `K2Tree` work over any value of K. 63 | - [x] Separate the `k` field into two distinct fields: `stem_k`, `leaf_k`. 64 | - [x] Increase compression ratio by removing the `stem_to_leaf` and `slayer_starts` field without compromising operation complexity. 65 | - [x] Implement serde's `Serialize` and `Deserialize` traits. 66 | - [ ] Unit test all the things. 67 | - [ ] Stabilise the API. 68 | 69 | \- GGabi 70 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_snake_case)] 2 | #![warn(missing_debug_implementations, rust_2018_idioms, missing_docs)] 3 | 4 | /*! 5 | A collection designed to efficiently compress sparsely-populated bit-matrices. 6 | 7 | See the original proposal [here](https://users.dcc.uchile.cl/~gnavarro/ps/spire09.1.pdf). 8 | 9 | **Note:** This library heavily relies upon [bitvec](https://docs.rs/bitvec/0.17.4/bitvec/) to optimally store its data. 10 | If you have `k2_tree` as a dependancy, always try to compile with optimisations! 11 | `bit_vec` is 12 | very slow without them! 13 | */ 14 | 15 | /*! 16 | # What's new in version 0.5: 17 | - `K2Tree` now implements serde's Serialize and Deserialize traits. 18 | */ 19 | 20 | /*! 21 | # When `K2Tree`s are Useful: 22 | 23 | `K2Tree`s are useful when you need to store two-dimensional data efficiently, especially when 24 | the data is sparsely populated. 25 | 26 | A real world example would be representing Web-Graphs. In this scenario, each column and row 27 | of a bit-matrix would represent a specific webpage, and all bits represent the whether two 28 | pages are joined by a hyperlink; 1 if yes and 0 if no. As it turns out, these types of Web-Graphs 29 | tend to produce sparsely populated bit-matrices. 30 | 31 | Another example would be representing Triple-Stores, which [this repo](https://github.com/GGabi/RippleDB) 32 | demonstrates is effective. 33 | */ 34 | 35 | /*! 36 | # How it Works: 37 | 38 | ## Original Bit-Matrix: 39 | 40 | ```ignore 41 | 00|00||10|10 42 | 00|00||00|11 43 | ------------ 44 | 00|00||00|00 45 | 00|00||00|10 46 | ============ 47 | 10|10||00|11 48 | 10|00||00|00 49 | ------------ 50 | 00|00||00|00 51 | 00|00||00|00 52 | ``` 53 | 54 | As shown above, the 8x8 bit-matrix is sub-divided into sub-matrices where: 55 | * The smallest is width k 56 | * All others are k * children_width 57 | 58 | ## Modified Matrix 59 | 60 | Then, all sub-matrices containing only zeroes are substituted by a single zero, like so: 61 | 62 | ```ignore 63 | 0 ||10|10 64 | ||00|11 65 | ||----- 66 | ||0 |00 67 | || |10 68 | ============ 69 | 10|10||0 |11 70 | 10|00|| |00 71 | ------------ 72 | 0 |0 ||0 |0 73 | | || | 74 | ``` 75 | 76 | ## `K2Tree` Representation of Modified Matrix 77 | 78 | And then the `K2Tree` is built from this modified matrix: 79 | 80 | ```ignore 81 | 0111 82 | ______|||________ 83 | | | | 84 | 1101 1100 0100 85 | |----|----| |----| | 86 | 1000 1011 0010 1010 1000 1100 87 | ``` 88 | 89 | From left-to-right in the first layer of the tree, each bit refers to one of the 4 largest quadrants in the modified matrix: 90 | * `0111` => Upper-left empty, upper-right not empty, lower-left not empty, lower-right not empty. 91 | 92 | Each block in the second layer refers to the sub-matrices of each parent: 93 | * The upper-right quadrant (`1101`) contains the following sub-quadrants: 94 | * Lower-left is empty. 95 | * Upper-left, upper-right and lower-right are not empty. 96 | * And so on. 97 | 98 | The final, or leaf, layer of the tree contains the actual data in the matrix. 99 | For example, the upper-left sub-quadrant of the upper-right quadrant contains the bits: `1000`. 100 | 101 | ## Bit Representation of K2Tree 102 | 103 | Finally, the above `K2Tree` is stored as a series of bits: 104 | 105 | `[0111; 1101, 1100, 0100; 1000, 1011, 0010, 1010, 1000, 1100]` 106 | 107 | (Where `;` separates layers and `,` separates blocks) 108 | 109 | ## Final `K2Tree`: 110 | 111 | ```ignore 112 | K2Tree { 113 | stem_k: 2, // usize 114 | leaf_k: 2, // usize 115 | max_slayers: 2, // usize 116 | stems: [0111110111000100], // BitVec 117 | leaves: [100010110010101010001100], // BitVec 118 | } 119 | ``` 120 | 121 | -- groels 122 | */ 123 | 124 | pub use tree::K2Tree; 125 | 126 | /// `K2Tree` structure and assosciated types. 127 | pub mod tree; 128 | 129 | /// Library error types. 130 | pub mod error; 131 | 132 | /// `BitMatrix` struct. 133 | pub mod matrix; -------------------------------------------------------------------------------- /src/tree/iterators.rs: -------------------------------------------------------------------------------- 1 | use bitvec::vec::BitVec; 2 | use crate::tree::datastore::K2Tree; 3 | 4 | /// A struct representing the value of a bit in a K2Tree's stems. 5 | /// 6 | /// This type is not intended to live for very long and 7 | /// is not linked to the live-state of the source K2Tree, 8 | /// so if the state of K2Tree changes then this could be invalid. 9 | #[derive(Copy, Clone, Debug, PartialEq)] 10 | pub struct StemBit { 11 | /// The value of the bit. 12 | pub value: bool, 13 | /// The stem-layer of the bit. 14 | pub layer: usize, 15 | /// The stem-number of the bit. 16 | pub stem: usize, 17 | /// The index of the bit within its stem. 18 | pub bit: usize, 19 | } 20 | 21 | /// A struct representing the value of a bit in a K2Tree's leaves. 22 | /// 23 | /// This type is not intended to live for very long and 24 | /// is not linked to the live-state of the source K2Tree, 25 | /// so if the state of K2Tree changes then this could be invalid. 26 | #[derive(Copy, Clone, Debug, PartialEq)] 27 | pub struct LeafBit { 28 | /// The value of the bit. 29 | pub value: bool, 30 | /// The x coordinate of the bit in the matrix the K2Tree represents. 31 | pub x: usize, 32 | /// The y coordinate of the bit in the matrix the K2Tree represents. 33 | pub y: usize, 34 | /// The leaf number of the bit. 35 | pub leaf: usize, 36 | /// The index of the bit within its leaf. 37 | pub bit: usize, 38 | } 39 | 40 | /// An iterator over a K2Tree's stems which produces instances of StemBit. 41 | #[derive(Debug)] 42 | pub struct Stems<'a> { 43 | tree: &'a K2Tree, 44 | pos: usize, 45 | layer: usize, 46 | stem: usize, 47 | bit: usize, 48 | } 49 | impl<'a> Iterator for Stems<'a> { 50 | type Item = StemBit; 51 | fn next(&mut self) -> Option { 52 | let stem_len = self.tree.stem_len(); 53 | if self.pos >= self.tree.stems.len() { 54 | return None 55 | } 56 | /* Grab the return value */ 57 | let ret_v = Some(StemBit { 58 | value: self.tree.stems[self.pos], 59 | layer: self.layer, 60 | stem: self.stem, 61 | bit: self.bit, 62 | }); 63 | /* Increment the iterator's state for next value */ 64 | self.pos += 1; 65 | if self.bit == stem_len-1 { 66 | self.bit = 0; 67 | if self.stem == (self.tree.layer_len(self.layer) / stem_len) - 1 { 68 | self.stem = 0; 69 | self.layer += 1; 70 | } 71 | else { 72 | self.stem += 1; 73 | } 74 | } 75 | else { 76 | self.bit += 1; 77 | } 78 | ret_v 79 | } 80 | } 81 | impl<'a> Stems<'a> { 82 | /// Produces a Stems iterator from a reference to a K2Tree. 83 | pub fn new(tree: &'a K2Tree) -> Self { 84 | Self { 85 | tree, 86 | pos: 0, 87 | layer: 0, 88 | stem: 0, 89 | bit: 0, 90 | } 91 | } 92 | } 93 | 94 | /// A consuming iterator over a K2Tree's stems which produces instances of StemBit. 95 | #[derive(Debug)] 96 | pub struct IntoStems { 97 | tree: K2Tree, 98 | pos: usize, 99 | layer: usize, 100 | stem: usize, 101 | bit: usize, 102 | } 103 | impl Iterator for IntoStems { 104 | type Item = StemBit; 105 | fn next(&mut self) -> Option { 106 | let stem_len = self.tree.stem_len(); 107 | if self.pos >= self.tree.stems.len() { 108 | return None 109 | } 110 | /* Grab the return value */ 111 | let ret_v = Some(StemBit { 112 | value: self.tree.stems[self.pos], 113 | layer: self.layer, 114 | stem: self.stem, 115 | bit: self.bit, 116 | }); 117 | /* Increment the iterator's state for next value */ 118 | self.pos += 1; 119 | if self.bit == stem_len-1 { 120 | self.bit = 0; 121 | if self.stem == (self.tree.layer_len(self.layer) / stem_len) - 1 { 122 | self.stem = 0; 123 | self.layer += 1; 124 | } 125 | else { 126 | self.stem += 1; 127 | } 128 | } 129 | else { 130 | self.bit += 1; 131 | } 132 | ret_v 133 | } 134 | } 135 | impl IntoStems { 136 | /// Produces a Stems iterator from a reference to a K2Tree. 137 | pub fn new(tree: K2Tree) -> Self { 138 | Self { 139 | tree, 140 | pos: 0, 141 | layer: 0, 142 | stem: 0, 143 | bit: 0, 144 | } 145 | } 146 | } 147 | 148 | /// An iterator over a K2Tree's leaves which produces instances of LeafBit. 149 | #[derive(Debug)] 150 | pub struct Leaves<'a> { 151 | tree: &'a K2Tree, 152 | pos: usize, 153 | } 154 | impl<'a> Iterator for Leaves<'a> { 155 | type Item = LeafBit; 156 | fn next(&mut self) -> Option { 157 | if self.pos == self.tree.leaves.len() { return None } 158 | let [x, y] = self.tree.get_coords(self.pos); 159 | let value = self.tree.leaves[self.pos]; 160 | let leaf = self.pos / self.tree.leaf_len(); 161 | let bit = self.pos % self.tree.leaf_len(); 162 | self.pos += 1; 163 | Some(LeafBit { 164 | value, 165 | x, 166 | y, 167 | leaf, 168 | bit 169 | }) 170 | } 171 | } 172 | impl<'a> Leaves<'a> { 173 | /// Produces a Leaves iterator from a reference to a K2Tree. 174 | pub fn new(tree: &'a K2Tree) -> Self { 175 | Self { 176 | tree, 177 | pos: 0, 178 | } 179 | } 180 | } 181 | 182 | /// A consuming iterator over a K2Tree's leaves which produces instances of LeafBit. 183 | #[derive(Debug)] 184 | pub struct IntoLeaves { 185 | tree: K2Tree, 186 | pos: usize, 187 | } 188 | impl Iterator for IntoLeaves { 189 | type Item = LeafBit; 190 | fn next(&mut self) -> Option { 191 | if self.pos == self.tree.leaves.len() { return None } 192 | let leaf_len = self.tree.leaf_len(); 193 | let [x, y] = self.tree.get_coords(self.pos); 194 | let value = self.tree.leaves[self.pos]; 195 | let leaf = self.pos / leaf_len; 196 | let bit = self.pos % leaf_len; 197 | self.pos += 1; 198 | Some(LeafBit { 199 | value, 200 | x, 201 | y, 202 | leaf, 203 | bit 204 | }) 205 | } 206 | } 207 | impl IntoLeaves { 208 | /// Produces an IntoLeaves iterator from a K2Tree. 209 | pub fn new(tree: K2Tree) -> Self { 210 | Self { 211 | tree, 212 | pos: 0, 213 | } 214 | } 215 | } 216 | 217 | /// An iterator over a K2Tree's stems which produces the raw boolean-values of each bit. 218 | #[derive(Debug)] 219 | pub struct StemsRaw<'a> { 220 | stems: &'a BitVec, 221 | pos: usize, 222 | } 223 | impl<'a> Iterator for StemsRaw<'a> { 224 | type Item = bool; 225 | fn next(&mut self) -> Option { 226 | if self.pos >= self.stems.len() { 227 | return None 228 | } 229 | let ret_v = Some(self.stems[self.pos]); 230 | self.pos += 1; 231 | ret_v 232 | } 233 | } 234 | impl<'a> StemsRaw<'a> { 235 | /// Produces a StemsRaw iterator from a reference to a K2Tree. 236 | pub fn new(tree: &'a K2Tree) -> Self { 237 | Self { 238 | stems: &tree.stems, 239 | pos: 0, 240 | } 241 | } 242 | } 243 | 244 | /// An iterator over a K2Tree's leaves which prduces the raw boolean-values of each bit. 245 | #[derive(Debug)] 246 | pub struct LeavesRaw<'a> { 247 | leaves: &'a BitVec, 248 | pos: usize, 249 | } 250 | impl<'a> Iterator for LeavesRaw<'a> { 251 | type Item = bool; 252 | fn next(&mut self) -> Option { 253 | if self.pos >= self.leaves.len() { 254 | return None 255 | } 256 | let ret_v = Some(self.leaves[self.pos]); 257 | self.pos += 1; 258 | ret_v 259 | } 260 | } 261 | impl<'a> LeavesRaw<'a> { 262 | /// Produces a LeavesRaw iterator from a reference to a K2Tree. 263 | pub fn new(tree: &'a K2Tree) -> Self { 264 | Self { 265 | leaves: &tree.leaves, 266 | pos: 0, 267 | } 268 | } 269 | } 270 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | These are all the custom errors that this library could return. 3 | 4 | This library uses a nesting system to convey the most useful information 5 | while minimising the number of unique enumerations required: 6 | - CorruptedK2Tree: 7 | - The K2Tree is *likely* to have been corrupted by the operation that resulted in this error. 8 | - Read: 9 | - The error occured during a Read operation, meaning that the state of the K2Tree could 10 | not have been changed by the operation that resulted in this error. 11 | - Write: 12 | - The error occured during a Write operation, meaning that the state of the K2Tree *may* 13 | have been changed by the operation that resulted in this error. 14 | */ 15 | 16 | /// Errors produced as a result of interactions with the K2Tree object. 17 | #[derive(Clone, Debug, PartialEq)] 18 | pub enum K2TreeError { 19 | /// Produced when a user attempts to create a K2Tree with a k values below 2. 20 | SmallStemKValue { 21 | /// 22 | stem_k: u8, 23 | }, 24 | /// Produced when a user attempts to create a K2Tree with a k values below 2. 25 | SmallLeafKValue { 26 | /// 27 | leaf_k: u8, 28 | }, 29 | /// Produced when a problem occurs attempting to traverse a K2Tree. 30 | /// 31 | /// This mostly appears because the internal state of K2Tree is corrupted, 32 | /// or the user found a way to search for an invalid coordinate within the bounds 33 | /// of the matrix the K2Tree represents. 34 | TraverseError { 35 | /// 36 | x: usize, 37 | /// 38 | y: usize 39 | }, 40 | /// Produced when a user attempts to access a coordinate outside the bounds of 41 | /// the matrix a K2Tree represents. 42 | OutOfBounds{ 43 | /// 44 | x_y: [usize; 2], 45 | /// 46 | min_x_y: [usize; 2], 47 | /// 48 | max_x_y: [usize; 2], 49 | }, 50 | /// Produced when a stem could not be inserted into a K2Tree's stems. 51 | StemInsertionError { 52 | /// The index the stem-insertion was attempted at. 53 | pos: usize, 54 | /// The length of the stem. 55 | len: usize 56 | }, 57 | /// Produced when a stem coud not be removed from a K2Tree's stems. 58 | StemRemovalError { 59 | /// The index the stem-removal was attempted at. 60 | pos: usize, 61 | /// The length of the stem. 62 | len: usize 63 | }, 64 | /// Produced when a leaf could not be inserted into a K2Tree's leaves. 65 | LeafInsertionError { 66 | /// The index the leaf-insertion was attempted at. 67 | pos: usize, 68 | /// The length of the leaf. 69 | len: usize 70 | }, 71 | /// Produced when a leaf could not be removed from a K2Tree's leaves. 72 | LeafRemovalError { 73 | /// The index the leaf-removal was attempted at. 74 | pos: usize, 75 | /// the length of the leaf. 76 | len: usize 77 | }, 78 | /// Produced when a problem occurs attempting to shrink the matrix a K2Tree represents. 79 | CouldNotShrink { 80 | /// 81 | reason: String 82 | }, 83 | /// Indicates that the source error resulted in the corruption of a K2Tree. 84 | CorruptedK2Tree { 85 | /// 86 | source: Box 87 | }, 88 | /// Indicates that the source error was produced during a read operation on a K2Tree. 89 | /// 90 | /// Almost certainly guarantees that the error did not cause any corruption. 91 | Read { 92 | /// 93 | source: Box 94 | }, 95 | /// Indicates that the source error was produced during a write operation on a K2Tree. 96 | Write { 97 | /// 98 | source: Box 99 | }, 100 | /// Propogation of a BitMatrixError. 101 | BitMatrixError { 102 | /// 103 | source: Box, 104 | }, 105 | /// Propogation of a SubRangesError. 106 | SubRangesError { 107 | /// 108 | source: Box, 109 | } 110 | } 111 | impl std::error::Error for K2TreeError { 112 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 113 | use K2TreeError::*; 114 | match self { 115 | CorruptedK2Tree{source} => Some(source), 116 | Read{source} => Some(source), 117 | Write{source} => Some(source), 118 | BitMatrixError{source} => Some(source), 119 | SubRangesError{source} => Some(source), 120 | _ => None, 121 | } 122 | } 123 | } 124 | impl std::fmt::Display for K2TreeError { 125 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 126 | use K2TreeError::*; 127 | match self { 128 | SmallStemKValue{stem_k} => write!(f, "Attempt to create a K2Tree with a stem_k value of {}, which less than the minimum of 2.", stem_k), 129 | SmallLeafKValue{leaf_k} => write!(f, "Attempt to create a K2Tree with a leaf_k value of {}, which less than the minimum of 2.", leaf_k), 130 | TraverseError{x, y} => write!(f, "Error encountered while traversing K2Tree for value at coordinates ({}, {})", x, y), 131 | OutOfBounds { 132 | x_y: [x, y], 133 | min_x_y: [min_x, min_y], 134 | max_x_y: [max_x, max_y] 135 | } => write!(f, "Attempt to access a bit at coordiantes ({}, {}) which are not in the range of the matrix represented by the K2Tree: ({}, {}) -> ({}, {})", x, y, min_x, min_y, max_x, max_y), 136 | StemInsertionError{pos, len} => write!(f, "Could not insert stem of length {} at index {}", len, pos), 137 | StemRemovalError{pos, len} => write!(f, "Could not remove stem of length {} at index {}", len, pos), 138 | LeafInsertionError{pos, len} => write!(f, "Could not insert leaf of length {} at index {}", len, pos), 139 | LeafRemovalError{pos, len} => write!(f, "Could not remove leaf of length {} at index {}", len, pos), 140 | CouldNotShrink{reason} => write!(f, "Could not shrink the matrix a K2Tree represents: {}", reason), 141 | CorruptedK2Tree{source} => write!(f, "The K2Tree's contents are corrupted as a result of the following error: {}", source), 142 | Read{source} => write!(f, "Error during read: {}", source), 143 | Write{source} => write!(f, "Error during write: {}", source), 144 | BitMatrixError{source} => write!(f, "{}", source), 145 | SubRangesError{source} => write!(f, "{}", source), 146 | } 147 | } 148 | } 149 | impl From for K2TreeError { 150 | fn from(error: BitMatrixError) -> Self { 151 | K2TreeError::BitMatrixError { 152 | source: Box::new(error) 153 | } 154 | } 155 | } 156 | impl From for K2TreeError { 157 | fn from(error: SubRangesError) -> Self { 158 | K2TreeError::SubRangesError { 159 | source: Box::new(error), 160 | } 161 | } 162 | } 163 | 164 | /// Errors produced as a result of interactions with the BitMatrix object. 165 | #[derive(Clone, Debug, PartialEq)] 166 | pub enum BitMatrixError { 167 | /// Produced when a user attempts to read or write to a bit outside of the 168 | /// valid range. 169 | OutOfBounds { 170 | /// 171 | x_y: [usize; 2], 172 | /// 173 | max_x_y: [usize; 2], 174 | } 175 | } 176 | impl std::error::Error for BitMatrixError { 177 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 178 | None 179 | } 180 | } 181 | impl std::fmt::Display for BitMatrixError { 182 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 183 | use BitMatrixError::*; 184 | match self { 185 | OutOfBounds { 186 | x_y: [x, y], 187 | max_x_y: [max_x, max_y], 188 | } => write!(f, "Attempts to access a bit at coordinates({}, {}) which are not in the range of the matrix: (0, 0) -> ({}, {})", x, y, max_x, max_y), 189 | } 190 | } 191 | } 192 | 193 | /// Errors produced as a result of interactions with the SubRanges object. 194 | #[derive(Clone, Debug, PartialEq)] 195 | pub enum SubRangesError { 196 | /// Produced when a user attempts a Range2D cannot be evenly subdivided 197 | /// by the requested number of subranges. 198 | CannotSubdivideRange { 199 | /// The range which could not be subdivided. 200 | range: [[usize; 2]; 2], 201 | /// The attempted number of horizontal subdivisions. 202 | horizontal_subdivisions: usize, 203 | /// The attempted number of vertical subdivisions. 204 | vertical_subdivisions: usize, 205 | } 206 | } 207 | impl std::error::Error for SubRangesError { 208 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 209 | None 210 | } 211 | } 212 | impl std::fmt::Display for SubRangesError { 213 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 214 | use SubRangesError::*; 215 | match self { 216 | CannotSubdivideRange { 217 | range: [[min_x, max_x], [min_y, max_y]], 218 | horizontal_subdivisions: hs, 219 | vertical_subdivisions: vs, 220 | } => write!(f, "The 2D range ({}, {}) -> ({}, {}) could not be evenly subdivided {} times horizontally or {} times vertically.", min_x, min_y, max_x, max_y, hs, vs), 221 | } 222 | } 223 | } -------------------------------------------------------------------------------- /src/tree/mod.rs: -------------------------------------------------------------------------------- 1 | 2 | mod datastore; 3 | mod iterators; 4 | 5 | pub use datastore::*; 6 | pub use datastore::K2Tree; 7 | pub use iterators::{ 8 | StemBit, 9 | LeafBit, 10 | Stems, 11 | StemsRaw, 12 | Leaves, 13 | IntoLeaves, 14 | LeavesRaw, 15 | }; 16 | 17 | /* Private Yet Common to Everything Module */ 18 | use bitvec::prelude::BitVec; 19 | 20 | impl K2Tree { 21 | // Internal: Never call with layer >= self.max_slayers 22 | fn layer_len(&self, l: usize) -> usize { 23 | if l == self.max_slayers-1 { 24 | return self.stems.len() - self.layer_start(l) 25 | } 26 | let layer_starts = self.layer_starts(); 27 | layer_starts[l+1] - layer_starts[l] 28 | } 29 | fn get_coords(&self, leaf_bit_pos: usize) -> [usize; 2] { 30 | /* Start at the leaf_bit and traverse our way up to the top of the tree, 31 | keeping track of the path we took on our way up in terms of 32 | bit-positions (offsets) in the stems. Then, traverse back down the same 33 | path to find the coords of the leaf_bit. */ 34 | let parent_bit = self.leaf_parent(leaf_bit_pos); 35 | let mut stem_start = self.stem_start(parent_bit); 36 | let mut offset = parent_bit - stem_start; 37 | let mut offsets = vec![offset]; 38 | for _ in 1..self.max_slayers { 39 | let parent = self.parent(stem_start).unwrap(); 40 | stem_start = parent[0]; 41 | offset = parent[1]; 42 | offsets.push(offset); 43 | } 44 | /* Reverse the offsets ready to traverse them back down the tree */ 45 | offsets.reverse(); 46 | let range_max = self.matrix_width()-1; 47 | let mut range = Range2D::new(0, range_max, 0, range_max); 48 | for child_offset in offsets.into_iter().take(self.max_slayers) { 49 | range = self.to_subranges(range).unwrap()[child_offset]; 50 | } 51 | let leaf_offset = leaf_bit_pos - self.leaf_start(leaf_bit_pos); 52 | let x = leaf_offset % self.leaf_k; 53 | let y = leaf_offset / self.leaf_k; 54 | [range.min_x + x, range.min_y + y] 55 | } 56 | fn leaf_parent(&self, bit_pos: usize) -> usize { 57 | let nth_leaf = bit_pos / self.leaf_len(); 58 | let final_stem_layer_start = self.layer_start(self.max_slayers-1); 59 | let stem_ones_positions = one_positions_range( 60 | &self.stems, 61 | final_stem_layer_start, 62 | self.stems.len() 63 | ); 64 | final_stem_layer_start + stem_ones_positions[nth_leaf] //TODO: check 65 | } 66 | fn parent(&self, stem_start: usize) -> std::result::Result<[usize; 2], ()> { 67 | /* Returns [stem_start, bit_offset] */ 68 | let stem_len = self.stem_len(); 69 | if stem_start < stem_len { 70 | return Err(()) //First stem cannot have parent 71 | } 72 | /* Find which layer stem_start is in */ 73 | let layer_starts = self.layer_starts(); 74 | let stem_layer = { 75 | let mut layer = self.max_slayers-1; //If no match, must be in highest layer 76 | for (i, &layer_start) in layer_starts.iter().enumerate() { 77 | if stem_start < layer_start { layer = i-1; break } 78 | } 79 | layer 80 | }; 81 | /* Find the nth stem it is in the layer */ 82 | let stem_num = (stem_start - layer_starts[stem_layer]) / stem_len; 83 | /* Find the nth 1 in the parent layer */ 84 | let parent_bit_relative_pos = one_positions_range( 85 | &self.stems, 86 | layer_starts[stem_layer-1], 87 | layer_starts[stem_layer] 88 | )[stem_num]; 89 | let parent_bit_absolute_pos = parent_bit_relative_pos + layer_starts[stem_layer-1]; 90 | Ok([self.stem_start(parent_bit_absolute_pos), parent_bit_absolute_pos % stem_len]) 91 | } 92 | fn layer_start(&self, l: usize) -> usize { 93 | //Private method, let it crash seeing as is just unwrapped otherwise 94 | let mut curr_layer = 1; 95 | let mut layer_starts = vec![0, self.stem_len()]; 96 | while curr_layer < l { 97 | let stems_in_curr_layer = ones_in_range( 98 | &self.stems, 99 | layer_starts[curr_layer-1], 100 | layer_starts[curr_layer] 101 | ); 102 | let curr_layer_len = stems_in_curr_layer * self.stem_len(); 103 | layer_starts.push(layer_starts[curr_layer] + curr_layer_len); 104 | curr_layer += 1; 105 | } 106 | layer_starts[l] 107 | } 108 | fn layer_starts(&self) -> Vec { 109 | //Private method, let it crash seeing as is just unwrapped otherwise 110 | let mut curr_layer = 1; 111 | let mut layer_starts = vec![0, self.stem_len()]; 112 | while curr_layer < self.max_slayers-1 { 113 | let stems_in_curr_layer = ones_in_range( 114 | &self.stems, 115 | layer_starts[curr_layer-1], 116 | layer_starts[curr_layer] 117 | ); 118 | let curr_layer_len = stems_in_curr_layer * self.stem_len(); 119 | layer_starts.push(layer_starts[curr_layer] + curr_layer_len); 120 | curr_layer += 1; 121 | } 122 | layer_starts 123 | } 124 | } 125 | 126 | /* Block Utils */ 127 | impl K2Tree { 128 | fn stem_len(&self) -> usize { 129 | self.stem_k.pow(2) 130 | } 131 | fn leaf_len(&self) -> usize { 132 | self.leaf_k.pow(2) 133 | } 134 | fn stem_start(&self, bit_pos: usize) -> usize { 135 | (bit_pos / self.stem_len()) * self.stem_len() 136 | } 137 | fn leaf_start(&self, bit_pos: usize) -> usize { 138 | (bit_pos / self.leaf_len()) * self.leaf_len() 139 | } 140 | fn to_subranges(&self, r: Range2D) -> std::result::Result { 141 | SubRanges::from_range(r, self.stem_k, self.stem_k) 142 | } 143 | } 144 | 145 | fn remove_block(bit_vec: &mut BitVec, block_start: usize, block_len: usize) -> std::result::Result<(), ()> { 146 | if block_start > bit_vec.len()-block_len 147 | || block_start % block_len != 0 { 148 | Err(()) 149 | } 150 | else { 151 | for _ in 0..block_len { bit_vec.remove(block_start); } 152 | Ok(()) 153 | } 154 | } 155 | fn insert_block(bit_vec: &mut BitVec, block_start: usize, block_len: usize) -> std::result::Result<(), ()> { 156 | if block_start > bit_vec.len() 157 | || block_start % block_len != 0 { 158 | Err(()) 159 | } 160 | else { 161 | for _ in 0..block_len { bit_vec.insert(block_start, false); } 162 | Ok(()) 163 | } 164 | } 165 | fn ones_in_range(bits: &BitVec, begin: usize, end: usize) -> usize { 166 | bits[begin..end].into_iter().fold(0, |total, bit| total + *bit as usize) 167 | } 168 | fn all_zeroes(bits: &BitVec, begin: usize, end: usize) -> bool { 169 | bits[begin..end].into_iter().fold(true, |total, bit| total & !bit) 170 | } 171 | fn one_positions(bits: impl Iterator) -> Vec { 172 | bits 173 | .enumerate() 174 | .filter_map( 175 | |(pos, bit)| 176 | if bit { Some(pos) } 177 | else { None }) 178 | .collect() 179 | } 180 | fn one_positions_bv(bits: &BitVec) -> Vec { 181 | bits.iter() 182 | .enumerate() 183 | .filter_map( 184 | |(pos, &bit)| 185 | if bit { Some(pos) } 186 | else { None }) 187 | .collect() 188 | } 189 | fn one_positions_range(bits: &BitVec, begin: usize, end: usize) -> Vec { 190 | bits[begin..end].into_iter().enumerate() 191 | .filter_map(|(pos, bit)| 192 | if *bit { Some(pos) } 193 | else { None } 194 | ).collect() 195 | } 196 | 197 | /* Ranges */ 198 | #[derive(Debug, Clone)] 199 | struct SubRanges { 200 | /// Number of horizontal subranges. 201 | #[allow(dead_code)] 202 | pub width: usize, 203 | /// Number of vertical subranges. 204 | #[allow(dead_code)] 205 | pub height: usize, 206 | /// Subranges 207 | subranges: Vec, 208 | } 209 | impl SubRanges { 210 | fn from_range(r: Range2D, w: usize, h: usize) -> std::result::Result { 211 | // If the range cannot be evenly divided up by w and h, break 212 | if r.width() / w * w != r.width() 213 | || r.height() / h * h != r.height() { 214 | return Err(crate::error::SubRangesError::CannotSubdivideRange { 215 | range: [[r.min_x, r.min_y], [r.max_x, r.max_y]], 216 | horizontal_subdivisions: w, 217 | vertical_subdivisions: h, 218 | }) 219 | } 220 | let mut subranges: Vec = Vec::new(); 221 | let sub_width = r.width() / w; 222 | let sub_height = r.height() / h; 223 | // Process subranges by rows then columns 224 | for y in 0..h { 225 | for x in 0..w { 226 | let min_x = r.min_x + (x * sub_width); 227 | let max_x = min_x + sub_width-1; 228 | let min_y = r.min_y + (y * sub_height); 229 | let max_y = min_y + sub_height-1; 230 | subranges.push(Range2D::new(min_x, max_x, min_y, max_y)); 231 | } 232 | } 233 | Ok(SubRanges { 234 | width: w, 235 | height: h, 236 | subranges 237 | }) 238 | } 239 | fn iter(&self) -> impl Iterator { 240 | self.subranges.iter() 241 | } 242 | } 243 | impl std::ops::Index for SubRanges { 244 | type Output = Range2D; 245 | fn index(&self, i: usize) -> &Self::Output { 246 | &self.subranges[i] 247 | } 248 | } 249 | impl std::ops::IndexMut for SubRanges { 250 | fn index_mut(&mut self, i: usize) -> &mut Self::Output { 251 | &mut self.subranges[i] 252 | } 253 | } 254 | 255 | #[derive(Debug, Clone, Copy)] 256 | struct Range2D { 257 | pub min_x: usize, 258 | pub max_x: usize, 259 | pub min_y: usize, 260 | pub max_y: usize 261 | } 262 | impl Range2D { 263 | fn new(min_x: usize, max_x: usize, min_y: usize, max_y: usize) -> Self { 264 | Range2D { 265 | min_x, 266 | max_x, 267 | min_y, 268 | max_y 269 | } 270 | } 271 | fn width(&self) -> usize { 272 | self.max_x - self.min_x + 1 // +1 because range is inclusive 273 | } 274 | fn height(&self) -> usize { 275 | self.max_y - self.min_y + 1 // +1 because range is inclusive 276 | } 277 | fn contains(&self, x: usize, y: usize) -> bool { 278 | x >= self.min_x && x <= self.max_x 279 | && y >= self.min_y && y <= self.max_y 280 | } 281 | } 282 | impl PartialEq for Range2D { 283 | fn eq(&self, other: &Self) -> bool { 284 | self.min_x == other.min_x 285 | && self.max_x == other.max_x 286 | && self.min_y == other.min_y 287 | && self.max_y == other.max_y 288 | } 289 | } 290 | impl Eq for Range2D {} 291 | 292 | /* Only used in tests */ 293 | #[cfg(test)] 294 | use { 295 | bitvec::prelude::bitvec, 296 | crate::matrix::BitMatrix 297 | }; 298 | 299 | /* Tests */ 300 | #[cfg(test)] 301 | mod range_tests { 302 | use super::*; 303 | type Result = std::result::Result; 304 | #[test] 305 | fn subranges_from_range2d_0() -> Result<()> { 306 | let original = Range2D::new(0, 7, 0, 7); 307 | let expected_subs = [ 308 | Range2D::new(0, 3, 0, 3), 309 | Range2D::new(4, 7, 0, 3), 310 | Range2D::new(0, 3, 4, 7), 311 | Range2D::new(4, 7, 4, 7), 312 | ]; 313 | let subs = SubRanges::from_range(original, 2, 2)?; 314 | for i in 0..4 { assert_eq!(expected_subs[i], subs[i]); } 315 | Ok(()) 316 | } 317 | #[test] 318 | fn subranges_from_range2d_1() -> Result<()> { 319 | let original = Range2D::new(0, 8, 0, 8); 320 | let expected_subs = [ 321 | Range2D::new(0, 2, 0, 2), 322 | Range2D::new(3, 5, 0, 2), 323 | Range2D::new(6, 8, 0, 2), 324 | Range2D::new(0, 2, 3, 5), 325 | Range2D::new(3, 5, 3, 5), 326 | Range2D::new(6, 8, 3, 5), 327 | Range2D::new(0, 2, 6, 8), 328 | Range2D::new(3, 5, 6, 8), 329 | Range2D::new(6, 8, 6, 8), 330 | ]; 331 | let subs = SubRanges::from_range(original, 3, 3)?; 332 | for i in 0..9 { assert_eq!(expected_subs[i], subs[i]); } 333 | Ok(()) 334 | } 335 | #[test] 336 | fn subranges_from_range2d_2() -> Result<()> { 337 | let original = Range2D::new(0, 8, 0, 7); 338 | let expected_subs = [ 339 | Range2D::new(0, 2, 0, 3), 340 | Range2D::new(3, 5, 0, 3), 341 | Range2D::new(6, 8, 0, 3), 342 | Range2D::new(0, 2, 4, 7), 343 | Range2D::new(3, 5, 4, 7), 344 | Range2D::new(6, 8, 4, 7), 345 | ]; 346 | let subs = SubRanges::from_range(original, 3, 2)?; 347 | for i in 0..6 { assert_eq!(expected_subs[i], subs[i]); } 348 | Ok(()) 349 | } 350 | } 351 | 352 | /* Private funcs used in testing */ 353 | #[cfg(test)] 354 | impl K2Tree { 355 | fn test_tree(k: usize) -> Self { 356 | match k { 357 | 2 => K2Tree { 358 | stem_k: 2, 359 | leaf_k: 2, 360 | max_slayers: 2, 361 | stems: bitvec![0,1,1,1, 1,1,0,1, 1,0,0,0, 1,0,0,0], 362 | leaves: bitvec![0,1,1,0, 0,1,0,1, 1,1,0,0, 1,0,0,0, 0,1,1,0], 363 | }, 364 | 3 => K2Tree { 365 | stem_k: 3, 366 | leaf_k: 3, 367 | max_slayers: 2, 368 | stems: bitvec![ 369 | 0,1,0,1,1,0,1,1,0, 1,1,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0,0, 370 | 1,0,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0,0 371 | ], 372 | leaves: bitvec![ 373 | 0,1,0,1,0,0,0,0,1, 1,0,0,1,0,0,1,0,0, 1,0,0,0,0,0,0,0,0, 374 | 0,1,0,1,0,0,0,0,0, 1,0,0,0,0,0,0,0,0, 0,1,0,1,0,0,0,0,0, 375 | ] 376 | }, 377 | 4 => K2Tree { 378 | stem_k: 4, 379 | leaf_k: 4, 380 | max_slayers: 2, 381 | stems: bitvec![ 382 | 1,0,0,1,0,0,0,1,1,0,0,0,1,1,0,1, 1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, 383 | 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1, 384 | 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1, 385 | 1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, 386 | ], 387 | leaves: bitvec![ 388 | 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0, 389 | 0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, 0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, 390 | 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, 0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, 391 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, 392 | ], 393 | }, 394 | _ => K2Tree::with_k(2, 2).unwrap(), 395 | } 396 | } 397 | fn test_matrix(k: usize) -> BitMatrix { 398 | match k { 399 | 2 => { 400 | let bits = bitvec![ 401 | 0,0,0,0, 0,1,0,1, 402 | 0,0,0,0, 1,0,0,1, 403 | 0,0,0,0, 0,0,1,1, 404 | 0,0,0,0, 0,0,0,0, 405 | 406 | 1,0,0,0, 0,1,0,0, 407 | 0,0,0,0, 1,0,0,0, 408 | 0,0,0,0, 0,0,0,0, 409 | 0,0,0,0, 0,0,0,0 410 | ]; 411 | BitMatrix::from_bits(8, 8, bits) 412 | }, 413 | 3 => { 414 | let bits = bitvec![ 415 | 0,0,0, 0,0,0, 0,0,0, 0,1,0, 1,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 416 | 0,0,0, 0,0,0, 0,0,0, 1,0,0, 1,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 417 | 0,0,0, 0,0,0, 0,0,0, 0,0,1, 1,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 418 | 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 419 | 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 420 | 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 421 | 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 422 | 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 423 | 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 424 | 425 | 1,0,0, 0,0,0, 0,0,0, 0,1,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 426 | 0,0,0, 0,0,0, 0,0,0, 1,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 427 | 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 428 | 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 429 | 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 430 | 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 431 | 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 432 | 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 433 | 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 434 | 435 | 1,0,0, 0,0,0, 0,0,0, 0,1,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 436 | 0,0,0, 0,0,0, 0,0,0, 1,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 437 | 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 438 | 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 439 | 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 440 | 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 441 | 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 442 | 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 443 | 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 444 | ]; 445 | BitMatrix::from_bits(27, 27, bits) 446 | }, 447 | _ => BitMatrix::new(), 448 | } 449 | } 450 | } 451 | 452 | #[cfg(test)] 453 | mod K2Tree_common_util { 454 | use super::*; 455 | #[test] 456 | fn layer_len() { 457 | let tree = K2Tree::test_tree(2); 458 | assert_eq!(4, tree.layer_len(0)); 459 | assert_eq!(12, tree.layer_len(1)); 460 | } 461 | #[test] 462 | fn get_coords() { 463 | let expected_coords = [ 464 | [4, 0], [5, 0], [4, 1], [5, 1], // Leaf 1 465 | [6, 0], [7, 0], [6, 1], [7, 1], // Leaf 2 466 | [6, 2], [7, 2], [6, 3], [7, 3], // Leaf 3 467 | [0, 4], [1, 4], [0, 5], [1, 5], // Leaf 4 468 | [4, 4], [5, 4], [4, 5], [5, 5], // Leaf 5 469 | ]; 470 | let tree = K2Tree::test_tree(2); 471 | for (leaf_offset, _) in tree.leaves.iter().enumerate() { 472 | assert_eq!( 473 | expected_coords[leaf_offset], 474 | tree.get_coords(leaf_offset) 475 | ); 476 | } 477 | } 478 | } 479 | -------------------------------------------------------------------------------- /src/matrix.rs: -------------------------------------------------------------------------------- 1 | 2 | use bitvec::vec::BitVec; 3 | use crate::error::BitMatrixError; 4 | 5 | type Result = std::result::Result; 6 | 7 | /// A 2-d bit-matrix. 8 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] 9 | pub struct BitMatrix { 10 | /// Width of the matrix. 11 | pub width: usize, 12 | /// Height of the matrix. 13 | pub height: usize, 14 | bits: BitVec, 15 | } 16 | impl BitMatrix { 17 | /// Creates an empty BitMatrix with zero width or height. 18 | pub fn new() -> Self { 19 | BitMatrix { 20 | width: 0, 21 | height: 0, 22 | bits: BitVec::new(), 23 | } 24 | } 25 | /// Creates an empty BitMatrix with predefined dimensions. 26 | pub fn with_dimensions(width: usize, height: usize) -> Self { 27 | let mut bits = BitVec::with_capacity(width*height); 28 | bits.resize_with(width*height, Default::default); 29 | BitMatrix { 30 | width, 31 | height, 32 | bits, 33 | } 34 | } 35 | /// Builds a BitMatrix instance from another collection of bits. 36 | /// 37 | /// If the data passed in contains more bits than will fit a matrix of the specified 38 | /// height and width, excess data is discarded. If not enough bits are passed in, 0s 39 | /// will be appended until the right size is reached. 40 | pub fn from_bits(width: usize, height: usize, data: impl IntoIterator) -> Self { 41 | let mut bits: BitVec = data.into_iter().collect(); 42 | bits.resize_with(width*height, Default::default); 43 | BitMatrix { 44 | width, 45 | height, 46 | bits, 47 | } 48 | } 49 | /// Returns the state of a bit at a specific coordinate. 50 | pub fn get(&self, x: usize, y: usize) -> Result { 51 | if x >= self.width || y >= self.height { 52 | return Err(BitMatrixError::OutOfBounds { 53 | x_y: [x, y], 54 | max_x_y: [self.width-1, self.height-1], 55 | }) 56 | } 57 | let index = y*self.width + x; 58 | return match self.bits.get(index) { 59 | Some(&bit) => Ok(bit), 60 | None => Err(BitMatrixError::OutOfBounds { 61 | x_y: [x, y], 62 | max_x_y: [self.width-1, self.height-1], 63 | }), 64 | }; 65 | } 66 | /// Returns the state of all the bits at a specific x-coordinate. 67 | /// 68 | /// Bits are ordered by row, starting at y-coordinate 0. 69 | pub fn get_column(&self, x: usize) -> Result> { 70 | if x >= self.width { 71 | return Err(BitMatrixError::OutOfBounds { 72 | x_y: [x, 0], 73 | max_x_y: [self.width-1, self.height-1], 74 | }) 75 | } 76 | let mut column = Vec::new(); 77 | for row in 0..self.height { 78 | column.push(self.bits[x + (row * self.width)]); 79 | } 80 | Ok(column) 81 | } 82 | /// Returns the state of all the bits at a specific y-coordinate. 83 | /// 84 | /// Bits are ordered by column, starting at x-coordinate 0. 85 | pub fn get_row(&self, y: usize) -> Result> { 86 | if y >= self.height { 87 | return Err(BitMatrixError::OutOfBounds { 88 | x_y: [0, y], 89 | max_x_y: [self.width-1, self.height-1], 90 | }) 91 | } 92 | let mut row = Vec::new(); 93 | for column in 0..self.width { 94 | row.push(self.bits[(y * self.width) + column]); 95 | } 96 | Ok(row) 97 | } 98 | /// Changes the state of a bit at a specififc coordinate. 99 | pub fn set(&mut self, x: usize, y: usize, state: bool) -> Result<()> { 100 | if x >= self.width || y >= self.height { 101 | return Err(BitMatrixError::OutOfBounds { 102 | x_y: [x, y], 103 | max_x_y: [self.width-1, self.height-1], 104 | }) 105 | } 106 | let index: usize = y*self.width + x; 107 | self.bits.set(index, state); 108 | Ok(()) 109 | } 110 | /// Changes the width of the matrix. 111 | /// 112 | /// If len is greater than matrix's width, each row is extended with 0s. 113 | /// Otherwise, each row is concatenated. 114 | pub fn resize_width(&mut self, len: usize) { 115 | // Add or remove values at the correct spaces from the end backwards, 116 | // as to not change the index of insertion sites on other rows. 117 | // Work out whether we're growing or shrinking 118 | if len > self.width { 119 | // Growing 120 | let diff = len - self.width; 121 | for row in (1..=self.height).rev() { 122 | let row_end = self.width * row; 123 | for _ in 0..diff { self.bits.insert(row_end, false); } 124 | } 125 | } 126 | else if len < self.width { 127 | // Shrinking 128 | let diff = self.width - len; 129 | for row in (1..=self.height).rev() { 130 | let row_end = self.width * row; 131 | for _ in 0..diff { self.bits.remove(row_end-diff); } 132 | } 133 | } 134 | self.width = len; 135 | } 136 | /// Changes the hieght of the matrix. 137 | /// 138 | /// If len is greater than matrix's height, it is extended with blank rows. 139 | /// Otherwise, the number of rows is suitably concatenated. 140 | pub fn resize_height(&mut self, len: usize) { 141 | if len > self.height { 142 | //Growing 143 | let new_rows = len - self.height; 144 | let new_bits = new_rows * self.width; 145 | let end = self.bits.len(); 146 | for _ in 0..new_bits { self.bits.insert(end, false); } 147 | } 148 | else if len < self.height { 149 | //Shrinking 150 | let less_rows = self.height - len; 151 | let less_bits = less_rows * self.width; 152 | let new_end = self.bits.len() - less_bits; 153 | for _ in 0..less_bits { self.bits.remove(new_end); } 154 | } 155 | self.height = len; 156 | } 157 | /// Produces the contents of the matrix as a flat vec of bits. 158 | /// 159 | /// Vec contains each row one after another. 160 | pub fn to_bits(&self) -> Vec { 161 | let mut bits = Vec::with_capacity(self.bits.len()); 162 | bits.extend(&self.bits); 163 | bits 164 | } 165 | /// Consumes the BitMatrix to produce its contents as a flat vec of bits. 166 | /// 167 | /// Vec contains each row one after another. 168 | pub fn into_bits(self) -> Vec { 169 | let mut bits = Vec::with_capacity(self.bits.len()); 170 | bits.extend(&self.bits); 171 | bits 172 | } 173 | /// Produces the contents of the matrix as a vec of its columns. 174 | pub fn to_columns(&self) -> Vec> { 175 | let mut vecs = vec![Vec::with_capacity(self.height); self.width]; 176 | for column in 0..self.width { 177 | for row in 0..self.height { 178 | vecs[column].push(self.bits[row*self.width + column]); 179 | } 180 | } 181 | vecs 182 | } 183 | /// Consumes the BitMatrix to produce its contents as a vec of its columns. 184 | pub fn into_columns(self) -> Vec> { 185 | let mut vecs = vec![Vec::with_capacity(self.height); self.width]; 186 | for column in 0..self.width { 187 | for row in 0..self.height { 188 | vecs[column].push(self.bits[row*self.width + column]); 189 | } 190 | } 191 | vecs 192 | } 193 | /// Produces the contents of the matrix as a vec of its rows. 194 | pub fn to_rows(&self) -> Vec> { 195 | let mut vecs = vec![Vec::with_capacity(self.width); self.height]; 196 | for row in 0..self.height { 197 | vecs[row].extend(&self.bits[row*self.width..(row+1)*self.width]); 198 | } 199 | vecs 200 | } 201 | /// Consumes the BitMatrix to produce its contents as a vec of its rows. 202 | pub fn into_rows(self) -> Vec> { 203 | let mut vecs = vec![Vec::with_capacity(self.width); self.height]; 204 | for row in 0..self.height { 205 | vecs[row].extend(&self.bits[row*self.width..(row+1)*self.width]); 206 | } 207 | vecs 208 | } 209 | /// Reduces the width and height such that there are no empty columns or rows 210 | /// on the edges. 211 | pub fn shrink_to_fit(&mut self) { 212 | //Find the rightmost column containing a 1 213 | //Find the lowest row containing a 1 214 | //Set width and height to those positions 215 | for col in (0..self.width).rev() { 216 | let col_bits = { 217 | let mut bv = BitVec::new(); 218 | bv.extend(self.get_column(col).unwrap()); 219 | bv 220 | }; 221 | if !all_zeroes(&col_bits, 0, col_bits.len()) { 222 | self.resize_width(col+1); 223 | break 224 | } 225 | } 226 | for row in (0..self.height).rev() { 227 | let row_bits = { 228 | let mut bv = BitVec::new(); 229 | bv.extend(self.get_row(row).unwrap()); 230 | bv 231 | }; 232 | if !all_zeroes(&row_bits, 0, row_bits.len()) { 233 | self.resize_height(row+1); 234 | break 235 | } 236 | } 237 | } 238 | } 239 | impl Default for BitMatrix { 240 | fn default() -> Self { 241 | BitMatrix::new() 242 | } 243 | } 244 | 245 | fn all_zeroes(bits: &BitVec, begin: usize, end: usize) -> bool { 246 | bits[begin..end].into_iter().fold(true, |total, bit| total & !bit) 247 | } 248 | 249 | #[cfg(test)] 250 | mod api { 251 | use super::*; 252 | #[test] 253 | fn new() { 254 | let m = BitMatrix::new(); 255 | assert_eq!(0, m.width); 256 | assert_eq!(0, m.height); 257 | assert_eq!(Vec::::new(), m.into_bits()); 258 | } 259 | #[test] 260 | fn with_dimensions_0() { 261 | let m = BitMatrix::with_dimensions(8, 8); 262 | assert_eq!(8, m.width); 263 | assert_eq!(8, m.height); 264 | assert_eq!(vec![false; 64], m.into_bits()); 265 | } 266 | #[test] 267 | fn with_dimensions_1() { 268 | let m = BitMatrix::with_dimensions(0, 0); 269 | assert_eq!(0, m.width); 270 | assert_eq!(0, m.height); 271 | assert_eq!(vec![false; 0], m.to_bits()); 272 | assert_eq!(BitMatrix::new(), m); 273 | } 274 | #[test] 275 | fn from_bit_0() { 276 | let bits = vec![ 277 | false,false,false,true, 278 | false,false,true,false, 279 | false,true,false,false, 280 | true,false,false,false, 281 | ]; 282 | let m = BitMatrix::from_bits(4, 4, bits.clone()); 283 | assert_eq!(4, m.width); 284 | assert_eq!(4, m.height); 285 | assert_eq!(bits, m.into_bits()); 286 | } 287 | #[test] 288 | fn from_bits_1() { 289 | let input_bits = vec![ 290 | false,false,false,true, 291 | false,false,true,false, 292 | false,true,false,false, 293 | true, 294 | ]; 295 | let expected_bits = vec![ 296 | false,false,false,true, 297 | false,false,true,false, 298 | false,true,false,false, 299 | true,false,false,false, 300 | ]; 301 | let m = BitMatrix::from_bits(4, 4, input_bits.clone()); 302 | assert_eq!(4, m.width); 303 | assert_eq!(4, m.height); 304 | assert_eq!(expected_bits, m.into_bits()); 305 | } 306 | #[test] 307 | fn from_bits_2() { 308 | let input_bits = vec![ 309 | false,false,false,true, 310 | false,false,true,false, 311 | false,true,false,false, 312 | true,false,false,false,true,true,false,false,true // excess bits to be discarded 313 | ]; 314 | let expected_bits = vec![ 315 | false,false,false,true, 316 | false,false,true,false, 317 | false,true,false,false, 318 | true,false,false,false, 319 | ]; 320 | let m = BitMatrix::from_bits(4, 4, input_bits.clone()); 321 | assert_eq!(4, m.width); 322 | assert_eq!(4, m.height); 323 | assert_eq!(expected_bits, m.into_bits()); 324 | } 325 | #[test] 326 | fn get() -> Result<()> { 327 | let bits = vec![ 328 | false,false,false,true, 329 | false,false,true,false, 330 | false,true,false,false, 331 | true,false,false,false, 332 | ]; 333 | let m = BitMatrix::from_bits(4, 4, bits.clone()); 334 | assert_eq!(false, m.get(0, 0)?); 335 | assert_eq!(false, m.get(0, 1)?); 336 | assert_eq!(true, m.get(3, 0)?); 337 | assert_eq!(true, m.get(2, 1)?); 338 | assert_eq!(true, m.get(1, 2)?); 339 | assert_eq!(true, m.get(0, 3)?); 340 | assert_eq!(false, m.get(3, 3)?); 341 | assert_eq!(BitMatrixError::OutOfBounds { 342 | x_y: [4, 4], 343 | max_x_y: [3, 3] 344 | }, 345 | m.get(4, 4).unwrap_err() 346 | ); 347 | Ok(()) 348 | } 349 | #[test] 350 | fn set() -> Result<()> { 351 | let mut m = BitMatrix::with_dimensions(8, 8); 352 | assert_eq!(false, m.get(0, 0)?); 353 | m.set(0, 0, true)?; 354 | assert_eq!(true, m.get(0, 0)?); 355 | m.set(0, 0, false)?; 356 | assert_eq!(false, m.get(0, 0)?); 357 | m.set(3, 3, true)?; 358 | assert_eq!(true, m.get(3, 3)?); 359 | assert_eq!(false, m.get(2, 3)?); 360 | assert_eq!(false, m.get(3, 2)?); 361 | assert_eq!(BitMatrixError::OutOfBounds { 362 | x_y: [8, 8], 363 | max_x_y: [7, 7] 364 | }, 365 | m.set(8, 8, true).unwrap_err() 366 | ); 367 | Ok(()) 368 | } 369 | #[test] 370 | fn resize_width_grow() -> Result<()> { 371 | let bits = vec![ 372 | false,false,false,true, 373 | false,false,true,false, 374 | false,true,false,false, 375 | true,false,false,false, 376 | ]; 377 | let mut m = BitMatrix::from_bits(4, 4, bits); 378 | assert_eq!(4, m.width); 379 | assert_eq!(true, m.get(3, 0)?); 380 | assert!(m.get(7, 0).is_err()); 381 | m.resize_width(8); 382 | assert_eq!(8, m.width); 383 | assert_eq!(true, m.get(3, 0)?); 384 | assert_eq!(false, m.get(4, 0)?); 385 | assert_eq!(false, m.get(7, 0)?); 386 | Ok(()) 387 | } 388 | #[test] 389 | fn resize_width_shrink() -> Result<()> { 390 | let bits = vec![ 391 | false,false,false,true, 392 | false,true,true,false, 393 | false,true,false,false, 394 | true,false,false,false, 395 | ]; 396 | let mut m = BitMatrix::from_bits(4, 4, bits); 397 | assert_eq!(4, m.width); 398 | assert_eq!(true, m.get(3, 0)?); 399 | assert_eq!(true, m.get(1, 2)?); 400 | m.resize_width(2); 401 | assert_eq!(2, m.width); 402 | assert!(m.get(3, 0).is_err()); 403 | assert_eq!(false, m.get(1, 0)?); 404 | assert_eq!(true, m.get(1, 1)?); 405 | assert_eq!(BitMatrixError::OutOfBounds { 406 | x_y: [2, 3], 407 | max_x_y: [1, 3] 408 | }, 409 | m.get(2, 3).unwrap_err() 410 | ); 411 | Ok(()) 412 | } 413 | #[test] 414 | fn resize_height_grow() -> Result<()> { 415 | let bits = vec![ 416 | false,false,false,true, 417 | false,false,true,false, 418 | false,true,false,false, 419 | true,false,false,false, 420 | ]; 421 | let mut m = BitMatrix::from_bits(4, 4, bits); 422 | assert_eq!(4, m.height); 423 | assert_eq!(true, m.get(0, 3)?); 424 | assert!(m.get(0, 5).is_err()); 425 | m.resize_height(8); 426 | assert_eq!(8, m.height); 427 | assert_eq!(true, m.get(0, 3)?); 428 | assert_eq!(false, m.get(0, 5)?); 429 | Ok(()) 430 | } 431 | #[test] 432 | fn resize_height_shrink() -> Result<()> { 433 | let bits = vec![ 434 | false,false,false,true, 435 | false,true,true,false, 436 | false,true,false,false, 437 | true,false,false,false, 438 | ]; 439 | let mut m = BitMatrix::from_bits(4, 4, bits); 440 | assert_eq!(4, m.height); 441 | assert_eq!(true, m.get(0, 3)?); 442 | assert_eq!(false, m.get(0, 1)?); 443 | m.resize_height(2); 444 | assert_eq!(2, m.height); 445 | assert!(m.get(0, 3).is_err()); 446 | assert_eq!(false, m.get(0, 1)?); 447 | assert_eq!(true, m.get(1, 1)?); 448 | assert_eq!(BitMatrixError::OutOfBounds { 449 | x_y: [3, 2], 450 | max_x_y: [3, 1] 451 | }, 452 | m.get(3, 2).unwrap_err() 453 | ); 454 | Ok(()) 455 | } 456 | #[test] 457 | fn to_bits() { 458 | let bits = vec![ 459 | false,false,false,true, 460 | false,false,true,false, 461 | false,true,false,false, 462 | true,false,false,false, 463 | ]; 464 | assert_eq!(bits, BitMatrix::from_bits(4, 4, bits.clone()).to_bits()); 465 | } 466 | #[test] 467 | fn into_bits() { 468 | let bits = vec![ 469 | false,false,false,true, 470 | false,false,true,false, 471 | false,true,false,false, 472 | true,false,false,false, 473 | ]; 474 | assert_eq!(bits, BitMatrix::from_bits(4, 4, bits.clone()).into_bits()); 475 | } 476 | #[test] 477 | fn to_columns() { 478 | let bits = vec![ 479 | false,false,false,true, 480 | false,false,true,false, 481 | false,true,false,false, 482 | true,false,false,false, 483 | ]; 484 | let vecs = BitMatrix::from_bits(4, 4, bits.clone()).to_columns(); 485 | assert_eq!(4, vecs.len()); 486 | for column in 0..4 { assert_eq!(4, vecs[column].len()); } 487 | assert_eq!(vec![bits[0], bits[4], bits[8], bits[12]], vecs[0]); 488 | assert_eq!(vec![bits[1], bits[5], bits[9], bits[13]], vecs[1]); 489 | assert_eq!(vec![bits[2], bits[6], bits[10], bits[14]], vecs[2]); 490 | assert_eq!(vec![bits[3], bits[7], bits[11], bits[15]], vecs[3]); 491 | } 492 | #[test] 493 | fn into_columns() { 494 | let bits = vec![ 495 | false,false,false,true, 496 | false,false,true,false, 497 | false,true,false,false, 498 | true,false,false,false, 499 | ]; 500 | let vecs = BitMatrix::from_bits(4, 4, bits.clone()).into_columns(); 501 | assert_eq!(4, vecs.len()); 502 | for column in 0..4 { assert_eq!(4, vecs[column].len()); } 503 | assert_eq!(vec![bits[0], bits[4], bits[8], bits[12]], vecs[0]); 504 | assert_eq!(vec![bits[1], bits[5], bits[9], bits[13]], vecs[1]); 505 | assert_eq!(vec![bits[2], bits[6], bits[10], bits[14]], vecs[2]); 506 | assert_eq!(vec![bits[3], bits[7], bits[11], bits[15]], vecs[3]); 507 | } 508 | #[test] 509 | fn to_rows() { 510 | let bits = vec![ 511 | false,false,false,true, 512 | false,false,true,false, 513 | false,true,false,false, 514 | true,false,false,false, 515 | ]; 516 | let rows = BitMatrix::from_bits(4, 4, bits.clone()).to_rows(); 517 | assert_eq!(4, rows.len()); 518 | for row in 0..4 { assert_eq!(4, rows[row].len()); } 519 | assert_eq!(bits[0..4].to_vec(), rows[0]); 520 | assert_eq!(bits[4..8].to_vec(), rows[1]); 521 | assert_eq!(bits[8..12].to_vec(), rows[2]); 522 | assert_eq!(bits[12..16].to_vec(), rows[3]); 523 | } 524 | #[test] 525 | fn into_rows() { 526 | let bits = vec![ 527 | false,false,false,true, 528 | false,false,true,false, 529 | false,true,false,false, 530 | true,false,false,false, 531 | ]; 532 | let rows = BitMatrix::from_bits(4, 4, bits.clone()).into_rows(); 533 | assert_eq!(4, rows.len()); 534 | for row in 0..4 { assert_eq!(4, rows[row].len()); } 535 | assert_eq!(bits[0..4].to_vec(), rows[0]); 536 | assert_eq!(bits[4..8].to_vec(), rows[1]); 537 | assert_eq!(bits[8..12].to_vec(), rows[2]); 538 | assert_eq!(bits[12..16].to_vec(), rows[3]); 539 | } 540 | #[test] 541 | fn get_column() -> Result<()> { 542 | let bits = vec![ 543 | false,false,false,true, 544 | false,false,true,false, 545 | false,true,false,false, 546 | true,false,false,false, 547 | ]; 548 | let m = BitMatrix::from_bits(4, 4, bits.clone()); 549 | assert_eq!( 550 | vec![false,false,false,true], 551 | m.get_column(0)? 552 | ); 553 | assert_eq!( 554 | vec![false,false,true,false], 555 | m.get_column(1)? 556 | ); 557 | assert_eq!( 558 | vec![false,true,false,false], 559 | m.get_column(2)? 560 | ); 561 | assert_eq!( 562 | vec![true,false,false,false], 563 | m.get_column(3)? 564 | ); 565 | Ok(()) 566 | } 567 | #[test] 568 | fn get_row() -> Result<()> { 569 | let bits = vec![ 570 | false,false,false,true, 571 | false,false,true,false, 572 | false,true,false,false, 573 | true,false,false,false, 574 | ]; 575 | let m = BitMatrix::from_bits(4, 4, bits.clone()); 576 | assert_eq!( 577 | vec![false,false,false,true], 578 | m.get_row(0)? 579 | ); 580 | assert_eq!( 581 | vec![false,false,true,false], 582 | m.get_row(1)? 583 | ); 584 | assert_eq!( 585 | vec![false,true,false,false], 586 | m.get_row(2)? 587 | ); 588 | assert_eq!( 589 | vec![true,false,false,false], 590 | m.get_row(3)? 591 | ); 592 | Ok(()) 593 | } 594 | #[test] 595 | fn shrink_to_fit() { 596 | let bits = vec![ 597 | true,true,false,false, 598 | true,false,true,false, 599 | false,false,false,false, 600 | false,false,false,false, 601 | ]; 602 | let mut m = BitMatrix::from_bits(4, 4, bits.clone()); 603 | assert_eq!(4, m.width); 604 | assert_eq!(4, m.height); 605 | m.shrink_to_fit(); 606 | assert_eq!(3, m.width); 607 | assert_eq!(2, m.height); 608 | } 609 | } 610 | -------------------------------------------------------------------------------- /src/tree/datastore.rs: -------------------------------------------------------------------------------- 1 | use { 2 | std::fmt, 3 | bitvec::{prelude::{bitvec, bitbox, BitVec}}, 4 | serde::{ 5 | Serialize, 6 | Deserialize, 7 | Serializer, 8 | Deserializer, 9 | ser::SerializeStruct, 10 | de::{self, Visitor, MapAccess} 11 | }, 12 | crate::error::K2TreeError as Error, 13 | crate::tree::*, 14 | crate::matrix::BitMatrix, 15 | }; 16 | 17 | type Result = std::result::Result; 18 | 19 | /// A collection designed to efficiently compress sparsely-populated bit-matrices. 20 | /// 21 | /// The `K2Tree` represents a matrix of bits and behaves ***as if*** it is a bit-matrix. 22 | /// The `k` value of this structure is currently fixed at 2, but future updates may allow customisation. 23 | /// The matrix represented by the `K2Tree` must always be square, with a width/height equal to a power of k: 8, 16, 32 etc. 24 | /// This isn't much of an issue because almost all empty cells in the matrix are compressed-away, so don't stress about wasted columns/rows. 25 | /// 26 | /// ``` 27 | /// fn main() -> Result<(), k2_tree::error::K2TreeError> { 28 | /// use k2_tree::K2Tree; 29 | /// //matrix_width = 8, k = 2 30 | /// let mut tree = K2Tree::with_k(2, 2)?; 31 | /// tree.set(0, 4, true); 32 | /// tree.set(6, 5, true); 33 | /// tree.set(0, 4, false); 34 | /// assert_eq!(false, tree.get(0, 4)?); 35 | /// assert_eq!(true, tree.get(6, 5)?); 36 | /// assert_eq!(false, tree.get(0, 0)?); 37 | /// Ok(()) 38 | /// } 39 | /// ``` 40 | #[derive(Debug, Clone)] 41 | pub struct K2Tree { 42 | /// The k value of the K2Tree's stems. 43 | pub stem_k: usize, 44 | /// The k value of the K2Tree's leaves. 45 | pub leaf_k: usize, 46 | /// The maximum number of stem-layers possible given the matrix_width. 47 | pub max_slayers: usize, 48 | /// The bits that comprise the stems of the tree. 49 | pub stems: BitVec, 50 | /// The bits that comprise the leaves of the tree. 51 | pub leaves: BitVec, 52 | } 53 | 54 | /* Public */ 55 | impl K2Tree { 56 | /// Returns a `K2Tree` representing an 8x8 bit-matrix of all 0s. K = 2. 57 | /// ``` 58 | /// use k2_tree::K2Tree; 59 | /// let tree = K2Tree::new(); 60 | /// assert!(tree.is_empty()); 61 | /// assert_eq!(8, tree.matrix_width()); 62 | /// assert_eq!(2, tree.stem_k); 63 | /// assert_eq!(2, tree.leaf_k); 64 | /// ``` 65 | pub fn new() -> Self { 66 | K2Tree { 67 | stem_k: 2, 68 | leaf_k: 2, 69 | max_slayers: 2, 70 | stems: bitvec![0; 4], 71 | leaves: BitVec::new(), 72 | } 73 | } 74 | /// Returns a `K2Tree` with a specified k-value, which represents an empty bit-matrix 75 | /// of width `k.pow(3)`. 76 | /// 77 | /// Returns a SmallKValue error if k < 2. 78 | /// ``` 79 | /// fn main() -> Result<(), k2_tree::error::K2TreeError> { 80 | /// use k2_tree::K2Tree; 81 | /// let tree = K2Tree::with_k(4, 4)?; 82 | /// assert!(tree.is_empty()); 83 | /// assert_eq!(4usize.pow(3), tree.matrix_width()); 84 | /// assert_eq!(64, tree.matrix_width()); 85 | /// assert_eq!(4, tree.stem_k); 86 | /// assert_eq!(4, tree.leaf_k); 87 | /// Ok(()) 88 | /// } 89 | /// ``` 90 | pub fn with_k(stem_k: usize, leaf_k: usize) -> Result { 91 | if stem_k < 2 { 92 | return Err(Error::SmallStemKValue { stem_k: stem_k as u8 }) 93 | } 94 | else if leaf_k < 2 { 95 | return Err(Error::SmallLeafKValue { leaf_k: leaf_k as u8 }) 96 | } 97 | Ok(K2Tree { 98 | stem_k, 99 | leaf_k, 100 | max_slayers: 2, 101 | stems: bitvec![0; stem_k*stem_k], 102 | leaves: BitVec::new(), 103 | }) 104 | } 105 | /// Changes the stem_k value of a `K2Tree`. This can be a time and space expensive operation 106 | /// for large, non-sparse datasets. 107 | /// Returns a SmallKValue error if stem_k < 2. 108 | /// ``` 109 | /// fn main() -> Result<(), k2_tree::error::K2TreeError> { 110 | /// use k2_tree::K2Tree; 111 | /// let mut tree = K2Tree::new(); 112 | /// tree.set_stem_k(4); 113 | /// assert!(tree.set_stem_k(1).is_err()); 114 | /// Ok(()) 115 | /// } 116 | /// ``` 117 | pub fn set_stem_k(&mut self, stem_k: usize) -> Result<()> { 118 | if self.stem_k == stem_k { return Ok(()) } 119 | if stem_k < 2 { 120 | return Err(Error::SmallStemKValue{stem_k: stem_k as u8}) 121 | } 122 | *self = K2Tree::from_matrix(self.to_matrix()?, stem_k, self.leaf_k)?; 123 | Ok(()) 124 | } 125 | /// Changes the leaf_k value of a `K2Tree`. This can be a time and space expensive operation 126 | /// for large, non-sparse datasets. 127 | /// Returns a SmallKValue error if stem_k < 2. 128 | /// ``` 129 | /// fn main() -> Result<(), k2_tree::error::K2TreeError> { 130 | /// use k2_tree::K2Tree; 131 | /// let mut tree = K2Tree::new(); 132 | /// tree.set_leaf_k(4); 133 | /// assert!(tree.set_leaf_k(1).is_err()); 134 | /// Ok(()) 135 | /// } 136 | /// ``` 137 | pub fn set_leaf_k(&mut self, leaf_k: usize) -> Result<()> { 138 | if self.leaf_k == leaf_k { return Ok(()) } 139 | if leaf_k < 2 { 140 | return Err(Error::SmallLeafKValue{leaf_k: leaf_k as u8}) 141 | } 142 | *self = K2Tree::from_matrix(self.to_matrix()?, self.stem_k, leaf_k)?; 143 | Ok(()) 144 | } 145 | ///Returns true if a `K2Tree` contains no 1s. 146 | pub fn is_empty(&self) -> bool { 147 | self.leaves.len() == 0 148 | } 149 | /// Returns that state of a bit at a specified coordinate in the bit-matrix the 150 | /// `K2Tree` represents. 151 | /// ``` 152 | /// fn main() -> Result<(), k2_tree::error::K2TreeError> { 153 | /// use k2_tree::K2Tree; 154 | /// let mut tree = K2Tree::with_k(2, 2)?; 155 | /// tree.set(0, 1, true)?; 156 | /// assert_eq!(true, tree.get(0, 1)?); 157 | /// assert_eq!(false, tree.get(0, 0)?); 158 | /// Ok(()) 159 | /// } 160 | /// ``` 161 | pub fn get(&self, x: usize, y: usize) -> Result { 162 | let matrix_width = self.matrix_width(); 163 | if x >= matrix_width || y >= matrix_width { 164 | return Err(Error::Read { 165 | source: Box::new(Error::OutOfBounds { 166 | x_y: [x, y], 167 | min_x_y: [0, 0], 168 | max_x_y: [matrix_width-1; 2] 169 | }) 170 | }) 171 | } 172 | let descend_result = match self.matrix_bit(x, y, matrix_width) { 173 | Ok(dr) => dr, 174 | Err(e) => return Err(Error::Read { 175 | source: Box::new(e) 176 | }), 177 | }; 178 | match descend_result { 179 | DescendResult::Leaf(leaf_start, leaf_range) => { 180 | if leaf_range.width() != self.leaf_k 181 | || leaf_range.height() != self.leaf_k { 182 | return Err(Error::Read { 183 | source: Box::new(Error::TraverseError{x, y}) 184 | }) 185 | } 186 | //Calculation removes extra branches, makes it faster 187 | // range = [[5, 6], [7, 8]] 188 | // (5, 7) = 0; (6, 7) = 1; (5, 8) = 2; (6, 8) = 3 189 | let offset = (self.leaf_k * (y - leaf_range.min_y)) + (x - leaf_range.min_x); 190 | Ok(self.leaves[leaf_start+offset]) 191 | }, 192 | DescendResult::Stem(_, _) => Ok(false), 193 | } 194 | } 195 | /// Returns a BitVec containing the bits in a specified row, in order. 196 | /// ``` 197 | /// fn main() -> Result<(), k2_tree::error::K2TreeError> { 198 | /// use bitvec::prelude::bitvec; 199 | /// use k2_tree::K2Tree; 200 | /// let mut tree = K2Tree::with_k(2, 2)?; 201 | /// tree.set(1, 0, true)?; 202 | /// tree.set(3, 0, true)?; 203 | /// tree.set(6, 0, true)?; 204 | /// assert_eq!( 205 | /// vec![false,true,false,true,false,false,true,false], 206 | /// tree.get_row(0)? 207 | /// ); 208 | /// Ok(()) 209 | /// } 210 | /// ``` 211 | pub fn get_row(&self, y: usize) -> Result> { 212 | let matrix_width = self.matrix_width(); 213 | if y >= matrix_width { 214 | return Err(Error::Read { 215 | source: Box::new(Error::OutOfBounds { 216 | x_y: [0, y], 217 | min_x_y: [0, 0], 218 | max_x_y: [matrix_width-1; 2] 219 | }) 220 | }) 221 | } 222 | let mut ret_v = Vec::new(); 223 | for x in (0..matrix_width).step_by(self.leaf_k) { 224 | let descend_result = match self.matrix_bit(x, y, matrix_width) { 225 | Ok(dr) => dr, 226 | Err(e) => return Err(Error::Read { 227 | source: Box::new(e) 228 | }), 229 | }; 230 | match descend_result { 231 | DescendResult::Leaf(leaf_start, leaf_range) => { 232 | if leaf_range.width() != self.leaf_k 233 | || leaf_range.height() != self.leaf_k { 234 | return Err(Error::Read { 235 | source: Box::new(Error::TraverseError{x, y}) 236 | }) 237 | } 238 | //Calculation instead of if-else block makes hot-code much faster 239 | let offset = (self.leaf_k * (y - leaf_range.min_y)) + (x - leaf_range.min_x); 240 | for i in 0..self.leaf_k { ret_v.push(self.leaves[leaf_start+offset+i]); } 241 | }, 242 | DescendResult::Stem(_, _) => { 243 | for _ in 0..self.leaf_k { ret_v.push(false); } 244 | }, 245 | } 246 | }; 247 | Ok(ret_v) 248 | } 249 | /// Returns a BitVec containing the bits in a specified column, in order. 250 | /// ``` 251 | /// fn main() -> Result<(), k2_tree::error::K2TreeError> { 252 | /// use bitvec::prelude::bitvec; 253 | /// use k2_tree::K2Tree; 254 | /// let mut tree = K2Tree::with_k(2, 2)?; 255 | /// tree.set(1, 1, true)?; 256 | /// tree.set(1, 3, true)?; 257 | /// tree.set(1, 6, true)?; 258 | /// assert_eq!( 259 | /// vec![false,true,false,true,false,false,true,false], 260 | /// tree.get_column(1)? 261 | /// ); 262 | /// Ok(()) 263 | /// } 264 | /// ``` 265 | pub fn get_column(&self, x: usize) -> Result> { 266 | let matrix_width = self.matrix_width(); 267 | if x >= matrix_width { 268 | return Err(Error::Read { 269 | source: Box::new(Error::OutOfBounds { 270 | x_y: [x, 0], 271 | min_x_y: [0, 0], 272 | max_x_y: [matrix_width-1; 2] 273 | }) 274 | }) 275 | } 276 | let mut ret_v = Vec::new(); 277 | for y in (0..matrix_width).step_by(self.leaf_k) { 278 | let descend_result = match self.matrix_bit(x, y, matrix_width) { 279 | Ok(dr) => dr, 280 | Err(e) => return Err(Error::Read { 281 | source: Box::new(e) 282 | }), 283 | }; 284 | match descend_result{ 285 | DescendResult::Leaf(leaf_start, leaf_range) => { 286 | if leaf_range.width() != self.leaf_k 287 | || leaf_range.height() != self.leaf_k { 288 | return Err(Error::Read { 289 | source: Box::new(Error::TraverseError{x, y}) 290 | }) 291 | } 292 | let offset = (self.leaf_k * (y - leaf_range.min_y)) + (x - leaf_range.min_x); 293 | for i in 0..self.leaf_k { ret_v.push(self.leaves[leaf_start+offset+(i*self.leaf_k)]); } 294 | }, 295 | DescendResult::Stem(_, _) => { 296 | for _ in 0..self.leaf_k { ret_v.push(false); } 297 | }, 298 | } 299 | }; 300 | Ok(ret_v) 301 | } 302 | /// Sets the state of a bit at the coordinates (x, y) in the bit-matrix the 303 | /// K2Tree represents. 304 | /// ``` 305 | /// fn main() -> Result<(), k2_tree::error::K2TreeError> { 306 | /// use k2_tree::K2Tree; 307 | /// let mut tree = K2Tree::with_k(2, 2)?; 308 | /// assert_eq!(false, tree.get(0, 0)?); 309 | /// tree.set(0, 0, true)?; 310 | /// assert_eq!(true, tree.get(0, 0)?); 311 | /// Ok(()) 312 | /// } 313 | /// ``` 314 | pub fn set(&mut self, x: usize, y: usize, state: bool) -> Result<()> { 315 | let matrix_width = self.matrix_width(); 316 | if x >= matrix_width || y >= matrix_width { 317 | return Err(Error::Write { 318 | source: Box::new(Error::OutOfBounds { 319 | x_y: [x, y], 320 | min_x_y: [0, 0], 321 | max_x_y: [matrix_width-1; 2] 322 | }) 323 | }) 324 | } 325 | let stem_len = self.stem_len(); 326 | let leaf_len = self.leaf_len(); 327 | let descend_result = match self.matrix_bit(x, y, matrix_width) { 328 | Ok(dr) => dr, 329 | Err(e) => { 330 | return Err(Error::Write { 331 | source: Box::new(e) 332 | }) 333 | }, 334 | }; 335 | match descend_result { 336 | DescendResult::Leaf(leaf_start, leaf_range) => { 337 | if leaf_range.width() != self.leaf_k 338 | || leaf_range.height() != self.leaf_k { 339 | /* Final submatrix isn't a k by k so can't be a leaf */ 340 | return Err(Error::Write { 341 | source: Box::new(Error::TraverseError{x, y}) 342 | }) 343 | } 344 | /* Set the bit in the leaf to the new state */ 345 | let offset = (self.leaf_k * (y - leaf_range.min_y)) + (x - leaf_range.min_x); 346 | self.leaves.set(leaf_start+offset, state); 347 | /* If leaf is now all 0's, remove leaf and alter rest of struct to reflect changes. 348 | Loop up the stems changing the parent bits to 0's and removing stems that become all 0's */ 349 | if !state && all_zeroes(&self.leaves, leaf_start, leaf_start+leaf_len) { 350 | /* - Remove the leaf 351 | - Use find the dead leaf's parent bit 352 | - Set parent bit to 0, check if stem now all 0's 353 | - If all 0's: 354 | - - Remove stem 355 | - - Alter layer_starts if needed 356 | - - Find parent bit and set to 0 357 | - - Repeat until reach stem that isn't all 0's or reach stem layer 0 */ 358 | if let Err(()) = remove_block(&mut self.leaves, leaf_start, leaf_len) { 359 | return Err(Error::CorruptedK2Tree { 360 | source: Box::new(Error::Write { 361 | source: Box::new(Error::LeafRemovalError { 362 | pos: leaf_start, 363 | len: leaf_len 364 | }) 365 | }) 366 | }) 367 | } 368 | let stem_bit_pos = self.leaf_parent(leaf_start); //TODO: check 369 | if self.leaves.is_empty() { 370 | /* If no more leaves, then remove all stems immediately 371 | and don't bother with complex stuff below */ 372 | self.stems = bitvec![0; stem_len]; 373 | return Ok(()) 374 | } 375 | self.stems.set(stem_bit_pos, false); //Dead leaf parent bit = 0 376 | let mut curr_layer = self.max_slayers-1; 377 | let mut stem_start = self.stem_start(stem_bit_pos); 378 | while curr_layer > 0 379 | && all_zeroes(&self.stems, stem_start, stem_start+stem_len) { 380 | let [parent_stem_start, bit_offset] = self.parent(stem_start).unwrap(); 381 | if let Err(()) = remove_block(&mut self.stems, stem_start, stem_len) { 382 | return Err(Error::CorruptedK2Tree { 383 | source: Box::new(Error::Write { 384 | source: Box::new(Error::StemRemovalError { 385 | pos: stem_start, 386 | len: stem_len 387 | }) 388 | }) 389 | }) 390 | } 391 | self.stems.set(parent_stem_start + bit_offset, false); 392 | stem_start = parent_stem_start; 393 | curr_layer -= 1; 394 | } 395 | } 396 | }, 397 | DescendResult::Stem(mut stem_start, mut stem_range) if state => { 398 | /* Descend returning Stem means no Leaf containing bit at (x, y), 399 | must be located in a submatrix of all 0's. 400 | If state = false: do nothing 401 | If state = true: 402 | - Construct needed stems until reach final layer 403 | - Construct leaf corresponding to range containing (x, y) 404 | - Set bit at (x, y) to 1 */ 405 | let mut layer_starts_len = if self.is_empty() { 406 | /* K2Tree either has 1 stem at layer 1 when empty 407 | or the max possible layers when a leaf exists */ 408 | 1 409 | } else { 410 | self.max_slayers 411 | }; 412 | let mut layer = self.layer_from_range(stem_range); 413 | let mut subranges: SubRanges; 414 | /* Create correct stems in layers on the way down to the final layer, 415 | which points to the leaves */ 416 | while layer < self.max_slayers-1 { 417 | subranges = match self.to_subranges(stem_range) { 418 | Ok(subranges) => subranges, 419 | Err(error) => return Err(Error::CorruptedK2Tree { 420 | source: Box::new(Error::Write { 421 | source: Box::new(Error::SubRangesError { 422 | source: Box::new(error), 423 | }), 424 | }), 425 | }) 426 | }; 427 | let (child_pos, &subrange) = 428 | match subranges.iter().enumerate().find( 429 | |(_, subrange)| subrange.contains(x, y) 430 | ) { 431 | Some(val) => val, 432 | None => return Err(Error::CorruptedK2Tree { 433 | source: Box::new(Error::Write { 434 | source: Box::new(Error::TraverseError{x, y}) 435 | }) 436 | }) 437 | }; 438 | /* Change bit containing (x, y) to 1 */ 439 | self.stems.set(stem_start + child_pos, true); 440 | /* If we're not at max possible layer, 441 | but at the lowest existing layer: Create new layer before 442 | adding new stem to it. 443 | Otherwise: Find the correct position to add the new stem 444 | in the child layer. */ 445 | if layer == layer_starts_len-1 { 446 | stem_start = self.stems.len(); 447 | layer_starts_len += 1; 448 | } 449 | else { 450 | stem_start = match self.child_stem(layer, stem_start, child_pos) { 451 | Ok(ss) => ss, 452 | Err(()) => return Err(Error::CorruptedK2Tree { 453 | source: Box::new(Error::Write { 454 | source: Box::new(Error::TraverseError{x, y}) 455 | }) 456 | }), 457 | }; 458 | } 459 | /* We're now working on the child layer */ 460 | layer += 1; 461 | stem_range = subrange; 462 | if let Err(()) = insert_block(&mut self.stems, stem_start, stem_len) { 463 | return Err(Error::CorruptedK2Tree { 464 | source: Box::new(Error::Write { 465 | source: Box::new(Error::StemInsertionError { 466 | pos: stem_start, 467 | len: stem_len 468 | }) 469 | }) 470 | }) 471 | } 472 | } 473 | /* We're at the final stem layer */ 474 | subranges = match self.to_subranges(stem_range) { 475 | Ok(subranges) => subranges, 476 | Err(error) => return Err(Error::CorruptedK2Tree { 477 | source: Box::new(Error::Write { 478 | source: Box::new(Error::SubRangesError { 479 | source: Box::new(error), 480 | }), 481 | }), 482 | }) 483 | }; 484 | let (child_pos, &subrange) = 485 | match subranges.iter().enumerate().find( 486 | |(_, subrange)| subrange.contains(x, y) 487 | ) { 488 | Some(val) => val, 489 | None => return Err(Error::CorruptedK2Tree { 490 | source: Box::new(Error::Write { 491 | source: Box::new(Error::TraverseError{x, y}) 492 | }) 493 | }) 494 | }; 495 | /* Set the correct stem bit to 1 */ 496 | self.stems.set(stem_start + child_pos, true); 497 | /* Find the index to insert the new leaf */ 498 | let nth_leaf = ones_in_range( 499 | &self.stems, 500 | self.layer_start(self.max_slayers-1), 501 | stem_start + child_pos 502 | ); 503 | let leaf_start = nth_leaf * leaf_len; //TODO: Check 504 | /* Create new leaf of all 0's */ 505 | if let Err(()) = insert_block(&mut self.leaves, leaf_start, leaf_len) { 506 | return Err(Error::CorruptedK2Tree { 507 | source: Box::new(Error::Write { 508 | source: Box::new(Error::LeafInsertionError { 509 | pos: leaf_start, 510 | len: leaf_len 511 | }) 512 | }) 513 | }) 514 | } 515 | /* Change bit at (x, y) to 1 */ 516 | let leaf_range = subrange; 517 | let offset = (self.leaf_k * (y - leaf_range.min_y)) + (x - leaf_range.min_x); 518 | self.leaves.set(leaf_start+offset, true); 519 | } 520 | _ => {}, 521 | }; 522 | Ok(()) 523 | } 524 | /// Returns the width of the bit-matrix that a K2Tree represents. 525 | /// 526 | /// The matrix is always square, so this is also the height. 527 | /// 528 | /// This can only have certain values, depending on the values of leaf_k and stem_k, 529 | /// so it is common for a K2Tree's matrix_width to be greater than the matrix it 530 | /// was built from. Thankfully, trailing rows/columns have no affect on the size 531 | /// of the K2Tree. 532 | /// ``` 533 | /// fn main() -> Result<(), k2_tree::error::K2TreeError> { 534 | /// use k2_tree::{K2Tree, matrix::BitMatrix}; 535 | /// let matrix = BitMatrix::with_dimensions(8, 8); 536 | /// let tree = K2Tree::from_matrix(matrix, 2, 2)?; 537 | /// assert_eq!(8, tree.matrix_width()); 538 | /// Ok(()) 539 | /// } 540 | /// ``` 541 | pub fn matrix_width(&self) -> usize { 542 | self.leaf_k * (self.stem_k.pow(self.max_slayers as u32)) 543 | } 544 | /// Returns an iterator over the K2Tree's stems which produces instances of StemBit. 545 | /// 546 | /// StemBit contains extra information on the layer, block and offset of the specific 547 | /// bit in the stems. 548 | pub fn stems(&self) -> iterators::Stems<'_> { 549 | iterators::Stems::new(self) 550 | } 551 | /// Consumes the K2Tree to return an iterator over its stems, which produces instances of StemBit. 552 | /// 553 | /// StemBit contains extra information on the layer, block and offset of the specific 554 | /// bit in the stems. 555 | pub fn into_stems(self) -> iterators::IntoStems { 556 | iterators::IntoStems::new(self) 557 | } 558 | /// Returns an iterator over the K2Tree's stems which produces only the raw boolean values. 559 | pub fn stems_raw(&self) -> iterators::StemsRaw<'_> { 560 | iterators::StemsRaw::new(self) 561 | } 562 | /// Returns an iterator over the K2Tree's leaves which produces instances of LeafBit. 563 | /// 564 | /// LeafBit contains extra information on the exact coordinates of each bit in the leaves. 565 | pub fn leaves(&self) -> iterators::Leaves<'_> { 566 | iterators::Leaves::new(self) 567 | } 568 | /// Consumes the K2Tree to return an iterator over its leaves, which produces instances of LeafBit. 569 | /// 570 | /// LeafBit contains extra information on the exact coordinates of each bit in the leaves. 571 | pub fn into_leaves(self) -> iterators::IntoLeaves { 572 | iterators::IntoLeaves::new(self) 573 | } 574 | /// Returns an iterator over the K2Tree's leaves which produces only the raw boolean values. 575 | pub fn leaves_raw(&self) -> iterators::LeavesRaw<'_> { 576 | iterators::LeavesRaw::new(self) 577 | } 578 | /// Increases the height and width of the matrix the K2Tree represents by a factor of k. 579 | /// ``` 580 | /// fn main() -> Result<(), k2_tree::error::K2TreeError> { 581 | /// use k2_tree::K2Tree; 582 | /// let mut tree = K2Tree::with_k(2, 2)?; 583 | /// assert_eq!(2, tree.stem_k); 584 | /// assert_eq!(2, tree.leaf_k); 585 | /// assert_eq!(8, tree.matrix_width()); 586 | /// tree.grow(); 587 | /// assert_eq!(16, tree.matrix_width()); 588 | /// tree.grow(); 589 | /// assert_eq!(32, tree.matrix_width()); 590 | /// Ok(()) 591 | /// } 592 | /// ``` 593 | pub fn grow(&mut self) { 594 | let stem_len = self.stem_len(); 595 | self.max_slayers += 1; 596 | if !self.is_empty() { 597 | /* Only insert the extra layers etc. if the 598 | tree isn't all 0s */ 599 | for _ in 0..stem_len-1 { self.stems.insert(0, false); } 600 | self.stems.insert(0, true); 601 | } 602 | } 603 | /// Only shrinks the height and width of the matrix the K2Tree represents by a factor of k 604 | /// if it is possible. 605 | /// 606 | /// Does not Err if the matrix cannot be shrunk i.e. it is already at the minimum size. 607 | /// ``` 608 | /// fn main() -> Result<(), k2_tree::error::K2TreeError> { 609 | /// use k2_tree::K2Tree; 610 | /// let mut tree = K2Tree::with_k(2, 2)?; 611 | /// tree.grow(); 612 | /// assert_eq!(16, tree.matrix_width()); 613 | /// tree.shrink_if_possible(); 614 | /// assert_eq!(8, tree.matrix_width()); 615 | /// tree.shrink_if_possible(); 616 | /// assert_eq!(8, tree.matrix_width()); 617 | /// Ok(()) 618 | /// } 619 | /// ``` 620 | pub fn shrink_if_possible(&mut self) { 621 | match self.shrink() { 622 | _ => () 623 | } 624 | } 625 | /// Attempts to reduce the height and width of the matrix the K2Tree represents by a factor of k. 626 | /// 627 | /// Returns an Err if the matrix cannot be shrunk i.e. it is already at the minimum size. 628 | /// ``` 629 | /// fn main() -> Result<(), k2_tree::error::K2TreeError> { 630 | /// use k2_tree::K2Tree; 631 | /// let mut tree = K2Tree::with_k(2, 2)?; 632 | /// tree.grow(); 633 | /// assert_eq!(16, tree.matrix_width()); 634 | /// assert!(tree.shrink().is_ok()); 635 | /// assert_eq!(8, tree.matrix_width()); 636 | /// assert!(tree.shrink().is_err()); 637 | /// Ok(()) 638 | /// } 639 | /// ``` 640 | pub fn shrink(&mut self) -> Result<()> { 641 | let stem_len = self.stem_len(); 642 | if self.matrix_width() <= self.leaf_k * self.stem_k.pow(2) { 643 | return Err(Error::CouldNotShrink { 644 | reason: format!("Already at minimum size: {}", self.matrix_width()) 645 | }) 646 | } 647 | else if self.stems[1..stem_len] != bitbox![0; stem_len-1] { 648 | return Err(Error::CouldNotShrink { 649 | reason: "Shrinking would lose information about the matrix".into() 650 | }) 651 | } 652 | self.max_slayers -= 1; 653 | /* Remove top layer stem */ 654 | for _ in 0..stem_len { self.stems.remove(0); } 655 | Ok(()) 656 | } 657 | /// Reduces the height and width of the matrix the K2Tree represents by a factor of k without 658 | /// doing any bounds checking before or integrity checking afterwards. 659 | /// 660 | /// # Safety 661 | /// Do not attempt to shrink matrix_width smaller than k^3. 662 | /// 663 | /// ``` 664 | /// fn main() -> Result<(), k2_tree::error::K2TreeError> { 665 | /// use k2_tree::K2Tree; 666 | /// let mut tree = K2Tree::with_k(2, 2)?; 667 | /// tree.grow(); 668 | /// assert_eq!(16, tree.matrix_width()); 669 | /// unsafe { tree.shrink_unchecked(); } 670 | /// assert_eq!(8, tree.matrix_width()); 671 | /// Ok(()) 672 | /// } 673 | /// ``` 674 | pub unsafe fn shrink_unchecked(&mut self) { 675 | let stem_len = self.stem_len(); 676 | self.max_slayers -= 1; 677 | /* Remove top layer stem */ 678 | for _ in 0..stem_len { self.stems.remove(0); } 679 | } 680 | /// Comsumes the K2Tree to produce the bit-matrix it represented. 681 | /// 682 | /// The matrix is presented as a list of columns of bits, Vec>. 683 | /// ``` 684 | /// fn main() -> Result<(), k2_tree::error::K2TreeError> { 685 | /// use k2_tree::K2Tree; 686 | /// let mut tree = K2Tree::with_k(2, 2)?; 687 | /// tree.set(0, 0, true)?; 688 | /// tree.set(5, 6, true)?; 689 | /// tree.set(7, 7, true)?; 690 | /// let matrix = tree.into_matrix()?; 691 | /// assert_eq!(true, matrix.get(0, 0).unwrap()); 692 | /// assert_eq!(true, matrix.get(5, 6).unwrap()); 693 | /// assert_eq!(true, matrix.get(7, 7).unwrap()); 694 | /// assert_eq!(false, matrix.get(4, 3).unwrap()); 695 | /// Ok(()) 696 | /// } 697 | /// ``` 698 | pub fn into_matrix(self) -> Result { 699 | let matrix_width = self.matrix_width(); 700 | let mut m = BitMatrix::with_dimensions(matrix_width, matrix_width); 701 | for (pos, &state) in self.leaves.iter().enumerate() { 702 | if state { 703 | let [x, y] = self.get_coords(pos); 704 | if let Err(e) = m.set(x, y, true) { 705 | return Err(Error::BitMatrixError { 706 | source: Box::new(e), 707 | }) 708 | } 709 | } 710 | } 711 | Ok(m) 712 | } 713 | /// Produces the bit-matrix a K2Tree represents. 714 | /// 715 | /// The matrix is presented as a list of columns of bits, Vec>. 716 | /// ``` 717 | /// fn main() -> Result<(), k2_tree::error::K2TreeError> { 718 | /// use k2_tree::K2Tree; 719 | /// let mut tree = K2Tree::with_k(2, 2)?; 720 | /// tree.set(0, 0, true)?; 721 | /// tree.set(5, 6, true)?; 722 | /// tree.set(7, 7, true)?; 723 | /// let matrix = tree.to_matrix()?; 724 | /// assert_eq!(true, matrix.get(0, 0).unwrap()); 725 | /// assert_eq!(true, matrix.get(5, 6).unwrap()); 726 | /// assert_eq!(true, matrix.get(7, 7).unwrap()); 727 | /// assert_eq!(false, matrix.get(4, 3).unwrap()); 728 | /// Ok(()) 729 | /// } 730 | /// ``` 731 | pub fn to_matrix(&self) -> Result { 732 | let matrix_width = self.matrix_width(); 733 | let mut m = BitMatrix::with_dimensions(matrix_width, matrix_width); 734 | for (pos, &state) in self.leaves.iter().enumerate() { 735 | if state { 736 | let [x, y] = self.get_coords(pos); 737 | if let Err(e) = m.set(x, y, true) { 738 | return Err(Error::BitMatrixError { 739 | source: Box::new(e), 740 | }) 741 | } 742 | } 743 | } 744 | Ok(m) 745 | } 746 | /// Constructs a K2Tree which represents the state of the input matrix. 747 | /// 748 | /// All types that can produce rows of bits are valid inputs. 749 | /// ``` 750 | /// use k2_tree::{K2Tree, matrix::BitMatrix}; 751 | /// let mut m = BitMatrix::with_dimensions(8, 8); 752 | /// m.set(0, 5, true); 753 | /// assert!(K2Tree::from_matrix(m, 2, 2).is_ok()); 754 | /// ``` 755 | pub fn from_matrix(matrix: BitMatrix, stem_k: usize, leaf_k: usize) -> Result { 756 | let mut tree = K2Tree::with_k(stem_k, leaf_k)?; 757 | while matrix.width > tree.matrix_width() 758 | || matrix.height > tree.matrix_width() { 759 | tree.grow(); 760 | } 761 | let rows = matrix.into_rows(); 762 | for (y, row) in rows.into_iter().enumerate() { 763 | let xs = one_positions(row.into_iter()); 764 | for x in xs.into_iter() { 765 | tree.set(x, y, true)?; 766 | } 767 | } 768 | Ok(tree) 769 | } 770 | } 771 | 772 | /* Traits */ 773 | impl core::fmt::Display for K2Tree { 774 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 775 | if self.leaves.len() == 0 { return write!(f, "[0000]") } 776 | let mut s = String::new(); 777 | let mut i: usize = 1; 778 | let layer_starts = self.layer_starts(); 779 | for layer_num in 0..self.max_slayers-1 { 780 | for bit_pos in layer_starts[layer_num]..layer_starts[layer_num+1] { 781 | if self.stems[bit_pos] { s.push('1'); } 782 | else { s.push('0'); } 783 | if i == self.stem_k*self.stem_k 784 | && (bit_pos - layer_starts[layer_num]) < self.layer_len(layer_num)-1 { 785 | s.push_str(", "); 786 | i = 1; 787 | } 788 | else { i += 1; } 789 | } 790 | i = 1; 791 | s.push_str("; "); 792 | } 793 | i = 1; 794 | for bit_pos in 0..self.leaves.len() { 795 | if self.leaves[bit_pos] { s.push('1'); } 796 | else { s.push('0'); } 797 | if i == self.leaf_k*self.leaf_k 798 | && bit_pos < self.leaves.len()-1 { 799 | s.push_str(", "); 800 | i = 1; 801 | } 802 | else { i += 1; } 803 | } 804 | write!(f, "[{}]", s) 805 | } 806 | } 807 | impl PartialEq for K2Tree { 808 | fn eq(&self, other: &Self) -> bool { 809 | self.stem_k == other.stem_k 810 | && self.leaf_k == other.leaf_k 811 | && self.max_slayers == other.max_slayers 812 | && self.stems == other.stems 813 | && self.leaves == other.leaves 814 | } 815 | } 816 | impl Eq for K2Tree {} 817 | impl Default for K2Tree { 818 | fn default() -> Self { 819 | Self::new() 820 | } 821 | } 822 | impl std::hash::Hash for K2Tree { 823 | fn hash(&self, state: &mut H) { 824 | self.stem_k.hash(state); 825 | self.leaf_k.hash(state); 826 | self.max_slayers.hash(state); 827 | self.stems.hash(state); 828 | self.leaves.hash(state); 829 | } 830 | } 831 | impl Serialize for K2Tree { 832 | fn serialize(&self, serializer: S) -> std::result::Result { 833 | let mut state = serializer.serialize_struct("K2Tree", 5)?; 834 | state.serialize_field("stemK", &self.stem_k)?; 835 | state.serialize_field("leafK", &self.leaf_k)?; 836 | state.serialize_field("maxStemLayers", &self.max_slayers)?; 837 | state.serialize_field("stems", &self.stems.clone().into_vec() as &Vec)?; 838 | state.serialize_field("leaves", &self.leaves.clone().into_vec() as &Vec)?; 839 | state.end() 840 | } 841 | } 842 | impl<'de> Deserialize<'de> for K2Tree { 843 | fn deserialize>(deserializer: D) -> std::result::Result { 844 | enum Field { 845 | StemK, 846 | LeafK, 847 | MaxStemLayers, 848 | Stems, 849 | Leaves 850 | } 851 | impl<'de> Deserialize<'de> for Field { 852 | fn deserialize>(deserializer: D) -> std::result::Result { 853 | struct FieldVisitor; 854 | impl<'de> Visitor<'de> for FieldVisitor { 855 | type Value = Field; 856 | fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { 857 | formatter.write_str("") 858 | } 859 | fn visit_str(self, value: &str) -> std::result::Result { 860 | match value { 861 | "stemK" => Ok(Field::StemK), 862 | "leafK" => Ok(Field::LeafK), 863 | "maxStemLayers" => Ok(Field::MaxStemLayers), 864 | "stems" => Ok(Field::Stems), 865 | "leaves" => Ok(Field::Leaves), 866 | _ => Err(de::Error::unknown_field(value, FIELDS)), 867 | } 868 | } 869 | } 870 | deserializer.deserialize_identifier(FieldVisitor) 871 | } 872 | } 873 | struct K2TreeVisitor; 874 | impl<'de> Visitor<'de> for K2TreeVisitor { 875 | type Value = K2Tree; 876 | fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 877 | formatter.write_str("struct K2Tree") 878 | } 879 | fn visit_map>(self, mut map: V) -> std::result::Result { 880 | let mut stem_k = None; 881 | let mut leaf_k = None; 882 | let mut max_slayers = None; 883 | let mut stems = None; 884 | let mut leaves = None; 885 | while let Some(key) = map.next_key()? { 886 | match key { 887 | Field::StemK => { 888 | if stem_k.is_some() { 889 | return Err(de::Error::duplicate_field("stem_k")); 890 | } 891 | stem_k = Some(map.next_value()?); 892 | }, 893 | Field::LeafK => { 894 | if leaf_k.is_some() { 895 | return Err(de::Error::duplicate_field("leaf_k")); 896 | } 897 | leaf_k = Some(map.next_value()?); 898 | }, 899 | Field::MaxStemLayers => { 900 | if max_slayers.is_some() { 901 | return Err(de::Error::duplicate_field("max_stem_layer")); 902 | } 903 | max_slayers = Some(map.next_value()?); 904 | }, 905 | Field::Stems => { 906 | if stems.is_some() { 907 | return Err(de::Error::duplicate_field("stems")); 908 | } 909 | stems = Some(BitVec::from(map.next_value::>()?)); 910 | }, 911 | Field::Leaves => { 912 | if leaves.is_some() { 913 | return Err(de::Error::duplicate_field("leaves")); 914 | } 915 | leaves = Some(BitVec::from_vec(map.next_value::>()?)); 916 | } 917 | } 918 | } 919 | let stem_k: usize = stem_k.ok_or_else(|| de::Error::missing_field("stemK"))?; 920 | let leaf_k: usize = leaf_k.ok_or_else(|| de::Error::missing_field("leafK"))?; 921 | let max_slayers = max_slayers.ok_or_else(|| de::Error::missing_field("maxStemLayers"))?; 922 | let mut stems = stems.ok_or_else(|| de::Error::missing_field("stems"))?; 923 | let mut leaves = leaves.ok_or_else(|| de::Error::missing_field("leaves"))?; 924 | 925 | // If any values missing, would have thrown by now 926 | // Remove any trailing zeroes that comes from converting blindly 927 | // from Vec to list of bits 928 | let stem_len: usize = stem_k.pow(2); 929 | let leaf_len: usize = leaf_k.pow(2); 930 | let last_1_stem = one_positions_bv(&stems).pop().unwrap(); 931 | let new_stem_len = if last_1_stem+1 % stem_len == 0 { 932 | last_1_stem 933 | } 934 | else { 935 | ((last_1_stem / stem_len) + 1) * stem_len 936 | }; 937 | stems.resize(new_stem_len, false); 938 | let last_1_leaf = one_positions_bv(&leaves).pop().unwrap(); 939 | let new_leaf_len = if last_1_leaf+1 % leaf_len == 0 { 940 | last_1_leaf 941 | } 942 | else { 943 | ((last_1_leaf / leaf_len) + 1) * leaf_len 944 | }; 945 | leaves.resize(new_leaf_len, false); 946 | 947 | Ok(K2Tree { 948 | stem_k, 949 | leaf_k, 950 | max_slayers, 951 | stems, 952 | leaves 953 | }) 954 | } 955 | } 956 | const FIELDS: &[&str] = &[ 957 | "stem_k", 958 | "leaf_k", 959 | "max_slayers", 960 | "stems", 961 | "leaves" 962 | ]; 963 | deserializer.deserialize_struct("K2Tree", FIELDS, K2TreeVisitor) 964 | } 965 | } 966 | 967 | /* Private */ 968 | enum DescendResult { 969 | Leaf(usize, Range2D), //leaf_start, leaf_range 970 | Stem(usize, Range2D), //stem_start, stem_range 971 | } 972 | struct DescendEnv { 973 | /* Allows for descend to be recursive without parameter hell */ 974 | x: usize, 975 | y: usize, 976 | slayer_max: usize, 977 | } 978 | impl K2Tree { 979 | fn layer_from_range(&self, r: Range2D) -> usize { 980 | (self.max_slayers+1) - 981 | ( 982 | ((r.width()/self.leaf_k) as f64).log(self.stem_k as f64) as usize 983 | +1 984 | ) 985 | } 986 | fn matrix_bit(&self, x: usize, y: usize, m_width: usize) -> Result { 987 | let env = DescendEnv { 988 | x, 989 | y, 990 | slayer_max: self.max_slayers-1, 991 | }; 992 | self.descend(&env, 0, 0, Range2D::new(0, m_width-1, 0, m_width-1)) 993 | } 994 | fn descend(&self, env: &DescendEnv, layer: usize, stem_pos: usize, range: Range2D) -> Result { 995 | let subranges = self.to_subranges(range)?; 996 | for (child_pos, child) in self.stems[stem_pos..stem_pos+self.stem_len()].iter().enumerate() { 997 | if subranges[child_pos].contains(env.x, env.y) { 998 | if !child { return Ok(DescendResult::Stem(stem_pos, range)) } //The bit exists within a range that has all zeros 999 | else if layer == env.slayer_max { 1000 | let leaf_start = match self.stem_to_leaf_start(stem_pos + child_pos) { 1001 | Ok(ls) => ls, 1002 | Err(_) => return Err(Error::TraverseError { 1003 | x: env.x, 1004 | y: env.y 1005 | }), 1006 | }; 1007 | return Ok(DescendResult::Leaf(leaf_start, subranges[child_pos])) 1008 | } 1009 | else { 1010 | let child_stem = match self.child_stem(layer, stem_pos, child_pos) { 1011 | Ok(cs) => cs, 1012 | Err(_) => return Err(Error::TraverseError { 1013 | x: env.x, 1014 | y: env.y 1015 | }), 1016 | }; 1017 | return self.descend(env, 1018 | layer+1, 1019 | child_stem, 1020 | subranges[child_pos]) 1021 | } 1022 | } 1023 | } 1024 | unreachable!() 1025 | } 1026 | fn num_stems_before_child(&self, bit_pos: usize, layer: usize) -> usize { 1027 | ones_in_range(&self.stems, self.layer_start(layer), bit_pos) 1028 | } 1029 | fn stem_to_leaf_start(&self, stem_bitpos: usize) -> std::result::Result { 1030 | if !self.stems[stem_bitpos] { Err(()) } 1031 | else { 1032 | let nth_leaf = ones_in_range( 1033 | &self.stems, 1034 | self.layer_start(self.max_slayers-1), 1035 | stem_bitpos 1036 | ); 1037 | Ok(nth_leaf * self.leaf_len()) 1038 | } 1039 | } 1040 | fn child_stem(&self, layer: usize, stem_start: usize, nth_child: usize) -> std::result::Result { 1041 | if !self.stems[stem_start+nth_child] 1042 | || layer == self.max_slayers-1 { 1043 | /* If stem_bit is 0 or final stem layer, cannot have children */ 1044 | return Err(()) 1045 | } 1046 | Ok(self.layer_start(layer+1) 1047 | + (self.num_stems_before_child(stem_start+nth_child, layer) * self.stem_len())) 1048 | } 1049 | } 1050 | 1051 | /* Private funcs used in testing */ 1052 | #[cfg(test)] 1053 | impl K2Tree { 1054 | fn parent_stem(&self, stem_start: usize) -> usize { 1055 | self.parent(stem_start).unwrap()[0] 1056 | } 1057 | fn parent_bit(&self, stem_start: usize) -> usize { 1058 | let [stem_start, bit_offset] = self.parent(stem_start).unwrap(); 1059 | stem_start + bit_offset 1060 | } 1061 | #[allow(dead_code)] 1062 | fn footprint(&self) -> usize { 1063 | let mut size: usize = std::mem::size_of_val(self); 1064 | size += self.stems.len() / 8; 1065 | size += self.leaves.len() / 8; 1066 | size 1067 | } 1068 | #[allow(dead_code)] 1069 | fn theoretical_size(&self) -> usize { 1070 | (self.stems.len() + self.leaves.len()) / 8 1071 | } 1072 | } 1073 | 1074 | /* Public Interface Tests */ 1075 | #[cfg(test)] 1076 | mod api { 1077 | use super::*; 1078 | use bitvec::bitbox; 1079 | #[test] 1080 | fn new() { 1081 | let expected = K2Tree { 1082 | stem_k: 2, 1083 | leaf_k: 2, 1084 | max_slayers: 2, 1085 | stems: bitvec![0,0,0,0], 1086 | leaves: bitvec![], 1087 | }; 1088 | assert_eq!(K2Tree::new(), expected); 1089 | } 1090 | #[test] 1091 | fn with_k_0() -> Result<()> { 1092 | assert_eq!(K2Tree::with_k(2, 2)?, K2Tree::new()); 1093 | Ok(()) 1094 | } 1095 | #[test] 1096 | fn with_k_1() -> Result<()> { 1097 | for stem_k in 2..9usize { 1098 | for leaf_k in 2..9usize { 1099 | let expected = K2Tree { 1100 | stem_k, 1101 | leaf_k, 1102 | max_slayers: 2, 1103 | stems: bitvec![0; stem_k.pow(2)], 1104 | leaves: BitVec::new(), 1105 | }; 1106 | assert_eq!(K2Tree::with_k(stem_k, leaf_k)?, expected); 1107 | } 1108 | } 1109 | Ok(()) 1110 | } 1111 | #[test] 1112 | fn with_k_small_stem() -> Result<()> { 1113 | let err = Err(Error::SmallStemKValue { stem_k: 1 }); 1114 | assert_eq!(K2Tree::with_k(1, 2), err); 1115 | Ok(()) 1116 | } 1117 | #[test] 1118 | fn with_k_small_leaf() -> Result<()> { 1119 | let err = Err(Error::SmallLeafKValue { leaf_k: 1 }); 1120 | assert_eq!(K2Tree::with_k(2, 1), err); 1121 | Ok(()) 1122 | } 1123 | #[test] 1124 | fn set_stem_k_0() { 1125 | let mut tree = K2Tree::new(); 1126 | for valid_k in 2..7 { 1127 | assert!(tree.set_stem_k(valid_k).is_ok()); 1128 | } 1129 | for invalid_k in 0..2 { 1130 | assert!(tree.set_stem_k(invalid_k).is_err()); 1131 | } 1132 | } 1133 | #[test] 1134 | fn set_stem_k_1() { 1135 | let mut tree = K2Tree::test_tree(2); 1136 | assert!(tree.set_stem_k(3).is_ok()); 1137 | let expected = K2Tree { 1138 | stem_k: 3, 1139 | leaf_k: 2, 1140 | max_slayers: 2, 1141 | stems: bitvec![ 1142 | 1,1,0,0,0,0,0,0,0, 0,0,1,0,0,0,1,0,1, 1143 | 1,0,0,1,0,0,0,0,0 1144 | ], 1145 | leaves: bitvec![ 1146 | 0,1,1,0, 1,0,0,0, 0,1,1,0, 1147 | 0,1,0,1, 1,1,0,0 1148 | ], 1149 | }; 1150 | assert_eq!(tree, expected); 1151 | } 1152 | #[test] 1153 | fn set_stem_k_2() { 1154 | let mut tree = K2Tree::test_tree(3); 1155 | assert!(tree.set_stem_k(2).is_ok()); 1156 | let expected = K2Tree { 1157 | stem_k: 2, 1158 | leaf_k: 3, 1159 | max_slayers: 4, 1160 | stems: bitvec![ 1161 | 1,0,0,0, 1,1,1,0, 0,1,1,1, 1,0,0,0, 0,0,1,1, //final layer begins here 1162 | 0,1,0,0, 0,0,1,0, 0,0,0,1, 1,0,0,0, 1,0,0,0, 0,1,0,0 1163 | ], 1164 | leaves: bitvec![ 1165 | 0,1,0,1,0,0,0,0,1, 1,0,0,0,0,0,0,0,0, 1166 | 0,1,0,1,0,0,0,0,0, 1,0,0,1,0,0,1,0,0, 1167 | 1,0,0,0,0,0,0,0,0, 0,1,0,1,0,0,0,0,0 1168 | ], 1169 | }; 1170 | assert_eq!(tree, expected); 1171 | } 1172 | #[test] 1173 | fn set_leaf_k_0() { 1174 | let mut tree = K2Tree::new(); 1175 | for valid_k in 2..7 { 1176 | assert!(tree.set_leaf_k(valid_k).is_ok()); 1177 | } 1178 | for invalid_k in 0..2 { 1179 | assert!(tree.set_leaf_k(invalid_k).is_err()); 1180 | } 1181 | } 1182 | #[test] 1183 | fn set_leaf_k_1() { 1184 | let mut tree = K2Tree::test_tree(2); 1185 | assert!(tree.set_leaf_k(3).is_ok()); 1186 | let expected = K2Tree { 1187 | stem_k: 2, 1188 | leaf_k: 3, 1189 | max_slayers: 2, 1190 | stems: bitvec![ 1191 | 1,1,0,0, 0,1,1,1, 1,0,0,0, 1192 | ], 1193 | leaves: bitvec![ 1194 | 0,0,1,0,1,0,0,0,0, 0,0,0,1,0,0,0,0,0, 1195 | 0,0,0,0,0,1,0,1,0, 0,1,0,0,1,0,1,1,0 1196 | ], 1197 | }; 1198 | assert_eq!(tree, expected); 1199 | } 1200 | #[test] 1201 | fn set_leaf_k_2() { 1202 | let mut tree = K2Tree::test_tree(3); 1203 | assert!(tree.set_leaf_k(2).is_ok()); 1204 | let expected = K2Tree { 1205 | stem_k: 3, 1206 | leaf_k: 2, 1207 | max_slayers: 3, 1208 | stems: bitvec![ 1209 | 1,0,0,1,0,0,0,0,0, 0,1,1,1,1,0,0,0,0, 1,1,0,0,0,0,0,0,0, //final layer starts below 1210 | 0,1,1,0,0,1,0,0,0, 1,0,0,1,0,0,0,0,0, 0,0,0,1,0,0,0,0,0, 1211 | 0,0,0,0,0,1,0,1,0, 1,0,0,0,0,0,0,0,0, 0,1,1,0,0,0,0,0,0 1212 | ], 1213 | leaves: bitvec![ 1214 | 0,0,0,1, 1,0,0,0, 0,1,0,0, 1,0,1,0, 1,0,0,0, 1215 | 0,0,1,0, 0,0,1,0, 0,1,0,0, 1,0,0,0, 0,0,0,1, 1216 | 1,0,0,0 1217 | ], 1218 | }; 1219 | assert_eq!(tree, expected); 1220 | } 1221 | #[test] 1222 | fn is_empty_0() -> Result<()> { 1223 | for stem_k in 2..10 { 1224 | for leaf_k in 2..10 { 1225 | let tree = K2Tree::with_k(stem_k, leaf_k)?; 1226 | assert!(tree.is_empty()); 1227 | } 1228 | } 1229 | Ok(()) 1230 | } 1231 | #[test] 1232 | fn is_empty_1() -> Result<()> { 1233 | for stem_k in 2..5 { 1234 | for leaf_k in 2..5 { 1235 | let mut tree = K2Tree::with_k(stem_k, leaf_k)?; 1236 | tree.set(0, 0, true)?; 1237 | assert!(!tree.is_empty()); 1238 | tree.set(0, 0, false)?; 1239 | assert!(tree.is_empty()); 1240 | } 1241 | } 1242 | Ok(()) 1243 | } 1244 | #[test] 1245 | fn get() -> Result<()> { 1246 | for k in 2..4 { 1247 | let tree = K2Tree::test_tree(k); 1248 | let matrix = K2Tree::test_matrix(k); 1249 | for y in 0..matrix.height { 1250 | for x in 0..matrix.width { 1251 | assert_eq!(tree.get(x, y)?, matrix.get(x, y)?); 1252 | } 1253 | } 1254 | } 1255 | Ok(()) 1256 | } 1257 | #[test] 1258 | fn get_row() -> Result<()> { 1259 | let tree = K2Tree::test_tree(2); 1260 | let rows = [ 1261 | vec![false,false,false,false,false,true,false,true], 1262 | vec![false,false,false,false,true,false,false,true], 1263 | vec![false,false,false,false,false,false,true,true], 1264 | vec![false; 8], 1265 | vec![true,false,false,false,false,true,false,false], 1266 | vec![false,false,false,false,true,false,false,false], 1267 | vec![false; 8], 1268 | vec![false; 8] 1269 | ]; 1270 | for i in 0..8 { 1271 | assert_eq!(rows[i], tree.get_row(i)?); 1272 | } 1273 | Ok(()) 1274 | } 1275 | #[test] 1276 | fn get_column() -> Result<()> { 1277 | let tree = K2Tree::test_tree(2); 1278 | let cols = [ 1279 | vec![false,false,false,false,true,false,false,false], 1280 | vec![false; 8], 1281 | vec![false; 8], 1282 | vec![false; 8], 1283 | vec![false,true,false,false,false,true,false,false], 1284 | vec![true,false,false,false,true,false,false,false], 1285 | vec![false,false,true,false,false,false,false,false], 1286 | vec![true,true,true,false,false,false,false,false], 1287 | ]; 1288 | for i in 0..8 { 1289 | assert_eq!(cols[i], tree.get_column(i)?); 1290 | } 1291 | Ok(()) 1292 | } 1293 | #[test] 1294 | fn set_0() -> Result<()> { 1295 | let mut tree = K2Tree::with_k(2, 2)?; 1296 | assert_eq!(false, tree.get(0, 0).unwrap()); 1297 | tree.set(0, 0, true)?; 1298 | assert_eq!(true, tree.get(0, 0).unwrap()); 1299 | tree.set(0, 0, false)?; 1300 | assert_eq!(false, tree.get(0, 0).unwrap()); 1301 | assert_eq!(false, tree.get(7, 7).unwrap()); 1302 | tree.set(7, 7, true)?; 1303 | assert_eq!(true, tree.get(7, 7).unwrap()); 1304 | tree.set(7, 7, false)?; 1305 | assert_eq!(false, tree.get(7, 7).unwrap()); 1306 | assert_eq!(false, tree.get(2, 6).unwrap()); 1307 | tree.set(2, 6, true)?; 1308 | assert_eq!(true, tree.get(2, 6).unwrap()); 1309 | tree.set(6, 2, true)?; 1310 | assert_eq!(true, tree.get(2, 6).unwrap()); 1311 | assert_eq!(true, tree.get(6, 2).unwrap()); 1312 | Ok(()) 1313 | } 1314 | #[test] 1315 | fn set_1() -> Result<()> { 1316 | let mut tree = K2Tree::with_k(2, 2)?; 1317 | tree.grow(); 1318 | for i in 0..256 { 1319 | let [x, y] = [i%16, i/16]; 1320 | assert_eq!(false, tree.get(x, y)?); 1321 | tree.set(x, y, true)?; 1322 | assert_eq!(true, tree.get(x, y)?); 1323 | tree.set(x, y, false)?; 1324 | } 1325 | Ok(()) 1326 | } 1327 | #[test] 1328 | fn set_2() -> Result<()> { 1329 | for k in 2..5 { 1330 | let mut tree = K2Tree::with_k(k, k)?; 1331 | for y in 0..(k.pow(3)) { 1332 | for x in 0..(k.pow(3)) { 1333 | assert_eq!(false, tree.get(x, y)?); 1334 | tree.set(x, y, true)?; 1335 | assert_eq!(true, tree.get(x, y)?); 1336 | tree.set(x, y, false)?; 1337 | } 1338 | } 1339 | } 1340 | Ok(()) 1341 | } 1342 | #[test] 1343 | fn set_3() -> Result<()> { 1344 | let mut tree = K2Tree::with_k(3, 3)?; 1345 | tree.grow(); 1346 | for i in 0..6561 { 1347 | let [x, y] = [i%81, i/81]; 1348 | assert_eq!(false, tree.get(x, y)?); 1349 | tree.set(x, y, true)?; 1350 | assert_eq!(true, tree.get(x, y)?); 1351 | tree.set(x, y, false)?; 1352 | } 1353 | Ok(()) 1354 | } 1355 | #[test] 1356 | fn set_unset_many_stem_layers() -> Result<()> { 1357 | let mut tree = K2Tree::with_k(2, 2)?; 1358 | for _ in 0..9 { tree.grow(); } 1359 | tree.set(256, 256, true)?; 1360 | tree.set(0, 0, true)?; 1361 | tree.set(0, 0, false)?; 1362 | Ok(()) 1363 | } 1364 | #[test] 1365 | fn matrix_width_and_grow_0() -> Result<()> { 1366 | for k in 2..9usize { 1367 | let k_cubed = k.pow(3); 1368 | let mut tree = K2Tree::with_k(k, k)?; 1369 | assert_eq!(k_cubed, tree.matrix_width()); 1370 | tree.grow(); 1371 | assert_eq!(k_cubed*k, tree.matrix_width()); 1372 | tree.grow(); 1373 | assert_eq!(k_cubed*k*k, tree.matrix_width()); 1374 | for _ in 0..3 { tree.grow(); } 1375 | assert_eq!(k_cubed*k.pow(5), tree.matrix_width()); 1376 | } 1377 | Ok(()) 1378 | } 1379 | #[test] 1380 | fn matrix_width_and_grow_1() -> Result<()> { 1381 | for k in 2..4usize { 1382 | let k_cubed = k.pow(3); 1383 | let mut tree = K2Tree::test_tree(k); 1384 | assert_eq!(k_cubed, tree.matrix_width()); 1385 | tree.grow(); 1386 | assert_eq!(k_cubed*k, tree.matrix_width()); 1387 | for _ in 0..3 { tree.grow(); } 1388 | assert_eq!(k_cubed*k.pow(4), tree.matrix_width()); 1389 | } 1390 | Ok(()) 1391 | } 1392 | #[test] 1393 | fn stem_k() -> Result<()> { 1394 | for k in 2..9 { 1395 | assert_eq!(k, K2Tree::with_k(k, k)?.stem_k); 1396 | } 1397 | Ok(()) 1398 | } 1399 | #[test] 1400 | fn into_stems_0() { 1401 | let tree = K2Tree::test_tree(2); 1402 | let values = bitvec![0,1,1,1, 1,1,0,1, 1,0,0,0, 1,0,0,0]; 1403 | let stems = [0, 0, 1, 2]; 1404 | let bits = [0, 1, 2, 3]; 1405 | for (i, stem) in tree.into_stems().enumerate() { 1406 | assert_eq!( 1407 | iterators::StemBit { 1408 | value: values[i], 1409 | layer: if i < 4 { 0 } else { 1 }, 1410 | stem: stems[i/4], 1411 | bit: bits[i%4], 1412 | }, 1413 | stem 1414 | ); 1415 | } 1416 | } 1417 | #[test] 1418 | fn stems_0() { 1419 | let tree = K2Tree::test_tree(2); 1420 | let values = bitvec![0,1,1,1, 1,1,0,1, 1,0,0,0, 1,0,0,0]; 1421 | let stems = [0, 0, 1, 2]; 1422 | let bits = [0, 1, 2, 3]; 1423 | for (i, stem) in tree.stems().enumerate() { 1424 | assert_eq!( 1425 | iterators::StemBit { 1426 | value: values[i], 1427 | layer: if i < 4 { 0 } else { 1 }, 1428 | stem: stems[i/4], 1429 | bit: bits[i%4], 1430 | }, 1431 | stem 1432 | ); 1433 | } 1434 | } 1435 | #[test] 1436 | fn stems_1() { 1437 | let tree = K2Tree::test_tree(3); 1438 | let values = bitvec![ 1439 | 0,1,0,1,1,0,1,1,0, 1,1,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0,0, 1440 | 1,0,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0,0 1441 | ]; 1442 | let stems = [0, 0, 1, 2, 3, 4]; 1443 | let bits = [0, 1, 2, 3, 4, 5, 6, 7, 8]; 1444 | for (i, stem) in tree.stems().enumerate() { 1445 | assert_eq!( 1446 | iterators::StemBit { 1447 | value: values[i], 1448 | layer: if i < 9 { 0 } else { 1 }, 1449 | stem: stems[i/9], 1450 | bit: bits[i%9], 1451 | }, 1452 | stem 1453 | ); 1454 | } 1455 | } 1456 | #[test] 1457 | fn stems_2() { 1458 | let tree = K2Tree::test_tree(4); 1459 | let values = bitbox![ 1460 | 1,0,0,1,0,0,0,1,1,0,0,0,1,1,0,1, 1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, 1461 | 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1, 1462 | 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1, 1463 | 1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, 1464 | ]; 1465 | let stems = [0,0,1,2,3,4,5,6]; 1466 | let bits = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]; 1467 | for (i, stem) in tree.stems().enumerate() { 1468 | assert_eq!( 1469 | iterators::StemBit { 1470 | value: values[i], 1471 | layer: if i < 16 { 0 } else { 1 }, 1472 | stem: stems[i/16], 1473 | bit: bits[i%16], 1474 | }, 1475 | stem 1476 | ); 1477 | } 1478 | } 1479 | #[test] 1480 | fn stems_raw_0() { 1481 | let tree = K2Tree::test_tree(2); 1482 | let values = bitbox![0,1,1,1, 1,1,0,1, 1,0,0,0, 1,0,0,0]; 1483 | for (i, stem) in tree.stems_raw().enumerate() { 1484 | assert_eq!(values[i], stem); 1485 | } 1486 | } 1487 | #[test] 1488 | fn stems_raw_1() { 1489 | let tree = K2Tree::test_tree(3); 1490 | let values = bitbox![ 1491 | 0,1,0,1,1,0,1,1,0, 1,1,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0,0, 1492 | 1,0,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0,0 1493 | ]; 1494 | for (i, stem) in tree.stems_raw().enumerate() { 1495 | assert_eq!(values[i], stem); 1496 | } 1497 | } 1498 | #[test] 1499 | fn stems_raw_2() { 1500 | let tree = K2Tree::test_tree(4); 1501 | let values = bitbox![ 1502 | 1,0,0,1,0,0,0,1,1,0,0,0,1,1,0,1, 1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, 1503 | 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1, 1504 | 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1, 1505 | 1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, 1506 | ]; 1507 | for (i, stem) in tree.stems_raw().enumerate() { 1508 | assert_eq!(values[i], stem); 1509 | } 1510 | } 1511 | #[test] 1512 | fn leaves_0() { 1513 | let tree = K2Tree::test_tree(2); 1514 | let values = bitbox![0,1,1,0, 0,1,0,1, 1,1,0,0, 1,0,0,0, 0,1,1,0]; 1515 | let xs = [4,5,4,5, 6,7,6,7, 6,7,6,7, 0,1,0,1, 4,5,4,5]; 1516 | let ys = [0,0,1,1, 0,0,1,1, 2,2,3,3, 4,4,5,5, 4,4,5,5]; 1517 | let leaves = [0,0,0,0, 1,1,1,1, 2,2,2,2, 3,3,3,3, 4,4,4,4]; 1518 | let bits = [0,1,2,3, 0,1,2,3, 0,1,2,3, 0,1,2,3, 0,1,2,3]; 1519 | for (i, leaf) in tree.leaves().enumerate() { 1520 | assert_eq!( 1521 | iterators::LeafBit { 1522 | value: values[i], 1523 | x: xs[i], 1524 | y: ys[i], 1525 | leaf: leaves[i], 1526 | bit: bits[i], 1527 | }, 1528 | leaf 1529 | ); 1530 | } 1531 | } 1532 | #[test] 1533 | fn leaves_1() { 1534 | let tree = K2Tree::test_tree(3); 1535 | let values = bitbox![ 1536 | 0,1,0,1,0,0,0,0,1, 1,0,0,1,0,0,1,0,0, 1,0,0,0,0,0,0,0,0, 1537 | 0,1,0,1,0,0,0,0,0, 1,0,0,0,0,0,0,0,0, 0,1,0,1,0,0,0,0,0, 1538 | ]; 1539 | let xs = [ 1540 | 9,10,11,9,10,11,9,10,11, 12,13,14,12,13,14,12,13,14, 1541 | 0,1,2,0,1,2,0,1,2, 9,10,11,9,10,11,9,10,11, 1542 | 0,1,2,0,1,2,0,1,2, 9,10,11,9,10,11,9,10,11 1543 | ]; 1544 | let ys = [ 1545 | 0,0,0,1,1,1,2,2,2, 0,0,0,1,1,1,2,2,2, 1546 | 9,9,9,10,10,10,11,11,11, 9,9,9,10,10,10,11,11,11, 1547 | 18,18,18,19,19,19,20,20,20, 18,18,18,19,19,19,20,20,20 1548 | ]; 1549 | let leaves = [ 1550 | 0,0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2, 1551 | 3,3,3,3,3,3,3,3,3, 4,4,4,4,4,4,4,4,4, 5,5,5,5,5,5,5,5,5, 1552 | ]; 1553 | let bits = [ 1554 | 0,1,2,3,4,5,6,7,8, 0,1,2,3,4,5,6,7,8, 0,1,2,3,4,5,6,7,8, 1555 | 0,1,2,3,4,5,6,7,8, 0,1,2,3,4,5,6,7,8, 0,1,2,3,4,5,6,7,8 1556 | ]; 1557 | for (i, leaf) in tree.leaves().enumerate() { 1558 | assert_eq!( 1559 | iterators::LeafBit { 1560 | value: values[i], 1561 | x: xs[i], 1562 | y: ys[i], 1563 | leaf: leaves[i], 1564 | bit: bits[i], 1565 | }, 1566 | leaf 1567 | ); 1568 | } 1569 | } 1570 | #[test] 1571 | fn leaves_raw_0() { 1572 | let tree = K2Tree::test_tree(2); 1573 | let values = bitbox![0,1,1,0, 0,1,0,1, 1,1,0,0, 1,0,0,0, 0,1,1,0]; 1574 | for (i, leaf) in tree.leaves_raw().enumerate() { 1575 | assert_eq!(values[i], leaf); 1576 | } 1577 | } 1578 | #[test] 1579 | fn leaves_raw_1() { 1580 | let tree = K2Tree::test_tree(3); 1581 | let values = bitbox![ 1582 | 0,1,0,1,0,0,0,0,1, 1,0,0,1,0,0,1,0,0, 1,0,0,0,0,0,0,0,0, 1583 | 0,1,0,1,0,0,0,0,0, 1,0,0,0,0,0,0,0,0, 0,1,0,1,0,0,0,0,0, 1584 | ]; 1585 | for (i, leaf) in tree.leaves_raw().enumerate() { 1586 | assert_eq!(values[i], leaf); 1587 | } 1588 | } 1589 | #[test] 1590 | fn shrink_if_possible() -> Result<()> { 1591 | for k in 2..9usize { 1592 | let mw = k.pow(3); 1593 | let mut tree = K2Tree::with_k(k, k)?; 1594 | tree.grow(); 1595 | assert_eq!(mw*k, tree.matrix_width()); 1596 | tree.shrink_if_possible(); 1597 | assert_eq!(mw, tree.matrix_width()); 1598 | tree.shrink_if_possible(); 1599 | assert_eq!(mw, tree.matrix_width()); 1600 | } 1601 | Ok(()) 1602 | } 1603 | #[test] 1604 | fn shrink() -> Result<()> { 1605 | for k in 2..9usize { 1606 | let mw = k.pow(3); 1607 | let mut tree = K2Tree::with_k(k, k)?; 1608 | tree.grow(); 1609 | assert_eq!(mw*k, tree.matrix_width()); 1610 | assert!(tree.shrink().is_ok()); 1611 | assert_eq!(mw, tree.matrix_width()); 1612 | assert!(tree.shrink().is_err()); 1613 | assert_eq!(mw, tree.matrix_width()); 1614 | } 1615 | Ok(()) 1616 | } 1617 | #[test] 1618 | fn shrink_unchecked() -> Result<()> { 1619 | for k in 2..9usize { 1620 | let mut tree = K2Tree::with_k(k, k)?; 1621 | tree.grow(); 1622 | assert_eq!(k.pow(4), tree.matrix_width()); 1623 | unsafe { tree.shrink_unchecked(); } 1624 | assert_eq!(k.pow(3), tree.matrix_width()); 1625 | } 1626 | Ok(()) 1627 | } 1628 | #[test] 1629 | fn from_matrix() -> Result<()> { 1630 | for k in 2..=3usize { 1631 | let matrix = K2Tree::test_matrix(k); 1632 | let tree = K2Tree::test_tree(k); 1633 | assert_eq!(tree, K2Tree::from_matrix(matrix, k, k)?); 1634 | } 1635 | Ok(()) 1636 | } 1637 | #[test] 1638 | fn to_matrix() -> Result<()> { 1639 | for k in 2..=3usize { 1640 | let tree = K2Tree::test_tree(k); 1641 | let matrix = K2Tree::test_matrix(k); 1642 | assert_eq!(matrix, tree.to_matrix()?); 1643 | assert_eq!(matrix, K2Tree::from_matrix(matrix.clone(), k, k)?.to_matrix()?); 1644 | } 1645 | Ok(()) 1646 | } 1647 | #[test] 1648 | fn into_matrix() -> Result<()> { 1649 | for k in 2..=3usize { 1650 | let tree = K2Tree::test_tree(k); 1651 | let matrix = K2Tree::test_matrix(k); 1652 | assert_eq!(matrix, tree.into_matrix()?); 1653 | assert_eq!(matrix, K2Tree::from_matrix(matrix.clone(), k, k)?.into_matrix()?); 1654 | } 1655 | Ok(()) 1656 | } 1657 | } 1658 | 1659 | #[cfg(test)] 1660 | mod util { 1661 | use super::*; 1662 | #[test] 1663 | fn all_zeroes_0() { 1664 | let zeroes = bitvec![0,0,0,0, 0,0,0,0, 0,0]; 1665 | let one = bitvec![0,0,0,0, 0,1,0,0, 0]; 1666 | let ones = bitvec![1,1,1,1, 1]; 1667 | let edge = bitvec![0,0,0,1]; 1668 | assert!(all_zeroes(&zeroes, 0, 10)); 1669 | assert!(!all_zeroes(&one, 0, 9)); 1670 | assert!(!all_zeroes(&ones, 0, 5)); 1671 | assert!(!all_zeroes(&edge, 0, 4)); 1672 | } 1673 | #[test] 1674 | fn one_positions_0() { 1675 | let bv = bitvec![0,1,0,1,0,1,0,0,0,1]; 1676 | assert_eq!(vec![1,3,5,9], one_positions(bv.into_iter())); 1677 | } 1678 | #[test] 1679 | fn ones_in_range_0() { 1680 | let ranges = [ 1681 | bitvec![0,1,1,1,0,0,1,0,1,1,0,0], 1682 | bitvec![0,0,0,0,0,0,1], 1683 | bitvec![0,1,1,1,1,1,1,0,1,0,0,1] 1684 | ]; 1685 | let num_ones = [6, 1, 8]; 1686 | for i in 0..ranges.len() { 1687 | assert_eq!(ones_in_range(&ranges[i], 0, ranges[i].len()), num_ones[i]); 1688 | } 1689 | } 1690 | #[test] 1691 | fn stem_layer_start_0() { 1692 | let tree = K2Tree::test_tree(2); 1693 | assert_eq!(tree.layer_start(0), 0); 1694 | assert_eq!(tree.layer_start(1), 4); 1695 | } 1696 | #[test] 1697 | fn stem_layer_start_1() { 1698 | let tree = K2Tree::test_tree(3); 1699 | assert_eq!(tree.layer_start(0), 0); 1700 | assert_eq!(tree.layer_start(1), 9); 1701 | } 1702 | #[test] 1703 | fn stem_layer_start_2() { 1704 | let tree = K2Tree::test_tree(4); 1705 | assert_eq!(tree.layer_start(0), 0); 1706 | assert_eq!(tree.layer_start(1), 16); 1707 | } 1708 | #[test] 1709 | fn stem_layer_len_0() { 1710 | let tree = K2Tree::test_tree(2); 1711 | assert_eq!(tree.layer_len(0), 4); 1712 | assert_eq!(tree.layer_len(1), 12); 1713 | } 1714 | #[test] 1715 | fn stem_layer_len_1() { 1716 | let tree = K2Tree::test_tree(3); 1717 | assert_eq!(tree.layer_len(0), 9); 1718 | assert_eq!(tree.layer_len(1), 45); 1719 | } 1720 | #[test] 1721 | fn stem_layer_len_2() { 1722 | let tree = K2Tree::test_tree(4); 1723 | assert_eq!(tree.layer_len(0), 16); 1724 | assert_eq!(tree.layer_len(1), 112); 1725 | } 1726 | #[test] 1727 | fn stem_to_leaf_start_0() { 1728 | let tree = K2Tree::test_tree(2); 1729 | assert_eq!(tree.stem_to_leaf_start(4), Ok(0)); 1730 | assert_eq!(tree.stem_to_leaf_start(5), Ok(4)); 1731 | assert_eq!(tree.stem_to_leaf_start(7), Ok(8)); 1732 | assert_eq!(tree.stem_to_leaf_start(8), Ok(12)); 1733 | assert_eq!(tree.stem_to_leaf_start(12), Ok(16)); 1734 | assert_eq!(tree.stem_to_leaf_start(9), Err(())); 1735 | } 1736 | #[test] 1737 | fn child_stem_0() { 1738 | let tree = K2Tree::test_tree(2); 1739 | assert_eq!(tree.child_stem(0, 0, 0), Err(())); 1740 | assert_eq!(tree.child_stem(0, 0, 1), Ok(4)); 1741 | assert_eq!(tree.child_stem(0, 0, 2), Ok(8)); 1742 | assert_eq!(tree.child_stem(0, 0, 3), Ok(12)); 1743 | assert_eq!(tree.child_stem(1, 4, 0), Err(())); 1744 | } 1745 | #[test] 1746 | fn parent_stem_0() { 1747 | let tree = K2Tree::test_tree(2); 1748 | assert_eq!(tree.parent_stem(4), 0); 1749 | assert_eq!(tree.parent_stem(8), 0); 1750 | assert_eq!(tree.parent_stem(12), 0); 1751 | } 1752 | #[test] 1753 | fn parent_bit_0() { 1754 | let tree = K2Tree::test_tree(2); 1755 | assert_eq!(tree.parent_bit(4), 1); 1756 | assert_eq!(tree.parent_bit(8), 2); 1757 | assert_eq!(tree.parent_bit(12), 3); 1758 | } 1759 | #[test] 1760 | fn get_coords_0() { 1761 | let tree = K2Tree::test_tree(2); 1762 | assert_eq!(tree.get_coords(12), [0, 4]); 1763 | } 1764 | #[test] 1765 | fn get_coords_1() -> std::result::Result<(), serde_json::Error> { 1766 | // This huge K2Tree is from an error case I found in the wild, 1767 | // using it as proof the bug was fixed in this test. 1768 | let leaves = K2Tree { 1769 | stem_k: 2, 1770 | leaf_k: 2, 1771 | max_slayers: 11, 1772 | stems: bitvec![ 1773 | 1,1,1,0,1,1,1,1,0,0,1,0,1,1,1,0,1,1,0,0,1,1,0,0,0,0,1,0,0,0,0,1,0,0,1,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0, 1774 | 1,0,1,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,1,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,0, 1775 | 1,0,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,0,0,1,0,1,0,1,0,1,0,0,0,1,1,0,0, 1776 | 1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0, 1777 | 1,1,0,0,1,1,0,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 1778 | 0,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0, 1779 | 1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,1,0,1,1,0,0,0,0,0,1, 1780 | 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 1781 | 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 1782 | 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 1783 | 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 1784 | 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 1785 | 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0,0,1,1, 1786 | 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 1787 | 0,0,1,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0, 1788 | 1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0, 1789 | 1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0, 1790 | 1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,1,0,0,1,0,0,0, 1791 | 1,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0, 1792 | 1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0, 1793 | 1,0,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0, 1794 | 1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0, 1795 | 1,0,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0, 1796 | 0,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,0,0,0,0,1,0,1,0,0,1,0, 1797 | 1,1,0,0,0,1,0,0,1,1,0,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 1798 | 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 1799 | 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1, 1800 | 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 1801 | 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1, 1802 | 0,0,0,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,1, 1803 | 0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 1804 | 0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1, 1805 | 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 1806 | 0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,1,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0, 1807 | 1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0, 1808 | 0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0, 1809 | 0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0, 1810 | 0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0, 1811 | 1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0, 1812 | 1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0, 1813 | 1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0, 1814 | 0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0, 1815 | 0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,0,1,0,1,1, 1816 | 0,1,0,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 1817 | 0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1, 1818 | 0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1, 1819 | 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 1820 | 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1, 1821 | 0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,0,0,0,1,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,1, 1822 | 0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,1, 1823 | 0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0, 1824 | 0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1, 1825 | 0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0,0,1, 1826 | 0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,0, 1827 | 0,0,1,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,1, 1828 | 0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,1,1, 1829 | 0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,1, 1830 | 0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,0, 1831 | 0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 1832 | 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,1,1,0,0,1,1,0,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,1,0, 1833 | 0,0,0,1,0,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0, 1834 | 0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0, 1835 | 1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0, 1836 | 1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0, 1837 | 1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0, 1838 | 1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0, 1839 | 0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0, 1840 | 0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0, 1841 | 1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0, 1842 | 0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,1,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0, 1843 | 1,1,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 1844 | 0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 1845 | 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 1846 | 0,0,1,0,0,0,1,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1, 1847 | 0,0,0,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 1848 | 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,1,1, 1849 | 0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,1,1, 1850 | 0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,1, 1851 | 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1, 1852 | 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,0,0,0,0,1, 1853 | 0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,1, 1854 | 0,0,1,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1, 1855 | 0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,1, 1856 | 0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,0,0,0,0,1, 1857 | 0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,0, 1858 | 0,0,1,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,0, 1859 | 0,0,1,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1, 1860 | 0,0,0,1,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0, 1861 | 0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0, 1862 | 0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,1, 1863 | 0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,1, 1864 | 0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,1, 1865 | 0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,1,0,0,1,1, 1866 | 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 1867 | 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0, 1868 | ], 1869 | leaves: bitvec![ 1870 | 0,0,1,0,0,0,0,1,0,0,1,1,0,0,0,1,1,1,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0, 1871 | 0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0, 1872 | 0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0, 1873 | 0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0, 1874 | 0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0, 1875 | 0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0, 1876 | 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1, 1877 | 0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1, 1878 | 0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0, 1879 | 0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,0,1, 1880 | 0,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,1,0,0,0,0,1,0,0,0,0,1,0,0,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,0,0,1,0, 1881 | 0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, 1882 | 0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0, 1883 | 0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0, 1884 | 0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0, 1885 | 0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1, 1886 | 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0, 1887 | 0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0, 1888 | 0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0, 1889 | 0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, 1890 | 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0, 1891 | 0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1, 1892 | 0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0, 1893 | 0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0, 1894 | 0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, 1895 | 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0, 1896 | 1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0, 1897 | 0,1,0,0,1,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0, 1898 | 1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,1,0,0, 1899 | 1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0, 1900 | 1,1,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0, 1901 | 0,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,1,0,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0, 1902 | 1,1,0,0,1,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,0,1,0,0, 1903 | 1,1,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0, 1904 | 0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,1,0,0, 1905 | 0,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,1,0,0,0,1,0,0,1,1,0,0,1,0,0,0,0,1,0,0, 1906 | 1,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,0,1,0,0, 1907 | 1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,1,0,0,0, 1908 | 1,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0, 1909 | 1,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,0,1,0,0, 1910 | 1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0, 1911 | 0,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,0,0,0,1,1,0,0, 1912 | 1,1,0,0,0,1,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,0,0,0, 1913 | 0,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,1,0,0, 1914 | 1,1,0,0,0,1,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0, 1915 | 1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0, 1916 | 1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0, 1917 | 1,1,0,0,1,1,0,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 1918 | ], 1919 | }.into_leaves(); 1920 | 1921 | let mut x = 0; 1922 | for _leaf in leaves { x += 1; } // Do a cheap op to make sure the value from leaves is assigned 1923 | let _y = x; 1924 | 1925 | Ok(()) 1926 | } 1927 | #[test] 1928 | fn layer_start_0() { 1929 | let trees = [ 1930 | K2Tree::test_tree(2), 1931 | K2Tree::test_tree(3), 1932 | K2Tree::test_tree(4) 1933 | ]; 1934 | let expecteds = [ 1935 | [0, 4], 1936 | [0, 9], 1937 | [0, 16] 1938 | ]; 1939 | for k in 0..trees.len() { 1940 | for layer in 0..expecteds[k].len() { 1941 | assert_eq!(expecteds[k][layer], trees[k].layer_start(layer)); 1942 | } 1943 | } 1944 | } 1945 | #[test] 1946 | fn layer_start_1() -> Result<()> { 1947 | let mut tree = K2Tree::test_tree(3); 1948 | for _ in 0..9 { tree.grow(); } 1949 | tree.set(67, 78, true)?; 1950 | tree.set(100, 100, true)?; 1951 | tree.set(33, 146, true)?; 1952 | tree.set(43, 146, true)?; 1953 | let expected = [0, 9, 18, 27, 36, 45, 54, 63, 72, 99, 135]; 1954 | for layer in 0..tree.max_slayers { 1955 | assert_eq!(expected[layer], tree.layer_start(layer)); 1956 | } 1957 | Ok(()) 1958 | } 1959 | } 1960 | 1961 | #[cfg(test)] 1962 | mod misc { 1963 | use super::*; 1964 | #[test] 1965 | fn flood() -> Result<()> { 1966 | use rand::Rng; 1967 | let mut rng = rand::thread_rng(); 1968 | let mut tree = K2Tree::with_k(2, 2)?; 1969 | for _ in 0..10 { tree.grow(); } 1970 | for _ in 0..500 { 1971 | let x: usize = rng.gen_range(0, 512); 1972 | let y: usize = rng.gen_range(0, 512); 1973 | tree.set(x, y, true)?; 1974 | } 1975 | Ok(()) 1976 | } 1977 | #[test] 1978 | fn is_send() { 1979 | fn assert_send() {} 1980 | assert_send::(); 1981 | } 1982 | #[test] 1983 | fn is_sync() { 1984 | fn assert_sync() {} 1985 | assert_sync::(); 1986 | } 1987 | #[test] 1988 | fn display() { 1989 | println!("{}", K2Tree::test_tree(3)); 1990 | } 1991 | #[test] 1992 | fn eq() -> Result<()> { 1993 | assert_eq!(K2Tree::new(), K2Tree::new()); 1994 | assert_eq!(K2Tree::test_tree(2), K2Tree::test_tree(2)); 1995 | assert_eq!(K2Tree::test_tree(3), K2Tree::test_tree(3)); 1996 | assert_eq!(K2Tree::test_tree(4), K2Tree::test_tree(4)); 1997 | for stem_k in 2..10 { 1998 | for leaf_k in 2..10 { 1999 | assert_eq!( 2000 | K2Tree::with_k(stem_k, leaf_k)?, 2001 | K2Tree::with_k(stem_k, leaf_k)? 2002 | ); 2003 | } 2004 | } 2005 | Ok(()) 2006 | } 2007 | } 2008 | 2009 | #[cfg(test)] 2010 | mod many_k { 2011 | use super::*; 2012 | #[test] 2013 | fn build() -> Result<()> { 2014 | for i in 2..=3 { 2015 | for stem_k in 2..9 { 2016 | for leaf_k in 2..9 { 2017 | let m = K2Tree::test_matrix(i); 2018 | let mut tree = K2Tree::with_k(stem_k, leaf_k)?; 2019 | while tree.matrix_width() < m.width { tree.grow(); } 2020 | for (y, row) in m.into_rows().into_iter().enumerate() { 2021 | for (x, state) in row.into_iter().enumerate() { 2022 | tree.set(x, y, state)?; 2023 | } 2024 | } 2025 | } 2026 | } 2027 | } 2028 | Ok(()) 2029 | } 2030 | } 2031 | 2032 | #[cfg(test)] 2033 | mod ser_de { 2034 | use super::*; 2035 | #[test] 2036 | fn serialize_json_0() -> std::result::Result<(), serde_json::Error> { 2037 | let expected = String::from(r#"{"stemK":2,"leafK":2,"maxStemLayers":2,"stems":[4542],"leaves":[398246]}"#); 2038 | let actual = serde_json::to_string(&K2Tree::test_tree(2))?; 2039 | assert_eq!(actual, expected); 2040 | Ok(()) 2041 | } 2042 | #[test] 2043 | fn serialize_json_1() -> std::result::Result<(), serde_json::Error> { 2044 | let expected = String::from(r#"{"stemK":3,"leafK":3,"maxStemLayers":2,"stems":[35253226047194],"leaves":[351913782842122]}"#); 2045 | let actual = serde_json::to_string(&K2Tree::test_tree(3))?; 2046 | assert_eq!(actual, expected); 2047 | Ok(()) 2048 | } 2049 | #[test] 2050 | fn serialize_json_2() -> std::result::Result<(), serde_json::Error> { 2051 | let expected = String::from( 2052 | r#"{"stemK":4,"leafK":4,"maxStemLayers":2,"stems":[13835058330193736073,2251825046626304],"leaves":[2269392002875393,140737488887808]}"# 2053 | ); 2054 | let actual = serde_json::to_string(&K2Tree::test_tree(4))?; 2055 | assert_eq!(actual, expected); 2056 | Ok(()) 2057 | } 2058 | #[test] 2059 | fn deserialize_json_0() -> std::result::Result<(), serde_json::Error> { 2060 | let expected = K2Tree::test_tree(2); 2061 | let json = r#"{"stemK":2,"leafK":2,"maxStemLayers":2,"stems":[4542],"leaves":[398246]}"#; 2062 | let actual: K2Tree = serde_json::from_str(json)?; 2063 | assert_eq!(actual, expected); 2064 | Ok(()) 2065 | } 2066 | #[test] 2067 | fn deserialize_json_1() -> std::result::Result<(), serde_json::Error> { 2068 | let expected = K2Tree::test_tree(3); 2069 | let json = r#"{"stemK":3,"leafK":3,"maxStemLayers":2,"stems":[35253226047194],"leaves":[351913782842122]}"#; 2070 | let actual: K2Tree = serde_json::from_str(json)?; 2071 | assert_eq!(actual, expected); 2072 | Ok(()) 2073 | } 2074 | #[test] 2075 | fn deserialize_json_2() -> std::result::Result<(), serde_json::Error> { 2076 | let expected = K2Tree::test_tree(4); 2077 | let json = r#"{"stemK":4,"leafK":4,"maxStemLayers":2,"stems":[13835058330193736073,2251825046626304],"leaves":[2269392002875393,140737488887808]}"#; 2078 | let actual: K2Tree = serde_json::from_str(json)?; 2079 | assert_eq!(actual, expected); 2080 | Ok(()) 2081 | } 2082 | } --------------------------------------------------------------------------------