Browse Source

usable ui

Nicolas Winkler 5 years ago
parent
commit
62174a9c2a

+ 24 - 7
Almond.cpp

@@ -78,7 +78,7 @@ void Almond::on_maxIterations_editingFinished()
 
 void Almond::on_chooseGradient_clicked()
 {
-    auto response = gcd.exec();
+    gcd.exec();
     auto gradient = gcd.getGradient();
     if (gradient)
         mw->setGradient(std::move(*gradient));
@@ -171,20 +171,32 @@ void Almond::on_displayInfo_stateChanged(int checked)
 
 void Almond::on_chooseGenerator_clicked()
 {
-    if (!generatorsDialog)
-        generatorsDialog = std::make_unique<ChooseGenerators>(mandelContext, *this);
+    std::unique_ptr<ChooseGenerators> generatorsDialog;
+    if (currentView == MANDELBROT)
+        generatorsDialog = std::make_unique<ChooseGenerators>(mandelContext, *mandelGenerator, *this);
+    else if (currentView == CUSTOM)
+        generatorsDialog = std::make_unique<ChooseGenerators>(mandelContext, this->currentCustom->gc, *customGenerator, *this);
+    else
+        return;
+
     generatorsDialog->exec();
 
     auto gen = generatorsDialog->extractChosenGenerator();
     if (gen) {
+        if (currentView == MANDELBROT || currentView == JULIA) {
+            mandelGenerator = gen.get();
+        }
+        else if (currentView == CUSTOM) {
+            customGenerator = gen.get();
+        }
         currentGenerator = gen.get();
+        this->mw->setGenerator(currentGenerator);
         adjustedGenerators.push_back(std::move(gen));
     }
     else {
         //mandelGenerator = &mandelContext.getDefaultGenerator();
     }
     //this->currentView = MANDELBROT;
-    this->mw->setGenerator(currentGenerator);
     //this->mw->getMandelInfo().julia = false;
     //printf("dialog executed\n"); fflush(stdout);
 }
@@ -305,7 +317,9 @@ void Almond::on_radioButton_2_toggled(bool checked)
         if (customGenerator == nullptr) {
             customGeneratorDialog->exec();
             if (auto* frac = customGeneratorDialog->getLastCompiled()) {
-                customGenerator = frac->gc.cpuGenerators[0].get();
+                customGenerator = frac->gc.adaptiveGenerator.get();
+                customGenerators.push_back(std::make_unique<FractalDef>(std::move(*frac)));
+                currentCustom = customGenerators[customGenerators.size() - 1].get();
             }
         }
         setViewType(CUSTOM);
@@ -316,7 +330,10 @@ void Almond::on_createCustom_clicked()
 {
     customGeneratorDialog->exec();
     if (auto* frac = customGeneratorDialog->getLastCompiled()) {
-        customGenerator = frac->gc.cpuGenerators[0].get();
+        customGenerator = frac->gc.adaptiveGenerator.get();
+        customGenerators.push_back(std::make_unique<FractalDef>(std::move(*frac)));
+        currentCustom = customGenerators[customGenerators.size() - 1].get();
+        this->ui.radioButton_2->setChecked(true);
+        setViewType(CUSTOM);
     }
-    setViewType(CUSTOM);
 }

+ 4 - 4
Almond.h

@@ -36,18 +36,18 @@ private:
     mnd::MandelContext mandelContext;
     std::unique_ptr<MandelWidget> mw;
     //std::unique_ptr<BenchmarkDialog> benchmarkDialog;
-    std::unique_ptr<ChooseGenerators> generatorsDialog;
     std::unique_ptr<CustomGenerator> customGeneratorDialog;
     GradientChooseDialog gcd;
 
-    std::vector<std::unique_ptr<mnd::MandelGenerator>> compiledGenerators;
+    std::vector<std::unique_ptr<FractalDef>> customGenerators;
+    FractalDef* currentCustom;
+    mnd::AdaptiveGenerator* customGenerator;
     std::vector<std::unique_ptr<mnd::AdaptiveGenerator>> adjustedGenerators;
 
     ViewType currentView;
     mnd::MandelViewport mandelViewSave;
     mnd::MandelViewport customViewSave;
-    mnd::MandelGenerator* mandelGenerator;
-    mnd::MandelGenerator* customGenerator;
+    mnd::AdaptiveGenerator* mandelGenerator;
     mnd::MandelGenerator* currentGenerator;
 public:
     Almond(QWidget *parent = Q_NULLPTR);

+ 133 - 40
choosegenerators.cpp

@@ -20,7 +20,33 @@ mnd::MandelViewport Benchmarker::benchViewport(void)
 }
 
 
