Blob Blame Raw
#ifndef GENERATOR_H
#define GENERATOR_H


#include <climits>
#include <map>

#include "surface.h"
#include "vector.h"


class Generator: public Shared {
public:
	struct CacheEntry;
	typedef std::map<ULongIntVector2, CacheEntry> Cache;
	
	struct CacheEntry {
		Cache::iterator next, previous;
		bool in_use;
		Vector4 value;
	};
	
	static inline ULongInt random(ULongInt x) {
		++x;
		x ^= x >> 2;
		x ^= x << 3;
		x ^= x >> 5;
		x ^= x << 7;
		x ^= x >> 11;
		x ^= x << 13;
		x ^= x >> 17;
		x ^= x << 19;
		x ^= x >> 23;
		x ^= x << 29;
		x ^= x >> 31;
		x ^= x << 37;
		x ^= x >> 41;
		x ^= x << 43;
		x ^= x >> 47;
		x ^= x << 53;
		x ^= x >> 59;
		x ^= x << 61;
		++x;
		return x;
	}

	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)); }
	
	static inline Real mirror_repeat(Real x) {
		x *= 0.5;
		x -= floor(x);
		x *= 2;
		return x > 1 ? 2 - x : x;
	}

private:
	const ULongInt one;
	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;
	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) const;
};


#endif