/** This file is a part of the rexy/r0nk/atlas project Copyright (C) 2020 rexy712 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef REXY_MAT_HPP #define REXY_MAT_HPP #include //size_t #include //integer_sequence #include //decay_t #include //sin, cos #include "detail/math.hpp" #include "detail/matrix.hpp" namespace math{ template class matrix : public detail::matrix_base { private: using base = detail::matrix_base; public: using value_type = typename base::value_type; using size_type = typename base::size_type; using pointer = typename base::pointer; using const_pointer = typename base::const_pointer; using reference = typename base::reference; using const_reference = typename base::const_reference; public: using detail::matrix_base::matrix_base; using detail::matrix_base::operator=; }; template class matrix : public detail::matrix_base { private: using base = detail::matrix_base; public: using value_type = typename base::value_type; using size_type = typename base::size_type; using pointer = typename base::pointer; using const_pointer = typename base::const_pointer; using reference = typename base::reference; using const_reference = typename base::const_reference; public: using detail::matrix_base::matrix_base; using detail::matrix_base::operator=; template static constexpr matrix rotation(value_type angle){ value_type c = std::cos(angle); value_type s = std::sin(angle); return rotation(s, c); } template static constexpr matrix rotation(value_type sin, value_type cos){ return matrix(cos, -sin, 0, sin, cos, 0, 0, 0, 1); } static constexpr matrix rotation(value_type angle_x, value_type angle_y, value_type angle_z){ //TODO } }; namespace detail{ template struct is_matrix_helper{ template static std::true_type test(matrix*); static std::false_type test(void*); static constexpr bool value = std::is_same*>(nullptr)))>::value; }; } template struct is_matrix{ static constexpr bool value = (detail::is_matrix_helper::value && ...); }; namespace detail{ template struct are_same_size_matrix{ using l = std::decay_t; using r = std::decay_t; static constexpr bool value = is_matrix::value && l::Columns == r::Columns && l::Rows == r::Rows; }; template using enable_if_matrix = std::enable_if_t::value,int>; template using enable_if_eq_matrix = std::enable_if_t::value,int>; } template constexpr bool operator==(const matrix& left, const matrix right){ for(size_t i = 0;i < left.size();++i){ if(left.get(i) != right.get(i)) return false; } return true; } template constexpr bool operator!=(const matrix& left, const matrix right){ return !(left == right); } template constexpr auto operator*(const matrix& left, const matrix& right){ using res_t = decltype(std::declval() * std::declval()); matrix res(no_initialize); size_t index = 0; for(size_t i = 0;i < right.rows();++i){ for(size_t j = 0;j < left.rows();++j){ for(size_t k = 0;k < left.columns();++k){ res.get(index) += left[j][k] * right[i][k]; } ++index; } } return res; } template constexpr auto operator*(const matrix& left, U&& right){ using res_t = decltype(std::declval() * std::declval()); matrix res(no_initialize); for(size_t i = 0;i < left.size();++i){ res.get(i) = left.get(i) * std::forward(right); } return res; } template constexpr auto operator/(const matrix& left, U&& right){ using res_t = decltype(std::declval() / std::declval()); matrix res(no_initialize); for(size_t i = 0;i < left.size();++i){ res.get(i) = left.get(i) / std::forward(right); } return res; } template constexpr auto operator+(const matrix& left, const matrix& right){ using res_t = decltype(std::declval() + std::declval()); matrix res(no_initialize); for(size_t i = 0;i < left.size();++i){ res.get(i) = left.get(i) + right.get(i); } return res; } template constexpr auto operator-(const matrix& left, const matrix& right){ using res_t = decltype(std::declval() - std::declval()); matrix res(no_initialize); for(size_t i = 0;i < left.size();++i){ res.get(i) = left.get(i) - right.get(i); } return res; } template constexpr auto operator-(const matrix& left){ using res_t = decltype(std::declval() - std::declval()); matrix res(no_initialize); for(size_t i = 0;i < left.size();++i){ res.get(i) = -left.get(i); } return res; } template constexpr decltype(auto) operator*=(matrix& left, const matrix& right){ //have to evaluate entire expression first since matrix multiplication depends on reusing many elements //cannot be expression templatized, TODO return (left = (left * right)); } template constexpr decltype(auto) operator*=(matrix& left, U&& right){ for(size_t i = 0;i < left.size();++i){ left.get(i) = left.get(i) * std::forward(right); } return left; } template constexpr decltype(auto) operator/=(matrix& left, U&& right){ for(size_t i = 0;i < left.size();++i){ left.get(i) = left.get(i) / std::forward(right); } return left; } template constexpr decltype(auto) operator+=(matrix& left, const matrix& right){ for(size_t i = 0;i < left.size();++i){ left.get(i) = left.get(i) + right.get(i); } return left; } template constexpr decltype(auto) operator-=(matrix& left, const matrix& right){ for(size_t i = 0;i < left.size();++i){ left.get(i) = left.get(i) - right.get(i); } return left; } } #endif