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