ソースを参照

adding octadoubles cl

Nicolas Winkler 4 年 前
コミット
555845e50b

+ 1 - 0
libmandel/CMakeLists.txt

@@ -38,6 +38,7 @@ SET(MandelSources
     src/Hardware.cpp
     src/MandelUtil.cpp
     src/Types.cpp
+    src/Real.cpp
     src/OpenClCode.cpp
     src/IterationGenerator.cpp
     src/IterationFormula.cpp

+ 13 - 1
libmandel/include/ClGenerators.h

@@ -39,6 +39,7 @@ namespace mnd
     class ClGeneratorTripleDouble;
     class ClGeneratorQuadDouble;
     class ClGeneratorHexDouble;
+    class ClGeneratorOctaDouble;
     class ClGenerator128;
     class ClGenerator64;
 }
@@ -151,7 +152,6 @@ protected:
 
 class mnd::ClGeneratorHexDouble : public ClGenerator
 {
-    bool smooth;
 public:
     ClGeneratorHexDouble(mnd::MandelDevice& device);
     virtual ~ClGeneratorHexDouble(void) = default;
@@ -162,6 +162,18 @@ protected:
 };
 
 
+class mnd::ClGeneratorOctaDouble : public ClGenerator
+{
+public:
+    ClGeneratorOctaDouble(mnd::MandelDevice& device);
+    virtual ~ClGeneratorOctaDouble(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:

+ 1 - 0
libmandel/include/CpuGenerators.h

@@ -2,6 +2,7 @@
 #define MANDEL_CPUGENERATORS_H
 
 #include "Generators.h"
+#include "Types.h"
 
 namespace mnd
 {

+ 2 - 62
libmandel/include/Generators.h

@@ -7,15 +7,12 @@
 #include <map>
 #include <utility>
 
-
-
 namespace mnd
 {
     class MandelGenerator;
 
     class AdaptiveGenerator;
 
-    enum class GeneratorType : int;
     enum class Precision : int
     {
         FLOAT,
@@ -26,6 +23,7 @@ namespace mnd
         TRIPLE_DOUBLE,
         QUAD_DOUBLE,
         HEX_DOUBLE,
+        OCTA_DOUBLE,
         FLOAT128,
         FLOAT256,
         FLOAT512,
@@ -50,74 +48,16 @@ namespace mnd
     std::string toString(CpuExtension);
 
     Real getPrecision(Precision p);
-    
+
     template<typename T>
     Real getPrecision(void);
 
-    template<> Real getPrecision<float>();
-    template<> Real getPrecision<double>();
-    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>();
-    template<> Real getPrecision<Float128>();
-    template<> Real getPrecision<Float256>();
-    template<> Real getPrecision<Float512>();
-
     template<typename T>
     Precision getType(void);
-    template<> inline Precision getType<float>() { return Precision::FLOAT; }
-    template<> inline Precision getType<double>() { return Precision::DOUBLE; }
-    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; }
-    template<> inline Precision getType<Float128>() { return Precision::FLOAT128; }
-    template<> inline Precision getType<Float256>() { return Precision::FLOAT256; }
-    template<> inline Precision getType<Float512>() { return Precision::FLOAT512; }
 
     class MandelDevice;
 }
 
-/*
-enum class mnd::GeneratorType : int
-{
-    UNSPECIFIED,
-    FLOAT,
-    FLOAT_SSE2,
-    FLOAT_AVX,
-    FLOAT_AVX_FMA,
-    FLOAT_AVX512,
-    FLOAT_NEON,
-    DOUBLE_FLOAT,
-    DOUBLE,
-    DOUBLE_SSE2,
-    DOUBLE_AVX,
-    DOUBLE_AVX_FMA,
-    DOUBLE_AVX512,
-    DOUBLE_NEON,
-    DOUBLE_DOUBLE,
-    DOUBLE_DOUBLE_AVX,
-    DOUBLE_DOUBLE_AVX_FMA,
-    DOUBLE_DOUBLE_NEON,
-    TRIPLE_DOUBLE,
-    TRIPLE_DOUBLE_AVX,
-    QUAD_DOUBLE,
-    QUAD_DOUBLE_AVX_FMA,
-    FLOAT128,
-    FLOAT256,
-    FIXED64,
-    FIXED128,
-    FIXED512
-};
-*/
-
 
 class mnd::MandelGenerator
 {

+ 1 - 1
libmandel/include/IterationFormula.h

@@ -7,7 +7,7 @@
 #include <stdexcept>
 #include <optional>
 
-#include "Types.h"
+#include "Real.h"
 
 namespace mnd
 {

+ 1 - 1
libmandel/include/IterationIR.h

@@ -7,7 +7,7 @@
 #include <any>
 
 #include "IterationFormula.h"
-#include "Types.h"
+#include "Real.h"
 #include "Arena.h"
 
 namespace mnd

+ 1 - 1
libmandel/include/MandelUtil.h

@@ -1,7 +1,7 @@
 #ifndef MANDEL_MANDELUTIL_H
 #define MANDEL_MANDELUTIL_H
 
-#include "Types.h"
+#include "Real.h"
 
 namespace mnd 
 {

+ 2 - 2
libmandel/include/NaiveIRGenerator.h

@@ -124,7 +124,7 @@ public:
 
 extern template class mnd::NaiveIRGenerator<float>;
 extern template class mnd::NaiveIRGenerator<double>;
-extern template class mnd::NaiveIRGenerator<mnd::DoubleDouble>;
-extern template class mnd::NaiveIRGenerator<mnd::QuadDouble>;
+//extern template class mnd::NaiveIRGenerator<mnd::DoubleDouble>;
+//extern template class mnd::NaiveIRGenerator<mnd::QuadDouble>;
 
 #endif // MANDEL_NAIVEIRGENERATOR_H

+ 1 - 0
libmandel/include/OpenClCode.h

@@ -13,6 +13,7 @@ namespace mnd
     std::string getTripleFloat_cl();
     std::string getQuadDouble_cl();
     std::string getHexDouble_cl();
+    std::string getOctaDouble_cl();
     std::string getFixed64_cl();
     std::string getFixed128_cl();
     std::string getFixed512_cl();

+ 37 - 38
libmandel/include/Types.h

@@ -1,6 +1,8 @@
 #ifndef MANDEL_TYPES_H
 #define MANDEL_TYPES_H
 
+#include "Real.h"
+
 #include <cinttypes>
 #include <cmath>
 #include <string>
@@ -26,6 +28,7 @@
 #include "TripleDouble.h"
 #include "TripleFloat.h"
 #include "HexDouble.h"
+#include "OctaDouble.h"
 
 namespace mnd
 {
@@ -68,46 +71,8 @@ namespace mnd
     inline Float256 sin(const Float256& x) { return boost::multiprecision::sin(x); }
     inline Float256 exp(const Float256& x) { return boost::multiprecision::exp(x); }
 
-    using Float512 = boost::multiprecision::number<
-        boost::multiprecision::backends::cpp_bin_float<
-            496, boost::multiprecision::backends::digit_base_2, void, boost::int16_t, -16382, 16383>,
-            boost::multiprecision::et_off>;
-
-    inline Float512 abs(const Float512& x) { return boost::multiprecision::abs(x); }
-    inline Float512 sqrt(const Float512& x) { return boost::multiprecision::sqrt(x); }
-    inline Float512 floor(const Float512& x) { return boost::multiprecision::floor(x); }
-    inline Float512 log(const Float512& x) { return boost::multiprecision::log(x); }
-    inline Float512 log2(const Float512& x) { return boost::multiprecision::log2(x); }
-    inline Float512 pow(const Float512& x, const Float512& y) { return boost::multiprecision::pow(x, y); }
-    inline Float512 atan2(const Float512& y, const Float512& x) { return boost::multiprecision::atan2(y, x); }
-    inline Float512 cos(const Float512& x) { return boost::multiprecision::cos(x); }
-    inline Float512 sin(const Float512& x) { return boost::multiprecision::sin(x); }
-    inline Float512 exp(const Float512& x) { return boost::multiprecision::exp(x); }
-
-    using Real = Float512;
-    using Integer = boost::multiprecision::int512_t;
-    /*boost::multiprecision::number<
-        boost::multiprecision::backends::cpp_bin_float<
-            1500, boost::multiprecision::backends::digit_base_2, void, boost::int16_t, -16382, 16383>,
-            boost::multiprecision::et_off>;
-
-    inline Real abs(const Real& x) { return boost::multiprecision::abs(x); }
-    inline Real sqrt(const Real& x) { return boost::multiprecision::sqrt(x); }
-    inline Real floor(const Real& x) { return boost::multiprecision::floor(x); }
-    inline Real log(const Real& x) { return boost::multiprecision::log(x); }
-    inline Real log2(const Real& x) { return boost::multiprecision::log2(x); }
-    inline Real pow(const Real& x, const Real& y) { return boost::multiprecision::pow(x, y); }
-    inline Real atan2(const Real& y, const Real& x) { return boost::multiprecision::atan2(y, x); }
-    inline Real cos(const Real& x) { return boost::multiprecision::cos(x); }
-    inline Real sin(const Real& x) { return boost::multiprecision::sin(x); }
-    inline Real exp(const Real& x) { return boost::multiprecision::exp(x); }
-*/
-#else
-    using Real = double;
-    using Integer = int64_t;
 #endif
 
-
     using DoubleDouble = dd_real;
     using QuadDouble = qd_real;
 
@@ -286,6 +251,39 @@ namespace mnd
     }
 
     template<>
+    inline Real convert<Real, OctaDouble>(const OctaDouble& x)
+    {
+        return Real{ x[0] } + x[1] + x[2] + x[3] + x[4] + x[5] + x[6] + x[7];
+    }
+
+    template<>
+    inline OctaDouble convert<OctaDouble, 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);
+        tmp = tmp - e5;
+        double e6 = static_cast<double>(tmp);
+        tmp = tmp - e6;
+        double e7 = static_cast<double>(tmp);
+        return OctaDouble{ s, e1, e2, e3, e4, e5, e6, e7 };
+    }
+
+    template<>
+    inline float convert<float, OctaDouble>(const OctaDouble& x)
+    {
+        return float(x.x[0] + x.x[1]);
+    }
+
+    template<>
     inline float convert<float, Fixed512>(const Fixed512& x)
     {
         return float(Real(x));
@@ -319,3 +317,4 @@ namespace mnd
 
 
 #endif // MANDEL_TYPES_H
+

+ 55 - 1
libmandel/src/ClGenerators.cpp

@@ -1,4 +1,5 @@
 #include "ClGenerators.h"
+#include "Types.h"
 #include "Mandel.h"
 #include "OpenClInternal.h"
 #include "OpenClCode.h"
@@ -23,6 +24,7 @@ using mnd::ClGeneratorDoubleDouble;
 using mnd::ClGeneratorTripleDouble;
 using mnd::ClGeneratorQuadDouble;
 using mnd::ClGeneratorHexDouble;
+using mnd::ClGeneratorOctaDouble;
 using mnd::ClGenerator128;
 using mnd::ClGenerator64;
 
@@ -559,7 +561,6 @@ void ClGeneratorHexDouble::generate(const mnd::MandelInfo& info, float* data)
     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);
@@ -592,6 +593,59 @@ std::string ClGeneratorHexDouble::getKernelCode(bool smooth) const
 }
 
 
+ClGeneratorOctaDouble::ClGeneratorOctaDouble(mnd::MandelDevice& device) :
+    ClGenerator{ device, getOctaDouble_cl(), mnd::Precision::OCTA_DOUBLE }
+{
+    kernel = Kernel(program, "iterate");
+}
+
+
+void ClGeneratorOctaDouble::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::OctaDouble x = mnd::convert<mnd::OctaDouble>(info.view.x);
+    mnd::OctaDouble y = mnd::convert<mnd::OctaDouble>(info.view.y);
+
+    mnd::OctaDouble psx = mnd::convert<mnd::OctaDouble>(info.view.width / info.bWidth);
+    mnd::OctaDouble psy = mnd::convert<mnd::OctaDouble>(info.view.height / info.bHeight);
+
+    mnd::OctaDouble jx = mnd::convert<mnd::OctaDouble>(info.juliaX);
+    mnd::OctaDouble jy = mnd::convert<mnd::OctaDouble>(info.juliaY);
+
+    const size_t argBufSize = 8 * 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 ClGeneratorOctaDouble::getKernelCode(bool smooth) const
+{
+    return getOctaDouble_cl();
+}
+
 ClGenerator128::ClGenerator128(mnd::MandelDevice& device) :
     ClGenerator{ device, getFixed512_cl(), mnd::Precision::FIXED128 }
 {

+ 6 - 0
libmandel/src/CpuGenerators.cpp

@@ -40,6 +40,9 @@ namespace mnd
     template class CpuGenerator<mnd::Float256, mnd::NONE, false>;
     template class CpuGenerator<mnd::Float256, mnd::NONE, true>;
 
+    template class CpuGenerator<mnd::Float512, mnd::NONE, false>;
+    template class CpuGenerator<mnd::Float512, mnd::NONE, true>;
+
     template class CpuGenerator<Fixed512, mnd::NONE, false>;
     template class CpuGenerator<Fixed512, mnd::NONE, true>;
 #endif
@@ -56,6 +59,9 @@ namespace mnd
 
     template class CpuGenerator<mnd::HexDouble, mnd::NONE, false>;
     template class CpuGenerator<mnd::HexDouble, mnd::NONE, true>;
+
+    template class CpuGenerator<mnd::OctaDouble, mnd::NONE, false>;
+    template class CpuGenerator<mnd::OctaDouble, mnd::NONE, true>;
 #endif
 }
 

+ 46 - 3
libmandel/src/Generators.cpp

@@ -1,17 +1,53 @@
 #include "Generators.h"
 
+#include "Types.h"
+
 #include <cstdio>
 
 using mnd::MandelGenerator;
 using mnd::AdaptiveGenerator;
 
 
-MandelGenerator::~MandelGenerator(void)
+namespace mnd
 {
+    template<> Real getPrecision<float>();
+    template<> Real getPrecision<double>();
+    template<> Real getPrecision<DoubleDouble>();
+    template<> Real getPrecision<TripleDouble>();
+    template<> Real getPrecision<QuadDouble>();
+    template<> Real getPrecision<HexDouble>();
+    template<> Real getPrecision<OctaDouble>();
+    template<> Real getPrecision<Fixed64>();
+    template<> Real getPrecision<Fixed128>();
+    template<> Real getPrecision<Fixed512>();
+    template<> Real getPrecision<Float128>();
+    template<> Real getPrecision<Float256>();
+    template<> Real getPrecision<Float512>();
+
+    template<typename T>
+    Precision getType(void);
+    template<> Precision getType<float>() { return Precision::FLOAT; }
+    template<> Precision getType<double>() { return Precision::DOUBLE; }
+    template<> Precision getType<DoubleDouble>() { return Precision::DOUBLE_DOUBLE; }
+    template<> Precision getType<TripleDouble>() { return Precision::TRIPLE_DOUBLE; }
+    template<> Precision getType<QuadDouble>() { return Precision::QUAD_DOUBLE; }
+    template<> Precision getType<HexDouble>() { return Precision::HEX_DOUBLE; }
+    template<> Precision getType<OctaDouble>() { return Precision::OCTA_DOUBLE; }
+    template<> Precision getType<Fixed64>() { return Precision::FIXED64; }
+    template<> Precision getType<Fixed128>() { return Precision::FIXED128; }
+    template<> Precision getType<Fixed512>() { return Precision::FIXED512; }
+    template<> Precision getType<Float128>() { return Precision::FLOAT128; }
+    template<> Precision getType<Float256>() { return Precision::FLOAT256; }
+    template<> Precision getType<Float512>() { return Precision::FLOAT512; }
 }
 
 
 
+MandelGenerator::~MandelGenerator(void)
+{
+}
+
+
 mnd::MandelDevice* MandelGenerator::getDevice(void)
 {
     return nullptr;
@@ -138,10 +174,12 @@ namespace mnd
             return "quad-double";
         case Precision::HEX_DOUBLE:
             return "hex-double";
+        case Precision::OCTA_DOUBLE:
+            return "octa-double";
         case Precision::FLOAT128:
-            return "IEEE 754 128-bit float";
+            return "float128";
         case Precision::FLOAT256:
-            return "IEEE 754 256-bit float";
+            return "float256";
         case Precision::FLOAT512:
             return "float512";
         case Precision::FIXED64:
@@ -188,6 +226,7 @@ namespace mnd
             { Precision::TRIPLE_DOUBLE, Real("1.0e-47") },
             { Precision::QUAD_DOUBLE, Real("1.0e-56") },
             { Precision::HEX_DOUBLE, Real("1.0e-94") },
+            { Precision::OCTA_DOUBLE, Real("1.0e-126") },
             { Precision::FIXED64, Real("3.5e-15") },
             { Precision::FIXED128, Real("1.317e-29") },
             { Precision::FIXED512, Real("1.5e-130") },
@@ -225,6 +264,10 @@ namespace mnd
         return Real("3.0e-94");
     }
     template<>
+    Real getPrecision<OctaDouble>() {
+        return Real("1.0e-126");
+    }
+    template<>
     Real getPrecision<Fixed64>() {
         return Real("3.5e-15");
     }

+ 7 - 1
libmandel/src/Mandel.cpp

@@ -127,18 +127,22 @@ MandelContext::MandelContext(void)
 #ifdef WITH_BOOST
     auto quad = std::make_unique<CpuGenerator<Float128, mnd::NONE, true>>();
     auto oct = std::make_unique<CpuGenerator<Float256, mnd::NONE, true>>();
+    auto f512 = std::make_unique<CpuGenerator<Float512, mnd::NONE, true>>();
     cpuGenerators.insert({ std::pair{ Precision::FLOAT128, CpuExtension::NONE }, std::move(quad) });
     cpuGenerators.insert({ std::pair{ Precision::FLOAT256, CpuExtension::NONE }, std::move(oct) });
+    cpuGenerators.insert({ std::pair{ Precision::FLOAT512, CpuExtension::NONE }, std::move(f512) });
 #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>>();
+    auto od = std::make_unique<CpuGenerator<OctaDouble, mnd::NONE, true>>();
     cpuGenerators.insert({ std::pair{ Precision::DOUBLE_DOUBLE, CpuExtension::NONE }, std::move(dd) });
     cpuGenerators.insert({ std::pair{ Precision::TRIPLE_DOUBLE, CpuExtension::NONE }, std::move(td) });
     cpuGenerators.insert({ std::pair{ Precision::QUAD_DOUBLE, CpuExtension::NONE }, std::move(qd) });
     cpuGenerators.insert({ std::pair{ Precision::HEX_DOUBLE, CpuExtension::NONE }, std::move(hd) });
+    cpuGenerators.insert({ std::pair{ Precision::OCTA_DOUBLE, CpuExtension::NONE }, std::move(od) });
 
 
     auto fix512 = std::make_unique<CpuGenerator<Fixed512, mnd::NONE, true>>();
@@ -161,7 +165,8 @@ std::unique_ptr<mnd::AdaptiveGenerator> MandelContext::createAdaptiveGenerator(v
         Precision::TRIPLE_DOUBLE,
         Precision::QUAD_DOUBLE,
         Precision::HEX_DOUBLE,
-        Precision::FIXED512
+        Precision::OCTA_DOUBLE,
+        Precision::FLOAT512
     };
 
     auto ag = std::make_unique<AdaptiveGenerator>();
@@ -262,6 +267,7 @@ std::vector<std::unique_ptr<MandelDevice>> MandelContext::createDevices(void)
                     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) });
