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. void smalldouble_to_cell(void*p, double d)
  11. {
  12. union u u;
  13. u.d = d;
  14. unsigned long long rest = u.u & 0x7fffffffffffffff;
  15. unsigned long long packed;
  16. if (rest > 0x7ff0000000000000)
  17. /* NaN */
  18. packed = u.u & 0xfffffffffffffffe;
  19. else
  20. {
  21. unsigned long long sign = u.u & 0x8000000000000000;
  22. if (rest >= 0x3ff0000000000000)
  23. rest = 0x3ff0000000000000;
  24. packed = sign | (rest << 1);
  25. }
  26. memcpy(p, &packed, 8);
  27. }
  28.  
  29. void double_to_cell(void *p, double d)
  30. {
  31. smalldouble_to_cell(p, ldexp(d, -512));
  32. }
  33.  
  34. double smalldouble_from_cell(void*p)
  35. {
  36. union u u;
  37. unsigned long long l;
  38. memcpy(&l, p, 8);
  39. unsigned long long sign = l & 0x8000000000000000;
  40. unsigned long long rest = (l & 0x7fffffffffffffff) >> 1;
  41. if (rest >= 0x3ff0000000000000) rest <<= 1;
  42. u.u = sign | rest;
  43. return u.d;
  44. }
  45.  
  46. double double_from_cell(void*p)
  47. {
  48. double d = smalldouble_from_cell(p);
  49. return ldexp(d, +512);
  50. }
  51.  
  52. void float_cell_add(void *d, void *s1, void *s2)
  53. {
  54. double d1 = smalldouble_from_cell(s1);
  55. double d2 = smalldouble_from_cell(s2);
  56. smalldouble_to_cell(d, d1 + d2);
  57. }
  58.  
  59. void float_cell_sub(void *d, void *s1, void *s2)
  60. {
  61. double d1 = smalldouble_from_cell(s1);
  62. double d2 = smalldouble_from_cell(s2);
  63. smalldouble_to_cell(d, d1 - d2);
  64. }
  65.  
  66. void float_cell_mul(void *d, void *s1, void *s2)
  67. {
  68. double d1 = smalldouble_from_cell(s1);
  69. double d2 = smalldouble_from_cell(s2);
  70. smalldouble_to_cell(d, ldexp(d1, +512) * d2);
  71. }
  72.  
  73. void float_cell_div(void *d, void *s1, void *s2)
  74. {
  75. double d1 = smalldouble_from_cell(s1);
  76. double d2 = smalldouble_from_cell(s2);
  77. smalldouble_to_cell(d, ldexp(d1/d2, -512));
  78. }
  79.  
  80. int main()
  81. {
  82. unsigned long long l1, l2, l3;
  83.  
  84. double_to_cell(&l1, 3.0);
  85. double_to_cell(&l2, 7.0);
  86. float_cell_add(&l3, &l1, &l2);
  87. printf("3.0 + 7.0 = %f\n", double_from_cell(&l3));
  88. printf("representations: %llx %llx %llx\n", l1, l2 , l3);
  89.  
  90. double_to_cell(&l1, nextafter(1.0, 2.0));
  91. double_to_cell(&l2, nextafter(1.5, 0.0));
  92. float_cell_add(&l3, &l1, &l2);
  93. printf("(1+) + (1.5-) = %f\n", double_from_cell(&l3));
  94. printf("representations: %llx %llx %llx\n", l1, l2 , l3);
  95.  
  96. double_to_cell(&l1, 1.0e-168);
  97. double_to_cell(&l2, 1.3e-168);
  98. float_cell_add(&l3, &l1, &l2);
  99. printf("(1.0-168) + (1.3-168) = %e\n", double_from_cell(&l3));
  100. printf("representations: %llx %llx %llx\n", l1, l2 , l3);
  101.  
  102. double_to_cell(&l1, 1.0e-90);
  103. double_to_cell(&l2, 1.3e-78);
  104. float_cell_mul(&l3, &l1, &l2);
  105. printf("(1.0-90) * (1.3-78) = %e\n", double_from_cell(&l3));
  106. printf("representations: %llx %llx %llx\n", l1, l2 , l3);
  107.  
  108. double_to_cell(&l1, 1.0e+70);
  109. double_to_cell(&l2, 1.3e+78);
  110. float_cell_mul(&l3, &l1, &l2);
  111. printf("(1.0+70) * (1.3+78) = %e\n", double_from_cell(&l3));
  112. printf("representations: %llx %llx %llx\n", l1, l2 , l3);
  113.  
  114. double_to_cell(&l1, 1.0e+90);
  115. double_to_cell(&l2, 1.3e+78);
  116. float_cell_mul(&l3, &l1, &l2);
  117. printf("(1.0+90) * (1.3+78) = %e\n", double_from_cell(&l3));
  118. printf("representations: %llx %llx %llx\n", l1, l2 , l3);
  119.  
  120. double_to_cell(&l1, 1.0e+90);
  121. double_to_cell(&l2, 1.3e+78);
  122. float_cell_div(&l3, &l1, &l2);
  123. printf("(1.0+90) / (1.3+78) = %e\n", double_from_cell(&l3));
  124. printf("representations: %llx %llx %llx\n", l1, l2 , l3);
  125.  
  126. double_to_cell(&l1, 1.0e200);
  127. double_to_cell(&l2, 1.0e-200);
  128. float_cell_div(&l3, &l1, &l2);
  129. printf("inf / 0 = %e\n", double_from_cell(&l3));
  130. printf("representations: %llx %llx %llx\n", l1, l2 , l3);
  131.  
  132. double_to_cell(&l1, 1.0e200);
  133. double_to_cell(&l2, 1.0e-200);
  134. float_cell_mul(&l3, &l1, &l2);
  135. printf("inf * 0 = %e\n", double_from_cell(&l3));
  136. printf("representations: %llx %llx %llx\n", l1, l2 , l3);
  137.  
  138. return 0;
  139. }
  140.  
Success #stdin #stdout 0s 1836KB
stdin
Standard input is empty
stdout
3.0 + 7.0 = 10.000000
representations: 4010000000000000 4038000000000000 4048000000000000
(1+) + (1.5-) = 2.500000
representations: 3fe0000000000002 3feffffffffffffe 4008000000000000
(1.0-168) + (1.3-168) = 2.318518e-168
representations: 1e 28 46
(1.0-90) * (1.3-78) = 1.324867e-168
representations: 1a8097b309321cde 1f86891d8f552d50 28
(1.0+70) * (1.3+78) = 1.300000e+148
representations: 5cee5d75adbb8e7a 604ce877b35bbef4 7d6088aa69bd653c
(1.0+90) * (1.3+78) = inf
representations: 653ed61e1252b38e 604ce877b35bbef4 7fe0000000000000
(1.0+90) / (1.3+78) = 7.692308e+11
representations: 653ed61e1252b38e 604ce877b35bbef4 44ccc66e8313b13a
inf / 0 = inf
representations: 7fe0000000000000 0 7fe0000000000000
inf * 0 = -nan
representations: 7fe0000000000000 0 fff8000000000000