diff --git a/stl/inc/valarray b/stl/inc/valarray index d17080150c7..4c50bff4795 100644 --- a/stl/inc/valarray +++ b/stl/inc/valarray @@ -938,9 +938,16 @@ public: slice_array() = delete; - slice_array(const slice_array&); // not defined + slice_array(const slice_array&) = default; - slice_array& operator=(const slice_array&); // not defined + const slice_array& operator=(const slice_array& _Right) const { + size_t _Dst_off = _Start; + size_t _Src_off = _Right._Start; + for (size_t _Idx = 0; _Idx < _Len; ++_Idx, _Dst_off += _Stride, _Src_off += _Right._Stride) { + _Myptr[_Dst_off] = _Right._Myptr[_Src_off]; + } + return *this; + } private: friend valarray<_Ty>; @@ -992,7 +999,7 @@ public: return _Ans; } - size_t _Totlen() const { + _NODISCARD size_t _Totlen() const { if (_Len.size() == 0) { return 0; } @@ -1073,15 +1080,23 @@ public: _GSLOP(>>= _Right[_Idx]); } - _Ty& _Data(size_t _Idx) const { + _NODISCARD _Ty& _Data(size_t _Idx) const { return _Myptr[_Idx]; } gslice_array() = delete; - gslice_array(const gslice_array&); // not defined + gslice_array(const gslice_array&) = default; - gslice_array& operator=(const gslice_array&); // not defined + const gslice_array& operator=(const gslice_array& _Right) const { + _Sizarray _Dst_indexarray(size_t{0}, _Nslice()); + _Sizarray _Src_indexarray(size_t{0}, _Right._Nslice()); + const size_t _Size = _Totlen(); + for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { + _Myptr[_Off(_Dst_indexarray)] = _Right._Myptr[_Right._Off(_Src_indexarray)]; + } + return *this; + } private: friend valarray<_Ty>; @@ -1155,15 +1170,32 @@ public: _MOP(>>= _Right[_Idx]); } - _Ty& _Data(size_t _Idx) const { + _NODISCARD _Ty& _Data(size_t _Idx) const { return _Myptr[_Idx]; } - bool _Mask(size_t _Idx) const { + _NODISCARD bool _Mask(size_t _Idx) const { return _Mybool[_Idx]; } - size_t _Totlen() const { + _NODISCARD size_t _Start_off() const { + size_t _Off = 0; + const size_t _Size = _Mybool.size(); + while (_Off < _Size && !_Mybool[_Off]) { + ++_Off; + } + return _Off; + } + + _NODISCARD size_t _Next_off(size_t _Off) const { + const size_t _Size = _Mybool.size(); + do { + ++_Off; + } while (_Off < _Size && !_Mybool[_Off]); + return _Off; + } + + _NODISCARD size_t _Totlen() const { size_t _Count = 0; for (size_t _Idx = 0; _Idx < _Mybool.size(); ++_Idx) { if (_Mybool[_Idx]) { @@ -1176,9 +1208,17 @@ public: mask_array() = delete; - mask_array(const mask_array&); // not defined + mask_array(const mask_array&) = default; - mask_array& operator=(const mask_array&); // not defined + const mask_array& operator=(const mask_array& _Right) const { + const size_t _Size = _Mybool.size(); + size_t _Dst_off = _Start_off(); + size_t _Src_off = _Right._Start_off(); + for (; _Dst_off < _Size; _Src_off = _Right._Next_off(_Src_off), _Dst_off = _Next_off(_Dst_off)) { + _Myptr[_Dst_off] = _Right._Myptr[_Src_off]; + } + return *this; + } private: friend valarray<_Ty>; @@ -1250,23 +1290,29 @@ public: _IOP(>>= _Right[_Idx]); } - _Ty& _Data(size_t _Idx) const { + _NODISCARD _Ty& _Data(size_t _Idx) const { return _Myptr[_Idx]; } - size_t _Indir(size_t _Idx) const { + _NODISCARD size_t _Indir(size_t _Idx) const { return _Myindarr[_Idx]; } - size_t _Totlen() const { + _NODISCARD size_t _Totlen() const { return _Myindarr.size(); } indirect_array() = delete; - indirect_array(const indirect_array&); // not defined + indirect_array(const indirect_array&) = default; - indirect_array& operator=(const indirect_array&); // not defined + const indirect_array& operator=(const indirect_array& _Right) const { + const size_t _Size = _Totlen(); + for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { + _Myptr[_Indir(_Idx)] = _Right._Myptr[_Right._Indir(_Idx)]; + } + return *this; + } private: friend valarray<_Ty>; diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index b2753dc3709..8c91cb2d01e 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -565,10 +565,6 @@ std/re/re.traits/transform.pass.cpp FAIL # STL bug: Incorrect return types. std/numerics/complex.number/cmplx.over/pow.pass.cpp FAIL -# STL bug: Missing assignment operators. -std/numerics/numarray/template.mask.array/mask.array.assign/mask_array.pass.cpp FAIL -std/numerics/numarray/template.slice.array/slice.arr.assign/slice_array.pass.cpp FAIL - # STL bug: We allow fill() and swap() for array. std/containers/sequences/array/array.fill/fill.fail.cpp FAIL std/containers/sequences/array/array.swap/swap.fail.cpp FAIL diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index 6f62c1c1b7d..61804e09fba 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -565,10 +565,6 @@ re\re.traits\transform.pass.cpp # STL bug: Incorrect return types. numerics\complex.number\cmplx.over\pow.pass.cpp -# STL bug: Missing assignment operators. -numerics\numarray\template.mask.array\mask.array.assign\mask_array.pass.cpp -numerics\numarray\template.slice.array\slice.arr.assign\slice_array.pass.cpp - # STL bug: We allow fill() and swap() for array. containers\sequences\array\array.fill\fill.fail.cpp containers\sequences\array\array.swap\swap.fail.cpp diff --git a/tests/std/test.lst b/tests/std/test.lst index dc0c7187509..9ce41e6b7c2 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -160,6 +160,7 @@ tests\GH_000545_include_compare tests\GH_000685_condition_variable_any tests\GH_000690_overaligned_function tests\GH_000890_pow_template +tests\GH_000940_missing_valarray_copy tests\GH_001010_filesystem_error_encoding tests\GH_001017_discrete_distribution_out_of_range tests\LWG2597_complex_branch_cut diff --git a/tests/std/tests/GH_000940_missing_valarray_copy/env.lst b/tests/std/tests/GH_000940_missing_valarray_copy/env.lst new file mode 100644 index 00000000000..19f025bd0e6 --- /dev/null +++ b/tests/std/tests/GH_000940_missing_valarray_copy/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_matrix.lst diff --git a/tests/std/tests/GH_000940_missing_valarray_copy/test.cpp b/tests/std/tests/GH_000940_missing_valarray_copy/test.cpp new file mode 100644 index 00000000000..91106130487 --- /dev/null +++ b/tests/std/tests/GH_000940_missing_valarray_copy/test.cpp @@ -0,0 +1,87 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include + +template +bool eq(const std::valarray& v, std::initializer_list il) { + return std::equal(begin(v), end(v), il.begin(), il.end()); +} + +void test_slice() { + std::valarray v{0, 1, 2, 3, 4}; + + std::slice_array slice_array = v[std::slice(2, 2, 2)]; + std::slice_array slice_array_copy = slice_array; + (void) slice_array_copy; + + assert(eq(v, {0, 1, 2, 3, 4})); + + std::slice_array other_slice_array = v[std::slice(0, 2, 1)]; + other_slice_array = slice_array; + + assert(eq(v, {2, 4, 2, 3, 4})); +} + +void test_gslice() { + std::valarray v{0, 1, 2, 3, 4}; + + std::gslice gslice(2, std::valarray{2}, std::valarray{2}); + std::gslice_array gslice_array = v[gslice]; + std::gslice_array gslice_array_copy = gslice_array; + (void) gslice_array_copy; + + assert(eq(v, {0, 1, 2, 3, 4})); + + std::gslice other_gslice(0, std::valarray{2}, std::valarray{1}); + std::gslice_array other_gslice_array = v[other_gslice]; + other_gslice_array = gslice_array; + + assert(eq(v, {2, 4, 2, 3, 4})); +} + +void test_mask() { + std::valarray v{0, 1, 2, 3, 4}; + + std::valarray mask{true, false, false, false, true}; + std::mask_array mask_array = v[mask]; + std::mask_array mask_array_copy = mask_array; + (void) mask_array_copy; + + assert(eq(v, {0, 1, 2, 3, 4})); + + std::valarray other_mask{false, true, true, false, false}; + std::mask_array other_mask_array = v[other_mask]; + other_mask_array = mask_array; + + assert(eq(v, {0, 0, 4, 3, 4})); +} + +void test_indirect() { + std::valarray v{0, 1, 2, 3, 4}; + + std::valarray indices{2, 3}; + std::indirect_array indirect_array = v[indices]; + std::indirect_array indirect_array_copy = indirect_array; + (void) indirect_array_copy; + + assert(eq(v, {0, 1, 2, 3, 4})); + + std::valarray other_indices{4, 0}; + std::indirect_array other_indirect_array = v[other_indices]; + other_indirect_array = indirect_array; + + assert(eq(v, {3, 1, 2, 3, 2})); +} + +int main() { + test_slice(); + test_gslice(); + test_mask(); + test_indirect(); + return 0; +}