Skip to content

Commit 777ad9d

Browse files
authored
Use BigFloat parsing for Float64 to fix Windows bug. (#143)
* Use BigFloat parsing for Float64 to fix Windows bug. Remove unnecessary `@eval`. * Fix atomic for Windows * Specific atomic for Irrational * Specific atomic for Rational * Do correct float rounding in new parse * Bump version of CRlibm required * Int -> Int64
1 parent 0d33df5 commit 777ad9d

File tree

4 files changed

+54
-25
lines changed

4 files changed

+54
-25
lines changed

REQUIRE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
julia 0.6
2-
CRlibm 0.5
2+
CRlibm 0.6
33
StaticArrays 0.5
44
FastRounding 0.0.4
55
AdjacentFloats 0.0.5

src/intervals/conversion.jl

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,30 @@ atomic(::Type{Interval{T}}, x::T) where {T<:Integer} = Interval{T}(x)
7474
atomic(::Type{Interval{T}}, x::AbstractString) where T<:AbstractFloat =
7575
parse(Interval{T}, x)
7676

77-
function atomic(::Type{Interval{T}}, x::S) where {T<:AbstractFloat, S<:Real}
78-
isinf(x) && return wideinterval(T(x))
77+
@static if is_windows() # Windows cannot round properly
78+
function atomic(::Type{Interval{T}}, x::S) where {T<:AbstractFloat, S<:Real}
79+
isinf(x) && return wideinterval(T(x))
7980

80-
Interval{T}( T(x, RoundDown), T(x, RoundUp) )
81-
# the rounding up could be done as nextfloat of the rounded down one?
82-
# use @round_up and @round_down here?
81+
Interval{T}( parse(T, string(x), RoundDown),
82+
parse(T, string(x), RoundUp) )
83+
end
84+
85+
function atomic(::Type{Interval{T}}, x::Union{Irrational,Rational}) where {T<:AbstractFloat}
86+
isinf(x) && return wideinterval(T(x))
87+
88+
Interval{T}( T(x, RoundDown), T(x, RoundUp) )
89+
# the rounding up could be done as nextfloat of the rounded down one?
90+
# use @round_up and @round_down here?
91+
end
92+
93+
else
94+
function atomic(::Type{Interval{T}}, x::S) where {T<:AbstractFloat, S<:Real}
95+
isinf(x) && return wideinterval(T(x))
96+
97+
Interval{T}( T(x, RoundDown), T(x, RoundUp) )
98+
# the rounding up could be done as nextfloat of the rounded down one?
99+
# use @round_up and @round_down here?
100+
end
83101
end
84102

85103
function atomic(::Type{Interval{T}}, x::S) where {T<:AbstractFloat, S<:AbstractFloat}

src/intervals/rounding.jl

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,33 +29,44 @@ In Julia v0.6 and later (but *not* in Julia v0.5), this automatically redefines
2929
"""Interval rounding trait type"""
3030
struct IntervalRounding{T} end
3131

32+
33+
34+
3235
# Functions that are the same for all rounding types:
33-
@eval begin
34-
# unary plus and minus:
35-
+(a::T, ::RoundingMode) where {T<:AbstractFloat} = a # ignore rounding
36-
-(a::T, ::RoundingMode) where {T<:AbstractFloat} = -a # ignore rounding
37-
38-
# zero:
39-
zero(a::Interval{T}, ::RoundingMode) where {T<:AbstractFloat} = zero(T)
40-
zero(::Type{T}, ::RoundingMode) where {T<:AbstractFloat} = zero(T)
41-
42-
convert(::Type{BigFloat}, x, rounding_mode::RoundingMode) =
43-
setrounding(BigFloat, rounding_mode) do
44-
convert(BigFloat, x)
45-
end
4636

47-
parse(::Type{T}, x, rounding_mode::RoundingMode) where {T} = setrounding(T, rounding_mode) do
48-
parse(T, x)
49-
end
37+
# unary plus and minus:
38+
+(a::T, ::RoundingMode) where {T<:AbstractFloat} = a # ignore rounding
39+
-(a::T, ::RoundingMode) where {T<:AbstractFloat} = -a # ignore rounding
5040

41+
# zero:
42+
zero(a::Interval{T}, ::RoundingMode) where {T<:AbstractFloat} = zero(T)
43+
zero(::Type{T}, ::RoundingMode) where {T<:AbstractFloat} = zero(T)
5144

52-
sqrt(a::T, rounding_mode::RoundingMode) where {T<:Rational} = setrounding(float(T), rounding_mode) do
53-
sqrt(float(a))
45+
convert(::Type{BigFloat}, x, rounding_mode::RoundingMode) =
46+
setrounding(BigFloat, rounding_mode) do
47+
convert(BigFloat, x)
5448
end
5549

50+
parse(::Type{T}, x::AbstractString, rounding_mode::RoundingMode) where {T} = setrounding(T, rounding_mode) do
51+
parse(T, x)
52+
end
53+
54+
# use BigFloat parser to get round issues on Windows:
55+
function parse(::Type{Float64}, s::AbstractString, r::RoundingMode)
56+
a = setprecision(BigFloat, 53) do
57+
setrounding(BigFloat, r) do
58+
parse(BigFloat, s) # correctly takes account of rounding mode
59+
end
60+
end
61+
62+
return Float64(a, r)
5663
end
5764

5865

66+
sqrt(a::T, rounding_mode::RoundingMode) where {T<:Rational} = setrounding(float(T), rounding_mode) do
67+
sqrt(float(a))
68+
end
69+
5970

6071
# no-ops for rational rounding:
6172
for f in (:+, :-, :*, :/)

test/interval_tests/construction.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ using Base.Test
106106
@test b == @floatinterval(pi)
107107
@test nextfloat(b.lo) == b.hi
108108
@test convert(Interval{Float64}, @biginterval(0.1)) == a
109-
x = typemax(Int)
109+
x = typemax(Int64)
110110
@test @interval(x) == @floatinterval(x)
111111
@test isthin(@interval(x)) == false
112112
x = rand()

0 commit comments

Comments
 (0)