diff --git a/include/common/qvec.hh b/include/common/qvec.hh index dc39135f..3ba59bc6 100644 --- a/include/common/qvec.hh +++ b/include/common/qvec.hh @@ -29,6 +29,7 @@ #include #include #include +#include #include "common/mathlib.hh" template @@ -43,7 +44,7 @@ protected: public: using value_type = T; - inline qvec() = default; + constexpr qvec() = default; #ifdef __clang__ #pragma clang diagnostic push @@ -164,157 +165,117 @@ public: [[nodiscard]] constexpr T &operator[](const size_t idx) { return at(idx); } private: - template - static constexpr void add_impl(O &out, const FT &a, const F &b, std::index_sequence packed) + // OUT = op THIS[N] + template + constexpr auto utransform_impl(UnaryOperation func, std::index_sequence) const { - ((out[pack] = a[pack] + b[pack]), ...); + using R = decltype(-T()); + return qvec { func(at(pack))... }; + } + + // OUT = THIS[N] op IN + template + constexpr auto transform_impl(BinaryOperation func, const InputType &b, std::index_sequence) const + { + using R = decltype(func(T(), InputType())); + return qvec { func(at(pack), b)... }; + } + + // OUT = THIS[N] op IN[N] + template + constexpr auto transformv_impl(BinaryOperation func, const InputType &b, std::index_sequence) const + { + using R = decltype(func(T(), InputType()[0])); + return qvec { func(at(pack), b[pack])... }; } public: + template + constexpr auto utransform(UnaryOperation func) const + { + return utransform_impl(func, std::make_index_sequence()); + } + + template + constexpr auto transform(BinaryOperation func, const InputType &b) const + { + return transform_impl(func, b, std::make_index_sequence()); + } + + template + constexpr auto transformv(BinaryOperation func, const InputType &b) const + { + return transformv_impl(func, b, std::make_index_sequence()); + } + template [[nodiscard]] constexpr inline auto operator+(const qvec &other) const { - qvec v; - - add_impl(v, *this, other, std::make_index_sequence()); - - return v; + return transformv(std::plus(), other); } -private: - template - static constexpr void sub_impl(O &out, const FT &a, const F &b, std::index_sequence packed) - { - ((out[pack] = a[pack] - b[pack]), ...); - } - -public: template [[nodiscard]] constexpr inline auto operator-(const qvec &other) const { - qvec v; - - sub_impl(v, *this, other, std::make_index_sequence()); - - return v; - } - -private: - template - static constexpr void scale_v_impl(O &out, const FT &a, const F &b, std::index_sequence packed) - { - ((out[pack] = a[pack] * b), ...); + return transformv(std::minus(), other); } -public: template [[nodiscard]] constexpr inline auto operator*(const S &scale) const { - qvec v; - - scale_v_impl(v, *this, scale, std::make_index_sequence()); - - return v; - } - -private: - template - static constexpr void scale_vf_impl(O &out, const FT &a, const F &b, std::index_sequence packed) - { - ((out[pack] = a[pack] * b[pack]), ...); + return transform(std::multiplies(), scale); } -public: template [[nodiscard]] constexpr inline auto operator*(const qvec &scale) const { - qvec v; - - scale_vf_impl(v, *this, scale, std::make_index_sequence()); - - return v; - } - -private: - template - static constexpr void div_v_impl(O &out, const FT &a, const F &b, std::index_sequence packed) - { - ((out[pack] = a[pack] / b), ...); + return transformv(std::multiplies(), scale); } -public: template [[nodiscard]] constexpr inline auto operator/(const S &scale) const { - qvec v; - - div_v_impl(v, *this, scale, std::make_index_sequence()); - - return v; - } - -private: - template - static constexpr void div_vf_impl(O &out, const FT &a, const F &b, std::index_sequence packed) - { - ((out[pack] = a[pack] / b[pack]), ...); + return transform(std::divides(), scale); } -public: template [[nodiscard]] constexpr inline auto operator/(const qvec &scale) const { - qvec v; - - div_vf_impl(v, *this, scale, std::make_index_sequence()); - - return v; - } - -private: - template - static constexpr void inv_v_impl(O &out, const FT &a, std::index_sequence packed) - { - ((out[pack] = -a[pack]), ...); + return transformv(std::divides(), scale); } -public: [[nodiscard]] constexpr inline auto operator-() const { - qvec v; - - inv_v_impl(v, *this, std::make_index_sequence()); - - return v; + return utransform(std::negate()); } template - inline qvec operator+=(const qvec &other) + constexpr qvec operator+=(const qvec &other) { return *this = *this + other; } template - inline qvec operator-=(const qvec &other) + constexpr qvec operator-=(const qvec &other) { return *this = *this - other; } template - inline qvec operator*=(const S &scale) + constexpr qvec operator*=(const S &scale) { return *this = *this * scale; } template - inline qvec &operator*=(const qvec &other) + constexpr qvec &operator*=(const qvec &other) { return *this = *this * other; } template - inline qvec operator/=(const S &scale) + constexpr qvec operator/=(const S &scale) { return *this = *this / scale; } template - inline qvec operator/=(const qvec &other) + constexpr qvec operator/=(const qvec &other) { return *this = *this * other; }