Nicolas Winkler před 5 roky
rodič
revize
d6d452a1d6

+ 4 - 0
MandelWidget.cpp

@@ -787,6 +787,10 @@ void MandelWidget::drawInfo(void)
         dis << factor << "e" << int(::floor(log10));
     }
 
+    if (maxWidth > 400) {
+        dis << "; per pixel: " << distPerPixel;
+    }
+
     float lineY = this->height() - DIST_FROM_BORDER;
     float lineXEnd = DIST_FROM_BORDER + pixels;
 

+ 9 - 0
choosegenerators.cpp

@@ -17,6 +17,12 @@ mnd::MandelViewport Benchmarker::benchViewport(void)
 
 
 const std::vector<mnd::MandelInfo> Benchmarker::benches {
+    mnd::MandelInfo{ benchViewport(), 25, 25, 15, false },
+    mnd::MandelInfo{ benchViewport(), 25, 25, 25, false },
+    mnd::MandelInfo{ benchViewport(), 25, 25, 75, false },
+    mnd::MandelInfo{ benchViewport(), 25, 25, 125, false },
+    mnd::MandelInfo{ benchViewport(), 25, 25, 250, false },
+    mnd::MandelInfo{ benchViewport(), 50, 25, 250, false },
     mnd::MandelInfo{ benchViewport(), 50, 50, 250, false },
     mnd::MandelInfo{ benchViewport(), 50, 50, 500, false },
     mnd::MandelInfo{ benchViewport(), 50, 100, 500, false },
@@ -90,6 +96,9 @@ double Benchmarker::benchmarkResult(mnd::Generator& mg) const
             fflush(stdout);
             break;
         }
+        else if (time < std::chrono::milliseconds(10)) {
+            i += 3;
+        }
     }
 
 

+ 1 - 6
libmandel/CMakeLists.txt

@@ -34,6 +34,7 @@ SET(MandelSources
     src/Hardware.cpp
     src/MandelUtil.cpp
     src/Types.cpp
+    src/OpenClCode.cpp
 )
 FILE(GLOB MandelHeaders include/*.h)
 
@@ -65,12 +66,6 @@ if (LTO_SUPPORTED AND WITH_LTO)
     set_property(TARGET qd PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
 endif()
 
-
-if(MPFR_INCLUDES AND MPFR_LIBRARIES)
-    set(MPFR_FOUND TRUE)
-    #target_compile_definitions(mandel PUBLIC WITH_MPFR)
-endif()
-
 if(OPENCL_FOUND)
     target_compile_definitions(mandel PUBLIC WITH_OPENCL)
     target_include_directories(mandel PUBLIC

+ 1 - 1
libmandel/include/ClGenerators.h

@@ -32,7 +32,7 @@ protected:
     cl::Program program;
     cl::CommandQueue queue;
 public:
-    ClGenerator(cl::Device device);
+    ClGenerator(cl::Device device, const mnd::Real& precision);
     virtual ~ClGenerator(void);
 
     virtual void generate(const MandelInfo& info, float* data);

+ 41 - 111
libmandel/include/CpuGenerators.h

@@ -16,27 +16,6 @@ namespace mnd
 
     template<typename T, mnd::CpuExtension ex = mnd::NONE, bool parallel = true>
     class CpuGenerator;
-
-
-    /*
-    class CpuGeneratorFloat;
-    class CpuGeneratorDouble;
-    class CpuGenerator128;
-
-#if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) 
-    class CpuGeneratorSse2Float;
-    class CpuGeneratorSse2Double;
-
-    class CpuGeneratorAvxFloat;
-    class CpuGeneratorAvxDouble;
-
-    class CpuGeneratorAvx512Float;
-    class CpuGeneratorAvx512Double;
-#elif defined(__arm__) || defined(__aarch64__) || defined(_M_ARM)
-    class CpuGeneratorNeonFloat;
-    class CpuGeneratorNeonDouble;
-#endif
-*/
 }
 
 
@@ -44,6 +23,10 @@ template<typename T, mnd::CpuExtension ex, bool parallel>
 class mnd::CpuGenerator : public Generator
 {
 public:
+    inline CpuGenerator(void) :
+        Generator{ mnd::getPrecision<T>() }
+    {
+    }
     virtual void generate(const MandelInfo& info, float* data);
 };
 
@@ -52,15 +35,22 @@ template<typename T, bool parallel>
 class mnd::CpuGenerator<T, mnd::NONE, parallel> : public Generator
 {
 public:
+    inline CpuGenerator(void) :
+        Generator{ mnd::getPrecision<T>() }
+    {
+    }
     virtual void generate(const MandelInfo& info, float* data);
 };
 
