Kaynağa Gözat

added opencl hex-double generator #4

Nicolas Winkler 4 yıl önce
ebeveyn
işleme
5a86f4aa23

+ 14 - 0
libmandel/include/ClGenerators.h

@@ -27,6 +27,7 @@ namespace mnd
     class ClGeneratorDoubleDouble;
     class ClGeneratorTripleDouble;
     class ClGeneratorQuadDouble;
+    class ClGeneratorHexDouble;
     class ClGenerator128;
     class ClGenerator64;
 }
@@ -125,6 +126,19 @@ protected:
 };
 
 
+class mnd::ClGeneratorHexDouble : public ClGenerator
+{
+    bool smooth;
+public:
+    ClGeneratorHexDouble(mnd::MandelDevice& device);
+    virtual ~ClGeneratorHexDouble(void) = default;
+
+    virtual void generate(const MandelInfo& info, float* data) override;
+protected:
+    virtual std::string getKernelCode(bool smooth) const;
+};
+
+
 class mnd::ClGenerator128 : public ClGenerator
 {
 public:

+ 4 - 1
libmandel/include/Generators.h

@@ -23,13 +23,14 @@ namespace mnd
         DOUBLE,
         DOUBLE_DOUBLE,
         TRIPLE_DOUBLE,
+        QUAD_DOUBLE,
+        HEX_DOUBLE,
         FLOAT128,
         FLOAT256,
         FLOAT512,
         FIXED64,
         FIXED128,
         FIXED512,
-        QUAD_DOUBLE,
         INF_PREC,
     };
 
@@ -57,6 +58,7 @@ namespace mnd
     template<> Real getPrecision<DoubleDouble>();
     template<> Real getPrecision<TripleDouble>();
     template<> Real getPrecision<QuadDouble>();
+    template<> Real getPrecision<HexDouble>();
     template<> Real getPrecision<Fixed64>();
     template<> Real getPrecision<Fixed128>();
     template<> Real getPrecision<Fixed512>();
@@ -71,6 +73,7 @@ namespace mnd
     template<> inline Precision getType<DoubleDouble>() { return Precision::DOUBLE_DOUBLE; }
     template<> inline Precision getType<TripleDouble>() { return Precision::TRIPLE_DOUBLE; }
     template<> inline Precision getType<QuadDouble>() { return Precision::QUAD_DOUBLE; }
+    template<> inline Precision getType<HexDouble>() { return Precision::HEX_DOUBLE; }
     template<> inline Precision getType<Fixed64>() { return Precision::FIXED64; }
     template<> inline Precision getType<Fixed128>() { return Precision::FIXED128; }
     template<> inline Precision getType<Fixed512>() { return Precision::FIXED512; }

+ 1 - 0
libmandel/include/OpenClCode.h

@@ -11,6 +11,7 @@ namespace mnd
     std::string getDoubleDouble_cl();
     std::string getTripleDouble_cl();
     std::string getQuadDouble_cl();
+    std::string getHexDouble_cl();
     std::string getFixed64_cl();
     std::string getFixed128_cl();
     std::string getFixed512_cl();

+ 74 - 0
libmandel/include/PolyfloatUtil.h

@@ -12,6 +12,23 @@ namespace mnd
             T b;
         };
 
+        template<typename T>
+        struct Triple
+        {
+            T a;
+            T b;
+            T c;
+        };
+
+        template<typename T>
+        struct Quadruple
+        {
+            T a;
+            T b;
+            T c;
+            T d;
+        };
+
         using DoublePair = Pair<double>;
         using FloatPair = Pair<float>;
 
@@ -33,6 +50,15 @@ namespace mnd
         }
 
         template<typename T>
+        inline Triple<T> threeSum(T a, T b, T c)
+        {
+            auto[t1, t2] = twoSum(a, b);
+            auto[r0, t3] = twoSum(t1, c);
+            auto[r1, r2] = twoSum(t2, t3);
+            return { r0, r1, r2 };
+        }
+
+        template<typename T>
         inline Pair<T> threeTwoSum(T a, T b, T c)
         {
             auto[t1, t2] = twoSum(a, b);
@@ -40,6 +66,54 @@ namespace mnd
             return { r0, t2 + t3 };
         }
 
+        template<typename T>
+        inline Quadruple<T> fourSum(T a, T b, T c, T d)
+        {
+            auto[t1, t2] = twoSum(a, b);
+            auto[t3, t4] = twoSum(t1, c);
+            auto[r0, t5] = twoSum(t3, d);
+            auto[r1, r2, r3] = threeSum(t2, t4, t5);
+            return { r0, r1, r2, r3 };
+        }
+
+        template<typename T>
+        inline Pair<T> fiveTwoSum(T a, T b, T c, T d, T e)
+        {
+            auto[t1, t2] = twoSum(a, b);
+            auto[t3, t4] = twoSum(t1, c);
+            auto[t5, t6] = twoSum(t3, d);
+            auto[r0, t7] = twoSum(t5, e);
+            return { r0, t2 + t4 + t6 + t7 };
+        }
+
+        template<typename T>
+        inline Triple<T> sixThreeSum(T a, T b, T c, T d, T e, T f)
+        {
+            auto[a1, a2, a3] = threeSum(a, b, c);
+            auto[b1, b2, b3] = threeSum(d, e, f);
+            
+            auto[r1, t1] = twoSum(a1, b1);
+            auto[t2, t3] = twoSum(a2, b2);
+            auto t4 = a3 + b3;
+
+            auto[r2, t5] = twoSum(t1, t2);
+            auto r3 = t4 + t3 + t5;
+            return { r1, r2, r3 };
+        }
+
+        template<typename T>
+        inline Triple<T> nineThreeSum(T a, T b, T c, T d, T e, T f, T g, T h, T i)
+        {
+            auto[a1, a2, a3] = threeSum(a, b, c);
+            auto[b1, b2, b3] = threeSum(d, e, f);
+            auto[c1, c2, c3] = threeSum(g, h, i);
+            
+            auto[r1, t1, t2] = threeSum(a1, b1, c1);
+            auto[r2, t3, t4, t5] = fourSum(a2, b2, c2, t1);
+            auto r3 = a3 + b3 + c3 + t2 + t3 + t4 + t5;
+            return { r1, r2, r3 };
+        }
+
         inline Pair<double> split(double a)
         {
             static const double splitter = double((1ULL << 27) + 1);

+ 31 - 1
libmandel/include/Types.h

@@ -24,6 +24,7 @@
 
 #include "LightDoubleDouble.h"
 #include "TripleDouble.h"
+#include "HexDouble.h"
 
 namespace mnd
 {
@@ -235,7 +236,36 @@ namespace mnd
     template<>
     inline float convert<float, QuadDouble>(const QuadDouble& x)
     {
-        return float(x.x[0] + x.x[1] + x.x[2] + x.x[3]);
+        return float(x.x[0] + x.x[1]);
+    }
+
+    template<>
+    inline Real convert<Real, HexDouble>(const HexDouble& x)
+    {
+        return Real{ x[0] } + x[1] + x[2] + x[3] + x[4] + x[5];
+    }
+
+    template<>
+    inline HexDouble convert<HexDouble, Real>(const Real& x)
+    {
+        double s = static_cast<double>(x);
+        Real tmp = x - s;
+        double e1 = static_cast<double>(tmp);
+        tmp = tmp - e1;
+        double e2 = static_cast<double>(tmp);
+        tmp = tmp - e2;
+        double e3 = static_cast<double>(tmp);
+        tmp = tmp - e3;
+        double e4 = static_cast<double>(tmp);
+        tmp = tmp - e4;
+        double e5 = static_cast<double>(tmp);
+        return HexDouble { s, e1, e2, e3, e4, e5 };
+    }
+
+    template<>
+    inline float convert<float, HexDouble>(const HexDouble& x)
+    {
+        return float(x.x[0] + x.x[1]);
     }
 
     template<>

+ 56 - 0
libmandel/src/ClGenerators.cpp

@@ -19,6 +19,7 @@ using mnd::ClGeneratorDouble;
 using mnd::ClGeneratorDoubleDouble;
 using mnd::ClGeneratorTripleDouble;
 using mnd::ClGeneratorQuadDouble;
+using mnd::ClGeneratorHexDouble;
 using mnd::ClGenerator128;
 using mnd::ClGenerator64;
 
@@ -504,6 +505,61 @@ std::string ClGeneratorQuadDouble::getKernelCode(bool smooth) const
 }
 
 
+ClGeneratorHexDouble::ClGeneratorHexDouble(mnd::MandelDevice& device) :
+    ClGenerator{ device, getHexDouble_cl(), mnd::Precision::HEX_DOUBLE }
+{
+    kernel = Kernel(program, "iterate");
+}
+
+
+void ClGeneratorHexDouble::generate(const mnd::MandelInfo& info, float* data)
+{
+    ::size_t bufferSize = info.bWidth * info.bHeight * sizeof(float);
+
+    Buffer buffer_A(context, CL_MEM_WRITE_ONLY, bufferSize);
+
+    mnd::HexDouble x = mnd::convert<mnd::HexDouble>(info.view.x);
+    mnd::HexDouble y = mnd::convert<mnd::HexDouble>(info.view.y);
+
+    mnd::HexDouble psx = mnd::convert<mnd::HexDouble>(info.view.width / info.bWidth);
+    mnd::HexDouble psy = mnd::convert<mnd::HexDouble>(info.view.height / info.bHeight);
+
+    mnd::HexDouble jx = mnd::convert<mnd::HexDouble>(info.juliaX);
+    mnd::HexDouble jy = mnd::convert<mnd::HexDouble>(info.juliaY);
+
+    double vals[] = {250, 250, 250, 250, 250, 250 };
+    const size_t argBufSize = 6 * sizeof(double);
+    Buffer xbuf(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, argBufSize, x.x);
+    Buffer ybuf(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, argBufSize, y.x);
+    Buffer psxbuf(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, argBufSize, psx.x);
+    Buffer psybuf(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, argBufSize, psy.x);
+    Buffer jxbuf(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, argBufSize, jx.x);
+    Buffer jybuf(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, argBufSize);
+
+    kernel.setArg(0, buffer_A);
+    kernel.setArg(1, int(info.bWidth));
+    kernel.setArg(2, xbuf);
+    kernel.setArg(3, ybuf);
+    kernel.setArg(4, psxbuf);
+    kernel.setArg(5, psybuf);
+    kernel.setArg(6, int(info.maxIter));
+    kernel.setArg(7, int(info.smooth ? 1 : 0));
+    kernel.setArg(8, int(info.julia ? 1 : 0));
+    kernel.setArg(9, jxbuf);
+    kernel.setArg(10, jybuf);
+
+    cl_int result = queue.enqueueNDRangeKernel(kernel, 0, NDRange(info.bWidth * info.bHeight));
+    queue.enqueueReadBuffer(buffer_A, CL_TRUE, 0, bufferSize, data);
+
+}
+
+
+std::string ClGeneratorHexDouble::getKernelCode(bool smooth) const
+{
+    return getHexDouble_cl();
+}
+
+
 ClGenerator128::ClGenerator128(mnd::MandelDevice& device) :
     ClGenerator{ device, getFixed512_cl(), mnd::Precision::FIXED128 }
 {

+ 3 - 0
libmandel/src/CpuGenerators.cpp

@@ -53,6 +53,9 @@ namespace mnd
 
     template class CpuGenerator<mnd::QuadDouble, mnd::NONE, false>;
     template class CpuGenerator<mnd::QuadDouble, mnd::NONE, true>;
+
+    template class CpuGenerator<mnd::HexDouble, mnd::NONE, false>;
+    template class CpuGenerator<mnd::HexDouble, mnd::NONE, true>;
 #endif
 }
 

+ 70 - 65
libmandel/src/CpuGeneratorsAVX.cpp

@@ -279,6 +279,9 @@ void generateDoubleAvx(long width, long height, float* data, bool parallel,
 }
 
 
+namespace avx_private
+{
+
 struct VecPair
 {
     __m256d a;
@@ -402,6 +405,73 @@ struct AvxDoubleDouble
 };
 
 
+struct AvxTripleDouble
+{
+    __m256d x[3];
+
+    inline AvxTripleDouble(__m256d a, __m256d b, __m256d c) :
+        x{ a, b, c }
+    {}
+
+    inline AvxTripleDouble(double a, double b, double c) :
+        x{ _mm256_set1_pd(a), _mm256_set1_pd(b), _mm256_set1_pd(c) }
+    {}
+
+    inline AvxTripleDouble operator + (const AvxTripleDouble& b) const
+    {
+        const auto& a = *this;
+        auto[r0, t0] = twoSum(a.x[0], b.x[0]);
+        auto[t1, t2] = twoSum(a.x[1], b.x[1]);
+        auto[r1, t3] = twoSum(t0, t1);
+        auto r2 = _mm256_add_pd(_mm256_add_pd(t2, _mm256_add_pd(a.x[2], b.x[2])), t3);
+
+        auto[re1, t4] = quickTwoSum(r0, r1);
+        auto[re2, re3] = quickTwoSum(t4, r2);
+        return { re1, re2, re3 };
+    }
+
+    inline AvxTripleDouble operator - (const AvxTripleDouble& b) const
+    {
+        const auto& a = *this;
+        auto[r0, t0] = twoDiff(a.x[0], b.x[0]);
+        auto[t1, t2] = twoDiff(a.x[1], b.x[1]);
+        auto[r1, t3] = twoSum(t0, t1);
+        auto r2 = _mm256_add_pd(_mm256_add_pd(t2, _mm256_sub_pd(a.x[2], b.x[2])), t3);
+
+        auto[re1, t4] = quickTwoSum(r0, r1);
+        auto[re2, re3] = quickTwoSum(t4, r2);
+        return { re1, re2, re3 };
+    }
+
+    inline AvxTripleDouble operator * (const AvxTripleDouble& b) const
+    {
+        const auto& a = *this;
+        auto[p1_0, p2_0] = twoProd(a.x[0], b.x[0]);
+        auto[p2_1, p3_0] = twoProd(a.x[0], b.x[1]);
+        auto[p2_2, p3_1] = twoProd(a.x[1], b.x[0]);
+
+        auto[t2, tl3] = threeTwoSum(p2_0, p2_1, p2_2);
+        auto t3 = _mm256_add_pd(tl3,
+            _mm256_add_pd(
+                _mm256_add_pd(p3_0, p3_1),
+                _mm256_add_pd(
+                    _mm256_mul_pd(a.x[1], b.x[1]),
+                    _mm256_add_pd(
+                        _mm256_mul_pd(a.x[2], b.x[0]),
+                        _mm256_mul_pd(a.x[0], b.x[2])
+                    )
+                )
+            )
+            );
+        auto[re0, q2] = quickTwoSum(p1_0, t2);
+        auto[re1, re2] = quickTwoSum(q2, t3);
+        return { re0, re1, re2 };
+    }
+};
+
+} // namespace avx_private
+
+
 void generateDoubleDoubleAvx(long width, long height, float* data, bool parallel,
     double vx1, double vx2, double vy1, double vy2, double vw1, double vw2, double vh1, double vh2, int maxIter, bool smooth,
     bool julia, double jX1, double jX2, double jY1, double jY2)
@@ -495,71 +565,6 @@ void generateDoubleDoubleAvx(long width, long height, float* data, bool parallel
     }
 }
 
