Table of Contents

DiscreteInterval<T> Struct

Definition

Namespace
Bodu.Numerics
Assembly
Bodu.Numerics.dll
Package
Bodu.Numerics 1.0.0
Source
DiscreteInterval{T}.Conversions.cs

Represents an immutable interval over a discrete integer domain - a set of consecutive integers of type T - with successor/predecessor-aware emptiness and adjacency.

public readonly struct DiscreteInterval<T> : ISpanFormattable, IFormattable, IUtf8SpanFormattable, IEquatable<DiscreteInterval<T>> where T : IBinaryInteger<T>

Type Parameters

T

The integer type used for the interval's endpoints.

Implements
Inherited Members
Extension Methods

Examples

using Bodu.Numerics;

DiscreteInterval<int>.Open(1, 2).IsEmpty;                 // True - no integer strictly between 1 and 2

var a = DiscreteInterval<int>.Closed(1, 2);
var b = DiscreteInterval<int>.Closed(3, 4);
a.TryUnion(b, out var run);                               // run = [1, 4], result = true (successor-adjacent)

DiscreteInterval<int>.Closed(1, 10).Count;                // 10

Remarks

DiscreteInterval<T> is the discrete counterpart to the continuous Interval<T>. Where Interval<T> models a continuum of real coordinates, DiscreteInterval<T> models the set of representable integers between its bounds, which changes two behaviours fundamentally:

  • Emptiness reflects representable membership. An open interval whose bounds are consecutive integers - for example (1, 2) - contains no integer and is therefore empty, unlike the non-empty continuous interval over the same bounds.
  • Adjacency is by successor. Two intervals that leave no integer between them - for example [1, 2] and [3, 4] - are adjacent and union to a single run [1, 4], because no integer lies in the gap.

Every interval is canonicalized to inclusive [First, Last] integer bounds at construction (an open bound is shifted inward by one), so all equal integer sets share one representation and the default value is the empty set. Unbounded and half-bounded intervals ([a, +∞), (-∞, b], (-∞, +∞)) are supported through the AtLeast(T), AtMost(T), and All factory family.

Domain scope. This type is deliberately integer-only - its domain is IBinaryInteger<TSelf>. It is not a general discrete-domain abstraction: ranges over DateOnly, char, enum values, or a custom successor domain are out of scope. For a disconnected result - the union of several runs - use IntervalSet<T>.

Properties

All

Gets the unbounded interval (-∞, +∞) - every integer of T.

public static DiscreteInterval<T> All { get; }

Property Value

DiscreteInterval<T>

An interval unbounded on both sides.

Count

Gets the number of integers in the interval.

public T Count { get; }

Property Value

T

The inclusive count Last - First + 1, or zero when empty.

Exceptions

InvalidOperationException

The interval is unbounded, so its count is infinite.

OverflowException

The count does not fit in T - a full-domain interval has one more member than the type can represent.

Empty

Gets the canonical empty interval - the interval that contains no integer. Equal to every other empty DiscreteInterval<T> and to the default value.

public static DiscreteInterval<T> Empty { get; }

Property Value

DiscreteInterval<T>

An interval whose IsEmpty is true.

First

Gets the inclusive lower bound. Meaningful only for a non-empty, lower-bounded interval.

public T First { get; }

Property Value

T

The smallest integer in the interval.

IsBounded

Gets a value indicating whether both sides are bounded by a finite integer.

public bool IsBounded { get; }

Property Value

bool

true when neither side is unbounded; otherwise false.

IsEmpty

Gets a value indicating whether the interval contains no integer.

public bool IsEmpty { get; }

Property Value

bool

true when empty; otherwise false.

Last

Gets the inclusive upper bound. Meaningful only for a non-empty, upper-bounded interval.

public T Last { get; }

Property Value

T

The largest integer in the interval.

LowerUnbounded

Gets a value indicating whether the lower side is unbounded (extends to -∞).

public bool LowerUnbounded { get; }

Property Value

bool

true when lower-unbounded; otherwise false.

UpperUnbounded

Gets a value indicating whether the upper side is unbounded (extends to +∞).

public bool UpperUnbounded { get; }

Property Value

bool

true when upper-unbounded; otherwise false.

Methods

AtLeast(T)

Creates the lower-bounded interval [lower, +∞) - every integer greater than or equal to lower.

public static DiscreteInterval<T> AtLeast(T lower)

Parameters

lower T

The inclusive lower bound.

Returns

DiscreteInterval<T>

An upper-unbounded interval.

AtMost(T)

Creates the upper-bounded interval (-∞, upper] - every integer less than or equal to upper.

public static DiscreteInterval<T> AtMost(T upper)

Parameters

upper T

The inclusive upper bound.

Returns

DiscreteInterval<T>

A lower-unbounded interval.

Closed(T, T)

