
#include "UnitTester.h"

#include "Sobol.h"
#include "DDWR.h"

#include <cstdint>
#include <algorithm>
#include <random>
#include <iostream>

namespace unittest {

void testSobol()
{
  {

    const size_t dim = 12;
    Sobol s(dim);
    CHECK_EQUAL(s.min(), 0u);
    CHECK_EQUAL(s.max(), -1u); // -1ul fails on LP64
    
    s.skip(12345);
    const std::vector<uint32_t>& b0 = s.buf();
    s.reset(12345);
    const std::vector<uint32_t>& b1 = s.buf();
    for (size_t i = 0; i < dim; ++i)
    {
      CHECK_EQUAL(b0[i], b1[i]);
    }
  }

  {


    std::vector<uint32_t> m{144, 150, 3, 2, 153, 345, 13, 11, 226, 304, 24, 18, 250, 336, 14, 21, 190, 176, 15, 14, 27, 10, 2, 3, 93, 135, 2, 6, 30, 465, 11, 28, 43, 463, 17, 76, 39, 458, 15, 88, 55, 316, 22, 50, 15, 25, 11, 17};

    uint32_t samples = std::accumulate(m.begin(), m.end(), 0);

    Sobol s(1);
    discrete_distribution_without_replacement<uint32_t> dist(m.begin(), m.end());

    std::vector<uint32_t> p(m.size(), 0);

    for (size_t i = 0; i < samples; ++i)
    {
      ++p[dist(s)];
    }

    for (size_t i = 0; i < m.size(); ++i)
    {
      CHECK(p[i] == m[i]);
    }

  }
};

}
