#ifndef GENERATOR_H
#define GENERATOR_H
#include <climits>
#include <map>
#include "surface.h"
#include "vector.h"
class Generator: public Shared {
public:
enum {
gray0 = 1ull << 28,
one = 1ull << 32,
gray1 = 1ull << 36,
big = 1ull << 60,
max_side = 1ull << 16,
max_area = 1ull << 32,
};
struct CacheEntry;
typedef std::map<ULongIntVector2, CacheEntry> Cache;
struct CacheEntry {
Cache::iterator next, previous;
bool in_use;
Vector4 value;
};
class GenSurface {
private:
Vector4 *data;
ULongInt w, h;
ULongIntVector2 m_offset;
ULongInt m_step;
public:
inline GenSurface():
data(), w(), h(), m_step() { }
inline GenSurface(const ULongIntPair2 &bounds, ULongInt step):
GenSurface() { create(bounds, step); }
inline GenSurface(const GenSurface &other):
GenSurface() { *this = other; }
inline GenSurface(GenSurface &&other):
data(other.data), w(other.w), h(other.h), m_offset(other.m_offset), m_step(other.m_step)
{ if (&other != this) other.data = nullptr; }
inline ~GenSurface()
{ reset(); }
void create(const ULongIntPair2 &bounds, ULongInt step);
void reset();
GenSurface& operator= (const GenSurface &other);
inline bool is_valid() const {
return data
&& w < max_side
&& h < max_side
&& w*h < max_area
&& w%2 && h%2
&& !(m_step & (m_step - 1))
&& !(m_offset.x & (m_step - 1))
&& !(m_offset.y & (m_step - 1))
&& m_offset.x & m_step
&& m_offset.y & m_step;
}
inline ULongInt width() const { return w; }
inline ULongInt height() const { return h; }
inline const ULongIntVector2& offset() const { return m_offset; }
inline ULongInt step() const { return m_step; }
inline Vector4* operator[] (ULongInt row) { return data + row*w; }
inline const Vector4* operator[] (ULongInt row) const { return data + row*w; }
inline ULongIntVector2 p0() const { return m_offset; }
inline ULongIntVector2 p1() const { return m_offset + ULongIntVector2(w-1, h-1)*m_step; }
};
static inline ULongInt random(ULongInt x)
{ return x*2862933555777941757ull + 3037000493ull; }
static inline Real random_to_real(ULongInt x)
{ return Real(x)/Real(ULLONG_MAX); }
static inline Real random_to_normal(ULongInt x, ULongInt y)
{ return sqrt(-2*log(random_to_real(x))) * sin(2*M_PI*random_to_real(y)); }
private:
const int max_cache_count;
mutable Cache m_cache;
mutable Cache::iterator m_cache_top;
mutable int m_cache_count;
ULongInt m_seeds[2][4];
public:
Generator();
explicit Generator(ULongInt seed);
inline const ULongInt* seeds_x() const { return m_seeds[0]; }
inline const ULongInt* seeds_y() const { return m_seeds[1]; }
inline ULongInt seed() const { return seeds_x()[0]; }
void set_seed(ULongInt x);
Real random(const ULongIntVector2 &coord, int index) const;
inline Vector4 random(const ULongIntVector2 &coord) const
{ return Vector4(random(coord, 0), random(coord, 1), random(coord, 2), random(coord, 3)); }
Real checks_value(Real coord, Real inv_precision) const;
Real checks_value(const Vector2 &coord, const Vector2 &inv_precision) const;
Vector4 generate(const ULongIntVector2 &coord, bool shrink_cache = true) const;
Vector4 generate(const Vector2 &coord, const Vector2 &precision) const;
void generate(Surface &target, const Pair2 &bounds, bool checks = false) const;
void generate(GenSurface &target) const;
void generate(GenSurface &target, const GenSurface &source) const;
void generate_checks(Surface &target, const Pair2 &bounds) const;
};
#endif