fork download
  1. #include <string.h>
  2. #include <math.h>
  3. #include <stdio.h>
  4.  
  5. union u {
  6. unsigned long long u; /* assumed to be 64-bit */
  7. double d;
  8. };
  9.  
  10. typedef unsigned long long boxed;
  11.  
  12. boxed smalldouble_to_boxed(double d)
  13. {
  14. union u u;
  15. u.d = d;
  16. boxed rest = u.u & 0x7fffffffffffffff;
  17. boxed packed;
  18. if (rest > 0x7ff0000000000000)
  19. /* NaN */
  20. packed = u.u;
  21. else
  22. {
  23. boxed sign = u.u & 0x8000000000000000;
  24. if (rest >= 0x3ff0000000000000)
  25. /* inf */
  26. rest = 0x3ff0000000000000;
  27. packed = sign | (rest << 1);
  28. }
  29. return packed | 1;
  30. }
  31.  
  32. boxed double_to_boxed(double d)
  33. {
  34. return smalldouble_to_boxed(ldexp(d, -512));
  35. }
  36.  
  37. double smalldouble_from_boxed(boxed l)
  38. {
  39. union u u;
  40. boxed sign = l & 0x8000000000000000;
  41. boxed rest = (l & 0x7fffffffffffffff) >> 1;
  42. if (rest >= 0x3ff0000000000000) rest <<= 1;
  43. u.u = sign | rest;
  44. return u.d;
  45. }
  46.  
  47. double double_from_boxed(boxed l)
  48. {
  49. double d = smalldouble_from_boxed(l);
  50. return ldexp(d, +512);
  51. }
  52.  
  53. boxed smalldouble_add(boxed s1, boxed s2)
  54. {
  55. double d1 = smalldouble_from_boxed(s1);
  56. double d2 = smalldouble_from_boxed(s2);
  57. return smalldouble_to_boxed(d1 + d2);
  58. }
  59.  
  60. boxed smalldouble_sub(boxed s1, boxed s2)
  61. {
  62. double d1 = smalldouble_from_boxed(s1);
  63. double d2 = smalldouble_from_boxed(s2);
  64. return smalldouble_to_boxed(d1 - d2);
  65. }
  66.  
  67. boxed smalldouble_mul(boxed s1, boxed s2)
  68. {
  69. double d1 = smalldouble_from_boxed(s1);
  70. double d2 = smalldouble_from_boxed(s2);
  71. return smalldouble_to_boxed(ldexp(d1, +512) * d2);
  72. }
  73.  
  74. boxed smalldouble_div(boxed s1, boxed s2)
  75. {
  76. double d1 = smalldouble_from_boxed(s1);
  77. double d2 = smalldouble_from_boxed(s2);
  78. return smalldouble_to_boxed(ldexp(d1/d2, -512));
  79. }
  80.  
  81. int main()
  82. {
  83. boxed l1, l2, l3;
  84.  
  85. l1 = double_to_boxed(3.0);
  86. l2 = double_to_boxed(7.0);
  87. l3 = smalldouble_add(l1, l2);
  88. printf("3.0 + 7.0 = %f\n", double_from_boxed(l3));
  89. printf("representations: %llx %llx %llx\n", l1, l2 , l3);
  90.  
  91. l1 = double_to_boxed(nextafter(1.0, 2.0));
  92. l2 = double_to_boxed(nextafter(1.5, 0.0));
  93. l3 = smalldouble_add(l1, l2);
  94. printf("(1+) + (1.5-) = %f\n", double_from_boxed(l3));
  95. printf("representations: %llx %llx %llx\n", l1, l2 , l3);
  96.  
  97. l1 = double_to_boxed(1.0e-168);
  98. l2 = double_to_boxed(1.3e-168);
  99. l3 = smalldouble_add(l1, l2);
  100. printf("(1.0-168) + (1.3-168) = %e\n", double_from_boxed(l3));
  101. printf("representations: %llx %llx %llx\n", l1, l2 , l3);
  102.  
  103. l1 = double_to_boxed(1.00000000001e-155);
  104. l2 = double_to_boxed(1.0e-155);
  105. l3 = smalldouble_sub(l1, l2);
  106. printf("(1.0...01-155) + (1.0-155) = %.16e\n", double_from_boxed(l3));
  107. printf("representations: %llx %llx %llx\n", l1, l2 , l3);
  108.  
  109. l1 = double_to_boxed(1.0e-90);
  110. l2 = double_to_boxed(1.3e-78);
  111. l3 = smalldouble_mul(l1, l2);
  112. printf("(1.0-90) * (1.3-78) = %e\n", double_from_boxed(l3));
  113. printf("representations: %llx %llx %llx\n", l1, l2 , l3);
  114.  
  115. l1 = double_to_boxed(1.0e+70);
  116. l2 = double_to_boxed(1.3e+78);
  117. l3 = smalldouble_mul(l1, l2);
  118. printf("(1.0+70) * (1.3+78) = %e\n", double_from_boxed(l3));
  119. printf("representations: %llx %llx %llx\n", l1, l2 , l3);
  120.  
  121. l1 = double_to_boxed(1.0e+90);
  122. l2 = double_to_boxed(1.3e+78);
  123. l3 = smalldouble_mul(l1, l2);
  124. printf("(1.0+90) * (1.3+78) = %e\n", double_from_boxed(l3));
  125. printf("representations: %llx %llx %llx\n", l1, l2 , l3);
  126.  
  127. l1 = double_to_boxed(1.0e+90);
  128. l2 = double_to_boxed(1.3e+78);
  129. l3 = smalldouble_div(l1, l2);
  130. printf("(1.0+90) / (1.3+78) = %e\n", double_from_boxed(l3));
  131. printf("representations: %llx %llx %llx\n", l1, l2 , l3);
  132.  
  133. l1 = double_to_boxed(1.0e200);
  134. l2 = double_to_boxed(1.0e-200);
  135. l3 = smalldouble_div(l1, l2);
  136. printf("inf / 0 = %e\n", double_from_boxed(l3));
  137. printf("representations: %llx %llx %llx\n", l1, l2 , l3);
  138.  
  139. l1 = double_to_boxed(1.0e200);
  140. l2 = double_to_boxed(1.0e-200);
  141. l3 = smalldouble_mul(l1, l2);
  142. printf("inf * 0 = %e\n", double_from_boxed(l3));
  143. printf("representations: %llx %llx %llx\n", l1, l2 , l3);
  144.  
  145. return 0;
  146. }
  147.  
