diff options
Diffstat (limited to 'include/numeric')
-rw-r--r-- | include/numeric | 84 |
1 files changed, 73 insertions, 11 deletions
diff --git a/include/numeric b/include/numeric index 4e68239d059e3..2118704d57f31 100644 --- a/include/numeric +++ b/include/numeric @@ -1,10 +1,9 @@ // -*- C++ -*- //===---------------------------- numeric ---------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -134,6 +133,10 @@ template <class M, class N> template <class M, class N> 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 */ @@ -142,6 +145,7 @@ template <class M, class N> #include <iterator> #include <limits> // for numeric_limits #include <functional> +#include <cmath> // for isnormal #include <version> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -456,10 +460,10 @@ iota(_ForwardIterator __first, _ForwardIterator __last, _Tp __value_) #if _LIBCPP_STD_VER > 14 -template <typename _Result, typename _Source, bool _IsSigned = is_signed<_Source>::value> struct __abs; +template <typename _Result, typename _Source, bool _IsSigned = is_signed<_Source>::value> struct __ct_abs; template <typename _Result, typename _Source> -struct __abs<_Result, _Source, true> { +struct __ct_abs<_Result, _Source, true> { _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY _Result operator()(_Source __t) const noexcept { @@ -470,7 +474,7 @@ struct __abs<_Result, _Source, true> { }; template <typename _Result, typename _Source> -struct __abs<_Result, _Source, false> { +struct __ct_abs<_Result, _Source, false> { _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY _Result operator()(_Source __t) const noexcept { return __t; } }; @@ -496,8 +500,8 @@ gcd(_Tp __m, _Up __n) using _Rp = common_type_t<_Tp,_Up>; using _Wp = make_unsigned_t<_Rp>; return static_cast<_Rp>(_VSTD::__gcd( - static_cast<_Wp>(__abs<_Rp, _Tp>()(__m)), - static_cast<_Wp>(__abs<_Rp, _Up>()(__n)))); + static_cast<_Wp>(__ct_abs<_Rp, _Tp>()(__m)), + static_cast<_Wp>(__ct_abs<_Rp, _Up>()(__n)))); } template<class _Tp, class _Up> @@ -512,14 +516,72 @@ lcm(_Tp __m, _Up __n) return 0; using _Rp = common_type_t<_Tp,_Up>; - _Rp __val1 = __abs<_Rp, _Tp>()(__m) / _VSTD::gcd(__m, __n); - _Rp __val2 = __abs<_Rp, _Up>()(__n); + _Rp __val1 = __ct_abs<_Rp, _Tp>()(__m) / _VSTD::gcd(__m, __n); + _Rp __val2 = __ct_abs<_Rp, _Up>()(__n); _LIBCPP_ASSERT((numeric_limits<_Rp>::max() / __val1 > __val2), "Overflow in lcm"); return __val1 * __val2; } #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> && !is_null_pointer_v<_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> + && is_object_v<remove_pointer_t<_TPtr>> + && ! is_void_v<remove_pointer_t<_TPtr>> + && (sizeof(remove_pointer_t<_TPtr>) > 0), _TPtr> +midpoint(_TPtr __a, _TPtr __b) noexcept +{ + return __a + _VSTD::midpoint(ptrdiff_t(0), __b - __a); +} + + +template <typename _Tp> +constexpr int __sign(_Tp __val) { + return (_Tp(0) < __val) - (__val < _Tp(0)); +} + +template <typename _Fp> +constexpr _Fp __fp_abs(_Fp __f) { return __f >= 0 ? __f : -__f; } + +template <class _Fp> +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t<is_floating_point_v<_Fp>, _Fp> +midpoint(_Fp __a, _Fp __b) noexcept +{ + constexpr _Fp __lo = numeric_limits<_Fp>::min()*2; + constexpr _Fp __hi = numeric_limits<_Fp>::max()/2; + return __fp_abs(__a) <= __hi && __fp_abs(__b) <= __hi ? // typical case: overflow is impossible + (__a + __b)/2 : // always correctly rounded + __fp_abs(__a) < __lo ? __a + __b/2 : // not safe to halve a + __fp_abs(__a) < __lo ? __a/2 + __b : // not safe to halve b + __a/2 + __b/2; // otherwise correctly rounded +} + +#endif // _LIBCPP_STD_VER > 17 + _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS |