pub struct TreeArena {
pub feature_idx: Vec<u32>,
pub threshold: Vec<f64>,
pub left: Vec<NodeId>,
pub right: Vec<NodeId>,
pub leaf_value: Vec<f64>,
pub is_leaf: Vec<bool>,
pub depth: Vec<u16>,
pub sample_count: Vec<u64>,
pub categorical_mask: Vec<Option<u64>>,
}alloc only.Expand description
Structure-of-Arrays arena storage for tree nodes.
All node properties are stored in parallel vectors for cache efficiency.
Internal nodes have feature_idx + threshold + children.
Leaf nodes have leaf_value.
§Invariants
- All vectors have the same length at all times.
- A leaf node has
is_leaf[id] == true,left[id] == NONE,right[id] == NONE. - An internal node has
is_leaf[id] == falseand validleft/rightchildren. depth[id]is set at allocation time and never changes.
Fields§
§feature_idx: Vec<u32>Feature index used for splitting (only meaningful for internal nodes).
threshold: Vec<f64>Split threshold (samples with feature <= threshold go left).
left: Vec<NodeId>Left child NodeId (NONE for leaves).
right: Vec<NodeId>Right child NodeId (NONE for leaves).
leaf_value: Vec<f64>Leaf prediction value.
is_leaf: Vec<bool>Whether this node is a leaf.
depth: Vec<u16>Depth of this node in the tree (root = 0).
sample_count: Vec<u64>Number of samples routed through this node.
categorical_mask: Vec<Option<u64>>Categorical split bitmask. For categorical splits, bit i set means
category i routes left. None for continuous splits (threshold-based).
Implementations§
Source§impl TreeArena
impl TreeArena
Sourcepub fn with_capacity(cap: usize) -> Self
pub fn with_capacity(cap: usize) -> Self
Create an empty arena with pre-allocated capacity for cap nodes.
This avoids reallocation when the maximum tree size is known upfront.
Sourcepub fn add_leaf(&mut self, depth: u16) -> NodeId
pub fn add_leaf(&mut self, depth: u16) -> NodeId
Allocate a new leaf node with value 0.0 at the given depth.
Returns the NodeId of the newly created leaf.
Sourcepub fn split_leaf(
&mut self,
leaf_id: NodeId,
feature_idx: u32,
threshold: f64,
left_value: f64,
right_value: f64,
) -> (NodeId, NodeId)
pub fn split_leaf( &mut self, leaf_id: NodeId, feature_idx: u32, threshold: f64, left_value: f64, right_value: f64, ) -> (NodeId, NodeId)
Convert a leaf node into an internal (split) node, creating two new leaf children.
The parent’s is_leaf flag is cleared and its feature_idx/threshold
are set. Two fresh leaf nodes are allocated at depth = parent.depth + 1
with the specified initial values.
§Panics
Panics if leaf_id does not reference a current leaf node.
§Returns
(left_id, right_id) – the NodeIds of the two new children.
Sourcepub fn split_leaf_categorical(
&mut self,
leaf_id: NodeId,
feature_idx: u32,
threshold: f64,
left_value: f64,
right_value: f64,
mask: u64,
) -> (NodeId, NodeId)
pub fn split_leaf_categorical( &mut self, leaf_id: NodeId, feature_idx: u32, threshold: f64, left_value: f64, right_value: f64, mask: u64, ) -> (NodeId, NodeId)
Split a leaf using a categorical bitmask instead of a threshold.
The mask is a u64 where bit i set means category i goes left.
The threshold is still stored as the midpoint of the split partition
for backward compatibility, but routing uses the bitmask.
§Panics
Panics if leaf_id does not reference a current leaf node.
Sourcepub fn get_categorical_mask(&self, id: NodeId) -> Option<u64>
pub fn get_categorical_mask(&self, id: NodeId) -> Option<u64>
Return the categorical bitmask for a split node, if it’s a categorical split.
Sourcepub fn set_leaf_value(&mut self, id: NodeId, value: f64)
pub fn set_leaf_value(&mut self, id: NodeId, value: f64)
Sourcepub fn get_feature_idx(&self, id: NodeId) -> u32
pub fn get_feature_idx(&self, id: NodeId) -> u32
Return the feature index used for splitting at this node.
Sourcepub fn get_threshold(&self, id: NodeId) -> f64
pub fn get_threshold(&self, id: NodeId) -> f64
Return the split threshold for this node.
Sourcepub fn get_sample_count(&self, id: NodeId) -> u64
pub fn get_sample_count(&self, id: NodeId) -> u64
Return the sample count for this node.
Sourcepub fn increment_sample_count(&mut self, id: NodeId)
pub fn increment_sample_count(&mut self, id: NodeId)
Increment the sample count for this node by one.