Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions benchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ endfunction()
add_benchmark(bitset_to_string src/bitset_to_string.cpp)
add_benchmark(find_and_count src/find_and_count.cpp)
add_benchmark(find_first_of src/find_first_of.cpp)
add_benchmark(iota src/iota.cpp)
add_benchmark(locale_classic src/locale_classic.cpp)
add_benchmark(minmax_element src/minmax_element.cpp)
add_benchmark(mismatch src/mismatch.cpp)
Expand Down
29 changes: 29 additions & 0 deletions benchmarks/src/iota.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <benchmark/benchmark.h>
#include <cstddef>
#include <cstdint>
#include <numeric>
#include <vector>

template <class T>
void bm(benchmark::State& state) {
const auto size = static_cast<std::size_t>(state.range(0));

std::vector<T> a(size);

for (auto _ : state) {
std::iota(a.begin(), a.end(), T{22});
benchmark::DoNotOptimize(a);
}
}

void common_args(auto bm) {
bm->Arg(7)->Arg(18)->Arg(43)->Arg(131)->Arg(315)->Arg(1212);
}

BENCHMARK(bm<std::uint32_t>)->Apply(common_args);
BENCHMARK(bm<std::uint64_t>)->Apply(common_args);

BENCHMARK_MAIN();
16 changes: 16 additions & 0 deletions stl/inc/numeric
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,22 @@ _CONSTEXPR20 void iota(_FwdIt _First, _FwdIt _Last, _Ty _Val) {
_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;
}
Expand Down
96 changes: 62 additions & 34 deletions stl/inc/utility
Original file line number Diff line number Diff line change
Expand Up @@ -788,20 +788,12 @@ _EXPORT_STD template <size_t _Idx>
constexpr in_place_index_t<_Idx> in_place_index{};
#endif // _HAS_CXX17

#if _HAS_CXX20
template <class _Ty>
constexpr bool _Is_standard_integer = is_integral_v<_Ty>
&& !_Is_any_of_v<remove_cv_t<_Ty>, bool, char,
#ifdef _NATIVE_WCHAR_T_DEFINED
wchar_t,
#endif // _NATIVE_WCHAR_T_DEFINED
#ifdef __cpp_char8_t
char8_t,
#endif // defined(__cpp_char8_t)
char16_t, char32_t>;
constexpr bool _Is_standard_integer = _Is_any_of_v<remove_cv_t<_Ty>, signed char, short, int, long, long long,
unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long>;

