You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
4.3 KiB

25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
  1. /* Determine some float parameters, much like gcc's "enquire.c". */
  2. /* Bruno Haible 24.8.1996 */
  3. /* This program expects to be compiled by an ANSI C or C++ compiler. */
  4. #include <stdio.h>
  5. typedef int boolean;
  6. #define TRUE 1
  7. #define FALSE 0
  8. #ifdef HAVE_LONGDOUBLE
  9. typedef long double ldouble;
  10. #endif
  11. static void header (void)
  12. {
  13. printf("/* Rounding modes, for use below */\n");
  14. printf("#define rounds_to_nearest 0 /* 0.5 ulp */\n");
  15. printf("#define rounds_to_zero 1 /* 1 ulp */\n");
  16. printf("#define rounds_to_infinity 2 /* 1 ulp */\n");
  17. printf("#define rounds_to_minus_infinity 3 /* 1 ulp */\n");
  18. printf("\n");
  19. }
  20. #define check(type,typeprefix,typestr,equalfn,mainfn) \
  21. static boolean equalfn (volatile type* x, volatile type* y); \
  22. static void mainfn (void) \
  23. { \
  24. int mant_bits; \
  25. int epsilon_bits = -1; \
  26. int negepsilon_bits = -1; \
  27. { type x = 1.0; type y; type z; \
  28. for (y = 1.0; ; y = 0.5*y) \
  29. { z = x + y; if (equalfn(&x,&z)) break; \
  30. z = z - x; if (!equalfn(&y,&z)) break; \
  31. epsilon_bits++; \
  32. } } \
  33. { type x = 1.0; type y; type z; \
  34. for (y = -1.0; ; y = 0.5*y) \
  35. { z = x + y; if (equalfn(&x,&z)) break; \
  36. z = z - x; if (!equalfn(&y,&z)) break; \
  37. negepsilon_bits++; \
  38. } } \
  39. printf("/* Properties of type `%s': */\n",typestr); \
  40. printf("/* Largest n for which 1+2^(-n) is exactly represented is %d. */\n",epsilon_bits); \
  41. printf("/* Largest n for which 1-2^(-n) is exactly represented is %d. */\n",negepsilon_bits); \
  42. if (negepsilon_bits <= epsilon_bits) \
  43. { printf("#error \"No exponent jump at 1.0 for type %s!\"\n",typestr); \
  44. mant_bits = -1; \
  45. } \
  46. else \
  47. { if (negepsilon_bits > epsilon_bits+1) \
  48. printf("/* Base for type `%s' is 2^%d\n",typestr,negepsilon_bits-epsilon_bits); \
  49. mant_bits = epsilon_bits+1; \
  50. printf("#define %s_mant_bits %d\n",typeprefix,mant_bits); \
  51. } \
  52. { int i; type x, y1, y2, ys1, ys2, z1, z2, zs1, zs2; \
  53. x = 1.0; for (i = 0; i < epsilon_bits; i++) { x = 0.5*x; } \
  54. y1 = 1.0 + 5.0*x; y2 = 1.0 + 6.0*x; \
  55. ys1 = 1.0 + 5.4*x; ys2 = 1.0 + 5.6*x; \
  56. z1 = -1.0 + (-5.0)*x; z2 = -1.0 + (-6.0)*x; \
  57. zs1 = -1.0 + (-5.4)*x; zs2 = -1.0 + (-5.6)*x; \
  58. if (equalfn(&ys1,&y1) && equalfn(&ys2,&y2) && equalfn(&zs1,&z1) && equalfn(&zs2,&z2)) \
  59. printf("#define %s_rounds rounds_to_nearest\n",typeprefix); \
  60. else if (equalfn(&ys1,&y1) && equalfn(&ys2,&y1) && equalfn(&zs1,&z1) && equalfn(&zs2,&z1)) \
  61. printf("#define %s_rounds rounds_to_zero\n",typeprefix); \
  62. else if (equalfn(&ys1,&y2) && equalfn(&ys2,&y2) && equalfn(&zs1,&z1) && equalfn(&zs2,&z1)) \
  63. printf("#define %s_rounds rounds_to_infinity\n",typeprefix); \
  64. else if (equalfn(&ys1,&y1) && equalfn(&ys2,&y1) && equalfn(&zs1,&z2) && equalfn(&zs2,&z2)) \
  65. printf("#define %s_rounds rounds_to_minus_infinity\n",typeprefix); \
  66. else \
  67. printf("#error \"Unknown rounding mode for type %s!\"\n",typestr); \
  68. } \
  69. printf("\n"); \
  70. } \
  71. static boolean equalfn (volatile type* x, volatile type* y) \
  72. { \
  73. return *x == *y; \
  74. } \
  75. check(float,"float","float",equal_float,main_float)
  76. check(double,"double","double",equal_double,main_double)
  77. #ifdef HAVE_LONGDOUBLE
  78. check(ldouble,"long_double","long double",equal_ldouble,main_ldouble)
  79. #endif
  80. /* Some systems (arm/linux) store doubles as little endian but with higher
  81. * and lower word reversed. */
  82. static void flipped_double (void)
  83. {
  84. typedef struct { unsigned lo, hi; } dfloat;
  85. union { dfloat eksplicit; double machine_double; } x;
  86. x.machine_double = 2;
  87. dfloat test = x.eksplicit;
  88. if (test.lo==0 && test.hi!=0) {
  89. printf("#define double_wordorder_bigendian_p 0\n");
  90. } else if (test.lo!=0 && test.hi==0) {
  91. printf("#define double_wordorder_bigendian_p 1\n");
  92. } else {
  93. /* Dazed and confused! Better not define anything.
  94. * Code should rely on CL_CPU_BIG_ENDIAN_P instead. */
  95. }
  96. printf("\n");
  97. }
  98. int main()
  99. {
  100. header();
  101. main_float();
  102. main_double();
  103. #ifdef HAVE_LONGDOUBLE
  104. main_ldouble();
  105. #endif
  106. flipped_double();
  107. if (ferror(stdout) || fclose(stdout)) return 1;
  108. return 0;
  109. }