Manipulating intervals

Display modes

There are several useful output representations for intervals. The display is controlled globally by the setdisplay function, which has the following options:

  • interval output format:

    • :infsup: output of the form [1.09999, 1.30001], rounded to the current number of significant figures.

    • :full: output of the form Interval(1.0999999999999999, 1.3), as in the showfull function.

    • :midpoint: output in the midpoint-radius form, e.g. 1.2 ± 0.100001.

  • sigdigits :: Int keyword argument: number of significant digits to show in standard mode.

  • decorations :: Bool keyword argument: whether to show decorations or not.

julia> using IntervalArithmeticjulia> a = interval(1.1, pi) # default displayInterval{Float64}(1.1, 3.1415926535897936, com, true)julia> setdisplay(; sigdigits = 10)Display options:  - format: full  - decorations: true (ignored)  - NG flag: true (ignored)  - significant digits: 10 (ignored)julia> aInterval{Float64}(1.1, 3.1415926535897936, com, true)julia> setdisplay(:full)Display options:  - format: full  - decorations: true (ignored)  - NG flag: true (ignored)  - significant digits: 10 (ignored)julia> aInterval{Float64}(1.1, 3.1415926535897936, com, true)julia> setdisplay(:midpoint)Display options:  - format: midpoint  - decorations: true  - NG flag: true  - significant digits: 10julia> a(2.120796327 ± 1.020796327)_comjulia> setdisplay(; sigdigits = 4)Display options:  - format: midpoint  - decorations: true  - NG flag: true  - significant digits: 4julia> a(2.121 ± 1.021)_comjulia> setdisplay(:infsup)Display options:  - format: infsup  - decorations: true  - NG flag: true  - significant digits: 4julia> a[1.1, 3.142]_com

Arithmetic operations

Basic arithmetic operations (+, -, *, /, ^) are defined for pairs of intervals in a standard way: the result is the smallest interval containing the result of operating with each element of each interval. More precisely, for two intervals $X$ and $Y$ and an operation $\bigcirc$, we define the operation on the two intervals by

\[X \bigcirc Y \bydef \{ x \bigcirc y \,:\, x \in X \text{ and } y \in Y \}.\]

For example,

julia> using IntervalArithmeticjulia> setdisplay(:full)Display options:  - format: full  - decorations: true (ignored)  - NG flag: true (ignored)  - significant digits: 4 (ignored)julia> X = interval(0, 1)Interval{Float64}(0.0, 1.0, com, true)julia> Y = interval(1, 2)Interval{Float64}(1.0, 2.0, com, true)julia> X + YInterval{Float64}(1.0, 3.0, com, true)

Due to the above definition, subtraction of two intervals may give poor enclosures:

julia> X - XInterval{Float64}(-1.0, 1.0, com, true)

Powers

Several power functions coexist, and they differ by the domain of definition of the underlying point function:

FunctionPoint functionDomain of definition
pown(x, n)$x^n$, with $n$ an integerall reals if $n \ge 0$, all non-zero reals if $n < 0$
pow(x, y)$\exp(y \log(x))$$x > 0$, together with $x = 0$ if $y > 0$
rootn(x, n)$x^{1/n}$, with $n$ an integerall reals if $n$ is odd, all non-negative reals if $n$ is even

These are the functions pown, pow and rootn of Table 9.1 of the IEEE Standard 1788-2015. The pairs lying outside of the domain of definition are simply discarded; the result may then be empty, and the decoration of the result is trv whenever the arguments are not entirely contained in the domain of definition. In particular, since the point function underlying pow is only defined for a positive base, the negative part of the interval is discarded:

julia> x = interval(-4, -2)Interval{Float64}(-4.0, -2.0, com, true)julia> pown(x, 2)Interval{Float64}(4.0, 16.0, com, true)julia> pow(x, interval(2))∅_trv

The operator ^ is not part of the IEEE Standard 1788-2015. It falls back on pown whenever the exponent is a thin integer, and on pow otherwise:

julia> x ^ interval(2)Interval{Float64}(4.0, 16.0, com, true)julia> x ^ interval(2.5)∅_trv

Lastly, fastpow and fastpown are faster variants of pow and pown respectively, at the cost of maybe returning a larger interval. They follow the same domain conventions as their counterparts, and they are the ones used by ^ under the default :fast power mode, see Configuration options.

