PolyfloatUtil.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. #ifndef MANDEL_POLYFLOATUTIL_H
  2. #define MANDEL_POLYFLOATUTIL_H
  3. namespace mnd
  4. {
  5. namespace pfu
  6. {
  7. template<typename T>
  8. struct Pair
  9. {
  10. T a;
  11. T b;
  12. };
  13. template<typename T>
  14. struct Triple
  15. {
  16. T a;
  17. T b;
  18. T c;
  19. };
  20. template<typename T>
  21. struct Quadruple
  22. {
  23. T a;
  24. T b;
  25. T c;
  26. T d;
  27. };
  28. using DoublePair = Pair<double>;
  29. using FloatPair = Pair<float>;
  30. template<typename T>
  31. inline static Pair<T> quickTwoSum(T a, T b)
  32. {
  33. T s = a + b;
  34. T e = b - (s - a);
  35. return { s, e };
  36. }
  37. template<typename T>
  38. inline Pair<T> twoSum(T a, T b)
  39. {
  40. T s = a + b;
  41. T v = s - a;
  42. T e = (a - (s - v)) + (b - v);
  43. return { s, e };
  44. }
  45. template<typename T>
  46. inline Triple<T> threeSum(T a, T b, T c)
  47. {
  48. auto[t1, t2] = twoSum(a, b);
  49. auto[r0, t3] = twoSum(t1, c);
  50. auto[r1, r2] = twoSum(t2, t3);
  51. return { r0, r1, r2 };
  52. }
  53. template<typename T>
  54. inline Pair<T> threeTwoSum(T a, T b, T c)
  55. {
  56. auto[t1, t2] = twoSum(a, b);
  57. auto[r0, t3] = twoSum(t1, c);
  58. return { r0, t2 + t3 };
  59. }
  60. template<typename T>
  61. inline Quadruple<T> fourSum(T a, T b, T c, T d)
  62. {
  63. auto[t1, t2] = twoSum(a, b);
  64. auto[t3, t4] = twoSum(t1, c);
  65. auto[r0, t5] = twoSum(t3, d);
  66. auto[r1, r2, r3] = threeSum(t2, t4, t5);
  67. return { r0, r1, r2, r3 };
  68. }
  69. template<typename T>
  70. inline Pair<T> fiveTwoSum(T a, T b, T c, T d, T e)
  71. {
  72. auto[t1, t2] = twoSum(a, b);
  73. auto[t3, t4] = twoSum(t1, c);
  74. auto[t5, t6] = twoSum(t3, d);
  75. auto[r0, t7] = twoSum(t5, e);
  76. return { r0, t2 + t4 + t6 + t7 };
  77. }
  78. template<typename T>
  79. inline Triple<T> sixThreeSum(T a, T b, T c, T d, T e, T f)
  80. {
  81. auto[a1, a2, a3] = threeSum(a, b, c);
  82. auto[b1, b2, b3] = threeSum(d, e, f);
  83. auto[r1, t1] = twoSum(a1, b1);
  84. auto[t2, t3] = twoSum(a2, b2);
  85. auto t4 = a3 + b3;
  86. auto[r2, t5] = twoSum(t1, t2);
  87. auto r3 = t4 + t3 + t5;
  88. return { r1, r2, r3 };
  89. }
  90. template<typename T>
  91. inline Triple<T> nineThreeSum(T a, T b, T c, T d, T e, T f, T g, T h, T i)
  92. {
  93. auto[a1, a2, a3] = threeSum(a, b, c);
  94. auto[b1, b2, b3] = threeSum(d, e, f);
  95. auto[c1, c2, c3] = threeSum(g, h, i);
  96. auto[r1, t1, t2] = threeSum(a1, b1, c1);
  97. auto[r2, t3, t4, t5] = fourSum(a2, b2, c2, t1);
  98. auto r3 = a3 + b3 + c3 + t2 + t3 + t4 + t5;
  99. return { r1, r2, r3 };
  100. }
  101. inline Pair<double> split(double a)
  102. {
  103. static const double splitter = double((1ULL << 27) + 1);
  104. double t = splitter * a;
  105. double ahi = t - (t - a);
  106. double alo = a - ahi;
  107. return { ahi, alo };
  108. }
  109. template<typename T>
  110. inline Pair<T> twoProd(T a, T b)
  111. {
  112. T p = a * b;
  113. auto [ahi, alo] = split(a);
  114. auto [bhi, blo] = split(b);
  115. T e = ((ahi * bhi - p) + ahi * blo + alo * bhi) + alo * blo;
  116. return { p, e };
  117. }
  118. template<typename T>
  119. inline Pair<T> twoProdFma(T a, T b)
  120. {
  121. T p = a * b;
  122. //T e = std::fma(a, b, -p);
  123. T e = 0;
  124. return { p, e };
  125. }
  126. }
  127. }
  128. #endif // MANDEL_POLYFLOATUTIL_H