| 
					
				 | 
			
			
				@@ -0,0 +1,105 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#ifndef MANDEL_LIGHTDOUBLEDOUBLE_H 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define MANDEL_LIGHTDOUBLEDOUBLE_H 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <utility> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+namespace mnd 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    struct LightDoubleDouble; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    namespace ldd 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        using DoublePair = std::pair<double, double>; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        inline static DoublePair quickTwoSum(double a, double b) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            double s = a + b; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            double e = b - (s - a); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return { s, e }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        inline DoublePair twoSum(double a, double b) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            double s = a + b; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            double v = s - a; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            double e = (a - (s - v)) + (b - v); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return { s, e }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        inline DoublePair 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 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        inline DoublePair twoProd(double a, double b) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            double p = a * b; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            auto [ahi, alo] = split(a); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            auto [bhi, blo] = split(b); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            double e = ((ahi * bhi - p) + ahi * blo + alo * bhi) + alo * blo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return { p, e }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        inline DoublePair twoProdFma(double a, double b) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            double p = a * b; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            double 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); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif // MANDEL_LIGHTDOUBLEDOUBLE_H 
			 |