mirror of
https://github.com/boostorg/multiprecision.git
synced 2026-01-19 04:22:11 +00:00
Begin adding CMake based testing to make debugging way easier
This commit is contained in:
@@ -38,7 +38,12 @@ else()
|
||||
|
||||
endif()
|
||||
|
||||
# Only enable tests when we're the root project
|
||||
if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
|
||||
|
||||
add_subdirectory(test)
|
||||
|
||||
endif()
|
||||
|
||||
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
|
||||
#Testing with CMake not currently used
|
||||
|
||||
12
test/CMakeLists.txt
Normal file
12
test/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
# Copyright 2018, 2019 Peter Dimov
|
||||
# Copyright 2023 Matt Borland
|
||||
# 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
|
||||
|
||||
include(BoostTestJamfile OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST)
|
||||
|
||||
if(HAVE_BOOST_TEST)
|
||||
|
||||
boost_test_jamfile(FILE Simple_Jamfile LINK_LIBRARIES Boost::multiprecision Boost::core Boost::math Boost::random)
|
||||
|
||||
endif()
|
||||
41
test/Simple_Jamfile
Normal file
41
test/Simple_Jamfile
Normal file
@@ -0,0 +1,41 @@
|
||||
# Copyright 2022 Peter Dimov
|
||||
# Copyright 2023 - 2024 Matt Borland
|
||||
# Copyright 2023 - 2024 Christopher Kormanyos
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
require-b2 5.0.1 ;
|
||||
import-search /boost/config/checks ;
|
||||
import config : requires ;
|
||||
import modules ;
|
||||
import testing ;
|
||||
|
||||
project : requirements
|
||||
|
||||
<toolset>gcc:<cxxflags>-Wall
|
||||
<toolset>gcc:<cxxflags>-Wextra
|
||||
|
||||
# Clang-Cl gives errors that are incorrect or irrelevant (e.g. C++98 compat)
|
||||
#<toolset>clang:<cxxflags>-Wall
|
||||
#<toolset>clang:<cxxflags>-Wextra
|
||||
|
||||
<toolset>msvc:<warnings>all
|
||||
|
||||
# Additional flags by request
|
||||
<toolset>gcc:<cxxflags>-Wsign-conversion
|
||||
<toolset>gcc:<cxxflags>-Wconversion
|
||||
<toolset>gcc:<cxxflags>-Wundef
|
||||
<toolset>gcc:<cxxflags>-Wold-style-cast
|
||||
#<toolset>gcc:<cxxflags>-Wduplicated-branches
|
||||
<toolset>gcc:<cxxflags>-Wfloat-equal
|
||||
|
||||
<toolset>clang:<cxxflags>-Wsign-conversion
|
||||
<toolset>clang:<cxxflags>-Wconversion
|
||||
<toolset>clang:<cxxflags>-Wundef
|
||||
<toolset>clang:<cxxflags>-Wold-style-cast
|
||||
<toolset>clang:<cxxflags>-Wfloat-equal
|
||||
|
||||
[ requires cxx14_decltype_auto cxx14_generic_lambdas cxx14_return_type_deduction cxx14_variable_templates cxx14_constexpr ]
|
||||
;
|
||||
|
||||
run reduced_cpp_double_fp.cpp ;
|
||||
133
test/reduced_cpp_double_fp.cpp
Normal file
133
test/reduced_cpp_double_fp.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/multiprecision/cpp_double_fp.hpp>
|
||||
#include <boost/math/special_functions/round.hpp>
|
||||
#include <boost/math/special_functions/trunc.hpp>
|
||||
#include <boost/math/special_functions/modf.hpp>
|
||||
#include <boost/math/special_functions/sign.hpp>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#include <random>
|
||||
|
||||
template <class T, class U>
|
||||
typename std::enable_if<!boost::multiprecision::is_interval_number<T>::value>::type check_within_half(T a, U u)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
const auto fabs_res {fabs(a - u)};
|
||||
if (fabs_res > 0.5f)
|
||||
{
|
||||
BOOST_ERROR("Rounded result differed by more than 0.5 from the original");
|
||||
std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
|
||||
<< std::left << a << u << std::endl;
|
||||
}
|
||||
if ((fabs(a - u) == 0.5f) && (fabs(static_cast<T>(u)) < fabs(a)))
|
||||
{
|
||||
BOOST_ERROR("Rounded result was towards zero with boost::round");
|
||||
std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
|
||||
<< std::left << a << u << std::endl;
|
||||
}
|
||||
}
|
||||
template <class T, class U>
|
||||
typename std::enable_if<boost::multiprecision::is_interval_number<T>::value>::type check_within_half(T a, U u)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if (upper(T(fabs(a - u))) > 0.5f)
|
||||
{
|
||||
BOOST_ERROR("Rounded result differed by more than 0.5 from the original");
|
||||
std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
|
||||
<< std::left << a << u << std::endl;
|
||||
}
|
||||
if ((upper(T(fabs(a - u))) == 0.5f) && (fabs(static_cast<T>(u)) < fabs(a)))
|
||||
{
|
||||
BOOST_ERROR("Rounded result was towards zero with boost::round");
|
||||
std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
|
||||
<< std::left << a << u << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// We may not have an abs overload for long long so provide a fall back:
|
||||
//
|
||||
inline unsigned safe_abs(int const& v)
|
||||
{
|
||||
return v < 0 ? static_cast<unsigned>(1u) + static_cast<unsigned>(-(v + 1)) : v;
|
||||
}
|
||||
inline unsigned long safe_abs(long const& v)
|
||||
{
|
||||
return v < 0 ? static_cast<unsigned long>(1u) + static_cast<unsigned long>(-(v + 1)) : v;
|
||||
}
|
||||
inline unsigned long long safe_abs(long long const& v)
|
||||
{
|
||||
return v < 0 ? static_cast<unsigned long long>(1u) + static_cast<unsigned long long>(-(v + 1)) : v;
|
||||
}
|
||||
template <class T>
|
||||
inline typename std::enable_if<!boost::multiprecision::detail::is_integral<T>::value, T>::type safe_abs(T const& v)
|
||||
{
|
||||
return v < 0 ? -v : v;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
void check_trunc_result(T a, U u)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if (fabs(a - u) >= 1)
|
||||
{
|
||||
BOOST_ERROR("Rounded result differed by more than 1 from the original");
|
||||
std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
|
||||
<< std::left << a << u << std::endl;
|
||||
}
|
||||
if (abs(a) < safe_abs(u))
|
||||
{
|
||||
BOOST_ERROR("Truncated result had larger absolute value than the original");
|
||||
std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
|
||||
<< std::left << abs(a) << safe_abs(u) << std::endl;
|
||||
}
|
||||
if (fabs(static_cast<T>(u)) > fabs(a))
|
||||
{
|
||||
BOOST_ERROR("Rounded result was away from zero with boost::trunc");
|
||||
std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
|
||||
<< std::left << a << u << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void test()
|
||||
{
|
||||
if (std::numeric_limits<T>::digits >= std::numeric_limits<long>::digits)
|
||||
{
|
||||
const auto lhs = static_cast<T>((std::numeric_limits<long>::max)());
|
||||
long k = lround(lhs);
|
||||
check_within_half(lhs, k);
|
||||
BOOST_TEST(k == lround(static_cast<T>((std::numeric_limits<long>::max)()) + 0));
|
||||
k = lround(static_cast<T>((std::numeric_limits<long>::min)()));
|
||||
check_within_half(static_cast<T>((std::numeric_limits<long>::min)()), k);
|
||||
BOOST_TEST(k == lround(static_cast<T>((std::numeric_limits<long>::min)()) + 0));
|
||||
k = ltrunc(static_cast<T>((std::numeric_limits<long>::max)()));
|
||||
check_trunc_result(static_cast<T>((std::numeric_limits<long>::max)()), k);
|
||||
BOOST_TEST(k == ltrunc(static_cast<T>((std::numeric_limits<long>::max)()) + 0));
|
||||
k = ltrunc(static_cast<T>((std::numeric_limits<long>::min)()));
|
||||
check_trunc_result(static_cast<T>((std::numeric_limits<long>::min)()), k);
|
||||
BOOST_TEST(k == ltrunc(static_cast<T>((std::numeric_limits<long>::min)()) + 0));
|
||||
|
||||
k = lround(static_cast<T>((std::numeric_limits<long>::max)() - 1));
|
||||
check_within_half(static_cast<T>((std::numeric_limits<long>::max)() - 1), k);
|
||||
k = lround(static_cast<T>((std::numeric_limits<long>::min)() + 1));
|
||||
check_within_half(static_cast<T>((std::numeric_limits<long>::min)() + 1), k);
|
||||
k = ltrunc(static_cast<T>((std::numeric_limits<long>::max)() - 1));
|
||||
check_trunc_result(static_cast<T>((std::numeric_limits<long>::max)() - 1), k);
|
||||
k = ltrunc(static_cast<T>((std::numeric_limits<long>::min)() + 1));
|
||||
check_trunc_result(static_cast<T>((std::numeric_limits<long>::min)() + 1), k);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test<boost::multiprecision::cpp_double_float>();
|
||||
test<boost::multiprecision::cpp_double_double>();
|
||||
BOOST_IF_CONSTEXPR (sizeof(double) != sizeof(long double))
|
||||
{
|
||||
test<boost::multiprecision::cpp_double_long_double>();
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
Reference in New Issue
Block a user