Skip to content
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

Add support for floating point exceptions #47930

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
Prev Previous commit
Next Next commit
add getter
  • Loading branch information
simonbyrne committed Dec 20, 2022
commit e024f5df5315b2f09a9cc5f99c4e2a3a69a051c4
75 changes: 62 additions & 13 deletions base/rounding.jl
Original file line number Diff line number Diff line change
Expand Up @@ -254,21 +254,70 @@ for IEEE arithmetic, and `true` if they might be converted to zeros.
get_zero_subnormals() = ccall(:jl_get_zero_subnormals,Int32,())!=0


function _get_exceptions()
excepts = ccall(:jl_set_fenv_except,Cint,())
if excepts < 0
error("Floating point exceptions not supported on this platform")
end
return excepts
end
function get_exceptions()
excepts = _get_exceptions()
return (;
invalid = excepts & JL_FE_INVALID != 0,
inexact = excepts & JL_FE_INEXACT != 0,
underflow = excepts & JL_FE_UNDERFLOW != 0,
overflow = excepts & JL_FE_OVERFLOW != 0,
dividebyzero = excepts & JL_FE_DIVBYZERO != 0,
)
end

function set_exceptions(;
invalid=false,
inexact=false,
overflow=false,
underflow=false,
dividebyzero=false
invalid=nothing,
inexact=nothing,
overflow=nothing,
underflow=nothing,
dividebyzero=nothing
)

excepts = (invalid * JL_FE_INVALID) |
(inexact * JL_FE_INEXACT) |
(underflow * JL_FE_UNDERFLOW) |
(overflow * JL_FE_OVERFLOW) |
(dividebyzero * JL_FE_DIVBYZERO)

ccall(:jl_set_fenv_except,Cint,(Cint,), excepts) == 0
excepts = _get_exceptions()
if !isnothing(invalid)
if invalid
excepts |= JL_FE_INVALID
else
excepts &= ~JL_FE_INVALID
end
end
if !isnothing(inexact)
if inexact
excepts |= JL_FE_INEXACT
else
excepts &= ~JL_FE_INEXACT
end
end
if !isnothing(underflow)
if underflow
excepts |= JL_FE_UNDERFLOW
else
excepts &= ~JL_FE_UNDERFLOW
end
end
if !isnothing(overflow)
if overflow
excepts |= JL_FE_OVERFLOW
else
excepts &= ~JL_FE_OVERFLOW
end
end
if !isnothing(dividebyzero)
if dividebyzero
excepts |= JL_FE_DIVBYZERO
else
excepts &= ~JL_FE_DIVBYZERO
end
end
if ccall(:jl_set_fenv_except,Cint,(Cint,), excepts) < 0
error("Floating point exceptions not supported on this platform")
end
end

end #module
39 changes: 36 additions & 3 deletions src/jlapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,40 @@ JL_DLLEXPORT int jl_set_fenv_rounding(int i)
return fesetround(i);
}


JL_DLLEXPORT int jl_get_fenv_except(void)
{
#if defined(__GLIBC__)
return fegetexcept();
#elif defined(_OS_WINDOWS_)
unsigned int flags = _controlfp(0, 0);
int excepts = 0;
if (flags & _EM_INEXACT)
excepts |= FE_INEXACT;
if (flags & _EM_UNDERFLOW)
excepts |= FE_UNDERFLOW;
if (flags & _EM_OVERFLOW)
excepts |= FE_OVERFLOW;
if (flags & _EM_ZERODIVIDE)
excepts |= FE_DIVBYZERO;
if (flags & _EM_INVALID)
excepts |= FE_INVALID;
return excepts;
#elif defined(_OS_DARWIN_)
fenv_t env;
fegetenv(&env);
#if defined(_CPU_AARCH64_)
return (env.__fpcr & FE_ALL_EXCEPT << 8);
#elif defined(_CPU_X86_64_)
return (~env.__mxcsr & FE_ALL_EXCEPT << 7);
#else
return -1;
#endif
#else
return -1;
#endif
}

JL_DLLEXPORT int jl_set_fenv_except(int excepts)
{
#if defined(__GLIBC__)
Expand Down Expand Up @@ -559,17 +593,16 @@ JL_DLLEXPORT int jl_set_fenv_except(int excepts)
env.__control = (env.__control | FE_ALL_EXCEPT) & ~excepts;
env.__mxcsr = (env.__mxcsr | FE_ALL_EXCEPT << 7) & ~(excepts << 7);
#else
return 1;
return -1;
#endif
fesetenv(&env);
return 0;
#else
return 1;
return -1;
#endif
}



static int exec_program(char *program)
{
JL_TRY {
Expand Down