-const std::vector<mnd::MandelInfo> Benchmarker::benches {
+static std::vector<mnd::MandelInfo> createBenches()
+{
+    std::vector<mnd::MandelInfo> vec;
+    for (int i = 0; i < 50; i++) {
+        int expo = i + 14;
+        int whe = 5;
+
+        if (expo > 16)
+            whe = 6;
+        if (expo > 18)
+            whe = 7;
+        if (expo > 20)
+            whe = 8;
+        if (expo > 23)
+            whe = 9;
+        if (expo > 26)
+            whe = 10;
+
+        long wh = 1L << whe;
+        long iter = 1L << (expo - 2 * whe);
+        vec.push_back(mnd::MandelInfo{ mnd::MandelViewport::centerView(), wh, wh, iter, false, false, 0.0, 0.0 });
+    }
+    return vec;
+}
+
+
+const std::vector<mnd::MandelInfo> Benchmarker::benches = createBenches(); /*{
     mnd::MandelInfo{ benchViewport(), 32, 32, 15, false },
     mnd::MandelInfo{ benchViewport(), 32, 32, 25, false },
     mnd::MandelInfo{ benchViewport(), 32, 32, 75, false },
@@ -60,7 +86,7 @@ const std::vector<mnd::MandelInfo> Benchmarker::benches {
     mnd::MandelInfo{ benchViewport(), 2048, 2048, 524288000, false },
     mnd::MandelInfo{ benchViewport(), 2048, 2048, 1048576000, false },
     mnd::MandelInfo{ benchViewport(), 2048, 2048, 2097152000, false },
-};
+};*/
 
 
 Benchmarker::~Benchmarker(void)
@@ -124,13 +150,13 @@ void Benchmarker::run(void)
 }
 
 
-ChooseGenerators::ChooseGenerators(mnd::MandelContext& mndCtxt, Almond& owner) :
+ChooseGenerators::ChooseGenerators(mnd::MandelContext& mndCtxt, mnd::AdaptiveGenerator& generator, Almond& owner) :
     QDialog{ &owner },
     owner{ owner },
     ui{ std::make_unique<Ui::ChooseGenerators>() },
     mndCtxt{ mndCtxt },
     tableContent{},
