HexDouble.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. #ifndef MANDEL_HEXDOUBLE_H
  2. #define MANDEL_HEXDOUBLE_H
  3. #include "PolyfloatUtil.h"
  4. namespace mnd
  5. {
  6. struct HexDouble;
  7. }
  8. struct mnd::HexDouble
  9. {
  10. double x[6];
  11. inline HexDouble(double val) :
  12. x{ val, 0.0, 0.0, 0.0, 0.0, 0.0 }
  13. {}
  14. inline HexDouble(double a, double b, double c, double d, double e, double f) :
  15. x{ a, b, c, d, e, f }
  16. {}
  17. double operator[] (int i) const { return x[i]; }
  18. const double& operator[] (int i) { return x[i]; }
  19. };
  20. inline mnd::HexDouble operator+(const mnd::HexDouble& a,
  21. const mnd::HexDouble& b)
  22. {
  23. auto[a0, a1] = mnd::pfu::twoSum(a[0], b[0]);
  24. auto[b0, b1] = mnd::pfu::twoSum(a[1], b[1]);
  25. auto[c0, c1] = mnd::pfu::twoSum(a[2], b[2]);
  26. auto[d0, d1] = mnd::pfu::twoSum(a[3], b[3]);
  27. auto[e0, e1] = mnd::pfu::twoSum(a[4], b[4]);
  28. auto t0 = a0;
  29. auto [t1, p1] = mnd::pfu::twoSum(a1, b0);
  30. auto [t2, p2, p3] = mnd::pfu::threeSum(b1, c0, p1);
  31. auto [t3, p4, p5, p6] = mnd::pfu::fourSum(c1, d0, p2, p3);
  32. auto [t4, p7] = mnd::pfu::fiveTwoSum(d1, e0, p4, p5, p6);
  33. auto t5 = a[5] + b[5] + e1 + p7;
  34. auto[re0, er1] = mnd::pfu::quickTwoSum(t0, t1);
  35. auto[re1, e2] = mnd::pfu::quickTwoSum(er1, t2);
  36. auto[re2, e3] = mnd::pfu::quickTwoSum(e2, t3);
  37. auto[re3, e4] = mnd::pfu::quickTwoSum(e3, t4);
  38. auto[re4, re5] = mnd::pfu::quickTwoSum(e4, t5);
  39. //return { t1, t2, t3, t4, t5, t6 };
  40. return { re0, re1, re2, re3, re4, re5 };
  41. }
  42. inline bool operator>(const mnd::HexDouble& a, const mnd::HexDouble& b)
  43. {
  44. if (a[0] > b[0])
  45. return true;
  46. if (a[0] < b[0])
  47. return false;
  48. if (a[1] > b[1])
  49. return true;
  50. if (a[1] < b[1])
  51. return false;
  52. return a[2] > b[2];
  53. }
  54. inline mnd::HexDouble operator-(const mnd::HexDouble& a,
  55. const mnd::HexDouble& b)
  56. {
  57. return a + mnd::HexDouble{ -b[0], -b[1], -b[2], -b[3], -b[4], -b[5] };
  58. }
  59. inline mnd::HexDouble operator*(const mnd::HexDouble& a,
  60. const mnd::HexDouble& b)
  61. {
  62. auto[p1_0, p2_0] = mnd::pfu::twoProd(a[0], b[0]);
  63. auto[p2_1, p3_0] = mnd::pfu::twoProd(a[0], b[1]);
  64. auto[p2_2, p3_1] = mnd::pfu::twoProd(a[1], b[0]);
  65. auto[p3_2, p4_0] = mnd::pfu::twoProd(a[2], b[0]);
  66. auto[p3_3, p4_1] = mnd::pfu::twoProd(a[1], b[1]);
  67. auto[p3_4, p4_2] = mnd::pfu::twoProd(a[0], b[2]);
  68. auto[p4_3, p5_0] = mnd::pfu::twoProd(a[3], b[0]);
  69. auto[p4_4, p5_1] = mnd::pfu::twoProd(a[2], b[1]);
  70. auto[p4_5, p5_2] = mnd::pfu::twoProd(a[1], b[2]);
  71. auto[p4_6, p5_3] = mnd::pfu::twoProd(a[0], b[3]);
  72. auto[p5_4, p6_0] = mnd::pfu::twoProd(a[4], b[0]);
  73. auto[p5_5, p6_1] = mnd::pfu::twoProd(a[3], b[1]);
  74. auto[p5_6, p6_2] = mnd::pfu::twoProd(a[2], b[2]);
  75. auto[p5_7, p6_3] = mnd::pfu::twoProd(a[1], b[3]);
  76. auto[p5_8, p6_4] = mnd::pfu::twoProd(a[0], b[4]);
  77. auto t1 = p1_0;
  78. auto[t2, tl3, tl4] = mnd::pfu::threeSum(p2_0, p2_1, p2_2);
  79. auto[t3, tl4_2, tl5] = mnd::pfu::sixThreeSum(p3_0, p3_1, p3_2, p3_3, p3_4, tl3);
  80. auto[t4, tl5_2, tl6] = mnd::pfu::nineThreeSum(p4_0, p4_1, p4_2, p4_3, p4_4, p4_5, p4_6, tl4, tl4_2);
  81. auto[x1, x2, x3] = mnd::pfu::nineThreeSum(p5_0, p5_1, p5_2, p5_3, p5_4, p5_5, p5_6, p5_7, p5_8);
  82. auto[t5, tl6_1, tl7] = mnd::pfu::sixThreeSum(x1, x2, x3, tl5, tl5_2, 0.0);
  83. auto t6 = tl6 + tl6_1 + tl7 + p6_0 + p6_1 + p6_2 + p6_3 + p6_4 +
  84. a[5] * b[0] + a[4] * b[1] + a[3] * b[2] + a[2] * b[3] + a[1] * b[4] + a[0] * b[5];
  85. auto[re0, e1] = mnd::pfu::quickTwoSum(t1, t2);
  86. auto[re1, e2] = mnd::pfu::quickTwoSum(e1, t3);
  87. auto[re2, e3] = mnd::pfu::quickTwoSum(e2, t4);
  88. auto[re3, e4] = mnd::pfu::quickTwoSum(e3, t5);
  89. auto[re4, re5] = mnd::pfu::quickTwoSum(e4, t6);
  90. //return { t1, t2, t3, t4, t5, t6 };
  91. return { re0, re1, re2, re3, re4, re5 };
  92. }
  93. #endif // MANDEL_HEXDOUBLE_H