nv-sgl 0.6.0__cp313-cp313-win_amd64.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. include/tevclient.h +393 -0
  2. nv_sgl-0.6.0.dist-info/LICENSE +29 -0
  3. nv_sgl-0.6.0.dist-info/METADATA +21 -0
  4. nv_sgl-0.6.0.dist-info/RECORD +142 -0
  5. nv_sgl-0.6.0.dist-info/WHEEL +5 -0
  6. nv_sgl-0.6.0.dist-info/top_level.txt +1 -0
  7. sgl/__init__.py +15 -0
  8. sgl/__init__.pyi +6738 -0
  9. sgl/d3d12/D3D12Core.dll +0 -0
  10. sgl/d3d12/d3d12SDKLayers.dll +0 -0
  11. sgl/dxcompiler.dll +0 -0
  12. sgl/dxil.dll +0 -0
  13. sgl/gfx.dll +0 -0
  14. sgl/include/sgl/app/app.h +113 -0
  15. sgl/include/sgl/core/bitmap.h +302 -0
  16. sgl/include/sgl/core/crypto.h +89 -0
  17. sgl/include/sgl/core/data_type.h +46 -0
  18. sgl/include/sgl/core/dds_file.h +103 -0
  19. sgl/include/sgl/core/enum.h +201 -0
  20. sgl/include/sgl/core/error.h +161 -0
  21. sgl/include/sgl/core/file_stream.h +77 -0
  22. sgl/include/sgl/core/file_system_watcher.h +141 -0
  23. sgl/include/sgl/core/format.h +36 -0
  24. sgl/include/sgl/core/fwd.h +90 -0
  25. sgl/include/sgl/core/hash.h +45 -0
  26. sgl/include/sgl/core/input.h +522 -0
  27. sgl/include/sgl/core/logger.h +214 -0
  28. sgl/include/sgl/core/macros.h +184 -0
  29. sgl/include/sgl/core/maths.h +45 -0
  30. sgl/include/sgl/core/memory_mapped_file.h +112 -0
  31. sgl/include/sgl/core/memory_mapped_file_stream.h +32 -0
  32. sgl/include/sgl/core/memory_stream.h +74 -0
  33. sgl/include/sgl/core/object.h +683 -0
  34. sgl/include/sgl/core/platform.h +239 -0
  35. sgl/include/sgl/core/plugin.h +331 -0
  36. sgl/include/sgl/core/resolver.h +39 -0
  37. sgl/include/sgl/core/short_vector.h +141 -0
  38. sgl/include/sgl/core/static_vector.h +111 -0
  39. sgl/include/sgl/core/stream.h +54 -0
  40. sgl/include/sgl/core/string.h +276 -0
  41. sgl/include/sgl/core/struct.h +360 -0
  42. sgl/include/sgl/core/thread.h +28 -0
  43. sgl/include/sgl/core/timer.h +52 -0
  44. sgl/include/sgl/core/traits.h +15 -0
  45. sgl/include/sgl/core/type_utils.h +19 -0
  46. sgl/include/sgl/core/window.h +177 -0
  47. sgl/include/sgl/device/agility_sdk.h +24 -0
  48. sgl/include/sgl/device/blit.h +88 -0
  49. sgl/include/sgl/device/buffer_cursor.h +162 -0
  50. sgl/include/sgl/device/command.h +539 -0
  51. sgl/include/sgl/device/cuda_api.h +766 -0
  52. sgl/include/sgl/device/cuda_interop.h +39 -0
  53. sgl/include/sgl/device/cuda_utils.h +107 -0
  54. sgl/include/sgl/device/cursor_utils.h +129 -0
  55. sgl/include/sgl/device/device.h +668 -0
  56. sgl/include/sgl/device/device_resource.h +37 -0
  57. sgl/include/sgl/device/fence.h +91 -0
  58. sgl/include/sgl/device/formats.h +330 -0
  59. sgl/include/sgl/device/framebuffer.h +85 -0
  60. sgl/include/sgl/device/fwd.h +164 -0
  61. sgl/include/sgl/device/helpers.h +20 -0
  62. sgl/include/sgl/device/hot_reload.h +75 -0
  63. sgl/include/sgl/device/input_layout.h +74 -0
  64. sgl/include/sgl/device/kernel.h +69 -0
  65. sgl/include/sgl/device/memory_heap.h +155 -0
  66. sgl/include/sgl/device/native_formats.h +342 -0
  67. sgl/include/sgl/device/native_handle.h +73 -0
  68. sgl/include/sgl/device/native_handle_traits.h +65 -0
  69. sgl/include/sgl/device/pipeline.h +138 -0
  70. sgl/include/sgl/device/print.h +45 -0
  71. sgl/include/sgl/device/python/cursor_utils.h +853 -0
  72. sgl/include/sgl/device/query.h +52 -0
  73. sgl/include/sgl/device/raytracing.h +84 -0
  74. sgl/include/sgl/device/reflection.h +1254 -0
  75. sgl/include/sgl/device/resource.h +705 -0
  76. sgl/include/sgl/device/sampler.h +57 -0
  77. sgl/include/sgl/device/shader.h +516 -0
  78. sgl/include/sgl/device/shader_cursor.h +85 -0
  79. sgl/include/sgl/device/shader_object.h +94 -0
  80. sgl/include/sgl/device/shader_offset.h +67 -0
  81. sgl/include/sgl/device/shared_handle.h +12 -0
  82. sgl/include/sgl/device/slang_utils.h +54 -0
  83. sgl/include/sgl/device/swapchain.h +74 -0
  84. sgl/include/sgl/device/types.h +782 -0
  85. sgl/include/sgl/math/colorspace.h +56 -0
  86. sgl/include/sgl/math/constants.h +7 -0
  87. sgl/include/sgl/math/float16.h +146 -0
  88. sgl/include/sgl/math/matrix.h +6 -0
  89. sgl/include/sgl/math/matrix_math.h +746 -0
  90. sgl/include/sgl/math/matrix_types.h +207 -0
  91. sgl/include/sgl/math/python/primitivetype.h +33 -0
  92. sgl/include/sgl/math/quaternion.h +6 -0
  93. sgl/include/sgl/math/quaternion_math.h +484 -0
  94. sgl/include/sgl/math/quaternion_types.h +83 -0
  95. sgl/include/sgl/math/ray.h +47 -0
  96. sgl/include/sgl/math/scalar_math.h +249 -0
  97. sgl/include/sgl/math/scalar_types.h +107 -0
  98. sgl/include/sgl/math/vector.h +6 -0
  99. sgl/include/sgl/math/vector_math.h +1796 -0
  100. sgl/include/sgl/math/vector_types.h +336 -0
  101. sgl/include/sgl/python/nanobind.h +489 -0
  102. sgl/include/sgl/python/py_doc.h +11600 -0
  103. sgl/include/sgl/python/sgl_ext_pch.h +8 -0
  104. sgl/include/sgl/sgl.h +21 -0
  105. sgl/include/sgl/sgl_pch.h +6 -0
  106. sgl/include/sgl/stl/bit.h +377 -0
  107. sgl/include/sgl/tests/testing.h +54 -0
  108. sgl/include/sgl/ui/fwd.h +34 -0
  109. sgl/include/sgl/ui/imgui_config.h +43 -0
  110. sgl/include/sgl/ui/ui.h +71 -0
  111. sgl/include/sgl/ui/widgets.h +918 -0
  112. sgl/include/sgl/utils/python/slangpy.h +366 -0
  113. sgl/include/sgl/utils/renderdoc.h +50 -0
  114. sgl/include/sgl/utils/slangpy.h +153 -0
  115. sgl/include/sgl/utils/tev.h +93 -0
  116. sgl/include/sgl/utils/texture_loader.h +106 -0
  117. sgl/math/__init__.pyi +5083 -0
  118. sgl/platform/__init__.pyi +102 -0
  119. sgl/renderdoc/__init__.pyi +51 -0
  120. sgl/sgl.dll +0 -0
  121. sgl/sgl_ext.cp313-win_amd64.pyd +0 -0
  122. sgl/shaders/nvapi/nvHLSLExtns.h +2315 -0
  123. sgl/shaders/nvapi/nvHLSLExtnsInternal.h +758 -0
  124. sgl/shaders/nvapi/nvShaderExtnEnums.h +142 -0
  125. sgl/shaders/sgl/device/blit.slang +93 -0
  126. sgl/shaders/sgl/device/nvapi.slang +5 -0
  127. sgl/shaders/sgl/device/nvapi.slangh +7 -0
  128. sgl/shaders/sgl/device/print.slang +445 -0
  129. sgl/shaders/sgl/math/constants.slang +4 -0
  130. sgl/shaders/sgl/math/ray.slang +29 -0
  131. sgl/shaders/sgl/ui/imgui.slang +49 -0
  132. sgl/slang-glslang.dll +0 -0
  133. sgl/slang-llvm.dll +0 -0
  134. sgl/slang-rt.dll +0 -0
  135. sgl/slang.dll +0 -0
  136. sgl/slangpy/__init__.pyi +268 -0
  137. sgl/tev/__init__.pyi +108 -0
  138. sgl/tevclient.lib +0 -0
  139. sgl/thread/__init__.pyi +4 -0
  140. sgl/ui/__init__.pyi +1118 -0
  141. share/cmake/tevclient/tevclient-config-release.cmake +19 -0
  142. share/cmake/tevclient/tevclient-config.cmake +108 -0