-    generator{ mndCtxt.getDefaultGenerator() }
+    generator{ generator }
 {
     ui->setupUi(this);
     ui->progressBar->setRange(0, 1000);
@@ -148,12 +174,89 @@ ChooseGenerators::ChooseGenerators(mnd::MandelContext& mndCtxt, Almond& owner) :
         generators.insert({ QString::fromStdString(typeName), mndCtxt.getCpuGenerator(genType) });
     }
     for (auto& device : mndCtxt.getDevices()) {
+        for (auto genType : device->getSupportedTypes()) {
+            const std::string& typeName = mnd::getGeneratorName(genType) + " [" + device->getName() + "]";
+            generators.insert({ QString::fromStdString(typeName), device->getGenerator(genType) });
+        }
+    }
+
+    std::vector<mnd::MandelGenerator*> allGenerators;
+
+    /*for (auto genType : mndCtxt.getSupportedTypes()) {
+        allGenerators.push_back(mndCtxt.getCpuGenerator(genType));
+    }
+    for (auto& device : mndCtxt.getDevices()) {
         for (auto genType : device.getSupportedTypes()) {
-            const std::string& typeName = mnd::getGeneratorName(genType) + " [" + device.getName() + "]";
-            generators.insert({ QString::fromStdString(typeName), device.getGenerator(genType) });
+            allGenerators.push_back(device.getGenerator(genType));
         }
+    }*/
+
+    initializeTables(allGenerators);
+
+    //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(mnd::MandelContext& mndCtxt, mnd::GeneratorCollection& gc,
+                                   mnd::AdaptiveGenerator& generator, Almond& owner) :
+    QDialog{ &owner },
+    owner{ owner },
+    ui{ std::make_unique<Ui::ChooseGenerators>() },
+    mndCtxt{ mndCtxt },
+    tableContent{},
+    generator{ generator }
+{
+    ui->setupUi(this);
+    ui->progressBar->setRange(0, 1000);
+    benchmarker.setMaxThreadCount(1);
+
+    QFont f("unexistent");
+    f.setStyleHint(QFont::Monospace);
+    f.setPointSize(12);
+
+    QRegExp floatingpoint{ "^[-+]?(\\d*\\.?\\d+|\\d+\\.?\\d*)([eE][-+]\\d+)?$" };
+    floatValidator = std::make_unique<QRegExpValidator>(floatingpoint, this);
+
+    for (auto& gen : gc.cpuGenerators) {
+        const mnd::Precision p = gen->getType();
+        const mnd::CpuExtension ce = gen->getExtension();
+        std::string typeName = mnd::toString(p) + " " + mnd::toString(ce);
+        generators.insert({ QString::fromStdString(typeName), gen.get() });
+    }
+
+
+    for (auto& gen : gc.clGenerators) {
+        const mnd::Precision p = gen->getType();
+        const mnd::CpuExtension ce = gen->getExtension();
+        mnd::MandelDevice* dev = gen->getDevice();
+        std::string devString = dev != nullptr ? dev->getName() : "";
+        std::string typeName = mnd::toString(p) + " " + mnd::toString(ce) + " [" + devString + "]";
+        generators.insert({ QString::fromStdString(typeName), gen.get() });
     }
 
+    std::vector<mnd::MandelGenerator*> allGenerators;
+
+    /*for (auto& gen : gc.cpuGenerators) {
+        allGenerators.push_back(gen.get());
+    }
+    for (auto& gen : gc.clGenerators) {
+        allGenerators.push_back(gen.get());
+    }*/
+
+    initializeTables(allGenerators);
+}
+
+
+ChooseGenerators::~ChooseGenerators()
+{
+}
+
+
+
+void ChooseGenerators::initializeTables(const std::vector<mnd::MandelGenerator*>& allGenerators)
+{
     for (auto it = generator.getGenerators().rbegin(); it != generator.getGenerators().rend(); it++) {
         auto& [prec, gen] = *it;
         ui->table->insertRow(0);
@@ -175,7 +278,27 @@ ChooseGenerators::ChooseGenerators(mnd::MandelContext& mndCtxt, Almond& owner) :
     }
     ui->table->resizeColumnsToContents();
 
-    std::vector<mnd::GeneratorType> generatorTypes = mndCtxt.getSupportedTypes();
+    int i = 0;
+    for (auto it = generators.begin(); it != generators.end(); ++it, ++i) {
+        int rowCount = ui->generatorTable->rowCount();
+        ui->generatorTable->insertRow(rowCount);
+        ui->generatorTable->setItem(rowCount, 0, new QTableWidgetItem);
+        ui->generatorTable->setItem(rowCount, 1, new QTableWidgetItem);
+        mnd::MandelGenerator& gene = *it->second;
+        mnd::Precision p = gene.getType();
+        mnd::CpuExtension ex = gene.getExtension();
+        mnd::MandelDevice* dev = gene.getDevice();
+
+        std::string desc = mnd::toString(p) + " " + mnd::toString(ex);
+        if (dev)
+            desc += "[" + dev->getName() + "]";
+        const mnd::Real& prec = gene.getPrecision();
+        ui->generatorTable->item(rowCount, 0)->setText(QString::fromStdString(desc));
+        ui->generatorTable->item(rowCount, 1)->setText(QString::fromStdString(mnd::toLegibleString(prec)));
+        actualGenerators.push_back(&gene);
+    }
+
+    /*std::vector<mnd::GeneratorType> generatorTypes = mndCtxt.getSupportedTypes();
     for (size_t i = 0; i < generatorTypes.size(); i++) {
         int rowCount = ui->generatorTable->rowCount();
         ui->generatorTable->insertRow(rowCount);
@@ -201,27 +324,7 @@ ChooseGenerators::ChooseGenerators(mnd::MandelContext& mndCtxt, Almond& owner) :
             ui->generatorTable->item(rowCount, 1)->setText(QString::fromStdString(mnd::toLegibleString(prec)));
             actualGenerators.push_back(device.getGenerator(generatorTypes[i]));
         }
-    }
-
-    //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(mnd::MandelContext& mndCtxt, mnd::GeneratorCollection& gc, Almond& owner) :
-    QDialog{ &owner },
-    owner{ owner },
-    ui{ std::make_unique<Ui::ChooseGenerators>() },
-    mndCtxt{ mndCtxt },
-    tableContent{},
-    generator{ mndCtxt.getDefaultGenerator() }
-{
-}
-
-
-ChooseGenerators::~ChooseGenerators()
-{
+    }*/
 }
 
 