-struct AvxTripleDouble
-{
-    __m256d x[3];
-
-    inline AvxTripleDouble(__m256d a, __m256d b, __m256d c) :
-        x{ a, b, c }
-    {}
-
-    inline AvxTripleDouble(double a, double b, double c) :
-        x{ _mm256_set1_pd(a), _mm256_set1_pd(b), _mm256_set1_pd(c) }
-    {}
-
-    inline AvxTripleDouble operator + (const AvxTripleDouble& b) const
-    {
-        const auto& a = *this;
-        auto[r0, t0] = twoSum(a.x[0], b.x[0]);
-        auto[t1, t2] = twoSum(a.x[1], b.x[1]);
-        auto[r1, t3] = twoSum(t0, t1);
-        auto r2 = _mm256_add_pd(_mm256_add_pd(t2, _mm256_add_pd(a.x[2], b.x[2])), t3);
-
-        auto[re1, t4] = quickTwoSum(r0, r1);
-        auto[re2, re3] = quickTwoSum(t4, r2);
-        return { re1, re2, re3 };
-    }
-
-    inline AvxTripleDouble operator - (const AvxTripleDouble& b) const
-    {
-        const auto& a = *this;
-        auto[r0, t0] = twoDiff(a.x[0], b.x[0]);
-        auto[t1, t2] = twoDiff(a.x[1], b.x[1]);
-        auto[r1, t3] = twoSum(t0, t1);
-        auto r2 = _mm256_add_pd(_mm256_add_pd(t2, _mm256_sub_pd(a.x[2], b.x[2])), t3);
-
-        auto[re1, t4] = quickTwoSum(r0, r1);
-        auto[re2, re3] = quickTwoSum(t4, r2);
-        return { re1, re2, re3 };
-    }
-
-    inline AvxTripleDouble operator * (const AvxTripleDouble& b) const
-    {
-        const auto& a = *this;
-        auto[p1_0, p2_0] = twoProd(a.x[0], b.x[0]);
-        auto[p2_1, p3_0] = twoProd(a.x[0], b.x[1]);
-        auto[p2_2, p3_1] = twoProd(a.x[1], b.x[0]);
-
-        auto[t2, tl3] = threeTwoSum(p2_0, p2_1, p2_2);
-        auto t3 = _mm256_add_pd(tl3,
-            _mm256_add_pd(
-                _mm256_add_pd(p3_0, p3_1),
-                _mm256_add_pd(
-                    _mm256_mul_pd(a.x[1], b.x[1]),
-                    _mm256_add_pd(
-                        _mm256_mul_pd(a.x[2], b.x[0]),
-                        _mm256_mul_pd(a.x[0], b.x[2])
-                    )
-                )
-            )
-            );
-        auto[re0, q2] = quickTwoSum(p1_0, t2);
-        auto[re1, re2] = quickTwoSum(q2, t3);
-        return { re0, re1, re2 };
-    }
-};
-
-
 void generateTripleDoubleAvx(long width, long height, float* data, bool parallel,
     double vx1, double vx2, double vx3, double vy1, double vy2, double vy3,
     double vw1, double vw2, double vw3, double vh1, double vh2, double vh3,

+ 9 - 2
libmandel/src/Generators.cpp

@@ -132,6 +132,10 @@ namespace mnd
             return "double-double";
         case Precision::TRIPLE_DOUBLE:
             return "triple-double";
+        case Precision::QUAD_DOUBLE:
+            return "quad-double";
+        case Precision::HEX_DOUBLE:
+            return "hex-double";
         case Precision::FLOAT128:
             return "float128";
         case Precision::FLOAT256:
@@ -144,8 +148,6 @@ namespace mnd
             return "fixed128";
         case Precision::FIXED512:
             return "fixed512";
-        case Precision::QUAD_DOUBLE:
-            return "quad-double";
         case Precision::INF_PREC:
             return "real";
         }
@@ -182,6 +184,7 @@ namespace mnd
             { Precision::DOUBLE_DOUBLE, Real("1.0e-29") },
             { Precision::TRIPLE_DOUBLE, Real("1.0e-47") },
             { Precision::QUAD_DOUBLE, Real("1.0e-56") },
+            { Precision::HEX_DOUBLE, Real("1.0e-94") },
             { Precision::FIXED64, Real("3.5e-15") },
             { Precision::FIXED128, Real("1.317e-29") },
             { Precision::FIXED512, Real("1.5e-130") },
@@ -215,6 +218,10 @@ namespace mnd
         return Real("3.0e-64");
     }
     template<>
+    Real getPrecision<HexDouble>() {
+        return Real("3.0e-94");
+    }
+    template<>
     Real getPrecision<Fixed64>() {
         return Real("3.5e-15");
     }

+ 7 - 4
libmandel/src/Mandel.cpp

@@ -132,12 +132,14 @@ MandelContext::MandelContext(void)
 #endif // WITH_BOOST
 
     auto dd = std::make_unique<CpuGenerator<DoubleDouble, mnd::NONE, true>>();
+    auto td = std::make_unique<CpuGenerator<TripleDouble, mnd::NONE, true>>();
     auto qd = std::make_unique<CpuGenerator<QuadDouble, mnd::NONE, true>>();
+    auto hd = std::make_unique<CpuGenerator<HexDouble, mnd::NONE, true>>();
     cpuGenerators.insert({ { Precision::DOUBLE_DOUBLE, CpuExtension::NONE }, std::move(dd) });
+    cpuGenerators.insert({ { Precision::TRIPLE_DOUBLE, CpuExtension::NONE }, std::move(td) });
     cpuGenerators.insert({ { Precision::QUAD_DOUBLE, CpuExtension::NONE }, std::move(qd) });
+    cpuGenerators.insert({ { Precision::HEX_DOUBLE, CpuExtension::NONE }, std::move(hd) });
 
-    auto td = std::make_unique<CpuGenerator<TripleDouble, mnd::NONE, true>>();
-    cpuGenerators.insert({ { Precision::TRIPLE_DOUBLE, CpuExtension::NONE }, std::move(td) });
 
     auto fix512 = std::make_unique<CpuGenerator<Fixed512, mnd::NONE, true>>();
     cpuGenerators.insert({ { Precision::FIXED512, CpuExtension::NONE }, std::move(fix512) });
@@ -158,8 +160,8 @@ std::unique_ptr<mnd::AdaptiveGenerator> MandelContext::createAdaptiveGenerator(v
         Precision::DOUBLE_DOUBLE,
         Precision::TRIPLE_DOUBLE,
         Precision::QUAD_DOUBLE,
-        Precision::FLOAT256,
-        Precision::FLOAT512
+        Precision::HEX_DOUBLE,
+        Precision::FIXED512
     };
 
     auto ag = std::make_unique<AdaptiveGenerator>();
@@ -253,6 +255,7 @@ std::vector<std::unique_ptr<MandelDevice>> MandelContext::createDevices(void)
                     md.mandelGenerators.insert({ Precision::DOUBLE_DOUBLE, std::make_unique<ClGeneratorDoubleDouble>(md) });
                     md.mandelGenerators.insert({ Precision::TRIPLE_DOUBLE, std::make_unique<ClGeneratorTripleDouble>(md) });
                     md.mandelGenerators.insert({ Precision::QUAD_DOUBLE, std::make_unique<ClGeneratorQuadDouble>(md) });
+                    md.mandelGenerators.insert({ Precision::HEX_DOUBLE, std::make_unique<ClGeneratorHexDouble>(md) });
                 }
                 catch (const std::string& err) {
                     printf("err: %s", err.c_str());

+ 5 - 0
libmandel/src/OpenClCode.cpp

@@ -6,6 +6,7 @@
 #include "opencl/doubledouble.h"
 #include "opencl/tripledouble.h"
 #include "opencl/quaddouble.h"
+#include "opencl/hexdouble.h"
 
 #include "opencl/fixed64.h"
 #include "opencl/fixed128.h"
@@ -37,6 +38,10 @@ namespace mnd
         return std::string{ (char*) quaddouble_cl, quaddouble_cl_len };
     }
 
+    std::string getHexDouble_cl() {
+        return std::string{ (char*) hexdouble_cl, hexdouble_cl_len };
+    }
+
     std::string getFixed64_cl() {
         return std::string{ (char*) fixed64_cl, fixed64_cl_len };
     }

+ 218 - 225
libmandel/src/opencl/float.h

