STL/stl/inc/numeric

828 строки
36 KiB
C++

// numeric standard header
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#ifndef _NUMERIC_
#define _NUMERIC_
#include <yvals_core.h>
#if _STL_COMPILER_PREPROCESSOR
#include <xutility>
#if _HAS_CXX17
#include <__msvc_bit_utils.hpp>
#endif // _HAS_CXX17
#pragma pack(push, _CRT_PACKING)
#pragma warning(push, _STL_WARNING_LEVEL)
#pragma warning(disable : _STL_DISABLED_WARNINGS)
_STL_DISABLE_CLANG_WARNINGS
#pragma push_macro("new")
#undef new
_STD_BEGIN
_EXPORT_STD template <class _InIt, class _Ty, class _Fn>
_NODISCARD _CONSTEXPR20 _Ty accumulate(const _InIt _First, const _InIt _Last, _Ty _Val, _Fn _Reduce_op) {
// return noncommutative and nonassociative reduction of _Val and all in [_First, _Last), using _Reduce_op
_STD _Adl_verify_range(_First, _Last);
auto _UFirst = _STD _Get_unwrapped(_First);
const auto _ULast = _STD _Get_unwrapped(_Last);
for (; _UFirst != _ULast; ++_UFirst) {
#if _HAS_CXX20
_Val = _Reduce_op(_STD move(_Val), *_UFirst);
#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv
_Val = _Reduce_op(_Val, *_UFirst);
#endif // ^^^ !_HAS_CXX20 ^^^
}
return _Val;
}
_EXPORT_STD template <class _InIt, class _Ty>
_NODISCARD _CONSTEXPR20 _Ty accumulate(const _InIt _First, const _InIt _Last, _Ty _Val) {
// return noncommutative and nonassociative reduction of _Val and all in [_First, _Last)
return _STD accumulate(_First, _Last, _Val, plus<>{});
}
#if _HAS_CXX17
#if _STD_VECTORIZE_WITH_FLOAT_CONTROL
template <class _InIt, class _Ty, class _BinOp>
constexpr bool _Plus_on_arithmetic_ranges_reduction_v =
conjunction_v<is_arithmetic<_Ty>, is_arithmetic<remove_pointer_t<_InIt>>, is_same<plus<>, _BinOp>>;
#pragma float_control(precise, off, push)
template <class _InIt, class _Ty>
_Ty _Reduce_plus_arithmetic_ranges(_InIt _First, const _InIt _Last, _Ty _Val) {
// return reduction, plus arithmetic on contiguous ranges case
#pragma loop(ivdep)
for (; _First != _Last; ++_First) {
_Val += *_First;
}
return _Val;
}
#pragma float_control(pop)
#endif // ^^^ _STD_VECTORIZE_WITH_FLOAT_CONTROL ^^^
_EXPORT_STD template <class _InIt, class _Ty, class _BinOp>
_NODISCARD _CONSTEXPR20 _Ty reduce(const _InIt _First, const _InIt _Last, _Ty _Val, _BinOp _Reduce_op) {
// return commutative and associative reduction of _Val and [_First, _Last), using _Reduce_op
_STD _Adl_verify_range(_First, _Last);
auto _UFirst = _STD _Get_unwrapped(_First);
const auto _ULast = _STD _Get_unwrapped(_Last);
#if _STD_VECTORIZE_WITH_FLOAT_CONTROL
if constexpr (_Plus_on_arithmetic_ranges_reduction_v<_Unwrapped_t<const _InIt&>, _Ty, _BinOp>) {
#if _HAS_CXX20
if (!_STD is_constant_evaluated())
#endif // _HAS_CXX20
{
return _STD _Reduce_plus_arithmetic_ranges(_UFirst, _ULast, _Val);
}
}
#endif // ^^^ _STD_VECTORIZE_WITH_FLOAT_CONTROL ^^^
for (; _UFirst != _ULast; ++_UFirst) {
_Val = _Reduce_op(_STD move(_Val), *_UFirst); // Requirement missing from N4950
}
return _Val;
}
_EXPORT_STD template <class _InIt, class _Ty>
_NODISCARD _CONSTEXPR20 _Ty reduce(const _InIt _First, const _InIt _Last, _Ty _Val) {
// return commutative and associative reduction of _Val and [_First, _Last)
return _STD reduce(_First, _Last, _STD move(_Val), plus{});
}
_EXPORT_STD template <class _InIt>
_NODISCARD _CONSTEXPR20 _Iter_value_t<_InIt> reduce(const _InIt _First, const _InIt _Last) {
// return commutative and associative reduction of
// iterator_traits<_InIt>::value_type{} and [_First, _Last)
return _STD reduce(_First, _Last, _Iter_value_t<_InIt>{}, plus{});
}
_EXPORT_STD template <class _ExPo, class _FwdIt, class _Ty, class _BinOp, _Enable_if_execution_policy_t<_ExPo> = 0>
_NODISCARD _Ty reduce(_ExPo&& _Exec, _FwdIt _First, _FwdIt _Last, _Ty _Val, _BinOp _Reduce_op) noexcept; // terminates
_EXPORT_STD template <class _ExPo, class _FwdIt, class _Ty, _Enable_if_execution_policy_t<_ExPo> = 0>
_NODISCARD _Ty reduce(_ExPo&& _Exec, const _FwdIt _First, const _FwdIt _Last, _Ty _Val) noexcept /* terminates */ {
// return commutative and associative reduction of _Val and [_First, _Last)
return _STD reduce(_STD forward<_ExPo>(_Exec), _First, _Last, _STD move(_Val), plus{});
}
_EXPORT_STD template <class _ExPo, class _FwdIt, _Enable_if_execution_policy_t<_ExPo> = 0>
_NODISCARD _Iter_value_t<_FwdIt> reduce(_ExPo&& _Exec, const _FwdIt _First, const _FwdIt _Last) noexcept
/* terminates */ {
// return commutative and associative reduction of
// iterator_traits<_FwdIt>::value_type{} and [_First, _Last)
return _STD reduce(_STD forward<_ExPo>(_Exec), _First, _Last, _Iter_value_t<_FwdIt>{}, plus{});
}
#endif // _HAS_CXX17
_EXPORT_STD template <class _InIt1, class _InIt2, class _Ty, class _BinOp1, class _BinOp2>
_NODISCARD _CONSTEXPR20 _Ty inner_product(
_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _Ty _Val, _BinOp1 _Reduce_op, _BinOp2 _Transform_op) {
// return noncommutative and nonassociative transform-reduction of sequences, using
// _Reduce_op and _Transform_op
_STD _Adl_verify_range(_First1, _Last1);
auto _UFirst1 = _STD _Get_unwrapped(_First1);
const auto _ULast1 = _STD _Get_unwrapped(_Last1);
auto _UFirst2 = _STD _Get_unwrapped_n(_First2, _STD _Idl_distance<_InIt1>(_UFirst1, _ULast1));
for (; _UFirst1 != _ULast1; ++_UFirst1, (void) ++_UFirst2) {
#if _HAS_CXX20
_Val = _Reduce_op(_STD move(_Val), _Transform_op(*_UFirst1, *_UFirst2)); // Requirement missing from N4950
#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv
_Val = _Reduce_op(_Val, _Transform_op(*_UFirst1, *_UFirst2)); // Requirement missing from N4950
#endif // ^^^ !_HAS_CXX20 ^^^
}
return _Val;
}
_EXPORT_STD template <class _InIt1, class _InIt2, class _Ty>
_NODISCARD _CONSTEXPR20 _Ty inner_product(const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2, _Ty _Val) {
// return noncommutative and nonassociative transform-reduction of sequences
return _STD inner_product(_First1, _Last1, _First2, _STD move(_Val), plus<>{}, multiplies<>{});
}
#if _HAS_CXX17
#if _STD_VECTORIZE_WITH_FLOAT_CONTROL
template <class _InIt1, class _InIt2, class _Ty, class _BinOp1, class _BinOp2>
constexpr bool _Default_ops_transform_reduce_v =
conjunction_v<is_arithmetic<_Ty>, is_arithmetic<remove_pointer_t<_InIt1>>, is_arithmetic<remove_pointer_t<_InIt2>>,
is_same<plus<>, _BinOp1>, is_same<multiplies<>, _BinOp2>>;
#pragma float_control(precise, off, push)
template <class _InIt1, class _InIt2, class _Ty>
_Ty _Transform_reduce_arithmetic_defaults(_InIt1 _First1, const _InIt1 _Last1, _InIt2 _First2, _Ty _Val) {
// return transform-reduction, default ops on contiguous arithmetic ranges case
#pragma loop(ivdep)
for (; _First1 != _Last1; ++_First1, (void) ++_First2) {
_Val += *_First1 * *_First2;
}
return _Val;
}
#pragma float_control(pop)
#endif // ^^^ _STD_VECTORIZE_WITH_FLOAT_CONTROL ^^^
_EXPORT_STD template <class _InIt1, class _InIt2, class _Ty, class _BinOp1, class _BinOp2>
_NODISCARD _CONSTEXPR20 _Ty transform_reduce(
_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _Ty _Val, _BinOp1 _Reduce_op, _BinOp2 _Transform_op) {
// return commutative and associative transform-reduction of sequences, using
// _Reduce_op and _Transform_op
_STD _Adl_verify_range(_First1, _Last1);
auto _UFirst1 = _STD _Get_unwrapped(_First1);
const auto _ULast1 = _STD _Get_unwrapped(_Last1);
auto _UFirst2 = _STD _Get_unwrapped_n(_First2, _STD _Idl_distance<_InIt1>(_UFirst1, _ULast1));
#if _STD_VECTORIZE_WITH_FLOAT_CONTROL
if constexpr (_Default_ops_transform_reduce_v<_Unwrapped_t<const _InIt1&>, _Unwrapped_t<const _InIt2&>, _Ty,
_BinOp1, _BinOp2>) {
#if _HAS_CXX20
// TRANSITION, DevCom-878972
if (!_STD is_constant_evaluated())
#endif // _HAS_CXX20
{
return _STD _Transform_reduce_arithmetic_defaults(_UFirst1, _ULast1, _UFirst2, _STD move(_Val));
}
}
#endif // ^^^ _STD_VECTORIZE_WITH_FLOAT_CONTROL ^^^
for (; _UFirst1 != _ULast1; ++_UFirst1, (void) ++_UFirst2) {
_Val = _Reduce_op(_STD move(_Val), _Transform_op(*_UFirst1, *_UFirst2)); // Requirement missing from N4950
}
return _Val;
}
_EXPORT_STD template <class _InIt1, class _InIt2, class _Ty>
_NODISCARD _CONSTEXPR20 _Ty transform_reduce(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _Ty _Val) {
// return commutative and associative transform-reduction of sequences
return _STD transform_reduce(_First1, _Last1, _First2, _STD move(_Val), plus{}, multiplies{});
}
_EXPORT_STD template <class _InIt, class _Ty, class _BinOp, class _UnaryOp>
_NODISCARD _CONSTEXPR20 _Ty transform_reduce(
const _InIt _First, const _InIt _Last, _Ty _Val, _BinOp _Reduce_op, _UnaryOp _Transform_op) {
// return commutative and associative reduction of transformed sequence, using
// _Reduce_op and _Transform_op
_STD _Adl_verify_range(_First, _Last);
auto _UFirst = _STD _Get_unwrapped(_First);
const auto _ULast = _STD _Get_unwrapped(_Last);
for (; _UFirst != _ULast; ++_UFirst) {
_Val = _Reduce_op(_STD move(_Val), _Transform_op(*_UFirst)); // Requirement missing from N4950
}
return _Val;
}
_EXPORT_STD template <class _ExPo, class _FwdIt1, class _FwdIt2, class _Ty, class _BinOp1, class _BinOp2,
_Enable_if_execution_policy_t<_ExPo> = 0>
_NODISCARD _Ty transform_reduce(_ExPo&& _Exec, _FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _Ty _Val,
_BinOp1 _Reduce_op, _BinOp2 _Transform_op) noexcept; // terminates
_EXPORT_STD template <class _ExPo, class _FwdIt1, class _FwdIt2, class _Ty, _Enable_if_execution_policy_t<_ExPo> = 0>
_NODISCARD _Ty transform_reduce(_ExPo&& _Exec, _FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _Ty _Val) noexcept
/* terminates */ {
// return commutative and associative transform-reduction of sequences
return _STD transform_reduce(
_STD forward<_ExPo>(_Exec), _First1, _Last1, _First2, _STD move(_Val), plus{}, multiplies{});
}
_EXPORT_STD template <class _ExPo, class _FwdIt, class _Ty, class _BinOp, class _UnaryOp,
_Enable_if_execution_policy_t<_ExPo> = 0>
_NODISCARD _Ty transform_reduce(_ExPo&& _Exec, _FwdIt _First1, _FwdIt _Last1, _Ty _Val, _BinOp _Reduce_op,
_UnaryOp _Transform_op) noexcept; // terminates
#endif // _HAS_CXX17
_EXPORT_STD template <class _InIt, class _OutIt, class _BinOp>
_CONSTEXPR20 _OutIt partial_sum(const _InIt _First, const _InIt _Last, _OutIt _Dest, _BinOp _Reduce_op) {
// compute partial noncommutative and nonassociative reductions into _Dest, using _Reduce_op
_STD _Adl_verify_range(_First, _Last);
auto _UFirst = _STD _Get_unwrapped(_First);
const auto _ULast = _STD _Get_unwrapped(_Last);
auto _UDest = _STD _Get_unwrapped_n(_Dest, _STD _Idl_distance<_InIt>(_UFirst, _ULast));
if (_UFirst != _ULast) {
_Iter_value_t<_InIt> _Val(*_UFirst);
for (;;) {
*_UDest = _Val;
++_UDest;
++_UFirst;
if (_UFirst == _ULast) {
break;
}
#if _HAS_CXX20
_Val = _Reduce_op(_STD move(_Val), *_UFirst);
#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv
_Val = _Reduce_op(_Val, *_UFirst);
#endif // ^^^ !_HAS_CXX20 ^^^
}
}
_STD _Seek_wrapped(_Dest, _UDest);
return _Dest;
}
_EXPORT_STD template <class _InIt, class _OutIt>
_CONSTEXPR20 _OutIt partial_sum(_InIt _First, _InIt _Last, _OutIt _Dest) {
// compute partial noncommutative and nonassociative reductions into _Dest
return _STD partial_sum(_First, _Last, _Dest, plus<>{});
}
#if _HAS_CXX17
_EXPORT_STD template <class _InIt, class _OutIt, class _Ty, class _BinOp>
_CONSTEXPR20 _OutIt exclusive_scan(const _InIt _First, const _InIt _Last, _OutIt _Dest, _Ty _Val, _BinOp _Reduce_op) {
// set each value in [_Dest, _Dest + (_Last - _First)) to the associative reduction of predecessors and _Val
_STD _Adl_verify_range(_First, _Last);
auto _UFirst = _STD _Get_unwrapped(_First);
const auto _ULast = _STD _Get_unwrapped(_Last);
auto _UDest = _STD _Get_unwrapped_n(_Dest, _STD _Idl_distance<_InIt>(_UFirst, _ULast));
if (_UFirst != _ULast) {
for (;;) {
_Ty _Tmp = _Reduce_op(_Val, *_UFirst); // temp to enable _First == _Dest, also requirement missing
*_UDest = _Val;
++_UDest;
++_UFirst;
if (_UFirst == _ULast) {
break;
}
_Val = _STD move(_Tmp); // Requirement missing from N4950
}
}
_STD _Seek_wrapped(_Dest, _UDest);
return _Dest;
}
_EXPORT_STD template <class _InIt, class _OutIt, class _Ty>
_CONSTEXPR20 _OutIt exclusive_scan(const _InIt _First, const _InIt _Last, const _OutIt _Dest, _Ty _Val) {
// set each value in [_Dest, _Dest + (_Last - _First)) to the associative reduction of predecessors and _Val
return _STD exclusive_scan(_First, _Last, _Dest, _STD move(_Val), plus{});
}
_EXPORT_STD template <class _ExPo, class _FwdIt1, class _FwdIt2, class _Ty, class _BinOp,
_Enable_if_execution_policy_t<_ExPo> = 0>
_FwdIt2 exclusive_scan(_ExPo&& _Exec, _FwdIt1 _First, _FwdIt1 _Last, _FwdIt2 _Dest, _Ty _Val,
_BinOp _Reduce_op) noexcept; // terminates
_EXPORT_STD template <class _ExPo, class _FwdIt1, class _FwdIt2, class _Ty, _Enable_if_execution_policy_t<_ExPo> = 0>
_FwdIt2 exclusive_scan(_ExPo&& _Exec, const _FwdIt1 _First, const _FwdIt1 _Last, const _FwdIt2 _Dest, _Ty _Val) noexcept
/* terminates */ {
// set each value in [_Dest, _Dest + (_Last - _First)) to the associative reduction of predecessors and _Val
return _STD exclusive_scan(_STD forward<_ExPo>(_Exec), _First, _Last, _Dest, _STD move(_Val), plus{});
}
_EXPORT_STD template <class _InIt, class _OutIt, class _Ty, class _BinOp>
_CONSTEXPR20 _OutIt inclusive_scan(const _InIt _First, const _InIt _Last, _OutIt _Dest, _BinOp _Reduce_op, _Ty _Val) {
// compute partial noncommutative and associative reductions including _Val into _Dest, using _Reduce_op
_STD _Adl_verify_range(_First, _Last);
auto _UFirst = _STD _Get_unwrapped(_First);
const auto _ULast = _STD _Get_unwrapped(_Last);
auto _UDest = _STD _Get_unwrapped_n(_Dest, _STD _Idl_distance<_InIt>(_UFirst, _ULast));
for (; _UFirst != _ULast; ++_UFirst) {
_Val = _Reduce_op(_STD move(_Val), *_UFirst); // Requirement missing from N4950
*_UDest = _Val;
++_UDest;
}
_STD _Seek_wrapped(_Dest, _UDest);
return _Dest;
}
_EXPORT_STD template <class _InIt, class _OutIt, class _BinOp>
_CONSTEXPR20 _OutIt inclusive_scan(const _InIt _First, const _InIt _Last, _OutIt _Dest, _BinOp _Reduce_op) {
// compute partial noncommutative and associative reductions into _Dest, using _Reduce_op
_STD _Adl_verify_range(_First, _Last);
auto _UFirst = _STD _Get_unwrapped(_First);
const auto _ULast = _STD _Get_unwrapped(_Last);
auto _UDest = _STD _Get_unwrapped_n(_Dest, _STD _Idl_distance<_InIt>(_UFirst, _ULast));
if (_UFirst != _ULast) {
_Iter_value_t<_InIt> _Val(*_UFirst); // Requirement missing from N4950
for (;;) {
*_UDest = _Val;
++_UDest;
++_UFirst;
if (_UFirst == _ULast) {
break;
}
_Val = _Reduce_op(_STD move(_Val), *_UFirst); // Requirement missing from N4950
}
}
_STD _Seek_wrapped(_Dest, _UDest);
return _Dest;
}
_EXPORT_STD template <class _InIt, class _OutIt>
_CONSTEXPR20 _OutIt inclusive_scan(const _InIt _First, const _InIt _Last, const _OutIt _Dest) {
// compute partial noncommutative and associative reductions into _Dest
return _STD inclusive_scan(_First, _Last, _Dest, plus{});
}
_EXPORT_STD template <class _ExPo, class _FwdIt1, class _FwdIt2, class _BinOp, class _Ty,
_Enable_if_execution_policy_t<_ExPo> = 0>
_FwdIt2 inclusive_scan(
_ExPo&& _Exec, _FwdIt1 _First, _FwdIt1 _Last, _FwdIt2 _Dest, _BinOp _Reduce_op, _Ty _Val) noexcept; // terminates
_EXPORT_STD template <class _ExPo, class _FwdIt1, class _FwdIt2, class _BinOp, _Enable_if_execution_policy_t<_ExPo> = 0>
_FwdIt2 inclusive_scan(
_ExPo&& _Exec, _FwdIt1 _First, _FwdIt1 _Last, _FwdIt2 _Dest, _BinOp _Reduce_op) noexcept; // terminates
_EXPORT_STD template <class _ExPo, class _FwdIt1, class _FwdIt2, _Enable_if_execution_policy_t<_ExPo> = 0>
_FwdIt2 inclusive_scan(_ExPo&& _Exec, const _FwdIt1 _First, const _FwdIt1 _Last, const _FwdIt2 _Dest) noexcept
/* terminates */ {
// compute partial noncommutative and associative reductions into _Dest
return _STD inclusive_scan(_STD forward<_ExPo>(_Exec), _First, _Last, _Dest, plus{});
}
_EXPORT_STD template <class _InIt, class _OutIt, class _Ty, class _BinOp, class _UnaryOp>
_CONSTEXPR20 _OutIt transform_exclusive_scan(
const _InIt _First, const _InIt _Last, _OutIt _Dest, _Ty _Val, _BinOp _Reduce_op, _UnaryOp _Transform_op) {
// set each value in [_Dest, _Dest + (_Last - _First)) to the associative reduction of transformed predecessors
_STD _Adl_verify_range(_First, _Last);
auto _UFirst = _STD _Get_unwrapped(_First);
const auto _ULast = _STD _Get_unwrapped(_Last);
auto _UDest = _STD _Get_unwrapped_n(_Dest, _STD _Idl_distance<_InIt>(_UFirst, _ULast));
if (_UFirst != _ULast) {
for (;;) {
_Ty _Tmp = _Reduce_op(_Val, _Transform_op(*_UFirst)); // temp to enable _First == _Dest
*_UDest = _Val;
++_UDest;
++_UFirst;
if (_UFirst == _ULast) {
break;
}
_Val = _STD move(_Tmp); // Requirement missing from N4950
}
}
_STD _Seek_wrapped(_Dest, _UDest);
return _Dest;
}
_EXPORT_STD template <class _ExPo, class _FwdIt1, class _OutIt, class _Ty, class _BinOp, class _UnaryOp,
_Enable_if_execution_policy_t<_ExPo> = 0>
_OutIt transform_exclusive_scan(_ExPo&& _Exec, _FwdIt1 _First, _FwdIt1 _Last, _OutIt _Dest, _Ty _Val, _BinOp _Reduce_op,
_UnaryOp _Transform_op) noexcept; // terminates
_EXPORT_STD template <class _InIt, class _OutIt, class _Ty, class _BinOp, class _UnaryOp>
_CONSTEXPR20 _OutIt transform_inclusive_scan(
const _InIt _First, const _InIt _Last, _OutIt _Dest, _BinOp _Reduce_op, _UnaryOp _Transform_op, _Ty _Val) {
// compute partial noncommutative and associative transformed reductions including _Val into _Dest
_STD _Adl_verify_range(_First, _Last);
auto _UFirst = _STD _Get_unwrapped(_First);
const auto _ULast = _STD _Get_unwrapped(_Last);
auto _UDest = _STD _Get_unwrapped_n(_Dest, _STD _Idl_distance<_InIt>(_UFirst, _ULast));
for (; _UFirst != _ULast; ++_UFirst) {
_Val = _Reduce_op(_STD move(_Val), _Transform_op(*_UFirst)); // Requirement missing from N4950
*_UDest = _Val;
++_UDest;
}
_STD _Seek_wrapped(_Dest, _UDest);
return _Dest;
}
_EXPORT_STD template <class _InIt, class _OutIt, class _BinOp, class _UnaryOp>
_CONSTEXPR20 _OutIt transform_inclusive_scan(
const _InIt _First, const _InIt _Last, _OutIt _Dest, _BinOp _Reduce_op, _UnaryOp _Transform_op) {
// compute partial noncommutative and associative transformed reductions into _Dest
_STD _Adl_verify_range(_First, _Last);
auto _UFirst = _STD _Get_unwrapped(_First);
const auto _ULast = _STD _Get_unwrapped(_Last);
auto _UDest = _STD _Get_unwrapped_n(_Dest, _STD _Idl_distance<_InIt>(_UFirst, _ULast));
if (_UFirst != _ULast) {
auto _Val = _Transform_op(*_UFirst); // Requirement missing from N4950, also type to use unclear
for (;;) {
*_UDest = _Val;
++_UDest;
++_UFirst;
if (_UFirst == _ULast) {
break;
}
_Val = _Reduce_op(_STD move(_Val), _Transform_op(*_UFirst)); // Requirement missing from N4950
}
}
_STD _Seek_wrapped(_Dest, _UDest);
return _Dest;
}
_EXPORT_STD template <class _ExPo, class _FwdIt1, class _FwdIt2, class _Ty, class _BinOp, class _UnaryOp,
_Enable_if_execution_policy_t<_ExPo> = 0>
_FwdIt2 transform_inclusive_scan(_ExPo&& _Exec, _FwdIt1 _First, _FwdIt1 _Last, _FwdIt2 _Dest, _BinOp _Reduce_op,
_UnaryOp _Transform_op, _Ty _Val) noexcept; // terminates
_EXPORT_STD template <class _ExPo, class _FwdIt1, class _FwdIt2, class _BinOp, class _UnaryOp,
_Enable_if_execution_policy_t<_ExPo> = 0>
_FwdIt2 transform_inclusive_scan(_ExPo&& _Exec, _FwdIt1 _First, _FwdIt1 _Last, _FwdIt2 _Dest, _BinOp _Reduce_op,
_UnaryOp _Transform_op) noexcept; // terminates
#endif // _HAS_CXX17
template <class _TyDest, class _TySrc, class _BinOp>
void _Adjacent_difference_no_overlap(
_TyDest* const _RESTRICT _Dest, _TySrc* const _RESTRICT _Src, const ptrdiff_t _Count, _BinOp _Func) {
_Dest[0] = _Src[0];
for (ptrdiff_t _Ix = 1; _Ix != _Count; ++_Ix) {
#if _HAS_CXX20
_TySrc _Tmp = _Src[_Ix - 1];
_Dest[_Ix] = _Func(_Src[_Ix], _STD move(_Tmp));
#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv
_Dest[_Ix] = _Func(_Src[_Ix], _Src[_Ix - 1]);
#endif // ^^^ !_HAS_CXX20 ^^^
}
}
_EXPORT_STD template <class _InIt, class _OutIt, class _BinOp>
_CONSTEXPR20 _OutIt adjacent_difference(const _InIt _First, const _InIt _Last, _OutIt _Dest, _BinOp _Func) {
// compute adjacent differences into _Dest
_STD _Adl_verify_range(_First, _Last);
auto _UFirst = _STD _Get_unwrapped(_First);
const auto _ULast = _STD _Get_unwrapped(_Last);
auto _UDest = _STD _Get_unwrapped_n(_Dest, _STD _Idl_distance<_InIt>(_UFirst, _ULast));
if (_UFirst != _ULast) {
if constexpr (_Iterators_are_contiguous<decltype(_UFirst), decltype(_UDest)> && !_Iterator_is_volatile<_InIt>
&& is_trivially_copyable_v<_Iter_value_t<_InIt>>) {
#if _HAS_CXX20
if (!_STD is_constant_evaluated())
#endif
{
// Go with pointers and without loop-carried dependency to enable vectorization
const auto _First_ptr = _STD _To_address(_UFirst);
const auto _Last_ptr = _STD _To_address(_ULast);
const auto _Dest_ptr = _STD _To_address(_UDest);
const auto _Count = _Last_ptr - _First_ptr;
// Need to perform aliasing analysis.
// The vectorizer is generally able to do that on its own, and would guard the vectorized code with
// that, but when we eliminate the loop-carried dependency we change the semantics of the unvectorized
// code too. So we need to perform this check manually, and after that we can tell the compiler that
// there's no aliasing, to avoid it checking for that again.
if (reinterpret_cast<uintptr_t>(_Dest_ptr + _Count) <= reinterpret_cast<uintptr_t>(_First_ptr)
|| reinterpret_cast<uintptr_t>(_Last_ptr) <= reinterpret_cast<uintptr_t>(_Dest_ptr)) {
_STD _Adjacent_difference_no_overlap(_Dest_ptr, _First_ptr, _Count, _STD _Pass_fn(_Func));
_STD _Seek_wrapped(_Dest, _UDest + _Count);
return _Dest;
}
}
}
_Iter_value_t<_InIt> _Val(*_UFirst);
*_UDest = _Val;
while (++_UFirst != _ULast) { // compute another difference
_Iter_value_t<_InIt> _Tmp(*_UFirst);
#if _HAS_CXX20
*++_UDest = _Func(_Tmp, _STD move(_Val));
#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv
*++_UDest = _Func(_Tmp, _Val);
#endif // ^^^ !_HAS_CXX20 ^^^
_Val = _STD move(_Tmp);
}
++_UDest;
}
_STD _Seek_wrapped(_Dest, _UDest);
return _Dest;
}
_EXPORT_STD template <class _InIt, class _OutIt>
_CONSTEXPR20 _OutIt adjacent_difference(const _InIt _First, const _InIt _Last, const _OutIt _Dest) {
// compute adjacent differences into _Dest
return _STD adjacent_difference(_First, _Last, _Dest, minus<>{});
}
#if _HAS_CXX17
_EXPORT_STD template <class _ExPo, class _FwdIt1, class _FwdIt2, class _BinOp, _Enable_if_execution_policy_t<_ExPo> = 0>
_FwdIt2 adjacent_difference(
_ExPo&& _Exec, _FwdIt1 _First, _FwdIt1 _Last, _FwdIt2 _Dest, _BinOp _Diff_op) noexcept; // terminates
_EXPORT_STD template <class _ExPo, class _FwdIt1, class _FwdIt2, _Enable_if_execution_policy_t<_ExPo> = 0>
_FwdIt2 adjacent_difference(_ExPo&& _Exec, const _FwdIt1 _First, const _FwdIt1 _Last, const _FwdIt2 _Dest) noexcept
/* terminates */ {
// compute adjacent differences into _Dest
return _STD adjacent_difference(_STD forward<_ExPo>(_Exec), _First, _Last, _Dest, minus{});
}
#endif // _HAS_CXX17
_EXPORT_STD template <class _FwdIt, class _Ty>
_CONSTEXPR20 void iota(_FwdIt _First, _FwdIt _Last, _Ty _Val) {
// compute increasing sequence into [_First, _Last)
_STD _Adl_verify_range(_First, _Last);
auto _UFirst = _STD _Get_unwrapped(_First);
const auto _ULast = _STD _Get_unwrapped(_Last);
if constexpr (_Iterator_is_contiguous<decltype(_UFirst)> && is_integral_v<_Ty> && sizeof(_Ty) >= 4) {
// TRANSITION, DevCom-10593477: help the compiler vectorize
const auto _Ptr = _To_address(_UFirst);
const auto _Size = static_cast<size_t>(_ULast - _UFirst);
if (_STD _In_range<_Ty>(_Size)) {
const auto _Size_typed = static_cast<_Ty>(_Size);
for (_Ty _Ix = 0; _Ix != _Size_typed; ++_Ix) {
_Ptr[_Ix] = _Val + _Ix;
}
return;
}
}
for (; _UFirst != _ULast; ++_UFirst, (void) ++_Val) {
*_UFirst = _Val;
}
}
#if _HAS_CXX23
namespace ranges {
_EXPORT_STD template <class _Out, class _Ty>
using iota_result = out_value_result<_Out, _Ty>;
class _Iota_fn {
public:
template <input_or_output_iterator _It, sentinel_for<_It> _Se, weakly_incrementable _Ty>
requires indirectly_writable<_It, const _Ty&>
_STATIC_CALL_OPERATOR constexpr iota_result<_It, _Ty> operator()(
_It _First, _Se _Last, _Ty _Val) _CONST_CALL_OPERATOR {
_STD _Adl_verify_range(_First, _Last);
_STD _Seek_wrapped(_First, _Iota_impl(_RANGES _Unwrap_iter<_Se>(_STD move(_First)),
_RANGES _Unwrap_sent<_It>(_STD move(_Last)), _Val));
return {_STD move(_First), _STD move(_Val)};
}
template <weakly_incrementable _Ty, output_range<const _Ty&> _Rng>
_STATIC_CALL_OPERATOR constexpr iota_result<borrowed_iterator_t<_Rng>, _Ty> operator()(
_Rng&& _Range, _Ty _Val) _CONST_CALL_OPERATOR {
auto _First = _RANGES begin(_Range);
_STD _Seek_wrapped(
_First, _Iota_impl(_RANGES _Unwrap_range_iter<_Rng>(_STD move(_First)), _Uend(_Range), _Val));
return {_STD move(_First), _STD move(_Val)};
}
private:
template <class _It, class _Se, class _Ty>
_NODISCARD static constexpr _It _Iota_impl(_It _First, const _Se _Last, _Ty& _Val) {
_STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se, _It>);
_STL_INTERNAL_STATIC_ASSERT(weakly_incrementable<_Ty>);
_STL_INTERNAL_STATIC_ASSERT(indirectly_writable<_It, const _Ty&>);
if constexpr (_Iterator_is_contiguous<_It> && sized_sentinel_for<_Se, _It> && is_integral_v<_Ty>
&& sizeof(_Ty) >= 4) {
// TRANSITION, DevCom-10593477: help the compiler vectorize
const auto _Ptr = _To_address(_First);
const auto _Size = static_cast<size_t>(_Last - _First);
if (_STD _In_range<_Ty>(_Size)) {
const auto _Size_typed = static_cast<_Ty>(_Size);
for (_Ty _Ix = 0; _Ix != _Size_typed; ++_Ix) {
const _Ty _Const_val = _Val + _Ix;
_Ptr[_Ix] = _Const_val;
}
_Val += _Size_typed;
return _First + _Size;
}
}
const _Ty& _Const_val = _Val;
for (; _First != _Last; ++_First, (void) ++_Val) {
*_First = _Const_val;
}
return _First;
}
};
_EXPORT_STD inline constexpr _Iota_fn iota;
} // namespace ranges
#endif // _HAS_CXX23
#if _HAS_CXX17
template <class _Integral>
_NODISCARD constexpr auto _Abs_u(const _Integral _Val) noexcept {
// computes absolute value of _Val (converting to an unsigned integer type if necessary to avoid overflow
// representing the negation of the minimum value)
static_assert(is_integral_v<_Integral>);
if constexpr (is_signed_v<_Integral>) {
using _Unsigned = make_unsigned_t<_Integral>;
if (_Val < 0) {
// note static_cast to _Unsigned such that _Integral == short returns unsigned short rather than int
return static_cast<_Unsigned>(_Unsigned{0} - static_cast<_Unsigned>(_Val));
}
return static_cast<_Unsigned>(_Val);
} else {
return _Val;
}
}
_EXPORT_STD template <class _Mt, class _Nt>
_NODISCARD constexpr common_type_t<_Mt, _Nt> gcd(const _Mt _Mx, const _Nt _Nx) noexcept /* strengthened */ {
// calculate greatest common divisor
static_assert(_Is_nonbool_integral<_Mt> && _Is_nonbool_integral<_Nt>, "GCD requires nonbool integral types");
using _Common = common_type_t<_Mt, _Nt>;
using _Common_unsigned = make_unsigned_t<_Common>;
if constexpr (is_signed_v<_Common>) {
#ifndef _DEBUG
if (_STD _Is_constant_evaluated())
#endif // ^^^ !defined(_DEBUG) ^^^
{
constexpr auto _Min_common = _STD _Min_limit<_Common>();
if (_Mx == _Min_common || _Nx == _Min_common) {
_STL_REPORT_ERROR("Preconditions: |m| and |n| are representable as a value of common_type_t<M, N>. "
"(N4981 [numeric.ops.gcd]/2, N4981 [numeric.ops.lcm]/2)");
}
}
}
return _Select_countr_zero_impl<_Common_unsigned>([=](auto _Countr_zero_impl) {
_Common_unsigned _Mx_magnitude = _Abs_u(_Mx);
_Common_unsigned _Nx_magnitude = _Abs_u(_Nx);
if (_Mx_magnitude == 0U) {
return static_cast<_Common>(_Nx_magnitude);
}
if (_Nx_magnitude == 0U) {
return static_cast<_Common>(_Mx_magnitude);
}
const auto _Mx_trailing_zeroes = static_cast<unsigned long>(_Countr_zero_impl(_Mx_magnitude));
auto _Nx_trailing_zeroes = static_cast<unsigned long>(_Countr_zero_impl(_Nx_magnitude));
const auto _Common_factors_of_2 = (_STD min)(_Mx_trailing_zeroes, _Nx_trailing_zeroes);
_Mx_magnitude >>= _Mx_trailing_zeroes;
for (;;) {
_Nx_magnitude >>= _Nx_trailing_zeroes;
if (_Mx_magnitude > _Nx_magnitude) {
_Common_unsigned _Temp = _Mx_magnitude;
_Mx_magnitude = _Nx_magnitude;
_Nx_magnitude = _Temp;
}
_Nx_magnitude -= _Mx_magnitude;
if (_Nx_magnitude == 0U) {
return static_cast<_Common>(_Mx_magnitude << _Common_factors_of_2);
}
_Nx_trailing_zeroes = static_cast<unsigned long>(_Countr_zero_impl(_Nx_magnitude));
}
});
}
_EXPORT_STD template <class _Mt, class _Nt>
_NODISCARD constexpr common_type_t<_Mt, _Nt> lcm(const _Mt _Mx, const _Nt _Nx) noexcept /* strengthened */ {
// calculate least common multiple
static_assert(_Is_nonbool_integral<_Mt> && _Is_nonbool_integral<_Nt>, "LCM requires nonbool integral types");
using _Common = common_type_t<_Mt, _Nt>;
using _Common_unsigned = make_unsigned_t<_Common>;
const _Common_unsigned _Mx_magnitude = _Abs_u(_Mx);
const _Common_unsigned _Nx_magnitude = _Abs_u(_Nx);
if (_Mx_magnitude == 0 || _Nx_magnitude == 0) {
return 0;
}
#ifndef _DEBUG
if (!_STD _Is_constant_evaluated()) {
return static_cast<_Common>((_Mx_magnitude / _STD gcd(_Mx_magnitude, _Nx_magnitude)) * _Nx_magnitude);
}
#endif // ^^^ !defined(_DEBUG) ^^^
_Common_unsigned _Result = 0;
_Common_unsigned _Tmp = static_cast<_Common_unsigned>(_Mx_magnitude / _STD gcd(_Mx_magnitude, _Nx_magnitude));
if (_Mul_overflow(_Tmp, _Nx_magnitude, _Result) || !_In_range<_Common>(_Result)) {
_STL_REPORT_ERROR("Preconditions: The least common multiple of |m| and |n| is representable as a value of "
"type common_type_t<M, N>. (N4981 [numeric.ops.lcm]/2)");
}
return static_cast<_Common>(_Result);
}
#endif // _HAS_CXX17
#if _HAS_CXX20
_EXPORT_STD template <class _Ty>
requires is_arithmetic_v<_Ty> && (!is_same_v<remove_cv_t<_Ty>, bool>)
_NODISCARD constexpr _Ty midpoint(const _Ty _Val1, const _Ty _Val2) noexcept {
if constexpr (is_floating_point_v<_Ty>) {
if (_STD is_constant_evaluated()) {
if (_Is_nan(_Val1)) {
return _Val1;
}
if (_Is_nan(_Val2)) {
return _Val2;
}
} else {
if (_Is_nan(_Val1) || _Is_nan(_Val2)) {
// raise FE_INVALID if at least one of _Val1 and _Val2 is signaling NaN
return _Val1 + _Val2;
}
}
constexpr _Ty _High_limit = _Floating_type_traits<remove_cv_t<_Ty>>::_Maximum_value / 2;
const auto _Val1_a = _Float_abs(_Val1);
const auto _Val2_a = _Float_abs(_Val2);
if (_Val1_a <= _High_limit && _Val2_a <= _High_limit) {
// _Val1 and _Val2 are small enough that _Val1 + _Val2 won't overflow
// For the division to be inexact, the result of the addition must produce a value with the smallest
// effective exponent and the low order bit in the mantissa set. For an addition to be inexact in this
// condition, the difference between the inputs would have to be smaller than one ULP, but that is
// impossible.
//
// For example, with doubles, the sum/difference of the inputs would have to be finer than 2^-1074, for it
// to round (via whatever mode) to the value with a least significant 1 bit and p-1022, but the inputs can't
// be finer than 2^-1074 and addition/subtraction can't create smaller steps.
return (_Val1 + _Val2) / 2;
}
// Here at least one of {_Val1, _Val2} has large magnitude.
// Therefore, if one of the values is too small to divide by 2 exactly, the small magnitude is much less than
// one ULP of the result, so we can add it directly without the potentially inexact division by 2.
// In the default rounding mode this less than one ULP difference will always be rounded away, so under
// /fp:fast we could avoid these tests if we had some means of detecting it in the caller.
constexpr _Ty _Low_limit = _Floating_type_traits<remove_cv_t<_Ty>>::_Minimum_value * 2;
if (_Val1_a < _Low_limit) {
return _Val1 + _Val2 / 2;
}
if (_Val2_a < _Low_limit) {
// division of _Val2 by 2 would be inexact, etc.
return _Val1 / 2 + _Val2;
}
return _Val1 / 2 + _Val2 / 2;
} else {
using _Unsigned = make_unsigned_t<_Ty>;
const auto _Val1_u = static_cast<_Unsigned>(_Val1);
const auto _Val2_u = static_cast<_Unsigned>(_Val2);
if (_Val1 > _Val2) {
return static_cast<_Ty>(_Val1 - static_cast<_Ty>(static_cast<_Unsigned>(_Val1_u - _Val2_u) / 2));
} else {
return static_cast<_Ty>(_Val1 + static_cast<_Ty>(static_cast<_Unsigned>(_Val2_u - _Val1_u) / 2));
}
}
}
_EXPORT_STD template <class _Ty>
requires is_object_v<_Ty>
_NODISCARD constexpr _Ty* midpoint(_Ty* const _Val1, _Ty* const _Val2) noexcept /* strengthened */ {
if (_Val1 > _Val2) {
return _Val1 - ((_Val1 - _Val2) >> 1); // shift for codegen
} else {
return _Val1 + ((_Val2 - _Val1) >> 1); // shift for codegen
}
}
#endif // _HAS_CXX20
_STD_END
#pragma pop_macro("new")
_STL_RESTORE_CLANG_WARNINGS
#pragma warning(pop)
#pragma pack(pop)
#endif // _STL_COMPILER_PREPROCESSOR
#endif // _NUMERIC_