forked from OSchip/llvm-project
Add std::midpoint for integral and poiner types. Described in P0811, reviewed as D59099.
llvm-svn: 356162
This commit is contained in:
parent
4962816e72
commit
330ab33f7c
|
@ -133,6 +133,10 @@ template <class M, class N>
|
||||||
template <class M, class N>
|
template <class M, class N>
|
||||||
constexpr common_type_t<M,N> lcm(M m, N n); // C++17
|
constexpr common_type_t<M,N> lcm(M m, N n); // C++17
|
||||||
|
|
||||||
|
integer midpoint(integer a, integer b); // C++20
|
||||||
|
pointer midpoint(pointer a, pointer b); // C++20
|
||||||
|
floating_point midpoint(floating_point a, floating_point b); // C++20
|
||||||
|
|
||||||
} // std
|
} // std
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
@ -519,6 +523,37 @@ lcm(_Tp __m, _Up __n)
|
||||||
|
|
||||||
#endif /* _LIBCPP_STD_VER > 14 */
|
#endif /* _LIBCPP_STD_VER > 14 */
|
||||||
|
|
||||||
|
#if _LIBCPP_STD_VER > 17
|
||||||
|
template <class _Tp>
|
||||||
|
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||||
|
enable_if_t<is_integral_v<_Tp> && !is_same_v<bool, _Tp>, _Tp>
|
||||||
|
midpoint(_Tp __a, _Tp __b) noexcept
|
||||||
|
_LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
|
||||||
|
{
|
||||||
|
using _Up = std::make_unsigned_t<_Tp>;
|
||||||
|
|
||||||
|
int __sign = 1;
|
||||||
|
_Up __m = __a;
|
||||||
|
_Up __M = __b;
|
||||||
|
if (__a > __b)
|
||||||
|
{
|
||||||
|
__sign = -1;
|
||||||
|
__m = __b;
|
||||||
|
__M = __a;
|
||||||
|
}
|
||||||
|
return __a + __sign * _Tp(_Up(__M-__m) >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class _TPtr>
|
||||||
|
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||||
|
enable_if_t<is_pointer_v<_TPtr>, _TPtr>
|
||||||
|
midpoint(_TPtr __a, _TPtr __b) noexcept
|
||||||
|
{
|
||||||
|
return __a + _VSTD::midpoint(ptrdiff_t(0), __b - __a);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
_LIBCPP_END_NAMESPACE_STD
|
_LIBCPP_END_NAMESPACE_STD
|
||||||
|
|
||||||
_LIBCPP_POP_MACROS
|
_LIBCPP_POP_MACROS
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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 _Tp>
|
||||||
|
// _Tp midpoint(_Tp __a, _Tp __b) noexcept
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <numeric>
|
||||||
|
#include <cassert>
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
// Users are not supposed to provide template argument lists for
|
||||||
|
// functions in the standard library (there's an exception for min and max)
|
||||||
|
// However, libc++ protects against this for pointers, so we check to make
|
||||||
|
// sure that our protection is working here.
|
||||||
|
// In some cases midpoint<int>(0,0) might get deduced as the pointer overload.
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void test()
|
||||||
|
{
|
||||||
|
ASSERT_SAME_TYPE(T, decltype(std::midpoint<T>(0, 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**)
|
||||||
|
{
|
||||||
|
test<signed char>();
|
||||||
|
test<short>();
|
||||||
|
test<int>();
|
||||||
|
test<long>();
|
||||||
|
test<long long>();
|
||||||
|
|
||||||
|
test<int8_t>();
|
||||||
|
test<int16_t>();
|
||||||
|
test<int32_t>();
|
||||||
|
test<int64_t>();
|
||||||
|
test<__int128_t>();
|
||||||
|
|
||||||
|
test<unsigned char>();
|
||||||
|
test<unsigned short>();
|
||||||
|
test<unsigned int>();
|
||||||
|
test<unsigned long>();
|
||||||
|
test<unsigned long long>();
|
||||||
|
|
||||||
|
test<uint8_t>();
|
||||||
|
test<uint16_t>();
|
||||||
|
test<uint32_t>();
|
||||||
|
test<uint64_t>();
|
||||||
|
test<__uint128_t>();
|
||||||
|
|
||||||
|
test<char>();
|
||||||
|
test<ptrdiff_t>();
|
||||||
|
test<size_t>();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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 _Tp>
|
||||||
|
// _Tp midpoint(_Tp __a, _Tp __b) noexcept
|
||||||
|
|
||||||
|
// An overload exists for each of char and all arithmetic types except bool.
|
||||||
|
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
int main(int, char**)
|
||||||
|
{
|
||||||
|
(void) std::midpoint(false, true); // expected-error {{no matching function for call to 'midpoint'}}
|
||||||
|
|
||||||
|
// A couple of odd pointer types that should fail
|
||||||
|
(void) std::midpoint(nullptr, nullptr); // expected-error {{no matching function for call to 'midpoint'}}
|
||||||
|
(void) std::midpoint((void *)0, (void *)0); // expected-error@numeric:* {{arithmetic on pointers to void}}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,137 @@
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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 _Tp>
|
||||||
|
// _Tp midpoint(_Tp __a, _Tp __b) noexcept
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <numeric>
|
||||||
|
#include <cassert>
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void signed_test()
|
||||||
|
{
|
||||||
|
constexpr T zero{0};
|
||||||
|
constexpr T one{1};
|
||||||
|
constexpr T two{2};
|
||||||
|
constexpr T three{3};
|
||||||
|
constexpr T four{4};
|
||||||
|
|
||||||
|
ASSERT_SAME_TYPE(decltype(std::midpoint(T(), T())), T);
|
||||||
|
ASSERT_NOEXCEPT( std::midpoint(T(), T()));
|
||||||
|
using limits = std::numeric_limits<T>;
|
||||||
|
|
||||||
|
static_assert(std::midpoint(one, three) == two, "");
|
||||||
|
static_assert(std::midpoint(three, one) == two, "");
|
||||||
|
|
||||||
|
assert(std::midpoint(zero, zero) == zero);
|
||||||
|
assert(std::midpoint(zero, two) == one);
|
||||||
|
assert(std::midpoint(two, zero) == one);
|
||||||
|
assert(std::midpoint(two, two) == two);
|
||||||
|
|
||||||
|
assert(std::midpoint(one, four) == two);
|
||||||
|
assert(std::midpoint(four, one) == three);
|
||||||
|
assert(std::midpoint(three, four) == three);
|
||||||
|
assert(std::midpoint(four, three) == four);
|
||||||
|
|
||||||
|
assert(std::midpoint(T( 3), T( 4)) == T(3));
|
||||||
|
assert(std::midpoint(T( 4), T( 3)) == T(4));
|
||||||
|
assert(std::midpoint(T(-3), T( 4)) == T(0));
|
||||||
|
assert(std::midpoint(T(-4), T( 3)) == T(-1));
|
||||||
|
assert(std::midpoint(T( 3), T(-4)) == T(0));
|
||||||
|
assert(std::midpoint(T( 4), T(-3)) == T(1));
|
||||||
|
assert(std::midpoint(T(-3), T(-4)) == T(-3));
|
||||||
|
assert(std::midpoint(T(-4), T(-3)) == T(-4));
|
||||||
|
|
||||||
|
static_assert(std::midpoint(limits::min(), limits::max()) == T(-1), "");
|
||||||
|
static_assert(std::midpoint(limits::max(), limits::min()) == T( 0), "");
|
||||||
|
|
||||||
|
static_assert(std::midpoint(limits::min(), T(6)) == limits::min()/2 + 3, "");
|
||||||
|
assert( std::midpoint(T(6), limits::min()) == limits::min()/2 + 3);
|
||||||
|
assert( std::midpoint(limits::max(), T(6)) == limits::max()/2 + 4);
|
||||||
|
static_assert(std::midpoint(T(6), limits::max()) == limits::max()/2 + 3, "");
|
||||||
|
|
||||||
|
assert( std::midpoint(limits::min(), T(-6)) == limits::min()/2 - 3);
|
||||||
|
static_assert(std::midpoint(T(-6), limits::min()) == limits::min()/2 - 3, "");
|
||||||
|
static_assert(std::midpoint(limits::max(), T(-6)) == limits::max()/2 - 2, "");
|
||||||
|
assert( std::midpoint(T(-6), limits::max()) == limits::max()/2 - 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void unsigned_test()
|
||||||
|
{
|
||||||
|
constexpr T zero{0};
|
||||||
|
constexpr T one{1};
|
||||||
|
constexpr T two{2};
|
||||||
|
constexpr T three{3};
|
||||||
|
constexpr T four{4};
|
||||||
|
|
||||||
|
ASSERT_SAME_TYPE(decltype(std::midpoint(T(), T())), T);
|
||||||
|
ASSERT_NOEXCEPT( std::midpoint(T(), T()));
|
||||||
|
using limits = std::numeric_limits<T>;
|
||||||
|
const T half_way = (limits::max() - limits::min())/2;
|
||||||
|
|
||||||
|
static_assert(std::midpoint(one, three) == two, "");
|
||||||
|
static_assert(std::midpoint(three, one) == two, "");
|
||||||
|
|
||||||
|
assert(std::midpoint(zero, zero) == zero);
|
||||||
|
assert(std::midpoint(zero, two) == one);
|
||||||
|
assert(std::midpoint(two, zero) == one);
|
||||||
|
assert(std::midpoint(two, two) == two);
|
||||||
|
|
||||||
|
assert(std::midpoint(one, four) == two);
|
||||||
|
assert(std::midpoint(four, one) == three);
|
||||||
|
assert(std::midpoint(three, four) == three);
|
||||||
|
assert(std::midpoint(four, three) == four);
|
||||||
|
|
||||||
|
assert(std::midpoint(limits::min(), limits::max()) == T(half_way));
|
||||||
|
assert(std::midpoint(limits::max(), limits::min()) == T(half_way + 1));
|
||||||
|
|
||||||
|
static_assert(std::midpoint(limits::min(), T(6)) == limits::min()/2 + 3, "");
|
||||||
|
assert( std::midpoint(T(6), limits::min()) == limits::min()/2 + 3);
|
||||||
|
assert( std::midpoint(limits::max(), T(6)) == half_way + 4);
|
||||||
|
static_assert(std::midpoint(T(6), limits::max()) == half_way + 3, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int, char**)
|
||||||
|
{
|
||||||
|
signed_test<signed char>();
|
||||||
|
signed_test<short>();
|
||||||
|
signed_test<int>();
|
||||||
|
signed_test<long>();
|
||||||
|
signed_test<long long>();
|
||||||
|
|
||||||
|
signed_test<int8_t>();
|
||||||
|
signed_test<int16_t>();
|
||||||
|
signed_test<int32_t>();
|
||||||
|
signed_test<int64_t>();
|
||||||
|
signed_test<__int128_t>();
|
||||||
|
|
||||||
|
unsigned_test<unsigned char>();
|
||||||
|
unsigned_test<unsigned short>();
|
||||||
|
unsigned_test<unsigned int>();
|
||||||
|
unsigned_test<unsigned long>();
|
||||||
|
unsigned_test<unsigned long long>();
|
||||||
|
|
||||||
|
unsigned_test<uint8_t>();
|
||||||
|
unsigned_test<uint16_t>();
|
||||||
|
unsigned_test<uint32_t>();
|
||||||
|
unsigned_test<uint64_t>();
|
||||||
|
unsigned_test<__uint128_t>();
|
||||||
|
|
||||||
|
// int_test<char>();
|
||||||
|
signed_test<ptrdiff_t>();
|
||||||
|
unsigned_test<size_t>();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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 _Tp>
|
||||||
|
// _Tp* midpoint(_Tp* __a, _Tp* __b) noexcept
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <numeric>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void pointer_test()
|
||||||
|
{
|
||||||
|
T array[1000] = {}; // we need an array to make valid pointers
|
||||||
|
constexpr T cArray[2] = {};
|
||||||
|
ASSERT_SAME_TYPE(decltype(std::midpoint(array, array)), T*);
|
||||||
|
ASSERT_NOEXCEPT( std::midpoint(array, array));
|
||||||
|
|
||||||
|
static_assert(std::midpoint(cArray, cArray + 2) == cArray + 1, "");
|
||||||
|
static_assert(std::midpoint(cArray + 2, cArray) == cArray + 1, "");
|
||||||
|
|
||||||
|
assert(std::midpoint(array, array) == array);
|
||||||
|
assert(std::midpoint(array, array + 1000) == array + 500);
|
||||||
|
|
||||||
|
assert(std::midpoint(array, array + 9) == array + 4);
|
||||||
|
assert(std::midpoint(array, array + 10) == array + 5);
|
||||||
|
assert(std::midpoint(array, array + 11) == array + 5);
|
||||||
|
assert(std::midpoint(array + 9, array) == array + 5);
|
||||||
|
assert(std::midpoint(array + 10, array) == array + 5);
|
||||||
|
assert(std::midpoint(array + 11, array) == array + 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int, char**)
|
||||||
|
{
|
||||||
|
pointer_test< char>();
|
||||||
|
pointer_test<const char>();
|
||||||
|
pointer_test< volatile char>();
|
||||||
|
pointer_test<const volatile char>();
|
||||||
|
|
||||||
|
pointer_test<int>();
|
||||||
|
pointer_test<double>();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue