The Interval class

Main author: Simon Rohou

The Interval class represents closed and connected subsets of \(\mathbb{R}\). It is based on the gaol::interval structure and extends it with many utility methods.

Creating Intervals

An interval \([a,b]\) can be created using the constructor Interval(a, b). You can also create degenerate intervals, unbounded intervals, or intervals from collections.

x = Interval(3, 5)                          # [3.0, 5.0]
x = Interval(4.2)                           # [4.2, 4.2]
x = Interval()                              # [-∞, ∞]
x = Interval(-oo, -10)                      # [-∞, -10]
x = Interval([2.0, -3.0])                   # [-3.0, 2.0]
x = Interval([3.14])                        # [3.14, 3.14]

Note

Note that in Codac, the value positive infinity is represented by the constant oo (and -oo for negative infinity). One possible implementation of this constant is std::numeric_limits<double>::infinity() in C++, or math.inf in Python. Therefore, the declarations Interval() and Interval(-oo,oo) are equivalent.

Predefined constants

Some common intervals are predefined:

x = Interval()                              # [-∞,∞] (default value)
x = Interval.empty()                        # ∅
x = Interval.pi()                           # [π]
x = Interval.two_pi()                       # [2π]
x = Interval.half_pi()                      # [π/2]
x = Interval.zero()                         # [0]
x = Interval.one()                          # [1]

Note

Note that the constant \([\pi]\) is a reliable enclosure of the \(\pi\) value, that cannot be exactly represented in a computer with a single floating-point value.

x = Interval.pi()                           # [π]
# x = [3.141592653589793, 3.141592653589794]

In case you need a non-reliable floating point value for \(\pi\), you can use the PI constant already available.

Interval properties

You can access key interval properties:

x.lb()      # lower bound
x.ub()      # upper bound
x.mid()     # midpoint
x.rad()     # radius
x.diam()    # diameter
x.mag()     # magnitude
x.mig()     # mignitude
x.size()    # dimension (always 1)

Testing intervals

Intervals support a wide range of predicates:

  • is_empty(): test if the interval is empty

  • is_degenerated(): test if it’s of the form [a,a]

  • is_integer(): test if it’s an integer singleton

  • has_integer_bounds(): test if the bounds are integers

  • is_unbounded(): test if any bound is infinite

  • contains(x): test if it contains a real number

  • intersects(y): test if it intersects with another interval

  • is_subset(y): test if it is a subset of another

  • is_strict_subset(y), is_interior_subset(y), etc.

Advanced operations

Supported advanced methods for a given interval \([x]\)

Method

Description

inflate(rad)

Expands the interval by ±rad

bisect([ratio])

Splits into two intervals at given ratio (default is 0.49)

complementary()

Computes complement \(\mathbb{R} \setminus [x]\)

diff(y)

Computes set difference \([x] \setminus [y]\)

rand()

Returns a random sample within the interval

init()

Re-initializes to \([-\infty,\infty]\)

init_from_list(l)

Initializes using the hull of a list of values

Interval arithmetic

All standard arithmetic operations are supported, both element-wise and with real numbers.

x = Interval(2,3)
y = Interval(1,2)
z = x + y              # [3, 5]
z = x - 1              # [1, 2]
z = 2 * x              # [4, 6]
z = x / y              # [1, 3]

Unary and binary functions

Mathematical functions such as \(\sin\), \(\cos\), \(\exp\), \(\log\), \(\sqrt{\cdot}\), etc., are overloaded to work with intervals. Some examples:

x = Interval.half_pi()
x |= 0               # x = [0, π/2]
y = sin(x)           # y = [0, 1]
z = exp(x)           # z = [1, e^(π/2)]

For a complete list of additional operations, see the page Analytic operators.

Literals

In C++, a user-defined literal is provided in C++ to construct an interval directly from a floating-point number:

Interval x = 2.5_i;  // [2.5, 2.5]

Floating-point adjacency

The previous_float and next_float functions return the floating-point numbers directly adjacent to a given value. These functions are useful in the context of interval arithmetic to tightly control rounding directions.

inline double codac2::previous_float(double x)

Returns the previous representable double-precision floating-point value before x.

This function computes the largest double value that is strictly less than the input value x, effectively moving one step down in the floating-point representation.

See also

For obtaining the next representable double value greater than x, use next_float().

Parameters:

x – The input double value.

Returns:

The previous representable double value before x.

x = previous_float(1.0)
# x = 0.9999999999999999

Technical documentation

See the C++ API documentation of this class.