vector.hpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. //
  2. // vector.hpp
  3. // vector
  4. //
  5. // Created by Sam Jaffe on 8/15/16.
  6. //
  7. #pragma once
  8. #include <cassert>
  9. #include <cmath>
  10. #include <cstddef>
  11. #include <array>
  12. #include <initializer_list>
  13. #include <stdexcept>
  14. #include <type_traits>
  15. #include "expect/expect.hpp"
  16. #include "forward.h"
  17. #include "traits.hpp"
  18. #define VECTOR_ENABLE_IF_LT_N(index, expr) \
  19. template <bool _ = true> \
  20. typename std::enable_if<std::size_t(index) < N && _, expr>::type
  21. #define VECTOR_ENABLE_IF_EQ_N(index, t, n) \
  22. template <bool _ = true> \
  23. typename std::enable_if<std::size_t(index) == N && _, vector<t, n>>::type
  24. #define VECTOR_ENABLE_IF_EQ_T(_type, t, n) \
  25. typename std::enable_if<std::is_same<_type, t>::value, vector<t, n>>::type
  26. #define VECTOR_DISABLE_IF_VECTOR(_type, t, n) \
  27. typename std::enable_if<!is_vector<_type>::value, vector<t, n>>::type
  28. #define VECTOR_ACCESS_FN(name, i) \
  29. VECTOR_ENABLE_IF_LT_N(i, value_type const &) name() const { \
  30. return _data[i]; \
  31. } \
  32. VECTOR_ENABLE_IF_LT_N(i, value_type &) name() { return _data[i]; }
  33. #define VECTOR_FOR_EACH_RANGE(var, end) \
  34. for (std::size_t var = 0; var < end; ++var)
  35. #define VECTOR_FOR_EACH(var) VECTOR_FOR_EACH_RANGE(var, N)
  36. namespace math { namespace vector {
  37. template <typename T, std::size_t N> class vector {
  38. public:
  39. using value_type = T;
  40. private:
  41. using mag_t = decltype(std::sqrt(std::declval<T>()));
  42. template <typename M>
  43. using mul_t = decltype(std::declval<T>() * std::declval<M>());
  44. template <typename M>
  45. using div_t = decltype(std::declval<T>() / std::declval<M>());
  46. public:
  47. // Constructors
  48. vector() = default;
  49. vector(std::array<T, N> const & init) {
  50. VECTOR_FOR_EACH(i) { _data[i] = init[i]; }
  51. }
  52. vector(vector const & other) { *this = other; }
  53. vector(vector && other) { *this = std::move(other); }
  54. // Conversion
  55. template <typename T2, std::size_t N2>
  56. explicit vector(vector<T2, N2> const & other) {
  57. VECTOR_FOR_EACH_RANGE(i, std::min(N, N2)) {
  58. _data[i] = static_cast<T>(other[i]);
  59. }
  60. }
  61. vector(T const & v, fill_t) {
  62. VECTOR_FOR_EACH(i) { _data[i] = v; }
  63. }
  64. // Assignment
  65. vector & operator=(vector const & other) {
  66. VECTOR_FOR_EACH(i) { _data[i] = other[i]; }
  67. return *this;
  68. }
  69. vector & operator=(vector && other) {
  70. VECTOR_FOR_EACH(i) { _data[i] = std::move(other._data[i]); }
  71. return *this;
  72. }
  73. // Named Accessors
  74. // - Numeric Vector Accessors
  75. VECTOR_ACCESS_FN(x, 0)
  76. VECTOR_ACCESS_FN(y, 1)
  77. VECTOR_ACCESS_FN(z, 2)
  78. VECTOR_ACCESS_FN(w, 3)
  79. // - Color Vector Accessors
  80. VECTOR_ACCESS_FN(r, 0)
  81. VECTOR_ACCESS_FN(g, 1)
  82. VECTOR_ACCESS_FN(b, 2)
  83. VECTOR_ACCESS_FN(a, 3)
  84. // Unnamed Accessors
  85. value_type const & operator[](std::size_t idx) const { return _data[idx]; }
  86. value_type & operator[](std::size_t idx) { return _data[idx]; }
  87. value_type const & at(std::size_t idx) const {
  88. expects(idx < N, std::out_of_range, "index out of range");
  89. return _data[idx];
  90. }
  91. value_type & at(std::size_t idx) {
  92. expects(idx < N, std::out_of_range, "index out of range");
  93. return _data[idx];
  94. }
  95. // Mathematical Operations
  96. vector & operator+=(vector const & other) {
  97. VECTOR_FOR_EACH(i) { _data[i] += other[i]; }
  98. return *this;
  99. }
  100. vector & operator+=(T const & other) {
  101. return operator+=(vector(other, fill));
  102. }
  103. vector operator+(vector const & other) const {
  104. return vector{*this} += other;
  105. }
  106. vector operator+(T const & other) const {
  107. return operator+(vector(other, fill));
  108. }
  109. friend vector operator+(T const & lhs, vector const & rhs) {
  110. return rhs + lhs;
  111. }
  112. vector & operator-=(vector const & other) {
  113. VECTOR_FOR_EACH(i) { _data[i] -= other[i]; }
  114. return *this;
  115. }
  116. vector & operator-=(T const & other) {
  117. return operator-=(vector(other, fill));
  118. }
  119. vector operator-(vector const & other) const {
  120. return vector{*this} -= other;
  121. }
  122. vector operator-(T const & other) const {
  123. return operator-(vector(other, fill));
  124. }
  125. friend vector operator-(T const & lhs, vector const & rhs) {
  126. return vector(lhs, fill) - rhs;
  127. }
  128. vector operator-() const { return vector{} -= *this; }
  129. template <typename M>
  130. VECTOR_ENABLE_IF_EQ_T(mul_t<M>, T, N) & operator*=(M c) {
  131. VECTOR_FOR_EACH(i) { _data[i] *= c; }
  132. return *this;
  133. }
  134. template <typename M>
  135. VECTOR_DISABLE_IF_VECTOR(M, mul_t<M>, N)
  136. operator*(M c) const {
  137. return vector<mul_t<M>, N>{*this} *= c;
  138. }
  139. template <typename M>
  140. friend VECTOR_DISABLE_IF_VECTOR(M, mul_t<M>, N)
  141. operator*(M c, vector<T, N> const & v) {
  142. return v * c;
  143. }
  144. template <typename M>
  145. VECTOR_ENABLE_IF_EQ_T(mul_t<M>, T, N) & operator*=(vector<M, N> c) {
  146. VECTOR_FOR_EACH(i) { _data[i] *= c[i]; }
  147. return *this;
  148. }
  149. template <typename M>
  150. vector<mul_t<M>, N> operator*(vector<M, N> const & other) const {
  151. return vector<mul_t<M>, N>{*this} *= other;
  152. }
  153. template <typename M>
  154. VECTOR_ENABLE_IF_EQ_T(div_t<M>, T, N) & operator/=(M c) {
  155. expects(c != 0, std::domain_error, "divide by zero");
  156. VECTOR_FOR_EACH(i) { _data[i] /= c; }
  157. return *this;
  158. }
  159. template <typename M>
  160. VECTOR_DISABLE_IF_VECTOR(M, div_t<M>, N)
  161. operator/(M c) const {
  162. return vector<div_t<M>, N>{*this} /= c;
  163. }
  164. template <typename M>
  165. VECTOR_ENABLE_IF_EQ_T(div_t<M>, T, N) & operator/=(vector<M, N> c) {
  166. VECTOR_FOR_EACH(i) {
  167. expects(c[i] != 0, std::domain_error, "divide by zero");
  168. }
  169. VECTOR_FOR_EACH(i) { _data[i] /= c[i]; }
  170. return *this;
  171. }
  172. template <typename M>
  173. vector<div_t<M>, N> operator/(vector<M, N> const & other) const {
  174. return vector<div_t<M>, N>{*this} /= other;
  175. }
  176. // Vector Operations
  177. value_type dot(vector const & other) const {
  178. value_type accum{};
  179. VECTOR_FOR_EACH(i) { accum += at(i) * other.at(i); }
  180. return accum;
  181. }
  182. mag_t magnitude() const { return std::sqrt(dot(*this)); }
  183. vector<mag_t, N> unit() const { return *this / magnitude(); }
  184. VECTOR_ENABLE_IF_EQ_N(3, T, N) cross(vector const & other) const {
  185. return {{y() * other.z() - z() * other.y(),
  186. z() * other.x() - x() * other.z(),
  187. x() * other.y() - y() * other.x()}};
  188. }
  189. VECTOR_ENABLE_IF_EQ_N(2, T, 3) cross(vector const & other) const {
  190. return {{0, 0, x() * other.y() - y() * other.x()}};
  191. }
  192. vector<mag_t, N> projection(vector const & other) const {
  193. vector<mag_t, N> b_p = other.unit();
  194. return b_p * vector<mag_t, N>{*this}.dot(b_p);
  195. }
  196. private:
  197. value_type _data[N] = {value_type()};
  198. };
  199. template <typename T, std::size_t N>
  200. vector<T, N> abs(vector<T, N> const & self) {
  201. vector<T, N> tmp(self);
  202. using std::abs;
  203. VECTOR_FOR_EACH(i) { tmp[i] = abs(tmp[i]); }
  204. return tmp;
  205. }
  206. template <typename T, std::size_t N>
  207. int compare(vector<T, N> const & lhs, vector<T, N> const & rhs) {
  208. VECTOR_FOR_EACH(i) {
  209. if (lhs[i] < rhs[i])
  210. return -1;
  211. else if (lhs[i] > rhs[i])
  212. return 1;
  213. }
  214. return 0;
  215. }
  216. template <typename T, std::size_t N>
  217. bool operator==(vector<T, N> const & lhs, vector<T, N> const & rhs) {
  218. return compare(lhs, rhs) == 0;
  219. }
  220. template <typename T, std::size_t N>
  221. bool operator!=(vector<T, N> const & lhs, vector<T, N> const & rhs) {
  222. return compare(lhs, rhs) != 0;
  223. }
  224. template <typename T, std::size_t N>
  225. bool operator<(vector<T, N> const & lhs, vector<T, N> const & rhs) {
  226. return compare(lhs, rhs) < 0;
  227. }
  228. template <typename T, std::size_t N>
  229. bool operator<=(vector<T, N> const & lhs, vector<T, N> const & rhs) {
  230. return compare(lhs, rhs) <= 0;
  231. }
  232. template <typename T, std::size_t N>
  233. bool operator>(vector<T, N> const & lhs, vector<T, N> const & rhs) {
  234. return compare(lhs, rhs) > 0;
  235. }
  236. template <typename T, std::size_t N>
  237. bool operator>=(vector<T, N> const & lhs, vector<T, N> const & rhs) {
  238. return compare(lhs, rhs) >= 0;
  239. }
  240. }}
  241. template <typename... Ts>
  242. auto make_vector(Ts &&... elems)
  243. -> math::vector::vector<typename std::common_type<Ts...>::type,
  244. sizeof...(Ts)> {
  245. return {{elems...}};
  246. }
  247. using math::vector::abs;