@@ -286,8 +389,8 @@ void ChooseGenerators::on_buttonBox_accepted()
                 chosenGenerator->addGenerator(precision, *generator);
         }*/
         for (size_t i = 0; i < ui->table->rowCount(); i++) {
-            QLineEdit* precItem = dynamic_cast<QLineEdit*>(ui->table->cellWidget(0, i));
-            QWidget* genWidget = ui->table->cellWidget(1, i);
+            QLineEdit* precItem = dynamic_cast<QLineEdit*>(ui->table->cellWidget(i, 0));
+            QWidget* genWidget = ui->table->cellWidget(i, 1);
             QComboBox* genItem = dynamic_cast<QComboBox*>(genWidget);
             if (precItem && genItem) {
                 QString precString = precItem->text();
@@ -343,16 +446,6 @@ void ChooseGenerators::on_generatorTable_cellDoubleClicked(int row, int column)
 }
 
 
-void ChooseGenerators::on_compile_clicked()
-{
-}
-
-
-void ChooseGenerators::on_benchmark_clicked()
-{
-}
-
-
 
 void ChooseGenerators::on_addRow_clicked()
 {

+ 6 - 4
choosegenerators.h

@@ -81,17 +81,21 @@ public:
     /*!
      * \brief create a dialog that lets choose from the default mandelbrot generators
      */
-    ChooseGenerators(mnd::MandelContext& mndCtxt, Almond& owner);
+    ChooseGenerators(mnd::MandelContext& mndCtxt, mnd::AdaptiveGenerator& generator, Almond& owner);
 
     /*!
      * \brief create a dialog that lets choose from the default mandelbrot generators
      */
-    ChooseGenerators(mnd::MandelContext& mndCtxt, mnd::GeneratorCollection& gc, Almond& owner);
+    ChooseGenerators(mnd::MandelContext& mndCtxt, mnd::GeneratorCollection& gc,
+                     mnd::AdaptiveGenerator& generator, Almond& owner);
     ~ChooseGenerators();
 
     inline std::unique_ptr<mnd::AdaptiveGenerator> extractChosenGenerator(void) { return std::move(chosenGenerator); }
 
 private:
+
+    void initializeTables(const std::vector<mnd::MandelGenerator *> &allGenerators);
+
     QComboBox* createComboBox(void);
     QLineEdit* createFloatText(void);
 
@@ -103,8 +107,6 @@ private slots:
     void on_buttonBox_accepted();
     void on_run_clicked();
     void on_generatorTable_cellDoubleClicked(int row, int column);
-    void on_compile_clicked();
-    void on_benchmark_clicked();
     void on_addRow_clicked();
     void on_removeRow_clicked();
 };

+ 39 - 39
choosegenerators.ui

@@ -21,50 +21,13 @@
        <item>
         <widget class="QTabWidget" name="tabWidget">
          <property name="currentIndex">
-          <number>1</number>
+          <number>0</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="generatorTable">
-             <property name="editTriggers">
-              <set>QAbstractItemView::NoEditTriggers</set>
-             </property>
-             <property name="alternatingRowColors">
-              <bool>true</bool>
-             </property>
-             <attribute name="horizontalHeaderVisible">
-              <bool>false</bool>
-             </attribute>
-             <attribute name="horizontalHeaderDefaultSectionSize">
-              <number>180</number>
-             </attribute>
-             <attribute name="horizontalHeaderMinimumSectionSize">
-              <number>100</number>
-             </attribute>
-             <attribute name="verticalHeaderVisible">
-              <bool>false</bool>
-             </attribute>
-             <column>
-              <property name="text">
-               <string>Generator Type</string>
-              </property>
-             </column>
-             <column>
-              <property name="text">
-               <string>Precision</string>
-              </property>
-             </column>
-             <column>
-              <property name="text">
-               <string>Performance</string>
-              </property>
-             </column>
-            </widget>
-           </item>
+          <layout class="QHBoxLayout" name="horizontalLayout_3" stretch="1,2">
            <item>
             <layout class="QVBoxLayout" name="verticalLayout_3">
              <item>
@@ -135,6 +98,43 @@
              </item>
             </layout>
            </item>
+           <item>
+            <widget class="QTableWidget" name="generatorTable">
+             <property name="editTriggers">
+              <set>QAbstractItemView::NoEditTriggers</set>
+             </property>
+             <property name="alternatingRowColors">
+              <bool>true</bool>
+             </property>
+             <attribute name="horizontalHeaderVisible">
+              <bool>false</bool>
+             </attribute>
+             <attribute name="horizontalHeaderDefaultSectionSize">
+              <number>180</number>
+             </attribute>
+             <attribute name="horizontalHeaderMinimumSectionSize">
+              <number>100</number>
+             </attribute>
+             <attribute name="verticalHeaderVisible">
+              <bool>false</bool>
+             </attribute>
+             <column>
+              <property name="text">
+               <string>Generator Type</string>
+              </property>
+             </column>
+             <column>
+              <property name="text">
+               <string>Precision</string>
+              </property>
+             </column>
+             <column>
+              <property name="text">
+               <string>Performance</string>
+              </property>
+             </column>
+            </widget>
+           </item>
           </layout>
          </widget>
          <widget class="QWidget" name="tab_2">

+ 38 - 48
customgenerator.ui

@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>835</width>
-    <height>479</height>
+    <width>725</width>
+    <height>303</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -15,7 +15,7 @@
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
-    <layout class="QHBoxLayout" name="horizontalLayout_4">
+    <layout class="QHBoxLayout" name="horizontalLayout_4" stretch="10,0,17">
      <item>
       <widget class="QLabel" name="label_3">
        <property name="sizePolicy">
@@ -25,7 +25,20 @@
         </sizepolicy>
        </property>
        <property name="text">
-        <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt; font-weight:600;&quot;&gt;Formula Editor&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+        <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt; font-weight:600;&quot;&gt;Formula Editor&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-size:9pt;&quot;&gt;Almond applies an escape-time algorithm to display fractals. A formula can be entered in this form, which will then be iteratively applied to complex numbers until its absolute value reaches a certain threshold. Depending on how many iterations were needed to reach the threshold, a different color is applied to the image.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+       </property>
+       <property name="textFormat">
+        <enum>Qt::AutoText</enum>
+       </property>
+       <property name="wordWrap">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="Line" name="line">
+       <property name="orientation">
+        <enum>Qt::Vertical</enum>
        </property>
       </widget>
      </item>
@@ -33,40 +46,6 @@
       <layout class="QVBoxLayout" name="verticalLayout_5">
        <item>
         <layout class="QFormLayout" name="formLayout">
-         <item row="3" column="0">
-          <widget class="QLabel" name="label_2">
-           <property name="font">
-            <font>
-             <pointsize>12</pointsize>
-            </font>
-           </property>
-           <property name="text">
-            <string>z := </string>
-           </property>
-          </widget>
-         </item>
-         <item row="3" column="1">
-          <widget class="QLineEdit" name="formula_zi">
-           <property name="font">
-            <font>
-             <pointsize>12</pointsize>
-            </font>
-           </property>
-           <property name="text">
-            <string>z^2+c</string>
-           </property>
-          </widget>
-         </item>
-         <item row="5" column="0">
-          <widget class="QPushButton" name="benchmark">
-           <property name="text">
-            <string>Benchmark</string>
-           </property>
-          </widget>
-         </item>
-         <item row="5" column="1">
-          <widget class="QLineEdit" name="compBenchResult"/>
-         </item>
          <item row="0" column="0" colspan="2">
           <widget class="QLabel" name="descriptionInitial">
            <property name="font">
@@ -121,18 +100,29 @@
            </property>
           </widget>
          </item>
-         <item row="4" column="1">
-          <spacer name="verticalSpacer">
-           <property name="orientation">
-            <enum>Qt::Vertical</enum>
+         <item row="3" column="0">
+          <widget class="QLabel" name="label_2">
+           <property name="font">
+            <font>
+             <pointsize>12</pointsize>
+            </font>
+           </property>
+           <property name="text">
+            <string>z := </string>
+           </property>
+          </widget>
+         </item>
+         <item row="3" column="1">
+          <widget class="QLineEdit" name="formula_zi">
+           <property name="font">
+            <font>
+             <pointsize>12</pointsize>
+            </font>
            </property>
-           <property name="sizeHint" stdset="0">
-            <size>
-             <width>20</width>
-             <height>40</height>
-            </size>
+           <property name="text">
+            <string>z^2+c</string>
            </property>
-          </spacer>
+          </widget>
          </item>
         </layout>
        </item>

+ 1 - 0
libmandel/include/ClGenerators.h

@@ -40,6 +40,7 @@ public:
     virtual ~ClGenerator(void);
 
     virtual void generate(const MandelInfo& info, float* data) = 0;
+    virtual mnd::MandelDevice* getDevice(void);
 };
 
 

