midpoint.float.pass.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. //===----------------------------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
  10. // <numeric>
  11. // template <class _Float>
  12. // _Tp midpoint(_Float __a, _Float __b) noexcept
  13. //
  14. #include <numeric>
  15. #include <cassert>
  16. #include "test_macros.h"
  17. #include "fp_compare.h"
  18. // Totally arbitrary picks for precision
  19. template <typename T>
  20. constexpr T fp_error_pct();
  21. template <>
  22. constexpr float fp_error_pct<float>() { return 1.0e-4f; }
  23. template <>
  24. constexpr double fp_error_pct<double>() { return 1.0e-12; }
  25. template <>
  26. constexpr long double fp_error_pct<long double>() { return 1.0e-13l; }
  27. template <typename T>
  28. void fp_test()
  29. {
  30. ASSERT_SAME_TYPE(T, decltype(std::midpoint(T(), T())));
  31. ASSERT_NOEXCEPT( std::midpoint(T(), T()));
  32. constexpr T maxV = std::numeric_limits<T>::max();
  33. constexpr T minV = std::numeric_limits<T>::min();
  34. // Things that can be compared exactly
  35. static_assert((std::midpoint(T(0), T(0)) == T(0)), "");
  36. static_assert((std::midpoint(T(2), T(4)) == T(3)), "");
  37. static_assert((std::midpoint(T(4), T(2)) == T(3)), "");
  38. static_assert((std::midpoint(T(3), T(4)) == T(3.5)), "");
  39. static_assert((std::midpoint(T(0), T(0.4)) == T(0.2)), "");
  40. // Things that can't be compared exactly
  41. constexpr T pct = fp_error_pct<T>();
  42. assert((fptest_close_pct(std::midpoint(T( 1.3), T(11.4)), T( 6.35), pct)));
  43. assert((fptest_close_pct(std::midpoint(T(11.33), T(31.45)), T(21.39), pct)));
  44. assert((fptest_close_pct(std::midpoint(T(-1.3), T(11.4)), T( 5.05), pct)));
  45. assert((fptest_close_pct(std::midpoint(T(11.4), T(-1.3)), T( 5.05), pct)));
  46. assert((fptest_close_pct(std::midpoint(T(0.1), T(0.4)), T(0.25), pct)));
  47. assert((fptest_close_pct(std::midpoint(T(11.2345), T(14.5432)), T(12.88885), pct)));
  48. // From e to pi
  49. assert((fptest_close_pct(std::midpoint(T(2.71828182845904523536028747135266249775724709369995),
  50. T(3.14159265358979323846264338327950288419716939937510)),
  51. T(2.92993724102441923691146542731608269097720824653752), pct)));
  52. assert((fptest_close_pct(std::midpoint(maxV, T(0)), maxV/2, pct)));
  53. assert((fptest_close_pct(std::midpoint(T(0), maxV), maxV/2, pct)));
  54. assert((fptest_close_pct(std::midpoint(minV, T(0)), minV/2, pct)));
  55. assert((fptest_close_pct(std::midpoint(T(0), minV), minV/2, pct)));
  56. assert((fptest_close_pct(std::midpoint(maxV, maxV), maxV, pct)));
  57. assert((fptest_close_pct(std::midpoint(minV, minV), minV, pct)));
  58. assert((fptest_close_pct(std::midpoint(maxV, minV), maxV/2, pct)));
  59. assert((fptest_close_pct(std::midpoint(minV, maxV), maxV/2, pct)));
  60. // Near the min and the max
  61. assert((fptest_close_pct(std::midpoint(maxV*T(0.75), maxV*T(0.50)), maxV*T(0.625), pct)));
  62. assert((fptest_close_pct(std::midpoint(maxV*T(0.50), maxV*T(0.75)), maxV*T(0.625), pct)));
  63. assert((fptest_close_pct(std::midpoint(minV*T(2), minV*T(8)), minV*T(5), pct)));
  64. // Big numbers of different signs
  65. assert((fptest_close_pct(std::midpoint(maxV*T( 0.75), maxV*T(-0.5)), maxV*T( 0.125), pct)));
  66. assert((fptest_close_pct(std::midpoint(maxV*T(-0.75), maxV*T( 0.5)), maxV*T(-0.125), pct)));
  67. // Denormalized values
  68. // TODO
  69. // Check two values "close to each other"
  70. T d1 = T(3.14);
  71. T d0 = std::nextafter(d1, T(2));
  72. T d2 = std::nextafter(d1, T(5));
  73. assert(d0 < d1); // sanity checking
  74. assert(d1 < d2); // sanity checking
  75. #if defined(__PPC__) && __LONG_DOUBLE_128__ && !__LONG_DOUBLE_IEEE128__
  76. // For 128 bit long double implemented as 2 doubles on PowerPC,
  77. // nextafterl() of libm gives imprecise results which fails the
  78. // midpoint() tests below. So skip the test for this case.
  79. if constexpr (sizeof(T) != 16)
  80. #endif
  81. {
  82. // Since there's nothing in between, the midpoint has to be one or the other
  83. T res;
  84. res = std::midpoint(d0, d1);
  85. assert(res == d0 || res == d1);
  86. assert(d0 <= res);
  87. assert(res <= d1);
  88. res = std::midpoint(d1, d0);
  89. assert(res == d0 || res == d1);
  90. assert(d0 <= res);
  91. assert(res <= d1);
  92. res = std::midpoint(d1, d2);
  93. assert(res == d1 || res == d2);
  94. assert(d1 <= res);
  95. assert(res <= d2);
  96. res = std::midpoint(d2, d1);
  97. assert(res == d1 || res == d2);
  98. assert(d1 <= res);
  99. assert(res <= d2);
  100. }
  101. }
  102. int main (int, char**)
  103. {
  104. fp_test<float>();
  105. fp_test<double>();
  106. fp_test<long double>();
  107. return 0;
  108. }