| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 | 
							- #ifndef MANDEL_LIGHTDOUBLEDOUBLE_H
 
- #define MANDEL_LIGHTDOUBLEDOUBLE_H
 
- #include <utility>
 
- namespace mnd
 
- {
 
-     struct LightDoubleDouble;
 
-     struct LightDoubleFloat;
 
-     namespace ldd
 
-     {
 
-         template<typename T>
 
-         using Pair = std::pair<T, T>;
 
-         using DoublePair = Pair<double>;
 
-         using FloatPair = Pair<float>;
 
-         template<typename T>
 
-         inline static Pair<T> quickTwoSum(T a, T b)
 
-         {
 
-             T s = a + b;
 
-             T e = b - (s - a);
 
-             return { s, e };
 
-         }
 
-         template<typename T>
 
-         inline Pair<T> twoSum(T a, T b)
 
-         {
 
-             T s = a + b;
 
-             T v = s - a;
 
-             T e = (a - (s - v)) + (b - v);
 
-             return { s, e };
 
-         }
 
-         inline Pair<double> split(double a)
 
-         {
 
-             static const double splitter = double((1ULL << 27) + 1);
 
-             double t = splitter * a;
 
-             double ahi = t - (t - a);
 
-             double alo = a - ahi;
 
-             return { ahi, alo };
 
-         }
 
-         template<typename T>
 
-         inline Pair<T> twoProd(T a, T b)
 
-         {
 
-             T p = a * b;
 
-             auto [ahi, alo] = split(a);
 
-             auto [bhi, blo] = split(b);
 
-             T e = ((ahi * bhi - p) + ahi * blo + alo * bhi) + alo * blo;
 
-             return { p, e };
 
-         }
 
-         template<typename T>
 
-         inline Pair<T> twoProdFma(T a, T b)
 
-         {
 
-             T p = a * b;
 
-             T e = std::fma(a, b, -p);
 
-             return { p, e };
 
-         }
 
-     }
 
- }
 
- struct mnd::LightDoubleDouble
 
- {
 
-     double x[2];
 
-     inline LightDoubleDouble(double val) :
 
-         x{ val, 0 }
 
-     {}
 
-     inline LightDoubleDouble(double u, double l) :
 
-         x{ u, l }
 
-     {}
 
-     inline LightDoubleDouble(mnd::ldd::DoublePair dp) :
 
-         x{ dp.first, dp.second }
 
-     {}
 
-     double operator[]           (int i) const   { return x[i]; }
 
-     const double& operator[]    (int i)         { return x[i]; }
 
- private:
 
- };
 
- inline mnd::LightDoubleDouble operator+(const mnd::LightDoubleDouble& a,
 
-     const mnd::LightDoubleDouble& b)
 
- {
 
-     auto[s, e] = mnd::ldd::twoSum(a[0], b[0]);
 
-     e += a[1] + b[1];
 
-     return mnd::ldd::quickTwoSum(s, e);
 
- }
 
- inline mnd::LightDoubleDouble operator-(const mnd::LightDoubleDouble& a,
 
-     const mnd::LightDoubleDouble& b)
 
- {
 
-     auto[s, e] = mnd::ldd::twoSum(a[0], -b[0]);
 
-     e += a[1] - b[1];
 
-     return mnd::ldd::quickTwoSum(s, e);
 
- }
 
- inline mnd::LightDoubleDouble operator*(const mnd::LightDoubleDouble& a,
 
-     const mnd::LightDoubleDouble& b)
 
- {
 
-     auto[p1, p2] = mnd::ldd::twoProd(a[0], b[0]);
 
-     p2 += a[0] * b[1] + a[1] * b[0];
 
-     return mnd::ldd::quickTwoSum(p1, p2);
 
- }
 
- struct mnd::LightDoubleFloat
 
- {
 
-     float x[2];
 
-     inline LightDoubleFloat(double val)
 
-     {
 
-         x[0] = float(val);
 
-         x[1] = float(val - double(x[0]));
 
-     }
 
-     inline LightDoubleFloat(float u, float l) :
 
-         x{ u, l }
 
-     {}
 
-     inline LightDoubleFloat(mnd::ldd::FloatPair dp) :
 
-         x{ dp.first, dp.second }
 
-     {}
 
-     float operator[]           (int i) const   { return x[i]; }
 
-     const float& operator[]    (int i)         { return x[i]; }
 
- private:
 
- };
 
- inline mnd::LightDoubleFloat operator+(const mnd::LightDoubleFloat& a,
 
-     const mnd::LightDoubleFloat& b)
 
- {
 
-     auto[s, e] = mnd::ldd::twoSum(a[0], b[0]);
 
-     e += a[1] + b[1];
 
-     return mnd::ldd::quickTwoSum(s, e);
 
- }
 
- inline mnd::LightDoubleFloat operator-(const mnd::LightDoubleFloat& a,
 
-     const mnd::LightDoubleFloat& b)
 
- {
 
-     auto[s, e] = mnd::ldd::twoSum(a[0], -b[0]);
 
-     e += a[1] - b[1];
 
-     return mnd::ldd::quickTwoSum(s, e);
 
- }
 
- inline mnd::LightDoubleFloat operator*(const mnd::LightDoubleFloat& a,
 
-     const mnd::LightDoubleFloat& b)
 
- {
 
-     auto[p1, p2] = mnd::ldd::twoProd(a[0], b[0]);
 
-     p2 += a[0] * b[1] + a[1] * b[0];
 
-     return mnd::ldd::quickTwoSum(p1, p2);
 
- }
 
- #endif // MANDEL_LIGHTDOUBLEDOUBLE_H
 
 
  |