+                    md.mandelGenerators.insert({ Precision::OCTA_DOUBLE, std::make_unique<ClGeneratorOctaDouble>(md) });
                 }
                 catch (const std::string& err) {
                     printf("err: %s", err.c_str());

+ 1 - 0
libmandel/src/NaiveIRGenerator.cpp

@@ -1,6 +1,7 @@
 #include "NaiveIRGenerator.h"
 #include <omp.h>
 
+#include "Types.h"
 
 using mnd::NaiveIRGenerator;
 

+ 5 - 0
libmandel/src/OpenClCode.cpp

@@ -8,6 +8,7 @@
 #include "opencl/triplefloat.h"
 #include "opencl/quaddouble.h"
 #include "opencl/hexdouble.h"
+#include "opencl/octadouble.h"
 
 #include "opencl/fixed64.h"
 #include "opencl/fixed128.h"
@@ -47,6 +48,10 @@ namespace mnd
         return std::string{ (char*) hexdouble_cl, hexdouble_cl_len };
     }
 
+    std::string getOctaDouble_cl() {
+        return std::string{ (char*) octadouble_cl, octadouble_cl_len };
+    }
+
     std::string getFixed64_cl() {
         return std::string{ (char*) fixed64_cl, fixed64_cl_len };
     }

+ 0 - 76
libmandel/src/Types.cpp

