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

+ 5 - 6
benchmarkdialog.cpp

@@ -128,10 +128,9 @@ void Benchmarker::start(void)
         if (mnd::Generator* gpud; (gpud = devices[i].getGeneratorDouble())) {
             nTests++;
         }
-        /*
-        if (mnd::Generator* gpu128; (gpu128 = devices[i].getGeneratorQuad())) {
+        if (mnd::Generator* gpudd; (gpudd = devices[i].getGeneratorDoubleDouble())) {
             nTests++;
-        }*/
+        }
     }
 
     double progress = 90.0 / nTests;
@@ -184,11 +183,11 @@ void Benchmarker::start(void)
             br.percentage += progress;
             emit update(br);
         }
-        /*if (mnd::Generator* gpu128; (gpu128 = devices[i].getGenerator128())) {
-            gpu.push_back(benchmarkResult(*gpu128));
+        if (mnd::Generator* gpudd; (gpudd = devices[i].getGeneratorDoubleDouble())) {
+            gpu.push_back(benchmarkResult(*gpudd));
             br.percentage += progress;
             emit update(br);
-        }*/
+        }
     }
     emit update(br);
     emit finished();

+ 2 - 1
libmandel/include/ClGenerators.h

@@ -8,7 +8,7 @@
 #ifdef __APPLE__
 #include <OpenCL/cl.hpp>
 #else
-#include <CL/cl2.hpp>
+#include <CL/cl.hpp>
 #endif
 
 namespace mnd
@@ -64,6 +64,7 @@ protected:
 
 class mnd::ClGeneratorDoubleDouble : public ClGenerator
 {
+    bool smooth;
 public:
     ClGeneratorDoubleDouble(cl::Device device, bool smooth);
     virtual ~ClGeneratorDoubleDouble(void) = default;

+ 3 - 0
libmandel/include/Mandel.h

@@ -31,11 +31,13 @@ private:
 
     std::unique_ptr<Generator> floatGenerator;
     std::unique_ptr<Generator> doubleGenerator;
+    std::unique_ptr<Generator> doubleDoubleGenerator;
     //std::unique_ptr<Generator> quadGenerator;
     //std::unique_ptr<Generator> generator128;
 
     std::unique_ptr<Generator> floatGeneratorSmooth;
     std::unique_ptr<Generator> doubleGeneratorSmooth;
+    std::unique_ptr<Generator> doubleDoubleGeneratorSmooth;
     //std::unique_ptr<Generator> quadGeneratorSmooth;
     //std::unique_ptr<Generator> generator128Smooth;
 
@@ -47,6 +49,7 @@ public:
 
     Generator* getGeneratorFloat(bool smooth = true) const;
     Generator* getGeneratorDouble(bool smooth = true) const;
+    Generator* getGeneratorDoubleDouble(bool smooth = true) const;
     //Generator* getGeneratorQuad(bool smooth = true) const;
     //Generator* getGenerator128(bool smooth = true) const;
 };

+ 21 - 38
libmandel/src/ClGenerators.cpp

@@ -1,4 +1,5 @@
 #include "ClGenerators.h"
+#include "doubledouble.h"
 
 #ifdef WITH_OPENCL
 
@@ -307,12 +308,13 @@ std::string ClGeneratorDouble::getKernelCode(bool smooth) const
 
 
 ClGeneratorDoubleDouble::ClGeneratorDoubleDouble(cl::Device device, bool smooth) :
-    ClGenerator{ device }
+    ClGenerator{ device },
+    smooth{ smooth }
 {
     context = Context{ device };
     Program::Sources sources;
 
-    std::string kcode = this->getKernelCode(smooth);
+    std::string kcode = this->getKernelCode(false);
 
     sources.push_back({ kcode.c_str(), kcode.length() });
 
@@ -330,17 +332,26 @@ void ClGeneratorDoubleDouble::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);
-    double pixelScaleX = double(info.view.width / info.bWidth);
-    double pixelScaleY = double(info.view.height / info.bHeight);
+
+    mnd::DoubleDouble x = mnd::convert<mnd::DoubleDouble>(info.view.x);
+    mnd::DoubleDouble y = mnd::convert<mnd::DoubleDouble>(info.view.y);
+
+    mnd::DoubleDouble psx = mnd::convert<mnd::DoubleDouble>(info.view.width / info.bWidth);
+    mnd::DoubleDouble psy = mnd::convert<mnd::DoubleDouble>(info.view.height / info.bHeight);
 
     Kernel iterate = Kernel(program, "iterate");
     iterate.setArg(0, buffer_A);
     iterate.setArg(1, int(info.bWidth));
