Project
Loading...
Searching...
No Matches
internal.h
Go to the documentation of this file.
1
3
4#pragma once
5#include <limits>
6#include <utility>
7#include <algorithm>
8#include <cmath>
9#define SI_INLINE inline
10#define SI_INLINE_CONSTEXPR constexpr SI_INLINE
11
12namespace SI
13{
14 typedef long double angle;
15 typedef angle radians;
16 typedef double SIdouble;
17
18 namespace internal
19 {
20 namespace detail
21 {
22 template <class T> struct vec_trivally_constructible { using type = T; };
23 template <class T> struct vec_value_type { using type = T; };
24 template <class T> struct vec_value_type<vec_trivally_constructible<T>> { using type = T; };
25 template <class... T> using vec_common_type_t = std::common_type_t<typename vec_value_type<T>::type...>;
26 }
27
28 template <int N, class T>
29 struct vec;
30
31 template <class T>
32 struct vec<2, T> : vec<2, detail::vec_trivally_constructible<T>>
33 {
35
36 SI_INLINE_CONSTEXPR vec() : vec<2, detail::vec_trivally_constructible<T>>(0, 0) {}
37 };
38
39 template <class T>
40 struct vec<2, detail::vec_trivally_constructible<T>>
41 {
42 static_assert(std::is_arithmetic_v<T>);
43
45
47 {
48 static_assert(sizeof(vec) == 2 * sizeof(T));
49 static_assert(std::is_trivially_copyable_v<vec>);
50 }
51
52 template <class U>
53 SI_INLINE_CONSTEXPR explicit vec(const vec<2, U>& other) : vec(static_cast<T>(other.x), static_cast<T>(other.y)) {}
54
55 template <class U>
56 SI_INLINE_CONSTEXPR operator vec<2, U>() const { return vec<2, U>(x, static_cast<detail::vec_common_type_t<U>>(y)); } // NOLINT(google-explicit-constructor)
57
58 template <class U>
59 SI_INLINE_CONSTEXPR explicit vec(const vec<3, U>& other) : vec(static_cast<T>(other.x), static_cast<T>(other.y)) {}
60
61 SI_INLINE_CONSTEXPR explicit operator bool() const noexcept { return !(x == 0 && y == 0); }
62
63 T x;
64 T y;
65 };
66
67 template <class T>
68 struct vec<3, T> : vec<3, detail::vec_trivally_constructible<T>>
69 {
71 SI_INLINE_CONSTEXPR vec() : vec<3, detail::vec_trivally_constructible<T>>(0, 0, 0) {}
72 };
73
74 template <class T>
75 struct vec<3, detail::vec_trivally_constructible<T>>
76 {
77 static_assert(std::is_arithmetic_v<T>);
78
80
81 SI_INLINE_CONSTEXPR vec(T x, T y, T z) : x(x), y(y), z(z)
82 {
83 static_assert(sizeof(vec) == 3 * sizeof(T));
84 static_assert(std::is_trivially_copyable_v<vec>);
85 }
86
87 template <class U>
89
90 template <class U>
91 SI_INLINE_CONSTEXPR explicit vec(const vec<3, U>& other) : vec(static_cast<T>(other.x), static_cast<T>(other.y), static_cast<T>(other.z)) {}
92
93 template <class U>
94 SI_INLINE_CONSTEXPR operator vec<3, U>() const { return vec<3, U>(x, static_cast<detail::vec_common_type_t<U>>(y), static_cast<detail::vec_common_type_t<U>>(z)); } // NOLINT(google-explicit-constructor)
95
96 SI_INLINE_CONSTEXPR explicit operator bool() const noexcept { return !(x == 0 && y == 0 && z == 0); }
97 union
98 {
99 struct
100 {
101 T x;
102 T y;
103 };
105 };
106 T z;
107 };
108
109 template <class T> using vec2 = vec<2, T>;
110 template <class T> using vec3 = vec<3, T>;
111
112 // unary operators
113 template <class T> [[nodiscard]] SI_INLINE_CONSTEXPR vec2<T> operator-(const vec2<T>& v) { return { -v.x, -v.y }; }
114 template <class T> [[nodiscard]] SI_INLINE_CONSTEXPR vec3<T> operator-(const vec3<T>& v) { return { -v.x, -v.y, -v.z }; }
115
116 // comparsion operators
117 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR bool operator==(const vec2<T>& lhs, const vec2<U>& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y; }
118 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR bool operator==(const vec3<T>& lhs, const vec3<U>& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z; }
119 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR bool operator!=(const vec2<T>& lhs, const vec2<U>& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y; }
120 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR bool operator!=(const vec3<T>& lhs, const vec3<U>& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y || lhs.z != rhs.z; }
121
122 // compound assignment with other vectors
123 template <class T, class U> SI_INLINE_CONSTEXPR vec2<T>& operator+=(vec2<T>& lhs, const vec2<U>& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; }
124 template <class T, class U> SI_INLINE_CONSTEXPR vec3<T>& operator+=(vec3<T>& lhs, const vec3<U>& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; lhs.z += rhs.z; return lhs; }
125 template <class T, class U> SI_INLINE_CONSTEXPR vec2<T>& operator-=(vec2<T>& lhs, const vec2<U>& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; }
126 template <class T, class U> SI_INLINE_CONSTEXPR vec3<T>& operator-=(vec3<T>& lhs, const vec3<U>& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; lhs.z -= rhs.z; return lhs; }
127 template <class T, class U> SI_INLINE_CONSTEXPR vec2<T>& operator*=(vec2<T>& lhs, const vec2<U>& rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; return lhs; }
128 template <class T, class U> SI_INLINE_CONSTEXPR vec3<T>& operator*=(vec3<T>& lhs, const vec3<U>& rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; lhs.z *= rhs.z; return lhs; }
129 template <class T, class U> SI_INLINE_CONSTEXPR vec2<T>& operator/=(vec2<T>& lhs, const vec2<U>& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; return lhs; }
130 template <class T, class U> SI_INLINE_CONSTEXPR vec3<T>& operator/=(vec3<T>& lhs, const vec3<U>& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; lhs.z /= rhs.z; return lhs; }
131
132 // compound assignment with scalars
133 template <class T, class U> SI_INLINE_CONSTEXPR std::enable_if_t<std::is_arithmetic_v<U>, vec2<T>&> operator+=(vec2<T>& lhs, U rhs) { lhs.x += rhs; lhs.y += rhs; return lhs; }
134 template <class T, class U> SI_INLINE_CONSTEXPR std::enable_if_t<std::is_arithmetic_v<U>, vec3<T>&> operator+=(vec3<T>& lhs, U rhs) { lhs.x += rhs; lhs.y += rhs; lhs.z += rhs; return lhs; }
135 template <class T, class U> SI_INLINE_CONSTEXPR std::enable_if_t<std::is_arithmetic_v<U>, vec2<T>&> operator-=(vec2<T>& lhs, U rhs) { lhs.x -= rhs; lhs.y -= rhs; return lhs; }
136 template <class T, class U> SI_INLINE_CONSTEXPR std::enable_if_t<std::is_arithmetic_v<U>, vec3<T>&> operator-=(vec3<T>& lhs, U rhs) { lhs.x -= rhs; lhs.y -= rhs; lhs.z -= rhs; return lhs; }
137 template <class T, class U> SI_INLINE_CONSTEXPR std::enable_if_t<std::is_arithmetic_v<U>, vec2<T>&> operator*=(vec2<T>& lhs, U rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; }
138 template <class T, class U> SI_INLINE_CONSTEXPR std::enable_if_t<std::is_arithmetic_v<U>, vec3<T>&> operator*=(vec3<T>& lhs, U rhs) { lhs.x *= rhs; lhs.y *= rhs; lhs.z *= rhs; return lhs; }
139 template <class T, class U> SI_INLINE_CONSTEXPR std::enable_if_t<std::is_arithmetic_v<U>, vec2<T>&> operator/=(vec2<T>& lhs, U rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; }
140 template <class T, class U> SI_INLINE_CONSTEXPR std::enable_if_t<std::is_arithmetic_v<U>, vec3<T>&> operator/=(vec3<T>& lhs, U rhs) { lhs.x /= rhs; lhs.y /= rhs; lhs.z /= rhs; return lhs; }
141
142 // binary operators with other vectors
143 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec2<detail::vec_common_type_t<T, U>> operator+(const vec2<T>& lhs, const vec2<U>& rhs) { return {lhs.x + rhs.x, lhs.y + rhs.y }; }
144 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec3<detail::vec_common_type_t<T, U>> operator+(const vec3<T>& lhs, const vec3<U>& rhs) { return {lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z }; }
145 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec2<detail::vec_common_type_t<T, U>> operator-(const vec2<T>& lhs, const vec2<U>& rhs) { return {lhs.x - rhs.x, lhs.y - rhs.y }; }
146 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec3<detail::vec_common_type_t<T, U>> operator-(const vec3<T>& lhs, const vec3<U>& rhs) { return {lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z }; }
147 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec2<detail::vec_common_type_t<T, U>> operator*(const vec2<T>& lhs, const vec2<U>& rhs) { return {lhs.x * rhs.x, lhs.y * rhs.y }; }
148 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec3<detail::vec_common_type_t<T, U>> operator*(const vec3<T>& lhs, const vec3<U>& rhs) { return {lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z }; }
149 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec2<detail::vec_common_type_t<T, U>> operator/(const vec2<T>& lhs, const vec2<U>& rhs) { return {lhs.x / rhs.x, lhs.y / rhs.y }; }
150 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec3<detail::vec_common_type_t<T, U>> operator/(const vec3<T>& lhs, const vec3<U>& rhs) { return {lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z }; }
151
152 // binary operators with scalars on the right side
153 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec2<detail::vec_common_type_t<T, U>> operator+(const vec2<T>& lhs, U rhs) { return { lhs.x + rhs, lhs.y + rhs}; }
154 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec3<detail::vec_common_type_t<T, U>> operator+(const vec3<T>& lhs, U rhs) { return { lhs.x + rhs, lhs.y + rhs, lhs.z + rhs}; }
155 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec2<detail::vec_common_type_t<T, U>> operator-(const vec2<T>& lhs, U rhs) { return { lhs.x - rhs, lhs.y - rhs}; }
156 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec3<detail::vec_common_type_t<T, U>> operator-(const vec3<T>& lhs, U rhs) { return { lhs.x - rhs, lhs.y - rhs, lhs.z - rhs}; }
157 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec2<detail::vec_common_type_t<T, U>> operator*(const vec2<T>& lhs, U rhs) { return { lhs.x * rhs, lhs.y * rhs}; }
158 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec3<detail::vec_common_type_t<T, U>> operator*(const vec3<T>& lhs, U rhs) { return { lhs.x * rhs, lhs.y * rhs, lhs.z * rhs}; }
159 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec2<detail::vec_common_type_t<T, U>> operator/(const vec2<T>& lhs, U rhs) { return { lhs.x / rhs, lhs.y / rhs}; }
160 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec3<detail::vec_common_type_t<T, U>> operator/(const vec3<T>& lhs, U rhs) { return { lhs.x / rhs, lhs.y / rhs, lhs.z / rhs}; }
161
162 // binary operators with scalars on the left side
163 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec2<detail::vec_common_type_t<T, U>> operator+(T lhs, const vec2<U>& rhs) { return { lhs + rhs.x, lhs + rhs.y }; }
164 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec3<detail::vec_common_type_t<T, U>> operator+(T lhs, const vec3<U>& rhs) { return { lhs + rhs.x, lhs + rhs.y, lhs + rhs.z }; }
165 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec2<detail::vec_common_type_t<T, U>> operator-(T lhs, const vec2<U>& rhs) { return { lhs - rhs.x, lhs - rhs.y }; }
166 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec3<detail::vec_common_type_t<T, U>> operator-(T lhs, const vec3<U>& rhs) { return { lhs - rhs.x, lhs - rhs.y, lhs - rhs.z }; }
167 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec2<detail::vec_common_type_t<T, U>> operator*(T lhs, const vec2<U>& rhs) { return { lhs * rhs.x, lhs * rhs.y }; }
168 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec3<detail::vec_common_type_t<T, U>> operator*(T lhs, const vec3<U>& rhs) { return { lhs * rhs.x, lhs * rhs.y, lhs * rhs.z }; }
169 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec2<detail::vec_common_type_t<T, U>> operator/(T lhs, const vec2<U>& rhs) { return { lhs / rhs.x, lhs / rhs.y }; }
170 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec3<detail::vec_common_type_t<T, U>> operator/(T lhs, const vec3<U>& rhs) { return { lhs / rhs.x, lhs / rhs.y, lhs / rhs.z }; }
171
172 // absolute value (componentwise)
173 template <class T> [[nodiscard]] SI_INLINE_CONSTEXPR vec2<detail::vec_common_type_t<T>> abs(const vec2<T>& v) { return { std::abs(v.x), std::abs(v.y) }; }
174 template <class T> [[nodiscard]] SI_INLINE_CONSTEXPR vec3<detail::vec_common_type_t<T>> abs(const vec3<T>& v) { return { std::abs(v.x), std::abs(v.y), std::abs(v.z) }; }
175
176 // sign Of (componentwise)
177 template <class T> [[nodiscard]] SI_INLINE_CONSTEXPR std::enable_if_t<std::is_arithmetic_v<T>, T> sign(T x) { return x > 0 ? 1 : x < 0 ? -1 : 0; }
178 template <class T> [[nodiscard]] SI_INLINE_CONSTEXPR vec2<detail::vec_common_type_t<T>> sign(const vec2<T>& v) { return { sign(v.x), sign(v.y) }; }
179 template <class T> [[nodiscard]] SI_INLINE_CONSTEXPR vec3<detail::vec_common_type_t<T>> sign(const vec3<T>& v) { return { sign(v.x), sign(v.y), sign(v.z) }; }
180
181 // min / max (componentwise)
182 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR std::enable_if_t<std::is_arithmetic_v<T> && std::is_arithmetic_v<U>, std::common_type_t<T, U>> min(T lhs, U rhs) { return (rhs < lhs) ? rhs : lhs; }
183 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR std::enable_if_t<std::is_arithmetic_v<T> && std::is_arithmetic_v<U>, std::common_type_t<T, U>> max(T lhs, U rhs) { return (lhs < rhs) ? rhs : lhs; }
184 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec2<detail::vec_common_type_t<T, U>> min(const vec2<T>& lhs, const vec2<U>& rhs) { return { min(lhs.x, rhs.x), min(lhs.y, rhs.y) }; }
185 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec3<detail::vec_common_type_t<T, U>> min(const vec3<T>& lhs, const vec3<U>& rhs) { return { min(lhs.x, rhs.x), min(lhs.y, rhs.y), min(lhs.z, rhs.z) }; }
186 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec2<detail::vec_common_type_t<T, U>> max(const vec2<T>& lhs, const vec2<U>& rhs) { return { max(lhs.x, rhs.x), max(lhs.y, rhs.y) }; }
187 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec3<detail::vec_common_type_t<T, U>> max(const vec3<T>& lhs, const vec3<U>& rhs) { return { max(lhs.x, rhs.x), max(lhs.y, rhs.y), max(lhs.z, rhs.z) }; }
188
189 // clamping (componentwise)
190 template <class T, class U, class V> [[nodiscard]] SI_INLINE_CONSTEXPR std::enable_if_t<std::is_arithmetic_v<T>, std::common_type_t<T, U, V>> clamp(T value, U min, V max) { return (min > value) ? min : (max < value) ? max : value; }
191 template <class T, class U, class V> [[nodiscard]] SI_INLINE_CONSTEXPR vec2<detail::vec_common_type_t<T, U, V>> clamp(const vec2<T>& value, U min, V max) { return { clamp(value.x, min, max), clamp(value.y, min, max) }; }
192 template <class T, class U, class V> [[nodiscard]] SI_INLINE_CONSTEXPR vec2<detail::vec_common_type_t<T, U, V>> clamp(const vec2<T>& value, const vec2<U>& min, const vec2<V>& max) { return { clamp(value.x, min.x, max.x), clamp(value.y, min.y, max.y) }; }
193 template <class T, class U, class V> [[nodiscard]] SI_INLINE_CONSTEXPR vec3<detail::vec_common_type_t<T, U, V>> clamp(const vec3<T>& value, U min, V max) { return { clamp(value.x, min, max), clamp(value.y, min, max), clamp(value.z, min, max) }; }
194 template <class T, class U, class V> [[nodiscard]] SI_INLINE_CONSTEXPR vec3<detail::vec_common_type_t<T, U, V>> clamp(const vec3<T>& value, const vec3<U>& min, const vec3<V>& max) { return { clamp(value.x, min.x, max.x), clamp(value.y, min.y, max.y), clamp(value.z, min.z, max.z) }; }
195
196 // dot product / inner product of two vectors
197 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR auto dot(const vec2<T>& lhs, const vec2<U>& rhs) { return lhs.x * rhs.x + lhs.y * rhs.y; }
198 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR auto dot(const vec3<T>& lhs, const vec3<U>& rhs) { return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z; }
199
200 // Euclidean length of a vector
201 template <class T> [[nodiscard]] SI_INLINE auto length(const vec2<T>& v) { return std::sqrt(dot(v, v)); }
202 template <class T> [[nodiscard]] SI_INLINE auto length(const vec3<T>& v) { return std::sqrt(dot(v, v)); }
203
204 // normalization (returns null vector when given null vectors for robustness)
205 // multiplies with the inverse sqrt to be 1:1 compatible to GLM (avoids minimal, but noticeable deviations)
206 template <class T> [[nodiscard]] SI_INLINE auto normalize(const vec2<T>& v) { auto l = length(v); return v * (l ? (1 / l) : 0); }
207 template <class T> [[nodiscard]] SI_INLINE auto normalize(const vec3<T>& v) { auto l = length(v); return v * (l ? (1 / l) : 0); }
208
209 // Euclidean distance between to vectors / points
210 template <class T, class U> [[nodiscard]] SI_INLINE auto distance(const vec2<T>& a, const vec2<U>& b) { return length(b - a); }
211 template <class T, class U> [[nodiscard]] SI_INLINE auto distance(const vec3<T>& a, const vec3<U>& b) { return length(b - a); }
212
213 // cross product / outer product of two vectors
214 template <class T, class U> [[nodiscard]] SI_INLINE_CONSTEXPR vec3<detail::vec_common_type_t<T, U>> cross(const vec3<T>& lhs, const vec3<U>& rhs) { return { lhs.y * rhs.z - rhs.y * lhs.z, lhs.z * rhs.x - rhs.z * lhs.x, lhs.x * rhs.y - rhs.x * lhs.y }; }
215
216 // mixing / interpolation (componentwise), returns `(1 - t) * a + t * b`
217 template <class T, class U, class V> [[nodiscard]] SI_INLINE_CONSTEXPR std::common_type_t<T, U, V> mix(T a, U b, V t) { return (1 - t) * a + t * b; }
218 template <class T, class U, class V> [[nodiscard]] SI_INLINE_CONSTEXPR vec2<detail::vec_common_type_t<T, U, V>> mix(const vec2<T>& a, const vec2<U>& b, V t) { return { mix(a.x, b.x, t), mix(a.y, b.y, t) }; }
219 template <class T, class U, class V> [[nodiscard]] SI_INLINE_CONSTEXPR vec3<detail::vec_common_type_t<T, U, V>> mix(const vec3<T>& a, const vec3<U>& b, V t) { return { mix(a.x, b.x, t), mix(a.y, b.y, t), mix(a.z, b.z, t) }; }
220 }
221
222 namespace detail
223 {
224 template <class T>
226
227 template <class T>
229
230 // the dimension(s) of a physical quantity, specified by it's dimensional exponents.
231 template <long lengthExp, long massExp, long timeExp, long temperatureExp, long currentExp, long substanceExp, long intensityExp>
233 {
234 static constexpr long length = lengthExp;
235 static constexpr long mass = massExp;
236 static constexpr long time = timeExp;
237 static constexpr long temperature = temperatureExp;
238 static constexpr long current = currentExp;
239 static constexpr long substance = substanceExp;
240 static constexpr long intensity = intensityExp;
241 };
242
243 template <long Value>
245
246 // the 'dimensionless' datatype with zero dimensions.
248
249 template <class, class>
250 struct quantity;
251 template <class, class>
252 struct unit;
253
254 template <class T>
256 {
258 };
259
260 template <long Length, long Mass, long Time, long Temperature, long Current, long Substance, long Intensity>
261 struct dimension_of<dimension<Length, Mass, Time, Temperature, Current, Substance, Intensity>>
262 {
264 };
265
266 template <class Dimension, class T>
267 struct dimension_of<quantity<Dimension, T>>
268 {
269 using type = Dimension;
270 };
271
272 template <class Dimension, class Ratio>
273 struct dimension_of<unit<Dimension, Ratio>>
274 {
275 using type = Dimension;
276 };
277
278 // Resolves to the dimension of anything that might have a dimension (types with no dimension end up with dimensionless)
279 template <class T>
281
282 // Checks whether the given type is/has dimensionless
283 template <class T>
284 SI_INLINE_CONSTEXPR bool is_dimensionless_v = std::is_same_v<dimensionless, dimension_of_t<T>>;
285
286#define SI_DIMENSION_OP(op_) dimension< \
287 Lhs::length op_ Rhs::length, \
288 Lhs::mass op_ Rhs::mass, \
289 Lhs::time op_ Rhs::time, \
290 Lhs::temperature op_ Rhs::temperature, \
291 Lhs::current op_ Rhs::current, \
292 Lhs::substance op_ Rhs::substance, \
293 Lhs::intensity op_ Rhs::intensity>
294
295 template <class Lhs, class Rhs> using dimension_add_impl = SI_DIMENSION_OP(+);
296 template <class Lhs, class Rhs> using dimension_subtract_impl = SI_DIMENSION_OP(-);
297 template <class Lhs, class Rhs> using dimension_multiply_impl = SI_DIMENSION_OP(*);
298 template <class Lhs, class Rhs> using dimension_divide_impl = SI_DIMENSION_OP(/);
299
304
305#undef SI_DIMENSION_OP
306
307 struct zero_t {};
308
309 template <class T> struct scalar_value_type { using type = T; };
310 template <> struct scalar_value_type<zero_t> { using type = int; };
311 template <class Dimension, class T> struct scalar_value_type<quantity<Dimension, T>> { using type = typename scalar_value_type<T>::type; };
312
313 template <class T>
315
316 // Storage for plain arithmetic types (float, double, int, ...)
317 template <class Dimension, class T>
319 {
320 public:
322 : m_value(0)
323 {}
324
325 SI_INLINE_CONSTEXPR explicit operator bool() const
326 {
327 return static_cast<bool>(m_value);
328 }
329
330 private:
331 T m_value;
332
334 {
335 return x.m_value;
336 }
337
339 {
340 return x.m_value;
341 }
342 };
343
344 // Helper function for filling all components of either a scalar or a vector to a given value
345 template <class T>
346 SI_INLINE_CONSTEXPR std::enable_if_t<std::is_arithmetic_v<T>> fill(T& x, T value)
347 {
348 x = value;
349 }
350
351 template <class Dimension, class T>
352 struct quantity final : quantity_storage<Dimension, T>
353 {
354 // Make sure we are not creating quantities with dimensionless (dimensionlesss should be plain arithmetic types)
355 static_assert(!is_dimensionless_v<Dimension>);
356
357 using value_type = T;
358 using dimension_type = Dimension;
359
360 SI_INLINE_CONSTEXPR quantity(zero_t = {}) // NOLINT(google-explicit-constructor)
361 {
362 }
363
364 SI_INLINE_CONSTEXPR quantity(Dimension, const T& x)
365 {
366 value(*this) = x;
367 }
368
369 template <class U>
370 SI_INLINE_CONSTEXPR quantity(const quantity<Dimension, U>& q) // NOLINT(google-explicit-constructor)
371 {
372 value(*this) = value(q);
373 }
374
376 {
377 using scalar_type = scalar_value_type_t<T>;
378 static_assert(std::is_floating_point_v<scalar_type>);
379 T value = {};
380 fill(value, std::numeric_limits<scalar_type>::infinity());
381 return { Dimension(), value };
382 }
383
385 {
386 using scalar_type = scalar_value_type_t<T>;
387 static_assert(std::is_floating_point_v<scalar_type>);
388 T value = {};
389 fill(value, std::numeric_limits<scalar_type>::quiet_NaN());
390 return { Dimension(), value };
391 }
392 };
393
394 template <class T>
395 struct is_si : std::bool_constant<false> {};
396
397 template <class Dimension, class T>
398 struct is_si<quantity<Dimension, T> > : std::bool_constant<true> {};
399
400 template <>
401 struct is_si<zero_t> : std::bool_constant<true> {};
402
403 // Checks wheter the given type is a si type
404 template <class T>
406
407 // Fallback value for any plain type, simply returns the value as-is
408 template <class T, class = std::enable_if_t<!is_si_v<T>>>
409 SI_INLINE_CONSTEXPR const T& value(const T& x)
410 {
411 return x;
412 }
413
415 {
416 return 0;
417 }
418
419 // Helper function for arithmetic functions with two arguments, returns the value of the first argument but uses
420 // the second argument to deduce the returned type in case of si::zero
421 template <class T, class U>
422 SI_INLINE_CONSTEXPR decltype(auto) value2(T&& x, U)
423 {
424 return value(std::forward<T>(x));
425 }
426
427 template <class U>
428 SI_INLINE_CONSTEXPR auto value2(zero_t, const U& other)
429 {
430 // Return zero of the given other type (i.e. return vec2() instead of plain 0)
431 return decltype(value(other)){};
432 }
433
434 // Checks wheter two types have compatible dimensions (zero is compatible with everything)
435 template <class Lhs, class Rhs>
437 std::is_same_v<dimension_of_t<Lhs>, dimension_of_t<Rhs>> || std::is_same_v<Lhs, zero_t> || std::is_same_v<Rhs, zero_t>;
438
439 template <class Lhs, class Rhs>
440 using dimension_common = std::conditional_t<std::is_same_v<Lhs, zero_t>, dimension_of_t<Rhs>, dimension_of_t<Lhs>>;
441
442 template <class T, class U = void, class V = void>
443 using enable_for_si = std::enable_if_t<is_si_v<T> || is_si_v<U> || is_si_v<V>>;
444
445 template <class T, class Dimension>
451
452 template <class T, class Dimension, class U>
454 {
455 static_assert(has_common_dimension_v<Dimension, U>, "incompatible SI dimensions");
456 value(lhs) += value(rhs);
457 return lhs;
458 }
459
460 template <class T, class Dimension, class U>
462 {
463 static_assert(has_common_dimension_v<Dimension, U>, "incompatible SI dimensions");
464 value(lhs) -= value(rhs);
465 return lhs;
466 }
467
468 template <class T, class Dimension, class U>
470 {
471 static_assert(is_dimensionless_v<U>, "incompatible SI dimensions");
472 value(lhs) *= value(rhs);
473 return lhs;
474 }
475
476 template <class T, class Dimension, class U>
478 {
479 static_assert(is_dimensionless_v<U>, "incompatible SI dimensions");
480 value(lhs) /= value(rhs);
481 return lhs;
482 }
483
484 template <class Lhs, class Rhs, class = enable_for_si<Lhs, Rhs>>
485 SI_INLINE_CONSTEXPR auto operator<(const Lhs& lhs, const Rhs& rhs)
486 {
487 static_assert(has_common_dimension_v<Lhs, Rhs>, "incompatible SI dimensions");
488 return value2(lhs, rhs) < value2(rhs, lhs);
489 }
490
491 template <class Lhs, class Rhs, class = enable_for_si<Lhs, Rhs>>
492 SI_INLINE_CONSTEXPR auto operator<=(const Lhs& lhs, const Rhs& rhs)
493 {
494 static_assert(has_common_dimension_v<Lhs, Rhs>, "incompatible SI dimensions");
495 return value2(lhs, rhs) <= value2(rhs, lhs);
496 }
497
498 template <class Lhs, class Rhs, class = enable_for_si<Lhs, Rhs>>
499 SI_INLINE_CONSTEXPR auto operator>(const Lhs& lhs, const Rhs& rhs)
500 {
501 static_assert(has_common_dimension_v<Lhs, Rhs>, "incompatible SI dimensions");
502 return value2(lhs, rhs) > value2(rhs, lhs);
503 }
504
505 template <class Lhs, class Rhs, class = enable_for_si<Lhs, Rhs>>
506 SI_INLINE_CONSTEXPR auto operator>=(const Lhs& lhs, const Rhs& rhs)
507 {
508 static_assert(has_common_dimension_v<Lhs, Rhs>, "incompatible SI dimensions");
509 return value2(lhs, rhs) >= value2(rhs, lhs);
510 }
511
512 template <class Lhs, class Rhs, class = enable_for_si<Lhs, Rhs>>
513 SI_INLINE_CONSTEXPR auto operator==(const Lhs& lhs, const Rhs& rhs)
514 {
515 static_assert(has_common_dimension_v<Lhs, Rhs>, "incompatible SI dimensions");
516 return value2(lhs, rhs) == value2(rhs, lhs);
517 }
518
519 template <class Lhs, class Rhs, class = enable_for_si<Lhs, Rhs>>
520 SI_INLINE_CONSTEXPR auto operator!=(const Lhs& lhs, const Rhs& rhs)
521 {
522 static_assert(has_common_dimension_v<Lhs, Rhs>, "incompatible SI dimensions");
523 return value2(lhs, rhs) != value2(rhs, lhs);
524 }
525
526 // helper macro returning a quantity for non-null dimensions and plain value otherwise
527#define SI_RETURN_QUANTITY(dimension_, ...) \
528 if constexpr(is_dimensionless_v<dimension_>) return (__VA_ARGS__); \
529 else return quantity{dimension_(), (__VA_ARGS__)}
530
531 template <class Lhs, class Rhs, class = enable_for_si<Lhs, Rhs>>
532 SI_INLINE_CONSTEXPR auto operator+(const Lhs& lhs, const Rhs& rhs)
533 {
534 static_assert(has_common_dimension_v<Lhs, Rhs>, "incompatible SI dimensions");
535 using result_dimension = dimension_common<Lhs, Rhs>;
536 SI_RETURN_QUANTITY(result_dimension, value2(lhs, rhs) + value2(rhs, lhs));
537 }
538
539 template <class Lhs, class Rhs, class = enable_for_si<Lhs, Rhs>>
540 SI_INLINE_CONSTEXPR auto operator-(const Lhs& lhs, const Rhs& rhs)
541 {
542 static_assert(has_common_dimension_v<Lhs, Rhs>, "incompatible SI dimensions");
543 using result_dimension = dimension_common<Lhs, Rhs>;
544 SI_RETURN_QUANTITY(result_dimension, value2(lhs, rhs) - value2(rhs, lhs));
545 }
546
547 template <class Lhs, class Rhs, class = enable_for_si<Lhs, Rhs>>
548 SI_INLINE_CONSTEXPR auto operator*(const Lhs& lhs, const Rhs& rhs)
549 {
550 using result_dimension = dimension_add<Lhs, Rhs>;
551 SI_RETURN_QUANTITY(result_dimension, value2(lhs, rhs) * value2(rhs, lhs));
552 }
553
554 template <class Lhs, class Rhs, class = enable_for_si<Lhs, Rhs>>
555 SI_INLINE_CONSTEXPR auto operator/(const Lhs& lhs, const Rhs& rhs)
556 {
557 using result_dimension = dimension_subtract<Lhs, Rhs>;
558 SI_RETURN_QUANTITY(result_dimension, value2(lhs, rhs) / value2(rhs, lhs));
559 }
560
561 // Computes the absolute value of x.
562 template <class Dimension, class T>
564 {
565 return value(x) < 0.0 ? -x : x;
566 }
567
568 template <class Lhs, class Rhs, class = enable_for_si<Lhs, Rhs>>
569 SI_INLINE_CONSTEXPR auto dot(const Lhs& lhs, const Rhs& rhs)
570 {
571 using result_dimension = dimension_add<Lhs, Rhs>;
572 SI_RETURN_QUANTITY(result_dimension, dot(value(lhs), value(rhs)));
573 }
574
575 template <class Dimension, class T>
577 {
578 return normalize(value(x));
579 }
580
581 template <class Dimension, class T>
583 {
584 return quantity{ Dimension(), length(value(x)) };
585 }
586
587 template <class T>
592
593 template <long Exponent, class Dimension, class T>
595 {
596 using std::pow;
598 SI_RETURN_QUANTITY(result_dimension, pow(value(x), Exponent));
599 }
600
601 template <long Degree, class Dimension, class T>
603 {
604 using std::pow;
606 static_assert(std::is_same_v<dimension_multiply<result_dimension, value_dimension<Degree>>, Dimension>, "cannot take root of this SI dimension");
607
608 SI_RETURN_QUANTITY(result_dimension, pow(value(x), 1. / Degree));
609 }
610
611 template <class Dimension, class T>
613 {
614 using std::sqrt;
615 using result_dimension = dimension_divide<Dimension, value_dimension<2>>;
616 static_assert(std::is_same_v<dimension_multiply<result_dimension, value_dimension<2>>, Dimension>, "cannot take sqrt of this SI dimension");
617
618 SI_RETURN_QUANTITY(result_dimension, sqrt(value(x)));
619 }
620
621 template <class Dimension, class T>
627
628 template <class T> struct element_count : std::integral_constant<int, 1> {};
629 template <class Dimension, class T> struct element_count<quantity<Dimension, T>> : element_count<T> {};
630
631 template <class T>
633
634 template <class Value, class Min, class Max>
635 SI_INLINE_CONSTEXPR auto clamp(const Value& x, const Min& min, const Max& max)
636 {
637 static_assert(has_common_dimension_v<Value, Min>, "incompatible SI dimensions");
638 static_assert(has_common_dimension_v<Value, Max>, "incompatible SI dimensions");
639
640 using result_dimension = dimension_of_t<Value>;
641 SI_RETURN_QUANTITY(result_dimension, std::clamp(value(x), value(min), value(max)));
642 }
643
644 template <long Num, long Den>
645 struct ratio
646 {
647 static constexpr auto factor = static_cast<SIdouble>(Num) / Den;
648 };
649
650 struct tag_celsius {};
651 struct tag_fahrenheit {};
652
653 template <class Lhs, class Rhs>
655 {
656 static constexpr auto factor = Lhs::factor * Rhs::factor;
657 };
658
659 template <class Lhs, class Rhs>
661 {
662 static constexpr auto factor = Lhs::factor / Rhs::factor;
663 };
664
665 template <class T>
666 using promoted_scalar_type = std::conditional_t<std::is_same_v<scalar_value_type_t<T>, SIdouble>, SIdouble, SIdouble>;
667
668 template <class T>
669 struct is_arithmetic : std::is_arithmetic<T> {};
670
671 template <class Dimension, class UnitRatio>
672 struct unit
673 {
674 template <class T, class = std::enable_if_t<is_arithmetic<T>::value>>
675 SI_INLINE_CONSTEXPR auto operator()(const T& x) const
676 {
677 using scalar_type = promoted_scalar_type<T>;
678
679 if constexpr (std::is_same_v<tag_celsius, UnitRatio>)
680 {
681 SI_RETURN_QUANTITY(Dimension, x + static_cast<scalar_type>(273.15));
682 }
683 else if constexpr (std::is_same_v<tag_fahrenheit, UnitRatio>)
684 {
685 SI_RETURN_QUANTITY(Dimension, (x + static_cast<scalar_type>(459.67)) * static_cast<scalar_type>(5. / 9));
686 }
687 else
688 {
689 SI_RETURN_QUANTITY(Dimension, x * static_cast<scalar_type>(UnitRatio::factor));
690 }
691 }
692 template <class T, class U>
693 SI_INLINE_CONSTEXPR auto operator()(T x, U y) const
694 {
695 using common_type = std::common_type_t<T, U>;
696 using scalar_type = promoted_scalar_type<common_type>;
697
698 if constexpr (std::is_same_v<tag_celsius, UnitRatio>)
699 {
700 SI_RETURN_QUANTITY(Dimension, vec2<scalar_type>(x, y) + static_cast<scalar_type>(273.15));
701 }
702 else if constexpr (std::is_same_v<tag_fahrenheit, UnitRatio>)
703 {
704 SI_RETURN_QUANTITY(Dimension, (vec2<scalar_type>(x, y) + static_cast<scalar_type>(459.67)) * static_cast<scalar_type>(5. / 9));
705 }
706 else
707 {
708 SI_RETURN_QUANTITY(Dimension, vec2<scalar_type>(x, y) * static_cast<scalar_type>(UnitRatio::factor));
709 }
710 }
711
712 template <class T, class U, class V>
713 SI_INLINE_CONSTEXPR auto operator()(T x, U y, V z) const
714 {
715 using common_type = std::common_type_t<T, U, V>;
716 using scalar_type = promoted_scalar_type<common_type>;
717
718 if constexpr (std::is_same_v<tag_celsius, UnitRatio>)
719 {
720 SI_RETURN_QUANTITY(Dimension, vec3<scalar_type>(x, y, z) + static_cast<scalar_type>(273.15));
721 }
722 else if constexpr (std::is_same_v<tag_fahrenheit, UnitRatio>)
723 {
724 SI_RETURN_QUANTITY(Dimension, (vec3<scalar_type>(x, y, z) + static_cast<scalar_type>(459.67)) * static_cast<scalar_type>(5. / 9));
725 }
726 else
727 {
728 SI_RETURN_QUANTITY(Dimension, vec3<scalar_type>(x, y, z) * static_cast<scalar_type>(UnitRatio::factor));
729 }
730 }
731
732 template <class T>
734 {
735 using scalar_type = promoted_scalar_type<T>;
736
737 if constexpr(std::is_same_v<tag_celsius, UnitRatio>)
738 return value(q) - static_cast<scalar_type>(273.15);
739 else if constexpr (std::is_same_v<tag_fahrenheit, UnitRatio>)
740 return value(q) * static_cast<scalar_type>(9. / 5) - static_cast<scalar_type>(459.67);
741 else
742 return value(q) / static_cast<scalar_type>(UnitRatio::factor);
743 }
744 };
745
746 template <class Dimension, long N>
747 struct unit<Dimension, ratio<N, N>>
748 {
749 template <class T, class = std::enable_if_t<is_arithmetic<T>::value>>
751 {
752 SI_RETURN_QUANTITY(Dimension, value);
753 }
754
755 // Special operator for constructing a SI quantity from a trivally constructible internal::vec
756 template <long D, class T>
761
762 template <class T, class U>
763 SI_INLINE_CONSTEXPR auto operator()(T x, U y) const
764 {
765 using common_type = std::common_type_t<T, U>;
766
767 SI_RETURN_QUANTITY(Dimension, vec2<common_type>(x, y));
768 }
769
770 template <class T, class U, class V>
771 SI_INLINE_CONSTEXPR auto operator()(T x, U y, V z) const
772 {
773 using common_type = std::common_type_t<T, U, V>;
774
775 SI_RETURN_QUANTITY(Dimension, vec3<common_type>(x, y, z));
776 }
777
778 template <class T>
780 {
781 return value(q);
782 }
783
788
790 {
791 return value(q);
792 }
793
795 {
796 return value(q);
797 }
798 };
799
800 template <class Ratio>
801 struct unit<dimensionless, Ratio> {};
802
803 template <long N>
804 struct unit<dimensionless, ratio<N, N>>
805 {
806 template <class T, class = std::enable_if_t<is_arithmetic<T>::value>>
807 SI_INLINE_CONSTEXPR const T& operator()(const T& value) const
808 {
809 return value;
810 }
811 };
812
813 template <class DimensionLhs, class RatioLhs, class DimensionRhs, class RatioRhs>
818
819 template <class DimensionLhs, class RatioLhs, class DimensionRhs, class RatioRhs>
824 }
825
827
828 template <class Dimension, long long numerator = 1, long long denumerator = 1>
830
831 using detail::abs;
832 using detail::normalize;
833 using detail::norm;
834 using detail::distance;
835 using detail::pow;
836 using detail::root;
837 using detail::sqrt;
838 using detail::dot;
839 using detail::clamp;
840 using detail::deangle;
841 using detail::is_si;
842 using detail::is_si_v;
843} // end of namespace SI
SI_INLINE_CONSTEXPR quantity_storage()
Definition internal.h:321
friend SI_INLINE_CONSTEXPR T & value(quantity_storage &x)
Definition internal.h:338
friend SI_INLINE_CONSTEXPR const T & value(const quantity_storage &x)
Definition internal.h:333
#define SI_RETURN_QUANTITY(dimension_,...)
Definition internal.h:527
#define SI_INLINE_CONSTEXPR
Definition internal.h:10
#define SI_INLINE
Definition internal.h:9
#define SI_DIMENSION_OP(op_)
Definition internal.h:286
Definition internal.h:223
SI_INLINE_CONSTEXPR bool is_dimensionless_v
Definition internal.h:284
value_dimension< 0 > dimensionless
Definition internal.h:247
std::conditional_t< std::is_same_v< scalar_value_type_t< T >, SIdouble >, SIdouble, SIdouble > promoted_scalar_type
Definition internal.h:666
dimension_multiply_impl< dimension_of_t< Lhs >, dimension_of_t< Rhs > > dimension_multiply
Definition internal.h:302
dimension_add_impl< dimension_of_t< Lhs >, dimension_of_t< Rhs > > dimension_add
Definition internal.h:300
dimension< Value, Value, Value, Value, Value, Value, Value > value_dimension
Definition internal.h:244
SI_INLINE_CONSTEXPR long element_count_v
Definition internal.h:632
SI_INLINE_CONSTEXPR quantity< Dimension, T > & operator+=(quantity< Dimension, T > &lhs, const U &rhs)
Definition internal.h:453
SI_INLINE_CONSTEXPR quantity< Dimension, T > abs(const quantity< Dimension, T > &x)
Definition internal.h:563
dimension_subtract_impl< dimension_of_t< Lhs >, dimension_of_t< Rhs > > dimension_subtract
Definition internal.h:301
SI_INLINE auto normalize(const quantity< Dimension, T > &x)
Definition internal.h:576
SI_INLINE_CONSTEXPR quantity< Dimension, T > operator-(quantity< Dimension, T > x)
Definition internal.h:446
SI_INLINE_CONSTEXPR std::enable_if_t< std::is_arithmetic_v< T > > fill(T &x, T value)
Definition internal.h:346
SI_INLINE_CONSTEXPR const T & value(const T &x)
Definition internal.h:409
SI_INLINE_CONSTEXPR auto deangle(const quantity< Dimension, T > &x)
Definition internal.h:622
SI_INLINE_CONSTEXPR bool has_common_dimension_v
Definition internal.h:436
typename scalar_value_type< T >::type scalar_value_type_t
Definition internal.h:314
SI_INLINE_CONSTEXPR auto dot(const Lhs &lhs, const Rhs &rhs)
Definition internal.h:569
SI_DIMENSION_OP(+) dimension_add_impl
Definition internal.h:295
SI_INLINE_CONSTEXPR auto operator/(const Lhs &lhs, const Rhs &rhs)
Definition internal.h:555
SI_INLINE_CONSTEXPR quantity< Dimension, T > & operator/=(quantity< Dimension, T > &lhs, const U &rhs)
Definition internal.h:477
typename dimension_of< std::decay_t< T > >::type dimension_of_t
Definition internal.h:280
SI_DIMENSION_OP(*) dimension_multiply_impl
Definition internal.h:297
SI_INLINE_CONSTEXPR auto operator!=(const Lhs &lhs, const Rhs &rhs)
Definition internal.h:520
internal::vec2< T > vec2
Definition internal.h:225
SI_INLINE_CONSTEXPR auto operator>(const Lhs &lhs, const Rhs &rhs)
Definition internal.h:499
std::enable_if_t< is_si_v< T >||is_si_v< U >||is_si_v< V > > enable_for_si
Definition internal.h:443
SI_INLINE_CONSTEXPR auto operator*(const Lhs &lhs, const Rhs &rhs)
Definition internal.h:548
SI_INLINE_CONSTEXPR auto operator<=(const Lhs &lhs, const Rhs &rhs)
Definition internal.h:492
SI_DIMENSION_OP(/) dimension_divide_impl
Definition internal.h:298
SI_INLINE_CONSTEXPR quantity< Dimension, T > & operator*=(quantity< Dimension, T > &lhs, const U &rhs)
Definition internal.h:469
SI_INLINE_CONSTEXPR auto clamp(const Value &x, const Min &min, const Max &max)
Definition internal.h:635
SI_INLINE auto norm(const quantity< Dimension, T > &x)
Definition internal.h:582
internal::vec3< T > vec3
Definition internal.h:228
SI_INLINE_CONSTEXPR bool is_si_v
Definition internal.h:405
SI_INLINE auto pow(const quantity< Dimension, T > &x)
Definition internal.h:594
SI_INLINE auto root(const quantity< Dimension, T > &x)
Definition internal.h:602
std::conditional_t< std::is_same_v< Lhs, zero_t >, dimension_of_t< Rhs >, dimension_of_t< Lhs > > dimension_common
Definition internal.h:440
SI_INLINE_CONSTEXPR quantity< Dimension, T > & operator-=(quantity< Dimension, T > &lhs, const U &rhs)
Definition internal.h:461
SI_INLINE_CONSTEXPR auto operator+(const Lhs &lhs, const Rhs &rhs)
Definition internal.h:532
dimension_divide_impl< dimension_of_t< Lhs >, dimension_of_t< Rhs > > dimension_divide
Definition internal.h:303
SI_INLINE_CONSTEXPR auto operator<(const Lhs &lhs, const Rhs &rhs)
Definition internal.h:485
SI_INLINE auto distance(const quantity< dimension< 1, 0, 0, 0, 0, 0, 0 >, T > &a, const quantity< dimension< 1, 0, 0, 0, 0, 0, 0 >, T > &b)
Definition internal.h:588
SI_DIMENSION_OP(-) dimension_subtract_impl
Definition internal.h:296
SI_INLINE_CONSTEXPR decltype(auto) value2(T &&x, U)
Definition internal.h:422
SI_INLINE auto sqrt(const quantity< Dimension, T > &x)
Definition internal.h:612
SI_INLINE_CONSTEXPR auto operator==(const Lhs &lhs, const Rhs &rhs)
Definition internal.h:513
SI_INLINE_CONSTEXPR auto operator>=(const Lhs &lhs, const Rhs &rhs)
Definition internal.h:506
Definition internal.h:21
std::common_type_t< typename vec_value_type< T >::type... > vec_common_type_t
Definition internal.h:25
Definition internal.h:19
SI_INLINE_CONSTEXPR std::common_type_t< T, U, V > mix(T a, U b, V t)
Definition internal.h:217
SI_INLINE_CONSTEXPR vec3< detail::vec_common_type_t< T, U > > cross(const vec3< T > &lhs, const vec3< U > &rhs)
Definition internal.h:214
SI_INLINE_CONSTEXPR std::enable_if_t< std::is_arithmetic_v< T > &&std::is_arithmetic_v< U >, std::common_type_t< T, U > > max(T lhs, U rhs)
Definition internal.h:183
SI_INLINE_CONSTEXPR vec2< detail::vec_common_type_t< T, U > > operator+(const vec2< T > &lhs, const vec2< U > &rhs)
Definition internal.h:143
SI_INLINE_CONSTEXPR vec2< T > & operator-=(vec2< T > &lhs, const vec2< U > &rhs)
Definition internal.h:125
SI_INLINE_CONSTEXPR std::enable_if_t< std::is_arithmetic_v< T >, T > sign(T x)
Definition internal.h:177
SI_INLINE auto distance(const vec2< T > &a, const vec2< U > &b)
Definition internal.h:210
SI_INLINE_CONSTEXPR vec2< T > & operator*=(vec2< T > &lhs, const vec2< U > &rhs)
Definition internal.h:127
SI_INLINE_CONSTEXPR bool operator==(const vec2< T > &lhs, const vec2< U > &rhs)
Definition internal.h:117
SI_INLINE_CONSTEXPR auto dot(const vec2< T > &lhs, const vec2< U > &rhs)
Definition internal.h:197
SI_INLINE auto length(const vec2< T > &v)
Definition internal.h:201
SI_INLINE_CONSTEXPR vec2< T > & operator+=(vec2< T > &lhs, const vec2< U > &rhs)
Definition internal.h:123
vec< 2, T > vec2
Definition internal.h:109
SI_INLINE_CONSTEXPR bool operator!=(const vec2< T > &lhs, const vec2< U > &rhs)
Definition internal.h:119
SI_INLINE_CONSTEXPR vec2< detail::vec_common_type_t< T, U > > operator*(const vec2< T > &lhs, const vec2< U > &rhs)
Definition internal.h:147
SI_INLINE_CONSTEXPR vec2< T > operator-(const vec2< T > &v)
Definition internal.h:113
SI_INLINE_CONSTEXPR vec2< detail::vec_common_type_t< T > > abs(const vec2< T > &v)
Definition internal.h:173
SI_INLINE_CONSTEXPR vec2< T > & operator/=(vec2< T > &lhs, const vec2< U > &rhs)
Definition internal.h:129
SI_INLINE_CONSTEXPR vec2< detail::vec_common_type_t< T, U > > operator/(const vec2< T > &lhs, const vec2< U > &rhs)
Definition internal.h:149
SI_INLINE auto normalize(const vec2< T > &v)
Definition internal.h:206
SI_INLINE_CONSTEXPR std::enable_if_t< std::is_arithmetic_v< T > &&std::is_arithmetic_v< U >, std::common_type_t< T, U > > min(T lhs, U rhs)
Definition internal.h:182
SI_INLINE_CONSTEXPR std::enable_if_t< std::is_arithmetic_v< T >, std::common_type_t< T, U, V > > clamp(T value, U min, V max)
Definition internal.h:190
vec< 3, T > vec3
Definition internal.h:110
Definition constants.h:12
double SIdouble
internal datatype to hold floating point values
Definition internal.h:16
detail::unit< detail::dimension_of_t< Dimension >, detail::ratio< numerator, denumerator > > unit
Definition internal.h:829
SI_INLINE_CONSTEXPR detail::zero_t zero
Definition internal.h:826
angle radians
basic unit of radians for angle
Definition internal.h:15
long double angle
basic datatype to hold a dimensionless angle, e.g. 3.1415
Definition internal.h:14
dimension< Length, Mass, Time, Temperature, Current, Substance, Intensity > type
Definition internal.h:263
Dimension type
Definition internal.h:269
Dimension type
Definition internal.h:275
Definition internal.h:256
dimensionless type
Definition internal.h:257
Definition internal.h:233
Definition internal.h:628
Definition internal.h:669
Definition internal.h:395
Definition internal.h:353
SI_INLINE_CONSTEXPR quantity(Dimension, const T &x)
Definition internal.h:364
T value_type
Definition internal.h:357
static SI_INLINE_CONSTEXPR quantity< Dimension, T > infinity()
Definition internal.h:375
SI_INLINE_CONSTEXPR quantity(zero_t={})
Definition internal.h:360
Dimension dimension_type
Definition internal.h:358
static SI_INLINE_CONSTEXPR quantity< Dimension, T > NaN()
Definition internal.h:384
SI_INLINE_CONSTEXPR quantity(const quantity< Dimension, U > &q)
Definition internal.h:370
Definition internal.h:655
static constexpr auto factor
Definition internal.h:656
Definition internal.h:661
static constexpr auto factor
Definition internal.h:662
Definition internal.h:646
static constexpr auto factor
Definition internal.h:647
typename scalar_value_type< T >::type type
Definition internal.h:311
int type
Definition internal.h:310
Definition internal.h:309
T type
Definition internal.h:309
Definition internal.h:650
Definition internal.h:651
SI_INLINE_CONSTEXPR auto operator()(T x, U y, V z) const
Definition internal.h:771
SI_INLINE_CONSTEXPR vec3< SIdouble > operator()(const quantity< Dimension, vec3< SIdouble > > &q) const
Definition internal.h:794
SI_INLINE_CONSTEXPR vec2< SIdouble > operator()(const quantity< Dimension, vec2< SIdouble > > &q) const
Definition internal.h:789
SI_INLINE_CONSTEXPR SIdouble operator()(const quantity< Dimension, SIdouble > &q) const
Definition internal.h:784
SI_INLINE_CONSTEXPR auto operator()(T value) const
Definition internal.h:750
SI_INLINE_CONSTEXPR auto operator()(T x, U y) const
Definition internal.h:763
SI_INLINE_CONSTEXPR auto operator()(const internal::vec< D, internal::detail::vec_trivally_constructible< T > > &value) const
Definition internal.h:757
SI_INLINE_CONSTEXPR T operator()(const quantity< Dimension, T > &q) const
Definition internal.h:779
SI_INLINE_CONSTEXPR const T & operator()(const T &value) const
Definition internal.h:807
Definition internal.h:673
SI_INLINE_CONSTEXPR auto operator()(T x, U y, V z) const
Definition internal.h:713
SI_INLINE_CONSTEXPR auto operator()(T x, U y) const
Definition internal.h:693
SI_INLINE_CONSTEXPR auto operator()(const quantity< Dimension, T > &q) const
Definition internal.h:733
SI_INLINE_CONSTEXPR auto operator()(const T &x) const
Definition internal.h:675
Definition internal.h:307
Definition internal.h:23
T type
Definition internal.h:23
SI_INLINE_CONSTEXPR vec()
Definition internal.h:36
SI_INLINE_CONSTEXPR vec(T x, T y)
Definition internal.h:46
SI_INLINE_CONSTEXPR vec(const vec< 3, U > &other)
Definition internal.h:59
SI_INLINE_CONSTEXPR vec(const vec< 2, U > &other)
Definition internal.h:53
SI_INLINE_CONSTEXPR vec()
Definition internal.h:71
SI_INLINE_CONSTEXPR vec(const vec< 3, U > &other)
Definition internal.h:91
SI_INLINE_CONSTEXPR vec(T x, T y, T z)
Definition internal.h:81
internal::vec< 2, detail::vec_trivally_constructible< T > > xy
Definition internal.h:104
SI_INLINE_CONSTEXPR vec(const vec< 2, U > &xy, T z)
Definition internal.h:88
Definition internal.h:29