+ 12 - 0
libmandel/include/Generators.h

@@ -43,6 +43,9 @@ namespace mnd
         ARM_NEON,
     };
 
+    std::string toString(Precision);
+    std::string toString(CpuExtension);
+
     Real getPrecision(Precision p);
     Real getPrecision(GeneratorType p);
     
@@ -72,6 +75,8 @@ namespace mnd
     template<> inline Precision getType<Float128>() { return Precision::FLOAT128; }
     template<> inline Precision getType<Float256>() { return Precision::FLOAT256; }
     template<> inline Precision getType<Float512>() { return Precision::FLOAT512; }
+
+    class MandelDevice;
 }
 
 
@@ -142,7 +147,12 @@ public:
     MandelGenerator& operator=(MandelGenerator&&) = default;
 
     virtual void generate(const MandelInfo& info, float* data) = 0;
+
+    virtual mnd::MandelDevice* getDevice(void);
+
     virtual Real getPrecision(void) const;
+    virtual Precision getType(void) const;
+    virtual CpuExtension getExtension(void) const;
 };
 
 
@@ -151,6 +161,8 @@ class mnd::AdaptiveGenerator : public MandelGenerator
     std::map<Real, MandelGenerator*, std::greater<Real>> generators;
 public:
     AdaptiveGenerator(void);