Elementary functions

The main elementary functions are implemented. The functions for Interval{Float64} internally use routines from the correctly-rounded CRlibm library where possible, i.e. for the following functions defined in that library:

  • exp, expm1
  • log, log1p, log2, log10
  • sin, cos, tan
  • asin, acos, atan
  • sinh, cosh

Other functions that are implemented for Interval{Float64} internally convert to an Interval{BigFloat}, and then use routines from the MPFR library (BigFloat in Julia):

  • ^
  • exp2, exp10
  • atan, atanh

In particular, in order to obtain correct rounding for the power function (^), intervals are converted to and from BigFloat; this implies a significant slow-down in this case.

For example,

julia> X = interval(1)Interval{Float64}(1.0, 1.0, com, true)julia> sin(X)Interval{Float64}(0.8414709848078965, 0.8414709848078966, com, true)julia> cos(cosh(X))Interval{Float64}(0.027712143770207736, 0.02771214377020796, com, true)julia> setprecision(BigFloat, 53)53julia> Y = big(X)Interval{BigFloat}(1.0, 1.0, com, true)julia> sin(Y)Interval{BigFloat}(0.8414709848078965, 0.84147098480789662, com, true)julia> cos(cosh(Y))Interval{BigFloat}(0.027712143770207736, 0.027712143770207961, com, true)julia> setprecision(BigFloat, 128)128julia> sin(Y)Interval{BigFloat}(0.8414709848078965, 0.84147098480789662, com, true)

Comparisons

If the result of a comparison can be established with guarantee, it will be return, otherwise, an error is thrown.

julia> interval(1) < interval(2)truejulia> interval(1, 5) < interval(7, 9)truejulia> interval(1, 5) < interval(4.99, 9)ERROR: InconclusiveBooleanOperation: The operation `Interval{Float64}(1.0, 5.0, com, true) < Interval{Float64}(4.99, 9.0, com, true)` cannot be determined unambiguously. See the documentation for more information. See also `strictprecedes`.julia> interval(1.23) == interval(1.23)truejulia> interval(1.23) == interval(4.99, 9)falsejulia> interval(1.23) == interval(1.2, 1.3)ERROR: InconclusiveBooleanOperation: The operation `Interval{Float64}(1.23, 1.23, com, true) == Interval{Float64}(1.2, 1.3, com, true)` cannot be determined unambiguously. See the documentation for more information. See also `isequal_interval`.

In particular, if ... else ... end statements used for floating-points will often break with intervals.

See Philosophy for more details and why this choice was made.

Set operations

Set operations are all disallowed and error on intervals to avoid ambiguities. To perform set operations on intervals, use the *_interval equivalent explicitly, e.g. issubset_interval instead of issubset.

julia> issubset(interval(1, 2), interval(2))ERROR: ArgumentError: `issubset` is purposely not supported for intervals. See instead `issubset_interval`julia> issubset_interval(interval(1, 2), interval(2))falsejulia> intersect(interval(1, 2), interval(2))ERROR: ArgumentError: `intersect` is purposely not supported for intervals. See instead `intersect_interval`julia> intersect_interval(interval(1, 2), interval(2))Interval{Float64}(2.0, 2.0, trv, true)

See Philosophy for more details and why this choice was made.

Piecewise functions

Since intervals don't play well with if ... else ... end statement, we provide a utility to define function by pieces:

julia> myabs = Piecewise(           Domain{:open, :closed}(-Inf, 0) => x -> -x,           Domain{:open, :open}(0, Inf) => identity       )Piecewise function with 2 pieces:  (-Inf, 0] -> Main.var"#2#3"()  (0, Inf) -> identityjulia> myabs(-1.23)1.23julia> myabs(interval(-1, 23))Interval{Float64}(0.0, 23.0, def, true)

The resulting function work with both standard numbers and intervals, and deal properly with the decorations of intervals.

Custom interval bounds type

A BareInterval{T} or Interval{T} have the restriction T <: Union{Rational,AbstractFloat} which is the parametric type for the bounds of the interval. Supposing one wishes to use their own numeric type MyNumType <: Union{Rational,AbstractFloat}, they must provide their own arithmetic operations (with correct rounding!).