-
 #if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) 
 template<bool parallel>
 class mnd::CpuGenerator<float, mnd::X86_SSE2, parallel> : public Generator
 {
 public:
+    inline CpuGenerator(void) :
+        Generator{ mnd::getPrecision<T>() }
+    {
+    }
     virtual void generate(const MandelInfo& info, float* data);
 };
 
@@ -68,6 +58,10 @@ template<bool parallel>
 class mnd::CpuGenerator<double, mnd::X86_SSE2, parallel> : public Generator
 {
 public:
+    inline CpuGenerator(void) :
+        Generator{ mnd::getPrecision<T>() }
+    {
+    }
     virtual void generate(const MandelInfo& info, float* data);
 };
 
@@ -76,6 +70,10 @@ template<bool parallel>
 class mnd::CpuGenerator<float, mnd::X86_AVX, parallel> : public Generator
 {
 public:
+    inline CpuGenerator(void) :
+        Generator{ mnd::getPrecision<T>() }
+    {
+    }
     virtual void generate(const MandelInfo& info, float* data);
 };
 
@@ -83,6 +81,10 @@ template<bool parallel>
 class mnd::CpuGenerator<double, mnd::X86_AVX, parallel> : public Generator
 {
 public:
+    inline CpuGenerator(void) :
+        Generator{ mnd::getPrecision<T>() }
+    {
+    }
     virtual void generate(const MandelInfo& info, float* data);
 };
 
@@ -90,6 +92,10 @@ template<bool parallel>
 class mnd::CpuGenerator<mnd::DoubleDouble, mnd::X86_AVX, parallel> : public Generator
 {
 public:
+    inline CpuGenerator(void) :
+        Generator{ mnd::getPrecision<T>() }
+    {
+    }
     virtual void generate(const MandelInfo& info, float* data);
 };
 
@@ -98,6 +104,11 @@ template<bool parallel>
 class mnd::CpuGenerator<float, mnd::ARM_NEON, parallel> : public Generator
 {
 public:
+    CpuGenerator(void);
+    inline CpuGenerator(void) :
+        Generator{ mnd::getPrecision<float>() }
+    {
+    }
     virtual void generate(const MandelInfo& info, float* data);
 };
 
@@ -105,6 +116,10 @@ template<bool parallel>
 class mnd::CpuGenerator<double, mnd::ARM_NEON, parallel> : public Generator
 {
 public:
+    inline CpuGenerator(void) :
+        Generator{ mnd::getPrecision<double>() }
+    {
+    }
     virtual void generate(const MandelInfo& info, float* data);
 };
 #endif
@@ -113,97 +128,12 @@ template<bool parallel>
 class mnd::CpuGenerator<mnd::DoubleDouble, mnd::X86_AVX_FMA, parallel> : public Generator
 {
 public:
+    inline CpuGenerator(void) :
+        Generator{ mnd::getPrecision<DoubleDouble>() }
+    {
+    }
     virtual void generate(const MandelInfo& info, float* data);
 };
 
-template<bool parallel>
-class mnd::CpuGenerator<Fixed128, mnd::NONE, parallel> : public Generator
-{
-public:
-    virtual void generate(const MandelInfo& info, float* data);
-};
-
-/*
-class mnd::CpuGeneratorFloat : public Generator
-{
-public:
-    virtual void generate(const MandelInfo& info, float* data);
-};
-
-
-class mnd::CpuGeneratorDouble : public Generator
-{
-public:
-    virtual void generate(const MandelInfo& info, float* data);
-};
-
-
-class mnd::CpuGenerator128 : public Generator
-{
-public:
-    virtual void generate(const MandelInfo& info, float* data);
-};
-
-
-
-#if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) 
-class mnd::CpuGeneratorSse2Float : public Generator
-{
-public:
-    virtual void generate(const MandelInfo& info, float* data);
-};
-
-
-class mnd::CpuGeneratorSse2Double : public Generator
-{
-public:
-    virtual void generate(const MandelInfo& info, float* data);
-};
-
-
-class mnd::CpuGeneratorAvxFloat : public Generator
-{
-public:
-    virtual void generate(const MandelInfo& info, float* data);
-};
-
-
-class mnd::CpuGeneratorAvxDouble : public Generator
-{
-public:
-    virtual void generate(const MandelInfo& info, float* data);
-};
-
-
-class mnd::CpuGeneratorAvx512Float : public Generator
-{
-public:
-    virtual void generate(const MandelInfo& info, float* data);
-};
-
-
-class mnd::CpuGeneratorAvx512Double : public Generator
-{
-public:
-    virtual void generate(const MandelInfo& info, float* data);
-};
-
-#elif defined(__arm__) || defined(__aarch64__) || defined(_M_ARM)
-
-class mnd::CpuGeneratorNeonFloat : public Generator
-{
-public:
-    virtual void generate(const MandelInfo& info, float* data);
-};
-
-
-class mnd::CpuGeneratorNeonDouble : public Generator
-{
-public:
-    virtual void generate(const MandelInfo& info, float* data);
-};
-#endif
-
-*/
 
 #endif // MANDEL_CPUGENERATORS_H