+    AdaptiveGenerator(AdaptiveGenerator&) = default;
+    AdaptiveGenerator(AdaptiveGenerator&&) = default;
     AdaptiveGenerator(MandelGenerator* floatGen, MandelGenerator* doubleGen);
     virtual ~AdaptiveGenerator(void) = default;
 

+ 9 - 0
libmandel/include/IterationCompiler.h

@@ -41,6 +41,15 @@ struct mnd::GeneratorCollection
 {
     std::vector<std::unique_ptr<mnd::MandelGenerator>> cpuGenerators;
     std::vector<std::unique_ptr<mnd::MandelGenerator>> clGenerators;
+    std::unique_ptr<mnd::AdaptiveGenerator> adaptiveGenerator;
+
+    GeneratorCollection(void);
+    GeneratorCollection(const GeneratorCollection&) = delete;
+    GeneratorCollection(GeneratorCollection&&) = default;
+    ~GeneratorCollection(void) = default;
+
+    GeneratorCollection& operator=(GeneratorCollection&&) = default;
+    GeneratorCollection& operator=(const GeneratorCollection&) = delete;
 };
 
 

+ 4 - 4
libmandel/include/Mandel.h

@@ -44,8 +44,8 @@ private:
 
     std::map<GeneratorType, std::unique_ptr<MandelGenerator>> mandelGenerators;
 
-    MandelDevice(ClDeviceWrapper);
 public:
+    MandelDevice(ClDeviceWrapper);
     MandelDevice(const MandelDevice&) = delete;
     MandelDevice(MandelDevice&&) = default;
     MandelDevice& operator=(const MandelDevice&) = delete;
