.. _program_listing_file_include_ripple_container_array.hpp: Program Listing for File array.hpp ================================== |exhale_lsh| :ref:`Return to documentation for file ` (``include/ripple/container/array.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #ifndef RIPPLE_CONTAINER_ARRAY_HPP #define RIPPLE_CONTAINER_ARRAY_HPP #include "array_traits.hpp" #include namespace ripple { template struct Array { static constexpr size_t elements = array_traits_t::size; public: ripple_all constexpr decltype(auto) operator[](size_t i) noexcept { return impl()->operator[](i); } ripple_all constexpr decltype(auto) operator[](size_t i) const noexcept { return impl()->operator[](i); } ripple_all constexpr auto size() const noexcept -> size_t { return array_traits_t::size; } /*==--- [comparison operators] -------------------------------------------==*/ template ripple_all constexpr auto operator==(const Array& other) noexcept -> bool { assert_size_match(); for (size_t i = 0; i < elements; ++i) { if (impl()->operator[](i) != other[i]) { return false; } } return true; } template = 0> ripple_all constexpr auto operator==(T val) const noexcept -> bool { for (size_t i = 0; i < elements; ++i) { if (impl()->operator[](i) != val) { return false; } } return true; } template ripple_all constexpr auto operator!=(const Array& other) noexcept -> bool { return !(*this == other); } template = 0> ripple_all constexpr auto operator!=(T val) const noexcept -> bool { for (size_t i = 0; i < elements; ++i) { if (impl()->operator[](i) != val) { return true; } } return false; } template ripple_all constexpr auto operator<=(const Array& other) noexcept -> bool { for (size_t i = 0; i < elements; ++i) { if (impl()->operator[](i) > other[i]) { return false; } } return true; } template = 0> ripple_all constexpr auto operator<=(T val) const noexcept -> bool { for (size_t i = 0; i < elements; ++i) { if (impl()->operator[](i) > val) { return false; } } return true; } template ripple_all constexpr auto operator>=(const Array& other) noexcept -> bool { for (size_t i = 0; i < elements; ++i) { if (impl()->operator[](i) < other[i]) { return false; } } return true; } template = 0> ripple_all constexpr auto operator>=(T val) const noexcept -> bool { for (size_t i = 0; i < elements; ++i) { if (impl()->operator[](i) < val) { return false; } } return true; } template ripple_all constexpr auto operator<(const Array& other) const noexcept -> bool { for (size_t i = 0; i < elements; ++i) { if (impl()->operator[](i) >= other[i]) { return false; } } return true; } template = 0> ripple_all constexpr auto operator<(T val) const noexcept -> bool { for (size_t i = 0; i < elements; ++i) { if (impl()->operator[](i) >= val) { return false; } } return true; } template ripple_all constexpr auto operator>(const Array& a) const noexcept -> bool { for (size_t i = 0; i < elements; ++i) { if (impl()->operator[](i) <= a[i]) { return false; } } return true; } template = 0> ripple_all constexpr auto operator>(T val) const noexcept -> bool { for (size_t i = 0; i < elements; ++i) { if (impl()->operator[](i) <= val) { return false; } } return true; } /*==--- [operator {+,+=} overloads] --------------------------------------==*/ template ripple_all constexpr auto operator+=(const Array& other) noexcept -> Impl& { assert_size_match(); unrolled_for_bounded( [&](auto i) { impl()->operator[](i) += other[i]; }); return *impl(); } template = 0> ripple_all constexpr auto operator+=(T val) noexcept -> Impl& { using Value = typename array_traits_t::Value; unrolled_for_bounded( [&](auto i) { impl()->operator[](i) += static_cast(val); }); return *impl(); } template > ripple_all constexpr auto operator+(const Array& other) const noexcept -> R { R result; unrolled_for_bounded( [&](auto i) { result[i] = impl()->operator[](i) + other[i]; }); return result; } template < typename T, typename R = array_impl_t, array_value_enable_t = 0> ripple_all constexpr auto operator+(T val) const noexcept -> R { R result; using Value = typename array_traits_t::Value; unrolled_for_bounded([&](auto i) { result[i] = impl()->operator[](i) + static_cast(val); }); return result; } /*==--- [operator {-,-=} overloads] --------------------------------------==*/ template ripple_all constexpr auto operator-=(const Array& other) noexcept -> Impl& { assert_size_match(); unrolled_for_bounded( [&](auto i) { impl()->operator[](i) -= other[i]; }); return *impl(); } template = 0> ripple_all constexpr auto operator-=(T val) noexcept -> Impl& { using Value = typename array_traits_t::Value; unrolled_for_bounded( [&](auto i) { impl()->operator[](i) -= static_cast(val); }); return *impl(); } template > ripple_all constexpr auto operator-(const Array& other) const noexcept -> R { R result; unrolled_for_bounded( [&](auto i) { result[i] = impl()->operator[](i) - other[i]; }); return result; } template < typename T, typename R = array_impl_t, array_value_enable_t = 0> ripple_all constexpr auto operator-(T val) const noexcept -> R { R result; using Value = typename array_traits_t::Value; unrolled_for_bounded([&](auto i) { result[i] = impl()->operator[](i) - static_cast(val); }); return result; } /*==--- [operator {*,*=} overloads] --------------------------------------==*/ template ripple_all constexpr auto operator*=(const Array& other) noexcept -> Impl& { assert_size_match(); unrolled_for_bounded( [&](auto i) { impl()->operator[](i) *= other[i]; }); return *impl(); } template = 0> ripple_all constexpr auto operator*=(T val) noexcept -> Impl& { using Value = typename array_traits_t::Value; unrolled_for_bounded( [&](auto i) { impl()->operator[](i) *= static_cast(val); }); return *impl(); } template > ripple_all constexpr auto operator*(const Array& other) const noexcept -> R { R result; unrolled_for_bounded( [&](auto i) { result[i] = impl()->operator[](i) * other[i]; }); return result; } template < typename T, typename R = array_impl_t, array_value_enable_t = 0> ripple_all constexpr auto operator*(T val) const noexcept -> R { R result; using Value = typename array_traits_t::Value; unrolled_for_bounded([&](auto i) { result[i] = impl()->operator[](i) * static_cast(val); }); return result; } /*==--- [operator {/,/=} overloads] --------------------------------------==*/ template ripple_all constexpr auto operator/=(const Array& other) noexcept -> Impl& { assert_size_match(); unrolled_for_bounded( [&](auto i) { impl()->operator[](i) /= other[i]; }); return *impl(); } template = 0> ripple_all constexpr auto operator/=(T val) noexcept -> Impl& { using Value = typename array_traits_t::Value; unrolled_for_bounded( [&](auto i) { impl()->operator[](i) /= static_cast(val); }); return *impl(); } template > ripple_all constexpr auto operator/(const Array& other) const noexcept -> R { R result; unrolled_for_bounded( [&](auto i) { result[i] = impl()->operator[](i) / other[i]; }); return result; } template < typename T, typename R = array_impl_t, array_value_enable_t = 0> ripple_all constexpr auto operator/(T val) const noexcept -> R { R result; using Value = typename array_traits_t::Value; unrolled_for_bounded([&](auto i) { result[i] = impl()->operator[](i) / static_cast(val); }); return result; } private: ripple_all constexpr auto impl() noexcept -> Impl* { return static_cast(this); } ripple_all constexpr auto impl() const noexcept -> const Impl* { return static_cast(this); } template ripple_all constexpr auto assert_size_match() const noexcept -> void { constexpr size_t size_other = array_traits_t::size; static_assert( size_other == elements, "Arrays have different number of elements"); } }; /*==--- [operator overloads] -----------------------------------------------==*/ template < typename T, typename Impl, typename R = array_impl_t, array_value_enable_t = 0> ripple_all constexpr auto operator+(T val, const Array& a) noexcept -> R { using Value = typename array_traits_t::Value; using Type = std::decay_t; static_assert( std::is_same_v || std::is_convertible_v, "Cannot perform operations on an array with a type which is not the " "value type, or convertible to the value type!"); R result; unrolled_for_bounded::size>( [&](auto i) { result[i] = static_cast(val) + a[i]; }); return result; } template < typename T, typename Impl, typename R = array_impl_t, array_value_enable_t = 0> ripple_all constexpr auto operator-(T val, const Array& a) noexcept -> R { using Value = typename array_traits_t::Value; using Type = std::decay_t; static_assert( std::is_same_v || std::is_convertible_v, "Cannot perform operations on an array with a type which is not the " "value type, or convertible to the value type!"); R result; unrolled_for_bounded::size>( [&](auto i) { result[i] = static_cast(val) - a[i]; }); return result; } template < typename T, typename Impl, typename R = array_impl_t, array_value_enable_t = 0> ripple_all constexpr auto operator*(T val, const Array& a) noexcept -> R { using Value = typename array_traits_t::Value; using Type = std::decay_t; static_assert( std::is_same_v || std::is_convertible_v, "Cannot perform operations on an array with a type which is not the " "value type, or convertible to the value type!"); R result; unrolled_for_bounded::size>( [&](auto i) { result[i] = static_cast(val) * a[i]; }); return result; } template < typename T, typename Impl, typename R = array_impl_t, array_value_enable_t = 0> ripple_all constexpr auto operator/(T val, const Array& a) noexcept -> R { using Value = typename array_traits_t::Value; using Type = std::decay_t; static_assert( std::is_same_v || std::is_convertible_v, "Cannot perform operations on an array with a type which is not the " "value type, or convertible to the value type!"); R result; unrolled_for_bounded::size>( [&](auto i) { result[i] = static_cast(val) / a[i]; }); return result; } } // namespace ripple #endif // RIPPLE_CONTAINER_ARRAY_HPP