+ 77 - 148
libmandel/include/Fixed.h

@@ -1,6 +1,12 @@
 #ifndef MANDEL_FIXED128_H
 #define MANDEL_FIXED128_H
 
+#ifdef _MSC_VER
+#   include <intrin.h>
+#endif
+
+
+
 #include <cinttypes>
 #include <cmath>
 #include <utility>
@@ -11,6 +17,61 @@
 #include <boost/multiprecision/cpp_bin_float.hpp>
 
 
+namespace mnd
+{
+#ifdef _MSC_VER
+    static inline std::pair<int64_t, uint64_t> mul64(int64_t a, int64_t b) {
+        int64_t higher;
+        int64_t lower = _mul128(a, b, &higher);
+        return { higher, lower };
+    }
+
+    static inline std::pair<uint64_t, uint64_t> mulu64(uint64_t a, uint64_t b) {
+        uint64_t higher;
+        uint64_t lower = _umul128(a, b, &higher);
+        return { higher, lower };
+    }
+#else
+    static inline std::pair<int64_t, uint64_t> mul64(int64_t a, int64_t b) {
+        uint32_t aa[2] = { uint32_t(a >> 32), uint32_t(a & 0xFFFFFFFF) };
+        uint32_t bb[2] = { uint32_t(b >> 32), uint32_t(b & 0xFFFFFFFF) };
+
+        uint32_t res[4];
+        int64_t temp = uint64_t(aa[1]) * uint64_t(bb[1]);
+        res[3] = temp & 0xFFFFFFFF;
+        temp >>= 32;
+        temp += int64_t(int32_t(aa[0])) * int64_t(bb[1]) + int64_t(aa[1]) * int64_t(int32_t(bb[0]));
+        res[2] = temp & 0xFFFFFFFF;
+        temp >>= 32;
+        temp += int64_t(int32_t(aa[0])) * int64_t(int32_t(bb[0]));
+        res[1] = temp & 0xFFFFFFFF;
+        res[0] = temp >> 32;
+
+        return std::make_pair((int64_t(res[0]) << 32) | res[1], uint64_t((int64_t(res[2]) << 32) | res[3]));
+    }
+
+    static inline std::pair<uint64_t, uint64_t> mulu64(uint64_t a, uint64_t b) {
+        uint32_t aa[2] = { uint32_t(a >> 32), uint32_t(a & 0xFFFFFFFF) };
+        uint32_t bb[2] = { uint32_t(b >> 32), uint32_t(b & 0xFFFFFFFF) };
+
+        uint32_t res[4];
+        uint64_t temp = uint64_t(aa[1]) * bb[1];
+        res[3] = temp & 0xFFFFFFFF;
+        uint32_t carry = temp >> 32;
+        temp = uint64_t(aa[0]) * bb[1] + uint64_t(aa[1]) * bb[0] + carry;
+        res[2] = temp & 0xFFFFFFFF;
+        carry = temp >> 32;
+        temp = uint64_t(aa[0]) * bb[0] + carry;
+        res[1] = temp & 0xFFFFFFFF;
+        res[0] = temp >> 32;
+
+        return std::make_pair((uint64_t(res[0]) << 32) | res[1], (uint64_t(res[2]) << 32) | res[3] );
+    }
+#endif
+}
+
+
+
 struct Fixed512
 {
     using Once = boost::multiprecision::int512_t;
@@ -115,11 +176,6 @@ struct Fixed128
         upper = uint64_t(int64_t(x * twoToThe32));
         double remainder = x - double(upper) / twoToThe32;
         lower = uint64_t(int64_t(remainder * twoToThe32 * twoToThe32 * twoToThe32));
-        /*int integerPart = ::floor(x);
-        double fractionalPart = x - integerPart;
-        upper = int64_t(integerPart) << 32;
-        upper |= uint64_t(fractionalPart * (1ULL << 32)) & 0xFFFFFFFFULL;
-        lower = 0;// uint64_t(fractionalPart * (1ULL << 32) * (1ULL << 63) * 2);*/
     }
 
     inline Fixed128 operator + (const Fixed128& other) const {
@@ -145,6 +201,7 @@ struct Fixed128
         return this->operator~() + Fixed128{ 0, 0, 0, 1 };
     }
 
