diff options
Diffstat (limited to 'source/core/StarArray.hpp')
-rw-r--r-- | source/core/StarArray.hpp | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/source/core/StarArray.hpp b/source/core/StarArray.hpp new file mode 100644 index 0000000..1b3e150 --- /dev/null +++ b/source/core/StarArray.hpp @@ -0,0 +1,254 @@ +#ifndef STAR_ARRAY_H +#define STAR_ARRAY_H + +#include <array> + +#include "StarHash.hpp" + +namespace Star { + +// Somewhat nicer form of std::array, always initializes values, uses nicer +// constructor pattern. +template <typename ElementT, size_t SizeN> +class Array : public std::array<ElementT, SizeN> { +public: + typedef std::array<ElementT, SizeN> Base; + + typedef ElementT Element; + static size_t const ArraySize = SizeN; + + typedef Element* iterator; + typedef Element const* const_iterator; + + typedef Element& reference; + typedef Element const& const_reference; + + typedef Element value_type; + + static Array filled(Element const& e); + + template <typename Iterator> + static Array copyFrom(Iterator p, size_t n = NPos); + + Array(); + + explicit Array(Element const& e1); + + template <typename... T> + Array(Element const& e1, T const&... rest); + + template <typename Element2> + explicit Array(Array<Element2, SizeN> const& a); + + template <size_t i> + reference get(); + + template <size_t i> + const_reference get() const; + + template <typename T2> + Array& operator=(Array<T2, SizeN> const& array); + + Element* ptr(); + Element const* ptr() const; + + bool operator==(Array const& a) const; + bool operator!=(Array const& a) const; + bool operator<(Array const& a) const; + bool operator<=(Array const& a) const; + bool operator>(Array const& a) const; + bool operator>=(Array const& a) const; + + template <size_t Size2> + Array<ElementT, Size2> toSize() const; + +private: + // Instead of {} array initialization, use recursive assignment to mimic old + // C++ style construction with less strict narrowing rules. + template <typename T, typename... TL> + void set(T const& e, TL const&... rest); + void set(); +}; + +template <typename DataT, size_t SizeT> +struct hash<Array<DataT, SizeT>> { + size_t operator()(Array<DataT, SizeT> const& a) const; + Star::hash<DataT> dataHasher; +}; + +typedef Array<int, 2> Array2I; +typedef Array<size_t, 2> Array2S; +typedef Array<unsigned, 2> Array2U; +typedef Array<float, 2> Array2F; +typedef Array<double, 2> Array2D; + +typedef Array<int, 3> Array3I; +typedef Array<size_t, 3> Array3S; +typedef Array<unsigned, 3> Array3U; +typedef Array<float, 3> Array3F; +typedef Array<double, 3> Array3D; + +typedef Array<int, 4> Array4I; +typedef Array<size_t, 4> Array4S; +typedef Array<unsigned, 4> Array4U; +typedef Array<float, 4> Array4F; +typedef Array<double, 4> Array4D; + +template <typename Element, size_t Size> +Array<Element, Size> Array<Element, Size>::filled(Element const& e) { + Array a; + a.fill(e); + return a; +} + +template <typename Element, size_t Size> +template <typename Iterator> +Array<Element, Size> Array<Element, Size>::copyFrom(Iterator p, size_t n) { + Array a; + for (size_t i = 0; i < n && i < Size; ++i) + a[i] = *(p++); + return a; +} + +template <typename Element, size_t Size> +Array<Element, Size>::Array() + : Base() {} + +template <typename Element, size_t Size> +Array<Element, Size>::Array(Element const& e1) { + static_assert(Size == 1, "Incorrect size in Array constructor"); + set(e1); +} + +template <typename Element, size_t Size> +template <typename... T> +Array<Element, Size>::Array(Element const& e1, T const&... rest) { + static_assert(sizeof...(rest) == Size - 1, "Incorrect size in Array constructor"); + set(e1, rest...); +} + +template <typename Element, size_t Size> +template <typename Element2> +Array<Element, Size>::Array(Array<Element2, Size> const& a) { + std::copy(a.begin(), a.end(), Base::begin()); +} + +template <typename Element, size_t Size> +template <size_t i> +auto Array<Element, Size>::get() -> reference { + static_assert(i < Size, "Incorrect size in Array::at"); + return Base::operator[](i); +} + +template <typename Element, size_t Size> +template <size_t i> +auto Array<Element, Size>::get() const -> const_reference { + static_assert(i < Size, "Incorrect size in Array::at"); + return Base::operator[](i); +} + +template <typename Element, size_t Size> +template <typename T2> +Array<Element, Size>& Array<Element, Size>::operator=(Array<T2, Size> const& array) { + std::copy(array.begin(), array.end(), Base::begin()); + return *this; +} + +template <typename Element, size_t Size> +Element* Array<Element, Size>::ptr() { + return Base::data(); +} + +template <typename Element, size_t Size> +Element const* Array<Element, Size>::ptr() const { + return Base::data(); +} + +template <typename Element, size_t Size> +bool Array<Element, Size>::operator==(Array const& a) const { + for (size_t i = 0; i < Size; ++i) + if ((*this)[i] != a[i]) + return false; + return true; +} + +template <typename Element, size_t Size> +bool Array<Element, Size>::operator!=(Array const& a) const { + return !operator==(a); +} + +template <typename Element, size_t Size> +bool Array<Element, Size>::operator<(Array const& a) const { + for (size_t i = 0; i < Size; ++i) { + if ((*this)[i] < a[i]) + return true; + else if (a[i] < (*this)[i]) + return false; + } + return false; +} + +template <typename Element, size_t Size> +bool Array<Element, Size>::operator<=(Array const& a) const { + for (size_t i = 0; i < Size; ++i) { + if ((*this)[i] < a[i]) + return true; + else if (a[i] < (*this)[i]) + return false; + } + return true; +} + +template <typename Element, size_t Size> +bool Array<Element, Size>::operator>(Array const& a) const { + return a < *this; +} + +template <typename Element, size_t Size> +bool Array<Element, Size>::operator>=(Array const& a) const { + return a <= *this; +} + +template <typename Element, size_t Size> +template <size_t Size2> +Array<Element, Size2> Array<Element, Size>::toSize() const { + Array<Element, Size2> r; + size_t ns = std::min(Size2, Size); + for (size_t i = 0; i < ns; ++i) + r[i] = (*this)[i]; + return r; +} + +template <typename Element, size_t Size> +void Array<Element, Size>::set() {} + +template <typename Element, size_t Size> +template <typename T, typename... TL> +void Array<Element, Size>::set(T const& e, TL const&... rest) { + Base::operator[](Size - 1 - sizeof...(rest)) = e; + set(rest...); +} + +template <typename Element, size_t Size> +std::ostream& operator<<(std::ostream& os, Array<Element, Size> const& a) { + os << '['; + for (size_t i = 0; i < Size; ++i) { + os << a[i]; + if (i != Size - 1) + os << ", "; + } + os << ']'; + return os; +} + +template <typename DataT, size_t SizeT> +size_t hash<Array<DataT, SizeT>>::operator()(Array<DataT, SizeT> const& a) const { + size_t hashval = 0; + for (size_t i = 0; i < SizeT; ++i) + hashCombine(hashval, dataHasher(a[i])); + return hashval; +} + +} + +#endif |