fork download
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <limits.h>
  4. #include <assert.h>
  5.  
  6. #define C_ASSERT(expr) extern char CAssertExtern[(expr)?1:-1]
  7.  
  8. #if UINT_MAX >= 0xFFFFFFFF
  9. typedef unsigned int uint32;
  10. #else
  11. typedef unsigned long uint32;
  12. #endif
  13. typedef unsigned long long uint64;
  14.  
  15. C_ASSERT(CHAR_BIT == 8);
  16. C_ASSERT(sizeof(uint32) == 4);
  17. C_ASSERT(sizeof(float) == 4);
  18.  
  19. int ProductIsOne(float f1, float f2)
  20. {
  21. uint32 m1, m2;
  22. int e1, e2, s1, s2;
  23. int e;
  24. uint64 m;
  25.  
  26. // Make sure floats are 32-bit IEE754 and
  27. // reinterpreted as integers as we expect
  28. {
  29. static const float testf = 8873283.0f;
  30. uint32 testi;
  31. memcpy(&testi, &testf, sizeof(testf));
  32. assert(testi == 0x4B076543);
  33. }
  34.  
  35. memcpy(&m1, &f1, sizeof(f1));
  36. s1 = m1 >= 0x80000000;
  37. m1 &= 0x7FFFFFFF;
  38. e1 = m1 >> 23;
  39. m1 &= 0x7FFFFF;
  40. if (e1 > 0) m1 |= 0x800000;
  41.  
  42. memcpy(&m2, &f2, sizeof(f2));
  43. s2 = m2 >= 0x80000000;
  44. m2 &= 0x7FFFFFFF;
  45. e2 = m2 >> 23;
  46. m2 &= 0x7FFFFF;
  47. if (e2 > 0) m2 |= 0x800000;
  48.  
  49. if (e1 == 0xFF || e2 == 0xFF || s1 != s2) // Inf, NaN, different signs
  50. return 0;
  51.  
  52. m = (uint64)m1 * m2;
  53.  
  54. if (!m || (m & (m - 1))) // not a power of 2
  55. return 0;
  56.  
  57. e = e1 + !e1 - 0x7F - 23 + e2 + !e2 - 0x7F - 23;
  58. while (m > 1) m >>= 1, e++;
  59.  
  60. return e == 0;
  61. }
  62.  
  63. const float testData[][2] =
  64. {
  65. { .1f, 10.0f },
  66. { 0.5f, 2.0f },
  67. { 0.25f, 2.0f },
  68. { 4.0f, 0.25f },
  69. { 0.33333333f, 3.0f },
  70. { 0.00000762939453125f, 131072.0f }, // 2^-17 * 2^17
  71. { 1.26765060022822940E30f, 7.88860905221011805E-31f }, // 2^100 * 2^-100
  72. };
  73.  
  74. int main(void)
  75. {
  76. int i;
  77. for (i = 0; i < sizeof(testData) / sizeof(testData[0]); i++)
  78. printf("%g * %g %c= 1\n",
  79. testData[i][0], testData[i][1],
  80. "!="[ProductIsOne(testData[i][0], testData[i][1])]);
  81. return 0;
  82. }
  83.  
Success #stdin #stdout 0.02s 1720KB
stdin
Standard input is empty
stdout
0.1 * 10 != 1
0.5 * 2 == 1
0.25 * 2 != 1
4 * 0.25 == 1
0.333333 * 3 != 1
7.62939e-06 * 131072 == 1
1.26765e+30 * 7.88861e-31 == 1