Browse Source

adding double double cl compilation

Nicolas Winkler 4 years ago
parent
commit
709514e961

+ 1 - 5
libmandel/include/ClGenerators.h

@@ -111,8 +111,6 @@ public:
     virtual ~ClGeneratorDouble(void) = default;
     virtual ~ClGeneratorDouble(void) = default;
 
 
     virtual void generate(const MandelInfo& info, float* data) override;
     virtual void generate(const MandelInfo& info, float* data) override;
-protected:
-    virtual std::string getKernelCode(bool smooth) const;
 };
 };
 
 
 
 
@@ -120,12 +118,10 @@ class mnd::ClGeneratorDoubleDouble : public ClGenerator
 {
 {
     bool smooth;
     bool smooth;
 public:
 public:
-    ClGeneratorDoubleDouble(mnd::MandelDevice& device);
+    ClGeneratorDoubleDouble(mnd::MandelDevice& device, const std::string& source = getDoubleDouble_cl());
     virtual ~ClGeneratorDoubleDouble(void) = default;
     virtual ~ClGeneratorDoubleDouble(void) = default;
 
 
     virtual void generate(const MandelInfo& info, float* data) override;
     virtual void generate(const MandelInfo& info, float* data) override;
-protected:
-    virtual std::string getKernelCode(bool smooth) const;
 };
 };
 
 
 
 

+ 6 - 0
libmandel/include/IterationCompiler.h

@@ -33,6 +33,12 @@ namespace mnd
     GeneratorCollection compileFormula(mnd::MandelContext& mndCtxt,
     GeneratorCollection compileFormula(mnd::MandelContext& mndCtxt,
         const IterationFormula& z0,
         const IterationFormula& z0,
         const IterationFormula& zi);
         const IterationFormula& zi);
+
+#ifdef WITH_OPENCL
+    std::unique_ptr<MandelGenerator> compileClFloat(const ir::Formula&, MandelDevice&);
+    std::unique_ptr<MandelGenerator> compileClDouble(const ir::Formula&, MandelDevice&);
+    std::unique_ptr<MandelGenerator> compileClDoubleDouble(const ir::Formula&, MandelDevice&);
+#endif // WITH_OPENCL
 }
 }
 //void squareTest();
 //void squareTest();
 
 

+ 1 - 0
libmandel/include/IterationGenerator.h

@@ -104,6 +104,7 @@ class mnd::CompiledClGeneratorDoubleDouble : public mnd::ClGeneratorDoubleDouble
 public:
 public:
     CompiledClGeneratorDoubleDouble(MandelDevice& device, const std::string& code);
     CompiledClGeneratorDoubleDouble(MandelDevice& device, const std::string& code);
 };
 };
+
 #endif // WITH_OPENCL
 #endif // WITH_OPENCL
 
 
 
 

+ 3 - 0
libmandel/include/OpenClCode.h

@@ -17,6 +17,9 @@ namespace mnd
     std::string getFixed64_cl();
     std::string getFixed64_cl();
     std::string getFixed128_cl();
     std::string getFixed128_cl();
     std::string getFixed512_cl();
     std::string getFixed512_cl();
+
+
+    std::string getDoubleDouble_prelude();
 }
 }
 
 
 #endif // MANDEL_OPENCLCODE_H
 #endif // MANDEL_OPENCLCODE_H

+ 3 - 44
libmandel/src/ClGenerators.cpp

@@ -335,44 +335,9 @@ void ClGeneratorDouble::generate(const mnd::MandelInfo& info, float* data)
 }
 }
 
 
 
 
-std::string ClGeneratorDouble::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, int smooth) {\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 = ab + ab + cb;"
-        "       n++;"
-        "   }\n"
-        // N + 1 - log (log  |Z(N)|) / log 2
-        "   if (n >= max - 1)\n"
-        "       A[index] = max;\n"
-        "   else {"
-        "       if (smooth != 0)\n"
-        "           A[index] = ((float)n) + 1 - log(log((float)(a * a + b * b)) / 2) / log(2.0f);\n"
-        "       else\n"
-        "           A[index] = ((float)n);\n"
-        "   }"
-        "}";
-}
-
-
-ClGeneratorDoubleDouble::ClGeneratorDoubleDouble(mnd::MandelDevice& device) :
-    ClGenerator{ device, getDoubleDouble_cl(), mnd::Precision::DOUBLE_DOUBLE }
+ClGeneratorDoubleDouble::ClGeneratorDoubleDouble(mnd::MandelDevice& device,
+                                                 const std::string& code) :
+    ClGenerator{ device, code, mnd::Precision::DOUBLE_DOUBLE }
 {
 {
     kernel = Kernel(program, "iterate");
     kernel = Kernel(program, "iterate");
 }
 }
@@ -416,12 +381,6 @@ void ClGeneratorDoubleDouble::generate(const mnd::MandelInfo& info, float* data)
 }
 }
 
 
 
 
