Nicolas Winkler há 5 anos atrás
pai
commit
ef9fc44e53

+ 20 - 3
Almond.cpp

@@ -7,7 +7,7 @@
 
 #include <cmath>
 
-Almond::Almond(QWidget *parent) :
+Almond::Almond(QWidget* parent) :
     QMainWindow{ parent },
     mandelContext{ mnd::initializeContext() }
 {
@@ -25,11 +25,13 @@ void Almond::on_zoom_out_clicked()
     mw->zoom(2);
 }
 
+
 void Almond::on_zoom_in_clicked()
 {
     mw->zoom(0.5);
 }
 
+
 void Almond::on_maxIterations_editingFinished()
 {
     QString text = ui.maxIterations->text();
@@ -37,6 +39,7 @@ void Almond::on_maxIterations_editingFinished()
     mw->setMaxIterations(maxIter);
 }
 
+
 void Almond::on_chooseGradient_clicked()
 {
     auto response = gcd.exec();
@@ -45,6 +48,7 @@ void Almond::on_chooseGradient_clicked()
         mw->setGradient(std::move(*gradient));
 }
 
+
 void Almond::on_exportVideo_clicked()
 {
     ExportVideoInfo evi;
@@ -73,11 +77,13 @@ void Almond::on_exportVideo_clicked()
     }
 }
 
+
 void Almond::on_smooth_stateChanged(int checked)
 {
     this->mw->setSmoothColoring(checked != Qt::Unchecked);
 }
 
+
 void Almond::on_runBenchmark_clicked()
 {
     if (!benchmarkDialog)
@@ -85,6 +91,7 @@ void Almond::on_runBenchmark_clicked()
     benchmarkDialog->exec();
 }
 
+
 void Almond::on_exportImage_clicked()
 {
     ExportImageDialog dialog(this);
@@ -97,23 +104,33 @@ void Almond::on_exportImage_clicked()
         mi.bWidth = dialog.getWidth();
         mi.bHeight = dialog.getHeight();
         mi.view.adjustAspectRatio(mi.bWidth, mi.bHeight);
-        mnd::Generator& g = mandelContext.getDefaultGenerator(this->mw->getSmoothColoring());
+        mnd::Generator& g = mandelContext.getDefaultGenerator();
         auto fmap = Bitmap<float>(mi.bWidth, mi.bHeight);
         g.generate(mi, fmap.pixels.get());
         auto bitmap = fmap.map<RGBColor>([&mi, this] (float i) {
             return i >= mi.maxIter ? RGBColor{ 0,0,0 } : mw->getGradient().get(i);
         });
-        QImage img((unsigned char*) bitmap.pixels.get(), bitmap.width, bitmap.height, bitmap.width * 3, QImage::Format_RGB888);
+        QImage img(reinterpret_cast<unsigned char*>(bitmap.pixels.get()), bitmap.width, bitmap.height, bitmap.width * 3, QImage::Format_RGB888);
         img.save(dialog.getPath());
     }
 }
 
+
 void Almond::on_resetZoom_clicked()
 {
     mw->setViewport(mnd::MandelViewport::standardView());
 }
 
+
 void Almond::on_displayInfo_stateChanged(int checked)
 {
     this->mw->setDisplayInfo(checked != Qt::Unchecked);
 }
+
+
+void Almond::on_chooseGenerator_clicked()
+{
+    if (!generatorsDialog)
+        generatorsDialog = std::make_unique<ChooseGenerators>(this);
+    generatorsDialog->exec();
+}

+ 4 - 0
Almond.h

@@ -7,6 +7,7 @@
 #include "MandelWidget.h"
 #include "exportdialogs.h"
 #include "gradientchoosedialog.h"
+#include "choosegenerators.h"
 #include "benchmarkdialog.h"
 
 #include <memory>
@@ -18,6 +19,7 @@ private:
     mnd::MandelContext mandelContext;
     std::unique_ptr<MandelWidget> mw;
     std::unique_ptr<BenchmarkDialog> benchmarkDialog;
+    std::unique_ptr<ChooseGenerators> generatorsDialog;
     GradientChooseDialog gcd;
 public:
     Almond(QWidget *parent = Q_NULLPTR);
