I have code that I would like to optimize, if possible, while reducing the maximum number of iterations. I heard that there is a way to detect cyclic, but I tried to implement it in different ways, and either it became slower or it made garbage. Display functions are not displayed, as this does not cause a slowdown.
#pragma once
#include <SFML/Graphics/Rect.hpp>
#include <SFML/System/Vector2.hpp>
#include <cstdint>
#include <complex>
#include <functional>
#include <vector>
using namespace std;
template<class T>
class Fractal
{
public:
Fractal(void);
~Fractal(void);
vector<uint32_t> evaluate(const sf::Rect<T>& area, const sf::Vector2u& subdivisions);
typedef function<void(complex<T>&)> iterative_function;
void setIterativeFunction(iterative_function func);
typedef function<bool(complex<T>&)> domain_function;
void setDomainFunction(domain_function func);
void setMaxIterations(const uint32_t iterations);
uint32_t getMaxIterations() const;
class CoordinatesGenerator
{
public:
CoordinatesGenerator(const sf::Rect<T>& area, const sf::Vector2u& subdivisions);
~CoordinatesGenerator();
complex<T> operator()();
private:
const sf::Rect<T>& area_;
const sf::Vector2u& subdivisions_;
complex<T> coord_;
sf::Vector2u pixel_;
};
private:
uint32_t max_iterations_;
T tolerance_;
iterative_function iter_function_;
domain_function domain_function_;
uint32_t getIterations(complex<T> z) const;
};
template<class T>
Fractal<T>::Fractal()
{
max_iterations_ = 1000;
iter_function_ = iterative_function([](complex<T>& z)
{
z = z*z + complex<T>(1,0);
});
domain_function_ = domain_function([](complex<T>& z)
{
return abs(z) < 2;
});
}
template<class T>
void Fractal<T>::setIterativeFunction(iterative_function func)
{
iter_function_ = func;
}
template<class T>
void Fractal<T>::setDomainFunction(domain_function func)
{
domain_function_ = func;
}
template<class T>
void Fractal<T>::setMaxIterations(const uint32_t iterations)
{
max_iterations_ = iterations;
}
template<class T>
vector<uint32_t> Fractal<T>::evaluate(const sf::Rect<T>& area, const sf::Vector2u& subdivisions)
{
uint32_t temp;
complex<T> z(area.left,area.top);
uint32_t num_coordinates = (subdivisions.x)*(subdivisions.y);
vector<uint32_t> result;
vector<complex<T>> coordinates(num_coordinates);
CoordinatesGenerator generator(area,subdivisions);
generate(coordinates.begin(),coordinates.end(),generator);
for(auto& z: coordinates)
{
temp = getIterations(z);
result.push_back(temp);
}
return result;
}
template<class T>
uint32_t Fractal<T>::getIterations(complex<T> z) const
{
static uint32_t result;
result = 0;
while(domain_function_(z) && result < max_iterations_)
{
iter_function_(z);
result++;
}
return result;
}
template<class T>
Fractal<T>::CoordinatesGenerator::CoordinatesGenerator(const sf::Rect<T>& area, const sf::Vector2u& subdivisions):
area_(area),subdivisions_(subdivisions)
{
coord_ = complex<T>(area_.left,area_.top);
pixel_.x = 0;
pixel_.y = 0;
}
template<class T>
Fractal<T>::CoordinatesGenerator::~CoordinatesGenerator()
{
}
template<class T>
complex<T> Fractal<T>::CoordinatesGenerator::operator()()
{
T deltaX = area_.width/static_cast<T>(subdivisions_.x);
T deltaY = area_.height/static_cast<T>(subdivisions_.y);
coord_ = complex<T>(static_cast<T>(pixel_.x)*deltaX + area_.left,static_cast<T>(pixel_.y)*deltaY + area_.top);
pixel_.x++;
if(pixel_.x >= subdivisions_.x)
{
pixel_.y++;
pixel_.x = 0;
}
return coord_;
}
template<class T>
Fractal<T>::~Fractal()
{
}
template<class T>
uint32_t Fractal<T>::getMaxIterations() const
{
return max_iterations_;
}
source
share