← Back to davo.co
aboutsummaryrefslogtreecommitdiffstats
path: root/fp_except.c
blob: 5dc63ec35344c3d07b970cac14f060c3b4da5c61 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include "c23-fallback.h"
#include <stdio.h>
#include <fenv.h>
#include <float.h>
#ifndef INFINITY
#include <math.h>
#endif

#if !defined(__STDC_IEC_559__) && !defined(__STDC_IEC_60559_BFP__) && !FE_ALL_EXCEPT
#error "floating-point arithmetic is too weird"
#endif

static_assert(FE_ALL_EXCEPT, "floating point exceptions are not supported");

#ifdef FENV_OFF
#warning "switching FENV_ACCESS off"
#pragma STDC FENV_ACCESS OFF
#else
#pragma STDC FENV_ACCESS ON
#endif

bool const has_inf =
#ifdef INFINITY
  (1.0/0.0 == INFINITY)
#else
  false
#endif
  ;

int excepts[] = {
#ifdef FE_DIVBYZERO
  FE_DIVBYZERO,
#endif
#ifdef FE_INEXACT
  FE_INEXACT,
#endif
#ifdef FE_INVALID
  FE_INVALID,
#endif
#ifdef FE_OVERFLOW
  FE_OVERFLOW,
#endif
#ifdef FE_UNDERFLOW
  FE_UNDERFLOW,
#endif
};

void printexcept(void) {
  char const* name[] = {
#ifdef FE_DIVBYZERO
    "divbyzero",
#endif
#ifdef FE_INEXACT
    "inexact",
#endif
#ifdef FE_INVALID
    "invalid",
#endif
#ifdef FE_OVERFLOW
    "overflow",
#endif
#ifdef FE_UNDERFLOW
    "underflow",
#endif
  };
  int except = fetestexcept(FE_ALL_EXCEPT);
  if (except) {
    printf("[");
    for (unsigned j = 0; except; except &= ~excepts[j], ++j)
      if (excepts[j] & except)
        printf("%s ", name[j]);
    printf("]");
  }
}

int main (int argc, char* argv[static argc+1]) {
  printf("division by zero is %sequal to INFINITY\n", has_inf ? "" : "un");
  for (unsigned i = 1; i < argc; i++) {
    feclearexcept(FE_ALL_EXCEPT);
    double x = strtod(argv[i], nullptr);
    printf("%g ", x);
    printexcept();
    feclearexcept(FE_ALL_EXCEPT);
    printf(": %g ", 1.0/x);
    printexcept();
    puts("");
  }
}