//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// REQUIRES: long_tests
// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
// <random>
// template<class IntType = int>
// class discrete_distribution
// template<class _URNG> result_type operator()(_URNG& g);
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <random>
#include <vector>
#include "test_macros.h"
template <class T>
void tests() {
typedef long long Frequency;
{
typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
D d;
const int N = 100;
std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
assert(u.max_size() > static_cast<unsigned long long>(d.max()));
for (int i = 0; i < N; ++i)
{
typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[static_cast<std::size_t>(v)]++;
}
std::vector<double> prob = d.probabilities();
for (unsigned i = 0; i < u.size(); ++i)
assert((double)u[i]/N == prob[i]);
}
{
typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {.3};
D d(p0, p0+1);
const int N = 100;
std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
assert(u.max_size() > static_cast<unsigned long long>(d.max()));
for (int i = 0; i < N; ++i)
{
typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[static_cast<std::size_t>(v)]++;
}
std::vector<double> prob = d.probabilities();
for (unsigned i = 0; i < u.size(); ++i)
assert((double)u[i]/N == prob[i]);
}
{
typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {.75, .25};
D d(p0, p0+2);
const int N = 1000000;
std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
assert(u.max_size() > static_cast<unsigned long long>(d.max()));
for (int i = 0; i < N; ++i)
{
typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[static_cast<std::size_t>(v)]++;
}
std::vector<double> prob = d.probabilities();
for (unsigned i = 0; i < u.size(); ++i)
assert(std::abs((double)u[i] / N - prob[i]) / prob[i] < 0.0013);
}
{
typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {0, 1};
D d(p0, p0+2);
const int N = 1000000;
std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
assert(u.max_size() > static_cast<unsigned long long>(d.max()));
for (int i = 0; i < N; ++i)
{
typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[static_cast<std::size_t>(v)]++;
}
std::vector<double> prob = d.probabilities();
assert((double)u[0]/N == prob[0]);
assert((double)u[1]/N == prob[1]);
}
{
typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {1, 0};
D d(p0, p0+2);
const int N = 1000000;
std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
assert(u.max_size() > static_cast<unsigned long long>(d.max()));
for (int i = 0; i < N; ++i)
{
typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[static_cast<std::size_t>(v)]++;
}
std::vector<double> prob = d.probabilities();
assert((double)u[0]/N == prob[0]);
assert((double)u[1]/N == prob[1]);
}
{
typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {.3, .1, .6};
D d(p0, p0+3);
const int N = 10000000;
std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
assert(u.max_size() > static_cast<unsigned long long>(d.max()));
for (int i = 0; i < N; ++i)
{
typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[static_cast<std::size_t>(v)]++;
}
std::vector<double> prob = d.probabilities();
for (unsigned i = 0; i < u.size(); ++i)
assert(std::abs((double)u[i]/N - prob[i]) / prob[i] < 0.001);
}
{
typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {0, 25, 75};
D d(p0, p0+3);
const int N = 1000000;
std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
assert(u.max_size() > static_cast<unsigned long long>(d.max()));
for (int i = 0; i < N; ++i)
{
typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[static_cast<std::size_t>(v)]++;
}
std::vector<double> prob = d.probabilities();
for (unsigned i = 0; i < u.size(); ++i)
if (prob[i] != 0)
assert(std::abs((double)u[i] / N - prob[i]) / prob[i] < 0.0013);
else
assert(u[i] == 0);
}
{
typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {25, 0, 75};
D d(p0, p0+3);
const int N = 1000000;
std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
assert(u.max_size() > static_cast<unsigned long long>(d.max()));
for (int i = 0; i < N; ++i)
{
typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[static_cast<std::size_t>(v)]++;
}
std::vector<double> prob = d.probabilities();
for (unsigned i = 0; i < u.size(); ++i)
if (prob[i] != 0)
assert(std::abs((double)u[i]/N - prob[i]) / prob[i] < 0.001);
else
assert(u[i] == 0);
}
{
typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {25, 75, 0};
D d(p0, p0+3);
const int N = 1000000;
std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
assert(u.max_size() > static_cast<unsigned long long>(d.max()));
for (int i = 0; i < N; ++i)
{
typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[static_cast<std::size_t>(v)]++;
}
std::vector<double> prob = d.probabilities();
for (unsigned i = 0; i < u.size(); ++i)
if (prob[i] != 0)
assert(std::abs((double)u[i] / N - prob[i]) / prob[i] < 0.0013);
else
assert(u[i] == 0);
}
{
typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {0, 0, 1};
D d(p0, p0+3);
const int N = 100;
std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
assert(u.max_size() > static_cast<unsigned long long>(d.max()));
for (int i = 0; i < N; ++i)
{
typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[static_cast<std::size_t>(v)]++;
}
std::vector<double> prob = d.probabilities();
for (unsigned i = 0; i < u.size(); ++i)
if (prob[i] != 0)
assert(std::abs((double)u[i]/N - prob[i]) / prob[i] < 0.001);
else
assert(u[i] == 0);
}
{
typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {0, 1, 0};
D d(p0, p0+3);
const int N = 100;
std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
assert(u.max_size() > static_cast<unsigned long long>(d.max()));
for (int i = 0; i < N; ++i)
{
typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[static_cast<std::size_t>(v)]++;
}
std::vector<double> prob = d.probabilities();
for (unsigned i = 0; i < u.size(); ++i)
if (prob[i] != 0)
assert(std::abs((double)u[i]/N - prob[i]) / prob[i] < 0.001);
else
assert(u[i] == 0);
}
{
typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {1, 0, 0};
D d(p0, p0+3);
const int N = 100;
std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
assert(u.max_size() > static_cast<unsigned long long>(d.max()));
for (int i = 0; i < N; ++i)
{
typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[static_cast<std::size_t>(v)]++;
}
std::vector<double> prob = d.probabilities();
for (unsigned i = 0; i < u.size(); ++i)
if (prob[i] != 0)
assert(std::abs((double)u[i]/N - prob[i]) / prob[i] < 0.001);
else
assert(u[i] == 0);
}
{
typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {33, 0, 0, 67};
D d(p0, p0+3);
const int N = 1000000;
std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
assert(u.max_size() > static_cast<unsigned long long>(d.max()));
for (int i = 0; i < N; ++i)
{
typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[static_cast<std::size_t>(v)]++;
}
std::vector<double> prob = d.probabilities();
for (unsigned i = 0; i < u.size(); ++i)
if (prob[i] != 0)
assert(std::abs((double)u[i] / N - prob[i]) / prob[i] < 0.0013);
else
assert(u[i] == 0);
}
}
int main(int, char**) {
tests<short>();
tests<int>();
tests<long>();
tests<long long>();
tests<unsigned short>();
tests<unsigned int>();
tests<unsigned long>();
tests<unsigned long long>();
#if defined(_LIBCPP_VERSION) // extension
tests<std::int8_t>();
tests<std::uint8_t>();
#if !defined(TEST_HAS_NO_INT128)
tests<__int128_t>();
tests<__uint128_t>();
#endif
#endif
return 0;
}