QuadDouble.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #ifndef MANDEL_QUADDOUBLE_H
  2. #define MANDEL_QUADDOUBLE_H
  3. #include "PolyfloatUtil.h"
  4. namespace mnd
  5. {
  6. struct QuadDouble;
  7. inline mnd::pfu::Quadruple<double> renorm2(double x0, double x1, double x2, double x3, double x4)
  8. {
  9. auto [st1, t4] = mnd::pfu::quickTwoSum(x3, x4);
  10. auto [st2, t3] = mnd::pfu::quickTwoSum(x2, st1);
  11. auto [st3, t2] = mnd::pfu::quickTwoSum(x1, st2);
  12. auto [t0, t1] = mnd::pfu::quickTwoSum(x0, st3);
  13. auto e = t0;
  14. auto [r0, e1] = mnd::pfu::quickTwoSum(e, t1);
  15. auto [r1, e2] = mnd::pfu::quickTwoSum(e1, t2);
  16. auto [r2, e3] = mnd::pfu::quickTwoSum(e2, t3);
  17. auto r3 = e3 + t4;
  18. return { r0, r1, r2, r3 };
  19. }
  20. }
  21. struct mnd::QuadDouble
  22. {
  23. double x[4];
  24. inline QuadDouble(double val) :
  25. x{ val, 0.0, 0.0, 0.0 }
  26. {}
  27. inline QuadDouble(double a, double b, double c, double d) :
  28. x{ a, b, c, d }
  29. {}
  30. double operator[] (int i) const { return x[i]; }
  31. const double& operator[] (int i) { return x[i]; }
  32. };
  33. inline mnd::QuadDouble operator+(const mnd::QuadDouble& a,
  34. const mnd::QuadDouble& b)
  35. {
  36. auto[s0, e0] = mnd::pfu::twoSum(a[0], b[0]);
  37. auto[s1, e1] = mnd::pfu::twoSum(a[1], b[1]);
  38. auto[s2, e2] = mnd::pfu::twoSum(a[2], b[2]);
  39. auto[s3, e3] = mnd::pfu::twoSum(a[3], b[3]);
  40. auto r0 = s0;
  41. auto [r1, t0] = mnd::pfu::twoSum(s1, e0);
  42. auto [r2, t1, t2] = mnd::pfu::threeSum(s2, e1, t0);
  43. auto [r3, t3, _t4] = mnd::pfu::threeSum(s3, e2, t1);
  44. auto [r4, _t5, _t6] = mnd::pfu::threeSum(e3, t3, t2);
  45. auto[re0, er1] = mnd::pfu::quickTwoSum(r0, r1);
  46. auto[re1, er2] = mnd::pfu::quickTwoSum(er1, r2);
  47. auto[re2, er3] = mnd::pfu::quickTwoSum(er2, r3);
  48. auto[re3, er4] = mnd::pfu::quickTwoSum(er3, r4);
  49. return { re0, re1, re2, re3 };
  50. }
  51. inline bool operator>(const mnd::QuadDouble& a, const mnd::QuadDouble& b)
  52. {
  53. if (a[0] > b[0])
  54. return true;
  55. if (a[0] < b[0])
  56. return false;
  57. if (a[1] > b[1])
  58. return true;
  59. if (a[1] < b[1])
  60. return false;
  61. if (a[2] > b[2])
  62. return true;
  63. if (a[2] < b[2])
  64. return false;
  65. return a[3] > b[3];
  66. }
  67. inline mnd::QuadDouble operator-(const mnd::QuadDouble& a,
  68. const mnd::QuadDouble& b)
  69. {
  70. return a + mnd::QuadDouble{ -b[0], -b[1], -b[2], -b[3] };
  71. }
  72. inline mnd::QuadDouble operator*(const mnd::QuadDouble& a,
  73. const mnd::QuadDouble& b)
  74. {
  75. auto[a0, b0] = mnd::pfu::twoProd(a[0], b[0]);
  76. auto[b1, c0] = mnd::pfu::twoProd(a[0], b[1]);
  77. auto[b2, c1] = mnd::pfu::twoProd(a[1], b[0]);
  78. auto[c2, d0] = mnd::pfu::twoProd(a[0], b[2]);
  79. auto[c3, d1] = mnd::pfu::twoProd(a[1], b[1]);
  80. auto[c4, d2] = mnd::pfu::twoProd(a[2], b[0]);
  81. auto d5 = a[3] * b[0];
  82. auto d6 = a[2] * b[1];
  83. auto d7 = a[1] * b[2];
  84. auto d8 = a[0] * b[3];
  85. auto r0 = a0;
  86. auto[r1, c5, d3] = mnd::pfu::threeSum(b0, b1, b2);
  87. auto[r2, d4, e0] = mnd::pfu::sixThreeSum(c0, c1, c2, c3, c4, c5);
  88. auto[r3, e1, ex_] = mnd::pfu::nineThreeSum(d0, d1, d2, d3, d4, d5, d6, d7, d8);
  89. auto r4 = e0 + e1;
  90. auto [n0, n1, n2, n3] = mnd::renorm2(r0, r1, r2, r3, r4);
  91. return { n0, n1, n2, n3 };
  92. }
  93. #endif // MANDEL_QUADDOUBLE_H