Merge branch 'master' of ssh://rexy712.chickenkiller.com:1995/var/git/repos/rexy712/our_dick into master

This commit is contained in:
r0nk 2020-08-15 15:57:24 -05:00
commit 37152e6935
4 changed files with 437 additions and 0 deletions

View File

@ -15,6 +15,7 @@ must do's:
prefer reference over pointer prefer reference over pointer
keep implementation in source files with template and constexpr as exceptions keep implementation in source files with template and constexpr as exceptions
keep template/constexpr implementations in .tpp files alongside the .hpp files keep template/constexpr implementations in .tpp files alongside the .hpp files
prefer nullptr over NULL
functions: functions:
50 max length 50 max length
comments max 2 lines comments max 2 lines

19
include/detail/math.hpp Normal file
View File

@ -0,0 +1,19 @@
#ifndef REXY_DETAIL_MATH_HPP
#define REXY_DETAIL_MATH_HPP
namespace math{
namespace detail{
struct zero_initialize_t{};
struct no_initialize_t{};
struct id_initialize_t{};
}
static inline constexpr detail::zero_initialize_t zero_initialize;
static inline constexpr detail::no_initialize_t no_initialize;
static inline constexpr detail::id_initialize_t id_initialize;
}
#endif

190
include/detail/matrix.hpp Normal file
View File

@ -0,0 +1,190 @@
#ifndef REXY_DETAIL_MATRIX_HPP
#define REXY_DETAIL_MATRIX_HPP
#include <cstdlib> //size_t
#include <utility> //integer_sequence
namespace math::detail{
template<size_t SW, size_t W = SW, size_t H = SW-1, size_t... Args>
struct gen_id_tup{
using tup = typename gen_id_tup<SW, W-1, H, Args..., 0>::tup;
};
template<size_t SW, size_t H, size_t... Args>
struct gen_id_tup<SW,SW,H,Args...>{
using tup = typename gen_id_tup<SW, SW-1, H, Args..., 1>::tup;
};
template<size_t SW, size_t H, size_t... Args>
struct gen_id_tup<SW,0,H,Args...>{
using tup = typename gen_id_tup<SW, SW, H-1, Args..., 0>::tup;
};
template<size_t SW, size_t... Args>
struct gen_id_tup<SW,SW,0,Args...>{
using tup = std::integer_sequence<size_t,Args...,1>;
};
template<size_t N, size_t... Args>
struct gen_zero_tup{
using tup = typename gen_zero_tup<N-1,Args...,0>::tup;
};
template<size_t... Args>
struct gen_zero_tup<0,Args...>{
using tup = std::integer_sequence<size_t,Args...>;
};
template<size_t W>
struct id_initialization_matrix{
using tuple = typename gen_id_tup<W>::tup;
};
template<size_t W, size_t H>
struct default_initialization_matrix{
using tuple = typename gen_zero_tup<W>::tup;
};
template<size_t W>
struct default_initialization_matrix<W,W>{
using tuple = typename id_initialization_matrix<W>::tuple;
};
template<class T, size_t R>
class mat_ref_obj
{
public:
using size_type = size_t;
protected:
T* m_data = nullptr;
public:
constexpr mat_ref_obj(T* d, size_type i):
m_data(d+i){}
constexpr T& operator[](size_type i){
return m_data[i*R];
}
constexpr const T& operator[](size_type i)const{
return m_data[i*R];
}
};
template<class T, size_t W, size_t H>
class matrix_base
{
static_assert(W > 0, "Cannot have 0 columns matrix");
static_assert(H > 0, "Cannot have 0 rows matrix");
public:
using value_type = T;
using size_type = size_t;
using pointer = value_type*;
using const_pointer = const value_type*;
using reference = value_type&;
using const_reference = const value_type&;
static constexpr size_type Columns = W;
static constexpr size_type Rows = H;
protected:
value_type m_data[W*H];
protected:
template<size_type... Ss>
constexpr matrix_base(std::integer_sequence<size_type,Ss...>):
m_data{Ss...}{}
public:
//Default construct as identity when square, zero otherwise
constexpr matrix_base(void):
matrix_base(typename detail::default_initialization_matrix<Columns,Rows>::tuple{}){}
//Range initializing constructors
constexpr explicit matrix_base(zero_initialize_t):
m_data{}{}
constexpr explicit matrix_base(no_initialize_t){}
template<class U = void>
constexpr explicit matrix_base(id_initialize_t):
matrix_base()
{
static_assert(Columns == Rows, "Identity initialization only supported on square matrices");
}
//Value initializing constructors
constexpr explicit matrix_base(value_type v){
for(size_type i = 0;i < Columns*Rows;++i)
m_data[i] = v;
}
template<class... Args>
constexpr explicit matrix_base(Args&&... args):
m_data{std::forward<Args>(args)...}{}
//Copying constructors
constexpr matrix_base(const matrix_base&) = default;
constexpr matrix_base(matrix_base&&) = default;
template<class U>
constexpr matrix_base(const matrix_base<U,Columns,Rows>& m){
using mat = decltype(m);
for(typename mat::size_type i = 0;i < mat::Columns*mat::Rows;++i)
m_data[i] = m.get(i);
}
~matrix_base(void) = default;
//Assignement
template<class U>
constexpr matrix_base& operator=(const matrix_base<U,Columns,Rows>& m){
using mat = decltype(m);
for(typename mat::size_type i = 0;i < mat::Columns*mat::Rows;++i)
m_data[i] = m.get(i);
return *this;
}
constexpr matrix_base& operator=(const matrix_base&) = default;
constexpr matrix_base& operator=(matrix_base&&) = default;
//Getters/Setters
constexpr auto operator[](size_type x){
return detail::mat_ref_obj<value_type,Rows>{m_data, x};
}
constexpr auto operator[](size_type x)const{
return detail::mat_ref_obj<const value_type,Rows>{m_data, x};
}
constexpr reference get(size_type x, size_type y){
return m_data[x+(y*Rows)];
}
constexpr const_reference get(size_type x, size_type y)const{
return m_data[x+(y*Rows)];
}
constexpr reference get(size_type i){
return m_data[i];
}
constexpr const_reference get(size_type i)const{
return m_data[i];
}
constexpr size_type columns(void)const{
return Columns;
}
constexpr size_type rows(void)const{
return Rows;
}
constexpr size_type size(void)const{
return Columns*Rows;
}
constexpr pointer raw(void){
return m_data;
}
constexpr const_pointer raw(void)const{
return m_data;
}
constexpr operator pointer(void){
return m_data;
}
constexpr operator const_pointer(void)const{
return m_data;
}
};
}
#endif

