Nicolas Winkler 5 年 前
コミット
da77ad5f2e

+ 17 - 2
Almond.cpp

@@ -12,7 +12,8 @@ Almond::Almond(QWidget* parent) :
     mandelContext{ mnd::initializeContext() }
 {
     ui.setupUi(this);
-    mw = std::make_unique<MandelWidget>(mandelContext, ui.centralWidget);
+    currentGenerator = &mandelContext.getDefaultGenerator();
+    mw = std::make_unique<MandelWidget>(mandelContext, currentGenerator, ui.centralWidget);
     ui.mainContainer->addWidget(mw.get());
     ui.maxIterations->setValidator(new QIntValidator(1, 1000000000, this));
     //ui.verticalLayout_left->addWidget(new MyGLWidget(ui.centralWidget));
@@ -20,6 +21,11 @@ Almond::Almond(QWidget* parent) :
 }
 
 
+Almond::~Almond(void)
+{
+}
+
+
 void Almond::on_zoom_out_clicked()
 {
     mw->zoom(2);
@@ -131,6 +137,15 @@ void Almond::on_displayInfo_stateChanged(int checked)
 void Almond::on_chooseGenerator_clicked()
 {
     if (!generatorsDialog)
-        generatorsDialog = std::make_unique<ChooseGenerators>(this);
+        generatorsDialog = std::make_unique<ChooseGenerators>(mandelContext, this);
     generatorsDialog->exec();
+
+    if (generatorsDialog->getChosenGenerator()) {
+        this->currentGenerator = generatorsDialog->getChosenGenerator();
+    }
+    else {
+        this->currentGenerator = &mandelContext.getDefaultGenerator();
+    }
+    this->mw->setGenerator(currentGenerator);
+    printf("dialog executed\n"); fflush(stdout);
 }

+ 2 - 0
Almond.h

@@ -20,9 +20,11 @@ private:
     std::unique_ptr<MandelWidget> mw;
     std::unique_ptr<BenchmarkDialog> benchmarkDialog;
     std::unique_ptr<ChooseGenerators> generatorsDialog;
+    mnd::Generator* currentGenerator;
     GradientChooseDialog gcd;
 public:
     Almond(QWidget *parent = Q_NULLPTR);
+    ~Almond(void);
 
 private slots:
     void on_zoom_out_clicked();

+ 19 - 17
Almond.pro

@@ -81,12 +81,13 @@ else:unix:QMAKE_LFLAGS+= -fopenmp -flto
 LIBS += -fopenmp
 unix:LIBS += -lm -latomic -lquadmath
 
-win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../libs/ffmpeg-4.1.1-win32-dev/lib/ -lavcodec
-else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../libs/ffmpeg-4.1.1-win32-dev/lib/ -lavcodec
+win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../libs/ffmpeg-20200216-8578433-win64-dev/lib/ -lavcodec
+else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../libs/ffmpeg-20200216-8578433-win64-dev/lib/ -lavcodec
 else:unix: LIBS += -L$$PWD/../libs/ffmpeg-4.1.1-win32-dev/lib/ -lavcodec
 
-win32:INCLUDEPATH += $$PWD/../libs/ffmpeg-4.1.1-win32-dev/include
-win32:DEPENDPATH += $$PWD/../libs/ffmpeg-4.1.1-win32-dev/include
+win32:FFMPEGPATH = $$PWD/../libs/ffmpeg-20200216-8578433-win64-dev/lib/
+win32:INCLUDEPATH += $$PWD/../libs/ffmpeg-20200216-8578433-win64-dev/include
+win32:DEPENDPATH += $$PWD/../libs/ffmpeg-20200216-8578433-win64-dev/include
 
 win32:INCLUDEPATH += ../libs/boost_1_72_0
 DEFINES += WITH_BOOST=1
@@ -95,32 +96,33 @@ DEFINES += WITH_BOOST=1
 #else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/'../../../../../Program Files (x86)/AMD APP SDK/3.0/lib/x86/' -lOpenCL
 #else:unix: LIBS += -lOpenCL
 
+
 win32:INCLUDEPATH += $$PWD/'../../../../../Program Files (x86)/AMD APP SDK/3.0/include'
 win32:DEPENDPATH += $$PWD/'../../../../../Program Files (x86)/AMD APP SDK/3.0/include'
 
-win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../libs/ffmpeg-4.1.1-win32-dev/lib/ -lavformat
-else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../libs/ffmpeg-4.1.1-win32-dev/lib/ -lavformat
-else:unix: LIBS += -L$$PWD/../libs/ffmpeg-4.1.1-win32-dev/lib/ -lavformat
+win32:CONFIG(release, debug|release): LIBS += -L$FFMPEGPATH -lavformat
+else:win32:CONFIG(debug, debug|release): LIBS += -L$FFMPEGPATH -lavformat
+else:unix: LIBS += -L$FFMPEGPATH -lavformat
 
 #INCLUDEPATH += $$PWD/../libs/ffmpeg-4.1.1-win32-dev/include
 #DEPENDPATH += $$PWD/../libs/ffmpeg-4.1.1-win32-dev/include
 
-unix|win32: LIBS += -L$$PWD/../libs/ffmpeg-4.1.1-win32-dev/lib/ -lavdevice
+unix|win32: LIBS += -L$FFMPEGPATH -lavdevice
 
 #INCLUDEPATH += $$PWD/../libs/ffmpeg-4.1.1-win32-dev/include
 #DEPENDPATH += $$PWD/../libs/ffmpeg-4.1.1-win32-dev/include
 
-unix|win32: LIBS += -L$$PWD/../libs/ffmpeg-4.1.1-win32-dev/lib/ -lavfilter
+unix|win32: LIBS += -L$FFMPEGPATH -lavfilter
 
 #INCLUDEPATH += $$PWD/../libs/ffmpeg-4.1.1-win32-dev/include
 #DEPENDPATH += $$PWD/../libs/ffmpeg-4.1.1-win32-dev/include
 
-unix|win32: LIBS += -L$$PWD/../libs/ffmpeg-4.1.1-win32-dev/lib/ -lavutil
+unix|win32: LIBS += -L$FFMPEGPATH -lavutil
 
 #INCLUDEPATH += $$PWD/../libs/ffmpeg-4.1.1-win32-dev/include
 #DEPENDPATH += $$PWD/../libs/ffmpeg-4.1.1-win32-dev/include
 
-unix|win32: LIBS += -L$$PWD/../libs/ffmpeg-4.1.1-win32-dev/lib/ -lswscale
+unix|win32: LIBS += -L$FFMPEGPATH -lswscale
 
 #INCLUDEPATH += $$PWD/../libs/ffmpeg-4.1.1-win32-dev/include
 #DEPENDPATH += $$PWD/../libs/ffmpeg-4.1.1-win32-dev/include
@@ -136,14 +138,14 @@ win32:!win32-g++: PRE_TARGETDEPS += $$PWD/libmandel/mandel.lib  $$PWD/libmandel/
 else:unix|win32-g++: PRE_TARGETDEPS += $$PWD/libmandel/libmandel.a $$PWD/libmandel/qd.lib
 
 
-win32:CONFIG(release, debug|release): LIBS += -L$$PWD/'../../../../../Program Files (x86)/OCL_SDK_Light/lib/x86/' -lopencl
-else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/'../../../../../Program Files (x86)/OCL_SDK_Light/lib/x86/' -lopencl
+win32:CONFIG(release, debug|release): LIBS += -L$$PWD/'../../../../../Program Files (x86)/OCL_SDK_Light/lib/x86_64/' -lopencl
+else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/'../../../../../Program Files (x86)/OCL_SDK_Light/lib/x86_64/' -lopencl
 else:unix: LIBS += -lOpenCL
 
 win32:INCLUDEPATH += $$PWD/'../../../../../Program Files (x86)/OCL_SDK_Light/include'
 win32:DEPENDPATH += $$PWD/'../../../../../Program Files (x86)/OCL_SDK_Light/include'
 
-win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/'../../../../../Program Files (x86)/OCL_SDK_Light/lib/x86/libopencl.a'
-else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/'../../../../../Program Files (x86)/OCL_SDK_Light/lib/x86/libopencl.a'
-else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/'../../../../../Program Files (x86)/OCL_SDK_Light/lib/x86/opencl.lib'
-else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/'../../../../../Program Files (x86)/OCL_SDK_Light/lib/x86/opencl.lib'
+win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/'../../../../../Program Files (x86)/OCL_SDK_Light/lib/x86_64/libopencl.a'
+else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/'../../../../../Program Files (x86)/OCL_SDK_Light/lib/x86_64/libopencl.a'
+else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/'../../../../../Program Files (x86)/OCL_SDK_Light/lib/x86_64/opencl.lib'
+else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/'../../../../../Program Files (x86)/OCL_SDK_Light/lib/x86_64/opencl.lib'

+ 13 - 2
MandelWidget.cpp

@@ -569,9 +569,10 @@ void MandelView::cellReady(int level, GridIndex i, GridIndex j, Bitmap<RGBColor>
 }
 
 
-MandelWidget::MandelWidget(mnd::MandelContext& ctxt, QWidget* parent) :
+MandelWidget::MandelWidget(mnd::MandelContext& ctxt, mnd::Generator* generator, QWidget* parent) :
     QOpenGLWidget{ parent },
     mndContext{ ctxt },
+    generator{ generator },
     gradient{ Gradient::defaultGradient() }
 {
     this->setContentsMargins(0, 0, 0, 0);
@@ -637,6 +638,16 @@ void MandelWidget::setMaxIterations(int maxIter)
 }
 
 
+void MandelWidget::setGenerator(mnd::Generator* generator)
+{
+    if (this->generator != generator) {
+        this->generator = generator;
+        if (mandelView)
+            mandelView->setGenerator(generator);
+    }
+}
+
+
 void MandelWidget::initializeGL(void)
 {
     this->context()->functions()->glClearColor(0, 0, 0, 0);
@@ -657,7 +668,7 @@ void MandelWidget::initializeGL(void)
 void MandelWidget::paintGL(void)
 {
     if (mandelView == nullptr) {
-        mandelView = std::make_unique<MandelView>(&mndContext.getDefaultGenerator(), *this, maxIterations);
+        mandelView = std::make_unique<MandelView>(generator, *this, maxIterations);
         QObject::connect(mandelView.get(), &MandelView::redrawRequested, this, static_cast<void(QOpenGLWidget::*)(void)>(&QOpenGLWidget::update));
     }
 

+ 5 - 1
MandelWidget.h

@@ -277,6 +277,7 @@ class MandelWidget : public QOpenGLWidget
     Q_OBJECT
 private:
     mnd::MandelContext& mndContext;
+    mnd::Generator* generator;
 
     bool smoothColoring = true;
 
@@ -299,7 +300,7 @@ private:
 
     std::unique_ptr<MandelView> mandelView;
 public:
-    MandelWidget(mnd::MandelContext& ctxt, QWidget* parent = nullptr);
+    MandelWidget(mnd::MandelContext& ctxt, mnd::Generator* generator, QWidget* parent = nullptr);
     ~MandelWidget(void) override;
 
     inline const Gradient& getGradient(void) const { return gradient; }
@@ -314,6 +315,9 @@ public:
     inline int getMaxIterations(void) const { return maxIterations; }
     void setMaxIterations(int maxIter);
 
+    inline mnd::Generator* getGenerator(void) const { return generator; }
+    void setGenerator(mnd::Generator* generator);
+
     void initializeGL(void) override;
     void paintGL() override;
 

+ 118 - 4
choosegenerators.cpp

@@ -1,19 +1,133 @@
 #include "choosegenerators.h"
 #include "ui_choosegenerators.h"
 
+#include "Hardware.h"
+
 #include <QComboBox>
+#include <QRegExp>
+#include <QRegExpValidator>
 
-ChooseGenerators::ChooseGenerators(QWidget *parent) :
+ChooseGenerators::ChooseGenerators(mnd::MandelContext& mndCtxt, QWidget *parent) :
     QDialog{ parent },
-    ui{ std::make_unique<Ui::ChooseGenerators>() }
+    ui{ std::make_unique<Ui::ChooseGenerators>() },
+    mndCtxt{ mndCtxt },
+    tableContent{}
 {
     ui->setupUi(this);
 
-    ui->table->insertRow(0);
-    ui->table->setCellWidget(0, 1, new QComboBox(ui->table));
+    QRegExp floatingpoint{ "^[-+]?(\\d*\\.?\\d+|\\d+\\.?\\d*)([eE][-+]\\d+)?$" };
+    floatValidator = std::make_unique<QRegExpValidator>(floatingpoint, this);
+
+    generators = std::map<QString, mnd::Generator*> {
+        { "float", mndCtxt.getCpuGenerator(mnd::GeneratorType::FLOAT) },
+        { "double", mndCtxt.getCpuGenerator(mnd::GeneratorType::DOUBLE) },
+        { "double double", mndCtxt.getCpuGenerator(mnd::GeneratorType::DOUBLE_DOUBLE) },
+        { "quad double", mndCtxt.getCpuGenerator(mnd::GeneratorType::QUAD_DOUBLE) },
+        { "float256", mndCtxt.getCpuGenerator(mnd::GeneratorType::FLOAT256) },
+    };
+
+    if (mndCtxt.getCpuInfo().hasSse2()) {
+        generators.insert({ "float SSE2", mndCtxt.getCpuGenerator(mnd::GeneratorType::FLOAT_SSE2) });
+        generators.insert({ "double SSE2", mndCtxt.getCpuGenerator(mnd::GeneratorType::DOUBLE_SSE2) });
+    }
+    if (mndCtxt.getCpuInfo().hasAvx()) {
+        generators.insert({ "float AVX", mndCtxt.getCpuGenerator(mnd::GeneratorType::FLOAT_AVX) });
+        generators.insert({ "double AVX", mndCtxt.getCpuGenerator(mnd::GeneratorType::DOUBLE_AVX) });
+    }
+    if (mndCtxt.getCpuInfo().hasNeon()) {
+        generators.insert({ "float Neon", mndCtxt.getCpuGenerator(mnd::GeneratorType::FLOAT_NEON) });
+        generators.insert({ "double Neon", mndCtxt.getCpuGenerator(mnd::GeneratorType::DOUBLE_NEON) });
+    }
+    for (auto& device : mndCtxt.getDevices()) {
+        if (mnd::Generator* gen; (gen = device.getGenerator(mnd::GeneratorType::FLOAT))) {
+            generators.insert({ QString("float ") + QString::fromStdString(device.getName()),
+                                gen });
+        }
+        if (mnd::Generator* gen; (gen = device.getGenerator(mnd::GeneratorType::DOUBLE))) {
+            generators.insert({ QString("double ") + QString::fromStdString(device.getName()),
+                                gen });
+        }
+        if (mnd::Generator* gen; (gen = device.getGenerator(mnd::GeneratorType::DOUBLE_DOUBLE))) {
+            generators.insert({ QString("double double ") + QString::fromStdString(device.getName()),
+                                gen });
+        }
+    }
+
+    auto& defGen = mndCtxt.getDefaultGenerator();
+    for (auto it = defGen.getGenerators().rbegin(); it != defGen.getGenerators().rend(); it++) {
+        auto& [prec, gen] = *it;
+        ui->table->insertRow(0);
+        QLineEdit* le = createFloatText();
+        QComboBox* comboBox = createComboBox();
+        le->setSizePolicy(QSizePolicy::Policy::Preferred, QSizePolicy::Policy::Preferred);
+        comboBox->setSizePolicy(QSizePolicy::Policy::Preferred, QSizePolicy::Policy::Preferred);
+        ui->table->setCellWidget(0, 0, le);
+        ui->table->setCellWidget(0, 1, comboBox);
+        tableContent.push_back({ le, comboBox });
+        for (auto [n, g] : generators) {
+            if (gen == g) {
+                comboBox->setCurrentText(n);
+            }
+        }
+        le->setText(QString::number(static_cast<double>(prec)));
+        comboBox->adjustSize();
+        le->adjustSize();
+    }
+    ui->table->resizeColumnsToContents();
+
+
+    //ui->addRow->setIcon(ui->addRow->style()->standardIcon(QStyle::SP_));
+    //ui->moveRowUp->setIcon(ui->moveRowUp->style()->standardIcon(QStyle::SP_ArrowUp));
+    //ui->moveRowDown->setIcon(ui->moveRowDown->style()->standardIcon(QStyle::SP_ArrowDown));
 }
 
 
 ChooseGenerators::~ChooseGenerators()
 {
 }
+
+
+QComboBox* ChooseGenerators::createComboBox(void)
+{
+    QComboBox* qcb = new QComboBox(ui->table);
+
+    for (auto [name, type] : generators) {
+        qcb->addItem(name);
+    }
+
+    return qcb;
+}
+
+
+QLineEdit* ChooseGenerators::createFloatText(void)
+{
+    QLineEdit* le = new QLineEdit(ui->table);
+    le->setValidator(floatValidator.get());
+    return le;
+}
+
+
+void ChooseGenerators::on_buttonBox_accepted()
+{
+    if (!createdGenerator)
+        createdGenerator = std::make_unique<mnd::AdaptiveGenerator>();
+    createdGenerator->clear();
+    try {
+        for (size_t i = 0; i < tableContent.size(); i++) {
+            //std::cout << tableContent.at(i).first << std::endl;
+            //std::cout << tableContent.at(i).second << std::endl;
+            QString precString = tableContent.at(i).first->text();
+            QString genString = tableContent.at(i).second->currentText();
+
+            mnd::Real precision = mnd::Real(precString.toStdString().c_str());
+            mnd::Generator* generator = generators.at(genString);
+            if (generator)
+                createdGenerator->addGenerator(precision, *generator);
+        }
+    }
+    catch(...) {
+        // TODO
+        createdGenerator = nullptr;
+    }
+}
+

+ 21 - 1
choosegenerators.h

@@ -1,8 +1,15 @@
 #ifndef CHOOSEGENERATORS_H
 #define CHOOSEGENERATORS_H
+#include "ui_choosegenerators.h"
+
+#include "Mandel.h"
 
 #include <QDialog>
+#include <QValidator>
+#include <QLineEdit>
+#include <QComboBox>
 #include <memory>
+#include <map>
 
 namespace Ui
 {
@@ -15,11 +22,24 @@ class ChooseGenerators : public QDialog
     Q_OBJECT
 private:
     std::unique_ptr<Ui::ChooseGenerators> ui;
+    mnd::MandelContext& mndCtxt;
+    std::map<QString, mnd::Generator*> generators;
+    std::vector<std::pair<QLineEdit*, QComboBox*>> tableContent;
+    std::unique_ptr<QValidator> floatValidator;
+    std::unique_ptr<mnd::AdaptiveGenerator> createdGenerator;
 public:
-    explicit ChooseGenerators(QWidget* parent = nullptr);
+    ChooseGenerators(mnd::MandelContext& mndCtxt, QWidget* parent = nullptr);
     ~ChooseGenerators();
 
+    inline mnd::AdaptiveGenerator* getChosenGenerator(void) { return createdGenerator.get(); }
+
+private:
+    QComboBox* createComboBox(void);
+    QLineEdit* createFloatText(void);
+public slots:
 
+private slots:
+    void on_buttonBox_accepted();
 };
 
 #endif // CHOOSEGENERATORS_H

+ 128 - 16
choosegenerators.ui

@@ -15,21 +15,133 @@
   </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>
+    <layout class="QVBoxLayout" name="verticalLayout_2">
+     <item>
+      <widget class="QTabWidget" name="tabWidget">
+       <property name="currentIndex">
+        <number>1</number>
+       </property>
+       <widget class="QWidget" name="tab">
+        <attribute name="title">
+         <string>Measure Performance</string>
+        </attribute>
+        <layout class="QHBoxLayout" name="horizontalLayout_3">
+         <item>
+          <widget class="QTableWidget" name="tableWidget_2">
+           <property name="editTriggers">
+            <set>QAbstractItemView::NoEditTriggers</set>
+           </property>
+           <property name="columnCount">
+            <number>1</number>
+           </property>
+           <attribute name="verticalHeaderVisible">
+            <bool>false</bool>
+           </attribute>
+           <column/>
+          </widget>
+         </item>
+         <item>
+          <layout class="QVBoxLayout" name="verticalLayout_3">
+           <item>
+            <widget class="Line" name="line_2">
+             <property name="orientation">
+              <enum>Qt::Horizontal</enum>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="label">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Measure the preformance of Almond on this machine. To obtain good results, run the benchmarks while no other compute-heavy tasks are running on the computer.&lt;/p&gt;&lt;p&gt;The benchmarking consists of several renders of the Mandelbrot fractal each using a different datatype for the underlying operations. The more precision the type allows for, the slower it performs (normally). If you have a video card, Almond will try to use it to do calculations as the tasks are exceptionally well suited for parallel execution.&lt;/p&gt;&lt;p&gt;All results are measured in mega-iterations per second.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+             </property>
+             <property name="wordWrap">
+              <bool>true</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="Line" name="line">
+             <property name="orientation">
+              <enum>Qt::Horizontal</enum>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <layout class="QHBoxLayout" name="horizontalLayout_2">
+             <item>
+              <widget class="QPushButton" name="run">
+               <property name="text">
+                <string>Run</string>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QProgressBar" name="progressBar">
+               <property name="enabled">
+                <bool>false</bool>
+               </property>
+               <property name="maximum">
+                <number>100</number>
+               </property>
+               <property name="value">
+                <number>0</number>
+               </property>
+               <property name="textVisible">
+                <bool>false</bool>
+               </property>
+               <property name="invertedAppearance">
+                <bool>false</bool>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </item>
+          </layout>
+         </item>
+        </layout>
+       </widget>
+       <widget class="QWidget" name="tab_2">
+        <attribute name="title">
+         <string>Select Generators</string>
+        </attribute>
+        <layout class="QVBoxLayout" name="verticalLayout_4">
+         <item>
+          <widget class="QTableWidget" name="table">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <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>
+        </layout>
+       </widget>
+      </widget>
+     </item>
+     <item>
+      <layout class="QHBoxLayout" name="horizontalLayout"/>
+     </item>
+    </layout>
    </item>
    <item>
     <widget class="QDialogButtonBox" name="buttonBox">
@@ -37,7 +149,7 @@
       <enum>Qt::Horizontal</enum>
      </property>
      <property name="standardButtons">
-      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+      <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
      </property>
     </widget>
    </item>

+ 3 - 0
libmandel/include/Generators.h

@@ -57,6 +57,9 @@ public:
 
     void addGenerator(const Real& precision, Generator& generator);
     void addGenerator(Precision p, Generator& generator);
+    
+    const std::map<Real, Generator*, std::greater<Real>>& getGenerators(void) const { return generators; }
+    inline void clear(void) { generators.clear(); }
 
     virtual void generate(const MandelInfo& info, float* data);
 };

+ 3 - 3
libmandel/include/Hardware.h

@@ -35,13 +35,13 @@ public:
     inline const std::string& getBrand(void) const { return brand; };
 
 
-#if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) 
+//#if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86)
     inline bool hasSse2(void) const { return sse2; };
     inline bool hasAvx(void) const { return avx; };
     inline bool hasAvx512(void) const { return avx512; };
-#elif defined(__arm__) || defined(__aarch64__)
+//#elif defined(__arm__) || defined(__aarch64__)
     inline bool hasNeon(void) const { return neon; };
-#endif
+//#endif
 };
 
 #endif // MANDEL_HARDWARE_H

+ 1 - 1
libmandel/include/Mandel.h

@@ -89,7 +89,7 @@ public:
     MandelContext& operator=(const MandelContext&) = delete;
     MandelContext& operator=(MandelContext&&) = default;
 
-    Generator& getDefaultGenerator(void);
+    AdaptiveGenerator& getDefaultGenerator(void);
     const std::vector<MandelDevice>& getDevices(void);
 
     Generator* getCpuGenerator(mnd::GeneratorType type);

+ 12 - 4
libmandel/src/Hardware.cpp

@@ -17,7 +17,11 @@ using mnd::CpuInfo;
 
 
 #if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) 
-CpuInfo::CpuInfo(void)
+CpuInfo::CpuInfo(void) :
+    sse2{ false },
+    avx{ false },
+    avx512{ false },
+    neon{ false }
 {
 
 
@@ -46,7 +50,7 @@ CpuInfo::CpuInfo(void)
     nExtData = dat[0];
 #endif
 
-    for (int i = 0; i <= nData; i++) {
+    for (unsigned int i = 0; i <= nData; i++) {
 #ifdef __GNUC__
         __get_cpuid(i, &dat[0], &dat[1], &dat[2], &dat[3]);
 #else
@@ -55,7 +59,7 @@ CpuInfo::CpuInfo(void)
         cpuData.push_back(dat);
     }
 
-    for (int i = 0x80000000; i <= nExtData; i++) {
+    for (unsigned int i = 0x80000000; i <= nExtData; i++) {
 #ifdef __GNUC__
         __get_cpuid(i, &dat[0], &dat[1], &dat[2], &dat[3]);
 #else
@@ -107,7 +111,11 @@ CpuInfo::CpuInfo(void)
 
 #elif defined(__arm__) || defined(__aarch64__)
 
-CpuInfo::CpuInfo(void)
+CpuInfo::CpuInfo(void) :
+    sse2{ false },
+    avx{ false },
+    avx512{ false },
+    neon{ false }
 {
 #if defined(__aarch64__)
     arch = Arch::ARM64;

+ 1 - 1
libmandel/src/Mandel.cpp

@@ -196,7 +196,7 @@ std::vector<MandelDevice> MandelContext::createDevices(void)
 }
 
 
-Generator& MandelContext::getDefaultGenerator(void)
+AdaptiveGenerator& MandelContext::getDefaultGenerator(void)
 {
     return *adaptiveGenerator;
 }