├── fenv_constants.jl ├── intervals_using_exceptions.jl ├── good_intervals.jl └── FloatingPointExceptions.jl /fenv_constants.jl: -------------------------------------------------------------------------------- 1 | const JL_FE_INEXACT = 0x20 2 | const JL_FE_UNDERFLOW = 0x10 3 | const JL_FE_OVERFLOW = 0x08 4 | const JL_FE_DIVBYZERO = 0x04 5 | const JL_FE_INVALID = 0x01 6 | const JL_FE_TONEAREST = 0x0000 7 | const JL_FE_UPWARD = 0x0800 8 | const JL_FE_DOWNWARD = 0x0400 9 | const JL_FE_TOWARDZERO = 0x0c00 10 | 11 | @show JL_FE_INEXACT 12 | -------------------------------------------------------------------------------- /intervals_using_exceptions.jl: -------------------------------------------------------------------------------- 1 | push!(LOAD_PATH, ".") 2 | 3 | using FloatingPointExceptions 4 | 5 | import Base.+ 6 | function +(a::Float64, b::Float64, r::RoundingMode) 7 | old = get_rounding(Float64) 8 | 9 | set_rounding(Float64, r) 10 | clear_floatexcept() 11 | 12 | c = a + b; 13 | 14 | #exceptions = get_floatexcept() 15 | #@show exceptions 16 | #inexact = FEInexact in exceptions 17 | 18 | is_inexact = is_floatexcept(FEInexact) 19 | 20 | set_rounding(Float64, old) 21 | 22 | c, is_inexact 23 | 24 | end 25 | 26 | @show +(0.1, 0.2, RoundDown) 27 | -------------------------------------------------------------------------------- /good_intervals.jl: -------------------------------------------------------------------------------- 1 | # Andrioni from pull request 6170: 2 | 3 | using FloatingPointExceptions 4 | using ValidatedNumerics 5 | 6 | #set_rounding(Float64, RoundUp) 7 | 8 | function test2(x) 9 | clear_floatexcept() 10 | before = get_floatexcept() 11 | ret = 1.0 / x 12 | after = get_floatexcept() 13 | return ret, before, after 14 | end 15 | 16 | function make_interval(x::Number) 17 | clear_floatexcept() 18 | #before = get_floatexcept() 19 | #b = float("$x") #2x / 2 20 | 21 | #b = with_rounding(Float64, RoundUp) do 22 | #b = 10 * x / 10 23 | 24 | b = float(x) 25 | 26 | #end 27 | 28 | if FEInexact ∈ get_floatexcept() 29 | Interval(prevfloat(b), b) 30 | else 31 | Interval(b) 32 | end 33 | end 34 | 35 | function make_interval(x::String) 36 | clear_floatexcept() 37 | #before = get_floatexcept() 38 | b = parsefloat(x) # it's here that the exception is thrown 39 | 40 | if FEInexact ∈ get_floatexcept() 41 | Interval(prevfloat(b), b) 42 | else 43 | Interval(b) 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /FloatingPointExceptions.jl: -------------------------------------------------------------------------------- 1 | # From Simon Byrne's pull request https://github.com/JuliaLang/julia/pull/6170 2 | 3 | module FloatingPointExceptions 4 | 5 | include("fenv_constants.jl") 6 | 7 | ## floating point exceptions ## 8 | import Base: show, in, convert 9 | 10 | export FloatExceptions, FEInexact, FEUnderflow, FEOverflow, FEDivByZero, FEInvalid, FloatExceptionSet, 11 | FEAll, clear_floatexcept, get_floatexcept, is_floatexcept 12 | 13 | 14 | abstract FloatExceptions 15 | 16 | immutable FEInexact <: FloatExceptions end 17 | immutable FEUnderflow <: FloatExceptions end 18 | immutable FEOverflow <: FloatExceptions end 19 | immutable FEDivByZero <: FloatExceptions end 20 | immutable FEInvalid <: FloatExceptions end 21 | 22 | 23 | # IEEE 754 requires the ability to check/set/clear multiple exceptions 24 | immutable FloatExceptionSet 25 | flags::Cint 26 | FloatExceptionSet(e::Integer) = new(convert(Cint,e)) 27 | end 28 | 29 | convert(::Type{FloatExceptionSet},::Type{FEInexact}) = FloatExceptionSet(JL_FE_INEXACT) 30 | convert(::Type{FloatExceptionSet},::Type{FEUnderflow}) = FloatExceptionSet(JL_FE_UNDERFLOW) 31 | convert(::Type{FloatExceptionSet},::Type{FEOverflow}) = FloatExceptionSet(JL_FE_OVERFLOW) 32 | convert(::Type{FloatExceptionSet},::Type{FEDivByZero}) = FloatExceptionSet(JL_FE_DIVBYZERO) 33 | convert(::Type{FloatExceptionSet},::Type{FEInvalid}) = FloatExceptionSet(JL_FE_INVALID) 34 | 35 | const FEAll = FloatExceptionSet(JL_FE_INEXACT | JL_FE_UNDERFLOW | JL_FE_OVERFLOW | JL_FE_DIVBYZERO | JL_FE_INVALID) 36 | 37 | in(fs1::FloatExceptionSet,fs2::FloatExceptionSet) = fs1.flags & fs2.flags != zero(Cint) 38 | in{E<:FloatExceptions}(::Type{E},fs::FloatExceptionSet) = in(convert(FloatExceptionSet,E), fs) 39 | 40 | show(io::IO,fe::FloatExceptionSet) = showcompact(io, filter(x->in(x,fe),subtypes(FloatExceptions))) 41 | 42 | 43 | 44 | # IEEE754 2008 5.7.4 requires the following functions: 45 | # lowerFlags, raiseFlags, testFlags, testSavedFlags (handled by "in"), restoreFlags, saveAllFlags 46 | 47 | # lowerFlags 48 | function clear_floatexcept(f::FloatExceptionSet) 49 | if ccall(:feclearexcept, Cint, (Cint,), f.flags) != zero(Cint) 50 | error("Could not clear floating point exception flag") 51 | end 52 | end 53 | clear_floatexcept{E<:FloatExceptions}(::Type{E}) = clear_floatexcept(convert(FloatExceptionSet,E)) 54 | clear_floatexcept() = clear_floatexcept(FEAll) 55 | 56 | function get_floatexcept(f::FloatExceptionSet) 57 | FloatExceptionSet(ccall(:fetestexcept, Cint, (Cint,), f.flags)) 58 | end 59 | # saveAllFlags 60 | get_floatexcept() = get_floatexcept(FEAll) 61 | 62 | # testFlags 63 | is_floatexcept(f::FloatExceptionSet) = in(f,get_floatexcept(f)) 64 | is_floatexcept{E<:FloatExceptions}(::Type{E}) = is_floatexcept(convert(FloatExceptionSet,E)) 65 | is_floatexcept() = is_floatexcept(FEAll) 66 | 67 | # TODO: raiseFlags, restoreFlags 68 | 69 | end 70 | --------------------------------------------------------------------------------