From 44e70eca283d006c6a2ec33fd78b8a55fb5c46a7 Mon Sep 17 00:00:00 2001 From: ancarola Date: Tue, 5 Feb 2019 13:56:01 +0100 Subject: Test directory creation --- example.cpp | 62 -------------------------------------------------------- test/example.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 62 deletions(-) delete mode 100644 example.cpp create mode 100644 test/example.cpp diff --git a/example.cpp b/example.cpp deleted file mode 100644 index 3a00f58..0000000 --- a/example.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "mmvec.hpp" - -#include -#include - -int main(int argc, char *argv[]) { - // N dimensional vectors - std::cout << "N dimensional (int) vectors" << std::endl; - mm::vec u {3, 2, 1, 0, 1}; - mm::vec v {1, 2, 3, 4, 5}; - - std::cout << "u = " << u << std::endl; - std::cout << "v = " << v << std::endl; - std::cout << std::endl; - - // basic operations - std::cout << "u + v = " << u + v << std::endl; - std::cout << "u - v = " << u - v << std::endl; - std::cout << "2 * v = " << 2 * v << std::endl; - std::cout << "v * 2 = " << v * 2 << std::endl; - std::cout << "u * v = " << u * v << std::endl; - std::cout << std::endl; - - u += v; - - // three dimensional vectors - std::cout << "three dimensional (double) vectors" << std::endl; - - mm::vec3 a {1, 2, 3}; - mm::vec3 b {3, 2, 1}; - - std::cout << "a = " << a << std::endl; - std::cout << "b = " << b << std::endl; - std::cout << std::endl; - - std::cout << "a x b = " << mm::vec3::cross(a, b) << std::endl; - std::cout << "zenith(a) = " << a.zenith() << std::endl; - std::cout << "azimuth(a) = " << a.azimuth() << std::endl; - std::cout << "spherical(a) = " << a.spherical() << std::endl; - std::cout << std::endl; - - a -= b; - - // two dimensional vector - std::cout << "two dimensional (complex) vectors" << std::endl; - - mm::vec2> j {{1, 2}, {3, -1}}; - mm::vec2> k { 5, {-2, 1}}; - - std::cout << "j = " << j << std::endl; - std::cout << "k = " << k << std::endl; - std::cout << std::endl; - - std::cout << "j x k = " << mm::vec2>::cross(j, k) << std::endl; - std::cout << "angle(j) = " << j.angle() << std::endl; - std::cout << "polar(j) = " << j.polar() << std::endl; - std::cout << std::endl; - - j *= 10; - - return 0; -} diff --git a/test/example.cpp b/test/example.cpp new file mode 100644 index 0000000..3a00f58 --- /dev/null +++ b/test/example.cpp @@ -0,0 +1,62 @@ +#include "mmvec.hpp" + +#include +#include + +int main(int argc, char *argv[]) { + // N dimensional vectors + std::cout << "N dimensional (int) vectors" << std::endl; + mm::vec u {3, 2, 1, 0, 1}; + mm::vec v {1, 2, 3, 4, 5}; + + std::cout << "u = " << u << std::endl; + std::cout << "v = " << v << std::endl; + std::cout << std::endl; + + // basic operations + std::cout << "u + v = " << u + v << std::endl; + std::cout << "u - v = " << u - v << std::endl; + std::cout << "2 * v = " << 2 * v << std::endl; + std::cout << "v * 2 = " << v * 2 << std::endl; + std::cout << "u * v = " << u * v << std::endl; + std::cout << std::endl; + + u += v; + + // three dimensional vectors + std::cout << "three dimensional (double) vectors" << std::endl; + + mm::vec3 a {1, 2, 3}; + mm::vec3 b {3, 2, 1}; + + std::cout << "a = " << a << std::endl; + std::cout << "b = " << b << std::endl; + std::cout << std::endl; + + std::cout << "a x b = " << mm::vec3::cross(a, b) << std::endl; + std::cout << "zenith(a) = " << a.zenith() << std::endl; + std::cout << "azimuth(a) = " << a.azimuth() << std::endl; + std::cout << "spherical(a) = " << a.spherical() << std::endl; + std::cout << std::endl; + + a -= b; + + // two dimensional vector + std::cout << "two dimensional (complex) vectors" << std::endl; + + mm::vec2> j {{1, 2}, {3, -1}}; + mm::vec2> k { 5, {-2, 1}}; + + std::cout << "j = " << j << std::endl; + std::cout << "k = " << k << std::endl; + std::cout << std::endl; + + std::cout << "j x k = " << mm::vec2>::cross(j, k) << std::endl; + std::cout << "angle(j) = " << j.angle() << std::endl; + std::cout << "polar(j) = " << j.polar() << std::endl; + std::cout << std::endl; + + j *= 10; + + return 0; +} -- cgit v1.2.1 From 7e17d196eb888829dbfe31a7c0616350ba8114e8 Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Thu, 7 Feb 2019 18:17:53 +0100 Subject: Add move constructor and move operator= to mmvec --- include/mm/mmvec.hpp | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/include/mm/mmvec.hpp b/include/mm/mmvec.hpp index 4bac658..db3c390 100644 --- a/include/mm/mmvec.hpp +++ b/include/mm/mmvec.hpp @@ -51,13 +51,22 @@ struct mm::basic_vec : public std::array { basic_vec(); basic_vec(const std::initializer_list l); + + // copyable to a vector of size n <= d template basic_vec(const basic_vec& other); + // movable to a vector of size n <= d + template basic_vec(basic_vec&& other); T length() const; + // copy operator= template basic_vec& operator=(const mm::basic_vec& other); + // move operator= + template + basic_vec& operator=(mm::basic_vec&& other); + template basic_vec& operator+=(const mm::basic_vec& other); @@ -78,9 +87,6 @@ mm::basic_vec::basic_vec() : std::array() { template mm::basic_vec::basic_vec(const std::initializer_list l) { - // construct with empty values - basic_vec(); - // why can't this sh*t be a constexpr with static_assert??? assert(l.size() <= d); std::copy(l.begin(), l.end(), this->begin()); @@ -89,9 +95,12 @@ mm::basic_vec::basic_vec(const std::initializer_list l) { template template mm::basic_vec::basic_vec(const mm::basic_vec& other) { - // construct with empty values - basic_vec(); - // uses operator= + *this = other; +} + +template +template +mm::basic_vec::basic_vec(basic_vec&& other) { *this = other; } @@ -120,6 +129,19 @@ mm::basic_vec& mm::basic_vec::operator=(const mm::basic_vec& o return *this; } +template +template +mm::basic_vec& mm::basic_vec::operator=(mm::basic_vec&& 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 template mm::basic_vec& mm::basic_vec::operator+=(const mm::basic_vec& other) { -- cgit v1.2.1 From c74446c3e6a88ffbb13743dcc9f3b93d10aa009d Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Sun, 10 Feb 2019 22:41:15 +0100 Subject: Add CMake configuration, delete ninja files The new CMake configuration builds only static libraries --- CMakeLists.txt | 107 ++++++++++++++++++++++++++++++++++++++++++++++++ build.ninja | 11 ----- cmake/MMConfig.cmake.in | 9 ++++ ninja/rules.ninja | 27 ------------ 4 files changed, 116 insertions(+), 38 deletions(-) create mode 100644 CMakeLists.txt delete mode 100644 build.ninja create mode 100644 cmake/MMConfig.cmake.in delete mode 100644 ninja/rules.ninja diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..c31e16b --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,107 @@ +cmake_minimum_required(VERSION 3.10) +project( + MM + VERSION 0.1 + DESCRIPTION "MiniMath, a mathematical library that (ab)uses abstraction" + LANGUAGES CXX +) + +list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake) + +############################ +# build libmm +add_library(mm STATIC + mmvec.cpp +) + +add_library(MM:mm ALIAS mm) + +# set up headers +target_include_directories(mm + PUBLIC + $ + $ + PRIVATE + ${CMAKE_CURRENT_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include/mm +) + +target_compile_options(mm + PRIVATE + $<$: + -pedantic -Wall -Wextra -Wcast-qual -Wcast-align -Wpointer-arith + -Winit-self -Wshadow -Wswitch-enum -Wredundant-decls -Wfloat-equal + -Wundef -Wvla -Wconversion -Wstrict-aliasing + > + $<$:/W4> +) + +target_compile_definitions(mm + PRIVATE + $<$:DEBUG> +) + +# set compiler features +# For a complete list see: +# https://cmake.org/cmake/help/latest/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html +target_compile_features(mm + PRIVATE + cxx_std_17 +) + + +############################ +# installation +include(GNUInstallDirs) +set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/MM) + +install(TARGETS mm + EXPORT mm-targets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} +) + +set_target_properties(mm PROPERTIES EXPORT_NAME MM) + +# install public headers +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + +# export targets +install(EXPORT mm-targets + FILE + MMTargets.cmake + NAMESPACE + MM:: + DESTINATION + ${INSTALL_CONFIGDIR} +) + +# create ConfigVersion.cmake +include(CMakePackageConfigHelpers) +write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/MMConfigVersion.cmake + VERSION ${PROJECT_VERSION} + COMPATIBILITY AnyNewerVersion +) + +configure_package_config_file( + ${CMAKE_CURRENT_LIST_DIR}/cmake/MMConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/MMConfig.cmake + INSTALL_DESTINATION ${INSTALL_CONFIGDIR} +) + +# install config, configversion +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/MMConfig.cmake + ${CMAKE_CURRENT_BINARY_DIR}/MMConfigVersion.cmake + DESTINATION ${INSTALL_CONFIGDIR} +) + +############################ +# export from the build tree +export(EXPORT mm-targets + FILE ${CMAKE_CURRENT_BINARY_DIR}/MMTargets.cmake + NAMESPACE MM:: +) + +export(PACKAGE MM) diff --git a/build.ninja b/build.ninja deleted file mode 100644 index 9f51a13..0000000 --- a/build.ninja +++ /dev/null @@ -1,11 +0,0 @@ -include ninja/rules.ninja - -# libmm -build build/mmvec.o: cpp mmvec.cpp - -build build/libmm.a: link-static build/mmvec.o -build build/libmm.so: link-shared build/mmvec.o - -# examples -build build/example.o: cpp example.cpp -build build/example: link build/example.o diff --git a/cmake/MMConfig.cmake.in b/cmake/MMConfig.cmake.in new file mode 100644 index 0000000..c338eae --- /dev/null +++ b/cmake/MMConfig.cmake.in @@ -0,0 +1,9 @@ +get_filename_component(MM_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) + +list(REMOVE_AT CMAKE_MODULE_PATH -1) + +if (NOT TARGET MM::MM) + include("${MM_CMAKE_DIR}/MMTargets.cmake") +endif() + +set(MM_LIBRARIES MM::MM) diff --git a/ninja/rules.ninja b/ninja/rules.ninja deleted file mode 100644 index a17c01a..0000000 --- a/ninja/rules.ninja +++ /dev/null @@ -1,27 +0,0 @@ -includes = -I include/mm -cflags = -Wall -Werror -pedantic -fPIC -std=c++17 $includes - -libs = -lflags = $libs - -flags = -fdiagnostics-color - -rule mkdir - command = mkdir -p $out - description = creating directory $out - -rule cpp - command = g++ $flags $cflags -c $in -o $out $lflags - description = compiling $in - -rule link - command = g++ $flags $cflags -o $out $in $lflags - description = linking $out - -rule link-shared - command = g++ $flags $cflags -shared -o $out $in $lflags - description = linking shared object $out - -rule link-static - command = ar rvs $out $in - description = creating archive $out -- cgit v1.2.1 From 2aa0371a6848b3aae4d4183eb7b4ae12558f820a Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Mon, 11 Feb 2019 00:11:16 +0100 Subject: Fix MMConfig.cmake.in --- cmake/MMConfig.cmake.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmake/MMConfig.cmake.in b/cmake/MMConfig.cmake.in index c338eae..de91981 100644 --- a/cmake/MMConfig.cmake.in +++ b/cmake/MMConfig.cmake.in @@ -1,5 +1,9 @@ get_filename_component(MM_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) +include(CMakeFindDependencyMacro) +list(APPEND CMAKE_MODULE_PATH ${MM_CMAKE_DIR}) +# add dependencies if needed +# add_dependency() list(REMOVE_AT CMAKE_MODULE_PATH -1) if (NOT TARGET MM::MM) -- cgit v1.2.1 From 94d90dd045463a540fe14880b1c04e2ce44a1efe Mon Sep 17 00:00:00 2001 From: ancarola Date: Mon, 11 Feb 2019 12:48:58 +0100 Subject: CMakeLists: include fixes, include tree structure modified --- .gitignore | 1 + CMakeLists.txt | 14 +- cmake/MMConfig.cmake.in | 2 +- include/mm | 11 ++ include/mm.hpp | 11 -- include/mm/mmvec.hpp | 330 ------------------------------------------------ include/mmvec.hpp | 330 ++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 356 insertions(+), 343 deletions(-) create mode 100644 include/mm delete mode 100644 include/mm.hpp delete mode 100644 include/mm/mmvec.hpp create mode 100644 include/mmvec.hpp diff --git a/.gitignore b/.gitignore index ac480cc..3779814 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ build .ninja* +CMakeFiles diff --git a/CMakeLists.txt b/CMakeLists.txt index c31e16b..6e7d073 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,8 +63,20 @@ install(TARGETS mm set_target_properties(mm PROPERTIES EXPORT_NAME MM) + +if ("${CMAKE_SYSTEM}" MATCHES "Linux") + +# too bad but no other simpler choise +file(GLOB INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/include/*") + # install public headers -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +install(FILES ${INCLUDE_FILES} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/mm +) + +endif() + +# TODO, install setup for windows too # export targets install(EXPORT mm-targets diff --git a/cmake/MMConfig.cmake.in b/cmake/MMConfig.cmake.in index c338eae..b2857ae 100644 --- a/cmake/MMConfig.cmake.in +++ b/cmake/MMConfig.cmake.in @@ -1,6 +1,6 @@ get_filename_component(MM_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) -list(REMOVE_AT CMAKE_MODULE_PATH -1) +#list(REMOVE_AT CMAKE_MODULE_PATH -1) if (NOT TARGET MM::MM) include("${MM_CMAKE_DIR}/MMTargets.cmake") 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.hpp b/include/mm.hpp deleted file mode 100644 index 7e9f02b..0000000 --- a/include/mm.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#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 - * 2018 ~ 2019 - */ -#pragma once - -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace mm { - // generic implementation - template - struct basic_vec; - - // usable specializations - template - struct vec; - template - struct vec3; - template - struct vec2; -} - -template -struct mm::basic_vec : public std::array { - using type = T; - static constexpr std::size_t dimensions = d; - - // TODO: template away these - static constexpr T null_element = static_cast(0); - static constexpr T unit_element = static_cast(1); - static constexpr T unit_additive_inverse_element = static_cast(-1); - - basic_vec(); - basic_vec(const std::initializer_list l); - - // copyable to a vector of size n <= d - template basic_vec(const basic_vec& other); - // movable to a vector of size n <= d - template basic_vec(basic_vec&& other); - - T length() const; - - // copy operator= - template - basic_vec& operator=(const mm::basic_vec& other); - - // move operator= - template - basic_vec& operator=(mm::basic_vec&& other); - - template - basic_vec& operator+=(const mm::basic_vec& other); - - template - basic_vec& operator-=(const mm::basic_vec& other); - - - basic_vec& operator*=(const T& scalar); -}; - - -// member functions for basic_vec - -template -mm::basic_vec::basic_vec() : std::array() { - this->fill(basic_vec::null_element); -} - -template -mm::basic_vec::basic_vec(const std::initializer_list 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 -template -mm::basic_vec::basic_vec(const mm::basic_vec& other) { - *this = other; -} - -template -template -mm::basic_vec::basic_vec(basic_vec&& other) { - *this = other; -} - -template -T mm::basic_vec::length() const { - return std::sqrt(std::accumulate(this->begin(), this->end(), - basic_vec::null_element, - [](const T& init, const T& val) -> T { - return init + val * val; - } - )); -} - - -// memeber operator overloads for basic_vec - -template -template -mm::basic_vec& mm::basic_vec::operator=(const mm::basic_vec& 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 -template -mm::basic_vec& mm::basic_vec::operator=(mm::basic_vec&& 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 -template -mm::basic_vec& mm::basic_vec::operator+=(const mm::basic_vec& other) { - *this = *this + other; - return *this; -} - -template -template -mm::basic_vec& mm::basic_vec::operator-=(const mm::basic_vec& other) { - *this = *this - other; - return *this; -} - -template -mm::basic_vec& mm::basic_vec::operator*=(const T& scalar) { - *this = *this * scalar; - return *this; -} - - -// operator overloads for basic_vec - -template -mm::basic_vec operator+(const mm::basic_vec& rhs, const mm::basic_vec& lhs) { - mm::basic_vec out; - - std::transform(rhs.begin(), rhs.end(), lhs.begin(), out.begin(), - [](const T& r, const T& l) -> T { - return r + l; - } - ); - - return out; -} - -template -mm::basic_vec operator*(const mm::basic_vec& rhs, const T& lhs) { - return lhs * rhs; -} - -template -mm::basic_vec operator*(const T& rhs, const mm::basic_vec& lhs) { - mm::basic_vec out; - - std::transform(lhs.begin(), lhs.end(), out.begin(), - [rhs](const T& t) -> T { - return t * rhs; - }); - - return out; -} - -template -mm::basic_vec operator-(const mm::basic_vec& rhs, const mm::basic_vec& lhs) { - return rhs + mm::basic_vec::unit_additive_inverse_element * lhs; -} - -template -T operator*(const mm::basic_vec& rhs, const mm::basic_vec& lhs) { - return std::inner_product(rhs.begin(), rhs.end(), lhs.begin(), 0); -} - -template -std::ostream& operator<<(std::ostream& os, const mm::basic_vec& 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 -class mm::vec: public mm::basic_vec { -public: - vec(std::initializer_list l) : basic_vec(l) {} - - template - vec(const basic_vec& other) : basic_vec(other) {} -}; - - -// three dimensional specialization with a static cross product -// TODO: specialize operator+ for spherical coordinates - -template -class mm::vec3 : public mm::basic_vec { -public: - vec3() : basic_vec() {} - vec3(std::initializer_list l) : basic_vec(l) {} - - template - vec3(const basic_vec& other) : basic_vec(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 spherical() const; - - static vec3 cross(const vec3& rhs, const vec3& lhs); -}; - -template -T mm::vec3::zenith() const { - return std::acos(this->z() / this->length()); -} - -template -T mm::vec3::azimuth() const { - return std::atan(this->y() / this->x()); -} - -template -mm::vec3 mm::vec3::spherical() const { - return mm::vec3 { - this->length(), - this->zenith(), - this->azimuth(), - }; -} - -template -mm::vec3 mm::vec3::cross(const vec3& rhs, const vec3& lhs) { - mm::vec3 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 -class mm::vec2: public mm::basic_vec { -public: - vec2() : basic_vec() {} - vec2(std::initializer_list l) : basic_vec(l) {} - - template - vec2(const basic_vec& other) : basic_vec(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 polar() const; - - static vec3 cross(const vec2& rhs, const vec2& lhs); -}; - -template -T mm::vec2::angle() const { - return std::atan(this->y() / this->x()); -} - -template -mm::vec2 mm::vec2::polar() const { - return mm::vec2 { - this->length(), - this->angle() - }; -} - -template -mm::vec3 mm::vec2::cross(const mm::vec2& rhs, const mm::vec2& lhs) { - return mm::vec3::cross(mm::vec3(rhs), mm::vec3(lhs)); -} diff --git a/include/mmvec.hpp b/include/mmvec.hpp new file mode 100644 index 0000000..db3c390 --- /dev/null +++ b/include/mmvec.hpp @@ -0,0 +1,330 @@ +/* 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 + * 2018 ~ 2019 + */ +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace mm { + // generic implementation + template + struct basic_vec; + + // usable specializations + template + struct vec; + template + struct vec3; + template + struct vec2; +} + +template +struct mm::basic_vec : public std::array { + using type = T; + static constexpr std::size_t dimensions = d; + + // TODO: template away these + static constexpr T null_element = static_cast(0); + static constexpr T unit_element = static_cast(1); + static constexpr T unit_additive_inverse_element = static_cast(-1); + + basic_vec(); + basic_vec(const std::initializer_list l); + + // copyable to a vector of size n <= d + template basic_vec(const basic_vec& other); + // movable to a vector of size n <= d + template basic_vec(basic_vec&& other); + + T length() const; + + // copy operator= + template + basic_vec& operator=(const mm::basic_vec& other); + + // move operator= + template + basic_vec& operator=(mm::basic_vec&& other); + + template + basic_vec& operator+=(const mm::basic_vec& other); + + template + basic_vec& operator-=(const mm::basic_vec& other); + + + basic_vec& operator*=(const T& scalar); +}; + + +// member functions for basic_vec + +template +mm::basic_vec::basic_vec() : std::array() { + this->fill(basic_vec::null_element); +} + +template +mm::basic_vec::basic_vec(const std::initializer_list 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 +template +mm::basic_vec::basic_vec(const mm::basic_vec& other) { + *this = other; +} + +template +template +mm::basic_vec::basic_vec(basic_vec&& other) { + *this = other; +} + +template +T mm::basic_vec::length() const { + return std::sqrt(std::accumulate(this->begin(), this->end(), + basic_vec::null_element, + [](const T& init, const T& val) -> T { + return init + val * val; + } + )); +} + + +// memeber operator overloads for basic_vec + +template +template +mm::basic_vec& mm::basic_vec::operator=(const mm::basic_vec& 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 +template +mm::basic_vec& mm::basic_vec::operator=(mm::basic_vec&& 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 +template +mm::basic_vec& mm::basic_vec::operator+=(const mm::basic_vec& other) { + *this = *this + other; + return *this; +} + +template +template +mm::basic_vec& mm::basic_vec::operator-=(const mm::basic_vec& other) { + *this = *this - other; + return *this; +} + +template +mm::basic_vec& mm::basic_vec::operator*=(const T& scalar) { + *this = *this * scalar; + return *this; +} + + +// operator overloads for basic_vec + +template +mm::basic_vec operator+(const mm::basic_vec& rhs, const mm::basic_vec& lhs) { + mm::basic_vec out; + + std::transform(rhs.begin(), rhs.end(), lhs.begin(), out.begin(), + [](const T& r, const T& l) -> T { + return r + l; + } + ); + + return out; +} + +template +mm::basic_vec operator*(const mm::basic_vec& rhs, const T& lhs) { + return lhs * rhs; +} + +template +mm::basic_vec operator*(const T& rhs, const mm::basic_vec& lhs) { + mm::basic_vec out; + + std::transform(lhs.begin(), lhs.end(), out.begin(), + [rhs](const T& t) -> T { + return t * rhs; + }); + + return out; +} + +template +mm::basic_vec operator-(const mm::basic_vec& rhs, const mm::basic_vec& lhs) { + return rhs + mm::basic_vec::unit_additive_inverse_element * lhs; +} + +template +T operator*(const mm::basic_vec& rhs, const mm::basic_vec& lhs) { + return std::inner_product(rhs.begin(), rhs.end(), lhs.begin(), 0); +} + +template +std::ostream& operator<<(std::ostream& os, const mm::basic_vec& 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 +class mm::vec: public mm::basic_vec { +public: + vec(std::initializer_list l) : basic_vec(l) {} + + template + vec(const basic_vec& other) : basic_vec(other) {} +}; + + +// three dimensional specialization with a static cross product +// TODO: specialize operator+ for spherical coordinates + +template +class mm::vec3 : public mm::basic_vec { +public: + vec3() : basic_vec() {} + vec3(std::initializer_list l) : basic_vec(l) {} + + template + vec3(const basic_vec& other) : basic_vec(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 spherical() const; + + static vec3 cross(const vec3& rhs, const vec3& lhs); +}; + +template +T mm::vec3::zenith() const { + return std::acos(this->z() / this->length()); +} + +template +T mm::vec3::azimuth() const { + return std::atan(this->y() / this->x()); +} + +template +mm::vec3 mm::vec3::spherical() const { + return mm::vec3 { + this->length(), + this->zenith(), + this->azimuth(), + }; +} + +template +mm::vec3 mm::vec3::cross(const vec3& rhs, const vec3& lhs) { + mm::vec3 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 +class mm::vec2: public mm::basic_vec { +public: + vec2() : basic_vec() {} + vec2(std::initializer_list l) : basic_vec(l) {} + + template + vec2(const basic_vec& other) : basic_vec(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 polar() const; + + static vec3 cross(const vec2& rhs, const vec2& lhs); +}; + +template +T mm::vec2::angle() const { + return std::atan(this->y() / this->x()); +} + +template +mm::vec2 mm::vec2::polar() const { + return mm::vec2 { + this->length(), + this->angle() + }; +} + +template +mm::vec3 mm::vec2::cross(const mm::vec2& rhs, const mm::vec2& lhs) { + return mm::vec3::cross(mm::vec3(rhs), mm::vec3(lhs)); +} -- cgit v1.2.1 From d14d1a12fa0a8c6f60385468f18f99d799d7a5db Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Mon, 11 Feb 2019 14:24:59 +0100 Subject: Fix typos and other minor errors --- CMakeLists.txt | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e7d073..c7918e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,10 +11,10 @@ list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake) ############################ # build libmm add_library(mm STATIC - mmvec.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/mmvec.cpp ) -add_library(MM:mm ALIAS mm) +add_library(MM::mm ALIAS mm) # set up headers target_include_directories(mm @@ -64,20 +64,15 @@ install(TARGETS mm set_target_properties(mm PROPERTIES EXPORT_NAME MM) -if ("${CMAKE_SYSTEM}" MATCHES "Linux") - -# too bad but no other simpler choise -file(GLOB INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/include/*") - # install public headers -install(FILES ${INCLUDE_FILES} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/mm +install( + FILES + ${CMAKE_CURRENT_SOURCE_DIR}/include/mmvec.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/include/mm + DESTINATION + ${CMAKE_INSTALL_INCLUDEDIR}/mm ) -endif() - -# TODO, install setup for windows too - # export targets install(EXPORT mm-targets FILE -- cgit v1.2.1