@@ -2,79 +2,3 @@
 #include <sstream>
 
 
-namespace mnd
-{
-#ifdef WITH_BOOST
-    std::string toString(const Real& num)
-    {
-        return num.str();
-    }
-
-    std::string toLegibleString(const Real& num)
-    {
-        if (num == Real(0.0)) {
-            return "0";
-        }
-        int exponent = int(std::floor(static_cast<float>(mnd::log(num)) / ::logf(10.000001f)));
-        float fac = static_cast<float>(num / mnd::pow(Real(10), Real(exponent)));
-        std::stringstream ss;
-        ss.precision(3);
-        ss << std::fixed << fac << "e";
-        if (exponent < 0)
-            ss << "-" << -exponent;
-        else
-            ss << "+" << exponent;
-        return ss.str();
-    }
-#else // !WITH_BOOST
-    std::string toString(const Real& num)
-    {
-        std::stringstream ss;
-        ss << num;
-        return ss.str();
-    }
-#endif // WITH_BOOST
-
-
-/*
-    template<>
-    constexpr Real precision<float>(void)
-    {
-        return 1.0e-7;
-    }
-
-    template<>
-    constexpr Real precision<double>(void)
-    {
-        return 1.0e-15;
-    }
-
-#ifdef WITH_QD
-    template<>
-    constexpr Real precision<DoubleDouble>(void)
-    {
-        return Real("1.0e-29");
-    }
-
-    template<>
-    constexpr Real precision<QuadDouble>(void)
-    {
-        return Real("1.0e-57");
-    }
-#endif // WITH_QD
-#ifdef WITH_BOOST
-    template<>
-    constexpr Real precision<Float128>(void)
-    {
-        return Real("1.0e-29");
-    }
-
-    template<>
-    constexpr Real precision<Float256>(void)
-    {
-        return Real("1.0e-60");
-    }
-#endif // WITH_BOOST
-*/
-}
-

