diff --git a/Documentation/Examples/cascade_example.cc b/Documentation/Examples/cascade_example.cc index 2ca239e5b1acbf60a72e3c356dbfb11f08fc3a2d..8e21990c4557a9b4bdcfecba6f746e0fe0497774 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 5b21e9270e1f50e28323d0434580e29b3616b77a..4f68582b0d551701cd454e8758927c8688cb2da4 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 0000000000000000000000000000000000000000..145adb4761f40938a101d05a8f4d6c6bb087efce --- /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 0000000000000000000000000000000000000000..eeaecef96692347f54aace9839194e3132f422c4 --- /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 0000000000000000000000000000000000000000..9cae946918047166c347e73b907a5ea562a61479 --- /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