227
include/mat.hpp Normal file
View File

@ -0,0 +1,227 @@
/**
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 <http://www.gnu.org/licenses/>.
*/
#ifndef REXY_MAT_HPP
#define REXY_MAT_HPP
#include <cstdlib> //size_t
#include <utility> //integer_sequence
#include <type_traits> //decay_t
#include <cmath> //sin, cos
#include "detail/math.hpp"
#include "detail/matrix.hpp"
namespace math{
template<class T, size_t C, size_t R>
class matrix : public detail::matrix_base<T,C,R>
{
private:
using base = detail::matrix_base<T,C,R>;
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<T,C,R>::matrix_base;
using detail::matrix_base<T,C,R>::operator=;
};
template<class T>
class matrix<T,3,3> : public detail::matrix_base<T,3,3>
{
private:
using base = detail::matrix_base<T,3,3>;
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<T,3,3>::matrix_base;
using detail::matrix_base<T,3,3>::operator=;
template<class U = void>
static constexpr matrix rotation(value_type angle){
value_type c = std::cos(angle);
value_type s = std::sin(angle);
return rotation(s, c);
}
template<class U = void>
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<class T>
struct is_matrix_helper{
template<class U, size_t W, size_t H>
static std::true_type test(matrix<U,W,H>*);
static std::false_type test(void*);
static constexpr bool value = std::is_same<std::true_type,decltype(test(static_cast<std::decay_t<T>*>(nullptr)))>::value;
};
}
template<class... Ms>
struct is_matrix{
static constexpr bool value = (detail::is_matrix_helper<Ms>::value && ...);
};
namespace detail{
template<class M1, class M2>
struct are_same_size_matrix{
using l = std::decay_t<M1>;
using r = std::decay_t<M2>;
static constexpr bool value = is_matrix<M1,M2>::value && l::Columns == r::Columns && l::Rows == r::Rows;
};
template<class... Ms>
using enable_if_matrix = std::enable_if_t<is_matrix<Ms...>::value,int>;
template<class M1, class M2>
using enable_if_eq_matrix = std::enable_if_t<are_same_size_matrix<M1,M2>::value,int>;
}
template<class T, class U, size_t W, size_t H>
constexpr bool operator==(const matrix<T,W,H>& left, const matrix<U,W,H> right){
for(size_t i = 0;i < left.size();++i){
if(left.get(i) != right.get(i))
return false;
}
return true;
}
template<class T, class U, size_t W, size_t H>
constexpr bool operator!=(const matrix<T,W,H>& left, const matrix<U,W,H> right){
return !(left == right);
}
template<class T, class U, size_t R1, size_t C1, size_t C2>
constexpr auto operator*(const matrix<T,C1,R1>& left, const matrix<U,C2,C1>& right){
using res_t = decltype(std::declval<T>() * std::declval<U>());
matrix<res_t,C2,R1> 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<class T, class U, size_t C, size_t R>
constexpr auto operator*(const matrix<T,C,R>& left, U&& right){
using res_t = decltype(std::declval<T>() * std::declval<U>());
matrix<res_t,C,R> res(no_initialize);
for(size_t i = 0;i < left.size();++i){
res.get(i) = left.get(i) * std::forward<U>(right);
}
return res;
}
template<class T, class U, size_t C, size_t R>
constexpr auto operator/(const matrix<T,C,R>& left, U&& right){
using res_t = decltype(std::declval<T>() / std::declval<U>());
matrix<res_t,C,R> res(no_initialize);
for(size_t i = 0;i < left.size();++i){
res.get(i) = left.get(i) / std::forward<U>(right);
}
return res;
}
template<class T, class U, size_t C, size_t R>
constexpr auto operator+(const matrix<T,C,R>& left, const matrix<U,C,R>& right){
using res_t = decltype(std::declval<T>() + std::declval<U>());
matrix<res_t,C,R> res(no_initialize);
for(size_t i = 0;i < left.size();++i){
res.get(i) = left.get(i) + right.get(i);
}
return res;
}
template<class T, class U, size_t C, size_t R>
constexpr auto operator-(const matrix<T,C,R>& left, const matrix<U,C,R>& right){
using res_t = decltype(std::declval<T>() - std::declval<U>());
matrix<res_t,C,R> res(no_initialize);
for(size_t i = 0;i < left.size();++i){
res.get(i) = left.get(i) - right.get(i);
}
return res;
}
template<class T, class U, size_t C, size_t R>
constexpr auto operator-(const matrix<T,C,R>& left){
using res_t = decltype(std::declval<T>() - std::declval<U>());
matrix<res_t,C,R> res(no_initialize);
for(size_t i = 0;i < left.size();++i){
res.get(i) = -left.get(i);
}
return res;
}
template<class T, class U, size_t R1, size_t C1, size_t C2>
constexpr decltype(auto) operator*=(matrix<T,C1,R1>& left, const matrix<U,C2,C1>& 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<class T, class U, size_t C, size_t R>
constexpr decltype(auto) operator*=(matrix<T,C,R>& left, U&& right){
for(size_t i = 0;i < left.size();++i){
left.get(i) = left.get(i) * std::forward<U>(right);
}
return left;
}
template<class T, class U, size_t C, size_t R>
constexpr decltype(auto) operator/=(matrix<T,C,R>& left, U&& right){
for(size_t i = 0;i < left.size();++i){
left.get(i) = left.get(i) / std::forward<U>(right);
}
return left;
}
template<class T, class U, size_t C, size_t R>
constexpr decltype(auto) operator+=(matrix<T,C,R>& left, const matrix<U,C,R>& right){
for(size_t i = 0;i < left.size();++i){
left.get(i) = left.get(i) + right.get(i);
}
return left;
}
template<class T, class U, size_t C, size_t R>
constexpr decltype(auto) operator-=(matrix<T,C,R>& left, const matrix<U,C,R>& right){
for(size_t i = 0;i < left.size();++i){
left.get(i) = left.get(i) - right.get(i);
}
return left;
}
}
#endif