fork download
  1. #include <iostream>
  2. #include <math.h>
  3.  
  4. #define FP_UNSUPPORTED FP_NAN
  5.  
  6. /* 7.12.3.1 */
  7. /*
  8.   Return values for fpclassify.
  9.   These are based on Intel x87 fpu condition codes
  10.   in the high byte of status word and differ from
  11.   the return values for MS IEEE 754 extension _fpclass()
  12. */
  13. /*
  14. #define FP_NAN 0x0100
  15. #define FP_NORMAL 0x0400
  16. #define FP_INFINITE (FP_NAN | FP_NORMAL)
  17. #define FP_ZERO 0x4000
  18. #define FP_SUBNORMAL (FP_NORMAL | FP_ZERO)
  19. // 0x0200 is signbit mask
  20. */
  21.  
  22. /*__CRT_INLINE int __cdecl my_fpclassifyl(long double x)
  23. {
  24.   __mingw_fp_types_t hlp;
  25.   unsigned int e;
  26.   hlp.ld = &x;
  27.   e = hlp.ldt->lh.sign_exponent & 0x7fff;
  28.   unsigned int h = hlp.ldt->lh.high;
  29.   if (!e)
  30.   {
  31.   if (!(hlp.ldt->lh.low | h))
  32.   return FP_ZERO;
  33.   else if (!(h & 0x80000000))
  34.   return FP_SUBNORMAL;
  35.   }
  36.   else if (e == 0x7fff)
  37.   return (((hlp.ldt->lh.high & 0x7fffffff) | hlp.ldt->lh.low) == 0 ?
  38.   FP_INFINITE : FP_NAN);
  39.   return ((h & 0x80000000) == 0) ? FP_NAN : FP_NORMAL;
  40. }*/
  41.  
  42. template<class T>
  43. void printVal(T val, const char* format)
  44. {
  45. printf(format, val);
  46. }
  47.  
  48. typedef union my__mingw_ldbl_type_t
  49. {
  50. long double x;
  51. struct {
  52. unsigned int low, high;
  53. int sign_exponent : 16;
  54. int res1 : 16;
  55. int res0 : 32;
  56. } lh;
  57. } my__mingw_ldbl_type_t;
  58.  
  59. int myclassify(long double ld)
  60. {
  61. my__mingw_ldbl_type_t lds = *(my__mingw_ldbl_type_t*)&ld;
  62. //https://e...content-available-to-author-only...a.org/wiki/Extended_precision#x86_extended_precision_format
  63. auto bit63 = (lds.lh.high & 0x80000000) != 0;
  64. switch (lds.lh.sign_exponent & 0x7fff) //Exponent
  65. {
  66. case 0: //Exponent: All Zeros
  67. {
  68. if (!bit63) //Bit 63: Zero
  69. {
  70. if (lds.lh.low == 0 && (lds.lh.high & 0x7fffffff) == 0) //Bits 62-0: Zero
  71. {
  72. return FP_ZERO; //Zero. The sign bit gives the sign of the zero.
  73. }
  74. else //Bits 62-0: Non-zero
  75. {
  76. return FP_SUBNORMAL; //Denormal. The value is (−1)^s * m * 2^(−16382)
  77. }
  78. }
  79. else //Bit 63: One
  80. {
  81. return FP_SUBNORMAL; //Pseudo Denormal. The 80387 and later properly interpret this value but will not generate it. The value is (−1)^s * m * 2^(−16382)
  82. }
  83. }
  84.  
  85. case 0x7fff: //Exponent: All Ones
  86. {
  87. auto bit62 = (lds.lh.high & 0x40000000) != 0;
  88. auto bit61to0_zero = (lds.lh.high & 0x3fffffff) == 0 && lds.lh.low == 0;
  89. if (!bit63 && !bit62) //Bits 63,62: 00
  90. {
  91. if (bit61to0_zero) //Bits 61-0: Zero
  92. {
  93. return FP_UNSUPPORTED; //Pseudo-Infinity. The sign bit gives the sign of the infinity. The 8087 and 80287 treat this as Infinity. The 80387 and later treat this as an invalid operand.
  94. }
  95. else //Bits 61-0: Non-zero
  96. {
  97. return FP_UNSUPPORTED; //Pseudo Not a Number. The sign bit is meaningless. The 8087 and 80287 treat this as a Signaling Not a Number. The 80387 and later treat this as an invalid operand.
  98. }
  99. }
  100. else if (!bit63 && bit62) //Bits 63,62: 01
  101. {
  102. //Bits 61-0: Anything
  103. return FP_UNSUPPORTED; //Pseudo Not a Number. The sign bit is meaningless. The 8087 and 80287 treat this as a Signaling Not a Number. The 80387 and later treat this as an invalid operand.
  104. }
  105. else if (bit63 && !bit62) //Bits 63,62: 10
  106. {
  107. if (bit61to0_zero) //Bits 61-0: Zero
  108. {
  109. return FP_INFINITE; //Infinity. The sign bit gives the sign of the infinity. The 8087 and 80287 treat this as a Signaling Not a Number. The 8087 and 80287 coprocessors used the pseudo-infinity representation for infinities.
  110. }
  111. else //Bits 61-0: Non-zero
  112. {
  113. return FP_NAN; //Signalling Not a Number, the sign bit is meaningless.
  114. }
  115. }
  116. else if (bit63 && bit62) //Bits 63,62: 11
  117. {
  118. if (bit61to0_zero) //Bits 61-0: Zero
  119. {
  120. return FP_NAN; //Floating-point Indefinite, the result of invalid calculations such as square root of a negative number, logarithm of a negative number, 0/0, infinity / infinity, infinity times 0, and others when the processor has been configured to not generate exceptions for invalid operands. The sign bit is meaningless. This is a special case of a Quiet Not a Number.
  121. }
  122. else //Bits 61-0: Non-zero
  123. {
  124. return FP_NAN; //Quiet Not a Number, the sign bit is meaningless. The 8087 and 80287 treat this as a Signaling Not a Number.
  125. }
  126. }
  127. }
  128.  
  129. default: //Exponent: All other values
  130. {
  131. if (!bit63) //Bit 63: Zero
  132. {
  133. return FP_UNSUPPORTED; //Unnormal. Only generated on the 8087 and 80287. The 80387 and later treat this as an invalid operand. The value is (−1)^s * m * 2^(e−16383)
  134. }
  135. else //Bit 63: One
  136. {
  137. return FP_NORMAL; //Normalized value. The value is (−1)^s * m * 2^(e−16383)
  138. }
  139. }
  140. }
  141. }
  142. #include <string.h>
  143. # define fufu(x) __builtin_fpclassify (FP_NAN, FP_INFINITE, \
  144.   FP_NORMAL, FP_SUBNORMAL, FP_ZERO, x)
  145. int main()
  146. {
  147. long double ld;
  148. unsigned char data[10] = {0x5b, 0x01, 0x04, 0x5e, 0x85, 0x00, 0x00, 0x00, 0xd8, 0x59};
  149. memcpy(&ld, data, 10);
  150.  
  151. my__mingw_ldbl_type_t fuck = *(my__mingw_ldbl_type_t*)&ld;
  152.  
  153. printVal(fuck.lh.low, "lh.low: 0x%08X\n");
  154. printVal(fuck.lh.high, "lh.high: 0x%08X\n");
  155. printVal(fuck.lh.sign_exponent, "lh.sign_exponent: 0x%04X\n");
  156. printVal(fuck.lh.res0, "lh.res0: 0x%04X\n");
  157. printVal(fuck.lh.res1, "lh.res1: 0x%08X\n");
  158.  
  159. memset(&fuck, 0, sizeof(fuck));
  160. fuck.lh.low = 0xffffffff;
  161.  
  162. for(unsigned int sign_exponent = 0; sign_exponent < 65536; sign_exponent++)
  163. {
  164. for(unsigned int high = 0; high < 256; high++)
  165. {
  166. fuck.lh.sign_exponent = sign_exponent;
  167. fuck.lh.high = high;
  168. auto builtin = fufu(fuck.x);
  169. auto my = myclassify(fuck.x);
  170. if(builtin != my)
  171. {
  172. printf("FUCK, sign_exponent: 0x%X, high: 0x%X, 0x%X!=0x%X\n", sign_exponent, high, builtin, my);
  173. return 0;
  174. }
  175. }
  176. }
  177. puts("YAY");
  178. return 0;
  179. }
  180.  
  181.  
Success #stdin #stdout 2.16s 15240KB
stdin
Standard input is empty
stdout
lh.low: 0x5E04015B
lh.high: 0x00000085
lh.sign_exponent: 0x59D8
lh.res0: 0x2B96
lh.res1: 0x0000677C
YAY