summaryrefslogtreecommitdiff
path: root/include/numeric
diff options
context:
space:
mode:
Diffstat (limited to 'include/numeric')
-rw-r--r--include/numeric84
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