@@ -74,12 +74,12 @@ private:
 
     std::unique_ptr<AdaptiveGenerator> adaptiveGenerator;
 
-    std::vector<MandelDevice> devices;
+    std::vector<std::unique_ptr<mnd::MandelDevice>> devices;
 
     MandelContext(void);
 
     std::unique_ptr<AdaptiveGenerator> createAdaptiveGenerator(void);
-    std::vector<MandelDevice> createDevices(void);
+    std::vector<std::unique_ptr<mnd::MandelDevice>> createDevices(void);
 public:
     ~MandelContext(void);
     MandelContext(const MandelContext&) = delete;
@@ -88,7 +88,7 @@ public:
     MandelContext& operator=(MandelContext&&) = default;
 
     AdaptiveGenerator& getDefaultGenerator(void);
-    std::vector<MandelDevice>& getDevices(void);
+    std::vector<std::unique_ptr<mnd::MandelDevice>>& getDevices(void);
 
     asmjit::JitRuntime& getJitRuntime(void);
 

+ 6 - 0
libmandel/src/ClGenerators.cpp

@@ -105,6 +105,12 @@ ClGenerator::~ClGenerator(void)
 }
 
 
+mnd::MandelDevice* ClGenerator::getDevice(void)
+{
+    return &device;
+}
+
+
 ClGeneratorFloat::ClGeneratorFloat(mnd::MandelDevice& device, const std::string& code) :
     ClGenerator{ device, code, mnd::Precision::FLOAT }
 {

+ 71 - 1
libmandel/src/Generators.cpp

@@ -11,14 +11,34 @@ MandelGenerator::~MandelGenerator(void)
 }
 
 
+
+mnd::MandelDevice* MandelGenerator::getDevice(void)
+{
+    return nullptr;
+}
+
+
 mnd::Real MandelGenerator::getPrecision(void) const
 {
     return precision;
 }
 
 
+mnd::Precision MandelGenerator::getType(void) const
+{
+    return type;
+}
+
+
+mnd::CpuExtension MandelGenerator::getExtension(void) const
+{
+    return extension;
+}
+
+
 AdaptiveGenerator::AdaptiveGenerator(void) :
-    MandelGenerator{ mnd::Precision::INF_PREC }
+    MandelGenerator{ mnd::Precision::INF_PREC },
+    generators{}
 {
 }
 
