TripleDouble.h 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. #ifndef MANDEL_TRIPLEDOUBLE_H
  2. #define MANDEL_TRIPLEDOUBLE_H
  3. #include "PolyfloatUtil.h"
  4. namespace mnd
  5. {
  6. struct TripleDouble;
  7. }
  8. struct mnd::TripleDouble
  9. {
  10. double x[3];
  11. inline TripleDouble(double val) :
  12. x{ val, 0.0, 0.0 }
  13. {}
  14. inline TripleDouble(double a, double b, double c) :
  15. x{ a, b, c }
  16. {}
  17. double operator[] (int i) const { return x[i]; }
  18. const double& operator[] (int i) { return x[i]; }
  19. };
  20. inline mnd::TripleDouble operator+(const mnd::TripleDouble& a,
  21. const mnd::TripleDouble& b)
  22. {
  23. auto[r0, t0] = mnd::pfu::twoSum(a[0], b[0]);
  24. auto[t1, t2] = mnd::pfu::twoSum(a[1], b[1]);
  25. auto[r1, t3] = mnd::pfu::twoSum(t0, t1);
  26. auto r2 = t2 + t3 + a[2] + b[2];
  27. auto[re1, t4] = mnd::pfu::quickTwoSum(r0, r1);
  28. auto[re2, re3] = mnd::pfu::quickTwoSum(t4, r2);
  29. return { re1, re2, re3 };
  30. }
  31. inline bool operator>(const mnd::TripleDouble& a, const mnd::TripleDouble& b)
  32. {
  33. if (a[0] > b[0])
  34. return true;
  35. if (a[0] < b[0])
  36. return false;
  37. if (a[1] > b[1])
  38. return true;
  39. if (a[1] < b[1])
  40. return false;
  41. return a[2] > b[2];
  42. }
  43. inline mnd::TripleDouble operator-(const mnd::TripleDouble& a,
  44. const mnd::TripleDouble& b)
  45. {
  46. auto[r0, t0] = mnd::pfu::twoSum(a[0], -b[0]);
  47. auto[t1, t2] = mnd::pfu::twoSum(a[1], -b[1]);
  48. auto[r1, t3] = mnd::pfu::twoSum(t0, t1);
  49. auto r2 = t2 + t3 + a[2] - b[2];
  50. auto[re1, t4] = mnd::pfu::quickTwoSum(r0, r1);
  51. auto[re2, re3] = mnd::pfu::quickTwoSum(t4, r2);
  52. return { re1, re2, re3 };
  53. }
  54. inline mnd::TripleDouble operator*(const mnd::TripleDouble& a,
  55. const mnd::TripleDouble& b)
  56. {
  57. auto[p1_0, p2_0] = mnd::pfu::twoProd(a[0], b[0]);
  58. auto[p2_1, p3_0] = mnd::pfu::twoProd(a[0], b[1]);
  59. auto[p2_2, p3_1] = mnd::pfu::twoProd(a[1], b[0]);
  60. auto[t2, tl3] = mnd::pfu::threeTwoSum(p2_0, p2_1, p2_2);
  61. auto t3 = tl3 + p3_0 + p3_1 + a[1] * b[1] + a[2] * b[0] + a[0] * b[2];
  62. auto[re0, q2] = mnd::pfu::quickTwoSum(p1_0, t2);
  63. auto[re1, re2] = mnd::pfu::quickTwoSum(q2, t3);
  64. return { re0, re1, re2 };
  65. }
  66. #endif // MANDEL_TRIPLEDOUBLE_H