Blame c++/perspective/src/generator.h

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