@@ -1,6 +1,77 @@
 unsigned char float_cl[] = {
-  0x0d, 0x0a, 0x5f, 0x5f, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x20, 0x76,
-  0x6f, 0x69, 0x64, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x65, 0x28,
+  0x0a, 0x5f, 0x5f, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x20, 0x76, 0x6f,
+  0x69, 0x64, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x65, 0x28, 0x5f,
+  0x5f, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x66, 0x6c, 0x6f, 0x61,
+  0x74, 0x2a, 0x20, 0x41, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20,
+  0x69, 0x6e, 0x74, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x20, 0x66,
+  0x6c, 0x6f, 0x61, 0x74, 0x20, 0x78, 0x6c, 0x2c, 0x20, 0x66, 0x6c, 0x6f,
+  0x61, 0x74, 0x20, 0x79, 0x74, 0x2c, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74,
+  0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x58,
+  0x2c, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x70, 0x69, 0x78, 0x65,
+  0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x59, 0x2c, 0x20, 0x69, 0x6e, 0x74,
+  0x20, 0x6d, 0x61, 0x78, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x73, 0x6d,
+  0x6f, 0x6f, 0x74, 0x68, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x6a, 0x75,
+  0x6c, 0x69, 0x61, 0x2c, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6a,
+  0x75, 0x6c, 0x69, 0x61, 0x58, 0x2c, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74,
+  0x20, 0x6a, 0x75, 0x6c, 0x69, 0x61, 0x59, 0x29, 0x20, 0x7b, 0x0a, 0x20,
+  0x20, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20,
+  0x3d, 0x20, 0x67, 0x65, 0x74, 0x5f, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c,
+  0x5f, 0x69, 0x64, 0x28, 0x30, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x69,
+  0x6e, 0x74, 0x20, 0x78, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78,
+  0x20, 0x25, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3b, 0x0a, 0x20, 0x20,
+  0x20, 0x69, 0x6e, 0x74, 0x20, 0x79, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x64,
+  0x65, 0x78, 0x20, 0x2f, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3b, 0x0a,
+  0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x61, 0x20, 0x3d,
+  0x20, 0x78, 0x20, 0x2a, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x53, 0x63,
+  0x61, 0x6c, 0x65, 0x58, 0x20, 0x2b, 0x20, 0x78, 0x6c, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x62, 0x20, 0x3d, 0x20,
+  0x79, 0x20, 0x2a, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x53, 0x63, 0x61,
+  0x6c, 0x65, 0x59, 0x20, 0x2b, 0x20, 0x79, 0x74, 0x3b, 0x0a, 0x20, 0x20,
+  0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x63, 0x61, 0x20, 0x3d, 0x20,
+  0x6a, 0x75, 0x6c, 0x69, 0x61, 0x20, 0x21, 0x3d, 0x20, 0x30, 0x20, 0x3f,
+  0x20, 0x6a, 0x75, 0x6c, 0x69, 0x61, 0x58, 0x20, 0x3a, 0x20, 0x61, 0x3b,
+  0x0a, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x63, 0x62,
+  0x20, 0x3d, 0x20, 0x6a, 0x75, 0x6c, 0x69, 0x61, 0x20, 0x21, 0x3d, 0x20,
+  0x30, 0x20, 0x3f, 0x20, 0x6a, 0x75, 0x6c, 0x69, 0x61, 0x59, 0x20, 0x3a,
+  0x20, 0x62, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x20,
+  0x6e, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x77, 0x68,
+  0x69, 0x6c, 0x65, 0x20, 0x28, 0x6e, 0x20, 0x3c, 0x20, 0x6d, 0x61, 0x78,
+  0x20, 0x2d, 0x20, 0x31, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x61, 0x61, 0x20,
+  0x3d, 0x20, 0x61, 0x20, 0x2a, 0x20, 0x61, 0x3b, 0x0a, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x62, 0x62,
+  0x20, 0x3d, 0x20, 0x62, 0x20, 0x2a, 0x20, 0x62, 0x3b, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x61,
+  0x62, 0x20, 0x3d, 0x20, 0x61, 0x20, 0x2a, 0x20, 0x62, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x20, 0x3d, 0x20, 0x61, 0x61,
+  0x20, 0x2d, 0x20, 0x62, 0x62, 0x20, 0x2b, 0x20, 0x63, 0x61, 0x3b, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x20, 0x3d, 0x20, 0x61,
+  0x62, 0x20, 0x2b, 0x20, 0x61, 0x62, 0x20, 0x2b, 0x20, 0x63, 0x62, 0x3b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28,
+  0x61, 0x61, 0x20, 0x2b, 0x20, 0x62, 0x62, 0x20, 0x3e, 0x20, 0x31, 0x36,
+  0x29, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x6e, 0x2b, 0x2b, 0x3b, 0x0a, 0x20, 0x20, 0x20,
+  0x7d, 0x0a, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x6e, 0x20, 0x3e,
+  0x3d, 0x20, 0x6d, 0x61, 0x78, 0x20, 0x2d, 0x20, 0x31, 0x29, 0x20, 0x7b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x5b, 0x69, 0x6e,
+  0x64, 0x65, 0x78, 0x5d, 0x20, 0x3d, 0x20, 0x6d, 0x61, 0x78, 0x3b, 0x0a,
+  0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65,
+  0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66,
+  0x20, 0x28, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x20, 0x21, 0x3d, 0x20,
+  0x30, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x41, 0x5b, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x20, 0x3d,
+  0x20, 0x28, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x29, 0x6e, 0x29, 0x20,
+  0x2b, 0x20, 0x31, 0x20, 0x2d, 0x20, 0x6c, 0x6f, 0x67, 0x28, 0x6c, 0x6f,
+  0x67, 0x28, 0x61, 0x20, 0x2a, 0x20, 0x61, 0x20, 0x2b, 0x20, 0x62, 0x20,
+  0x2a, 0x20, 0x62, 0x29, 0x20, 0x2f, 0x20, 0x32, 0x29, 0x20, 0x2f, 0x20,
+  0x6c, 0x6f, 0x67, 0x28, 0x32, 0x2e, 0x30, 0x66, 0x29, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x5b,
+  0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x20, 0x3d, 0x20, 0x28, 0x28, 0x66,
+  0x6c, 0x6f, 0x61, 0x74, 0x29, 0x6e, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20,
+  0x7d, 0x0a, 0x7d, 0x0a, 0x0a, 0x0a, 0x2f, 0x2a, 0x0a, 0x5f, 0x5f, 0x6b,
+  0x65, 0x72, 0x6e, 0x65, 0x6c, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x69,
+  0x74, 0x65, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x65, 0x63, 0x34, 0x28,
   0x5f, 0x5f, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x66, 0x6c, 0x6f,
   0x61, 0x74, 0x2a, 0x20, 0x41, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74,
   0x20, 0x69, 0x6e, 0x74, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x20,
@@ -13,227 +84,149 @@ unsigned char float_cl[] = {
   0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x6a,
   0x75, 0x6c, 0x69, 0x61, 0x2c, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20,
   0x6a, 0x75, 0x6c, 0x69, 0x61, 0x58, 0x2c, 0x20, 0x66, 0x6c, 0x6f, 0x61,
-  0x74, 0x20, 0x6a, 0x75, 0x6c, 0x69, 0x61, 0x59, 0x29, 0x20, 0x7b, 0x0d,
-  0x0a, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x64, 0x65,
-  0x78, 0x20, 0x3d, 0x20, 0x67, 0x65, 0x74, 0x5f, 0x67, 0x6c, 0x6f, 0x62,
-  0x61, 0x6c, 0x5f, 0x69, 0x64, 0x28, 0x30, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
-  0x20, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x78, 0x20, 0x3d, 0x20, 0x69, 0x6e,
-  0x64, 0x65, 0x78, 0x20, 0x25, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3b,
-  0x0d, 0x0a, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x79, 0x20, 0x3d,
-  0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x2f, 0x20, 0x77, 0x69, 0x64,
-  0x74, 0x68, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61,
-  0x74, 0x20, 0x61, 0x20, 0x3d, 0x20, 0x78, 0x20, 0x2a, 0x20, 0x70, 0x69,
-  0x78, 0x65, 0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x58, 0x20, 0x2b, 0x20,
-  0x78, 0x6c, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61,
-  0x74, 0x20, 0x62, 0x20, 0x3d, 0x20, 0x79, 0x20, 0x2a, 0x20, 0x70, 0x69,
-  0x78, 0x65, 0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x59, 0x20, 0x2b, 0x20,
-  0x79, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61,
-  0x74, 0x20, 0x63, 0x61, 0x20, 0x3d, 0x20, 0x6a, 0x75, 0x6c, 0x69, 0x61,
-  0x20, 0x21, 0x3d, 0x20, 0x30, 0x20, 0x3f, 0x20, 0x6a, 0x75, 0x6c, 0x69,
-  0x61, 0x58, 0x20, 0x3a, 0x20, 0x61, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
-  0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x63, 0x62, 0x20, 0x3d, 0x20, 0x6a,
-  0x75, 0x6c, 0x69, 0x61, 0x20, 0x21, 0x3d, 0x20, 0x30, 0x20, 0x3f, 0x20,
-  0x6a, 0x75, 0x6c, 0x69, 0x61, 0x59, 0x20, 0x3a, 0x20, 0x62, 0x3b, 0x0d,
-  0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x6e, 0x20,
-  0x3d, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x77, 0x68, 0x69,
-  0x6c, 0x65, 0x20, 0x28, 0x6e, 0x20, 0x3c, 0x20, 0x6d, 0x61, 0x78, 0x20,
-  0x2d, 0x20, 0x31, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
-  0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x61, 0x61, 0x20,
-  0x3d, 0x20, 0x61, 0x20, 0x2a, 0x20, 0x61, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
-  0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x62,
-  0x62, 0x20, 0x3d, 0x20, 0x62, 0x20, 0x2a, 0x20, 0x62, 0x3b, 0x0d, 0x0a,
-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74,
-  0x20, 0x61, 0x62, 0x20, 0x3d, 0x20, 0x61, 0x20, 0x2a, 0x20, 0x62, 0x3b,
-  0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x20, 0x3d,
-  0x20, 0x61, 0x61, 0x20, 0x2d, 0x20, 0x62, 0x62, 0x20, 0x2b, 0x20, 0x63,
-  0x61, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62,
-  0x20, 0x3d, 0x20, 0x61, 0x62, 0x20, 0x2b, 0x20, 0x61, 0x62, 0x20, 0x2b,
-  0x20, 0x63, 0x62, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-  0x20, 0x69, 0x66, 0x20, 0x28, 0x61, 0x61, 0x20, 0x2b, 0x20, 0x62, 0x62,
-  0x20, 0x3e, 0x20, 0x31, 0x36, 0x29, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b,
-  0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x2b,
-  0x2b, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20,
-  0x20, 0x69, 0x66, 0x20, 0x28, 0x6e, 0x20, 0x3e, 0x3d, 0x20, 0x6d, 0x61,
-  0x78, 0x20, 0x2d, 0x20, 0x31, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
-  0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x5b, 0x69, 0x6e, 0x64, 0x65, 0x78,
-  0x5d, 0x20, 0x3d, 0x20, 0x6d, 0x61, 0x78, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
-  0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20,
-  0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66,
-  0x20, 0x28, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x20, 0x21, 0x3d, 0x20,
-  0x30, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-  0x20, 0x20, 0x20, 0x41, 0x5b, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x20,
-  0x3d, 0x20, 0x28, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x29, 0x6e, 0x29,
-  0x20, 0x2b, 0x20, 0x31, 0x20, 0x2d, 0x20, 0x6c, 0x6f, 0x67, 0x28, 0x6c,
-  0x6f, 0x67, 0x28, 0x61, 0x20, 0x2a, 0x20, 0x61, 0x20, 0x2b, 0x20, 0x62,
-  0x20, 0x2a, 0x20, 0x62, 0x29, 0x20, 0x2f, 0x20, 0x32, 0x29, 0x20, 0x2f,
-  0x20, 0x6c, 0x6f, 0x67, 0x28, 0x32, 0x2e, 0x30, 0x66, 0x29, 0x3b, 0x0d,
-  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65,
-  0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-  0x20, 0x41, 0x5b, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x20, 0x3d, 0x20,
-  0x28, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x29, 0x6e, 0x29, 0x3b, 0x0d,
-  0x0a, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
-  0x0d, 0x0a, 0x2f, 0x2a, 0x0d, 0x0a, 0x5f, 0x5f, 0x6b, 0x65, 0x72, 0x6e,
-  0x65, 0x6c, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x69, 0x74, 0x65, 0x72,
-  0x61, 0x74, 0x65, 0x5f, 0x76, 0x65, 0x63, 0x34, 0x28, 0x5f, 0x5f, 0x67,
-  0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x2a,
-  0x20, 0x41, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x69, 0x6e,
-  0x74, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x20, 0x66, 0x6c, 0x6f,
-  0x61, 0x74, 0x20, 0x78, 0x6c, 0x2c, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74,
-  0x20, 0x79, 0x74, 0x2c, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x70,
-  0x69, 0x78, 0x65, 0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x58, 0x2c, 0x20,
-  0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x53,
-  0x63, 0x61, 0x6c, 0x65, 0x59, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x6d,
-  0x61, 0x78, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x73, 0x6d, 0x6f, 0x6f,
-  0x74, 0x68, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x6a, 0x75, 0x6c, 0x69,
-  0x61, 0x2c, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6a, 0x75, 0x6c,
-  0x69, 0x61, 0x58, 0x2c, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6a,
-  0x75, 0x6c, 0x69, 0x61, 0x59, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
-  0x20, 0x69, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d,
-  0x20, 0x67, 0x65, 0x74, 0x5f, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f,
-  0x69, 0x64, 0x28, 0x30, 0x29, 0x20, 0x2a, 0x20, 0x34, 0x3b, 0x0d, 0x0a,
-  0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x78, 0x20, 0x3d, 0x20, 0x69,
-  0x6e, 0x64, 0x65, 0x78, 0x20, 0x25, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68,
-  0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x79, 0x20,
+  0x74, 0x20, 0x6a, 0x75, 0x6c, 0x69, 0x61, 0x59, 0x29, 0x20, 0x7b, 0x0a,
+  0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78,
+  0x20, 0x3d, 0x20, 0x67, 0x65, 0x74, 0x5f, 0x67, 0x6c, 0x6f, 0x62, 0x61,
+  0x6c, 0x5f, 0x69, 0x64, 0x28, 0x30, 0x29, 0x20, 0x2a, 0x20, 0x34, 0x3b,
+  0x0a, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x78, 0x20, 0x3d, 0x20,
+  0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x25, 0x20, 0x77, 0x69, 0x64, 0x74,
+  0x68, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x79, 0x20,
   0x3d, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x2f, 0x20, 0x77, 0x69,
-  0x64, 0x74, 0x68, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f,
-  0x61, 0x74, 0x34, 0x20, 0x61, 0x20, 0x3d, 0x20, 0x28, 0x66, 0x6c, 0x6f,
-  0x61, 0x74, 0x34, 0x29, 0x20, 0x28, 0x78, 0x20, 0x2a, 0x20, 0x70, 0x69,
-  0x78, 0x65, 0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x58, 0x20, 0x2b, 0x20,
-  0x78, 0x6c, 0x2c, 0x20, 0x28, 0x78, 0x20, 0x2b, 0x20, 0x31, 0x29, 0x20,
-  0x2a, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65,
-  0x58, 0x20, 0x2b, 0x20, 0x78, 0x6c, 0x2c, 0x20, 0x28, 0x78, 0x20, 0x2b,
-  0x20, 0x32, 0x29, 0x20, 0x2a, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x53,
-  0x63, 0x61, 0x6c, 0x65, 0x58, 0x20, 0x2b, 0x20, 0x78, 0x6c, 0x2c, 0x20,
-  0x28, 0x78, 0x20, 0x2b, 0x20, 0x33, 0x29, 0x20, 0x2a, 0x20, 0x70, 0x69,
-  0x78, 0x65, 0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x58, 0x20, 0x2b, 0x20,
-  0x78, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f,
-  0x61, 0x74, 0x34, 0x20, 0x62, 0x20, 0x3d, 0x20, 0x28, 0x66, 0x6c, 0x6f,
-  0x61, 0x74, 0x34, 0x29, 0x20, 0x28, 0x79, 0x20, 0x2a, 0x20, 0x70, 0x69,
-  0x78, 0x65, 0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x59, 0x20, 0x2b, 0x20,
-  0x79, 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f,
-  0x61, 0x74, 0x34, 0x20, 0x63, 0x61, 0x20, 0x3d, 0x20, 0x6a, 0x75, 0x6c,
-  0x69, 0x61, 0x20, 0x3f, 0x20, 0x28, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74,
-  0x34, 0x29, 0x28, 0x6a, 0x75, 0x6c, 0x69, 0x61, 0x58, 0x29, 0x29, 0x20,
-  0x3a, 0x20, 0x61, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f,
-  0x61, 0x74, 0x34, 0x20, 0x63, 0x62, 0x20, 0x3d, 0x20, 0x6a, 0x75, 0x6c,
-  0x69, 0x61, 0x20, 0x3f, 0x20, 0x28, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74,
-  0x34, 0x29, 0x28, 0x6a, 0x75, 0x6c, 0x69, 0x61, 0x59, 0x29, 0x29, 0x20,
-  0x3a, 0x20, 0x62, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f,
-  0x61, 0x74, 0x34, 0x20, 0x72, 0x65, 0x73, 0x61, 0x20, 0x3d, 0x20, 0x28,
-  0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x29, 0x28, 0x30, 0x29, 0x3b, 0x0d,
+  0x64, 0x74, 0x68, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61,
+  0x74, 0x34, 0x20, 0x61, 0x20, 0x3d, 0x20, 0x28, 0x66, 0x6c, 0x6f, 0x61,
+  0x74, 0x34, 0x29, 0x20, 0x28, 0x78, 0x20, 0x2a, 0x20, 0x70, 0x69, 0x78,
+  0x65, 0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x58, 0x20, 0x2b, 0x20, 0x78,
+  0x6c, 0x2c, 0x20, 0x28, 0x78, 0x20, 0x2b, 0x20, 0x31, 0x29, 0x20, 0x2a,
+  0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x58,
+  0x20, 0x2b, 0x20, 0x78, 0x6c, 0x2c, 0x20, 0x28, 0x78, 0x20, 0x2b, 0x20,
+  0x32, 0x29, 0x20, 0x2a, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x53, 0x63,
+  0x61, 0x6c, 0x65, 0x58, 0x20, 0x2b, 0x20, 0x78, 0x6c, 0x2c, 0x20, 0x28,
+  0x78, 0x20, 0x2b, 0x20, 0x33, 0x29, 0x20, 0x2a, 0x20, 0x70, 0x69, 0x78,
+  0x65, 0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x58, 0x20, 0x2b, 0x20, 0x78,
+  0x6c, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74,
+  0x34, 0x20, 0x62, 0x20, 0x3d, 0x20, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74,
+  0x34, 0x29, 0x20, 0x28, 0x79, 0x20, 0x2a, 0x20, 0x70, 0x69, 0x78, 0x65,
+  0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x59, 0x20, 0x2b, 0x20, 0x79, 0x74,
+  0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34,
+  0x20, 0x63, 0x61, 0x20, 0x3d, 0x20, 0x6a, 0x75, 0x6c, 0x69, 0x61, 0x20,
+  0x3f, 0x20, 0x28, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x29, 0x28,
+  0x6a, 0x75, 0x6c, 0x69, 0x61, 0x58, 0x29, 0x29, 0x20, 0x3a, 0x20, 0x61,
+  0x3b, 0x0a, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20,
+  0x63, 0x62, 0x20, 0x3d, 0x20, 0x6a, 0x75, 0x6c, 0x69, 0x61, 0x20, 0x3f,
+  0x20, 0x28, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x29, 0x28, 0x6a,
+  0x75, 0x6c, 0x69, 0x61, 0x59, 0x29, 0x29, 0x20, 0x3a, 0x20, 0x62, 0x3b,
   0x0a, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x72,
-  0x65, 0x73, 0x62, 0x20, 0x3d, 0x20, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74,
-  0x34, 0x29, 0x28, 0x30, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x66,
-  0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20,
-  0x3d, 0x20, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x29, 0x28, 0x30,
-  0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74,
-  0x20, 0x6e, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
-  0x69, 0x66, 0x20, 0x28, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x29, 0x20,
-  0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e,
-  0x74, 0x34, 0x20, 0x63, 0x6d, 0x70, 0x20, 0x3d, 0x20, 0x69, 0x73, 0x6c,
-  0x65, 0x73, 0x73, 0x28, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x29,
-  0x28, 0x31, 0x36, 0x2e, 0x30, 0x66, 0x29, 0x2c, 0x20, 0x28, 0x66, 0x6c,
-  0x6f, 0x61, 0x74, 0x34, 0x29, 0x28, 0x31, 0x36, 0x2e, 0x30, 0x66, 0x29,
-  0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77,
+  0x65, 0x73, 0x61, 0x20, 0x3d, 0x20, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74,
+  0x34, 0x29, 0x28, 0x30, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x66, 0x6c,
+  0x6f, 0x61, 0x74, 0x34, 0x20, 0x72, 0x65, 0x73, 0x62, 0x20, 0x3d, 0x20,
+  0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x29, 0x28, 0x30, 0x29, 0x3b,
+  0x0a, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x63,
+  0x6f, 0x75, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x28, 0x66, 0x6c, 0x6f, 0x61,
+  0x74, 0x34, 0x29, 0x28, 0x30, 0x29, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20,
+  0x69, 0x6e, 0x74, 0x20, 0x6e, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68,
+  0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69,
+  0x6e, 0x74, 0x34, 0x20, 0x63, 0x6d, 0x70, 0x20, 0x3d, 0x20, 0x69, 0x73,
+  0x6c, 0x65, 0x73, 0x73, 0x28, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34,
+  0x29, 0x28, 0x31, 0x36, 0x2e, 0x30, 0x66, 0x29, 0x2c, 0x20, 0x28, 0x66,
+  0x6c, 0x6f, 0x61, 0x74, 0x34, 0x29, 0x28, 0x31, 0x36, 0x2e, 0x30, 0x66,
+  0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77,
   0x68, 0x69, 0x6c, 0x65, 0x20, 0x28, 0x6e, 0x20, 0x3c, 0x20, 0x6d, 0x61,
-  0x78, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-  0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20,
-  0x61, 0x62, 0x20, 0x3d, 0x20, 0x61, 0x20, 0x2a, 0x20, 0x62, 0x3b, 0x0d,
-  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-  0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x63, 0x6d, 0x70, 0x56, 0x61,
-  0x6c, 0x20, 0x3d, 0x20, 0x66, 0x6d, 0x61, 0x28, 0x61, 0x2c, 0x20, 0x61,
-  0x2c, 0x20, 0x62, 0x20, 0x2a, 0x20, 0x62, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x20,
+  0x78, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x61,
+  0x62, 0x20, 0x3d, 0x20, 0x61, 0x20, 0x2a, 0x20, 0x62, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c,
+  0x6f, 0x61, 0x74, 0x34, 0x20, 0x63, 0x6d, 0x70, 0x56, 0x61, 0x6c, 0x20,
   0x3d, 0x20, 0x66, 0x6d, 0x61, 0x28, 0x61, 0x2c, 0x20, 0x61, 0x2c, 0x20,
-  0x2d, 0x66, 0x6d, 0x61, 0x28, 0x62, 0x2c, 0x20, 0x62, 0x2c, 0x20, 0x2d,
-  0x63, 0x61, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x20, 0x3d, 0x20, 0x66, 0x6d,
-  0x61, 0x28, 0x32, 0x2c, 0x20, 0x61, 0x62, 0x2c, 0x20, 0x63, 0x62, 0x29,
-  0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-  0x20, 0x20, 0x72, 0x65, 0x73, 0x61, 0x20, 0x3d, 0x20, 0x61, 0x73, 0x5f,
-  0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x28, 0x61, 0x73, 0x5f, 0x69,
-  0x6e, 0x74, 0x34, 0x28, 0x61, 0x29, 0x20, 0x26, 0x20, 0x63, 0x6d, 0x70,
-  0x29, 0x20, 0x7c, 0x20, 0x28, 0x61, 0x73, 0x5f, 0x69, 0x6e, 0x74, 0x34,
-  0x28, 0x72, 0x65, 0x73, 0x61, 0x29, 0x20, 0x26, 0x20, 0x7e, 0x63, 0x6d,
-  0x70, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-  0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x73, 0x62, 0x20, 0x3d, 0x20,
-  0x61, 0x73, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x28, 0x61,
-  0x73, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x28, 0x62, 0x29, 0x20, 0x26, 0x20,
-  0x63, 0x6d, 0x70, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x61, 0x73, 0x5f, 0x69,
-  0x6e, 0x74, 0x34, 0x28, 0x72, 0x65, 0x73, 0x62, 0x29, 0x20, 0x26, 0x20,
-  0x7e, 0x63, 0x6d, 0x70, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6d, 0x70, 0x20,
-  0x3d, 0x20, 0x69, 0x73, 0x6c, 0x65, 0x73, 0x73, 0x28, 0x63, 0x6d, 0x70,
-  0x56, 0x61, 0x6c, 0x2c, 0x20, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34,
-  0x29, 0x28, 0x31, 0x36, 0x2e, 0x30, 0x66, 0x29, 0x29, 0x3b, 0x0d, 0x0a,
-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69,
-  0x66, 0x20, 0x28, 0x21, 0x61, 0x6e, 0x79, 0x28, 0x63, 0x6d, 0x70, 0x29,
-  0x29, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x75,
-  0x6e, 0x74, 0x20, 0x2b, 0x3d, 0x20, 0x61, 0x73, 0x5f, 0x66, 0x6c, 0x6f,
-  0x61, 0x74, 0x34, 0x28, 0x63, 0x6d, 0x70, 0x20, 0x26, 0x20, 0x61, 0x73,
-  0x5f, 0x69, 0x6e, 0x74, 0x34, 0x28, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74,
-  0x34, 0x29, 0x28, 0x31, 0x29, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x2b, 0x2b,
-  0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d,
-  0x0a, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65,
-  0x6c, 0x73, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
-  0x20, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x28, 0x6e, 0x20, 0x3c,
-  0x20, 0x6d, 0x61, 0x78, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61,
-  0x74, 0x34, 0x20, 0x61, 0x62, 0x20, 0x3d, 0x20, 0x61, 0x20, 0x2a, 0x20,
-  0x62, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-  0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x63, 0x6d,
-  0x70, 0x56, 0x61, 0x6c, 0x20, 0x3d, 0x20, 0x66, 0x6d, 0x61, 0x28, 0x61,
-  0x2c, 0x20, 0x61, 0x2c, 0x20, 0x62, 0x20, 0x2a, 0x20, 0x62, 0x29, 0x3b,
-  0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-  0x20, 0x61, 0x20, 0x3d, 0x20, 0x66, 0x6d, 0x61, 0x28, 0x61, 0x2c, 0x20,
-  0x61, 0x2c, 0x20, 0x2d, 0x66, 0x6d, 0x61, 0x28, 0x62, 0x2c, 0x20, 0x62,
-  0x2c, 0x20, 0x2d, 0x63, 0x61, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x20, 0x3d,
-  0x20, 0x66, 0x6d, 0x61, 0x28, 0x32, 0x2c, 0x20, 0x61, 0x62, 0x2c, 0x20,
-  0x63, 0x62, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-  0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x34, 0x20, 0x63, 0x6d,
-  0x70, 0x20, 0x3d, 0x20, 0x69, 0x73, 0x6c, 0x65, 0x73, 0x73, 0x28, 0x63,
-  0x6d, 0x70, 0x56, 0x61, 0x6c, 0x2c, 0x20, 0x28, 0x66, 0x6c, 0x6f, 0x61,
-  0x74, 0x34, 0x29, 0x28, 0x31, 0x36, 0x2e, 0x30, 0x66, 0x29, 0x29, 0x3b,
-  0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-  0x20, 0x69, 0x66, 0x20, 0x28, 0x21, 0x61, 0x6e, 0x79, 0x28, 0x63, 0x6d,
-  0x70, 0x29, 0x29, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0d, 0x0a,
-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63,
-  0x6f, 0x75, 0x6e, 0x74, 0x20, 0x2b, 0x3d, 0x20, 0x61, 0x73, 0x5f, 0x66,
-  0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x63, 0x6d, 0x70, 0x20, 0x26, 0x20,
-  0x61, 0x73, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x28, 0x28, 0x66, 0x6c, 0x6f,
-  0x61, 0x74, 0x34, 0x29, 0x28, 0x31, 0x29, 0x29, 0x29, 0x3b, 0x0d, 0x0a,
-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6e,
-  0x2b, 0x2b, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-  0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
-  0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x72,
-  0x65, 0x73, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20,
-  0x28, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x20, 0x21, 0x3d, 0x20, 0x30,
-  0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-  0x20, 0x69, 0x66, 0x20, 0x28, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x73,
-  0x30, 0x20, 0x3e, 0x3d, 0x20, 0x30, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+  0x62, 0x20, 0x2a, 0x20, 0x62, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x20, 0x3d, 0x20, 0x66,
+  0x6d, 0x61, 0x28, 0x61, 0x2c, 0x20, 0x61, 0x2c, 0x20, 0x2d, 0x66, 0x6d,
+  0x61, 0x28, 0x62, 0x2c, 0x20, 0x62, 0x2c, 0x20, 0x2d, 0x63, 0x61, 0x29,
+  0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x62, 0x20, 0x3d, 0x20, 0x66, 0x6d, 0x61, 0x28, 0x32, 0x2c,
+  0x20, 0x61, 0x62, 0x2c, 0x20, 0x63, 0x62, 0x29, 0x3b, 0x0a, 0x20, 0x20,
   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x73,
-  0x20, 0x3d, 0x20, 0x28, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x29,
-  0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x29, 0x20, 0x2b, 0x20, 0x28, 0x28,
-  0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x29, 0x28, 0x31, 0x2e, 0x30, 0x66,
-  0x2c, 0x20, 0x31, 0x2e, 0x30, 0x66, 0x2c, 0x20, 0x31, 0x2e, 0x30, 0x66,
-  0x2c, 0x20, 0x31, 0x2e, 0x30, 0x66, 0x29, 0x29, 0x20, 0x2d, 0x20, 0x6c,
-  0x6f, 0x67, 0x32, 0x28, 0x6c, 0x6f, 0x67, 0x28, 0x66, 0x6d, 0x61, 0x28,
-  0x72, 0x65, 0x73, 0x61, 0x2c, 0x20, 0x72, 0x65, 0x73, 0x61, 0x2c, 0x20,
-  0x72, 0x65, 0x73, 0x62, 0x20, 0x2a, 0x20, 0x72, 0x65, 0x73, 0x62, 0x29,
-  0x29, 0x20, 0x2a, 0x20, 0x30, 0x2e, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
-  0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20,
-  0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x69, 0x6e, 0x74, 0x20, 0x69,
-  0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x69, 0x20, 0x3c, 0x20, 0x34, 0x20,
-  0x26, 0x26, 0x20, 0x69, 0x20, 0x2b, 0x20, 0x78, 0x20, 0x3c, 0x20, 0x77,
-  0x69, 0x64, 0x74, 0x68, 0x3b, 0x20, 0x69, 0x2b, 0x2b, 0x29, 0x20, 0x7b,
-  0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x73, 0x6d,
+  0x61, 0x20, 0x3d, 0x20, 0x61, 0x73, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74,
+  0x34, 0x28, 0x28, 0x61, 0x73, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x28, 0x61,
+  0x29, 0x20, 0x26, 0x20, 0x63, 0x6d, 0x70, 0x29, 0x20, 0x7c, 0x20, 0x28,
+  0x61, 0x73, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x28, 0x72, 0x65, 0x73, 0x61,
+  0x29, 0x20, 0x26, 0x20, 0x7e, 0x63, 0x6d, 0x70, 0x29, 0x29, 0x3b, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72,
+  0x65, 0x73, 0x62, 0x20, 0x3d, 0x20, 0x61, 0x73, 0x5f, 0x66, 0x6c, 0x6f,
+  0x61, 0x74, 0x34, 0x28, 0x28, 0x61, 0x73, 0x5f, 0x69, 0x6e, 0x74, 0x34,
+  0x28, 0x62, 0x29, 0x20, 0x26, 0x20, 0x63, 0x6d, 0x70, 0x29, 0x20, 0x7c,
+  0x20, 0x28, 0x61, 0x73, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x28, 0x72, 0x65,
+  0x73, 0x62, 0x29, 0x20, 0x26, 0x20, 0x7e, 0x63, 0x6d, 0x70, 0x29, 0x29,
+  0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x63, 0x6d, 0x70, 0x20, 0x3d, 0x20, 0x69, 0x73, 0x6c, 0x65, 0x73,
+  0x73, 0x28, 0x63, 0x6d, 0x70, 0x56, 0x61, 0x6c, 0x2c, 0x20, 0x28, 0x66,
+  0x6c, 0x6f, 0x61, 0x74, 0x34, 0x29, 0x28, 0x31, 0x36, 0x2e, 0x30, 0x66,
+  0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x21, 0x61, 0x6e, 0x79, 0x28,
+  0x63, 0x6d, 0x70, 0x29, 0x29, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x2b, 0x3d, 0x20, 0x61, 0x73, 0x5f,
+  0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x63, 0x6d, 0x70, 0x20, 0x26,
+  0x20, 0x61, 0x73, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x28, 0x28, 0x66, 0x6c,
+  0x6f, 0x61, 0x74, 0x34, 0x29, 0x28, 0x31, 0x29, 0x29, 0x29, 0x3b, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6e,
+  0x2b, 0x2b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d,
+  0x0a, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c,
+  0x73, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x28, 0x6e, 0x20, 0x3c, 0x20, 0x6d,
+  0x61, 0x78, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20,
+  0x61, 0x62, 0x20, 0x3d, 0x20, 0x61, 0x20, 0x2a, 0x20, 0x62, 0x3b, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66,
+  0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x63, 0x6d, 0x70, 0x56, 0x61, 0x6c,
+  0x20, 0x3d, 0x20, 0x66, 0x6d, 0x61, 0x28, 0x61, 0x2c, 0x20, 0x61, 0x2c,
+  0x20, 0x62, 0x20, 0x2a, 0x20, 0x62, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x20, 0x3d, 0x20,
+  0x66, 0x6d, 0x61, 0x28, 0x61, 0x2c, 0x20, 0x61, 0x2c, 0x20, 0x2d, 0x66,
+  0x6d, 0x61, 0x28, 0x62, 0x2c, 0x20, 0x62, 0x2c, 0x20, 0x2d, 0x63, 0x61,
+  0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x62, 0x20, 0x3d, 0x20, 0x66, 0x6d, 0x61, 0x28, 0x32,
+  0x2c, 0x20, 0x61, 0x62, 0x2c, 0x20, 0x63, 0x62, 0x29, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e,
+  0x74, 0x34, 0x20, 0x63, 0x6d, 0x70, 0x20, 0x3d, 0x20, 0x69, 0x73, 0x6c,
+  0x65, 0x73, 0x73, 0x28, 0x63, 0x6d, 0x70, 0x56, 0x61, 0x6c, 0x2c, 0x20,
+  0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x29, 0x28, 0x31, 0x36, 0x2e,
+  0x30, 0x66, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x21, 0x61, 0x6e,
+  0x79, 0x28, 0x63, 0x6d, 0x70, 0x29, 0x29, 0x20, 0x62, 0x72, 0x65, 0x61,
+  0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x2b, 0x3d, 0x20, 0x61,
+  0x73, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x63, 0x6d, 0x70,
+  0x20, 0x26, 0x20, 0x61, 0x73, 0x5f, 0x69, 0x6e, 0x74, 0x34, 0x28, 0x28,
+  0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x29, 0x28, 0x31, 0x29, 0x29, 0x29,
+  0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x6e, 0x2b, 0x2b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x72, 0x65, 0x73,
+  0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x73, 0x6d,
   0x6f, 0x6f, 0x74, 0x68, 0x20, 0x21, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x7b,
-  0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66,
-  0x20, 0x28, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5b, 0x69, 0x5d, 0x20, 0x3e,
-  0x3d, 0x20, 0x30, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20,
+  0x28, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x73, 0x30, 0x20, 0x3e, 0x3d,
+  0x20, 0x30, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x28, 0x28,
+  0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x29, 0x20, 0x63, 0x6f, 0x75, 0x6e,
+  0x74, 0x29, 0x20, 0x2b, 0x20, 0x28, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74,
+  0x34, 0x29, 0x28, 0x31, 0x2e, 0x30, 0x66, 0x2c, 0x20, 0x31, 0x2e, 0x30,
+  0x66, 0x2c, 0x20, 0x31, 0x2e, 0x30, 0x66, 0x2c, 0x20, 0x31, 0x2e, 0x30,
+  0x66, 0x29, 0x29, 0x20, 0x2d, 0x20, 0x6c, 0x6f, 0x67, 0x32, 0x28, 0x6c,
+  0x6f, 0x67, 0x28, 0x66, 0x6d, 0x61, 0x28, 0x72, 0x65, 0x73, 0x61, 0x2c,
+  0x20, 0x72, 0x65, 0x73, 0x61, 0x2c, 0x20, 0x72, 0x65, 0x73, 0x62, 0x20,
+  0x2a, 0x20, 0x72, 0x65, 0x73, 0x62, 0x29, 0x29, 0x20, 0x2a, 0x20, 0x30,
+  0x2e, 0x35, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x69, 0x6e,
+  0x74, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x69, 0x20, 0x3c,
+  0x20, 0x34, 0x20, 0x26, 0x26, 0x20, 0x69, 0x20, 0x2b, 0x20, 0x78, 0x20,
+  0x3c, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3b, 0x20, 0x69, 0x2b, 0x2b,
+  0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28,
+  0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x20, 0x21, 0x3d, 0x20, 0x30, 0x29,
+  0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69,
+  0x66, 0x20, 0x28, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5b, 0x69, 0x5d, 0x20,
+  0x3e, 0x3d, 0x20, 0x30, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x5b, 0x69, 0x6e, 0x64, 0x65,
   0x78, 0x20, 0x2b, 0x20, 0x69, 0x5d, 0x20, 0x3d, 0x20, 0x28, 0x28, 0x66,
   0x6c, 0x6f, 0x61, 0x74, 0x29, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5b,
@@ -243,12 +236,12 @@ unsigned char float_cl[] = {
   0x69, 0x5d, 0x2c, 0x20, 0x72, 0x65, 0x73, 0x62, 0x5b, 0x69, 0x5d, 0x20,
   0x2a, 0x20, 0x72, 0x65, 0x73, 0x62, 0x5b, 0x69, 0x5d, 0x29, 0x29, 0x20,
   0x2f, 0x20, 0x32, 0x29, 0x20, 0x2f, 0x20, 0x6c, 0x6f, 0x67, 0x28, 0x32,
-  0x2e, 0x30, 0x66, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d,
-  0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0d, 0x0a,
-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x5b, 0x69, 0x6e,
-  0x64, 0x65, 0x78, 0x20, 0x2b, 0x20, 0x69, 0x5d, 0x20, 0x3d, 0x20, 0x28,
-  0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x29, 0x20, 0x63, 0x6f, 0x75, 0x6e,
-  0x74, 0x5b, 0x69, 0x5d, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x7d,
-  0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x2a, 0x2f, 0x0d, 0x0a
+  0x2e, 0x30, 0x66, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x5b, 0x69, 0x6e, 0x64, 0x65, 0x78,
+  0x20, 0x2b, 0x20, 0x69, 0x5d, 0x20, 0x3d, 0x20, 0x28, 0x28, 0x66, 0x6c,
+  0x6f, 0x61, 0x74, 0x29, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5b, 0x69,
+  0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x7d, 0x0a, 0x2a,
+  0x2f, 0x0a
 };
-unsigned int float_cl_len = 3009;
+unsigned int float_cl_len = 2918;

+ 225 - 0
libmandel/src/opencl/hexdouble.cl

@@ -0,0 +1,225 @@
+#pragma OPENCL EXTENSION cl_khr_fp64 : enable
+
+
+typedef struct hex_double {
+    double x[6];
+} HexDouble;
+
+inline double2 twoSum(double a, double b) {
+    double s = a + b;
+    double bb = s - a;
+    double e = (a - (s - bb)) + (b - bb);
+    return (double2)(s, e);
+}
+
+inline double two_sum(double a, double b, double* err) {
+    double s = a + b;
+    double bb = s - a;
+    *err = (a - (s - bb)) + (b - bb);
+    return s;
+}
+
+inline double2 quickTwoSum(double a, double b) {
+    double s = a + b;
+    double e = b - (s - a);
+    return (double2)(s, e);
+}
+
+
+inline double2 twoProd(double a, double b) {
+    double p = a * b;
+    double e = fma(a, b, -p);
+    return (double2)(p, e);
+}
+
+
+inline double3 threeSum(double a, double b, double c)
+{
+    double2 x = twoSum(a, b);
+    double2 y = twoSum(x.s0, c);
+    double2 z = twoSum(x.s1, y.s1);
+    return (double3)(y.s0, z.s0, z.s1);
+}
+
+
+inline double4 fourSum(double a, double b, double c, double d)
+{
+    double2 x = twoSum(a, b);
+    double2 y = twoSum(x.s0, c);
+    double2 z = twoSum(y.s0, d);
+    double3 r = threeSum(x.s1, y.s1, z.s1);
+    return (double4)(z.s0, r.s0, r.s1, r.s2);
+}
+
+
+inline double2 fiveTwoSum(double a, double b, double c, double d, double e)
+{
+    double2 x = twoSum(a, b);
+    double2 y = twoSum(x.s0, c);
+    double2 z = twoSum(y.s0, d);
+    double2 w = twoSum(z.s0, e);
+    return (double2)(w.s0, x.s1 + y.s1 + z.s1 + w.s1);
+}
+
+
+inline double3 sixThreeSum(double a, double b, double c, double d, double e, double f)
+{
+    double3 av = threeSum(a, b, c);
+    double3 bv = threeSum(d, e, f);
+    
+    double2 r1t1 = twoSum(av.s0, bv.s0);
+    double2 t2t3 = twoSum(av.s1, bv.s1);
+    double t4 = av.s2 + bv.s2;
+
+    double2 r2t5 = twoSum(r1t1.s1, t2t3.s0);
+    double r3 = t4 + t2t3.s1 + r2t5.s1;
+    return (double3)(r1t1.s0, r2t5.s0, r3);
+}
+
+
+inline double3 nineThreeSum(double a, double b, double c, double d, double e,
+                            double f, double g, double h, double i)
+{
+    double3 av = threeSum(a, b, c);
+    double3 bv = threeSum(d, e, f);
+    double3 cv = threeSum(g, h, i);
+    
+    double3 r1t1t2 = threeSum(av.s0, bv.s0, cv.s0);
+    double4 r2t3t4t5 = fourSum(av.s1, bv.s1, cv.s1, r1t1t2.s1);
+    double r3 = av.s2 + bv.s2 + cv.s2 + r1t1t2.s2 + r2t3t4t5.s1 + r2t3t4t5.s2 + r2t3t4t5.s3;
+    return (double3)(r1t1t2.s0, r2t3t4t5.s0, r3);
+}
+
+
+inline HexDouble add(const __private HexDouble* a, const __private HexDouble* b)
+{
+    double2 ap = twoSum(a->x[0], b->x[0]);
+    double2 bp = twoSum(a->x[1], b->x[1]);
+    double2 cp = twoSum(a->x[2], b->x[2]);
+    double2 dp = twoSum(a->x[3], b->x[3]);
+    double2 ep = twoSum(a->x[4], b->x[4]);
+
+    double t0 = ap.s0;
+    double2 t1p1 = twoSum(ap.s1, bp.s0);
+    double3 t2p2p3 = threeSum(bp.s1, cp.s0, t1p1.s1);
+    double4 t3p456 = fourSum(cp.s1, dp.s0, t2p2p3.s1, t2p2p3.s2);
+    double2 t4p7 = fiveTwoSum(dp.s1, ep.s0, t3p456.s1, t3p456.s2, t3p456.s3);
+    double t5 = a->x[5] + b->x[5] + ep.s1 + t4p7.s1;
+
+    double2 r0 = quickTwoSum(t0, t1p1.s0);
+    double2 r1 = quickTwoSum(r0.s1, t2p2p3.s0);
+    double2 r2 = quickTwoSum(r1.s1, t3p456.s0);
+    double2 r3 = quickTwoSum(r2.s1, t4p7.s0);
+    double2 r45 = quickTwoSum(r3.s1, t5);
+
+    return (HexDouble){ r0.s0, r1.s0, r2.s0, r3.s0, r45.s0, r45.s1 };
+}
+
+
+inline HexDouble mul(const __private HexDouble* a, const __private HexDouble* b)
+{
+    double2 p0 = twoProd(a->x[0], b->x[0]);
+
+    double2 q0 = twoProd(a->x[0], b->x[1]);
+    double2 q1 = twoProd(a->x[1], b->x[0]);
+
+    double2 r0 = twoProd(a->x[2], b->x[0]);
+    double2 r1 = twoProd(a->x[1], b->x[1]);
+    double2 r2 = twoProd(a->x[0], b->x[2]);
+
+    double2 s0 = twoProd(a->x[3], b->x[0]);
+    double2 s1 = twoProd(a->x[2], b->x[1]);
+    double2 s2 = twoProd(a->x[1], b->x[2]);
+    double2 s3 = twoProd(a->x[0], b->x[3]);
+
+    double2 t0 = twoProd(a->x[4], b->x[0]);
+    double2 t1 = twoProd(a->x[3], b->x[1]);
+    double2 t2 = twoProd(a->x[2], b->x[2]);
+    double2 t3 = twoProd(a->x[1], b->x[3]);
+    double2 t4 = twoProd(a->x[0], b->x[4]);
+
+    double v1 = p0.s0;
+    double3 t2L34 = threeSum(p0.s1, q0.s0, q1.s0);
+    double3 t3L45 = sixThreeSum(q0.s1, q1.s1, r0.s0, r1.s0, r2.s0, t2L34.s1);
+    double3 t4L56 = nineThreeSum(r0.s1, r1.s1, r2.s1, s0.s0, s1.s0, s2.s0, s3.s0, t2L34.s2, t3L45.s1);
+    double3 x123 = nineThreeSum(s0.s1, s1.s1, s2.s1, s3.s1, t0.s0, t1.s0, t2.s0, t3.s0, t4.s0);
+    double3 t5L67 = sixThreeSum(x123.s0, x123.s1, x123.s2, t3L45.s2, t4L56.s1, 0.0);
+
+    double v6 = t4L56.s2 + t5L67.s1 + t5L67.s2 + t0.s1 + t1.s1 + t2.s1 + t3.s1 + t4.s1 +
+        a->x[5] * b->x[0] + a->x[4] * b->x[1] + a->x[3] * b->x[2] + a->x[2] * b->x[3] + a->x[1] * b->x[4] + a->x[0] * b->x[5];
+
+    double2 re0 = quickTwoSum(v1, t2L34.s0);
+    double2 re1 = quickTwoSum(re0.s1, t3L45.s0);
+    double2 re2 = quickTwoSum(re1.s1, t4L56.s0);
+    double2 re3 = quickTwoSum(re2.s1, t5L67.s0);
+    double2 re45 = quickTwoSum(re3.s1, v6);
+    return (HexDouble){ re0.s0, re1.s0, re2.s0, re3.s0, re45.s0, re45.s1 };
+}
+
+
+HexDouble loadHd(const __global double* v) {
+    return (HexDouble) {
+        v[0],
+        v[1],
+        v[2],
+        v[3],
+        v[4],
+        v[5],
+    };
+}
+
+
+__kernel void iterate(__global float* A, const int width,
+                      __global double* x, __global double* y,
+                      __global double* pw, __global double* ph, int max, int smooth, int julia,
+                      __global double* jx, __global double* jy) {
+    int index = get_global_id(0);
+    int px = index % width;
+    int py = index / width;
+
+    HexDouble xl = loadHd(x);
+    HexDouble yt = loadHd(y);
+    HexDouble pixelScaleX = loadHd(pw);
+    HexDouble pixelScaleY = loadHd(ph);
+
+    HexDouble pxh = { px, 0, 0, 0, 0, 0 };
+    HexDouble pyh = { py, 0, 0, 0, 0, 0 };
+
+    HexDouble caOff = mul(&pixelScaleX, &pxh);
+    HexDouble cbOff = mul(&pixelScaleY, &pyh);
+    HexDouble ca = add(&caOff, &xl); // pixelScaleX * px + xl
+    HexDouble cb = add(&cbOff, &yt); // pixelScaleY * py + yt
+    HexDouble a = ca;
+    HexDouble b = cb;
+    if (julia != 0) {
+        ca = loadHd(jx);
+        cb = loadHd(jy);
+    }
+
+    int n = 0;
+    while (n < max - 1) {
+        HexDouble aa = mul(&a, &a); /* TODO add squaring function */
+        HexDouble bb = mul(&b, &b);
+        HexDouble ab = mul(&a, &b);
+        HexDouble minusbb = { -bb.x[0], -bb.x[1], -bb.x[2], -bb.x[3], -bb.x[4], -bb.x[5] };
+        HexDouble aambb = add(&aa, &minusbb);
+        HexDouble abab = add(&ab, &ab);
+        a = add(&aambb, &ca);
+        b = add(&abab, &cb);
+        if (aa.x[0] + bb.x[0] > 16) break;
+        n++;
+    }
+
+    // N + 1 - log (log  |Z(N)|) / log 2
+    if (n >= max - 1)
+        A[index] = max;
+    else {
+        if (smooth != 0)
+            A[index] = ((float) n) + 1 - log2(log(a.x[0] * a.x[0] + b.x[0] * b.x[0]) * 0.5);
+        else
+            A[index] = ((float)n);
+    }
+    //               A[index] = ((float)n) + 1 - (a * a + b * b - 16) / (256 - 16);
+    //           A[get_global_id(0)] = 5;
+}
+

+ 584 - 0
libmandel/src/opencl/hexdouble.h

@@ -0,0 +1,584 @@
+unsigned char hexdouble_cl[] = {
+  0x23, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x20, 0x4f, 0x50, 0x45, 0x4e,
+  0x43, 0x4c, 0x20, 0x45, 0x58, 0x54, 0x45, 0x4e, 0x53, 0x49, 0x4f, 0x4e,
+  0x20, 0x63, 0x6c, 0x5f, 0x6b, 0x68, 0x72, 0x5f, 0x66, 0x70, 0x36, 0x34,
+  0x20, 0x3a, 0x20, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x0a, 0x0a, 0x0a,
+  0x74, 0x79, 0x70, 0x65, 0x64, 0x65, 0x66, 0x20, 0x73, 0x74, 0x72, 0x75,
+  0x63, 0x74, 0x20, 0x68, 0x65, 0x78, 0x5f, 0x64, 0x6f, 0x75, 0x62, 0x6c,
+  0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x20, 0x78, 0x5b, 0x36, 0x5d, 0x3b, 0x0a, 0x7d, 0x20, 0x48,
+  0x65, 0x78, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x3b, 0x0a, 0x0a, 0x69,
+  0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65,
+  0x32, 0x20, 0x74, 0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x64, 0x6f, 0x75,
+  0x62, 0x6c, 0x65, 0x20, 0x61, 0x2c, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c,
+  0x65, 0x20, 0x62, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x73, 0x20, 0x3d, 0x20, 0x61, 0x20,
+  0x2b, 0x20, 0x62, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75,
+  0x62, 0x6c, 0x65, 0x20, 0x62, 0x62, 0x20, 0x3d, 0x20, 0x73, 0x20, 0x2d,
+  0x20, 0x61, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x20, 0x65, 0x20, 0x3d, 0x20, 0x28, 0x61, 0x20, 0x2d, 0x20,
+  0x28, 0x73, 0x20, 0x2d, 0x20, 0x62, 0x62, 0x29, 0x29, 0x20, 0x2b, 0x20,
+  0x28, 0x62, 0x20, 0x2d, 0x20, 0x62, 0x62, 0x29, 0x3b, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x64, 0x6f,
+  0x75, 0x62, 0x6c, 0x65, 0x32, 0x29, 0x28, 0x73, 0x2c, 0x20, 0x65, 0x29,
+  0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20,
+  0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x77, 0x6f, 0x5f, 0x73,
+  0x75, 0x6d, 0x28, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x61, 0x2c,
+  0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x62, 0x2c, 0x20, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x2a, 0x20, 0x65, 0x72, 0x72, 0x29, 0x20,
+  0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65,
+  0x20, 0x73, 0x20, 0x3d, 0x20, 0x61, 0x20, 0x2b, 0x20, 0x62, 0x3b, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x62,
+  0x62, 0x20, 0x3d, 0x20, 0x73, 0x20, 0x2d, 0x20, 0x61, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x2a, 0x65, 0x72, 0x72, 0x20, 0x3d, 0x20, 0x28, 0x61,
+  0x20, 0x2d, 0x20, 0x28, 0x73, 0x20, 0x2d, 0x20, 0x62, 0x62, 0x29, 0x29,
+  0x20, 0x2b, 0x20, 0x28, 0x62, 0x20, 0x2d, 0x20, 0x62, 0x62, 0x29, 0x3b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20,
+  0x73, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65,
+  0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x71, 0x75, 0x69,
+  0x63, 0x6b, 0x54, 0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x64, 0x6f, 0x75,
+  0x62, 0x6c, 0x65, 0x20, 0x61, 0x2c, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c,
+  0x65, 0x20, 0x62, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x73, 0x20, 0x3d, 0x20, 0x61, 0x20,
+  0x2b, 0x20, 0x62, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75,
+  0x62, 0x6c, 0x65, 0x20, 0x65, 0x20, 0x3d, 0x20, 0x62, 0x20, 0x2d, 0x20,
+  0x28, 0x73, 0x20, 0x2d, 0x20, 0x61, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20,
+  0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x64, 0x6f, 0x75,
+  0x62, 0x6c, 0x65, 0x32, 0x29, 0x28, 0x73, 0x2c, 0x20, 0x65, 0x29, 0x3b,
+  0x0a, 0x7d, 0x0a, 0x0a, 0x0a, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20,
+  0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x74, 0x77, 0x6f, 0x50,
+  0x72, 0x6f, 0x64, 0x28, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x61,
+  0x2c, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x62, 0x29, 0x20,
+  0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65,
+  0x20, 0x70, 0x20, 0x3d, 0x20, 0x61, 0x20, 0x2a, 0x20, 0x62, 0x3b, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x65,
+  0x20, 0x3d, 0x20, 0x66, 0x6d, 0x61, 0x28, 0x61, 0x2c, 0x20, 0x62, 0x2c,
+  0x20, 0x2d, 0x70, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65,
+  0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65,
+  0x32, 0x29, 0x28, 0x70, 0x2c, 0x20, 0x65, 0x29, 0x3b, 0x0a, 0x7d, 0x0a,
+  0x0a, 0x0a, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x64, 0x6f, 0x75,
+  0x62, 0x6c, 0x65, 0x33, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x53, 0x75,
+  0x6d, 0x28, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x61, 0x2c, 0x20,
+  0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x62, 0x2c, 0x20, 0x64, 0x6f,
+  0x75, 0x62, 0x6c, 0x65, 0x20, 0x63, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x78, 0x20,
+  0x3d, 0x20, 0x74, 0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x61, 0x2c, 0x20,
+  0x62, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x32, 0x20, 0x79, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f, 0x53,
+  0x75, 0x6d, 0x28, 0x78, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x63, 0x29, 0x3b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32,
+  0x20, 0x7a, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28,
+  0x78, 0x2e, 0x73, 0x31, 0x2c, 0x20, 0x79, 0x2e, 0x73, 0x31, 0x29, 0x3b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20,
+  0x28, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x33, 0x29, 0x28, 0x79, 0x2e,
+  0x73, 0x30, 0x2c, 0x20, 0x7a, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x7a, 0x2e,
+  0x73, 0x31, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x0a, 0x69, 0x6e, 0x6c,
+  0x69, 0x6e, 0x65, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x34, 0x20,
+  0x66, 0x6f, 0x75, 0x72, 0x53, 0x75, 0x6d, 0x28, 0x64, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x20, 0x61, 0x2c, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65,
+  0x20, 0x62, 0x2c, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x63,
+  0x2c, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x64, 0x29, 0x0a,
+  0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65,
+  0x32, 0x20, 0x78, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f, 0x53, 0x75, 0x6d,
+  0x28, 0x61, 0x2c, 0x20, 0x62, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x79, 0x20, 0x3d, 0x20,
+  0x74, 0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x78, 0x2e, 0x73, 0x30, 0x2c,
+  0x20, 0x63, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75,
+  0x62, 0x6c, 0x65, 0x32, 0x20, 0x7a, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f,
+  0x53, 0x75, 0x6d, 0x28, 0x79, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x64, 0x29,
+  0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65,
+  0x33, 0x20, 0x72, 0x20, 0x3d, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x53,
+  0x75, 0x6d, 0x28, 0x78, 0x2e, 0x73, 0x31, 0x2c, 0x20, 0x79, 0x2e, 0x73,
+  0x31, 0x2c, 0x20, 0x7a, 0x2e, 0x73, 0x31, 0x29, 0x3b, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x64, 0x6f,
+  0x75, 0x62, 0x6c, 0x65, 0x34, 0x29, 0x28, 0x7a, 0x2e, 0x73, 0x30, 0x2c,
+  0x20, 0x72, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x72, 0x2e, 0x73, 0x31, 0x2c,
+  0x20, 0x72, 0x2e, 0x73, 0x32, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x0a,
+  0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c,
+  0x65, 0x32, 0x20, 0x66, 0x69, 0x76, 0x65, 0x54, 0x77, 0x6f, 0x53, 0x75,
+  0x6d, 0x28, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x61, 0x2c, 0x20,
+  0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x62, 0x2c, 0x20, 0x64, 0x6f,
+  0x75, 0x62, 0x6c, 0x65, 0x20, 0x63, 0x2c, 0x20, 0x64, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x20, 0x64, 0x2c, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65,
+  0x20, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f,
+  0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x78, 0x20, 0x3d, 0x20, 0x74, 0x77,
+  0x6f, 0x53, 0x75, 0x6d, 0x28, 0x61, 0x2c, 0x20, 0x62, 0x29, 0x3b, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20,
+  0x79, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x78,
+  0x2e, 0x73, 0x30, 0x2c, 0x20, 0x63, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20,
+  0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x7a, 0x20, 0x3d,
+  0x20, 0x74, 0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x79, 0x2e, 0x73, 0x30,
+  0x2c, 0x20, 0x64, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f,
+  0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x77, 0x20, 0x3d, 0x20, 0x74, 0x77,
+  0x6f, 0x53, 0x75, 0x6d, 0x28, 0x7a, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x65,
+  0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72,
+  0x6e, 0x20, 0x28, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x29, 0x28,
+  0x77, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x78, 0x2e, 0x73, 0x31, 0x20, 0x2b,
+  0x20, 0x79, 0x2e, 0x73, 0x31, 0x20, 0x2b, 0x20, 0x7a, 0x2e, 0x73, 0x31,
+  0x20, 0x2b, 0x20, 0x77, 0x2e, 0x73, 0x31, 0x29, 0x3b, 0x0a, 0x7d, 0x0a,
+  0x0a, 0x0a, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x64, 0x6f, 0x75,
+  0x62, 0x6c, 0x65, 0x33, 0x20, 0x73, 0x69, 0x78, 0x54, 0x68, 0x72, 0x65,
+  0x65, 0x53, 0x75, 0x6d, 0x28, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20,
+  0x61, 0x2c, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x62, 0x2c,
+  0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x63, 0x2c, 0x20, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x64, 0x2c, 0x20, 0x64, 0x6f, 0x75,
+  0x62, 0x6c, 0x65, 0x20, 0x65, 0x2c, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c,
+  0x65, 0x20, 0x66, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x33, 0x20, 0x61, 0x76, 0x20, 0x3d, 0x20,
+  0x74, 0x68, 0x72, 0x65, 0x65, 0x53, 0x75, 0x6d, 0x28, 0x61, 0x2c, 0x20,
+  0x62, 0x2c, 0x20, 0x63, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x33, 0x20, 0x62, 0x76, 0x20, 0x3d, 0x20,
+  0x74, 0x68, 0x72, 0x65, 0x65, 0x53, 0x75, 0x6d, 0x28, 0x64, 0x2c, 0x20,
+  0x65, 0x2c, 0x20, 0x66, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20,
+  0x72, 0x31, 0x74, 0x31, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f, 0x53, 0x75,
+  0x6d, 0x28, 0x61, 0x76, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x62, 0x76, 0x2e,
+  0x73, 0x30, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75,
+  0x62, 0x6c, 0x65, 0x32, 0x20, 0x74, 0x32, 0x74, 0x33, 0x20, 0x3d, 0x20,
+  0x74, 0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x61, 0x76, 0x2e, 0x73, 0x31,
+  0x2c, 0x20, 0x62, 0x76, 0x2e, 0x73, 0x31, 0x29, 0x3b, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x34, 0x20,
+  0x3d, 0x20, 0x61, 0x76, 0x2e, 0x73, 0x32, 0x20, 0x2b, 0x20, 0x62, 0x76,
+  0x2e, 0x73, 0x32, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f,
+  0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x72, 0x32, 0x74, 0x35, 0x20, 0x3d,
+  0x20, 0x74, 0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x72, 0x31, 0x74, 0x31,
+  0x2e, 0x73, 0x31, 0x2c, 0x20, 0x74, 0x32, 0x74, 0x33, 0x2e, 0x73, 0x30,
+  0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c,
+  0x65, 0x20, 0x72, 0x33, 0x20, 0x3d, 0x20, 0x74, 0x34, 0x20, 0x2b, 0x20,
+  0x74, 0x32, 0x74, 0x33, 0x2e, 0x73, 0x31, 0x20, 0x2b, 0x20, 0x72, 0x32,
+  0x74, 0x35, 0x2e, 0x73, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72,
+  0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x64, 0x6f, 0x75, 0x62, 0x6c,
+  0x65, 0x33, 0x29, 0x28, 0x72, 0x31, 0x74, 0x31, 0x2e, 0x73, 0x30, 0x2c,
+  0x20, 0x72, 0x32, 0x74, 0x35, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x72, 0x33,
+  0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x0a, 0x69, 0x6e, 0x6c, 0x69, 0x6e,
+  0x65, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x33, 0x20, 0x6e, 0x69,
+  0x6e, 0x65, 0x54, 0x68, 0x72, 0x65, 0x65, 0x53, 0x75, 0x6d, 0x28, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x61, 0x2c, 0x20, 0x64, 0x6f, 0x75,
+  0x62, 0x6c, 0x65, 0x20, 0x62, 0x2c, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c,
+  0x65, 0x20, 0x63, 0x2c, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20,
+  0x64, 0x2c, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x65, 0x2c,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20,
+  0x66, 0x2c, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x67, 0x2c,
+  0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x68, 0x2c, 0x20, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x69, 0x29, 0x0a, 0x7b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x33, 0x20, 0x61,
+  0x76, 0x20, 0x3d, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x53, 0x75, 0x6d,
+  0x28, 0x61, 0x2c, 0x20, 0x62, 0x2c, 0x20, 0x63, 0x29, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x33, 0x20, 0x62,
+  0x76, 0x20, 0x3d, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x53, 0x75, 0x6d,
+  0x28, 0x64, 0x2c, 0x20, 0x65, 0x2c, 0x20, 0x66, 0x29, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x33, 0x20, 0x63,
+  0x76, 0x20, 0x3d, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x53, 0x75, 0x6d,
+  0x28, 0x67, 0x2c, 0x20, 0x68, 0x2c, 0x20, 0x69, 0x29, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x33, 0x20, 0x72, 0x31, 0x74, 0x31, 0x74, 0x32, 0x20, 0x3d,
+  0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x53, 0x75, 0x6d, 0x28, 0x61, 0x76,
+  0x2e, 0x73, 0x30, 0x2c, 0x20, 0x62, 0x76, 0x2e, 0x73, 0x30, 0x2c, 0x20,
+  0x63, 0x76, 0x2e, 0x73, 0x30, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x34, 0x20, 0x72, 0x32, 0x74, 0x33,
+  0x74, 0x34, 0x74, 0x35, 0x20, 0x3d, 0x20, 0x66, 0x6f, 0x75, 0x72, 0x53,
+  0x75, 0x6d, 0x28, 0x61, 0x76, 0x2e, 0x73, 0x31, 0x2c, 0x20, 0x62, 0x76,
+  0x2e, 0x73, 0x31, 0x2c, 0x20, 0x63, 0x76, 0x2e, 0x73, 0x31, 0x2c, 0x20,
+  0x72, 0x31, 0x74, 0x31, 0x74, 0x32, 0x2e, 0x73, 0x31, 0x29, 0x3b, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x72,
+  0x33, 0x20, 0x3d, 0x20, 0x61, 0x76, 0x2e, 0x73, 0x32, 0x20, 0x2b, 0x20,
+  0x62, 0x76, 0x2e, 0x73, 0x32, 0x20, 0x2b, 0x20, 0x63, 0x76, 0x2e, 0x73,
+  0x32, 0x20, 0x2b, 0x20, 0x72, 0x31, 0x74, 0x31, 0x74, 0x32, 0x2e, 0x73,
+  0x32, 0x20, 0x2b, 0x20, 0x72, 0x32, 0x74, 0x33, 0x74, 0x34, 0x74, 0x35,
+  0x2e, 0x73, 0x31, 0x20, 0x2b, 0x20, 0x72, 0x32, 0x74, 0x33, 0x74, 0x34,
+  0x74, 0x35, 0x2e, 0x73, 0x32, 0x20, 0x2b, 0x20, 0x72, 0x32, 0x74, 0x33,
+  0x74, 0x34, 0x74, 0x35, 0x2e, 0x73, 0x33, 0x3b, 0x0a, 0x20, 0x20, 0x20,
+  0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x64, 0x6f, 0x75,
+  0x62, 0x6c, 0x65, 0x33, 0x29, 0x28, 0x72, 0x31, 0x74, 0x31, 0x74, 0x32,
+  0x2e, 0x73, 0x30, 0x2c, 0x20, 0x72, 0x32, 0x74, 0x33, 0x74, 0x34, 0x74,
+  0x35, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x72, 0x33, 0x29, 0x3b, 0x0a, 0x7d,
+  0x0a, 0x0a, 0x0a, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x48, 0x65,
+  0x78, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x61, 0x64, 0x64, 0x28,
+  0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x5f, 0x5f, 0x70, 0x72, 0x69, 0x76,
+  0x61, 0x74, 0x65, 0x20, 0x48, 0x65, 0x78, 0x44, 0x6f, 0x75, 0x62, 0x6c,
+  0x65, 0x2a, 0x20, 0x61, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20,
+  0x5f, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x48, 0x65,
+  0x78, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x2a, 0x20, 0x62, 0x29, 0x0a,
+  0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65,
+  0x32, 0x20, 0x61, 0x70, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f, 0x53, 0x75,
+  0x6d, 0x28, 0x61, 0x2d, 0x3e, 0x78, 0x5b, 0x30, 0x5d, 0x2c, 0x20, 0x62,
+  0x2d, 0x3e, 0x78, 0x5b, 0x30, 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20,
+  0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x62, 0x70, 0x20,
+  0x3d, 0x20, 0x74, 0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x61, 0x2d, 0x3e,
+  0x78, 0x5b, 0x31, 0x5d, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x78, 0x5b, 0x31,
+  0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x32, 0x20, 0x63, 0x70, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f,
+  0x53, 0x75, 0x6d, 0x28, 0x61, 0x2d, 0x3e, 0x78, 0x5b, 0x32, 0x5d, 0x2c,
+  0x20, 0x62, 0x2d, 0x3e, 0x78, 0x5b, 0x32, 0x5d, 0x29, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x64,
+  0x70, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x61,
+  0x2d, 0x3e, 0x78, 0x5b, 0x33, 0x5d, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x78,
+  0x5b, 0x33, 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f,
+  0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x65, 0x70, 0x20, 0x3d, 0x20, 0x74,
+  0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x61, 0x2d, 0x3e, 0x78, 0x5b, 0x34,
+  0x5d, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x78, 0x5b, 0x34, 0x5d, 0x29, 0x3b,
+  0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65,
+  0x20, 0x74, 0x30, 0x20, 0x3d, 0x20, 0x61, 0x70, 0x2e, 0x73, 0x30, 0x3b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32,
+  0x20, 0x74, 0x31, 0x70, 0x31, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f, 0x53,
+  0x75, 0x6d, 0x28, 0x61, 0x70, 0x2e, 0x73, 0x31, 0x2c, 0x20, 0x62, 0x70,
+  0x2e, 0x73, 0x30, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f,
+  0x75, 0x62, 0x6c, 0x65, 0x33, 0x20, 0x74, 0x32, 0x70, 0x32, 0x70, 0x33,
+  0x20, 0x3d, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x53, 0x75, 0x6d, 0x28,
+  0x62, 0x70, 0x2e, 0x73, 0x31, 0x2c, 0x20, 0x63, 0x70, 0x2e, 0x73, 0x30,
+  0x2c, 0x20, 0x74, 0x31, 0x70, 0x31, 0x2e, 0x73, 0x31, 0x29, 0x3b, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x34, 0x20,
+  0x74, 0x33, 0x70, 0x34, 0x35, 0x36, 0x20, 0x3d, 0x20, 0x66, 0x6f, 0x75,
+  0x72, 0x53, 0x75, 0x6d, 0x28, 0x63, 0x70, 0x2e, 0x73, 0x31, 0x2c, 0x20,
+  0x64, 0x70, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x74, 0x32, 0x70, 0x32, 0x70,
+  0x33, 0x2e, 0x73, 0x31, 0x2c, 0x20, 0x74, 0x32, 0x70, 0x32, 0x70, 0x33,
+  0x2e, 0x73, 0x32, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f,
+  0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x74, 0x34, 0x70, 0x37, 0x20, 0x3d,
+  0x20, 0x66, 0x69, 0x76, 0x65, 0x54, 0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28,
+  0x64, 0x70, 0x2e, 0x73, 0x31, 0x2c, 0x20, 0x65, 0x70, 0x2e, 0x73, 0x30,
+  0x2c, 0x20, 0x74, 0x33, 0x70, 0x34, 0x35, 0x36, 0x2e, 0x73, 0x31, 0x2c,
+  0x20, 0x74, 0x33, 0x70, 0x34, 0x35, 0x36, 0x2e, 0x73, 0x32, 0x2c, 0x20,
+  0x74, 0x33, 0x70, 0x34, 0x35, 0x36, 0x2e, 0x73, 0x33, 0x29, 0x3b, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x74,
+  0x35, 0x20, 0x3d, 0x20, 0x61, 0x2d, 0x3e, 0x78, 0x5b, 0x35, 0x5d, 0x20,
+  0x2b, 0x20, 0x62, 0x2d, 0x3e, 0x78, 0x5b, 0x35, 0x5d, 0x20, 0x2b, 0x20,
+  0x65, 0x70, 0x2e, 0x73, 0x31, 0x20, 0x2b, 0x20, 0x74, 0x34, 0x70, 0x37,
+  0x2e, 0x73, 0x31, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f,
+  0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x72, 0x30, 0x20, 0x3d, 0x20, 0x71,
+  0x75, 0x69, 0x63, 0x6b, 0x54, 0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x74,
+  0x30, 0x2c, 0x20, 0x74, 0x31, 0x70, 0x31, 0x2e, 0x73, 0x30, 0x29, 0x3b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32,
+  0x20, 0x72, 0x31, 0x20, 0x3d, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x54,
+  0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x72, 0x30, 0x2e, 0x73, 0x31, 0x2c,
+  0x20, 0x74, 0x32, 0x70, 0x32, 0x70, 0x33, 0x2e, 0x73, 0x30, 0x29, 0x3b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32,
+  0x20, 0x72, 0x32, 0x20, 0x3d, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x54,
+  0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x72, 0x31, 0x2e, 0x73, 0x31, 0x2c,
+  0x20, 0x74, 0x33, 0x70, 0x34, 0x35, 0x36, 0x2e, 0x73, 0x30, 0x29, 0x3b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32,
+  0x20, 0x72, 0x33, 0x20, 0x3d, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x54,
+  0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x72, 0x32, 0x2e, 0x73, 0x31, 0x2c,
+  0x20, 0x74, 0x34, 0x70, 0x37, 0x2e, 0x73, 0x30, 0x29, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x72,
+  0x34, 0x35, 0x20, 0x3d, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x54, 0x77,
+  0x6f, 0x53, 0x75, 0x6d, 0x28, 0x72, 0x33, 0x2e, 0x73, 0x31, 0x2c, 0x20,
+  0x74, 0x35, 0x29, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65,
+  0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x48, 0x65, 0x78, 0x44, 0x6f, 0x75,
+  0x62, 0x6c, 0x65, 0x29, 0x7b, 0x20, 0x72, 0x30, 0x2e, 0x73, 0x30, 0x2c,
+  0x20, 0x72, 0x31, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x72, 0x32, 0x2e, 0x73,
+  0x30, 0x2c, 0x20, 0x72, 0x33, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x72, 0x34,
+  0x35, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x72, 0x34, 0x35, 0x2e, 0x73, 0x31,
+  0x20, 0x7d, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x0a, 0x69, 0x6e, 0x6c, 0x69,
+  0x6e, 0x65, 0x20, 0x48, 0x65, 0x78, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65,
+  0x20, 0x6d, 0x75, 0x6c, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x5f,
+  0x5f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x48, 0x65, 0x78,
+  0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x2a, 0x20, 0x61, 0x2c, 0x20, 0x63,
+  0x6f, 0x6e, 0x73, 0x74, 0x20, 0x5f, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x61,
+  0x74, 0x65, 0x20, 0x48, 0x65, 0x78, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65,
+  0x2a, 0x20, 0x62, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x70, 0x30, 0x20, 0x3d, 0x20,
+  0x74, 0x77, 0x6f, 0x50, 0x72, 0x6f, 0x64, 0x28, 0x61, 0x2d, 0x3e, 0x78,
+  0x5b, 0x30, 0x5d, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x78, 0x5b, 0x30, 0x5d,
+  0x29, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x32, 0x20, 0x71, 0x30, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f,
+  0x50, 0x72, 0x6f, 0x64, 0x28, 0x61, 0x2d, 0x3e, 0x78, 0x5b, 0x30, 0x5d,
+  0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x78, 0x5b, 0x31, 0x5d, 0x29, 0x3b, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20,
+  0x71, 0x31, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f, 0x50, 0x72, 0x6f, 0x64,
+  0x28, 0x61, 0x2d, 0x3e, 0x78, 0x5b, 0x31, 0x5d, 0x2c, 0x20, 0x62, 0x2d,
+  0x3e, 0x78, 0x5b, 0x30, 0x5d, 0x29, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20,
+  0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x72, 0x30, 0x20,
+  0x3d, 0x20, 0x74, 0x77, 0x6f, 0x50, 0x72, 0x6f, 0x64, 0x28, 0x61, 0x2d,
+  0x3e, 0x78, 0x5b, 0x32, 0x5d, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x78, 0x5b,
+  0x30, 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75,
+  0x62, 0x6c, 0x65, 0x32, 0x20, 0x72, 0x31, 0x20, 0x3d, 0x20, 0x74, 0x77,
+  0x6f, 0x50, 0x72, 0x6f, 0x64, 0x28, 0x61, 0x2d, 0x3e, 0x78, 0x5b, 0x31,
+  0x5d, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x78, 0x5b, 0x31, 0x5d, 0x29, 0x3b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32,
+  0x20, 0x72, 0x32, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f, 0x50, 0x72, 0x6f,
+  0x64, 0x28, 0x61, 0x2d, 0x3e, 0x78, 0x5b, 0x30, 0x5d, 0x2c, 0x20, 0x62,
+  0x2d, 0x3e, 0x78, 0x5b, 0x32, 0x5d, 0x29, 0x3b, 0x0a, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x73, 0x30,
+  0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f, 0x50, 0x72, 0x6f, 0x64, 0x28, 0x61,
+  0x2d, 0x3e, 0x78, 0x5b, 0x33, 0x5d, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x78,
+  0x5b, 0x30, 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f,
+  0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x73, 0x31, 0x20, 0x3d, 0x20, 0x74,
+  0x77, 0x6f, 0x50, 0x72, 0x6f, 0x64, 0x28, 0x61, 0x2d, 0x3e, 0x78, 0x5b,
+  0x32, 0x5d, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x78, 0x5b, 0x31, 0x5d, 0x29,
+  0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65,
+  0x32, 0x20, 0x73, 0x32, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f, 0x50, 0x72,
+  0x6f, 0x64, 0x28, 0x61, 0x2d, 0x3e, 0x78, 0x5b, 0x31, 0x5d, 0x2c, 0x20,
+  0x62, 0x2d, 0x3e, 0x78, 0x5b, 0x32, 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x73, 0x33,
+  0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f, 0x50, 0x72, 0x6f, 0x64, 0x28, 0x61,
+  0x2d, 0x3e, 0x78, 0x5b, 0x30, 0x5d, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x78,
+  0x5b, 0x33, 0x5d, 0x29, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x74, 0x30, 0x20, 0x3d, 0x20,
+  0x74, 0x77, 0x6f, 0x50, 0x72, 0x6f, 0x64, 0x28, 0x61, 0x2d, 0x3e, 0x78,
+  0x5b, 0x34, 0x5d, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x78, 0x5b, 0x30, 0x5d,
+  0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c,
+  0x65, 0x32, 0x20, 0x74, 0x31, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f, 0x50,
+  0x72, 0x6f, 0x64, 0x28, 0x61, 0x2d, 0x3e, 0x78, 0x5b, 0x33, 0x5d, 0x2c,
+  0x20, 0x62, 0x2d, 0x3e, 0x78, 0x5b, 0x31, 0x5d, 0x29, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x74,
+  0x32, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f, 0x50, 0x72, 0x6f, 0x64, 0x28,
+  0x61, 0x2d, 0x3e, 0x78, 0x5b, 0x32, 0x5d, 0x2c, 0x20, 0x62, 0x2d, 0x3e,
+  0x78, 0x5b, 0x32, 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x74, 0x33, 0x20, 0x3d, 0x20,
+  0x74, 0x77, 0x6f, 0x50, 0x72, 0x6f, 0x64, 0x28, 0x61, 0x2d, 0x3e, 0x78,
+  0x5b, 0x31, 0x5d, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x78, 0x5b, 0x33, 0x5d,
+  0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c,
+  0x65, 0x32, 0x20, 0x74, 0x34, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f, 0x50,
+  0x72, 0x6f, 0x64, 0x28, 0x61, 0x2d, 0x3e, 0x78, 0x5b, 0x30, 0x5d, 0x2c,
+  0x20, 0x62, 0x2d, 0x3e, 0x78, 0x5b, 0x34, 0x5d, 0x29, 0x3b, 0x0a, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x76,
+  0x31, 0x20, 0x3d, 0x20, 0x70, 0x30, 0x2e, 0x73, 0x30, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x33, 0x20, 0x74,
+  0x32, 0x4c, 0x33, 0x34, 0x20, 0x3d, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65,
+  0x53, 0x75, 0x6d, 0x28, 0x70, 0x30, 0x2e, 0x73, 0x31, 0x2c, 0x20, 0x71,
+  0x30, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x71, 0x31, 0x2e, 0x73, 0x30, 0x29,
+  0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65,
+  0x33, 0x20, 0x74, 0x33, 0x4c, 0x34, 0x35, 0x20, 0x3d, 0x20, 0x73, 0x69,
+  0x78, 0x54, 0x68, 0x72, 0x65, 0x65, 0x53, 0x75, 0x6d, 0x28, 0x71, 0x30,
+  0x2e, 0x73, 0x31, 0x2c, 0x20, 0x71, 0x31, 0x2e, 0x73, 0x31, 0x2c, 0x20,
+  0x72, 0x30, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x72, 0x31, 0x2e, 0x73, 0x30,
+  0x2c, 0x20, 0x72, 0x32, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x74, 0x32, 0x4c,
+  0x33, 0x34, 0x2e, 0x73, 0x31, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x33, 0x20, 0x74, 0x34, 0x4c, 0x35,
+  0x36, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x54, 0x68, 0x72, 0x65,
+  0x65, 0x53, 0x75, 0x6d, 0x28, 0x72, 0x30, 0x2e, 0x73, 0x31, 0x2c, 0x20,
+  0x72, 0x31, 0x2e, 0x73, 0x31, 0x2c, 0x20, 0x72, 0x32, 0x2e, 0x73, 0x31,
+  0x2c, 0x20, 0x73, 0x30, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x73, 0x31, 0x2e,
+  0x73, 0x30, 0x2c, 0x20, 0x73, 0x32, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x73,
+  0x33, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x74, 0x32, 0x4c, 0x33, 0x34, 0x2e,
+  0x73, 0x32, 0x2c, 0x20, 0x74, 0x33, 0x4c, 0x34, 0x35, 0x2e, 0x73, 0x31,
+  0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c,
+  0x65, 0x33, 0x20, 0x78, 0x31, 0x32, 0x33, 0x20, 0x3d, 0x20, 0x6e, 0x69,
+  0x6e, 0x65, 0x54, 0x68, 0x72, 0x65, 0x65, 0x53, 0x75, 0x6d, 0x28, 0x73,
+  0x30, 0x2e, 0x73, 0x31, 0x2c, 0x20, 0x73, 0x31, 0x2e, 0x73, 0x31, 0x2c,
+  0x20, 0x73, 0x32, 0x2e, 0x73, 0x31, 0x2c, 0x20, 0x73, 0x33, 0x2e, 0x73,
+  0x31, 0x2c, 0x20, 0x74, 0x30, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x74, 0x31,
+  0x2e, 0x73, 0x30, 0x2c, 0x20, 0x74, 0x32, 0x2e, 0x73, 0x30, 0x2c, 0x20,
+  0x74, 0x33, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x74, 0x34, 0x2e, 0x73, 0x30,
+  0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c,
+  0x65, 0x33, 0x20, 0x74, 0x35, 0x4c, 0x36, 0x37, 0x20, 0x3d, 0x20, 0x73,
+  0x69, 0x78, 0x54, 0x68, 0x72, 0x65, 0x65, 0x53, 0x75, 0x6d, 0x28, 0x78,
+  0x31, 0x32, 0x33, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x78, 0x31, 0x32, 0x33,
+  0x2e, 0x73, 0x31, 0x2c, 0x20, 0x78, 0x31, 0x32, 0x33, 0x2e, 0x73, 0x32,
+  0x2c, 0x20, 0x74, 0x33, 0x4c, 0x34, 0x35, 0x2e, 0x73, 0x32, 0x2c, 0x20,
+  0x74, 0x34, 0x4c, 0x35, 0x36, 0x2e, 0x73, 0x31, 0x2c, 0x20, 0x30, 0x2e,
+  0x30, 0x29, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75,
+  0x62, 0x6c, 0x65, 0x20, 0x76, 0x36, 0x20, 0x3d, 0x20, 0x74, 0x34, 0x4c,
+  0x35, 0x36, 0x2e, 0x73, 0x32, 0x20, 0x2b, 0x20, 0x74, 0x35, 0x4c, 0x36,
+  0x37, 0x2e, 0x73, 0x31, 0x20, 0x2b, 0x20, 0x74, 0x35, 0x4c, 0x36, 0x37,
+  0x2e, 0x73, 0x32, 0x20, 0x2b, 0x20, 0x74, 0x30, 0x2e, 0x73, 0x31, 0x20,
+  0x2b, 0x20, 0x74, 0x31, 0x2e, 0x73, 0x31, 0x20, 0x2b, 0x20, 0x74, 0x32,
+  0x2e, 0x73, 0x31, 0x20, 0x2b, 0x20, 0x74, 0x33, 0x2e, 0x73, 0x31, 0x20,
+  0x2b, 0x20, 0x74, 0x34, 0x2e, 0x73, 0x31, 0x20, 0x2b, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x2d, 0x3e, 0x78, 0x5b, 0x35,
+  0x5d, 0x20, 0x2a, 0x20, 0x62, 0x2d, 0x3e, 0x78, 0x5b, 0x30, 0x5d, 0x20,
+  0x2b, 0x20, 0x61, 0x2d, 0x3e, 0x78, 0x5b, 0x34, 0x5d, 0x20, 0x2a, 0x20,
+  0x62, 0x2d, 0x3e, 0x78, 0x5b, 0x31, 0x5d, 0x20, 0x2b, 0x20, 0x61, 0x2d,
+  0x3e, 0x78, 0x5b, 0x33, 0x5d, 0x20, 0x2a, 0x20, 0x62, 0x2d, 0x3e, 0x78,
+  0x5b, 0x32, 0x5d, 0x20, 0x2b, 0x20, 0x61, 0x2d, 0x3e, 0x78, 0x5b, 0x32,
+  0x5d, 0x20, 0x2a, 0x20, 0x62, 0x2d, 0x3e, 0x78, 0x5b, 0x33, 0x5d, 0x20,
+  0x2b, 0x20, 0x61, 0x2d, 0x3e, 0x78, 0x5b, 0x31, 0x5d, 0x20, 0x2a, 0x20,
+  0x62, 0x2d, 0x3e, 0x78, 0x5b, 0x34, 0x5d, 0x20, 0x2b, 0x20, 0x61, 0x2d,
+  0x3e, 0x78, 0x5b, 0x30, 0x5d, 0x20, 0x2a, 0x20, 0x62, 0x2d, 0x3e, 0x78,
+  0x5b, 0x35, 0x5d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f,
+  0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x72, 0x65, 0x30, 0x20, 0x3d, 0x20,
+  0x71, 0x75, 0x69, 0x63, 0x6b, 0x54, 0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28,
+  0x76, 0x31, 0x2c, 0x20, 0x74, 0x32, 0x4c, 0x33, 0x34, 0x2e, 0x73, 0x30,
+  0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c,
+  0x65, 0x32, 0x20, 0x72, 0x65, 0x31, 0x20, 0x3d, 0x20, 0x71, 0x75, 0x69,
+  0x63, 0x6b, 0x54, 0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x72, 0x65, 0x30,
+  0x2e, 0x73, 0x31, 0x2c, 0x20, 0x74, 0x33, 0x4c, 0x34, 0x35, 0x2e, 0x73,
+  0x30, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x32, 0x20, 0x72, 0x65, 0x32, 0x20, 0x3d, 0x20, 0x71, 0x75,
+  0x69, 0x63, 0x6b, 0x54, 0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x72, 0x65,
+  0x31, 0x2e, 0x73, 0x31, 0x2c, 0x20, 0x74, 0x34, 0x4c, 0x35, 0x36, 0x2e,
+  0x73, 0x30, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75,
+  0x62, 0x6c, 0x65, 0x32, 0x20, 0x72, 0x65, 0x33, 0x20, 0x3d, 0x20, 0x71,
+  0x75, 0x69, 0x63, 0x6b, 0x54, 0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x72,
+  0x65, 0x32, 0x2e, 0x73, 0x31, 0x2c, 0x20, 0x74, 0x35, 0x4c, 0x36, 0x37,
+  0x2e, 0x73, 0x30, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f,
+  0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x72, 0x65, 0x34, 0x35, 0x20, 0x3d,
+  0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x54, 0x77, 0x6f, 0x53, 0x75, 0x6d,
+  0x28, 0x72, 0x65, 0x33, 0x2e, 0x73, 0x31, 0x2c, 0x20, 0x76, 0x36, 0x29,
+  0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
+  0x20, 0x28, 0x48, 0x65, 0x78, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x29,
+  0x7b, 0x20, 0x72, 0x65, 0x30, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x72, 0x65,
+  0x31, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x72, 0x65, 0x32, 0x2e, 0x73, 0x30,
+  0x2c, 0x20, 0x72, 0x65, 0x33, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x72, 0x65,
+  0x34, 0x35, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x72, 0x65, 0x34, 0x35, 0x2e,
+  0x73, 0x31, 0x20, 0x7d, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x0a, 0x48, 0x65,
+  0x78, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x6c, 0x6f, 0x61, 0x64,
+  0x48, 0x64, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x5f, 0x5f, 0x67,
+  0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65,
+  0x2a, 0x20, 0x76, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72,
+  0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x48, 0x65, 0x78, 0x44, 0x6f,
+  0x75, 0x62, 0x6c, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x76, 0x5b, 0x30, 0x5d, 0x2c, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x5b, 0x31, 0x5d, 0x2c, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x5b, 0x32, 0x5d,
+  0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x5b,
+  0x33, 0x5d, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x76, 0x5b, 0x34, 0x5d, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x76, 0x5b, 0x35, 0x5d, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x7d, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x0a, 0x5f, 0x5f, 0x6b, 0x65, 0x72,
+  0x6e, 0x65, 0x6c, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x69, 0x74, 0x65,
+  0x72, 0x61, 0x74, 0x65, 0x28, 0x5f, 0x5f, 0x67, 0x6c, 0x6f, 0x62, 0x61,
+  0x6c, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x2a, 0x20, 0x41, 0x2c, 0x20,
+  0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x77, 0x69,
+  0x64, 0x74, 0x68, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x5f, 0x5f, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20,
+  0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x2a, 0x20, 0x78, 0x2c, 0x20, 0x5f,
+  0x5f, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x64, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x2a, 0x20, 0x79, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x5f, 0x67, 0x6c, 0x6f, 0x62, 0x61,
+  0x6c, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x2a, 0x20, 0x70, 0x77,
+  0x2c, 0x20, 0x5f, 0x5f, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x2a, 0x20, 0x70, 0x68, 0x2c, 0x20, 0x69,
+  0x6e, 0x74, 0x20, 0x6d, 0x61, 0x78, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20,
+  0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20,
+  0x6a, 0x75, 0x6c, 0x69, 0x61, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x5f, 0x67, 0x6c, 0x6f, 0x62, 0x61,
+  0x6c, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x2a, 0x20, 0x6a, 0x78,
+  0x2c, 0x20, 0x5f, 0x5f, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x2a, 0x20, 0x6a, 0x79, 0x29, 0x20, 0x7b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x64,
+  0x65, 0x78, 0x20, 0x3d, 0x20, 0x67, 0x65, 0x74, 0x5f, 0x67, 0x6c, 0x6f,
+  0x62, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x28, 0x30, 0x29, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x70, 0x78, 0x20, 0x3d, 0x20,
+  0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x25, 0x20, 0x77, 0x69, 0x64, 0x74,
+  0x68, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x70,
+  0x79, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x2f, 0x20,
+  0x77, 0x69, 0x64, 0x74, 0x68, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x48, 0x65, 0x78, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x78, 0x6c,
+  0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x64, 0x28, 0x78, 0x29,
+  0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x48, 0x65, 0x78, 0x44, 0x6f, 0x75,
+  0x62, 0x6c, 0x65, 0x20, 0x79, 0x74, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x61,
+  0x64, 0x48, 0x64, 0x28, 0x79, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x48, 0x65, 0x78, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x70, 0x69,
+  0x78, 0x65, 0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x58, 0x20, 0x3d, 0x20,
+  0x6c, 0x6f, 0x61, 0x64, 0x48, 0x64, 0x28, 0x70, 0x77, 0x29, 0x3b, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x48, 0x65, 0x78, 0x44, 0x6f, 0x75, 0x62, 0x6c,
+  0x65, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65,
+  0x59, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x64, 0x28, 0x70,
+  0x68, 0x29, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x48, 0x65, 0x78,
+  0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x70, 0x78, 0x68, 0x20, 0x3d,
+  0x20, 0x7b, 0x20, 0x70, 0x78, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c,
+  0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x3b, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x48, 0x65, 0x78, 0x44, 0x6f, 0x75, 0x62, 0x6c,
+  0x65, 0x20, 0x70, 0x79, 0x68, 0x20, 0x3d, 0x20, 0x7b, 0x20, 0x70, 0x79,
+  0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30,
+  0x2c, 0x20, 0x30, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x48, 0x65, 0x78, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x63, 0x61,
+  0x4f, 0x66, 0x66, 0x20, 0x3d, 0x20, 0x6d, 0x75, 0x6c, 0x28, 0x26, 0x70,
+  0x69, 0x78, 0x65, 0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x58, 0x2c, 0x20,
+  0x26, 0x70, 0x78, 0x68, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x48,
+  0x65, 0x78, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x63, 0x62, 0x4f,
+  0x66, 0x66, 0x20, 0x3d, 0x20, 0x6d, 0x75, 0x6c, 0x28, 0x26, 0x70, 0x69,
+  0x78, 0x65, 0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x59, 0x2c, 0x20, 0x26,
+  0x70, 0x79, 0x68, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x48, 0x65,
+  0x78, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x63, 0x61, 0x20, 0x3d,
+  0x20, 0x61, 0x64, 0x64, 0x28, 0x26, 0x63, 0x61, 0x4f, 0x66, 0x66, 0x2c,
+  0x20, 0x26, 0x78, 0x6c, 0x29, 0x3b, 0x20, 0x2f, 0x2f, 0x20, 0x70, 0x69,
+  0x78, 0x65, 0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x58, 0x20, 0x2a, 0x20,
+  0x70, 0x78, 0x20, 0x2b, 0x20, 0x78, 0x6c, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x48, 0x65, 0x78, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x63, 0x62,
+  0x20, 0x3d, 0x20, 0x61, 0x64, 0x64, 0x28, 0x26, 0x63, 0x62, 0x4f, 0x66,
+  0x66, 0x2c, 0x20, 0x26, 0x79, 0x74, 0x29, 0x3b, 0x20, 0x2f, 0x2f, 0x20,
+  0x70, 0x69, 0x78, 0x65, 0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x59, 0x20,
+  0x2a, 0x20, 0x70, 0x79, 0x20, 0x2b, 0x20, 0x79, 0x74, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x48, 0x65, 0x78, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20,
+  0x61, 0x20, 0x3d, 0x20, 0x63, 0x61, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x48, 0x65, 0x78, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x62, 0x20,
+  0x3d, 0x20, 0x63, 0x62, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66,
+  0x20, 0x28, 0x6a, 0x75, 0x6c, 0x69, 0x61, 0x20, 0x21, 0x3d, 0x20, 0x30,
+  0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x63, 0x61, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x64, 0x28,
+  0x6a, 0x78, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x63, 0x62, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x64,
+  0x28, 0x6a, 0x79, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x6e, 0x20, 0x3d,
+  0x20, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x77, 0x68, 0x69, 0x6c,
+  0x65, 0x20, 0x28, 0x6e, 0x20, 0x3c, 0x20, 0x6d, 0x61, 0x78, 0x20, 0x2d,
+  0x20, 0x31, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x48, 0x65, 0x78, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20,
+  0x61, 0x61, 0x20, 0x3d, 0x20, 0x6d, 0x75, 0x6c, 0x28, 0x26, 0x61, 0x2c,
+  0x20, 0x26, 0x61, 0x29, 0x3b, 0x20, 0x2f, 0x2a, 0x20, 0x54, 0x4f, 0x44,
+  0x4f, 0x20, 0x61, 0x64, 0x64, 0x20, 0x73, 0x71, 0x75, 0x61, 0x72, 0x69,
+  0x6e, 0x67, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20,
+  0x2a, 0x2f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x48,
+  0x65, 0x78, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x62, 0x62, 0x20,
+  0x3d, 0x20, 0x6d, 0x75, 0x6c, 0x28, 0x26, 0x62, 0x2c, 0x20, 0x26, 0x62,
+  0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x48,
+  0x65, 0x78, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x61, 0x62, 0x20,
+  0x3d, 0x20, 0x6d, 0x75, 0x6c, 0x28, 0x26, 0x61, 0x2c, 0x20, 0x26, 0x62,
+  0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x48,
+  0x65, 0x78, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x6d, 0x69, 0x6e,
+  0x75, 0x73, 0x62, 0x62, 0x20, 0x3d, 0x20, 0x7b, 0x20, 0x2d, 0x62, 0x62,
+  0x2e, 0x78, 0x5b, 0x30, 0x5d, 0x2c, 0x20, 0x2d, 0x62, 0x62, 0x2e, 0x78,
+  0x5b, 0x31, 0x5d, 0x2c, 0x20, 0x2d, 0x62, 0x62, 0x2e, 0x78, 0x5b, 0x32,
+  0x5d, 0x2c, 0x20, 0x2d, 0x62, 0x62, 0x2e, 0x78, 0x5b, 0x33, 0x5d, 0x2c,
+  0x20, 0x2d, 0x62, 0x62, 0x2e, 0x78, 0x5b, 0x34, 0x5d, 0x2c, 0x20, 0x2d,
+  0x62, 0x62, 0x2e, 0x78, 0x5b, 0x35, 0x5d, 0x20, 0x7d, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x48, 0x65, 0x78, 0x44, 0x6f,
+  0x75, 0x62, 0x6c, 0x65, 0x20, 0x61, 0x61, 0x6d, 0x62, 0x62, 0x20, 0x3d,
+  0x20, 0x61, 0x64, 0x64, 0x28, 0x26, 0x61, 0x61, 0x2c, 0x20, 0x26, 0x6d,
+  0x69, 0x6e, 0x75, 0x73, 0x62, 0x62, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x48, 0x65, 0x78, 0x44, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x20, 0x61, 0x62, 0x61, 0x62, 0x20, 0x3d, 0x20, 0x61, 0x64,
+  0x64, 0x28, 0x26, 0x61, 0x62, 0x2c, 0x20, 0x26, 0x61, 0x62, 0x29, 0x3b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x20, 0x3d,
+  0x20, 0x61, 0x64, 0x64, 0x28, 0x26, 0x61, 0x61, 0x6d, 0x62, 0x62, 0x2c,
+  0x20, 0x26, 0x63, 0x61, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x62, 0x20, 0x3d, 0x20, 0x61, 0x64, 0x64, 0x28, 0x26,
+  0x61, 0x62, 0x61, 0x62, 0x2c, 0x20, 0x26, 0x63, 0x62, 0x29, 0x3b, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28,
+  0x61, 0x61, 0x2e, 0x78, 0x5b, 0x30, 0x5d, 0x20, 0x2b, 0x20, 0x62, 0x62,
+  0x2e, 0x78, 0x5b, 0x30, 0x5d, 0x20, 0x3e, 0x20, 0x31, 0x36, 0x29, 0x20,
+  0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x6e, 0x2b, 0x2b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x4e, 0x20,
+  0x2b, 0x20, 0x31, 0x20, 0x2d, 0x20, 0x6c, 0x6f, 0x67, 0x20, 0x28, 0x6c,
+  0x6f, 0x67, 0x20, 0x20, 0x7c, 0x5a, 0x28, 0x4e, 0x29, 0x7c, 0x29, 0x20,
+  0x2f, 0x20, 0x6c, 0x6f, 0x67, 0x20, 0x32, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x69, 0x66, 0x20, 0x28, 0x6e, 0x20, 0x3e, 0x3d, 0x20, 0x6d, 0x61, 0x78,
+  0x20, 0x2d, 0x20, 0x31, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x41, 0x5b, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x20, 0x3d,
+  0x20, 0x6d, 0x61, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c,
+  0x73, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x69, 0x66, 0x20, 0x28, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x20,
+  0x21, 0x3d, 0x20, 0x30, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x5b, 0x69, 0x6e, 0x64, 0x65,
+  0x78, 0x5d, 0x20, 0x3d, 0x20, 0x28, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74,
+  0x29, 0x20, 0x6e, 0x29, 0x20, 0x2b, 0x20, 0x31, 0x20, 0x2d, 0x20, 0x6c,
+  0x6f, 0x67, 0x32, 0x28, 0x6c, 0x6f, 0x67, 0x28, 0x61, 0x2e, 0x78, 0x5b,
+  0x30, 0x5d, 0x20, 0x2a, 0x20, 0x61, 0x2e, 0x78, 0x5b, 0x30, 0x5d, 0x20,
+  0x2b, 0x20, 0x62, 0x2e, 0x78, 0x5b, 0x30, 0x5d, 0x20, 0x2a, 0x20, 0x62,
+  0x2e, 0x78, 0x5b, 0x30, 0x5d, 0x29, 0x20, 0x2a, 0x20, 0x30, 0x2e, 0x35,
+  0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65,
+  0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x41, 0x5b, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d,
+  0x20, 0x3d, 0x20, 0x28, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x29, 0x6e,
+  0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20,
+  0x20, 0x2f, 0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x5b, 0x69, 0x6e, 0x64, 0x65,
+  0x78, 0x5d, 0x20, 0x3d, 0x20, 0x28, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74,
+  0x29, 0x6e, 0x29, 0x20, 0x2b, 0x20, 0x31, 0x20, 0x2d, 0x20, 0x28, 0x61,
+  0x20, 0x2a, 0x20, 0x61, 0x20, 0x2b, 0x20, 0x62, 0x20, 0x2a, 0x20, 0x62,
+  0x20, 0x2d, 0x20, 0x31, 0x36, 0x29, 0x20, 0x2f, 0x20, 0x28, 0x32, 0x35,
+  0x36, 0x20, 0x2d, 0x20, 0x31, 0x36, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20,
+  0x20, 0x2f, 0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x41, 0x5b, 0x67, 0x65, 0x74, 0x5f, 0x67, 0x6c, 0x6f, 0x62,
+  0x61, 0x6c, 0x5f, 0x69, 0x64, 0x28, 0x30, 0x29, 0x5d, 0x20, 0x3d, 0x20,
+  0x35, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a
+};
+unsigned int hexdouble_cl_len = 6966;

+ 12 - 2
libmandel/tests/accurate.cpp

@@ -1,10 +1,11 @@
 #include "../include/TripleDouble.h"
 #include "../include/Types.h"
+#include "../include/HexDouble.h"
 
 #include <vector>
 #include <boost/random.hpp>
 
-const int nTests = 1000;
+const int nTests = 10000;
 
 using namespace boost::multiprecision;
 using namespace boost::random;
@@ -12,7 +13,7 @@ using namespace boost::random;
 std::vector<mnd::Real> generateRandom(int len, int seed)
 {
     uniform_real_distribution<mnd::Real> dist(0, 1);
-    uniform_int_distribution<int> expDist(-30, 30);
+    uniform_int_distribution<int> expDist(-120, 120);
     independent_bits_engine<mt19937, std::numeric_limits<cpp_bin_float_50>::digits, cpp_int> gen(seed);
 
     std::vector<mnd::Real> numbers;
@@ -59,10 +60,19 @@ int main()
 
     mnd::Real tripleDoubleAdd = maxErr<mnd::TripleDouble>([] (const auto& a, const auto& b) { return a + b; });
     mnd::Real tripleDoubleMul = maxErr<mnd::TripleDouble>([] (const auto& a, const auto& b) { return a * b; });
+    mnd::Real tripleDoubleAABBA = maxErr<mnd::TripleDouble>([] (const auto& a, const auto& b) { return a * a - b * b + a; });
     std::cout << std::setprecision(10) << std::scientific;
     std::cout << "max triple double add error: " << tripleDoubleAdd << std::endl;
     std::cout << "max triple double mul error: " << tripleDoubleMul << std::endl;
+    std::cout << "max triple double aa - bb + a error: " << tripleDoubleAABBA << std::endl;
 
+    mnd::Real hexDoubleAdd = maxErr<mnd::HexDouble>([] (const auto& a, const auto& b) { return a + b; });
+    mnd::Real hexDoubleMul = maxErr<mnd::HexDouble>([] (const auto& a, const auto& b) { return a * b; });
+    mnd::Real hexDoubleAABBA = maxErr<mnd::HexDouble>([] (const auto& a, const auto& b) { return a * a - b * b + a; });
+    std::cout << std::setprecision(10) << std::scientific;
+    std::cout << "max hex double add error: " << hexDoubleAdd << std::endl;
+    std::cout << "max hex double mul error: " << hexDoubleMul << std::endl;
+    std::cout << "max hex double aa - bb + a error: " << hexDoubleAABBA << std::endl;
 
 }