Home | History | Annotate | Line # | Download | only in include
      1 // -*- C++ -*-
      2 //===---------------------------- numeric ---------------------------------===//
      3 //
      4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      5 // See https://llvm.org/LICENSE.txt for license information.
      6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #ifndef _LIBCPP_NUMERIC
     11 #define _LIBCPP_NUMERIC
     12 
     13 /*
     14     numeric synopsis
     15 
     16 namespace std
     17 {
     18 
     19 template <class InputIterator, class T>
     20     constexpr T  // constexpr since C++20
     21     accumulate(InputIterator first, InputIterator last, T init);
     22 
     23 template <class InputIterator, class T, class BinaryOperation>
     24     constexpr T  // constexpr since C++20
     25     accumulate(InputIterator first, InputIterator last, T init, BinaryOperation binary_op);
     26 
     27 template<class InputIterator>
     28     constexpr typename iterator_traits<InputIterator>::value_type  // constexpr since C++20
     29     reduce(InputIterator first, InputIterator last);  // C++17
     30 
     31 template<class InputIterator, class T>
     32     constexpr T  // constexpr since C++20
     33     reduce(InputIterator first, InputIterator last, T init);  // C++17
     34 
     35 template<class InputIterator, class T, class BinaryOperation>
     36     constexpr T  // constexpr since C++20
     37     reduce(InputIterator first, InputIterator last, T init, BinaryOperation binary_op);  // C++17
     38 
     39 template <class InputIterator1, class InputIterator2, class T>
     40     constexpr T  // constexpr since C++20
     41     inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init);
     42 
     43 template <class InputIterator1, class InputIterator2, class T, class BinaryOperation1, class BinaryOperation2>
     44     constexpr T  // constexpr since C++20
     45     inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2,
     46                   T init, BinaryOperation1 binary_op1, BinaryOperation2 binary_op2);
     47 
     48 
     49 template<class InputIterator1, class InputIterator2, class T>
     50     constexpr T  // constexpr since C++20
     51     transform_reduce(InputIterator1 first1, InputIterator1 last1,
     52                      InputIterator2 first2, T init);  // C++17
     53 
     54 template<class InputIterator1, class InputIterator2, class T, class BinaryOperation1, class BinaryOperation2>
     55     constexpr T  // constexpr since C++20
     56     transform_reduce(InputIterator1 first1, InputIterator1 last1,
     57                      InputIterator2 first2, T init,
     58                      BinaryOperation1 binary_op1, BinaryOperation2 binary_op2);  // C++17
     59 
     60 template<class InputIterator, class T, class BinaryOperation, class UnaryOperation>
     61     constexpr T  // constexpr since C++20
     62     transform_reduce(InputIterator first, InputIterator last, T init,
     63                      BinaryOperation binary_op, UnaryOperation unary_op);  // C++17
     64 
     65 template <class InputIterator, class OutputIterator>
     66     constexpr OutputIterator  // constexpr since C++20
     67     partial_sum(InputIterator first, InputIterator last, OutputIterator result);
     68 
     69 template <class InputIterator, class OutputIterator, class BinaryOperation>
     70     constexpr OutputIterator  // constexpr since C++20
     71     partial_sum(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op);
     72 
     73 template<class InputIterator, class OutputIterator, class T>
     74     constexpr OutputIterator  // constexpr since C++20
     75     exclusive_scan(InputIterator first, InputIterator last,
     76                    OutputIterator result, T init); // C++17
     77 
     78 template<class InputIterator, class OutputIterator, class T, class BinaryOperation>
     79     constexpr OutputIterator  // constexpr since C++20
     80     exclusive_scan(InputIterator first, InputIterator last,
     81                    OutputIterator result, T init, BinaryOperation binary_op); // C++17
     82 
     83 template<class InputIterator, class OutputIterator>
     84     constexpr OutputIterator  // constexpr since C++20
     85     inclusive_scan(InputIterator first, InputIterator last, OutputIterator result);  // C++17
     86 
     87 template<class InputIterator, class OutputIterator, class BinaryOperation>
     88     constexpr OutputIterator  // constexpr since C++20
     89     inclusive_scan(InputIterator first, InputIterator last,
     90                    OutputIterator result, BinaryOperation binary_op);  // C++17
     91 
     92 template<class InputIterator, class OutputIterator, class BinaryOperation, class T>
     93     constexpr OutputIterator  // constexpr since C++20
     94     inclusive_scan(InputIterator first, InputIterator last,
     95                    OutputIterator result, BinaryOperation binary_op, T init);  // C++17
     96 
     97 template<class InputIterator, class OutputIterator, class T,
     98          class BinaryOperation, class UnaryOperation>
     99     constexpr OutputIterator  // constexpr since C++20
    100     transform_exclusive_scan(InputIterator first, InputIterator last,
    101                              OutputIterator result, T init,
    102                              BinaryOperation binary_op, UnaryOperation unary_op);  // C++17
    103 
    104 template<class InputIterator, class OutputIterator,
    105          class BinaryOperation, class UnaryOperation>
    106     constexpr OutputIterator  // constexpr since C++20
    107     transform_inclusive_scan(InputIterator first, InputIterator last,
    108                              OutputIterator result,
    109                              BinaryOperation binary_op, UnaryOperation unary_op);  // C++17
    110 
    111 template<class InputIterator, class OutputIterator,
    112          class BinaryOperation, class UnaryOperation, class T>
    113     constexpr OutputIterator  // constexpr since C++20
    114     transform_inclusive_scan(InputIterator first, InputIterator last,
    115                              OutputIterator result,
    116                              BinaryOperation binary_op, UnaryOperation unary_op,
    117                              T init);  // C++17
    118 
    119 template <class InputIterator, class OutputIterator>
    120     constexpr OutputIterator  // constexpr since C++20
    121     adjacent_difference(InputIterator first, InputIterator last, OutputIterator result);
    122 
    123 template <class InputIterator, class OutputIterator, class BinaryOperation>
    124     constexpr OutputIterator  // constexpr since C++20
    125     adjacent_difference(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op);
    126 
    127 template <class ForwardIterator, class T>
    128     constexpr void  // constexpr since C++20
    129     iota(ForwardIterator first, ForwardIterator last, T value);
    130 
    131 template <class M, class N>
    132     constexpr common_type_t<M,N> gcd(M m, N n);    // C++17
    133 
    134 template <class M, class N>
    135     constexpr common_type_t<M,N> lcm(M m, N n);    // C++17
    136 
    137 template<class T>
    138     constexpr T midpoint(T a, T b) noexcept;  // C++20
    139 
    140 template<class T>
    141     constexpr T* midpoint(T* a, T* b);        // C++20
    142 
    143 }  // std
    144 
    145 */
    146 
    147 #include <__config>
    148 #include <__debug>
    149 #include <cmath> // for isnormal
    150 #include <functional>
    151 #include <iterator>
    152 #include <limits> // for numeric_limits
    153 #include <version>
    154 
    155 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
    156 #pragma GCC system_header
    157 #endif
    158 
    159 _LIBCPP_PUSH_MACROS
    160 #include <__undef_macros>
    161 
    162 _LIBCPP_BEGIN_NAMESPACE_STD
    163 
    164 template <class _InputIterator, class _Tp>
    165 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    166 _Tp
    167 accumulate(_InputIterator __first, _InputIterator __last, _Tp __init)
    168 {
    169     for (; __first != __last; ++__first)
    170 #if _LIBCPP_STD_VER > 17
    171         __init = _VSTD::move(__init) + *__first;
    172 #else
    173         __init = __init + *__first;
    174 #endif
    175     return __init;
    176 }
    177 
    178 template <class _InputIterator, class _Tp, class _BinaryOperation>
    179 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    180 _Tp
    181 accumulate(_InputIterator __first, _InputIterator __last, _Tp __init, _BinaryOperation __binary_op)
    182 {
    183     for (; __first != __last; ++__first)
    184 #if _LIBCPP_STD_VER > 17
    185         __init = __binary_op(_VSTD::move(__init), *__first);
    186 #else
    187         __init = __binary_op(__init, *__first);
    188 #endif
    189     return __init;
    190 }
    191 
    192 #if _LIBCPP_STD_VER > 14
    193 template <class _InputIterator, class _Tp, class _BinaryOp>
    194 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    195 _Tp
    196 reduce(_InputIterator __first, _InputIterator __last, _Tp __init, _BinaryOp __b)
    197 {
    198     for (; __first != __last; ++__first)
    199         __init = __b(__init, *__first);
    200     return __init;
    201 }
    202 
    203 template <class _InputIterator, class _Tp>
    204 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    205 _Tp
    206 reduce(_InputIterator __first, _InputIterator __last, _Tp __init)
    207 {
    208     return _VSTD::reduce(__first, __last, __init, _VSTD::plus<>());
    209 }
    210 
    211 template <class _InputIterator>
    212 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    213 typename iterator_traits<_InputIterator>::value_type
    214 reduce(_InputIterator __first, _InputIterator __last)
    215 {
    216     return _VSTD::reduce(__first, __last,
    217        typename iterator_traits<_InputIterator>::value_type{});
    218 }
    219 #endif
    220 
    221 template <class _InputIterator1, class _InputIterator2, class _Tp>
    222 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    223 _Tp
    224 inner_product(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _Tp __init)
    225 {
    226     for (; __first1 != __last1; ++__first1, (void) ++__first2)
    227 #if _LIBCPP_STD_VER > 17
    228         __init = _VSTD::move(__init) + *__first1 * *__first2;
    229 #else
    230         __init = __init + *__first1 * *__first2;
    231 #endif
    232     return __init;
    233 }
    234 
    235 template <class _InputIterator1, class _InputIterator2, class _Tp, class _BinaryOperation1, class _BinaryOperation2>
    236 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    237 _Tp
    238 inner_product(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2,
    239               _Tp __init, _BinaryOperation1 __binary_op1, _BinaryOperation2 __binary_op2)
    240 {
    241     for (; __first1 != __last1; ++__first1, (void) ++__first2)
    242 #if _LIBCPP_STD_VER > 17
    243         __init = __binary_op1(_VSTD::move(__init), __binary_op2(*__first1, *__first2));
    244 #else
    245         __init = __binary_op1(__init, __binary_op2(*__first1, *__first2));
    246 #endif
    247     return __init;
    248 }
    249 
    250 #if _LIBCPP_STD_VER > 14
    251 template <class _InputIterator, class _Tp, class _BinaryOp, class _UnaryOp>
    252 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    253 _Tp
    254 transform_reduce(_InputIterator __first, _InputIterator __last,
    255            _Tp __init,  _BinaryOp __b, _UnaryOp __u)
    256 {
    257     for (; __first != __last; ++__first)
    258         __init = __b(__init, __u(*__first));
    259     return __init;
    260 }
    261 
    262 template <class _InputIterator1, class _InputIterator2,
    263           class _Tp, class _BinaryOp1, class _BinaryOp2>
    264 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    265 _Tp
    266 transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1,
    267                  _InputIterator2 __first2, _Tp __init,  _BinaryOp1 __b1, _BinaryOp2 __b2)
    268 {
    269     for (; __first1 != __last1; ++__first1, (void) ++__first2)
    270         __init = __b1(__init, __b2(*__first1, *__first2));
    271     return __init;
    272 }
    273 
    274 template <class _InputIterator1, class _InputIterator2, class _Tp>
    275 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    276 _Tp
    277 transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1,
    278                  _InputIterator2 __first2, _Tp __init)
    279 {
    280     return _VSTD::transform_reduce(__first1, __last1, __first2, _VSTD::move(__init),
    281                                    _VSTD::plus<>(), _VSTD::multiplies<>());
    282 }
    283 #endif
    284 
    285 template <class _InputIterator, class _OutputIterator>
    286 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    287 _OutputIterator
    288 partial_sum(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
    289 {
    290     if (__first != __last)
    291     {
    292         typename iterator_traits<_InputIterator>::value_type __t(*__first);
    293         *__result = __t;
    294         for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result)
    295         {
    296 #if _LIBCPP_STD_VER > 17
    297             __t = _VSTD::move(__t) + *__first;
    298 #else
    299             __t = __t + *__first;
    300 #endif
    301             *__result = __t;
    302         }
    303     }
    304     return __result;
    305 }
    306 
    307 template <class _InputIterator, class _OutputIterator, class _BinaryOperation>
    308 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    309 _OutputIterator
    310 partial_sum(_InputIterator __first, _InputIterator __last, _OutputIterator __result,
    311               _BinaryOperation __binary_op)
    312 {
    313     if (__first != __last)
    314     {
    315         typename iterator_traits<_InputIterator>::value_type __t(*__first);
    316         *__result = __t;
    317         for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result)
    318         {
    319 #if _LIBCPP_STD_VER > 17
    320             __t = __binary_op(_VSTD::move(__t), *__first);
    321 #else
    322             __t = __binary_op(__t, *__first);
    323 #endif
    324             *__result = __t;
    325         }
    326     }
    327     return __result;
    328 }
    329 
    330 #if _LIBCPP_STD_VER > 14
    331 template <class _InputIterator, class _OutputIterator, class _Tp, class _BinaryOp>
    332 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    333 _OutputIterator
    334 exclusive_scan(_InputIterator __first, _InputIterator __last,
    335                _OutputIterator __result, _Tp __init, _BinaryOp __b)
    336 {
    337     if (__first != __last)
    338     {
    339         _Tp __tmp(__b(__init, *__first));
    340         while (true)
    341         {
    342             *__result = _VSTD::move(__init);
    343             ++__result;
    344             ++__first;
    345             if (__first == __last)
    346                 break;
    347             __init = _VSTD::move(__tmp);
    348             __tmp = __b(__init, *__first);
    349         }
    350     }
    351     return __result;
    352 }
    353 
    354 template <class _InputIterator, class _OutputIterator, class _Tp>
    355 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    356 _OutputIterator
    357 exclusive_scan(_InputIterator __first, _InputIterator __last,
    358                _OutputIterator __result, _Tp __init)
    359 {
    360     return _VSTD::exclusive_scan(__first, __last, __result, __init, _VSTD::plus<>());
    361 }
    362 
    363 template <class _InputIterator, class _OutputIterator, class _Tp, class _BinaryOp>
    364 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    365 _OutputIterator inclusive_scan(_InputIterator __first, _InputIterator __last,
    366                                _OutputIterator __result, _BinaryOp __b,  _Tp __init)
    367 {
    368     for (; __first != __last; ++__first, (void) ++__result) {
    369         __init = __b(__init, *__first);
    370         *__result = __init;
    371     }
    372     return __result;
    373 }
    374 
    375 template <class _InputIterator, class _OutputIterator, class _BinaryOp>
    376 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    377 _OutputIterator inclusive_scan(_InputIterator __first, _InputIterator __last,
    378                                _OutputIterator __result, _BinaryOp __b)
    379 {
    380     if (__first != __last) {
    381         typename iterator_traits<_InputIterator>::value_type __init = *__first;
    382         *__result++ = __init;
    383         if (++__first != __last)
    384             return _VSTD::inclusive_scan(__first, __last, __result, __b, __init);
    385     }
    386 
    387     return __result;
    388 }
    389 
    390 template <class _InputIterator, class _OutputIterator>
    391 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    392 _OutputIterator inclusive_scan(_InputIterator __first, _InputIterator __last,
    393                                _OutputIterator __result)
    394 {
    395     return _VSTD::inclusive_scan(__first, __last, __result, _VSTD::plus<>());
    396 }
    397 
    398 template <class _InputIterator, class _OutputIterator, class _Tp,
    399           class _BinaryOp, class _UnaryOp>
    400 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    401 _OutputIterator
    402 transform_exclusive_scan(_InputIterator __first, _InputIterator __last,
    403                            _OutputIterator __result, _Tp __init,
    404                            _BinaryOp __b, _UnaryOp __u)
    405 {
    406     if (__first != __last)
    407     {
    408         _Tp __saved = __init;
    409         do
    410         {
    411             __init = __b(__init, __u(*__first));
    412             *__result = __saved;
    413             __saved = __init;
    414             ++__result;
    415         } while (++__first != __last);
    416     }
    417     return __result;
    418 }
    419 
    420 template <class _InputIterator, class _OutputIterator, class _Tp, class _BinaryOp, class _UnaryOp>
    421 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    422 _OutputIterator
    423 transform_inclusive_scan(_InputIterator __first, _InputIterator __last,
    424                            _OutputIterator __result, _BinaryOp __b, _UnaryOp __u, _Tp __init)
    425 {
    426     for (; __first != __last; ++__first, (void) ++__result) {
    427         __init = __b(__init, __u(*__first));
    428         *__result = __init;
    429         }
    430 
    431     return __result;
    432 }
    433 
    434 template <class _InputIterator, class _OutputIterator, class _BinaryOp, class _UnaryOp>
    435 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    436 _OutputIterator
    437 transform_inclusive_scan(_InputIterator __first, _InputIterator __last,
    438                                _OutputIterator __result, _BinaryOp __b, _UnaryOp __u)
    439 {
    440     if (__first != __last) {
    441         typename iterator_traits<_InputIterator>::value_type __init = __u(*__first);
    442         *__result++ = __init;
    443         if (++__first != __last)
    444             return _VSTD::transform_inclusive_scan(__first, __last, __result, __b, __u, __init);
    445     }
    446 
    447     return __result;
    448 }
    449 #endif
    450 
    451 template <class _InputIterator, class _OutputIterator>
    452 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    453 _OutputIterator
    454 adjacent_difference(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
    455 {
    456     if (__first != __last)
    457     {
    458         typename iterator_traits<_InputIterator>::value_type __acc(*__first);
    459         *__result = __acc;
    460         for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result)
    461         {
    462             typename iterator_traits<_InputIterator>::value_type __val(*__first);
    463 #if _LIBCPP_STD_VER > 17
    464             *__result = __val - _VSTD::move(__acc);
    465 #else
    466             *__result = __val - __acc;
    467 #endif
    468             __acc = _VSTD::move(__val);
    469         }
    470     }
    471     return __result;
    472 }
    473 
    474 template <class _InputIterator, class _OutputIterator, class _BinaryOperation>
    475 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    476 _OutputIterator
    477 adjacent_difference(_InputIterator __first, _InputIterator __last, _OutputIterator __result,
    478                       _BinaryOperation __binary_op)
    479 {
    480     if (__first != __last)
    481     {
    482         typename iterator_traits<_InputIterator>::value_type __acc(*__first);
    483         *__result = __acc;
    484         for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result)
    485         {
    486             typename iterator_traits<_InputIterator>::value_type __val(*__first);
    487 #if _LIBCPP_STD_VER > 17
    488             *__result = __binary_op(__val, _VSTD::move(__acc));
    489 #else
    490             *__result = __binary_op(__val, __acc);
    491 #endif
    492             __acc = _VSTD::move(__val);
    493         }
    494     }
    495     return __result;
    496 }
    497 
    498 template <class _ForwardIterator, class _Tp>
    499 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
    500 void
    501 iota(_ForwardIterator __first, _ForwardIterator __last, _Tp __value_)
    502 {
    503     for (; __first != __last; ++__first, (void) ++__value_)
    504         *__first = __value_;
    505 }
    506 
    507 
    508 #if _LIBCPP_STD_VER > 14
    509 template <typename _Result, typename _Source, bool _IsSigned = is_signed<_Source>::value> struct __ct_abs;
    510 
    511 template <typename _Result, typename _Source>
    512 struct __ct_abs<_Result, _Source, true> {
    513     _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    514     _Result operator()(_Source __t) const noexcept
    515     {
    516         if (__t >= 0) return __t;
    517         if (__t == numeric_limits<_Source>::min()) return -static_cast<_Result>(__t);
    518         return -__t;
    519     }
    520 };
    521 
    522 template <typename _Result, typename _Source>
    523 struct __ct_abs<_Result, _Source, false> {
    524     _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    525     _Result operator()(_Source __t) const noexcept { return __t; }
    526 };
    527 
    528 
    529 template<class _Tp>
    530 _LIBCPP_CONSTEXPR _LIBCPP_HIDDEN
    531 _Tp __gcd(_Tp __m, _Tp __n)
    532 {
    533     static_assert((!is_signed<_Tp>::value), "");
    534     return __n == 0 ? __m : _VSTD::__gcd<_Tp>(__n, __m % __n);
    535 }
    536 
    537 
    538 template<class _Tp, class _Up>
    539 _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    540 common_type_t<_Tp,_Up>
    541 gcd(_Tp __m, _Up __n)
    542 {
    543     static_assert((is_integral<_Tp>::value && is_integral<_Up>::value), "Arguments to gcd must be integer types");
    544     static_assert((!is_same<typename remove_cv<_Tp>::type, bool>::value), "First argument to gcd cannot be bool" );
    545     static_assert((!is_same<typename remove_cv<_Up>::type, bool>::value), "Second argument to gcd cannot be bool" );
    546     using _Rp = common_type_t<_Tp,_Up>;
    547     using _Wp = make_unsigned_t<_Rp>;
    548     return static_cast<_Rp>(_VSTD::__gcd(
    549         static_cast<_Wp>(__ct_abs<_Rp, _Tp>()(__m)),
    550         static_cast<_Wp>(__ct_abs<_Rp, _Up>()(__n))));
    551 }
    552 
    553 template<class _Tp, class _Up>
    554 _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    555 common_type_t<_Tp,_Up>
    556 lcm(_Tp __m, _Up __n)
    557 {
    558     static_assert((is_integral<_Tp>::value && is_integral<_Up>::value), "Arguments to lcm must be integer types");
    559     static_assert((!is_same<typename remove_cv<_Tp>::type, bool>::value), "First argument to lcm cannot be bool" );
    560     static_assert((!is_same<typename remove_cv<_Up>::type, bool>::value), "Second argument to lcm cannot be bool" );
    561     if (__m == 0 || __n == 0)
    562         return 0;
    563 
    564     using _Rp = common_type_t<_Tp,_Up>;
    565     _Rp __val1 = __ct_abs<_Rp, _Tp>()(__m) / _VSTD::gcd(__m, __n);
    566     _Rp __val2 = __ct_abs<_Rp, _Up>()(__n);
    567     _LIBCPP_ASSERT((numeric_limits<_Rp>::max() / __val1 > __val2), "Overflow in lcm");
    568     return __val1 * __val2;
    569 }
    570 
    571 #endif /* _LIBCPP_STD_VER > 14 */
    572 
    573 #if _LIBCPP_STD_VER > 17
    574 template <class _Tp>
    575 _LIBCPP_INLINE_VISIBILITY constexpr
    576 enable_if_t<is_integral_v<_Tp> && !is_same_v<bool, _Tp> && !is_null_pointer_v<_Tp>, _Tp>
    577 midpoint(_Tp __a, _Tp __b) noexcept
    578 _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
    579 {
    580     using _Up = make_unsigned_t<_Tp>;
    581     constexpr _Up __bitshift = numeric_limits<_Up>::digits - 1;
    582 
    583     _Up __diff = _Up(__b) - _Up(__a);
    584     _Up __sign_bit = __b < __a;
    585 
    586     _Up __half_diff = (__diff / 2) + (__sign_bit << __bitshift) + (__sign_bit & __diff);
    587 
    588     return __a + __half_diff;
    589 }
    590 
    591 
    592 template <class _TPtr>
    593 _LIBCPP_INLINE_VISIBILITY constexpr
    594 enable_if_t<is_pointer_v<_TPtr>
    595              && is_object_v<remove_pointer_t<_TPtr>>
    596              && ! is_void_v<remove_pointer_t<_TPtr>>
    597              && (sizeof(remove_pointer_t<_TPtr>) > 0), _TPtr>
    598 midpoint(_TPtr __a, _TPtr __b) noexcept
    599 {
    600     return __a + _VSTD::midpoint(ptrdiff_t(0), __b - __a);
    601 }
    602 
    603 
    604 template <typename _Tp>
    605 constexpr int __sign(_Tp __val) {
    606     return (_Tp(0) < __val) - (__val < _Tp(0));
    607 }
    608 
    609 template <typename _Fp>
    610 constexpr _Fp __fp_abs(_Fp __f) { return __f >= 0 ? __f : -__f; }
    611 
    612 template <class _Fp>
    613 _LIBCPP_INLINE_VISIBILITY constexpr
    614 enable_if_t<is_floating_point_v<_Fp>, _Fp>
    615 midpoint(_Fp __a, _Fp __b) noexcept
    616 {
    617     constexpr _Fp __lo = numeric_limits<_Fp>::min()*2;
    618     constexpr _Fp __hi = numeric_limits<_Fp>::max()/2;
    619     return __fp_abs(__a) <= __hi && __fp_abs(__b) <= __hi ?  // typical case: overflow is impossible
    620       (__a + __b)/2 :                                        // always correctly rounded
    621       __fp_abs(__a) < __lo ? __a + __b/2 :                   // not safe to halve a
    622       __fp_abs(__b) < __lo ? __a/2 + __b :                   // not safe to halve b
    623       __a/2 + __b/2;                                         // otherwise correctly rounded
    624 }
    625 
    626 #endif // _LIBCPP_STD_VER > 17
    627 
    628 _LIBCPP_END_NAMESPACE_STD
    629 
    630 _LIBCPP_POP_MACROS
    631 
    632 #if defined(_LIBCPP_HAS_PARALLEL_ALGORITHMS) && _LIBCPP_STD_VER >= 17
    633 #   include <__pstl_numeric>
    634 #endif
    635 
    636 #endif // _LIBCPP_NUMERIC
    637