/////////////////////////////////////////////////////////////////////////////// // Copyright 2021 Fahad Syed. // Copyright 2021 Christopher Kormanyos. // Copyright 2021 Janek Kozicki. // Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Basic compilation, constructors, and operatory tests for cpp_double_float<> #include #include #include #include #include #include namespace test_cpp_double_constructors { template ::value, bool>::type = true> FloatingPointType uniform_real() { static std::random_device rd; static std::mt19937 gen(rd()); static std::uniform_real_distribution dis(0.0, 1.0); return dis(gen); } template ::value, bool>::type = true> NumericType uniform_integral_number() { NumericType out = 0; for (int i = 0; i < sizeof(NumericType); ++i) out = (out << 8) + static_cast(std::round(256.0 * uniform_real())); return out; } template int test_constructor() { constexpr int Trials = 50000; std::cout << "Testing constructor for "; std::cout.width(30); std::cout << typeid(NumericType).name() << "... "; using double_float_t = boost::multiprecision::backends::cpp_double_float; for (int i = 0; i < Trials; ++i) { NumericType n = uniform_integral_number(); double_float_t d(n); double_float_t::rep_type rep(d.rep()); double_float_t::normalize_pair(rep); // Check if representation of the cpp_double_float is not normalized if (rep != d.rep()) { std::cerr << "[FAILED]\n" << typeid(NumericType).name() << " = " << n << " (cpp_double_float<" << typeid(FloatingPointType).name() << "> = " << d.get_raw_str() << ")" << std::endl; return -1; } // Check if value is accurately represented and correctly rounded constexpr int NumericTypeBits = std::numeric_limits::digits; constexpr int MaxRepresentableBits = std::numeric_limits::digits * 2; const NumericType RoundedBitsMask = (NumericType(1) << (NumericTypeBits - MaxRepresentableBits)) - 1; const NumericType RoundedMargin = (RoundedBitsMask + 1) >> 1; NumericType n_prime(n); n_prime >>= NumericTypeBits - MaxRepresentableBits; // Round correctly if (n & RoundedBitsMask > RoundedMargin) n_prime |= 1; if (n & RoundedBitsMask < RoundedMargin) n_prime &= ~NumericType(1); n_prime <<= NumericTypeBits - MaxRepresentableBits; if (std::abs(signed(n_prime - n)) < std::abs(signed(static_cast(d) - n))) { std::cerr << "[FAILED]\nn = 0x" << std::hex << n << " | cpp_double_float<" << typeid(FloatingPointType).name() << "> = 0x" << std::hex << static_cast(d) << " (expected 0x" << std::hex << n_prime << ")" << std::endl; return -1; } } std::cout << "[PASSED] (" << Trials << " cases tested)" << std::endl; return 0; } // Test compilation, constructors, basic operatory template int test_constructors() { using double_float_t = boost::multiprecision::backends::cpp_double_float; double_float_t a, b; std::cout << "Testing cpp_double_float< " << typeid(FloatingPointType).name() << " >...\n===" << std::endl; int e = 0; e += test_constructor(); e += test_constructor(); e += test_constructor(); e += test_constructor(); e += test_constructor(); e += test_constructor(); e += test_constructor(); e += test_constructor(); if (e == 0) std::cout << "PASSED ALL TESTS"; else std::cout << "FAILED " << -e << " TESTS"; std::cout << std::endl << std::endl; return e == 0 ? 0 : -1; } } // namespace test_cpp_double_constructors int main() { test_cpp_double_constructors::test_constructors(); test_cpp_double_constructors::test_constructors(); std::cin.get(); return 0; }