@@ -35,6 +37,8 @@ private slots:
 
     void on_displayInfo_stateChanged(int arg1);
 
+    void on_chooseGenerator_clicked();
+
 private:
     Ui::AlmondClass ui;
 };

+ 3 - 0
Almond.pro

@@ -36,6 +36,7 @@ SOURCES += \
         MandelWidget.cpp \
         VideoStream.cpp \
         benchmarkdialog.cpp \
+        choosegenerators.cpp \
         exportdialogs.cpp \
         gradientchoosedialog.cpp \
         main.cpp
@@ -51,12 +52,14 @@ HEADERS += \
         MandelWidget.h \
         VideoStream.h \
         benchmarkdialog.h \
+        choosegenerators.h \
         exportdialogs.h \
         gradientchoosedialog.h
 
 FORMS += \
         Almond.ui \
         benchmarks.ui \
+        choosegenerators.ui \
         exportimagedialog.ui \
         exportvideodialog.ui \
         gradientchooser.ui

+ 7 - 0
Almond.ui

@@ -173,6 +173,13 @@
         </widget>
        </item>
        <item>
+        <widget class="QPushButton" name="chooseGenerator">
+         <property name="text">
+          <string>Select Generators</string>
+         </property>
+        </widget>
+       </item>
+       <item>
         <widget class="QPushButton" name="exportVideo">
          <property name="text">
           <string>Export Video</string>

+ 1 - 1
Bitmap.h

