<commit_before>#include "Core/SampleGenerator/SGStratified.h"
#include "Core/Filmic/Film.h"
#include "Core/Sample.h"
#include "Math/Random.h"
#include "FileIO/SDL/InputPacket.h"

#include <iostream>

namespace ph
{

SGStratified::SGStratified(const std::size_t numSamples,
                           const std::size_t numStrata2dX,
                           const std::size_t numStrata2dY) :
	//SampleGenerator(numSamples, numSamples)
	SampleGenerator(numSamples, 4), // HACK
	m_numStrata2dX(numStrata2dX), m_numStrata2dY(numStrata2dY)
{}

SGStratified::~SGStratified() = default;

void SGStratified::genArray1D(SampleArray1D* const out_array)
{
	for(std::size_t i = 0; i < out_array->numElements(); i++)
	{
		const real jitter = Random::genUniformReal_i0_e1();
		out_array->set(i, i + jitter);
	}

	out_array->perElementShuffle();
}

void SGStratified::genArray2D(SampleArray2D* const out_array)
{
	const std::size_t numStrata = m_numStrata2dX * m_numStrata2dY;
	if(out_array->numElements() >= numStrata)
	{
		const real dx = 1.0_r / static_cast<real>(m_numStrata2dX);
		const real dy = 1.0_r / static_cast<real>(m_numStrata2dY);
		for(std::size_t y = 0; y < m_numStrata2dY; y++)
		{
			const std::size_t baseIndex = y * m_numStrata2dX;
			for(std::size_t x = 0; x < m_numStrata2dX; x++)
			{
				const real jitterX = Random::genUniformReal_i0_e1();
				const real jitterY = Random::genUniformReal_i0_e1();
				out_array->set(baseIndex + x, 
				               (static_cast<real>(x) + jitterX) * dx,
				               (static_cast<real>(y) + jitterY) * dy);
			}
		}

		for(std::size_t i = numStrata; i < out_array->numElements(); i++)
		{
			out_array->set(i,
			               Random::genUniformReal_i0_e1(),
			               Random::genUniformReal_i0_e1());
		}

		out_array->perElementShuffle();
	}
	else
	{
		for(std::size_t i = 0; i < out_array->numElements(); i++)
		{
			out_array->set(i, 
			               Random::genUniformReal_i0_e1(), 
			               Random::genUniformReal_i0_e1());
		}
	}
}

std::unique_ptr<SampleGenerator> SGStratified::genNewborn(const std::size_t numSamples) const
{
	return std::make_unique<SGStratified>(numSamples,
	                                      m_numStrata2dX,<commit_msg>stratified SG now tries to generate as many <numStrata> batch as possible<commit_after>#include "Core/SampleGenerator/SGStratified.h"
#include "Core/Filmic/Film.h"
#include "Core/Sample.h"
#include "Math/Random.h"
#include "FileIO/SDL/InputPacket.h"
#include "Common/assertion.h"

#include <iostream>

namespace ph
{

SGStratified::SGStratified(const std::size_t numSamples,
                           const std::size_t numStrata2dX,
                           const std::size_t numStrata2dY) :
	//SampleGenerator(numSamples, numSamples)
	SampleGenerator(numSamples, 4), // HACK
	m_numStrata2dX(numStrata2dX > 0 ? numStrata2dX : 1), 
	m_numStrata2dY(numStrata2dY > 0 ? numStrata2dY : 1)
{}

SGStratified::~SGStratified() = default;

void SGStratified::genArray1D(SampleArray1D* const out_array)
{
	// TODO: generate stratified
	for(std::size_t i = 0; i < out_array->numElements(); i++)
	{
		const real jitter = Random::genUniformReal_i0_e1();
		out_array->set(i, i + jitter);
	}

	out_array->perElementShuffle();
}

void SGStratified::genArray2D(SampleArray2D* const out_array)
{
	const std::size_t numStrata = m_numStrata2dX * m_numStrata2dY;
	PH_ASSERT(numStrata > 0);

	// OPT: It is possible to precompute how many samples will be in a
	// stratum and generate them together. 

	// Tries to generate <numStrata> samples over and over again until there 
	// is no room in <out_array> to fit another <numStrata> samples.
	//
	std::size_t currentIndex = 0;
	while(currentIndex + numStrata <= out_array->numElements())
	{
		const real dx = 1.0_r / static_cast<real>(m_numStrata2dX);
		const real dy = 1.0_r / static_cast<real>(m_numStrata2dY);
		for(std::size_t y = 0; y < m_numStrata2dY; ++y)
		{
			for(std::size_t x = 0; x < m_numStrata2dX; ++x)
			{
				const real jitterX = Random::genUniformReal_i0_e1();
				const real jitterY = Random::genUniformReal_i0_e1();
				out_array->set(currentIndex,
				               (static_cast<real>(x) + jitterX) * dx,
				               (static_cast<real>(y) + jitterY) * dy);
				++currentIndex;
			}
		}
	}

	// There is no room to fit another <numStrata> samples. We fill the resting
	// spaces with random ones.
	//
	PH_ASSERT(out_array->numElements() - currentIndex < numStrata);
	for(std::size_t i = currentIndex; i < out_array->numElements(); ++i)
	{
		out_array->set(i, 
		               Random::genUniformReal_i0_e1(), 
		               Random::genUniformReal_i0_e1());
	}

	out_array->perElementShuffle();
}

std::unique_ptr<SampleGenerator> SGStratified::genNewborn(const std::size_t numSamples) const
{
	return std::make_unique<SGStratified>(numSamples,
	                                      m_numStrata2dX,
{'fraction_non_alphanumeric': 0.12990998363338788, 'fraction_numerical': 0.01718494271685761, 'mean_word_length': 3.539461467038069, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1080374', 'n_tokens_mistral': 1964, 'n_tokens_neox': 1814, 'n_words': 335}