+ 18 - 5
libmandel/src/opencl/hexdouble.cl

@@ -158,6 +158,19 @@ inline HexDouble mul(const __private HexDouble* a, const __private HexDouble* b)
 }
 
 
+inline HexDouble twice(const __private HexDouble* a)
+{
+    return (HexDouble) {
+        a->x[0] * 2,
+        a->x[1] * 2,
+        a->x[2] * 2,
+        a->x[3] * 2,
+        a->x[4] * 2,
+        a->x[5] * 2,
+    };
+}
+
+
 HexDouble loadHd(const __constant double* v) {
     return (HexDouble) {
         v[0],
@@ -172,7 +185,7 @@ HexDouble loadHd(const __constant double* v) {
 
 __kernel void iterate(__global float* A, const int width,
                       __constant double* x, __constant double* y,
-                      __constant double* pw, __constant double* ph, int max, int smooth, int julia,
+                      __constant double* pw, __constant double* ph, int maxIter, int smooth, int julia,
                       __constant double* jx, __constant double* jy) {
     int index = get_global_id(0);
     int px = index % width;
@@ -198,13 +211,13 @@ __kernel void iterate(__global float* A, const int width,
     }
 
     int n = 0;
-    while (n < max - 1) {
+    while (n < maxIter - 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);
+        HexDouble abab = twice(&ab);
         a = add(&aambb, &ca);
         b = add(&abab, &cb);
         if (aa.x[0] + bb.x[0] > 16) break;
@@ -212,8 +225,8 @@ __kernel void iterate(__global float* A, const int width,
     }
 
     // N + 1 - log (log  |Z(N)|) / log 2
-    if (n >= max - 1)
-        A[index] = max;
+    if (n >= maxIter - 1)
+        A[index] = maxIter;
     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);

+ 180 - 161
libmandel/src/opencl/hexdouble.h

@@ -416,173 +416,192 @@ unsigned char hexdouble_cl[] = {
   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, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61,
-  0x6e, 0x74, 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,
+  0x0a, 0x7d, 0x0a, 0x0a, 0x0a, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20,
+  0x48, 0x65, 0x78, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x77,
+  0x69, 0x63, 0x65, 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, 0x29, 0x0a, 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, 0x61, 0x2d, 0x3e,
+  0x78, 0x5b, 0x30, 0x5d, 0x20, 0x2a, 0x20, 0x32, 0x2c, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x2d, 0x3e, 0x78, 0x5b, 0x31,
+  0x5d, 0x20, 0x2a, 0x20, 0x32, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x61, 0x2d, 0x3e, 0x78, 0x5b, 0x32, 0x5d, 0x20, 0x2a,
+  0x20, 0x32, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x61, 0x2d, 0x3e, 0x78, 0x5b, 0x33, 0x5d, 0x20, 0x2a, 0x20, 0x32, 0x2c,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x2d, 0x3e,
+  0x78, 0x5b, 0x34, 0x5d, 0x20, 0x2a, 0x20, 0x32, 0x2c, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x2d, 0x3e, 0x78, 0x5b, 0x35,
+  0x5d, 0x20, 0x2a, 0x20, 0x32, 0x2c, 0x0a, 0x20, 0x20, 0x20, 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, 0x63, 0x6f, 0x6e, 0x73, 0x74,
+  0x61, 0x6e, 0x74, 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,
-  0x5f, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x20, 0x64,
-  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x2a, 0x20, 0x78, 0x2c, 0x20, 0x5f, 0x5f,
-  0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x20, 0x64, 0x6f, 0x75,
-  0x62, 0x6c, 0x65, 0x2a, 0x20, 0x79, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x5f, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x20,
+  0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x2a, 0x20, 0x78, 0x2c, 0x20, 0x5f,
+  0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 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, 0x5f, 0x5f, 0x63, 0x6f, 0x6e, 0x73,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x5f, 0x63, 0x6f, 0x6e,
+  0x73, 0x74, 0x61, 0x6e, 0x74, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65,
+  0x2a, 0x20, 0x70, 0x77, 0x2c, 0x20, 0x5f, 0x5f, 0x63, 0x6f, 0x6e, 0x73,
   0x74, 0x61, 0x6e, 0x74, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x2a,
-  0x20, 0x70, 0x77, 0x2c, 0x20, 0x5f, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x74,
-  0x61, 0x6e, 0x74, 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, 0x70, 0x68, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x6d, 0x61, 0x78,
+  0x49, 0x74, 0x65, 0x72, 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, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x5f,
-  0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x20, 0x64, 0x6f, 0x75,
-  0x62, 0x6c, 0x65, 0x2a, 0x20, 0x6a, 0x78, 0x2c, 0x20, 0x5f, 0x5f, 0x63,
-  0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 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, 0x5f, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e,
+  0x74, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x2a, 0x20, 0x6a, 0x78,
+  0x2c, 0x20, 0x5f, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74,
+  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, 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,
+  0x65, 0x20, 0x61, 0x20, 0x3d, 0x20, 0x63, 0x61, 0x3b, 0x0a, 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,
+  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,
+  0x49, 0x74, 0x65, 0x72, 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, 0x74, 0x77, 0x69, 0x63, 0x65, 0x28, 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, 0x49, 0x74, 0x65, 0x72, 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, 0x49,
+  0x74, 0x65, 0x72, 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,
-  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
+  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 = 7011;
+unsigned int hexdouble_cl_len = 7241;

+ 272 - 0
libmandel/src/opencl/octadouble.cl

@@ -0,0 +1,272 @@
+#pragma OPENCL EXTENSION cl_khr_fp64 : enable
+#pragma OPENCL FP_CONTRACT OFF
+
+
+typedef double8 OctaDouble;
+
+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 OctaDouble add(const __private OctaDouble* a, const __private OctaDouble* b)
+{
+    double2 ap = twoSum(a->s0, b->s0);
+    double2 bp = twoSum(a->s1, b->s1);
+    double2 cp = twoSum(a->s2, b->s2);
+    double2 dp = twoSum(a->s3, b->s3);
+    double2 ep = twoSum(a->s4, b->s4);
+    double2 fp = twoSum(a->s5, b->s5);
+    double2 gp = twoSum(a->s6, b->s6);
+
+    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);
+    double3 t4p78 = sixThreeSum(dp.s1, ep.s0, t3p456.s1, t3p456.s2, t3p456.s3, 0.0);
+    double3 t5p910 = sixThreeSum(ep.s1, fp.s0, t4p78.s1, t4p78.s2, 0.0, 0.0);
+    double2 t6p11 = fiveTwoSum(fp.s1, gp.s0, t5p910.s1, t5p910.s2, 0.0);
+    double t7 = a->s7 + b->s7 + gp.s1 + t6p11.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, t4p78.s0);
+    double2 r4 = quickTwoSum(r3.s1, t5p910.s0);
+    double2 r5 = quickTwoSum(r4.s1, t6p11.s0);
+    double2 r67 = quickTwoSum(r5.s1, t7);
+
+    return (OctaDouble)(r0.s0, r1.s0, r2.s0, r3.s0, r4.s0, r5.s0, r67.s0, r67.s1);
+}
+
+
+inline OctaDouble mul(const __private OctaDouble* a, const __private OctaDouble* b)
+{
+
+    double r[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+    for (int i = 0; i < 8; i++) {
+        for (int j = 0; i + j < 8; j++) {
+            double2 se = twoProd((*a)[i], (*b)[j]);
+            for (int k = 0; k < 8; k++) {
+                double3 x123 = threeSum(r[k], se.s0, se.s1);
+                r[k] = x123.s0;
+                se.s0 = x123.s1;
+                se.s1 = x123.s2;
+            }
+        }
+    }
+
+    return (OctaDouble) (r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]);
+    /*double2 p0 = twoProd(a->s0, b->s0);
+
+    double2 q0 = twoProd(a->s0, b->s1);
+    double2 q1 = twoProd(a->s1, b->s0);
+
+    double2 r0 = twoProd(a->s2, b->s0);
+    double2 r1 = twoProd(a->s1, b->s1);
+    double2 r2 = twoProd(a->s0, b->s2);
+
+    double2 s0 = twoProd(a->s3, b->s0);
+    double2 s1 = twoProd(a->s2, b->s1);
+    double2 s2 = twoProd(a->s1, b->s2);
+    double2 s3 = twoProd(a->s0, b->s3);
+
+    double2 t0 = twoProd(a->s4, b->s0);
+    double2 t1 = twoProd(a->s3, b->s1);
+    double2 t2 = twoProd(a->s2, b->s2);
+    double2 t3 = twoProd(a->s1, b->s3);
+    double2 t4 = twoProd(a->s0, b->s4);
+
+    double2 u0 = twoProd(a->s5, b->s0);
+    double2 u1 = twoProd(a->s4, b->s1);
+    double2 u2 = twoProd(a->s3, b->s2);
+    double2 u3 = twoProd(a->s2, b->s3);
+    double2 u4 = twoProd(a->s1, b->s4);
+    double2 u5 = twoProd(a->s0, b->s5);
+
+    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, t4L56.s2);
+    double3 x456 = nineThreeSum(t0.s1, t1.s1, t2.s1, t3.s1, t4.s1, u0.s0, u1.s0, u2.s0, u3.s0);
+    double3 t6L89 = nineThreeSum(x456.s0, x456.s1, x456.s2, t5L67.s1, t5L67.s2, u4.s0, u5.s0, 0.0, 0.0);
+
+    double v7 = t6L89.s1 + t6L89.s2 + 
+        a->s6 * b->s0 + a->s5 * b->s1 + a->s4 * b->s2 + a->s3 * b->s3 + a->s2 * b->s4 + a->s1 * b->s5 + a->s0 * b->s6;
+
+    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 re4 = quickTwoSum(re3.s1, t6L89.s0);
+    double2 re56 = quickTwoSum(re4.s1, v7);
+    return (OctaDouble)(re0.s0, re1.s0, re2.s0, re3.s0, re4.s0, re56.s0, re56.s1, 0.0);*/
+}
+
+
+inline OctaDouble twice(const __private OctaDouble* a)
+{
+    return (OctaDouble) (
+        a->s0 * 2,
+        a->s1 * 2,
+        a->s2 * 2,
+        a->s3 * 2,
+        a->s4 * 2,
+        a->s5 * 2,
+        a->s6 * 2,
+        a->s7 * 2
+    );
+}
+
+
+OctaDouble loadHd(const __constant double* v) {
+    return (OctaDouble) (
+        v[0],
+        v[1],
+        v[2],
+        v[3],
+        v[4],
+        v[5],
+        v[6],
+        v[7]
+    );
+}
+
+
+__kernel void iterate(__global float* A, const int width,
+                      __constant double* x, __constant double* y,
+                      __constant double* pw, __constant double* ph, int maxIter, int smooth, int julia,
+                      __constant double* jx, __constant double* jy) {
+    int index = get_global_id(0);
+    int px = index % width;
+    int py = index / width;
+
+    OctaDouble xl = loadHd(x);
+    OctaDouble yt = loadHd(y);
+    OctaDouble pixelScaleX = loadHd(pw);
+    OctaDouble pixelScaleY = loadHd(ph);
+
+    OctaDouble pxh = { px, 0, 0, 0, 0, 0, 0, 0 };
+    OctaDouble pyh = { py, 0, 0, 0, 0, 0, 0, 0 };
+
+    OctaDouble caOff = mul(&pixelScaleX, &pxh);
+    OctaDouble cbOff = mul(&pixelScaleY, &pyh);
+    OctaDouble ca = add(&caOff, &xl); // pixelScaleX * px + xl
+    OctaDouble cb = add(&cbOff, &yt); // pixelScaleY * py + yt
+    OctaDouble a = ca;
+    OctaDouble b = cb;
+    if (julia != 0) {
+        ca = loadHd(jx);
+        cb = loadHd(jy);
+    }
+
+    int n = 0;
+    while (n < maxIter - 1) {
+        OctaDouble aa = mul(&a, &a); /* TODO add squaring function */
+        OctaDouble bb = mul(&b, &b);
+        OctaDouble ab = mul(&a, &b);
+        OctaDouble minusbb = (OctaDouble)(-bb.s0, -bb.s1, -bb.s2, -bb.s3, -bb.s4, -bb.s5, -bb.s6, -bb.s7);
+        OctaDouble aambb = add(&aa, &minusbb);
+        OctaDouble abab = twice(&ab);
+        a = add(&aambb, &ca);
+        b = add(&abab, &cb);
+        if (aa.s0 + bb.s0 > 16) break;
+        n++;
+    }
+
+    // N + 1 - log (log  |Z(N)|) / log 2
+    if (n >= maxIter - 1)
+        A[index] = maxIter;
+    else {
+        if (smooth != 0)
+            A[index] = ((float) n) + 1 - log2(log(a.s0 * a.s0 + b.s0 * b.s0) * 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;
+}
+

+ 712 - 0
libmandel/src/opencl/octadouble.h

@@ -0,0 +1,712 @@
+unsigned char octadouble_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, 0x23, 0x70,
+  0x72, 0x61, 0x67, 0x6d, 0x61, 0x20, 0x4f, 0x50, 0x45, 0x4e, 0x43, 0x4c,
+  0x20, 0x46, 0x50, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x52, 0x41, 0x43, 0x54,
+  0x20, 0x4f, 0x46, 0x46, 0x0a, 0x0a, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x64,
+  0x65, 0x66, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x38, 0x20, 0x4f,
+  0x63, 0x74, 0x61, 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, 0x4f,
+  0x63, 0x74, 0x61, 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, 0x4f, 0x63, 0x74, 0x61, 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, 0x4f, 0x63, 0x74, 0x61, 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, 0x73, 0x30, 0x2c,
+  0x20, 0x62, 0x2d, 0x3e, 0x73, 0x30, 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,
+  0x73, 0x31, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x73, 0x31, 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, 0x73, 0x32, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x73, 0x32,
+  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, 0x73, 0x33, 0x2c, 0x20, 0x62, 0x2d,
+  0x3e, 0x73, 0x33, 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, 0x73, 0x34, 0x2c,
+  0x20, 0x62, 0x2d, 0x3e, 0x73, 0x34, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20,
+  0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x66, 0x70, 0x20,
+  0x3d, 0x20, 0x74, 0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x61, 0x2d, 0x3e,
+  0x73, 0x35, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x73, 0x35, 0x29, 0x3b, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20,
+  0x67, 0x70, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28,
+  0x61, 0x2d, 0x3e, 0x73, 0x36, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x73, 0x36,
+  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, 0x33, 0x20, 0x74, 0x34, 0x70, 0x37,
+  0x38, 0x20, 0x3d, 0x20, 0x73, 0x69, 0x78, 0x54, 0x68, 0x72, 0x65, 0x65,
+  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, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20,
+  0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x33, 0x20, 0x74, 0x35, 0x70,
+  0x39, 0x31, 0x30, 0x20, 0x3d, 0x20, 0x73, 0x69, 0x78, 0x54, 0x68, 0x72,
+  0x65, 0x65, 0x53, 0x75, 0x6d, 0x28, 0x65, 0x70, 0x2e, 0x73, 0x31, 0x2c,
+  0x20, 0x66, 0x70, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x74, 0x34, 0x70, 0x37,
+  0x38, 0x2e, 0x73, 0x31, 0x2c, 0x20, 0x74, 0x34, 0x70, 0x37, 0x38, 0x2e,
+  0x73, 0x32, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x30,
+  0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c,
+  0x65, 0x32, 0x20, 0x74, 0x36, 0x70, 0x31, 0x31, 0x20, 0x3d, 0x20, 0x66,
+  0x69, 0x76, 0x65, 0x54, 0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x66, 0x70,
+  0x2e, 0x73, 0x31, 0x2c, 0x20, 0x67, 0x70, 0x2e, 0x73, 0x30, 0x2c, 0x20,
+  0x74, 0x35, 0x70, 0x39, 0x31, 0x30, 0x2e, 0x73, 0x31, 0x2c, 0x20, 0x74,
+  0x35, 0x70, 0x39, 0x31, 0x30, 0x2e, 0x73, 0x32, 0x2c, 0x20, 0x30, 0x2e,
+  0x30, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x20, 0x74, 0x37, 0x20, 0x3d, 0x20, 0x61, 0x2d, 0x3e, 0x73,
+  0x37, 0x20, 0x2b, 0x20, 0x62, 0x2d, 0x3e, 0x73, 0x37, 0x20, 0x2b, 0x20,
+  0x67, 0x70, 0x2e, 0x73, 0x31, 0x20, 0x2b, 0x20, 0x74, 0x36, 0x70, 0x31,
+  0x31, 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, 0x38, 0x2e, 0x73, 0x30, 0x29, 0x3b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32,
+  0x20, 0x72, 0x34, 0x20, 0x3d, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x54,
+  0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x72, 0x33, 0x2e, 0x73, 0x31, 0x2c,
+  0x20, 0x74, 0x35, 0x70, 0x39, 0x31, 0x30, 0x2e, 0x73, 0x30, 0x29, 0x3b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32,
+  0x20, 0x72, 0x35, 0x20, 0x3d, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x54,
+  0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x72, 0x34, 0x2e, 0x73, 0x31, 0x2c,
+  0x20, 0x74, 0x36, 0x70, 0x31, 0x31, 0x2e, 0x73, 0x30, 0x29, 0x3b, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20,
+  0x72, 0x36, 0x37, 0x20, 0x3d, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x54,
+  0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x72, 0x35, 0x2e, 0x73, 0x31, 0x2c,
+  0x20, 0x74, 0x37, 0x29, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72,
+  0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x4f, 0x63, 0x74, 0x61, 0x44,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x29, 0x28, 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, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x72, 0x35, 0x2e, 0x73, 0x30, 0x2c,
+  0x20, 0x72, 0x36, 0x37, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x72, 0x36, 0x37,
+  0x2e, 0x73, 0x31, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x0a, 0x69, 0x6e,
+  0x6c, 0x69, 0x6e, 0x65, 0x20, 0x4f, 0x63, 0x74, 0x61, 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,
+  0x4f, 0x63, 0x74, 0x61, 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, 0x4f, 0x63, 0x74, 0x61, 0x44,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x2a, 0x20, 0x62, 0x29, 0x0a, 0x7b, 0x0a,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20,
+  0x72, 0x5b, 0x38, 0x5d, 0x20, 0x3d, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20,
+  0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20,
+  0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x3b, 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, 0x38,
+  0x3b, 0x20, 0x69, 0x2b, 0x2b, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x69, 0x6e,
+  0x74, 0x20, 0x6a, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x69, 0x20, 0x2b,
+  0x20, 0x6a, 0x20, 0x3c, 0x20, 0x38, 0x3b, 0x20, 0x6a, 0x2b, 0x2b, 0x29,
+  0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x73,
+  0x65, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f, 0x50, 0x72, 0x6f, 0x64, 0x28,
+  0x28, 0x2a, 0x61, 0x29, 0x5b, 0x69, 0x5d, 0x2c, 0x20, 0x28, 0x2a, 0x62,
+  0x29, 0x5b, 0x6a, 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28,
+  0x69, 0x6e, 0x74, 0x20, 0x6b, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x6b,
+  0x20, 0x3c, 0x20, 0x38, 0x3b, 0x20, 0x6b, 0x2b, 0x2b, 0x29, 0x20, 0x7b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x33,
+  0x20, 0x78, 0x31, 0x32, 0x33, 0x20, 0x3d, 0x20, 0x74, 0x68, 0x72, 0x65,
+  0x65, 0x53, 0x75, 0x6d, 0x28, 0x72, 0x5b, 0x6b, 0x5d, 0x2c, 0x20, 0x73,
+  0x65, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x73, 0x65, 0x2e, 0x73, 0x31, 0x29,
+  0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x5b, 0x6b, 0x5d, 0x20, 0x3d,
+  0x20, 0x78, 0x31, 0x32, 0x33, 0x2e, 0x73, 0x30, 0x3b, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x73, 0x65, 0x2e, 0x73, 0x30, 0x20, 0x3d, 0x20, 0x78, 0x31,
+  0x32, 0x33, 0x2e, 0x73, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73,
+  0x65, 0x2e, 0x73, 0x31, 0x20, 0x3d, 0x20, 0x78, 0x31, 0x32, 0x33, 0x2e,
+  0x73, 0x32, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x4f,
+  0x63, 0x74, 0x61, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x29, 0x20, 0x28,
+  0x72, 0x5b, 0x30, 0x5d, 0x2c, 0x20, 0x72, 0x5b, 0x31, 0x5d, 0x2c, 0x20,
+  0x72, 0x5b, 0x32, 0x5d, 0x2c, 0x20, 0x72, 0x5b, 0x33, 0x5d, 0x2c, 0x20,
+  0x72, 0x5b, 0x34, 0x5d, 0x2c, 0x20, 0x72, 0x5b, 0x35, 0x5d, 0x2c, 0x20,
+  0x72, 0x5b, 0x36, 0x5d, 0x2c, 0x20, 0x72, 0x5b, 0x37, 0x5d, 0x29, 0x3b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2a, 0x64, 0x6f, 0x75, 0x62, 0x6c,
+  0x65, 0x32, 0x20, 0x70, 0x30, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f, 0x50,
+  0x72, 0x6f, 0x64, 0x28, 0x61, 0x2d, 0x3e, 0x73, 0x30, 0x2c, 0x20, 0x62,
+  0x2d, 0x3e, 0x73, 0x30, 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,
+  0x73, 0x30, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x73, 0x31, 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, 0x73, 0x31, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x73,
+  0x30, 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, 0x73, 0x32, 0x2c,
+  0x20, 0x62, 0x2d, 0x3e, 0x73, 0x30, 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, 0x73, 0x31, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x73, 0x31, 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, 0x73, 0x30, 0x2c, 0x20, 0x62, 0x2d, 0x3e,
+  0x73, 0x32, 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, 0x73, 0x33,
+  0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x73, 0x30, 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, 0x73, 0x32, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x73, 0x31, 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, 0x73, 0x31, 0x2c, 0x20, 0x62, 0x2d,
+  0x3e, 0x73, 0x32, 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, 0x73, 0x30,
+  0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x73, 0x33, 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, 0x73, 0x34, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x73, 0x30,
+  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, 0x73, 0x33, 0x2c, 0x20, 0x62,
+  0x2d, 0x3e, 0x73, 0x31, 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, 0x73,
+  0x32, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x73, 0x32, 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, 0x73, 0x31, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x73, 0x33,
+  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, 0x73, 0x30, 0x2c, 0x20, 0x62,
+  0x2d, 0x3e, 0x73, 0x34, 0x29, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x75, 0x30, 0x20, 0x3d,
+  0x20, 0x74, 0x77, 0x6f, 0x50, 0x72, 0x6f, 0x64, 0x28, 0x61, 0x2d, 0x3e,
+  0x73, 0x35, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x73, 0x30, 0x29, 0x3b, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20,
+  0x75, 0x31, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f, 0x50, 0x72, 0x6f, 0x64,
+  0x28, 0x61, 0x2d, 0x3e, 0x73, 0x34, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x73,
+  0x31, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x32, 0x20, 0x75, 0x32, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f,
+  0x50, 0x72, 0x6f, 0x64, 0x28, 0x61, 0x2d, 0x3e, 0x73, 0x33, 0x2c, 0x20,
+  0x62, 0x2d, 0x3e, 0x73, 0x32, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x75, 0x33, 0x20, 0x3d,
+  0x20, 0x74, 0x77, 0x6f, 0x50, 0x72, 0x6f, 0x64, 0x28, 0x61, 0x2d, 0x3e,
+  0x73, 0x32, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x73, 0x33, 0x29, 0x3b, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20,
+  0x75, 0x34, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f, 0x50, 0x72, 0x6f, 0x64,
+  0x28, 0x61, 0x2d, 0x3e, 0x73, 0x31, 0x2c, 0x20, 0x62, 0x2d, 0x3e, 0x73,
+  0x34, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x32, 0x20, 0x75, 0x35, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f,
+  0x50, 0x72, 0x6f, 0x64, 0x28, 0x61, 0x2d, 0x3e, 0x73, 0x30, 0x2c, 0x20,
+  0x62, 0x2d, 0x3e, 0x73, 0x35, 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, 0x74, 0x34, 0x4c, 0x35, 0x36,
+  0x2e, 0x73, 0x32, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f,
+  0x75, 0x62, 0x6c, 0x65, 0x33, 0x20, 0x78, 0x34, 0x35, 0x36, 0x20, 0x3d,
+  0x20, 0x6e, 0x69, 0x6e, 0x65, 0x54, 0x68, 0x72, 0x65, 0x65, 0x53, 0x75,
+  0x6d, 0x28, 0x74, 0x30, 0x2e, 0x73, 0x31, 0x2c, 0x20, 0x74, 0x31, 0x2e,
+  0x73, 0x31, 0x2c, 0x20, 0x74, 0x32, 0x2e, 0x73, 0x31, 0x2c, 0x20, 0x74,
+  0x33, 0x2e, 0x73, 0x31, 0x2c, 0x20, 0x74, 0x34, 0x2e, 0x73, 0x31, 0x2c,
+  0x20, 0x75, 0x30, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x75, 0x31, 0x2e, 0x73,
+  0x30, 0x2c, 0x20, 0x75, 0x32, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x75, 0x33,
+  0x2e, 0x73, 0x30, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f,
+  0x75, 0x62, 0x6c, 0x65, 0x33, 0x20, 0x74, 0x36, 0x4c, 0x38, 0x39, 0x20,
+  0x3d, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x54, 0x68, 0x72, 0x65, 0x65, 0x53,
+  0x75, 0x6d, 0x28, 0x78, 0x34, 0x35, 0x36, 0x2e, 0x73, 0x30, 0x2c, 0x20,
+  0x78, 0x34, 0x35, 0x36, 0x2e, 0x73, 0x31, 0x2c, 0x20, 0x78, 0x34, 0x35,
+  0x36, 0x2e, 0x73, 0x32, 0x2c, 0x20, 0x74, 0x35, 0x4c, 0x36, 0x37, 0x2e,
+  0x73, 0x31, 0x2c, 0x20, 0x74, 0x35, 0x4c, 0x36, 0x37, 0x2e, 0x73, 0x32,
+  0x2c, 0x20, 0x75, 0x34, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x75, 0x35, 0x2e,
+  0x73, 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x30,
+  0x29, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x20, 0x76, 0x37, 0x20, 0x3d, 0x20, 0x74, 0x36, 0x4c, 0x38,
+  0x39, 0x2e, 0x73, 0x31, 0x20, 0x2b, 0x20, 0x74, 0x36, 0x4c, 0x38, 0x39,
+  0x2e, 0x73, 0x32, 0x20, 0x2b, 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x61, 0x2d, 0x3e, 0x73, 0x36, 0x20, 0x2a, 0x20, 0x62,
+  0x2d, 0x3e, 0x73, 0x30, 0x20, 0x2b, 0x20, 0x61, 0x2d, 0x3e, 0x73, 0x35,
+  0x20, 0x2a, 0x20, 0x62, 0x2d, 0x3e, 0x73, 0x31, 0x20, 0x2b, 0x20, 0x61,
+  0x2d, 0x3e, 0x73, 0x34, 0x20, 0x2a, 0x20, 0x62, 0x2d, 0x3e, 0x73, 0x32,
+  0x20, 0x2b, 0x20, 0x61, 0x2d, 0x3e, 0x73, 0x33, 0x20, 0x2a, 0x20, 0x62,
+  0x2d, 0x3e, 0x73, 0x33, 0x20, 0x2b, 0x20, 0x61, 0x2d, 0x3e, 0x73, 0x32,
+  0x20, 0x2a, 0x20, 0x62, 0x2d, 0x3e, 0x73, 0x34, 0x20, 0x2b, 0x20, 0x61,
+  0x2d, 0x3e, 0x73, 0x31, 0x20, 0x2a, 0x20, 0x62, 0x2d, 0x3e, 0x73, 0x35,
+  0x20, 0x2b, 0x20, 0x61, 0x2d, 0x3e, 0x73, 0x30, 0x20, 0x2a, 0x20, 0x62,
+  0x2d, 0x3e, 0x73, 0x36, 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, 0x20, 0x3d,
+  0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x54, 0x77, 0x6f, 0x53, 0x75, 0x6d,
+  0x28, 0x72, 0x65, 0x33, 0x2e, 0x73, 0x31, 0x2c, 0x20, 0x74, 0x36, 0x4c,
+  0x38, 0x39, 0x2e, 0x73, 0x30, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x72, 0x65, 0x35, 0x36,
+  0x20, 0x3d, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x54, 0x77, 0x6f, 0x53,
+  0x75, 0x6d, 0x28, 0x72, 0x65, 0x34, 0x2e, 0x73, 0x31, 0x2c, 0x20, 0x76,
+  0x37, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75,
+  0x72, 0x6e, 0x20, 0x28, 0x4f, 0x63, 0x74, 0x61, 0x44, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x29, 0x28, 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, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x72, 0x65, 0x35, 0x36,
+  0x2e, 0x73, 0x30, 0x2c, 0x20, 0x72, 0x65, 0x35, 0x36, 0x2e, 0x73, 0x31,
+  0x2c, 0x20, 0x30, 0x2e, 0x30, 0x29, 0x3b, 0x2a, 0x2f, 0x0a, 0x7d, 0x0a,
+  0x0a, 0x0a, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x4f, 0x63, 0x74,
+  0x61, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x77, 0x69, 0x63,
+  0x65, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x5f, 0x5f, 0x70, 0x72,
+  0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x4f, 0x63, 0x74, 0x61, 0x44, 0x6f,
+  0x75, 0x62, 0x6c, 0x65, 0x2a, 0x20, 0x61, 0x29, 0x0a, 0x7b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x4f,
+  0x63, 0x74, 0x61, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x29, 0x20, 0x28,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x2d, 0x3e,
+  0x73, 0x30, 0x20, 0x2a, 0x20, 0x32, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x61, 0x2d, 0x3e, 0x73, 0x31, 0x20, 0x2a, 0x20,
+  0x32, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61,
+  0x2d, 0x3e, 0x73, 0x32, 0x20, 0x2a, 0x20, 0x32, 0x2c, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x2d, 0x3e, 0x73, 0x33, 0x20,
+  0x2a, 0x20, 0x32, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x61, 0x2d, 0x3e, 0x73, 0x34, 0x20, 0x2a, 0x20, 0x32, 0x2c, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x2d, 0x3e, 0x73,
+  0x35, 0x20, 0x2a, 0x20, 0x32, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x61, 0x2d, 0x3e, 0x73, 0x36, 0x20, 0x2a, 0x20, 0x32,
+  0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x2d,
+  0x3e, 0x73, 0x37, 0x20, 0x2a, 0x20, 0x32, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x0a, 0x4f, 0x63, 0x74, 0x61, 0x44,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x64,
+  0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x5f, 0x5f, 0x63, 0x6f, 0x6e,
+  0x73, 0x74, 0x61, 0x6e, 0x74, 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, 0x4f, 0x63, 0x74, 0x61, 0x44,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x29, 0x20, 0x28, 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, 0x20, 0x20, 0x20, 0x20, 0x76, 0x5b, 0x36, 0x5d, 0x2c, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x5b, 0x37, 0x5d, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x29, 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, 0x63, 0x6f, 0x6e,
+  0x73, 0x74, 0x61, 0x6e, 0x74, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65,
+  0x2a, 0x20, 0x78, 0x2c, 0x20, 0x5f, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x74,
+  0x61, 0x6e, 0x74, 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, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x20,
+  0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x2a, 0x20, 0x70, 0x77, 0x2c, 0x20,
+  0x5f, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x20, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x2a, 0x20, 0x70, 0x68, 0x2c, 0x20, 0x69,
+  0x6e, 0x74, 0x20, 0x6d, 0x61, 0x78, 0x49, 0x74, 0x65, 0x72, 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, 0x63,
+  0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x20, 0x64, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x2a, 0x20, 0x6a, 0x78, 0x2c, 0x20, 0x5f, 0x5f, 0x63, 0x6f,
+  0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 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, 0x4f, 0x63, 0x74, 0x61,
+  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, 0x4f, 0x63, 0x74, 0x61, 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, 0x4f, 0x63,
+  0x74, 0x61, 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, 0x4f, 0x63, 0x74, 0x61, 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, 0x4f, 0x63, 0x74,
+  0x61, 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, 0x2c, 0x20, 0x30,
+  0x2c, 0x20, 0x30, 0x20, 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x4f,
+  0x63, 0x74, 0x61, 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, 0x2c,
+  0x20, 0x30, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x4f, 0x63, 0x74, 0x61, 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, 0x4f, 0x63, 0x74, 0x61, 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, 0x4f, 0x63, 0x74, 0x61, 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, 0x4f, 0x63, 0x74, 0x61, 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, 0x4f, 0x63, 0x74, 0x61,
+  0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x61, 0x20, 0x3d, 0x20, 0x63,
+  0x61, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x4f, 0x63, 0x74, 0x61, 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, 0x49, 0x74, 0x65, 0x72, 0x20, 0x2d,
+  0x20, 0x31, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x4f, 0x63, 0x74, 0x61, 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,
+  0x4f, 0x63, 0x74, 0x61, 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, 0x4f, 0x63, 0x74, 0x61, 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, 0x4f, 0x63, 0x74, 0x61, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65,
+  0x20, 0x6d, 0x69, 0x6e, 0x75, 0x73, 0x62, 0x62, 0x20, 0x3d, 0x20, 0x28,
+  0x4f, 0x63, 0x74, 0x61, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x29, 0x28,
+  0x2d, 0x62, 0x62, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x2d, 0x62, 0x62, 0x2e,
+  0x73, 0x31, 0x2c, 0x20, 0x2d, 0x62, 0x62, 0x2e, 0x73, 0x32, 0x2c, 0x20,
+  0x2d, 0x62, 0x62, 0x2e, 0x73, 0x33, 0x2c, 0x20, 0x2d, 0x62, 0x62, 0x2e,
+  0x73, 0x34, 0x2c, 0x20, 0x2d, 0x62, 0x62, 0x2e, 0x73, 0x35, 0x2c, 0x20,
+  0x2d, 0x62, 0x62, 0x2e, 0x73, 0x36, 0x2c, 0x20, 0x2d, 0x62, 0x62, 0x2e,
+  0x73, 0x37, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x4f, 0x63, 0x74, 0x61, 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,
+  0x4f, 0x63, 0x74, 0x61, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x61,
+  0x62, 0x61, 0x62, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x69, 0x63, 0x65, 0x28,
+  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, 0x73, 0x30, 0x20, 0x2b,
+  0x20, 0x62, 0x62, 0x2e, 0x73, 0x30, 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, 0x49, 0x74, 0x65, 0x72, 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, 0x49, 0x74, 0x65,
+  0x72, 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, 0x73, 0x30, 0x20, 0x2a, 0x20,
+  0x61, 0x2e, 0x73, 0x30, 0x20, 0x2b, 0x20, 0x62, 0x2e, 0x73, 0x30, 0x20,
+  0x2a, 0x20, 0x62, 0x2e, 0x73, 0x30, 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 octadouble_cl_len = 8503;

+ 1 - 0
resources/Almond.qrc

@@ -8,6 +8,7 @@
         <file alias="cancel">icons/cancel.svg</file>
     </qresource>
     <qresource prefix="/gradients">
+        <file alias="almond">gradients/almond.xml</file>
         <file alias="oldschool">gradients/oldschool.xml</file>
         <file alias="clouds">gradients/clouds.xml</file>
         <file alias="rainbow">gradients/rainbow.xml</file>

+ 1 - 0
src/Almond.cpp

@@ -72,6 +72,7 @@ Almond::Almond(QWidget* parent) :
     connect(aboutSm, &AlmondSubMenu::accepted, [] () {});
     connect(aboutSm, &AlmondSubMenu::cancelled, [] () {});
 
+    fractalWidget->setGradient(gradientMenu->getGradient());
 
     /*QStatusBar* bar = new QStatusBar(this);
     bar->addWidget(new QLabel("ayay"));

+ 1 - 0
src/GradientMenu.cpp

@@ -12,6 +12,7 @@
 using alm::Gradient;
 
 const QString GradientMenu::presetNames[] = {
+    "almond",
     "blue gold",
     "clouds",
     "oldschool",