Skip to content

Add IntervalSet#179

Draft
llucax wants to merge 2 commits into
frequenz-floss:v1.x.xfrom
llucax:interval-set
Draft

Add IntervalSet#179
llucax wants to merge 2 commits into
frequenz-floss:v1.x.xfrom
llucax:interval-set

Conversation

@llucax

@llucax llucax commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Add IntervalSet[T] to frequenz.core.math: a normalized, immutable set of Interval[T] values that supports O(log n) membership testing via the in operator.

On construction, IntervalSet sorts the passed intervals by start and merges any that overlap or share an inclusive endpoint. Only the normalized form is stored, so equality, hashing, and iteration are well-defined regardless of input order; callers that need the original inputs can keep them separately.

Unbounded intervals are handled via the existing Interval[T] convention: a None start is treated as -infinity and a None end as +infinity during sort/merge, so for example IntervalSet((Interval(None, 5), Interval(3, None))) collapses to a single Interval(None, None).

The generic container-of-containers variant discussed during design is deferred: there is no immediate use case, and adding IntervalSet alone is a fully additive step that does not foreclose a future generic type in a separate module.

`Interval`'s type parameter no longer includes `None`. The exported type
variable `LessThanComparableOrNoneT` (bound to
`LessThanComparable | None`) was deprecated and replaced with
`LessThanComparableT` (bound to `LessThanComparable`).

`None` is still accepted as a value for `start` / `end` to indicate an
unbounded side, but it is treated purely as bound metadata rather than
a value in the interval's comparable space.

Note that explicitly using `Interval[int | None]` still works, as
`(int | None) | None` is equivalent to `int | None`, even when it is no
longer needed nor recommended. Old code will mostly work, but there is
one soft breaking change: `None in some_interval` and
`None in some_interval_set` is now a type-check error at call sites,
matching the design intent that `None` is a bound marker and never a
member value.

Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
@github-actions github-actions Bot added part:docs Affects the documentation part:tests Affects the unit, integration and performance (benchmarks) tests part:math Affects the math module labels Jul 3, 2026
@llucax

llucax commented Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

Draft because it is based in #178.

Add IntervalSet[T] to frequenz.core.math: a normalized, immutable set of
Interval[T] values that supports O(log n) membership testing via the `in`
operator.

On construction, IntervalSet sorts the passed intervals by start and
merges any that overlap or share an inclusive endpoint. Only the
normalized form is stored, so equality, hashing, and iteration are
well-defined regardless of input order; callers that need the original
inputs can keep them separately.

Unbounded intervals are handled via the existing Interval[T] convention:
a None start is treated as -infinity and a None end as +infinity during
sort/merge, so for example IntervalSet((Interval(None, 5), Interval(3,
None))) collapses to a single Interval(None, None).

The generic container-of-containers variant discussed during design is
deferred: there is no immediate use case, and adding IntervalSet alone
is a fully additive step that does not foreclose a future generic type
in a separate module.

Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

part:docs Affects the documentation part:math Affects the math module part:tests Affects the unit, integration and performance (benchmarks) tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant