.. _sec-intervals-class:
The Interval class
==================
Main author: `Simon Rohou `_
The ``Interval`` class represents closed and connected subsets of :math:`\mathbb{R}`.
It is based on the ``gaol::interval`` structure and extends it with many utility methods.
Creating Intervals
------------------
An interval :math:`[a,b]` can be created using the constructor ``Interval(a, b)``.
You can also create degenerate intervals, unbounded intervals, or intervals from collections.
.. tabs::
.. group-tab:: Python
.. literalinclude:: src.py
:language: py
:start-after: [interval-class-1-beg]
:end-before: [interval-class-1-end]
:dedent: 4
.. group-tab:: C++
.. literalinclude:: src.cpp
:language: c++
:start-after: [interval-class-1-beg]
:end-before: [interval-class-1-end]
:dedent: 4
.. code-tab:: matlab
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::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:
.. tabs::
.. group-tab:: Python
.. literalinclude:: src.py
:language: py
:start-after: [interval-class-2-beg]
:end-before: [interval-class-2-end]
:dedent: 4
.. group-tab:: C++
.. literalinclude:: src.cpp
:language: c++
:start-after: [interval-class-2-beg]
:end-before: [interval-class-2-end]
:dedent: 4
.. code-tab:: matlab
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 :math:`[\pi]` is a reliable enclosure of the :math:`\pi` value, that cannot be exactly represented in a computer with a single floating-point value.
.. tabs::
.. group-tab:: Python
.. literalinclude:: src.py
:language: py
:start-after: [interval-class-3-beg]
:end-before: [interval-class-3-end]
:dedent: 4
.. group-tab:: C++
.. literalinclude:: src.cpp
:language: c++
:start-after: [interval-class-3-beg]
:end-before: [interval-class-3-end]
:dedent: 4
.. code-tab:: matlab
x = Interval().pi % [π]
% x = [3.14159, 3.1416]
In case you need a non-reliable floating point value for :math:`\pi`, you can use the ``PI`` constant already available.
Interval properties
-------------------
You can access key interval properties:
.. tabs::
.. group-tab:: Python
.. literalinclude:: src.py
:language: py
:start-after: [interval-class-4-beg]
:end-before: [interval-class-4-end]
:dedent: 4
.. group-tab:: C++
.. literalinclude:: src.cpp
:language: c++
:start-after: [interval-class-4-beg]
:end-before: [interval-class-4-end]
:dedent: 4
.. code-tab:: matlab
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
-------------------
.. list-table:: Supported advanced methods for a given interval :math:`[x]`
:widths: 30 70
:header-rows: 1
* - 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 :math:`\mathbb{R} \setminus [x]`
* - ``diff(y)``
- Computes set difference :math:`[x] \setminus [y]`
* - ``rand()``
- Returns a random sample within the interval
* - ``init()``
- Re-initializes to :math:`[-\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.
.. tabs::
.. group-tab:: Python
.. literalinclude:: src.py
:language: py
:start-after: [interval-class-5-beg]
:end-before: [interval-class-5-end]
:dedent: 4
.. group-tab:: C++
.. literalinclude:: src.cpp
:language: c++
:start-after: [interval-class-5-beg]
:end-before: [interval-class-5-end]
:dedent: 4
.. code-tab:: matlab
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 :math:`\sin`, :math:`\cos`, :math:`\exp`, :math:`\log`, :math:`\sqrt{\cdot}`, *etc.*, are overloaded to work with intervals. Some examples:
.. tabs::
.. group-tab:: Python
.. literalinclude:: src.py
:language: py
:start-after: [interval-class-6-beg]
:end-before: [interval-class-6-end]
:dedent: 4
.. group-tab:: C++
.. literalinclude:: src.cpp
:language: c++
:start-after: [interval-class-6-beg]
:end-before: [interval-class-6-end]
:dedent: 4
.. code-tab:: matlab
x = Interval.half_pi();
x.self_union(0); % x = [0, π/2]
y = sin(x); % y = [0, 1]
z = exp(x); % z = [1, exp(π/2)]
For a complete list of additional operations, see the page :ref:`sec-functions-analytic-operators`.
Literals
--------
In C++, a user-defined literal is provided in C++ to construct an interval directly from a floating-point number:
.. literalinclude:: src.cpp
:language: c++
:start-after: [interval-class-6b-beg]
:end-before: [interval-class-6b-end]
:dedent: 4
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.
.. doxygenfunction:: codac2::previous_float
:project: codac
.. tabs::
.. group-tab:: Python
.. literalinclude:: src.py
:language: py
:start-after: [interval-class-7-beg]
:end-before: [interval-class-7-end]
:dedent: 4
.. group-tab:: C++
.. literalinclude:: src.cpp
:language: c++
:start-after: [interval-class-7-beg]
:end-before: [interval-class-7-end]
:dedent: 4
.. code-tab:: matlab
x = previous_float(1.0);
% x = 0.9999999999999999
.. admonition:: Technical documentation
See the `C++ API documentation of this class <../../api/html/classcodac2_1_1_interval.html>`_.