Files
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

164 lines
4.9 KiB
C++

//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// REQUIRES: std-at-least-c++20
// <numeric>
// template<class T>
// constexpr T midpoint(T a, T b) noexcept;
#include <cassert>
#include <cmath>
#include <concepts>
#include <limits>
#include <numeric>
#include "test_macros.h"
#include "fp_compare.h"
template <typename T>
constexpr bool is_nan(T x) {
return x != x;
}
template <typename T>
constexpr T get_error_pct() {
if constexpr (std::same_as<T, float>)
return 1.0e-4f;
else if constexpr (std::same_as<T, double>)
return 1.0e-12;
else
return 1.0e-13l;
}
template <typename T>
constexpr bool check_near(T a, T b, T expect) {
if (std::is_constant_evaluated())
return true;
return fptest_close_pct(std::midpoint(a, b), expect, get_error_pct<T>());
}
template <typename T>
constexpr bool check_exact(T a, T b, T expect) {
T res = std::midpoint(a, b);
if (is_nan(expect))
return is_nan(res);
return res == expect;
}
template <std::floating_point T>
constexpr bool test_ppc_edge_cases() {
if (std::is_constant_evaluated())
return true;
// For 128 bit long double implemented as 2 doubles on PowerPC,
// nextafterl() of libm gives imprecise results which fails the
// midpoint() tests below. So skip the test for this case.
#if defined(__PPC__) && (defined(__LONG_DOUBLE_128__) && __LONG_DOUBLE_128__) && \
!(defined(__LONG_DOUBLE_IEEE128__) && __LONG_DOUBLE_IEEE128__)
if constexpr (sizeof(T) == 16)
return true;
#endif
T d1 = 3.14;
T d0 = std::nextafter(d1, T{2});
T d2 = std::nextafter(d1, T{5});
auto verify = [](T res, T low, T high) { return (res == low || res == high) && (low <= res && res <= high); };
return verify(std::midpoint(d0, d1), d0, d1) && verify(std::midpoint(d1, d2), d1, d2);
}
template <typename T>
constexpr bool test_floating_points() {
ASSERT_SAME_TYPE(T, decltype(std::midpoint(T{}, T{})));
ASSERT_NOEXCEPT(std::midpoint(T{}, T{}));
constexpr T max_v = std::numeric_limits<T>::max();
constexpr T min_v = std::numeric_limits<T>::min();
constexpr T denorm_min = std::numeric_limits<T>::denorm_min();
constexpr T inf = std::numeric_limits<T>::infinity();
constexpr T qnan = std::numeric_limits<T>::quiet_NaN();
// Things that can be compared exactly
assert(check_exact<T>(0, 0, 0));
assert(check_exact<T>(2, 4, 3));
assert(check_exact<T>(4, 2, 3));
assert(check_exact<T>(3, 4, 3.5));
assert(check_exact<T>(0, 0.4, 0.2));
assert(check_exact<T>(-2, -4, -3));
assert(check_exact<T>(-2, 2, 0));
assert(check_exact<T>(2, -2, 0));
// Infinity
assert(check_exact<T>(inf, inf, inf));
assert(check_exact<T>(-inf, -inf, -inf));
if (!std::is_constant_evaluated()) {
assert(check_exact<T>(inf, -inf, qnan));
}
assert(check_exact<T>(inf, 0, inf));
// NaN
if (!std::is_constant_evaluated()) {
assert(check_exact<T>(qnan, 0, qnan));
assert(check_exact<T>(qnan, qnan, qnan));
}
// Subnormal
assert(check_exact<T>(denorm_min, 0, 0));
assert(check_exact<T>(denorm_min, denorm_min, denorm_min));
// Things that can't be compared exactly
assert(check_near<T>(1.3, 11.4, 6.35));
assert(check_near<T>(11.33, 31.45, 21.39));
assert(check_near<T>(-1.3, 11.4, 5.05));
assert(check_near<T>(11.4, -1.3, 5.05));
assert(check_near<T>(11.2345, 14.5432, 12.88885));
assert(check_near<T>(2.71828182845904523536028747135266249775724709369995,
3.14159265358979323846264338327950288419716939937510,
2.92993724102441923691146542731608269097720824653752));
assert(check_near<T>(max_v, 0, max_v / 2));
assert(check_near<T>(0, max_v, max_v / 2));
assert(check_near<T>(min_v, 0, min_v / 2));
assert(check_near<T>(0, min_v, min_v / 2));
assert(check_near<T>(max_v, max_v, max_v));
assert(check_near<T>(min_v, min_v, min_v));
assert(check_near<T>(max_v, min_v, max_v / 2));
assert(check_near<T>(min_v, max_v, max_v / 2));
// Near the min and the max
assert(check_near<T>(max_v * 0.75, max_v * 0.50, max_v * 0.625));
assert(check_near<T>(max_v * 0.50, max_v * 0.75, max_v * 0.625));
assert(check_near<T>(min_v * 2, min_v * 8, min_v * 5));
// Big numbers of different signs
assert(check_near<T>(max_v * 0.75, max_v * -0.50, max_v * 0.125));
assert(check_near<T>(max_v * -0.75, max_v * 0.50, max_v * -0.125));
assert(test_ppc_edge_cases<T>());
return true;
}
constexpr bool test() {
test_floating_points<float>();
test_floating_points<double>();
test_floating_points<long double>();
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}