diff --git a/Cargo.toml b/Cargo.toml index c5af697..c879bbf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,8 @@ thiserror = "2.0.9" nohash = "0.2.0" page_size = "0.6.0" enum-iterator = "2.1.0" +thread_local = "1.1.8" +crossbeam = "0.8.4" [dev-dependencies] anyhow = "1.0.95" diff --git a/src/distance/cosine.rs b/src/distance/cosine.rs index cdb5789..b3b524a 100644 --- a/src/distance/cosine.rs +++ b/src/distance/cosine.rs @@ -20,7 +20,7 @@ pub enum Cosine {} #[repr(C)] #[derive(Pod, Zeroable, Clone, Copy)] pub struct NodeHeaderCosine { - norm: f32, + pub(crate) norm: f32, } impl fmt::Debug for NodeHeaderCosine { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/distance/mod.rs b/src/distance/mod.rs index 318a802..99db8c0 100644 --- a/src/distance/mod.rs +++ b/src/distance/mod.rs @@ -117,6 +117,10 @@ pub trait Distance: Send + Sync + Sized + Clone + fmt::Debug + 'static { ) -> heed::Result<()> { Ok(()) } + + fn size_of_item(dimensions: usize) -> usize { + std::mem::size_of::() + Self::VectorCodec::size_of_item(dimensions) + } } fn two_means( diff --git a/src/metadata.rs b/src/metadata.rs index 6b0814a..79c5113 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -23,7 +23,7 @@ impl<'a> heed::BytesEncode<'a> for MetadataCodec { fn bytes_encode(item: &'a Self::EItem) -> Result, BoxedError> { let Metadata { dimensions, items, roots, distance } = item; - debug_assert!(!distance.as_bytes().iter().any(|&b| b == 0)); + debug_assert!(!distance.as_bytes().contains(&0)); let mut output = Vec::with_capacity( size_of::() diff --git a/src/node.rs b/src/node.rs index 56cf7a4..5d5ab37 100644 --- a/src/node.rs +++ b/src/node.rs @@ -19,6 +19,20 @@ pub enum Node<'a, D: Distance> { SplitPlaneNormal(SplitPlaneNormal<'a, D>), } +impl<'a, D: Distance> Node<'a, D> { + pub fn into_owned(self) -> Node<'static, D> { + match self { + Node::Leaf(leaf) => Node::Leaf(leaf.into_owned()), + Node::Descendants(descendants) => Node::Descendants(Descendants { + descendants: Cow::Owned(descendants.descendants.into_owned()), + }), + Node::SplitPlaneNormal(split_plane_normal) => { + Node::SplitPlaneNormal(split_plane_normal.into_owned()) + } + } + } +} + /// A node generic over the version of the database. /// Should only be used while reading from the database. #[derive(Clone, Debug)] @@ -40,8 +54,15 @@ impl<'a, D: Distance> Node<'a, D> { None } } -} + pub fn descendants(self) -> Option> { + if let Node::Descendants(descendants) = self { + Some(descendants) + } else { + None + } + } +} /// A leaf node which corresponds to the vector inputed /// by the user and the distance header. pub struct Leaf<'a, D: Distance> { @@ -142,6 +163,19 @@ impl fmt::Debug for SplitPlaneNormal<'_, D> { } } +impl SplitPlaneNormal<'_, D> { + pub fn into_owned(self) -> SplitPlaneNormal<'static, D> { + SplitPlaneNormal { + left: self.left, + right: self.right, + normal: self.normal.map(|normal| Leaf { + header: normal.header, + vector: Cow::Owned(normal.vector.into_owned()), + }), + } + } +} + impl Clone for SplitPlaneNormal<'_, D> { fn clone(&self) -> Self { Self { left: self.left, right: self.right, normal: self.normal.clone() } diff --git a/src/parallel.rs b/src/parallel.rs index 8bf8936..0ab9a62 100644 --- a/src/parallel.rs +++ b/src/parallel.rs @@ -1,6 +1,6 @@ use core::slice; use std::fs::File; -use std::io::{BufWriter, Write}; +use std::io::{BufReader, BufWriter, Read, Seek, SeekFrom, Write}; use std::marker; use std::path::Path; use std::sync::atomic::{AtomicBool, AtomicU32, AtomicU64, Ordering}; @@ -8,47 +8,116 @@ use std::sync::atomic::{AtomicBool, AtomicU32, AtomicU64, Ordering}; use heed::types::Bytes; use heed::{BytesDecode, BytesEncode, RoTxn}; use memmap2::Mmap; -use nohash::{BuildNoHashHasher, IntMap, IntSet}; +use nohash::{BuildNoHashHasher, IntMap}; use rand::seq::index; use rand::Rng; use roaring::{RoaringBitmap, RoaringTreemap}; use crate::internals::{KeyCodec, Leaf, NodeCodec}; use crate::key::{Key, Prefix, PrefixCodec}; -use crate::node::{Node, SplitPlaneNormal}; +use crate::node::Node; use crate::{Database, Distance, Error, ItemId, Result}; +#[derive(Default, Debug)] +enum TmpNodesState { + Writing(BufWriter), + Reading(BufReader), + // Ugly trick because otherwise I can't take the value out of the enum. Can we do better? + // The enum should never be let in this state. + #[default] + Invalid, +} + +impl TmpNodesState { + pub fn write_all(&mut self, bytes: &[u8]) -> Result<()> { + let this = match std::mem::take(self) { + TmpNodesState::Writing(mut writer) => { + writer.write_all(bytes)?; + TmpNodesState::Writing(writer) + } + TmpNodesState::Reading(reader) => { + let mut writer = BufWriter::new(reader.into_inner()); + writer.write_all(bytes)?; + TmpNodesState::Writing(writer) + } + TmpNodesState::Invalid => unreachable!(), + }; + + debug_assert!(!matches!(this, TmpNodesState::Invalid)); + + *self = this; + Ok(()) + } + + pub fn read_all(&mut self, (start, end): (usize, usize)) -> Result> { + debug_assert!(start < end); + let mut buffer = vec![0; end - start]; + + let this = match std::mem::take(self) { + TmpNodesState::Writing(mut writer) => { + writer.flush()?; + let mut reader = BufReader::new(writer.into_inner().expect("Could not convert the writer to a file even thought it was flushed right before")); + reader.seek(SeekFrom::Start(start as u64))?; + reader.read_exact(&mut buffer)?; + TmpNodesState::Reading(reader) + } + TmpNodesState::Reading(mut reader) => { + reader.seek(SeekFrom::Start(start as u64))?; + reader.read_exact(&mut buffer)?; + TmpNodesState::Reading(reader) + } + TmpNodesState::Invalid => unreachable!(), + }; + + debug_assert!(!matches!(this, TmpNodesState::Invalid)); + + *self = this; + Ok(buffer) + } + + pub fn into_inner(self) -> Result { + let file = match self { + TmpNodesState::Writing(mut writer) => { + writer.flush()?; + writer.into_inner().expect("Could not convert the writer to a file even thought it was flushed right before") + } + TmpNodesState::Reading(reader) => reader.into_inner(), + TmpNodesState::Invalid => unreachable!(), + }; + Ok(file) + } +} + /// A structure to store the tree nodes out of the heed database. +/// You should avoid alternating between writing and reading as it flushes the file on each operation and lose the read buffer. +/// The structure is optimized for reading the last written nodes. pub struct TmpNodes { - file: BufWriter, + file: TmpNodesState, ids: Vec, bounds: Vec, deleted: RoaringBitmap, - remap_ids: IntMap, _marker: marker::PhantomData, } -impl<'a, DE: BytesEncode<'a>> TmpNodes { +impl<'a, D: Distance> TmpNodes { /// Creates an empty `TmpNodes`. - pub fn new() -> heed::Result> { + pub fn new() -> heed::Result> { Ok(TmpNodes { - file: tempfile::tempfile().map(BufWriter::new)?, + file: TmpNodesState::Writing(tempfile::tempfile().map(BufWriter::new)?), ids: Vec::new(), bounds: vec![0], deleted: RoaringBitmap::new(), - remap_ids: IntMap::default(), _marker: marker::PhantomData, }) } /// Creates an empty `TmpNodes` in the defined folder. - pub fn new_in(path: &Path) -> heed::Result> { + pub fn new_in(path: &Path) -> heed::Result> { Ok(TmpNodes { - file: tempfile::tempfile_in(path).map(BufWriter::new)?, + file: TmpNodesState::Writing(tempfile::tempfile_in(path).map(BufWriter::new)?), ids: Vec::new(), bounds: vec![0], deleted: RoaringBitmap::new(), - remap_ids: IntMap::default(), _marker: marker::PhantomData, }) } @@ -59,10 +128,10 @@ impl<'a, DE: BytesEncode<'a>> TmpNodes { // TODO move that in the type &mut self, item: ItemId, - data: &'a DE::EItem, - ) -> heed::Result<()> { + data: &'a Node, + ) -> Result<()> { assert!(item != ItemId::MAX); - let bytes = DE::bytes_encode(data).map_err(heed::Error::Encoding)?; + let bytes = NodeCodec::bytes_encode(data).map_err(heed::Error::Encoding)?; self.file.write_all(&bytes)?; let last_bound = self.bounds.last().unwrap(); self.bounds.push(last_bound + bytes.len()); @@ -74,13 +143,18 @@ impl<'a, DE: BytesEncode<'a>> TmpNodes { Ok(()) } - /// Remap the item id of an already inserted node to another node. - /// - /// Only applies to the nodes to insert. It won't interact with the to_delete nodes. - pub fn remap(&mut self, current: ItemId, new: ItemId) { - if current != new { - self.remap_ids.insert(current, new); - } + /// Get the node at the given item id. + /// Ignore the remapped ids and deletions, only suitable when appending to the file. + /// A flush will be executed on the file if the previous operation was a write. + pub fn get(&mut self, item: ItemId) -> Result>> { + // In our current implementation, when we starts retrieving the nodes, it's always the nodes of the last tree, + // so it makes sense to search in reverse order. + let Some(position) = self.ids.iter().rev().position(|id| *id == item) else { + return Ok(None); + }; + let bounds = &self.bounds[self.bounds.len() - position - 2..self.bounds.len() - position]; + let bytes = self.file.read_all((bounds[0], bounds[1]))?; + Ok(Some(NodeCodec::bytes_decode(&bytes).map_err(heed::Error::Decoding)?.into_owned())) } /// Delete the tmp_nodes and the node in the database. @@ -91,18 +165,12 @@ impl<'a, DE: BytesEncode<'a>> TmpNodes { /// Converts it into a readers to read the nodes. pub fn into_bytes_reader(self) -> Result { - let file = self.file.into_inner().map_err(|iie| iie.into_error())?; + let file = self.file.into_inner()?; // safety: No one should move our files around let mmap = unsafe { Mmap::map(&file)? }; #[cfg(unix)] mmap.advise(memmap2::Advice::Sequential)?; - Ok(TmpNodesReader { - mmap, - ids: self.ids, - bounds: self.bounds, - deleted: self.deleted, - remap_ids: self.remap_ids, - }) + Ok(TmpNodesReader { mmap, ids: self.ids, bounds: self.bounds, deleted: self.deleted }) } } @@ -112,7 +180,6 @@ pub struct TmpNodesReader { ids: Vec, bounds: Vec, deleted: RoaringBitmap, - remap_ids: IntMap, } impl TmpNodesReader { @@ -126,10 +193,6 @@ impl TmpNodesReader { .iter() .zip(self.bounds.windows(2)) .filter(|(&id, _)| !self.deleted.contains(id)) - .map(|(id, bounds)| match self.remap_ids.get(id) { - Some(new_id) => (new_id, bounds), - None => (id, bounds), - }) .map(|(id, bounds)| { let [start, end] = [bounds[0], bounds[1]]; (*id, &self.mmap[start..end]) @@ -202,58 +265,26 @@ pub struct ImmutableLeafs<'t, D> { impl<'t, D: Distance> ImmutableLeafs<'t, D> { /// Creates the structure by fetching all the leaf pointers /// and keeping the transaction making the pointers valid. - /// Do not take more items than memory allows. - /// Remove from the list of candidates all the items that were selected and return them. pub fn new( rtxn: &'t RoTxn, database: Database, + items: &RoaringBitmap, index: u16, - candidates: &mut RoaringBitmap, - memory: usize, - ) -> heed::Result<(Self, RoaringBitmap)> { - let page_size = page_size::get(); - let nb_page_allowed = (memory as f64 / page_size as f64).floor() as usize; - - let mut leafs = IntMap::with_capacity_and_hasher( - nb_page_allowed.min(candidates.len() as usize), // We cannot approximate the capacity better because we don't know yet the size of an item - BuildNoHashHasher::default(), - ); - let mut pages_used = IntSet::with_capacity_and_hasher( - nb_page_allowed.min(candidates.len() as usize), - BuildNoHashHasher::default(), - ); - let mut selected_items = RoaringBitmap::new(); + ) -> heed::Result { + let mut leafs = + IntMap::with_capacity_and_hasher(items.len() as usize, BuildNoHashHasher::default()); let mut constant_length = None; - while let Some(item_id) = candidates.select(0) { + for item_id in items { let bytes = database.remap_data_type::().get(rtxn, &Key::item(index, item_id))?.unwrap(); assert_eq!(*constant_length.get_or_insert(bytes.len()), bytes.len()); let ptr = bytes.as_ptr(); - let addr = ptr as usize; - let start = addr / page_size; - let end = (addr + bytes.len()) / page_size; - - pages_used.insert(start); - if start != end { - pages_used.insert(end); - } - - if pages_used.len() >= nb_page_allowed && leafs.len() >= 200 { - break; - } - - // Safe because the items comes from another roaring bitmap - selected_items.push(item_id); - candidates.remove_smallest(1); leafs.insert(item_id, ptr); } - Ok(( - ImmutableLeafs { leafs, constant_length, _marker: marker::PhantomData }, - selected_items, - )) + Ok(ImmutableLeafs { leafs, constant_length, _marker: marker::PhantomData }) } /// Returns the leafs identified by the given ID. @@ -467,40 +498,6 @@ impl<'t, D: Distance> ImmutableTrees<'t, D> { Ok(ImmutableTrees { trees, _marker: marker::PhantomData }) } - /// Creates the structure by fetching all the children of the `start`ing tree nodes specified. - /// Keeps a reference to the transaction to ensure the pointers stays valid. - pub fn sub_tree_from_id( - rtxn: &'t RoTxn, - database: Database, - index: u16, - start: ItemId, - ) -> Result { - let mut trees = IntMap::default(); - let mut explore = vec![start]; - while let Some(current) = explore.pop() { - let bytes = - database.remap_data_type::().get(rtxn, &Key::tree(index, current))?.unwrap(); - let node: Node<'_, D> = NodeCodec::bytes_decode(bytes).unwrap(); - match node { - Node::Leaf(_leaf) => unreachable!(), - Node::Descendants(_descendants) => { - trees.insert(current, (bytes.len(), bytes.as_ptr())); - } - Node::SplitPlaneNormal(SplitPlaneNormal { left, right, normal: _ }) => { - trees.insert(current, (bytes.len(), bytes.as_ptr())); - explore.push(left); - explore.push(right); - } - } - } - - Ok(Self { trees, _marker: marker::PhantomData }) - } - - pub fn empty() -> Self { - Self { trees: IntMap::default(), _marker: marker::PhantomData } - } - /// Returns the tree node identified by the given ID. pub fn get(&self, item_id: ItemId) -> heed::Result>> { let (ptr, len) = match self.trees.get(&item_id) { diff --git a/src/tests/fit_in_memory.rs b/src/tests/fit_in_memory.rs new file mode 100644 index 0000000..1488f4d --- /dev/null +++ b/src/tests/fit_in_memory.rs @@ -0,0 +1,75 @@ +use crate::distance::Distance; +use crate::distances::Euclidean; +use crate::writer::fit_in_memory; +use rand::rngs::StdRng; +use rand::SeedableRng; +use roaring::RoaringBitmap; + +#[test] +fn test_empty_bitmap() { + let mut rng = StdRng::seed_from_u64(28); + let mut bitmap = RoaringBitmap::new(); + let result = fit_in_memory::(1024 * 1024, &mut bitmap, 128, &mut rng); + assert!(result.is_none()); +} + +#[test] +fn test_all_items_fit() { + let mut rng = StdRng::seed_from_u64(35); + let mut bitmap = RoaringBitmap::from_sorted_iter(0..100).unwrap(); + let result = fit_in_memory::(usize::MAX, &mut bitmap, 128, &mut rng).unwrap(); + assert_eq!(result.len(), 100); + assert!(bitmap.is_empty()); +} + +#[test] +fn test_less_items_than_dimensions() { + let mut rng = StdRng::seed_from_u64(26); + let mut bitmap = RoaringBitmap::from_sorted_iter(0..10).unwrap(); + let result = fit_in_memory::(0, &mut bitmap, 128, &mut rng).unwrap(); + assert_eq!(result.len(), 10); + assert!(bitmap.is_empty()); +} + +#[test] +fn test_partial_fit() { + let mut rng = StdRng::seed_from_u64(3141592); + let mut bitmap = RoaringBitmap::from_sorted_iter(0..1000).unwrap(); + + let dimensions = 128; + let largest_item_size = Euclidean::size_of_item(dimensions); + let memory = largest_item_size * 500; + + let result = fit_in_memory::(memory, &mut bitmap, dimensions, &mut rng).unwrap(); + // We can't assert properly on the len of the result because the page_size vary depending on the system + assert!(result.len() > dimensions as u64); + assert_eq!(1000, bitmap.len() + result.len()); +} + +#[test] +fn test_random_selection() { + let mut rng = StdRng::seed_from_u64(24); + let bitmap = RoaringBitmap::from_sorted_iter(0..1000).unwrap(); + + let dimensions = 128; + let largest_item_size = Euclidean::size_of_item(dimensions); + let memory = largest_item_size * 500; + + // Get first batch + let mut bitmap_clone = bitmap.clone(); + let result1 = + fit_in_memory::(memory, &mut bitmap_clone, dimensions, &mut rng).unwrap(); + assert!(result1.len() > dimensions as u64); + assert_eq!(1000, bitmap_clone.len() + result1.len()); + + // Get second batch + let mut bitmap_clone = bitmap.clone(); + let result2 = + fit_in_memory::(memory, &mut bitmap_clone, dimensions, &mut rng).unwrap(); + assert!(result2.len() > dimensions as u64); + assert_eq!(1000, bitmap_clone.len() + result2.len()); + + // Batch must be different because of random selection but they must contains the same number of items + assert_eq!(result1.len(), result2.len()); + assert_ne!(result1, result2); +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 55e1830..94069bd 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -12,7 +12,9 @@ use crate::version::VersionCodec; use crate::{Database, Distance, MetadataCodec, NodeCodec, NodeMode, Reader}; mod binary_quantized; +mod fit_in_memory; mod reader; +mod tmp_nodes; mod upgrade; mod writer; diff --git a/src/tests/snapshots/arroy__tests__writer__write_and_update_lot_of_random_points-2.snap b/src/tests/snapshots/arroy__tests__writer__write_and_update_lot_of_random_points-2.snap index ced1290..f569e84 100644 --- a/src/tests/snapshots/arroy__tests__writer__write_and_update_lot_of_random_points-2.snap +++ b/src/tests/snapshots/arroy__tests__writer__write_and_update_lot_of_random_points-2.snap @@ -6,201 +6,195 @@ expression: handle Dumping index 0 Root: Metadata { dimensions: 30, items: RoaringBitmap<100 values between 0 and 99>, roots: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], distance: "euclidean" } Version: Version { major: 0, minor: 7, patch: 0 } -Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 14, right: 17, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.8587" }, vector: [-0.1204, 0.0883, -0.1193, 0.0487, -0.2937, 0.1358, 0.0452, 0.0063, 0.0002, 0.3049, "other ..."] } }) -Tree 1: SplitPlaneNormal(SplitPlaneNormal { left: 21, right: 26, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.5437" }, vector: [-0.3998, -0.0657, -0.1329, -0.0396, 0.0148, 0.1862, -0.0011, 0.0465, 0.1301, 0.1252, "other ..."] } }) -Tree 2: SplitPlaneNormal(SplitPlaneNormal { left: 34, right: 37, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.6127" }, vector: [-0.0024, -0.2313, -0.3514, 0.2460, 0.1578, 0.1174, 0.1903, 0.2528, -0.1544, -0.0109, "other ..."] } }) -Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 41, right: 46, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.3197" }, vector: [-0.4323, -0.0243, -0.2204, -0.2440, -0.1659, 0.2287, 0.0464, 0.1377, 0.0778, -0.1993, "other ..."] } }) -Tree 4: SplitPlaneNormal(SplitPlaneNormal { left: 56, right: 57, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.9992" }, vector: [0.1629, 0.1656, 0.3348, -0.1713, -0.2520, 0.0814, -0.0464, 0.2963, 0.2613, -0.1932, "other ..."] } }) -Tree 5: SplitPlaneNormal(SplitPlaneNormal { left: 63, right: 66, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.2444" }, vector: [-0.3338, 0.1111, 0.3212, 0.0072, -0.3659, 0.2717, 0.0245, -0.1254, -0.0674, 0.0525, "other ..."] } }) -Tree 6: SplitPlaneNormal(SplitPlaneNormal { left: 72, right: 75, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.0702" }, vector: [0.0110, 0.0447, -0.1004, -0.0082, 0.3757, 0.1258, -0.0217, -0.0066, -0.0891, -0.1647, "other ..."] } }) -Tree 7: SplitPlaneNormal(SplitPlaneNormal { left: 83, right: 84, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.6027" }, vector: [-0.2057, -0.2175, 0.2291, 0.1105, 0.1273, -0.0631, 0.3744, 0.0516, 0.1016, 0.1725, "other ..."] } }) -Tree 8: SplitPlaneNormal(SplitPlaneNormal { left: 88, right: 91, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.1412" }, vector: [-0.1594, -0.1073, 0.0726, 0.0262, -0.0675, -0.0409, 0.2032, -0.0833, 0.0508, 0.1313, "other ..."] } }) -Tree 9: SplitPlaneNormal(SplitPlaneNormal { left: 97, right: 102, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.1949" }, vector: [0.3612, -0.2770, -0.0294, -0.3396, -0.1454, -0.0856, 0.0828, 0.0365, 0.1651, -0.0627, "other ..."] } }) -Tree 14: SplitPlaneNormal(SplitPlaneNormal { left: 18, right: 47, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.3583" }, vector: [-0.1507, 0.0936, -0.1410, -0.0426, -0.0272, 0.0549, -0.2374, 0.1346, 0.4567, 0.1029, "other ..."] } }) -Tree 17: SplitPlaneNormal(SplitPlaneNormal { left: 67, right: 76, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.5487" }, vector: [-0.0609, -0.1763, 0.1863, -0.1253, 0.0214, 0.1748, -0.3100, 0.0888, 0.0450, -0.0296, "other ..."] } }) -Tree 18: Descendants(Descendants { descendants: [4, 7, 8, 9, 10, 11, 16, 19, 20, 31, 33, 35, 38, 39, 45, 59, 63, 70, 74, 76, 80, 89, 93, 97, 98] }) -Tree 21: Descendants(Descendants { descendants: [6, 8, 9, 10, 11, 12, 18, 31, 34, 39, 43, 45, 51, 52, 53, 59, 64, 69, 70, 72, 73, 74, 75, 76, 79, 80, 87, 91, 98] }) -Tree 22: SplitPlaneNormal(SplitPlaneNormal { left: 92, right: 103, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.5808" }, vector: [-0.0861, -0.1813, -0.2528, 0.0210, 0.4075, 0.1035, -0.0114, -0.1078, -0.2045, 0.2059, "other ..."] } }) -Tree 25: SplitPlaneNormal(SplitPlaneNormal { left: 105, right: 106, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.6646" }, vector: [0.0595, 0.0292, 0.2245, 0.1728, -0.0419, 0.2241, -0.1050, -0.4817, -0.2974, -0.1538, "other ..."] } }) -Tree 26: SplitPlaneNormal(SplitPlaneNormal { left: 22, right: 25, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.1262" }, vector: [-0.3075, 0.0809, -0.0415, -0.1913, -0.0817, -0.1210, 0.3237, -0.1618, 0.3302, 0.3665, "other ..."] } }) -Tree 27: Descendants(Descendants { descendants: [2, 13, 21, 25, 41, 42, 48, 51, 52, 54, 55, 56, 61, 67, 68, 71, 78, 82, 84, 88, 90] }) -Tree 34: SplitPlaneNormal(SplitPlaneNormal { left: 110, right: 111, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.1455" }, vector: [-0.0277, -0.0613, 0.0898, -0.0738, -0.2247, 0.4502, 0.0476, 0.1368, 0.0567, -0.0642, "other ..."] } }) -Tree 37: SplitPlaneNormal(SplitPlaneNormal { left: 115, right: 116, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.5907" }, vector: [0.2827, 0.1375, 0.0248, -0.0827, -0.0255, 0.1696, -0.0483, 0.0977, -0.0035, 0.0598, "other ..."] } }) -Tree 38: Descendants(Descendants { descendants: [6, 17, 27, 28, 37, 40, 46, 50, 62, 64, 72, 73, 85, 87, 91, 96] }) -Tree 41: SplitPlaneNormal(SplitPlaneNormal { left: 118, right: 119, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.5946" }, vector: [-0.0666, 0.2425, 0.2231, -0.0832, 0.0048, 0.1720, -0.3127, 0.3050, 0.2562, -0.1960, "other ..."] } }) -Tree 46: SplitPlaneNormal(SplitPlaneNormal { left: 121, right: 124, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.2123" }, vector: [0.1203, 0.0802, 0.0132, -0.0008, -0.0150, -0.1361, 0.1184, 0.0181, -0.3241, 0.0382, "other ..."] } }) -Tree 47: SplitPlaneNormal(SplitPlaneNormal { left: 27, right: 38, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.2441" }, vector: [-0.0337, 0.0395, 0.2545, -0.0209, -0.0500, 0.0174, -0.0905, 0.1263, -0.1114, -0.0391, "other ..."] } }) -Tree 52: SplitPlaneNormal(SplitPlaneNormal { left: 126, right: 127, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.6694" }, vector: [0.3277, 0.2137, 0.1183, -0.2773, 0.2715, -0.1895, -0.1208, 0.0624, 0.2566, 0.2144, "other ..."] } }) -Tree 55: SplitPlaneNormal(SplitPlaneNormal { left: 131, right: 132, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.8189" }, vector: [0.2277, 0.0114, -0.2483, 0.3118, 0.2174, 0.1382, 0.1920, -0.0382, -0.2836, -0.1416, "other ..."] } }) -Tree 56: SplitPlaneNormal(SplitPlaneNormal { left: 52, right: 55, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.6438" }, vector: [0.0375, 0.0466, -0.1290, -0.0388, -0.0623, 0.0907, 0.0547, 0.3634, 0.1866, 0.2968, "other ..."] } }) -Tree 57: Descendants(Descendants { descendants: [3, 4, 5, 10, 11, 12, 20, 21, 22, 28, 39, 50, 52, 54, 64, 67, 69, 71, 81, 91, 92] }) -Tree 59: Descendants(Descendants { descendants: [3, 15, 21, 37, 40, 44, 46, 54, 57, 64, 69, 73, 76, 77, 79, 82, 83, 86, 87, 89, 95, 99] }) -Tree 62: SplitPlaneNormal(SplitPlaneNormal { left: 136, right: 137, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.6681" }, vector: [0.0710, -0.3201, -0.2137, 0.0807, 0.1029, 0.1935, 0.0684, 0.0305, -0.3658, 0.0831, "other ..."] } }) -Tree 63: SplitPlaneNormal(SplitPlaneNormal { left: 59, right: 62, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.1936" }, vector: [0.3169, -0.1754, -0.1837, -0.0504, 0.1379, 0.2769, -0.0601, -0.2512, 0.2685, -0.1864, "other ..."] } }) -Tree 66: SplitPlaneNormal(SplitPlaneNormal { left: 139, right: 140, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0261" }, vector: [-0.0792, -0.0103, -0.1817, 0.0642, -0.0389, 0.0718, -0.1323, -0.0211, 0.0930, 0.1575, "other ..."] } }) -Tree 67: Descendants(Descendants { descendants: [0, 1, 12, 18, 23, 24, 26, 34, 36, 43, 47, 49, 53, 69, 79, 92, 94, 95, 99] }) -Tree 72: SplitPlaneNormal(SplitPlaneNormal { left: 142, right: 143, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.1014" }, vector: [-0.2587, 0.1207, 0.1587, 0.2606, 0.2159, -0.3657, -0.0254, 0.1476, -0.1004, 0.0398, "other ..."] } }) -Tree 75: SplitPlaneNormal(SplitPlaneNormal { left: 145, right: 148, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.3356" }, vector: [-0.0211, 0.0775, -0.3595, -0.3072, -0.0880, 0.1992, 0.0779, 0.2085, 0.2588, 0.1848, "other ..."] } }) -Tree 76: Descendants(Descendants { descendants: [3, 5, 14, 15, 22, 29, 30, 32, 44, 57, 58, 60, 65, 66, 75, 77, 81, 83, 86] }) -Tree 79: SplitPlaneNormal(SplitPlaneNormal { left: 150, right: 151, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.4333" }, vector: [-0.2306, -0.0192, 0.0642, 0.0643, 0.1117, 0.0232, -0.1879, -0.1950, 0.1756, 0.3299, "other ..."] } }) -Tree 82: SplitPlaneNormal(SplitPlaneNormal { left: 153, right: 154, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.7035" }, vector: [-0.1421, -0.0018, 0.1388, 0.2021, -0.0849, -0.1314, -0.2178, 0.0890, -0.1961, -0.2924, "other ..."] } }) -Tree 83: SplitPlaneNormal(SplitPlaneNormal { left: 79, right: 82, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.8187" }, vector: [-0.0254, 0.2078, -0.1625, -0.1171, -0.1369, 0.1272, 0.0764, -0.1323, 0.2202, 0.2376, "other ..."] } }) -Tree 84: Descendants(Descendants { descendants: [0, 4, 17, 18, 23, 33, 43, 48, 49, 53, 55, 56, 59, 64, 65, 69, 75, 76, 79, 82, 84, 90, 97, 98, 99] }) -Tree 88: SplitPlaneNormal(SplitPlaneNormal { left: 156, right: 159, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0409" }, vector: [-0.1687, -0.0628, 0.1602, 0.0723, -0.1128, -0.1952, 0.0614, -0.0014, -0.1617, -0.3672, "other ..."] } }) -Tree 91: SplitPlaneNormal(SplitPlaneNormal { left: 161, right: 164, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.3744" }, vector: [0.3148, -0.3027, 0.0198, -0.2564, 0.2014, -0.0346, -0.1262, 0.2663, -0.0236, -0.0206, "other ..."] } }) -Tree 92: Descendants(Descendants { descendants: [0, 1, 4, 20, 21, 25, 40, 41, 50, 60, 62, 77, 78, 89, 93, 94] }) -Tree 97: SplitPlaneNormal(SplitPlaneNormal { left: 166, right: 167, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.9072" }, vector: [-0.0095, 0.0137, 0.0291, -0.0747, 0.1161, 0.2513, -0.0429, 0.1858, -0.2055, -0.3207, "other ..."] } }) -Tree 102: SplitPlaneNormal(SplitPlaneNormal { left: 169, right: 172, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.2241" }, vector: [-0.0066, 0.1769, -0.0978, -0.1370, 0.0001, -0.2377, 0.3400, -0.0391, -0.0535, -0.3450, "other ..."] } }) -Tree 103: Descendants(Descendants { descendants: [2, 7, 13, 16, 22, 29, 30, 33, 38, 44, 56, 58, 63, 67, 83, 84, 88, 96] }) -Tree 105: Descendants(Descendants { descendants: [3, 15, 17, 24, 35, 37, 42, 46, 47, 54, 55, 57, 61, 66, 71, 82, 85, 86, 92, 95] }) -Tree 106: Descendants(Descendants { descendants: [5, 14, 19, 23, 26, 27, 28, 32, 36, 48, 49, 65, 68, 81, 90, 97, 99] }) -Tree 108: Descendants(Descendants { descendants: [0, 3, 6, 10, 15, 17, 21, 28, 32, 34, 38, 40, 52, 53, 55, 59, 71, 77, 86, 87, 89] }) -Tree 109: Descendants(Descendants { descendants: [4, 23, 26, 43, 54, 62, 63, 84, 96, 99] }) -Tree 110: SplitPlaneNormal(SplitPlaneNormal { left: 108, right: 109, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.0678" }, vector: [0.1832, -0.0604, -0.1903, 0.1249, 0.1529, -0.0436, 0.0464, -0.2818, -0.1328, -0.1161, "other ..."] } }) -Tree 111: Descendants(Descendants { descendants: [5, 12, 14, 25, 27, 36, 46, 67, 72, 73, 85, 88, 91] }) -Tree 113: Descendants(Descendants { descendants: [1, 7, 8, 9, 11, 16, 19, 22, 31, 33, 39, 45, 58, 65, 66, 69, 80, 97] }) -Tree 114: Descendants(Descendants { descendants: [18, 35, 44, 48, 49, 51, 56, 68, 70, 74, 75, 76, 81, 83, 94] }) -Tree 115: SplitPlaneNormal(SplitPlaneNormal { left: 113, right: 114, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.7197" }, vector: [-0.1191, -0.1347, -0.1105, -0.0634, 0.0476, -0.0570, 0.1561, 0.0278, 0.3110, 0.1025, "other ..."] } }) -Tree 116: Descendants(Descendants { descendants: [2, 13, 20, 24, 29, 30, 37, 41, 42, 47, 50, 57, 60, 61, 64, 78, 79, 82, 90, 92, 93, 95, 98] }) -Tree 118: Descendants(Descendants { descendants: [4, 7, 8, 15, 17, 26, 27, 30, 34, 37, 38, 45, 46, 55, 62, 63, 64, 65, 66, 74, 76, 79, 82, 87, 88, 93, 95, 96, 99] }) -Tree 119: Descendants(Descendants { descendants: [3, 6, 21, 23, 24, 28, 40, 54, 67, 72, 73, 77, 91] }) -Tree 121: Descendants(Descendants { descendants: [5, 9, 11, 14, 18, 19, 22, 25, 32, 35, 39, 42, 44, 51, 53, 56, 57, 61, 68, 69, 75, 81, 83, 84, 85, 90, 92] }) -Tree 122: Descendants(Descendants { descendants: [10, 13, 33, 48, 52, 58, 71, 78, 80, 86, 89] }) -Tree 123: Descendants(Descendants { descendants: [0, 1, 2, 12, 16, 20, 29, 31, 36, 41, 43, 47, 49, 50, 59, 60, 70, 94, 97, 98] }) -Tree 124: SplitPlaneNormal(SplitPlaneNormal { left: 122, right: 123, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0070" }, vector: [0.2068, -0.2665, 0.2804, -0.2477, -0.2679, 0.2094, 0.1012, -0.0581, -0.1127, 0.2252, "other ..."] } }) -Tree 126: Descendants(Descendants { descendants: [0, 13, 18, 19, 25, 32, 36, 37, 41, 51, 56, 59, 62, 66, 78, 83, 84, 88, 90, 93, 96, 98] }) -Tree 127: Descendants(Descendants { descendants: [2, 6, 23, 26, 27, 34, 38, 40, 43, 45, 46, 60, 63, 73, 87, 89, 99] }) -Tree 129: Descendants(Descendants { descendants: [1, 8, 14, 30, 47, 48, 49, 57, 61, 70, 74, 75, 85, 94, 95] }) -Tree 130: Descendants(Descendants { descendants: [7, 9, 15, 17, 24, 33, 42, 44, 53, 55, 58, 65, 68, 72, 76, 77, 79, 82, 86, 97] }) -Tree 131: SplitPlaneNormal(SplitPlaneNormal { left: 129, right: 130, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.4878" }, vector: [0.1437, -0.0597, 0.1705, -0.1005, 0.2766, -0.0831, -0.1938, 0.2954, -0.1470, 0.0447, "other ..."] } }) -Tree 132: Descendants(Descendants { descendants: [16, 29, 31, 35, 80] }) -Tree 134: Descendants(Descendants { descendants: [13, 19, 20, 23, 39, 42, 43, 45, 60, 63, 74, 75, 96] }) -Tree 135: Descendants(Descendants { descendants: [6, 24, 26, 28, 32, 34, 41, 47, 50, 51, 52, 53, 55, 61, 71, 72, 78, 85, 90, 92] }) -Tree 136: SplitPlaneNormal(SplitPlaneNormal { left: 134, right: 135, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.2948" }, vector: [-0.0303, 0.0203, -0.1330, -0.2370, -0.2714, 0.3580, 0.1198, 0.0400, 0.1578, 0.0378, "other ..."] } }) -Tree 137: Descendants(Descendants { descendants: [2, 4, 16, 29, 30, 35, 36, 48, 70, 80, 88] }) -Tree 139: Descendants(Descendants { descendants: [5, 7, 9, 14, 31, 33, 56, 58, 59, 65, 68, 93] }) -Tree 140: Descendants(Descendants { descendants: [0, 1, 8, 10, 11, 12, 17, 18, 22, 25, 27, 38, 49, 62, 66, 67, 81, 84, 91, 94, 97, 98] }) -Tree 142: Descendants(Descendants { descendants: [0, 1, 11, 12, 25, 30, 36, 37, 50, 55, 64, 72, 85, 91, 92, 94] }) -Tree 143: Descendants(Descendants { descendants: [3, 7, 8, 9, 17, 18, 27, 29, 33, 34, 40, 46, 62, 65, 66, 69, 73, 74, 76, 79, 81, 82, 87, 93, 95, 99] }) -Tree 145: Descendants(Descendants { descendants: [2, 4, 10, 13, 16, 19, 20, 31, 35, 38, 39, 45, 52, 54, 58, 59, 60, 63, 67, 70, 80, 84, 89, 97, 98] }) -Tree 146: Descendants(Descendants { descendants: [6, 15, 23, 24, 26, 43, 53, 71, 86] }) -Tree 147: Descendants(Descendants { descendants: [5, 14, 21, 22, 28, 32, 41, 42, 44, 47, 48, 49, 51, 56, 57, 61, 68, 75, 77, 78, 83, 88, 90, 96] }) -Tree 148: SplitPlaneNormal(SplitPlaneNormal { left: 146, right: 147, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.5716" }, vector: [-0.2365, 0.0094, -0.0455, 0.1613, -0.1131, 0.2797, 0.0360, -0.1615, -0.1389, -0.1377, "other ..."] } }) -Tree 150: Descendants(Descendants { descendants: [6, 12, 13, 16, 20, 29, 31, 35, 36, 38, 39, 41, 45, 50, 51, 52, 67, 80, 83, 86, 89, 93] }) -Tree 151: Descendants(Descendants { descendants: [2, 25, 42, 46, 60, 61, 63, 74, 88, 96] }) -Tree 153: Descendants(Descendants { descendants: [24, 27, 34, 40, 47, 57, 72, 73, 77, 78, 85, 87, 92] }) -Tree 154: Descendants(Descendants { descendants: [1, 3, 5, 7, 8, 9, 10, 11, 14, 15, 19, 21, 22, 26, 28, 30, 32, 37, 44, 54, 58, 62, 66, 68, 70, 71, 81, 91, 94, 95] }) -Tree 156: Descendants(Descendants { descendants: [3, 6, 23, 24, 27, 30, 34, 36, 40, 47, 62, 72, 73, 77, 79, 85, 91] }) -Tree 157: Descendants(Descendants { descendants: [0, 10, 20, 21, 32, 41, 50, 52, 59, 89, 90, 93] }) -Tree 158: Descendants(Descendants { descendants: [2, 4, 13, 28, 37, 38, 42, 43, 45, 51, 54, 60, 61, 71, 78, 84, 86, 92, 95, 96, 98] }) -Tree 159: SplitPlaneNormal(SplitPlaneNormal { left: 157, right: 158, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0248" }, vector: [-0.0094, 0.1652, -0.3196, -0.0240, 0.2200, -0.1241, 0.0343, 0.0713, 0.1279, 0.2481, "other ..."] } }) -Tree 161: Descendants(Descendants { descendants: [8, 17, 18, 48, 49, 66, 75, 81, 87, 94, 97, 99] }) -Tree 162: Descendants(Descendants { descendants: [1, 9, 12, 16, 19, 25, 26, 31, 35, 39, 55, 56, 65, 69, 70, 74, 80, 82] }) -Tree 163: Descendants(Descendants { descendants: [5, 7, 11, 14, 15, 22, 29, 33, 44, 46, 53, 57, 58, 63, 64, 67, 68, 76, 83, 88] }) -Tree 164: SplitPlaneNormal(SplitPlaneNormal { left: 162, right: 163, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.2275" }, vector: [0.1379, 0.1448, 0.0057, -0.0746, 0.1027, 0.3650, -0.1491, 0.0923, 0.0893, -0.0562, "other ..."] } }) -Tree 166: Descendants(Descendants { descendants: [1, 2, 3, 6, 10, 13, 24, 25, 27, 38, 40, 46, 48, 54, 60, 62, 65, 66, 72, 85, 90, 92, 97] }) -Tree 167: Descendants(Descendants { descendants: [8, 11, 16, 19, 28, 29, 33, 39, 45, 51, 57, 58, 61, 63, 67, 77, 80, 83, 87, 88, 89, 93, 95, 96] }) -Tree 169: Descendants(Descendants { descendants: [7, 9, 14, 15, 26, 30, 44, 49, 68, 75, 76, 82, 84] }) -Tree 170: Descendants(Descendants { descendants: [4, 12, 17, 20, 23, 31, 34, 35, 36, 37, 41, 42, 43, 50, 53, 55, 56, 59, 64, 69, 70, 73, 74, 78, 86, 98, 99] }) -Tree 171: Descendants(Descendants { descendants: [0, 5, 18, 21, 22, 32, 47, 52, 71, 79, 81, 91, 94] }) -Tree 172: SplitPlaneNormal(SplitPlaneNormal { left: 170, right: 171, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.4343" }, vector: [-0.1736, 0.3073, -0.0470, 0.1472, -0.4490, 0.2965, -0.2401, 0.0550, 0.1695, -0.1494, "other ..."] } }) -Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.3709, 0.3974, 0.5971, 0.7814, 0.2075, 0.5392, 0.4790, 0.5432, 0.4844, 0.3367, "other ..."] }) +Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 88, right: 91, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.3733" }, vector: [-0.0475, -0.1496, 0.1344, -0.1902, -0.2161, -0.4158, -0.1593, 0.1212, -0.0136, 0.2277, "other ..."] } }) +Tree 1: SplitPlaneNormal(SplitPlaneNormal { left: 76, right: 81, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.4143" }, vector: [-0.1850, 0.1162, 0.1506, 0.1488, 0.2308, 0.1370, -0.2152, -0.0274, -0.0407, -0.2282, "other ..."] } }) +Tree 2: SplitPlaneNormal(SplitPlaneNormal { left: 66, right: 73, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.0804" }, vector: [0.1941, -0.1680, -0.0860, -0.4588, 0.2054, 0.0884, 0.0622, 0.1314, 0.1377, -0.2936, "other ..."] } }) +Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 58, right: 63, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0458" }, vector: [-0.0598, -0.0926, -0.1871, -0.0077, 0.2839, 0.2008, 0.1168, -0.3345, -0.0870, 0.0621, "other ..."] } }) +Tree 4: SplitPlaneNormal(SplitPlaneNormal { left: 50, right: 53, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0933" }, vector: [-0.2249, -0.2354, -0.2492, 0.0508, -0.0488, 0.3083, 0.0932, -0.0190, -0.4116, -0.0404, "other ..."] } }) +Tree 5: SplitPlaneNormal(SplitPlaneNormal { left: 38, right: 45, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0963" }, vector: [0.0636, -0.2729, 0.4830, 0.1626, 0.0343, -0.0273, -0.0742, 0.0450, -0.3975, -0.3293, "other ..."] } }) +Tree 6: SplitPlaneNormal(SplitPlaneNormal { left: 32, right: 35, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.6869" }, vector: [0.0755, 0.2682, -0.0986, 0.3341, 0.0086, -0.0666, -0.2590, -0.1551, 0.0651, -0.0362, "other ..."] } }) +Tree 7: SplitPlaneNormal(SplitPlaneNormal { left: 26, right: 29, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0797" }, vector: [-0.0053, 0.4627, 0.0033, -0.1321, 0.2763, -0.0670, -0.0985, -0.1405, 0.3819, 0.0681, "other ..."] } }) +Tree 8: SplitPlaneNormal(SplitPlaneNormal { left: 22, right: 23, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.3843" }, vector: [-0.3055, 0.2263, 0.3598, -0.0777, -0.0538, -0.1513, -0.0809, 0.1401, 0.0514, 0.2712, "other ..."] } }) +Tree 9: SplitPlaneNormal(SplitPlaneNormal { left: 12, right: 17, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.9466" }, vector: [-0.1459, -0.2139, -0.2989, 0.0100, -0.1856, -0.0497, 0.1403, 0.0371, -0.2027, 0.1831, "other ..."] } }) +Tree 12: SplitPlaneNormal(SplitPlaneNormal { left: 118, right: 119, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.9158" }, vector: [-0.0458, 0.2305, 0.1661, 0.0458, -0.2590, -0.1403, 0.2607, 0.4083, 0.4034, -0.0825, "other ..."] } }) +Tree 15: SplitPlaneNormal(SplitPlaneNormal { left: 116, right: 117, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.6717" }, vector: [0.2202, -0.1642, -0.2834, -0.0990, 0.0846, -0.0629, -0.0479, -0.1356, -0.1214, -0.0144, "other ..."] } }) +Tree 16: Descendants(Descendants { descendants: [1, 4, 5, 7, 9, 20, 29, 31, 34, 35, 42, 49, 53, 58, 63, 65, 69, 75, 82, 83, 90, 94, 97] }) +Tree 17: SplitPlaneNormal(SplitPlaneNormal { left: 15, right: 16, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.3772" }, vector: [0.1033, -0.4242, -0.0800, -0.1632, 0.1052, -0.0050, 0.2207, -0.1568, -0.0534, -0.0278, "other ..."] } }) +Tree 20: SplitPlaneNormal(SplitPlaneNormal { left: 104, right: 105, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.3104" }, vector: [0.0826, -0.5362, 0.1182, -0.0236, -0.1482, -0.0931, 0.1951, -0.2227, -0.1086, -0.0982, "other ..."] } }) +Tree 21: SplitPlaneNormal(SplitPlaneNormal { left: 102, right: 103, normal: Leaf { header: NodeHeaderEuclidean { bias: "-1.0630" }, vector: [-0.0780, 0.1337, 0.4574, 0.0526, 0.1908, 0.0708, -0.0698, -0.1701, 0.1157, 0.0710, "other ..."] } }) +Tree 22: SplitPlaneNormal(SplitPlaneNormal { left: 20, right: 21, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.2139" }, vector: [0.0683, -0.0814, 0.0252, -0.1067, -0.2097, -0.0424, 0.1001, 0.3194, 0.0825, 0.0236, "other ..."] } }) +Tree 23: Descendants(Descendants { descendants: [1, 3, 5, 6, 7, 9, 15, 17, 26, 27, 32, 39, 44, 53, 60, 69, 73, 79, 81, 90, 92, 96] }) +Tree 26: SplitPlaneNormal(SplitPlaneNormal { left: 94, right: 95, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.2166" }, vector: [-0.1899, 0.2916, 0.3346, 0.0524, 0.0863, -0.2032, -0.0673, -0.0062, -0.1249, -0.0454, "other ..."] } }) +Tree 27: Descendants(Descendants { descendants: [2, 8, 17, 19, 23, 27, 32, 40, 41, 45, 47, 52, 53, 54, 55, 56, 64, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 91, 97, 99] }) +Tree 28: SplitPlaneNormal(SplitPlaneNormal { left: 96, right: 97, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.2331" }, vector: [-0.0662, -0.0246, 0.0656, -0.1624, -0.0047, -0.2392, 0.2543, 0.0888, 0.0744, -0.0221, "other ..."] } }) +Tree 29: SplitPlaneNormal(SplitPlaneNormal { left: 27, right: 28, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.3445" }, vector: [0.0543, -0.0671, 0.0759, 0.0437, -0.0054, -0.0953, 0.1007, 0.0988, 0.0009, -0.2796, "other ..."] } }) +Tree 32: SplitPlaneNormal(SplitPlaneNormal { left: 140, right: 141, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.3528" }, vector: [-0.1255, 0.2100, 0.2201, -0.0886, -0.0719, 0.1535, -0.0794, -0.3796, -0.0068, 0.0762, "other ..."] } }) +Tree 35: SplitPlaneNormal(SplitPlaneNormal { left: 136, right: 137, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0092" }, vector: [0.0108, -0.0562, 0.4257, 0.0562, -0.1473, 0.0892, -0.1165, -0.0178, -0.1477, -0.1727, "other ..."] } }) +Tree 38: SplitPlaneNormal(SplitPlaneNormal { left: 130, right: 131, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.5951" }, vector: [-0.2909, 0.2667, 0.1728, 0.0055, -0.1251, -0.1814, 0.1971, 0.2927, -0.0904, 0.0955, "other ..."] } }) +Tree 45: SplitPlaneNormal(SplitPlaneNormal { left: 122, right: 123, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.7796" }, vector: [0.2439, 0.1112, 0.0842, 0.0732, -0.1858, 0.1108, 0.1022, -0.0101, -0.0240, 0.0866, "other ..."] } }) +Tree 50: SplitPlaneNormal(SplitPlaneNormal { left: 112, right: 113, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.0886" }, vector: [-0.1092, 0.0967, -0.4147, 0.2370, 0.0932, -0.1638, 0.3286, -0.0270, -0.0593, 0.2244, "other ..."] } }) +Tree 53: SplitPlaneNormal(SplitPlaneNormal { left: 106, right: 109, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0112" }, vector: [0.2581, -0.1616, 0.0520, -0.0158, -0.0994, -0.1019, -0.2418, -0.0599, 0.0749, 0.0170, "other ..."] } }) +Tree 58: SplitPlaneNormal(SplitPlaneNormal { left: 100, right: 101, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.5915" }, vector: [0.1357, 0.1271, 0.4036, -0.1687, -0.1611, -0.3156, -0.0362, 0.0930, -0.0564, 0.1692, "other ..."] } }) +Tree 61: SplitPlaneNormal(SplitPlaneNormal { left: 92, right: 93, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.0411" }, vector: [0.1302, 0.1023, -0.0111, 0.0435, -0.0185, -0.2444, -0.3379, -0.0689, 0.1791, 0.0961, "other ..."] } }) +Tree 62: Descendants(Descendants { descendants: [7, 10, 11, 13, 19, 31, 33, 45, 54, 56, 62, 65, 69, 84, 91, 94, 97] }) +Tree 63: SplitPlaneNormal(SplitPlaneNormal { left: 61, right: 62, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.3949" }, vector: [-0.0495, 0.0658, 0.2323, 0.1854, 0.3495, -0.0897, -0.1301, -0.1341, -0.1506, -0.0808, "other ..."] } }) +Tree 66: SplitPlaneNormal(SplitPlaneNormal { left: 138, right: 139, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0191" }, vector: [0.1925, 0.1837, 0.2125, -0.1185, 0.0735, -0.2200, -0.0427, 0.0901, -0.2491, 0.0148, "other ..."] } }) +Tree 67: Descendants(Descendants { descendants: [10, 17, 21, 26, 36, 37, 40, 41, 47, 59, 60, 68, 74, 76, 77, 85, 96, 98] }) +Tree 72: SplitPlaneNormal(SplitPlaneNormal { left: 128, right: 129, normal: Leaf { header: NodeHeaderEuclidean { bias: "-1.4394" }, vector: [0.1356, 0.0893, 0.1515, -0.0121, 0.0644, -0.1414, -0.2150, 0.3689, 0.2727, 0.3711, "other ..."] } }) +Tree 73: SplitPlaneNormal(SplitPlaneNormal { left: 67, right: 72, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.1344" }, vector: [0.0129, 0.2435, 0.2349, -0.0484, 0.2422, -0.2681, 0.1833, -0.1857, -0.3249, -0.1537, "other ..."] } }) +Tree 76: SplitPlaneNormal(SplitPlaneNormal { left: 126, right: 127, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.0400" }, vector: [-0.1900, -0.2147, -0.0647, 0.0511, -0.4092, 0.2976, -0.0874, 0.1915, 0.0428, -0.0973, "other ..."] } }) +Tree 81: SplitPlaneNormal(SplitPlaneNormal { left: 114, right: 115, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0927" }, vector: [0.1306, -0.2980, 0.1347, 0.1086, -0.0555, -0.0421, -0.3452, 0.0438, -0.0418, -0.2373, "other ..."] } }) +Tree 84: SplitPlaneNormal(SplitPlaneNormal { left: 110, right: 111, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.2518" }, vector: [-0.1457, 0.0668, -0.0585, 0.3369, -0.3826, 0.0071, 0.1223, -0.0799, -0.1587, 0.1256, "other ..."] } }) +Tree 87: Descendants(Descendants { descendants: [0, 1, 10, 11, 13, 19, 26, 27, 30, 31, 33, 45, 46, 47, 48, 50, 54, 56, 62, 65, 70, 72, 82, 91, 97] }) +Tree 88: SplitPlaneNormal(SplitPlaneNormal { left: 84, right: 87, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0201" }, vector: [-0.1124, 0.1501, 0.1593, 0.1114, 0.1879, 0.1623, -0.2202, -0.1170, -0.3266, 0.2916, "other ..."] } }) +Tree 91: SplitPlaneNormal(SplitPlaneNormal { left: 98, right: 99, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.9950" }, vector: [-0.0869, 0.1981, 0.2025, -0.1256, 0.0042, -0.2087, 0.3637, 0.0604, 0.0826, -0.1302, "other ..."] } }) +Tree 92: Descendants(Descendants { descendants: [5, 20, 25, 38, 41, 42, 44, 49, 51, 59, 64, 68, 75, 78, 83, 87, 88] }) +Tree 93: Descendants(Descendants { descendants: [0, 2, 8, 16, 17, 23, 27, 34, 35, 36, 40, 48, 50, 52, 53, 55, 58, 63, 67, 72, 73, 74, 80, 82, 85, 99] }) +Tree 94: Descendants(Descendants { descendants: [0, 1, 7, 11, 25, 28, 29, 30, 31, 34, 35, 46, 49, 58, 62, 63, 65, 66, 69, 82] }) +Tree 95: Descendants(Descendants { descendants: [4, 5, 6, 10, 14, 15, 16, 22, 33, 42, 59, 83, 86, 89, 92, 93, 94, 96] }) +Tree 96: Descendants(Descendants { descendants: [12, 13, 20, 21, 26, 36, 39, 43, 48, 50, 51, 57, 60, 61, 81, 85, 90, 95, 98] }) +Tree 97: Descendants(Descendants { descendants: [3, 9, 18, 24, 37, 38, 44, 67, 68, 75, 84, 87, 88] }) +Tree 98: Descendants(Descendants { descendants: [6, 28, 29, 76, 77, 84, 89, 90, 92] }) +Tree 99: Descendants(Descendants { descendants: [3, 4, 5, 7, 9, 15, 18, 22, 23, 24, 32, 35, 39, 44, 53, 55, 57, 59, 60, 63, 66, 81, 83, 86, 95, 96] }) +Tree 100: Descendants(Descendants { descendants: [12, 14, 24, 29, 30, 43, 47, 57, 61, 70] }) +Tree 101: Descendants(Descendants { descendants: [1, 3, 4, 6, 9, 15, 18, 21, 22, 26, 28, 32, 37, 39, 46, 60, 66, 71, 76, 77, 79, 81, 86, 89, 90, 92, 93, 95, 96, 98] }) +Tree 102: Descendants(Descendants { descendants: [0, 2, 10, 11, 14, 20, 24, 25, 28, 29, 37, 41, 42, 46, 55, 57, 58, 72, 76, 77, 84, 85, 86, 91, 93, 95, 99] }) +Tree 103: Descendants(Descendants { descendants: [8, 40, 52, 54, 56, 67, 74, 97, 98] }) +Tree 104: Descendants(Descendants { descendants: [12, 13, 16, 19, 21, 22, 23, 38, 43, 47, 48, 61, 64, 68, 70, 71, 78, 80, 87, 88] }) +Tree 105: Descendants(Descendants { descendants: [4, 18, 30, 31, 33, 34, 35, 36, 45, 49, 50, 51, 59, 62, 63, 65, 66, 75, 82, 83, 89, 94] }) +Tree 106: Descendants(Descendants { descendants: [5, 12, 13, 20, 38, 42, 61, 83, 87, 88, 90] }) +Tree 107: Descendants(Descendants { descendants: [0, 1, 2, 25, 27, 28, 29, 30, 41, 57, 58, 65, 68, 85, 92, 93] }) +Tree 108: Descendants(Descendants { descendants: [4, 7, 9, 22, 31, 33, 34, 45, 47, 48, 51, 54, 62, 78, 81, 82, 95, 97] }) +Tree 109: SplitPlaneNormal(SplitPlaneNormal { left: 107, right: 108, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.0140" }, vector: [0.2537, 0.4037, -0.0105, -0.2316, 0.3283, 0.0570, -0.0756, -0.0590, -0.1890, 0.0121, "other ..."] } }) +Tree 110: Descendants(Descendants { descendants: [2, 8, 12, 20, 21, 25, 36, 37, 40, 41, 43, 51, 52, 61, 67, 68, 71, 78, 85, 88, 98] }) +Tree 111: Descendants(Descendants { descendants: [14, 16, 17, 34, 38, 42, 49, 58, 64, 69, 73, 74, 75, 79, 80, 87, 93, 94, 99] }) +Tree 112: Descendants(Descendants { descendants: [3, 8, 10, 11, 15, 18, 21, 24, 26, 39, 40, 46, 52, 56, 59, 60, 66, 67, 76, 77, 79, 84, 89, 91, 96, 98] }) +Tree 113: Descendants(Descendants { descendants: [6, 14, 16, 17, 19, 23, 32, 35, 36, 37, 43, 44, 49, 50, 53, 55, 63, 64, 69, 70, 71, 72, 73, 74, 75, 80, 86, 94, 99] }) +Tree 114: Descendants(Descendants { descendants: [3, 4, 5, 8, 9, 12, 13, 17, 27, 40, 45, 51, 54, 61, 65, 67, 73, 77, 85, 87, 88] }) +Tree 115: Descendants(Descendants { descendants: [0, 2, 7, 10, 11, 19, 24, 25, 29, 31, 33, 39, 41, 48, 50, 52, 56, 58, 66, 74, 81, 84, 86, 91, 92, 93, 96, 97, 98] }) +Tree 116: Descendants(Descendants { descendants: [3, 8, 15, 17, 18, 24, 27, 30, 44, 57, 60, 61, 68, 78, 79, 81] }) +Tree 117: Descendants(Descendants { descendants: [0, 2, 14, 22, 23, 25, 28, 33, 37, 38, 46, 47, 55, 64, 70, 71, 73, 76, 80, 84, 86, 87, 92, 95, 99] }) +Tree 118: Descendants(Descendants { descendants: [6, 10, 11, 12, 13, 16, 19, 36, 39, 40, 41, 45, 48, 50, 51, 52, 54, 56, 59, 62, 67, 72, 74, 77, 85, 89, 91] }) +Tree 119: Descendants(Descendants { descendants: [21, 26, 32, 43, 66, 88, 93, 96, 98] }) +Tree 120: Descendants(Descendants { descendants: [2, 7, 13, 20, 24, 25, 30, 33, 34, 42, 51, 60, 66, 67, 72, 99] }) +Tree 121: Descendants(Descendants { descendants: [0, 5, 6, 10, 11, 15, 16, 18, 35, 49, 56, 59, 69, 75, 83, 84, 90] }) +Tree 122: SplitPlaneNormal(SplitPlaneNormal { left: 120, right: 121, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.3399" }, vector: [-0.2135, 0.0117, 0.1496, -0.1049, 0.0717, -0.0390, -0.1250, 0.0523, 0.2200, 0.0932, "other ..."] } }) +Tree 123: Descendants(Descendants { descendants: [1, 4, 9, 29, 31, 39, 45, 46, 50, 58, 62, 63, 65, 82, 86, 89, 92, 93, 96, 97] }) +Tree 124: Descendants(Descendants { descendants: [14, 16, 18, 20, 32, 35, 36, 37, 38, 42, 43, 53, 55, 57, 59, 62, 71, 75, 78, 80, 94, 95] }) +Tree 125: Descendants(Descendants { descendants: [6, 15, 22, 23, 44, 60, 63, 69, 70, 72, 79, 83, 89, 90, 99] }) +Tree 126: SplitPlaneNormal(SplitPlaneNormal { left: 124, right: 125, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.2654" }, vector: [-0.0413, 0.0551, 0.3348, -0.0135, 0.0135, 0.0968, -0.4112, 0.2955, -0.1179, 0.3146, "other ..."] } }) +Tree 127: Descendants(Descendants { descendants: [1, 21, 26, 28, 30, 34, 46, 47, 49, 64, 68, 76, 82] }) +Tree 128: Descendants(Descendants { descendants: [4, 5, 6, 12, 13, 14, 18, 19, 20, 22, 38, 42, 44, 45, 51, 61, 64, 65, 73, 75, 78, 80, 83, 87, 90] }) +Tree 129: Descendants(Descendants { descendants: [11, 15, 16, 23, 24, 34, 35, 39, 43, 49, 50, 52, 53, 55, 62, 63, 66, 67, 69, 70, 71, 72, 84, 86, 88, 94] }) +Tree 130: Descendants(Descendants { descendants: [14, 19, 23, 26, 28, 36, 40, 41, 43, 48, 52, 53, 55, 61, 70, 71, 74, 76, 78, 85, 91, 94, 98] }) +Tree 131: Descendants(Descendants { descendants: [3, 8, 12, 17, 21, 22, 27, 32, 37, 38, 44, 47, 54, 57, 64, 68, 73, 77, 79, 80, 81, 87, 88, 95] }) +Tree 132: Descendants(Descendants { descendants: [11, 18, 19, 64, 68, 76, 81, 91] }) +Tree 133: Descendants(Descendants { descendants: [2, 8, 16, 23, 27, 28, 32, 36, 37, 45, 48, 50, 55, 57, 63, 70, 72, 73, 74, 79, 80, 84, 86, 87, 95] }) +Tree 134: SplitPlaneNormal(SplitPlaneNormal { left: 132, right: 133, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.3133" }, vector: [0.3021, 0.1322, 0.0217, -0.1230, 0.2695, -0.2384, 0.2780, -0.0483, -0.1448, 0.1303, "other ..."] } }) +Tree 135: Descendants(Descendants { descendants: [3, 12, 52, 61, 67, 97] }) +Tree 136: SplitPlaneNormal(SplitPlaneNormal { left: 134, right: 135, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.6145" }, vector: [-0.2144, -0.0469, 0.2871, -0.2047, 0.1997, 0.2381, -0.0809, 0.4253, 0.0301, -0.0456, "other ..."] } }) +Tree 137: Descendants(Descendants { descendants: [1, 6, 7, 13, 21, 26, 46, 47, 54, 56, 62, 77, 89, 90, 93, 98] }) +Tree 138: Descendants(Descendants { descendants: [0, 2, 8, 25, 27, 28, 30, 32, 46, 54, 56, 57, 58, 79, 81, 91, 92, 99] }) +Tree 139: Descendants(Descendants { descendants: [1, 3, 7, 9, 29, 31, 33, 48, 82, 89, 93, 95, 97] }) +Tree 140: Descendants(Descendants { descendants: [4, 9, 14, 22, 25, 29, 30, 35, 39, 42, 43, 58, 65, 66, 69, 83, 85, 88, 92, 96] }) +Tree 141: Descendants(Descendants { descendants: [0, 5, 10, 15, 17, 20, 24, 31, 33, 34, 38, 40, 41, 44, 49, 51, 53, 59, 60, 71, 75, 78, 82, 94, 99] }) +Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.2240, 0.0136, 0.1967, 0.7482, 0.6849, 0.7949, 0.0809, 0.5504, 0.6339, 0.6978, "other ..."] }) Item 1: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.4199, 0.2620, 0.2655, 0.8414, 0.0192, 0.3828, 0.2561, 0.2692, 0.0368, 0.4624, "other ..."] }) -Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.7462, 0.9877, 0.0796, 0.4441, 0.9824, 0.6855, 0.0985, 0.0618, 0.0551, 0.5251, "other ..."] }) +Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.7711, 0.4016, 0.1489, 0.9991, 0.5236, 0.5613, 0.4596, 0.2214, 0.5016, 0.1191, "other ..."] }) Item 3: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0001, 0.7870, 0.9674, 0.4568, 0.5250, 0.2701, 0.2417, 0.8742, 0.6869, 0.8759, "other ..."] }) -Item 4: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.8421, 0.8103, 0.5294, 0.6795, 0.9634, 0.3110, 0.8945, 0.1541, 0.5916, 0.1082, "other ..."] }) +Item 4: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.7473, 0.3347, 0.9786, 0.4693, 0.3540, 0.1280, 0.9628, 0.2076, 0.3437, 0.4589, "other ..."] }) Item 5: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0850, 0.7778, 0.8818, 0.3427, 0.1293, 0.7240, 0.4773, 0.2871, 0.3988, 0.4014, "other ..."] }) -Item 6: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.8491, 0.4500, 0.8568, 0.1146, 0.7974, 0.5148, 0.0862, 0.6020, 0.7705, 0.6189, "other ..."] }) +Item 6: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.1874, 0.7676, 0.9707, 0.5148, 0.7242, 0.4714, 0.1278, 0.2181, 0.2651, 0.5674, "other ..."] }) Item 7: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.5699, 0.5919, 0.7788, 0.3705, 0.3807, 0.1708, 0.3678, 0.5629, 0.0612, 0.4826, "other ..."] }) -Item 8: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.2720, 0.7143, 0.6966, 0.9709, 0.4263, 0.7441, 0.8624, 0.1372, 0.0418, 0.7771, "other ..."] }) +Item 8: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.3157, 0.8096, 0.5024, 0.5421, 0.4327, 0.3696, 0.6485, 0.7972, 0.9792, 0.9554, "other ..."] }) Item 9: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.8134, 0.9647, 0.6640, 0.4464, 0.7439, 0.6904, 0.3159, 0.7607, 0.3483, 0.9963, "other ..."] }) -Item 10: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.4278, 0.5749, 0.9222, 0.8668, 0.5708, 0.7825, 0.1484, 0.1654, 0.7721, 0.1671, "other ..."] }) +Item 10: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.1559, 0.1898, 0.2475, 0.4582, 0.5481, 0.5846, 0.1844, 0.4898, 0.2916, 0.2669, "other ..."] }) Item 11: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.6560, 0.2343, 0.4079, 0.5972, 0.5766, 0.6739, 0.2985, 0.6167, 0.4834, 0.2818, "other ..."] }) -Item 12: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.5174, 0.1043, 0.5020, 0.7082, 0.0108, 0.7768, 0.2805, 0.5635, 0.1165, 0.3446, "other ..."] }) +Item 12: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.1712, 0.6340, 0.2866, 0.6282, 0.9072, 0.7589, 0.6432, 0.8676, 0.2942, 0.4375, "other ..."] }) Item 13: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.1726, 0.7399, 0.0271, 0.8721, 0.8725, 0.4023, 0.1558, 0.1044, 0.2096, 0.2081, "other ..."] }) -Item 14: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.7594, 0.3160, 0.8848, 0.2336, 0.2080, 0.9798, 0.2609, 0.3579, 0.9043, 0.5035, "other ..."] }) +Item 14: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.8145, 0.6759, 0.1411, 0.7878, 0.3556, 0.8440, 0.5301, 0.2627, 0.7050, 0.4145, "other ..."] }) Item 15: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.6031, 0.2970, 0.9485, 0.0272, 0.4336, 0.1339, 0.2209, 0.8350, 0.2566, 0.9481, "other ..."] }) -Item 16: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.7278, 0.0499, 0.4536, 0.3295, 0.8839, 0.5060, 0.5773, 0.3133, 0.2521, 0.6842, "other ..."] }) +Item 16: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.4594, 0.9245, 0.5151, 0.7390, 0.6121, 0.5891, 0.5795, 0.6295, 0.0595, 0.6471, "other ..."] }) Item 17: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0819, 0.5362, 0.8215, 0.2263, 0.3109, 0.2738, 0.6133, 0.5147, 0.9334, 0.9877, "other ..."] }) -Item 18: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.3202, 0.9724, 0.0590, 0.9146, 0.0865, 0.5347, 0.9236, 0.5211, 0.4621, 0.4500, "other ..."] }) +Item 18: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.5102, 0.8700, 0.3910, 0.0807, 0.1067, 0.0692, 0.7037, 0.4229, 0.0066, 0.1894, "other ..."] }) Item 19: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.1390, 0.7531, 0.3249, 0.8754, 0.9984, 0.7362, 0.0281, 0.2016, 0.9443, 0.1989, "other ..."] }) -Item 20: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.7403, 0.1475, 0.8585, 0.3990, 0.5766, 0.0263, 0.2665, 0.6317, 0.8026, 0.0227, "other ..."] }) +Item 20: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.8077, 0.3229, 0.5031, 0.0472, 0.6957, 0.9603, 0.8790, 0.2009, 0.3837, 0.1765, "other ..."] }) Item 21: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.6252, 0.9240, 0.7227, 0.6810, 0.2563, 0.3321, 0.2283, 0.9226, 0.8494, 0.0356, "other ..."] }) -Item 22: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0981, 0.2398, 0.2595, 0.6075, 0.1605, 0.7487, 0.1070, 0.8330, 0.7908, 0.0203, "other ..."] }) +Item 22: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.1651, 0.4144, 0.2816, 0.0037, 0.3038, 0.2344, 0.3321, 0.1985, 0.4704, 0.3710, "other ..."] }) Item 23: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.9915, 0.6886, 0.1976, 0.1725, 0.6776, 0.1356, 0.3842, 0.4424, 0.6939, 0.8016, "other ..."] }) -Item 24: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.9586, 0.8715, 0.0659, 0.6144, 0.4995, 0.6693, 0.1415, 0.7556, 0.9350, 0.9924, "other ..."] }) +Item 24: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.7192, 0.5087, 0.9102, 0.0269, 0.7119, 0.7909, 0.0259, 0.6221, 0.9168, 0.1528, "other ..."] }) Item 25: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0116, 0.5323, 0.3940, 0.1382, 0.1987, 0.7287, 0.4026, 0.1442, 0.5957, 0.0340, "other ..."] }) -Item 26: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.9907, 0.6582, 0.3640, 0.9777, 0.6001, 0.3023, 0.3154, 0.2637, 0.7202, 0.7507, "other ..."] }) +Item 26: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.5587, 0.8792, 0.9279, 0.4203, 0.9903, 0.7524, 0.0600, 0.9020, 0.8837, 0.1950, "other ..."] }) Item 27: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.3569, 0.9070, 0.8412, 0.3201, 0.6998, 0.8674, 0.5494, 0.2322, 0.2969, 0.9787, "other ..."] }) -Item 28: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.6910, 0.9733, 0.3937, 0.8154, 0.2171, 0.7616, 0.3415, 0.4227, 0.6408, 0.0355, "other ..."] }) +Item 28: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.9353, 0.1703, 0.1992, 0.7788, 0.4769, 0.5431, 0.4292, 0.5249, 0.7629, 0.9059, "other ..."] }) Item 29: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.6021, 0.0690, 0.1080, 0.2535, 0.6817, 0.7899, 0.3297, 0.8656, 0.1566, 0.3560, "other ..."] }) -Item 30: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.8030, 0.0396, 0.0641, 0.3958, 0.3427, 0.9163, 0.0129, 0.4500, 0.8504, 0.8711, "other ..."] }) +Item 30: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.3473, 0.1415, 0.1873, 0.7472, 0.3808, 0.6412, 0.1944, 0.5869, 0.0722, 0.3215, "other ..."] }) Item 31: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.7584, 0.3448, 0.7315, 0.5405, 0.6797, 0.3253, 0.8611, 0.0846, 0.0174, 0.0882, "other ..."] }) -Item 32: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.6515, 0.6402, 0.4825, 0.1251, 0.1569, 0.9048, 0.3695, 0.0092, 0.1574, 0.1528, "other ..."] }) +Item 32: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.4076, 0.8830, 0.7654, 0.5911, 0.3055, 0.0942, 0.7024, 0.9471, 0.9752, 0.4628, "other ..."] }) Item 33: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.3494, 0.5787, 0.8027, 0.9625, 0.5944, 0.6781, 0.4204, 0.5899, 0.0209, 0.9001, "other ..."] }) -Item 34: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.5256, 0.7737, 0.1071, 0.1049, 0.5131, 0.1703, 0.7922, 0.1135, 0.4165, 0.0898, "other ..."] }) +Item 34: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.6939, 0.0973, 0.2992, 0.4254, 0.0919, 0.8203, 0.3851, 0.0823, 0.4547, 0.4283, "other ..."] }) Item 35: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.3281, 0.1178, 0.0533, 0.4172, 0.3990, 0.0395, 0.8533, 0.1435, 0.9799, 0.4063, "other ..."] }) -Item 36: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.7826, 0.2989, 0.7770, 0.4571, 0.1601, 0.9667, 0.6717, 0.1903, 0.1169, 0.8590, "other ..."] }) +Item 36: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.7093, 0.6425, 0.0423, 0.0877, 0.7820, 0.6701, 0.4963, 0.1499, 0.8631, 0.8113, "other ..."] }) Item 37: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.6603, 0.3675, 0.1019, 0.2193, 0.3180, 0.0591, 0.9934, 0.8583, 0.7473, 0.3644, "other ..."] }) -Item 38: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0498, 0.3107, 0.7264, 0.3119, 0.9096, 0.1574, 0.0399, 0.6895, 0.0600, 0.7256, "other ..."] }) +Item 38: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0152, 0.9782, 0.0253, 0.6194, 0.6177, 0.6446, 0.8634, 0.8343, 0.1429, 0.6369, "other ..."] }) Item 39: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.4498, 0.4107, 0.9992, 0.3928, 0.4779, 0.4661, 0.1282, 0.8140, 0.7490, 0.5641, "other ..."] }) -Item 40: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.8769, 0.4665, 0.6818, 0.3210, 0.8711, 0.3130, 0.2871, 0.8996, 0.6896, 0.5484, "other ..."] }) +Item 40: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.5514, 0.2225, 0.8400, 0.2598, 0.5622, 0.6231, 0.5772, 0.0082, 0.8470, 0.9596, "other ..."] }) Item 41: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.7821, 0.0623, 0.1168, 0.3609, 0.6040, 0.8336, 0.0911, 0.2181, 0.7485, 0.0281, "other ..."] }) -Item 42: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.4460, 0.4258, 0.3236, 0.3679, 0.9002, 0.2569, 0.4921, 0.9407, 0.7830, 0.2773, "other ..."] }) +Item 42: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.9144, 0.0223, 0.5079, 0.6873, 0.5501, 0.2577, 0.9304, 0.3154, 0.1546, 0.3749, "other ..."] }) Item 43: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.8608, 0.8689, 0.4918, 0.2239, 0.9291, 0.0622, 0.6843, 0.4184, 0.4703, 0.3202, "other ..."] }) -Item 44: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.3994, 0.3790, 0.3149, 0.3094, 0.6979, 0.4079, 0.0662, 0.5442, 0.6009, 0.6694, "other ..."] }) +Item 44: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.5159, 0.9516, 0.6267, 0.1007, 0.4283, 0.1452, 0.9565, 0.4723, 0.4935, 0.7395, "other ..."] }) Item 45: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.9838, 0.4742, 0.5307, 0.6989, 0.9323, 0.2140, 0.1371, 0.1113, 0.0322, 0.3001, "other ..."] }) -Item 46: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.1804, 0.0669, 0.8639, 0.6324, 0.8798, 0.3417, 0.1164, 0.5756, 0.9767, 0.7200, "other ..."] }) +Item 46: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.3709, 0.3974, 0.5971, 0.7814, 0.2075, 0.5392, 0.4790, 0.5432, 0.4844, 0.3367, "other ..."] }) Item 47: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.4506, 0.8658, 0.1164, 0.2339, 0.2266, 0.9050, 0.5849, 0.9792, 0.5951, 0.7706, "other ..."] }) -Item 48: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.1112, 0.3992, 0.0741, 0.7318, 0.9446, 0.2970, 0.9245, 0.1696, 0.6283, 0.9061, "other ..."] }) +Item 48: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.7462, 0.9877, 0.0796, 0.4441, 0.9824, 0.6855, 0.0985, 0.0618, 0.0551, 0.5251, "other ..."] }) Item 49: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.1322, 0.0670, 0.3404, 0.5339, 0.0229, 0.5964, 0.5497, 0.3819, 0.6553, 0.7129, "other ..."] }) -Item 50: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.5324, 0.0597, 0.9226, 0.4007, 0.0213, 0.2651, 0.8515, 0.9985, 0.8066, 0.3377, "other ..."] }) +Item 50: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.8421, 0.8103, 0.5294, 0.6795, 0.9634, 0.3110, 0.8945, 0.1541, 0.5916, 0.1082, "other ..."] }) Item 51: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.3643, 0.3282, 0.2580, 0.4477, 0.5920, 0.3581, 0.3502, 0.2441, 0.1707, 0.1243, "other ..."] }) -Item 52: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.8413, 0.5136, 0.9661, 0.4242, 0.3183, 0.6281, 0.1580, 0.7145, 0.7564, 0.3747, "other ..."] }) +Item 52: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.8491, 0.4500, 0.8568, 0.1146, 0.7974, 0.5148, 0.0862, 0.6020, 0.7705, 0.6189, "other ..."] }) Item 53: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.5928, 0.6267, 0.1717, 0.1604, 0.6506, 0.0302, 0.8289, 0.5930, 0.9304, 0.6067, "other ..."] }) -Item 54: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.4342, 0.3014, 0.2043, 0.0254, 0.4983, 0.0908, 0.2461, 0.3160, 0.8436, 0.6165, "other ..."] }) +Item 54: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.2720, 0.7143, 0.6966, 0.9709, 0.4263, 0.7441, 0.8624, 0.1372, 0.0418, 0.7771, "other ..."] }) Item 55: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.6095, 0.6335, 0.4740, 0.0746, 0.3871, 0.1016, 0.6414, 0.3076, 0.5484, 0.7602, "other ..."] }) -Item 56: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0281, 0.0875, 0.0095, 0.6868, 0.8335, 0.4665, 0.7833, 0.7046, 0.3141, 0.3595, "other ..."] }) +Item 56: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.4278, 0.5749, 0.9222, 0.8668, 0.5708, 0.7825, 0.1484, 0.1654, 0.7721, 0.1671, "other ..."] }) Item 57: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.1524, 0.3441, 0.2368, 0.4350, 0.5328, 0.3005, 0.7021, 0.3614, 0.6369, 0.7984, "other ..."] }) -Item 58: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.4958, 0.8618, 0.1820, 0.6038, 0.6089, 0.2997, 0.1746, 0.9517, 0.0863, 0.1896, "other ..."] }) +Item 58: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.5174, 0.1043, 0.5020, 0.7082, 0.0108, 0.7768, 0.2805, 0.5635, 0.1165, 0.3446, "other ..."] }) Item 59: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.6227, 0.1202, 0.9715, 0.3936, 0.3423, 0.7479, 0.6526, 0.1867, 0.5568, 0.0922, "other ..."] }) -Item 60: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.4640, 0.7249, 0.8636, 0.6015, 0.8082, 0.7408, 0.1704, 0.4970, 0.3101, 0.9973, "other ..."] }) +Item 60: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.7594, 0.3160, 0.8848, 0.2336, 0.2080, 0.9798, 0.2609, 0.3579, 0.9043, 0.5035, "other ..."] }) Item 61: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.1347, 0.7000, 0.0530, 0.4959, 0.8227, 0.9831, 0.5433, 0.5201, 0.7924, 0.3847, "other ..."] }) -Item 62: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.6358, 0.6999, 0.3624, 0.8972, 0.2007, 0.2002, 0.0201, 0.0121, 0.5644, 0.4314, "other ..."] }) +Item 62: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.7278, 0.0499, 0.4536, 0.3295, 0.8839, 0.5060, 0.5773, 0.3133, 0.2521, 0.6842, "other ..."] }) Item 63: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.9221, 0.3578, 0.3207, 0.9945, 0.9288, 0.4608, 0.3001, 0.0296, 0.4678, 0.7422, "other ..."] }) -Item 64: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.8309, 0.1828, 0.5901, 0.0360, 0.8896, 0.6041, 0.9906, 0.9869, 0.6515, 0.7573, "other ..."] }) +Item 64: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.3202, 0.9724, 0.0590, 0.9146, 0.0865, 0.5347, 0.9236, 0.5211, 0.4621, 0.4500, "other ..."] }) Item 65: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.5677, 0.1247, 0.4928, 0.4097, 0.8433, 0.9238, 0.7848, 0.4437, 0.4696, 0.9886, "other ..."] }) -Item 66: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.1020, 0.2740, 0.1490, 0.9172, 0.0754, 0.0941, 0.6428, 0.3073, 0.3354, 0.4870, "other ..."] }) +Item 66: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.7403, 0.1475, 0.8585, 0.3990, 0.5766, 0.0263, 0.2665, 0.6317, 0.8026, 0.0227, "other ..."] }) Item 67: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.5299, 0.5421, 0.8194, 0.1018, 0.5426, 0.9350, 0.3228, 0.7979, 0.7473, 0.1118, "other ..."] }) -Item 68: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.7906, 0.4598, 0.6650, 0.0958, 0.9495, 0.9751, 0.4430, 0.0334, 0.9154, 0.5768, "other ..."] }) +Item 68: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0981, 0.2398, 0.2595, 0.6075, 0.1605, 0.7487, 0.1070, 0.8330, 0.7908, 0.0203, "other ..."] }) Item 69: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.6163, 0.7762, 0.4365, 0.6713, 0.5647, 0.3449, 0.6615, 0.9430, 0.5941, 0.3563, "other ..."] }) -Item 70: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.4215, 0.0579, 0.3761, 0.6015, 0.0281, 0.1383, 0.8450, 0.4595, 0.9031, 0.1857, "other ..."] }) +Item 70: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.9586, 0.8715, 0.0659, 0.6144, 0.4995, 0.6693, 0.1415, 0.7556, 0.9350, 0.9924, "other ..."] }) Item 71: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.6478, 0.9371, 0.2378, 0.4279, 0.1400, 0.2146, 0.3193, 0.7330, 0.7932, 0.7295, "other ..."] }) -Item 72: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.9551, 0.2375, 0.5644, 0.1951, 0.2454, 0.7228, 0.5815, 0.5276, 0.9947, 0.6278, "other ..."] }) +Item 72: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.9907, 0.6582, 0.3640, 0.9777, 0.6001, 0.3023, 0.3154, 0.2637, 0.7202, 0.7507, "other ..."] }) Item 73: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.4640, 0.7218, 0.0154, 0.0829, 0.4829, 0.5139, 0.4344, 0.5872, 0.2770, 0.3745, "other ..."] }) -Item 74: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.6041, 0.3629, 0.6610, 0.6124, 0.6909, 0.0379, 0.4711, 0.3341, 0.5966, 0.6614, "other ..."] }) +Item 74: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.6910, 0.9733, 0.3937, 0.8154, 0.2171, 0.7616, 0.3415, 0.4227, 0.6408, 0.0355, "other ..."] }) Item 75: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.3639, 0.3210, 0.3718, 0.7818, 0.6264, 0.2524, 0.6018, 0.4059, 0.9744, 0.3568, "other ..."] }) -Item 76: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.5009, 0.1136, 0.6603, 0.2698, 0.1138, 0.2779, 0.5030, 0.9509, 0.2323, 0.9182, "other ..."] }) +Item 76: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.8030, 0.0396, 0.0641, 0.3958, 0.3427, 0.9163, 0.0129, 0.4500, 0.8504, 0.8711, "other ..."] }) Item 77: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.6003, 0.7202, 0.3803, 0.5052, 0.4006, 0.6708, 0.0438, 0.8432, 0.8772, 0.6849, "other ..."] }) -Item 78: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.9992, 0.7691, 0.0377, 0.0207, 0.7633, 0.8107, 0.5643, 0.1879, 0.3600, 0.4194, "other ..."] }) +Item 78: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.6515, 0.6402, 0.4825, 0.1251, 0.1569, 0.9048, 0.3695, 0.0092, 0.1574, 0.1528, "other ..."] }) Item 79: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.8093, 0.7442, 0.3738, 0.9164, 0.5923, 0.7353, 0.5379, 0.6815, 0.5925, 0.7954, "other ..."] }) -Item 80: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.7377, 0.4242, 0.0401, 0.9311, 0.7764, 0.7900, 0.9932, 0.2166, 0.1077, 0.4245, "other ..."] }) +Item 80: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.5256, 0.7737, 0.1071, 0.1049, 0.5131, 0.1703, 0.7922, 0.1135, 0.4165, 0.0898, "other ..."] }) Item 81: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.2370, 0.7334, 0.4755, 0.8921, 0.1448, 0.2971, 0.2116, 0.1124, 0.7297, 0.2965, "other ..."] }) -Item 82: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.7488, 0.3886, 0.3360, 0.7323, 0.1531, 0.0919, 0.6584, 0.7152, 0.5447, 0.9921, "other ..."] }) +Item 82: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.7826, 0.2989, 0.7770, 0.4571, 0.1601, 0.9667, 0.6717, 0.1903, 0.1169, 0.8590, "other ..."] }) Item 83: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.3071, 0.2166, 0.0566, 0.5153, 0.8628, 0.9601, 0.6390, 0.4052, 0.2759, 0.4989, "other ..."] }) -Item 84: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0920, 0.0212, 0.5221, 0.5551, 0.3172, 0.3603, 0.0231, 0.2973, 0.5497, 0.4320, "other ..."] }) +Item 84: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0498, 0.3107, 0.7264, 0.3119, 0.9096, 0.1574, 0.0399, 0.6895, 0.0600, 0.7256, "other ..."] }) Item 85: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.4718, 0.3682, 0.4350, 0.3129, 0.1289, 0.7526, 0.8249, 0.5640, 0.9296, 0.8479, "other ..."] }) -Item 86: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.7522, 0.8666, 0.5982, 0.0355, 0.9164, 0.3943, 0.6033, 0.9599, 0.6571, 0.0694, "other ..."] }) +Item 86: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.8769, 0.4665, 0.6818, 0.3210, 0.8711, 0.3130, 0.2871, 0.8996, 0.6896, 0.5484, "other ..."] }) Item 87: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.2909, 0.8867, 0.3238, 0.4342, 0.3491, 0.4305, 0.8452, 0.0936, 0.1220, 0.3452, "other ..."] }) -Item 88: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.8770, 0.6135, 0.1378, 0.5732, 0.5669, 0.7852, 0.3687, 0.2821, 0.1570, 0.5212, "other ..."] }) +Item 88: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.4460, 0.4258, 0.3236, 0.3679, 0.9002, 0.2569, 0.4921, 0.9407, 0.7830, 0.2773, "other ..."] }) Item 89: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.6270, 0.3774, 0.7874, 0.7272, 0.4240, 0.1508, 0.0360, 0.5710, 0.2254, 0.0950, "other ..."] }) -Item 90: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.5869, 0.4228, 0.7590, 0.8688, 0.9431, 0.8353, 0.2878, 0.4860, 0.9406, 0.6326, "other ..."] }) +Item 90: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.3994, 0.3790, 0.3149, 0.3094, 0.6979, 0.4079, 0.0662, 0.5442, 0.6009, 0.6694, "other ..."] }) Item 91: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.8560, 0.9670, 0.3969, 0.5008, 0.1567, 0.7420, 0.0072, 0.1891, 0.9690, 0.0387, "other ..."] }) -Item 92: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.3940, 0.7846, 0.2091, 0.0774, 0.4577, 0.8833, 0.9819, 0.8965, 0.8243, 0.4367, "other ..."] }) +Item 92: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.1804, 0.0669, 0.8639, 0.6324, 0.8798, 0.3417, 0.1164, 0.5756, 0.9767, 0.7200, "other ..."] }) Item 93: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.5034, 0.4728, 0.9950, 0.7630, 0.0154, 0.4453, 0.6893, 0.6996, 0.0246, 0.0245, "other ..."] }) -Item 94: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.1326, 0.5568, 0.0976, 0.1845, 0.0121, 0.5213, 0.5094, 0.1090, 0.3868, 0.1924, "other ..."] }) +Item 94: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.1112, 0.3992, 0.0741, 0.7318, 0.9446, 0.2970, 0.9245, 0.1696, 0.6283, 0.9061, "other ..."] }) Item 95: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.8157, 0.8688, 0.2659, 0.6080, 0.5274, 0.1883, 0.7562, 0.8511, 0.6928, 0.8151, "other ..."] }) -Item 96: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.5040, 0.4085, 0.6572, 0.9547, 0.6785, 0.0967, 0.1732, 0.1943, 0.4009, 0.1434, "other ..."] }) +Item 96: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.5324, 0.0597, 0.9226, 0.4007, 0.0213, 0.2651, 0.8515, 0.9985, 0.8066, 0.3377, "other ..."] }) Item 97: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0850, 0.4087, 0.7257, 0.3157, 0.9526, 0.5290, 0.5818, 0.5460, 0.1906, 0.9422, "other ..."] }) -Item 98: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.7849, 0.0672, 0.7446, 0.6176, 0.4259, 0.8941, 0.3356, 0.0410, 0.0297, 0.8411, "other ..."] }) +Item 98: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.8413, 0.5136, 0.9661, 0.4242, 0.3183, 0.6281, 0.1580, 0.7145, 0.7564, 0.3747, "other ..."] }) Item 99: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.8320, 0.5156, 0.6172, 0.6617, 0.4999, 0.2464, 0.4536, 0.3265, 0.2163, 0.5406, "other ..."] }) diff --git a/src/tests/snapshots/arroy__tests__writer__write_and_update_lot_of_random_points.snap b/src/tests/snapshots/arroy__tests__writer__write_and_update_lot_of_random_points.snap index 3c7c9e5..b6b894d 100644 --- a/src/tests/snapshots/arroy__tests__writer__write_and_update_lot_of_random_points.snap +++ b/src/tests/snapshots/arroy__tests__writer__write_and_update_lot_of_random_points.snap @@ -6,100 +6,98 @@ expression: handle Dumping index 0 Root: Metadata { dimensions: 30, items: RoaringBitmap<100 values between 0 and 99>, roots: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], distance: "euclidean" } Version: Version { major: 0, minor: 7, patch: 0 } -Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 14, right: 17, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.8587" }, vector: [-0.1204, 0.0883, -0.1193, 0.0487, -0.2937, 0.1358, 0.0452, 0.0063, 0.0002, 0.3049, "other ..."] } }) -Tree 1: SplitPlaneNormal(SplitPlaneNormal { left: 21, right: 26, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.5437" }, vector: [-0.3998, -0.0657, -0.1329, -0.0396, 0.0148, 0.1862, -0.0011, 0.0465, 0.1301, 0.1252, "other ..."] } }) -Tree 2: SplitPlaneNormal(SplitPlaneNormal { left: 34, right: 37, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.6127" }, vector: [-0.0024, -0.2313, -0.3514, 0.2460, 0.1578, 0.1174, 0.1903, 0.2528, -0.1544, -0.0109, "other ..."] } }) -Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 41, right: 46, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.3197" }, vector: [-0.4323, -0.0243, -0.2204, -0.2440, -0.1659, 0.2287, 0.0464, 0.1377, 0.0778, -0.1993, "other ..."] } }) -Tree 4: SplitPlaneNormal(SplitPlaneNormal { left: 56, right: 57, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.9992" }, vector: [0.1629, 0.1656, 0.3348, -0.1713, -0.2520, 0.0814, -0.0464, 0.2963, 0.2613, -0.1932, "other ..."] } }) -Tree 5: SplitPlaneNormal(SplitPlaneNormal { left: 63, right: 66, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.2444" }, vector: [-0.3338, 0.1111, 0.3212, 0.0072, -0.3659, 0.2717, 0.0245, -0.1254, -0.0674, 0.0525, "other ..."] } }) -Tree 6: SplitPlaneNormal(SplitPlaneNormal { left: 72, right: 75, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.0702" }, vector: [0.0110, 0.0447, -0.1004, -0.0082, 0.3757, 0.1258, -0.0217, -0.0066, -0.0891, -0.1647, "other ..."] } }) -Tree 7: SplitPlaneNormal(SplitPlaneNormal { left: 83, right: 84, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.6027" }, vector: [-0.2057, -0.2175, 0.2291, 0.1105, 0.1273, -0.0631, 0.3744, 0.0516, 0.1016, 0.1725, "other ..."] } }) -Tree 8: SplitPlaneNormal(SplitPlaneNormal { left: 88, right: 91, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.1412" }, vector: [-0.1594, -0.1073, 0.0726, 0.0262, -0.0675, -0.0409, 0.2032, -0.0833, 0.0508, 0.1313, "other ..."] } }) -Tree 9: SplitPlaneNormal(SplitPlaneNormal { left: 97, right: 102, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.1949" }, vector: [0.3612, -0.2770, -0.0294, -0.3396, -0.1454, -0.0856, 0.0828, 0.0365, 0.1651, -0.0627, "other ..."] } }) -Tree 10: Descendants(Descendants { descendants: [2, 7, 9, 11, 27, 36, 39, 46, 62, 66, 67, 80, 89, 97] }) -Tree 11: Descendants(Descendants { descendants: [0, 4, 8, 17, 18, 21, 25, 32, 37, 50, 55, 56, 59, 61, 64, 71, 72, 73, 74, 78, 84, 85, 86, 93] }) -Tree 12: Descendants(Descendants { descendants: [6, 10, 12, 13, 19, 22, 28, 30, 31, 33, 34, 35, 40, 41, 42, 45, 51, 52, 54, 63, 87, 91, 92, 98] }) -Tree 13: SplitPlaneNormal(SplitPlaneNormal { left: 11, right: 12, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.7776" }, vector: [0.1393, -0.0513, -0.0768, 0.1270, 0.0373, -0.2633, -0.2015, -0.4977, -0.2852, 0.1163, "other ..."] } }) -Tree 14: SplitPlaneNormal(SplitPlaneNormal { left: 10, right: 13, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.6510" }, vector: [0.0688, -0.1157, -0.4195, 0.0549, -0.0075, -0.0146, 0.1418, -0.0685, 0.1387, -0.3440, "other ..."] } }) -Tree 15: Descendants(Descendants { descendants: [1, 5, 14, 16, 20, 26, 29, 38, 43, 44, 47, 48, 49, 53, 57, 58, 60, 70, 75, 76, 81, 82, 88, 90] }) -Tree 16: Descendants(Descendants { descendants: [3, 15, 23, 24, 65, 68, 69, 77, 79, 83, 94, 95, 96, 99] }) -Tree 17: SplitPlaneNormal(SplitPlaneNormal { left: 15, right: 16, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.9388" }, vector: [0.1487, 0.2203, 0.3673, 0.0253, 0.2058, -0.0370, -0.0664, 0.1108, -0.0408, 0.1954, "other ..."] } }) -Tree 19: Descendants(Descendants { descendants: [4, 9, 11, 20, 22, 31, 32, 36, 39, 45, 53, 69, 75, 79, 80, 86, 91, 92, 94] }) -Tree 20: Descendants(Descendants { descendants: [8, 18, 24, 30, 43, 46, 51, 52, 56, 59, 64, 66, 72, 73, 78, 87] }) -Tree 21: SplitPlaneNormal(SplitPlaneNormal { left: 19, right: 20, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.4404" }, vector: [-0.1670, 0.1858, -0.2109, -0.2648, -0.1416, 0.2012, 0.0523, -0.1372, 0.0213, -0.3516, "other ..."] } }) -Tree 22: Descendants(Descendants { descendants: [0, 1, 2, 7, 10, 12, 13, 16, 21, 25, 28, 29, 33, 34, 41, 42, 44, 48, 50, 63, 67, 74, 76, 77, 83, 89, 93, 96, 98] }) -Tree 23: Descendants(Descendants { descendants: [23, 35, 47, 49, 55, 58, 60, 61, 71, 82, 99] }) -Tree 24: Descendants(Descendants { descendants: [3, 5, 6, 14, 15, 17, 19, 26, 27, 37, 38, 40, 54, 57, 62, 65, 68, 70, 81, 84, 85, 88, 90, 95, 97] }) -Tree 25: SplitPlaneNormal(SplitPlaneNormal { left: 23, right: 24, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.1497" }, vector: [-0.1334, 0.0228, 0.3475, 0.1570, 0.0302, -0.0366, -0.1385, -0.0532, 0.0307, 0.0044, "other ..."] } }) -Tree 26: SplitPlaneNormal(SplitPlaneNormal { left: 22, right: 25, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.1262" }, vector: [-0.3075, 0.0809, -0.0415, -0.1913, -0.0817, -0.1210, 0.3237, -0.1618, 0.3302, 0.3665, "other ..."] } }) -Tree 28: Descendants(Descendants { descendants: [15, 20, 22, 23, 44, 67, 80, 82, 89] }) -Tree 29: Descendants(Descendants { descendants: [2, 3, 5, 12, 16, 21, 24, 25, 30, 43, 54, 56, 60, 63, 66, 71, 73, 78, 87, 88, 92, 94, 99] }) -Tree 30: Descendants(Descendants { descendants: [6, 8, 27, 28, 40, 62, 90, 91] }) -Tree 31: SplitPlaneNormal(SplitPlaneNormal { left: 29, right: 30, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.1502" }, vector: [0.0811, 0.0435, -0.0346, 0.2936, -0.0010, -0.2537, -0.3247, -0.0604, 0.1465, 0.0740, "other ..."] } }) -Tree 32: Descendants(Descendants { descendants: [17, 46, 53, 55, 59, 72, 77, 85] }) -Tree 33: SplitPlaneNormal(SplitPlaneNormal { left: 31, right: 32, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.3366" }, vector: [0.1309, -0.2229, -0.0815, -0.0774, -0.0238, -0.2149, -0.0611, 0.0292, 0.2175, 0.2365, "other ..."] } }) -Tree 34: SplitPlaneNormal(SplitPlaneNormal { left: 28, right: 33, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.2613" }, vector: [-0.2091, 0.1176, -0.1417, 0.3153, 0.0392, 0.0072, 0.2998, -0.2809, 0.0782, 0.1063, "other ..."] } }) -Tree 35: Descendants(Descendants { descendants: [4, 7, 9, 10, 13, 29, 33, 36, 38, 45, 47, 48, 50, 51, 57, 58, 61, 64, 65, 68, 70, 76, 79, 83, 86, 93, 95, 96, 97] }) -Tree 36: Descendants(Descendants { descendants: [0, 1, 11, 14, 18, 19, 26, 31, 32, 34, 35, 37, 39, 41, 42, 49, 52, 69, 74, 75, 81, 84, 98] }) -Tree 37: SplitPlaneNormal(SplitPlaneNormal { left: 35, right: 36, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.3308" }, vector: [0.0388, -0.1794, -0.0309, -0.1356, -0.1757, -0.0890, -0.0417, -0.0318, 0.4685, -0.2420, "other ..."] } }) -Tree 39: Descendants(Descendants { descendants: [6, 16, 21, 22, 23, 28, 36, 37, 45, 48, 62, 63, 65, 67, 73, 79, 90, 91, 93, 95, 96, 99] }) -Tree 40: Descendants(Descendants { descendants: [3, 7, 8, 15, 17, 20, 26, 27, 54, 55, 66, 77, 80, 87, 94] }) -Tree 41: SplitPlaneNormal(SplitPlaneNormal { left: 39, right: 40, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0459" }, vector: [-0.2209, 0.1963, 0.1062, 0.0898, 0.0185, -0.1583, 0.1786, -0.2590, -0.1887, 0.1668, "other ..."] } }) -Tree 42: Descendants(Descendants { descendants: [1, 5, 14, 19, 24, 25, 31, 32, 34, 40, 42, 59, 60, 69, 82, 84, 88, 92] }) -Tree 43: Descendants(Descendants { descendants: [10, 12, 13, 18, 30, 35, 39, 41, 43, 51, 52, 56, 57, 61, 64, 68, 72, 74, 83, 85, 89] }) -Tree 44: SplitPlaneNormal(SplitPlaneNormal { left: 42, right: 43, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.2613" }, vector: [0.0889, -0.0106, -0.1512, -0.2271, 0.2004, -0.1394, -0.0955, 0.2163, -0.1615, -0.0438, "other ..."] } }) -Tree 45: Descendants(Descendants { descendants: [0, 2, 4, 9, 11, 29, 33, 38, 44, 46, 47, 49, 50, 53, 58, 70, 71, 75, 76, 78, 81, 86, 97, 98] }) -Tree 46: SplitPlaneNormal(SplitPlaneNormal { left: 44, right: 45, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.5807" }, vector: [0.2204, 0.1546, -0.0481, -0.0138, 0.1466, 0.0739, 0.1373, 0.2711, -0.0635, 0.1936, "other ..."] } }) -Tree 48: Descendants(Descendants { descendants: [8, 12, 16, 23, 28, 40, 41, 44, 48, 54, 60, 64, 68, 73, 99] }) -Tree 49: Descendants(Descendants { descendants: [13, 19, 24, 25, 27, 30, 34, 46, 51, 56, 63, 66, 72, 83, 87, 92] }) -Tree 50: SplitPlaneNormal(SplitPlaneNormal { left: 48, right: 49, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.5499" }, vector: [-0.0518, 0.3110, 0.0163, 0.1242, 0.0115, 0.2871, -0.1097, -0.0757, -0.1376, -0.0725, "other ..."] } }) -Tree 51: Descendants(Descendants { descendants: [6, 36, 37, 43, 45, 59, 82, 89, 90, 93] }) -Tree 52: SplitPlaneNormal(SplitPlaneNormal { left: 50, right: 51, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.0630" }, vector: [0.2358, -0.1554, 0.3851, 0.2011, -0.2047, -0.2508, -0.0279, 0.1935, -0.1501, -0.1522, "other ..."] } }) -Tree 53: Descendants(Descendants { descendants: [1, 7, 9, 10, 15, 17, 26, 29, 33, 47, 50, 55, 57, 61, 65, 77, 79, 85, 95, 97] }) -Tree 54: Descendants(Descendants { descendants: [0, 4, 20, 31, 32, 35, 38, 42, 49, 52, 53, 58, 70, 75, 76, 84, 88] }) -Tree 55: SplitPlaneNormal(SplitPlaneNormal { left: 53, right: 54, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.0744" }, vector: [0.0700, -0.1293, -0.0627, 0.3912, -0.0190, -0.1505, 0.1277, -0.1224, 0.0108, -0.4143, "other ..."] } }) -Tree 56: SplitPlaneNormal(SplitPlaneNormal { left: 52, right: 55, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.6438" }, vector: [0.0375, 0.0466, -0.1290, -0.0388, -0.0623, 0.0907, 0.0547, 0.3634, 0.1866, 0.2968, "other ..."] } }) -Tree 57: Descendants(Descendants { descendants: [2, 3, 5, 11, 14, 18, 21, 22, 39, 62, 67, 69, 71, 74, 78, 80, 81, 86, 91, 94, 96, 98] }) -Tree 59: Descendants(Descendants { descendants: [3, 12, 15, 21, 28, 37, 54, 57, 66, 69, 73, 77, 79, 83, 87, 89, 90, 94, 95, 99] }) -Tree 60: Descendants(Descendants { descendants: [13, 16, 19, 29, 39, 41, 42, 45, 46, 50, 56, 63, 64, 72, 85] }) -Tree 61: Descendants(Descendants { descendants: [0, 4, 8, 18, 20, 22, 23, 24, 35, 43, 47, 51, 52, 53, 55, 58, 61, 68, 71, 75, 76, 78, 80, 82, 86] }) -Tree 62: SplitPlaneNormal(SplitPlaneNormal { left: 60, right: 61, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.9435" }, vector: [0.0581, 0.1085, -0.1341, -0.2348, -0.3228, -0.2522, 0.3097, 0.2076, -0.0093, 0.1565, "other ..."] } }) -Tree 63: SplitPlaneNormal(SplitPlaneNormal { left: 59, right: 62, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.1936" }, vector: [0.3169, -0.1754, -0.1837, -0.0504, 0.1379, 0.2769, -0.0601, -0.2512, 0.2685, -0.1864, "other ..."] } }) -Tree 64: Descendants(Descendants { descendants: [5, 7, 9, 14, 27, 31, 32, 36, 38, 48, 59, 62, 65, 67, 70, 74, 84, 93, 96] }) -Tree 65: Descendants(Descendants { descendants: [1, 2, 6, 10, 11, 17, 25, 26, 30, 33, 34, 40, 44, 49, 60, 81, 88, 91, 92, 97, 98] }) -Tree 66: SplitPlaneNormal(SplitPlaneNormal { left: 64, right: 65, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.0309" }, vector: [0.0180, -0.1078, -0.1967, 0.0956, -0.0008, -0.0663, -0.1064, -0.2888, 0.2329, 0.0285, "other ..."] } }) -Tree 68: Descendants(Descendants { descendants: [8, 9, 17, 27, 30, 37, 40, 42, 52, 55, 73, 85, 87, 91] }) -Tree 69: Descendants(Descendants { descendants: [3, 6, 7, 18, 26, 29, 32, 36, 38, 48, 65, 79, 81, 86, 93, 95, 96] }) -Tree 70: Descendants(Descendants { descendants: [0, 1, 2, 10, 11, 14, 25, 33, 62, 69, 70, 74, 84, 88, 99] }) -Tree 71: SplitPlaneNormal(SplitPlaneNormal { left: 69, right: 70, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0118" }, vector: [-0.3279, -0.0715, 0.0546, -0.2410, -0.1629, -0.1665, 0.0214, -0.1654, -0.0215, -0.3053, "other ..."] } }) -Tree 72: SplitPlaneNormal(SplitPlaneNormal { left: 68, right: 71, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.2180" }, vector: [-0.1710, -0.0641, 0.1282, 0.2421, -0.0241, -0.0552, 0.1967, 0.1703, -0.1733, 0.1647, "other ..."] } }) -Tree 73: Descendants(Descendants { descendants: [4, 13, 15, 16, 19, 24, 28, 31, 35, 39, 44, 45, 46, 50, 54, 56, 57, 63, 64, 66, 67, 72, 77, 80, 89, 90, 92, 94, 97, 98] }) -Tree 74: Descendants(Descendants { descendants: [5, 12, 20, 21, 22, 23, 34, 41, 43, 47, 49, 51, 53, 58, 59, 60, 61, 68, 71, 75, 76, 78, 82, 83] }) -Tree 75: SplitPlaneNormal(SplitPlaneNormal { left: 73, right: 74, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0342" }, vector: [0.0119, -0.0391, -0.0191, -0.1374, -0.3241, 0.0455, 0.1109, -0.0617, 0.0776, 0.0513, "other ..."] } }) -Tree 77: Descendants(Descendants { descendants: [8, 18, 20, 29, 31, 39, 41, 45, 50, 51, 56, 61, 63, 64, 66, 67, 72, 76, 80, 83, 93] }) -Tree 78: Descendants(Descendants { descendants: [0, 2, 10, 13, 25, 30, 34, 35, 36, 42, 44, 62, 74, 89, 92] }) -Tree 79: SplitPlaneNormal(SplitPlaneNormal { left: 77, right: 78, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.4580" }, vector: [-0.2811, 0.1602, 0.1534, 0.1554, -0.1615, -0.2227, 0.0627, -0.2144, -0.0981, 0.0526, "other ..."] } }) -Tree 80: Descendants(Descendants { descendants: [6, 11, 14, 19, 26, 27, 28, 40, 52, 86, 91, 96] }) -Tree 81: Descendants(Descendants { descendants: [1, 3, 5, 7, 9, 15, 16, 21, 24, 37, 46, 47, 48, 57, 68, 70, 71, 73, 77, 78, 81, 85, 87, 90, 95, 98] }) -Tree 82: SplitPlaneNormal(SplitPlaneNormal { left: 80, right: 81, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.1230" }, vector: [-0.1801, -0.1814, -0.2144, -0.0675, 0.0791, 0.0581, 0.3301, 0.0860, -0.3168, 0.1403, "other ..."] } }) -Tree 83: SplitPlaneNormal(SplitPlaneNormal { left: 79, right: 82, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.8187" }, vector: [-0.0254, 0.2078, -0.1625, -0.1171, -0.1369, 0.1272, 0.0764, -0.1323, 0.2202, 0.2376, "other ..."] } }) -Tree 84: Descendants(Descendants { descendants: [4, 12, 17, 22, 23, 32, 33, 38, 43, 49, 53, 54, 55, 58, 59, 60, 65, 69, 75, 79, 82, 84, 88, 94, 97, 99] }) -Tree 86: Descendants(Descendants { descendants: [12, 13, 16, 21, 22, 41, 44, 45, 46, 50, 51, 54, 56, 59, 66, 72, 77, 80, 89, 93, 98] }) -Tree 87: Descendants(Descendants { descendants: [3, 6, 8, 23, 27, 28, 37, 40, 43, 47, 61, 64, 68, 71, 73, 78, 79, 85, 91, 95, 96] }) -Tree 88: SplitPlaneNormal(SplitPlaneNormal { left: 86, right: 87, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.3410" }, vector: [-0.0558, 0.1524, -0.2597, -0.1741, -0.0292, -0.1124, 0.1826, -0.0289, 0.2622, 0.4321, "other ..."] } }) -Tree 89: Descendants(Descendants { descendants: [0, 1, 2, 5, 7, 9, 10, 11, 14, 15, 19, 24, 29, 30, 31, 33, 36, 39, 42, 52, 62, 63, 65, 67, 69, 83, 87, 90, 92] }) -Tree 90: Descendants(Descendants { descendants: [4, 17, 18, 20, 25, 26, 32, 34, 35, 38, 48, 49, 53, 55, 57, 58, 60, 70, 74, 75, 76, 81, 82, 84, 86, 88, 94, 97, 99] }) -Tree 91: SplitPlaneNormal(SplitPlaneNormal { left: 89, right: 90, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.6926" }, vector: [-0.1723, -0.3093, -0.2410, 0.0338, -0.1640, -0.0282, 0.1961, -0.2324, 0.2395, -0.0665, "other ..."] } }) -Tree 93: Descendants(Descendants { descendants: [0, 29, 33, 36, 42, 44, 45, 48, 50, 56, 61, 65, 67, 72, 76, 80, 93, 95, 96, 97] }) -Tree 94: Descendants(Descendants { descendants: [1, 10, 11, 13, 16, 19, 24, 25, 28, 30, 39, 40, 46, 51, 54, 62, 63, 66, 77, 89, 90] }) -Tree 95: Descendants(Descendants { descendants: [2, 3, 6, 8, 26, 27, 38, 57, 83, 85, 87] }) -Tree 96: SplitPlaneNormal(SplitPlaneNormal { left: 94, right: 95, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0383" }, vector: [-0.0480, 0.0431, -0.0749, 0.1977, -0.0936, -0.0084, 0.4198, 0.1228, 0.0345, 0.3257, "other ..."] } }) -Tree 97: SplitPlaneNormal(SplitPlaneNormal { left: 93, right: 96, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.5940" }, vector: [-0.1380, -0.0146, -0.0335, 0.0588, -0.2350, -0.2671, -0.0050, -0.4234, 0.0922, 0.0457, "other ..."] } }) -Tree 98: Descendants(Descendants { descendants: [21, 32, 34, 41, 43, 47, 49, 58, 68, 78, 79, 81, 82, 86] }) -Tree 99: Descendants(Descendants { descendants: [5, 7, 9, 14, 15, 23, 31, 35, 52, 55, 70, 71, 74, 91, 92, 98] }) -Tree 100: Descendants(Descendants { descendants: [4, 12, 17, 18, 20, 22, 37, 53, 59, 60, 64, 69, 73, 75, 84, 88, 94, 99] }) -Tree 101: SplitPlaneNormal(SplitPlaneNormal { left: 99, right: 100, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.2037" }, vector: [-0.1937, -0.0438, 0.1336, 0.0052, 0.0790, 0.1019, 0.2513, -0.0888, 0.1992, -0.1184, "other ..."] } }) -Tree 102: SplitPlaneNormal(SplitPlaneNormal { left: 98, right: 101, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.0708" }, vector: [0.0469, -0.0452, 0.1103, -0.1461, 0.1633, -0.1284, 0.0917, 0.0132, -0.1658, -0.0299, "other ..."] } }) +Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 88, right: 91, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.3733" }, vector: [-0.0475, -0.1496, 0.1344, -0.1902, -0.2161, -0.4158, -0.1593, 0.1212, -0.0136, 0.2277, "other ..."] } }) +Tree 1: SplitPlaneNormal(SplitPlaneNormal { left: 76, right: 81, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.4143" }, vector: [-0.1850, 0.1162, 0.1506, 0.1488, 0.2308, 0.1370, -0.2152, -0.0274, -0.0407, -0.2282, "other ..."] } }) +Tree 2: SplitPlaneNormal(SplitPlaneNormal { left: 66, right: 73, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.0804" }, vector: [0.1941, -0.1680, -0.0860, -0.4588, 0.2054, 0.0884, 0.0622, 0.1314, 0.1377, -0.2936, "other ..."] } }) +Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 58, right: 63, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0458" }, vector: [-0.0598, -0.0926, -0.1871, -0.0077, 0.2839, 0.2008, 0.1168, -0.3345, -0.0870, 0.0621, "other ..."] } }) +Tree 4: SplitPlaneNormal(SplitPlaneNormal { left: 50, right: 53, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0933" }, vector: [-0.2249, -0.2354, -0.2492, 0.0508, -0.0488, 0.3083, 0.0932, -0.0190, -0.4116, -0.0404, "other ..."] } }) +Tree 5: SplitPlaneNormal(SplitPlaneNormal { left: 38, right: 45, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0963" }, vector: [0.0636, -0.2729, 0.4830, 0.1626, 0.0343, -0.0273, -0.0742, 0.0450, -0.3975, -0.3293, "other ..."] } }) +Tree 6: SplitPlaneNormal(SplitPlaneNormal { left: 32, right: 35, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.6869" }, vector: [0.0755, 0.2682, -0.0986, 0.3341, 0.0086, -0.0666, -0.2590, -0.1551, 0.0651, -0.0362, "other ..."] } }) +Tree 7: SplitPlaneNormal(SplitPlaneNormal { left: 26, right: 29, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0797" }, vector: [-0.0053, 0.4627, 0.0033, -0.1321, 0.2763, -0.0670, -0.0985, -0.1405, 0.3819, 0.0681, "other ..."] } }) +Tree 8: SplitPlaneNormal(SplitPlaneNormal { left: 22, right: 23, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.3843" }, vector: [-0.3055, 0.2263, 0.3598, -0.0777, -0.0538, -0.1513, -0.0809, 0.1401, 0.0514, 0.2712, "other ..."] } }) +Tree 9: SplitPlaneNormal(SplitPlaneNormal { left: 12, right: 17, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.9466" }, vector: [-0.1459, -0.2139, -0.2989, 0.0100, -0.1856, -0.0497, 0.1403, 0.0371, -0.2027, 0.1831, "other ..."] } }) +Tree 10: Descendants(Descendants { descendants: [2, 11, 13, 19, 20, 24, 30, 36, 39, 41, 42, 43, 45, 46, 51, 54, 56, 59, 62, 66, 68, 77, 80, 85, 89, 91, 92, 93] }) +Tree 11: Descendants(Descendants { descendants: [4, 8, 18, 21, 22, 52, 64, 67, 72, 78, 98] }) +Tree 12: SplitPlaneNormal(SplitPlaneNormal { left: 10, right: 11, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.1444" }, vector: [0.0412, 0.0950, -0.0460, -0.3947, -0.0556, 0.1065, 0.1877, 0.3147, 0.2321, -0.1957, "other ..."] } }) +Tree 13: Descendants(Descendants { descendants: [3, 14, 17, 25, 26, 32, 33, 37, 38, 44, 47, 50, 55, 57, 61, 71, 73, 79, 88, 90, 94, 95, 96] }) +Tree 14: Descendants(Descendants { descendants: [6, 12, 15, 23, 27, 28, 34, 40, 81, 86, 87, 99] }) +Tree 15: SplitPlaneNormal(SplitPlaneNormal { left: 13, right: 14, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.3565" }, vector: [0.1751, -0.0027, -0.1028, -0.0282, 0.0387, -0.1329, -0.1364, -0.2423, -0.1042, -0.1441, "other ..."] } }) +Tree 16: Descendants(Descendants { descendants: [0, 1, 5, 7, 9, 10, 16, 29, 31, 35, 48, 49, 53, 58, 60, 63, 65, 69, 70, 74, 75, 76, 82, 83, 84, 97] }) +Tree 17: SplitPlaneNormal(SplitPlaneNormal { left: 15, right: 16, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.3772" }, vector: [0.1033, -0.4242, -0.0800, -0.1632, 0.1052, -0.0050, 0.2207, -0.1568, -0.0534, -0.0278, "other ..."] } }) +Tree 18: Descendants(Descendants { descendants: [12, 16, 20, 21, 22, 23, 31, 34, 35, 43, 45, 47, 48, 49, 50, 51, 54, 58, 59, 61, 64, 68, 71, 75, 76, 78, 87, 89, 90, 94] }) +Tree 19: Descendants(Descendants { descendants: [10, 13, 19, 24, 30, 33, 36, 44, 46, 56, 63, 65, 72, 80, 83, 92] }) +Tree 20: SplitPlaneNormal(SplitPlaneNormal { left: 18, right: 19, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.6890" }, vector: [-0.0953, 0.0544, -0.0235, -0.3023, 0.1023, 0.4182, -0.2031, -0.1618, -0.1613, 0.2265, "other ..."] } }) +Tree 21: Descendants(Descendants { descendants: [0, 4, 6, 8, 11, 25, 28, 29, 32, 37, 40, 41, 42, 52, 55, 57, 60, 67, 70, 74, 77, 85, 86, 91, 93, 95, 97, 98, 99] }) +Tree 22: SplitPlaneNormal(SplitPlaneNormal { left: 20, right: 21, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.2139" }, vector: [0.0683, -0.0814, 0.0252, -0.1067, -0.2097, -0.0424, 0.1001, 0.3194, 0.0825, 0.0236, "other ..."] } }) +Tree 23: Descendants(Descendants { descendants: [1, 2, 3, 5, 7, 9, 14, 15, 17, 18, 26, 27, 38, 39, 53, 62, 66, 69, 73, 79, 81, 82, 84, 88, 96] }) +Tree 24: Descendants(Descendants { descendants: [4, 5, 12, 15, 18, 22, 29, 31, 33, 38, 49, 50, 56, 58, 59, 62, 65, 69, 74, 76, 82, 84, 88, 93, 94] }) +Tree 25: Descendants(Descendants { descendants: [0, 1, 7, 10, 11, 20, 24, 25, 30, 32, 34, 35, 36, 44, 48, 60, 63, 70, 83, 89, 92] }) +Tree 26: SplitPlaneNormal(SplitPlaneNormal { left: 24, right: 25, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.8580" }, vector: [0.0064, -0.0347, -0.5050, 0.1150, -0.1841, -0.1740, -0.1482, -0.2880, 0.0158, -0.1222, "other ..."] } }) +Tree 27: Descendants(Descendants { descendants: [2, 6, 16, 17, 19, 23, 26, 27, 28, 40, 41, 42, 45, 47, 53, 55, 64, 68, 71, 73, 77, 79, 91, 97, 99] }) +Tree 28: Descendants(Descendants { descendants: [3, 8, 9, 13, 14, 21, 37, 39, 43, 46, 51, 52, 54, 57, 61, 66, 67, 72, 75, 78, 80, 81, 85, 86, 87, 90, 95, 96, 98] }) +Tree 29: SplitPlaneNormal(SplitPlaneNormal { left: 27, right: 28, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.3445" }, vector: [0.0543, -0.0671, 0.0759, 0.0437, -0.0054, -0.0953, 0.1007, 0.0988, 0.0009, -0.2796, "other ..."] } }) +Tree 30: Descendants(Descendants { descendants: [5, 9, 12, 15, 17, 18, 22, 33, 52, 53, 58, 69, 71, 74, 75, 82, 85, 88, 99] }) +Tree 31: Descendants(Descendants { descendants: [4, 10, 25, 29, 30, 31, 32, 34, 35, 38, 39, 41, 43, 49, 51, 59, 60, 64, 65, 70, 76, 83, 84, 92] }) +Tree 32: SplitPlaneNormal(SplitPlaneNormal { left: 30, right: 31, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0413" }, vector: [-0.1386, -0.0892, -0.2192, 0.1007, 0.1662, 0.1992, 0.1561, -0.1894, -0.0047, -0.5036, "other ..."] } }) +Tree 33: Descendants(Descendants { descendants: [0, 2, 3, 7, 16, 21, 23, 24, 37, 44, 47, 50, 55, 57, 66, 67, 68, 73, 77, 80, 81, 87, 89, 94, 95, 96, 97, 98] }) +Tree 34: Descendants(Descendants { descendants: [1, 6, 8, 11, 13, 14, 19, 20, 26, 27, 28, 36, 40, 42, 45, 46, 48, 54, 56, 61, 62, 63, 72, 78, 79, 86, 90, 91, 93] }) +Tree 35: SplitPlaneNormal(SplitPlaneNormal { left: 33, right: 34, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.7813" }, vector: [0.2283, -0.0301, 0.0221, 0.3419, -0.1074, 0.1028, -0.0143, -0.4095, 0.1713, -0.2207, "other ..."] } }) +Tree 36: Descendants(Descendants { descendants: [18, 23, 24, 38, 41, 43, 47, 61, 64, 71, 79, 95] }) +Tree 37: Descendants(Descendants { descendants: [3, 6, 8, 17, 19, 20, 21, 26, 27, 37, 46, 52, 53, 55, 57, 60, 66, 68, 72, 73, 77, 78, 81, 85, 86, 87, 90, 91] }) +Tree 38: SplitPlaneNormal(SplitPlaneNormal { left: 36, right: 37, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.9826" }, vector: [0.0621, 0.1333, 0.1151, -0.1787, -0.1980, -0.2909, -0.1670, -0.2455, 0.1465, -0.2411, "other ..."] } }) +Tree 39: Descendants(Descendants { descendants: [9, 30, 33, 65] }) +Tree 40: Descendants(Descendants { descendants: [1, 13, 15, 16, 22, 28, 36, 45, 48, 54, 56, 58, 63, 80, 83, 89, 94, 97] }) +Tree 41: Descendants(Descendants { descendants: [0, 2, 7, 11, 14, 39, 40, 42, 44, 62, 67, 69, 96, 98, 99] }) +Tree 42: SplitPlaneNormal(SplitPlaneNormal { left: 40, right: 41, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.3337" }, vector: [-0.0277, 0.0111, 0.2902, -0.1474, -0.2389, 0.1891, -0.1465, 0.3082, 0.3863, -0.1365, "other ..."] } }) +Tree 43: SplitPlaneNormal(SplitPlaneNormal { left: 39, right: 42, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.7534" }, vector: [-0.0250, -0.2548, 0.1022, 0.2544, -0.2040, -0.3794, -0.0195, 0.2224, -0.0019, -0.2172, "other ..."] } }) +Tree 44: Descendants(Descendants { descendants: [4, 5, 10, 12, 25, 29, 31, 32, 34, 35, 49, 50, 51, 59, 70, 74, 75, 76, 82, 84, 88, 92, 93] }) +Tree 45: SplitPlaneNormal(SplitPlaneNormal { left: 43, right: 44, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0741" }, vector: [-0.1841, -0.3075, -0.1588, -0.0624, -0.0917, -0.1359, 0.3864, -0.1105, -0.0036, -0.2592, "other ..."] } }) +Tree 46: Descendants(Descendants { descendants: [0, 4, 11, 14, 15, 17, 18, 20, 32, 35, 49, 52, 53, 55, 56, 59, 75, 77, 84, 89, 92, 94, 98] }) +Tree 47: Descendants(Descendants { descendants: [3, 24, 30, 39, 46, 62, 66, 67, 69, 73, 91] }) +Tree 48: SplitPlaneNormal(SplitPlaneNormal { left: 46, right: 47, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0823" }, vector: [-0.0437, 0.4360, 0.0071, -0.3022, 0.1217, 0.0621, -0.0552, -0.1529, -0.1505, 0.1638, "other ..."] } }) +Tree 49: Descendants(Descendants { descendants: [6, 8, 16, 19, 21, 22, 23, 28, 37, 43, 54, 58, 60, 63, 64, 68, 71, 72, 78, 79, 80, 82, 88, 90, 99] }) +Tree 50: SplitPlaneNormal(SplitPlaneNormal { left: 48, right: 49, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0810" }, vector: [0.0085, 0.1364, -0.1779, 0.1409, 0.0822, -0.1502, 0.2116, -0.3355, 0.1380, 0.0108, "other ..."] } }) +Tree 51: Descendants(Descendants { descendants: [2, 7, 12, 27, 29, 33, 34, 36, 47, 51, 57, 61, 74, 85, 86, 93, 95, 96, 97] }) +Tree 52: Descendants(Descendants { descendants: [1, 5, 9, 10, 13, 25, 26, 31, 38, 40, 41, 42, 44, 45, 48, 50, 65, 70, 76, 81, 83, 87] }) +Tree 53: SplitPlaneNormal(SplitPlaneNormal { left: 51, right: 52, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.1338" }, vector: [-0.0609, 0.0086, -0.2000, 0.0923, 0.1533, 0.1656, -0.0856, -0.3540, 0.1304, -0.0072, "other ..."] } }) +Tree 54: Descendants(Descendants { descendants: [36, 39, 62, 81, 89, 93] }) +Tree 55: Descendants(Descendants { descendants: [0, 1, 3, 6, 9, 14, 26, 29, 32, 34, 37, 38, 44, 47, 50, 54, 57, 61, 74, 77, 79, 86, 90, 95, 96] }) +Tree 56: SplitPlaneNormal(SplitPlaneNormal { left: 54, right: 55, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.7111" }, vector: [-0.0483, 0.0173, -0.3836, -0.1830, 0.2282, 0.0862, 0.0591, 0.2533, -0.0096, 0.1085, "other ..."] } }) +Tree 57: Descendants(Descendants { descendants: [15, 20, 21, 22, 43, 58, 71, 76, 80, 82] }) +Tree 58: SplitPlaneNormal(SplitPlaneNormal { left: 56, right: 57, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.3395" }, vector: [0.1390, 0.0334, 0.1318, -0.2016, 0.1608, -0.0309, -0.0216, -0.0063, -0.0220, 0.0322, "other ..."] } }) +Tree 59: Descendants(Descendants { descendants: [5, 16, 25, 30, 35, 40, 41, 48, 49, 51, 60, 70, 85, 92] }) +Tree 60: Descendants(Descendants { descendants: [4, 8, 12, 17, 18, 23, 24, 27, 28, 52, 53, 55, 56, 59, 63, 64, 67, 68, 73, 75, 78, 83, 87, 88, 94, 99] }) +Tree 61: SplitPlaneNormal(SplitPlaneNormal { left: 59, right: 60, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.4039" }, vector: [0.3769, 0.0376, 0.1871, 0.1913, 0.3110, -0.2000, 0.1085, 0.1982, 0.1683, 0.0548, "other ..."] } }) +Tree 62: Descendants(Descendants { descendants: [2, 7, 10, 11, 13, 19, 31, 33, 42, 45, 46, 65, 66, 69, 72, 84, 91, 97, 98] }) +Tree 63: SplitPlaneNormal(SplitPlaneNormal { left: 61, right: 62, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.3949" }, vector: [-0.0495, 0.0658, 0.2323, 0.1854, 0.3495, -0.0897, -0.1301, -0.1341, -0.1506, -0.0808, "other ..."] } }) +Tree 64: Descendants(Descendants { descendants: [1, 2, 3, 6, 10, 14, 25, 26, 27, 31, 40, 42, 44, 57, 62, 79, 81, 88, 90, 91, 97, 99] }) +Tree 65: Descendants(Descendants { descendants: [7, 9, 29, 33, 36, 38, 48, 50, 70, 86, 89, 93, 95, 96] }) +Tree 66: SplitPlaneNormal(SplitPlaneNormal { left: 64, right: 65, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.1602" }, vector: [0.1521, 0.1089, -0.1552, 0.0846, -0.2234, 0.0801, 0.0090, 0.3519, -0.3178, 0.2954, "other ..."] } }) +Tree 67: Descendants(Descendants { descendants: [17, 21, 37, 41, 46, 47, 52, 59, 60, 77, 85, 98] }) +Tree 68: Descendants(Descendants { descendants: [0, 4, 8, 11, 15, 18, 20, 28, 30, 32, 35, 39, 53, 66, 67, 69, 72, 73, 74, 75, 84] }) +Tree 69: Descendants(Descendants { descendants: [34, 45, 49, 54, 56, 63, 65, 76, 83, 92, 94] }) +Tree 70: SplitPlaneNormal(SplitPlaneNormal { left: 68, right: 69, normal: Leaf { header: NodeHeaderEuclidean { bias: "-1.0899" }, vector: [0.0031, 0.0549, 0.2685, 0.3145, 0.1133, 0.2947, -0.0886, -0.2127, 0.0126, 0.2376, "other ..."] } }) +Tree 71: Descendants(Descendants { descendants: [5, 12, 13, 16, 19, 22, 23, 24, 43, 51, 55, 58, 61, 64, 68, 71, 78, 80, 82, 87] }) +Tree 72: SplitPlaneNormal(SplitPlaneNormal { left: 70, right: 71, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.3044" }, vector: [-0.0145, 0.3141, -0.1642, -0.1171, -0.1654, -0.0233, -0.0565, -0.1028, 0.0166, 0.2478, "other ..."] } }) +Tree 73: SplitPlaneNormal(SplitPlaneNormal { left: 67, right: 72, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.1344" }, vector: [0.0129, 0.2435, 0.2349, -0.0484, 0.2422, -0.2681, 0.1833, -0.1857, -0.3249, -0.1537, "other ..."] } }) +Tree 74: Descendants(Descendants { descendants: [1, 16, 18, 21, 22, 23, 35, 37, 43, 47, 54, 55, 71, 78, 80, 82, 89, 90, 95, 98] }) +Tree 75: Descendants(Descendants { descendants: [15, 20, 24, 32, 34, 38, 49, 52, 53, 57, 58, 59, 60, 63, 68, 69, 75, 76, 79, 83, 84, 86, 88, 92, 94, 99] }) +Tree 76: SplitPlaneNormal(SplitPlaneNormal { left: 74, right: 75, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.3279" }, vector: [-0.2219, -0.1252, 0.0397, 0.2645, -0.0092, 0.1469, 0.0777, -0.1615, -0.1043, 0.0669, "other ..."] } }) +Tree 77: Descendants(Descendants { descendants: [0, 8, 11, 19, 30, 41, 42, 44, 45, 46, 51, 56, 64, 66, 67, 72, 73, 81] }) +Tree 78: Descendants(Descendants { descendants: [3, 5, 6, 9, 14, 17, 26, 27, 28, 40, 48, 77, 85, 87, 91, 93, 96] }) +Tree 79: SplitPlaneNormal(SplitPlaneNormal { left: 77, right: 78, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.0001" }, vector: [-0.0435, 0.3355, 0.3262, 0.0352, -0.2209, 0.0684, -0.1247, -0.0310, 0.1508, 0.0856, "other ..."] } }) +Tree 80: Descendants(Descendants { descendants: [2, 4, 7, 10, 12, 13, 25, 29, 31, 33, 36, 39, 50, 61, 62, 65, 70, 74, 97] }) +Tree 81: SplitPlaneNormal(SplitPlaneNormal { left: 79, right: 80, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.4929" }, vector: [-0.2899, -0.1000, -0.0545, -0.0710, 0.1562, -0.0686, 0.2158, 0.0031, -0.3984, 0.1937, "other ..."] } }) +Tree 82: Descendants(Descendants { descendants: [4, 18, 30, 34, 41, 43, 49, 51, 56, 61, 64, 76, 79, 84, 85, 88, 93, 94] }) +Tree 83: Descendants(Descendants { descendants: [8, 12, 17, 21, 25, 37, 40, 52, 60, 67, 69, 71, 73, 75, 78, 87, 99] }) +Tree 84: SplitPlaneNormal(SplitPlaneNormal { left: 82, right: 83, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.4767" }, vector: [0.1869, 0.1680, -0.0610, -0.1739, -0.2091, -0.3621, -0.2980, 0.0260, -0.2019, 0.1121, "other ..."] } }) +Tree 85: Descendants(Descendants { descendants: [2, 6, 13, 16, 19, 24, 26, 27, 28, 36, 42, 44, 45, 50, 54, 62, 65, 66, 72, 97] }) +Tree 86: Descendants(Descendants { descendants: [1, 10, 11, 31, 33, 46, 47, 70, 86, 91, 98] }) +Tree 87: SplitPlaneNormal(SplitPlaneNormal { left: 85, right: 86, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.2676" }, vector: [0.2076, -0.2436, -0.3938, 0.0593, -0.2604, 0.0931, -0.1010, 0.2622, 0.2030, -0.1545, "other ..."] } }) +Tree 88: SplitPlaneNormal(SplitPlaneNormal { left: 84, right: 87, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.0201" }, vector: [-0.1124, 0.1501, 0.1593, 0.1114, 0.1879, 0.1623, -0.2202, -0.1170, -0.3266, 0.2916, "other ..."] } }) +Tree 89: Descendants(Descendants { descendants: [0, 5, 7, 9, 14, 15, 22, 29, 32, 35, 39, 53, 55, 59, 74, 82, 89, 92, 96] }) +Tree 90: Descendants(Descendants { descendants: [3, 20, 23, 38, 48, 57, 58, 63, 68, 77, 80, 81, 83, 90, 95] }) +Tree 91: SplitPlaneNormal(SplitPlaneNormal { left: 89, right: 90, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.7103" }, vector: [-0.0174, 0.1012, -0.3409, 0.1977, 0.2175, -0.0333, -0.1155, -0.3879, 0.1104, 0.1831, "other ..."] } }) Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.8013, 0.2371, 0.6955, 0.8606, 0.5280, 0.2667, 0.6057, 0.9830, 0.9430, 0.0479, "other ..."] }) Item 1: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.4199, 0.2620, 0.2655, 0.8414, 0.0192, 0.3828, 0.2561, 0.2692, 0.0368, 0.4624, "other ..."] }) Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.1040, 0.9647, 0.8238, 0.5344, 0.4903, 0.4420, 0.7937, 0.4028, 0.2083, 0.3315, "other ..."] }) diff --git a/src/tests/snapshots/arroy__tests__writer__write_and_update_lot_of_random_points_with_little_memory-2.snap b/src/tests/snapshots/arroy__tests__writer__write_and_update_lot_of_random_points_with_little_memory-2.snap new file mode 100644 index 0000000..076d650 --- /dev/null +++ b/src/tests/snapshots/arroy__tests__writer__write_and_update_lot_of_random_points_with_little_memory-2.snap @@ -0,0 +1,567 @@ +--- +source: src/tests/writer.rs +expression: handle +--- +================== +Dumping index 0 +Root: Metadata { dimensions: 3, items: RoaringBitmap<150 values between 0 and 149>, roots: [0, 1, 188], distance: "cosine" } +Version: Version { major: 0, minor: 7, patch: 0 } +Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 94, right: 95, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.7419, -0.0092, 0.6705] } }) +Tree 1: SplitPlaneNormal(SplitPlaneNormal { left: 2, right: 3, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.5938, 0.3404, -0.7290] } }) +Tree 2: SplitPlaneNormal(SplitPlaneNormal { left: 64, right: 65, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.5969, 0.7955, -0.1042] } }) +Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 4, right: 5, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6720, -0.7180, 0.1817] } }) +Tree 4: SplitPlaneNormal(SplitPlaneNormal { left: 42, right: 45, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.8971, 0.4184, 0.1423] } }) +Tree 5: SplitPlaneNormal(SplitPlaneNormal { left: 6, right: 7, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.2091, -0.4533, 0.8665] } }) +Tree 6: SplitPlaneNormal(SplitPlaneNormal { left: 26, right: 27, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.3881, 0.4833, 0.7847] } }) +Tree 7: SplitPlaneNormal(SplitPlaneNormal { left: 8, right: 9, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.0141, 0.8224, -0.5688] } }) +Tree 8: SplitPlaneNormal(SplitPlaneNormal { left: 16, right: 17, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.6128, 0.7615, 0.2113] } }) +Tree 9: SplitPlaneNormal(SplitPlaneNormal { left: 10, right: 12, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.7223, -0.6315, -0.2819] } }) +Tree 10: SplitPlaneNormal(SplitPlaneNormal { left: 473, right: 474, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.1805, -0.5812, 0.7935] } }) +Tree 12: Descendants(Descendants { descendants: [4, 59, 138] }) +Tree 16: SplitPlaneNormal(SplitPlaneNormal { left: 18, right: 19, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.4400, -0.6017, -0.6666] } }) +Tree 17: SplitPlaneNormal(SplitPlaneNormal { left: 457, right: 458, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.7648, -0.3201, -0.5591] } }) +Tree 18: SplitPlaneNormal(SplitPlaneNormal { left: 20, right: 21, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6356, -0.3787, -0.6728] } }) +Tree 19: SplitPlaneNormal(SplitPlaneNormal { left: 453, right: 454, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.3880, -0.0274, -0.9212] } }) +Tree 20: SplitPlaneNormal(SplitPlaneNormal { left: 447, right: 448, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.2480, -0.9656, 0.0777] } }) +Tree 21: Descendants(Descendants { descendants: [46, 75, 120] }) +Tree 26: SplitPlaneNormal(SplitPlaneNormal { left: 40, right: 41, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.1973, 0.9757, 0.0950] } }) +Tree 27: SplitPlaneNormal(SplitPlaneNormal { left: 28, right: 29, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6078, -0.7489, -0.2641] } }) +Tree 28: SplitPlaneNormal(SplitPlaneNormal { left: 34, right: 35, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6381, -0.4144, -0.6490] } }) +Tree 29: SplitPlaneNormal(SplitPlaneNormal { left: 433, right: 434, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.3862, 0.9188, 0.0820] } }) +Tree 34: SplitPlaneNormal(SplitPlaneNormal { left: 36, right: 37, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.7289, -0.4821, -0.4861] } }) +Tree 35: Descendants(Descendants { descendants: [19, 81, 118] }) +Tree 36: SplitPlaneNormal(SplitPlaneNormal { left: 413, right: 414, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.2625, -0.3008, 0.9169] } }) +Tree 37: SplitPlaneNormal(SplitPlaneNormal { left: 38, right: 39, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.4520, 0.7619, -0.4638] } }) +Tree 38: SplitPlaneNormal(SplitPlaneNormal { left: 405, right: 406, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.2309, -0.7225, 0.6517] } }) +Tree 39: Descendants(Descendants { descendants: [45, 71] }) +Tree 40: SplitPlaneNormal(SplitPlaneNormal { left: 403, right: 404, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.1757, 0.8241, 0.5385] } }) +Tree 41: SplitPlaneNormal(SplitPlaneNormal { left: 395, right: 396, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.3164, -0.9406, 0.1233] } }) +Tree 42: SplitPlaneNormal(SplitPlaneNormal { left: 52, right: 53, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.1610, 0.3819, -0.9101] } }) +Tree 45: SplitPlaneNormal(SplitPlaneNormal { left: 46, right: 47, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.1491, 0.5140, -0.8448] } }) +Tree 46: Descendants(Descendants { descendants: [49, 91] }) +Tree 47: SplitPlaneNormal(SplitPlaneNormal { left: 48, right: 49, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.8454, -0.4542, 0.2812] } }) +Tree 48: SplitPlaneNormal(SplitPlaneNormal { left: 375, right: 376, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.4911, -0.2623, 0.8307] } }) +Tree 49: Descendants(Descendants { descendants: [13, 23, 140] }) +Tree 52: SplitPlaneNormal(SplitPlaneNormal { left: 341, right: 342, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.5599, 0.1200, -0.8199] } }) +Tree 53: SplitPlaneNormal(SplitPlaneNormal { left: 335, right: 336, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.7792, 0.5645, 0.2723] } }) +Tree 64: SplitPlaneNormal(SplitPlaneNormal { left: 80, right: 84, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.7926, -0.2856, -0.5388] } }) +Tree 65: SplitPlaneNormal(SplitPlaneNormal { left: 66, right: 72, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.0680, 0.7454, -0.6632] } }) +Tree 66: SplitPlaneNormal(SplitPlaneNormal { left: 493, right: 494, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.2240, 0.8675, -0.4442] } }) +Tree 72: SplitPlaneNormal(SplitPlaneNormal { left: 479, right: 480, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.9140, -0.3803, 0.1412] } }) +Tree 80: SplitPlaneNormal(SplitPlaneNormal { left: 88, right: 89, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.4346, 0.7756, -0.4578] } }) +Tree 84: SplitPlaneNormal(SplitPlaneNormal { left: 443, right: 444, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.4369, -0.8596, -0.2651] } }) +Tree 88: SplitPlaneNormal(SplitPlaneNormal { left: 90, right: 91, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.9628, -0.0719, 0.2605] } }) +Tree 89: SplitPlaneNormal(SplitPlaneNormal { left: 441, right: 442, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.7235, 0.4241, -0.5447] } }) +Tree 90: SplitPlaneNormal(SplitPlaneNormal { left: 92, right: 93, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.8021, 0.4808, 0.3542] } }) +Tree 91: Descendants(Descendants { descendants: [55, 109, 147] }) +Tree 92: SplitPlaneNormal(SplitPlaneNormal { left: 439, right: 440, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.2673, 0.9257, -0.2676] } }) +Tree 93: Descendants(Descendants { descendants: [37, 51] }) +Tree 94: SplitPlaneNormal(SplitPlaneNormal { left: 128, right: 129, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.4785, -0.8779, -0.0195] } }) +Tree 95: SplitPlaneNormal(SplitPlaneNormal { left: 96, right: 97, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.9268, -0.3400, -0.1595] } }) +Tree 96: SplitPlaneNormal(SplitPlaneNormal { left: 114, right: 115, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.0640, 0.8356, -0.5456] } }) +Tree 97: SplitPlaneNormal(SplitPlaneNormal { left: 98, right: 100, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.1260, 0.8927, -0.4327] } }) +Tree 98: SplitPlaneNormal(SplitPlaneNormal { left: 108, right: 109, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.3363, -0.8669, 0.3680] } }) +Tree 100: SplitPlaneNormal(SplitPlaneNormal { left: 407, right: 408, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.3952, -0.6037, 0.6924] } }) +Tree 108: SplitPlaneNormal(SplitPlaneNormal { left: 389, right: 390, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.8002, -0.4737, -0.3679] } }) +Tree 109: SplitPlaneNormal(SplitPlaneNormal { left: 110, right: 111, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.8863, -0.1858, 0.4241] } }) +Tree 110: SplitPlaneNormal(SplitPlaneNormal { left: 387, right: 388, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.8246, -0.3603, -0.4361] } }) +Tree 111: Descendants(Descendants { descendants: [37] }) +Tree 114: SplitPlaneNormal(SplitPlaneNormal { left: 363, right: 364, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.2172, 0.8988, -0.3807] } }) +Tree 115: SplitPlaneNormal(SplitPlaneNormal { left: 116, right: 117, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.4503, 0.5907, -0.6696] } }) +Tree 116: SplitPlaneNormal(SplitPlaneNormal { left: 353, right: 354, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.7613, -0.5632, 0.3214] } }) +Tree 117: SplitPlaneNormal(SplitPlaneNormal { left: 345, right: 346, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.3455, 0.2540, -0.9034] } }) +Tree 128: SplitPlaneNormal(SplitPlaneNormal { left: 152, right: 153, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.6325, 0.7077, -0.3149] } }) +Tree 129: SplitPlaneNormal(SplitPlaneNormal { left: 130, right: 131, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.3229, 0.5291, -0.7847] } }) +Tree 130: SplitPlaneNormal(SplitPlaneNormal { left: 140, right: 141, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.5718, -0.3132, 0.7583] } }) +Tree 131: SplitPlaneNormal(SplitPlaneNormal { left: 137, right: 134, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.0720, -0.5319, 0.8437] } }) +Tree 134: SplitPlaneNormal(SplitPlaneNormal { left: 487, right: 488, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.4324, -0.7417, -0.5127] } }) +Tree 137: SplitPlaneNormal(SplitPlaneNormal { left: 138, right: 139, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.2183, 0.8233, 0.5240] } }) +Tree 138: Descendants(Descendants { descendants: [5, 27, 77] }) +Tree 139: SplitPlaneNormal(SplitPlaneNormal { left: 467, right: 468, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.2398, -0.8384, 0.4896] } }) +Tree 140: SplitPlaneNormal(SplitPlaneNormal { left: 461, right: 462, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.5080, 0.7989, 0.3219] } }) +Tree 141: SplitPlaneNormal(SplitPlaneNormal { left: 142, right: 143, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.1645, -0.9636, 0.2109] } }) +Tree 142: Descendants(Descendants { descendants: [10, 87] }) +Tree 143: SplitPlaneNormal(SplitPlaneNormal { left: 144, right: 145, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.0415, 0.9886, -0.1449] } }) +Tree 144: SplitPlaneNormal(SplitPlaneNormal { left: 459, right: 460, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.6675, -0.1477, 0.7298] } }) +Tree 145: Descendants(Descendants { descendants: [38, 93, 133] }) +Tree 152: SplitPlaneNormal(SplitPlaneNormal { left: 166, right: 167, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.1407, 0.7156, -0.6842] } }) +Tree 153: SplitPlaneNormal(SplitPlaneNormal { left: 160, right: 159, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.5494, -0.1561, -0.8208] } }) +Tree 159: SplitPlaneNormal(SplitPlaneNormal { left: 429, right: 430, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.6129, 0.5604, -0.5571] } }) +Tree 160: SplitPlaneNormal(SplitPlaneNormal { left: 419, right: 420, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6269, -0.5350, 0.5664] } }) +Tree 166: SplitPlaneNormal(SplitPlaneNormal { left: 178, right: 180, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.6048, -0.0853, 0.7918] } }) +Tree 167: SplitPlaneNormal(SplitPlaneNormal { left: 168, right: 169, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6431, -0.6135, -0.4582] } }) +Tree 168: SplitPlaneNormal(SplitPlaneNormal { left: 170, right: 171, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6919, -0.1450, -0.7073] } }) +Tree 169: SplitPlaneNormal(SplitPlaneNormal { left: 399, right: 400, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.1544, -0.4894, 0.8583] } }) +Tree 170: Descendants(Descendants { descendants: [85, 135] }) +Tree 171: SplitPlaneNormal(SplitPlaneNormal { left: 172, right: 173, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.4012, 0.1846, -0.8972] } }) +Tree 172: SplitPlaneNormal(SplitPlaneNormal { left: 391, right: 392, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.0946, -0.6360, 0.7658] } }) +Tree 173: SplitPlaneNormal(SplitPlaneNormal { left: 174, right: 175, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6930, -0.7206, -0.0238] } }) +Tree 174: SplitPlaneNormal(SplitPlaneNormal { left: 385, right: 386, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.7429, -0.4517, -0.4941] } }) +Tree 175: Descendants(Descendants { descendants: [57, 69] }) +Tree 178: SplitPlaneNormal(SplitPlaneNormal { left: 371, right: 372, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6954, -0.3130, -0.6469] } }) +Tree 180: SplitPlaneNormal(SplitPlaneNormal { left: 329, right: 330, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.1684, 0.8359, -0.5224] } }) +Tree 188: SplitPlaneNormal(SplitPlaneNormal { left: 189, right: 190, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.3588, 0.9273, -0.1069] } }) +Tree 189: SplitPlaneNormal(SplitPlaneNormal { left: 287, right: 288, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.4411, -0.2194, 0.8702] } }) +Tree 190: SplitPlaneNormal(SplitPlaneNormal { left: 191, right: 192, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.4813, 0.4888, -0.7276] } }) +Tree 191: SplitPlaneNormal(SplitPlaneNormal { left: 193, right: 194, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.1905, 0.8307, -0.5231] } }) +Tree 192: SplitPlaneNormal(SplitPlaneNormal { left: 219, right: 220, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.5020, 0.0420, 0.8639] } }) +Tree 193: SplitPlaneNormal(SplitPlaneNormal { left: 213, right: 214, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.9237, 0.1519, -0.3517] } }) +Tree 194: SplitPlaneNormal(SplitPlaneNormal { left: 195, right: 196, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.5054, 0.6634, -0.5519] } }) +Tree 195: SplitPlaneNormal(SplitPlaneNormal { left: 197, right: 198, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.0960, 0.8217, -0.5618] } }) +Tree 196: SplitPlaneNormal(SplitPlaneNormal { left: 209, right: 210, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.4870, 0.5360, -0.6896] } }) +Tree 197: SplitPlaneNormal(SplitPlaneNormal { left: 205, right: 206, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.9733, 0.1535, 0.1707] } }) +Tree 198: SplitPlaneNormal(SplitPlaneNormal { left: 199, right: 200, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.9474, -0.2820, -0.1513] } }) +Tree 199: SplitPlaneNormal(SplitPlaneNormal { left: 201, right: 202, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.9048, -0.1897, 0.3813] } }) +Tree 200: SplitPlaneNormal(SplitPlaneNormal { left: 203, right: 204, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.1717, -0.7823, 0.5988] } }) +Tree 201: Descendants(Descendants { descendants: [8, 106, 130] }) +Tree 202: Descendants(Descendants { descendants: [22, 134] }) +Tree 203: Descendants(Descendants { descendants: [137] }) +Tree 204: Descendants(Descendants { descendants: [26, 56, 121] }) +Tree 205: Descendants(Descendants { descendants: [58, 79] }) +Tree 206: SplitPlaneNormal(SplitPlaneNormal { left: 207, right: 208, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6205, 0.5886, -0.5183] } }) +Tree 207: Descendants(Descendants { descendants: [3, 24, 76] }) +Tree 208: Descendants(Descendants { descendants: [149] }) +Tree 209: SplitPlaneNormal(SplitPlaneNormal { left: 211, right: 212, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.9497, 0.1519, -0.2738] } }) +Tree 210: Descendants(Descendants { descendants: [104] }) +Tree 211: Descendants(Descendants { descendants: [40, 103] }) +Tree 212: Descendants(Descendants { descendants: [14, 136] }) +Tree 213: SplitPlaneNormal(SplitPlaneNormal { left: 217, right: 218, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.4724, 0.8516, -0.2274] } }) +Tree 214: SplitPlaneNormal(SplitPlaneNormal { left: 215, right: 216, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.4389, -0.7273, 0.5277] } }) +Tree 215: Descendants(Descendants { descendants: [7, 28] }) +Tree 216: Descendants(Descendants { descendants: [53, 127] }) +Tree 217: Descendants(Descendants { descendants: [55, 82, 148] }) +Tree 218: Descendants(Descendants { descendants: [43, 68] }) +Tree 219: SplitPlaneNormal(SplitPlaneNormal { left: 221, right: 222, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6571, -0.7532, 0.0308] } }) +Tree 220: SplitPlaneNormal(SplitPlaneNormal { left: 243, right: 244, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6584, -0.4453, 0.6068] } }) +Tree 221: SplitPlaneNormal(SplitPlaneNormal { left: 233, right: 234, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.8660, 0.4999, -0.0087] } }) +Tree 222: SplitPlaneNormal(SplitPlaneNormal { left: 223, right: 224, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.1999, -0.0850, -0.9761] } }) +Tree 223: SplitPlaneNormal(SplitPlaneNormal { left: 225, right: 226, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.0333, -0.5051, 0.8624] } }) +Tree 224: Descendants(Descendants { descendants: [19, 61] }) +Tree 225: SplitPlaneNormal(SplitPlaneNormal { left: 231, right: 232, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.2287, 0.0044, 0.9735] } }) +Tree 226: SplitPlaneNormal(SplitPlaneNormal { left: 227, right: 228, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.5883, 0.7959, 0.1430] } }) +Tree 227: SplitPlaneNormal(SplitPlaneNormal { left: 229, right: 230, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.2436, -0.1970, 0.9497] } }) +Tree 228: Descendants(Descendants { descendants: [57] }) +Tree 229: Descendants(Descendants { descendants: [34, 90] }) +Tree 230: Descendants(Descendants { descendants: [113, 125] }) +Tree 231: Descendants(Descendants { descendants: [101, 141] }) +Tree 232: Descendants(Descendants { descendants: [1, 81] }) +Tree 233: SplitPlaneNormal(SplitPlaneNormal { left: 235, right: 236, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.3358, -0.0493, -0.9406] } }) +Tree 234: Descendants(Descendants { descendants: [6] }) +Tree 235: SplitPlaneNormal(SplitPlaneNormal { left: 237, right: 238, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6166, -0.6852, 0.3878] } }) +Tree 236: SplitPlaneNormal(SplitPlaneNormal { left: 239, right: 240, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.7724, 0.5675, 0.2853] } }) +Tree 237: Descendants(Descendants { descendants: [117, 128] }) +Tree 238: Descendants(Descendants { descendants: [45, 71] }) +Tree 239: SplitPlaneNormal(SplitPlaneNormal { left: 241, right: 242, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.3038, -0.3798, 0.8738] } }) +Tree 240: Descendants(Descendants { descendants: [65] }) +Tree 241: Descendants(Descendants { descendants: [36, 97] }) +Tree 242: Descendants(Descendants { descendants: [30, 124, 143] }) +Tree 243: SplitPlaneNormal(SplitPlaneNormal { left: 245, right: 246, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.4678, -0.2194, 0.8562] } }) +Tree 244: SplitPlaneNormal(SplitPlaneNormal { left: 251, right: 252, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.1438, 0.4183, -0.8968] } }) +Tree 245: SplitPlaneNormal(SplitPlaneNormal { left: 249, right: 250, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.8382, 0.2362, -0.4916] } }) +Tree 246: SplitPlaneNormal(SplitPlaneNormal { left: 247, right: 248, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.8161, -0.1328, 0.5625] } }) +Tree 247: Descendants(Descendants { descendants: [83, 84, 116] }) +Tree 248: Descendants(Descendants { descendants: [50] }) +Tree 249: Descendants(Descendants { descendants: [72, 74, 92] }) +Tree 250: Descendants(Descendants { descendants: [12, 105] }) +Tree 251: SplitPlaneNormal(SplitPlaneNormal { left: 253, right: 254, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.2413, -0.5591, 0.7932] } }) +Tree 252: SplitPlaneNormal(SplitPlaneNormal { left: 283, right: 284, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.8495, 0.5177, -0.1022] } }) +Tree 253: SplitPlaneNormal(SplitPlaneNormal { left: 261, right: 262, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.8814, -0.4628, -0.0949] } }) +Tree 254: SplitPlaneNormal(SplitPlaneNormal { left: 255, right: 256, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.7387, 0.6726, 0.0441] } }) +Tree 255: SplitPlaneNormal(SplitPlaneNormal { left: 257, right: 258, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.3479, 0.8960, -0.2758] } }) +Tree 256: Descendants(Descendants { descendants: [0, 91, 119] }) +Tree 257: SplitPlaneNormal(SplitPlaneNormal { left: 259, right: 260, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6173, 0.1505, -0.7722] } }) +Tree 258: Descendants(Descendants { descendants: [9, 48, 70] }) +Tree 259: Descendants(Descendants { descendants: [20, 29, 98] }) +Tree 260: Descendants(Descendants { descendants: [4, 54, 59] }) +Tree 261: SplitPlaneNormal(SplitPlaneNormal { left: 279, right: 280, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.9326, 0.3602, -0.0232] } }) +Tree 262: SplitPlaneNormal(SplitPlaneNormal { left: 263, right: 264, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.7109, -0.1362, -0.6900] } }) +Tree 263: Descendants(Descendants { descendants: [44, 85] }) +Tree 264: SplitPlaneNormal(SplitPlaneNormal { left: 265, right: 266, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.6672, 0.7372, 0.1067] } }) +Tree 265: SplitPlaneNormal(SplitPlaneNormal { left: 275, right: 276, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.3336, -0.8868, 0.3197] } }) +Tree 266: SplitPlaneNormal(SplitPlaneNormal { left: 267, right: 268, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.1407, 0.6579, -0.7399] } }) +Tree 267: SplitPlaneNormal(SplitPlaneNormal { left: 269, right: 270, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.4655, 0.1595, -0.8706] } }) +Tree 268: Descendants(Descendants { descendants: [114, 126] }) +Tree 269: SplitPlaneNormal(SplitPlaneNormal { left: 271, right: 272, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.5039, 0.7948, -0.3383] } }) +Tree 270: Descendants(Descendants { descendants: [33] }) +Tree 271: Descendants(Descendants { descendants: [21, 39] }) +Tree 272: SplitPlaneNormal(SplitPlaneNormal { left: 273, right: 274, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.1299, 0.5124, -0.8489] } }) +Tree 273: Descendants(Descendants { descendants: [99, 123, 135] }) +Tree 274: Descendants(Descendants { descendants: [66, 142] }) +Tree 275: SplitPlaneNormal(SplitPlaneNormal { left: 277, right: 278, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.4732, -0.8507, 0.2291] } }) +Tree 276: Descendants(Descendants { descendants: [138] }) +Tree 277: Descendants(Descendants { descendants: [69, 100, 145] }) +Tree 278: Descendants(Descendants { descendants: [118] }) +Tree 279: SplitPlaneNormal(SplitPlaneNormal { left: 281, right: 282, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.7038, 0.1428, -0.6959] } }) +Tree 280: Descendants(Descendants { descendants: [25, 139, 146] }) +Tree 281: Descendants(Descendants { descendants: [49, 111] }) +Tree 282: Descendants(Descendants { descendants: [13, 52] }) +Tree 283: SplitPlaneNormal(SplitPlaneNormal { left: 285, right: 286, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.7841, 0.6195, -0.0365] } }) +Tree 284: Descendants(Descendants { descendants: [23, 41, 140] }) +Tree 285: Descendants(Descendants { descendants: [31, 112] }) +Tree 286: Descendants(Descendants { descendants: [78, 96] }) +Tree 287: SplitPlaneNormal(SplitPlaneNormal { left: 289, right: 290, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.1124, 0.6347, -0.7645] } }) +Tree 288: SplitPlaneNormal(SplitPlaneNormal { left: 303, right: 304, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.8003, 0.2595, -0.5406] } }) +Tree 289: SplitPlaneNormal(SplitPlaneNormal { left: 299, right: 300, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.3454, 0.6185, 0.7058] } }) +Tree 290: SplitPlaneNormal(SplitPlaneNormal { left: 291, right: 292, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.3311, -0.5678, -0.7536] } }) +Tree 291: Descendants(Descendants { descendants: [15, 42] }) +Tree 292: SplitPlaneNormal(SplitPlaneNormal { left: 293, right: 294, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.2595, -0.9487, -0.1805] } }) +Tree 293: SplitPlaneNormal(SplitPlaneNormal { left: 297, right: 298, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.2025, -0.8428, 0.4986] } }) +Tree 294: SplitPlaneNormal(SplitPlaneNormal { left: 295, right: 296, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.1648, -0.9419, -0.2926] } }) +Tree 295: Descendants(Descendants { descendants: [27, 132, 144] }) +Tree 296: Descendants(Descendants { descendants: [5, 77] }) +Tree 297: Descendants(Descendants { descendants: [17, 60] }) +Tree 298: Descendants(Descendants { descendants: [18, 47, 86] }) +Tree 299: SplitPlaneNormal(SplitPlaneNormal { left: 301, right: 302, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.2957, -0.4370, 0.8495] } }) +Tree 300: Descendants(Descendants { descendants: [64, 110, 122] }) +Tree 301: Descendants(Descendants { descendants: [108, 131] }) +Tree 302: Descendants(Descendants { descendants: [11, 80] }) +Tree 303: SplitPlaneNormal(SplitPlaneNormal { left: 305, right: 306, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.8935, 0.2904, 0.3426] } }) +Tree 304: SplitPlaneNormal(SplitPlaneNormal { left: 309, right: 310, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.4390, -0.8720, -0.2164] } }) +Tree 305: SplitPlaneNormal(SplitPlaneNormal { left: 307, right: 308, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.5735, 0.7820, 0.2440] } }) +Tree 306: Descendants(Descendants { descendants: [37, 109, 147] }) +Tree 307: Descendants(Descendants { descendants: [73, 95] }) +Tree 308: Descendants(Descendants { descendants: [51, 62] }) +Tree 309: SplitPlaneNormal(SplitPlaneNormal { left: 321, right: 322, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.4056, -0.6411, 0.6515] } }) +Tree 310: SplitPlaneNormal(SplitPlaneNormal { left: 311, right: 312, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.3626, 0.7425, -0.5632] } }) +Tree 311: SplitPlaneNormal(SplitPlaneNormal { left: 313, right: 314, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6511, -0.3522, -0.6723] } }) +Tree 312: SplitPlaneNormal(SplitPlaneNormal { left: 317, right: 318, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.4850, -0.5652, -0.6674] } }) +Tree 313: Descendants(Descendants { descendants: [67] }) +Tree 314: SplitPlaneNormal(SplitPlaneNormal { left: 315, right: 316, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.5180, 0.6032, -0.6065] } }) +Tree 315: Descendants(Descendants { descendants: [32, 35] }) +Tree 316: Descendants(Descendants { descendants: [88, 89] }) +Tree 317: SplitPlaneNormal(SplitPlaneNormal { left: 319, right: 320, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.4502, -0.5103, 0.7327] } }) +Tree 318: Descendants(Descendants { descendants: [115] }) +Tree 319: Descendants(Descendants { descendants: [46, 75] }) +Tree 320: Descendants(Descendants { descendants: [38, 120] }) +Tree 321: SplitPlaneNormal(SplitPlaneNormal { left: 325, right: 326, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6008, 0.1985, -0.7743] } }) +Tree 322: SplitPlaneNormal(SplitPlaneNormal { left: 323, right: 324, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6741, 0.3535, -0.6486] } }) +Tree 323: Descendants(Descendants { descendants: [102, 129] }) +Tree 324: Descendants(Descendants { descendants: [16, 93, 133] }) +Tree 325: SplitPlaneNormal(SplitPlaneNormal { left: 327, right: 328, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.2242, -0.7741, 0.5920] } }) +Tree 326: Descendants(Descendants { descendants: [63, 94] }) +Tree 327: Descendants(Descendants { descendants: [2, 87, 107] }) +Tree 328: Descendants(Descendants { descendants: [10] }) +Tree 329: SplitPlaneNormal(SplitPlaneNormal { left: 331, right: 332, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.5918, -0.8057, -0.0251] } }) +Tree 330: Descendants(Descendants { descendants: [44, 48, 70] }) +Tree 331: Descendants(Descendants { descendants: [9] }) +Tree 332: SplitPlaneNormal(SplitPlaneNormal { left: 333, right: 334, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.7703, -0.3282, -0.5468] } }) +Tree 333: Descendants(Descendants { descendants: [29] }) +Tree 334: Descendants(Descendants { descendants: [20, 54, 98] }) +Tree 335: SplitPlaneNormal(SplitPlaneNormal { left: 337, right: 338, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.2529, -0.0839, -0.9638] } }) +Tree 336: Descendants(Descendants { descendants: [65] }) +Tree 337: Descendants(Descendants { descendants: [30] }) +Tree 338: SplitPlaneNormal(SplitPlaneNormal { left: 339, right: 340, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.6012, 0.4896, 0.6315] } }) +Tree 339: Descendants(Descendants { descendants: [36, 143] }) +Tree 340: Descendants(Descendants { descendants: [97, 124] }) +Tree 341: Descendants(Descendants { descendants: [0, 52, 85] }) +Tree 342: SplitPlaneNormal(SplitPlaneNormal { left: 343, right: 344, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.7599, -0.6195, 0.1971] } }) +Tree 343: Descendants(Descendants { descendants: [96, 117] }) +Tree 344: Descendants(Descendants { descendants: [31, 78, 128] }) +Tree 345: SplitPlaneNormal(SplitPlaneNormal { left: 347, right: 348, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.7789, 0.1483, -0.6094] } }) +Tree 346: Descendants(Descendants { descendants: [105] }) +Tree 347: Descendants(Descendants { descendants: [25, 50] }) +Tree 348: SplitPlaneNormal(SplitPlaneNormal { left: 349, right: 350, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.2266, 0.3561, -0.9066] } }) +Tree 349: SplitPlaneNormal(SplitPlaneNormal { left: 351, right: 352, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.0382, 0.4334, -0.9004] } }) +Tree 350: Descendants(Descendants { descendants: [74] }) +Tree 351: Descendants(Descendants { descendants: [139] }) +Tree 352: Descendants(Descendants { descendants: [83, 84, 116] }) +Tree 353: SplitPlaneNormal(SplitPlaneNormal { left: 359, right: 360, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.7709, -0.3440, 0.5361] } }) +Tree 354: SplitPlaneNormal(SplitPlaneNormal { left: 355, right: 356, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.1993, 0.6683, -0.7167] } }) +Tree 355: SplitPlaneNormal(SplitPlaneNormal { left: 357, right: 358, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.2637, -0.7109, 0.6520] } }) +Tree 356: Descendants(Descendants { descendants: [49, 111, 137] }) +Tree 357: Descendants(Descendants { descendants: [56, 106, 130] }) +Tree 358: Descendants(Descendants { descendants: [3, 8, 149] }) +Tree 359: Descendants(Descendants { descendants: [14, 104, 146] }) +Tree 360: SplitPlaneNormal(SplitPlaneNormal { left: 361, right: 362, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.8255, -0.4591, 0.3283] } }) +Tree 361: Descendants(Descendants { descendants: [40, 103, 136] }) +Tree 362: Descendants(Descendants { descendants: [22, 134] }) +Tree 363: SplitPlaneNormal(SplitPlaneNormal { left: 365, right: 366, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.0431, -0.9825, 0.1814] } }) +Tree 364: SplitPlaneNormal(SplitPlaneNormal { left: 369, right: 370, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.5787, 0.6873, -0.4390] } }) +Tree 365: SplitPlaneNormal(SplitPlaneNormal { left: 367, right: 368, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.6171, 0.7767, -0.1258] } }) +Tree 366: Descendants(Descendants { descendants: [109, 147] }) +Tree 367: Descendants(Descendants { descendants: [55, 82, 148] }) +Tree 368: Descendants(Descendants { descendants: [43] }) +Tree 369: Descendants(Descendants { descendants: [68] }) +Tree 370: Descendants(Descendants { descendants: [24, 76, 79] }) +Tree 371: SplitPlaneNormal(SplitPlaneNormal { left: 373, right: 374, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.3818, 0.8672, -0.3198] } }) +Tree 372: Descendants(Descendants { descendants: [100, 118, 145] }) +Tree 373: Descendants(Descendants { descendants: [4, 59] }) +Tree 374: Descendants(Descendants { descendants: [21, 39] }) +Tree 375: Descendants(Descendants { descendants: [6, 12, 105] }) +Tree 376: SplitPlaneNormal(SplitPlaneNormal { left: 377, right: 378, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.8947, -0.0131, 0.4465] } }) +Tree 377: SplitPlaneNormal(SplitPlaneNormal { left: 379, right: 380, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.7897, 0.0893, 0.6069] } }) +Tree 378: Descendants(Descendants { descendants: [50] }) +Tree 379: Descendants(Descendants { descendants: [72] }) +Tree 380: SplitPlaneNormal(SplitPlaneNormal { left: 381, right: 382, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.3953, 0.2039, -0.8956] } }) +Tree 381: SplitPlaneNormal(SplitPlaneNormal { left: 383, right: 384, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.2688, -0.4681, 0.8418] } }) +Tree 382: Descendants(Descendants { descendants: [41, 74, 92] }) +Tree 383: Descendants(Descendants { descendants: [83, 84, 116] }) +Tree 384: Descendants(Descendants { descendants: [139] }) +Tree 385: Descendants(Descendants { descendants: [31, 112] }) +Tree 386: Descendants(Descendants { descendants: [45, 71] }) +Tree 387: Descendants(Descendants { descendants: [51, 62] }) +Tree 388: Descendants(Descendants { descendants: [73, 95, 102] }) +Tree 389: Descendants(Descendants { descendants: [53, 127] }) +Tree 390: Descendants(Descendants { descendants: [16, 129] }) +Tree 391: Descendants(Descendants { descendants: [33, 114, 126] }) +Tree 392: SplitPlaneNormal(SplitPlaneNormal { left: 393, right: 394, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.1930, -0.7028, 0.6847] } }) +Tree 393: Descendants(Descendants { descendants: [66] }) +Tree 394: Descendants(Descendants { descendants: [99, 123, 142] }) +Tree 395: Descendants(Descendants { descendants: [60, 61] }) +Tree 396: SplitPlaneNormal(SplitPlaneNormal { left: 397, right: 398, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.2317, -0.3972, -0.8880] } }) +Tree 397: Descendants(Descendants { descendants: [18, 47, 86] }) +Tree 398: Descendants(Descendants { descendants: [17, 132] }) +Tree 399: Descendants(Descendants { descendants: [19, 141] }) +Tree 400: SplitPlaneNormal(SplitPlaneNormal { left: 401, right: 402, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.0266, 0.3570, -0.9337] } }) +Tree 401: Descendants(Descendants { descendants: [1, 34] }) +Tree 402: Descendants(Descendants { descendants: [81, 101] }) +Tree 403: Descendants(Descendants { descendants: [5, 77] }) +Tree 404: Descendants(Descendants { descendants: [27, 144] }) +Tree 405: Descendants(Descendants { descendants: [57] }) +Tree 406: Descendants(Descendants { descendants: [69, 100, 145] }) +Tree 407: SplitPlaneNormal(SplitPlaneNormal { left: 409, right: 410, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.3772, 0.5230, -0.7644] } }) +Tree 408: Descendants(Descendants { descendants: [7, 28, 58] }) +Tree 409: Descendants(Descendants { descendants: [26, 121] }) +Tree 410: SplitPlaneNormal(SplitPlaneNormal { left: 411, right: 412, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.7612, -0.6355, 0.1293] } }) +Tree 411: Descendants(Descendants { descendants: [52, 91] }) +Tree 412: Descendants(Descendants { descendants: [0, 119] }) +Tree 413: Descendants(Descendants { descendants: [112] }) +Tree 414: SplitPlaneNormal(SplitPlaneNormal { left: 415, right: 416, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.1601, 0.6635, -0.7308] } }) +Tree 415: SplitPlaneNormal(SplitPlaneNormal { left: 417, right: 418, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.0057, 0.5858, -0.8104] } }) +Tree 416: Descendants(Descendants { descendants: [114, 126] }) +Tree 417: Descendants(Descendants { descendants: [99, 142] }) +Tree 418: Descendants(Descendants { descendants: [33, 66] }) +Tree 419: SplitPlaneNormal(SplitPlaneNormal { left: 421, right: 422, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.8259, 0.2847, -0.4867] } }) +Tree 420: SplitPlaneNormal(SplitPlaneNormal { left: 425, right: 426, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.5278, -0.0750, 0.8460] } }) +Tree 421: SplitPlaneNormal(SplitPlaneNormal { left: 423, right: 424, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.7425, -0.1049, -0.6616] } }) +Tree 422: Descendants(Descendants { descendants: [6, 12] }) +Tree 423: Descendants(Descendants { descendants: [41, 92] }) +Tree 424: Descendants(Descendants { descendants: [72, 140] }) +Tree 425: SplitPlaneNormal(SplitPlaneNormal { left: 427, right: 428, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.4267, 0.0742, -0.9014] } }) +Tree 426: Descendants(Descendants { descendants: [13, 23] }) +Tree 427: Descendants(Descendants { descendants: [78, 96] }) +Tree 428: Descendants(Descendants { descendants: [117, 128] }) +Tree 429: SplitPlaneNormal(SplitPlaneNormal { left: 431, right: 432, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.2489, -0.0813, -0.9651] } }) +Tree 430: Descendants(Descendants { descendants: [65, 97] }) +Tree 431: Descendants(Descendants { descendants: [30] }) +Tree 432: Descendants(Descendants { descendants: [36, 124, 143] }) +Tree 433: Descendants(Descendants { descendants: [15, 42, 110] }) +Tree 434: SplitPlaneNormal(SplitPlaneNormal { left: 435, right: 436, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.3958, -0.0632, -0.9161] } }) +Tree 435: Descendants(Descendants { descendants: [113, 125] }) +Tree 436: SplitPlaneNormal(SplitPlaneNormal { left: 437, right: 438, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.1763, -0.5962, 0.7833] } }) +Tree 437: Descendants(Descendants { descendants: [101, 141] }) +Tree 438: Descendants(Descendants { descendants: [1, 34, 90] }) +Tree 439: Descendants(Descendants { descendants: [62, 73, 95] }) +Tree 440: Descendants(Descendants { descendants: [102, 129] }) +Tree 441: Descendants(Descendants { descendants: [127] }) +Tree 442: Descendants(Descendants { descendants: [7, 28, 53] }) +Tree 443: Descendants(Descendants { descendants: [16, 133] }) +Tree 444: SplitPlaneNormal(SplitPlaneNormal { left: 445, right: 446, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.5886, -0.4567, 0.6670] } }) +Tree 445: Descendants(Descendants { descendants: [88, 89] }) +Tree 446: Descendants(Descendants { descendants: [32, 35, 67] }) +Tree 447: SplitPlaneNormal(SplitPlaneNormal { left: 449, right: 450, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.5735, -0.2849, 0.7681] } }) +Tree 448: Descendants(Descendants { descendants: [38, 93] }) +Tree 449: Descendants(Descendants { descendants: [63, 94] }) +Tree 450: SplitPlaneNormal(SplitPlaneNormal { left: 451, right: 452, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.3672, 0.6352, -0.6795] } }) +Tree 451: Descendants(Descendants { descendants: [10] }) +Tree 452: Descendants(Descendants { descendants: [2, 87, 107] }) +Tree 453: Descendants(Descendants { descendants: [11, 80, 115] }) +Tree 454: SplitPlaneNormal(SplitPlaneNormal { left: 455, right: 456, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.3017, -0.7158, -0.6297] } }) +Tree 455: Descendants(Descendants { descendants: [64, 122] }) +Tree 456: Descendants(Descendants { descendants: [108, 131] }) +Tree 457: Descendants(Descendants { descendants: [29] }) +Tree 458: Descendants(Descendants { descendants: [20, 54, 98] }) +Tree 459: Descendants(Descendants { descendants: [88, 89] }) +Tree 460: Descendants(Descendants { descendants: [32, 35, 67] }) +Tree 461: SplitPlaneNormal(SplitPlaneNormal { left: 465, right: 466, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.4980, 0.3895, 0.7748] } }) +Tree 462: SplitPlaneNormal(SplitPlaneNormal { left: 463, right: 464, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.5404, -0.3224, 0.7772] } }) +Tree 463: Descendants(Descendants { descendants: [63, 94] }) +Tree 464: Descendants(Descendants { descendants: [2, 107] }) +Tree 465: Descendants(Descendants { descendants: [11, 80, 115] }) +Tree 466: Descendants(Descendants { descendants: [46, 75, 120] }) +Tree 467: Descendants(Descendants { descendants: [60, 61, 90] }) +Tree 468: SplitPlaneNormal(SplitPlaneNormal { left: 469, right: 470, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.1229, -0.8266, 0.5493] } }) +Tree 469: SplitPlaneNormal(SplitPlaneNormal { left: 471, right: 472, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.3011, 0.4124, 0.8598] } }) +Tree 470: Descendants(Descendants { descendants: [47, 132, 144] }) +Tree 471: Descendants(Descendants { descendants: [17, 18, 86] }) +Tree 472: Descendants(Descendants { descendants: [42] }) +Tree 473: SplitPlaneNormal(SplitPlaneNormal { left: 477, right: 478, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.5029, -0.8060, 0.3122] } }) +Tree 474: SplitPlaneNormal(SplitPlaneNormal { left: 475, right: 476, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.7305, 0.6762, 0.0959] } }) +Tree 475: Descendants(Descendants { descendants: [9, 48] }) +Tree 476: Descendants(Descendants { descendants: [70, 119] }) +Tree 477: Descendants(Descendants { descendants: [44, 123, 135] }) +Tree 478: Descendants(Descendants { descendants: [21, 39] }) +Tree 479: SplitPlaneNormal(SplitPlaneNormal { left: 481, right: 482, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.8517, 0.2846, -0.4400] } }) +Tree 480: SplitPlaneNormal(SplitPlaneNormal { left: 483, right: 484, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.5694, -0.6826, 0.4581] } }) +Tree 481: Descendants(Descendants { descendants: [40, 103, 136] }) +Tree 482: Descendants(Descendants { descendants: [14, 25, 104] }) +Tree 483: Descendants(Descendants { descendants: [111, 146] }) +Tree 484: SplitPlaneNormal(SplitPlaneNormal { left: 485, right: 486, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.9397, 0.3209, 0.1184] } }) +Tree 485: Descendants(Descendants { descendants: [26, 121, 137] }) +Tree 486: Descendants(Descendants { descendants: [106, 130] }) +Tree 487: Descendants(Descendants { descendants: [113, 125, 138] }) +Tree 488: SplitPlaneNormal(SplitPlaneNormal { left: 489, right: 490, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.2350, -0.9386, -0.2527] } }) +Tree 489: SplitPlaneNormal(SplitPlaneNormal { left: 491, right: 492, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.1033, 0.9496, -0.2960] } }) +Tree 490: Descendants(Descendants { descendants: [108, 131] }) +Tree 491: Descendants(Descendants { descendants: [64, 122] }) +Tree 492: Descendants(Descendants { descendants: [15, 110] }) +Tree 493: SplitPlaneNormal(SplitPlaneNormal { left: 501, right: 502, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.4123, -0.8800, 0.2359] } }) +Tree 494: SplitPlaneNormal(SplitPlaneNormal { left: 495, right: 496, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.9377, -0.3459, 0.0330] } }) +Tree 495: SplitPlaneNormal(SplitPlaneNormal { left: 497, right: 498, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6086, -0.6856, 0.3994] } }) +Tree 496: SplitPlaneNormal(SplitPlaneNormal { left: 499, right: 500, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.0393, -0.8199, 0.5712] } }) +Tree 497: Descendants(Descendants { descendants: [22, 134] }) +Tree 498: Descendants(Descendants { descendants: [3, 24, 76] }) +Tree 499: Descendants(Descendants { descendants: [8, 56] }) +Tree 500: Descendants(Descendants { descendants: [58, 79, 149] }) +Tree 501: Descendants(Descendants { descendants: [43, 68] }) +Tree 502: Descendants(Descendants { descendants: [82, 148] }) +Item 0: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9249" }, vector: [0.4079, 0.5972, 0.5766] }) +Item 1: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0443" }, vector: [0.8606, 0.5280, 0.2667] }) +Item 2: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9610" }, vector: [0.6739, 0.2985, 0.6167] }) +Item 3: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.5378" }, vector: [0.0479, 0.2927, 0.4487] }) +Item 4: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.6832" }, vector: [0.4834, 0.2818, 0.3920] }) +Item 5: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7470" }, vector: [0.7418, 0.0595, 0.0652] }) +Item 6: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0038" }, vector: [0.2409, 0.9702, 0.0911] }) +Item 7: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.4776" }, vector: [0.2155, 0.1841, 0.3845] }) +Item 8: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1446" }, vector: [0.2453, 0.6558, 0.9055] }) +Item 9: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.5567" }, vector: [0.9152, 0.7847, 0.9849] }) +Item 10: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0765" }, vector: [0.7360, 0.3131, 0.7204] }) +Item 11: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9246" }, vector: [0.8414, 0.0192, 0.3828] }) +Item 12: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7468" }, vector: [0.0299, 0.7458, 0.0238] }) +Item 13: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1116" }, vector: [0.4624, 0.8739, 0.5080] }) +Item 14: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9879" }, vector: [0.1737, 0.7046, 0.6704] }) +Item 15: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.6977" }, vector: [0.6341, 0.1904, 0.2201] }) +Item 16: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.3220" }, vector: [0.8351, 0.2749, 0.9873] }) +Item 17: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.6904" }, vector: [0.6554, 0.2088, 0.0586] }) +Item 18: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8414" }, vector: [0.7914, 0.2447, 0.1475] }) +Item 19: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.2199" }, vector: [0.9246, 0.7944, 0.0473] }) +Item 20: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1741" }, vector: [0.7740, 0.4535, 0.7574] }) +Item 21: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8493" }, vector: [0.5344, 0.4903, 0.4420] }) +Item 22: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8526" }, vector: [0.0332, 0.5334, 0.6643] }) +Item 23: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7987" }, vector: [0.3315, 0.6684, 0.2849] }) +Item 24: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8138" }, vector: [0.1125, 0.4113, 0.6932] }) +Item 25: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9546" }, vector: [0.1173, 0.7807, 0.5366] }) +Item 26: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1688" }, vector: [0.4522, 0.7108, 0.8101] }) +Item 27: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.3820" }, vector: [0.3727, 0.0552, 0.0634] }) +Item 28: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9284" }, vector: [0.4659, 0.3048, 0.7430] }) +Item 29: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.4602" }, vector: [0.8893, 0.6025, 0.9890] }) +Item 30: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.2877" }, vector: [0.8442, 0.9418, 0.2419] }) +Item 31: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7464" }, vector: [0.4568, 0.5250, 0.2701] }) +Item 32: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0318" }, vector: [0.7590, 0.0127, 0.6989] }) +Item 33: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.3377" }, vector: [0.8759, 0.8323, 0.5742] }) +Item 34: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9270" }, vector: [0.7743, 0.4338, 0.2675] }) +Item 35: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8325" }, vector: [0.6038, 0.0168, 0.5729] }) +Item 36: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.3546" }, vector: [0.9357, 0.9794, 0.0114] }) +Item 37: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9081" }, vector: [0.2978, 0.0910, 0.8530] }) +Item 38: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1584" }, vector: [0.8744, 0.1726, 0.7399] }) +Item 39: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7896" }, vector: [0.5211, 0.4583, 0.3767] }) +Item 40: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.2339" }, vector: [0.0271, 0.8721, 0.8725] }) +Item 41: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9873" }, vector: [0.3022, 0.8817, 0.3255] }) +Item 42: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.4438" }, vector: [0.4023, 0.1558, 0.1044] }) +Item 43: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.6672" }, vector: [0.0860, 0.2202, 0.6240] }) +Item 44: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.3497" }, vector: [0.2096, 0.2081, 0.1872] }) +Item 45: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.2019" }, vector: [0.8040, 0.7845, 0.4275] }) +Item 46: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.6738" }, vector: [0.5438, 0.1299, 0.3760] }) +Item 47: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7506" }, vector: [0.7083, 0.1976, 0.1506] }) +Item 48: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1406" }, vector: [0.7304, 0.5688, 0.6662] }) +Item 49: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1160" }, vector: [0.3805, 0.8072, 0.6701] }) +Item 50: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9121" }, vector: [0.0684, 0.8029, 0.4273] }) +Item 51: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8113" }, vector: [0.3427, 0.1293, 0.7240] }) +Item 52: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.2950" }, vector: [0.5500, 0.9148, 0.7332] }) +Item 53: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8488" }, vector: [0.4014, 0.2562, 0.7026] }) +Item 54: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.3913" }, vector: [0.9506, 0.5606, 0.8472] }) +Item 55: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8270" }, vector: [0.1645, 0.1968, 0.7862] }) +Item 56: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.3288" }, vector: [0.4429, 0.7944, 0.9688] }) +Item 57: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8996" }, vector: [0.6386, 0.5482, 0.3175] }) +Item 58: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9797" }, vector: [0.3389, 0.4818, 0.7828] }) +Item 59: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7839" }, vector: [0.5580, 0.3213, 0.4471] }) +Item 60: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7833" }, vector: [0.7237, 0.2860, 0.0901] }) +Item 61: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0168" }, vector: [0.9176, 0.4249, 0.1069] }) +Item 62: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8952" }, vector: [0.4310, 0.0837, 0.7802] }) +Item 63: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0165" }, vector: [0.7313, 0.3394, 0.6192] }) +Item 64: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9699" }, vector: [0.8863, 0.1804, 0.3504] }) +Item 65: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0281" }, vector: [0.5298, 0.8744, 0.1086] }) +Item 66: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.2347" }, vector: [0.7707, 0.7848, 0.5609] }) +Item 67: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8433" }, vector: [0.5919, 0.0467, 0.5988] }) +Item 68: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9905" }, vector: [0.0585, 0.3819, 0.9120] }) +Item 69: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.1911" }, vector: [0.1383, 0.1076, 0.0762] }) +Item 70: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.4642" }, vector: [0.8155, 0.8139, 0.9035] }) +Item 71: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.5580" }, vector: [0.3705, 0.3807, 0.1708] }) +Item 72: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7419" }, vector: [0.2916, 0.6647, 0.1535] }) +Item 73: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9156" }, vector: [0.4826, 0.0217, 0.7778] }) +Item 74: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9966" }, vector: [0.2028, 0.9424, 0.2528] }) +Item 75: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7771" }, vector: [0.6375, 0.1274, 0.4257] }) +Item 76: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8002" }, vector: [0.1006, 0.4131, 0.6779] }) +Item 77: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.2842" }, vector: [0.2800, 0.0278, 0.0397] }) +Item 78: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7925" }, vector: [0.4195, 0.6031, 0.2970] }) +Item 79: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1725" }, vector: [0.3166, 0.5944, 0.9598] }) +Item 80: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0432" }, vector: [0.9485, 0.0272, 0.4336] }) +Item 81: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9749" }, vector: [0.7733, 0.5495, 0.2244] }) +Item 82: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8740" }, vector: [0.1339, 0.2209, 0.8350] }) +Item 83: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.5051" }, vector: [0.1072, 0.4570, 0.1867] }) +Item 84: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0568" }, vector: [0.2566, 0.9481, 0.3899] }) +Item 85: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.2351" }, vector: [0.6583, 0.8015, 0.6706] }) +Item 86: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0194" }, vector: [0.9689, 0.2817, 0.1451] }) +Item 87: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.3859" }, vector: [0.9524, 0.4419, 0.9046] }) +Item 88: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.1995" }, vector: [0.1504, 0.0124, 0.1305] }) +Item 89: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.2740" }, vector: [0.9664, 0.0525, 0.8284] }) +Item 90: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0572" }, vector: [0.9029, 0.4726, 0.2814] }) +Item 91: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1088" }, vector: [0.4464, 0.7439, 0.6904] }) +Item 92: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9216" }, vector: [0.2904, 0.8287, 0.2799] }) +Item 93: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.3908" }, vector: [0.9963, 0.2933, 0.9251] }) +Item 94: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.3501" }, vector: [0.9755, 0.4346, 0.8260] }) +Item 95: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7770" }, vector: [0.4079, 0.0195, 0.6610] }) +Item 96: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0922" }, vector: [0.5369, 0.8875, 0.3421] }) +Item 97: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7225" }, vector: [0.4484, 0.5659, 0.0259] }) +Item 98: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1565" }, vector: [0.7837, 0.4348, 0.7310] }) +Item 99: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.5328" }, vector: [0.9591, 0.9487, 0.7276] }) +Item 100: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7411" }, vector: [0.5390, 0.4001, 0.3141] }) +Item 101: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9705" }, vector: [0.8369, 0.4671, 0.1519] }) +Item 102: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9412" }, vector: [0.5237, 0.1241, 0.7721] }) +Item 103: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.5568" }, vector: [0.0097, 0.3834, 0.4036] }) +Item 104: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.1946" }, vector: [0.0274, 0.1508, 0.1198] }) +Item 105: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9778" }, vector: [0.0151, 0.9768, 0.0396] }) +Item 106: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7807" }, vector: [0.1998, 0.5217, 0.5453] }) +Item 107: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8917" }, vector: [0.6266, 0.2753, 0.5716] }) +Item 108: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7514" }, vector: [0.7083, 0.0762, 0.2390] }) +Item 109: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.5511" }, vector: [0.0972, 0.0819, 0.5362] }) +Item 110: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9070" }, vector: [0.8215, 0.2263, 0.3109] }) +Item 111: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8462" }, vector: [0.2738, 0.6133, 0.5147] }) +Item 112: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.4499" }, vector: [0.9334, 0.9877, 0.5054] }) +Item 113: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0514" }, vector: [0.8811, 0.4353, 0.3735] }) +Item 114: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.2423" }, vector: [0.7596, 0.8341, 0.5202] }) +Item 115: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9094" }, vector: [0.8083, 0.0235, 0.4160] }) +Item 116: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7452" }, vector: [0.1656, 0.6664, 0.2896] }) +Item 117: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0026" }, vector: [0.5461, 0.7987, 0.2628] }) +Item 118: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0341" }, vector: [0.7858, 0.5026, 0.4464] }) +Item 119: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9175" }, vector: [0.4663, 0.5407, 0.5762] }) +Item 120: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9376" }, vector: [0.7453, 0.1027, 0.5595] }) +Item 121: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.3753" }, vector: [0.5039, 0.8272, 0.9763] }) +Item 122: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0754" }, vector: [0.9918, 0.1477, 0.3887] }) +Item 123: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.3925" }, vector: [0.8795, 0.8468, 0.6697] }) +Item 124: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1098" }, vector: [0.7647, 0.7957, 0.1173] }) +Item 125: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1476" }, vector: [0.9591, 0.4926, 0.3932] }) +Item 126: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9134" }, vector: [0.5712, 0.5981, 0.3877] }) +Item 127: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9111" }, vector: [0.3695, 0.2631, 0.7901] }) +Item 128: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1932" }, vector: [0.6963, 0.9067, 0.3417] }) +Item 129: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9262" }, vector: [0.5209, 0.1390, 0.7531] }) +Item 130: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.3670" }, vector: [0.3249, 0.8754, 0.9984] }) +Item 131: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7638" }, vector: [0.7362, 0.0281, 0.2016] }) +Item 132: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9733" }, vector: [0.9443, 0.1989, 0.1268] }) +Item 133: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1471" }, vector: [0.7461, 0.2756, 0.8266] }) +Item 134: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8314" }, vector: [0.0999, 0.5222, 0.6392] }) +Item 135: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.5262" }, vector: [0.9377, 0.9354, 0.7583] }) +Item 136: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.2001" }, vector: [0.1164, 0.8645, 0.8242] }) +Item 137: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.4666" }, vector: [0.1620, 0.2974, 0.3209] }) +Item 138: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1939" }, vector: [0.9473, 0.4661, 0.5575] }) +Item 139: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0903" }, vector: [0.2633, 0.9335, 0.4981] }) +Item 140: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.5685" }, vector: [0.2509, 0.4837, 0.1620] }) +Item 141: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.1324" }, vector: [0.1082, 0.0741, 0.0183] }) +Item 142: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9244" }, vector: [0.5846, 0.5706, 0.4327] }) +Item 143: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.3347" }, vector: [0.9265, 0.9559, 0.0970] }) +Item 144: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7351" }, vector: [0.7162, 0.1286, 0.1047] }) +Item 145: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0301" }, vector: [0.7652, 0.5422, 0.4261] }) +Item 146: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0697" }, vector: [0.2670, 0.8095, 0.6462] }) +Item 147: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8406" }, vector: [0.1504, 0.0946, 0.8216] }) +Item 148: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0285" }, vector: [0.1483, 0.2682, 0.9818] }) +Item 149: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1411" }, vector: [0.2397, 0.6252, 0.9240] }) diff --git a/src/tests/snapshots/arroy__tests__writer__write_and_update_lot_of_random_points_with_little_memory.snap b/src/tests/snapshots/arroy__tests__writer__write_and_update_lot_of_random_points_with_little_memory.snap new file mode 100644 index 0000000..32e6847 --- /dev/null +++ b/src/tests/snapshots/arroy__tests__writer__write_and_update_lot_of_random_points_with_little_memory.snap @@ -0,0 +1,296 @@ +--- +source: src/tests/writer.rs +expression: handle +--- +================== +Dumping index 0 +Root: Metadata { dimensions: 3, items: RoaringBitmap<100 values between 0 and 99>, roots: [0, 1], distance: "cosine" } +Version: Version { major: 0, minor: 7, patch: 0 } +Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 94, right: 95, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.7419, -0.0092, 0.6705] } }) +Tree 1: SplitPlaneNormal(SplitPlaneNormal { left: 2, right: 3, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.5938, 0.3404, -0.7290] } }) +Tree 2: SplitPlaneNormal(SplitPlaneNormal { left: 64, right: 65, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.5969, 0.7955, -0.1042] } }) +Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 4, right: 5, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6720, -0.7180, 0.1817] } }) +Tree 4: SplitPlaneNormal(SplitPlaneNormal { left: 42, right: 43, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.8971, 0.4184, 0.1423] } }) +Tree 5: SplitPlaneNormal(SplitPlaneNormal { left: 6, right: 7, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.2091, -0.4533, 0.8665] } }) +Tree 6: SplitPlaneNormal(SplitPlaneNormal { left: 26, right: 27, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.3881, 0.4833, 0.7847] } }) +Tree 7: SplitPlaneNormal(SplitPlaneNormal { left: 8, right: 9, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.0141, 0.8224, -0.5688] } }) +Tree 8: SplitPlaneNormal(SplitPlaneNormal { left: 16, right: 17, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.6128, 0.7615, 0.2113] } }) +Tree 9: SplitPlaneNormal(SplitPlaneNormal { left: 10, right: 11, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.7223, -0.6315, -0.2819] } }) +Tree 10: SplitPlaneNormal(SplitPlaneNormal { left: 14, right: 15, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.6219, -0.0774, 0.7793] } }) +Tree 11: SplitPlaneNormal(SplitPlaneNormal { left: 12, right: 13, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.4038, 0.3552, -0.8431] } }) +Tree 12: Descendants(Descendants { descendants: [52, 59] }) +Tree 13: Descendants(Descendants { descendants: [10, 58] }) +Tree 14: Descendants(Descendants { descendants: [21, 39] }) +Tree 15: Descendants(Descendants { descendants: [9, 60] }) +Tree 16: SplitPlaneNormal(SplitPlaneNormal { left: 18, right: 19, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.4400, -0.6017, -0.6666] } }) +Tree 17: Descendants(Descendants { descendants: [29, 48, 68] }) +Tree 18: SplitPlaneNormal(SplitPlaneNormal { left: 20, right: 21, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6356, -0.3787, -0.6728] } }) +Tree 19: Descendants(Descendants { descendants: [4, 8, 11] }) +Tree 20: SplitPlaneNormal(SplitPlaneNormal { left: 22, right: 23, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.0340, -0.9313, 0.3626] } }) +Tree 21: Descendants(Descendants { descendants: [40, 75] }) +Tree 22: Descendants(Descendants { descendants: [63, 87] }) +Tree 23: SplitPlaneNormal(SplitPlaneNormal { left: 24, right: 25, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.5292, 0.3868, -0.7553] } }) +Tree 24: Descendants(Descendants { descendants: [0, 93] }) +Tree 25: Descendants(Descendants { descendants: [78, 82] }) +Tree 26: SplitPlaneNormal(SplitPlaneNormal { left: 40, right: 41, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.1973, 0.9757, 0.0950] } }) +Tree 27: SplitPlaneNormal(SplitPlaneNormal { left: 28, right: 29, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6078, -0.7489, -0.2641] } }) +Tree 28: SplitPlaneNormal(SplitPlaneNormal { left: 34, right: 35, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6381, -0.4144, -0.6490] } }) +Tree 29: SplitPlaneNormal(SplitPlaneNormal { left: 30, right: 31, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.3553, -0.9153, 0.1896] } }) +Tree 30: SplitPlaneNormal(SplitPlaneNormal { left: 32, right: 33, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.2376, 0.2217, -0.9457] } }) +Tree 31: Descendants(Descendants { descendants: [15, 80] }) +Tree 32: Descendants(Descendants { descendants: [98] }) +Tree 33: Descendants(Descendants { descendants: [1, 22, 84] }) +Tree 34: SplitPlaneNormal(SplitPlaneNormal { left: 36, right: 37, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.7289, -0.4821, -0.4861] } }) +Tree 35: Descendants(Descendants { descendants: [19, 81] }) +Tree 36: Descendants(Descendants { descendants: [6, 33, 99] }) +Tree 37: SplitPlaneNormal(SplitPlaneNormal { left: 38, right: 39, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.4520, 0.7619, -0.4638] } }) +Tree 38: Descendants(Descendants { descendants: [57, 69] }) +Tree 39: Descendants(Descendants { descendants: [45, 71] }) +Tree 40: Descendants(Descendants { descendants: [5, 27, 77] }) +Tree 41: Descendants(Descendants { descendants: [17, 47, 61] }) +Tree 42: SplitPlaneNormal(SplitPlaneNormal { left: 52, right: 53, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.1610, 0.3819, -0.9101] } }) +Tree 43: SplitPlaneNormal(SplitPlaneNormal { left: 44, right: 45, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.2809, -0.1702, 0.9445] } }) +Tree 44: Descendants(Descendants { descendants: [34] }) +Tree 45: SplitPlaneNormal(SplitPlaneNormal { left: 46, right: 47, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.1491, 0.5140, -0.8448] } }) +Tree 46: SplitPlaneNormal(SplitPlaneNormal { left: 50, right: 51, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.1298, -0.6816, 0.7201] } }) +Tree 47: SplitPlaneNormal(SplitPlaneNormal { left: 48, right: 49, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.8454, -0.4542, 0.2812] } }) +Tree 48: Descendants(Descendants { descendants: [41, 76, 83] }) +Tree 49: Descendants(Descendants { descendants: [13, 23, 92] }) +Tree 50: Descendants(Descendants { descendants: [36, 49] }) +Tree 51: Descendants(Descendants { descendants: [2, 91] }) +Tree 52: SplitPlaneNormal(SplitPlaneNormal { left: 56, right: 57, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6084, -0.1180, -0.7848] } }) +Tree 53: SplitPlaneNormal(SplitPlaneNormal { left: 54, right: 55, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.7969, 0.5480, 0.2541] } }) +Tree 54: Descendants(Descendants { descendants: [12, 97] }) +Tree 55: Descendants(Descendants { descendants: [14, 65, 72] }) +Tree 56: SplitPlaneNormal(SplitPlaneNormal { left: 58, right: 59, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.3148, -0.3591, 0.8786] } }) +Tree 57: Descendants(Descendants { descendants: [24, 31, 42] }) +Tree 58: SplitPlaneNormal(SplitPlaneNormal { left: 60, right: 61, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.4706, 0.6113, -0.6363] } }) +Tree 59: Descendants(Descendants { descendants: [85] }) +Tree 60: SplitPlaneNormal(SplitPlaneNormal { left: 62, right: 63, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.3742, -0.6750, 0.6359] } }) +Tree 61: Descendants(Descendants { descendants: [38] }) +Tree 62: Descendants(Descendants { descendants: [16, 18] }) +Tree 63: Descendants(Descendants { descendants: [90, 96] }) +Tree 64: SplitPlaneNormal(SplitPlaneNormal { left: 80, right: 81, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.7926, -0.2856, -0.5388] } }) +Tree 65: SplitPlaneNormal(SplitPlaneNormal { left: 66, right: 67, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.0680, 0.7454, -0.6632] } }) +Tree 66: SplitPlaneNormal(SplitPlaneNormal { left: 74, right: 75, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.7091, 0.5040, -0.4931] } }) +Tree 67: SplitPlaneNormal(SplitPlaneNormal { left: 68, right: 69, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.5085, 0.4515, -0.7332] } }) +Tree 68: Descendants(Descendants { descendants: [20, 50] }) +Tree 69: SplitPlaneNormal(SplitPlaneNormal { left: 70, right: 71, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.6425, 0.4399, -0.6274] } }) +Tree 70: SplitPlaneNormal(SplitPlaneNormal { left: 72, right: 73, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.8015, -0.4493, 0.3947] } }) +Tree 71: Descendants(Descendants { descendants: [54] }) +Tree 72: Descendants(Descendants { descendants: [25, 26, 66] }) +Tree 73: Descendants(Descendants { descendants: [32] }) +Tree 74: SplitPlaneNormal(SplitPlaneNormal { left: 78, right: 79, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6325, -0.7151, 0.2977] } }) +Tree 75: SplitPlaneNormal(SplitPlaneNormal { left: 76, right: 77, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.8716, 0.0210, 0.4898] } }) +Tree 76: Descendants(Descendants { descendants: [70, 94] }) +Tree 77: Descendants(Descendants { descendants: [74, 79, 86] }) +Tree 78: Descendants(Descendants { descendants: [3, 30] }) +Tree 79: Descendants(Descendants { descendants: [28, 43] }) +Tree 80: SplitPlaneNormal(SplitPlaneNormal { left: 88, right: 89, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.4346, 0.7756, -0.4578] } }) +Tree 81: SplitPlaneNormal(SplitPlaneNormal { left: 82, right: 83, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.3623, 0.9297, 0.0661] } }) +Tree 82: SplitPlaneNormal(SplitPlaneNormal { left: 84, right: 85, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.0722, 0.9920, -0.1031] } }) +Tree 83: Descendants(Descendants { descendants: [44] }) +Tree 84: SplitPlaneNormal(SplitPlaneNormal { left: 86, right: 87, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6043, 0.4030, -0.6874] } }) +Tree 85: Descendants(Descendants { descendants: [56] }) +Tree 86: Descendants(Descendants { descendants: [35, 67] }) +Tree 87: Descendants(Descendants { descendants: [88, 89] }) +Tree 88: SplitPlaneNormal(SplitPlaneNormal { left: 90, right: 91, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.9628, -0.0719, 0.2605] } }) +Tree 89: Descendants(Descendants { descendants: [7, 53, 64] }) +Tree 90: SplitPlaneNormal(SplitPlaneNormal { left: 92, right: 93, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.8021, 0.4808, 0.3542] } }) +Tree 91: Descendants(Descendants { descendants: [55, 62] }) +Tree 92: Descendants(Descendants { descendants: [73, 95] }) +Tree 93: Descendants(Descendants { descendants: [37, 46, 51] }) +Tree 94: SplitPlaneNormal(SplitPlaneNormal { left: 128, right: 129, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.4785, -0.8779, -0.0195] } }) +Tree 95: SplitPlaneNormal(SplitPlaneNormal { left: 96, right: 97, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.9268, -0.3400, -0.1595] } }) +Tree 96: SplitPlaneNormal(SplitPlaneNormal { left: 114, right: 115, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.0640, 0.8356, -0.5456] } }) +Tree 97: SplitPlaneNormal(SplitPlaneNormal { left: 98, right: 99, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.1260, 0.8927, -0.4327] } }) +Tree 98: SplitPlaneNormal(SplitPlaneNormal { left: 108, right: 109, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.3363, -0.8669, 0.3680] } }) +Tree 99: SplitPlaneNormal(SplitPlaneNormal { left: 100, right: 101, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.8726, -0.1613, -0.4610] } }) +Tree 100: SplitPlaneNormal(SplitPlaneNormal { left: 104, right: 105, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.0318, -0.7392, 0.6728] } }) +Tree 101: SplitPlaneNormal(SplitPlaneNormal { left: 102, right: 103, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.3143, -0.7022, 0.6389] } }) +Tree 102: Descendants(Descendants { descendants: [48, 70, 94] }) +Tree 103: Descendants(Descendants { descendants: [44, 64] }) +Tree 104: Descendants(Descendants { descendants: [2, 36, 91] }) +Tree 105: SplitPlaneNormal(SplitPlaneNormal { left: 106, right: 107, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6759, 0.4713, -0.5666] } }) +Tree 106: Descendants(Descendants { descendants: [28] }) +Tree 107: Descendants(Descendants { descendants: [7, 74, 86] }) +Tree 108: Descendants(Descendants { descendants: [53] }) +Tree 109: SplitPlaneNormal(SplitPlaneNormal { left: 110, right: 111, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.8863, -0.1858, 0.4241] } }) +Tree 110: SplitPlaneNormal(SplitPlaneNormal { left: 112, right: 113, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.6023, 0.7592, 0.2465] } }) +Tree 111: Descendants(Descendants { descendants: [37] }) +Tree 112: Descendants(Descendants { descendants: [73, 95] }) +Tree 113: Descendants(Descendants { descendants: [46, 51] }) +Tree 114: SplitPlaneNormal(SplitPlaneNormal { left: 126, right: 127, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.1874, 0.9064, -0.3786] } }) +Tree 115: SplitPlaneNormal(SplitPlaneNormal { left: 116, right: 117, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.4503, 0.5907, -0.6696] } }) +Tree 116: SplitPlaneNormal(SplitPlaneNormal { left: 122, right: 123, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.8347, 0.2874, -0.4699] } }) +Tree 117: SplitPlaneNormal(SplitPlaneNormal { left: 118, right: 119, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.5426, -0.3202, 0.7766] } }) +Tree 118: Descendants(Descendants { descendants: [76, 83] }) +Tree 119: SplitPlaneNormal(SplitPlaneNormal { left: 120, right: 121, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.5526, 0.4617, -0.6938] } }) +Tree 120: Descendants(Descendants { descendants: [25, 26, 66] }) +Tree 121: Descendants(Descendants { descendants: [54] }) +Tree 122: SplitPlaneNormal(SplitPlaneNormal { left: 124, right: 125, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6193, 0.5548, -0.5555] } }) +Tree 123: Descendants(Descendants { descendants: [32, 49] }) +Tree 124: Descendants(Descendants { descendants: [3, 30, 50] }) +Tree 125: Descendants(Descendants { descendants: [20] }) +Tree 126: Descendants(Descendants { descendants: [43, 55, 62] }) +Tree 127: Descendants(Descendants { descendants: [79] }) +Tree 128: SplitPlaneNormal(SplitPlaneNormal { left: 152, right: 153, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.6325, 0.7077, -0.3149] } }) +Tree 129: SplitPlaneNormal(SplitPlaneNormal { left: 130, right: 131, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.3229, 0.5291, -0.7847] } }) +Tree 130: SplitPlaneNormal(SplitPlaneNormal { left: 140, right: 141, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.5718, -0.3132, 0.7583] } }) +Tree 131: SplitPlaneNormal(SplitPlaneNormal { left: 132, right: 133, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.0720, -0.5319, 0.8437] } }) +Tree 132: SplitPlaneNormal(SplitPlaneNormal { left: 136, right: 137, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.3891, -0.6811, -0.6202] } }) +Tree 133: SplitPlaneNormal(SplitPlaneNormal { left: 134, right: 135, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.0610, -0.9292, 0.3644] } }) +Tree 134: Descendants(Descendants { descendants: [15, 40, 80] }) +Tree 135: Descendants(Descendants { descendants: [4, 8] }) +Tree 136: Descendants(Descendants { descendants: [22, 84] }) +Tree 137: SplitPlaneNormal(SplitPlaneNormal { left: 138, right: 139, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.2183, 0.8233, 0.5240] } }) +Tree 138: Descendants(Descendants { descendants: [5, 27, 77] }) +Tree 139: Descendants(Descendants { descendants: [17, 47, 61] }) +Tree 140: SplitPlaneNormal(SplitPlaneNormal { left: 148, right: 149, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.4907, -0.7578, -0.4301] } }) +Tree 141: SplitPlaneNormal(SplitPlaneNormal { left: 142, right: 143, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.1645, -0.9636, 0.2109] } }) +Tree 142: Descendants(Descendants { descendants: [87] }) +Tree 143: SplitPlaneNormal(SplitPlaneNormal { left: 144, right: 145, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.0415, 0.9886, -0.1449] } }) +Tree 144: SplitPlaneNormal(SplitPlaneNormal { left: 146, right: 147, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.6677, -0.1664, 0.7256] } }) +Tree 145: Descendants(Descendants { descendants: [56, 93] }) +Tree 146: Descendants(Descendants { descendants: [88, 89] }) +Tree 147: Descendants(Descendants { descendants: [35, 67] }) +Tree 148: SplitPlaneNormal(SplitPlaneNormal { left: 150, right: 151, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.3166, 0.9469, -0.0553] } }) +Tree 149: Descendants(Descendants { descendants: [11, 75] }) +Tree 150: Descendants(Descendants { descendants: [0, 78, 82] }) +Tree 151: Descendants(Descendants { descendants: [63] }) +Tree 152: SplitPlaneNormal(SplitPlaneNormal { left: 166, right: 167, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.1407, 0.7156, -0.6842] } }) +Tree 153: SplitPlaneNormal(SplitPlaneNormal { left: 154, right: 155, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.5494, -0.1561, -0.8208] } }) +Tree 154: SplitPlaneNormal(SplitPlaneNormal { left: 160, right: 161, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.8677, -0.4957, -0.0375] } }) +Tree 155: SplitPlaneNormal(SplitPlaneNormal { left: 156, right: 157, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.8505, 0.5224, -0.0614] } }) +Tree 156: SplitPlaneNormal(SplitPlaneNormal { left: 158, right: 159, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.7746, 0.6224, -0.1124] } }) +Tree 157: Descendants(Descendants { descendants: [14, 34] }) +Tree 158: Descendants(Descendants { descendants: [12, 42] }) +Tree 159: Descendants(Descendants { descendants: [65, 72, 97] }) +Tree 160: SplitPlaneNormal(SplitPlaneNormal { left: 164, right: 165, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.7947, 0.5223, -0.3094] } }) +Tree 161: SplitPlaneNormal(SplitPlaneNormal { left: 162, right: 163, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.5999, -0.1255, -0.7902] } }) +Tree 162: Descendants(Descendants { descendants: [16, 18, 38] }) +Tree 163: Descendants(Descendants { descendants: [24] }) +Tree 164: Descendants(Descendants { descendants: [13, 23] }) +Tree 165: Descendants(Descendants { descendants: [41, 92] }) +Tree 166: SplitPlaneNormal(SplitPlaneNormal { left: 178, right: 179, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.6048, -0.0853, 0.7918] } }) +Tree 167: SplitPlaneNormal(SplitPlaneNormal { left: 168, right: 169, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6431, -0.6135, -0.4582] } }) +Tree 168: SplitPlaneNormal(SplitPlaneNormal { left: 170, right: 171, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6919, -0.1450, -0.7073] } }) +Tree 169: Descendants(Descendants { descendants: [1, 19, 81] }) +Tree 170: Descendants(Descendants { descendants: [85, 90] }) +Tree 171: SplitPlaneNormal(SplitPlaneNormal { left: 172, right: 173, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.4012, 0.1846, -0.8972] } }) +Tree 172: Descendants(Descendants { descendants: [33, 99] }) +Tree 173: SplitPlaneNormal(SplitPlaneNormal { left: 174, right: 175, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6930, -0.7206, -0.0238] } }) +Tree 174: SplitPlaneNormal(SplitPlaneNormal { left: 176, right: 177, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.6883, -0.3049, -0.6582] } }) +Tree 175: Descendants(Descendants { descendants: [57, 69] }) +Tree 176: Descendants(Descendants { descendants: [31, 96] }) +Tree 177: Descendants(Descendants { descendants: [6, 45, 71] }) +Tree 178: SplitPlaneNormal(SplitPlaneNormal { left: 184, right: 185, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.6981, 0.6082, 0.3780] } }) +Tree 179: SplitPlaneNormal(SplitPlaneNormal { left: 180, right: 181, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.2183, 0.8496, -0.4801] } }) +Tree 180: SplitPlaneNormal(SplitPlaneNormal { left: 182, right: 183, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [0.2662, 0.6364, -0.7240] } }) +Tree 181: Descendants(Descendants { descendants: [60] }) +Tree 182: Descendants(Descendants { descendants: [29, 68] }) +Tree 183: Descendants(Descendants { descendants: [9, 52] }) +Tree 184: SplitPlaneNormal(SplitPlaneNormal { left: 186, right: 187, normal: Leaf { header: NodeHeaderCosine { norm: "0.0000" }, vector: [-0.4736, -0.0890, 0.8762] } }) +Tree 185: Descendants(Descendants { descendants: [21, 39] }) +Tree 186: Descendants(Descendants { descendants: [98] }) +Tree 187: Descendants(Descendants { descendants: [10, 58, 59] }) +Item 0: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0872" }, vector: [0.8013, 0.2371, 0.6955] }) +Item 1: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0443" }, vector: [0.8606, 0.5280, 0.2667] }) +Item 2: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.4908" }, vector: [0.6057, 0.9830, 0.9430] }) +Item 3: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.5378" }, vector: [0.0479, 0.2927, 0.4487] }) +Item 4: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9436" }, vector: [0.8798, 0.0246, 0.3401] }) +Item 5: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7470" }, vector: [0.7418, 0.0595, 0.0652] }) +Item 6: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1644" }, vector: [0.7750, 0.7425, 0.4517] }) +Item 7: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.4776" }, vector: [0.2155, 0.1841, 0.3845] }) +Item 8: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1195" }, vector: [0.9954, 0.1512, 0.4894] }) +Item 9: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.5567" }, vector: [0.9152, 0.7847, 0.9849] }) +Item 10: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.5616" }, vector: [0.4199, 0.2620, 0.2655] }) +Item 11: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9246" }, vector: [0.8414, 0.0192, 0.3828] }) +Item 12: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.3734" }, vector: [0.2561, 0.2692, 0.0368] }) +Item 13: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1116" }, vector: [0.4624, 0.8739, 0.5080] }) +Item 14: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0011" }, vector: [0.4557, 0.8887, 0.0685] }) +Item 15: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.6977" }, vector: [0.6341, 0.1904, 0.2201] }) +Item 16: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1907" }, vector: [0.6947, 0.8503, 0.4607] }) +Item 17: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.6904" }, vector: [0.6554, 0.2088, 0.0586] }) +Item 18: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.2539" }, vector: [0.6857, 0.9343, 0.4788] }) +Item 19: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.2199" }, vector: [0.9246, 0.7944, 0.0473] }) +Item 20: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.2728" }, vector: [0.1040, 0.9647, 0.8238] }) +Item 21: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8493" }, vector: [0.5344, 0.4903, 0.4420] }) +Item 22: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9142" }, vector: [0.7937, 0.4028, 0.2083] }) +Item 23: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7987" }, vector: [0.3315, 0.6684, 0.2849] }) +Item 24: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.2609" }, vector: [0.8002, 0.9037, 0.3644] }) +Item 25: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9546" }, vector: [0.1173, 0.7807, 0.5366] }) +Item 26: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1379" }, vector: [0.1554, 0.9343, 0.6308] }) +Item 27: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.3820" }, vector: [0.3727, 0.0552, 0.0634] }) +Item 28: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1230" }, vector: [0.3584, 0.4273, 0.9748] }) +Item 29: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.4602" }, vector: [0.8893, 0.6025, 0.9890] }) +Item 30: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.2471" }, vector: [0.0001, 0.7870, 0.9674] }) +Item 31: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7464" }, vector: [0.4568, 0.5250, 0.2701] }) +Item 32: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1377" }, vector: [0.2417, 0.8742, 0.6869] }) +Item 33: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.3377" }, vector: [0.8759, 0.8323, 0.5742] }) +Item 34: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7853" }, vector: [0.3201, 0.7171, 0.0057] }) +Item 35: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8325" }, vector: [0.6038, 0.0168, 0.5729] }) +Item 36: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0547" }, vector: [0.4393, 0.7574, 0.5881] }) +Item 37: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9081" }, vector: [0.2978, 0.0910, 0.8530] }) +Item 38: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0339" }, vector: [0.5171, 0.8481, 0.2869] }) +Item 39: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7896" }, vector: [0.5211, 0.4583, 0.3767] }) +Item 40: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0489" }, vector: [0.8616, 0.3239, 0.5030] }) +Item 41: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9873" }, vector: [0.3022, 0.8817, 0.3255] }) +Item 42: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.3946" }, vector: [0.9170, 0.9928, 0.3439] }) +Item 43: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.6672" }, vector: [0.0860, 0.2202, 0.6240] }) +Item 44: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0014" }, vector: [0.6195, 0.3361, 0.7113] }) +Item 45: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.2019" }, vector: [0.8040, 0.7845, 0.4275] }) +Item 46: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8810" }, vector: [0.3626, 0.1384, 0.7909] }) +Item 47: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7506" }, vector: [0.7083, 0.1976, 0.1506] }) +Item 48: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1895" }, vector: [0.6972, 0.5359, 0.8010] }) +Item 49: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1160" }, vector: [0.3805, 0.8072, 0.6701] }) +Item 50: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1789" }, vector: [0.0850, 0.7778, 0.8818] }) +Item 51: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8113" }, vector: [0.3427, 0.1293, 0.7240] }) +Item 52: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.6850" }, vector: [0.4773, 0.2871, 0.3988] }) +Item 53: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8488" }, vector: [0.4014, 0.2562, 0.7026] }) +Item 54: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.4090" }, vector: [0.0131, 0.3608, 0.1922] }) +Item 55: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8270" }, vector: [0.1645, 0.1968, 0.7862] }) +Item 56: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.2929" }, vector: [0.9030, 0.2735, 0.8840] }) +Item 57: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8996" }, vector: [0.6386, 0.5482, 0.3175] }) +Item 58: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1399" }, vector: [0.8519, 0.5081, 0.5617] }) +Item 59: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7839" }, vector: [0.5580, 0.3213, 0.4471] }) +Item 60: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.5511" }, vector: [0.8761, 0.9344, 0.8748] }) +Item 61: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0168" }, vector: [0.9176, 0.4249, 0.1069] }) +Item 62: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0041" }, vector: [0.0392, 0.1024, 0.9981] }) +Item 63: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0165" }, vector: [0.7313, 0.3394, 0.6192] }) +Item 64: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9513" }, vector: [0.4707, 0.3849, 0.7316] }) +Item 65: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0281" }, vector: [0.5298, 0.8744, 0.1086] }) +Item 66: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8002" }, vector: [0.0631, 0.6646, 0.4413] }) +Item 67: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8433" }, vector: [0.5919, 0.0467, 0.5988] }) +Item 68: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.2920" }, vector: [0.8101, 0.4828, 0.8831] }) +Item 69: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.1911" }, vector: [0.1383, 0.1076, 0.0762] }) +Item 70: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1321" }, vector: [0.5699, 0.5919, 0.7788] }) +Item 71: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.5580" }, vector: [0.3705, 0.3807, 0.1708] }) +Item 72: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.6752" }, vector: [0.3678, 0.5629, 0.0612] }) +Item 73: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9156" }, vector: [0.4826, 0.0217, 0.7778] }) +Item 74: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.6857" }, vector: [0.2831, 0.3242, 0.5338] }) +Item 75: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7771" }, vector: [0.6375, 0.1274, 0.4257] }) +Item 76: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9184" }, vector: [0.2305, 0.7650, 0.4528] }) +Item 77: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.2842" }, vector: [0.2800, 0.0278, 0.0397] }) +Item 78: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8796" }, vector: [0.6639, 0.2003, 0.5412] }) +Item 79: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1725" }, vector: [0.3166, 0.5944, 0.9598] }) +Item 80: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1152" }, vector: [0.9520, 0.3982, 0.4226] }) +Item 81: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.9749" }, vector: [0.7733, 0.5495, 0.2244] }) +Item 82: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.0292" }, vector: [0.7816, 0.2531, 0.6199] }) +Item 83: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.5051" }, vector: [0.1072, 0.4570, 0.1867] }) +Item 84: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.6358" }, vector: [0.5403, 0.2813, 0.1820] }) +Item 85: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.2351" }, vector: [0.6583, 0.8015, 0.6706] }) +Item 86: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8018" }, vector: [0.3091, 0.4282, 0.6033] }) +Item 87: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.3859" }, vector: [0.9524, 0.4419, 0.9046] }) +Item 88: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.3135" }, vector: [0.2348, 0.0132, 0.2073] }) +Item 89: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.2740" }, vector: [0.9664, 0.0525, 0.8284] }) +Item 90: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.4259" }, vector: [0.8134, 0.9647, 0.6640] }) +Item 91: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1088" }, vector: [0.4464, 0.7439, 0.6904] }) +Item 92: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.8943" }, vector: [0.3159, 0.7607, 0.3483] }) +Item 93: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.3908" }, vector: [0.9963, 0.2933, 0.9251] }) +Item 94: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.2017" }, vector: [0.1057, 0.1036, 0.1371] }) +Item 95: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7770" }, vector: [0.4079, 0.0195, 0.6610] }) +Item 96: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.3821" }, vector: [0.8298, 0.9571, 0.5529] }) +Item 97: Leaf(Leaf { header: NodeHeaderCosine { norm: "0.7225" }, vector: [0.4484, 0.5659, 0.0259] }) +Item 98: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.1580" }, vector: [0.9343, 0.5204, 0.4442] }) +Item 99: Leaf(Leaf { header: NodeHeaderCosine { norm: "1.5328" }, vector: [0.9591, 0.9487, 0.7276] }) diff --git a/src/tests/tmp_nodes.rs b/src/tests/tmp_nodes.rs new file mode 100644 index 0000000..98460fd --- /dev/null +++ b/src/tests/tmp_nodes.rs @@ -0,0 +1,104 @@ +use std::borrow::Cow; + +use insta::assert_debug_snapshot; +use roaring::RoaringBitmap; + +use crate::{ + distance::{Cosine, NodeHeaderCosine}, + internals::UnalignedVector, + node::{Descendants, Leaf, Node, SplitPlaneNormal}, + parallel::TmpNodes, +}; + +#[test] +fn test_put_and_get_tmp_nodes() { + let mut tmp_nodes = TmpNodes::::new().unwrap(); + for i in 0..10 { + let node = Node::Descendants(Descendants { + descendants: Cow::Owned(RoaringBitmap::from_iter(&[i + 0, i + 1, i + 2])), + }); + tmp_nodes.put(i, &node).unwrap(); + } + + assert_debug_snapshot!(tmp_nodes.get(0).unwrap().unwrap(), @r" + Descendants( + Descendants { + descendants: [ + 0, + 1, + 2, + ], + }, + ) + "); + assert_debug_snapshot!(tmp_nodes.get(9).unwrap().unwrap(), @r" + Descendants( + Descendants { + descendants: [ + 9, + 10, + 11, + ], + }, + ) + "); + assert_debug_snapshot!(tmp_nodes.get(10).unwrap(), @"None"); + + // We start at 11 so there will be a hole at the id 10 + for i in 11..20 { + let normal = + if i % 2 == 0 { Some(UnalignedVector::from_vec(vec![i as f32])) } else { None }; + let node = Node::SplitPlaneNormal(SplitPlaneNormal { + left: i * 2, + right: i * 2 + 1, + normal: normal.map(|v| Leaf { header: NodeHeaderCosine { norm: 0. }, vector: v }), + }); + tmp_nodes.put(i, &node).unwrap(); + } + + assert_debug_snapshot!(tmp_nodes.get(10).unwrap(), @"None"); + assert_debug_snapshot!(tmp_nodes.get(11).unwrap().unwrap(), @r#" + SplitPlaneNormal( + SplitPlaneNormal { + left: 22, + right: 23, + normal: "none", + }, + ) + "#); + + assert_debug_snapshot!(tmp_nodes.get(15).unwrap().unwrap(), @r#" + SplitPlaneNormal( + SplitPlaneNormal { + left: 30, + right: 31, + normal: "none", + }, + ) + "#); + + assert_debug_snapshot!(tmp_nodes.get(19).unwrap().unwrap(), @r#" + SplitPlaneNormal( + SplitPlaneNormal { + left: 38, + right: 39, + normal: "none", + }, + ) + "#); + + assert_debug_snapshot!(tmp_nodes.get(20).unwrap(), @"None"); + + // can we still get the previous nodes correctly? + assert_debug_snapshot!(tmp_nodes.get(3).unwrap().unwrap(), @r" + Descendants( + Descendants { + descendants: [ + 3, + 4, + 5, + ], + }, + ) + "); +} diff --git a/src/tests/writer.rs b/src/tests/writer.rs index b8c95c4..d40239a 100644 --- a/src/tests/writer.rs +++ b/src/tests/writer.rs @@ -281,7 +281,7 @@ fn write_vectors_until_there_is_a_split() { Dumping index 0 Root: Metadata { dimensions: 3, items: RoaringBitmap<[0, 1, 2, 3]>, roots: [0], distance: "euclidean" } Version: Version { major: 0, minor: 7, patch: 0 } - Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "-2.3506" }, vector: [0.5774, 0.5774, 0.5774] } }) + Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "-2.3960" }, vector: [0.5774, 0.5774, 0.5774] } }) Tree 1: Descendants(Descendants { descendants: [0, 1] }) Tree 2: Descendants(Descendants { descendants: [2, 3] }) Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0000, 0.0000, 0.0000] }) @@ -404,11 +404,13 @@ fn overwrite_one_item_incremental() { Dumping index 0 Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2, 3, 4, 5]>, roots: [0], distance: "euclidean" } Version: Version { major: 0, minor: 7, patch: 0 } - Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 4, normal: Leaf { header: NodeHeaderEuclidean { bias: "-3.0143" }, vector: [1.0000, 0.0000] } }) - Tree 1: Descendants(Descendants { descendants: [0, 1] }) - Tree 2: Descendants(Descendants { descendants: [2, 3] }) - Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "-1.5000" }, vector: [1.0000, 0.0000] } }) + Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 6, normal: Leaf { header: NodeHeaderEuclidean { bias: "-2.7500" }, vector: [1.0000, 0.0000] } }) + Tree 1: Descendants(Descendants { descendants: [2] }) + Tree 2: Descendants(Descendants { descendants: [0, 1] }) + Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "1.0000" }, vector: [-1.0000, 0.0000] } }) Tree 4: Descendants(Descendants { descendants: [4, 5] }) + Tree 5: Descendants(Descendants { descendants: [3] }) + Tree 6: SplitPlaneNormal(SplitPlaneNormal { left: 4, right: 5, normal: Leaf { header: NodeHeaderEuclidean { bias: "3.7500" }, vector: [-1.0000, 0.0000] } }) Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0000, 0.0000] }) Item 1: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [1.0000, 0.0000] }) Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [2.0000, 0.0000] }) @@ -431,13 +433,13 @@ fn overwrite_one_item_incremental() { Dumping index 0 Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2, 3, 4, 5]>, roots: [0], distance: "euclidean" } Version: Version { major: 0, minor: 7, patch: 0 } - Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 4, normal: Leaf { header: NodeHeaderEuclidean { bias: "-3.0143" }, vector: [1.0000, 0.0000] } }) - Tree 1: Descendants(Descendants { descendants: [0, 1] }) - Tree 2: Descendants(Descendants { descendants: [2] }) - Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "-1.5000" }, vector: [1.0000, 0.0000] } }) - Tree 4: SplitPlaneNormal(SplitPlaneNormal { left: 5, right: 6, normal: Leaf { header: NodeHeaderEuclidean { bias: "-5.1571" }, vector: [1.0000, 0.0000] } }) - Tree 5: Descendants(Descendants { descendants: [4, 5] }) - Tree 6: Descendants(Descendants { descendants: [3] }) + Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 4, normal: Leaf { header: NodeHeaderEuclidean { bias: "-2.7500" }, vector: [1.0000, 0.0000] } }) + Tree 1: Descendants(Descendants { descendants: [2] }) + Tree 2: Descendants(Descendants { descendants: [0, 1] }) + Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "1.0000" }, vector: [-1.0000, 0.0000] } }) + Tree 4: SplitPlaneNormal(SplitPlaneNormal { left: 7, right: 8, normal: Leaf { header: NodeHeaderEuclidean { bias: "4.5625" }, vector: [-1.0000, 0.0000] } }) + Tree 7: Descendants(Descendants { descendants: [3, 5] }) + Tree 8: Descendants(Descendants { descendants: [4] }) Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0000, 0.0000] }) Item 1: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [1.0000, 0.0000] }) Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [2.0000, 0.0000] }) @@ -604,9 +606,9 @@ fn delete_one_leaf_in_a_split() { Dumping index 0 Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2]>, roots: [0], distance: "euclidean" } Version: Version { major: 0, minor: 7, patch: 0 } - Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "1.1875" }, vector: [-1.0000, 0.0000] } }) - Tree 1: Descendants(Descendants { descendants: [2] }) - Tree 2: Descendants(Descendants { descendants: [0, 1] }) + Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "-0.7143" }, vector: [1.0000, 0.0000] } }) + Tree 1: Descendants(Descendants { descendants: [0] }) + Tree 2: Descendants(Descendants { descendants: [1, 2] }) Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0000, 0.0000] }) Item 1: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [1.0000, 0.0000] }) Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [2.0000, 0.0000] }) @@ -688,11 +690,13 @@ fn delete_one_item() { Dumping index 0 Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2, 3, 4, 5]>, roots: [0], distance: "euclidean" } Version: Version { major: 0, minor: 7, patch: 0 } - Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 4, normal: Leaf { header: NodeHeaderEuclidean { bias: "-3.0143" }, vector: [1.0000, 0.0000] } }) - Tree 1: Descendants(Descendants { descendants: [0, 1] }) - Tree 2: Descendants(Descendants { descendants: [2, 3] }) - Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "-1.5000" }, vector: [1.0000, 0.0000] } }) + Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 6, normal: Leaf { header: NodeHeaderEuclidean { bias: "-2.7500" }, vector: [1.0000, 0.0000] } }) + Tree 1: Descendants(Descendants { descendants: [2] }) + Tree 2: Descendants(Descendants { descendants: [0, 1] }) + Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "1.0000" }, vector: [-1.0000, 0.0000] } }) Tree 4: Descendants(Descendants { descendants: [4, 5] }) + Tree 5: Descendants(Descendants { descendants: [3] }) + Tree 6: SplitPlaneNormal(SplitPlaneNormal { left: 4, right: 5, normal: Leaf { header: NodeHeaderEuclidean { bias: "3.7500" }, vector: [-1.0000, 0.0000] } }) Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0000, 0.0000] }) Item 1: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [1.0000, 0.0000] }) Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [2.0000, 0.0000] }) @@ -714,10 +718,10 @@ fn delete_one_item() { Dumping index 0 Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2, 4, 5]>, roots: [0], distance: "euclidean" } Version: Version { major: 0, minor: 7, patch: 0 } - Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 4, normal: Leaf { header: NodeHeaderEuclidean { bias: "-3.0143" }, vector: [1.0000, 0.0000] } }) - Tree 1: Descendants(Descendants { descendants: [0, 1] }) - Tree 2: Descendants(Descendants { descendants: [2] }) - Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "-1.5000" }, vector: [1.0000, 0.0000] } }) + Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 4, normal: Leaf { header: NodeHeaderEuclidean { bias: "-2.7500" }, vector: [1.0000, 0.0000] } }) + Tree 1: Descendants(Descendants { descendants: [2] }) + Tree 2: Descendants(Descendants { descendants: [0, 1] }) + Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "1.0000" }, vector: [-1.0000, 0.0000] } }) Tree 4: Descendants(Descendants { descendants: [4, 5] }) Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0000, 0.0000] }) Item 1: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [1.0000, 0.0000] }) @@ -740,7 +744,7 @@ fn delete_one_item() { Dumping index 0 Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 2, 4, 5]>, roots: [0], distance: "euclidean" } Version: Version { major: 0, minor: 7, patch: 0 } - Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 4, normal: Leaf { header: NodeHeaderEuclidean { bias: "-3.0143" }, vector: [1.0000, 0.0000] } }) + Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 4, normal: Leaf { header: NodeHeaderEuclidean { bias: "-2.7500" }, vector: [1.0000, 0.0000] } }) Tree 3: Descendants(Descendants { descendants: [0, 2] }) Tree 4: Descendants(Descendants { descendants: [4, 5] }) Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0000, 0.0000] }) @@ -850,7 +854,7 @@ fn add_one_item_incrementally_to_create_a_split_node() { Dumping index 0 Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2]>, roots: [0], distance: "euclidean" } Version: Version { major: 0, minor: 7, patch: 0 } - Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "1.2500" }, vector: [-1.0000, 0.0000] } }) + Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "1.2778" }, vector: [-1.0000, 0.0000] } }) Tree 1: Descendants(Descendants { descendants: [2] }) Tree 2: Descendants(Descendants { descendants: [0, 1] }) Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0000, 0.0000] }) @@ -877,11 +881,13 @@ fn add_one_item_incrementally() { Dumping index 0 Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2, 3, 4, 5]>, roots: [0], distance: "euclidean" } Version: Version { major: 0, minor: 7, patch: 0 } - Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 4, normal: Leaf { header: NodeHeaderEuclidean { bias: "-3.0143" }, vector: [1.0000, 0.0000] } }) - Tree 1: Descendants(Descendants { descendants: [0, 1] }) - Tree 2: Descendants(Descendants { descendants: [2, 3] }) - Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "-1.5000" }, vector: [1.0000, 0.0000] } }) + Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 6, normal: Leaf { header: NodeHeaderEuclidean { bias: "-2.7500" }, vector: [1.0000, 0.0000] } }) + Tree 1: Descendants(Descendants { descendants: [2] }) + Tree 2: Descendants(Descendants { descendants: [0, 1] }) + Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "1.0000" }, vector: [-1.0000, 0.0000] } }) Tree 4: Descendants(Descendants { descendants: [4, 5] }) + Tree 5: Descendants(Descendants { descendants: [3] }) + Tree 6: SplitPlaneNormal(SplitPlaneNormal { left: 4, right: 5, normal: Leaf { header: NodeHeaderEuclidean { bias: "3.7500" }, vector: [-1.0000, 0.0000] } }) Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0000, 0.0000] }) Item 1: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [1.0000, 0.0000] }) Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [2.0000, 0.0000] }) @@ -903,13 +909,15 @@ fn add_one_item_incrementally() { Dumping index 0 Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2, 3, 4, 5, 25]>, roots: [0], distance: "euclidean" } Version: Version { major: 0, minor: 7, patch: 0 } - Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 4, normal: Leaf { header: NodeHeaderEuclidean { bias: "-3.0143" }, vector: [1.0000, 0.0000] } }) - Tree 1: Descendants(Descendants { descendants: [0, 1] }) - Tree 2: Descendants(Descendants { descendants: [2, 3] }) - Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "-1.5000" }, vector: [1.0000, 0.0000] } }) - Tree 4: SplitPlaneNormal(SplitPlaneNormal { left: 5, right: 6, normal: Leaf { header: NodeHeaderEuclidean { bias: "-14.6429" }, vector: [1.0000, 0.0000] } }) - Tree 5: Descendants(Descendants { descendants: [4, 5] }) - Tree 6: Descendants(Descendants { descendants: [25] }) + Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 6, normal: Leaf { header: NodeHeaderEuclidean { bias: "-2.7500" }, vector: [1.0000, 0.0000] } }) + Tree 1: Descendants(Descendants { descendants: [2] }) + Tree 2: Descendants(Descendants { descendants: [0, 1] }) + Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "1.0000" }, vector: [-1.0000, 0.0000] } }) + Tree 4: SplitPlaneNormal(SplitPlaneNormal { left: 7, right: 8, normal: Leaf { header: NodeHeaderEuclidean { bias: "14.9000" }, vector: [-1.0000, 0.0000] } }) + Tree 5: Descendants(Descendants { descendants: [3] }) + Tree 6: SplitPlaneNormal(SplitPlaneNormal { left: 4, right: 5, normal: Leaf { header: NodeHeaderEuclidean { bias: "3.7500" }, vector: [-1.0000, 0.0000] } }) + Tree 7: Descendants(Descendants { descendants: [25] }) + Tree 8: Descendants(Descendants { descendants: [4, 5] }) Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0000, 0.0000] }) Item 1: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [1.0000, 0.0000] }) Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [2.0000, 0.0000] }) @@ -932,15 +940,17 @@ fn add_one_item_incrementally() { Dumping index 0 Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2, 3, 4, 5, 8, 25]>, roots: [0], distance: "euclidean" } Version: Version { major: 0, minor: 7, patch: 0 } - Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 4, normal: Leaf { header: NodeHeaderEuclidean { bias: "-3.0143" }, vector: [1.0000, 0.0000] } }) - Tree 1: Descendants(Descendants { descendants: [0, 1] }) - Tree 2: Descendants(Descendants { descendants: [2, 3] }) - Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "-1.5000" }, vector: [1.0000, 0.0000] } }) - Tree 4: SplitPlaneNormal(SplitPlaneNormal { left: 5, right: 6, normal: Leaf { header: NodeHeaderEuclidean { bias: "-14.6429" }, vector: [1.0000, 0.0000] } }) - Tree 5: SplitPlaneNormal(SplitPlaneNormal { left: 7, right: 8, normal: Leaf { header: NodeHeaderEuclidean { bias: "-6.3333" }, vector: [1.0000, 0.0000] } }) - Tree 6: Descendants(Descendants { descendants: [25] }) - Tree 7: Descendants(Descendants { descendants: [4, 5] }) - Tree 8: Descendants(Descendants { descendants: [8] }) + Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 6, normal: Leaf { header: NodeHeaderEuclidean { bias: "-2.7500" }, vector: [1.0000, 0.0000] } }) + Tree 1: Descendants(Descendants { descendants: [2] }) + Tree 2: Descendants(Descendants { descendants: [0, 1] }) + Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "1.0000" }, vector: [-1.0000, 0.0000] } }) + Tree 4: SplitPlaneNormal(SplitPlaneNormal { left: 7, right: 8, normal: Leaf { header: NodeHeaderEuclidean { bias: "14.9000" }, vector: [-1.0000, 0.0000] } }) + Tree 5: Descendants(Descendants { descendants: [3] }) + Tree 6: SplitPlaneNormal(SplitPlaneNormal { left: 4, right: 5, normal: Leaf { header: NodeHeaderEuclidean { bias: "3.7500" }, vector: [-1.0000, 0.0000] } }) + Tree 7: Descendants(Descendants { descendants: [25] }) + Tree 8: SplitPlaneNormal(SplitPlaneNormal { left: 9, right: 10, normal: Leaf { header: NodeHeaderEuclidean { bias: "6.2778" }, vector: [-1.0000, 0.0000] } }) + Tree 9: Descendants(Descendants { descendants: [8] }) + Tree 10: Descendants(Descendants { descendants: [4, 5] }) Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0000, 0.0000] }) Item 1: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [1.0000, 0.0000] }) Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [2.0000, 0.0000] }) @@ -971,12 +981,12 @@ fn delete_extraneous_tree() { Dumping index 0 Root: Metadata { dimensions: 4, items: RoaringBitmap<[0, 1, 2, 3, 4]>, roots: [0, 1], distance: "euclidean" } Version: Version { major: 0, minor: 7, patch: 0 } - Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 2, right: 3, normal: Leaf { header: NodeHeaderEuclidean { bias: "-1.9500" }, vector: [1.0000, 0.0000, 0.0000, 0.0000] } }) - Tree 1: SplitPlaneNormal(SplitPlaneNormal { left: 5, right: 6, normal: Leaf { header: NodeHeaderEuclidean { bias: "1.7333" }, vector: [-1.0000, 0.0000, 0.0000, 0.0000] } }) - Tree 2: Descendants(Descendants { descendants: [0, 1] }) - Tree 3: Descendants(Descendants { descendants: [2, 3, 4] }) - Tree 5: Descendants(Descendants { descendants: [2, 3, 4] }) - Tree 6: Descendants(Descendants { descendants: [0, 1] }) + Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 4, right: 5, normal: Leaf { header: NodeHeaderEuclidean { bias: "1.5952" }, vector: [-1.0000, 0.0000, 0.0000, 0.0000] } }) + Tree 1: SplitPlaneNormal(SplitPlaneNormal { left: 2, right: 3, normal: Leaf { header: NodeHeaderEuclidean { bias: "-2.2778" }, vector: [1.0000, 0.0000, 0.0000, 0.0000] } }) + Tree 2: Descendants(Descendants { descendants: [0, 1, 2] }) + Tree 3: Descendants(Descendants { descendants: [3, 4] }) + Tree 4: Descendants(Descendants { descendants: [2, 3, 4] }) + Tree 5: Descendants(Descendants { descendants: [0, 1] }) Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0000, 0.0000, 0.0000, 0.0000] }) Item 1: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [1.0000, 0.0000, 0.0000, 0.0000] }) Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [2.0000, 0.0000, 0.0000, 0.0000] }) @@ -994,12 +1004,12 @@ fn delete_extraneous_tree() { Dumping index 0 Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2, 3, 4]>, roots: [0, 1], distance: "euclidean" } Version: Version { major: 0, minor: 7, patch: 0 } - Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 2, right: 3, normal: Leaf { header: NodeHeaderEuclidean { bias: "-1.9500" }, vector: [1.0000, 0.0000, 0.0000, 0.0000] } }) - Tree 1: SplitPlaneNormal(SplitPlaneNormal { left: 5, right: 6, normal: Leaf { header: NodeHeaderEuclidean { bias: "1.7333" }, vector: [-1.0000, 0.0000, 0.0000, 0.0000] } }) - Tree 2: Descendants(Descendants { descendants: [0, 1] }) - Tree 3: Descendants(Descendants { descendants: [2, 3, 4] }) - Tree 5: Descendants(Descendants { descendants: [2, 3, 4] }) - Tree 6: Descendants(Descendants { descendants: [0, 1] }) + Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 4, right: 5, normal: Leaf { header: NodeHeaderEuclidean { bias: "1.5952" }, vector: [-1.0000, 0.0000, 0.0000, 0.0000] } }) + Tree 1: SplitPlaneNormal(SplitPlaneNormal { left: 2, right: 3, normal: Leaf { header: NodeHeaderEuclidean { bias: "-2.2778" }, vector: [1.0000, 0.0000, 0.0000, 0.0000] } }) + Tree 2: Descendants(Descendants { descendants: [0, 1, 2] }) + Tree 3: Descendants(Descendants { descendants: [3, 4] }) + Tree 4: Descendants(Descendants { descendants: [2, 3, 4] }) + Tree 5: Descendants(Descendants { descendants: [0, 1] }) Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0000, 0.0000, 0.0000, 0.0000] }) Item 1: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [1.0000, 0.0000, 0.0000, 0.0000] }) Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [2.0000, 0.0000, 0.0000, 0.0000] }) @@ -1017,9 +1027,9 @@ fn delete_extraneous_tree() { Dumping index 0 Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2, 3, 4]>, roots: [1], distance: "euclidean" } Version: Version { major: 0, minor: 7, patch: 0 } - Tree 1: SplitPlaneNormal(SplitPlaneNormal { left: 5, right: 6, normal: Leaf { header: NodeHeaderEuclidean { bias: "1.7333" }, vector: [-1.0000, 0.0000, 0.0000, 0.0000] } }) - Tree 5: Descendants(Descendants { descendants: [2, 3, 4] }) - Tree 6: Descendants(Descendants { descendants: [0, 1] }) + Tree 1: SplitPlaneNormal(SplitPlaneNormal { left: 2, right: 3, normal: Leaf { header: NodeHeaderEuclidean { bias: "-2.2778" }, vector: [1.0000, 0.0000, 0.0000, 0.0000] } }) + Tree 2: Descendants(Descendants { descendants: [0, 1, 2] }) + Tree 3: Descendants(Descendants { descendants: [3, 4] }) Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0000, 0.0000, 0.0000, 0.0000] }) Item 1: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [1.0000, 0.0000, 0.0000, 0.0000] }) Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [2.0000, 0.0000, 0.0000, 0.0000] }) @@ -1047,11 +1057,13 @@ fn create_root_split_node_with_empty_child() { Dumping index 0 Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2, 3, 4, 5]>, roots: [0], distance: "euclidean" } Version: Version { major: 0, minor: 7, patch: 0 } - Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 4, normal: Leaf { header: NodeHeaderEuclidean { bias: "-3.0143" }, vector: [1.0000, 0.0000] } }) - Tree 1: Descendants(Descendants { descendants: [0, 1] }) - Tree 2: Descendants(Descendants { descendants: [2, 3] }) - Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "-1.5000" }, vector: [1.0000, 0.0000] } }) + Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 6, normal: Leaf { header: NodeHeaderEuclidean { bias: "-2.7500" }, vector: [1.0000, 0.0000] } }) + Tree 1: Descendants(Descendants { descendants: [2] }) + Tree 2: Descendants(Descendants { descendants: [0, 1] }) + Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "1.0000" }, vector: [-1.0000, 0.0000] } }) Tree 4: Descendants(Descendants { descendants: [4, 5] }) + Tree 5: Descendants(Descendants { descendants: [3] }) + Tree 6: SplitPlaneNormal(SplitPlaneNormal { left: 4, right: 5, normal: Leaf { header: NodeHeaderEuclidean { bias: "3.7500" }, vector: [-1.0000, 0.0000] } }) Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0000, 0.0000] }) Item 1: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [1.0000, 0.0000] }) Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [2.0000, 0.0000] }) @@ -1074,11 +1086,9 @@ fn create_root_split_node_with_empty_child() { Dumping index 0 Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 2, 3, 4]>, roots: [0], distance: "euclidean" } Version: Version { major: 0, minor: 7, patch: 0 } - Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 4, normal: Leaf { header: NodeHeaderEuclidean { bias: "-3.0143" }, vector: [1.0000, 0.0000] } }) - Tree 1: Descendants(Descendants { descendants: [0] }) - Tree 2: Descendants(Descendants { descendants: [2, 3] }) - Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "-1.5000" }, vector: [1.0000, 0.0000] } }) - Tree 4: Descendants(Descendants { descendants: [4] }) + Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 6, normal: Leaf { header: NodeHeaderEuclidean { bias: "-2.7500" }, vector: [1.0000, 0.0000] } }) + Tree 3: Descendants(Descendants { descendants: [0, 2] }) + Tree 6: Descendants(Descendants { descendants: [3, 4] }) Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0000, 0.0000] }) Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [2.0000, 0.0000] }) Item 3: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [3.0000, 0.0000] }) @@ -1098,9 +1108,9 @@ fn create_root_split_node_with_empty_child() { Dumping index 0 Root: Metadata { dimensions: 2, items: RoaringBitmap<[2, 3, 4]>, roots: [0], distance: "euclidean" } Version: Version { major: 0, minor: 7, patch: 0 } - Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 4, normal: Leaf { header: NodeHeaderEuclidean { bias: "-3.0143" }, vector: [1.0000, 0.0000] } }) - Tree 3: Descendants(Descendants { descendants: [2, 3] }) - Tree 4: Descendants(Descendants { descendants: [4] }) + Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 6, normal: Leaf { header: NodeHeaderEuclidean { bias: "-2.7500" }, vector: [1.0000, 0.0000] } }) + Tree 3: Descendants(Descendants { descendants: [2] }) + Tree 6: Descendants(Descendants { descendants: [3, 4] }) Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [2.0000, 0.0000] }) Item 3: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [3.0000, 0.0000] }) Item 4: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [4.0000, 0.0000] }) @@ -1125,11 +1135,13 @@ fn reuse_node_id() { Dumping index 0 Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2, 3, 4, 5]>, roots: [0], distance: "euclidean" } Version: Version { major: 0, minor: 7, patch: 0 } - Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 4, normal: Leaf { header: NodeHeaderEuclidean { bias: "-3.0143" }, vector: [1.0000, 0.0000] } }) - Tree 1: Descendants(Descendants { descendants: [0, 1] }) - Tree 2: Descendants(Descendants { descendants: [2, 3] }) - Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "-1.5000" }, vector: [1.0000, 0.0000] } }) + Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 6, normal: Leaf { header: NodeHeaderEuclidean { bias: "-2.7500" }, vector: [1.0000, 0.0000] } }) + Tree 1: Descendants(Descendants { descendants: [2] }) + Tree 2: Descendants(Descendants { descendants: [0, 1] }) + Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "1.0000" }, vector: [-1.0000, 0.0000] } }) Tree 4: Descendants(Descendants { descendants: [4, 5] }) + Tree 5: Descendants(Descendants { descendants: [3] }) + Tree 6: SplitPlaneNormal(SplitPlaneNormal { left: 4, right: 5, normal: Leaf { header: NodeHeaderEuclidean { bias: "3.7500" }, vector: [-1.0000, 0.0000] } }) Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0000, 0.0000] }) Item 1: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [1.0000, 0.0000] }) Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [2.0000, 0.0000] }) @@ -1141,8 +1153,7 @@ fn reuse_node_id() { let mut wtxn = handle.env.write_txn().unwrap(); let writer = Writer::new(handle.database, 0, 2); - // if we delete the 3 and 4 it should free the tree node 2 - writer.del_item(&mut wtxn, 3).unwrap(); + // if we delete 4 it should free the tree node 3 and 5 writer.del_item(&mut wtxn, 4).unwrap(); writer.builder(&mut rng).n_trees(1).build(&mut wtxn).unwrap(); wtxn.commit().unwrap(); @@ -1150,24 +1161,24 @@ fn reuse_node_id() { insta::assert_snapshot!(handle, @r#" ================== Dumping index 0 - Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2, 5]>, roots: [0], distance: "euclidean" } + Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2, 3, 5]>, roots: [0], distance: "euclidean" } Version: Version { major: 0, minor: 7, patch: 0 } - Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 4, normal: Leaf { header: NodeHeaderEuclidean { bias: "-3.0143" }, vector: [1.0000, 0.0000] } }) - Tree 1: Descendants(Descendants { descendants: [0, 1] }) - Tree 2: Descendants(Descendants { descendants: [2] }) - Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "-1.5000" }, vector: [1.0000, 0.0000] } }) - Tree 4: Descendants(Descendants { descendants: [5] }) + Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 6, normal: Leaf { header: NodeHeaderEuclidean { bias: "-2.7500" }, vector: [1.0000, 0.0000] } }) + Tree 1: Descendants(Descendants { descendants: [2] }) + Tree 2: Descendants(Descendants { descendants: [0, 1] }) + Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "1.0000" }, vector: [-1.0000, 0.0000] } }) + Tree 6: Descendants(Descendants { descendants: [3, 5] }) Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0000, 0.0000] }) Item 1: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [1.0000, 0.0000] }) Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [2.0000, 0.0000] }) + Item 3: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [3.0000, 0.0000] }) Item 5: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [5.0000, 0.0000] }) "#); let mut wtxn = handle.env.write_txn().unwrap(); let writer = Writer::new(handle.database, 0, 2); - // if we re-insert both nodes, the id 2 should be re-used - writer.add_item(&mut wtxn, 3, &[3., 0.]).unwrap(); + // if we re-insert both nodes, the ids 3 and 5 should be re-used writer.add_item(&mut wtxn, 4, &[4., 0.]).unwrap(); writer.builder(&mut rng).n_trees(1).build(&mut wtxn).unwrap(); wtxn.commit().unwrap(); @@ -1177,11 +1188,13 @@ fn reuse_node_id() { Dumping index 0 Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2, 3, 4, 5]>, roots: [0], distance: "euclidean" } Version: Version { major: 0, minor: 7, patch: 0 } - Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 4, normal: Leaf { header: NodeHeaderEuclidean { bias: "-3.0143" }, vector: [1.0000, 0.0000] } }) - Tree 1: Descendants(Descendants { descendants: [0, 1] }) - Tree 2: Descendants(Descendants { descendants: [2, 3] }) - Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "-1.5000" }, vector: [1.0000, 0.0000] } }) - Tree 4: Descendants(Descendants { descendants: [4, 5] }) + Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 6, normal: Leaf { header: NodeHeaderEuclidean { bias: "-2.7500" }, vector: [1.0000, 0.0000] } }) + Tree 1: Descendants(Descendants { descendants: [2] }) + Tree 2: Descendants(Descendants { descendants: [0, 1] }) + Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "1.0000" }, vector: [-1.0000, 0.0000] } }) + Tree 4: Descendants(Descendants { descendants: [5] }) + Tree 5: Descendants(Descendants { descendants: [3, 4] }) + Tree 6: SplitPlaneNormal(SplitPlaneNormal { left: 4, right: 5, normal: Leaf { header: NodeHeaderEuclidean { bias: "4.2000" }, vector: [-1.0000, 0.0000] } }) Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0000, 0.0000] }) Item 1: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [1.0000, 0.0000] }) Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [2.0000, 0.0000] }) @@ -1200,20 +1213,22 @@ fn reuse_node_id() { insta::assert_snapshot!(handle, @r#" ================== Dumping index 0 - Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2, 3, 4, 5]>, roots: [0, 5], distance: "euclidean" } + Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2, 3, 4, 5]>, roots: [0, 7], distance: "euclidean" } Version: Version { major: 0, minor: 7, patch: 0 } - Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 4, normal: Leaf { header: NodeHeaderEuclidean { bias: "-3.0143" }, vector: [1.0000, 0.0000] } }) - Tree 1: Descendants(Descendants { descendants: [0, 1] }) - Tree 2: Descendants(Descendants { descendants: [2, 3] }) - Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "-1.5000" }, vector: [1.0000, 0.0000] } }) - Tree 4: Descendants(Descendants { descendants: [4, 5] }) - Tree 5: SplitPlaneNormal(SplitPlaneNormal { left: 8, right: 11, normal: Leaf { header: NodeHeaderEuclidean { bias: "-2.7500" }, vector: [1.0000, 0.0000] } }) - Tree 6: Descendants(Descendants { descendants: [0, 1] }) - Tree 7: Descendants(Descendants { descendants: [2] }) - Tree 8: SplitPlaneNormal(SplitPlaneNormal { left: 6, right: 7, normal: Leaf { header: NodeHeaderEuclidean { bias: "-1.3333" }, vector: [1.0000, 0.0000] } }) - Tree 9: Descendants(Descendants { descendants: [4, 5] }) - Tree 10: Descendants(Descendants { descendants: [3] }) - Tree 11: SplitPlaneNormal(SplitPlaneNormal { left: 9, right: 10, normal: Leaf { header: NodeHeaderEuclidean { bias: "3.7500" }, vector: [-1.0000, 0.0000] } }) + Tree 0: SplitPlaneNormal(SplitPlaneNormal { left: 3, right: 6, normal: Leaf { header: NodeHeaderEuclidean { bias: "-2.7500" }, vector: [1.0000, 0.0000] } }) + Tree 1: Descendants(Descendants { descendants: [2] }) + Tree 2: Descendants(Descendants { descendants: [0, 1] }) + Tree 3: SplitPlaneNormal(SplitPlaneNormal { left: 1, right: 2, normal: Leaf { header: NodeHeaderEuclidean { bias: "1.0000" }, vector: [-1.0000, 0.0000] } }) + Tree 4: Descendants(Descendants { descendants: [5] }) + Tree 5: Descendants(Descendants { descendants: [3, 4] }) + Tree 6: SplitPlaneNormal(SplitPlaneNormal { left: 4, right: 5, normal: Leaf { header: NodeHeaderEuclidean { bias: "4.2000" }, vector: [-1.0000, 0.0000] } }) + Tree 7: SplitPlaneNormal(SplitPlaneNormal { left: 10, right: 13, normal: Leaf { header: NodeHeaderEuclidean { bias: "-2.3714" }, vector: [1.0000, 0.0000] } }) + Tree 8: Descendants(Descendants { descendants: [1, 2] }) + Tree 9: Descendants(Descendants { descendants: [0] }) + Tree 10: SplitPlaneNormal(SplitPlaneNormal { left: 8, right: 9, normal: Leaf { header: NodeHeaderEuclidean { bias: "0.8714" }, vector: [-1.0000, 0.0000] } }) + Tree 11: Descendants(Descendants { descendants: [4, 5] }) + Tree 12: Descendants(Descendants { descendants: [3] }) + Tree 13: SplitPlaneNormal(SplitPlaneNormal { left: 11, right: 12, normal: Leaf { header: NodeHeaderEuclidean { bias: "3.6250" }, vector: [-1.0000, 0.0000] } }) Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [0.0000, 0.0000] }) Item 1: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [1.0000, 0.0000] }) Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: "0.0000" }, vector: [2.0000, 0.0000] }) @@ -1356,3 +1371,31 @@ fn cancel_indexing_process() { .unwrap_err(); assert_snapshot!(err, @"The corresponding build process has been cancelled"); } + +#[test] +fn write_and_update_lot_of_random_points_with_little_memory() { + let handle = create_database::(); + let mut wtxn = handle.env.write_txn().unwrap(); + let writer = Writer::new(handle.database, 0, 3); + let mut rng = rng(); + for id in 0..100 { + let vector: [f32; 3] = std::array::from_fn(|_| rng.gen()); + writer.add_item(&mut wtxn, id, &vector).unwrap(); + } + + // With 0 bytes of memory, the builder will default to the size of a descendant + 1 + writer.builder(&mut rng).available_memory(0).n_trees(2).build(&mut wtxn).unwrap(); + wtxn.commit().unwrap(); + insta::assert_snapshot!(handle); + + let mut wtxn = handle.env.write_txn().unwrap(); + let writer = Writer::new(handle.database, 0, 3); + for id in (0..100).step_by(2).chain(100..150) { + let vector: [f32; 3] = std::array::from_fn(|_| rng.gen()); + writer.add_item(&mut wtxn, id, &vector).unwrap(); + } + writer.builder(&mut rng).available_memory(0).n_trees(3).build(&mut wtxn).unwrap(); + wtxn.commit().unwrap(); + + insta::assert_snapshot!(handle); +} diff --git a/src/unaligned_vector/binary_quantized.rs b/src/unaligned_vector/binary_quantized.rs index d4f4f29..d373e9a 100644 --- a/src/unaligned_vector/binary_quantized.rs +++ b/src/unaligned_vector/binary_quantized.rs @@ -71,6 +71,10 @@ impl UnalignedVectorCodec for BinaryQuantized { fn is_zero(vec: &UnalignedVector) -> bool { vec.as_bytes().iter().all(|b| *b == 0) } + + fn size_of_item(dimensions: usize) -> usize { + dimensions / QUANTIZED_WORD_BITS + } } pub(super) fn from_slice_non_optimized(slice: &[f32]) -> Vec { diff --git a/src/unaligned_vector/f32.rs b/src/unaligned_vector/f32.rs index aa078de..274642f 100644 --- a/src/unaligned_vector/f32.rs +++ b/src/unaligned_vector/f32.rs @@ -54,4 +54,8 @@ impl UnalignedVectorCodec for f32 { fn is_zero(vec: &UnalignedVector) -> bool { vec.iter().all(|v| v == 0.0) } + + fn size_of_item(dimensions: usize) -> usize { + dimensions * size_of::() + } } diff --git a/src/unaligned_vector/mod.rs b/src/unaligned_vector/mod.rs index 1b58739..1e6df85 100644 --- a/src/unaligned_vector/mod.rs +++ b/src/unaligned_vector/mod.rs @@ -43,6 +43,9 @@ pub trait UnalignedVectorCodec: std::borrow::ToOwned + Sized { /// Returns true if all the elements in the vector are equal to 0. fn is_zero(vec: &UnalignedVector) -> bool; + + /// Returns the size of an item in bytes. + fn size_of_item(dimensions: usize) -> usize; } /// A wrapper struct that is used to read unaligned vectors directly from memory. diff --git a/src/writer.rs b/src/writer.rs index 5d96f76..fdf2778 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -1,15 +1,20 @@ use std::any::TypeId; use std::borrow::Cow; +use std::cell::RefCell; use std::path::PathBuf; use std::sync::atomic::AtomicU32; use std::sync::Arc; +use crossbeam::channel::{bounded, Sender}; use heed::types::{Bytes, DecodeIgnore, Unit}; use heed::{MdbError, PutFlags, RoTxn, RwTxn}; +use nohash::{BuildNoHashHasher, IntMap}; +use rand::rngs::StdRng; use rand::{Rng, SeedableRng}; use rayon::iter::repeatn; -use rayon::prelude::*; +use rayon::{current_num_threads, prelude::*, Scope}; use roaring::RoaringBitmap; +use thread_local::ThreadLocal; use crate::distance::Distance; use crate::internals::{KeyCodec, Side}; @@ -17,7 +22,6 @@ use crate::item_iter::ItemIter; use crate::node::{Descendants, ItemIds, Leaf, SplitPlaneNormal}; use crate::parallel::{ ConcurrentNodeIds, ImmutableLeafs, ImmutableSubsetLeafs, ImmutableTrees, TmpNodes, - TmpNodesReader, }; use crate::reader::item_leaf; use crate::unaligned_vector::UnalignedVector; @@ -28,7 +32,7 @@ use crate::{ }; /// The options available when building the arroy database. -pub struct ArroyBuilder<'a, D: Distance, R: Rng + SeedableRng> { +pub struct ArroyBuilder<'a, D: Distance, R: Rng + SeedableRng + Send + Sync> { writer: &'a Writer, rng: &'a mut R, inner: BuildOption<'a>, @@ -114,7 +118,7 @@ impl BuildOption<'_> { } } -impl<'a, D: Distance, R: Rng + SeedableRng> ArroyBuilder<'a, D, R> { +impl<'a, D: Distance, R: Rng + SeedableRng + Send + Sync> ArroyBuilder<'a, D, R> { /// The number of trees to build. If not set arroy will determine the best amount to build for your number of vectors by itself. /// /// # Example @@ -468,11 +472,14 @@ impl Writer { } /// Returns an [`ArroyBuilder`] to configure the available options to build the database. - pub fn builder<'a, R: Rng + SeedableRng>(&'a self, rng: &'a mut R) -> ArroyBuilder<'a, D, R> { + pub fn builder<'a, R: Rng + SeedableRng + Send + Sync>( + &'a self, + rng: &'a mut R, + ) -> ArroyBuilder<'a, D, R> { ArroyBuilder { writer: self, rng, inner: BuildOption::default() } } - fn build( + fn build( &self, wtxn: &mut RwTxn, rng: &mut R, @@ -512,37 +519,76 @@ impl Writer { // Before taking any references on the DB, remove all the items we must remove. self.delete_items_from_trees(wtxn, options, &mut roots, &to_delete)?; + // From this point on, we're not going to write anything to the DB until the very end. + // Each thread will have its own TmpNodes and we're going to write them all to the DB at the end. + + let leafs = ImmutableLeafs::new(wtxn, self.database, &item_indices, self.index)?; + let immutable_tree_nodes = + ImmutableTrees::new(wtxn, self.database, self.index, nb_tree_nodes)?; + let frozen_reader = FrozzenReader { + leafs: &leafs, + trees: &immutable_tree_nodes, + concurrent_node_ids: &concurrent_node_ids, + }; + + let files_tls = Arc::new(ThreadLocal::new()); + // The next method is called from multiple place so we have to update the progress here (options.progress)(WriterProgress { main: MainStep::InsertItemsInCurrentTrees, sub: None }); - let mut large_descendants = self.insert_items_in_current_trees( - wtxn, - rng, - options, - to_insert, - &roots, - nb_tree_nodes, - &concurrent_node_ids, - )?; + let mut descendants = + self.insert_items_in_current_trees(rng, options, to_insert, &roots, &frozen_reader)?; + // Create a new descendant that contains all items for every missing trees let nb_missing_trees = target_n_trees.saturating_sub(roots.len() as u64); for _ in 0..nb_missing_trees { let new_id = concurrent_node_ids.next()?; roots.push(new_id); - large_descendants.insert(new_id); - self.database.put( - wtxn, - &Key::tree(self.index, new_id), - &Node::Descendants(Descendants { descendants: Cow::Borrowed(&item_indices) }), - )?; + descendants.insert(new_id, item_indices.clone()); } - self.incremental_index_large_descendants( - wtxn, - rng, - options, - concurrent_node_ids, - large_descendants, - )?; + // When a task fails, a message must be sent in this channel. + // When a taks starts it must check if the channel contains something and stop asap. + // The channel will be openend only after all the tasks have been stopped. + let (error_snd, error_rcv) = bounded(1); + + rayon::scope(|s| { + let frozen_reader = &frozen_reader; + let files_tls = files_tls.clone(); + let error_snd = error_snd.clone(); + + // Spawn a thread that will create all the tasks + s.spawn(move |s| { + let rng = StdRng::from_seed(rng.gen()); + let ret = self.insert_descendants_in_file_and_spawn_tasks( + rng, + options, + &error_snd, + s, + frozen_reader, + files_tls, + descendants, + ); + if let Err(e) = ret { + let _ = error_snd.try_send(e); + } + }); + }); + + if let Ok(e) = error_rcv.try_recv() { + return Err(e); + } + + let files_tls = Arc::into_inner(files_tls).expect("Threads have all finished their works"); + for file in files_tls.into_iter() { + let tmp_nodes = file.into_inner().into_bytes_reader()?; + for (item_id, item_bytes) in tmp_nodes.to_insert() { + self.database.remap_data_type::().put( + wtxn, + &Key::tree(self.index, item_id), + item_bytes, + )?; + } + } tracing::debug!("write the metadata..."); (options.progress)(WriterProgress { main: MainStep::WriteTheMetadata, sub: None }); @@ -590,132 +636,180 @@ impl Writer { Ok(()) } - /// Loop over the list of large descendants and split them into sub trees with respect to the available memory. - fn incremental_index_large_descendants( - &self, - wtxn: &mut RwTxn, - rng: &mut R, - options: &BuildOption, - concurrent_node_ids: ConcurrentNodeIds, - mut large_descendants: RoaringBitmap, - ) -> Result<(), Error> { + /// Loop over the items of the specified descendant and explode it into a tree with respect to the available memory. + /// Returns the new descendants that are ready to store in the database. + /// Push more tasks to the scope for all the descendants that are still too large to fit in memory. + /// Write the tree squeleton to its local tmp file. That file must be written to the DB at the end. + #[allow(clippy::too_many_arguments)] + fn incremental_index_large_descendant<'scope, R: Rng + SeedableRng + Send + Sync>( + &'scope self, + mut rng: R, + options: &'scope BuildOption, + error_snd: &Sender, + scope: &Scope<'scope>, + descendant: (ItemId, RoaringBitmap), + frozen_reader: &'scope FrozzenReader, + tmp_nodes: Arc>>>, + ) -> Result<()> { (options.progress)(WriterProgress { main: MainStep::IncrementalIndexLargeDescendants, sub: None, }); + options.cancelled()?; + if error_snd.is_full() { + return Ok(()); + } - while let Some(descendant_id) = large_descendants.select(0) { - large_descendants.remove_smallest(1); - options.cancelled()?; - let node = self.database.get(wtxn, &Key::tree(self.index, descendant_id))?.unwrap(); - let Node::Descendants(Descendants { descendants }) = node else { unreachable!() }; - let mut descendants = descendants.into_owned(); + let tmp_node = tmp_nodes.get_or_try(|| match self.tmpdir.as_ref() { + Some(path) => TmpNodes::new_in(path).map(RefCell::new), + None => TmpNodes::new().map(RefCell::new), + })?; + // Safe to borrow mut here because we're the only thread running with this variable + let mut tmp_node = tmp_node.borrow_mut(); + let mut descendants = IntMap::::default(); + let (descendant_id, mut to_insert) = descendant; - // For each steps of the loop we starts by creating a new sub-tree with as many items as possible - // and then insert all the remaining items that couldn't be selected into this new created tree. - let (leafs, to_insert) = ImmutableLeafs::new( - wtxn, - self.database, - self.index, - &mut descendants, - options.available_memory.unwrap_or(usize::MAX), - )?; - let frozen_reader = FrozzenReader { - leafs: &leafs, - trees: &ImmutableTrees::empty(), - concurrent_node_ids: &concurrent_node_ids, - }; + let available_memory = + options.available_memory.unwrap_or(usize::MAX) / current_num_threads(); - let mut tmp_nodes = match self.tmpdir.as_ref() { - Some(path) => TmpNodes::new_in(path)?, - None => TmpNodes::new()?, - }; - let (root_id, nb_new_tree_nodes) = - self.make_tree_in_file(options, &frozen_reader, rng, &to_insert, &mut tmp_nodes)?; - // We cannot update our father so we're going to overwrite the new root node as ourselves. - tmp_nodes.remap(root_id, descendant_id); + // safe to unwrap because we know the descendant is large + let items_for_tree = + fit_in_memory::(available_memory, &mut to_insert, self.dimensions, &mut rng) + .unwrap(); - let tmp_nodes = tmp_nodes.into_bytes_reader()?; - // We never delete anything while building trees - for (item_id, item_bytes) in tmp_nodes.to_insert() { - options.cancelled()?; - let key = Key::tree(self.index, item_id); - self.database.remap_data_type::().put(wtxn, &key, item_bytes)?; + let (root_id, _nb_new_tree_nodes) = self.make_tree_in_file( + options, + frozen_reader, + error_snd, + &mut rng, + &items_for_tree, + &mut descendants, + Some(descendant_id), + &mut tmp_node, + )?; + assert_eq!(root_id, descendant_id); + + while let Some(to_insert) = + fit_in_memory::(available_memory, &mut to_insert, self.dimensions, &mut rng) + { + options.cancelled()?; + if error_snd.is_full() { + return Ok(()); } - let descendants_became_too_large = self.insert_items_in_current_trees( - wtxn, - rng, + insert_items_in_descendants_from_tmpfile( options, - descendants, - &[descendant_id], - nb_new_tree_nodes, - &concurrent_node_ids, + frozen_reader, + &mut tmp_node, + error_snd, + &mut rng, + descendant_id, + &to_insert, + &mut descendants, )?; - large_descendants |= descendants_became_too_large; } + drop(tmp_node); + self.insert_descendants_in_file_and_spawn_tasks( + rng, + options, + error_snd, + scope, + frozen_reader, + tmp_nodes, + descendants, + )?; + Ok(()) } + /// Explore the IntMap of descendants and when a descendant is too large to fit in memory, spawn a task to index it. + /// Otherwise, insert the descendant in the tempfile. #[allow(clippy::too_many_arguments)] + fn insert_descendants_in_file_and_spawn_tasks<'scope, R: Rng + SeedableRng + Send + Sync>( + &'scope self, + mut rng: R, + options: &'scope BuildOption, + error_snd: &Sender, + scope: &Scope<'scope>, + frozen_reader: &'scope FrozzenReader<'_, D>, + tmp_nodes: Arc>>>, + descendants: IntMap, + ) -> Result<(), Error> { + options.cancelled()?; + if error_snd.is_full() { + return Ok(()); + } + let tmp_node = tmp_nodes.get_or_try(|| match self.tmpdir.as_ref() { + Some(path) => TmpNodes::new_in(path).map(RefCell::new), + None => TmpNodes::new().map(RefCell::new), + })?; + // Safe to borrow mut here because we're the only thread running with this variable + let mut tmp_node = tmp_node.borrow_mut(); + + for (item_id, item_indices) in descendants.into_iter() { + options.cancelled()?; + if error_snd.is_full() { + return Ok(()); + } + if self.fit_in_descendant(options, item_indices.len()) { + tmp_node.put( + item_id, + &Node::Descendants(Descendants { descendants: Cow::Borrowed(&item_indices) }), + )?; + } else { + let tmp_nodes = tmp_nodes.clone(); + let rng = StdRng::from_seed(rng.gen()); + let error_snd = error_snd.clone(); + scope.spawn(move |s| { + let ret = self.incremental_index_large_descendant( + rng, + options, + &error_snd, + s, + (item_id, item_indices), + frozen_reader, + tmp_nodes, + ); + if let Err(e) = ret { + let _ = error_snd.try_send(e); + } + }); + } + } + + Ok(()) + } + fn insert_items_in_current_trees( &self, - wtxn: &mut RwTxn, rng: &mut R, options: &BuildOption, mut to_insert: RoaringBitmap, roots: &[ItemId], - nb_tree_nodes: u64, - concurrent_node_ids: &ConcurrentNodeIds, - ) -> Result { - let mut large_descendants = RoaringBitmap::new(); - + frozen_reader: &FrozzenReader, + ) -> Result> { if roots.is_empty() { - return Ok(large_descendants); + return Ok(IntMap::default()); } - while !to_insert.is_empty() { + let mut descendants = IntMap::::default(); + + while let Some(to_insert) = fit_in_memory::( + options.available_memory.unwrap_or(usize::MAX), + &mut to_insert, + self.dimensions, + rng, + ) { options.cancelled()?; - // If we have only one roots it means we're splitting a large descendants. - // Otherwise it means we're updating the whole database and will need all the tree nodes. - let immutable_tree_nodes = if roots.len() == 1 { - ImmutableTrees::sub_tree_from_id(wtxn, self.database, self.index, roots[0])? - } else { - ImmutableTrees::new(wtxn, self.database, self.index, nb_tree_nodes)? - }; - let (leafs, to_insert) = ImmutableLeafs::new( - wtxn, - self.database, - self.index, - &mut to_insert, - // We let the indexing process uses 2/3 of the memory for the items and the last third for the tree. - options - .available_memory - .map_or(usize::MAX, |memory| (memory as f64 * 2.0 / 3.0).floor() as usize), - )?; - let frozzen_reader = - FrozzenReader { leafs: &leafs, trees: &immutable_tree_nodes, concurrent_node_ids }; - let tmp_descendant_to_write = - self.insert_items_in_tree(options, rng, roots, &to_insert, &frozzen_reader)?; - - for (tmp_node, descendants) in tmp_descendant_to_write.iter() { - large_descendants |= descendants; - - for item_id in tmp_node.to_delete() { - options.cancelled()?; - let key = Key::tree(self.index, item_id); - self.database.remap_data_type::().delete(wtxn, &key)?; - } - for (item_id, item_bytes) in tmp_node.to_insert() { - options.cancelled()?; - let key = Key::tree(self.index, item_id); - self.database.remap_data_type::().put(wtxn, &key, item_bytes)?; - } + let desc = self.insert_items_in_tree(options, rng, roots, &to_insert, frozen_reader)?; + for (item_id, desc) in desc { + descendants.entry(item_id).or_default().extend(desc); } } - Ok(large_descendants) + + Ok(descendants) } fn reset_and_retrieve_updated_items( @@ -817,12 +911,11 @@ impl Writer { sub: None, }); - let mut tmp_nodes: TmpNodes> = match self.tmpdir.as_ref() { + let mut tmp_nodes: TmpNodes = match self.tmpdir.as_ref() { Some(path) => TmpNodes::new_in(path)?, None => TmpNodes::new()?, }; - // TODO: Parallelize for root in roots.iter_mut() { options.cancelled()?; let (new_root, _) = @@ -847,14 +940,16 @@ impl Writer { /// Remove items in O(n). We must explore the whole list of items. /// That could be reduced to O(log(n)) if we had a `RoTxn` of the previous state of the database. + /// Return the new node id and the list of all the items contained in this branch. + /// If there is too many items to create a single descendant, we return `None`. fn delete_items_in_file( &self, options: &BuildOption, rtxn: &RoTxn, current_node: ItemId, - tmp_nodes: &mut TmpNodes>, + tmp_nodes: &mut TmpNodes, to_delete: &RoaringBitmap, - ) -> Result<(ItemId, RoaringBitmap)> { + ) -> Result<(ItemId, Option)> { options.cancelled()?; match self.database.get(rtxn, &Key::tree(self.index, current_node))?.unwrap() { Node::Leaf(_) => unreachable!(), @@ -872,7 +967,7 @@ impl Writer { }), )?; } - Ok((current_node, new_descendants)) + Ok((current_node, Some(new_descendants))) } Node::SplitPlaneNormal(SplitPlaneNormal { normal, left, right }) => { let (new_left, left_items) = @@ -881,47 +976,62 @@ impl Writer { let (new_right, right_items) = self.delete_items_in_file(options, rtxn, right, tmp_nodes, to_delete)?; - let total_items = &left_items | &right_items; - - if self.fit_in_descendant(options, total_items.len()) { - // Since we're shrinking we KNOW that new_left and new_right are descendants - // thus we can delete them directly knowing there is no sub-tree to look at. - tmp_nodes.remove(new_left); - tmp_nodes.remove(new_right); - - tmp_nodes.put( - current_node, - &Node::Descendants(Descendants { - descendants: Cow::Owned(total_items.clone()), - }), - )?; - - // we should merge both branch and update ourselves to be a single descendant node - Ok((current_node, total_items)) - - // If we don't have any items in either the left or right we can delete ourselves and point directly to our child - } else if left_items.is_empty() { - tmp_nodes.remove(new_left); - tmp_nodes.remove(current_node); - Ok((new_right, total_items)) - } else if right_items.is_empty() { - tmp_nodes.remove(new_right); - tmp_nodes.remove(current_node); - Ok((new_left, total_items)) - } else { - // if either the left or the right changed we must update ourselves inplace - if new_left != left || new_right != right { - tmp_nodes.put( - current_node, - &Node::SplitPlaneNormal(SplitPlaneNormal { - normal, - left: new_left, - right: new_right, - }), - )?; + match (left_items, right_items) { + (Some(left_items), right_items) if left_items.is_empty() => { + tmp_nodes.remove(new_left); + tmp_nodes.remove(current_node); + Ok((new_right, right_items)) + } + (left_items, Some(right_items)) if right_items.is_empty() => { + tmp_nodes.remove(new_right); + tmp_nodes.remove(current_node); + Ok((new_left, left_items)) + } + (Some(left_items), Some(right_items)) => { + let total_items = left_items.len() + right_items.len(); + if self.fit_in_descendant(options, total_items) { + let total_items = left_items | right_items; + // Since we're shrinking we KNOW that new_left and new_right are descendants + // thus we can delete them directly knowing there is no sub-tree to look at. + tmp_nodes.remove(new_left); + tmp_nodes.remove(new_right); + + tmp_nodes.put( + current_node, + &Node::Descendants(Descendants { + descendants: Cow::Borrowed(&total_items), + }), + )?; + + // we should merge both branch and update ourselves to be a single descendant node + Ok((current_node, Some(total_items))) + } else { + if new_left != left || new_right != right { + tmp_nodes.put( + current_node, + &Node::SplitPlaneNormal(SplitPlaneNormal { + normal, + left: new_left, + right: new_right, + }), + )?; + } + Ok((current_node, None)) + } + } + (None, Some(_)) | (Some(_), None) | (None, None) => { + if new_left != left || new_right != right { + tmp_nodes.put( + current_node, + &Node::SplitPlaneNormal(SplitPlaneNormal { + normal, + left: new_left, + right: new_right, + }), + )?; + } + Ok((current_node, None)) } - - Ok((current_node, total_items)) } } } @@ -930,7 +1040,6 @@ impl Writer { /// Insert items in the specified trees without creating new tree nodes. /// Return the list of nodes modified that must be inserted into the database and /// the roaring bitmap of descendants that became too large in the process. - #[allow(clippy::too_many_arguments)] fn insert_items_in_tree( &self, opt: &BuildOption, @@ -938,143 +1047,65 @@ impl Writer { roots: &[ItemId], to_insert: &RoaringBitmap, frozen_reader: &FrozzenReader, - ) -> Result> { + ) -> Result> { repeatn(rng.next_u64(), roots.len()) .zip(roots) .map(|(seed, root)| { opt.cancelled()?; tracing::debug!("started updating tree {root:X}..."); let mut rng = R::seed_from_u64(seed.wrapping_add(*root as u64)); - let mut tmp_descendant: TmpNodes> = match self.tmpdir.as_ref() { - Some(path) => TmpNodes::new_in(path)?, - None => TmpNodes::new()?, - }; - let mut large_descendants = RoaringBitmap::new(); - self.insert_items_in_file( + let mut descendants_to_update = IntMap::with_hasher(BuildNoHashHasher::default()); + insert_items_in_descendants_from_frozen_reader( opt, frozen_reader, &mut rng, *root, to_insert, - &mut large_descendants, - &mut tmp_descendant, + &mut descendants_to_update, )?; tracing::debug!("finished updating tree {root:X}"); - Ok((tmp_descendant.into_bytes_reader()?, large_descendants)) + Ok(descendants_to_update) }) - .collect() - } - - /// Find all the descendants that matches the list of items to insert and write them to a file - #[allow(clippy::too_many_arguments)] - fn insert_items_in_file( - &self, - opt: &BuildOption, - frozen_reader: &FrozzenReader, - rng: &mut R, - current_node: ItemId, - to_insert: &RoaringBitmap, - large_descendants: &mut RoaringBitmap, - tmp_nodes: &mut TmpNodes>, - ) -> Result { - opt.cancelled()?; - match frozen_reader.trees.get(current_node)?.unwrap() { - Node::Leaf(_) => unreachable!(), - Node::Descendants(Descendants { descendants }) => { - let mut new_descendants = descendants.clone().into_owned(); - // insert all of our IDs in the descendants - new_descendants |= to_insert; - - if !self.fit_in_descendant(opt, new_descendants.len()) { - large_descendants.insert(current_node); - } - - // If the number of descendant changed it means we inserted new items and must overwrite the node - if descendants.len() != new_descendants.len() { - // otherwise we can just update our descendants - tmp_nodes.put( - current_node, - &Node::Descendants(Descendants { - descendants: Cow::Owned(new_descendants.clone()), - }), - )?; - } - Ok(current_node) - } - Node::SplitPlaneNormal(SplitPlaneNormal { normal, left, right }) => { - // Split the to_insert into two bitmaps on the left and right of this normal - let mut left_ids = RoaringBitmap::new(); - let mut right_ids = RoaringBitmap::new(); - - match normal { - None => { - randomly_split_children(rng, to_insert, &mut left_ids, &mut right_ids); - } - Some(ref normal) => { - for leaf in to_insert { - let node = frozen_reader.leafs.get(leaf)?.unwrap(); - match D::side(normal, &node) { - Side::Left => left_ids.insert(leaf), - Side::Right => right_ids.insert(leaf), - }; + .reduce( + || Ok(IntMap::with_hasher(BuildNoHashHasher::default())), + |acc, descendants_to_update| match (acc, descendants_to_update) { + (Err(e), _) | (_, Err(e)) => Err(e), + (Ok(mut acc), Ok(descendants_to_update)) => { + for (item_id, descendants) in descendants_to_update.into_iter() { + acc.entry(item_id).or_default().extend(descendants.clone()); } + Ok(acc) } - } - - let new_left = self.insert_items_in_file( - opt, - frozen_reader, - rng, - left, - &left_ids, - large_descendants, - tmp_nodes, - )?; - let new_right = self.insert_items_in_file( - opt, - frozen_reader, - rng, - right, - &right_ids, - large_descendants, - tmp_nodes, - )?; - - if new_left != left || new_right != right { - tmp_nodes.put( - current_node, - &Node::SplitPlaneNormal(SplitPlaneNormal { - normal, - left: new_left, - right: new_right, - }), - )?; - Ok(current_node) - } else { - Ok(current_node) - } - } - } + }, + ) } /// Creates a tree of nodes from the frozzen items that lives /// in the database and generates descendants, split normal /// and root nodes in files that will be stored in the database later. /// Return the root node + the total number of tree node generated. + #[allow(clippy::too_many_arguments)] fn make_tree_in_file( &self, opt: &BuildOption, reader: &FrozzenReader, + error_snd: &Sender, rng: &mut R, item_indices: &RoaringBitmap, - tmp_nodes: &mut TmpNodes>, + descendants: &mut IntMap, + next_id: Option, + tmp_nodes: &mut TmpNodes, ) -> Result<(ItemId, u64)> { opt.cancelled()?; + if error_snd.is_full() { + // We can return anything as the whole process is being stopped and nothing will be written + return Ok((0, 0)); + } if self.fit_in_descendant(opt, item_indices.len()) { - let item_id = reader.concurrent_node_ids.next()?; - let item = Node::Descendants(Descendants { descendants: Cow::Borrowed(item_indices) }); - tmp_nodes.put(item_id, &item)?; + let item_id = next_id.map(Ok).unwrap_or_else(|| reader.concurrent_node_ids.next())?; + // Don't write the descendants to the tmp nodes yet because they may become too large later + descendants.insert(item_id, item_indices.clone()); return Ok((item_id, 1)); } @@ -1123,11 +1154,29 @@ impl Writer { ) }; - let (left, l) = self.make_tree_in_file(opt, reader, rng, &children_left, tmp_nodes)?; - let (right, r) = self.make_tree_in_file(opt, reader, rng, &children_right, tmp_nodes)?; + let (left, l) = self.make_tree_in_file( + opt, + reader, + error_snd, + rng, + &children_left, + descendants, + None, + tmp_nodes, + )?; + let (right, r) = self.make_tree_in_file( + opt, + reader, + error_snd, + rng, + &children_right, + descendants, + None, + tmp_nodes, + )?; let normal = SplitPlaneNormal { normal, left, right }; - let new_node_id = reader.concurrent_node_ids.next()?; + let new_node_id = next_id.map(Ok).unwrap_or_else(|| reader.concurrent_node_ids.next())?; tmp_nodes.put(new_node_id, &Node::SplitPlaneNormal(normal))?; Ok((new_node_id, l + r + 1)) @@ -1262,3 +1311,189 @@ pub(crate) fn target_n_trees( } } } + +/// Find all the descendants that matches the list of items to insert and add them to the descendants_to_update map +#[allow(clippy::too_many_arguments)] +fn insert_items_in_descendants_from_frozen_reader( + opt: &BuildOption, + frozen_reader: &FrozzenReader, + rng: &mut R, + current_node: ItemId, + to_insert: &RoaringBitmap, + descendants_to_update: &mut IntMap, +) -> Result<()> { + opt.cancelled()?; + match frozen_reader.trees.get(current_node)?.unwrap() { + Node::Leaf(_) => unreachable!(), + Node::Descendants(Descendants { descendants }) => { + descendants_to_update.insert(current_node, descendants.into_owned() | to_insert); + } + Node::SplitPlaneNormal(SplitPlaneNormal { normal, left, right }) => { + // Split the to_insert into two bitmaps on the left and right of this normal + let mut left_ids = RoaringBitmap::new(); + let mut right_ids = RoaringBitmap::new(); + + match normal { + None => { + randomly_split_children(rng, to_insert, &mut left_ids, &mut right_ids); + } + Some(ref normal) => { + for leaf in to_insert { + let node = frozen_reader.leafs.get(leaf)?.unwrap(); + match D::side(normal, &node) { + Side::Left => left_ids.insert(leaf), + Side::Right => right_ids.insert(leaf), + }; + } + } + } + + if !left_ids.is_empty() { + insert_items_in_descendants_from_frozen_reader( + opt, + frozen_reader, + rng, + left, + &left_ids, + descendants_to_update, + )?; + } + if !right_ids.is_empty() { + insert_items_in_descendants_from_frozen_reader( + opt, + frozen_reader, + rng, + right, + &right_ids, + descendants_to_update, + )?; + } + } + } + Ok(()) +} + +/// Find all the descendants that matches the list of items to insert and add them to the descendants_to_update map +#[allow(clippy::too_many_arguments)] +fn insert_items_in_descendants_from_tmpfile( + opt: &BuildOption, + // We still need this to read the leafs + frozen_reader: &FrozzenReader, + // Must be mutable because we're going to seek and read in it + tmp_nodes: &mut TmpNodes, + error_snd: &Sender, + rng: &mut R, + current_node: ItemId, + to_insert: &RoaringBitmap, + descendants_to_update: &mut IntMap, +) -> Result<()> { + opt.cancelled()?; + if error_snd.is_full() { + return Ok(()); + } + match tmp_nodes.get(current_node)? { + Some(Node::Leaf(_) | Node::Descendants(_)) => unreachable!(), + None => { + *descendants_to_update.get_mut(¤t_node).unwrap() |= to_insert; + } + Some(Node::SplitPlaneNormal(SplitPlaneNormal { normal, left, right })) => { + // Split the to_insert into two bitmaps on the left and right of this normal + let mut left_ids = RoaringBitmap::new(); + let mut right_ids = RoaringBitmap::new(); + + match normal { + None => { + randomly_split_children(rng, to_insert, &mut left_ids, &mut right_ids); + } + Some(ref normal) => { + for leaf in to_insert { + let node = frozen_reader.leafs.get(leaf)?.unwrap(); + match D::side(normal, &node) { + Side::Left => left_ids.insert(leaf), + Side::Right => right_ids.insert(leaf), + }; + } + } + } + + if !left_ids.is_empty() { + insert_items_in_descendants_from_tmpfile( + opt, + frozen_reader, + tmp_nodes, + error_snd, + rng, + left, + &left_ids, + descendants_to_update, + )?; + } + if !right_ids.is_empty() { + insert_items_in_descendants_from_tmpfile( + opt, + frozen_reader, + tmp_nodes, + error_snd, + rng, + right, + &right_ids, + descendants_to_update, + )?; + } + } + } + Ok(()) +} + +/// Returns the items from the `to_insert` that fit in memory. +/// If there is no items to insert anymore, returns `None`. +/// If everything fits in memory, returns the `to_insert` bitmap. +pub(crate) fn fit_in_memory( + memory: usize, + to_insert: &mut RoaringBitmap, + dimensions: usize, + rng: &mut R, +) -> Option { + if to_insert.is_empty() { + return None; + } else if to_insert.len() <= dimensions as u64 { + // We need at least dimensions + one extra item to create a split. + // If we return less than that it won't be used. + return Some(std::mem::take(to_insert)); + } + + let page_size = page_size::get(); + let nb_page_allowed = (memory as f64 / page_size as f64).floor() as usize; + let largest_item_size = D::size_of_item(dimensions); + let nb_items_per_page = page_size / largest_item_size; + let nb_page_per_item = (largest_item_size as f64 / page_size as f64).ceil() as usize; + + let nb_items = if nb_items_per_page > 1 { + debug_assert_eq!(nb_page_per_item, 1); + nb_page_allowed * nb_items_per_page + } else if nb_page_per_item > 1 { + debug_assert_eq!(nb_items_per_page, 1); + nb_page_allowed / nb_page_per_item + } else { + nb_page_allowed + }; + + // We must insert at least dimensions items to create a split + let nb_items = if nb_items <= dimensions { dimensions + 1 } else { nb_items }; + + if nb_items as u64 >= to_insert.len() { + return Some(std::mem::take(to_insert)); + } + + let mut items = RoaringBitmap::new(); + + for _ in 0..nb_items { + let idx = rng.gen_range(0..to_insert.len()); + // Safe to unwrap because we know nb_items is smaller than the number of items in the bitmap + let item = to_insert.select(idx as u32).unwrap(); + items.insert(item); + to_insert.remove(item); + } + + Some(items) +}