From 9559d5013ae5073ff5b435ddd42a38e1575ce21c Mon Sep 17 00:00:00 2001 From: Lukas Nellen <lukas@nucleares.unam.mx> Date: Tue, 15 Jan 2019 00:38:47 -0600 Subject: [PATCH] Linux / OSX portable floating point exception enable/disable --- Documentation/Examples/cascade_example.cc | 3 +- Framework/Utilities/CMakeLists.txt | 13 +++- Framework/Utilities/CorsikaFenv.cc | 90 +++++++++++++++++++++++ Framework/Utilities/CorsikaFenv.h | 35 +++++++++ Framework/Utilities/testCorsikaFenv.cc | 33 +++++++++ 5 files changed, 171 insertions(+), 3 deletions(-) create mode 100644 Framework/Utilities/CorsikaFenv.cc create mode 100644 Framework/Utilities/CorsikaFenv.h create mode 100644 Framework/Utilities/testCorsikaFenv.cc diff --git a/Documentation/Examples/cascade_example.cc b/Documentation/Examples/cascade_example.cc index 2ca239e5..8e21990c 100644 --- a/Documentation/Examples/cascade_example.cc +++ b/Documentation/Examples/cascade_example.cc @@ -31,10 +31,11 @@ #include <corsika/random/RNGManager.h> +#include <corsika/utl/CorsikaFenv.h> + #include <boost/type_index.hpp> using boost::typeindex::type_id_with_cvr; -#include <fenv.h> #include <iostream> #include <limits> #include <typeinfo> diff --git a/Framework/Utilities/CMakeLists.txt b/Framework/Utilities/CMakeLists.txt index 5b21e927..4f68582b 100644 --- a/Framework/Utilities/CMakeLists.txt +++ b/Framework/Utilities/CMakeLists.txt @@ -2,13 +2,14 @@ set ( UTILITIES_SOURCES COMBoost.cc - ) + CorsikaFenv.cc) set ( UTILITIES_HEADERS COMBoost.h Bit.h Singleton.h + CorsikaFenv.h ) set ( @@ -58,5 +59,13 @@ target_link_libraries ( CORSIKAutilities CORSIKAthirdparty # for catch2 ) -CORSIKA_ADD_TEST(testCOMBoost) +add_executable (testCorsikaFenv testCorsikaFenv.cc) + +target_link_libraries ( + testCorsikaFenv + CORSIKAutilities + CORSIKAthirdparty # for catch2 +) +CORSIKA_ADD_TEST(testCOMBoost) +add_test(testCorsikaFenv testCorsikaFenv) diff --git a/Framework/Utilities/CorsikaFenv.cc b/Framework/Utilities/CorsikaFenv.cc new file mode 100644 index 00000000..145adb47 --- /dev/null +++ b/Framework/Utilities/CorsikaFenv.cc @@ -0,0 +1,90 @@ +/** + * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu + * + * See file AUTHORS for a list of contributors. + * + * This software is distributed under the terms of the GNU General Public + * Licence version 3 (GPL Version 3). See file LICENSE for a full version of + * the license. + * + * Provide portable or fallback versions of feenableexcept() and fedisableexcept() + * Exist by default in glibc since version 2.2, but not in the standard + * fenv.h / cfenv headers for C 99 or C++ 11 + * + * \author Lukas Nellen + * \date 14 Jan 2019 + * + */ + +#include <corsika/utl/CorsikaFenv.h> +#include <cfenv> + +#if defined(__GLIBC__) +// do nothing functions exist + +#elif defined(__APPLE__) && defined(__MACH__) +// Implementation of OS X on intel X64_86 +// code from https://stackoverflow.com/questions/37819235/how-do-you-enable-floating-point-exceptions-for-clang-in-os-x +// based on http://www-personal.umich.edu/~williams/archive/computation/fe-handling-example.c + +extern "C" { + + int + feenableexcept(int excepts) { + static fenv_t fenv; + int new_excepts = excepts & FE_ALL_EXCEPT; + // previous masks + int old_excepts; + + if (fegetenv(&fenv)) { + return -1; + } + old_excepts = fenv.__control & FE_ALL_EXCEPT; + + // unmask + fenv.__control &= ~new_excepts; + fenv.__mxcsr &= ~(new_excepts << 7); + + return fesetenv(&fenv) ? -1 : old_excepts; + } + + int + fedisableexcept(int excepts) { + static fenv_t fenv; + int new_excepts = excepts & FE_ALL_EXCEPT; + // all previous masks + int old_excepts; + + if (fegetenv(&fenv)) { + return -1; + } + old_excepts = fenv.__control & FE_ALL_EXCEPT; + + // mask + fenv.__control |= new_excepts; + fenv.__mxcsr |= new_excepts << 7; + + return fesetenv(&fenv) ? -1 : old_excepts; + } + +} + +#else +// unknown environment, dummy implementations + +extern "C" { +#warning No enabling/disabling of floating point exceptions + + int feenableexcept(int excepts) + { + return -1; + } + + int fedisableexcept(int excepts) + { + return -1; + } + +} + +#endif diff --git a/Framework/Utilities/CorsikaFenv.h b/Framework/Utilities/CorsikaFenv.h new file mode 100644 index 00000000..eeaecef9 --- /dev/null +++ b/Framework/Utilities/CorsikaFenv.h @@ -0,0 +1,35 @@ +/** + * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu + * + * See file AUTHORS for a list of contributors. + * + * This software is distributed under the terms of the GNU General Public + * Licence version 3 (GPL Version 3). See file LICENSE for a full version of + * the license. + * + * Provide portable or fallback versions of feenableexcept() and fedisableexcept() + * Exist by default in glibc since version 2.2, but not in the standard + * fenv.h / cfenv headers for C 99 or C++ 11 + * + * \author Lukas Nellen + * \date 14 Jan 2019 + * + */ + +#ifndef CORSIKA_CORSIKAFENV_H +#define CORSIKA_CORSIKAFENV_H + +#include <cfenv> + +#if !defined(__GLIBC__) +extern "C" { + + int + feenableexcept(int excepts); + int + fedisableexcept(int excepts); + +} +#endif + +#endif //CORSIKA_CORSIKAFENV_H diff --git a/Framework/Utilities/testCorsikaFenv.cc b/Framework/Utilities/testCorsikaFenv.cc new file mode 100644 index 00000000..9cae9469 --- /dev/null +++ b/Framework/Utilities/testCorsikaFenv.cc @@ -0,0 +1,33 @@ +/** + * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu + * + * See file AUTHORS for a list of contributors. + * + * This software is distributed under the terms of the GNU General Public + * Licence version 3 (GPL Version 3). See file LICENSE for a full version of + * the license. + */ + +#include <corsika/utl/CorsikaFenv.h> + +#include <cmath> +#include <iostream> +#include <csignal> + +extern "C" { + static void + handle_fpe(int /*signo*/ ) { + exit(0); + } +} + + +int +main() { + feenableexcept(FE_ALL_EXCEPT); + signal(SIGFPE, handle_fpe); + + std::cout << std::log(0.) << std::endl; + + exit(1); +} \ No newline at end of file -- GitLab