Nicolas Winkler 5 年之前
父節點
當前提交
501ff6ccdc

+ 3 - 0
Almond.pro

@@ -6,6 +6,9 @@
 
 QT       += core gui opengl xml
 
+QMAKE_LINK=clang++
+QMAKE_CXX=clang++
+
 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
 
 TARGET = Almond

+ 17 - 21
MandelWidget.cpp

@@ -166,13 +166,13 @@ TexGrid::TexGrid(MandelView& owner, int level) :
 }
 
 
-std::pair<GridIndex, GridIndex> TexGrid::getCellIndices(double x, double y)
+std::pair<GridIndex, GridIndex> TexGrid::getCellIndices(mnd::Real x, mnd::Real y)
 {
     return { ::floor(x / dpp / MandelView::chunkSize), ::floor(y / dpp / MandelView::chunkSize) };
 }
 
 
-std::pair<double, double> TexGrid::getPositions(GridIndex x, GridIndex y)
+std::pair<mnd::Real, mnd::Real> TexGrid::getPositions(GridIndex x, GridIndex y)
 {
     return { x * dpp * MandelView::chunkSize, y * dpp * MandelView::chunkSize };
 }
@@ -205,7 +205,7 @@ void TexGrid::clearCells(void)
 void Job::run(void)
 {
     auto [absX, absY] = grid->getPositions(i, j);
-    double gw = grid->dpp * MandelView::chunkSize;
+    mnd::Real gw = grid->dpp * MandelView::chunkSize;
 
     Bitmap<float> f(MandelView::chunkSize, MandelView::chunkSize);
     mnd::MandelInfo mi;
@@ -214,6 +214,8 @@ void Job::run(void)
     mi.view.width = mi.view.height = gw;
     mi.bWidth = mi.bHeight = MandelView::chunkSize;
     mi.maxIter = maxIter;
+    printf("w: %ld, h: %ld\n", mi.bWidth, mi.bHeight);
+    fflush(stdout);
     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);
@@ -315,12 +317,12 @@ MandelView::MandelView(mnd::Generator* generator, MandelWidget& owner, int maxIt
 }
 
 
