-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
RFC: basic floating point exception functionality #6170
Conversation
I'll give it a try. About the FEInexact, it might be because of random internal operations or even grisu, it's pretty hard to avoid it. |
function test2()
clear_floatexcept()
before = get_floatexcept()
ret = 1.0 / 7
after = get_floatexcept()
return ret, before, after
end This returns no exceptions on both cases, which is very weird. I'm not sure if LLVM is reordering the operations, or anything else is happening. If anyone is good with LLVM IR, here goes it: define { double, %FloatExceptionSet, %FloatExceptionSet } @julia_test215504() {
top:
call void @julia_clear_floatexcept15323(%FloatExceptionSet { i32 61 }), !dbg !1356
%0 = call i32 inttoptr (i64 140646004314944 to i32 (i32)*)(i32 61), !dbg !1357
%1 = insertvalue %FloatExceptionSet undef, i32 %0, 0, !dbg !1357, !julia_type !1358
%2 = call i32 inttoptr (i64 140646004314944 to i32 (i32)*)(i32 61), !dbg !1359
%3 = insertvalue %FloatExceptionSet undef, i32 %2, 0, !dbg !1359, !julia_type !1358
%4 = insertvalue { double, %FloatExceptionSet, %FloatExceptionSet } { double 0x3FC2492492492492, %FloatExceptionSet undef, %FloatExceptionSet undef }, %FloatExceptionSet %1, 1, !dbg !1360, !julia_type !1361
%5 = insertvalue { double, %FloatExceptionSet, %FloatExceptionSet } %4, %FloatExceptionSet %3, 2, !dbg !1360, !julia_type !1361
ret { double, %FloatExceptionSet, %FloatExceptionSet } %5, !dbg !1360
} |
Oh, I guess LLVM is constant-folding, so it doesn't raise the exception at runtime. |
Yeah, indeed that was the case: function test2(x)
clear_floatexcept()
before = get_floatexcept()
ret = 1.0 / x
after = get_floatexcept()
return ret, before, after
end
julia> test2(2)
(0.5,{},{})
julia> test2(7)
(0.14285714285714285,{},{FEInexact}) |
Okay, I've added functions to raise floating point flags. The C functions to save and restore flags are |
In the worst case, you can just grab a |
@andrioni That does seem like a reasonable approach, but I'm guessing that can't be done using the preprocessor as in |
You can stick a function in Or you could use the implementations of these functions from openlibm, which vary have various definitions of |
@vtjnash Fantastic, thanks. I now have the save/restore working (for IEEE types). |
About I think the interface is fine to start with. |
I've been thinking a little more about this, and it would be much more useful if this could be incorporated into the general julia exception handling machinery: the IEEE standard covers this in section 8.3. Delayed exception handling would be easy to implement: we could define a method like: function watch_floatexcept(f,T,fe)
state = save_floatexcept(T,fe)
clear_floatexcept(T,fe)
f()
is_floatexcept(T,fe) && throw(FloatError(fe))
restore_floatexcept(T,state,fe)
end which could then be used: try
watch_floatexcept(Float64,FEUnderflow) do
# do something
end
catch e
# handle exception
end (this could also be done with a macro). Immediate handling would be much more difficult: we would need something similar to how |
A possible option is to trap |
Have a look at the existing fpe handler (throws DivisionError) |
@ihnorton Thanks: so does that mean we're already trapping it? That should make it easier to implement, though again, beyond my abilities. |
Is this something we should include in 0.3? It is independent new functionality. |
I'm not a wizard on floating point exceptions, but if I can help on grisu issues, just let me know. |
6c7c7e3
to
1a4c02f
Compare
What is the status on this -- would be great to have the |
I have extracted the relevant parts of the first commit into a module: https://gist.github.com/dpsanders/321546d749370403e0bc @simonbyrne Please let me know if there is any problem with this, of course. [And could you please check that I got the value of Maybe some version of this could be registered as a package if it is not going to be included in Base. EDIT: I tried to check out your branch (to a new directory) and compile, but got some errors. |
I don't know. My ideal preference would be to make use of floating point exception masking/unmasking, as I outlined here: #5234 (comment), but I realise that this is unlikely to happen soon. This interface is a bit unwieldy, but it does have the advantage of at least being straightforward to implement. I'm not sure about |
Should we close this as stale? |
This adds basic functionality for checking and clearing floating point exception flags (#2976). Usage is currently:
Still to do:
BigFloat
flags: I've now added these, but the exceptions don't exactly match the IEEE onesFEInexact
(input, printing, etc.), even for exact numbers (e.g.x=1.0
): I'm not sure what the correct behaviour is here.cc: @andrioni