mirror of
https://github.com/luxfi/intx.git
synced 2026-10-30 16:22:26 +00:00
143 lines
4.3 KiB
C++
143 lines
4.3 KiB
C++
// intx: extended precision integer library.
|
|
// Copyright 2020 Pawel Bylica.
|
|
// Licensed under the Apache License, Version 2.0.
|
|
|
|
#include "random.hpp"
|
|
#include <intx/intx.hpp>
|
|
|
|
namespace intx::test
|
|
{
|
|
namespace
|
|
{
|
|
std::array<uint64_t, num_samples> samples_64_norm;
|
|
std::array<uint128, num_samples> samples_128_norm;
|
|
std::array<uint256, num_samples> samples_256[lt_x_256 - x_64 + 1];
|
|
std::array<uint512, num_samples> samples_512[y_512 - x_64 + 1];
|
|
std::array<uint64_t, num_samples> samples_shift_w[4];
|
|
std::array<uint64_t, num_samples> samples_shift_mixed;
|
|
|
|
std::span<uint64_t, 1> as_words(uint64_t& x) noexcept
|
|
{
|
|
return std::span<uint64_t, 1>{&x, 1};
|
|
}
|
|
|
|
bool init() noexcept
|
|
{
|
|
std::mt19937_64 rng{0}; // NOLINT(cert-msc51-cpp,cert-msc32-c)
|
|
|
|
const auto gen_int = [&rng](auto& out, size_t num_significant_words) noexcept {
|
|
std::ranges::generate(as_words(out).subspan(0, num_significant_words),
|
|
[&rng] { return std::uniform_int_distribution<uint64_t>{}(rng); });
|
|
};
|
|
|
|
const auto lt_fixup = [&rng](uint256& tgt, const uint256& src) noexcept {
|
|
if (tgt[3] > src[3])
|
|
tgt[3] = std::uniform_int_distribution<uint64_t>{0, src[3]}(rng);
|
|
assert(tgt <= src);
|
|
};
|
|
|
|
for (size_t i = 0; i < num_samples; ++i)
|
|
{
|
|
gen_int(samples_64_norm[i], 1);
|
|
samples_64_norm[i] |= 0x8000000000000000;
|
|
|
|
gen_int(samples_128_norm[i], 2);
|
|
samples_128_norm[i][1] |= 0x8000000000000000;
|
|
|
|
gen_int(samples_256[x_64][i], 1);
|
|
gen_int(samples_256[y_64][i], 1);
|
|
samples_512[x_64][i] = samples_256[x_64][i];
|
|
|
|
gen_int(samples_256[x_128][i], 2);
|
|
gen_int(samples_256[y_128][i], 2);
|
|
samples_512[x_128][i] = samples_256[x_128][i];
|
|
|
|
gen_int(samples_256[x_192][i], 3);
|
|
gen_int(samples_256[y_192][i], 3);
|
|
samples_512[x_192][i] = samples_256[x_192][i];
|
|
|
|
gen_int(samples_256[x_256][i], 4);
|
|
gen_int(samples_256[y_256][i], 4);
|
|
gen_int(samples_256[lt_256][i], 4);
|
|
gen_int(samples_256[lt_x_256][i], 4);
|
|
|
|
lt_fixup(samples_256[lt_256][i], samples_256[x_256][i]);
|
|
lt_fixup(samples_256[lt_256][i], samples_256[y_256][i]);
|
|
lt_fixup(samples_256[lt_x_256][i], samples_256[x_256][i]);
|
|
|
|
samples_512[x_256][i] = samples_256[x_256][i];
|
|
samples_512[y_256][i] = samples_256[y_256][i];
|
|
samples_512[lt_256][i] = samples_256[lt_256][i];
|
|
samples_512[lt_x_256][i] = samples_256[lt_x_256][i];
|
|
|
|
gen_int(samples_512[x_512][i], 8);
|
|
gen_int(samples_512[y_512][i], 8);
|
|
}
|
|
|
|
// Generate samples for shift amounts: ranges, 0-64, 0-128, ... and mix of those.
|
|
for (size_t w = 0; w < 4; ++w)
|
|
{
|
|
std::ranges::generate(samples_shift_w[w], [&rng, w]() noexcept {
|
|
return std::uniform_int_distribution<uint64_t>{w * 64, (w + 1) * 64 - 1}(rng);
|
|
});
|
|
std::copy_n(std::begin(samples_shift_w[w]), num_samples / 4,
|
|
&samples_shift_mixed[(num_samples / 4) * w]);
|
|
|
|
std::copy_n(std::begin(samples_256[x_64 + w]), num_samples / 4,
|
|
&samples_256[x_256_mixed][(num_samples / 4) * w]);
|
|
std::copy_n(std::begin(samples_256[y_64 + w]), num_samples / 4,
|
|
&samples_256[y_256_mixed][(num_samples / 4) * w]);
|
|
}
|
|
std::ranges::shuffle(samples_shift_mixed, rng);
|
|
|
|
auto rng_copy = rng;
|
|
std::ranges::shuffle(samples_256[x_256_mixed], rng);
|
|
std::ranges::shuffle(samples_256[y_256_mixed], rng_copy);
|
|
|
|
return true;
|
|
}
|
|
|
|
const auto _ = init();
|
|
} // namespace
|
|
|
|
template <>
|
|
const std::array<uint64_t, num_samples>& get_samples<uint64_t>(samples_set_id id) noexcept
|
|
{
|
|
switch (id)
|
|
{
|
|
case norm:
|
|
return samples_64_norm;
|
|
case shift_w0:
|
|
case shift_w1:
|
|
case shift_w2:
|
|
case shift_w3:
|
|
return samples_shift_w[id - shift_w0];
|
|
case shift_mixed:
|
|
return samples_shift_mixed;
|
|
default:
|
|
std::abort();
|
|
}
|
|
}
|
|
|
|
template <>
|
|
const std::array<uint128, num_samples>& get_samples<uint128>(samples_set_id id) noexcept
|
|
{
|
|
if (id != norm)
|
|
std::abort();
|
|
return samples_128_norm;
|
|
}
|
|
|
|
template <>
|
|
const std::array<uint256, num_samples>& get_samples<uint256>(samples_set_id id) noexcept
|
|
{
|
|
return samples_256[id];
|
|
}
|
|
|
|
template <>
|
|
const std::array<uint512, num_samples>& get_samples<uint512>(samples_set_id id) noexcept
|
|
{
|
|
return samples_512[id];
|
|
}
|
|
|
|
} // namespace intx::test
|