#include "hwy/auto_tune.h"
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <random>
#include <vector>
#include "hwy/base.h"
#include "hwy/nanobenchmark.h"
#include "hwy/tests/hwy_gtest.h"
#include "hwy/tests/test_util-inl.h"
namespace hwy {
namespace {
static double Random(RandomState& rng) {
const int32_t bits = static_cast<int32_t>(Random32(&rng)) & 1023;
return (bits - 512) / 64.0;
}
TEST(AutoTuneTest, TestCostDistribution) {
const size_t kMaxValues = CostDistribution::kMaxValues;
for (size_t num : {size_t{3}, kMaxValues - 1, kMaxValues, kMaxValues + 1}) {
const double kVal = 6.5;
for (double outlier : {0.0, 1000.0}) {
CostDistribution cd;
const size_t num_outliers = HWY_MAX(num / 4, size_t{1});
for (size_t i = 0; i < num - num_outliers; ++i) cd.Notify(kVal);
for (size_t i = 0; i < num_outliers; ++i) cd.Notify(outlier);
const double cost = cd.EstimateCost();
HWY_ASSERT(cost >= kVal - 0.25);
HWY_ASSERT(cost <= kVal + 0.25);
}
}
RandomState rng;
for (size_t rep = 0; rep < AdjustedReps(1000); ++rep) {
CostDistribution cd;
const size_t num = 1000; for (size_t i = 0; i < num; ++i) {
double sum = 500.0;
for (size_t sum_idx = 0; sum_idx < 100; ++sum_idx) sum += Random(rng);
const uint32_t r = Random32(&rng);
if (r < (1u << 28)) {
static constexpr double kPowers[4] = {0.0, 1E3, 1E4, 1E5};
static constexpr double kMul[4] = {0.50, 0.75, 0.85, 0.90};
if (r & 3) { sum += kPowers[r & 3];
} else { sum *= kMul[(r >> 2) & 3];
}
}
cd.Notify(sum);
}
const double cost = cd.EstimateCost();
if (!(490.0 <= cost && cost <= 540.0)) {
HWY_ABORT("Cost %f outside expected range.", cost);
}
}
}
TEST(AutoTuneTest, TestNextEdges) {
NextWithSkip list(123);
HWY_ASSERT_EQ(0, list.Next(122)); HWY_ASSERT_EQ(1, list.Next(0));
list.Skip(1);
HWY_ASSERT_EQ(2, list.Next(0));
list.Skip(2);
HWY_ASSERT_EQ(3, list.Next(0));
list.Skip(122);
HWY_ASSERT_EQ(0, list.Next(121));
list.Skip(0);
HWY_ASSERT_EQ(3, list.Next(121));
}
TEST(AutoTuneTest, TestNextSkipAllButOne) {
for (size_t num : {size_t{37}, size_t{63}, size_t{513}}) {
NextWithSkip list(num);
std::vector<uint32_t> pos;
pos.reserve(num);
for (size_t i = 0; i < num; ++i) {
pos.push_back(static_cast<uint32_t>(i));
}
std::mt19937 rng(static_cast<uint_fast32_t>(129 * Unpredictable1()));
std::shuffle(pos.begin(), pos.end(), rng);
for (size_t i = 0; i < num - 1; ++i) {
list.Skip(pos[i]);
}
HWY_ASSERT_EQ(pos.back(), list.Next(pos.back())); }
}
} }
HWY_TEST_MAIN();