feat: intern cell keys for O(1) comparison and indexing

Refactor DataStore to use interned keys (InternedKey) instead of
string-based CellKey for O(1) hash and compare operations.

Introduce SymbolTable-backed interning for all category and item
names, storing them as Symbol identifiers throughout the data structure.

Add secondary index mapping (category, item) pairs to sets of interned
keys, enabling efficient partial match queries without scanning all cells.

Optimize matching_values() to avoid allocating CellKey strings by
working directly with interned keys and intersecting index sets.

Update all callers to use new API: iter_cells(), matching_values(),
and internal lookup_key() helper.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
This commit is contained in:
Edward Langley
2026-04-05 01:07:08 -07:00
parent 6c211e5421
commit 82ad459c4e
3 changed files with 158 additions and 22 deletions

View File

@ -200,9 +200,9 @@ impl Model {
// Aggregate raw data across all None-axis categories
let values: Vec<f64> = self
.data
.matching_cells(&key.0)
.matching_values(&key.0)
.into_iter()
.filter_map(|(_, v)| v.as_f64())
.filter_map(|v| v.as_f64())
.collect();
if values.is_empty() {
@ -303,9 +303,9 @@ impl Model {
}
let values: Vec<f64> = model
.data
.matching_cells(&partial.0)
.matching_values(&partial.0)
.into_iter()
.filter_map(|(_, v)| v.as_f64())
.filter_map(|v| v.as_f64())
.collect();
match func {
AggFunc::Sum => Some(values.iter().sum()),