_EXPORT_STD template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool cmp_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept {
template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool _Cmp_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept {
static_assert(_Is_standard_integer<_Ty1> && _Is_standard_integer<_Ty2>,
"The integer comparison functions only accept standard and extended integer types.");
if constexpr (is_signed_v<_Ty1> == is_signed_v<_Ty2>) {
Expand All @@ -813,13 +805,13 @@ _NODISCARD constexpr bool cmp_equal(const _Ty1 _Left, const _Ty2 _Right) noexcep
}
}

_EXPORT_STD template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool cmp_not_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept {
return !_STD cmp_equal(_Left, _Right);
template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool _Cmp_not_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept {
return !_STD _Cmp_equal(_Left, _Right);
}

_EXPORT_STD template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool cmp_less(const _Ty1 _Left, const _Ty2 _Right) noexcept {
template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool _Cmp_less(const _Ty1 _Left, const _Ty2 _Right) noexcept {
static_assert(_Is_standard_integer<_Ty1> && _Is_standard_integer<_Ty2>,
"The integer comparison functions only accept standard and extended integer types.");
if constexpr (is_signed_v<_Ty1> == is_signed_v<_Ty2>) {
Expand All @@ -831,24 +823,24 @@ _NODISCARD constexpr bool cmp_less(const _Ty1 _Left, const _Ty2 _Right) noexcept
}
}

_EXPORT_STD template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool cmp_greater(const _Ty1 _Left, const _Ty2 _Right) noexcept {
return _STD cmp_less(_Right, _Left);
template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool _Cmp_greater(const _Ty1 _Left, const _Ty2 _Right) noexcept {
return _STD _Cmp_less(_Right, _Left);
}

_EXPORT_STD template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool cmp_less_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept {
return !_STD cmp_less(_Right, _Left);
template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool _Cmp_less_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept {
return !_STD _Cmp_less(_Right, _Left);
}

_EXPORT_STD template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool cmp_greater_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept {
return !_STD cmp_less(_Left, _Right);
template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool _Cmp_greater_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept {
return !_STD _Cmp_less(_Left, _Right);
}

template <class _Ty>
_NODISCARD consteval _Ty _Min_limit() noexcept { // same as (numeric_limits<_Ty>::min)(), less throughput cost
static_assert(_Is_standard_integer<_Ty>); // doesn't attempt to handle all types
_NODISCARD constexpr _Ty _Min_limit() noexcept { // same as (numeric_limits<_Ty>::min)(), less throughput cost
_STL_INTERNAL_STATIC_ASSERT(_Is_standard_integer<_Ty>); // doesn't attempt to handle all types
if constexpr (is_signed_v<_Ty>) {
constexpr auto _Unsigned_max = static_cast<make_unsigned_t<_Ty>>(-1);
return static_cast<_Ty>((_Unsigned_max >> 1) + 1); // well-defined, N4950 [conv.integral]/3
Expand All @@ -858,8 +850,8 @@ _NODISCARD consteval _Ty _Min_limit() noexcept { // same as (numeric_limits<_Ty>
}

template <class _Ty>
_NODISCARD consteval _Ty _Max_limit() noexcept { // same as (numeric_limits<_Ty>::max)(), less throughput cost
static_assert(_Is_standard_integer<_Ty>); // doesn't attempt to handle all types
_NODISCARD constexpr _Ty _Max_limit() noexcept { // same as (numeric_limits<_Ty>::max)(), less throughput cost
_STL_INTERNAL_STATIC_ASSERT(_Is_standard_integer<_Ty>); // doesn't attempt to handle all types
if constexpr (is_signed_v<_Ty>) {
constexpr auto _Unsigned_max = static_cast<make_unsigned_t<_Ty>>(-1);
return static_cast<_Ty>(_Unsigned_max >> 1);
Expand All @@ -868,15 +860,15 @@ _NODISCARD consteval _Ty _Max_limit() noexcept { // same as (numeric_limits<_Ty>
}
}

_EXPORT_STD template <class _Rx, class _Ty>
_NODISCARD constexpr bool in_range(const _Ty _Value) noexcept {
template <class _Rx, class _Ty>
_NODISCARD constexpr bool _In_range(const _Ty _Value) noexcept {
static_assert(_Is_standard_integer<_Rx> && _Is_standard_integer<_Ty>,
"The integer comparison functions only accept standard and extended integer types.");

constexpr auto _Ty_min = _Min_limit<_Ty>();
constexpr auto _Rx_min = _Min_limit<_Rx>();

if constexpr (_STD cmp_less(_Ty_min, _Rx_min)) {
if constexpr (_STD _Cmp_less(_Ty_min, _Rx_min)) {
if (_Value < _Ty{_Rx_min}) {
return false;
}
Expand All @@ -885,14 +877,50 @@ _NODISCARD constexpr bool in_range(const _Ty _Value) noexcept {
constexpr auto _Ty_max = _Max_limit<_Ty>();
constexpr auto _Rx_max = _Max_limit<_Rx>();

if constexpr (_STD cmp_greater(_Ty_max, _Rx_max)) {
if constexpr (_STD _Cmp_greater(_Ty_max, _Rx_max)) {
if (_Value > _Ty{_Rx_max}) {
return false;
}
}

return true;
}

#if _HAS_CXX20
_EXPORT_STD template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool cmp_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept {
return _STD _Cmp_equal(_Left, _Right);
}

_EXPORT_STD template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool cmp_not_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept {
return _STD _Cmp_not_equal(_Left, _Right);
}

_EXPORT_STD template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool cmp_less(const _Ty1 _Left, const _Ty2 _Right) noexcept {
return _STD _Cmp_less(_Left, _Right);
}

_EXPORT_STD template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool cmp_greater(const _Ty1 _Left, const _Ty2 _Right) noexcept {
return _STD _Cmp_greater(_Left, _Right);
}

_EXPORT_STD template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool cmp_less_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept {
return _STD _Cmp_less_equal(_Left, _Right);
}

_EXPORT_STD template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool cmp_greater_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept {
return _STD _Cmp_greater_equal(_Left, _Right);
}

_EXPORT_STD template <class _Rx, class _Ty>
_NODISCARD constexpr bool in_range(const _Ty _Value) noexcept {
return _STD _In_range<_Rx>(_Value);
}
#endif // _HAS_CXX20

#if _HAS_CXX23
Expand Down