-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Control rounding for many functions #56
Changes from all commits
30e3b26
adc81aa
5e033e6
3767485
da7d389
a54f549
7725141
8aacce1
e0ea364
0987ad5
9a07de4
92ac0b3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,20 @@ | ||
language: julia | ||
|
||
sudo: required | ||
|
||
services: | ||
- docker | ||
|
||
os: | ||
- linux | ||
- osx | ||
|
||
julia: | ||
- release | ||
- 0.4 | ||
- nightly | ||
|
||
notifications: | ||
email: false | ||
|
||
after_success: | ||
- julia -e 'cd(Pkg.dir("ValidatedNumerics")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder()); Codecov.submit(process_folder())' | ||
|
||
sudo: false | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
julia 0.3 | ||
julia 0.4 | ||
Docile | ||
Compat | ||
FactCheck 0.3 | ||
Polynomials | ||
|
||
CRlibm |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -85,10 +85,10 @@ function +{T<:Real}(a::Interval{T}, b::Interval{T}) | |
end | ||
+(a::Interval) = a | ||
|
||
-{T<:Real}(a::Interval{T}) = @round(T, -a.hi, -a.lo) | ||
-(a::Interval) = Interval(-a.hi, -a.lo) | ||
function -{T<:Real}(a::Interval{T}, b::Interval{T}) | ||
(isempty(a) || isempty(b)) && return emptyinterval(T) | ||
a + (-b) # @round(a.lo - b.hi, a.hi - b.lo) | ||
@round(T, a.lo - b.hi, a.hi - b.lo) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think |
||
end | ||
|
||
|
||
|
@@ -112,23 +112,19 @@ function *{T<:Real}(a::Interval{T}, b::Interval{T}) | |
a.hi < zero(T) && return @round(T, a.lo*b.hi, a.lo*b.lo) | ||
return @round(T, min(a.lo*b.hi, a.hi*b.lo), max(a.lo*b.lo, a.hi*b.hi)) | ||
end | ||
# @round(T, min( a.lo*b.lo, a.lo*b.hi, a.hi*b.lo, a.hi*b.hi ), | ||
# max( a.lo*b.lo, a.lo*b.hi, a.hi*b.lo, a.hi*b.hi ) ) | ||
end | ||
|
||
|
||
## Division | ||
|
||
function inv(a::Interval) | ||
function inv{T<:Real}(a::Interval{T}) | ||
isempty(a) && return emptyinterval(a) | ||
|
||
T = eltype(a) | ||
S = typeof(inv(a.lo)) | ||
if in(zero(T), a) | ||
a.lo < zero(T) == a.hi && return Interval{S}(-Inf, inv(a.lo)) | ||
a.lo == zero(T) < a.hi && return Interval{S}(inv(a.hi), Inf) | ||
a.lo < zero(T) < a.hi && return entireinterval(S) | ||
a == zero(a) && return emptyinterval(S) | ||
a.lo < zero(T) == a.hi && return @round(T, -Inf, inv(a.lo)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I must admit, that this one was actually caught by ITF1788... |
||
a.lo == zero(T) < a.hi && return @round(T, inv(a.hi), Inf) | ||
a.lo < zero(T) < a.hi && return entireinterval(T) | ||
a == zero(a) && return emptyinterval(T) | ||
end | ||
|
||
@round(T, inv(a.hi), inv(a.lo)) | ||
|
@@ -174,24 +170,60 @@ function /{T<:Real}(a::Interval{T}, b::Interval{T}) | |
|
||
end | ||
end | ||
# a * inv(b) | ||
# @round(S, min( a.lo/b.lo, a.lo/b.hi, a.hi/b.lo, a.hi/b.hi ), | ||
# max( a.lo/b.lo, a.lo/b.hi, a.hi/b.lo, a.hi/b.hi ) ) | ||
end | ||
|
||
//(a::Interval, b::Interval) = a / b # to deal with rationals | ||
|
||
|
||
## fma: fused multiply-add | ||
function fma(a::Interval, b::Interval, c::Interval) | ||
T = promote_type(eltype(a), eltype(b), eltype(c)) | ||
|
||
(isempty(a) || isempty(b) || isempty(c)) && return emptyinterval(T) | ||
|
||
if isentire(a) | ||
b == zero(b) && return c | ||
return entireinterval(T) | ||
elseif isentire(b) | ||
a == zero(a) && return c | ||
return entireinterval(T) | ||
end | ||
|
||
lo = with_rounding(T, RoundDown) do | ||
lo1 = fma(a.lo, b.lo, c.lo) | ||
lo2 = fma(a.lo, b.hi, c.lo) | ||
lo3 = fma(a.hi, b.lo, c.lo) | ||
lo4 = fma(a.hi, b.hi, c.lo) | ||
min(lo1, lo2, lo3, lo4) | ||
end | ||
hi = with_rounding(T, RoundUp) do | ||
hi1 = fma(a.lo, b.lo, c.hi) | ||
hi2 = fma(a.lo, b.hi, c.hi) | ||
hi3 = fma(a.hi, b.lo, c.hi) | ||
hi4 = fma(a.hi, b.hi, c.hi) | ||
max(hi1, hi2, hi3, hi4) | ||
end | ||
Interval(lo, hi) | ||
end | ||
|
||
|
||
## Scalar functions on intervals (no directed rounding used) | ||
|
||
function mag(a::Interval) | ||
function mag{T<:Real}(a::Interval{T}) | ||
isempty(a) && return convert(eltype(a), NaN) | ||
# r1, r2 = with_rounding(T, RoundUp) do | ||
# abs(a.lo), abs(a.hi) | ||
# end | ||
max( abs(a.lo), abs(a.hi) ) | ||
end | ||
function mig(a::Interval) | ||
|
||
function mig{T<:Real}(a::Interval{T}) | ||
isempty(a) && return convert(eltype(a), NaN) | ||
zero(a.lo) ∈ a && return zero(a.lo) | ||
min(abs(a.lo), abs(a.hi)) | ||
r1, r2 = with_rounding(T, RoundDown) do | ||
abs(a.lo), abs(a.hi) | ||
end | ||
min( r1, r2 ) | ||
end | ||
|
||
|
||
|
@@ -202,18 +234,28 @@ supremum(a::Interval) = a.hi | |
|
||
## Functions needed for generic linear algebra routines to work | ||
real(a::Interval) = a | ||
|
||
function abs(a::Interval) | ||
isempty(a) && return emptyinterval(a) | ||
Interval(mig(a), mag(a)) | ||
end | ||
|
||
function min(a::Interval, b::Interval) | ||
(isempty(a) || isempty(b)) && return emptyinterval(a) | ||
Interval( min(a.lo, b.lo), min(a.hi, b.hi)) | ||
end | ||
|
||
function max(a::Interval, b::Interval) | ||
(isempty(a) || isempty(b)) && return emptyinterval(a) | ||
Interval( max(a.lo, b.lo), max(a.hi, b.hi)) | ||
end | ||
|
||
|
||
## Set operations | ||
|
||
function intersect{T}(a::Interval{T}, b::Interval{T}) | ||
isdisjoint(a,b) && return emptyinterval(T) | ||
|
||
#@round(T, max(a.lo, b.lo), min(a.hi, b.hi)) | ||
Interval(max(a.lo, b.lo), min(a.hi, b.hi)) | ||
end | ||
|
||
|
@@ -227,17 +269,46 @@ union(a::Interval, b::Interval) = hull(a, b) | |
dist(a::Interval, b::Interval) = max(abs(a.lo-b.lo), abs(a.hi-b.hi)) | ||
eps(a::Interval) = max(eps(a.lo), eps(a.hi)) | ||
|
||
## floor, ceil, trunc and sign | ||
|
||
function floor(a::Interval) | ||
isempty(a) && return emptyinterval(a) | ||
Interval(floor(a.lo), floor(a.hi)) | ||
end | ||
|
||
function ceil(a::Interval) | ||
isempty(a) && return emptyinterval(a) | ||
Interval(ceil(a.lo), ceil(a.hi)) | ||
end | ||
|
||
function trunc(a::Interval) | ||
isempty(a) && return emptyinterval(a) | ||
Interval(trunc(a.lo), trunc(a.hi)) | ||
end | ||
|
||
function sign{T<:Real}(a::Interval{T}) | ||
isempty(a) && return emptyinterval(a) | ||
|
||
a == zero(a) && return a | ||
if a ≤ zero(a) | ||
zero(T) ∈ a && return Interval(-one(T), zero(T)) | ||
return Interval(-one(T)) | ||
elseif a ≥ zero(a) | ||
zero(T) ∈ a && return Interval(zero(T), one(T)) | ||
return Interval(one(T)) | ||
end | ||
return Interval(-one(T), one(T)) | ||
end | ||
|
||
floor(a::Interval) = Interval(floor(a.lo), floor(a.hi)) | ||
ceil(a::Interval) = Interval(ceil(a.lo), ceil(a.hi)) | ||
|
||
function mid(a::Interval) | ||
isentire(a) && return zero(a.lo) | ||
(a.lo + a.hi) / 2 | ||
end | ||
function diam(a::Interval) | ||
isempty(a) && return convert(eltype(a), NaN) | ||
a.hi - a.lo | ||
|
||
function diam{T<:Real}(a::Interval{T}) | ||
isempty(a) && return convert(T, NaN) | ||
@with_rounding(T, a.hi - a.lo, RoundUp) #cf page 64 of IEEE1788 | ||
end | ||
|
||
# Should `radius` this yield diam(a)/2? This affects other functions! | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,15 +2,13 @@ | |
|
||
## Conversion and promotion | ||
|
||
## Default conversion is to Interval{Float64} | ||
## Default conversion to Interval, corresponds to Interval{Float64} | ||
convert{T<:Real}(::Type{Interval}, x::T) = make_interval(Float64, x) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we really need this "default" conversion? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is the most reasonable thing, in the sense that usually we use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But do we actually use this conversion anywhere? Can it just be removed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the user has to be careful to specify to what kind of interval they want to convert. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we simply define it, but don't use it, aside from the tests. Since the definition of these rules was already before, I guess I simply made them consistent with |
||
@compat convert{T<:Union{Float64,BigFloat,Rational}}(::Type{Interval}, x::T) = | ||
make_interval(T, x) | ||
|
||
## Conversion to intervals (with rounding) from Integer or Irrational | ||
@compat convert{T<:Union{Float64,BigFloat}, S<:Real}(::Type{Interval{T}}, x::S) = | ||
make_interval(T, x) | ||
convert{T<:Integer, S<:Real}(::Type{Interval{Rational{T}}}, x::S) = | ||
## Conversion to specific type intervals | ||
@compat convert{T<:Union{Float64,BigFloat}}(::Type{Interval{T}}, x::Real) = | ||
make_interval(T,x) | ||
convert{T<:Integer}(::Type{Interval{Rational{T}}}, x::Real) = | ||
make_interval(Rational{T}, x) | ||
|
||
## Promotion rules | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch that no rounding is required here.