-
Notifications
You must be signed in to change notification settings - Fork 0
/
vec.h
185 lines (164 loc) · 4.97 KB
/
vec.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// Copyright © 2018-2020 Artyom Tokarev. All rights reserved.
// Licensed under the MIT License.
#pragma once
#include <cmath>
#include <cstdint>
#include <array>
namespace spt {
using default_value_type = double;
template <std::size_t Dim, typename ValueType = default_value_type>
struct vec;
template <std::size_t Dim> using veci = vec<Dim, std::int64_t>;
template <std::size_t Dim> using vecu = vec<Dim, std::uint64_t>;
template <std::size_t Dim> using vecf = vec<Dim, float>;
template <std::size_t Dim> using vecd = vec<Dim, double>;
template <typename ValueType>
using vec2 = vec<2, ValueType>;
using vec2i = vec2<std::int64_t>;
using vec2u = vec2<std::uint64_t>;
using vec2f = vec2<float>;
using vec2d = vec2<double>;
template <typename ValueType>
using vec3 = vec<3, ValueType>;
using vec3i = vec3<std::int64_t>;
using vec3u = vec3<std::uint64_t>;
using vec3f = vec3<float>;
using vec3d = vec3<double>;
template <typename ValueType>
using vec4 = vec<4, ValueType>;
using vec4i = vec4<std::int64_t>;
using vec4u = vec4<std::uint64_t>;
using vec4f = vec4<float>;
using vec4d = vec4<double>;
template <std::size_t Dim, typename ValueType>
struct vec {
static constexpr std::size_t dim = Dim;
using value_type = ValueType;
std::array<ValueType, Dim> x{};
static vec zeros() {
return {};
}
static vec ones() {
return filled_with(static_cast<ValueType>(1));
}
static vec filled_with(ValueType val) {
vec res;
std::fill(res.x.begin(), res.x.end(), val);
return res;
}
auto magnitude() const {
return std::sqrt(magnitude2());
}
ValueType magnitude2() const {
return dot(*this, *this);
}
vec& normalize() {
ValueType inv_magn = static_cast<ValueType>(1) / magnitude();
for (std::size_t i = 0; i < Dim; ++i)
x[i] *= inv_magn;
return *this;
}
vec& operator=(const vec& right) {
x = right.x;
return *this;
}
vec operator-() const {
vec res = *this;
for (std::size_t i = 0; i < Dim; ++i)
res.x[i] = -res.x[i];
return res;
}
vec operator+(const vec& right) const {
vec res = *this;
for (std::size_t i = 0; i < Dim; ++i)
res.x[i] += right.x[i];
return res;
}
vec operator-(const vec& right) const {
vec res = *this;
for (std::size_t i = 0; i < Dim; ++i)
res.x[i] -= right.x[i];
return res;
}
vec operator*(ValueType scalar) const {
vec res = *this;
for (std::size_t i = 0; i < Dim; ++i)
res.x[i] *= scalar;
return res;
}
vec operator/(ValueType scalar) const {
vec res = *this;
for (std::size_t i = 0; i < Dim; ++i)
res.x[i] /= scalar;
return res;
}
vec& operator+=(const vec& right) {
for (std::size_t i = 0; i < Dim; ++i)
x[i] += right.x[i];
return *this;
}
vec& operator-=(const vec& right) {
for (std::size_t i = 0; i < Dim; ++i)
x[i] -= right.x[i];
return *this;
}
vec& operator*=(ValueType scalar) {
for (std::size_t i = 0; i < Dim; ++i)
x[i] *= scalar;
return *this;
}
vec& operator/=(ValueType scalar) {
for (std::size_t i = 0; i < Dim; ++i)
x[i] /= scalar;
return *this;
}
bool operator==(const vec& right) const {
for (std::size_t i = 0; i < Dim; ++i)
if (std::abs(right.x[i] - x[i]) > std::numeric_limits<ValueType>::epsilon()
* std::abs(right.x[i] + x[i]))
return false;
return true;
}
bool operator!=(const vec& right) const {
return !(*this == right);
}
bool operator<(const vec& right) const {
return x < right.x;
}
ValueType& operator[](std::size_t i) {
return x[i];
}
const ValueType& operator[](std::size_t i) const {
return x[i];
}
vec() {
std::fill(x.begin(), x.end(), static_cast<ValueType>(0));
}
template <typename FromValueType>
vec(const vec<Dim, FromValueType>& other) {
for (std::size_t i = 0; i < Dim; ++i)
x[i] = static_cast<ValueType>(other.x[i]);
}
vec(const vec& other) {
x = other.x;
}
vec(const std::array<ValueType, Dim>& x) : x{x} {}
};
template<std::size_t Dim, typename ValueType>
vec(const std::array<ValueType, Dim>& x) -> vec<Dim, ValueType>;
} // namespace spt
template <std::size_t Dim, typename ValueType>
spt::vec<Dim, ValueType> operator*(ValueType scalar, const spt::vec<Dim, ValueType>& v) {
return v * scalar;
}
// taken from boost
template<std::size_t Dim, typename ValueType>
struct std::hash<spt::vec<Dim, ValueType>> {
std::size_t operator()(const spt::vec<Dim, ValueType>& key) const {
std::hash<ValueType> hasher;
std::size_t h = 0;
for (auto e : key.x)
h ^= hasher(e) + 0x9e3779b9 + (h << 6) + (h >> 2);
return h;
}
};