-    iterate.setArg(2, double(info.view.x));
-    iterate.setArg(3, double(info.view.y));
-    iterate.setArg(4, double(pixelScaleX));
-    iterate.setArg(5, double(pixelScaleY));
-    iterate.setArg(6, int(info.maxIter));
+    iterate.setArg(2, x.x[0]);
+    iterate.setArg(3, x.x[1]);
+    iterate.setArg(4, y.x[0]);
+    iterate.setArg(5, y.x[1]);
+    iterate.setArg(6, psx.x[0]);
+    iterate.setArg(7, psx.x[1]);
+    iterate.setArg(8, psy.x[0]);
+    iterate.setArg(9, psy.x[1]);
+    iterate.setArg(10, int(info.maxIter));
+    iterate.setArg(11, int(smooth ? 1 : 0));
 
     cl_int result = queue.enqueueNDRangeKernel(iterate, 0, NDRange(info.bWidth * info.bHeight));
     queue.enqueueReadBuffer(buffer_A, CL_TRUE, 0, bufferSize, data);
@@ -349,35 +360,7 @@ void ClGeneratorDoubleDouble::generate(const mnd::MandelInfo& info, float* data)
 
 std::string ClGeneratorDoubleDouble::getKernelCode(bool smooth) const
 {
-    return
-        "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"
-        "__kernel void iterate(__global float* A, const int width, double xl, double yt, double pixelScaleX, double pixelScaleY, int max) {\n"
-        "   int index = get_global_id(0);\n"
-        "   int x = index % width;"
-        "   int y = index / width;"
-        "   double a = x * pixelScaleX + xl;"
-        "   double b = y * pixelScaleY + yt;"
-        "   double ca = a;"
-        "   double cb = b;"
-        ""
-        "   int n = 0;"
-        "   while (n < max - 1) {"
-        "       double aa = a * a;"
-        "       double bb = b * b;"
-        "       double ab = a * b;"
-        "       if (aa + bb > 16) break;"
-        "       a = aa - bb + ca;"
-        "       b = 2 * ab + cb;"
-        "       n++;"
-        "   }\n"
-        // N + 1 - log (log  |Z(N)|) / log 2
-        "   if (n >= max - 1)\n"
-        "       A[index] = max;\n"
-        "   else"
-        "       A[index] = ((float)n);\n"
-        //            "   A[index] = ((float)n) + 1 - (a * a + b * b - 16) / (256 - 16);\n"
-        //        "   A[get_global_id(0)] = 5;"
-        "}";
+    return (char*) doubledouble_cl;
 }
 
 

+ 24 - 0
libmandel/src/Mandel.cpp

@@ -46,6 +46,15 @@ mnd::Generator* MandelDevice::getGeneratorDouble(bool smooth) const
 }
 
 
