- `SegmentTree<T, TMonoid>` — range aggregates over an arbitrary associative fold. The gap was written down in the library's own documentation: the `FenwickTree<T>` section of the API reference closed by saying a segment tree "are the next step (not shipped)". Fenwick is constrained to `INumber<T>` for a structural reason, not a stylistic one — its range query is the *difference* of two prefix folds, so the operation must have an inverse — which left the entire non-invertible half of the range-query space (min, max, gcd, bitwise and/or, any user-written fold) unreachable, with no BCL counterpart either. Status: `done` — `IMonoid<T>` ships as a `struct` type parameter alongside five built-in folds, so `Combine` inlines rather than costing a virtual call per level. Three calls are worth recording. First, the layout is the flat **`2n`** array, not the power-of-two-padded `4n` one that is usually recommended: the objection to `2n` is that the leaves sit in a rotated order at non-power-of-two lengths, so an internal node can span a wrapped range — but a query that walks outward from both ends into two separate accumulators never combines such a node into the wrong side, and an exhaustive differential sweep over every length and every range under a **non-commutative** fold pins that. A commutative fold cannot observe the difference, which is why min/max/sum could not be the oracle and the fuzz target and the differential suite both run "first non-zero wins" and string concatenation instead. The one visible consequence is that `Aggregate` is a query rather than a root read. Second, **lazy propagation was left out** rather than half-shipped: range updates need a second monoid describing how updates compose plus a distributive law relating the two, which is a different type with a different contract, and it is stated as an exclusion on every doc surface. Third, `T` is deliberately **unconstrained** — a `string`-concatenation monoid is a legitimate fold and the tree's own storage does not care — where the sibling `FenwickTree<T>` is `struct, INumber<T>`. The kill criterion (≥10x over the array scan on interleaved update + range-min at 100k) was measured after implementation and cleared at **14.8x**, with **81x** on a query batch against a pre-built tree; at 1k it is only 1.4x, and the README and API reference both lead with that rather than quoting the headline alone. The floating-point caveat on `MinMonoid` / `MaxMonoid` (the identity is the largest / smallest *finite* value, and a `NaN` resolves by operand position) is documented on the type, in the API reference and in the tests. Tracked in [#348](https://github.com/marius-bughiu/Celerity/issues/348).
0 commit comments