diff --git a/include/ircd/fpe.h b/include/ircd/fpe.h index c1bf40fa8..524868ea4 100644 --- a/include/ircd/fpe.h +++ b/include/ircd/fpe.h @@ -14,6 +14,7 @@ namespace ircd::fpe { struct errors_handle; + struct scope_round; string_view reflect_sicode(const int &); string_view reflect(const ushort &flag); @@ -21,9 +22,35 @@ namespace ircd::fpe [[noreturn]] void _throw_errors(const ushort &flags); void throw_errors(const ushort &flags); - std::fexcept_t set(const ushort &flag); + + void set_round(const std::float_round_style &style); + std::fexcept_t set_excepts(const ushort &flag); } +/// scope_round +/// +struct ircd::fpe::scope_round +{ + int theirs + { + std::fegetround() + }; + + scope_round(const std::float_round_style &ours) noexcept + { + std::fesetround(ours); + } + + scope_round(const scope_round &) = delete; + scope_round &operator=(const scope_round &) = delete; + ~scope_round() noexcept + { + std::fesetround(theirs); + } +}; + +/// errors_handle +/// /// Perform a single floating point operation at a time within the scope /// of fpe::errors_handle. After each operation check the floating point /// unit for an error status flag and throw a C++ exception. @@ -84,3 +111,21 @@ const { return std::fetestexcept(FE_ALL_EXCEPT); } + +// +// ircd::fpe +// + +inline std::fexcept_t +ircd::fpe::set_excepts(const ushort &flags) +{ + std::fexcept_t theirs; + syscall(std::fesetexceptflag, &theirs, flags); + return theirs; +} + +inline void +ircd::fpe::set_round(const std::float_round_style &style) +{ + syscall(std::fesetround, style); +} diff --git a/ircd/fpe.cc b/ircd/fpe.cc index fe566b3c0..ef5228daa 100644 --- a/ircd/fpe.cc +++ b/ircd/fpe.cc @@ -12,14 +12,6 @@ #pragma STDC FENV_ACCESS on #endif -std::fexcept_t -ircd::fpe::set(const ushort &flags) -{ - std::fexcept_t theirs; - syscall(std::fesetexceptflag, &theirs, flags); - return theirs; -} - void ircd::fpe::_throw_errors(const ushort &flags) {