@@ -93,6 +113,56 @@ void AdaptiveGenerator::generate(const mnd::MandelInfo& info, float* data)
 
 namespace mnd
 {
+    std::string toString(Precision p)
+    {
+        switch (p) {
+        case Precision::FLOAT:
+            return "float";
+        case Precision::DOUBLE_FLOAT:
+            return "double-float";
+        case Precision::DOUBLE:
+            return "double";
+        case Precision::DOUBLE_DOUBLE:
+            return "double-double";
+        case Precision::FLOAT128:
+            return "float128";
+        case Precision::FLOAT256:
+            return "float256";
+        case Precision::FLOAT512:
+            return "float512";
+        case Precision::FIXED64:
+            return "fixed64";
+        case Precision::FIXED128:
+            return "fixed128";
+        case Precision::FIXED512:
+            return "fixed512";
+        case Precision::QUAD_DOUBLE:
+            return "quad-double";
+        case Precision::INF_PREC:
+            return "real";
+        }
+    }
+
+
+    std::string toString(CpuExtension ce)
+    {
+        switch (ce) {
+        case CpuExtension::NONE:
+            return "";
+        case CpuExtension::X86_SSE2:
+            return "SSE2";
+        case CpuExtension::X86_AVX:
+            return "AVX";
+        case CpuExtension::X86_AVX_FMA:
+            return "AVX2+FMA";
+        case CpuExtension::X86_AVX_512:
+            return "AVX512";
+        case CpuExtension::ARM_NEON:
+            return "NEON";
+        }
+    }
+
+
     Real getPrecision(Precision p)
     {
         static const std::map<Precision, Real> precs {

+ 17 - 2
libmandel/src/IterationCompiler.cpp

@@ -475,15 +475,30 @@ namespace mnd
     {
         GeneratorCollection cr;
         cr.cpuGenerators = compileCpu(mndCtxt, z0, zi);
-        for (mnd::MandelDevice& dev : mndCtxt.getDevices()) {
-            auto gens = compileOpenCl(dev, z0, zi);
+        for (auto& dev : mndCtxt.getDevices()) {
+            auto gens = compileOpenCl(*dev, z0, zi);
             std::move(gens.begin(), gens.end(), std::back_inserter(cr.clGenerators));
         }
 
+        cr.adaptiveGenerator = std::make_unique<mnd::AdaptiveGenerator>();
+        if (!cr.clGenerators.empty()) {
+            cr.adaptiveGenerator->addGenerator(mnd::getPrecision<float>(), *cr.clGenerators[0]);
+        }
+        if (!cr.cpuGenerators.empty()) {
+            cr.adaptiveGenerator->addGenerator(mnd::getPrecision<double>(), *cr.cpuGenerators[0]);
+        }
+
         return cr;
     }
 }
 
+mnd::GeneratorCollection::GeneratorCollection(void) :
+    cpuGenerators{},
+    clGenerators{},
+    adaptiveGenerator{ nullptr }
+{
+
+}
 
 
 using namespace asmjit;

+ 11 - 9
libmandel/src/Mandel.cpp

@@ -213,10 +213,10 @@ std::unique_ptr<mnd::AdaptiveGenerator> MandelContext::createAdaptiveGenerator(v
 
     if (!devices.empty()) {
         auto& device = devices[0];
-        auto* fGen = device.getGenerator(GeneratorType::FLOAT);
-        auto* dGen = device.getGenerator(GeneratorType::DOUBLE);
-        auto* ddGen = device.getGenerator(GeneratorType::DOUBLE_DOUBLE);
-        auto* qdGen = device.getGenerator(GeneratorType::QUAD_DOUBLE);
+        auto* fGen = device->getGenerator(GeneratorType::FLOAT);
+        auto* dGen = device->getGenerator(GeneratorType::DOUBLE);
+        auto* ddGen = device->getGenerator(GeneratorType::DOUBLE_DOUBLE);
+        auto* qdGen = device->getGenerator(GeneratorType::QUAD_DOUBLE);
 
         if (fGen)
             floatGen = fGen;
@@ -240,9 +240,9 @@ std::unique_ptr<mnd::AdaptiveGenerator> MandelContext::createAdaptiveGenerator(v
 }
 
 
-std::vector<MandelDevice> MandelContext::createDevices(void)
+std::vector<std::unique_ptr<MandelDevice>> MandelContext::createDevices(void)
 {
-    std::vector<MandelDevice> mandelDevices;
+    std::vector<std::unique_ptr<MandelDevice>> mandelDevices;
 #ifdef WITH_OPENCL
     std::vector<cl::Platform> platforms;
     cl::Platform::get(&platforms);
@@ -269,7 +269,9 @@ std::vector<MandelDevice> MandelContext::createDevices(void)
             auto supportsDouble = extensions.find("cl_khr_fp64") != std::string::npos;
 
             //printf("Device extensions: %s\n", ext.c_str());
-            MandelDevice md{ ClDeviceWrapper{ device, cl::Context{ device } } };
+            auto mandelDevice = std::make_unique<mnd::MandelDevice>(
+                ClDeviceWrapper{ device, cl::Context{ device } });
+            MandelDevice& md = *mandelDevice;
 
             //printf("clock: %d", device.getInfo<CL_DEVICE_MAX_CLOCK_FREQUENCY>());
 
@@ -304,7 +306,7 @@ std::vector<MandelDevice> MandelContext::createDevices(void)
                 //fprintf(stderr, "error creating 128bit cl generator: %s\n", err.c_str());
             }
 
-            mandelDevices.push_back(std::move(md));
+            mandelDevices.push_back(std::move(mandelDevice));
         }
     }
 #endif // WITH_OPENCL
@@ -324,7 +326,7 @@ AdaptiveGenerator& MandelContext::getDefaultGenerator(void)
 }
 
 
-std::vector<MandelDevice>& MandelContext::getDevices(void)
+std::vector<std::unique_ptr<mnd::MandelDevice>>& MandelContext::getDevices(void)
 {
     return devices;
 }