From d28ea926ff00c18306f8f62fe9519c6f89b2fe78 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 21 Jun 2026 09:41:07 +0000 Subject: [PATCH] perf: use squared distance in clustering loops Replaced `libm::sqrt` with squared distance checks inside hot loops of `auto_k_selection` and `DBSCAN::region_query` in `crates/aether-core/src/ml/clustering.rs`. Also properly rejected negative/NaN thresholds and implemented an early loop break if `sum >= eps_sq`, keeping robust NaN handling. This significantly speeds up clustering algorithms by removing `sqrt` overhead. Co-authored-by: teerthsharma <78080953+teerthsharma@users.noreply.github.com> --- .jules/bolt.md | 3 +++ crates/aether-core/src/ml/clustering.rs | 34 ++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index ff54159..78ee4fa 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -9,3 +9,6 @@ ## 2026-06-20 - Fast Spatial Neighborhood Checks **Learning:** In hot paths doing spatial scanning (like SparseAttentionGraph), calling `libm::sqrt` for distance thresholds is a massive bottleneck. Moreover, using a squared distance optimization `d^2 < r^2` must be robust to NaN values. **Action:** Always optimize spatial neighborhood checks using squared distances (`eps_sq`) inside an inline loop. Explicitly check for invalid thresholds before the loop (e.g. `!(epsilon > 0.0)`), and use the `!(sum < eps_sq)` pattern for early exits to handle NaNs safely while matching standard Euclidean semantics without the `sqrt` overhead. +## 2026-06-21 - Optimization in DBSCAN and Auto-K Selection +**Learning:** In hot loops such as `auto_k_selection` and `DBSCAN::region_query`, avoiding `libm::sqrt` by using squared distances (`d^2 < r^2`) significantly reduces mathematical overhead and speeds up the algorithms. Also, explicitly rejecting negative or NaN thresholds before the loop (e.g., `!(epsilon > 0.0)`) and using early exits within the loop formatted as `!(sum < eps_sq)` safely handles `NaN` values without altering behavioral logic. +**Action:** Whenever iterating over distance computations that compare against a threshold, prefer comparing the sum of squared differences directly against the squared threshold instead of taking the square root. Handle edge cases like invalid distances properly. diff --git a/crates/aether-core/src/ml/clustering.rs b/crates/aether-core/src/ml/clustering.rs index 5614792..e6db911 100644 --- a/crates/aether-core/src/ml/clustering.rs +++ b/crates/aether-core/src/ml/clustering.rs @@ -273,6 +273,11 @@ impl KMeans { /// Automatically determine optimal K using topological analysis pub fn auto_k_selection(data: &[[f64; D]], n: usize, epsilon: f64) -> usize { + if !(epsilon > 0.0) { + return n.clamp(1, MAX_POINTS); + } + let eps_sq = epsilon * epsilon; + // Build epsilon-neighborhood graph and count connected components (β₀) let mut components = 0; let mut visited = [false; MAX_POINTS]; @@ -300,8 +305,17 @@ pub fn auto_k_selection(data: &[[f64; D]], n: usize, epsilon: f6 // Add neighbors for i in 0..n { if !visited[i] && i != current { - let dist = distance(&data[current], &data[i]); - if dist < epsilon && top < 64 { + let mut sum = 0.0; + let mut is_neighbor = true; + for d in 0..D { + let diff = data[current][d] - data[i][d]; + sum += diff * diff; + if !(sum < eps_sq) { + is_neighbor = false; + break; + } + } + if is_neighbor && top < 64 { stack[top] = i; top += 1; } @@ -447,9 +461,23 @@ impl DBSCAN { i: usize, ) -> heapless::Vec { let mut neighbors = heapless::Vec::new(); + if !(self.epsilon >= 0.0) { + return neighbors; + } + let eps_sq = self.epsilon * self.epsilon; for j in 0..n { - if distance(&data[i], &data[j]) <= self.epsilon { + let mut sum = 0.0; + let mut is_neighbor = true; + for d in 0..D { + let diff = data[i][d] - data[j][d]; + sum += diff * diff; + if !(sum <= eps_sq) { + is_neighbor = false; + break; + } + } + if is_neighbor { let _ = neighbors.push(j); } }