-std::string ClGeneratorDoubleDouble::getKernelCode(bool smooth) const
-{
-    return getDoubleDouble_cl();
-}
-
-
 ClGeneratorTripleDouble::ClGeneratorTripleDouble(mnd::MandelDevice& device) :
 ClGeneratorTripleDouble::ClGeneratorTripleDouble(mnd::MandelDevice& device) :
     ClGenerator{ device, getTripleDouble_cl(), mnd::Precision::TRIPLE_DOUBLE }
     ClGenerator{ device, getTripleDouble_cl(), mnd::Precision::TRIPLE_DOUBLE }
 {
 {

+ 26 - 7
libmandel/src/IterationCompiler.cpp

@@ -377,7 +377,7 @@ namespace mnd
         static double myAtan2(double y, double x)
         static double myAtan2(double y, double x)
         {
         {
             double result = ::atan2(y, x);
             double result = ::atan2(y, x);
-            printf("atan2(%f, %f) = %f\n", y, x, result);
+            //printf("atan2(%f, %f) = %f\n", y, x, result);
             return result;
             return result;
         }
         }
 
 
@@ -763,10 +763,10 @@ namespace mnd
         return std::make_unique<CompiledClGenerator>(md, compileToOpenCl(formula));
         return std::make_unique<CompiledClGenerator>(md, compileToOpenCl(formula));
     }
     }
 
 
