// array standard header
#ifndef _ARRAY_
#define _ARRAY_

#if defined(__ghs)
 #include <yvals.h>
 #if !_HAS_CPP11
  #error This file requires ISO C++11 support in the compiler
 #endif /* _HAS_CPP11 */
#endif /* __ghs */

#include <algorithm>
#include <iterator>
#include <tuple>

 #if defined(__ghs)
  #pragma ghs start_cxx_lib_header
  #pragma ghs startdata
  #if defined(__ghs_max_pack_value)
   #pragma pack (push, __ghs_max_pack_value)
  #endif /* defined(__ghs_max_pack_value) */
 #endif /* defined(__ghs) */

 #if defined(__ghs) && _HAS_CPP17
  #define __cpp_lib_array_constexpr 201603L
  #define __cpp_lib_nonmember_container_access 201411L
 #endif /* defined(__ghs) && _HAS_CPP17 */

_STD_BEGIN
	// TEMPLATE CLASS array
template<class _Ty,
	_INT_OR_SIZE_T _Size>
	class array
	{	// fixed size array of values
public:
	typedef array<_Ty, _Size> _Myt;
	typedef _Ty value_type;
	typedef size_t size_type;
	typedef ptrdiff_t difference_type;
	typedef _Ty *pointer;
	typedef const _Ty *const_pointer;
	typedef _Ty& reference;
	typedef const _Ty& const_reference;

	typedef _Array_iterator<_Ty, _Size> iterator;
	typedef _Array_const_iterator<_Ty, _Size> const_iterator;

	typedef _STD reverse_iterator<iterator> reverse_iterator;
	typedef _STD reverse_iterator<const_iterator> const_reverse_iterator;

 #if !defined(__ghs) && _HAS_CPP17
	template<class... _Types>
		 array(_Types... _Vals)
		: _Elems{_STD forward<_Types>(_Vals)...}
		{	// construct from elements
		}
 #endif /* _HAS_CPP17 */

	void assign(const _Ty& _Value)
		{	// assign value to all elements
		_Fill_n(_Elems, _Size, _Value);
		}

	void fill(const _Ty& _Value)
		{	// assign value to all elements
		_Fill_n(_Elems, _Size, _Value);
		}

	void swap(_Myt& _Other)
		_NOEXCEPT_OP(
			_NOEXCEPT_OP(_Swap_adl(_Other._Elems[0], _Other._Elems[0])))
		{	// swap contents with _Other
		_Swap_ranges(_STD addressof(_Elems[0]),
			_STD addressof(_Elems[0]) + _Size,
			_STD addressof(_Other._Elems[0]));
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	iterator begin() _NOEXCEPT
		{	// return iterator for beginning of mutable sequence
		return (iterator(_STD addressof(_Elems[0]), 0));
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	const_iterator begin() const _NOEXCEPT
		{	// return iterator for beginning of nonmutable sequence
		return (const_iterator(_STD addressof(_Elems[0]), 0));
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	iterator end() _NOEXCEPT
		{	// return iterator for end of mutable sequence
		return (iterator(_STD addressof(_Elems[0]), _Size));
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	const_iterator end() const _NOEXCEPT
		{	// return iterator for beginning of nonmutable sequence
		return (const_iterator(_STD addressof(_Elems[0]), _Size));
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	reverse_iterator rbegin() _NOEXCEPT
		{	// return iterator for beginning of reversed mutable sequence
		return (reverse_iterator(end()));
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	const_reverse_iterator rbegin() const _NOEXCEPT
		{	// return iterator for beginning of reversed nonmutable sequence
		return (const_reverse_iterator(end()));
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	reverse_iterator rend() _NOEXCEPT
		{	// return iterator for end of reversed mutable sequence
		return (reverse_iterator(begin()));
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	const_reverse_iterator rend() const _NOEXCEPT
		{	// return iterator for end of reversed nonmutable sequence
		return (const_reverse_iterator(begin()));
		}

 #if _HAS_CPP11
#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif		
	const_iterator cbegin() const _NOEXCEPT
		{	// return iterator for beginning of nonmutable sequence
		return (begin());
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	const_iterator cend() const _NOEXCEPT
		{	// return iterator for end of nonmutable sequence
		return (end());
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	const_reverse_iterator crbegin() const _NOEXCEPT
		{	// return iterator for beginning of reversed nonmutable sequence
		return (rbegin());
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	const_reverse_iterator crend() const _NOEXCEPT
		{	// return iterator for end of reversed nonmutable sequence
		return (rend());
		}
 #endif /* _HAS_CPP11 */

	_CONST_FUN size_type size() const _NOEXCEPT
		{	// return length of sequence
		return (_Size);
		}

	_CONST_FUN size_type max_size() const _NOEXCEPT
		{	// return maximum possible length of sequence
		return (_Size);
		}

	_CONST_FUN bool empty() const _NOEXCEPT
		{	// test if sequence is empty
		return (false);
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	reference at(size_type _Pos)
		{	// subscript mutable sequence with checking
		if (_Size <= _Pos)
			_Xran();
		return (_Elems[_Pos]);
		}

	_CONST_FUN const_reference at(size_type _Pos) const
		{	// subscript nonmutable sequence with checking
		return (_Size <= _Pos
			? (_Xran(), _Elems[_Pos])
			: _Elems[_Pos]);
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	reference operator[](size_type _Pos)
		{	// subscript mutable sequence
 #if _ITERATOR_DEBUG_LEVEL == 2
		if (_Size <= _Pos)
			_DEBUG_ERROR("array subscript out of range");

 #elif _ITERATOR_DEBUG_LEVEL == 1
		_SCL_SECURE_VALIDATE_RANGE(_Pos < _Size);
 #endif /* _ITERATOR_DEBUG_LEVEL */

		return (_Elems[_Pos]);
		}

	static void _Bad_subscript()
		{	// report invalid subscript
 #if _ITERATOR_DEBUG_LEVEL == 2
		_DEBUG_ERROR("array subscript out of range");

 #elif _ITERATOR_DEBUG_LEVEL == 1
		_SCL_SECURE_VALIDATE_RANGE(false);
 #endif /* _ITERATOR_DEBUG_LEVEL */
		}

	_CONST_FUN const_reference operator[](size_type _Pos) const
		{	// subscript nonmutable sequence
 #if _ITERATOR_DEBUG_LEVEL == 0
		return (_Elems[_Pos]);

 #else /* _ITERATOR_DEBUG_LEVEL == 0 */
		return (_Size <= _Pos
			? (_Bad_subscript(), _Elems[_Pos])
			: _Elems[_Pos]);
 #endif /* _ITERATOR_DEBUG_LEVEL == 0 */
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	reference front()
		{	// return first element of mutable sequence
		return (_Elems[0]);
		}

	_CONST_FUN const_reference front() const
		{	// return first element of nonmutable sequence
		return (_Elems[0]);
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	reference back()
		{	// return last element of mutable sequence
		return (_Elems[_Size - 1]);
		}

	_CONST_FUN const_reference back() const
		{	// return last element of nonmutable sequence
		return (_Elems[_Size - 1]);
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	_Ty *data() _NOEXCEPT
		{	// return pointer to mutable data array
		return (_Elems);
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	const _Ty *data() const _NOEXCEPT
		{	// return pointer to nonmutable data array
		return (_Elems);
		}

	_NO_RETURN_MEMBER(_Xran()) const
		{	// report an out_of_range error
		_Xout_of_range("invalid array<T, N> subscript");
		}

	_Ty _Elems[_Size];
	};

#if defined(__ghs)
struct _Zero_len_array_dummy_type { };
#endif /* defined(__ghs) */

template<class _Ty>
	class array<_Ty, 0>
	{	// zero size array of values
public:
	typedef array<_Ty, 0> _Myt;
	typedef _Ty value_type;
	typedef size_t size_type;
	typedef ptrdiff_t difference_type;
	typedef _Ty *pointer;
	typedef const _Ty *const_pointer;
	typedef _Ty& reference;
	typedef const _Ty& const_reference;

	typedef _Array_iterator<_Ty, 0> iterator;
	typedef _Array_const_iterator<_Ty, 0> const_iterator;
	typedef _STD reverse_iterator<iterator> reverse_iterator;
	typedef _STD reverse_iterator<const_iterator> const_reverse_iterator;

	void assign(const _Ty&)
		{	// assign value to all elements
		}

	void fill(const _Ty&)
		{	// assign value to all elements
		}

	void swap(_Myt&) _NOEXCEPT
		{	// swap contents with _Other
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	iterator begin()
		{	// return iterator for beginning of mutable sequence
		return (iterator(0, 0));
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	const_iterator begin() const
		{	// return iterator for beginning of nonmutable sequence
		return (iterator(0, 0));
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	iterator end()
		{	// return iterator for end of mutable sequence
		return (iterator(0, 0));
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	const_iterator end() const
		{	// return iterator for beginning of nonmutable sequence
		return (iterator(0, 0));
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	reverse_iterator rbegin()
		{	// return iterator for beginning of reversed mutable sequence
		return (reverse_iterator(end()));
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	const_reverse_iterator rbegin() const
		{	// return iterator for beginning of reversed nonmutable sequence
		return (const_reverse_iterator(end()));
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	reverse_iterator rend()
		{	// return iterator for end of reversed mutable sequence
		return (reverse_iterator(begin()));
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	const_reverse_iterator rend() const
		{	// return iterator for end of reversed nonmutable sequence
		return (const_reverse_iterator(begin()));
		}

 #if _HAS_CPP11
#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	const_iterator cbegin() const
		{	// return iterator for beginning of nonmutable sequence
		return (iterator(0, 0));
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	const_iterator cend() const
		{	// return iterator for end of nonmutable sequence
		return (iterator(0, 0));
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	const_reverse_iterator crbegin() const
		{	// return iterator for beginning of reversed nonmutable sequence
		return (rbegin());
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	const_reverse_iterator crend() const
		{	// return iterator for end of reversed nonmutable sequence
		return (rend());
		}
 #endif /* _HAS_CPP11 */

	_CONST_FUN size_type size() const
		{	// return length of sequence
		return (0);
		}

	_CONST_FUN size_type max_size() const
		{	// return maximum possible length of sequence
		return (0);
		}

	_CONST_FUN bool empty() const
		{	// test if sequence is empty
		return (true);
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	reference at(size_type)
		{	// subscript mutable sequence with checking
#if defined(__ghs)
		_Xran();
		return *data();
#else
		static int _Zero = 0;

		if (_Zero == 0)	// to quiet diagnostics
			_Xran();
		return (_Elems[0]);
#endif	    
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	const_reference at(size_type) const
		{	// subscript nonmutable sequence with checking
#if defined(__ghs)
		_Xran();
		return *data();
#else
		static int _Zero = 0;

		if (_Zero == 0)	// to quiet diagnostics
			_Xran();
		return (_Elems[0]);
#endif
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	reference operator[](size_type)
		{	// subscript mutable sequence
 #if _ITERATOR_DEBUG_LEVEL == 2
		_DEBUG_ERROR("array subscript out of range");

 #elif _ITERATOR_DEBUG_LEVEL == 1
		_SCL_SECURE_VALIDATE_RANGE(false);
 #endif /* _ITERATOR_DEBUG_LEVEL */

#if defined(__ghs)
		return *data();
#else
		return (_Elems[0]);
#endif /* defined(__ghs) */
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	const_reference operator[](size_type) const
		{	// subscript nonmutable sequence
 #if _ITERATOR_DEBUG_LEVEL == 2
		_DEBUG_ERROR("array subscript out of range");

 #elif _ITERATOR_DEBUG_LEVEL == 1
		_SCL_SECURE_VALIDATE_RANGE(false);
 #endif /* _ITERATOR_DEBUG_LEVEL */

#if defined(__ghs)
		return *data();
#else
		return (_Elems[0]);
#endif /* defined(__ghs) */
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	reference front()
		{	// return first element of mutable sequence
 #if _ITERATOR_DEBUG_LEVEL == 2
		_DEBUG_ERROR("array<T, 0>::front() invalid");

 #elif _ITERATOR_DEBUG_LEVEL == 1
		_SCL_SECURE_VALIDATE_RANGE(false);
 #endif /* _ITERATOR_DEBUG_LEVEL */

#if defined(__ghs)
		return *data();
#else
		return (_Elems[0]);
#endif /* defined(__ghs) */
		}

#if defined(__ghs) && _HAS_CPP14
	_CONST_FUN
#endif
	const_reference front() const
		{	// return first element of nonmutable sequence
 #if _ITERATOR_DEBUG_LEVEL == 2
		_DEBUG_ERROR("array<T, 0>::front() invalid");

 #elif _ITERATOR_DEBUG_LEVEL == 1
		_SCL_SECURE_VALIDATE_RANGE(false);
 #endif /* _ITERATOR_DEBUG_LEVEL */

#if defined(__ghs)
		return *data();
#else
		return (_Elems[0]);
#endif /* defined(__ghs) */
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	reference back()
		{	// return last element of mutable sequence
 #if _ITERATOR_DEBUG_LEVEL == 2
		_DEBUG_ERROR("array<T, 0>::back() invalid");

 #elif _ITERATOR_DEBUG_LEVEL == 1
		_SCL_SECURE_VALIDATE_RANGE(false);
 #endif /* _ITERATOR_DEBUG_LEVEL */

#if defined(__ghs)
		return *data();
#else
		return (_Elems[0]);
#endif /* defined(__ghs) */
		}

#if defined(__ghs) && _HAS_CPP14
	_CONST_FUN
#endif
	const_reference back() const
		{	// return last element of nonmutable sequence
 #if _ITERATOR_DEBUG_LEVEL == 2
		_DEBUG_ERROR("array<T, 0>::back() invalid");

 #elif _ITERATOR_DEBUG_LEVEL == 1
		_SCL_SECURE_VALIDATE_RANGE(false);
 #endif /* _ITERATOR_DEBUG_LEVEL */
#if defined(__ghs)
		return *data();
#else
		return (_Elems[0]);
#endif /* defined(__ghs) */
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	_Ty *data()
		{	// return pointer to mutable data array
#if defined(__ghs)
		return (nullptr);
#else
		return (_Elems);
#endif /* defined(__ghs) */
		}

#if defined(__ghs) && _HAS_CPP17
	_CONST_FUN
#endif
	const _Ty *data() const
		{	// return pointer to nonmutable data array
#if defined(__ghs)
		return (nullptr);
#else
		return (_Elems);
#endif /* defined(__ghs) */
		}

	_NO_RETURN_MEMBER(_Xran()) const
		{	// report an out_of_range error
		_Xout_of_range("invalid array<T, 0> subscript");
		}

#if defined(__ghs)
	_Zero_len_array_dummy_type _DummyElem; // LWG 2157
#else
	_Ty _Elems[1];
#endif /* defined(__ghs) */
	};

 #if _HAS_CPP17
template<class _Ty,
	_INT_OR_SIZE_T _Size,
	class = enable_if_t<_Size == 0
		|| is_swappable<_Ty>::value,
		void> > inline

 #else /* _HAS_CPP17 */
template<class _Ty,
	_INT_OR_SIZE_T _Size>
 #endif /* _HAS_CPP17 */

	void swap(array<_Ty,_Size>& _Left,
		array<_Ty,_Size>& _Right)
			_NOEXCEPT_OP(_NOEXCEPT_OP(_Left.swap(_Right)))
	{	// swap arrays
	return (_Left.swap(_Right));
	}

 #if defined(__ghs) && _HAS_CPP17
// LWG 2766
template<class _Ty,
	_INT_OR_SIZE_T _Size,
	class _Dummy = void,
	class = enable_if_t<!(_Size == 0
		|| is_swappable<_Ty>::value),
		void> >

	void swap(array<_Ty,_Size>&,
		array<_Ty,_Size>&) = delete;
 #endif /* defined(__ghs) && _HAS_CPP17 */

template<class _Ty,
	_INT_OR_SIZE_T _Size>
	bool operator==(const array<_Ty,_Size>& _Left,
		const array<_Ty,_Size>& _Right)
	{	// test for array equality
	return (_STD equal(_Left.begin(), _Left.end(), _Right.begin()));
	}

template<class _Ty,
	_INT_OR_SIZE_T _Size>
	bool operator!=(const array<_Ty,_Size>& _Left,
		const array<_Ty,_Size>& _Right)
	{	// test for array inequality
	return (!(_Left == _Right));
	}

template<class _Ty,
	_INT_OR_SIZE_T _Size>
	bool operator<(const array<_Ty,_Size>& _Left,
		const array<_Ty,_Size>& _Right)
	{	// test if _Left < _Right for arrays
	return (_STD lexicographical_compare(_Left.begin(), _Left.end(),
		_Right.begin(), _Right.end()));
	}

template<class _Ty,
	_INT_OR_SIZE_T _Size>
	bool operator>(const array<_Ty,_Size>& _Left,
		const array<_Ty,_Size>& _Right)
	{	// test if _Left > _Right for arrays
	return (_Right < _Left);
	}

template<class _Ty,
	_INT_OR_SIZE_T _Size>
	bool operator<=(const array<_Ty,_Size>& _Left,
	const array<_Ty,_Size>& _Right)
	{	// test if _Left <= _Right for arrays
	return (!(_Right < _Left));
	}

template<class _Ty,
	_INT_OR_SIZE_T _Size>
	bool operator>=(const array<_Ty,_Size>& _Left,
	const array<_Ty,_Size>& _Right)
	{	// test if _Left >= _Right for arrays
	return (!(_Left < _Right));
	}

 #if _HAS_TR1
	// TUPLE INTERFACE TO array
template<size_t _Idx,
	class _Ty,
	_INT_OR_SIZE_T _Size>
	_CONST_FUN _Ty& get(array<_Ty, _Size>& _Arr) _NOEXCEPT
	{	// return element at _Idx in array _Arr
	_STATIC_ASSERT2(_Idx < _Size, "array index out of bounds");
	return (_Arr._Elems[_Idx]);
	}

template<size_t _Idx,
	class _Ty,
	_INT_OR_SIZE_T _Size>
	_CONST_FUN const _Ty& get(const array<_Ty, _Size>& _Arr) _NOEXCEPT
	{	// return const element at _Idx in array _Arr
	_STATIC_ASSERT2(_Idx < _Size, "array index out of bounds");
	return (_Arr._Elems[_Idx]);
	}

 #if _HAS_RVALUE_REFERENCES
template<size_t _Idx,
	class _Ty,
	_INT_OR_SIZE_T _Size>
	_CONST_FUN _Ty&& get(array<_Ty, _Size>&& _Arr) _NOEXCEPT
	{	// return element at _Idx in array _Arr
	_STATIC_ASSERT2(_Idx < _Size, "array index out of bounds");
	return (_STD move(_Arr._Elems[_Idx]));
	}
 #endif /* _HAS_RVALUE_REFERENCES */

 #endif /* _HAS_TR1 */

 #if _HAS_CPP17
template<size_t _Idx,
	class _Ty,
	_INT_OR_SIZE_T _Size>
	_CONST_FUN const _Ty&& get(const array<_Ty, _Size>&& _Arr) _NOEXCEPT
	{	// return const element at _Idx in array _Arr
	_STATIC_ASSERT2(_Idx < _Size, "array index out of bounds");
	return (_STD move(_Arr._Elems[_Idx]));
	}

#if defined(__ghs)
//deduction guide
template<typename _Ty, typename... _Others>
  array(_Ty, _Others...) ->
      array<enable_if_t<(is_same<_Ty, _Others>::value && ...), _Ty>,
						        1 + sizeof...(_Others)>;
#endif

namespace experimental {
	inline namespace fundamentals_v2 {
	// TEMPLATE FUNCTION make_array
template<class _Ty = void,
	class... _Types> inline
	_CONST_FUN array<
		conditional_t<is_void<_Ty>::value,
			typename common_type<decay_t<_Types>...>::type,
			_Ty>,
		sizeof... (_Types)>
	make_array(_Types... _Args)
	{	// make an array
	typedef array<
		conditional_t<is_void<_Ty>::value,
			typename common_type<decay_t<_Types>...>::type,
			_Ty>,
		sizeof... (_Types)> _Myarr;
	return (_Myarr(_STD forward<_Types>(_Args)...));
	}

	// TEMPLATE FUNCTION to_array
template<class _Ty,
	size_t _Size> inline
	_CONST_FUN array<remove_cv_t<_Ty>, _Size>
		to_array(_Ty (&_Arg)[_Size])
	{	// make an array
	array<remove_cv_t<_Ty>, _Size> _Arr;
	for (size_t _Idx = 0; _Idx < _Size; ++_Idx)
		_Arr[_Idx] = _Arg[_Idx];
	return (_Arr);
	}
		} // namespace fundamentals_v2
	} // namespace experimental
using namespace experimental::fundamentals_v2;
 #endif /* _HAS_CPP17 */

 #if _HAS_TR1_IMPORTS
namespace tr1 {	// TR1 ADDITIONS
using _STD array;
using _STD get;
	} // namespace tr1
 #endif /* _HAS_TR1_IMPORTS */

_STD_END

 #if defined(__ghs)
  #if defined(__ghs_max_pack_value)
   #pragma pack(pop)
  #endif /* defined(__ghs_max_pack_value) */
  #pragma ghs enddata
  #pragma ghs end_cxx_lib_header
 #endif /* defined(__ghs) */

#endif /* _ARRAY_ */

/*
 * Copyright (c) by P.J. Plauger. All rights reserved.
 * Consult your license regarding permissions and restrictions.
V8.03b/17:0063 */
