diff options
author | ancarola <raffaele.ancarola@epfl.ch> | 2019-02-11 12:48:58 +0100 |
---|---|---|
committer | ancarola <raffaele.ancarola@epfl.ch> | 2019-02-11 12:48:58 +0100 |
commit | 94d90dd045463a540fe14880b1c04e2ce44a1efe (patch) | |
tree | 90be7ed7f773d2d627341281373fd22473db21aa /include/mm | |
parent | Add CMake configuration, delete ninja files (diff) | |
download | libmm-94d90dd045463a540fe14880b1c04e2ce44a1efe.tar.gz libmm-94d90dd045463a540fe14880b1c04e2ce44a1efe.zip |
CMakeLists: include fixes, include tree structure modified
Diffstat (limited to 'include/mm')
-rw-r--r-- | include/mm | 11 | ||||
-rw-r--r-- | include/mm/mmvec.hpp | 330 |
2 files changed, 11 insertions, 330 deletions
diff --git a/include/mm b/include/mm new file mode 100644 index 0000000..7e9f02b --- /dev/null +++ b/include/mm @@ -0,0 +1,11 @@ +#pragma once + +/* MiniMath + * A mathematical vector library that (ab)uses modern C++ abstraction features. + * This header includes the entire library. + * + * Warning: having (ab)used a lot of templated code it is not recommended to + * include everything as it may slow down the compiler. + */ + +#include "mm/mmvec.hpp" diff --git a/include/mm/mmvec.hpp b/include/mm/mmvec.hpp deleted file mode 100644 index db3c390..0000000 --- a/include/mm/mmvec.hpp +++ /dev/null @@ -1,330 +0,0 @@ -/* mmvec.hpp - * Part of Mathematical library built (ab)using Modern C++ 17 abstractions. - * - * This library is not intended to be _performant_, it does not contain - * hand written SMID / SSE / AVX optimizations. It is instead an example - * of highly abstracted code, where Vectors can contain any data type. - * - * As a challenge, the vector data structure has been built on a container - * of static capacity. But if a dynamic base container is needed, the code - * should be easily modifiable to add further abstraction, by templating - * the container, and by consequence the allocator. - * - * Naoki Pross <naopross@thearcway.org> - * 2018 ~ 2019 - */ -#pragma once - -#include <cassert> -#include <cmath> - -#include <iostream> -#include <array> -#include <algorithm> -#include <numeric> -#include <complex> -#include <initializer_list> - -namespace mm { - // generic implementation - template<typename T, std::size_t d> - struct basic_vec; - - // usable specializations - template<typename T, std::size_t d> - struct vec; - template<typename T> - struct vec3; - template<typename T> - struct vec2; -} - -template<typename T, std::size_t d> -struct mm::basic_vec : public std::array<T, d> { - using type = T; - static constexpr std::size_t dimensions = d; - - // TODO: template away these - static constexpr T null_element = static_cast<T>(0); - static constexpr T unit_element = static_cast<T>(1); - static constexpr T unit_additive_inverse_element = static_cast<T>(-1); - - basic_vec(); - basic_vec(const std::initializer_list<T> l); - - // copyable to a vector of size n <= d - template<std::size_t n> basic_vec(const basic_vec<T, n>& other); - // movable to a vector of size n <= d - template<std::size_t n> basic_vec(basic_vec<T, n>&& other); - - T length() const; - - // copy operator= - template<std::size_t n> - basic_vec<T, d>& operator=(const mm::basic_vec<T, n>& other); - - // move operator= - template<std::size_t n> - basic_vec<T, d>& operator=(mm::basic_vec<T, n>&& other); - - template<std::size_t n> - basic_vec<T, d>& operator+=(const mm::basic_vec<T, n>& other); - - template<std::size_t n> - basic_vec<T, d>& operator-=(const mm::basic_vec<T, n>& other); - - - basic_vec<T, d>& operator*=(const T& scalar); -}; - - -// member functions for basic_vec - -template<typename T, std::size_t d> -mm::basic_vec<T, d>::basic_vec() : std::array<T, d>() { - this->fill(basic_vec<T, d>::null_element); -} - -template<typename T, std::size_t d> -mm::basic_vec<T, d>::basic_vec(const std::initializer_list<T> l) { - // why can't this sh*t be a constexpr with static_assert??? - assert(l.size() <= d); - std::copy(l.begin(), l.end(), this->begin()); -} - -template<typename T, std::size_t d> -template<std::size_t n> -mm::basic_vec<T, d>::basic_vec(const mm::basic_vec<T, n>& other) { - *this = other; -} - -template<typename T, std::size_t d> -template<std::size_t n> -mm::basic_vec<T, d>::basic_vec(basic_vec<T, n>&& other) { - *this = other; -} - -template<typename T, std::size_t d> -T mm::basic_vec<T, d>::length() const { - return std::sqrt(std::accumulate(this->begin(), this->end(), - basic_vec<T, d>::null_element, - [](const T& init, const T& val) -> T { - return init + val * val; - } - )); -} - - -// memeber operator overloads for basic_vec - -template<typename T, std::size_t d> -template<std::size_t n> -mm::basic_vec<T, d>& mm::basic_vec<T, d>::operator=(const mm::basic_vec<T, n>& other) { - static_assert( - d >= n, "cannot copy higher dimensional vector into a smaller one" - ); - - std::copy(other.begin(), other.end(), this->begin()); - - return *this; -} - -template<typename T, std::size_t d> -template<std::size_t n> -mm::basic_vec<T, d>& mm::basic_vec<T, d>::operator=(mm::basic_vec<T, n>&& other) { - static_assert( - d >= n, "cannot move a higher dimensional vector into a smaller one" - ); - - std::move(other.begin(), other.end(), this->begin()); - - return *this; -} - - -template<typename T, std::size_t d> -template<std::size_t n> -mm::basic_vec<T, d>& mm::basic_vec<T, d>::operator+=(const mm::basic_vec<T, n>& other) { - *this = *this + other; - return *this; -} - -template<typename T, std::size_t d> -template<std::size_t n> -mm::basic_vec<T, d>& mm::basic_vec<T, d>::operator-=(const mm::basic_vec<T, n>& other) { - *this = *this - other; - return *this; -} - -template<typename T, std::size_t d> -mm::basic_vec<T, d>& mm::basic_vec<T, d>::operator*=(const T& scalar) { - *this = *this * scalar; - return *this; -} - - -// operator overloads for basic_vec - -template<typename T, std::size_t d> -mm::basic_vec<T, d> operator+(const mm::basic_vec<T, d>& rhs, const mm::basic_vec<T, d>& lhs) { - mm::basic_vec<T, d> out; - - std::transform(rhs.begin(), rhs.end(), lhs.begin(), out.begin(), - [](const T& r, const T& l) -> T { - return r + l; - } - ); - - return out; -} - -template<typename T, std::size_t d> -mm::basic_vec<T, d> operator*(const mm::basic_vec<T, d>& rhs, const T& lhs) { - return lhs * rhs; -} - -template<typename T, std::size_t d> -mm::basic_vec<T, d> operator*(const T& rhs, const mm::basic_vec<T, d>& lhs) { - mm::basic_vec<T, d> out; - - std::transform(lhs.begin(), lhs.end(), out.begin(), - [rhs](const T& t) -> T { - return t * rhs; - }); - - return out; -} - -template<typename T, std::size_t d> -mm::basic_vec<T, d> operator-(const mm::basic_vec<T, d>& rhs, const mm::basic_vec<T, d>& lhs) { - return rhs + mm::basic_vec<T, d>::unit_additive_inverse_element * lhs; -} - -template<typename T, std::size_t d> -T operator*(const mm::basic_vec<T, d>& rhs, const mm::basic_vec<T, d>& lhs) { - return std::inner_product(rhs.begin(), rhs.end(), lhs.begin(), 0); -} - -template<typename T, std::size_t d> -std::ostream& operator<<(std::ostream& os, const mm::basic_vec<T, d>& v) { - os << "<"; - std::for_each(v.begin(), v.end() -1, [&](const T& el) { - os << el << ", "; - }); - os << v.back() << ">"; - - return os; -} - - -// actual vectors to use in your code - -template<typename T, std::size_t d> -class mm::vec: public mm::basic_vec<T, d> { -public: - vec(std::initializer_list<T> l) : basic_vec<T, d>(l) {} - - template<std::size_t n> - vec(const basic_vec<T, n>& other) : basic_vec<T, d>(other) {} -}; - - -// three dimensional specialization with a static cross product -// TODO: specialize operator+ for spherical coordinates - -template<typename T> -class mm::vec3 : public mm::basic_vec<T, 3> { -public: - vec3() : basic_vec<T, 3>() {} - vec3(std::initializer_list<T> l) : basic_vec<T, 3>(l) {} - - template<std::size_t n> - vec3(const basic_vec<T, n>& other) : basic_vec<T, 3>(other) {} - - T& x() { return this->at(0); } - T& y() { return this->at(1); } - T& z() { return this->at(2); } - - const T& x() const { return this->at(0); } - const T& y() const { return this->at(1); } - const T& z() const { return this->at(2); } - - T zenith() const; - T azimuth() const; - vec3<T> spherical() const; - - static vec3<T> cross(const vec3<T>& rhs, const vec3<T>& lhs); -}; - -template<typename T> -T mm::vec3<T>::zenith() const { - return std::acos(this->z() / this->length()); -} - -template<typename T> -T mm::vec3<T>::azimuth() const { - return std::atan(this->y() / this->x()); -} - -template<typename T> -mm::vec3<T> mm::vec3<T>::spherical() const { - return mm::vec3<T> { - this->length(), - this->zenith(), - this->azimuth(), - }; -} - -template<typename T> -mm::vec3<T> mm::vec3<T>::cross(const vec3<T>& rhs, const vec3<T>& lhs) { - mm::vec3<T> res; - - res.x() = (rhs.y() * lhs.z()) - (rhs.z() * lhs.y()); - res.y() = (rhs.z() * lhs.x()) - (rhs.x() * lhs.z()); - res.z() = (rhs.x() * lhs.y()) - (rhs.y() * lhs.x()); - - return res; -} - - -// two dimensional specialization with a polar conversion -// TODO: specialize operator+ for polar coordinates - -template<typename T> -class mm::vec2: public mm::basic_vec<T, 2> { -public: - vec2() : basic_vec<T, 2>() {} - vec2(std::initializer_list<T> l) : basic_vec<T, 2>(l) {} - - template<std::size_t n> - vec2(const basic_vec<T, n>& other) : basic_vec<T, 2>(other) {} - - T& x() { return this->at(0); } - T& y() { return this->at(1); } - - const T& x() const { return this->at(0); } - const T& y() const { return this->at(1); } - - T angle() const; - vec2<T> polar() const; - - static vec3<T> cross(const vec2<T>& rhs, const vec2<T>& lhs); -}; - -template<typename T> -T mm::vec2<T>::angle() const { - return std::atan(this->y() / this->x()); -} - -template<typename T> -mm::vec2<T> mm::vec2<T>::polar() const { - return mm::vec2 { - this->length(), - this->angle() - }; -} - -template<typename T> -mm::vec3<T> mm::vec2<T>::cross(const mm::vec2<T>& rhs, const mm::vec2<T>& lhs) { - return mm::vec3<T>::cross(mm::vec3<T>(rhs), mm::vec3<T>(lhs)); -} |