-    std::unique_ptr<MandelGenerator> compileClDouble(const ir::Formula& formula, MandelDevice& md)
+    /*std::unique_ptr<MandelGenerator> compileClDouble(const ir::Formula& formula, MandelDevice& md)
     {
     {
         return std::make_unique<CompiledClGeneratorDouble>(md, compileToOpenClDouble(formula));
         return std::make_unique<CompiledClGeneratorDouble>(md, compileToOpenClDouble(formula));
-    }
+    }*/
 #endif
 #endif
 
 
     std::vector<std::unique_ptr<mnd::MandelGenerator>> compileCpu(mnd::MandelContext& mndCtxt,
     std::vector<std::unique_ptr<mnd::MandelGenerator>> compileCpu(mnd::MandelContext& mndCtxt,
@@ -818,12 +818,31 @@ namespace mnd
         printf("ir: %s\n", irf.toString().c_str()); fflush(stdout);
         printf("ir: %s\n", irf.toString().c_str()); fflush(stdout);
 
 
 #ifdef WITH_OPENCL
 #ifdef WITH_OPENCL
-        auto fl = compileCl(irf, dev);
-        vec.push_back(std::move(fl));
+        try {
+            auto fl = compileClFloat(irf, dev);
+            vec.push_back(std::move(fl));
+        }
+        catch(const std::string& err) {
+            printf("cl error: %s", err.c_str());
+        }
+
         if (dev.supportsDouble()) {
         if (dev.supportsDouble()) {
             irf.clearNodeData();
             irf.clearNodeData();
-            auto fld = compileClDouble(irf, dev);
-            vec.push_back(std::move(fld));
+            try {
+                auto fld = compileClDouble(irf, dev);
+                vec.push_back(std::move(fld));
+            }
+            catch(const std::string& err) {
+                printf("cl error: %s", err.c_str());
+            }
+            irf.clearNodeData();
+            try {
+                auto fldd = compileClDoubleDouble(irf, dev);
+                vec.push_back(std::move(fldd));
+            }
+            catch(const std::string& err) {
+                printf("cl error: %s", err.c_str());
+            }
         }
         }
 #endif // WITH_OPENCL
 #endif // WITH_OPENCL
 
 

+ 273 - 80
libmandel/src/IterationCompilerCl.cpp

@@ -15,25 +15,225 @@
 #include <string>
 #include <string>
 
 
 using namespace std::string_literals;
 using namespace std::string_literals;
+
+#ifdef WITH_OPENCL
 namespace mnd
 namespace mnd
 {
 {
-    struct OpenClDDVisitor
+    struct FloatTraits
     {
     {
-        int varnameCounter = 0;
-        std::stringstream code;
-        std::string floatTypeName;
+        static std::string getPrelude() {
+            return
+                "__kernel void iterate(__global float* A, const int width,"
+                "                      float xl, float yt, float pixelScaleX, float pixelScaleY,"
+                "                      int max, int smooth, int julia, float juliaX, float juliaY) {\n"
+                "   int index = get_global_id(0);\n"
+                "   int ix = index % width;\n"
+                "   int iy = index / width;\n"
+                "   float c_re = ix * pixelScaleX + xl;\n"
+                "   float c_im = iy * pixelScaleY + yt;\n";
+        }
 
 
-        OpenClDDVisitor(int startVarname, const std::string& floatTypeName) :
-            varnameCounter{ startVarname },
-            floatTypeName{ floatTypeName }
-        {
+        static std::string getEscapeCheck() {
+            return "   if (z_re * z_re + z_im * z_im >= 16) break;";
         }
         }
 
 
-        std::string createVarname(void)
-        {
-            return "tmp"s + std::to_string(varnameCounter++);
+        static std::string getPostlude() {
+            return
+                "   if (n >= max - 1) {\n"
+                "       A[index] = max;\n"
+                "   }\n"
+                "   else {\n"
+                "       A[index] = ((float) n);\n"
+                "   }\n"
+                "}\n";
+        }
+
+        static std::string getTypeName() {
+            return "float";
+        }
+
+        static std::string constant(const mnd::Real& v) {
+            return "((float) "s + std::to_string(mnd::convert<float>(v)) + ")";
+        }
+        static std::string neg(const std::string& v) {
+            return "-"s + v;
+        }
+        static std::string add(const std::string& a, const std::string& b) {
+            return "("s + a + ") + (" + b + ")";
+        }
+        static std::string sub(const std::string& a, const std::string& b) {
+            return "("s + a + ") - (" + b + ")";
+        }
+        static std::string mul(const std::string& a, const std::string& b) {
+            return "("s + a + ") * (" + b + ")";
+        }
+        static std::string div(const std::string& a, const std::string& b) {
+            return "("s + a + ") / (" + b + ")";
+        }
+        static std::string atan2(const std::string& a, const std::string& b) {
+            return "atan2("s + a + ", " + b + ")";
+        }
+        static std::string pow(const std::string& a, const std::string& b) {
+            return "pow("s + a + ", " + b + ")";
+        }
+        static std::string cos(const std::string& x) {
+            return "cos("s + x + ")";
+        }
+        static std::string sin(const std::string& x) {
+            return "sin("s + x + ")";
+        }
+        static std::string exp(const std::string& x) {
+            return "exp("s + x + ")";
+        }
+        static std::string ln(const std::string& x) {
+            return "log("s + x + ")";
+        }
+    };
+
+    struct DoubleTraits
+    {
+        static std::string getPrelude() {
+            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, int smooth, int julia, double juliaX, double juliaY) {\n"
+                "   int index = get_global_id(0);\n"
+                "   int ix = index % width;\n"
+                "   int iy = index / width;\n"
+                "   double c_re = ix * pixelScaleX + xl;\n"
+                "   double c_im = iy * pixelScaleY + yt;\n";
+        }
+
+        static std::string getEscapeCheck() {
+            return "   if (z_re * z_re + z_im * z_im >= 16) break;";
+        }
+
+        static std::string getPostlude() {
+            return
+                "   if (n >= max - 1) {\n"
+                "       A[index] = max;\n"
+                "   }\n"
+                "   else {\n"
+                "       A[index] = ((float) n);\n"
+                "   }\n"
+                "}\n";
+        }
+
+        static std::string getTypeName() {
+            return "double";
+        }
+
+        static std::string constant(const mnd::Real& v) {
+            return mnd::toString(v);
+        }
+        static std::string neg(const std::string& v) {
+            return "-"s + v;
+        }
+        static std::string add(const std::string& a, const std::string& b) {
+            return "("s + a + ") + (" + b + ")";
+        }
+        static std::string sub(const std::string& a, const std::string& b) {
+            return "("s + a + ") - (" + b + ")";
+        }
+        static std::string mul(const std::string& a, const std::string& b) {
+            return "("s + a + ") * (" + b + ")";
+        }
+        static std::string div(const std::string& a, const std::string& b) {
+            return "("s + a + ") / (" + b + ")";
+        }
+        static std::string atan2(const std::string& a, const std::string& b) {
+            return "atan2("s + a + ", " + b + ")";
+        }
+        static std::string pow(const std::string& a, const std::string& b) {
+            return "pow("s + a + ", " + b + ")";
+        }
+        static std::string cos(const std::string& x) {
+            return "cos("s + x + ")";
+        }
+        static std::string sin(const std::string& x) {
+            return "sin("s + x + ")";
+        }
+        static std::string exp(const std::string& x) {
+            return "exp("s + x + ")";
+        }
+        static std::string ln(const std::string& x) {
+            return "log("s + x + ")";
+        }
+    };
+
+    struct DoubleDoubleTraits
+    {
+        static std::string getPrelude() {
+            return getDoubleDouble_prelude();
+        }
+
+        static std::string getEscapeCheck() {
+            return "   if (z_re.s0 * z_re.s0 + z_im.s0 * z_im.s0 >= 16) break;";
         }
         }
 
 
+        static std::string getPostlude() {
+            return
+                "   if (n >= max - 1) {\n"
+                "       A[index] = max;\n"
+                "   }\n"
+                "   else {\n"
+                "       A[index] = ((float) n);\n"
+                "   }\n"
+                "}\n";
+        }
+
+        static std::string getTypeName() {
+            return "double2";
+        }
+
+        static std::string constant(const mnd::Real& v) {
+            mnd::DoubleDouble dd = mnd::convert<mnd::DoubleDouble>(v);
+            return "(double2)(" + std::to_string(dd.x[0]) + ", " + std::to_string(dd.x[1]) + ")";
+        }
+        static std::string neg(const std::string& v) {
+            return "(-"s + v + ".s0, -" + v + ".s1)";
+        }
+        static std::string add(const std::string& a, const std::string& b) {
+            return "add("s + a + ", " + b + ")";
+        }
+        static std::string sub(const std::string& a, const std::string& b) {
+            return "add("s + a + ", " + neg(b) + ")";
+        }
+        static std::string mul(const std::string& a, const std::string& b) {
+            return "mul("s + a + ", " + b + ")";
+        }
+        static std::string div(const std::string& a, const std::string& b) {
+            return "div("s + a + ") / (" + b + ")";
+        }
+        static std::string atan2(const std::string& a, const std::string& b) {
+            return "atan2("s + a + ", " + b + ")";
+        }
+        static std::string pow(const std::string& a, const std::string& b) {
+            return "pow("s + a + ", " + b + ")";
+        }
+        static std::string cos(const std::string& x) {
+            return "cos("s + x + ")";
+        }
+        static std::string sin(const std::string& x) {
+            return "sin("s + x + ")";
+        }
+        static std::string exp(const std::string& x) {
+            return "exp("s + x + ")";
+        }
+        static std::string ln(const std::string& x) {
+            return "log("s + x + ")";
+        }
+    };
+
+    template<typename Traits>
+    class ClTranspiler
+    {
+        int varnameCounter = 0;
+        std::stringstream code;
+    public:
+        ClTranspiler(void) = default;
+
         std::string visitNode(ir::Node& node)
         std::string visitNode(ir::Node& node)
         {
         {
             auto& nodeData = std::visit([] (auto& n) -> std::any& { return n.nodeData; }, node);
             auto& nodeData = std::visit([] (auto& n) -> std::any& { return n.nodeData; }, node);
@@ -44,7 +244,7 @@ namespace mnd
                 std::string value = std::visit(*this, node);
                 std::string value = std::visit(*this, node);
                 if (!std::get_if<ir::Variable>(&node) && !std::get_if<ir::Constant>(&node)) {
                 if (!std::get_if<ir::Variable>(&node) && !std::get_if<ir::Constant>(&node)) {
                     std::string varname = createVarname();
                     std::string varname = createVarname();
-                    code << floatTypeName << " " << varname << " = " << value << ";" << std::endl;
+                    code << Traits::getTypeName() << " " << varname << " = " << value << ";" << std::endl;
                     nodeData = varname;
                     nodeData = varname;
                     return varname;
                     return varname;
                 }
                 }
@@ -52,113 +252,106 @@ namespace mnd
             }
             }
         }
         }
 
 
-        std::string operator()(const ir::Constant& c) {
-            return std::to_string(mnd::convert<double>(c.value)) + ((floatTypeName == "float") ? "f" : "");
+        std::string createVarname(void)
+        {
+            return "tmp"s + std::to_string(varnameCounter++);
         }
         }
 
 
+        std::string compile(const ir::Formula& formula)
+        {
+            code << Traits::getPrelude();
+
+            std::string startA = visitNode(*formula.startA);
+            std::string startB = visitNode(*formula.startB);
+
+            code <<
+            "    " << Traits::getTypeName() << " z_re = " << startA << ";\n" <<
+            "    " << Traits::getTypeName() << " z_im = " << startB << ";\n" <<
+            "    int n = 0;\n"
+            "    while (n < max - 1) {\n";
+
+            std::string newA = visitNode(*formula.newA);
+            std::string newB = visitNode(*formula.newB);
+
+            code <<
+            "    z_re = " << newA << ";\n" <<
+            "    z_im = " << newB << ";\n";
+
+            code << Traits::getEscapeCheck();
+            code <<
+            "    n++;\n"
+            "}\n";
+
+            code << Traits::getPostlude();
+            return code.str();
+        }
+
+        std::string operator()(const ir::Constant& c) {
+            return Traits::constant(c.value);
+        }
         std::string operator()(const ir::Variable& v) {
         std::string operator()(const ir::Variable& v) {
             return v.name;
             return v.name;
         }
         }
-
         std::string operator()(const ir::Negation& n) {
         std::string operator()(const ir::Negation& n) {
-            return "-("s + visitNode(*n.value) + ")";
+            return Traits::neg(visitNode(*n.value));
         }
         }
-
         std::string operator()(const ir::Addition& a) {
         std::string operator()(const ir::Addition& a) {
-            return "("s + visitNode(*a.left) + ") + (" + visitNode(*a.right) + ")";
+            return Traits::add(visitNode(*a.left), visitNode(*a.right));
         }
         }
-
         std::string operator()(const ir::Subtraction& a) {
         std::string operator()(const ir::Subtraction& a) {
-            return "("s + visitNode(*a.left) + ") - (" + visitNode(*a.right) + ")";
+            return Traits::sub(visitNode(*a.left), visitNode(*a.right));
         }
         }
-
         std::string operator()(const ir::Multiplication& a) {
         std::string operator()(const ir::Multiplication& a) {
-            return "("s + visitNode(*a.left) + ") * (" + visitNode(*a.right) + ")";
+            return Traits::mul(visitNode(*a.left), visitNode(*a.right));
         }
         }
-
         std::string operator()(const ir::Division& a) {
         std::string operator()(const ir::Division& a) {
-            return "("s + visitNode(*a.left) + ") / (" + visitNode(*a.right) + ")";
+            return Traits::div(visitNode(*a.left), visitNode(*a.right));
         }
         }
-
         std::string operator()(const ir::Atan2& a) {
         std::string operator()(const ir::Atan2& a) {
-            return "atan2("s + visitNode(*a.left) + ", " + visitNode(*a.right) + ")";
+            return Traits::atan2(visitNode(*a.left), visitNode(*a.right));
         }
         }
-
         std::string operator()(const ir::Pow& a) {
         std::string operator()(const ir::Pow& a) {
-            return "pow("s + visitNode(*a.left) + ", " + visitNode(*a.right) + ")";
+            return Traits::pow(visitNode(*a.left), visitNode(*a.right));
         }
         }
-
         std::string operator()(const ir::Cos& a) {
         std::string operator()(const ir::Cos& a) {
-            return "cos("s + visitNode(*a.value) + ")";
+            return Traits::cos(visitNode(*a.value));
         }
         }
 
 
         std::string operator()(const ir::Sin& a) {
         std::string operator()(const ir::Sin& a) {
-            return "sin("s + visitNode(*a.value) + ")";
+            return Traits::sin(visitNode(*a.value));
         }
         }
 
 
         std::string operator()(const ir::Exp& a) {
         std::string operator()(const ir::Exp& a) {
-            return "exp("s + visitNode(*a.value) + ")";
+            return Traits::exp(visitNode(*a.value));
         }
         }
 
 
         std::string operator()(const ir::Ln& a) {
         std::string operator()(const ir::Ln& a) {
-            return "log("s + visitNode(*a.value) + ")";
+            return Traits::ln(visitNode(*a.value));
         }
         }
     };
     };
 
 
-    std::string compileToOpenClDoubleDouble(const ir::Formula& formula)
+    std::unique_ptr<MandelGenerator> compileClFloat(const ir::Formula& formula, MandelDevice& md)
     {
     {
-        OpenClDDVisitor z0Visitor{ 0, "double2" };
-        std::string startA = z0Visitor.visitNode(*formula.startA);
-        std::string startB = z0Visitor.visitNode(*formula.startB);
-
-        OpenClDDVisitor ocv{ z0Visitor.varnameCounter, "double2" };
-        std::string newA = ocv.visitNode(*formula.newA);
-        std::string newB = ocv.visitNode(*formula.newB);
-
-        std::string prelude =
-            "#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, int smooth, int julia, double juliaX, double juliaY) {\n"
-            "   int index = get_global_id(0);\n"
-            "   int ix = index % width;\n"
-            "   int iy = index / width;\n"
-            "   double c_re = ix * pixelScaleX + xl;\n"
-            "   double c_im = iy * pixelScaleY + yt;\n";
-        prelude += z0Visitor.code.str() +
-            "   double z_re = " + startA + ";\n" +
-            "   double z_im = " + startB + ";\n" +
-            "\n"
-            "   int n = 0;\n"
-            "   while (n < max - 1) {\n";
-
-        std::string after = 
-            "       if (z_re * z_re + z_im * z_im > 16) break;\n"
-            "       n++;\n"
-            "   }\n"
-            "   if (n >= max - 1) {\n"
-            "       A[index] = max;\n"
-            "   }\n"
-            "   else {\n"
-            "       A[index] = ((float)n);\n"
-            "   }\n"
-            "}\n";
-
+        ClTranspiler<FloatTraits> clt;
+        std::string code = clt.compile(formula);
+        return std::make_unique<CompiledClGenerator>(md, code);
+    }
 
 
-        std::string code = prelude + ocv.code.str();
-        code += "z_re = " + newA + ";\n";
-        code += "z_im = " + newB + ";\n";
-        code += after;
-        //code = mnd::getFloat_cl();
-        printf("cld: %s\n", code.c_str()); fflush(stdout);
-        return code;
+    std::unique_ptr<MandelGenerator> compileClDouble(const ir::Formula& formula, MandelDevice& md)
+    {
+        ClTranspiler<DoubleTraits> clt;
+        std::string code = clt.compile(formula);
+        return std::make_unique<CompiledClGeneratorDouble>(md, code);
     }
     }
 
 
-#ifdef WITH_OPENCL
     std::unique_ptr<MandelGenerator> compileClDoubleDouble(const ir::Formula& formula, MandelDevice& md)
     std::unique_ptr<MandelGenerator> compileClDoubleDouble(const ir::Formula& formula, MandelDevice& md)
     {
     {
-        return nullptr;
-        //return std::make_unique<CompiledClGeneratorDouble>(md, compileToOpenClDouble(formula));
+        ClTranspiler<DoubleDoubleTraits> clt;
+        std::string code = clt.compile(formula);
+        printf("doubledouble cl code: %s", code.c_str());
+        return std::make_unique<CompiledClGeneratorDoubleDouble>(md, code);
     }
     }
-#endif
 }
 }
 
 