-int MandelView::getLevel(double dpp) {
+int MandelView::getLevel(mnd::Real dpp) {
     return int(::log2(dpp / chunkSize));
 }
 
 
-double MandelView::getDpp(int level)
+mnd::Real MandelView::getDpp(int level)
 {
     return ::pow(2, level) * chunkSize;
 }
@@ -472,25 +474,25 @@ GridElement* MandelView::searchUnder(int level, GridIndex i, GridIndex j, int re
 
 void MandelView::paint(const mnd::MandelViewport& mvp)
 {
-    double dpp = mvp.width / width;
+    mnd::Real dpp = mvp.width / width;
     int level = getLevel(dpp) - 1;
     auto& grid = getGrid(level);
-    double gw = getDpp(level) * chunkSize;
+    mnd::Real gw = getDpp(level) * chunkSize;
     auto [left, top] = grid.getCellIndices(mvp.x, mvp.y);
     auto [right, bottom] = grid.getCellIndices(mvp.right(), mvp.bottom());
 
     garbageCollect(level, (left + right) / 2, (top + bottom) / 2);
     emit calcer.setCurrentLevel(level);
 
-    double w = width * gw / mvp.width;
+    mnd::Real w = width * gw / mvp.width;
 
     auto [realXLeft, realYTop] = grid.getPositions(left, top);
     realXLeft = (realXLeft - mvp.x) * width / mvp.width;
     realYTop = (realYTop - mvp.y) * height / mvp.height;
     for(GridIndex i = left; i <= right; i++) {
         for(GridIndex j = top; j <= bottom; j++) {
-            double x = realXLeft + (i - left) * w;
-            double y = realYTop + (j - top) * w;
+            mnd::Real x = realXLeft + (i - left) * w;
+            mnd::Real y = realYTop + (j - top) * w;
 
             GridElement* t = grid.getCell(i, j);
 
@@ -730,19 +732,14 @@ void MandelWidget::resizeEvent(QResizeEvent* re)
     QOpenGLWidget::resizeEvent(re);
     double aspect = double(geometry().width()) / geometry().height();
 
-    //if (viewport.width > viewport.height * aspect)
-    currentViewport.height = (currentViewport.width / aspect);
+    currentViewport.height = currentViewport.width / aspect;
     targetViewport = currentViewport;
-    //else
-    //    viewport.width = (viewport.height * aspect);
 
     if (mandelView.get() != nullptr) {
         mandelView->width = this->width();
         mandelView->height = this->height();
     }
-    //printf("resized\n");
     requestRecalc();
-    //redraw();
 }
 
 
@@ -801,10 +798,10 @@ void MandelWidget::mouseReleaseEvent(QMouseEvent* me)
         if(rect.width() != 0 && rect.height() != 0) {
             QRect full = this->geometry();
 
-            targetViewport.x += double(rect.left()) * targetViewport.width / full.width();
-            targetViewport.y += double(rect.top()) * targetViewport.height / full.height();
-            targetViewport.width *= double(rect.width()) / full.width();
-            targetViewport.height *= double(rect.height()) / full.height();
+            targetViewport.x += mnd::Real(rect.left()) * targetViewport.width / full.width();
+            targetViewport.y += mnd::Real(rect.top()) * targetViewport.height / full.height();
+            targetViewport.width *= mnd::Real(rect.width()) / full.width();
+            targetViewport.height *= mnd::Real(rect.height()) / full.height();
             targetViewport.normalize();
             currentViewport = targetViewport;
         }
@@ -822,7 +819,6 @@ void MandelWidget::wheelEvent(QWheelEvent* we)
     float x = float(we->x()) / this->width();
     float y = float(we->y()) / this->height();
     float scale = ::powf(0.9975f, we->angleDelta().y());
-    //printf("scale: %f\n", double(scale));
     zoom(scale, x, y);
     if (!we->pixelDelta().isNull())
         this->currentViewport = this->targetViewport;

+ 6 - 8
MandelWidget.h

@@ -23,7 +23,7 @@
 #include <unordered_set>
 
 
-using GridIndex = long long;
+using GridIndex = mnd::Integer;
 Q_DECLARE_METATYPE(GridIndex)
 
 
@@ -142,21 +142,19 @@ struct GridElement
 };
 
 
-
-
 class TexGrid
 {
 public:
     MandelView& owner;
     int level;
-    double dpp;
+    mnd::Real dpp;
     std::unordered_map<std::pair<GridIndex, GridIndex>, std::unique_ptr<GridElement>, PairHash> cells;
 public:
     //inline TexGrid(MandelV& owner) : level{ 1.0 }, owner{ owner } {}
     TexGrid(MandelView& owner, int level);
 
-    std::pair<GridIndex, GridIndex> getCellIndices(double x, double y);
-    std::pair<double, double> getPositions(GridIndex i, GridIndex j);
+    std::pair<GridIndex, GridIndex> getCellIndices(mnd::Real x, mnd::Real y);
+    std::pair<mnd::Real, mnd::Real> getPositions(GridIndex i, GridIndex j);
     GridElement* getCell(GridIndex i, GridIndex j);
     void setCell(GridIndex i, GridIndex j, std::unique_ptr<GridElement> tex);
 
@@ -256,8 +254,8 @@ public:
 public:
     static const int chunkSize = 256;
     MandelView(mnd::Generator* generator, MandelWidget& owner, int maxIter);
-    int getLevel(double dpp);
-    double getDpp(int level);
+    int getLevel(mnd::Real dpp);
+    mnd::Real getDpp(int level);
 
     TexGrid& getGrid(int level);
 

+ 16 - 10
benchmarkdialog.cpp

@@ -105,9 +105,12 @@ void Benchmarker::start(void)
 {
     mnd::Generator& cpuf = mndContext.getCpuGeneratorFloat();
     mnd::Generator& cpud = mndContext.getCpuGeneratorDouble();
-    mnd::Generator& cpu128 = mndContext.getCpuGenerator128();
+    mnd::Generator* cpu128 = mndContext.getCpuGeneratorQuad();
 
-    double nTests = 3;
+    double nTests = 2;
+
+    if (cpu128)
+        nTests++;
 
     auto& devices = mndContext.getDevices();
     for (size_t i = 0; i < devices.size(); i++) {
@@ -117,9 +120,10 @@ void Benchmarker::start(void)
         if (mnd::Generator* gpud; (gpud = devices[i].getGeneratorDouble())) {
             nTests++;
         }
-        if (mnd::Generator* gpu128; (gpu128 = devices[i].getGenerator128())) {
+        /*
+        if (mnd::Generator* gpu128; (gpu128 = devices[i].getGeneratorQuad())) {
             nTests++;
-        }
+        }*/
     }
 
     double progress = 90.0 / nTests;
@@ -137,9 +141,11 @@ void Benchmarker::start(void)
     cpu.push_back(benchmarkResult(cpud));
     br.percentage += progress;
     emit update(br);
-    cpu.push_back(benchmarkResult(cpu128));
-    br.percentage += progress;
-    emit update(br);
+    if (cpu128) {
+        cpu.push_back(benchmarkResult(*cpu128));
+        br.percentage += progress;
+        emit update(br);
+    }
 
     for (size_t i = 0; i < devices.size(); i++) {
         br.values.push_back({});
@@ -154,11 +160,11 @@ void Benchmarker::start(void)
             br.percentage += progress;
             emit update(br);
         }
-        if (mnd::Generator* gpu128; (gpu128 = devices[i].getGenerator128())) {
+        /*if (mnd::Generator* gpu128; (gpu128 = devices[i].getGenerator128())) {
             gpu.push_back(benchmarkResult(*gpu128));
             br.percentage += progress;
             emit update(br);
-        }
+        }*/
     }
     emit update(br);
     emit finished();
@@ -177,7 +183,7 @@ BenchmarkDialog::BenchmarkDialog(mnd::MandelContext& mndContext, QWidget *parent
     int nDevices = devices.size() + 1;
     ui.tableWidget->setColumnCount(3);
     ui.tableWidget->setRowCount(nDevices);
-    ui.tableWidget->setHorizontalHeaderLabels({"Single Precision", "Double Precision", "128-bit Fixed Point"});
+    ui.tableWidget->setHorizontalHeaderLabels({"Single Precision", "Double Precision", "Quad Precision"});
 
     QString cpuDesc = ("CPU [" + mndContext.getCpuInfo().getBrand() + "]").c_str();
     ui.tableWidget->setVerticalHeaderItem(0, new QTableWidgetItem(cpuDesc));

+ 8 - 0
libmandel/CMakeLists.txt

@@ -10,6 +10,8 @@ project(mandel VERSION 1.0.0 DESCRIPTION "library for mandelbrot calculations")
 
 find_package(OpenCL)
 find_package(OpenMP)
+set(Boost_DEBUG 1)
+find_package(Boost 1.53)
 
 find_path(MPFR_INCLUDES
   NAMES
@@ -64,6 +66,12 @@ if (APPLE AND OpenCL_FOUND)
     SET(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} -framework OpenCL")
 endif()
 
+    target_compile_definitions(mandel PUBLIC WITH_BOOST)
+if(BOOST_FOUND)
+    target_compile_definitions(mandel PUBLIC WITH_BOOST)
+    include_directories(${Boost_INCLUDE_DIR})
+endif(BOOST_FOUND)
+
 if (ARCH STREQUAL "X86_64" OR ARCH STREQUAL "X86")
     if (MSVC)
         set_source_files_properties(src/CpuGeneratorsAVX.cpp PROPERTIES COMPILE_FLAGS /arch:AVX)

+ 2 - 1
libmandel/include/Generators.h

@@ -35,9 +35,10 @@ public:
 
 class mnd::AdaptiveGenerator : public Generator
 {
-    std::vector<std::pair<double, Generator*>> generators;
+    std::vector<std::pair<Real, Generator*>> generators;
 public:
     AdaptiveGenerator(Generator* floatGen, Generator* doubleGen);
+    AdaptiveGenerator(Generator* floatGen, Generator* doubleGen, Generator* quadGen);
     virtual ~AdaptiveGenerator(void) = default;
 
     virtual void generate(const MandelInfo& info, float* data);

+ 15 - 8
libmandel/include/Mandel.h

@@ -30,10 +30,13 @@ private:
 
     std::unique_ptr<Generator> floatGenerator;
     std::unique_ptr<Generator> doubleGenerator;
-    std::unique_ptr<Generator> generator128;
+    //std::unique_ptr<Generator> quadGenerator;
+    //std::unique_ptr<Generator> generator128;
+
     std::unique_ptr<Generator> floatGeneratorSmooth;
     std::unique_ptr<Generator> doubleGeneratorSmooth;
-    std::unique_ptr<Generator> generator128Smooth;
+    //std::unique_ptr<Generator> quadGeneratorSmooth;
+    //std::unique_ptr<Generator> generator128Smooth;
 
     MandelDevice(void);
 public:
@@ -43,7 +46,8 @@ public:
 
     Generator* getGeneratorFloat(bool smooth = true) const;
     Generator* getGeneratorDouble(bool smooth = true) const;
-    Generator* getGenerator128(bool smooth = true) const;
+    //Generator* getGeneratorQuad(bool smooth = true) const;
+    //Generator* getGenerator128(bool smooth = true) const;
 };
 
 
@@ -56,13 +60,15 @@ private:
 
     std::unique_ptr<Generator> cpuGeneratorFloat;
     std::unique_ptr<Generator> cpuGeneratorDouble;
-    std::unique_ptr<Generator> cpuGenerator128;
-    std::unique_ptr<Generator> cpuGeneratorFixedp;
+    std::unique_ptr<Generator> cpuGeneratorQuad;
+    //std::unique_ptr<Generator> cpuGenerator128;
+    //std::unique_ptr<Generator> cpuGeneratorFixedp;
 
     std::unique_ptr<Generator> cpuGeneratorFloatSmooth;
     std::unique_ptr<Generator> cpuGeneratorDoubleSmooth;
-    std::unique_ptr<Generator> cpuGenerator128Smooth;
-    std::unique_ptr<Generator> cpuGeneratorFixedpSmooth;
+    std::unique_ptr<Generator> cpuGeneratorQuadSmooth;
+    //std::unique_ptr<Generator> cpuGenerator128Smooth;
+    //std::unique_ptr<Generator> cpuGeneratorFixedpSmooth;
 
     std::unique_ptr<Generator> adaptiveGenerator;
     std::unique_ptr<Generator> adaptiveGeneratorSmooth;
@@ -79,7 +85,8 @@ public:
 
     Generator& getCpuGeneratorFloat(void);
     Generator& getCpuGeneratorDouble(void); 
-    Generator& getCpuGenerator128(void); 
+    Generator* getCpuGeneratorQuad(void); 
+    //Generator& getCpuGenerator128(void); 
 
     const CpuInfo& getCpuInfo(void) const { return cpuInfo; }
 };

+ 9 - 7
libmandel/include/MandelUtil.h

@@ -1,6 +1,8 @@
 #ifndef MANDEL_MANDELUTIL_H
 #define MANDEL_MANDELUTIL_H
 
+#include "Types.h"
+
 namespace mnd 
 {
     struct MandelViewport;
@@ -11,16 +13,16 @@ namespace mnd
 struct mnd::MandelViewport
 {
     /// real part of the top left corner
-    double x = -2.1;
+    Real x = -2.1;
 
     /// imaginary part of the top left corner
-    double y = -1.5;
+    Real y = -1.5;
 
     /// real-part span of the picture to be generated
-    double width = 3;
+    Real width = 3;
 
     /// imaginary-part span of the picture to be generated
-    double height = 3;
+    Real height = 3;
 
     /*!
      * \brief adjusts the aspect ratio of the viewport, making sure
@@ -50,8 +52,8 @@ struct mnd::MandelViewport
      */
     static MandelViewport standardView(void);
 
-    inline double right() const { return x + width; }
-    inline double bottom() const { return y + height; }
+    inline Real right() const { return x + width; }
+    inline Real bottom() const { return y + height; }
 };
 
 struct mnd::MandelInfo
@@ -66,7 +68,7 @@ struct mnd::MandelInfo
     long bHeight;
     
     /// maximum iterations
-    int maxIter;
+    long maxIter;
 };
 
 #endif // MANDEL_MANDELUTIL_H

+ 6 - 6
libmandel/src/ClGenerators.cpp

@@ -87,8 +87,8 @@ void ClGenerator::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);
-    float pixelScaleX = info.view.width / info.bWidth;
-    float pixelScaleY = info.view.height / info.bHeight;
+    float pixelScaleX = float(info.view.width / info.bWidth);
+    float pixelScaleY = float(info.view.height / info.bHeight);
 
     Kernel iterate = Kernel(program, "iterate");
     iterate.setArg(0, buffer_A);
@@ -221,8 +221,8 @@ void ClGeneratorDouble::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);
-    float pixelScaleX = info.view.width / info.bWidth;
-    float pixelScaleY = info.view.height / info.bHeight;
+    double pixelScaleX = double(info.view.width / info.bWidth);
+    double pixelScaleY = double(info.view.height / info.bHeight);
 
     Kernel iterate = Kernel(program, "iterate");
     iterate.setArg(0, buffer_A);
@@ -330,8 +330,8 @@ void ClGenerator128::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);
-    float pixelScaleX = info.view.width / info.bWidth;
-    float pixelScaleY = info.view.height / info.bHeight;
+    float pixelScaleX = float(info.view.width / info.bWidth);
+    float pixelScaleY = float(info.view.height / info.bHeight);
 
     Kernel iterate = Kernel(program, "iterate");
     iterate.setArg(0, buffer_A);

+ 29 - 16
libmandel/src/CpuGenerators.cpp

@@ -1,5 +1,5 @@
 #include "CpuGenerators.h"
-#include "Fixed.h"
+#include "Types.h"
 
 #ifdef WITH_MPFR
 #include "MpfrWrapper.h"
@@ -12,20 +12,33 @@
 
 using mnd::CpuGenerator;
 
-template class CpuGenerator<float, mnd::NONE, false, false>;
-template class CpuGenerator<float, mnd::NONE, false, true>;
-template class CpuGenerator<float, mnd::NONE, true, false>;
-template class CpuGenerator<float, mnd::NONE, true, true>;
-
-template class CpuGenerator<double, mnd::NONE, false, false>;
-template class CpuGenerator<double, mnd::NONE, false, true>;
-template class CpuGenerator<double, mnd::NONE, true, false>;
-template class CpuGenerator<double, mnd::NONE, true, true>;
-
-template class CpuGenerator<Fixed128, mnd::NONE, false, false>;
-template class CpuGenerator<Fixed128, mnd::NONE, false, true>;
-template class CpuGenerator<Fixed128, mnd::NONE, true, false>;
-template class CpuGenerator<Fixed128, mnd::NONE, true, true>;
+namespace mnd
+{
+    template class CpuGenerator<float, mnd::NONE, false, false>;
+    template class CpuGenerator<float, mnd::NONE, false, true>;
+    template class CpuGenerator<float, mnd::NONE, true, false>;
+    template class CpuGenerator<float, mnd::NONE, true, true>;
+
+    template class CpuGenerator<double, mnd::NONE, false, false>;
+    template class CpuGenerator<double, mnd::NONE, false, true>;
+    template class CpuGenerator<double, mnd::NONE, true, false>;
+    template class CpuGenerator<double, mnd::NONE, true, true>;
+
+    /*
+    template class CpuGenerator<Fixed128, mnd::NONE, false, false>;
+    template class CpuGenerator<Fixed128, mnd::NONE, false, true>;
+    template class CpuGenerator<Fixed128, mnd::NONE, true, false>;
+    template class CpuGenerator<Fixed128, mnd::NONE, true, true>;
+    */
+
+#ifdef WITH_BOOST
+#include <boost/multiprecision/cpp_bin_float.hpp>
+    template class CpuGenerator<mnd::Float128, mnd::NONE, false, false>;
+    template class CpuGenerator<mnd::Float128, mnd::NONE, false, true>;
+    template class CpuGenerator<mnd::Float128, mnd::NONE, true, false>;
+    template class CpuGenerator<mnd::Float128, mnd::NONE, true, true>;
+#endif
+}
 
 
 template<typename T, bool parallel, bool smooth>
@@ -60,7 +73,7 @@ void CpuGenerator<T, mnd::NONE, parallel, smooth>::generate(const mnd::MandelInf
                 if (k >= info.maxIter)
                     data[i + j * info.bWidth] = info.maxIter;
                 else
-                    data[i + j * info.bWidth] = ((float) k) + 1 - ::log(::log(a * a + b * b) / 2) / ::log(2.0f);
+                    data[i + j * info.bWidth] = ((float) k) + 1 - ::logf(::logf(float(a * a + b * b)) / 2) / ::logf(2.0f);
             }
             else
                 data[i + j * info.bWidth] = k;

+ 17 - 14
libmandel/src/CpuGeneratorsAVX.cpp

@@ -8,15 +8,18 @@
 
 using mnd::CpuGenerator;
 
-template class CpuGenerator<float, mnd::X86_AVX, false, false>;
-template class CpuGenerator<float, mnd::X86_AVX, false, true>;
-template class CpuGenerator<float, mnd::X86_AVX, true, false>;
-template class CpuGenerator<float, mnd::X86_AVX, true, true>;
-
-template class CpuGenerator<double, mnd::X86_AVX, false, false>;
-template class CpuGenerator<double, mnd::X86_AVX, false, true>;
-template class CpuGenerator<double, mnd::X86_AVX, true, false>;
-template class CpuGenerator<double, mnd::X86_AVX, true, true>;
+namespace mnd
+{
+    template class CpuGenerator<float, mnd::X86_AVX, false, false>;
+    template class CpuGenerator<float, mnd::X86_AVX, false, true>;
+    template class CpuGenerator<float, mnd::X86_AVX, true, false>;
+    template class CpuGenerator<float, mnd::X86_AVX, true, true>;
+
+    template class CpuGenerator<double, mnd::X86_AVX, false, false>;
+    template class CpuGenerator<double, mnd::X86_AVX, false, true>;
+    template class CpuGenerator<double, mnd::X86_AVX, true, false>;
+    template class CpuGenerator<double, mnd::X86_AVX, true, true>;
+}
 
 template<bool parallel, bool smooth>
 void CpuGenerator<float, mnd::X86_AVX, parallel, smooth>::generate(const mnd::MandelInfo& info, float* data)
@@ -109,14 +112,14 @@ void CpuGenerator<double, mnd::X86_AVX, parallel, smooth>::generate(const mnd::M
         omp_set_num_threads(2 * omp_get_num_procs());
 #pragma omp parallel for if (smooth)
     for (long j = 0; j < info.bHeight; j++) {
-        T y = T(view.y) + T(j) * view.height / info.bHeight;
+        T y = T(view.y + T(j) * view.height / info.bHeight);
         long i = 0;
         for (i; i < info.bWidth; i += 4) {
             __m256d xs = {
-                double(view.x) + double(i) * view.width / info.bWidth,
-                double(view.x) + double(i + 1) * view.width / info.bWidth,
-                double(view.x) + double(i + 2) * view.width / info.bWidth,
-                double(view.x) + double(i + 3) * view.width / info.bWidth
+                double(view.x + double(i) * view.width / info.bWidth),
+                double(view.x + double(i + 1) * view.width / info.bWidth),
+                double(view.x + double(i + 2) * view.width / info.bWidth),
+                double(view.x + double(i + 3) * view.width / info.bWidth)
             };
 
             int itRes[4] = { 0, 0, 0, 0 };

+ 12 - 9
libmandel/src/CpuGeneratorsSSE2.cpp

@@ -7,15 +7,18 @@
 
 using mnd::CpuGenerator;
 
-template class CpuGenerator<float, mnd::X86_SSE2, false, false>;
-template class CpuGenerator<float, mnd::X86_SSE2, false, true>;
-template class CpuGenerator<float, mnd::X86_SSE2, true, false>;
-template class CpuGenerator<float, mnd::X86_SSE2, true, true>;
-
-template class CpuGenerator<double, mnd::X86_SSE2, false, false>;
-template class CpuGenerator<double, mnd::X86_SSE2, false, true>;
-template class CpuGenerator<double, mnd::X86_SSE2, true, false>;
-template class CpuGenerator<double, mnd::X86_SSE2, true, true>;
+namespace mnd
+{
+    template class CpuGenerator<float, mnd::X86_SSE2, false, false>;
+    template class CpuGenerator<float, mnd::X86_SSE2, false, true>;
+    template class CpuGenerator<float, mnd::X86_SSE2, true, false>;
+    template class CpuGenerator<float, mnd::X86_SSE2, true, true>;
+
+    template class CpuGenerator<double, mnd::X86_SSE2, false, false>;
+    template class CpuGenerator<double, mnd::X86_SSE2, false, true>;
+    template class CpuGenerator<double, mnd::X86_SSE2, true, false>;
+    template class CpuGenerator<double, mnd::X86_SSE2, true, true>;
+}
 
 template<bool parallel, bool smooth>
 void CpuGenerator<float, mnd::X86_SSE2, parallel, smooth>::generate(const mnd::MandelInfo& info, float* data)

+ 16 - 4
libmandel/src/Generators.cpp

@@ -17,11 +17,21 @@ AdaptiveGenerator::AdaptiveGenerator(Generator* floatGen, Generator* doubleGen)
 }
 
 
+AdaptiveGenerator::AdaptiveGenerator(Generator* floatGen, Generator* doubleGen, Generator* quadGen)
+{
+    generators.push_back({ 0.0000001, floatGen });
+    generators.push_back({ 1.0e-17, doubleGen });
+    generators.push_back({ 0.0, quadGen });
+}
+
+
 void AdaptiveGenerator::generate(const mnd::MandelInfo& info, float* data)
 {
-    double pixelW = info.view.width / info.bWidth;
-    double pixelH = info.view.height / info.bHeight;
-    double minimum = pixelW < pixelH ? pixelW : pixelH;
+    printf("w: %ld, h: %ld\n", info.bWidth, info.bHeight);
+    fflush(stdout);
+    Real pixelW = info.view.width / info.bWidth;
+    Real pixelH = info.view.height / info.bHeight;
+    Real minimum = pixelW < pixelH ? pixelW : pixelH;
 
     Generator* toUse = nullptr;
     int i = 0;
@@ -37,7 +47,9 @@ void AdaptiveGenerator::generate(const mnd::MandelInfo& info, float* data)
         toUse->generate(info, data);
     }
     else {
-
+        for (long s = 0; s < info.bWidth * info.bHeight; s++) {
+            data[s] = 0.0;
+        }
     }
 }
 

+ 42 - 11
libmandel/src/mandel.cpp

@@ -21,10 +21,8 @@ MandelContext mnd::initializeContext(void)
 MandelDevice::MandelDevice(void) :
     floatGenerator{ nullptr },
     doubleGenerator{ nullptr },
-    generator128{ nullptr },
     floatGeneratorSmooth{ nullptr },
-    doubleGeneratorSmooth{ nullptr },
-    generator128Smooth{ nullptr }
+    doubleGeneratorSmooth{ nullptr }
 
 {
 }
@@ -48,6 +46,17 @@ mnd::Generator* MandelDevice::getGeneratorDouble(bool smooth) const
 }
 
 
+/*
+mnd::Generator* MandelDevice::getGeneratorQuad(bool smooth) const
+{
+    if (smooth)
+        return quadGeneratorSmooth.get();
+    else
+        return quadGenerator.get();
+}*/
+
+
+/*
 mnd::Generator* MandelDevice::getGenerator128(bool smooth) const
 {
     if (smooth)
@@ -55,9 +64,11 @@ mnd::Generator* MandelDevice::getGenerator128(bool smooth) const
     else
         return generator128.get();
 }
+*/
 
-
-MandelContext::MandelContext(void)
+MandelContext::MandelContext(void) :
+    cpuGeneratorQuad{ nullptr },
+    cpuGeneratorQuadSmooth{ nullptr }
 {
 
 #if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) 
@@ -90,14 +101,29 @@ MandelContext::MandelContext(void)
         cpuGeneratorDoubleSmooth = std::make_unique<CpuGenerator<double, mnd::NONE, true, true>>();
     }
 
-    cpuGenerator128 = std::make_unique<CpuGenerator<Fixed128, mnd::NONE, true, false>>();
-    cpuGenerator128Smooth = std::make_unique<CpuGenerator<Fixed128>>();
+    //cpuGenerator128 = std::make_unique<CpuGenerator<Fixed128, mnd::NONE, true, false>>();
+    //cpuGenerator128Smooth = std::make_unique<CpuGenerator<Fixed128>>();
     //cpuGeneratorFixedp = std::make_unique<CpuGenerator<fixed<1, 3>>>();
 
+#ifdef WITH_BOOST
+    cpuGeneratorQuad = std::make_unique<CpuGenerator<Float128, mnd::NONE, true, false>>();
+    cpuGeneratorQuadSmooth = std::make_unique<CpuGenerator<Float128, mnd::NONE, true, true>>();
+#endif // WITH_BOOST
+
     devices = createDevices();
     if (devices.empty()) {
-        adaptiveGenerator = std::make_unique<AdaptiveGenerator>(cpuGeneratorFloat.get(), cpuGeneratorDouble.get());
-        adaptiveGeneratorSmooth = std::make_unique<AdaptiveGenerator>(cpuGeneratorFloatSmooth.get(), cpuGeneratorDoubleSmooth.get());
+#ifdef WITH_BOOST
+        adaptiveGenerator = std::make_unique<AdaptiveGenerator>(
+            cpuGeneratorFloat.get(), cpuGeneratorDouble.get(), cpuGeneratorQuad.get());
+        adaptiveGeneratorSmooth = std::make_unique<AdaptiveGenerator>(
+            cpuGeneratorFloatSmooth.get(), cpuGeneratorDoubleSmooth.get(),
+            cpuGeneratorQuadSmooth.get());
+#else
+        adaptiveGenerator = std::make_unique<AdaptiveGenerator>(
+            cpuGeneratorFloat.get(), cpuGeneratorDouble.get());
+        adaptiveGeneratorSmooth = std::make_unique<AdaptiveGenerator>(
+            cpuGeneratorFloatSmooth.get(), cpuGeneratorDoubleSmooth.get());
+#endif
     }
     else {
         auto& device1 = devices[0];
@@ -113,8 +139,13 @@ MandelContext::MandelContext(void)
             floatGeneratorSmooth = cpuGeneratorFloatSmooth.get();
         if (doubleGeneratorSmooth == nullptr)
             doubleGeneratorSmooth = cpuGeneratorDoubleSmooth.get();
+#ifdef WITH_BOOST
+        adaptiveGeneratorSmooth = std::make_unique<AdaptiveGenerator>(floatGeneratorSmooth, doubleGeneratorSmooth, cpuGeneratorQuadSmooth.get());
+        adaptiveGenerator = std::make_unique<AdaptiveGenerator>(floatGenerator, doubleGenerator, cpuGeneratorQuad.get());
+#else
         adaptiveGeneratorSmooth = std::make_unique<AdaptiveGenerator>(floatGeneratorSmooth, doubleGeneratorSmooth);
         adaptiveGenerator = std::make_unique<AdaptiveGenerator>(floatGenerator, doubleGenerator);
+#endif
     }
 }
 
@@ -218,7 +249,7 @@ Generator& MandelContext::getCpuGeneratorDouble(void)
 }
 
 
-Generator& MandelContext::getCpuGenerator128(void)
+Generator* MandelContext::getCpuGeneratorQuad(void)
 {
-    return *cpuGenerator128;
+    return cpuGeneratorQuad.get();
 }