Creates the closed interval [lower, upper] - every integer from lower to upper inclusive.

public static DiscreteInterval<T> Closed(T lower, T upper)

Parameters

lower T

The inclusive lower bound.

upper T

The inclusive upper bound.

Returns

DiscreteInterval<T>

The interval, or Empty when lower exceeds upper.

ClosedOpen(T, T)

Creates the closed-open interval [lower, upper) - every integer from lower inclusive up to but excluding upper.

public static DiscreteInterval<T> ClosedOpen(T lower, T upper)

Parameters

lower T

The inclusive lower bound.

upper T

The exclusive upper bound.

Returns

DiscreteInterval<T>

The canonicalized interval.

Contains(T)

Determines whether value is an integer of this interval.

public bool Contains(T value)

Parameters

value T

The integer to test.

Returns

bool

true when the interval contains value; otherwise false.

Difference(DiscreteInterval<T>)

Returns this interval with the integers of other removed - the set difference this \ other - as zero, one, or two disjoint intervals.

public DiscreteIntervalPair<T> Difference(DiscreteInterval<T> other)

Parameters

other DiscreteInterval<T>

The interval whose integers are removed from this one.

Returns

DiscreteIntervalPair<T>

The remaining integers as a DiscreteIntervalPair<T>.

Examples

DiscreteInterval<int>.Closed(0, 10).Difference(DiscreteInterval<int>.Closed(3, 5));   // [0, 2] ∪ [6, 10]

Equals(DiscreteInterval<T>)

Determines whether this interval equals other as a set of integers. Because every interval is canonicalized to a single representation, equal sets compare equal by their stored fields.

public bool Equals(DiscreteInterval<T> other)

Parameters

other DiscreteInterval<T>

The interval to compare against.

Returns

bool

true when the two describe the same integer set; otherwise false.

Equals(object?)

Determines whether this interval equals the boxed obj.

public override bool Equals(object? obj)

Parameters

obj object

The object to compare against.

Returns

bool

true when obj is an equal DiscreteInterval<T>; otherwise false.

FromInterval(Interval<T>)

Creates the discrete interval containing exactly the integers of interval, snapping open bounds inward to the nearest contained integer.

public static DiscreteInterval<T> FromInterval(Interval<T> interval)

Parameters

interval Interval<T>

The continuous interval to convert.

Returns

DiscreteInterval<T>

The discrete interval of the integers within interval.

GetHashCode()

Returns a hash code consistent with Equals(DiscreteInterval<T>).

public override int GetHashCode()

Returns

int

A 32-bit hash code.

GreaterThan(T)

Creates the lower-bounded interval (lower, +∞) - every integer greater than lower.

public static DiscreteInterval<T> GreaterThan(T lower)

Parameters

lower T

The exclusive lower bound.

Returns

DiscreteInterval<T>

An upper-unbounded interval, or Empty when lower is the domain maximum and no integer lies above it.

Intersect(DiscreteInterval<T>)

Returns the intersection of this interval with other - the integers in both.

public DiscreteInterval<T> Intersect(DiscreteInterval<T> other)

Parameters

other DiscreteInterval<T>

The interval to intersect with.

Returns

DiscreteInterval<T>

The intersection, or Empty when the two share no integer.

LessThan(T)

Creates the upper-bounded interval (-∞, upper) - every integer less than upper.

public static DiscreteInterval<T> LessThan(T upper)

Parameters

upper T

The exclusive upper bound.

Returns

DiscreteInterval<T>

A lower-unbounded interval, or Empty when upper is the domain minimum and no integer lies below it.

Open(T, T)

Creates the open interval (lower, upper) - every integer strictly between the bounds. Adjacent integer bounds (for example (1, 2)) admit no integer and yield Empty.

public static DiscreteInterval<T> Open(T lower, T upper)

Parameters

lower T

The exclusive lower bound.

upper T

The exclusive upper bound.

Returns

DiscreteInterval<T>

The canonicalized interval.

OpenClosed(T, T)

Creates the open-closed interval (lower, upper] - every integer above lower up to and including upper.

public static DiscreteInterval<T> OpenClosed(T lower, T upper)

Parameters

lower T

The exclusive lower bound.

upper T

The inclusive upper bound.

Returns

DiscreteInterval<T>

The canonicalized interval.

Overlaps(DiscreteInterval<T>)

Determines whether this interval shares any integer with other.

public bool Overlaps(DiscreteInterval<T> other)

Parameters

other DiscreteInterval<T>

The interval to test for overlap.

Returns

bool

true when the two share at least one integer; otherwise false.

Singleton(T)

Creates the single-integer interval [value, value].

public static DiscreteInterval<T> Singleton(T value)

Parameters

value T

The single integer the interval contains.

Returns

DiscreteInterval<T>

A one-element interval.

