#ifndef PARADISO_MATRIXBASE_HPP #define PARADISO_MATRIXBASE_HPP #include #include namespace paradiso { template struct MatrixBase { using value_type = Scalar; using reference = Scalar&; using const_reference = const Scalar&; using pointer = Scalar*; using const_pointer = const Scalar*; using iterator = Scalar*; using const_iterator = const Scalar*; constexpr pointer data() { return &derived().data[0]; } constexpr const_pointer data() const noexcept { return &derived().data[0]; } constexpr iterator begin() noexcept { return this->data(); } constexpr iterator end() noexcept { return this->data() + size(); } constexpr const_iterator begin() const noexcept { return this->data(); } constexpr const_iterator end() const noexcept { return this->data() + size(); } constexpr const_iterator cbegin() const noexcept { return this->data(); } constexpr const_iterator cend() const noexcept { return this->data() + size(); } constexpr Scalar& operator[](std::size_t i) { return this->data()[i]; } constexpr const Scalar& operator[](std::size_t i) const { return this->data()[i]; } Derived& derived() { return static_cast(*this); } const Derived& derived() const { return static_cast(*this); } std::size_t size() const { return std::extent::value; } constexpr Derived& fill(const Scalar& v) noexcept { std::fill(std::begin(*this), std::end(*this), Scalar(v)); return derived(); } static constexpr Derived zero() noexcept { Derived d; d.fill(0); return d; } constexpr Scalar squared_norm() const { return dot(*this, *this); } constexpr Scalar norm() const { return std::sqrt(squared_norm()); } constexpr Derived normalized() const { return *this / this->norm(); } constexpr void normalize() { *this /= this->norm(); } static constexpr Scalar dot(const Derived& a, const Derived& b) { return std::inner_product(std::begin(a), std::end(a), std::begin(b), Scalar{0}); } static constexpr Derived lerp(const Derived& a, const Derived& b, const Scalar& t) { return a + (b - a) * t; } constexpr void operator*=(const Scalar& b) { for (auto& e : *this) e *= b; } constexpr void operator/=(const Scalar& b) { for (auto& e : *this) e /= b; } constexpr void operator+=(const Scalar& b) { for (auto& e : *this) e += b; } constexpr void operator-=(const Scalar& b) { for (auto& e : *this) e -= b; } constexpr const Derived operator*(const Scalar& b) const { Derived r(derived()); for (auto& e : r) e *= b; return r; } constexpr const Derived operator/(const Scalar& b) const { Derived r(derived()); for (auto& e : r) e /= b; return r; } constexpr const Derived operator+(const Scalar& b) const { Derived r(derived()); for (auto& e : r) e += b; return r; } constexpr const Derived operator-(const Scalar& b) const { Derived r(derived()); for (auto& e : r) e -= b; return r; } }; } // namespace paradiso #endif