/////////////////////////////////////////////////////////////////////////////// // 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) // // Test comparision operators of cpp_double_float<> // Note: This series of tests depend on the correctness of constructor // so please run test_cpp_double_float_constructors.cpp before this #include #include #ifdef BOOST_MATH_USE_FLOAT128 #include #endif #include #include #include #include #include #include #include #include namespace test_cpp_double_comparision { template ::value, bool>::type = true> FloatingPointType uniform_real() { //static std::random_device rd; static std::mt19937 gen/*(rd())*/; static boost::random::uniform_real_distribution dis(0.0, 1.0); return dis(gen); } template ::value && !boost::multiprecision::backends::detail::is_floating_point_or_float128::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; } int rand_in_range(int a, int b) { return a + int(float(b - a) * uniform_real()); } template ::value && !boost::multiprecision::backends::detail::is_floating_point_or_float128::value, bool>::type = true> NumericType uniform_rand() { return uniform_integral_number(); } template ::value, bool>::type = true> FloatingPointType uniform_rand() { return uniform_real(); } template boost::multiprecision::backends::cpp_double_float uniform_rand() { using float_type = typename FloatingPointType::float_type; return boost::multiprecision::backends::cpp_double_float(uniform_real()) * boost::multiprecision::backends::cpp_double_float(uniform_real()); } template ::value>::type const* = nullptr> NumericType log_rand() { return uniform_integral_number() >> int(uniform_real() * float(std::numeric_limits::digits+1)); } template ::value>::type const* = nullptr> FloatingPointType log_rand() { if (uniform_real() < (1. / 100.)) return 0; // throw in a few zeroes using std::ldexp; return ldexp(uniform_real(), rand_in_range(std::numeric_limits::min_exponent, std::numeric_limits::max_exponent)); } template boost::multiprecision::backends::cpp_double_float log_rand() { boost::multiprecision::backends::cpp_double_float a(uniform_rand >()); a *= log_rand(); return a; } template int test() { using double_float_t = boost::multiprecision::backends::cpp_double_float; #ifdef BOOST_MATH_USE_FLOAT128 using largest_type = boost::multiprecision::backends::cpp_double_float; #else using largest_type = boost::multiprecision::backends::cpp_double_float; #endif std::string type_name = typeid(ComparisionType).name(); size_t idx; if ((idx = type_name.rfind(":")) != std::string::npos) type_name = type_name.substr(idx+1, type_name.size()); std::cout << "* Testing comparision operators vs "; std::cout.width(30); std::cout.setf(std::ios::left, std::ios::adjustfield); std::cout.fill(' '); std::cout << type_name << "..."; bool failed = false; int i; for (i = 0; i < 10000; ++i) { ComparisionType r1 = uniform_rand(); ComparisionType r2 = log_rand(); r2 = (uniform_real() < 0.5) ? r1 + r2 : r1 - r2; double_float_t a = double_float_t(r1); ComparisionType b = r2; // operator> if (a > b) { if (static_cast(a) <= static_cast(b)) failed = true; if (b > a || b >= a || b == a || a == b) failed = true; } else { if (!(a <= b)) failed = true; if (!(b >= a)) failed = true; } if (failed) { std::cerr << " [FAILED] operator> failed" << std::endl; return -1; } // operator< if (a < b) { if (static_cast(a) >= static_cast(b)) failed = true; if (b < a || b <= a || b == a || a == b) failed = true; } else { if (!(a >= b)) failed = true; if (!(b <= a)) failed = true; } if (failed) { std::cerr << " [FAILED] operator< failed" << std::endl; return -1; } // operator<= if (a <= b) { if (b < a) failed = true; if (static_cast(a) > static_cast(b)) failed = true; } else { if (!(a > b)) failed = true; if (!(b < a)) failed = true; } if (failed) { std::cerr << " [FAILED] operator<= failed" << std::endl; return -1; } // operator>= if (a >= b) { if (b > a) failed = true; if (static_cast(a) < static_cast(b)) failed = true; } else { if (!(a < b)) failed = true; if (!(b > a)) failed = true; } if (failed) { std::cerr << " [FAILED] operator>= failed" << std::endl; return -1; } // operator== if (a == b) { if (b != a) failed = true; if (static_cast(a) != static_cast(b)) failed = true; } else { if (!(a != b)) failed = true; if (!(b != a)) failed = true; } if (failed) { std::cerr << " [FAILED] operator== failed" << std::endl; return -1; } // operator!= if (a != b) { if (b == a) failed = true; if (static_cast(a) == static_cast(b)) failed = true; } else { if (!(a == b)) failed = true; if (!(b == a)) failed = true; } if (failed) { std::cerr << " [FAILED] operator!= failed" << std::endl; return -1; } } std::cout << " ok [" << i << " tests]" << std::endl; return 0; } template int test_basic() { using double_float_t = boost::multiprecision::backends::cpp_double_float; std::cout << "Performing basic comparision tests for cpp_double_float<" << typeid(FloatingPointType).name() << ">... "; int i; for (i = 0; i < 10000; ++i) { double_float_t a(uniform_rand()), a_prime; a_prime = a + std::numeric_limits::epsilon(); if (a > a_prime) { std::cerr << "operator> failed" << std::endl; return -1; } if (a >= a_prime) { std::cerr << "operator>= failed" << std::endl; return -1; } if (a_prime < a) { std::cerr << "operator< failed" << std::endl; return -1; } if (a_prime <= a) { std::cerr << "operator<= failed" << std::endl; return -1; } if (a == a_prime || a_prime == a) { std::cerr << "operator== failed" << std::endl; return -1; } if (!(a != a_prime) || !(a_prime != a)) { std::cerr << "operator!= failed" << std::endl; return -1; } a_prime = a - std::numeric_limits::epsilon(); if (a < a_prime) { std::cerr << "operator< failed" << std::endl; return -1; } if (a <= a_prime) { std::cerr << "operator<= failed" << std::endl; return -1; } if (a_prime > a) { std::cerr << "operator> failed" << std::endl; return -1; } if (a_prime >= a) { std::cerr << "operator>= failed" << std::endl; return -1; } if (a == a_prime || a_prime == a) { std::cerr << "operator== failed" << std::endl; return -1; } if (!(a != a_prime) || !(a_prime != a)) { std::cerr << "operator!= failed" << std::endl; return -1; } } std::cerr << "ok [" << i << " tests]" << std::endl; return 0; } } // namespace test_cpp_double_comparision template int test_comparison() { int e = 0; e += test_cpp_double_comparision::test_basic(); std::cout << "\nTesting comparision operators for cpp_double_float<" << boost::core::demangle(typeid(FloatingPointType).name()) << ">" << std::endl; e += test_cpp_double_comparision::test(); e += test_cpp_double_comparision::test(); e += test_cpp_double_comparision::test(); e += test_cpp_double_comparision::test(); e += test_cpp_double_comparision::test(); e += test_cpp_double_comparision::test(); e += test_cpp_double_comparision::test(); e += test_cpp_double_comparision::test(); e += test_cpp_double_comparision::test(); e += test_cpp_double_comparision::test(); e += test_cpp_double_comparision::test(); #ifdef BOOST_MATH_USE_FLOAT128 e += test_cpp_double_comparision::test(); #endif e += test_cpp_double_comparision::test >(); e += test_cpp_double_comparision::test >(); e += test_cpp_double_comparision::test >(); #ifdef BOOST_MATH_USE_FLOAT128 e += test_cpp_double_comparision::test >(); #endif std::cout << std::endl; return e; } int main() { int e = 0; e += test_comparison(); e += test_comparison(); e += test_comparison(); #ifdef BOOST_MATH_USE_FLOAT128 e += test_comparison(); #endif std::cout << (e == 0 ? "PASSED all tests" : "FAILED some test(s)") << std::endl; return int(e == 0) - 1; }