Skip to content

Commit

Permalink
Add basetype (#10)
Browse files Browse the repository at this point in the history
This is used to switch the `valuetype`: if `TN` is a ThickNumber then
`basetype(TN)(args...)` should construct from the argument-types
without coercion.
  • Loading branch information
timholy authored Oct 12, 2023
1 parent 445575e commit 07df3a7
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 1 deletion.
4 changes: 4 additions & 0 deletions ThickNumbersInterfaceTests/src/ThickNumbersInterfaceTests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,12 @@ function test_required(f::Function, @nospecialize(TN), @nospecialize(Ts=nothing)
@test hi x
@test lo loval(x)
@test hi hival(x)
if isa(TN, UnionAll)
@test basetype(TN) === TN
end
if Ts !== nothing
for T in Ts
@test basetype(TN{T}) === TN
for (x, l, h) in ((f(TN{T}, lo, hi), lo, hi), (f(TN{T}, 1, 2.0), 1.0, 2.0))
@test typeof(x) <: TN{T}
@test valuetype(x) === valuetype(typeof(x)) === T
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ Interval{T}(x::Number) where T = Interval{T}(x, x)
ThickNumbers.loval(x::Interval) = x.lo
ThickNumbers.hival(x::Interval) = x.hi
ThickNumbers.lohi(::Type{I}, lo, hi) where I<:Interval = I(lo, hi)
ThickNumbers.basetype(::Type{Interval{T}}) where T = Interval
ThickNumbers.basetype(::Type{Interval}) = Interval

# These are needed only for `Interval` and not `Interval{T}`
ThickNumbers.midrad(::Type{Interval}, mid::T, rad::T) where T = midrad(Interval{T}, mid, rad)
Expand Down
1 change: 1 addition & 0 deletions docs/src/developers.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ The following interface functions must be defined:

- [`loval(x)`](@ref): should return the lower span (i.e., the "lower bound" if such bounds are strict).
- [`hival(x)`](@ref): should return the upper span.
- [`basetype(x)`](@ref): should strip the `valuetype`, i.e., `basetype(Interval{Float64})` returns `Interval`.
- any arithmetic operations you need, e.g., `+`, `-`, `*`, and `/`

The implementation of these functions must satisfy certain requirements spelled out in the documentation of each of these functions.
Expand Down
1 change: 1 addition & 0 deletions docs/src/required.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Each package creating a new `ThickNumber` subtype must implement:
```@docs
loval
hival
basetype
```

If possible, you should also implement:
Expand Down
35 changes: 34 additions & 1 deletion src/ThickNumbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ using LinearAlgebra
export ThickNumber, FPTNException

# Traits
export valuetype
export valuetype, basetype

# These mimic IEEE Std 1788-2015, Table 9.2, but with `inf` and `sup`
# replaced by names that do not imply true bounds.
Expand Down Expand Up @@ -124,6 +124,39 @@ the presence of roundoff error.
"""
lohi(::Type{TN}, lo, hi) where TN<:ThickNumber = error("lohi not defined for $TN")

"""
basetype(::Type{TN}) where TN<:ThickNumber
Strip the `valuetype` from `TN`.
# Interface requirements
`basetype` must be implemented by all ThickNumber subtypes.
# Examples
In a package implementing `Interval` you would define
```julia
ThickNumbers.basetype(::Type{Interval{T}}) where T = Interval
ThickNumbers.basetype(::Type{Interval}) = Interval
```
so that
```julia
julia> basetype(Interval{Float64})
Interval
```
This can be used to construct `valuetype`-agnostic ThickNumbers:
```julia
julia> lohi(basetype(Interval{Float64}), 1, 2))
Interval{$Int}(1, 2)
```
"""
basetype(::Type{TN}) where TN<:ThickNumber = error("basetype not defined for $TN")

# Optional specializations

Expand Down
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ using IntervalArith
@test mag(Interval(-5, 1)) === 5
@test lohi(Interval{Float64}, 1, 3) === x
@test midrad(Interval{Float64}, 2, 1) === x
@test basetype(Interval{Float64}) === Interval

@test isequal_tn(Interval(1, 2), Interval(1, 2))
@test_throws FPTNException isequal(Interval(1, 2), Interval(1, 2))
Expand Down

0 comments on commit 07df3a7

Please sign in to comment.