@@ -0,0 +1,1796 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+
3
+ #pragma once
4
+
5
+ #include "sgl/math/vector_types.h"
6
+ #include "sgl/math/scalar_math.h"
7
+ #include "sgl/core/format.h"
8
+
9
+ #include <string>
10
+
11
+ namespace sgl::math {
12
+
13
+ // ----------------------------------------------------------------------------
14
+ // Boolean reductions
15
+ // ----------------------------------------------------------------------------
16
+
17
+ // clang-format off
18
+ [[nodiscard]] constexpr bool any(const bool1 v) noexcept { return v.x; }
19
+ [[nodiscard]] constexpr bool any(const bool2 v) noexcept { return v.x || v.y; }
20
+ [[nodiscard]] constexpr bool any(const bool3 v) noexcept { return v.x || v.y || v.z; }
21
+ [[nodiscard]] constexpr bool any(const bool4 v) noexcept { return v.x || v.y || v.z || v.w; }
22
+
23
+ [[nodiscard]] constexpr bool all(const bool1 v) noexcept { return v.x; }
24
+ [[nodiscard]] constexpr bool all(const bool2 v) noexcept { return v.x && v.y; }
25
+ [[nodiscard]] constexpr bool all(const bool3 v) noexcept { return v.x && v.y && v.z; }
26
+ [[nodiscard]] constexpr bool all(const bool4 v) noexcept { return v.x && v.y && v.z && v.w; }
27
+
28
+ [[nodiscard]] constexpr bool none(const bool1 v) noexcept { return !any(v); }
29
+ [[nodiscard]] constexpr bool none(const bool2 v) noexcept { return !any(v); }
30
+ [[nodiscard]] constexpr bool none(const bool3 v) noexcept { return !any(v); }
31
+ [[nodiscard]] constexpr bool none(const bool4 v) noexcept { return !any(v); }
32
+ // clang-format on
33
+
34
+ // ----------------------------------------------------------------------------
35
+ // Unary operators
36
+ // ----------------------------------------------------------------------------
37
+
38
+ /// Unary plus operator
39
+ template<arithmetic T, int N>
40
+ [[nodiscard]] constexpr auto operator+(const vector<T, N> v) noexcept
41
+ {
42
+ return v;
43
+ }
44
+
45
+ SGL_DIAGNOSTIC_PUSH
46
+ // unary minus operator applied to unsigned type, result still unsigned
47
+ SGL_DISABLE_MSVC_WARNING(4146)
48
+
49
+ /// Unary minus operator
50
+ template<arithmetic T, int N>
51
+ [[nodiscard]] constexpr auto operator-(const vector<T, N> v) noexcept
52
+ {
53
+ if constexpr (N == 1)
54
+ return vector<T, N>{-v.x};
55
+ else if constexpr (N == 2)
56
+ return vector<T, N>{-v.x, -v.y};
57
+ else if constexpr (N == 3)
58
+ return vector<T, N>{-v.x, -v.y, -v.z};
59
+ else
60
+ return vector<T, N>{-v.x, -v.y, -v.z, -v.w};
61
+ }
62
+
63
+ SGL_DIAGNOSTIC_POP
64
+
65
+ /// Unary not operator
66
+ template<typename T, int N>
67
+ [[nodiscard]] constexpr auto operator!(const vector<T, N> v) noexcept
68
+ {
69
+ if constexpr (N == 1)
70
+ return bool1{!v.x};
71
+ else if constexpr (N == 2)
72
+ return bool2{!v.x, !v.y};
73
+ else if constexpr (N == 3)
74
+ return bool3{!v.x, !v.y, !v.z};
75
+ else
76
+ return bool4{!v.x, !v.y, !v.z, !v.w};
77
+ }
78
+
79
+ /// Unary not operator
80
+ template<integral T, int N>
81
+ [[nodiscard]] constexpr auto operator~(const vector<T, N> v) noexcept
82
+ {
83
+ if constexpr (N == 1)
84
+ return vector<T, N>{~v.x};
85
+ else if constexpr (N == 2)
86
+ return vector<T, N>{~v.x, ~v.y};
87
+ else if constexpr (N == 3)
88
+ return vector<T, N>{~v.x, ~v.y, ~v.z};
89
+ else
90
+ return vector<T, N>{~v.x, ~v.y, ~v.z, ~v.w};
91
+ }
92
+
93
+ // ----------------------------------------------------------------------------
94
+ // Binary operators
95
+ // ----------------------------------------------------------------------------
96
+
97
+ // clang-format off
98
+ /* <<<PYMACRO
99
+ def print_binary_operator(op, concept):
100
+ print(f"""/// Binary {op} operator
101
+ template<{concept} T, int N>
102
+ [[nodiscard]] constexpr vector<T, N> operator{op}(const vector<T, N>& lhs, const vector<T, N>& rhs)
103
+ {{
104
+ if constexpr (N == 1)
105
+ return vector<T, N>{{lhs.x {op} rhs.x}};
106
+ else if constexpr (N == 2)
107
+ return vector<T, N>{{lhs.x {op} rhs.x, lhs.y {op} rhs.y}};
108
+ else if constexpr (N == 3)
109
+ return vector<T, N>{{lhs.x {op} rhs.x, lhs.y {op} rhs.y, lhs.z {op} rhs.z}};
110
+ else if constexpr (N == 4)
111
+ return vector<T, N>{{lhs.x {op} rhs.x, lhs.y {op} rhs.y, lhs.z {op} rhs.z, lhs.w {op} rhs.w}};
112
+ }}
113
+
114
+ /// Binary {op} operator
115
+ template<{concept} T, int N>
116
+ [[nodiscard]] constexpr vector<T, N> operator{op}(const vector<T, N>& lhs, T rhs)
117
+ {{
118
+ return lhs {op} vector<T, N>(rhs);
119
+ }}
120
+
121
+ /// Binary {op} operator
122
+ template<{concept} T, int N>
123
+ [[nodiscard]] constexpr vector<T, N> operator{op}(T lhs, const vector<T, N>& rhs)
124
+ {{
125
+ return vector<T, N>(lhs) {op} rhs;
126
+ }}
127
+ """)
128
+
129
+ print_binary_operator("+", "arithmetic")
130
+ print_binary_operator("-", "arithmetic")
131
+ print_binary_operator("*", "arithmetic")
132
+ print_binary_operator("/", "arithmetic")
133
+ print_binary_operator("%", "integral")
134
+ print_binary_operator("<<", "integral")
135
+ print_binary_operator(">>", "integral")
136
+ print_binary_operator("|", "integral")
137
+ print_binary_operator("&", "integral")
138
+ print_binary_operator("^", "integral")
139
+ >>> */
140
+ /// Binary + operator
141
+ template<arithmetic T, int N>
142
+ [[nodiscard]] constexpr vector<T, N> operator+(const vector<T, N>& lhs, const vector<T, N>& rhs)
143
+ {
144
+ if constexpr (N == 1)
145
+ return vector<T, N>{lhs.x + rhs.x};
146
+ else if constexpr (N == 2)
147
+ return vector<T, N>{lhs.x + rhs.x, lhs.y + rhs.y};
148
+ else if constexpr (N == 3)
149
+ return vector<T, N>{lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z};
150
+ else if constexpr (N == 4)
151
+ return vector<T, N>{lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w};
152
+ }
153
+
154
+ /// Binary + operator
155
+ template<arithmetic T, int N>
156
+ [[nodiscard]] constexpr vector<T, N> operator+(const vector<T, N>& lhs, T rhs)
157
+ {
158
+ return lhs + vector<T, N>(rhs);
159
+ }
160
+
161
+ /// Binary + operator
162
+ template<arithmetic T, int N>
163
+ [[nodiscard]] constexpr vector<T, N> operator+(T lhs, const vector<T, N>& rhs)
164
+ {
165
+ return vector<T, N>(lhs) + rhs;
166
+ }
167
+
168
+ /// Binary - operator
169
+ template<arithmetic T, int N>
170
+ [[nodiscard]] constexpr vector<T, N> operator-(const vector<T, N>& lhs, const vector<T, N>& rhs)
171
+ {
172
+ if constexpr (N == 1)
173
+ return vector<T, N>{lhs.x - rhs.x};
174
+ else if constexpr (N == 2)
175
+ return vector<T, N>{lhs.x - rhs.x, lhs.y - rhs.y};
176
+ else if constexpr (N == 3)
177
+ return vector<T, N>{lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z};
178
+ else if constexpr (N == 4)
179
+ return vector<T, N>{lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w};
180
+ }
181
+
182
+ /// Binary - operator
183
+ template<arithmetic T, int N>
184
+ [[nodiscard]] constexpr vector<T, N> operator-(const vector<T, N>& lhs, T rhs)
185
+ {
186
+ return lhs - vector<T, N>(rhs);
187
+ }
188
+
189
+ /// Binary - operator
190
+ template<arithmetic T, int N>
191
+ [[nodiscard]] constexpr vector<T, N> operator-(T lhs, const vector<T, N>& rhs)
192
+ {
193
+ return vector<T, N>(lhs) - rhs;
194
+ }
195
+
196
+ /// Binary * operator
197
+ template<arithmetic T, int N>
198
+ [[nodiscard]] constexpr vector<T, N> operator*(const vector<T, N>& lhs, const vector<T, N>& rhs)
199
+ {
200
+ if constexpr (N == 1)
201
+ return vector<T, N>{lhs.x * rhs.x};
202
+ else if constexpr (N == 2)
203
+ return vector<T, N>{lhs.x * rhs.x, lhs.y * rhs.y};
204
+ else if constexpr (N == 3)
205
+ return vector<T, N>{lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z};
206
+ else if constexpr (N == 4)
207
+ return vector<T, N>{lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w};
208
+ }
209
+
210
+ /// Binary * operator
211
+ template<arithmetic T, int N>
212
+ [[nodiscard]] constexpr vector<T, N> operator*(const vector<T, N>& lhs, T rhs)
213
+ {
214
+ return lhs * vector<T, N>(rhs);
215
+ }
216
+
217
+ /// Binary * operator
218
+ template<arithmetic T, int N>
219
+ [[nodiscard]] constexpr vector<T, N> operator*(T lhs, const vector<T, N>& rhs)
220
+ {
221
+ return vector<T, N>(lhs) * rhs;
222
+ }
223
+
224
+ /// Binary / operator
225
+ template<arithmetic T, int N>
226
+ [[nodiscard]] constexpr vector<T, N> operator/(const vector<T, N>& lhs, const vector<T, N>& rhs)
227
+ {
228
+ if constexpr (N == 1)
229
+ return vector<T, N>{lhs.x / rhs.x};
230
+ else if constexpr (N == 2)
231
+ return vector<T, N>{lhs.x / rhs.x, lhs.y / rhs.y};
232
+ else if constexpr (N == 3)
233
+ return vector<T, N>{lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z};
234
+ else if constexpr (N == 4)
235
+ return vector<T, N>{lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w};
236
+ }
237
+
238
+ /// Binary / operator
239
+ template<arithmetic T, int N>
240
+ [[nodiscard]] constexpr vector<T, N> operator/(const vector<T, N>& lhs, T rhs)
241
+ {
242
+ return lhs / vector<T, N>(rhs);
243
+ }
244
+
245
+ /// Binary / operator
246
+ template<arithmetic T, int N>
247
+ [[nodiscard]] constexpr vector<T, N> operator/(T lhs, const vector<T, N>& rhs)
248
+ {
249
+ return vector<T, N>(lhs) / rhs;
250
+ }
251
+
252
+ /// Binary % operator
253
+ template<integral T, int N>
254
+ [[nodiscard]] constexpr vector<T, N> operator%(const vector<T, N>& lhs, const vector<T, N>& rhs)
255
+ {
256
+ if constexpr (N == 1)
257
+ return vector<T, N>{lhs.x % rhs.x};
258
+ else if constexpr (N == 2)
259
+ return vector<T, N>{lhs.x % rhs.x, lhs.y % rhs.y};
260
+ else if constexpr (N == 3)
261
+ return vector<T, N>{lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z};
262
+ else if constexpr (N == 4)
263
+ return vector<T, N>{lhs.x % rhs.x, lhs.y % rhs.y, lhs.z % rhs.z, lhs.w % rhs.w};
264
+ }
265
+
266
+ /// Binary % operator
267
+ template<integral T, int N>
268
+ [[nodiscard]] constexpr vector<T, N> operator%(const vector<T, N>& lhs, T rhs)
269
+ {
270
+ return lhs % vector<T, N>(rhs);
271
+ }
272
+
273
+ /// Binary % operator
274
+ template<integral T, int N>
275
+ [[nodiscard]] constexpr vector<T, N> operator%(T lhs, const vector<T, N>& rhs)
276
+ {
277
+ return vector<T, N>(lhs) % rhs;
278
+ }
279
+
280
+ /// Binary << operator
281
+ template<integral T, int N>
282
+ [[nodiscard]] constexpr vector<T, N> operator<<(const vector<T, N>& lhs, const vector<T, N>& rhs)
283
+ {
284
+ if constexpr (N == 1)
285
+ return vector<T, N>{lhs.x << rhs.x};
286
+ else if constexpr (N == 2)
287
+ return vector<T, N>{lhs.x << rhs.x, lhs.y << rhs.y};
288
+ else if constexpr (N == 3)
289
+ return vector<T, N>{lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z};
290
+ else if constexpr (N == 4)
291
+ return vector<T, N>{lhs.x << rhs.x, lhs.y << rhs.y, lhs.z << rhs.z, lhs.w << rhs.w};
292
+ }
293
+
294
+ /// Binary << operator
295
+ template<integral T, int N>
296
+ [[nodiscard]] constexpr vector<T, N> operator<<(const vector<T, N>& lhs, T rhs)
297
+ {
298
+ return lhs << vector<T, N>(rhs);
299
+ }
300
+
301
+ /// Binary << operator
302
+ template<integral T, int N>
303
+ [[nodiscard]] constexpr vector<T, N> operator<<(T lhs, const vector<T, N>& rhs)
304
+ {
305
+ return vector<T, N>(lhs) << rhs;
306
+ }
307
+
308
+ /// Binary >> operator
309
+ template<integral T, int N>
310
+ [[nodiscard]] constexpr vector<T, N> operator>>(const vector<T, N>& lhs, const vector<T, N>& rhs)
311
+ {
312
+ if constexpr (N == 1)
313
+ return vector<T, N>{lhs.x >> rhs.x};
314
+ else if constexpr (N == 2)
315
+ return vector<T, N>{lhs.x >> rhs.x, lhs.y >> rhs.y};
316
+ else if constexpr (N == 3)
317
+ return vector<T, N>{lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z};
318
+ else if constexpr (N == 4)
319
+ return vector<T, N>{lhs.x >> rhs.x, lhs.y >> rhs.y, lhs.z >> rhs.z, lhs.w >> rhs.w};
320
+ }
321
+
322
+ /// Binary >> operator
323
+ template<integral T, int N>
324
+ [[nodiscard]] constexpr vector<T, N> operator>>(const vector<T, N>& lhs, T rhs)
325
+ {
326
+ return lhs >> vector<T, N>(rhs);
327
+ }
328
+
329
+ /// Binary >> operator
330
+ template<integral T, int N>
331
+ [[nodiscard]] constexpr vector<T, N> operator>>(T lhs, const vector<T, N>& rhs)
332
+ {
333
+ return vector<T, N>(lhs) >> rhs;
334
+ }
335
+
336
+ /// Binary | operator
337
+ template<integral T, int N>
338
+ [[nodiscard]] constexpr vector<T, N> operator|(const vector<T, N>& lhs, const vector<T, N>& rhs)
339
+ {
340
+ if constexpr (N == 1)
341
+ return vector<T, N>{lhs.x | rhs.x};
342
+ else if constexpr (N == 2)
343
+ return vector<T, N>{lhs.x | rhs.x, lhs.y | rhs.y};
344
+ else if constexpr (N == 3)
345
+ return vector<T, N>{lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z};
346
+ else if constexpr (N == 4)
347
+ return vector<T, N>{lhs.x | rhs.x, lhs.y | rhs.y, lhs.z | rhs.z, lhs.w | rhs.w};
348
+ }
349
+
350
+ /// Binary | operator
351
+ template<integral T, int N>
352
+ [[nodiscard]] constexpr vector<T, N> operator|(const vector<T, N>& lhs, T rhs)
353
+ {
354
+ return lhs | vector<T, N>(rhs);
355
+ }
356
+
357
+ /// Binary | operator
358
+ template<integral T, int N>
359
+ [[nodiscard]] constexpr vector<T, N> operator|(T lhs, const vector<T, N>& rhs)
360
+ {
361
+ return vector<T, N>(lhs) | rhs;
362
+ }
363
+
364
+ /// Binary & operator
365
+ template<integral T, int N>
366
+ [[nodiscard]] constexpr vector<T, N> operator&(const vector<T, N>& lhs, const vector<T, N>& rhs)
367
+ {
368
+ if constexpr (N == 1)
369
+ return vector<T, N>{lhs.x & rhs.x};
370
+ else if constexpr (N == 2)
371
+ return vector<T, N>{lhs.x & rhs.x, lhs.y & rhs.y};
372
+ else if constexpr (N == 3)
373
+ return vector<T, N>{lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z};
374
+ else if constexpr (N == 4)
375
+ return vector<T, N>{lhs.x & rhs.x, lhs.y & rhs.y, lhs.z & rhs.z, lhs.w & rhs.w};
376
+ }
377
+
378
+ /// Binary & operator
379
+ template<integral T, int N>
380
+ [[nodiscard]] constexpr vector<T, N> operator&(const vector<T, N>& lhs, T rhs)
381
+ {
382
+ return lhs & vector<T, N>(rhs);
383
+ }
384
+
385
+ /// Binary & operator
386
+ template<integral T, int N>
387
+ [[nodiscard]] constexpr vector<T, N> operator&(T lhs, const vector<T, N>& rhs)
388
+ {
389
+ return vector<T, N>(lhs) & rhs;
390
+ }
391
+
392
+ /// Binary ^ operator
393
+ template<integral T, int N>
394
+ [[nodiscard]] constexpr vector<T, N> operator^(const vector<T, N>& lhs, const vector<T, N>& rhs)
395
+ {
396
+ if constexpr (N == 1)
397
+ return vector<T, N>{lhs.x ^ rhs.x};
398
+ else if constexpr (N == 2)
399
+ return vector<T, N>{lhs.x ^ rhs.x, lhs.y ^ rhs.y};
400
+ else if constexpr (N == 3)
401
+ return vector<T, N>{lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z};
402
+ else if constexpr (N == 4)
403
+ return vector<T, N>{lhs.x ^ rhs.x, lhs.y ^ rhs.y, lhs.z ^ rhs.z, lhs.w ^ rhs.w};
404
+ }
405
+
406
+ /// Binary ^ operator
407
+ template<integral T, int N>
408
+ [[nodiscard]] constexpr vector<T, N> operator^(const vector<T, N>& lhs, T rhs)
409
+ {
410
+ return lhs ^ vector<T, N>(rhs);
411
+ }
412
+
413
+ /// Binary ^ operator
414
+ template<integral T, int N>
415
+ [[nodiscard]] constexpr vector<T, N> operator^(T lhs, const vector<T, N>& rhs)
416
+ {
417
+ return vector<T, N>(lhs) ^ rhs;
418
+ }
419
+
420
+ /* <<<PYMACROEND>>> */
421
+ // clang-format on
422
+
423
+ // ----------------------------------------------------------------------------
424
+ // Binary logic operators
425
+ // ----------------------------------------------------------------------------
426
+
427
+ // clang-format off
428
+ /* <<<PYMACRO
429
+ def print_binary_operator(op, concept):
430
+ print(f"""/// Binary {op} operator
431
+ template<{concept} T, int N>
432
+ [[nodiscard]] constexpr auto operator{op}(const vector<T, N>& lhs, const vector<T, N>& rhs)
433
+ {{
434
+ if constexpr (N == 1)
435
+ return bool1{{lhs.x {op} rhs.x}};
436
+ else if constexpr (N == 2)
437
+ return bool2{{lhs.x {op} rhs.x, lhs.y {op} rhs.y}};
438
+ else if constexpr (N == 3)
439
+ return bool3{{lhs.x {op} rhs.x, lhs.y {op} rhs.y, lhs.z {op} rhs.z}};
440
+ else if constexpr (N == 4)
441
+ return bool4{{lhs.x {op} rhs.x, lhs.y {op} rhs.y, lhs.z {op} rhs.z, lhs.w {op} rhs.w}};
442
+ }}
443
+
444
+ /// Binary {op} operator
445
+ template<{concept} T, int N>
446
+ [[nodiscard]] constexpr auto operator{op}(const vector<T, N>& lhs, T rhs)
447
+ {{
448
+ return lhs {op} vector<T, N>(rhs);
449
+ }}
450
+
451
+ /// Binary {op} operator
452
+ template<{concept} T, int N>
453
+ [[nodiscard]] constexpr auto operator{op}(T lhs, const vector<T, N>& rhs)
454
+ {{
455
+ return vector<T, N>(lhs) {op} rhs;
456
+ }}
457
+ """)
458
+
459
+ print_binary_operator("||", "boolean")
460
+ print_binary_operator("&&", "boolean")
461
+ print_binary_operator("==", "typename")
462
+ print_binary_operator("!=", "typename")
463
+ print_binary_operator("<", "arithmetic")
464
+ print_binary_operator(">", "arithmetic")
465
+ print_binary_operator("<=", "arithmetic")
466
+ print_binary_operator(">=", "arithmetic")
467
+ >>> */
468
+ /// Binary || operator
469
+ template<boolean T, int N>
470
+ [[nodiscard]] constexpr auto operator||(const vector<T, N>& lhs, const vector<T, N>& rhs)
471
+ {
472
+ if constexpr (N == 1)
473
+ return bool1{lhs.x || rhs.x};
474
+ else if constexpr (N == 2)
475
+ return bool2{lhs.x || rhs.x, lhs.y || rhs.y};
476
+ else if constexpr (N == 3)
477
+ return bool3{lhs.x || rhs.x, lhs.y || rhs.y, lhs.z || rhs.z};
478
+ else if constexpr (N == 4)
479
+ return bool4{lhs.x || rhs.x, lhs.y || rhs.y, lhs.z || rhs.z, lhs.w || rhs.w};
480
+ }
481
+
482
+ /// Binary || operator
483
+ template<boolean T, int N>
484
+ [[nodiscard]] constexpr auto operator||(const vector<T, N>& lhs, T rhs)
485
+ {
486
+ return lhs || vector<T, N>(rhs);
487
+ }
488
+
489
+ /// Binary || operator
490
+ template<boolean T, int N>
491
+ [[nodiscard]] constexpr auto operator||(T lhs, const vector<T, N>& rhs)
492
+ {
493
+ return vector<T, N>(lhs) || rhs;
494
+ }
495
+
496
+ /// Binary && operator
497
+ template<boolean T, int N>
498
+ [[nodiscard]] constexpr auto operator&&(const vector<T, N>& lhs, const vector<T, N>& rhs)
499
+ {
500
+ if constexpr (N == 1)
501
+ return bool1{lhs.x && rhs.x};
502
+ else if constexpr (N == 2)
503
+ return bool2{lhs.x && rhs.x, lhs.y && rhs.y};
504
+ else if constexpr (N == 3)
505
+ return bool3{lhs.x && rhs.x, lhs.y && rhs.y, lhs.z && rhs.z};
506
+ else if constexpr (N == 4)
507
+ return bool4{lhs.x && rhs.x, lhs.y && rhs.y, lhs.z && rhs.z, lhs.w && rhs.w};
508
+ }
509
+
510
+ /// Binary && operator
511
+ template<boolean T, int N>
512
+ [[nodiscard]] constexpr auto operator&&(const vector<T, N>& lhs, T rhs)
513
+ {
514
+ return lhs && vector<T, N>(rhs);
515
+ }
516
+
517
+ /// Binary && operator
518
+ template<boolean T, int N>
519
+ [[nodiscard]] constexpr auto operator&&(T lhs, const vector<T, N>& rhs)
520
+ {
521
+ return vector<T, N>(lhs) && rhs;
522
+ }
523
+
524
+ /// Binary == operator
525
+ template<typename T, int N>
526
+ [[nodiscard]] constexpr auto operator==(const vector<T, N>& lhs, const vector<T, N>& rhs)
527
+ {
528
+ if constexpr (N == 1)
529
+ return bool1{lhs.x == rhs.x};
530
+ else if constexpr (N == 2)
531
+ return bool2{lhs.x == rhs.x, lhs.y == rhs.y};
532
+ else if constexpr (N == 3)
533
+ return bool3{lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z};
534
+ else if constexpr (N == 4)
535
+ return bool4{lhs.x == rhs.x, lhs.y == rhs.y, lhs.z == rhs.z, lhs.w == rhs.w};
536
+ }
537
+
538
+ /// Binary == operator
539
+ template<typename T, int N>
540
+ [[nodiscard]] constexpr auto operator==(const vector<T, N>& lhs, T rhs)
541
+ {
542
+ return lhs == vector<T, N>(rhs);
543
+ }
544
+
545
+ /// Binary == operator
546
+ template<typename T, int N>
547
+ [[nodiscard]] constexpr auto operator==(T lhs, const vector<T, N>& rhs)
548
+ {
549
+ return vector<T, N>(lhs) == rhs;
550
+ }
551
+
552
+ /// Binary != operator
553
+ template<typename T, int N>
554
+ [[nodiscard]] constexpr auto operator!=(const vector<T, N>& lhs, const vector<T, N>& rhs)
555
+ {
556
+ if constexpr (N == 1)
557
+ return bool1{lhs.x != rhs.x};
558
+ else if constexpr (N == 2)
559
+ return bool2{lhs.x != rhs.x, lhs.y != rhs.y};
560
+ else if constexpr (N == 3)
561
+ return bool3{lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z};
562
+ else if constexpr (N == 4)
563
+ return bool4{lhs.x != rhs.x, lhs.y != rhs.y, lhs.z != rhs.z, lhs.w != rhs.w};
564
+ }
565
+
566
+ /// Binary != operator
567
+ template<typename T, int N>
568
+ [[nodiscard]] constexpr auto operator!=(const vector<T, N>& lhs, T rhs)
569
+ {
570
+ return lhs != vector<T, N>(rhs);
571
+ }
572
+
573
+ /// Binary != operator
574
+ template<typename T, int N>
575
+ [[nodiscard]] constexpr auto operator!=(T lhs, const vector<T, N>& rhs)
576
+ {
577
+ return vector<T, N>(lhs) != rhs;
578
+ }
579
+
580
+ /// Binary < operator
581
+ template<arithmetic T, int N>
582
+ [[nodiscard]] constexpr auto operator<(const vector<T, N>& lhs, const vector<T, N>& rhs)
583
+ {
584
+ if constexpr (N == 1)
585
+ return bool1{lhs.x < rhs.x};
586
+ else if constexpr (N == 2)
587
+ return bool2{lhs.x < rhs.x, lhs.y < rhs.y};
588
+ else if constexpr (N == 3)
589
+ return bool3{lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z};
590
+ else if constexpr (N == 4)
591
+ return bool4{lhs.x < rhs.x, lhs.y < rhs.y, lhs.z < rhs.z, lhs.w < rhs.w};
592
+ }
593
+
594
+ /// Binary < operator
595
+ template<arithmetic T, int N>
596
+ [[nodiscard]] constexpr auto operator<(const vector<T, N>& lhs, T rhs)
597
+ {
598
+ return lhs < vector<T, N>(rhs);
599
+ }
600
+
601
+ /// Binary < operator
602
+ template<arithmetic T, int N>
603
+ [[nodiscard]] constexpr auto operator<(T lhs, const vector<T, N>& rhs)
604
+ {
605
+ return vector<T, N>(lhs) < rhs;
606
+ }
607
+
608
+ /// Binary > operator
609
+ template<arithmetic T, int N>
610
+ [[nodiscard]] constexpr auto operator>(const vector<T, N>& lhs, const vector<T, N>& rhs)
611
+ {
612
+ if constexpr (N == 1)
613
+ return bool1{lhs.x > rhs.x};
614
+ else if constexpr (N == 2)
615
+ return bool2{lhs.x > rhs.x, lhs.y > rhs.y};
616
+ else if constexpr (N == 3)
617
+ return bool3{lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z};
618
+ else if constexpr (N == 4)
619
+ return bool4{lhs.x > rhs.x, lhs.y > rhs.y, lhs.z > rhs.z, lhs.w > rhs.w};
620
+ }
621
+
622
+ /// Binary > operator
623
+ template<arithmetic T, int N>
624
+ [[nodiscard]] constexpr auto operator>(const vector<T, N>& lhs, T rhs)
625
+ {
626
+ return lhs > vector<T, N>(rhs);
627
+ }
628
+
629
+ /// Binary > operator
630
+ template<arithmetic T, int N>
631
+ [[nodiscard]] constexpr auto operator>(T lhs, const vector<T, N>& rhs)
632
+ {
633
+ return vector<T, N>(lhs) > rhs;
634
+ }
635
+
636
+ /// Binary <= operator
637
+ template<arithmetic T, int N>
638
+ [[nodiscard]] constexpr auto operator<=(const vector<T, N>& lhs, const vector<T, N>& rhs)
639
+ {
640
+ if constexpr (N == 1)
641
+ return bool1{lhs.x <= rhs.x};
642
+ else if constexpr (N == 2)
643
+ return bool2{lhs.x <= rhs.x, lhs.y <= rhs.y};
644
+ else if constexpr (N == 3)
645
+ return bool3{lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z};
646
+ else if constexpr (N == 4)
647
+ return bool4{lhs.x <= rhs.x, lhs.y <= rhs.y, lhs.z <= rhs.z, lhs.w <= rhs.w};
648
+ }
649
+
650
+ /// Binary <= operator
651
+ template<arithmetic T, int N>
652
+ [[nodiscard]] constexpr auto operator<=(const vector<T, N>& lhs, T rhs)
653
+ {
654
+ return lhs <= vector<T, N>(rhs);
655
+ }
656
+
657
+ /// Binary <= operator
658
+ template<arithmetic T, int N>
659
+ [[nodiscard]] constexpr auto operator<=(T lhs, const vector<T, N>& rhs)
660
+ {
661
+ return vector<T, N>(lhs) <= rhs;
662
+ }
663
+
664
+ /// Binary >= operator
665
+ template<arithmetic T, int N>
666
+ [[nodiscard]] constexpr auto operator>=(const vector<T, N>& lhs, const vector<T, N>& rhs)
667
+ {
668
+ if constexpr (N == 1)
669
+ return bool1{lhs.x >= rhs.x};
670
+ else if constexpr (N == 2)
671
+ return bool2{lhs.x >= rhs.x, lhs.y >= rhs.y};
672
+ else if constexpr (N == 3)
673
+ return bool3{lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z};
674
+ else if constexpr (N == 4)
675
+ return bool4{lhs.x >= rhs.x, lhs.y >= rhs.y, lhs.z >= rhs.z, lhs.w >= rhs.w};
676
+ }
677
+
678
+ /// Binary >= operator
679
+ template<arithmetic T, int N>
680
+ [[nodiscard]] constexpr auto operator>=(const vector<T, N>& lhs, T rhs)
681
+ {
682
+ return lhs >= vector<T, N>(rhs);
683
+ }
684
+
685
+ /// Binary >= operator
686
+ template<arithmetic T, int N>
687
+ [[nodiscard]] constexpr auto operator>=(T lhs, const vector<T, N>& rhs)
688
+ {
689
+ return vector<T, N>(lhs) >= rhs;
690
+ }
691
+
692
+ /* <<<PYMACROEND>>> */
693
+ // clang-format on
694
+
695
+ // ----------------------------------------------------------------------------
696
+ // Assignment operators
697
+ // ----------------------------------------------------------------------------
698
+
699
+ // clang-format off
700
+ /* <<<PYMACRO
701
+ def print_assignment_operator(op, concept):
702
+ print(f"""/// {op} assignment operator
703
+ template<{concept} T, int N>
704
+ constexpr vector<T, N> operator{op}(vector<T, N>& lhs, const vector<T, N>& rhs)
705
+ {{
706
+ lhs.x {op} rhs.x;
707
+ if constexpr (N >= 2)
708
+ lhs.y {op} rhs.y;
709
+ if constexpr (N >= 3)
710
+ lhs.z {op} rhs.z;
711
+ if constexpr (N >= 4)
712
+ lhs.w {op} rhs.w;
713
+ return lhs;
714
+ }}
715
+
716
+ /// {op} assignment operator
717
+ template<{concept} T, int N>
718
+ constexpr vector<T, N> operator{op}(vector<T, N>& lhs, T rhs)
719
+ {{
720
+ return (lhs {op} vector<T, N>(rhs));
721
+ }}
722
+ """)
723
+
724
+ print_assignment_operator("+=", "arithmetic")
725
+ print_assignment_operator("-=", "arithmetic")
726
+ print_assignment_operator("*=", "arithmetic")
727
+ print_assignment_operator("/=", "arithmetic")
728
+ print_assignment_operator("%=", "integral")
729
+ print_assignment_operator("<<=", "integral")
730
+ print_assignment_operator(">>=", "integral")
731
+ print_assignment_operator("|=", "integral")
732
+ print_assignment_operator("&=", "integral")
733
+ print_assignment_operator("^=", "integral")
734
+ >>> */
735
+ /// += assignment operator
736
+ template<arithmetic T, int N>
737
+ constexpr vector<T, N> operator+=(vector<T, N>& lhs, const vector<T, N>& rhs)
738
+ {
739
+ lhs.x += rhs.x;
740
+ if constexpr (N >= 2)
741
+ lhs.y += rhs.y;
742
+ if constexpr (N >= 3)
743
+ lhs.z += rhs.z;
744
+ if constexpr (N >= 4)
745
+ lhs.w += rhs.w;
746
+ return lhs;
747
+ }
748
+
749
+ /// += assignment operator
750
+ template<arithmetic T, int N>
751
+ constexpr vector<T, N> operator+=(vector<T, N>& lhs, T rhs)
752
+ {
753
+ return (lhs += vector<T, N>(rhs));
754
+ }
755
+
756
+ /// -= assignment operator
757
+ template<arithmetic T, int N>
758
+ constexpr vector<T, N> operator-=(vector<T, N>& lhs, const vector<T, N>& rhs)
759
+ {
760
+ lhs.x -= rhs.x;
761
+ if constexpr (N >= 2)
762
+ lhs.y -= rhs.y;
763
+ if constexpr (N >= 3)
764
+ lhs.z -= rhs.z;
765
+ if constexpr (N >= 4)
766
+ lhs.w -= rhs.w;
767
+ return lhs;
768
+ }
769
+
770
+ /// -= assignment operator
771
+ template<arithmetic T, int N>
772
+ constexpr vector<T, N> operator-=(vector<T, N>& lhs, T rhs)
773
+ {
774
+ return (lhs -= vector<T, N>(rhs));
775
+ }
776
+
777
+ /// *= assignment operator
778
+ template<arithmetic T, int N>
779
+ constexpr vector<T, N> operator*=(vector<T, N>& lhs, const vector<T, N>& rhs)
780
+ {
781
+ lhs.x *= rhs.x;
782
+ if constexpr (N >= 2)
783
+ lhs.y *= rhs.y;
784
+ if constexpr (N >= 3)
785
+ lhs.z *= rhs.z;
786
+ if constexpr (N >= 4)
787
+ lhs.w *= rhs.w;
788
+ return lhs;
789
+ }
790
+
791
+ /// *= assignment operator
792
+ template<arithmetic T, int N>
793
+ constexpr vector<T, N> operator*=(vector<T, N>& lhs, T rhs)
794
+ {
795
+ return (lhs *= vector<T, N>(rhs));
796
+ }
797
+
798
+ /// /= assignment operator
799
+ template<arithmetic T, int N>
800
+ constexpr vector<T, N> operator/=(vector<T, N>& lhs, const vector<T, N>& rhs)
801
+ {
802
+ lhs.x /= rhs.x;
803
+ if constexpr (N >= 2)
804
+ lhs.y /= rhs.y;
805
+ if constexpr (N >= 3)
806
+ lhs.z /= rhs.z;
807
+ if constexpr (N >= 4)
808
+ lhs.w /= rhs.w;
809
+ return lhs;
810
+ }
811
+
812
+ /// /= assignment operator
813
+ template<arithmetic T, int N>
814
+ constexpr vector<T, N> operator/=(vector<T, N>& lhs, T rhs)
815
+ {
816
+ return (lhs /= vector<T, N>(rhs));
817
+ }
818
+
819
+ /// %= assignment operator
820
+ template<integral T, int N>
821
+ constexpr vector<T, N> operator%=(vector<T, N>& lhs, const vector<T, N>& rhs)
822
+ {
823
+ lhs.x %= rhs.x;
824
+ if constexpr (N >= 2)
825
+ lhs.y %= rhs.y;
826
+ if constexpr (N >= 3)
827
+ lhs.z %= rhs.z;
828
+ if constexpr (N >= 4)
829
+ lhs.w %= rhs.w;
830
+ return lhs;
831
+ }
832
+
833
+ /// %= assignment operator
834
+ template<integral T, int N>
835
+ constexpr vector<T, N> operator%=(vector<T, N>& lhs, T rhs)
836
+ {
837
+ return (lhs %= vector<T, N>(rhs));
838
+ }
839
+
840
+ /// <<= assignment operator
841
+ template<integral T, int N>
842
+ constexpr vector<T, N> operator<<=(vector<T, N>& lhs, const vector<T, N>& rhs)
843
+ {
844
+ lhs.x <<= rhs.x;
845
+ if constexpr (N >= 2)
846
+ lhs.y <<= rhs.y;
847
+ if constexpr (N >= 3)
848
+ lhs.z <<= rhs.z;
849
+ if constexpr (N >= 4)
850
+ lhs.w <<= rhs.w;
851
+ return lhs;
852
+ }
853
+
854
+ /// <<= assignment operator
855
+ template<integral T, int N>
856
+ constexpr vector<T, N> operator<<=(vector<T, N>& lhs, T rhs)
857
+ {
858
+ return (lhs <<= vector<T, N>(rhs));
859
+ }
860
+
861
+ /// >>= assignment operator
862
+ template<integral T, int N>
863
+ constexpr vector<T, N> operator>>=(vector<T, N>& lhs, const vector<T, N>& rhs)
864
+ {
865
+ lhs.x >>= rhs.x;
866
+ if constexpr (N >= 2)
867
+ lhs.y >>= rhs.y;
868
+ if constexpr (N >= 3)
869
+ lhs.z >>= rhs.z;
870
+ if constexpr (N >= 4)
871
+ lhs.w >>= rhs.w;
872
+ return lhs;
873
+ }
874
+
875
+ /// >>= assignment operator
876
+ template<integral T, int N>
877
+ constexpr vector<T, N> operator>>=(vector<T, N>& lhs, T rhs)
878
+ {
879
+ return (lhs >>= vector<T, N>(rhs));
880
+ }
881
+
882
+ /// |= assignment operator
883
+ template<integral T, int N>
884
+ constexpr vector<T, N> operator|=(vector<T, N>& lhs, const vector<T, N>& rhs)
885
+ {
886
+ lhs.x |= rhs.x;
887
+ if constexpr (N >= 2)
888
+ lhs.y |= rhs.y;
889
+ if constexpr (N >= 3)
890
+ lhs.z |= rhs.z;
891
+ if constexpr (N >= 4)
892
+ lhs.w |= rhs.w;
893
+ return lhs;
894
+ }
895
+
896
+ /// |= assignment operator
897
+ template<integral T, int N>
898
+ constexpr vector<T, N> operator|=(vector<T, N>& lhs, T rhs)
899
+ {
900
+ return (lhs |= vector<T, N>(rhs));
901
+ }
902
+
903
+ /// &= assignment operator
904
+ template<integral T, int N>
905
+ constexpr vector<T, N> operator&=(vector<T, N>& lhs, const vector<T, N>& rhs)
906
+ {
907
+ lhs.x &= rhs.x;
908
+ if constexpr (N >= 2)
909
+ lhs.y &= rhs.y;
910
+ if constexpr (N >= 3)
911
+ lhs.z &= rhs.z;
912
+ if constexpr (N >= 4)
913
+ lhs.w &= rhs.w;
914
+ return lhs;
915
+ }
916
+
917
+ /// &= assignment operator
918
+ template<integral T, int N>
919
+ constexpr vector<T, N> operator&=(vector<T, N>& lhs, T rhs)
920
+ {
921
+ return (lhs &= vector<T, N>(rhs));
922
+ }
923
+
924
+ /// ^= assignment operator
925
+ template<integral T, int N>
926
+ constexpr vector<T, N> operator^=(vector<T, N>& lhs, const vector<T, N>& rhs)
927
+ {
928
+ lhs.x ^= rhs.x;
929
+ if constexpr (N >= 2)
930
+ lhs.y ^= rhs.y;
931
+ if constexpr (N >= 3)
932
+ lhs.z ^= rhs.z;
933
+ if constexpr (N >= 4)
934
+ lhs.w ^= rhs.w;
935
+ return lhs;
936
+ }
937
+
938
+ /// ^= assignment operator
939
+ template<integral T, int N>
940
+ constexpr vector<T, N> operator^=(vector<T, N>& lhs, T rhs)
941
+ {
942
+ return (lhs ^= vector<T, N>(rhs));
943
+ }
944
+
945
+ /* <<<PYMACROEND>>> */
946
+ // clang-format on
947
+
948
+ // ----------------------------------------------------------------------------
949
+ // Intrinsics
950
+ // ----------------------------------------------------------------------------
951
+
952
+ // clang-format off
953
+ /* <<<PYMACRO
954
+ def print_section(name):
955
+ print(f"""// ----------------------------------------------------------------------------
956
+ // {name}
957
+ // ----------------------------------------------------------------------------
958
+ """)
959
+ def print_unary_func(func, concept, arg="x", return_type="T"):
960
+ print(f"""/// {func}
961
+ template<{concept} T, int N>
962
+ [[nodiscard]] constexpr vector<{return_type}, N> {func}(const vector<T, N>& {arg})
963
+ {{
964
+ if constexpr (N == 1)
965
+ return vector<{return_type}, N>{{{func}({arg}.x)}};
966
+ else if constexpr (N == 2)
967
+ return vector<{return_type}, N>{{{func}({arg}.x), {func}({arg}.y)}};
968
+ else if constexpr (N == 3)
969
+ return vector<{return_type}, N>{{{func}({arg}.x), {func}({arg}.y), {func}({arg}.z)}};
970
+ else if constexpr (N == 4)
971
+ return vector<{return_type}, N>{{{func}({arg}.x), {func}({arg}.y), {func}({arg}.z), {func}({arg}.w)}};
972
+ }}
973
+ """)
974
+ def print_binary_func(func, concept, arg0="x", arg1="y", return_type="T"):
975
+ print(f"""/// {func}
976
+ template<{concept} T, int N>
977
+ [[nodiscard]] constexpr vector<{return_type}, N> {func}(const vector<T, N>& {arg0}, const vector<T, N>& {arg1})
978
+ {{
979
+ if constexpr (N == 1)
980
+ return vector<{return_type}, N>{{{func}({arg0}.x, {arg1}.x)}};
981
+ else if constexpr (N == 2)
982
+ return vector<{return_type}, N>{{{func}({arg0}.x, {arg1}.x), {func}({arg0}.y, {arg1}.y)}};
983
+ else if constexpr (N == 3)
984
+ return vector<{return_type}, N>{{{func}({arg0}.x, {arg1}.x), {func}({arg0}.y, {arg1}.y), {func}({arg0}.z, {arg1}.z)}};
985
+ else if constexpr (N == 4)
986
+ return vector<{return_type}, N>{{{func}({arg0}.x, {arg1}.x), {func}({arg0}.y, {arg1}.y), {func}({arg0}.z, {arg1}.z), {func}({arg0}.w, {arg1}.w)}};
987
+ }}
988
+ """)
989
+ def print_ternary_func(func, concept, arg0="x", arg1="y", arg2="z", return_type="T"):
990
+ print(f"""/// {func}
991
+ template<{concept} T, int N>
992
+ [[nodiscard]] constexpr vector<{return_type}, N> {func}(const vector<T, N>& {arg0}, const vector<T, N>& {arg1}, const vector<T, N>& {arg2})
993
+ {{
994
+ if constexpr (N == 1)
995
+ return vector<{return_type}, N>{{{func}({arg0}.x, {arg1}.x, {arg2}.x)}};
996
+ else if constexpr (N == 2)
997
+ return vector<{return_type}, N>{{{func}({arg0}.x, {arg1}.x, {arg2}.x), {func}({arg0}.y, {arg1}.y, {arg2}.y)}};
998
+ else if constexpr (N == 3)
999
+ return vector<{return_type}, N>{{{func}({arg0}.x, {arg1}.x, {arg2}.x), {func}({arg0}.y, {arg1}.y, {arg2}.y), {func}({arg0}.z, {arg1}.z, {arg2}.z)}};
1000
+ else if constexpr (N == 4)
1001
+ return vector<{return_type}, N>{{{func}({arg0}.x, {arg1}.x, {arg2}.x), {func}({arg0}.y, {arg1}.y, {arg2}.y), {func}({arg0}.z, {arg1}.z, {arg2}.z), {func}({arg0}.w, {arg1}.w, {arg2}.w)}};
1002
+ }}
1003
+ """)
1004
+ print_section("Basic functions")
1005
+ print_binary_func("min", "arithmetic")
1006
+ print_binary_func("max", "arithmetic")
1007
+ print_ternary_func("clamp", "arithmetic", "x", "min_", "max_")
1008
+ print_unary_func("abs", "signed_number")
1009
+ print_unary_func("sign", "signed_number")
1010
+ print_section("Floating point checks")
1011
+ print_unary_func("isfinite", "floating_point", "x", "bool")
1012
+ print_unary_func("isinf", "floating_point", "x", "bool")
1013
+ print_unary_func("isnan", "floating_point", "x", "bool")
1014
+ print_section("Rounding")
1015
+ print_unary_func("floor", "floating_point")
1016
+ print_unary_func("ceil", "floating_point")
1017
+ print_unary_func("trunc", "floating_point")
1018
+ print_unary_func("round", "floating_point")
1019
+ print_section("Exponential")
1020
+ print_binary_func("pow", "floating_point", "x", "y")
1021
+ print_unary_func("sqrt", "floating_point")
1022
+ print_unary_func("rsqrt", "floating_point")
1023
+ print_unary_func("exp", "floating_point")
1024
+ print_unary_func("exp2", "floating_point")
1025
+ print_unary_func("log", "floating_point")
1026
+ print_unary_func("log2", "floating_point")
1027
+ print_unary_func("log10", "floating_point")
1028
+ print_section("Trigonometry")
1029
+ print_unary_func("radians", "floating_point")
1030
+ print_unary_func("degrees", "floating_point")
1031
+ print_unary_func("sin", "floating_point")
1032
+ print_unary_func("cos", "floating_point")
1033
+ print_unary_func("tan", "floating_point")
1034
+ print_unary_func("asin", "floating_point")
1035
+ print_unary_func("acos", "floating_point")
1036
+ print_unary_func("atan", "floating_point")
1037
+ print_binary_func("atan2", "floating_point", "y", "x")
1038
+ print_unary_func("sinh", "floating_point")
1039
+ print_unary_func("cosh", "floating_point")
1040
+ print_unary_func("tanh", "floating_point")
1041
+ print_section("Misc")
1042
+ print_binary_func("fmod", "floating_point", "x", "y")
1043
+ print_unary_func("frac", "floating_point")
1044
+ print_ternary_func("lerp", "floating_point", "x", "y", "s")
1045
+ print_unary_func("rcp", "floating_point")
1046
+ print_unary_func("saturate", "floating_point")
1047
+ print_ternary_func("smoothstep", "floating_point", "min_", "max_", "x")
1048
+ print_binary_func("step", "floating_point", "x", "y")
1049
+ >>> */
1050
+ // ----------------------------------------------------------------------------
1051
+ // Basic functions
1052
+ // ----------------------------------------------------------------------------
1053
+
1054
+ /// min
1055
+ template<arithmetic T, int N>
1056
+ [[nodiscard]] constexpr vector<T, N> min(const vector<T, N>& x, const vector<T, N>& y)
1057
+ {
1058
+ if constexpr (N == 1)
1059
+ return vector<T, N>{min(x.x, y.x)};
1060
+ else if constexpr (N == 2)
1061
+ return vector<T, N>{min(x.x, y.x), min(x.y, y.y)};
1062
+ else if constexpr (N == 3)
1063
+ return vector<T, N>{min(x.x, y.x), min(x.y, y.y), min(x.z, y.z)};
1064
+ else if constexpr (N == 4)
1065
+ return vector<T, N>{min(x.x, y.x), min(x.y, y.y), min(x.z, y.z), min(x.w, y.w)};
1066
+ }
1067
+
1068
+ /// max
1069
+ template<arithmetic T, int N>
1070
+ [[nodiscard]] constexpr vector<T, N> max(const vector<T, N>& x, const vector<T, N>& y)
1071
+ {
1072
+ if constexpr (N == 1)
1073
+ return vector<T, N>{max(x.x, y.x)};
1074
+ else if constexpr (N == 2)
1075
+ return vector<T, N>{max(x.x, y.x), max(x.y, y.y)};
1076
+ else if constexpr (N == 3)
1077
+ return vector<T, N>{max(x.x, y.x), max(x.y, y.y), max(x.z, y.z)};
1078
+ else if constexpr (N == 4)
1079
+ return vector<T, N>{max(x.x, y.x), max(x.y, y.y), max(x.z, y.z), max(x.w, y.w)};
1080
+ }
1081
+
1082
+ /// clamp
1083
+ template<arithmetic T, int N>
1084
+ [[nodiscard]] constexpr vector<T, N> clamp(const vector<T, N>& x, const vector<T, N>& min_, const vector<T, N>& max_)
1085
+ {
1086
+ if constexpr (N == 1)
1087
+ return vector<T, N>{clamp(x.x, min_.x, max_.x)};
1088
+ else if constexpr (N == 2)
1089
+ return vector<T, N>{clamp(x.x, min_.x, max_.x), clamp(x.y, min_.y, max_.y)};
1090
+ else if constexpr (N == 3)
1091
+ return vector<T, N>{clamp(x.x, min_.x, max_.x), clamp(x.y, min_.y, max_.y), clamp(x.z, min_.z, max_.z)};
1092
+ else if constexpr (N == 4)
1093
+ return vector<T, N>{clamp(x.x, min_.x, max_.x), clamp(x.y, min_.y, max_.y), clamp(x.z, min_.z, max_.z), clamp(x.w, min_.w, max_.w)};
1094
+ }
1095
+
1096
+ /// abs
1097
+ template<signed_number T, int N>
1098
+ [[nodiscard]] constexpr vector<T, N> abs(const vector<T, N>& x)
1099
+ {
1100
+ if constexpr (N == 1)
1101
+ return vector<T, N>{abs(x.x)};
1102
+ else if constexpr (N == 2)
1103
+ return vector<T, N>{abs(x.x), abs(x.y)};
1104
+ else if constexpr (N == 3)
1105
+ return vector<T, N>{abs(x.x), abs(x.y), abs(x.z)};
1106
+ else if constexpr (N == 4)
1107
+ return vector<T, N>{abs(x.x), abs(x.y), abs(x.z), abs(x.w)};
1108
+ }
1109
+
1110
+ /// sign
1111
+ template<signed_number T, int N>
1112
+ [[nodiscard]] constexpr vector<T, N> sign(const vector<T, N>& x)
1113
+ {
1114
+ if constexpr (N == 1)
1115
+ return vector<T, N>{sign(x.x)};
1116
+ else if constexpr (N == 2)
1117
+ return vector<T, N>{sign(x.x), sign(x.y)};
1118
+ else if constexpr (N == 3)
1119
+ return vector<T, N>{sign(x.x), sign(x.y), sign(x.z)};
1120
+ else if constexpr (N == 4)
1121
+ return vector<T, N>{sign(x.x), sign(x.y), sign(x.z), sign(x.w)};
1122
+ }
1123
+
1124
+ // ----------------------------------------------------------------------------
1125
+ // Floating point checks
1126
+ // ----------------------------------------------------------------------------
1127
+
1128
+ /// isfinite
1129
+ template<floating_point T, int N>
1130
+ [[nodiscard]] constexpr vector<bool, N> isfinite(const vector<T, N>& x)
1131
+ {
1132
+ if constexpr (N == 1)
1133
+ return vector<bool, N>{isfinite(x.x)};
1134
+ else if constexpr (N == 2)
1135
+ return vector<bool, N>{isfinite(x.x), isfinite(x.y)};
1136
+ else if constexpr (N == 3)
1137
+ return vector<bool, N>{isfinite(x.x), isfinite(x.y), isfinite(x.z)};
1138
+ else if constexpr (N == 4)
1139
+ return vector<bool, N>{isfinite(x.x), isfinite(x.y), isfinite(x.z), isfinite(x.w)};
1140
+ }
1141
+
1142
+ /// isinf
1143
+ template<floating_point T, int N>
1144
+ [[nodiscard]] constexpr vector<bool, N> isinf(const vector<T, N>& x)
1145
+ {
1146
+ if constexpr (N == 1)
1147
+ return vector<bool, N>{isinf(x.x)};
1148
+ else if constexpr (N == 2)
1149
+ return vector<bool, N>{isinf(x.x), isinf(x.y)};
1150
+ else if constexpr (N == 3)
1151
+ return vector<bool, N>{isinf(x.x), isinf(x.y), isinf(x.z)};
1152
+ else if constexpr (N == 4)
1153
+ return vector<bool, N>{isinf(x.x), isinf(x.y), isinf(x.z), isinf(x.w)};
1154
+ }
1155
+
1156
+ /// isnan
1157
+ template<floating_point T, int N>
1158
+ [[nodiscard]] constexpr vector<bool, N> isnan(const vector<T, N>& x)
1159
+ {
1160
+ if constexpr (N == 1)
1161
+ return vector<bool, N>{isnan(x.x)};
1162
+ else if constexpr (N == 2)
1163
+ return vector<bool, N>{isnan(x.x), isnan(x.y)};
1164
+ else if constexpr (N == 3)
1165
+ return vector<bool, N>{isnan(x.x), isnan(x.y), isnan(x.z)};
1166
+ else if constexpr (N == 4)
1167
+ return vector<bool, N>{isnan(x.x), isnan(x.y), isnan(x.z), isnan(x.w)};
1168
+ }
1169
+
1170
+ // ----------------------------------------------------------------------------
1171
+ // Rounding
1172
+ // ----------------------------------------------------------------------------
1173
+
1174
+ /// floor
1175
+ template<floating_point T, int N>
1176
+ [[nodiscard]] constexpr vector<T, N> floor(const vector<T, N>& x)
1177
+ {
1178
+ if constexpr (N == 1)
1179
+ return vector<T, N>{floor(x.x)};
1180
+ else if constexpr (N == 2)
1181
+ return vector<T, N>{floor(x.x), floor(x.y)};
1182
+ else if constexpr (N == 3)
1183
+ return vector<T, N>{floor(x.x), floor(x.y), floor(x.z)};
1184
+ else if constexpr (N == 4)
1185
+ return vector<T, N>{floor(x.x), floor(x.y), floor(x.z), floor(x.w)};
1186
+ }
1187
+
1188
+ /// ceil
1189
+ template<floating_point T, int N>
1190
+ [[nodiscard]] constexpr vector<T, N> ceil(const vector<T, N>& x)
1191
+ {
1192
+ if constexpr (N == 1)
1193
+ return vector<T, N>{ceil(x.x)};
1194
+ else if constexpr (N == 2)
1195
+ return vector<T, N>{ceil(x.x), ceil(x.y)};
1196
+ else if constexpr (N == 3)
1197
+ return vector<T, N>{ceil(x.x), ceil(x.y), ceil(x.z)};
1198
+ else if constexpr (N == 4)
1199
+ return vector<T, N>{ceil(x.x), ceil(x.y), ceil(x.z), ceil(x.w)};
1200
+ }
1201
+
1202
+ /// trunc
1203
+ template<floating_point T, int N>
1204
+ [[nodiscard]] constexpr vector<T, N> trunc(const vector<T, N>& x)
1205
+ {
1206
+ if constexpr (N == 1)
1207
+ return vector<T, N>{trunc(x.x)};
1208
+ else if constexpr (N == 2)
1209
+ return vector<T, N>{trunc(x.x), trunc(x.y)};
1210
+ else if constexpr (N == 3)
1211
+ return vector<T, N>{trunc(x.x), trunc(x.y), trunc(x.z)};
1212
+ else if constexpr (N == 4)
1213
+ return vector<T, N>{trunc(x.x), trunc(x.y), trunc(x.z), trunc(x.w)};
1214
+ }
1215
+
1216
+ /// round
1217
+ template<floating_point T, int N>
1218
+ [[nodiscard]] constexpr vector<T, N> round(const vector<T, N>& x)
1219
+ {
1220
+ if constexpr (N == 1)
1221
+ return vector<T, N>{round(x.x)};
1222
+ else if constexpr (N == 2)
1223
+ return vector<T, N>{round(x.x), round(x.y)};
1224
+ else if constexpr (N == 3)
1225
+ return vector<T, N>{round(x.x), round(x.y), round(x.z)};
1226
+ else if constexpr (N == 4)
1227
+ return vector<T, N>{round(x.x), round(x.y), round(x.z), round(x.w)};
1228
+ }
1229
+
1230
+ // ----------------------------------------------------------------------------
1231
+ // Exponential
1232
+ // ----------------------------------------------------------------------------
1233
+
1234
+ /// pow
1235
+ template<floating_point T, int N>
1236
+ [[nodiscard]] constexpr vector<T, N> pow(const vector<T, N>& x, const vector<T, N>& y)
1237
+ {
1238
+ if constexpr (N == 1)
1239
+ return vector<T, N>{pow(x.x, y.x)};
1240
+ else if constexpr (N == 2)
1241
+ return vector<T, N>{pow(x.x, y.x), pow(x.y, y.y)};
1242
+ else if constexpr (N == 3)
1243
+ return vector<T, N>{pow(x.x, y.x), pow(x.y, y.y), pow(x.z, y.z)};
1244
+ else if constexpr (N == 4)
1245
+ return vector<T, N>{pow(x.x, y.x), pow(x.y, y.y), pow(x.z, y.z), pow(x.w, y.w)};
1246
+ }
1247
+
1248
+ /// sqrt
1249
+ template<floating_point T, int N>
1250
+ [[nodiscard]] constexpr vector<T, N> sqrt(const vector<T, N>& x)
1251
+ {
1252
+ if constexpr (N == 1)
1253
+ return vector<T, N>{sqrt(x.x)};
1254
+ else if constexpr (N == 2)
1255
+ return vector<T, N>{sqrt(x.x), sqrt(x.y)};
1256
+ else if constexpr (N == 3)
1257
+ return vector<T, N>{sqrt(x.x), sqrt(x.y), sqrt(x.z)};
1258
+ else if constexpr (N == 4)
1259
+ return vector<T, N>{sqrt(x.x), sqrt(x.y), sqrt(x.z), sqrt(x.w)};
1260
+ }
1261
+
1262
+ /// rsqrt
1263
+ template<floating_point T, int N>
1264
+ [[nodiscard]] constexpr vector<T, N> rsqrt(const vector<T, N>& x)
1265
+ {
1266
+ if constexpr (N == 1)
1267
+ return vector<T, N>{rsqrt(x.x)};
1268
+ else if constexpr (N == 2)
1269
+ return vector<T, N>{rsqrt(x.x), rsqrt(x.y)};
1270
+ else if constexpr (N == 3)
1271
+ return vector<T, N>{rsqrt(x.x), rsqrt(x.y), rsqrt(x.z)};
1272
+ else if constexpr (N == 4)
1273
+ return vector<T, N>{rsqrt(x.x), rsqrt(x.y), rsqrt(x.z), rsqrt(x.w)};
1274
+ }
1275
+
1276
+ /// exp
1277
+ template<floating_point T, int N>
1278
+ [[nodiscard]] constexpr vector<T, N> exp(const vector<T, N>& x)
1279
+ {
1280
+ if constexpr (N == 1)
1281
+ return vector<T, N>{exp(x.x)};
1282
+ else if constexpr (N == 2)
1283
+ return vector<T, N>{exp(x.x), exp(x.y)};
1284
+ else if constexpr (N == 3)
1285
+ return vector<T, N>{exp(x.x), exp(x.y), exp(x.z)};
1286
+ else if constexpr (N == 4)
1287
+ return vector<T, N>{exp(x.x), exp(x.y), exp(x.z), exp(x.w)};
1288
+ }
1289
+
1290
+ /// exp2
1291
+ template<floating_point T, int N>
1292
+ [[nodiscard]] constexpr vector<T, N> exp2(const vector<T, N>& x)
1293
+ {
1294
+ if constexpr (N == 1)
1295
+ return vector<T, N>{exp2(x.x)};
1296
+ else if constexpr (N == 2)
1297
+ return vector<T, N>{exp2(x.x), exp2(x.y)};
1298
+ else if constexpr (N == 3)
1299
+ return vector<T, N>{exp2(x.x), exp2(x.y), exp2(x.z)};
1300
+ else if constexpr (N == 4)
1301
+ return vector<T, N>{exp2(x.x), exp2(x.y), exp2(x.z), exp2(x.w)};
1302
+ }
1303
+
1304
+ /// log
1305
+ template<floating_point T, int N>
1306
+ [[nodiscard]] constexpr vector<T, N> log(const vector<T, N>& x)
1307
+ {
1308
+ if constexpr (N == 1)
1309
+ return vector<T, N>{log(x.x)};
1310
+ else if constexpr (N == 2)
1311
+ return vector<T, N>{log(x.x), log(x.y)};
1312
+ else if constexpr (N == 3)
1313
+ return vector<T, N>{log(x.x), log(x.y), log(x.z)};
1314
+ else if constexpr (N == 4)
1315
+ return vector<T, N>{log(x.x), log(x.y), log(x.z), log(x.w)};
1316
+ }
1317
+
1318
+ /// log2
1319
+ template<floating_point T, int N>
1320
+ [[nodiscard]] constexpr vector<T, N> log2(const vector<T, N>& x)
1321
+ {
1322
+ if constexpr (N == 1)
1323
+ return vector<T, N>{log2(x.x)};
1324
+ else if constexpr (N == 2)
1325
+ return vector<T, N>{log2(x.x), log2(x.y)};
1326
+ else if constexpr (N == 3)
1327
+ return vector<T, N>{log2(x.x), log2(x.y), log2(x.z)};
1328
+ else if constexpr (N == 4)
1329
+ return vector<T, N>{log2(x.x), log2(x.y), log2(x.z), log2(x.w)};
1330
+ }
1331
+
1332
+ /// log10
1333
+ template<floating_point T, int N>
1334
+ [[nodiscard]] constexpr vector<T, N> log10(const vector<T, N>& x)
1335
+ {
1336
+ if constexpr (N == 1)
1337
+ return vector<T, N>{log10(x.x)};
1338
+ else if constexpr (N == 2)
1339
+ return vector<T, N>{log10(x.x), log10(x.y)};
1340
+ else if constexpr (N == 3)
1341
+ return vector<T, N>{log10(x.x), log10(x.y), log10(x.z)};
1342
+ else if constexpr (N == 4)
1343
+ return vector<T, N>{log10(x.x), log10(x.y), log10(x.z), log10(x.w)};
1344
+ }
1345
+
1346
+ // ----------------------------------------------------------------------------
1347
+ // Trigonometry
1348
+ // ----------------------------------------------------------------------------
1349
+
1350
+ /// radians
1351
+ template<floating_point T, int N>
1352
+ [[nodiscard]] constexpr vector<T, N> radians(const vector<T, N>& x)
1353
+ {
1354
+ if constexpr (N == 1)
1355
+ return vector<T, N>{radians(x.x)};
1356
+ else if constexpr (N == 2)
1357
+ return vector<T, N>{radians(x.x), radians(x.y)};
1358
+ else if constexpr (N == 3)
1359
+ return vector<T, N>{radians(x.x), radians(x.y), radians(x.z)};
1360
+ else if constexpr (N == 4)
1361
+ return vector<T, N>{radians(x.x), radians(x.y), radians(x.z), radians(x.w)};
1362
+ }
1363
+
1364
+ /// degrees
1365
+ template<floating_point T, int N>
1366
+ [[nodiscard]] constexpr vector<T, N> degrees(const vector<T, N>& x)
1367
+ {
1368
+ if constexpr (N == 1)
1369
+ return vector<T, N>{degrees(x.x)};
1370
+ else if constexpr (N == 2)
1371
+ return vector<T, N>{degrees(x.x), degrees(x.y)};
1372
+ else if constexpr (N == 3)
1373
+ return vector<T, N>{degrees(x.x), degrees(x.y), degrees(x.z)};
1374
+ else if constexpr (N == 4)
1375
+ return vector<T, N>{degrees(x.x), degrees(x.y), degrees(x.z), degrees(x.w)};
1376
+ }
1377
+
1378
+ /// sin
1379
+ template<floating_point T, int N>
1380
+ [[nodiscard]] constexpr vector<T, N> sin(const vector<T, N>& x)
1381
+ {
1382
+ if constexpr (N == 1)
1383
+ return vector<T, N>{sin(x.x)};
1384
+ else if constexpr (N == 2)
1385
+ return vector<T, N>{sin(x.x), sin(x.y)};
1386
+ else if constexpr (N == 3)
1387
+ return vector<T, N>{sin(x.x), sin(x.y), sin(x.z)};
1388
+ else if constexpr (N == 4)
1389
+ return vector<T, N>{sin(x.x), sin(x.y), sin(x.z), sin(x.w)};
1390
+ }
1391
+
1392
+ /// cos
1393
+ template<floating_point T, int N>
1394
+ [[nodiscard]] constexpr vector<T, N> cos(const vector<T, N>& x)
1395
+ {
1396
+ if constexpr (N == 1)
1397
+ return vector<T, N>{cos(x.x)};
1398
+ else if constexpr (N == 2)
1399
+ return vector<T, N>{cos(x.x), cos(x.y)};
1400
+ else if constexpr (N == 3)
1401
+ return vector<T, N>{cos(x.x), cos(x.y), cos(x.z)};
1402
+ else if constexpr (N == 4)
1403
+ return vector<T, N>{cos(x.x), cos(x.y), cos(x.z), cos(x.w)};
1404
+ }
1405
+
1406
+ /// tan
1407
+ template<floating_point T, int N>
1408
+ [[nodiscard]] constexpr vector<T, N> tan(const vector<T, N>& x)
1409
+ {
1410
+ if constexpr (N == 1)
1411
+ return vector<T, N>{tan(x.x)};
1412
+ else if constexpr (N == 2)
1413
+ return vector<T, N>{tan(x.x), tan(x.y)};
1414
+ else if constexpr (N == 3)
1415
+ return vector<T, N>{tan(x.x), tan(x.y), tan(x.z)};
1416
+ else if constexpr (N == 4)
1417
+ return vector<T, N>{tan(x.x), tan(x.y), tan(x.z), tan(x.w)};
1418
+ }
1419
+
1420
+ /// asin
1421
+ template<floating_point T, int N>
1422
+ [[nodiscard]] constexpr vector<T, N> asin(const vector<T, N>& x)
1423
+ {
1424
+ if constexpr (N == 1)
1425
+ return vector<T, N>{asin(x.x)};
1426
+ else if constexpr (N == 2)
1427
+ return vector<T, N>{asin(x.x), asin(x.y)};
1428
+ else if constexpr (N == 3)
1429
+ return vector<T, N>{asin(x.x), asin(x.y), asin(x.z)};
1430
+ else if constexpr (N == 4)
1431
+ return vector<T, N>{asin(x.x), asin(x.y), asin(x.z), asin(x.w)};
1432
+ }
1433
+
1434
+ /// acos
1435
+ template<floating_point T, int N>
1436
+ [[nodiscard]] constexpr vector<T, N> acos(const vector<T, N>& x)
1437
+ {
1438
+ if constexpr (N == 1)
1439
+ return vector<T, N>{acos(x.x)};
1440
+ else if constexpr (N == 2)
1441
+ return vector<T, N>{acos(x.x), acos(x.y)};
1442
+ else if constexpr (N == 3)
1443
+ return vector<T, N>{acos(x.x), acos(x.y), acos(x.z)};
1444
+ else if constexpr (N == 4)
1445
+ return vector<T, N>{acos(x.x), acos(x.y), acos(x.z), acos(x.w)};
1446
+ }
1447
+
1448
+ /// atan
1449
+ template<floating_point T, int N>
1450
+ [[nodiscard]] constexpr vector<T, N> atan(const vector<T, N>& x)
1451
+ {
1452
+ if constexpr (N == 1)
1453
+ return vector<T, N>{atan(x.x)};
1454
+ else if constexpr (N == 2)
1455
+ return vector<T, N>{atan(x.x), atan(x.y)};
1456
+ else if constexpr (N == 3)
1457
+ return vector<T, N>{atan(x.x), atan(x.y), atan(x.z)};
1458
+ else if constexpr (N == 4)
1459
+ return vector<T, N>{atan(x.x), atan(x.y), atan(x.z), atan(x.w)};
1460
+ }
1461
+
1462
+ /// atan2
1463
+ template<floating_point T, int N>
1464
+ [[nodiscard]] constexpr vector<T, N> atan2(const vector<T, N>& y, const vector<T, N>& x)
1465
+ {
1466
+ if constexpr (N == 1)
1467
+ return vector<T, N>{atan2(y.x, x.x)};
1468
+ else if constexpr (N == 2)
1469
+ return vector<T, N>{atan2(y.x, x.x), atan2(y.y, x.y)};
1470
+ else if constexpr (N == 3)
1471
+ return vector<T, N>{atan2(y.x, x.x), atan2(y.y, x.y), atan2(y.z, x.z)};
1472
+ else if constexpr (N == 4)
1473
+ return vector<T, N>{atan2(y.x, x.x), atan2(y.y, x.y), atan2(y.z, x.z), atan2(y.w, x.w)};
1474
+ }
1475
+
1476
+ /// sinh
1477
+ template<floating_point T, int N>
1478
+ [[nodiscard]] constexpr vector<T, N> sinh(const vector<T, N>& x)
1479
+ {
1480
+ if constexpr (N == 1)
1481
+ return vector<T, N>{sinh(x.x)};
1482
+ else if constexpr (N == 2)
1483
+ return vector<T, N>{sinh(x.x), sinh(x.y)};
1484
+ else if constexpr (N == 3)
1485
+ return vector<T, N>{sinh(x.x), sinh(x.y), sinh(x.z)};
1486
+ else if constexpr (N == 4)
1487
+ return vector<T, N>{sinh(x.x), sinh(x.y), sinh(x.z), sinh(x.w)};
1488
+ }
1489
+
1490
+ /// cosh
1491
+ template<floating_point T, int N>
1492
+ [[nodiscard]] constexpr vector<T, N> cosh(const vector<T, N>& x)
1493
+ {
1494
+ if constexpr (N == 1)
1495
+ return vector<T, N>{cosh(x.x)};
1496
+ else if constexpr (N == 2)
1497
+ return vector<T, N>{cosh(x.x), cosh(x.y)};
1498
+ else if constexpr (N == 3)
1499
+ return vector<T, N>{cosh(x.x), cosh(x.y), cosh(x.z)};
1500
+ else if constexpr (N == 4)
1501
+ return vector<T, N>{cosh(x.x), cosh(x.y), cosh(x.z), cosh(x.w)};
1502
+ }
1503
+
1504
+ /// tanh
1505
+ template<floating_point T, int N>
1506
+ [[nodiscard]] constexpr vector<T, N> tanh(const vector<T, N>& x)
1507
+ {
1508
+ if constexpr (N == 1)
1509
+ return vector<T, N>{tanh(x.x)};
1510
+ else if constexpr (N == 2)
1511
+ return vector<T, N>{tanh(x.x), tanh(x.y)};
1512
+ else if constexpr (N == 3)
1513
+ return vector<T, N>{tanh(x.x), tanh(x.y), tanh(x.z)};
1514
+ else if constexpr (N == 4)
1515
+ return vector<T, N>{tanh(x.x), tanh(x.y), tanh(x.z), tanh(x.w)};
1516
+ }
1517
+
1518
+ // ----------------------------------------------------------------------------
1519
+ // Misc
1520
+ // ----------------------------------------------------------------------------
1521
+
1522
+ /// fmod
1523
+ template<floating_point T, int N>
1524
+ [[nodiscard]] constexpr vector<T, N> fmod(const vector<T, N>& x, const vector<T, N>& y)
1525
+ {
1526
+ if constexpr (N == 1)
1527
+ return vector<T, N>{fmod(x.x, y.x)};
1528
+ else if constexpr (N == 2)
1529
+ return vector<T, N>{fmod(x.x, y.x), fmod(x.y, y.y)};
1530
+ else if constexpr (N == 3)
1531
+ return vector<T, N>{fmod(x.x, y.x), fmod(x.y, y.y), fmod(x.z, y.z)};
1532
+ else if constexpr (N == 4)
1533
+ return vector<T, N>{fmod(x.x, y.x), fmod(x.y, y.y), fmod(x.z, y.z), fmod(x.w, y.w)};
1534
+ }
1535
+
1536
+ /// frac
1537
+ template<floating_point T, int N>
1538
+ [[nodiscard]] constexpr vector<T, N> frac(const vector<T, N>& x)
1539
+ {
1540
+ if constexpr (N == 1)
1541
+ return vector<T, N>{frac(x.x)};
1542
+ else if constexpr (N == 2)
1543
+ return vector<T, N>{frac(x.x), frac(x.y)};
1544
+ else if constexpr (N == 3)
1545
+ return vector<T, N>{frac(x.x), frac(x.y), frac(x.z)};
1546
+ else if constexpr (N == 4)
1547
+ return vector<T, N>{frac(x.x), frac(x.y), frac(x.z), frac(x.w)};
1548
+ }
1549
+
1550
+ /// lerp
1551
+ template<floating_point T, int N>
1552
+ [[nodiscard]] constexpr vector<T, N> lerp(const vector<T, N>& x, const vector<T, N>& y, const vector<T, N>& s)
1553
+ {
1554
+ if constexpr (N == 1)
1555
+ return vector<T, N>{lerp(x.x, y.x, s.x)};
1556
+ else if constexpr (N == 2)
1557
+ return vector<T, N>{lerp(x.x, y.x, s.x), lerp(x.y, y.y, s.y)};
1558
+ else if constexpr (N == 3)
1559
+ return vector<T, N>{lerp(x.x, y.x, s.x), lerp(x.y, y.y, s.y), lerp(x.z, y.z, s.z)};
1560
+ else if constexpr (N == 4)
1561
+ return vector<T, N>{lerp(x.x, y.x, s.x), lerp(x.y, y.y, s.y), lerp(x.z, y.z, s.z), lerp(x.w, y.w, s.w)};
1562
+ }
1563
+
1564
+ /// rcp
1565
+ template<floating_point T, int N>
1566
+ [[nodiscard]] constexpr vector<T, N> rcp(const vector<T, N>& x)
1567
+ {
1568
+ if constexpr (N == 1)
1569
+ return vector<T, N>{rcp(x.x)};
1570
+ else if constexpr (N == 2)
1571
+ return vector<T, N>{rcp(x.x), rcp(x.y)};
1572
+ else if constexpr (N == 3)
1573
+ return vector<T, N>{rcp(x.x), rcp(x.y), rcp(x.z)};
1574
+ else if constexpr (N == 4)
1575
+ return vector<T, N>{rcp(x.x), rcp(x.y), rcp(x.z), rcp(x.w)};
1576
+ }
1577
+
1578
+ /// saturate
1579
+ template<floating_point T, int N>
1580
+ [[nodiscard]] constexpr vector<T, N> saturate(const vector<T, N>& x)
1581
+ {
1582
+ if constexpr (N == 1)
1583
+ return vector<T, N>{saturate(x.x)};
1584
+ else if constexpr (N == 2)
1585
+ return vector<T, N>{saturate(x.x), saturate(x.y)};
1586
+ else if constexpr (N == 3)
1587
+ return vector<T, N>{saturate(x.x), saturate(x.y), saturate(x.z)};
1588
+ else if constexpr (N == 4)
1589
+ return vector<T, N>{saturate(x.x), saturate(x.y), saturate(x.z), saturate(x.w)};
1590
+ }
1591
+
1592
+ /// smoothstep
1593
+ template<floating_point T, int N>
1594
+ [[nodiscard]] constexpr vector<T, N> smoothstep(const vector<T, N>& min_, const vector<T, N>& max_, const vector<T, N>& x)
1595
+ {
1596
+ if constexpr (N == 1)
1597
+ return vector<T, N>{smoothstep(min_.x, max_.x, x.x)};
1598
+ else if constexpr (N == 2)
1599
+ return vector<T, N>{smoothstep(min_.x, max_.x, x.x), smoothstep(min_.y, max_.y, x.y)};
1600
+ else if constexpr (N == 3)
1601
+ return vector<T, N>{smoothstep(min_.x, max_.x, x.x), smoothstep(min_.y, max_.y, x.y), smoothstep(min_.z, max_.z, x.z)};
1602
+ else if constexpr (N == 4)
1603
+ return vector<T, N>{smoothstep(min_.x, max_.x, x.x), smoothstep(min_.y, max_.y, x.y), smoothstep(min_.z, max_.z, x.z), smoothstep(min_.w, max_.w, x.w)};
1604
+ }
1605
+
1606
+ /// step
1607
+ template<floating_point T, int N>
1608
+ [[nodiscard]] constexpr vector<T, N> step(const vector<T, N>& x, const vector<T, N>& y)
1609
+ {
1610
+ if constexpr (N == 1)
1611
+ return vector<T, N>{step(x.x, y.x)};
1612
+ else if constexpr (N == 2)
1613
+ return vector<T, N>{step(x.x, y.x), step(x.y, y.y)};
1614
+ else if constexpr (N == 3)
1615
+ return vector<T, N>{step(x.x, y.x), step(x.y, y.y), step(x.z, y.z)};
1616
+ else if constexpr (N == 4)
1617
+ return vector<T, N>{step(x.x, y.x), step(x.y, y.y), step(x.z, y.z), step(x.w, y.w)};
1618
+ }
1619
+
1620
+ /* <<<PYMACROEND>>> */
1621
+ // clang-format on
1622
+
1623
+ // ----------------------------------------------------------------------------
1624
+ // Conversion
1625
+ // ----------------------------------------------------------------------------
1626
+
1627
+ [[nodiscard]] inline float2 f16tof32(const uint2& value) noexcept
1628
+ {
1629
+ return float2{f16tof32(value.x), f16tof32(value.y)};
1630
+ }
1631
+
1632
+ [[nodiscard]] inline float3 f16tof32(const uint3& value) noexcept
1633
+ {
1634
+ return float3{f16tof32(value.x), f16tof32(value.y), f16tof32(value.z)};
1635
+ }
1636
+
1637
+ [[nodiscard]] inline float4 f16tof32(const uint4& value) noexcept
1638
+ {
1639
+ return float4{f16tof32(value.x), f16tof32(value.y), f16tof32(value.z), f16tof32(value.w)};
1640
+ }
1641
+
1642
+ [[nodiscard]] inline uint2 f32tof16(const float2& value) noexcept
1643
+ {
1644
+ return uint2{f32tof16(value.x), f32tof16(value.y)};
1645
+ }
1646
+
1647
+ [[nodiscard]] inline uint3 f32tof16(const float3& value) noexcept
1648
+ {
1649
+ return uint3{f32tof16(value.x), f32tof16(value.y), f32tof16(value.z)};
1650
+ }
1651
+
1652
+ [[nodiscard]] inline uint4 f32tof16(const float4& value) noexcept
1653
+ {
1654
+ return uint4{f32tof16(value.x), f32tof16(value.y), f32tof16(value.z), f32tof16(value.w)};
1655
+ }
1656
+
1657
+ [[nodiscard]] inline uint2 asuint(const float2& value) noexcept
1658
+ {
1659
+ return uint2(asuint(value.x), asuint(value.y));
1660
+ }
1661
+
1662
+ [[nodiscard]] inline uint3 asuint(const float3& value) noexcept
1663
+ {
1664
+ return uint3(asuint(value.x), asuint(value.y), asuint(value.z));
1665
+ }
1666
+
1667
+ [[nodiscard]] inline uint4 asuint(const float4& value) noexcept
1668
+ {
1669
+ return uint4(asuint(value.x), asuint(value.y), asuint(value.z), asuint(value.w));
1670
+ }
1671
+
1672
+
1673
+ // TODO(@skallweit) should we have implicit scalar -> vector conversion?
1674
+ template<floating_point T, int N>
1675
+ [[nodiscard]] constexpr vector<T, N> lerp(const vector<T, N>& a, const vector<T, N>& b, const T& s)
1676
+ {
1677
+ if constexpr (N == 1)
1678
+ return vector<T, N>{lerp(a.x, b.x, s)};
1679
+ else if constexpr (N == 2)
1680
+ return vector<T, N>{lerp(a.x, b.x, s), lerp(a.y, b.y, s)};
1681
+ else if constexpr (N == 3)
1682
+ return vector<T, N>{lerp(a.x, b.x, s), lerp(a.y, b.y, s), lerp(a.z, b.z, s)};
1683
+ else if constexpr (N == 4)
1684
+ return vector<T, N>{lerp(a.x, b.x, s), lerp(a.y, b.y, s), lerp(a.z, b.z, s), lerp(a.w, b.w, s)};
1685
+ }
1686
+
1687
+ /// dot
1688
+ template<typename T, int N>
1689
+ [[nodiscard]] constexpr T dot(const vector<T, N>& lhs, const vector<T, N>& rhs)
1690
+ {
1691
+ T result = lhs.x * rhs.x;
1692
+ if constexpr (N >= 2)
1693
+ result += lhs.y * rhs.y;
1694
+ if constexpr (N >= 3)
1695
+ result += lhs.z * rhs.z;
1696
+ if constexpr (N >= 4)
1697
+ result += lhs.w * rhs.w;
1698
+ return result;
1699
+ }
1700
+
1701
+ /// cross
1702
+ template<typename T>
1703
+ [[nodiscard]] constexpr vector<T, 3> cross(const vector<T, 3>& lhs, const vector<T, 3>& rhs)
1704
+ {
1705
+ return vector<T, 3>(lhs.y * rhs.z - lhs.z * rhs.y, lhs.z * rhs.x - lhs.x * rhs.z, lhs.x * rhs.y - lhs.y * rhs.x);
1706
+ }
1707
+
1708
+ /// length
1709
+ template<floating_point T, int N>
1710
+ [[nodiscard]] constexpr T length(const vector<T, N>& v)
1711
+ {
1712
+ return sqrt(dot(v, v));
1713
+ }
1714
+
1715
+ /// normalize
1716
+ template<floating_point T, int N>
1717
+ [[nodiscard]] constexpr vector<T, N> normalize(const vector<T, N>& v)
1718
+ {
1719
+ return v * rsqrt(dot(v, v));
1720
+ }
1721
+
1722
+ /// reflect
1723
+ template<floating_point T, int N>
1724
+ [[nodiscard]] constexpr vector<T, N> reflect(const vector<T, N>& v, const vector<T, N>& n)
1725
+ {
1726
+ return v - T(2) * dot(v, n) * n;
1727
+ }
1728
+
1729
+ /// Convert vector to string.
1730
+ template<typename T, int N>
1731
+ [[nodiscard]] std::string to_string(const vector<T, N>& v)
1732
+ {
1733
+ return ::fmt::format("{}", v);
1734
+ }
1735
+
1736
+ } // namespace sgl::math
1737
+
1738
+ // Specialize std::less to allow using vectors as key in std::map for example.
1739
+ template<typename T, int N>
1740
+ struct std::less<::sgl::math::vector<T, N>> {
1741
+ constexpr bool operator()(const ::sgl::math::vector<T, N>& lhs, const ::sgl::math::vector<T, N>& rhs) const
1742
+ {
1743
+ for (int i = 0; i < N; ++i)
1744
+ if (lhs[i] != rhs[i])
1745
+ return lhs[i] < rhs[i];
1746
+ return false;
1747
+ }
1748
+ };
1749
+
1750
+ template<typename T, int N>
1751
+ struct std::equal_to<::sgl::math::vector<T, N>> {
1752
+ constexpr bool operator()(const ::sgl::math::vector<T, N>& lhs, const ::sgl::math::vector<T, N>& rhs) const
1753
+ {
1754
+ for (int i = 0; i < N; ++i)
1755
+ if (lhs[i] != rhs[i])
1756
+ return false;
1757
+ return true;
1758
+ }
1759
+ };
1760
+ template<typename T, int N>
1761
+ struct std::not_equal_to<::sgl::math::vector<T, N>> {
1762
+ constexpr bool operator()(const ::sgl::math::vector<T, N>& lhs, const ::sgl::math::vector<T, N>& rhs) const
1763
+ {
1764
+ for (int i = 0; i < N; ++i)
1765
+ if (lhs[i] == rhs[i])
1766
+ return false;
1767
+ return true;
1768
+ }
1769
+ };
1770
+
1771
+ template<typename T, int N>
1772
+ struct std::hash<::sgl::math::vector<T, N>> {
1773
+ constexpr int operator()(const ::sgl::math::vector<T, N>& v) const
1774
+ {
1775
+ size_t result = 0;
1776
+ for (int i = 0; i < N; ++i)
1777
+ result ^= std::hash<T>()(v[i]) + 0x9e3779b9 + (result << 6) + (result >> 2);
1778
+ return result;
1779
+ }
1780
+ };
1781
+
1782
+ /// Vector string formatter.
1783
+ template<typename T, int N>
1784
+ struct fmt::formatter<sgl::math::vector<T, N>> : formatter<T> {
1785
+ template<typename FormatContext>
1786
+ auto format(const sgl::math::vector<T, N>& v, FormatContext& ctx) const
1787
+ {
1788
+ auto out = ctx.out();
1789
+ for (int i = 0; i < N; ++i) {
1790
+ out = ::fmt::format_to(out, "{}", (i == 0) ? "{" : ", ");
1791
+ out = formatter<T>::format(v[i], ctx);
1792
+ }
1793
+ out = ::fmt::format_to(out, "}}");
1794
+ return out;
1795
+ }
1796
+ };