SymmetricDifference(DiscreteInterval<T>)

Returns the symmetric difference of this interval and other - the integers in exactly one of the two - as zero, one, or two disjoint intervals.

public DiscreteIntervalPair<T> SymmetricDifference(DiscreteInterval<T> other)

Parameters

other DiscreteInterval<T>

The interval to symmetric-difference with.

Returns

DiscreteIntervalPair<T>

The integers covered by exactly one operand as a DiscreteIntervalPair<T>.

Examples

DiscreteInterval<int>.Closed(0, 5).SymmetricDifference(DiscreteInterval<int>.Closed(3, 8));   // [0, 2] ∪ [6, 8]

ToInterval()

Returns the continuous Interval<T> covering the same bounds, in canonical closed form.

public Interval<T> ToInterval()

Returns

Interval<T>

The equivalent continuous interval.

Remarks

The result is a continuous interval over the same integer endpoints; it contains the non-integer coordinates between them as well, so it is a superset of this discrete interval's integer members.

ToString()

Returns the canonical bracket-notation string representation - always closed on a finite side, using the infinity glyphs on an unbounded side, and the empty-set glyph for the empty interval.

public override string ToString()

Returns

string

"[first, last]" for a bounded interval, "[first, +∞)" / "(-∞, last]" / "(-∞, +∞)" for unbounded shapes, or "∅" when empty.

Remarks

All formatting delegates to the equivalent continuous Interval<T> (via ToInterval()), whose canonical closed form over the same endpoints renders identically.

ToString(string?)

Returns a string representation of this interval using the endpoint format specifier format applied to First and Last.

public string ToString(string? format)

Parameters

format string

A format specifier accepted by T (e.g. "D4", "N0").

Returns

string

The interval text with each endpoint formatted by format.

ToString(string?, IFormatProvider?)

Returns a string representation of this interval using the supplied endpoint format and culture.

public string ToString(string? format, IFormatProvider? formatProvider)

Parameters

format string

A format specifier accepted by T.

formatProvider IFormatProvider

The culture used to render each endpoint.

Returns

string

The interval text with each endpoint formatted by format under formatProvider.

TryFormat(Span<byte>, out int, ReadOnlySpan<char>, IFormatProvider?)

Attempts to format this interval into the provided UTF-8 byte span.

public bool TryFormat(Span<byte> utf8Destination, out int bytesWritten, ReadOnlySpan<char> format, IFormatProvider? provider)

Parameters

utf8Destination Span<byte>

The span that receives the formatted UTF-8 bytes.

bytesWritten int

When this method returns, contains the number of bytes written.

format ReadOnlySpan<char>

The endpoint format specifier.

provider IFormatProvider

The culture used to render each endpoint.

Returns

bool

true if formatting succeeded; otherwise, false.

TryFormat(Span<char>, out int, ReadOnlySpan<char>, IFormatProvider?)

Attempts to format this interval into the provided character span.

public bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider? provider)

Parameters

destination Span<char>

The span that receives the formatted characters.

charsWritten int

When this method returns, contains the number of characters written.

format ReadOnlySpan<char>

The endpoint format specifier.

provider IFormatProvider

The culture used to render each endpoint.

Returns

bool

true if formatting succeeded; otherwise, false.

TryUnion(DiscreteInterval<T>, out DiscreteInterval<T>)

Attempts to compute the union of this interval with other as a single contiguous run of integers, treating successor-adjacent intervals (no integer between them) as contiguous.

public bool TryUnion(DiscreteInterval<T> other, out DiscreteInterval<T> result)

Parameters

other DiscreteInterval<T>

The interval to union with.

result DiscreteInterval<T>

When this method returns true, the contiguous union; otherwise Empty.

Returns

bool

true when the two intervals overlap or are successor-adjacent; false when an integer gap separates them so their union needs two runs.

Examples

DiscreteInterval<int>.Closed(1, 2).TryUnion(DiscreteInterval<int>.Closed(3, 4), out var run);
// run == [1, 4], result == true (no integer lies between 2 and 3)

Operators

operator ==(DiscreteInterval<T>, DiscreteInterval<T>)

Determines whether two intervals are equal as sets.

public static bool operator ==(DiscreteInterval<T> left, DiscreteInterval<T> right)

Parameters

left DiscreteInterval<T>

The first interval.

right DiscreteInterval<T>

The second interval.

Returns

bool

true when equal; otherwise false.

operator !=(DiscreteInterval<T>, DiscreteInterval<T>)

Determines whether two intervals are not equal as sets.

public static bool operator !=(DiscreteInterval<T> left, DiscreteInterval<T> right)

Parameters

left DiscreteInterval<T>

The first interval.

right DiscreteInterval<T>

The second interval.

Returns

bool

true when they differ; otherwise false.

Applies to

ProductVersions
.NET8, 10