+    /*
 //private:
     static inline std::pair<uint64_t, uint64_t> mul64(int64_t a, int64_t b) {
         int32_t aa[2] = { int32_t(a >> 32), int32_t(a & 0xFFFFFFFF) };
@@ -181,6 +238,7 @@ struct Fixed128
 
         return std::make_pair((uint64_t(res[0]) << 32) | res[1], (uint64_t(res[2]) << 32) | res[3] );
     }
+    */
 
 public:
     inline Fixed128 operator * (const Fixed128& other) const {
@@ -190,10 +248,10 @@ public:
         if (other.isNegative()) {
             return -((-other) * (*this));
         }
-        auto [uuc, uu] = mulu64(upper, other.upper);
-        auto [ulc, ul] = mulu64(upper, other.lower);
-        auto [luc, lu] = mulu64(lower, other.upper);
-        auto [llc, ll] = mulu64(lower, other.lower);
+        auto [uuc, uu] = mnd::mulu64(upper, other.upper);
+        auto [ulc, ul] = mnd::mulu64(upper, other.lower);
+        auto [luc, lu] = mnd::mulu64(lower, other.upper);
+        auto [llc, ll] = mnd::mulu64(lower, other.lower);
 
         uint64_t res[4] = { 0, 0, 0, 0 };
         res[3] = ll;
@@ -215,7 +273,6 @@ public:
             res[0]++;
         res[0] += uuc;
 
-
         return Fixed128{ uint32_t(res[0] & 0xFFFFFFFF), uint32_t(int64_t(res[1]) >> 32), uint32_t(res[1] & 0xFFFFFFFF), uint32_t(int64_t(res[2]) >> 32) };
 
         /*if (isNegative()) {
@@ -267,95 +324,6 @@ public:
         return std::make_pair(Fixed128{ newQ[0], newQ[1], newQ[2], newQ[3] }, carry);
     }
 
-    /*
-    inline void arshift(int fac32) {
-        uint32_t temp = 0;
-        switch (fac32) {
-        case 0:
-            return;
-        case 1:
-            temp = upper & 0xFFFFFFFF;
-            upper = uint64_t(int64_t(upper) >> 32);
-            lower >>= 32;
-            lower |= uint64_t(temp) << 32;
-        case 2:
-            lower = upper;
-            upper = uint64_t(int64_t(upper) >> 63);
-        case 3:
-            lower = uint64_t(int64_t(upper) >> 32);
-            upper = uint64_t(int64_t(upper) >> 63);
-        default:
-            lower = uint64_t(int64_t(upper) >> 63);
-            upper = uint64_t(int64_t(upper) >> 63);
-        }
-    }*/
-    /*
-    inline Fixed128 operator * (const Fixed128& other) const {
-        int32_t quarters[4] = {
-            (upper >> 32) & 0xFFFFFFFF,
-            upper & 0xFFFFFFFF,
-            (lower >> 32) & 0xFFFFFFFF,
-            lower & 0xFFFFFFFF
-        };
-
-        int32_t otherQuarters[4] = {
-            (other.upper >> 32) & 0xFFFFFFFF,
-            other.upper & 0xFFFFFFFF,
-            (other.lower >> 32) & 0xFFFFFFFF,
-            other.lower & 0xFFFFFFFF
-        };
-
-        int64_t prods[4][4];
-        for (int i = 0; i < 4; i++) {
-            for (int j = 0; j < 4 && j + i < 5; j++) {
-                if (i == 0 || j == 0)
-                    prods[i][j] = int64_t(quarters[i]) * int64_t(otherQuarters[j]);
-                else
-                    prods[i][j] = uint64_t(uint32_t(quarters[i])) * uint64_t(uint32_t(otherQuarters[j]));
-            }
-        }
-
-        Fixed128 ret = { 0, 0 };
-        for (int i = 0; i < 4; i++) {
-            for (int j = 0; j < 4 && j + i < 5; j++) {
-                if (i == 0 || j == 0)
-                    ret.addSigned(prods[i][j], i + j);
-                else
-                    ret.add(prods[i][j], i + j);
-            }
-        }
-        return ret;
-        
-        /*
-        int64_t x00 = int64_t(quarters[0]) * int64_t(otherQuarters[0]);
-        int64_t x01 = int64_t(quarters[0]) * int64_t(otherQuarters[1]);
-        int64_t x02 = int64_t(quarters[0]) * int64_t(otherQuarters[2]);
-        int64_t x03 = int64_t(quarters[0]) * int64_t(otherQuarters[3]);
-        int64_t x10 = int64_t(quarters[1]) * int64_t(otherQuarters[0]);
-        int64_t x11 = int64_t(quarters[1]) * int64_t(otherQuarters[1]);
-        int64_t x12 = int64_t(quarters[1]) * int64_t(otherQuarters[2]);
-        int64_t x13 = int64_t(quarters[1]) * int64_t(otherQuarters[3]);
-        int64_t x20 = int64_t(quarters[2]) * int64_t(otherQuarters[0]);
-        int64_t x21 = int64_t(quarters[2]) * int64_t(otherQuarters[1]);
-        int64_t x22 = int64_t(quarters[2]) * int64_t(otherQuarters[2]);
-        int64_t x30 = int64_t(quarters[3]) * int64_t(otherQuarters[0]);
-        int64_t x31 = int64_t(quarters[3]) * int64_t(otherQuarters[1]);
-
-        Fixed128 ret = { 0, 0 };
-        /*uint32_t newQuarters[4] = {
-            x00,
-            x01 + x10,
-            x02 + x11 + x20,
-            x03 + x12 + x21 + x30,
-        };*//*
-        ret.add(x00, 0);
-        ret.add(x01 + x10, 1);
-        ret.add(x02 + x11 + x20, 2);
-        ret.add(x03 + x12 + x21 + x30, 3);
-        ret.add(x13 + x22 + x31, 4);
-
-        return ret;*/
-    /*}*/
 
 private:
     inline void add(uint64_t val, int b32offset) {
@@ -532,6 +500,7 @@ public:
     }
 };
 
