#include <atomic>
#include <fenv.h>
#include <functional>
#include <iostream>
#include <mutex>
#include <sstream>
#include <thread>
#include <vector>
#include "src/__support/FPUtil/FPBits.h"
#include "exhaustive_test.h"
template <typename T, typename FloatType>
void LlvmLibcExhaustiveTest<T, FloatType>::test_full_range(
T start, T stop, mpfr::RoundingMode rounding) {
int n_threads = std::thread::hardware_concurrency();
std::vector<std::thread> thread_list;
std::mutex mx_cur_val;
int current_percent = -1;
T current_value = start;
std::atomic<uint64_t> failed(0);
for (int i = 0; i < n_threads; ++i) {
thread_list.emplace_back([&, this]() {
while (true) {
T range_begin, range_end;
int new_percent = -1;
{
std::lock_guard<std::mutex> lock(mx_cur_val);
if (current_value == stop)
return;
range_begin = current_value;
if (stop >= increment && stop - increment >= current_value) {
range_end = current_value + increment;
} else
range_end = stop;
current_value = range_end;
int pc = 100.0 * double(range_end - start) / double(stop - start);
if (current_percent != pc) {
new_percent = pc;
current_percent = pc;
}
}
if (new_percent >= 0) {
std::stringstream msg;
msg << new_percent << "% is in process \r";
std::cout << msg.str() << std::flush;
;
}
bool check_passed = check(range_begin, range_end, rounding);
if (!check_passed) {
std::stringstream msg;
msg << "Test failed in range: " << std::dec << range_begin << " to "
<< range_end << " [0x" << std::hex << range_begin << ", 0x"
<< range_end << "), [" << std::hexfloat
<< static_cast<FloatType>(__llvm_libc::fputil::FPBits<FloatType>(
static_cast<T>(range_begin)))
<< ", "
<< static_cast<FloatType>(
__llvm_libc::fputil::FPBits<FloatType>(range_end))
<< ") " << std::endl;
std::cerr << msg.str() << std::flush;
failed.fetch_add(1);
}
}
});
}
for (auto &thread : thread_list) {
if (thread.joinable()) {
thread.join();
}
}
std::cout << std::endl;
std::cout << "Test " << ((failed > 0) ? "FAILED" : "PASSED") << std::endl;
}
template void
LlvmLibcExhaustiveTest<uint32_t>::test_full_range(uint32_t, uint32_t,
mpfr::RoundingMode);
template void LlvmLibcExhaustiveTest<uint64_t, double>::test_full_range(
uint64_t, uint64_t, mpfr::RoundingMode);