float_ieee_host.c (1581B)
1 /* Independent host reference for result words and exception flags. 2 * Host NaNs provide quiet-class/flag checks; Python checks payload/sign policy. 3 */ 4 #include <fenv.h> 5 #include <float.h> 6 #include <inttypes.h> 7 #include <stdint.h> 8 #include <stdio.h> 9 #include <string.h> 10 #pragma STDC FENV_ACCESS ON 11 12 int main(void) { 13 if (sizeof(double) != 8 || FLT_RADIX != 2 || DBL_MANT_DIG != 53 || 14 DBL_MIN_EXP != -1021 || DBL_MAX_EXP != 1024 || fesetround(FE_TONEAREST)) return 2; 15 double one = 1.0; 16 uint64_t one_bits; 17 memcpy(&one_bits, &one, 8); 18 if (one_bits != UINT64_C(0x3ff0000000000000)) return 3; 19 unsigned op; 20 uint64_t a, b; 21 while (scanf("%u %" SCNx64 " %" SCNx64, &op, &a, &b) == 3) { 22 volatile double left, right, result; 23 memcpy((void *)&left, &a, 8); 24 memcpy((void *)&right, &b, 8); 25 if (feclearexcept(FE_ALL_EXCEPT)) return 4; 26 switch (op) { 27 case 0: result = left + right; break; 28 case 1: result = left - right; break; 29 case 2: result = left * right; break; 30 case 3: result = left / right; break; 31 default: return 5; 32 } 33 int raised = fetestexcept(FE_ALL_EXCEPT); 34 unsigned flags = !!(raised & FE_INVALID) | (!!(raised & FE_DIVBYZERO) << 1) | 35 (!!(raised & FE_OVERFLOW) << 2) | (!!(raised & FE_UNDERFLOW) << 3) | 36 (!!(raised & FE_INEXACT) << 4); 37 uint64_t bits; 38 memcpy(&bits, (const void *)&result, 8); 39 printf("%016" PRIx64 " %u\n", bits, flags); 40 } 41 return ferror(stdin) ? 6 : 0; 42 }