+
 struct Fixed64
 {
     int64_t bits;
@@ -540,26 +509,21 @@ struct Fixed64
     ~Fixed64() = default;
 
 
-    inline Fixed64(int64_t bits, bool /* dummy */) :
+    explicit inline Fixed64(int64_t bits, bool /* dummy */) :
         bits{ bits }
     {
     }
 
     inline Fixed64(double x)
     {
-        /*int integerPart = int(x);
-        double fractionalPart = x - integerPart;
-        bits = uint64_t(integerPart) << 32;
-        bits |= uint64_t(fractionalPart * (1ULL << 32)) & 0xFFFFFFFF;
-        */
-        bits = x * (1LL << 32);
+        bits = x * (1LL << 48);
     }
 
     inline operator float(void) const {
-        return bits * (1.0f / (1ULL << 32));
+        return bits * (1.0f / (1ULL << 48));
     }
     inline operator double(void) const {
-        return bits * (1.0 / (1ULL << 32));
+        return bits * (1.0 / (1ULL << 48));
     }
 
     inline Fixed64 operator + (const Fixed64& other) const {
@@ -574,47 +538,12 @@ struct Fixed64
     inline Fixed64 operator - (const Fixed64& other) const {
         return Fixed64{ bits - other.bits, true };
     }
+
     inline Fixed64& operator -= (const Fixed64& other) {
         bits -= other.bits;
         return *this;
     }
 
-    static inline std::pair<int64_t, uint64_t> mul64(int64_t a, int64_t b) {
-        uint32_t aa[2] = { uint32_t(a >> 32), uint32_t(a & 0xFFFFFFFF) };
-        uint32_t bb[2] = { uint32_t(b >> 32), uint32_t(b & 0xFFFFFFFF) };
-
-        uint32_t res[4];
-        int64_t temp = uint64_t(aa[1]) * uint64_t(bb[1]);
-        res[3] = temp & 0xFFFFFFFF;
-        temp >>= 32;
-        temp += int64_t(int32_t(aa[0])) * int64_t(bb[1]) + int64_t(aa[1]) * int64_t(int32_t(bb[0]));
-        res[2] = temp & 0xFFFFFFFF;
-        temp >>= 32;
-        temp += int64_t(int32_t(aa[0])) * int64_t(int32_t(bb[0]));
-        res[1] = temp & 0xFFFFFFFF;
-        res[0] = temp >> 32;
-
-        return std::make_pair((int64_t(res[0]) << 32) | res[1], uint64_t((int64_t(res[2]) << 32) | res[3]));
-    }
-
-    static inline std::pair<uint64_t, uint64_t> mulu64(uint64_t a, uint64_t b) {
-        uint32_t aa[2] = { uint32_t(a >> 32), uint32_t(a & 0xFFFFFFFF) };
-        uint32_t bb[2] = { uint32_t(b >> 32), uint32_t(b & 0xFFFFFFFF) };
-
-        uint32_t res[4];
-        uint64_t temp = uint64_t(aa[1]) * bb[1];
-        res[3] = temp & 0xFFFFFFFF;
-        uint32_t carry = temp >> 32;
-        temp = uint64_t(aa[0]) * bb[1] + uint64_t(aa[1]) * bb[0] + carry;
-        res[2] = temp & 0xFFFFFFFF;
-        carry = temp >> 32;
-        temp = uint64_t(aa[0]) * bb[0] + carry;
-        res[1] = temp & 0xFFFFFFFF;
-        res[0] = temp >> 32;
-
-        return std::make_pair((uint64_t(res[0]) << 32) | res[1], (uint64_t(res[2]) << 32) | res[3] );
-    }
-
     inline Fixed64 operator * (const Fixed64& other) {
         /*int32_t upper = bits >> 32;
         uint32_t lower = uint32_t(bits & 0xFFFFFFFF);
@@ -628,10 +557,10 @@ struct Fixed64
         double od = int32_t(other.bits >> 32) + double(uint32_t(other.bits)) / (1ULL << 32);
         return d * od;*/
 
-        /*auto[hi, lo] = mul64(bits, other.bits);
-        return Fixed64{ int64_t((hi << 32) | (lo >> 32)), true };*/
+        auto[hi, lo] = mnd::mul64(bits, other.bits);
+        return Fixed64{ int64_t((hi << 16) | (lo >> 48)), true };
 
-        uint32_t a[2] = { uint32_t(uint64_t(bits) >> 32), uint32_t(bits & 0xFFFFFFFF) };
+        /*uint32_t a[2] = { uint32_t(uint64_t(bits) >> 32), uint32_t(bits & 0xFFFFFFFF) };
         uint32_t b[2] = { uint32_t(uint64_t(other.bits) >> 32), uint32_t(other.bits & 0xFFFFFFFF) };
 
         uint64_t a1b1 = uint64_t(a[1]) * b[1];
@@ -642,7 +571,7 @@ struct Fixed64
         int64_t res = a1b1 >> 32;
         res += a0b1 + a1b0;
         res += a0b0 << 32;
-        return Fixed64{ res, true };
+        return Fixed64{ res, true };*/
 
         /*
         uint32_t aa[2] = { uint32_t(uint64_t(bits) >> 32), uint32_t(bits & 0xFFFFFFFF) };

+ 22 - 3
libmandel/include/Generators.h

@@ -18,22 +18,40 @@ namespace mnd
     enum class Precision : int
     {
         FLOAT,
+        DOUBLE_FLOAT,
         DOUBLE,
         DOUBLE_DOUBLE,
         FLOAT128,
+        FIXED64,
+        FIXED128,
         QUAD_DOUBLE,
         FLOAT256,
         INF_PREC,
     };
 
     Real getPrecision(Precision p);
+    
+    template<typename T>
+    Real getPrecision(void);
+
+    template<> Real getPrecision<float>();
+    template<> Real getPrecision<double>();
+    template<> Real getPrecision<DoubleDouble>();
+    template<> Real getPrecision<QuadDouble>();
+    template<> Real getPrecision<Fixed128>();
 }
 
 
 class mnd::Generator
 {
+protected:
+    Real precision;
 public:
-    Generator(void) = default;
+    inline Generator(const Real& precision) :
+        precision{ precision }
+    {
+    }
+
     virtual ~Generator(void);
 
 
@@ -44,6 +62,7 @@ public:
     Generator& operator=(Generator&&) = default;
 
     virtual void generate(const MandelInfo& info, float* data) = 0;
+    virtual Real getPrecision(void) const;
 };
 
 
@@ -51,7 +70,7 @@ class mnd::AdaptiveGenerator : public Generator
 {
     std::map<Real, Generator*, std::greater<Real>> generators;
 public:
-    AdaptiveGenerator(void) = default;
+    AdaptiveGenerator(void);
     AdaptiveGenerator(Generator* floatGen, Generator* doubleGen);
     virtual ~AdaptiveGenerator(void) = default;
 
@@ -61,7 +80,7 @@ public:
     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);
+    virtual void generate(const MandelInfo& info, float* data) override;
 };
 
 

+ 1 - 0
libmandel/include/Mandel.h

@@ -46,6 +46,7 @@ enum class mnd::GeneratorType
     FLOAT128,
     FLOAT256,
     FIXED64,
+    FIXED128,
     FIXED512
 };
 

+ 11 - 2
libmandel/include/Types.h

@@ -139,9 +139,18 @@ namespace mnd
     }
 
     template<>
-    inline Fixed64 convert<Fixed64, Float512>(const Float512& x)
+    inline Fixed64 convert<Fixed64, Real>(const Real& x)
     {
-        return Fixed64(double(Real(x)));
+        return Fixed64(double(x));
+    }
+
+    template<>
+    inline Fixed128 convert<Fixed128, Real>(const Real& x)
+    {
+        mnd::Integer i = mnd::Integer(x * mnd::pow(Real(1LL << 32), 3));
+        uint64_t lo = uint64_t(i & 0xFFFFFFFFFFFFFFFFULL);
+        uint64_t hi = uint64_t((i >> 64) & 0xFFFFFFFFFFFFFFFFULL);
+        return Fixed128(hi, lo);
     }
 #endif
 

+ 10 - 11
libmandel/src/ClGenerators.cpp

@@ -1,8 +1,7 @@
 #include "ClGenerators.h"
 #include "doubledouble.h"
 #include "doublefloat.h"
-#include "opencl/fixed512.h"
-#include "opencl/fixed64.h"
+#include "OpenClCode.h"
 
 #ifdef WITH_OPENCL
 
@@ -62,7 +61,8 @@ Device getDevice(Platform& platform, int i, bool display = false) {
 }
 
 
-ClGenerator::ClGenerator(cl::Device device) :
+ClGenerator::ClGenerator(cl::Device device, const mnd::Real& precision) :
+    Generator{ precision },
     device{ device }
 {
     /*Platform p = getPlatform();
@@ -120,7 +120,7 @@ void ClGenerator::generate(const mnd::MandelInfo& info, float* data)
 
 
 ClGeneratorFloat::ClGeneratorFloat(cl::Device device) :
-    ClGenerator{ device }
+    ClGenerator{ device, mnd::getPrecision(mnd::Precision::FLOAT) }
 {
     context = Context{ device };
     Program::Sources sources;
@@ -174,7 +174,7 @@ std::string ClGeneratorFloat::getKernelCode(bool smooth) const
 
 
 ClGeneratorDoubleFloat::ClGeneratorDoubleFloat(cl::Device device) :
-    ClGenerator{ device }
+    ClGenerator{ device, mnd::getPrecision(mnd::Precision::DOUBLE_FLOAT)  }
 {
     context = Context{ device };
     Program::Sources sources;
@@ -344,7 +344,7 @@ std::string ClGeneratorDoubleFloat::getKernelCode(bool smooth) const
 
 
 ClGeneratorDouble::ClGeneratorDouble(cl::Device device) :
-    ClGenerator{ device }
+    ClGenerator{ device, mnd::getPrecision(mnd::Precision::DOUBLE) }
 {
     context = Context{ device };
     Program::Sources sources;
@@ -422,7 +422,7 @@ std::string ClGeneratorDouble::getKernelCode(bool smooth) const
 
 
 ClGeneratorDoubleDouble::ClGeneratorDoubleDouble(cl::Device device) :
-    ClGenerator{ device }
+    ClGenerator{ device, mnd::getPrecision(mnd::Precision::DOUBLE_DOUBLE) }
 {
     context = Context{ device };
     Program::Sources sources;
@@ -478,7 +478,7 @@ std::string ClGeneratorDoubleDouble::getKernelCode(bool smooth) const
 
 
 ClGeneratorQuadDouble::ClGeneratorQuadDouble(cl::Device device) :
-    ClGenerator{ device }
+    ClGenerator{ device, mnd::getPrecision(mnd::Precision::QUAD_DOUBLE) }
 {
     context = Context{ device };
     Program::Sources sources;
@@ -535,7 +535,7 @@ std::string ClGeneratorQuadDouble::getKernelCode(bool smooth) const
 
 
 ClGenerator128::ClGenerator128(cl::Device device) :
-    ClGenerator{ device }
+    ClGenerator{ device, mnd::getPrecision(mnd::Precision::FIXED128) }
 {
     context = Context{ device };
     Program::Sources sources;
@@ -603,7 +603,7 @@ std::string ClGenerator128::getKernelCode(bool smooth) const
 
 
 ClGenerator64::ClGenerator64(cl::Device device) :
-    ClGenerator{ device }
+    ClGenerator{ device, mnd::getPrecision(mnd::Precision::FIXED64) }
 {
     context = Context{ device };
     Program::Sources sources;
@@ -637,7 +637,6 @@ void ClGenerator64::generate(const mnd::MandelInfo& info, float* data)
     ull h = ull(::round(double(pixelScaleY) * (1LL << 48)));
     //x = 0;
     //y = 0;
-
     
     Kernel iterate = Kernel(program, "iterate");
     iterate.setArg(0, buffer_A);

+ 10 - 4
libmandel/src/CpuGenerators.cpp

@@ -22,12 +22,15 @@ namespace mnd
 
     template class CpuGenerator<Fixed64, mnd::NONE, false>;
     template class CpuGenerator<Fixed64, mnd::NONE, true>;
-    
+
+    template class CpuGenerator<Fixed128, mnd::NONE, false>;
+    template class CpuGenerator<Fixed128, mnd::NONE, true>;
+
     //template class CpuGenerator<Fixed128, mnd::NONE, false>;
     //template class CpuGenerator<Fixed128, mnd::NONE, false, true>;
     //template class CpuGenerator<Fixed128, mnd::NONE, true>;
     //template class CpuGenerator<Fixed128, mnd::NONE, true, true>;
-    
+
 
 #ifdef WITH_BOOST
 #include <boost/multiprecision/cpp_bin_float.hpp>
@@ -87,8 +90,11 @@ void CpuGenerator<T, mnd::NONE, parallel>::generate(const mnd::MandelInfo& info,
             if (info.smooth) {
                 if (k >= 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);
+                else {
+                    float aapp = mnd::convert<float>(a);
+                    float bapp = mnd::convert<float>(b);
+                    data[i + j * info.bWidth] = ((float) k) + 1 - ::logf(::logf(aapp * aapp + bapp * bapp) / 2) / ::logf(2.0f);
+                }
             }
             else
                 data[i + j * info.bWidth] = k;

+ 44 - 4
libmandel/src/Generators.cpp

@@ -10,7 +10,20 @@ Generator::~Generator(void)
 }
 
 
-AdaptiveGenerator::AdaptiveGenerator(Generator* floatGen, Generator* doubleGen)
+mnd::Real Generator::getPrecision(void) const
+{
+    return precision;
+}
+
+
+AdaptiveGenerator::AdaptiveGenerator(void) :
+    Generator{ 0.0 }
+{
+}
+
+
+AdaptiveGenerator::AdaptiveGenerator(Generator* floatGen, Generator* doubleGen) :
+    AdaptiveGenerator{}
 {
     generators.insert({ 0.0000001, floatGen });
     generators.insert({ 0.0, doubleGen });
@@ -33,7 +46,7 @@ void AdaptiveGenerator::addGenerator(const mnd::Real& precision, mnd::Generator&
 
 void AdaptiveGenerator::addGenerator(mnd::Precision p, Generator& generator)
 {
-    generators.insert({ getPrecision(p), &generator });
+    generators.insert({ mnd::getPrecision(p), &generator });
 }
 
 
@@ -76,21 +89,48 @@ void AdaptiveGenerator::generate(const mnd::MandelInfo& info, float* data)
     }*/
 }
 
+
 namespace mnd
 {
     Real getPrecision(Precision p)
     {
         static const std::map<Precision, Real> precs {
-            { Precision::FLOAT, Real("1.0e-7") },
-            { Precision::DOUBLE, Real("1.0e-15") },
+            { Precision::FLOAT, getPrecision<float>() },
+            { Precision::DOUBLE, getPrecision<double>() },
             { Precision::DOUBLE_DOUBLE, Real("1.0e-29") },
             { Precision::QUAD_DOUBLE, Real("1.0e-56") },
+            { Precision::FIXED128, Real("1.317e-29") },
             { Precision::FLOAT256, Real("1.0e-58") },
             { Precision::INF_PREC, Real(0.0) },
         };
 
         return precs.at(p);
     }
+
+
+    template<>
+    Real getPrecision<float>() {
+        return Real("1.0e-7");
+    }
+    template<>
+    Real getPrecision<double>() {
+        return Real("1.0e-15");
+    }
+    template<>
+    Real getPrecision<DoubleDouble>() {
+        return Real("1.0e-29");
+    }
+    template<>
+    Real getPrecision<QuadDouble>() {
+        return Real("1.0e-56");
+    }
+    template<>
+    Real getPrecision<Fixed128>() {
+        return Real("1.5e-29");
+    }
+
+
+
 }
 
 

+ 6 - 0
libmandel/src/Mandel.cpp

@@ -42,6 +42,7 @@ static const std::map<mnd::GeneratorType, std::string> typeNames =
     { mnd::GeneratorType::FLOAT128, "float128" },
     { mnd::GeneratorType::FLOAT256, "float256" },
     { mnd::GeneratorType::FIXED64, "fixed64" },
+    { mnd::GeneratorType::FIXED128, "fixed128" },
     { mnd::GeneratorType::FIXED512, "fixed512" },
 };
 
@@ -133,6 +134,11 @@ MandelContext::MandelContext(void)
         auto db = std::make_unique<CpuGenerator<double, mnd::NONE, true>>();
         cpuGenerators.insert({ GeneratorType::FLOAT, std::move(fl) });
         cpuGenerators.insert({ GeneratorType::DOUBLE, std::move(db) });
+
+        auto fx64 = std::make_unique<CpuGenerator<Fixed64, mnd::NONE, true>>();
+        auto fx128 = std::make_unique<CpuGenerator<Fixed128, mnd::NONE, true>>();
+        cpuGenerators.insert({ GeneratorType::FIXED64, std::move(fx64) });
+        cpuGenerators.insert({ GeneratorType::FIXED128, std::move(fx128) });
     }
 
 #ifdef WITH_BOOST