@@ -35,7 +35,7 @@ public:
     template<typename T>
     Bitmap<T> map(std::function<T(Pixel)> f) const {
         Bitmap<T> b{ width, height };
-        for (::size_t i = 0; i < width * height; i++) {
+        for (long i = 0; i < width * height; i++) {
             b.pixels[i] = f(pixels[i]);
         }
         return b;

+ 27 - 13
MandelWidget.cpp

@@ -224,7 +224,8 @@ void Job::run(void)
     mi->view.y = absY;
     mi->view.width = mi->view.height = gw;
     mi->bWidth = mi->bHeight = MandelView::chunkSize;
-    mi->maxIter = maxIter;
+    mi->maxIter = owner.getMaxIterations();
+    mi->smooth = owner.getSmoothColoring();
     generator->generate(*mi, f.pixels.get());
     auto* rgb = new Bitmap<RGBColor>(f.map<RGBColor>([&mi, this](float i) {
         return i >= mi->maxIter ? RGBColor{ 0, 0, 0 } : gradient.get(i);
@@ -233,6 +234,19 @@ void Job::run(void)
 }
 
 
+Calcer::Calcer(mnd::Generator* generator, MandelWidget& owner, int maxIter, bool smooth) :
+    generator{ generator },
+    jobsMutex{ QMutex::Recursive },
+    owner{ owner },
+    gradient{ owner.getGradient() },
+    threadPool{ std::make_unique<QThreadPool>() },
+    maxIter{ maxIter },
+    smooth{ smooth }
+{
+    threadPool->setMaxThreadCount(1);
+}
+
+
 void Calcer::setMaxIter(int maxIter)
 {
     this->maxIter = maxIter;
@@ -251,7 +265,7 @@ void Calcer::calc(TexGrid& grid, int level, GridIndex i, GridIndex j, int priori
 {
     jobsMutex.lock();
     if (jobs.find({ level, i, j }) == jobs.end()) {
-        Job* job = new Job(generator, gradient, maxIter, &grid, level, i, j, calcState);
+        Job* job = new Job(generator, gradient, owner, &grid, level, i, j, calcState);
         connect(job, &Job::done, this, &Calcer::redirect);
         connect(job, &QObject::destroyed, this, [this, level, i, j] () { this->notFinished(level, i, j); });
         jobs.emplace(std::tuple{level, i, j}, job);
@@ -309,7 +323,7 @@ const int MandelView::chunkSize = 256;
 
 MandelView::MandelView(mnd::Generator* generator, MandelWidget& owner, int maxIter) :
     generator{ generator },
-    calcer{ generator, owner.getGradient(), maxIter },
+    calcer{ generator, owner, maxIter, owner.getSmoothColoring() },
     owner{ owner },
     maxIter{ maxIter }
 {
@@ -600,7 +614,7 @@ void MandelWidget::setSmoothColoring(bool sc)
         this->smoothColoring = sc;
         if (mandelView) {
             mandelView->clearCells();
-            mandelView->setGenerator(&mndContext.getDefaultGenerator(smoothColoring));
+            emit update();
         }
     }
 }
@@ -615,6 +629,14 @@ void MandelWidget::setDisplayInfo(bool di)
 }
 
 
+void MandelWidget::setMaxIterations(int maxIter)
+{
+    this->maxIterations = maxIter;
+    if (mandelView)
+        mandelView->setMaxIter(maxIter);
+}
+
+
 void MandelWidget::initializeGL(void)
 {
     this->context()->functions()->glClearColor(0, 0, 0, 0);
@@ -635,7 +657,7 @@ void MandelWidget::initializeGL(void)
 void MandelWidget::paintGL(void)
 {
     if (mandelView == nullptr) {
-        mandelView = std::make_unique<MandelView>(&mndContext.getDefaultGenerator(smoothColoring), *this, maxIterations);
+        mandelView = std::make_unique<MandelView>(&mndContext.getDefaultGenerator(), *this, maxIterations);
         QObject::connect(mandelView.get(), &MandelView::redrawRequested, this, static_cast<void(QOpenGLWidget::*)(void)>(&QOpenGLWidget::update));
     }
 
@@ -776,14 +798,6 @@ void MandelWidget::setViewport(const mnd::MandelViewport& viewport)
 }
 
 
-void MandelWidget::setMaxIterations(int maxIter)
-{
-    this->maxIterations = maxIter;
-    if (mandelView)
-        mandelView->setMaxIter(maxIter);
-}
-
-
 void MandelWidget::requestRecalc()
 {
     emit update();

+ 10 - 15
MandelWidget.h

@@ -171,21 +171,21 @@ class Job : public QObject, public QRunnable
 public:
     mnd::Generator* generator;
     const Gradient& gradient;
-    int maxIter;
+    MandelWidget& owner;
     TexGrid* grid;
     int level;
     GridIndex i, j;
     long calcState = 0;
 
-    inline Job( mnd::Generator* generator,
+    inline Job(mnd::Generator* generator,
                const Gradient& gradient,
-               int maxIter,
+               MandelWidget& owner,
                TexGrid* grid,
                int level, GridIndex i, GridIndex j,
                long calcState) :
         generator{ generator },
         gradient{ gradient },
-        maxIter{ maxIter },
+        owner{ owner },
         grid{ grid },
         level{ level },
         i{ i }, j{ j },
@@ -206,22 +206,15 @@ class Calcer : public QObject
     QMutex jobsMutex;
     mnd::Generator* generator;
     std::unique_ptr<QThreadPool> threadPool;
+    MandelWidget& owner;
     const Gradient& gradient;
     int maxIter;
+    bool smooth;
     int currentLevel;
 
     volatile long calcState = 0;
 public:
-    inline Calcer(mnd::Generator* generator, const Gradient& gradient, int maxIter) :
-        jobsMutex{ QMutex::Recursive },
-        generator{ generator },
-        threadPool{ std::make_unique<QThreadPool>() },
-        gradient{ gradient },
-        maxIter{ maxIter }
-    {
-        threadPool->setMaxThreadCount(1);
-    }
-
+    Calcer(mnd::Generator* generator, MandelWidget& owner, int maxIter, bool smooth);
     void setMaxIter(int maxIter);
     void clearAll(void);
     void setGenerator(mnd::Generator* generator) { this->generator = generator; changeState(); }
@@ -318,6 +311,9 @@ public:
     inline bool doesDisplayInfo(void) const { return displayInfo; }
     void setDisplayInfo(bool di);
 
+    inline int getMaxIterations(void) const { return maxIterations; }
+    void setMaxIterations(int maxIter);
+
     void initializeGL(void) override;
     void paintGL() override;
 
@@ -330,7 +326,6 @@ public:
 
     void zoom(float scale, float x = 0.5f, float y = 0.5f);
     void setViewport(const mnd::MandelViewport& viewport);
-    void setMaxIterations(int maxIter);
 
     void requestRecalc(void);
 

+ 19 - 0
choosegenerators.cpp

@@ -0,0 +1,19 @@
+#include "choosegenerators.h"
+#include "ui_choosegenerators.h"
+
+#include <QComboBox>
+
+ChooseGenerators::ChooseGenerators(QWidget *parent) :
+    QDialog{ parent },
+    ui{ std::make_unique<Ui::ChooseGenerators>() }
+{
+    ui->setupUi(this);
+
+    ui->table->insertRow(0);
+    ui->table->setCellWidget(0, 1, new QComboBox(ui->table));
+}
+
+
+ChooseGenerators::~ChooseGenerators()
+{
+}

+ 26 - 0
choosegenerators.h

@@ -0,0 +1,26 @@
+#ifndef CHOOSEGENERATORS_H
+#define CHOOSEGENERATORS_H
+
+#include <QDialog>
+#include <memory>
+
+namespace Ui
+{
+    class ChooseGenerators;
+}
+
+
+class ChooseGenerators : public QDialog
+{
+    Q_OBJECT
+private:
+    std::unique_ptr<Ui::ChooseGenerators> ui;
+public:
+    explicit ChooseGenerators(QWidget* parent = nullptr);
+    ~ChooseGenerators();
+
+
+};
+
+#endif // CHOOSEGENERATORS_H
+

+ 81 - 0
choosegenerators.ui

@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ChooseGenerators</class>
+ <widget class="QDialog" name="ChooseGenerators">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>647</width>
+    <height>377</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QTableWidget" name="table">
+     <property name="columnCount">
+      <number>2</number>
+     </property>
+     <column>
+      <property name="text">
+       <string>Precision</string>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>Generator</string>
+      </property>
+     </column>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>ChooseGenerators</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>ChooseGenerators</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>

+ 1 - 1
libmandel/include/Fixed.h

@@ -547,7 +547,7 @@ struct Fixed32
 
     inline Fixed32(double x)
     {
-        int integerPart = ::floor(x);
+        int integerPart = int(::floor(x));
         double fractionalPart = x - integerPart;
         /*if (x < 0) {
             integerPart--;

+ 1 - 1
libmandel/include/Generators.h

@@ -23,7 +23,7 @@ namespace mnd
         FLOAT128,
         QUAD_DOUBLE,
         FLOAT256,
-        INFINITE
+        INF_PREC,
     };
 
     Real getPrecision(Precision p);

+ 9 - 3
libmandel/include/Mandel.h

@@ -54,13 +54,15 @@ private:
 
     MandelDevice(void);
 public:
+    MandelDevice(const MandelDevice&) = delete;
+    MandelDevice(MandelDevice&&) = default;
+    MandelDevice& operator=(const MandelDevice&) = delete;
+    MandelDevice& operator=(MandelDevice&&) = default;
 
     inline const std::string& getVendor(void) const { return vendor; }
     inline const std::string& getName(void) const { return name; }
 
     Generator* getGenerator(GeneratorType type) const;
-    //Generator* getGeneratorQuad(bool smooth = true) const;
-    //Generator* getGenerator128(bool smooth = true) const;
 };
 
 
@@ -82,8 +84,12 @@ private:
     std::unique_ptr<AdaptiveGenerator> createAdaptiveGenerator(void);
     std::vector<MandelDevice> createDevices(void);
 public:
+    MandelContext(const MandelContext&) = delete;
+    MandelContext(MandelContext&&) = default;
+    MandelContext& operator=(const MandelContext&) = delete;
+    MandelContext& operator=(MandelContext&&) = default;
 
-    Generator& getDefaultGenerator(bool smooth = true);
+    Generator& getDefaultGenerator(void);
     const std::vector<MandelDevice>& getDevices(void);
 
     Generator* getCpuGenerator(mnd::GeneratorType type);

+ 63 - 126
libmandel/src/ClGenerators.cpp

@@ -100,6 +100,7 @@ void ClGenerator::generate(const mnd::MandelInfo& info, float* data)
     iterate.setArg(4, float(pixelScaleX));
     iterate.setArg(5, float(pixelScaleY));
     iterate.setArg(6, int(info.maxIter));
+    iterate.setArg(7, int(info.smooth ? 1 : 0));
 
     // TODO check for overflow
     if (false && device.getInfo<CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT>() == 4) {
@@ -114,8 +115,6 @@ void ClGenerator::generate(const mnd::MandelInfo& info, float* data)
 ClGeneratorFloat::ClGeneratorFloat(cl::Device device) :
     ClGenerator{ device }
 {
-    /*Platform p = getPlatform();
-    device = getDevice(p, 0, true);*/
     context = Context{ device };
     Program::Sources sources;
 
@@ -134,68 +133,36 @@ ClGeneratorFloat::ClGeneratorFloat(cl::Device device) :
 
 std::string ClGeneratorFloat::getKernelCode(bool smooth) const
 {
-    if (smooth) {
-        return 
-    //        "#pragma OPENCL EXTENSION cl_khr_fp64 : enable"
-            "__kernel void iterate(__global float* A, const int width, float xl, float yt, float pixelScaleX, float pixelScaleY, int max) {"
-            "   int index = get_global_id(0);\n"
-            "   int x = index % width;"
-            "   int y = index / width;"
-            "   float a = x * pixelScaleX + xl;"
-            "   float b = y * pixelScaleY + yt;"
-            "   float ca = a;"
-            "   float cb = b;"
-            ""
-            "   int n = 0;"
-            "   while (n < max - 1) {"
-            "       float aa = a * a;"
-            "       float bb = b * b;"
-            "       float 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) + 1 - log(log(a * a + b * b) / 2) / log(2.0f);\n"
-//            "   A[index] = ((float)n) + 1 - (a * a + b * b - 16) / (256 - 16);\n"
-    //        "   A[get_global_id(0)] = 5;"
-            "}";
-    }
-    else {
-        return
-    //        "#pragma OPENCL EXTENSION cl_khr_fp64 : enable"
-            "__kernel void iterate(__global float* A, const int width, float xl, float yt, float pixelScaleX, float pixelScaleY, int max) {"
-            "   int index = get_global_id(0);\n"
-            "   int x = index % width;"
-            "   int y = index / width;"
-            "   float a = x * pixelScaleX + xl;"
-            "   float b = y * pixelScaleY + yt;"
-            "   float ca = a;"
-            "   float cb = b;"
-            ""
-            "   int n = 0;"
-            "   while (n < max - 1) {"
-            "       float aa = a * a;"
-            "       float bb = b * b;"
-            "       float 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 
+//        "#pragma OPENCL EXTENSION cl_khr_fp64 : enable"
+        "__kernel void iterate(__global float* A, const int width, float xl, float yt, float pixelScaleX, float pixelScaleY, int max, int smooth) {"
+        "   int index = get_global_id(0);\n"
+        "   int x = index % width;"
+        "   int y = index / width;"
+        "   float a = x * pixelScaleX + xl;"
+        "   float b = y * pixelScaleY + yt;"
+        "   float ca = a;"
+        "   float cb = b;"
+        ""
+        "   int n = 0;"
+        "   while (n < max - 1) {"
+        "       float aa = a * a;"
+        "       float bb = b * b;"
+        "       float ab = a * b;"
+        "       if (aa + bb > 16) break;"
+        "       a = aa - bb + ca;"
+        "       b = 2 * ab + cb;"
+        "       n++;"
+        "   }\n"
+        "   if (n >= max - 1)\n"
+        "       A[index] = max;\n"
+        "   else {"
+        "       if (smooth != 0)\n"
+        "           A[index] = ((float)n) + 1 - log(log(a * a + b * b) / 2) / log(2.0f);\n"
+        "       else\n"
+        "           A[index] = ((float)n);\n"
+        "   }"
+        "}";
 }
 
 
@@ -234,6 +201,7 @@ void ClGeneratorDouble::generate(const mnd::MandelInfo& info, float* data)
     iterate.setArg(4, double(pixelScaleX));
     iterate.setArg(5, double(pixelScaleY));
     iterate.setArg(6, int(info.maxIter));
+    iterate.setArg(7, int(info.smooth ? 1 : 0));
 
     cl_int result = queue.enqueueNDRangeKernel(iterate, 0, NDRange(info.bWidth * info.bHeight));
     queue.enqueueReadBuffer(buffer_A, CL_TRUE, 0, bufferSize, data);
@@ -242,68 +210,37 @@ void ClGeneratorDouble::generate(const mnd::MandelInfo& info, float* data)
 
 std::string ClGeneratorDouble::getKernelCode(bool smooth) const
 {
-    if (smooth) {
-        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) + 1 - log(log((float)(a * a + b * b)) / 2) / log(2.0f);\n"
-            //            "   A[index] = ((float)n) + 1 - (a * a + b * b - 16) / (256 - 16);\n"
-            //        "   A[get_global_id(0)] = 5;"
-            "}";
-    }
-    else {
-        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
+        "#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 = 2 * 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"
+        "   }"
+        "}";
 }
 
 

+ 1 - 1
libmandel/src/CpuGenerators.cpp

@@ -81,7 +81,7 @@ void CpuGenerator<T, mnd::NONE, parallel>::generate(const mnd::MandelInfo& info,
             }
             if (info.smooth) {
                 if (k >= info.maxIter)
-                    data[i + j * info.bWidth] = info.maxIter;
+                    data[i + j * info.bWidth] = float(info.maxIter);
                 else
                     data[i + j * info.bWidth] = ((float) k) + 1 - ::logf(::logf(mnd::convert<float>(a * a + b * b)) / 2) / ::logf(2.0f);
             }

+ 4 - 0
libmandel/src/CpuGeneratorsAVX.cpp

@@ -135,6 +135,10 @@ void CpuGenerator<double, mnd::X86_AVX, parallel>::generate(const mnd::MandelInf
                 a = _mm256_add_pd(_mm256_sub_pd(aa, bb), xs);
                 b = _mm256_add_pd(abab, ys);
                 __m256i cmp = _mm256_castpd_si256(_mm256_cmp_pd(_mm256_add_pd(aa, bb), threshold, _CMP_LE_OQ));
+                /*if (info.smooth) {
+                    resultsa = _mm256_or_pd(_mm256_andnot_ps(cmp, resultsa), _mm256_and_ps(cmp, a));
+                    resultsb = _mm256_or_ps(_mm256_andnot_ps(cmp, resultsb), _mm256_and_ps(cmp, b));
+                }*/
                 adder = _mm256_and_pd(adder, _mm256_castsi256_pd(cmp));
                 counter = _mm256_add_pd(counter, adder);
                 if ((k & 0x7) == 0 && _mm256_testz_si256(cmp, cmp) != 0) {

+ 2 - 2
libmandel/src/Generators.cpp

@@ -31,7 +31,7 @@ void AdaptiveGenerator::addGenerator(const mnd::Real& precision, mnd::Generator&
 }
 
 
-void AdaptiveGenerator::addGenerator(Precision p, Generator& generator)
+void AdaptiveGenerator::addGenerator(mnd::Precision p, Generator& generator)
 {
     generators.insert({ getPrecision(p), &generator });
 }
@@ -85,7 +85,7 @@ namespace mnd
             { Precision::DOUBLE_DOUBLE, Real("1.0e-29") },
             { Precision::QUAD_DOUBLE, Real("1.0e-56") },
             { Precision::FLOAT256, Real("1.0e-58") },
-            { Precision::INFINITE, Real(0.0) },
+            { Precision::INF_PREC, Real(0.0) },
         };
 
         return precs.at(p);

+ 2 - 1
libmandel/src/Mandel.cpp

@@ -123,6 +123,7 @@ std::unique_ptr<mnd::AdaptiveGenerator> MandelContext::createAdaptiveGenerator(v
     ag->addGenerator(Precision::DOUBLE_DOUBLE, *doubleDoubleGen);
     ag->addGenerator(Precision::QUAD_DOUBLE, *quadDoubleGen);
     ag->addGenerator(Precision::FLOAT256, *f256Gen);
+    ag->addGenerator(Precision::INF_PREC, *f256Gen);
 
     return ag;
 }
@@ -195,7 +196,7 @@ std::vector<MandelDevice> MandelContext::createDevices(void)
 }
 
 
-Generator& MandelContext::getDefaultGenerator(bool smooth)
+Generator& MandelContext::getDefaultGenerator(void)
 {
     return *adaptiveGenerator;
 }