зеркало из https://github.com/microsoft/STL.git
`<mdspan>`: Fixes signed overflow in `_Fwd_prod_of_extents` (#4037)
Co-authored-by: Stephan T. Lavavej <stl@nuwen.net>
This commit is contained in:
Родитель
11c8fc3bfa
Коммит
a577749de0
|
@ -348,11 +348,13 @@ public:
|
|||
if constexpr (_Extents::rank() == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
typename _Extents::index_type _Result = 1;
|
||||
// Use an unsigned type to prevent overflow when called from mdspan::size.
|
||||
typename _Extents::size_type _Result = 1;
|
||||
for (size_t _Dim = 0; _Dim < _Idx; ++_Dim) {
|
||||
_Result *= _Exts.extent(_Dim);
|
||||
_Result *= static_cast<_Extents::size_type>(_Exts.extent(_Dim));
|
||||
}
|
||||
return _Result;
|
||||
|
||||
return static_cast<_Extents::index_type>(_Result);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -231,6 +231,7 @@ tests\GH_003676_format_large_hh_mm_ss_values
|
|||
tests\GH_003735_char_traits_signatures
|
||||
tests\GH_003840_tellg_when_reading_lf_file_in_text_mode
|
||||
tests\GH_003867_output_nan
|
||||
tests\GH_004023_mdspan_fwd_prod_overflow
|
||||
tests\LWG2381_num_get_floating_point
|
||||
tests\LWG2597_complex_branch_cut
|
||||
tests\LWG3018_shared_ptr_function
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
RUNALL_INCLUDE ..\concepts_latest_matrix.lst
|
|
@ -0,0 +1,79 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <mdspan>
|
||||
#include <type_traits>
|
||||
|
||||
using namespace std;
|
||||
|
||||
struct layout_packed_upper { // LAPACK packed storage, VERY INCOMPLETE
|
||||
template <class Extents>
|
||||
class mapping {
|
||||
public:
|
||||
using extents_type = Extents;
|
||||
using index_type = extents_type::index_type;
|
||||
using size_type = extents_type::size_type;
|
||||
using rank_type = extents_type::rank_type;
|
||||
using layout_type = layout_packed_upper;
|
||||
|
||||
constexpr mapping() noexcept = default;
|
||||
constexpr mapping(const extents_type& ex_) : ex{ex_} {}
|
||||
|
||||
constexpr const extents_type& extents() const {
|
||||
return ex;
|
||||
}
|
||||
|
||||
constexpr index_type required_span_size() const {
|
||||
if (dim % 2 == 0) {
|
||||
return (dim / 2) * (dim + 1);
|
||||
} else {
|
||||
return ((dim + 1) / 2) * dim;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
extents_type ex = extents_type();
|
||||
index_type dim = ex.extent(0);
|
||||
};
|
||||
};
|
||||
|
||||
int main() {
|
||||
constexpr int32_t dim = 47'000; // sqrt(2^32) > dim > sqrt(2^31), dim assumed even below
|
||||
constexpr auto expected_size = [] {
|
||||
int32_t unused;
|
||||
bool overflow = _Mul_overflow(dim, dim, unused);
|
||||
assert(overflow);
|
||||
|
||||
using UType = remove_cv_t<make_unsigned_t<decltype(dim)>>;
|
||||
const auto udim = static_cast<UType>(dim);
|
||||
UType result{};
|
||||
overflow = _Mul_overflow(udim, udim, result);
|
||||
assert(!overflow);
|
||||
return result;
|
||||
}();
|
||||
|
||||
constexpr auto expected_req_size = [] {
|
||||
int32_t result{};
|
||||
const bool overflow = _Mul_overflow(dim / 2, dim + 1, result);
|
||||
assert(!overflow);
|
||||
return result;
|
||||
}();
|
||||
|
||||
{
|
||||
using E = extents<int32_t, dim, dim>;
|
||||
constexpr mdspan<double, E, layout_packed_upper> m(nullptr);
|
||||
static_assert(m.size() == expected_size);
|
||||
static_assert(m.mapping().required_span_size() == expected_req_size);
|
||||
}
|
||||
|
||||
{
|
||||
using E = dextents<int32_t, 2>;
|
||||
constexpr mdspan<double, E, layout_packed_upper> m(nullptr, dim, dim);
|
||||
static_assert(m.size() == expected_size);
|
||||
static_assert(m.mapping().required_span_size() == expected_req_size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Загрузка…
Ссылка в новой задаче