#pragma once #include "aare/defs.hpp" #include #include #include #include namespace aare { template class ArrayExpr { public: static constexpr bool is_leaf = false; auto operator[](size_t i) const { return static_cast(*this)[i]; } auto operator()(size_t i) const { return static_cast(*this)[i]; } auto size() const { return static_cast(*this).size(); } std::array shape() const { return static_cast(*this).shape(); } }; template class ArrayAdd : public ArrayExpr, Ndim> { const A &arr1_; const B &arr2_; public: ArrayAdd(const A &arr1, const B &arr2) : arr1_(arr1), arr2_(arr2) { assert(arr1.size() == arr2.size()); } auto operator[](int i) const { return arr1_[i] + arr2_[i]; } size_t size() const { return arr1_.size(); } std::array shape() const { return arr1_.shape(); } }; template class ArraySub : public ArrayExpr, Ndim> { const A &arr1_; const B &arr2_; public: ArraySub(const A &arr1, const B &arr2) : arr1_(arr1), arr2_(arr2) { assert(arr1.size() == arr2.size()); } auto operator[](int i) const { return arr1_[i] - arr2_[i]; } size_t size() const { return arr1_.size(); } std::array shape() const { return arr1_.shape(); } }; template class ArrayMul : public ArrayExpr, Ndim> { const A &arr1_; const B &arr2_; public: ArrayMul(const A &arr1, const B &arr2) : arr1_(arr1), arr2_(arr2) { assert(arr1.size() == arr2.size()); } auto operator[](int i) const { return arr1_[i] * arr2_[i]; } size_t size() const { return arr1_.size(); } std::array shape() const { return arr1_.shape(); } }; template class ArrayDiv : public ArrayExpr, Ndim> { const A &arr1_; const B &arr2_; public: ArrayDiv(const A &arr1, const B &arr2) : arr1_(arr1), arr2_(arr2) { assert(arr1.size() == arr2.size()); } auto operator[](int i) const { return arr1_[i] / arr2_[i]; } size_t size() const { return arr1_.size(); } std::array shape() const { return arr1_.shape(); } }; template auto operator+(const ArrayExpr &arr1, const ArrayExpr &arr2) { return ArrayAdd, ArrayExpr, Ndim>(arr1, arr2); } template auto operator-(const ArrayExpr &arr1, const ArrayExpr &arr2) { return ArraySub, ArrayExpr, Ndim>(arr1, arr2); } template auto operator*(const ArrayExpr &arr1, const ArrayExpr &arr2) { return ArrayMul, ArrayExpr, Ndim>(arr1, arr2); } template auto operator/(const ArrayExpr &arr1, const ArrayExpr &arr2) { return ArrayDiv, ArrayExpr, Ndim>(arr1, arr2); } } // namespace aare