+#endif
 
 

+ 1 - 1
libmandel/src/IterationGenerator.cpp

@@ -261,7 +261,7 @@ CompiledClGeneratorDouble::CompiledClGeneratorDouble(mnd::MandelDevice& device,
 
 
 
 
 CompiledClGeneratorDoubleDouble::CompiledClGeneratorDoubleDouble(mnd::MandelDevice& device, const std::string& code) :
 CompiledClGeneratorDoubleDouble::CompiledClGeneratorDoubleDouble(mnd::MandelDevice& device, const std::string& code) :
-    ClGeneratorDoubleDouble{ device } // TODO make this const take code as arg
+    ClGeneratorDoubleDouble{ device, code }
 {
 {
 }
 }
 
 

+ 6 - 1
libmandel/src/IterationIR.cpp

@@ -166,7 +166,12 @@ namespace mnd
 
 
             if (p.integerExponent) {
             if (p.integerExponent) {
                 if (auto* ex = std::get_if<ir::Constant>(c)) {
                 if (auto* ex = std::get_if<ir::Constant>(c)) {
-                    return intPow({ a, b }, int(ex->value));
+                    if (int(ex->value) <= 20) {
+                        return intPow({ a, b }, int(ex->value));
+                    }
+                    else {
+                        return realPow({ a, b }, c);
+                    }
                 }
                 }
             }
             }
             if (p.realExponent) {
             if (p.realExponent) {

+ 6 - 0
libmandel/src/OpenClCode.cpp

@@ -14,6 +14,8 @@
 #include "opencl/fixed128.h"
 #include "opencl/fixed128.h"
 #include "opencl/fixed512.h"
 #include "opencl/fixed512.h"
 
 
+#include "opencl_template/doubledouble_prelude.h"
+
 namespace mnd
 namespace mnd
 {
 {
     std::string getFloat_cl() {
     std::string getFloat_cl() {
@@ -63,6 +65,10 @@ namespace mnd
     std::string getFixed512_cl() {
     std::string getFixed512_cl() {
         return std::string{ (char*) fixed512_cl, fixed512_cl_len };
         return std::string{ (char*) fixed512_cl, fixed512_cl_len };
     }
     }
+
+    std::string getDoubleDouble_prelude() {
+        return std::string{ (char*) doubledouble_prelude_cl, doubledouble_prelude_cl_len };
+    }
 }
 }
 
 
 
 

+ 0 - 231
libmandel/src/opencl_template/doubledouble.h

@@ -1,231 +0,0 @@
-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, 0x0d, 0x0a, 0x0d,
-  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, 0x0d, 0x0a, 0x20, 0x20,
-  0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x73, 0x20, 0x3d,
-  0x20, 0x61, 0x20, 0x2b, 0x20, 0x62, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
-  0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x62, 0x62, 0x20, 0x3d,
-  0x20, 0x73, 0x20, 0x2d, 0x20, 0x61, 0x3b, 0x0d, 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, 0x0d, 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, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a,
-  0x0d, 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, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62,
-  0x6c, 0x65, 0x20, 0x73, 0x20, 0x3d, 0x20, 0x61, 0x20, 0x2b, 0x20, 0x62,
-  0x3b, 0x0d, 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, 0x0d, 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, 0x0d,
-  0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 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, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62,
-  0x6c, 0x65, 0x20, 0x70, 0x20, 0x3d, 0x20, 0x61, 0x20, 0x2a, 0x20, 0x62,
-  0x3b, 0x0d, 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, 0x0d, 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, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 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, 0x0d, 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, 0x0d, 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, 0x0d, 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, 0x0d,
-  0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65,
-  0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x73, 0x71, 0x28,
-  0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x61, 0x29, 0x20, 0x7b,
-  0x0d, 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, 0x61, 0x2e, 0x73, 0x30,
-  0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62,
-  0x6c, 0x65, 0x20, 0x65, 0x20, 0x3d, 0x20, 0x32, 0x20, 0x2a, 0x20, 0x61,
-  0x2e, 0x73, 0x30, 0x20, 0x2a, 0x20, 0x61, 0x2e, 0x73, 0x31, 0x3b, 0x0d,
-  0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x2e, 0x73, 0x31, 0x20, 0x2b, 0x3d,
-  0x20, 0x65, 0x3b, 0x0d, 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, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 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, 0x0d, 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, 0x0d, 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, 0x0d, 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, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 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, 0x0d, 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, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
-  0x70, 0x2e, 0x73, 0x31, 0x20, 0x2b, 0x3d, 0x20, 0x61, 0x2e, 0x73, 0x31,
-  0x20, 0x2a, 0x20, 0x62, 0x3b, 0x0d, 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, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d,
-  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, 0x0d, 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, 0x0d, 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,
-  0x2c, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-  0x20, 0x69, 0x6e, 0x74, 0x20, 0x6a, 0x75, 0x6c, 0x69, 0x61, 0x2c, 0x20,
-  0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x6a, 0x78, 0x31, 0x2c, 0x20,
-  0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x6a, 0x78, 0x32, 0x2c, 0x20,
-  0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x6a, 0x79, 0x31, 0x2c, 0x20,
-  0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x6a, 0x79, 0x32, 0x29, 0x20,
-  0x7b, 0x0d, 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,
-  0x0d, 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, 0x0d, 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, 0x0d, 0x0a,
-  0x0d, 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, 0x0d, 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, 0x0d, 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, 0x0d, 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, 0x0d, 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, 0x0d, 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, 0x0d, 0x0a,
-  0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20,
-  0x63, 0x61, 0x20, 0x3d, 0x20, 0x6a, 0x75, 0x6c, 0x69, 0x61, 0x20, 0x21,
-  0x3d, 0x20, 0x30, 0x20, 0x3f, 0x20, 0x28, 0x28, 0x64, 0x6f, 0x75, 0x62,
-  0x6c, 0x65, 0x32, 0x29, 0x20, 0x28, 0x6a, 0x78, 0x31, 0x2c, 0x20, 0x6a,
-  0x78, 0x32, 0x29, 0x29, 0x20, 0x3a, 0x20, 0x61, 0x3b, 0x0d, 0x0a, 0x20,
-  0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x63,
-  0x62, 0x20, 0x3d, 0x20, 0x6a, 0x75, 0x6c, 0x69, 0x61, 0x20, 0x21, 0x3d,
-  0x20, 0x30, 0x20, 0x3f, 0x20, 0x28, 0x28, 0x64, 0x6f, 0x75, 0x62, 0x6c,
-  0x65, 0x32, 0x29, 0x20, 0x28, 0x6a, 0x79, 0x31, 0x2c, 0x20, 0x6a, 0x79,
-  0x32, 0x29, 0x29, 0x20, 0x3a, 0x20, 0x62, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a,
-  0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x6e, 0x20,
-  0x3d, 0x20, 0x30, 0x3b, 0x0d, 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, 0x0d, 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, 0x0d, 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, 0x0d, 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, 0x0d, 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, 0x0d, 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, 0x0d, 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, 0x0d, 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, 0x0d,
-  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x2b, 0x2b,
-  0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 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, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66,
-  0x20, 0x28, 0x6e, 0x20, 0x3e, 0x3d, 0x20, 0x6d, 0x61, 0x78, 0x20, 0x2d,
-  0x20, 0x31, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-  0x20, 0x41, 0x5b, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x20, 0x3d, 0x20,
-  0x6d, 0x61, 0x78, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c,
-  0x73, 0x65, 0x20, 0x7b, 0x0d, 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, 0x0d, 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, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
-  0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0d, 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, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
-  0x20, 0x20, 0x7d, 0x0d, 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, 0x0d, 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, 0x0d,
-  0x0a, 0x7d
-};
-unsigned int doubledouble_cl_len = 2726;

+ 12 - 29
libmandel/src/opencl_template/doubledouble.cl → libmandel/src/opencl_template/doubledouble_prelude.cl

@@ -44,6 +44,16 @@ inline double2 mulDouble(double2 a, double b) {
     return quickTwoSum(p.s0, p.s1);
     return quickTwoSum(p.s0, p.s1);
 }
 }
 
 
+inline double2 div(double2 a, double2 b) {
+    double q1 = a.s0 / b.s0;
+    double2 r = mulDouble(b, q1);
+    double2 s = twoSum(a.s0, -r.s0);
+    s.s1 -= r.s1;
+    s.s1 += a.s1;
+    double q2 = (s.s0 + s.s1) / b.s0;
+    return quickTwoSum(q1, q2);
+}
+
 __kernel void iterate(__global float* A, const int width,
 __kernel void iterate(__global float* A, const int width,
                       double x1, double x2, double y1, double y2,
                       double x1, double x2, double y1, double y2,
                       double pw1, double pw2, double ph1, double ph2, int max, int smooth,
                       double pw1, double pw2, double ph1, double ph2, int max, int smooth,
@@ -56,33 +66,6 @@ __kernel void iterate(__global float* A, const int width,
     double2 yt = (double2)(y1, y2);
     double2 yt = (double2)(y1, y2);
     double2 pixelScaleX = (double2)(pw1, pw2);
     double2 pixelScaleX = (double2)(pw1, pw2);
     double2 pixelScaleY = (double2)(ph1, ph2);
     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 = julia != 0 ? ((double2) (jx1, jx2)) : a;
-    double2 cb = julia != 0 ? ((double2) (jy1, jy2)) : b;
-
-
-    int n = 0;
-    while (n < max - 1) {
-        double2 aa = mul(a, a);
-        double2 bb = mul(b, b);
-        double2 ab = mul(a, b);
-        double2 minusbb = (double2)(-bb.s0, -bb.s1);
-        a = add(add(aa, minusbb), ca);
-        b = add(add(ab, ab), cb);
-        if (aa.s0 + bb.s0 > 16) break;
-        n++;
-    }
+    double2 c_re = add(mulDouble(pixelScaleX, (double) px), xl); // pixelScaleX * px + xl
+    double2 c_im = add(mulDouble(pixelScaleY, (double) py), yt); // pixelScaleY * py + yt
 
 
-    // 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;
-}

+ 175 - 0
libmandel/src/opencl_template/doubledouble_prelude.h

@@ -0,0 +1,175 @@
+unsigned char doubledouble_prelude_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,
+  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, 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, 0x73, 0x71, 0x28, 0x64, 0x6f, 0x75,
+  0x62, 0x6c, 0x65, 0x32, 0x20, 0x61, 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, 0x61, 0x2e, 0x73, 0x30, 0x29, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x65, 0x20,
+  0x3d, 0x20, 0x32, 0x20, 0x2a, 0x20, 0x61, 0x2e, 0x73, 0x30, 0x20, 0x2a,
+  0x20, 0x61, 0x2e, 0x73, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70,
+  0x2e, 0x73, 0x31, 0x20, 0x2b, 0x3d, 0x20, 0x65, 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, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x64, 0x6f,
+  0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x64, 0x69, 0x76, 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, 0x20, 0x71, 0x31, 0x20,
+  0x3d, 0x20, 0x61, 0x2e, 0x73, 0x30, 0x20, 0x2f, 0x20, 0x62, 0x2e, 0x73,
+  0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c,
+  0x65, 0x32, 0x20, 0x72, 0x20, 0x3d, 0x20, 0x6d, 0x75, 0x6c, 0x44, 0x6f,
+  0x75, 0x62, 0x6c, 0x65, 0x28, 0x62, 0x2c, 0x20, 0x71, 0x31, 0x29, 0x3b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x32,
+  0x20, 0x73, 0x20, 0x3d, 0x20, 0x74, 0x77, 0x6f, 0x53, 0x75, 0x6d, 0x28,
+  0x61, 0x2e, 0x73, 0x30, 0x2c, 0x20, 0x2d, 0x72, 0x2e, 0x73, 0x30, 0x29,
+  0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x2e, 0x73, 0x31, 0x20, 0x2d,
+  0x3d, 0x20, 0x72, 0x2e, 0x73, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x73, 0x2e, 0x73, 0x31, 0x20, 0x2b, 0x3d, 0x20, 0x61, 0x2e, 0x73, 0x31,
+  0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65,
+  0x20, 0x71, 0x32, 0x20, 0x3d, 0x20, 0x28, 0x73, 0x2e, 0x73, 0x30, 0x20,
+  0x2b, 0x20, 0x73, 0x2e, 0x73, 0x31, 0x29, 0x20, 0x2f, 0x20, 0x62, 0x2e,
+  0x73, 0x30, 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, 0x71, 0x31, 0x2c, 0x20, 0x71, 0x32, 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,
+  0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x69, 0x6e, 0x74, 0x20, 0x6a, 0x75, 0x6c, 0x69, 0x61, 0x2c, 0x20, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x6a, 0x78, 0x31, 0x2c, 0x20, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x6a, 0x78, 0x32, 0x2c, 0x20, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x6a, 0x79, 0x31, 0x2c, 0x20, 0x64,
+  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x6a, 0x79, 0x32, 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, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f,
+  0x75, 0x62, 0x6c, 0x65, 0x32, 0x20, 0x63, 0x5f, 0x72, 0x65, 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,
+  0x63, 0x5f, 0x69, 0x6d, 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, 0x0a
+};
+unsigned int doubledouble_prelude_cl_len = 2059;