зеркало из https://github.com/microsoft/STL.git
1366 строки
42 KiB
C++
1366 строки
42 KiB
C++
// valarray standard header
|
|
|
|
// Copyright (c) Microsoft Corporation.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#pragma once
|
|
#ifndef _VALARRAY_
|
|
#define _VALARRAY_
|
|
#include <yvals_core.h>
|
|
#if _STL_COMPILER_PREPROCESSOR
|
|
#include <cmath>
|
|
#include <xmemory>
|
|
|
|
#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
|
|
// FORWARD REFERENCES
|
|
class gslice;
|
|
class slice;
|
|
|
|
template <class _Ty>
|
|
class gslice_array;
|
|
template <class _Ty>
|
|
class indirect_array;
|
|
template <class _Ty>
|
|
class mask_array;
|
|
template <class _Ty>
|
|
class slice_array;
|
|
template <class _Ty>
|
|
class valarray;
|
|
|
|
// FUNCTION TEMPLATE _Allocate_for_op_delete
|
|
template <class _Ty>
|
|
_Ty* _Allocate_for_op_delete(size_t _Count) {
|
|
// allocates space for _Count copies of _Ty, which will be freed with scalar delete
|
|
if (_Count == 0) {
|
|
return nullptr;
|
|
}
|
|
|
|
const size_t _Bytes = _Get_size_of_n<sizeof(_Ty)>(_Count);
|
|
#ifdef __cpp_aligned_new
|
|
constexpr bool _Extended_alignment = alignof(_Ty) > __STDCPP_DEFAULT_NEW_ALIGNMENT__;
|
|
if _CONSTEXPR_IF (_Extended_alignment) {
|
|
return static_cast<_Ty*>(::operator new (_Bytes, align_val_t{alignof(_Ty)}));
|
|
} else
|
|
#endif // __cpp_aligned_new
|
|
{
|
|
return static_cast<_Ty*>(::operator new(_Bytes));
|
|
}
|
|
}
|
|
|
|
using _Boolarray = valarray<bool>;
|
|
using _Sizarray = valarray<size_t>;
|
|
|
|
// MACROS FOR valarray
|
|
#define _VALOP(TYPE, LENGTH, RHS) /* assign RHS(_Idx) to new valarray */ \
|
|
valarray<TYPE> _Ans(LENGTH); \
|
|
for (size_t _Idx = 0; _Idx < _Ans.size(); ++_Idx) { \
|
|
_Ans[_Idx] = RHS; \
|
|
} \
|
|
return _Ans
|
|
|
|
#define _VALGOP(RHS) /* apply RHS(_Idx) to valarray */ \
|
|
for (size_t _Idx = 0; _Idx < size(); ++_Idx) { \
|
|
_Myptr[_Idx] RHS; \
|
|
} \
|
|
return *this
|
|
|
|
// CLASS TEMPLATE valarray
|
|
template <class _Ty>
|
|
class valarray { // store array with various indexing options
|
|
private:
|
|
friend _Tidy_deallocate_guard<valarray>;
|
|
|
|
public:
|
|
using value_type = _Ty;
|
|
|
|
valarray() { // construct empty valarray
|
|
_Tidy_init();
|
|
}
|
|
|
|
explicit valarray(size_t _Count) { // construct with _Count * _Ty()
|
|
_Tidy_init();
|
|
_Grow(_Count);
|
|
}
|
|
|
|
valarray(const _Ty& _Val, size_t _Count) { // construct with _Count * _Val
|
|
_Tidy_init();
|
|
_Grow(_Count, &_Val);
|
|
}
|
|
|
|
valarray(const _Ty* _Ptr, size_t _Count) { // construct with [_Ptr, _Ptr + _Count)
|
|
_Tidy_init();
|
|
_Grow(_Count, _Ptr, 1);
|
|
}
|
|
|
|
valarray(const valarray& _Right) {
|
|
_Tidy_init();
|
|
_Grow(_Right.size(), _Right._Myptr, 1);
|
|
}
|
|
|
|
valarray(const slice_array<_Ty>& _Slicearr) {
|
|
_Tidy_init();
|
|
*this = _Slicearr;
|
|
}
|
|
|
|
valarray(const gslice_array<_Ty>& _Gslicearr) {
|
|
_Tidy_init();
|
|
*this = _Gslicearr;
|
|
}
|
|
|
|
valarray(const mask_array<_Ty>& _Maskarr) {
|
|
_Tidy_init();
|
|
*this = _Maskarr;
|
|
}
|
|
|
|
valarray(const indirect_array<_Ty>& _Indarr) {
|
|
_Tidy_init();
|
|
*this = _Indarr;
|
|
}
|
|
|
|
valarray(valarray&& _Right) noexcept {
|
|
_Tidy_init();
|
|
_Assign_rv(_STD move(_Right));
|
|
}
|
|
|
|
valarray& operator=(valarray&& _Right) noexcept {
|
|
_Assign_rv(_STD move(_Right));
|
|
return *this;
|
|
}
|
|
|
|
void _Assign_rv(valarray&& _Right) {
|
|
if (this != _STD addressof(_Right)) { // clear this and steal from _Right
|
|
_Tidy_deallocate();
|
|
_Myptr = _Right._Myptr;
|
|
_Mysize = _Right._Mysize;
|
|
_Right._Tidy_init();
|
|
}
|
|
}
|
|
|
|
valarray(initializer_list<_Ty> _Ilist) {
|
|
_Tidy_init();
|
|
_Grow(_Ilist.size(), _Ilist.begin(), 1);
|
|
}
|
|
|
|
valarray& operator=(initializer_list<_Ty> _Ilist) {
|
|
_Assign(_Ilist.size(), _Ilist.begin());
|
|
return *this;
|
|
}
|
|
|
|
void swap(valarray& _Right) noexcept {
|
|
if (this != _STD addressof(_Right)) {
|
|
_STD swap(_Myptr, _Right._Myptr);
|
|
_STD swap(_Mysize, _Right._Mysize);
|
|
}
|
|
}
|
|
|
|
~valarray() noexcept {
|
|
_Tidy_deallocate();
|
|
}
|
|
|
|
valarray& operator=(const valarray& _Right) {
|
|
if (this != _STD addressof(_Right)) {
|
|
_Assign(_Right.size(), _Right._Myptr);
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
valarray& operator=(const _Ty& _Val) {
|
|
_VALGOP(= _Val);
|
|
}
|
|
|
|
void resize(size_t _Newsize) { // determine new length, filling with _Ty() elements
|
|
_Tidy_deallocate();
|
|
_Grow(_Newsize);
|
|
}
|
|
|
|
void resize(size_t _Newsize, _Ty _Val) { // determine new length, filling with _Val elements
|
|
_Tidy_deallocate();
|
|
_Grow(_Newsize, &_Val, 0);
|
|
}
|
|
|
|
valarray& operator=(const slice_array<_Ty>& _Slicearr); // defined below
|
|
|
|
valarray& operator=(const gslice_array<_Ty>& _Gslicearr); // defined below
|
|
|
|
valarray& operator=(const mask_array<_Ty>& _Maskarr); // defined below
|
|
|
|
valarray& operator=(const indirect_array<_Ty>& _Indarr); // defined below
|
|
|
|
_NODISCARD valarray operator+() const {
|
|
_VALOP(_Ty, size(), +_Myptr[_Idx]);
|
|
}
|
|
|
|
_NODISCARD valarray operator-() const {
|
|
_VALOP(_Ty, size(), -_Myptr[_Idx]);
|
|
}
|
|
|
|
_NODISCARD valarray operator~() const {
|
|
_VALOP(_Ty, size(), ~_Myptr[_Idx]);
|
|
}
|
|
|
|
_NODISCARD _Boolarray operator!() const {
|
|
_VALOP(bool, size(), !_Myptr[_Idx]);
|
|
}
|
|
|
|
valarray& operator*=(const _Ty& _Right) {
|
|
_VALGOP(*= _Right);
|
|
}
|
|
|
|
valarray& operator/=(const _Ty& _Right) {
|
|
_VALGOP(/= _Right);
|
|
}
|
|
|
|
valarray& operator%=(const _Ty& _Right) {
|
|
_VALGOP(%= _Right);
|
|
}
|
|
|
|
valarray& operator+=(const _Ty& _Right) {
|
|
_VALGOP(+= _Right);
|
|
}
|
|
|
|
valarray& operator-=(const _Ty& _Right) {
|
|
_VALGOP(-= _Right);
|
|
}
|
|
|
|
valarray& operator^=(const _Ty& _Right) {
|
|
_VALGOP(^= _Right);
|
|
}
|
|
|
|
valarray& operator&=(const _Ty& _Right) {
|
|
_VALGOP(&= _Right);
|
|
}
|
|
|
|
valarray& operator|=(const _Ty& _Right) {
|
|
_VALGOP(|= _Right);
|
|
}
|
|
|
|
valarray& operator<<=(const _Ty& _Right) {
|
|
_VALGOP(<<= _Right);
|
|
}
|
|
|
|
valarray& operator>>=(const _Ty& _Right) {
|
|
_VALGOP(>>= _Right);
|
|
}
|
|
|
|
valarray& operator*=(const valarray& _Right) {
|
|
_VALGOP(*= _Right[_Idx]);
|
|
}
|
|
|
|
valarray& operator/=(const valarray& _Right) {
|
|
_VALGOP(/= _Right[_Idx]);
|
|
}
|
|
|
|
valarray& operator%=(const valarray& _Right) {
|
|
_VALGOP(%= _Right[_Idx]);
|
|
}
|
|
|
|
valarray& operator+=(const valarray& _Right) {
|
|
_VALGOP(+= _Right[_Idx]);
|
|
}
|
|
|
|
valarray& operator-=(const valarray& _Right) {
|
|
_VALGOP(-= _Right[_Idx]);
|
|
}
|
|
|
|
valarray& operator^=(const valarray& _Right) {
|
|
_VALGOP(^= _Right[_Idx]);
|
|
}
|
|
|
|
valarray& operator|=(const valarray& _Right) {
|
|
_VALGOP(|= _Right[_Idx]);
|
|
}
|
|
|
|
valarray& operator&=(const valarray& _Right) {
|
|
_VALGOP(&= _Right[_Idx]);
|
|
}
|
|
|
|
valarray& operator<<=(const valarray& _Right) {
|
|
_VALGOP(<<= _Right[_Idx]);
|
|
}
|
|
|
|
valarray& operator>>=(const valarray& _Right) {
|
|
_VALGOP(>>= _Right[_Idx]);
|
|
}
|
|
|
|
_NODISCARD size_t size() const noexcept /* strengthened */ {
|
|
return _Mysize;
|
|
}
|
|
|
|
_NODISCARD const _Ty& operator[](size_t _Off) const noexcept /* strengthened */ {
|
|
return _Myptr[_Off];
|
|
}
|
|
|
|
_NODISCARD _Ty& operator[](size_t _Off) noexcept /* strengthened */ {
|
|
return _Myptr[_Off];
|
|
}
|
|
|
|
_NODISCARD valarray operator[](slice _Slicearr) const; // defined below
|
|
|
|
_NODISCARD slice_array<_Ty> operator[](slice _Slicearr); // defined below
|
|
|
|
_NODISCARD valarray operator[](const gslice& _Gslicearr) const; // defined below
|
|
|
|
_NODISCARD gslice_array<_Ty> operator[](const gslice& _Gslicearr); // defined below
|
|
|
|
_NODISCARD valarray operator[](const _Boolarray& _Boolarr) const; // defined below
|
|
|
|
_NODISCARD mask_array<_Ty> operator[](const _Boolarray& _Boolarr); // defined below
|
|
|
|
_NODISCARD valarray operator[](const _Sizarray& _Indarr) const; // defined below
|
|
|
|
_NODISCARD indirect_array<_Ty> operator[](const _Sizarray& _Indarr); // defined below
|
|
|
|
_NODISCARD _Ty sum() const {
|
|
_Ty _Sum = _Myptr[0];
|
|
for (size_t _Idx = 1; _Idx < size(); ++_Idx) {
|
|
_Sum += _Myptr[_Idx];
|
|
}
|
|
|
|
return _Sum;
|
|
}
|
|
|
|
_NODISCARD _Ty(min)() const {
|
|
_Ty _Min = _Myptr[0];
|
|
for (size_t _Idx = 1; _Idx < size(); ++_Idx) {
|
|
if (_Myptr[_Idx] < _Min) {
|
|
_Min = _Myptr[_Idx];
|
|
}
|
|
}
|
|
|
|
return _Min;
|
|
}
|
|
|
|
_NODISCARD _Ty(max)() const {
|
|
_Ty _Max = _Myptr[0];
|
|
for (size_t _Idx = 1; _Idx < size(); ++_Idx) {
|
|
if (_Max < _Myptr[_Idx]) {
|
|
_Max = _Myptr[_Idx];
|
|
}
|
|
}
|
|
|
|
return _Max;
|
|
}
|
|
|
|
_NODISCARD valarray shift(int _Count) const {
|
|
__PURE_APPDOMAIN_GLOBAL static _Ty _Dflt;
|
|
_VALOP(_Ty, size(),
|
|
(0 < _Count && size() - _Idx <= static_cast<size_t>(_Count))
|
|
|| (_Count < 0 && _Idx < static_cast<size_t>(-_Count))
|
|
? _Dflt
|
|
: _Myptr[_Idx + _Count]);
|
|
}
|
|
|
|
_NODISCARD valarray cshift(int _Count) const {
|
|
if (size() != 0) {
|
|
if (_Count < 0) { // right shift
|
|
if (size() < size_t{0} - _Count) {
|
|
_Count = static_cast<int>(size() - (size_t{0} - _Count - size()) % size());
|
|
} else {
|
|
_Count = static_cast<int>(size() + _Count);
|
|
}
|
|
} else if (size() <= static_cast<size_t>(_Count)) {
|
|
_Count %= size();
|
|
}
|
|
}
|
|
|
|
_VALOP(_Ty, size(),
|
|
size() - _Idx <= static_cast<size_t>(_Count) ? _Myptr[_Idx - size() + _Count] : _Myptr[_Idx + _Count]);
|
|
}
|
|
|
|
_NODISCARD valarray apply(_Ty _Func(_Ty)) const {
|
|
_VALOP(_Ty, size(), _Func(_Myptr[_Idx]));
|
|
}
|
|
|
|
_NODISCARD valarray apply(_Ty _Func(const _Ty&)) const {
|
|
// return valarray transformed by _Func, nonmutable argument
|
|
_VALOP(_Ty, size(), _Func(_Myptr[_Idx]));
|
|
}
|
|
|
|
private:
|
|
void _Grow(size_t _Newsize) { // allocate space for _Count elements and fill with default values
|
|
if (0 < _Newsize) { // worth doing, allocate
|
|
_Myptr = _Allocate_for_op_delete<_Ty>(_Newsize);
|
|
_Tidy_deallocate_guard<valarray> _Guard{this};
|
|
for (size_t _Idx = 0; _Idx < _Newsize; ++_Idx) {
|
|
_Construct_in_place(_Myptr[_Idx]);
|
|
}
|
|
|
|
_Guard._Target = nullptr;
|
|
_Mysize = _Newsize;
|
|
}
|
|
}
|
|
|
|
void _Grow(size_t _Newsize, const _Ty* _Ptr, size_t _Inc = 0) {
|
|
// allocate space for _Count elements and fill with *_Ptr
|
|
if (0 < _Newsize) { // worth doing, allocate
|
|
_Myptr = _Allocate_for_op_delete<_Ty>(_Newsize);
|
|
_Tidy_deallocate_guard<valarray> _Guard{this};
|
|
for (size_t _Idx = 0; _Idx < _Newsize; ++_Idx, _Ptr += _Inc) {
|
|
_Construct_in_place(_Myptr[_Idx], *_Ptr);
|
|
}
|
|
|
|
_Guard._Target = nullptr;
|
|
_Mysize = _Newsize;
|
|
}
|
|
}
|
|
|
|
void _Tidy_init() noexcept {
|
|
_Mysize = 0;
|
|
_Myptr = nullptr;
|
|
}
|
|
|
|
void _Tidy_deallocate() noexcept {
|
|
if (_Myptr) { // destroy elements
|
|
for (size_t _Idx = 1; _Idx < _Mysize; ++_Idx) {
|
|
_Destroy_in_place(_Myptr[_Idx]);
|
|
}
|
|
|
|
delete _Myptr;
|
|
}
|
|
|
|
_Tidy_init();
|
|
}
|
|
|
|
void _Assign(size_t _Newsize, const _Ty* _Ptr) {
|
|
if (size() == _Newsize) {
|
|
for (size_t _Idx = 0; _Idx < size(); ++_Idx) {
|
|
_Myptr[_Idx] = _Ptr[_Idx];
|
|
}
|
|
} else { // resize and copy
|
|
_Tidy_deallocate();
|
|
_Grow(_Newsize, _Ptr, 1);
|
|
}
|
|
}
|
|
|
|
_Ty* _Myptr; // current storage reserved for array
|
|
size_t _Mysize; // current length of sequence
|
|
};
|
|
|
|
#if _HAS_CXX17
|
|
template <class _Ty, size_t _Nx>
|
|
valarray(const _Ty (&)[_Nx], size_t) -> valarray<_Ty>;
|
|
#endif // _HAS_CXX17
|
|
|
|
template <class _Ty>
|
|
void swap(valarray<_Ty>& _Left, valarray<_Ty>& _Right) noexcept {
|
|
_Left.swap(_Right);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Ty* begin(valarray<_Ty>& _Array) {
|
|
return &_Array[0];
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD const _Ty* begin(const valarray<_Ty>& _Array) {
|
|
return &_Array[0];
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Ty* end(valarray<_Ty>& _Array) {
|
|
return &_Array[0] + _Array.size();
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD const _Ty* end(const valarray<_Ty>& _Array) {
|
|
return &_Array[0] + _Array.size();
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator*(const valarray<_Ty>& _Left, const typename valarray<_Ty>::value_type& _Right) {
|
|
_VALOP(_Ty, _Left.size(), _Left[_Idx] * _Right);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator*(const typename valarray<_Ty>::value_type& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Right.size(), _Left * _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator/(const valarray<_Ty>& _Left, const typename valarray<_Ty>::value_type& _Right) {
|
|
_VALOP(_Ty, _Left.size(), _Left[_Idx] / _Right);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator/(const typename valarray<_Ty>::value_type& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Right.size(), _Left / _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator%(const valarray<_Ty>& _Left, const typename valarray<_Ty>::value_type& _Right) {
|
|
_VALOP(_Ty, _Left.size(), _Left[_Idx] % _Right);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator%(const typename valarray<_Ty>::value_type& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Right.size(), _Left % _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator+(const valarray<_Ty>& _Left, const typename valarray<_Ty>::value_type& _Right) {
|
|
_VALOP(_Ty, _Left.size(), _Left[_Idx] + _Right);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator+(const typename valarray<_Ty>::value_type& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Right.size(), _Left + _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator-(const valarray<_Ty>& _Left, const typename valarray<_Ty>::value_type& _Right) {
|
|
_VALOP(_Ty, _Left.size(), _Left[_Idx] - _Right);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator-(const typename valarray<_Ty>::value_type& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Right.size(), _Left - _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator^(const valarray<_Ty>& _Left, const typename valarray<_Ty>::value_type& _Right) {
|
|
_VALOP(_Ty, _Left.size(), _Left[_Idx] ^ _Right);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator^(const typename valarray<_Ty>::value_type& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Right.size(), _Left ^ _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator&(const valarray<_Ty>& _Left, const typename valarray<_Ty>::value_type& _Right) {
|
|
_VALOP(_Ty, _Left.size(), _Left[_Idx] & _Right);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator&(const typename valarray<_Ty>::value_type& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Right.size(), _Left & _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator|(const valarray<_Ty>& _Left, const typename valarray<_Ty>::value_type& _Right) {
|
|
_VALOP(_Ty, _Left.size(), _Left[_Idx] | _Right);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator|(const typename valarray<_Ty>::value_type& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Right.size(), _Left | _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator<<(const valarray<_Ty>& _Left, const typename valarray<_Ty>::value_type& _Right) {
|
|
_VALOP(_Ty, _Left.size(), _Left[_Idx] << _Right);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator<<(const typename valarray<_Ty>::value_type& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Right.size(), _Left << _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator>>(const valarray<_Ty>& _Left, const typename valarray<_Ty>::value_type& _Right) {
|
|
_VALOP(_Ty, _Left.size(), _Left[_Idx] >> _Right);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator>>(const typename valarray<_Ty>::value_type& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Right.size(), _Left >> _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator&&(const valarray<_Ty>& _Left, const typename valarray<_Ty>::value_type& _Right) {
|
|
_VALOP(bool, _Left.size(), _Left[_Idx] && _Right);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator&&(const typename valarray<_Ty>::value_type& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(bool, _Right.size(), _Left&& _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator||(const valarray<_Ty>& _Left, const typename valarray<_Ty>::value_type& _Right) {
|
|
_VALOP(bool, _Left.size(), _Left[_Idx] || _Right);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator||(const typename valarray<_Ty>::value_type& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(bool, _Right.size(), _Left || _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator*(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Left.size(), _Left[_Idx] * _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator/(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Left.size(), _Left[_Idx] / _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator%(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Left.size(), _Left[_Idx] % _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator+(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Left.size(), _Left[_Idx] + _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator-(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Left.size(), _Left[_Idx] - _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator^(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Left.size(), _Left[_Idx] ^ _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator&(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Left.size(), _Left[_Idx] & _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator|(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Left.size(), _Left[_Idx] | _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator<<(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Left.size(), _Left[_Idx] << _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> operator>>(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Left.size(), _Left[_Idx] >> _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator&&(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(bool, _Left.size(), _Left[_Idx] && _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator||(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(bool, _Left.size(), _Left[_Idx] || _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator==(const valarray<_Ty>& _Left, const typename valarray<_Ty>::value_type& _Right) {
|
|
_VALOP(bool, _Left.size(), _Left[_Idx] == _Right);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator==(const typename valarray<_Ty>::value_type& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(bool, _Right.size(), _Left == _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator==(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(bool, _Left.size(), _Left[_Idx] == _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator!=(const valarray<_Ty>& _Left, const typename valarray<_Ty>::value_type& _Right) {
|
|
_VALOP(bool, _Left.size(), _Left[_Idx] != _Right);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator!=(const typename valarray<_Ty>::value_type& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(bool, _Right.size(), _Left != _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator!=(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(bool, _Left.size(), _Left[_Idx] != _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator<(const valarray<_Ty>& _Left, const typename valarray<_Ty>::value_type& _Right) {
|
|
_VALOP(bool, _Left.size(), _Left[_Idx] < _Right);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator<(const typename valarray<_Ty>::value_type& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(bool, _Right.size(), _Left < _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator<(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(bool, _Left.size(), _Left[_Idx] < _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator>(const valarray<_Ty>& _Left, const typename valarray<_Ty>::value_type& _Right) {
|
|
_VALOP(bool, _Left.size(), _Left[_Idx] > _Right);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator>(const typename valarray<_Ty>::value_type& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(bool, _Right.size(), _Left > _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator>(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(bool, _Left.size(), _Left[_Idx] > _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator<=(const valarray<_Ty>& _Left, const typename valarray<_Ty>::value_type& _Right) {
|
|
_VALOP(bool, _Left.size(), _Left[_Idx] <= _Right);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator<=(const typename valarray<_Ty>::value_type& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(bool, _Right.size(), _Left <= _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator<=(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(bool, _Left.size(), _Left[_Idx] <= _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator>=(const valarray<_Ty>& _Left, const typename valarray<_Ty>::value_type& _Right) {
|
|
_VALOP(bool, _Left.size(), _Left[_Idx] >= _Right);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator>=(const typename valarray<_Ty>::value_type& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(bool, _Right.size(), _Left >= _Right[_Idx]);
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD _Boolarray operator>=(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(bool, _Left.size(), _Left[_Idx] >= _Right[_Idx]);
|
|
}
|
|
|
|
// [valarray.transcend] Transcendentals
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> abs(const valarray<_Ty>& _Left) {
|
|
_VALOP(_Ty, _Left.size(), abs(_Left[_Idx])); // using ADL, N4835 [valarray.transcend]/1
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> acos(const valarray<_Ty>& _Left) {
|
|
_VALOP(_Ty, _Left.size(), acos(_Left[_Idx])); // using ADL, N4835 [valarray.transcend]/1
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> asin(const valarray<_Ty>& _Left) {
|
|
_VALOP(_Ty, _Left.size(), asin(_Left[_Idx])); // using ADL, N4835 [valarray.transcend]/1
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> atan(const valarray<_Ty>& _Left) {
|
|
_VALOP(_Ty, _Left.size(), atan(_Left[_Idx])); // using ADL, N4835 [valarray.transcend]/1
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> atan2(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Left.size(), atan2(_Left[_Idx], _Right[_Idx])); // using ADL, N4835 [valarray.transcend]/1
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> atan2(const valarray<_Ty>& _Left, const typename valarray<_Ty>::value_type& _Right) {
|
|
_VALOP(_Ty, _Left.size(), atan2(_Left[_Idx], _Right)); // using ADL, N4835 [valarray.transcend]/1
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> atan2(const typename valarray<_Ty>::value_type& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Right.size(), atan2(_Left, _Right[_Idx])); // using ADL, N4835 [valarray.transcend]/1
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> cos(const valarray<_Ty>& _Left) {
|
|
_VALOP(_Ty, _Left.size(), cos(_Left[_Idx])); // using ADL, N4835 [valarray.transcend]/1
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> cosh(const valarray<_Ty>& _Left) {
|
|
_VALOP(_Ty, _Left.size(), cosh(_Left[_Idx])); // using ADL, N4835 [valarray.transcend]/1
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> exp(const valarray<_Ty>& _Left) {
|
|
_VALOP(_Ty, _Left.size(), exp(_Left[_Idx])); // using ADL, N4835 [valarray.transcend]/1
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> log(const valarray<_Ty>& _Left) {
|
|
_VALOP(_Ty, _Left.size(), log(_Left[_Idx])); // using ADL, N4835 [valarray.transcend]/1
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> log10(const valarray<_Ty>& _Left) {
|
|
_VALOP(_Ty, _Left.size(), log10(_Left[_Idx])); // using ADL, N4835 [valarray.transcend]/1
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> pow(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Left.size(), pow(_Left[_Idx], _Right[_Idx])); // using ADL, N4835 [valarray.transcend]/1
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> pow(const valarray<_Ty>& _Left, const typename valarray<_Ty>::value_type& _Right) {
|
|
_VALOP(_Ty, _Left.size(), pow(_Left[_Idx], _Right)); // using ADL, N4835 [valarray.transcend]/1
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> pow(const typename valarray<_Ty>::value_type& _Left, const valarray<_Ty>& _Right) {
|
|
_VALOP(_Ty, _Right.size(), pow(_Left, _Right[_Idx])); // using ADL, N4835 [valarray.transcend]/1
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> sin(const valarray<_Ty>& _Left) {
|
|
_VALOP(_Ty, _Left.size(), sin(_Left[_Idx])); // using ADL, N4835 [valarray.transcend]/1
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> sinh(const valarray<_Ty>& _Left) {
|
|
_VALOP(_Ty, _Left.size(), sinh(_Left[_Idx])); // using ADL, N4835 [valarray.transcend]/1
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> sqrt(const valarray<_Ty>& _Left) {
|
|
_VALOP(_Ty, _Left.size(), sqrt(_Left[_Idx])); // using ADL, N4835 [valarray.transcend]/1
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> tan(const valarray<_Ty>& _Left) {
|
|
_VALOP(_Ty, _Left.size(), tan(_Left[_Idx])); // using ADL, N4835 [valarray.transcend]/1
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> tanh(const valarray<_Ty>& _Left) {
|
|
_VALOP(_Ty, _Left.size(), tanh(_Left[_Idx])); // using ADL, N4835 [valarray.transcend]/1
|
|
}
|
|
|
|
// CLASS slice
|
|
class slice { // define a slice of a valarray
|
|
public:
|
|
slice() = default;
|
|
|
|
slice(size_t _Off, size_t _Count, size_t _Inc) noexcept // strengthened
|
|
: _Start(_Off), _Len(_Count), _Stride(_Inc) {}
|
|
|
|
_NODISCARD size_t start() const noexcept /* strengthened */ {
|
|
return _Start;
|
|
}
|
|
|
|
_NODISCARD size_t size() const noexcept /* strengthened */ {
|
|
return _Len;
|
|
}
|
|
|
|
_NODISCARD size_t stride() const noexcept /* strengthened */ {
|
|
return _Stride;
|
|
}
|
|
|
|
protected:
|
|
size_t _Start = 0; // the starting offset
|
|
size_t _Len = 0; // the number of elements
|
|
size_t _Stride = 0; // the distance between elements
|
|
};
|
|
|
|
// MACROS FOR slice_array
|
|
#define _SLOP(RHS) /* apply RHS(_Idx) to slice_array */ \
|
|
size_t _Off = _Start; \
|
|
for (size_t _Idx = 0; _Idx < _Len; ++_Idx, _Off += _Stride) { \
|
|
_Myptr[_Off] RHS; \
|
|
}
|
|
|
|
// CLASS TEMPLATE slice_array
|
|
template <class _Ty>
|
|
class slice_array : public slice { // define a slice of a valarray
|
|
public:
|
|
using value_type = _Ty;
|
|
|
|
void operator=(const valarray<_Ty>& _Right) const {
|
|
_SLOP(= _Right[_Idx]);
|
|
}
|
|
|
|
void operator=(const _Ty& _Right) const {
|
|
_SLOP(= _Right);
|
|
}
|
|
|
|
void operator*=(const valarray<_Ty>& _Right) const {
|
|
_SLOP(*= _Right[_Idx]);
|
|
}
|
|
|
|
void operator/=(const valarray<_Ty>& _Right) const {
|
|
_SLOP(/= _Right[_Idx]);
|
|
}
|
|
|
|
void operator%=(const valarray<_Ty>& _Right) const {
|
|
_SLOP(%= _Right[_Idx]);
|
|
}
|
|
|
|
void operator+=(const valarray<_Ty>& _Right) const {
|
|
_SLOP(+= _Right[_Idx]);
|
|
}
|
|
|
|
void operator-=(const valarray<_Ty>& _Right) const {
|
|
_SLOP(-= _Right[_Idx]);
|
|
}
|
|
|
|
void operator^=(const valarray<_Ty>& _Right) const {
|
|
_SLOP(^= _Right[_Idx]);
|
|
}
|
|
|
|
void operator&=(const valarray<_Ty>& _Right) const {
|
|
_SLOP(&= _Right[_Idx]);
|
|
}
|
|
|
|
void operator|=(const valarray<_Ty>& _Right) const {
|
|
_SLOP(|= _Right[_Idx]);
|
|
}
|
|
|
|
void operator<<=(const valarray<_Ty>& _Right) const {
|
|
_SLOP(<<= _Right[_Idx]);
|
|
}
|
|
|
|
void operator>>=(const valarray<_Ty>& _Right) const {
|
|
_SLOP(>>= _Right[_Idx]);
|
|
}
|
|
|
|
_Ty& _Data(size_t _Idx) const {
|
|
return _Myptr[_Idx];
|
|
}
|
|
|
|
slice_array() = delete;
|
|
|
|
slice_array(const slice_array&); // not defined
|
|
|
|
slice_array& operator=(const slice_array&); // not defined
|
|
|
|
private:
|
|
friend valarray<_Ty>;
|
|
|
|
slice_array(const slice& _Slice, _Ty* _Pdata) : slice(_Slice), _Myptr(_Pdata) {}
|
|
|
|
_Ty* _Myptr; // pointer to valarray contents
|
|
};
|
|
|
|
// CLASS gslice
|
|
class gslice { // define a generalized (multidimensional) slice of a valarray
|
|
public:
|
|
gslice() : _Start(0) { // construct with all zeros
|
|
}
|
|
|
|
gslice(size_t _Off, const _Sizarray& _Lenarr, const _Sizarray& _Incarr)
|
|
: _Start(_Off), _Len(_Lenarr), _Stride(_Incarr) {}
|
|
|
|
_NODISCARD size_t start() const {
|
|
return _Start;
|
|
}
|
|
|
|
_NODISCARD _Sizarray size() const {
|
|
return _Len;
|
|
}
|
|
|
|
_NODISCARD _Sizarray stride() const {
|
|
return _Stride;
|
|
}
|
|
|
|
size_t _Nslice() const {
|
|
return _Len.size();
|
|
}
|
|
|
|
size_t _Off(_Sizarray& _Indexarr) const {
|
|
size_t _Idx, _Ans = _Start;
|
|
|
|
for (_Idx = 0; _Idx < _Indexarr.size(); ++_Idx) {
|
|
_Ans += _Indexarr[_Idx] * _Stride[_Idx]; // compute offset
|
|
}
|
|
|
|
while (0 < _Idx--) {
|
|
if (++_Indexarr[_Idx] < _Len[_Idx]) {
|
|
break; // increment done, quit
|
|
} else {
|
|
_Indexarr[_Idx] = 0; // carry to more-significant index
|
|
}
|
|
}
|
|
|
|
return _Ans;
|
|
}
|
|
|
|
size_t _Totlen() const {
|
|
if (_Len.size() == 0) {
|
|
return 0;
|
|
}
|
|
|
|
size_t _Count = _Len[0];
|
|
for (size_t _Idx = 1; _Idx < _Len.size(); ++_Idx) {
|
|
_Count *= _Len[_Idx];
|
|
}
|
|
|
|
return _Count;
|
|
}
|
|
|
|
private:
|
|
size_t _Start; // the starting offset
|
|
_Sizarray _Len; // array of numbers of elements
|
|
_Sizarray _Stride; // array of distances between elements
|
|
};
|
|
|
|
// MACROS FOR gslice_array
|
|
#define _GSLOP(RHS) /* apply RHS(_Idx) to gslice_array */ \
|
|
_Sizarray _Indexarray(size_t{0}, _Nslice()); \
|
|
size_t _Size = _Totlen(); \
|
|
for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { \
|
|
_Myptr[_Off(_Indexarray)] RHS; \
|
|
}
|
|
|
|
// CLASS TEMPLATE gslice_array
|
|
template <class _Ty>
|
|
class gslice_array : public gslice { // define a generalized slice of a valarray
|
|
public:
|
|
using value_type = _Ty;
|
|
|
|
void operator=(const valarray<_Ty>& _Right) const {
|
|
_GSLOP(= _Right[_Idx]);
|
|
}
|
|
|
|
void operator=(const _Ty& _Right) const {
|
|
_GSLOP(= _Right);
|
|
}
|
|
|
|
void operator*=(const valarray<_Ty>& _Right) const { // multiply generalized slice by valarray
|
|
_GSLOP(*= _Right[_Idx]);
|
|
}
|
|
|
|
void operator/=(const valarray<_Ty>& _Right) const { // divide generalized slice by valarray
|
|
_GSLOP(/= _Right[_Idx]);
|
|
}
|
|
|
|
void operator%=(const valarray<_Ty>& _Right) const { // remainder generalized slice by valarray
|
|
_GSLOP(%= _Right[_Idx]);
|
|
}
|
|
|
|
void operator+=(const valarray<_Ty>& _Right) const { // add valarray to generalized slice
|
|
_GSLOP(+= _Right[_Idx]);
|
|
}
|
|
|
|
void operator-=(const valarray<_Ty>& _Right) const { // subtract valarray from generalized slice
|
|
_GSLOP(-= _Right[_Idx]);
|
|
}
|
|
|
|
void operator^=(const valarray<_Ty>& _Right) const { // XOR valarray into generalized slice
|
|
_GSLOP(^= _Right[_Idx]);
|
|
}
|
|
|
|
void operator&=(const valarray<_Ty>& _Right) const { // AND valarray into generalized slice
|
|
_GSLOP(&= _Right[_Idx]);
|
|
}
|
|
|
|
void operator|=(const valarray<_Ty>& _Right) const { // OR valarray into generalized slice
|
|
_GSLOP(|= _Right[_Idx]);
|
|
}
|
|
|
|
void operator<<=(const valarray<_Ty>& _Right) const { // left shift generalized slice by valarray
|
|
_GSLOP(<<= _Right[_Idx]);
|
|
}
|
|
|
|
void operator>>=(const valarray<_Ty>& _Right) const { // right shift generalized slice by valarray
|
|
_GSLOP(>>= _Right[_Idx]);
|
|
}
|
|
|
|
_Ty& _Data(size_t _Idx) const {
|
|
return _Myptr[_Idx];
|
|
}
|
|
|
|
gslice_array() = delete;
|
|
|
|
gslice_array(const gslice_array&); // not defined
|
|
|
|
gslice_array& operator=(const gslice_array&); // not defined
|
|
|
|
private:
|
|
friend valarray<_Ty>;
|
|
|
|
gslice_array(const gslice& _Gslice, _Ty* _Ptr) : gslice(_Gslice), _Myptr(_Ptr) {}
|
|
|
|
_Ty* _Myptr; // pointer to valarray contents
|
|
};
|
|
|
|
// MACROS FOR mask_array
|
|
#define _MOP(RHS) /* apply RHS(_Idx) to mask_array */ \
|
|
size_t _Off = 0; \
|
|
size_t _Size = _Totlen(); \
|
|
for (size_t _Idx = 0; _Idx < _Size; ++_Off) { \
|
|
if (_Mask(_Off)) { \
|
|
_Myptr[_Off] RHS, ++_Idx; \
|
|
} \
|
|
}
|
|
|
|
// CLASS TEMPLATE mask_array
|
|
template <class _Ty>
|
|
class mask_array { // define a subset of a valarray with an array of mask bits
|
|
public:
|
|
using value_type = _Ty;
|
|
|
|
void operator=(const valarray<_Ty>& _Right) const {
|
|
_MOP(= _Right[_Idx]);
|
|
}
|
|
|
|
void operator=(const _Ty& _Right) const {
|
|
_MOP(= _Right);
|
|
}
|
|
|
|
void operator*=(const valarray<_Ty>& _Right) const { // multiply masked array by valarray
|
|
_MOP(*= _Right[_Idx]);
|
|
}
|
|
|
|
void operator/=(const valarray<_Ty>& _Right) const { // divide masked array by valarray
|
|
_MOP(/= _Right[_Idx]);
|
|
}
|
|
|
|
void operator%=(const valarray<_Ty>& _Right) const { // remainder masked array by valarray
|
|
_MOP(%= _Right[_Idx]);
|
|
}
|
|
|
|
void operator+=(const valarray<_Ty>& _Right) const { // add valarray to masked array
|
|
_MOP(+= _Right[_Idx]);
|
|
}
|
|
|
|
void operator-=(const valarray<_Ty>& _Right) const { // subtract valarray from masked array
|
|
_MOP(-= _Right[_Idx]);
|
|
}
|
|
|
|
void operator^=(const valarray<_Ty>& _Right) const { // XOR valarray into masked array
|
|
_MOP(^= _Right[_Idx]);
|
|
}
|
|
|
|
void operator&=(const valarray<_Ty>& _Right) const { // OR valarray into masked array
|
|
_MOP(&= _Right[_Idx]);
|
|
}
|
|
|
|
void operator|=(const valarray<_Ty>& _Right) const { // OR valarray into masked array
|
|
_MOP(|= _Right[_Idx]);
|
|
}
|
|
|
|
void operator<<=(const valarray<_Ty>& _Right) const { // left shift masked array by valarray
|
|
_MOP(<<= _Right[_Idx]);
|
|
}
|
|
|
|
void operator>>=(const valarray<_Ty>& _Right) const { // right shift masked array by valarray
|
|
_MOP(>>= _Right[_Idx]);
|
|
}
|
|
|
|
_Ty& _Data(size_t _Idx) const {
|
|
return _Myptr[_Idx];
|
|
}
|
|
|
|
bool _Mask(size_t _Idx) const {
|
|
return _Mybool[_Idx];
|
|
}
|
|
|
|
size_t _Totlen() const {
|
|
size_t _Count = 0;
|
|
for (size_t _Idx = 0; _Idx < _Mybool.size(); ++_Idx) {
|
|
if (_Mybool[_Idx]) {
|
|
++_Count;
|
|
}
|
|
}
|
|
|
|
return _Count;
|
|
}
|
|
|
|
mask_array() = delete;
|
|
|
|
mask_array(const mask_array&); // not defined
|
|
|
|
mask_array& operator=(const mask_array&); // not defined
|
|
|
|
private:
|
|
friend valarray<_Ty>;
|
|
|
|
mask_array(const _Boolarray& _Maskarr, _Ty* _Pdata) : _Mybool(_Maskarr), _Myptr(_Pdata) {}
|
|
|
|
_Boolarray _Mybool; // array of mask bits
|
|
_Ty* _Myptr; // pointer to valarray contents
|
|
};
|
|
|
|
// MACROS FOR indirect_array
|
|
#define _IOP(RHS) /* apply RHS(_Idx) to indirect_array */ \
|
|
size_t _Size = _Totlen(); \
|
|
for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { \
|
|
_Myptr[_Indir(_Idx)] RHS; \
|
|
}
|
|
|
|
// CLASS TEMPLATE indirect_array
|
|
template <class _Ty>
|
|
class indirect_array { // define a subset of a valarray with an array of indexes
|
|
public:
|
|
using value_type = _Ty;
|
|
|
|
void operator=(const valarray<_Ty>& _Right) const {
|
|
_IOP(= _Right[_Idx]);
|
|
}
|
|
|
|
void operator=(const _Ty& _Right) const {
|
|
_IOP(= _Right);
|
|
}
|
|
|
|
void operator*=(const valarray<_Ty>& _Right) const { // multiply indirect array by valarray
|
|
_IOP(*= _Right[_Idx]);
|
|
}
|
|
|
|
void operator/=(const valarray<_Ty>& _Right) const { // divide indirect array by valarray
|
|
_IOP(/= _Right[_Idx]);
|
|
}
|
|
|
|
void operator%=(const valarray<_Ty>& _Right) const { // remainder indirect array by valarray
|
|
_IOP(%= _Right[_Idx]);
|
|
}
|
|
|
|
void operator+=(const valarray<_Ty>& _Right) const { // add valarray to indirect array
|
|
_IOP(+= _Right[_Idx]);
|
|
}
|
|
|
|
void operator-=(const valarray<_Ty>& _Right) const { // subtract valarray from indirect array
|
|
_IOP(-= _Right[_Idx]);
|
|
}
|
|
|
|
void operator^=(const valarray<_Ty>& _Right) const { // XOR valarray into indirect array
|
|
_IOP(^= _Right[_Idx]);
|
|
}
|
|
|
|
void operator&=(const valarray<_Ty>& _Right) const { // AND valarray into indirect array
|
|
_IOP(&= _Right[_Idx]);
|
|
}
|
|
|
|
void operator|=(const valarray<_Ty>& _Right) const { // OR valarray into indirect array
|
|
_IOP(|= _Right[_Idx]);
|
|
}
|
|
|
|
void operator<<=(const valarray<_Ty>& _Right) const { // left shift indirect array by valarray
|
|
_IOP(<<= _Right[_Idx]);
|
|
}
|
|
|
|
void operator>>=(const valarray<_Ty>& _Right) const { // right shift indirect array by valarray
|
|
_IOP(>>= _Right[_Idx]);
|
|
}
|
|
|
|
_Ty& _Data(size_t _Idx) const {
|
|
return _Myptr[_Idx];
|
|
}
|
|
|
|
size_t _Indir(size_t _Idx) const {
|
|
return _Myindarr[_Idx];
|
|
}
|
|
|
|
size_t _Totlen() const {
|
|
return _Myindarr.size();
|
|
}
|
|
|
|
indirect_array() = delete;
|
|
|
|
indirect_array(const indirect_array&); // not defined
|
|
|
|
indirect_array& operator=(const indirect_array&); // not defined
|
|
|
|
private:
|
|
friend valarray<_Ty>;
|
|
|
|
indirect_array(const _Sizarray& _Indarr, _Ty* _Ptr) : _Myindarr(_Indarr), _Myptr(_Ptr) {}
|
|
|
|
_Sizarray _Myindarr; // array of indirect indexes
|
|
_Ty* _Myptr; // pointer to valarray contents
|
|
};
|
|
|
|
template <class _Ty>
|
|
valarray<_Ty>& valarray<_Ty>::operator=(const slice_array<_Ty>& _Slicearr) {
|
|
_Tidy_deallocate();
|
|
_Grow(_Slicearr.size(), &_Slicearr._Data(_Slicearr.start()), _Slicearr.stride());
|
|
return *this;
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> valarray<_Ty>::operator[](slice _Slice) const {
|
|
return valarray<_Ty>(slice_array<_Ty>(_Slice, _Myptr));
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD slice_array<_Ty> valarray<_Ty>::operator[](slice _Slice) {
|
|
return slice_array<_Ty>(_Slice, _Myptr);
|
|
}
|
|
|
|
template <class _Ty>
|
|
valarray<_Ty>& valarray<_Ty>::operator=(const gslice_array<_Ty>& _Gslicearr) {
|
|
_Tidy_deallocate();
|
|
_Grow(_Gslicearr._Totlen());
|
|
_Sizarray _Indexarray(size_t{0}, _Gslicearr._Nslice());
|
|
_VALGOP(= _Gslicearr._Data(_Gslicearr._Off(_Indexarray)));
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> valarray<_Ty>::operator[](const gslice& _Gslice) const {
|
|
return valarray<_Ty>(gslice_array<_Ty>(_Gslice, _Myptr));
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD gslice_array<_Ty> valarray<_Ty>::operator[](const gslice& _Gslicearr) {
|
|
return gslice_array<_Ty>(_Gslicearr, _Myptr);
|
|
}
|
|
|
|
template <class _Ty>
|
|
valarray<_Ty>& valarray<_Ty>::operator=(const mask_array<_Ty>& _Maskarr) {
|
|
|
|
_Tidy_deallocate();
|
|
_Grow(_Maskarr._Totlen());
|
|
size_t _Count = 0;
|
|
|
|
for (size_t _Idx = 0; _Idx < size(); ++_Count) {
|
|
if (_Maskarr._Mask(_Count)) {
|
|
_Myptr[_Idx++] = _Maskarr._Data(_Count);
|
|
}
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> valarray<_Ty>::operator[](const _Boolarray& _Boolarr) const {
|
|
return valarray<_Ty>(mask_array<_Ty>(_Boolarr, _Myptr));
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD mask_array<_Ty> valarray<_Ty>::operator[](const _Boolarray& _Boolarr) {
|
|
return mask_array<_Ty>(_Boolarr, _Myptr);
|
|
}
|
|
|
|
template <class _Ty>
|
|
valarray<_Ty>& valarray<_Ty>::operator=(const indirect_array<_Ty>& _Indarr) {
|
|
_Tidy_deallocate();
|
|
_Grow(_Indarr._Totlen());
|
|
_VALGOP(= _Indarr._Data(_Indarr._Indir(_Idx)));
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD valarray<_Ty> valarray<_Ty>::operator[](const _Sizarray& _Indarr) const {
|
|
return valarray<_Ty>(indirect_array<_Ty>(_Indarr, _Myptr));
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD indirect_array<_Ty> valarray<_Ty>::operator[](const _Sizarray& _Indarr) {
|
|
return indirect_array<_Ty>(_Indarr, _Myptr);
|
|
}
|
|
_STD_END
|
|
|
|
#pragma pop_macro("new")
|
|
_STL_RESTORE_CLANG_WARNINGS
|
|
#pragma warning(pop)
|
|
#pragma pack(pop)
|
|
#endif // _STL_COMPILER_PREPROCESSOR
|
|
#endif // _VALARRAY_
|