+mnd::Generator* MandelDevice::getGeneratorDoubleDouble(bool smooth) const
+{
+    if (smooth)
+        return doubleDoubleGeneratorSmooth.get();
+    else
+        return doubleDoubleGenerator.get();
+}
+
+
 /*
 mnd::Generator* MandelDevice::getGeneratorQuad(bool smooth) const
 {
@@ -130,24 +139,35 @@ MandelContext::MandelContext(void) :
         auto& device1 = devices[0];
         Generator* floatGenerator = device1.getGeneratorFloat(false);
         Generator* doubleGenerator = device1.getGeneratorDouble(false);
+        Generator* doubleDoubleGenerator = device1.getGeneratorDoubleDouble(false);
         Generator* floatGeneratorSmooth = device1.getGeneratorFloat(true);
         Generator* doubleGeneratorSmooth = device1.getGeneratorDouble(true);
+        Generator* doubleDoubleGeneratorSmooth = device1.getGeneratorDoubleDouble(true);
         if (floatGenerator != nullptr)
             adaptiveGenerator->addGenerator(1.0e-7, *floatGenerator);
         else
             adaptiveGenerator->addGenerator(1.0e-7, *cpuGeneratorFloat);
+
         if (doubleGenerator != nullptr)
             adaptiveGenerator->addGenerator(0.5e-15, *doubleGenerator);
         else
             adaptiveGenerator->addGenerator(0.5e-15, *cpuGeneratorDouble);
+
         if (floatGeneratorSmooth != nullptr)
             adaptiveGeneratorSmooth->addGenerator(1.0e-7, *floatGeneratorSmooth);
         else
             adaptiveGeneratorSmooth->addGenerator(1.0e-7, *cpuGeneratorFloatSmooth);
+
         if (doubleGeneratorSmooth != nullptr)
             adaptiveGeneratorSmooth->addGenerator(0.5e-15, *doubleGeneratorSmooth);
         else
             adaptiveGeneratorSmooth->addGenerator(0.5e-15, *cpuGeneratorDoubleSmooth);
+
+        if (doubleDoubleGenerator != nullptr)
+            adaptiveGenerator->addGenerator(Real("1.0e-29"), *doubleDoubleGenerator);
+        if (doubleDoubleGeneratorSmooth != nullptr)
+            adaptiveGeneratorSmooth->addGenerator(Real("1.0e-29"), *doubleDoubleGeneratorSmooth);
+
     }
 
 #ifdef WITH_QD
@@ -208,8 +228,12 @@ std::vector<MandelDevice> MandelContext::createDevices(void)
                 try {
                     md.doubleGenerator = std::make_unique<ClGeneratorDouble>(device, false);
                     md.doubleGeneratorSmooth = std::make_unique<ClGeneratorDouble>(device, true);
+                    md.doubleDoubleGenerator = std::make_unique<ClGeneratorDoubleDouble>(device, false);
+                    md.doubleDoubleGeneratorSmooth = std::make_unique<ClGeneratorDoubleDouble>(device, true);
                 }
                 catch (const std::string& err) {
+                    printf("err: %s", err.c_str());
+                    fflush(stdout);
                 }
             }
 

+ 55 - 51
libmandel/src/doubledouble.cl

@@ -1,23 +1,23 @@
 #pragma OPENCL EXTENSION cl_khr_fp64 : enable
 
 inline double2 twoSum(double a, double b) {
-  double s = a + b;
-  double bb = s - a;
-  double e = (a - (s - bb)) + (b - bb);
-  return (s, e);
+    double s = a + b;
+    double bb = s - a;
+    double e = (a - (s - bb)) + (b - bb);
+    return (double2)(s, e);
 }
 
 inline double2 quickTwoSum(double a, double b) {
-  double s = a + b;
-  double e = b - (s - a);
-  return (s, e);
+    double s = a + b;
+    double e = b - (s - a);
+    return (double2)(s, e);
 }
 
 inline double2 twoProd(double a, double b) {
 //#ifdef QD_FMS
-  double p = a * b;
-  double e = fma(a, b, -p);
-  return (p, e);
+    double p = a * b;
+    double e = fma(a, b, -p);
+    return (double2)(p, e);
 //#else
 //  double a_hi, a_lo, b_hi, b_lo;
 //  double p = a * b;
@@ -29,57 +29,61 @@ inline double2 twoProd(double a, double b) {
 }
 
 inline double2 mul(double2 a, double2 b) {
-    double2 p = twoProd(a.0, b.0);
-    p.1 += a.0 * b.1 + a.1 * b.0;
-    return quickTwoSum(p.0, p.1);
+    double2 p = twoProd(a.s0, b.s0);
+    p.s1 += (a.s0 * b.s1 + a.s1 * b.s0);
+    return quickTwoSum(p.s0, p.s1);
 }
 
 inline double2 add(double2 a, double2 b) {
-    double se = twoSum(a.0, b.0);
-    se.1 += a.1 + b.1;
-    return quickTwoSum(se.0, se.1);
+    double2 se = twoSum(a.s0, b.s0);
+    se.s1 += a.s1 + b.s1;
+    return quickTwoSum(se.s0, se.s1);
 }
 
 inline double2 mulDouble(double2 a, double b) {
-    double2 p = twoProd(a.0, b);
-    p.1 += a.1 * b;
-    return quickTwoSum(p.0, p.1);
+    double2 p = twoProd(a.s0, b);
+    p.s1 += a.s1 * b;
+    return quickTwoSum(p.s0, p.s1);
 }
 
 __kernel void iterate(__global float* A, const int width,
                       double x1, double x2, double y1, double y2,
-                      double pw1, double pw2, double ph1, double ph2, int max) {
-   int index = get_global_id(0);
-   int px = index % width;
-   int py = index / width;
+                      double pw1, double pw2, double ph1, double ph2, int max, int smooth) {
+    int index = get_global_id(0);
+    int px = index % width;
+    int py = index / width;
 
-   double2 xl = (x1, x2);
-   double2 yt = (y1, y2);
-   double2 pixelScaleX = (pw1, pw2);
-   double2 pixelScaleY = (ph1, ph2);
+    double2 xl = (double2)(x1, x2);
+    double2 yt = (double2)(y1, y2);
+    double2 pixelScaleX = (double2)(pw1, pw2);
+    double2 pixelScaleY = (double2)(ph1, ph2);
 
-   double2 a = add(mulDouble(pixelScaleX, (double) px), xl); // pixelScaleX * px + xl
-   double2 b = add(mulDouble(pixelScaleY, (double) py), yt) // pixelScaleY * py + yt
-   double2 ca = a;
-   double2 cb = b;
+    double2 a = add(mulDouble(pixelScaleX, (double) px), xl); // pixelScaleX * px + xl
+    double2 b = add(mulDouble(pixelScaleY, (double) py), yt); // pixelScaleY * py + yt
+    double2 ca = a;
+    double2 cb = b;
 
-   int n = 0;
-   while (n < max - 1) {
-       double2 aa = mul(a, a);
-       double2 bb = mul(b, b);
-       double2 ab = mul(a, b);
-       if (aa.0 + aa.1 + bb.0 + bb.1 > 16) break;
-       double2 minusbb = (-bb.0, -bb.1)
-       a = add(add(aa, minusbb), ca);
-       double2 halfb = add(ab + cb);
-       b = add(halfb, halfb);
-       n++;
-   }
-// N + 1 - log (log  |Z(N)|) / log 2
-   if (n >= max - 1)
-       A[index] = max;
-   else
-       A[index] = ((float)n);
-//               A[index] = ((float)n) + 1 - (a * a + b * b - 16) / (256 - 16);
-//           A[get_global_id(0)] = 5;
-};
+    int n = 0;
+    while (n < max - 1) {
+        double2 aa = mul(a, a);
+        double2 bb = mul(b, b);
+        double2 ab = mul(a, b);
+        if (aa.s0 + aa.s1 + bb.s0 + bb.s1 > 16) break;
+        double2 minusbb = (double2)(-bb.s0, -bb.s1);
+        a = add(add(aa, minusbb), ca);
+        b = add(add(ab, ab), cb);
+        n++;
+    }
+
+    // N + 1 - log (log  |Z(N)|) / log 2
+    if (n >= max - 1)
+        A[index] = max;
+    else {
+        if (smooth != 0)
+            A[index] = ((float) n) + 1 - log(log(a.s0 * a.s0 + b.s0 * b.s0) / 2) / log(2.0f);
+        else
+            A[index] = ((float)n);
+    }
+    //               A[index] = ((float)n) + 1 - (a * a + b * b - 16) / (256 - 16);
+    //           A[get_global_id(0)] = 5;
+}

+ 218 - 0
libmandel/src/doubledouble.h

@@ -0,0 +1,218 @@
+unsigned char doubledouble_cl[] = {
+  0x23, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x20, 0x4f, 0x50, 0x45, 0x4e,
+  0x43, 0x4c, 0x20, 0x45, 0x58, 0x54, 0x45, 0x4e, 0x53, 0x49, 0x4f, 0x4e,
+  0x20, 0x63, 0x6c, 0x5f, 0x6b, 0x68, 0x72, 0x5f, 0x66, 0x70, 0x36, 0x34,
+  0x20, 0x3a, 0x20, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x0a, 0x0a, 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, 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, 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,
+  0x2f, 0x2f, 0x23, 0x69, 0x66, 0x64, 0x65, 0x66, 0x20, 0x51, 0x44, 0x5f,
+  0x46, 0x4d, 0x53, 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,
+  0x2f, 0x2f, 0x23, 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x2f, 0x2f, 0x20, 0x20,
+  0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x61, 0x5f, 0x68, 0x69, 0x2c,
+  0x20, 0x61, 0x5f, 0x6c, 0x6f, 0x2c, 0x20, 0x62, 0x5f, 0x68, 0x69, 0x2c,
+  0x20, 0x62, 0x5f, 0x6c, 0x6f, 0x3b, 0x0a, 0x2f, 0x2f, 0x20, 0x20, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x70, 0x20, 0x3d, 0x20, 0x61, 0x20,
+  0x2a, 0x20, 0x62, 0x3b, 0x0a, 0x2f, 0x2f, 0x20, 0x20, 0x73, 0x70, 0x6c,
+  0x69, 0x74, 0x28, 0x61, 0x2c, 0x20, 0x61, 0x5f, 0x68, 0x69, 0x2c, 0x20,
+  0x61, 0x5f, 0x6c, 0x6f, 0x29, 0x3b, 0x0a, 0x2f, 0x2f, 0x20, 0x20, 0x73,
+  0x70, 0x6c, 0x69, 0x74, 0x28, 0x62, 0x2c, 0x20, 0x62, 0x5f, 0x68, 0x69,
+  0x2c, 0x20, 0x62, 0x5f, 0x6c, 0x6f, 0x29, 0x3b, 0x0a, 0x2f, 0x2f, 0x20,
+  0x20, 0x65, 0x72, 0x72, 0x20, 0x3d, 0x20, 0x28, 0x28, 0x61, 0x5f, 0x68,
+  0x69, 0x20, 0x2a, 0x20, 0x62, 0x5f, 0x68, 0x69, 0x20, 0x2d, 0x20, 0x70,
+  0x29, 0x20, 0x2b, 0x20, 0x61, 0x5f, 0x68, 0x69, 0x20, 0x2a, 0x20, 0x62,
+  0x5f, 0x6c, 0x6f, 0x20, 0x2b, 0x20, 0x61, 0x5f, 0x6c, 0x6f, 0x20, 0x2a,
+  0x20, 0x62, 0x5f, 0x68, 0x69, 0x29, 0x20, 0x2b, 0x20, 0x61, 0x5f, 0x6c,
+  0x6f, 0x20, 0x2a, 0x20, 0x62, 0x5f, 0x6c, 0x6f, 0x3b, 0x0a, 0x2f, 0x2f,
+  0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x70, 0x3b, 0x0a,
+  0x2f, 0x2f, 0x23, 0x65, 0x6e, 0x64, 0x69, 0x66, 0x0a, 0x7d, 0x0a, 0x0a,
+  0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c,
+  0x65, 0x32, 0x20, 0x6d, 0x75, 0x6c, 0x28, 0x64, 0x6f, 0x75, 0x62, 0x6c,
+  0x65, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65,
+  0x32, 0x20, 0x62, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x70, 0x20, 0x3d, 0x20, 0x74,
+  0x77, 0x6f, 0x50, 0x72, 0x6f, 0x64, 0x28, 0x61, 0x2e, 0x73, 0x30, 0x2c,
+  0x20, 0x62, 0x2e, 0x73, 0x30, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x70, 0x2e, 0x73, 0x31, 0x20, 0x2b, 0x3d, 0x20, 0x28, 0x61, 0x2e, 0x73,
+  0x30, 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x73, 0x31, 0x20, 0x2b, 0x20, 0x61,
+  0x2e, 0x73, 0x31, 0x20, 0x2a, 0x20, 0x62, 0x2e, 0x73, 0x30, 0x29, 0x3b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20,
+  0x71, 0x75, 0x69, 0x63, 0x6b, 0x54, 0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28,
+  0x70, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x70, 0x2e, 0x73, 0x31, 0x29, 0x3b,
+  0x0a, 0x7d, 0x0a, 0x0a, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x61, 0x64, 0x64, 0x28, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x61, 0x2c, 0x20, 0x64, 0x6f,
+  0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x62, 0x29, 0x20, 0x7b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x73,
+  0x65, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28, 0x61,
+  0x2e, 0x73, 0x30, 0x2c, 0x20, 0x62, 0x2e, 0x73, 0x30, 0x29, 0x3b, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x73, 0x65, 0x2e, 0x73, 0x31, 0x20, 0x2b, 0x3d,
+  0x20, 0x61, 0x2e, 0x73, 0x31, 0x20, 0x2b, 0x20, 0x62, 0x2e, 0x73, 0x31,
+  0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
+  0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x54, 0x77, 0x6f, 0x53, 0x75, 0x6d,
+  0x28, 0x73, 0x65, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x73, 0x65, 0x2e, 0x73,
+  0x31, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x69, 0x6e, 0x6c, 0x69, 0x6e,
+  0x65, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x6d, 0x75,
+  0x6c, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x28, 0x64, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x32, 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, 0x32, 0x20, 0x70, 0x20, 0x3d, 0x20, 0x74,
+  0x77, 0x6f, 0x50, 0x72, 0x6f, 0x64, 0x28, 0x61, 0x2e, 0x73, 0x30, 0x2c,
+  0x20, 0x62, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x2e, 0x73,
+  0x31, 0x20, 0x2b, 0x3d, 0x20, 0x61, 0x2e, 0x73, 0x31, 0x20, 0x2a, 0x20,
+  0x62, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72,
+  0x6e, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x54, 0x77, 0x6f, 0x53, 0x75,
+  0x6d, 0x28, 0x70, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x70, 0x2e, 0x73, 0x31,
+  0x29, 0x3b, 0x0a, 0x7d, 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, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x78, 0x31, 0x2c,
+  0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x78, 0x32, 0x2c, 0x20,
+  0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x79, 0x31, 0x2c, 0x20, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x79, 0x32, 0x2c, 0x0a, 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, 0x70, 0x77, 0x31, 0x2c, 0x20, 0x64, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x20, 0x70, 0x77, 0x32, 0x2c, 0x20, 0x64, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x20, 0x70, 0x68, 0x31, 0x2c, 0x20, 0x64, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x20, 0x70, 0x68, 0x32, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20,
+  0x6d, 0x61, 0x78, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x73, 0x6d, 0x6f,
+  0x6f, 0x74, 0x68, 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, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65,
+  0x32, 0x20, 0x78, 0x6c, 0x20, 0x3d, 0x20, 0x28, 0x64, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x32, 0x29, 0x28, 0x78, 0x31, 0x2c, 0x20, 0x78, 0x32, 0x29,
+  0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65,
+  0x32, 0x20, 0x79, 0x74, 0x20, 0x3d, 0x20, 0x28, 0x64, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x32, 0x29, 0x28, 0x79, 0x31, 0x2c, 0x20, 0x79, 0x32, 0x29,
+  0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65,
+  0x32, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65,
+  0x58, 0x20, 0x3d, 0x20, 0x28, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32,
+  0x29, 0x28, 0x70, 0x77, 0x31, 0x2c, 0x20, 0x70, 0x77, 0x32, 0x29, 0x3b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32,
+  0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x59,
+  0x20, 0x3d, 0x20, 0x28, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x29,
+  0x28, 0x70, 0x68, 0x31, 0x2c, 0x20, 0x70, 0x68, 0x32, 0x29, 0x3b, 0x0a,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32,
+  0x20, 0x61, 0x20, 0x3d, 0x20, 0x61, 0x64, 0x64, 0x28, 0x6d, 0x75, 0x6c,
+  0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x28, 0x70, 0x69, 0x78, 0x65, 0x6c,
+  0x53, 0x63, 0x61, 0x6c, 0x65, 0x58, 0x2c, 0x20, 0x28, 0x64, 0x6f, 0x75,
+  0x62, 0x6c, 0x65, 0x29, 0x20, 0x70, 0x78, 0x29, 0x2c, 0x20, 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, 0x64, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x32, 0x20, 0x62, 0x20, 0x3d, 0x20, 0x61, 0x64, 0x64, 0x28,
+  0x6d, 0x75, 0x6c, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x28, 0x70, 0x69,
+  0x78, 0x65, 0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x59, 0x2c, 0x20, 0x28,
+  0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x29, 0x20, 0x70, 0x79, 0x29, 0x2c,
+  0x20, 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, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x63, 0x61, 0x20, 0x3d, 0x20,
+  0x61, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c,
+  0x65, 0x32, 0x20, 0x63, 0x62, 0x20, 0x3d, 0x20, 0x62, 0x3b, 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, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x61, 0x61, 0x20,
+  0x3d, 0x20, 0x6d, 0x75, 0x6c, 0x28, 0x61, 0x2c, 0x20, 0x61, 0x29, 0x3b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75,
+  0x62, 0x6c, 0x65, 0x32, 0x20, 0x62, 0x62, 0x20, 0x3d, 0x20, 0x6d, 0x75,
+  0x6c, 0x28, 0x62, 0x2c, 0x20, 0x62, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32,
+  0x20, 0x61, 0x62, 0x20, 0x3d, 0x20, 0x6d, 0x75, 0x6c, 0x28, 0x61, 0x2c,
+  0x20, 0x62, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x69, 0x66, 0x20, 0x28, 0x61, 0x61, 0x2e, 0x73, 0x30, 0x20, 0x2b,
+  0x20, 0x61, 0x61, 0x2e, 0x73, 0x31, 0x20, 0x2b, 0x20, 0x62, 0x62, 0x2e,
+  0x73, 0x30, 0x20, 0x2b, 0x20, 0x62, 0x62, 0x2e, 0x73, 0x31, 0x20, 0x3e,
+  0x20, 0x31, 0x36, 0x29, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62,
+  0x6c, 0x65, 0x32, 0x20, 0x6d, 0x69, 0x6e, 0x75, 0x73, 0x62, 0x62, 0x20,
+  0x3d, 0x20, 0x28, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x29, 0x28,
+  0x2d, 0x62, 0x62, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x2d, 0x62, 0x62, 0x2e,
+  0x73, 0x31, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x61, 0x20, 0x3d, 0x20, 0x61, 0x64, 0x64, 0x28, 0x61, 0x64, 0x64,
+  0x28, 0x61, 0x61, 0x2c, 0x20, 0x6d, 0x69, 0x6e, 0x75, 0x73, 0x62, 0x62,
+  0x29, 0x2c, 0x20, 0x63, 0x61, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x62, 0x20, 0x3d, 0x20, 0x61, 0x64, 0x64, 0x28,
+  0x61, 0x64, 0x64, 0x28, 0x61, 0x62, 0x2c, 0x20, 0x61, 0x62, 0x29, 0x2c,
+  0x20, 0x63, 0x62, 0x29, 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, 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, 0x2f, 0x20, 0x32,
+  0x29, 0x20, 0x2f, 0x20, 0x6c, 0x6f, 0x67, 0x28, 0x32, 0x2e, 0x30, 0x66,
+  0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 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
+};
+unsigned int doubledouble_cl_len = 2573;