about summary refs log tree commit diff stats
path: root/001help.cc
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-06-06 22:46:51 -0700
committerKartik K. Agaram <vc@akkartik.com>2016-06-06 22:46:51 -0700
commit5a6645bc94aecb0b907a961c724dfcc9b76b37b7 (patch)
treea27c27b2b4455f37b0e836e26660e96ede4fe98a /001help.cc
parentdfd9ac2b294dc7a135ce530131de886a2420aa01 (diff)
downloadmu-5a6645bc94aecb0b907a961c724dfcc9b76b37b7.tar.gz
3036
Drastically streamlined floating-point overflow/underflow detection.

For some reason I can't find a way to actually handle SIGFPE traps; they
have to segfault the program.
Diffstat (limited to '001help.cc')
-rw-r--r--001help.cc28
1 files changed, 27 insertions, 1 deletions
diff --git a/001help.cc b/001help.cc
index 25dd27d5..a0241e95 100644
--- a/001help.cc
+++ b/001help.cc
@@ -113,7 +113,7 @@ void initialize_signal_handlers() {
   sigaction(SIGABRT, &action, NULL);  // assert() failure or integer overflow on linux (with -ftrapv)
   sigaction(SIGILL,  &action, NULL);  // integer overflow on OS X (with -ftrapv)
 }
-void dump_and_exit(int sig, siginfo_t* siginfo, unused void* dummy) {
+void dump_and_exit(int sig, unused siginfo_t* dummy1, unused void* dummy2) {
   switch (sig) {
     case SIGABRT:
       #ifndef __APPLE__
@@ -134,6 +134,32 @@ void dump_and_exit(int sig, siginfo_t* siginfo, unused void* dummy) {
 :(before "End Includes")
 #include <signal.h>
 
+//: For good measure we'll also enable SIGFPE.
+:(before "atexit(teardown)")
+feenableexcept(FE_OVERFLOW | FE_UNDERFLOW);
+//? assert(sizeof(int) == 4 && sizeof(float) == 4);
+//? //                          | exp   |  mantissa
+//? int smallest_subnormal = 0b00000000000000000000000000000001;
+//? float smallest_subnormal_f = *reinterpret_cast<int*>(&smallest_subnormal);
+//? cerr << "ε/2: " << smallest_subnormal_f/2 << " (underflow)\n";  // test SIGFPE
+:(before "End Includes")
+#include <fenv.h>
+:(code)
+#ifdef __APPLE__
+// Public domain polyfill for feenableexcept on OS X
+// http://www-personal.umich.edu/~williams/archive/computation/fe-handling-example.c
+inline int feenableexcept (unsigned int excepts) {
+  static fenv_t fenv;
+  unsigned int new_excepts = excepts & FE_ALL_EXCEPT;
+  unsigned int old_excepts;
+  if (fegetenv(&fenv)) return -1;
+  old_excepts = fenv.__control & FE_ALL_EXCEPT;
+  fenv.__control &= ~new_excepts;
+  fenv.__mxcsr   &= ~(new_excepts << 7);
+  return fesetenv(&fenv) ? -1 : old_excepts;
+}
+#endif
+
 //: 6. Map's operator[] being non-const is fucking evil.
 :(before "Globals")  // can't generate prototypes for these
 // from http://stackoverflow.com/questions/152643/idiomatic-c-for-reading-from-a-const-map