Success #stdin #stdout 0s 1836KB
stdin
Standard input is empty
stdout
3.0 + 7.0 = 10.000000
representations: 4010000000000001 4038000000000001 4048000000000001
(1+) + (1.5-) = 2.500000
representations: 3fe0000000000003 3fefffffffffffff 4008000000000001
(1.0-168) + (1.3-168) = 2.318518e-168
representations: 1f 29 47
(1.0...01-155) + (1.0-155) = 9.9961249618917165e-167
representations: 11297872da887 11297872d9cbd bcb
(1.0-90) * (1.3-78) = 1.324867e-168
representations: 1a8097b309321cdf 1f86891d8f552d51 29
(1.0+70) * (1.3+78) = 1.300000e+148
representations: 5cee5d75adbb8e7b 604ce877b35bbef5 7d6088aa69bd653d
(1.0+90) * (1.3+78) = inf
representations: 653ed61e1252b38f 604ce877b35bbef5 7fe0000000000001
(1.0+90) / (1.3+78) = 7.692308e+11
representations: 653ed61e1252b38f 604ce877b35bbef5 44ccc66e8313b13b
inf / 0 = inf
representations: 7fe0000000000001 1 7fe0000000000001
inf * 0 = -nan
representations: 7fe0000000000001 1 fff8000000000001