#include "Generators.h" #include "Types.h" #include using mnd::MandelGenerator; using mnd::AdaptiveGenerator; namespace mnd { template<> Real getPrecision(); template<> Real getPrecision(); template<> Real getPrecision(); template<> Real getPrecision(); template<> Real getPrecision(); template<> Real getPrecision(); template<> Real getPrecision(); template<> Real getPrecision(); template<> Real getPrecision(); template<> Real getPrecision(); template<> Real getPrecision(); template<> Real getPrecision(); template<> Real getPrecision(); template Precision getType(void); template<> Precision getType() { return Precision::FLOAT; } template<> Precision getType() { return Precision::DOUBLE; } template<> Precision getType() { return Precision::DOUBLE_DOUBLE; } template<> Precision getType() { return Precision::TRIPLE_DOUBLE; } template<> Precision getType() { return Precision::QUAD_DOUBLE; } template<> Precision getType() { return Precision::HEX_DOUBLE; } template<> Precision getType() { return Precision::OCTA_DOUBLE; } template<> Precision getType() { return Precision::FIXED64; } template<> Precision getType() { return Precision::FIXED128; } template<> Precision getType() { return Precision::FIXED512; } template<> Precision getType() { return Precision::FLOAT128; } template<> Precision getType() { return Precision::FLOAT256; } template<> Precision getType() { return Precision::FLOAT512; } } mnd::MandelDevice* MandelGenerator::getDevice(void) { return nullptr; } mnd::Real MandelGenerator::getPrecision(void) const { return precision; } mnd::Precision MandelGenerator::getType(void) const { return type; } mnd::HardwareFeature 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::addGenerator(MandelGenerator& generator) { generators.insert({ generator.getPrecision(), &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::TRIPLE_FLOAT: return "triple-float"; case Precision::DOUBLE: return "double"; case Precision::DOUBLE_DOUBLE: return "double-double"; case Precision::TRIPLE_DOUBLE: return "triple-double"; case Precision::QUAD_DOUBLE: return "quad-double"; case Precision::HEX_DOUBLE: return "hex-double"; case Precision::OCTA_DOUBLE: return "octa-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::INF_PREC: return "real"; } return ""; } std::string toString(HardwareFeature ce) { switch (ce) { case HardwareFeature::NONE: return ""; case HardwareFeature::X86_SSE2: return "SSE2"; case HardwareFeature::X86_AVX: return "AVX"; case HardwareFeature::X86_AVX_FMA: return "AVX2+FMA"; case HardwareFeature::X86_AVX_512: return "AVX512"; case HardwareFeature::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::TRIPLE_FLOAT, Real("1.0e-21") }, { Precision::DOUBLE, getPrecision() }, { Precision::DOUBLE_DOUBLE, Real("1.0e-29") }, { Precision::TRIPLE_DOUBLE, Real("1.0e-47") }, { Precision::QUAD_DOUBLE, Real("1.0e-56") }, { Precision::HEX_DOUBLE, Real("1.0e-94") }, { Precision::OCTA_DOUBLE, Real("1.0e-126") }, { 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); } 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-47"); } template<> Real getPrecision() { return Real("3.0e-64"); } template<> Real getPrecision() { return Real("3.0e-94"); } template<> Real getPrecision() { return Real("1.0e-126"); } 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"); } }