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 formInterval(1.0999999999999999, 1.3), as in theshowfullfunction.:midpoint: output in the midpoint-radius form, e.g.1.2 ± 0.100001.
sigdigits :: Intkeyword argument: number of significant digits to show in standard mode.decorations :: Boolkeyword 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)
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,expm1log,log1p,log2,log10sin,cos,tanasin,acos,atansinh,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,exp10atan,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: ArgumentError: `<` is purposely not supported for overlapping intervals. See instead `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: ArgumentError: `==` is purposely not supported for overlapping non-thin intervals. See instead `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!).