| /* Small test program for probing how various math functions |
| * with specific operands set floating point exceptions |
| */ |
| |
| #define _ISOC99_SOURCE 1 |
| #define _GNU_SOURCE 1 |
| |
| #include <stdint.h> |
| #include <math.h> |
| #include <fenv.h> |
| #include <stdio.h> |
| |
| int main(int argc, char **argv) |
| { |
| float largest, small, t, inf_float; |
| |
| largest = small = 1; |
| while (1) { |
| t = largest + small; |
| /* optimizations may make plain "t == largest" unreliable */ |
| if (memcmp(&t, &largest, sizeof(float)) == 0) |
| break; |
| if (isfinite(t)) { |
| largest = t; |
| small *= 2; |
| continue; |
| } |
| small /= 2; |
| } |
| inf_float = largest + largest; |
| //printf("%.40g ", largest); |
| //printf("[%llx]\n", (long long) (*(uint32_t *)&largest)); |
| |
| feclearexcept(FE_ALL_EXCEPT); |
| |
| //t = 1.0 / 0.0; // simple test: FE_DIVBYZERO |
| //t = nextafterf(largest, 1); // glibc 2.8: no math exceptions raised |
| //t = nextafterf(largest, largest); // glibc 2.8: no math exceptions raised |
| //t = nextafterf(largest, inf_float); // glibc 2.8: FE_INEXACT FE_OVERFLOW |
| |
| #define PREX(ex) do { if (fetestexcept(ex)) printf(#ex " "); } while(0) |
| #ifdef FE_INEXACT |
| PREX(FE_INEXACT); |
| #endif |
| #ifdef FE_DIVBYZERO |
| PREX(FE_DIVBYZERO); |
| #endif |
| #ifdef FE_UNDERFLOW |
| PREX(FE_UNDERFLOW); |
| #endif |
| #ifdef FE_OVERFLOW |
| PREX(FE_OVERFLOW); |
| #endif |
| #ifdef FE_INVALID |
| PREX(FE_INVALID); |
| #endif |
| if (fetestexcept(FE_ALL_EXCEPT)) |
| printf("\n"); |
| else |
| printf("no math exceptions raised\n"); |
| |
| printf("%.40g\n", t); |
| return 0; |
| } |