#include "Generators.h" #include using mnd::MandelGenerator; using mnd::AdaptiveGenerator; 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 }, generators{} { } AdaptiveGenerator::AdaptiveGenerator(MandelGenerator* floatGen, MandelGenerator* doubleGen) : AdaptiveGenerator{} { generators.insert({ 0.0000001, floatGen }); generators.insert({ 0.0, doubleGen }); } /* AdaptiveGenerator::AdaptiveGenerator(Generator* floatGen, Generator* doubleGen, Generator* quadGen) { generators.insert({ 0.0000001, floatGen }); generators.insert({ 5.0e-16, doubleGen }); generators.insert({ Real("1.0e-28"), quadGen }); }*/ void AdaptiveGenerator::addGenerator(const mnd::Real& precision, mnd::MandelGenerator& generator) { generators.insert({ precision, &generator }); } void AdaptiveGenerator::addGenerator(mnd::Precision p, MandelGenerator& generator) { generators.insert({ mnd::getPrecision(p), &generator }); } void AdaptiveGenerator::generate(const mnd::MandelInfo& info, float* data) { Real pixelW = info.view.width / info.bWidth; Real pixelH = info.view.height / info.bHeight; Real neededPrecision = pixelW < pixelH ? pixelW : pixelH; //Generator* toUse = nullptr; auto firstSmaller = generators.lower_bound(neededPrecision); if (firstSmaller != generators.end()) { //printf("use generator with precision: %s\n", mnd::toString(firstSmaller->first).c_str()); //printf("gen: %p\n", firstSmaller->second);fflush(stdout); firstSmaller->second->generate(info, data); } else { for (long s = 0; s < info.bWidth * info.bHeight; s++) { data[s] = 0.0; } } return; /* int i = 0; for (auto [thresh, gen] : generators) { ++i; if (neededPrecision > thresh) { toUse = gen; } } if (toUse != nullptr) { toUse->generate(info, data); } else { for (long s = 0; s < info.bWidth * info.bHeight; s++) { data[s] = 0.0; } }*/ } 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::TRIPLE_DOUBLE: return "triple-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"; } return ""; } 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"; } return ""; } Real getPrecision(Precision p) { static const std::map precs { { Precision::FLOAT, getPrecision() }, { Precision::DOUBLE_FLOAT, Real("4.0e-15") }, { Precision::DOUBLE, getPrecision() }, { Precision::DOUBLE_DOUBLE, Real("1.0e-29") }, { Precision::TRIPLE_DOUBLE, Real("1.0e-45") }, { Precision::QUAD_DOUBLE, Real("1.0e-56") }, { Precision::FIXED64, Real("3.5e-15") }, { Precision::FIXED128, Real("1.317e-29") }, { Precision::FIXED512, Real("1.5e-130") }, { Precision::FLOAT128, Real("1.5e-29") }, { Precision::FLOAT256, Real("1.0e-58") }, { Precision::FLOAT512, Real("1.0e-145") }, { Precision::INF_PREC, Real(0.0) }, }; return precs.at(p); } Real getPrecision(GeneratorType t) { switch(t) { case GeneratorType::FLOAT: case GeneratorType::FLOAT_SSE2: case GeneratorType::FLOAT_AVX: case GeneratorType::FLOAT_AVX_FMA: case GeneratorType::FLOAT_AVX512: case GeneratorType::FLOAT_NEON: return getPrecision(); case GeneratorType::DOUBLE_FLOAT: return getPrecision(Precision::DOUBLE_FLOAT); case GeneratorType::DOUBLE: case GeneratorType::DOUBLE_SSE2: case GeneratorType::DOUBLE_AVX: case GeneratorType::DOUBLE_AVX_FMA: case GeneratorType::DOUBLE_AVX512: case GeneratorType::DOUBLE_NEON: return getPrecision(); case GeneratorType::DOUBLE_DOUBLE: case GeneratorType::DOUBLE_DOUBLE_AVX: case GeneratorType::DOUBLE_DOUBLE_AVX_FMA: return getPrecision(); case GeneratorType::TRIPLE_DOUBLE: return getPrecision(); case GeneratorType::QUAD_DOUBLE: return getPrecision(); case GeneratorType::FLOAT128: return getPrecision(); case GeneratorType::FLOAT256: return getPrecision(); case GeneratorType::FIXED64: return getPrecision(); case GeneratorType::FIXED128: return getPrecision(); case GeneratorType::FIXED512: return getPrecision(); case GeneratorType::UNSPECIFIED: default: return Real(0); } } template<> Real getPrecision() { return Real("1.0e-7"); } template<> Real getPrecision() { return Real("1.0e-15"); } template<> Real getPrecision() { return Real("1.0e-29"); } template<> Real getPrecision() { return Real("1.0e-46"); } template<> Real getPrecision() { return Real("3.0e-64"); } template<> Real getPrecision() { return Real("3.5e-15"); } template<> Real getPrecision() { return Real("1.5e-29"); } template<> Real getPrecision() { return Real("1.5e-130"); } template<> Real getPrecision() { return Real("1.5e-29"); } template<> Real getPrecision() { return Real("1.4e-72"); } template<> Real getPrecision() { return Real("1.0e-145"); } }