diff options
author | Marshall Clow <mclow.lists@gmail.com> | 2019-04-25 12:11:43 +0000 |
---|---|---|
committer | Marshall Clow <mclow.lists@gmail.com> | 2019-04-25 12:11:43 +0000 |
commit | d3d0ecbfd52cca2c7e0f4478e5682c493fd99ef2 (patch) | |
tree | fbac170739e7b24bba17e84dfa2fe7d4cb2e9841 /libcxx/test/std/numerics/numeric.ops/numeric.ops.midpoint/midpoint.float.pass.cpp | |
parent | 31aa2ea3a3f9669e5783654117804f055f787f7a (diff) | |
download | bcm5719-llvm-d3d0ecbfd52cca2c7e0f4478e5682c493fd99ef2.tar.gz bcm5719-llvm-d3d0ecbfd52cca2c7e0f4478e5682c493fd99ef2.zip |
Implement midpoint for floating point types. Reviewed as https://reviews.llvm.org/D61014.
llvm-svn: 359184
Diffstat (limited to 'libcxx/test/std/numerics/numeric.ops/numeric.ops.midpoint/midpoint.float.pass.cpp')
-rw-r--r-- | libcxx/test/std/numerics/numeric.ops/numeric.ops.midpoint/midpoint.float.pass.cpp | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.midpoint/midpoint.float.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.midpoint/midpoint.float.pass.cpp new file mode 100644 index 00000000000..4abb2325d33 --- /dev/null +++ b/libcxx/test/std/numerics/numeric.ops/numeric.ops.midpoint/midpoint.float.pass.cpp @@ -0,0 +1,113 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 +// <numeric> + +// template <class _Float> +// _Tp midpoint(_Float __a, _Float __b) noexcept +// + +#include <numeric> +#include <cassert> + +#include "test_macros.h" +#include "fp_compare.h" + +// Totally arbitrary picks for precision +template <typename T> +constexpr T fp_error_pct(); + +template <> +constexpr float fp_error_pct<float>() { return 1.0e-4f; } + +template <> +constexpr double fp_error_pct<double>() { return 1.0e-12; } + +template <> +constexpr long double fp_error_pct<long double>() { return 1.0e-13l; } + + +template <typename T> +void fp_test() +{ + ASSERT_SAME_TYPE(T, decltype(std::midpoint(T(), T()))); + ASSERT_NOEXCEPT( std::midpoint(T(), T())); + + constexpr T maxV = std::numeric_limits<T>::max(); + constexpr T minV = std::numeric_limits<T>::min(); + +// Things that can be compared exactly + assert((std::midpoint(T(0), T(0)) == T(0))); + assert((std::midpoint(T(2), T(4)) == T(3))); + assert((std::midpoint(T(4), T(2)) == T(3))); + assert((std::midpoint(T(3), T(4)) == T(3.5))); + assert((std::midpoint(T(0), T(0.4)) == T(0.2))); + +// Things that can't be compared exactly + constexpr T pct = fp_error_pct<T>(); + assert((fptest_close_pct(std::midpoint(T( 1.3), T(11.4)), T( 6.35), pct))); + assert((fptest_close_pct(std::midpoint(T(11.33), T(31.45)), T(21.39), pct))); + assert((fptest_close_pct(std::midpoint(T(-1.3), T(11.4)), T( 5.05), pct))); + assert((fptest_close_pct(std::midpoint(T(11.4), T(-1.3)), T( 5.05), pct))); + assert((fptest_close_pct(std::midpoint(T(0.1), T(0.4)), T(0.25), pct))); + + assert((fptest_close_pct(std::midpoint(T(11.2345), T(14.5432)), T(12.88885), pct))); + +// From e to pi + assert((fptest_close_pct(std::midpoint(T(2.71828182845904523536028747135266249775724709369995), + T(3.14159265358979323846264338327950288419716939937510)), + T(2.92993724102441923691146542731608269097720824653752), pct))); + + assert((fptest_close_pct(std::midpoint(maxV, T(0)), maxV/2, pct))); + assert((fptest_close_pct(std::midpoint(T(0), maxV), maxV/2, pct))); + assert((fptest_close_pct(std::midpoint(minV, T(0)), minV/2, pct))); + assert((fptest_close_pct(std::midpoint(T(0), minV), minV/2, pct))); + assert((fptest_close_pct(std::midpoint(maxV, maxV), maxV, pct))); + assert((fptest_close_pct(std::midpoint(minV, minV), minV, pct))); + +// Denormalized values +// TODO + +// Check two values "close to each other" + T d1 = 3.14; + T d0 = std::nexttoward(d1, T(2)); + T d2 = std::nexttoward(d1, T(5)); + assert(d0 < d1); // sanity checking + assert(d1 < d2); // sanity checking + +// Since there's nothing in between, the midpoint has to be one or the other + T res; + res = std::midpoint(d0, d1); + assert(res == d0 || res == d1); + assert(d0 <= res); + assert(res <= d1); + res = std::midpoint(d1, d0); + assert(res == d0 || res == d1); + assert(d0 <= res); + assert(res <= d1); + + res = std::midpoint(d1, d2); + assert(res == d1 || res == d2); + assert(d1 <= res); + assert(res <= d2); + res = std::midpoint(d2, d1); + assert(res == d1 || res == d2); + assert(d1 <= res); + assert(res <= d2); +} + + +int main (int, char**) +{ + fp_test<float>(); + fp_test<double>(); + fp_test<long double>(); + + return 0; +} |