#include "IterationGenerator.h" #include using mnd::IterationGenerator; using mnd::NaiveGenerator; using mnd::IterationFormula; IterationGenerator::IterationGenerator(IterationFormula itf, const mnd::Real& prec) : mnd::MandelGenerator{ prec }, itf{ std::move(itf) } { } NaiveGenerator::NaiveGenerator(IterationFormula itf, const mnd::Real& prec) : IterationGenerator{ std::move(itf), prec } { this->itf.optimize(); } void NaiveGenerator::generate(const mnd::MandelInfo& info, float* data) { const MandelViewport& view = info.view; const bool parallel = true; using T = double; T viewx = mnd::convert(view.x); T viewy = mnd::convert(view.y); T wpp = mnd::convert(view.width / info.bWidth); T hpp = mnd::convert(view.height / info.bHeight); T juliaX = mnd::convert(info.juliaX); T juliaY = mnd::convert(info.juliaY); if constexpr (parallel) omp_set_num_threads(omp_get_num_procs()); #pragma omp parallel for schedule(static, 1) if (parallel) for (long j = 0; j < info.bHeight; j++) { T y = viewy + T(double(j)) * hpp; long i = 0; for (i; i < info.bWidth; i++) { T x = viewx + T(double(i)) * wpp; T cx = info.julia ? juliaX : x; T cy = info.julia ? juliaY : y; std::complex z{ x, y }; if (!info.julia) { z = 0; } std::complex c{ cx, cy }; int k = 0; for (k = 0; k < info.maxIter; k++) { z = this->iterate(z, c); if (std::abs(z) >= 4) break; } data[i + j * info.bWidth] = float(k); /*if (info.smooth) { if (k >= info.maxIter) data[i + j * info.bWidth] = float(info.maxIter); else { float aapp = mnd::convert(a); float bapp = mnd::convert(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;*/ } } } std::complex NaiveGenerator::iterate(std::complex z, std::complex c) { auto& expr = *itf.expr; return calc(expr, z, c); } std::complex NaiveGenerator::calc(mnd::Expression& expr, std::complex z, std::complex c) { std::complex result = 0; std::visit([this, &result, z, c] (auto&& ex) { using T = std::decay_t; if constexpr (std::is_same::value) { result = std::complex{ ex.re, ex.im }; } else if constexpr (std::is_same::value) { if (ex.name == "z") result = z; else if (ex.name == "c") result = c; else if (ex.name == "i") result = std::complex{ 0.0, 1.0 }; } else if constexpr (std::is_same::value) { result = -calc(*ex.operand, z, c); } else if constexpr (std::is_same::value) { if (ex.subtraction) result = calc(*ex.left, z, c) - calc(*ex.right, z, c); else result = calc(*ex.left, z, c) + calc(*ex.right, z, c); } else if constexpr (std::is_same::value) { result = calc(*ex.left, z, c) * calc(*ex.right, z, c); } else if constexpr (std::is_same::value) { result = calc(*ex.left, z, c) / calc(*ex.right, z, c); } else if constexpr (std::is_same::value) { result = std::pow(calc(*ex.left, z, c), calc(*ex.right, z, c)); } }, expr); return result; }