Source browser
detail/math.hpp
Read the complete file below or download its original bytes. Line numbers provide stable links to a declaration or processing step.
File fingerprint
1/** @file math.hpp
2 * @brief GLSL-compatible scalar, vector and matrix operations for C++11.
3 *
4 * Vectors provide x/y/z/w component fields, indexed access, and writable
5 * swizzles. Color and texture-coordinate aliases are accessor functions in
6 * ordinary C++ code. Matrices use GLSL column-major order. The same types and
7 * functions are available to generated CPU kernels and application code.
8 *
9 * Floating-point precision and exceptional values depend on the implementation.
10 * Normalize nonzero vectors, invert nonsingular matrices and use valid shift
11 * counts. Keep signed arithmetic within its representable range and use
12 * nonnegative signed operands for left shifts to follow portable C++ rules.
13 * Resource element layout is defined by the buffer and image APIs separately.
14 */
15#ifndef SHDR_DETAIL_MATH_HPP // Include this math layer only once.
16#define SHDR_DETAIL_MATH_HPP // Remember that the math layer is available.
17#include <cmath> // Use the standard scalar math functions.
18#include <cstddef> // Use portable size types.
19#include <cstdint> // Use exact-width GLSL integer types.
20#include <cstring> // Copy bit patterns through byte storage.
21#include <initializer_list> // Accept ordinary C++ brace lists.
22#include <limits> // Query numeric limits and quiet NaNs.
23#include <ostream> // Support readable vector and matrix output.
24#include <stdexcept> // Report invalid array initializers.
25#include <type_traits> // Choose only compatible template overloads.
26namespace shdr { // Keep these names inside the shdr namespace.
27namespace glsl { // Keep these names inside the glsl namespace.
28/** @brief GLSL's portable 32-bit unsigned scalar spelling. */
29typedef std::uint32_t uint; // Use a portable 32-bit unsigned scalar.
30template <class T, std::size_t N> class vec; // Store a fixed-size vector with named component fields.
31template <class T, std::size_t N> class array; // Store a fixed number of values of one element type.
32template <class T, std::size_t N, std::size_t... I> class swizzle_ref; // Describe a component selection that refers to a vector.
33template <class T, std::size_t C, std::size_t R> class mat; // Describe a matrix by its scalar type and dimensions.
34namespace detail { // Keep these names inside the detail namespace.
35template <class T, std::size_t N> struct storage; // Choose named storage for the vector dimension.
36template <class T> struct storage<T, 2> { // Choose named storage for the vector dimension.
37 T x, y; // Store the named vector components in order.
38 T& at(std::size_t i) { // Select the named component matching this index.
39 return i == 0 ? x : y; // Select the named field for this valid component index.
40 } // Finish the at operation.
41 const T& at(std::size_t i) const { // Select the named component matching this index.
42 return i == 0 ? x : y; // Select the named field for this valid component index.
43 } // Finish the at operation.
44}; // Finish the storage type description.
45template <class T> struct storage<T, 3> { // Choose named storage for the vector dimension.
46 T x, y, z; // Store the named vector components in order.
47 T& at(std::size_t i) { // Select the named component matching this index.
48 return i == 0 ? x : (i == 1 ? y : z); // Select the named field for this valid component index.
49 } // Finish the at operation.
50 const T& at(std::size_t i) const { // Select the named component matching this index.
51 return i == 0 ? x : (i == 1 ? y : z); // Select the named field for this valid component index.
52 } // Finish the at operation.
53}; // Finish the storage type description.
54template <class T> struct storage<T, 4> { // Choose named storage for the vector dimension.
55 T x, y, z, w; // Store the named vector components in order.
56 T& at(std::size_t i) { // Select the named component matching this index.
57 return i == 0 ? x : (i == 1 ? y : (i == 2 ? z : w)); // Select the named field for this valid component index.
58 } // Finish the at operation.
59 const T& at(std::size_t i) const { // Select the named component matching this index.
60 return i == 0 ? x : (i == 1 ? y : (i == 2 ? z : w)); // Select the named field for this valid component index.
61 } // Finish the at operation.
62}; // Finish the storage type description.
63template <class A> struct shape { // Describe an ordinary scalar input.
64 typedef A scalar; // Keep the chosen component type for the calculation.
65 static const std::size_t size = 1; // Treat a scalar as one component.
66 static const bool vector = false; // Keep this input out of vector-only overloads.
67 static const bool valid = std::is_arithmetic<A>::value; // Record whether componentwise arithmetic accepts this shape.
68}; // Finish the shape type description.
69template <class T, std::size_t N> struct shape<vec<T, N>> { // Describe the scalar type and size of a vector.
70 typedef T scalar; // Keep the chosen component type for the calculation.
71 static const std::size_t size = N; // Keep the fixed component count available at compile time.
72 static const bool vector = true; // Mark this input as a vector-shaped value.
73 static const bool valid = true; // Record whether componentwise arithmetic accepts this shape.
74}; // Finish the shape type description.
75template <class T, std::size_t N, std::size_t... I> struct shape<swizzle_ref<T, N, I...>> { // Describe the scalar type and size of a component selection.
76 typedef T scalar; // Keep the chosen component type for the calculation.
77 static const std::size_t size = sizeof...(I); // Count the selected vector components.
78 static const bool vector = true; // Mark this input as a vector-shaped value.
79 static const bool valid = true; // Record whether componentwise arithmetic accepts this shape.
80}; // Finish the shape type description.
81template <class A> struct traits : shape<typename std::decay<A>::type> {}; // Ignore references and const when inspecting an input type.
82template <class... A> struct count; // Count components supplied by constructor arguments.
83template <> struct count<> { // Count components supplied by constructor arguments.
84 static const std::size_t value = 0; // Start the component count at zero.
85}; // Finish the count type description.
86template <class A, class... B> struct count<A, B...> { // Count components supplied by constructor arguments.
87 static const std::size_t value = traits<A>::size + count<B...>::value; // Add this argument count to the remaining components.
88}; // Finish the count type description.
89template <class... A> struct prefix_count; // Count constructor components before the final argument.
90template <class Last> struct prefix_count<Last> { // Count constructor components before the final argument.
91 static const std::size_t value = 0; // Start the component count at zero.
92}; // Finish the prefix_count type description.
93template <class A, class B, class... Rest> struct prefix_count<A, B, Rest...> { // Count constructor components before the final argument.
94 static const std::size_t value = traits<A>::size + prefix_count<B, Rest...>::value; // Add this argument count to the remaining components.
95}; // Finish the prefix_count type description.
96template <class A> struct is_matrix : std::false_type {}; // Identify matrix types at compile time.
97template <class T, std::size_t C, std::size_t R> struct is_matrix<mat<T, C, R>> : std::true_type {}; // Identify matrix types at compile time.
98template <class T, std::size_t C, std::size_t R> struct shape<mat<T, C, R>> { // Describe a matrix separately from vector arithmetic.
99 typedef T scalar; // Keep the chosen component type for the calculation.
100 static const std::size_t size = C * R; // Count scalar entries across every matrix column.
101 static const bool vector = false; // Keep this input out of vector-only overloads.
102 static const bool valid = false; // Record whether componentwise arithmetic accepts this shape.
103}; // Finish the shape type description.
104template <class... A> struct any_matrix; // Check whether a constructor argument is a matrix.
105template <> struct any_matrix<> : std::false_type {}; // Check whether a constructor argument is a matrix.
106template <class A, class... B> // Accept the matching input types and dimensions.
107struct any_matrix<A, B...> // Describe this input or selection at compile time.
108 : std::integral_constant<bool, // Turn the component rule into a compile-time boolean.
109 is_matrix<typename std::decay<A>::type>::value || // Complete the type and dimension rule for this overload.
110 any_matrix<B...>::value> {}; // Complete the type and dimension rule for this overload.
111template <std::size_t Needle, std::size_t... I> struct contains; // Check whether the remaining index list contains an index.
112template <std::size_t Needle> struct contains<Needle> : std::false_type {}; // Check whether the remaining index list contains an index.
113template <std::size_t Needle, std::size_t A, std::size_t... I> // Accept the matching input types and dimensions.
114struct contains<Needle, A, I...> // Describe this input or selection at compile time.
115 : std::integral_constant<bool, Needle == A || contains<Needle, I...>::value> {}; // Turn the component rule into a compile-time boolean.
116template <std::size_t... I> struct unique; // Check that selected component indices are distinct.
117template <> struct unique<> : std::true_type {}; // Check that selected component indices are distinct.
118template <std::size_t A, std::size_t... I> // Accept the matching input types and dimensions.
119struct unique<A, I...> // Describe this input or selection at compile time.
120 : std::integral_constant<bool, !contains<A, I...>::value && unique<I...>::value> {}; // Turn the component rule into a compile-time boolean.
121template <class A> struct writable_shape : std::false_type {}; // Identify vector selections that can receive values.
122template <class T, std::size_t N> struct writable_shape<vec<T, N>> : std::true_type {}; // Describe the scalar type and size of a vector.
123template <class T, std::size_t N, std::size_t... I> // Accept the matching input types and dimensions.
124struct writable_shape<swizzle_ref<T, N, I...>> : unique<I...> {}; // Describe this input or selection at compile time.
125template <class A> // Accept the matching input types and dimensions.
126struct writable // Describe this input or selection at compile time.
127 : std::integral_constant<bool, // Turn the component rule into a compile-time boolean.
128 writable_shape<typename std::decay<A>::type>::value && // Complete the type and dimension rule for this overload.
129 !std::is_const<typename std::remove_reference<A>::type>::value> {}; // Complete the type and dimension rule for this overload.
130template <std::size_t N, std::size_t... I> struct in_range; // Check that every selected index fits the vector.
131template <std::size_t N> struct in_range<N> : std::true_type {}; // Check that every selected index fits the vector.
132template <std::size_t N, std::size_t A, std::size_t... I> // Accept the matching input types and dimensions.
133struct in_range<N, A, I...> : std::integral_constant<bool, // Check this index and the remaining selected indices.
134 A < N && in_range<N, I...>::value> {}; // Require every selected component index to fit the vector.
135template <class A> // Accept the matching input types and dimensions.
136typename std::enable_if<!traits<A>::vector, typename traits<A>::scalar>::type // Enable this overload only for compatible input types.
137component(const A& a, std::size_t) { // Read the requested scalar or vector component.
138 return a; // Return the scalar unchanged.
139} // Finish the component operation.
140template <class A> // Accept the matching input types and dimensions.
141typename std::enable_if<traits<A>::vector, typename traits<A>::scalar>::type // Enable this overload only for compatible input types.
142component(const A& a, std::size_t i) { // Read the requested scalar or vector component.
143 return a[i]; // Read the requested scalar or vector component.
144} // Finish the component operation.
145template <class A, class B> struct binary { // Choose compatible componentwise operand shapes.
146 static const bool valid = // Record whether componentwise arithmetic accepts this shape.
147 traits<A>::valid && traits<B>::valid && (traits<A>::vector || traits<B>::vector) && // Complete the type and dimension rule for this overload.
148 (!traits<A>::vector || !traits<B>::vector || traits<A>::size == traits<B>::size); // Require equal lengths when both operands are vectors.
149 typedef typename std::conditional<traits<A>::vector, // Name the type selected for this math result.
150 typename traits<A>::scalar, // Preserve the selected component type and result shape.
151 typename traits<B>::scalar>::type scalar; // Preserve the selected component type and result shape.
152 static const std::size_t size = traits<A>::vector ? traits<A>::size : traits<B>::size; // Record the compile-time component rule.
153 typedef vec<scalar, size> result; // Name the vector type produced by this operation.
154}; // Finish the binary type description.
155template <class A> struct result { // Choose the value type for this expression result.
156 typedef typename std::conditional<traits<A>::vector, // Name the type selected for this math result.
157 vec<typename traits<A>::scalar, traits<A>::size>, // Preserve the selected component type and result shape.
158 typename traits<A>::scalar>::type type; // Preserve the selected component type and result shape.
159}; // Finish the result type description.
160template <class T, class U> // Accept the matching input types and dimensions.
161typename std::enable_if<std::is_arithmetic<U>::value>::type // Enable this overload only for compatible input types.
162append(T* target, std::size_t& n, const U& a) { // Append the next argument to the flat component list.
163 target[n++] = static_cast<T>(a); // Append this component and advance the destination position.
164} // Finish the append operation.
165template <class T, class U, std::size_t N> // Accept the matching input types and dimensions.
166void append(T* target, std::size_t& n, const vec<U, N>& a) { // Append constructor components in their original order.
167 for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
168 target[n++] = static_cast<T>(a[i]); // Append this component and advance the destination position.
169} // Finish the append operation.
170template <class T, class U, std::size_t N, std::size_t... I> // Accept the matching input types and dimensions.
171void append(T* target, std::size_t& n, const swizzle_ref<U, N, I...>& a) { // Append constructor components in their original order.
172 for (std::size_t i = 0; i < sizeof...(I); ++i) // Visit each component needed by this calculation.
173 target[n++] = static_cast<T>(a[i]); // Append this component and advance the destination position.
174} // Finish the append operation.
175template <class T, class U, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
176void append(T* target, std::size_t& n, const mat<U, C, R>& a) { // Append constructor components in their original order.
177 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
178 for (std::size_t r = 0; r < R; ++r) // Visit each matrix row.
179 target[n++] = static_cast<T>(a[c][r]); // Append this component and advance the destination position.
180} // Finish the append operation.
181template <class T> void flatten(T*, std::size_t&) { // Accept the matching input types and dimensions.
182} // Finish the flatten operation.
183template <class T, class A, class... B> // Accept the matching input types and dimensions.
184void flatten(T* target, std::size_t& n, const A& a, const B&... b) { // Collect components from the remaining constructor arguments.
185 append(target, n, a); // Append the next argument to the flat component list.
186 flatten(target, n, b...); // Append the remaining arguments in order.
187} // Finish the flatten operation.
188} // namespace detail
189
190/** @brief A fixed-size array for GLSL local variables and function arguments.
191 * The size must be positive. Default construction initializes every element to
192 * its zero/default value. component construction requires exactly N elements.
193 * Copy construction and assignment copy all elements. Use length() to query
194 * the element count and operator[] to select an element with a valid index.
195 * Resource ports define buffer and uniform memory layouts separately.
196 */
197template <class T, std::size_t N> class array { // Store a fixed number of values of one element type.
198 static_assert(N > 0, "GLSL fixed arrays require a positive size"); // Require at least one fixed-array element.
199 T elements_[N]; // Keep exactly N fixed-array elements.
200
201 public: // Expose the public math operations.
202 typedef T value_type; // Expose the element type to host code and templates.
203 static const std::size_t size_value = N; // Keep the fixed component count available at compile time.
204 /** @brief Return the number of array elements. */
205 static constexpr std::size_t length() { // Record the compile-time component rule.
206 return N; // Return the fixed number of available components.
207 } // Finish the length operation.
208 /** @brief Initialize every element to its zero/default value. */
209 array() : elements_() { // Initialize fixed-array storage from the supplied values.
210 } // Finish initializing the fixed array.
211 /** @brief Construct from exactly N scalar or aggregate element values. */
212 template <class... A> // Accept the matching input types and dimensions.
213 explicit array(const A&... values) : elements_{static_cast<T>(values)...} { // Initialize fixed-array storage from the supplied values.
214 static_assert(sizeof...(A) == N, "array constructor element count mismatch"); // Require exactly one argument for each array element.
215 } // Finish initializing the fixed array.
216 /** @brief Initialize from a C++ brace list containing exactly N elements.
217 * A length mismatch throws std::invalid_argument.
218 */
219 array(std::initializer_list<T> values) : elements_() { // Initialize fixed-array storage from the supplied values.
220 if (values.size() != N) // Reject a brace list with the wrong element count.
221 throw std::invalid_argument("array initializer element count mismatch"); // Report an initializer length mismatch.
222 std::size_t i = 0; // Begin filling the first array element.
223 for (const T& value : values) // Read initializer values in their original order.
224 elements_[i++] = value; // Store the next brace-list element.
225 } // Finish initializing the fixed array.
226 /** @brief Read or modify element i. i must be less than length(). */
227 T& operator[](std::size_t i) { // Provide this arithmetic or component access overload.
228 return elements_[i]; // Return the selected component with its original reference type.
229 } // Finish this operator overload.
230 const T& operator[](std::size_t i) const { // Provide this arithmetic or component access overload.
231 return elements_[i]; // Return the selected component with its original reference type.
232 } // Finish this operator overload.
233}; // Finish the array type description.
234template <class T, std::size_t N> const std::size_t array<T, N>::size_value; // Accept the matching input types and dimensions.
235/** @brief Compare two arrays by comparing every element. */
236template <class T, std::size_t N> bool operator==(const array<T, N>& a, const array<T, N>& b) { // Accept the matching input types and dimensions.
237 for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
238 if (!(a[i] == b[i])) // Stop when corresponding components differ.
239 return false; // Report that at least one component differs.
240 return true; // Report that every required component matched.
241} // Finish this operator overload.
242/** @brief Return true when any pair of corresponding elements differs. */
243template <class T, std::size_t N> bool operator!=(const array<T, N>& a, const array<T, N>& b) { // Accept the matching input types and dimensions.
244 return !(a == b); // Return the component count or geometric length.
245} // Finish this operator overload.
246
247/** @brief A vector with two, three or four components of one scalar type.
248 * A scalar constructor fills every component. Component constructors consume
249 * scalar, vector and matrix arguments from left to right. matrices contribute
250 * columns in order. Excess components in the final argument are discarded.
251 * Vector conversion takes the first N components of a source with at least N components.
252 * Default construction initializes every component to zero. Indexing requires
253 * an index less than length().
254 */
255template <class T, std::size_t N> class vec : public detail::storage<T, N> { // Store a fixed-size vector with named component fields.
256 static_assert(N >= 2 && N <= 4, "GLSL vectors require 2 to 4 components"); // Require two, three or four vector components.
257
258 public: // Expose the public math operations.
259 typedef T value_type; // Expose the element type to host code and templates.
260 typedef T component_type; // Expose the element type to host code and templates.
261 static const std::size_t length_value = N; // Keep the fixed component count available at compile time.
262 /** @brief Return the number of vector components. */
263 static constexpr std::size_t length() { // Record the compile-time component rule.
264 return N; // Return the fixed number of available components.
265 } // Finish the length operation.
266 vec() { // Initialize vector components from the supplied values.
267 for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
268 (*this)[i] = T(); // Update the selected destination component.
269 } // Finish initializing the vector.
270 template <class U, typename std::enable_if<std::is_arithmetic<U>::value, int>::type = 0> // Accept the matching input types and dimensions.
271 explicit vec(U value) { // Initialize vector components from the supplied values.
272 for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
273 (*this)[i] = static_cast<T>(value); // Update the selected destination component.
274 } // Finish initializing the vector.
275 template <class U, std::size_t M> explicit vec(const vec<U, M>& value) { // Accept the matching input types and dimensions.
276 static_assert(M >= N, "vector conversion cannot invent components"); // Check this type or dimension requirement at compile time.
277 for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
278 (*this)[i] = static_cast<T>(value[i]); // Update the selected destination component.
279 } // Finish initializing the vector.
280 template <class U, std::size_t M, std::size_t... I> vec(const swizzle_ref<U, M, I...>& value) { // Accept the matching input types and dimensions.
281 static_assert(sizeof...(I) >= N, "swizzle conversion cannot invent components"); // Check this type or dimension requirement at compile time.
282 for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
283 (*this)[i] = static_cast<T>(value[i]); // Update the selected destination component.
284 } // Finish initializing the vector.
285 /** @brief Read matrix columns consecutively to initialize the vector. */
286 template <class U, std::size_t C, std::size_t R> explicit vec(const mat<U, C, R>& value) { // Accept the matching input types and dimensions.
287 static_assert(C * R >= N, "matrix does not provide enough vector components"); // Check this type or dimension requirement at compile time.
288 for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
289 (*this)[i] = static_cast<T>(value[i / R][i % R]); // Update the selected destination component.
290 } // Finish initializing the vector.
291 template <class A, class B, class... Rest> // Accept the matching input types and dimensions.
292 explicit vec(const A& a, const B& b, const Rest&... rest) { // Initialize vector components from the supplied values.
293 static_assert(detail::count<A, B, Rest...>::value >= N, // Require enough components to fill the destination.
294 "vector constructor has too few components"); // Explain the rejected input: vector constructor has too few components.
295 static_assert(detail::prefix_count<A, B, Rest...>::value < N, // Reject constructor arguments that would go unused.
296 "vector constructor has unused arguments"); // Explain the rejected input: vector constructor has unused arguments.
297 T values[detail::count<A, B, Rest...>::value]; // Allocate space for the supplied constructor components.
298 std::size_t n = 0; // Begin appending at the first temporary component.
299 detail::flatten(values, n, a, b, rest...); // Append the remaining arguments in order.
300 for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
301 (*this)[i] = values[i]; // Update the selected destination component.
302 } // Finish initializing the vector.
303 /** @brief Read or modify component i. */
304 T& operator[](std::size_t i) { // Provide this arithmetic or component access overload.
305 return this->at(i); // Return the selected component with its original reference type.
306 } // Finish this operator overload.
307 const T& operator[](std::size_t i) const { // Provide this arithmetic or component access overload.
308 return this->at(i); // Return the selected component with its original reference type.
309 } // Finish this operator overload.
310 /** @brief Color aliases for x/y/z/w. b and a require three and four components. */
311 T& r() { // Expose the first component through its color name.
312 return (*this)[0]; // Return the selected component with its original reference type.
313 } // Finish the r operation.
314 const T& r() const { // Expose the first component through its color name.
315 return (*this)[0]; // Return the selected component with its original reference type.
316 } // Finish the r operation.
317 T& g() { // Expose the second component through its color name.
318 return (*this)[1]; // Return the selected component with its original reference type.
319 } // Finish the g operation.
320 const T& g() const { // Expose the second component through its color name.
321 return (*this)[1]; // Return the selected component with its original reference type.
322 } // Finish the g operation.
323 T& b() { // Expose the third component through its color name.
324 static_assert(N >= 3, "b needs three components"); // Check this type or dimension requirement at compile time.
325 return (*this)[2]; // Return the selected component with its original reference type.
326 } // Finish the b operation.
327 const T& b() const { // Expose the third component through its color name.
328 static_assert(N >= 3, "b needs three components"); // Check this type or dimension requirement at compile time.
329 return (*this)[2]; // Return the selected component with its original reference type.
330 } // Finish the b operation.
331 T& a() { // Expose the fourth component through its color name.
332 static_assert(N >= 4, "a needs four components"); // Check this type or dimension requirement at compile time.
333 return (*this)[3]; // Return the selected component with its original reference type.
334 } // Finish the a operation.
335 const T& a() const { // Expose the fourth component through its color name.
336 static_assert(N >= 4, "a needs four components"); // Check this type or dimension requirement at compile time.
337 return (*this)[3]; // Return the selected component with its original reference type.
338 } // Finish the a operation.
339 /** @brief Texture-coordinate aliases for x/y/z/w. */
340 T& s() { // Expose the first texture coordinate.
341 return (*this)[0]; // Return the selected component with its original reference type.
342 } // Finish the s operation.
343 const T& s() const { // Expose the first texture coordinate.
344 return (*this)[0]; // Return the selected component with its original reference type.
345 } // Finish the s operation.
346 T& t() { // Expose the second texture coordinate.
347 return (*this)[1]; // Return the selected component with its original reference type.
348 } // Finish the t operation.
349 const T& t() const { // Expose the second texture coordinate.
350 return (*this)[1]; // Return the selected component with its original reference type.
351 } // Finish the t operation.
352 T& p() { // Expose the third texture coordinate.
353 static_assert(N >= 3, "p needs three components"); // Check this type or dimension requirement at compile time.
354 return (*this)[2]; // Return the selected component with its original reference type.
355 } // Finish the p operation.
356 const T& p() const { // Expose the third texture coordinate.
357 static_assert(N >= 3, "p needs three components"); // Check this type or dimension requirement at compile time.
358 return (*this)[2]; // Return the selected component with its original reference type.
359 } // Finish the p operation.
360 T& q() { // Expose the fourth texture coordinate.
361 static_assert(N >= 4, "q needs four components"); // Check this type or dimension requirement at compile time.
362 return (*this)[3]; // Return the selected component with its original reference type.
363 } // Finish the q operation.
364 const T& q() const { // Expose the fourth texture coordinate.
365 static_assert(N >= 4, "q needs four components"); // Check this type or dimension requirement at compile time.
366 return (*this)[3]; // Return the selected component with its original reference type.
367 } // Finish the q operation.
368 /** @brief Select one component as a scalar reference. */
369 template <std::size_t I> T& swizzle() { // Accept the matching input types and dimensions.
370 static_assert(I < N, "swizzle index out of range"); // Reject a component index outside the vector.
371 return (*this)[I]; // Return the selected component with its original reference type.
372 } // Finish the swizzle operation.
373 template <std::size_t I> const T& swizzle() const { // Accept the matching input types and dimensions.
374 static_assert(I < N, "swizzle index out of range"); // Reject a component index outside the vector.
375 return (*this)[I]; // Return the selected component with its original reference type.
376 } // Finish the swizzle operation.
377 /** @brief Select components in the requested order. writable destinations
378 * must contain unique indices. Const vectors produce an independent value.
379 */
380 template <std::size_t... I> // Accept the matching input types and dimensions.
381 typename std::enable_if<(sizeof...(I) >= 2), swizzle_ref<T, N, I...>>::type swizzle() { // Enable this overload only for compatible input types.
382 static_assert(sizeof...(I) >= 2 && sizeof...(I) <= 4, "swizzles require 2 to 4 components"); // Check this type or dimension requirement at compile time.
383 static_assert(detail::in_range<N, I...>::value, "swizzle index out of range"); // Reject a component index outside the vector.
384 return swizzle_ref<T, N, I...>(*this); // Select components in the requested order.
385 } // Finish the swizzle operation.
386 template <std::size_t... I> // Accept the matching input types and dimensions.
387 typename std::enable_if<(sizeof...(I) >= 2), vec<T, sizeof...(I)>>::type swizzle() const { // Enable this overload only for compatible input types.
388 static_assert(sizeof...(I) >= 2 && sizeof...(I) <= 4, "swizzles require 2 to 4 components"); // Check this type or dimension requirement at compile time.
389 static_assert(detail::in_range<N, I...>::value, "swizzle index out of range"); // Reject a component index outside the vector.
390 const std::size_t indices[] = {I...}; // Keep the requested component order available for indexing.
391 vec<T, sizeof...(I)> out; // Keep an independent value for the result or aliased inputs.
392 for (std::size_t j = 0; j < sizeof...(I); ++j) // Visit each component needed by this calculation.
393 out[j] = (*this)[indices[j]]; // Store the computed component in the independent result.
394 return out; // Return the completed result.
395 } // Finish the swizzle operation.
396#define SHDR_DETAIL_VEC_ASSIGN(OP) /* Generate the matching scalar and vector overloads. */ \
397 template <class A> vec& operator OP(const A & a) { /* Accept the matching input types and dimensions. */ \
398 static_assert(!detail::traits<A>::vector || detail::traits<A>::size == N, /* Require matching component counts. */ \
399 "vector dimension mismatch"); /* Explain the rejected input: vector dimension mismatch. */ \
400 T values[N]; /* Allocate space for the supplied constructor components. */ \
401 for (std::size_t i = 0; i < N; ++i) { /* Visit each component needed by this calculation. */ \
402 values[i] = static_cast<T>(detail::component(a, i)); /* Copy source components before any destination is changed. */ \
403 } /* Finish this component or matrix pass. */ \
404 for (std::size_t i = 0; i < N; ++i) { /* Visit each component needed by this calculation. */ \
405 (*this)[i] OP values[i]; /* Update the selected destination component. */ \
406 } /* Finish this component or matrix pass. */ \
407 return *this; /* Allow this update to be used in a chained expression. */ \
408 } /* Finish this operator overload. */
409 SHDR_DETAIL_VEC_ASSIGN(+=) // Provide componentwise addition.
410 SHDR_DETAIL_VEC_ASSIGN(-=) // Provide componentwise subtraction.
411 SHDR_DETAIL_VEC_ASSIGN(*=) // Provide componentwise multiplication.
412 SHDR_DETAIL_VEC_ASSIGN(/=) // Provide componentwise division.
413 SHDR_DETAIL_VEC_ASSIGN(%=) // Provide componentwise integer remainder.
414 SHDR_DETAIL_VEC_ASSIGN(&=) // Provide componentwise bitwise AND.
415 SHDR_DETAIL_VEC_ASSIGN(|=) // Provide componentwise bitwise OR.
416 SHDR_DETAIL_VEC_ASSIGN(^=) // Provide componentwise bitwise XOR.
417 SHDR_DETAIL_VEC_ASSIGN(<<=) // Provide componentwise left shifting.
418 SHDR_DETAIL_VEC_ASSIGN(>>=) // Provide componentwise right shifting.
419#undef SHDR_DETAIL_VEC_ASSIGN // Remove this local code generator macro.
420 vec& operator++() { // Provide this arithmetic or component access overload.
421 for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
422 ++(*this)[i]; // Increment this vector component.
423 return *this; // Allow this update to be used in a chained expression.
424 } // Finish this operator overload.
425 vec operator++(int) { // Provide this arithmetic or component access overload.
426 vec old(*this); // Save the vector value before incrementing or decrementing it.
427 ++*this; // Increment every vector component.
428 return old; // Return the value from before the update.
429 } // Finish this operator overload.
430 vec& operator--() { // Provide this arithmetic or component access overload.
431 for (std::size_t i = 0; i < N; ++i) // Visit each component needed by this calculation.
432 --(*this)[i]; // Decrement this vector component.
433 return *this; // Allow this update to be used in a chained expression.
434 } // Finish this operator overload.
435 vec operator--(int) { // Provide this arithmetic or component access overload.
436 vec old(*this); // Save the vector value before incrementing or decrementing it.
437 --*this; // Decrement every vector component.
438 return old; // Return the value from before the update.
439 } // Finish this operator overload.
440}; // Finish the vec type description.
441template <class T, std::size_t N> const std::size_t vec<T, N>::length_value; // Accept the matching input types and dimensions.
442
443/** @brief A component selection referencing an existing vector.
444 * Assignment evaluates all source components before writing any destination,
445 * so exchanging components of the same vector is safe. Duplicate destination
446 * indices are rejected at compile time. The vector must outlive the selection.
447 * construct a vec value to keep an independent copy.
448 */
449template <class T, std::size_t N, std::size_t... I> class swizzle_ref { // Describe a component selection that refers to a vector.
450 vec<T, N>* source_; // Refer to the vector that owns the selected components.
451
452 public: // Expose the public math operations.
453 static constexpr std::size_t length() { // Record the compile-time component rule.
454 return sizeof...(I); // Return the fixed number of available components.
455 } // Finish the length operation.
456 explicit swizzle_ref(vec<T, N>& source) : source_(&source) { // Keep a reference to the source vector.
457 } // Finish keeping the source vector reference.
458 swizzle_ref(const swizzle_ref&) = default; // Copy the reference to the same source vector.
459 T& operator[](std::size_t i) { // Provide this arithmetic or component access overload.
460 const std::size_t indices[] = {I...}; // Keep the requested component order available for indexing.
461 return (*source_)[indices[i]]; // Return the selected component with its original reference type.
462 } // Finish this operator overload.
463 const T& operator[](std::size_t i) const { // Provide this arithmetic or component access overload.
464 const std::size_t indices[] = {I...}; // Keep the requested component order available for indexing.
465 return (*source_)[indices[i]]; // Return the selected component with its original reference type.
466 } // Finish this operator overload.
467 operator vec<T, sizeof...(I)>() const { // Provide this arithmetic or component access overload.
468 return vec<T, sizeof...(I)>(*this); // Return the component count or geometric length.
469 } // Finish this operator overload.
470 swizzle_ref& operator=(const swizzle_ref& rhs) { // Provide this arithmetic or component access overload.
471 return assign(rhs); // Write through a temporary so overlapping selections remain safe.
472 } // Finish this operator overload.
473 template <class A> swizzle_ref& operator=(const A& rhs) { // Accept the matching input types and dimensions.
474 return assign(rhs); // Write through a temporary so overlapping selections remain safe.
475 } // Finish this operator overload.
476 template <class A> swizzle_ref& assign(const A& rhs) { // Accept the matching input types and dimensions.
477 static_assert(detail::unique<I...>::value, "a writable swizzle cannot repeat components"); // Prevent repeated destination components.
478 static_assert(!detail::traits<A>::vector || detail::traits<A>::size == sizeof...(I), // Require matching component counts.
479 "swizzle dimension mismatch"); // Explain the rejected input: swizzle dimension mismatch.
480 vec<T, sizeof...(I)> temp; // Keep an independent value for the result or aliased inputs.
481 for (std::size_t j = 0; j < sizeof...(I); ++j) // Visit each component needed by this calculation.
482 temp[j] = static_cast<T>(detail::component(rhs, j)); // Save this source component before writing the selection.
483 for (std::size_t j = 0; j < sizeof...(I); ++j) // Visit each component needed by this calculation.
484 (*this)[j] = temp[j]; // Update the selected destination component.
485 return *this; // Allow this update to be used in a chained expression.
486 } // Finish the assign operation.
487#define SHDR_DETAIL_SWIZZLE_ASSIGN(OP, BINARY) /* Generate the matching scalar and vector overloads. */ \
488 template <class A> swizzle_ref& operator OP(const A & rhs) { /* Accept the matching input types and dimensions. */ \
489 return assign(vec<T, sizeof...(I)>(*this) BINARY rhs); /* Write through a temporary so overlapping selections remain safe. */ \
490 } /* Finish this operator overload. */
491 SHDR_DETAIL_SWIZZLE_ASSIGN(+=, +) // Provide componentwise addition.
492 SHDR_DETAIL_SWIZZLE_ASSIGN(-=, -) // Provide componentwise subtraction.
493 SHDR_DETAIL_SWIZZLE_ASSIGN(*=, *) // Provide componentwise multiplication.
494 SHDR_DETAIL_SWIZZLE_ASSIGN(/=, /) // Provide componentwise division.
495 SHDR_DETAIL_SWIZZLE_ASSIGN(%=, %) // Provide componentwise integer remainder.
496 SHDR_DETAIL_SWIZZLE_ASSIGN(&=, &) // Provide componentwise bitwise AND.
497 SHDR_DETAIL_SWIZZLE_ASSIGN(|=, |) // Provide componentwise bitwise OR.
498 SHDR_DETAIL_SWIZZLE_ASSIGN(^=, ^) // Provide componentwise bitwise XOR.
499 SHDR_DETAIL_SWIZZLE_ASSIGN(<<=, <<) // Provide componentwise left shifting.
500 SHDR_DETAIL_SWIZZLE_ASSIGN(>>=, >>) // Provide componentwise right shifting.
501#undef SHDR_DETAIL_SWIZZLE_ASSIGN // Remove this local code generator macro.
502}; // Finish the swizzle_ref type description.
503/** @name Vector component arithmetic
504 * Vector/scalar and scalar/vector forms broadcast the scalar.
505 * Integer operators require integer components, as in GLSL.
506 * @{ */
507#define SHDR_DETAIL_VEC_BINARY(OP) /* Generate the matching scalar and vector overloads. */ \
508 template <class A, class B> /* Accept the matching input types and dimensions. */ \
509 typename std::enable_if<detail::binary<A, B>::valid, /* Enable this overload only for compatible input types. */ \
510 typename detail::binary<A, B>::result>::type /* Preserve the selected component type and result shape. */ \
511 operator OP(const A& a, const B& b) { /* Provide this arithmetic or component access overload. */ \
512 typedef typename detail::binary<A, B>::scalar T; /* Keep the chosen component type for the calculation. */ \
513 typename detail::binary<A, B>::result out; /* Allocate an independent result with the correct shape. */ \
514 for (std::size_t i = 0; i < detail::binary<A, B>::size; ++i) { /* Visit each component needed by this calculation. */ \
515 out[i] = static_cast<T>(detail::component(a, i) OP detail::component(b, i)); /* Store the computed component in the independent result. */ \
516 } /* Finish this component or matrix pass. */ \
517 return out; /* Return the completed result. */ \
518 } /* Finish this operator overload. */
519SHDR_DETAIL_VEC_BINARY(+) // Provide componentwise addition.
520SHDR_DETAIL_VEC_BINARY(-) // Provide componentwise subtraction.
521SHDR_DETAIL_VEC_BINARY(*) // Provide componentwise multiplication.
522SHDR_DETAIL_VEC_BINARY(/) // Provide componentwise division.
523SHDR_DETAIL_VEC_BINARY(%) // Provide componentwise integer remainder.
524SHDR_DETAIL_VEC_BINARY(&) // Provide componentwise bitwise AND.
525SHDR_DETAIL_VEC_BINARY(|) // Provide componentwise bitwise OR.
526SHDR_DETAIL_VEC_BINARY(^) // Provide componentwise bitwise XOR.
527SHDR_DETAIL_VEC_BINARY(<<) // Provide componentwise left shifting.
528SHDR_DETAIL_VEC_BINARY(>>) // Provide componentwise right shifting.
529#undef SHDR_DETAIL_VEC_BINARY // Remove this local code generator macro.
530template <class A> // Accept the matching input types and dimensions.
531typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
532operator-(const A& a) { // Provide this arithmetic or component access overload.
533 typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
534 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
535 out[i] = -a[i]; // Store the computed component in the independent result.
536 return out; // Return the completed result.
537} // Finish this operator overload.
538template <class A> // Accept the matching input types and dimensions.
539typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
540operator+(const A& a) { // Provide this arithmetic or component access overload.
541 return typename detail::result<A>::type(a); // Copy source components before changing the destination.
542} // Finish this operator overload.
543template <class A> // Accept the matching input types and dimensions.
544typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
545operator~(const A& a) { // Provide this arithmetic or component access overload.
546 typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
547 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
548 out[i] = ~a[i]; // Store the computed component in the independent result.
549 return out; // Return the completed result.
550} // Finish this operator overload.
551template <class A, class B> // Accept the matching input types and dimensions.
552typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector && // Enable this overload only for compatible input types.
553 detail::traits<A>::size == detail::traits<B>::size, // Complete the type and dimension rule for this overload.
554 bool>::type // Complete the type and dimension rule for this overload.
555operator==(const A& a, const B& b) { // Provide this arithmetic or component access overload.
556 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) { // Visit each component needed by this calculation.
557 if (a[i] != b[i]) // Stop when corresponding components differ.
558 return false; // Report that at least one component differs.
559 } // Finish this component or matrix pass.
560 return true; // Report that every required component matched.
561} // Finish this operator overload.
562template <class A, class B> // Accept the matching input types and dimensions.
563typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector && // Enable this overload only for compatible input types.
564 detail::traits<A>::size == detail::traits<B>::size, // Complete the type and dimension rule for this overload.
565 bool>::type // Complete the type and dimension rule for this overload.
566operator!=(const A& a, const B& b) { // Provide this arithmetic or component access overload.
567 return !(a == b); // Copy source components before changing the destination.
568} // Finish this operator overload.
569/** @} */
570typedef vec<float, 2> vec2; // Name the 2-component float vector.
571typedef vec<float, 3> vec3; // Name the 3-component float vector.
572typedef vec<float, 4> vec4; // Name the 4-component float vector.
573typedef vec<double, 2> dvec2; // Name the 2-component double vector.
574typedef vec<double, 3> dvec3; // Name the 3-component double vector.
575typedef vec<double, 4> dvec4; // Name the 4-component double vector.
576typedef vec<std::int32_t, 2> ivec2; // Name the 2-component signed integer vector.
577typedef vec<std::int32_t, 3> ivec3; // Name the 3-component signed integer vector.
578typedef vec<std::int32_t, 4> ivec4; // Name the 4-component signed integer vector.
579typedef vec<std::uint32_t, 2> uvec2; // Name the 2-component unsigned integer vector.
580typedef vec<std::uint32_t, 3> uvec3; // Name the 3-component unsigned integer vector.
581typedef vec<std::uint32_t, 4> uvec4; // Name the 4-component unsigned integer vector.
582typedef vec<bool, 2> bvec2; // Name the 2-component boolean vector.
583typedef vec<bool, 3> bvec3; // Name the 3-component boolean vector.
584typedef vec<bool, 4> bvec4; // Name the 4-component boolean vector.
585template <class T, std::size_t N> // Accept the matching input types and dimensions.
586std::ostream& operator<<(std::ostream& out, const vec<T, N>& value) { // Provide this arithmetic or component access overload.
587 out << '('; // Write the next component or separator for readable output.
588 for (std::size_t i = 0; i < N; ++i) { // Visit each component needed by this calculation.
589 if (i) // Write a separator only after the first component.
590 out << ", "; // Write the next component or separator for readable output.
591 out << value[i]; // Write the next component or separator for readable output.
592 } // Finish this component or matrix pass.
593 return out << ')'; // Finish the readable representation and return the stream.
594} // Finish this operator overload.
595
596/** @brief A floating-point matrix with C columns and R rows.
597 * A scalar constructor initializes the diagonal and sets other entries to
598 * zero. Component constructors consume scalars and vectors in column order,
599 * discarding excess components in the final argument. Matrix conversion copies
600 * the common region and fills the remaining entries with the identity matrix.
601 * Default construction initializes every component to zero.
602 */
603template <class T, std::size_t C, std::size_t R> class mat { // Describe a matrix by its scalar type and dimensions.
604 static_assert(C >= 2 && C <= 4 && R >= 2 && R <= 4, "matrix dimensions require 2 to 4"); // Require matching component counts.
605 static_assert(std::is_floating_point<T>::value, // Require floating-point components for this operation.
606 "GLSL matrices require floating point components"); // Explain the rejected input: GLSL matrices require floating point components.
607 vec<T, R> columns_[C]; // Store each matrix column as a vector.
608
609 public: // Expose the public math operations.
610 typedef T value_type; // Expose the element type to host code and templates.
611 typedef vec<T, R> column_type; // Expose the vector type used for each matrix column.
612 static const std::size_t columns = C; // Keep the matrix column count available at compile time.
613 static const std::size_t rows = R; // Keep the matrix row count available at compile time.
614 /** @brief Return the number of matrix columns. */
615 static constexpr std::size_t length() { // Record the compile-time component rule.
616 return C; // Return the fixed number of available components.
617 } // Finish the length operation.
618 mat() : columns_() { // Initialize matrix columns from the supplied values.
619 } // Finish initializing the matrix.
620 template <class U, typename std::enable_if<std::is_arithmetic<U>::value, int>::type = 0> // Accept the matching input types and dimensions.
621 explicit mat(U diagonal) : columns_() { // Initialize matrix columns from the supplied values.
622 for (std::size_t c = 0; c < C && c < R; ++c) // Visit each matrix column.
623 columns_[c][c] = static_cast<T>(diagonal); // Set this diagonal entry to the requested scalar.
624 } // Finish initializing the matrix.
625 template <class U, std::size_t A, std::size_t B> // Accept the matching input types and dimensions.
626 explicit mat(const mat<U, A, B>& other) : columns_() { // Initialize matrix columns from the supplied values.
627 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
628 for (std::size_t r = 0; r < R; ++r) // Visit each matrix row.
629 columns_[c][r] = // Copy or complete this matrix entry.
630 c < A && r < B ? static_cast<T>(other[c][r]) : (c == r ? T(1) : T(0)); // Copy the common region and use identity entries elsewhere.
631 } // Finish initializing the matrix.
632 /** @brief Construct a matrix from the components of one vector or swizzle. */
633 template <class A, typename std::enable_if<detail::traits<A>::vector, int>::type = 0> // Accept the matching input types and dimensions.
634 explicit mat(const A& value) { // Initialize matrix columns from the supplied values.
635 static_assert(detail::traits<A>::size >= C * R, // Check this type or dimension requirement at compile time.
636 "matrix constructor has too few components"); // Explain the rejected input: matrix constructor has too few components.
637 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
638 for (std::size_t r = 0; r < R; ++r) // Visit each matrix row.
639 columns_[c][r] = static_cast<T>(value[c * R + r]); // Copy the next source component in column order.
640 } // Finish initializing the matrix.
641 template <class A, class B, class... Rest> // Accept the matching input types and dimensions.
642 explicit mat(const A& a, const B& b, const Rest&... rest) { // Initialize matrix columns from the supplied values.
643 static_assert(!detail::any_matrix<A, B, Rest...>::value, // Check this type or dimension requirement at compile time.
644 "matrix conversion cannot be mixed with other arguments"); // Require the matrix to be the sole conversion argument.
645 static_assert(detail::count<A, B, Rest...>::value >= C * R, // Require enough components to fill the destination.
646 "matrix constructor has too few components"); // Explain the rejected input: matrix constructor has too few components.
647 static_assert(detail::prefix_count<A, B, Rest...>::value < C * R, // Reject constructor arguments that would go unused.
648 "matrix constructor has unused arguments"); // Explain the rejected input: matrix constructor has unused arguments.
649 T values[detail::count<A, B, Rest...>::value]; // Allocate space for the supplied constructor components.
650 std::size_t n = 0; // Begin appending at the first temporary component.
651 detail::flatten(values, n, a, b, rest...); // Append the remaining arguments in order.
652 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
653 for (std::size_t r = 0; r < R; ++r) // Visit each matrix row.
654 columns_[c][r] = values[c * R + r]; // Fill the column from the flattened constructor values.
655 } // Finish initializing the matrix.
656 /** @brief Read or modify column c. m[c][r] selects row r within that column. */
657 column_type& operator[](std::size_t c) { // Provide this arithmetic or component access overload.
658 return columns_[c]; // Return the component count or geometric length.
659 } // Finish this operator overload.
660 const column_type& operator[](std::size_t c) const { // Provide this arithmetic or component access overload.
661 return columns_[c]; // Return the component count or geometric length.
662 } // Finish this operator overload.
663 mat& operator+=(const mat& b) { // Provide this arithmetic or component access overload.
664 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
665 columns_[c] += b[c]; // Add the corresponding matrix column.
666 return *this; // Allow this update to be used in a chained expression.
667 } // Finish this operator overload.
668 mat& operator-=(const mat& b) { // Provide this arithmetic or component access overload.
669 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
670 columns_[c] -= b[c]; // Subtract the corresponding matrix column.
671 return *this; // Allow this update to be used in a chained expression.
672 } // Finish this operator overload.
673 mat& operator+=(T b) { // Provide this arithmetic or component access overload.
674 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
675 columns_[c] += b; // Add the scalar to every entry in this column.
676 return *this; // Allow this update to be used in a chained expression.
677 } // Finish this operator overload.
678 mat& operator-=(T b) { // Provide this arithmetic or component access overload.
679 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
680 columns_[c] -= b; // Subtract the scalar from every entry in this column.
681 return *this; // Allow this update to be used in a chained expression.
682 } // Finish this operator overload.
683 mat& operator*=(T b) { // Provide this arithmetic or component access overload.
684 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
685 columns_[c] *= b; // Scale this column by the scalar.
686 return *this; // Allow this update to be used in a chained expression.
687 } // Finish this operator overload.
688 mat& operator/=(T b) { // Provide this arithmetic or component access overload.
689 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
690 columns_[c] /= b; // Divide this column by the scalar.
691 return *this; // Allow this update to be used in a chained expression.
692 } // Finish this operator overload.
693 mat& operator/=(const mat& b) { // Provide this arithmetic or component access overload.
694 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
695 columns_[c] /= b[c]; // Divide corresponding entries in this column.
696 return *this; // Allow this update to be used in a chained expression.
697 } // Finish this operator overload.
698 mat& operator*=(const mat<T, C, C>& b) { // Provide this arithmetic or component access overload.
699 *this = *this * b;
700 return *this; // Allow this update to be used in a chained expression.
701 } // Finish this operator overload.
702}; // Finish the mat type description.
703template <class T, std::size_t C, std::size_t R> const std::size_t mat<T, C, R>::columns; // Accept the matching input types and dimensions.
704template <class T, std::size_t C, std::size_t R> const std::size_t mat<T, C, R>::rows; // Accept the matching input types and dimensions.
705
706/** @brief Convert a scalar, or the first component of a vector, to T.
707 * This implements GLSL scalar constructors such as float(vec3) for generated
708 * C++ kernels. Ordinary C++ callers may use scalar_cast<float>(value) directly.
709 */
710template <class T, class A> // Accept the matching input types and dimensions.
711typename std::enable_if<std::is_arithmetic<T>::value && detail::traits<A>::valid, T>::type // Enable this overload only for compatible input types.
712scalar_cast(const A& value) { // Convert the first scalar component to the requested type.
713 return static_cast<T>(detail::component(value, 0)); // Convert the first scalar component to the requested type.
714} // Finish the scalar_cast operation.
715/** @brief Convert the first column's first matrix component to scalar type T. */
716template <class T, class U, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
717typename std::enable_if<std::is_arithmetic<T>::value, T>::type // Enable this overload only for compatible input types.
718scalar_cast(const mat<U, C, R>& value) { // Convert the first scalar component to the requested type.
719 return static_cast<T>(value[0][0]); // Convert the first scalar component to the requested type.
720} // Finish the scalar_cast operation.
721/** @brief GLSL square and rectangular matrix aliases. dimensions are columns
722 * followed by rows. Float aliases are mat2..4 and mat2x2..mat4x4. double aliases
723 * use dmat. Double arithmetic is a host extension and requires a supporting
724 * desktop GLSL profile when used by shared shaders.
725 */
726#define SHDR_DETAIL_MATRIX_ALIASES(T, PREFIX) /* Generate the matching scalar and vector overloads. */ \
727 typedef mat<T, 2, 2> PREFIX##2; /* Name the type selected for this math result. */ \
728 typedef mat<T, 3, 3> PREFIX##3; /* Name the type selected for this math result. */ \
729 typedef mat<T, 4, 4> PREFIX##4; /* Name the type selected for this math result. */ \
730 typedef mat<T, 2, 2> PREFIX##2x2; /* Name the type selected for this math result. */ \
731 typedef mat<T, 2, 3> PREFIX##2x3; /* Name the type selected for this math result. */ \
732 typedef mat<T, 2, 4> PREFIX##2x4; /* Name the type selected for this math result. */ \
733 typedef mat<T, 3, 2> PREFIX##3x2; /* Name the type selected for this math result. */ \
734 typedef mat<T, 3, 3> PREFIX##3x3; /* Name the type selected for this math result. */ \
735 typedef mat<T, 3, 4> PREFIX##3x4; /* Name the type selected for this math result. */ \
736 typedef mat<T, 4, 2> PREFIX##4x2; /* Name the type selected for this math result. */ \
737 typedef mat<T, 4, 3> PREFIX##4x3; /* Name the type selected for this math result. */ \
738 typedef mat<T, 4, 4> PREFIX##4x4; /* Name the type selected for this math result. */
739SHDR_DETAIL_MATRIX_ALIASES(float, mat) // Provide the single-precision matrix names.
740SHDR_DETAIL_MATRIX_ALIASES(double, dmat) // Provide the double-precision matrix names.
741#undef SHDR_DETAIL_MATRIX_ALIASES // Remove this local code generator macro.
742template <class T, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
743mat<T, C, R> operator+(mat<T, C, R> a, const mat<T, C, R>& b) { // Keep an independent value for the result or aliased inputs.
744 return a += b; // Convert the first scalar component to the requested type.
745} // Finish this operator overload.
746template <class T, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
747mat<T, C, R> operator-(mat<T, C, R> a, const mat<T, C, R>& b) { // Keep an independent value for the result or aliased inputs.
748 return a -= b; // Convert the first scalar component to the requested type.
749} // Finish this operator overload.
750template <class T, std::size_t C, std::size_t R> mat<T, C, R> operator-(const mat<T, C, R>& a) { // Accept the matching input types and dimensions.
751 mat<T, C, R> out; // Keep an independent value for the result or aliased inputs.
752 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
753 out[c] = -a[c]; // Store the computed component in the independent result.
754 return out; // Return the completed result.
755} // Finish this operator overload.
756template <class T, std::size_t C, std::size_t R> mat<T, C, R> operator+(const mat<T, C, R>& a) { // Accept the matching input types and dimensions.
757 return a; // Return the scalar unchanged.
758} // Finish this operator overload.
759#define SHDR_DETAIL_MATRIX_SCALAR(OP, ASSIGN) /* Generate the matching scalar and vector overloads. */ \
760 template <class T, std::size_t C, std::size_t R, class U> /* Accept the matching input types and dimensions. */ \
761 typename std::enable_if<std::is_arithmetic<U>::value, mat<T, C, R>>::type operator OP( /* Enable this overload only for compatible input types. */ \
762 mat<T, C, R> a, U b) { /* Keep an independent value for the result or aliased inputs. */ \
763 return a ASSIGN static_cast<T>(b); /* Convert the first scalar component to the requested type. */ \
764 } /* Finish this declaration. */ \
765 template <class T, std::size_t C, std::size_t R, class U> /* Accept the matching input types and dimensions. */ \
766 typename std::enable_if<std::is_arithmetic<U>::value, mat<T, C, R>>::type operator OP( /* Enable this overload only for compatible input types. */ \
767 U a, const mat<T, C, R>& b) { /* Accept a scalar before the matrix operand. */ \
768 mat<T, C, R> out; /* Keep an independent value for the result or aliased inputs. */ \
769 for (std::size_t c = 0; c < C; ++c) { /* Visit each matrix column. */ \
770 out[c] = static_cast<T>(a) OP b[c]; /* Store the computed component in the independent result. */ \
771 } /* Finish this component or matrix pass. */ \
772 return out; /* Return the completed result. */ \
773 } /* Finish this declaration. */
774SHDR_DETAIL_MATRIX_SCALAR(+, +=) // Provide componentwise addition.
775SHDR_DETAIL_MATRIX_SCALAR(-, -=) // Provide componentwise subtraction.
776#undef SHDR_DETAIL_MATRIX_SCALAR // Remove this local code generator macro.
777template <class T, std::size_t C, std::size_t R, class U> // Accept the matching input types and dimensions.
778typename std::enable_if<std::is_arithmetic<U>::value, mat<T, C, R>>::type operator*(mat<T, C, R> a, // Enable this overload only for compatible input types.
779 U b) { // Accept a scalar after the matrix operand.
780 return a *= static_cast<T>(b); // Convert the first scalar component to the requested type.
781} // Finish this declaration.
782template <class T, std::size_t C, std::size_t R, class U> // Accept the matching input types and dimensions.
783typename std::enable_if<std::is_arithmetic<U>::value, mat<T, C, R>>::type // Enable this overload only for compatible input types.
784operator*(U a, mat<T, C, R> b) { // Provide this arithmetic or component access overload.
785 return b *= static_cast<T>(a); // Convert the first scalar component to the requested type.
786} // Finish this operator overload.
787template <class T, std::size_t C, std::size_t R, class U> // Accept the matching input types and dimensions.
788typename std::enable_if<std::is_arithmetic<U>::value, mat<T, C, R>>::type operator/(mat<T, C, R> a, // Enable this overload only for compatible input types.
789 U b) { // Accept a scalar after the matrix operand.
790 return a /= static_cast<T>(b); // Convert the first scalar component to the requested type.
791} // Finish this declaration.
792template <class T, std::size_t C, std::size_t R, class U> // Accept the matching input types and dimensions.
793typename std::enable_if<std::is_arithmetic<U>::value, mat<T, C, R>>::type // Enable this overload only for compatible input types.
794operator/(U a, const mat<T, C, R>& b) { // Provide this arithmetic or component access overload.
795 mat<T, C, R> out; // Keep an independent value for the result or aliased inputs.
796 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
797 out[c] = static_cast<T>(a) / b[c]; // Store the computed component in the independent result.
798 return out; // Return the completed result.
799} // Finish this operator overload.
800template <class T, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
801mat<T, C, R> operator/(const mat<T, C, R>& a, const mat<T, C, R>& b) { // Provide this arithmetic or component access overload.
802 mat<T, C, R> out; // Keep an independent value for the result or aliased inputs.
803 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
804 out[c] = a[c] / b[c]; // Store the computed component in the independent result.
805 return out; // Return the completed result.
806} // Finish this operator overload.
807template <class T, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
808bool operator==(const mat<T, C, R>& a, const mat<T, C, R>& b) { // Provide this arithmetic or component access overload.
809 for (std::size_t c = 0; c < C; ++c) { // Visit each matrix column.
810 if (a[c] != b[c]) // Handle the exceptional or boundary case before continuing.
811 return false; // Report that at least one component differs.
812 } // Finish this component or matrix pass.
813 return true; // Report that every required component matched.
814} // Finish this operator overload.
815template <class T, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
816bool operator!=(const mat<T, C, R>& a, const mat<T, C, R>& b) { // Provide this arithmetic or component access overload.
817 return !(a == b); // Convert the first scalar component to the requested type.
818} // Finish this operator overload.
819/** @brief Algebraic matrix-vector multiplication. */
820template <class T, std::size_t C, std::size_t R, class A> // Accept the matching input types and dimensions.
821typename std::enable_if<detail::traits<A>::vector && detail::traits<A>::size == C, vec<T, R>>::type // Enable this overload only for compatible input types.
822operator*(const mat<T, C, R>& a, const A& b) { // Provide this arithmetic or component access overload.
823 vec<T, R> out(T(0)); // Keep an independent value for the result or aliased inputs.
824 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
825 out += a[c] * b[c]; // Add this component product to the running total.
826 return out; // Return the completed result.
827} // Finish this operator overload.
828template <class T, std::size_t C, std::size_t R, class A> // Accept the matching input types and dimensions.
829typename std::enable_if<detail::traits<A>::vector && detail::traits<A>::size == R, vec<T, C>>::type // Enable this overload only for compatible input types.
830operator*(const A& a, const mat<T, C, R>& b) { // Provide this arithmetic or component access overload.
831 vec<T, C> out(T(0)); // Keep an independent value for the result or aliased inputs.
832 for (std::size_t c = 0; c < C; ++c) { // Visit each matrix column.
833 for (std::size_t r = 0; r < R; ++r) // Visit each matrix row.
834 out[c] += a[r] * b[c][r]; // Store the computed component in the independent result.
835 } // Finish this component or matrix pass.
836 return out; // Return the completed result.
837} // Finish this operator overload.
838/** @brief Algebraic multiplication, including nonsquare matrices. */
839template <class T, std::size_t C, std::size_t R, std::size_t K> // Accept the matching input types and dimensions.
840mat<T, K, R> operator*(const mat<T, C, R>& a, const mat<T, K, C>& b) { // Provide this arithmetic or component access overload.
841 mat<T, K, R> out; // Keep an independent value for the result or aliased inputs.
842 for (std::size_t c = 0; c < K; ++c) // Visit each matrix column.
843 out[c] = a * b[c]; // Store the computed component in the independent result.
844 return out; // Return the completed result.
845} // Finish this operator overload.
846/** @brief Exchange rows and columns, including rectangular matrices. */
847template <class T, std::size_t C, std::size_t R> mat<T, R, C> transpose(const mat<T, C, R>& a) { // Accept the matching input types and dimensions.
848 mat<T, R, C> out; // Keep an independent value for the result or aliased inputs.
849 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
850 for (std::size_t r = 0; r < R; ++r) // Visit each matrix row.
851 out[r][c] = a[c][r]; // Copy the entry to its exchanged row and column.
852 return out; // Return the completed result.
853} // Finish the transpose operation.
854/** @brief Multiply corresponding matrix components element by element. */
855template <class T, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
856mat<T, C, R> matrixCompMult(const mat<T, C, R>& a, const mat<T, C, R>& b) { // Multiply corresponding matrix entries.
857 mat<T, C, R> out; // Keep an independent value for the result or aliased inputs.
858 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
859 out[c] = a[c] * b[c]; // Store the computed component in the independent result.
860 return out; // Return the completed result.
861} // Finish the matrixCompMult operation.
862/** @brief Form a column-by-row outer product. output column j is column*row[j]. */
863template <class T, std::size_t R, std::size_t C> // Accept the matching input types and dimensions.
864mat<T, C, R> outerProduct(const vec<T, R>& column, const vec<T, C>& row) { // Keep an independent value for the result or aliased inputs.
865 mat<T, C, R> out; // Keep an independent value for the result or aliased inputs.
866 for (std::size_t c = 0; c < C; ++c) // Visit each matrix column.
867 out[c] = column * row[c]; // Store the computed component in the independent result.
868 return out; // Return the completed result.
869} // Finish the outerProduct operation.
870/** @brief Determinant using partial-pivot elimination. */
871template <class T, std::size_t N> T determinant(mat<T, N, N> a) { // Accept the matching input types and dimensions.
872 T result(1); // Begin the determinant product with multiplicative identity.
873 for (std::size_t i = 0; i < N; ++i) { // Visit each component needed by this calculation.
874 std::size_t pivot = i; // Begin with the current row as the pivot candidate.
875 for (std::size_t r = i + 1; r < N; ++r) // Visit each matrix row.
876 if (std::abs(a[i][r]) > std::abs(a[i][pivot])) // Prefer the row with the larger pivot magnitude.
877 pivot = r; // Use the stronger row for the next pivot.
878 if (a[i][pivot] == T(0)) // Detect a singular column before division.
879 return T(0); // Compute the determinant with row pivoting.
880 if (pivot != i) { // Swap rows when a better pivot was found.
881 for (std::size_t c = 0; c < N; ++c) { // Visit each matrix column.
882 T temp = a[c][i]; // Save an entry while exchanging the two rows.
883 a[c][i] = a[c][pivot]; // Update this matrix entry during row elimination or exchange.
884 a[c][pivot] = temp; // Update this matrix entry during row elimination or exchange.
885 } // Finish this component or matrix pass.
886 result = -result; // Reverse the determinant sign after a row exchange.
887 } // Finish handling this condition.
888 T diagonal = a[i][i]; // Save the pivot value before normalizing the row.
889 result *= diagonal; // Multiply the determinant by the next diagonal value.
890 for (std::size_t r = i + 1; r < N; ++r) { // Visit each matrix row.
891 T factor = a[i][r] / diagonal; // Find the amount of the pivot row to eliminate.
892 for (std::size_t c = i + 1; c < N; ++c) // Visit each matrix column.
893 a[c][r] -= factor * a[c][i]; // Update this matrix entry during row elimination or exchange.
894 } // Finish this component or matrix pass.
895 } // Finish this component or matrix pass.
896 return result; // Return the completed result.
897} // Finish the determinant operation.
898/** @brief Inverse using partial-pivot Gauss-Jordan elimination.
899 * Singular input has undefined GLSL semantics. the host returns quiet NaNs.
900 */
901template <class T, std::size_t N> mat<T, N, N> inverse(mat<T, N, N> a) { // Accept the matching input types and dimensions.
902 mat<T, N, N> out(T(1)); // Keep an independent value for the result or aliased inputs.
903 for (std::size_t i = 0; i < N; ++i) { // Visit each component needed by this calculation.
904 std::size_t pivot = i; // Begin with the current row as the pivot candidate.
905 for (std::size_t r = i + 1; r < N; ++r) // Visit each matrix row.
906 if (std::abs(a[i][r]) > std::abs(a[i][pivot])) // Prefer the row with the larger pivot magnitude.
907 pivot = r; // Use the stronger row for the next pivot.
908 if (a[i][pivot] == T(0)) { // Detect a singular column before division.
909 for (std::size_t c = 0; c < N; ++c) // Visit each matrix column.
910 out[c] = vec<T, N>(std::numeric_limits<T>::quiet_NaN()); // Store the computed component in the independent result.
911 return out; // Return the completed result.
912 } // Finish handling this condition.
913 if (pivot != i) // Swap rows when a better pivot was found.
914 for (std::size_t c = 0; c < N; ++c) { // Visit each matrix column.
915 T temp = a[c][i]; // Save an entry while exchanging the two rows.
916 a[c][i] = a[c][pivot]; // Update this matrix entry during row elimination or exchange.
917 a[c][pivot] = temp; // Update this matrix entry during row elimination or exchange.
918 temp = out[c][i]; // Save an entry while exchanging the two rows.
919 out[c][i] = out[c][pivot]; // Store the computed component in the independent result.
920 out[c][pivot] = temp; // Store the computed component in the independent result.
921 } // Finish this component or matrix pass.
922 T diagonal = a[i][i]; // Save the pivot value before normalizing the row.
923 for (std::size_t c = 0; c < N; ++c) { // Visit each matrix column.
924 a[c][i] /= diagonal; // Update this matrix entry during row elimination or exchange.
925 out[c][i] /= diagonal; // Store the computed component in the independent result.
926 } // Finish this component or matrix pass.
927 for (std::size_t r = 0; r < N; ++r) // Visit each matrix row.
928 if (r != i) { // Handle the exceptional or boundary case before continuing.
929 T factor = a[i][r]; // Find the amount of the pivot row to eliminate.
930 for (std::size_t c = 0; c < N; ++c) { // Visit each matrix column.
931 a[c][r] -= factor * a[c][i]; // Update this matrix entry during row elimination or exchange.
932 out[c][r] -= factor * out[c][i]; // Subtract the pivot-row contribution from the inverse.
933 } // Finish this component or matrix pass.
934 } // Finish handling this condition.
935 } // Finish this component or matrix pass.
936 return out; // Return the completed result.
937} // Finish the inverse operation.
938template <class T, std::size_t C, std::size_t R> // Accept the matching input types and dimensions.
939std::ostream& operator<<(std::ostream& out, const mat<T, C, R>& value) { // Provide this arithmetic or component access overload.
940 out << '['; // Write the next component or separator for readable output.
941 for (std::size_t c = 0; c < C; ++c) { // Visit each matrix column.
942 if (c) // Write a separator only after the first component.
943 out << ", "; // Write the next component or separator for readable output.
944 out << value[c]; // Write the next component or separator for readable output.
945 } // Finish this component or matrix pass.
946 return out << ']'; // Finish the readable representation and return the stream.
947} // Finish this operator overload.
948/** @name Angle, exponential and common scalar/vector math
949 * Floating-point overloads preserve their component type. Vector overloads
950 * apply each scalar operation independently, including swizzle expressions.
951 * @{ */
952#define SHDR_DETAIL_FLOAT_UNARY(NAME, EXPR) /* Generate the matching scalar and vector overloads. */ \
953 template <class T> /* Accept the matching input types and dimensions. */ \
954 typename std::enable_if<std::is_floating_point<T>::value, T>::type NAME(T x) { /* Enable this overload only for compatible input types. */ \
955 return static_cast<T>(EXPR); /* Compute the inverse with row pivoting. */ \
956 } /* Finish this generated overload. */ \
957 template <class A> /* Accept the matching input types and dimensions. */ \
958 typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type /* Enable this overload only for compatible input types. */ \
959 NAME(const A& x) { /* Start the matching math overload. */ \
960 typedef typename detail::traits<A>::scalar T; /* Keep the chosen component type for the calculation. */ \
961 static_assert(std::is_floating_point<T>::value, "floating point components required"); /* Require floating-point components for this operation. */ \
962 typename detail::result<A>::type out; /* Allocate an independent result with the correct shape. */ \
963 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) /* Visit each component needed by this calculation. */ \
964 out[i] = glsl::NAME(x[i]); /* Store the computed component in the independent result. */ \
965 return out; /* Return the completed result. */ \
966 } /* Finish this generated overload. */
967SHDR_DETAIL_FLOAT_UNARY(radians, x* T(0.01745329251994329576923690768489L)) // Convert degrees to radians for scalars and vector components.
968SHDR_DETAIL_FLOAT_UNARY(degrees, x* T(57.295779513082320876798154814105L)) // Convert radians to degrees for scalars and vector components.
969SHDR_DETAIL_FLOAT_UNARY(sin, std::sin(x)) // Compute the sine for scalars and vector components.
970SHDR_DETAIL_FLOAT_UNARY(cos, std::cos(x)) // Compute the cosine for scalars and vector components.
971SHDR_DETAIL_FLOAT_UNARY(tan, std::tan(x)) // Compute the tangent for scalars and vector components.
972SHDR_DETAIL_FLOAT_UNARY(asin, std::asin(x)) // Compute the inverse sine for scalars and vector components.
973SHDR_DETAIL_FLOAT_UNARY(acos, std::acos(x)) // Compute the inverse cosine for scalars and vector components.
974SHDR_DETAIL_FLOAT_UNARY(atan, std::atan(x)) // Compute the inverse tangent for scalars and vector components.
975SHDR_DETAIL_FLOAT_UNARY(sinh, std::sinh(x)) // Compute the hyperbolic sine for scalars and vector components.
976SHDR_DETAIL_FLOAT_UNARY(cosh, std::cosh(x)) // Compute the hyperbolic cosine for scalars and vector components.
977SHDR_DETAIL_FLOAT_UNARY(tanh, std::tanh(x)) // Compute the hyperbolic tangent for scalars and vector components.
978SHDR_DETAIL_FLOAT_UNARY(asinh, std::asinh(x)) // Compute the inverse hyperbolic sine for scalars and vector components.
979SHDR_DETAIL_FLOAT_UNARY(acosh, std::acosh(x)) // Compute the inverse hyperbolic cosine for scalars and vector components.
980SHDR_DETAIL_FLOAT_UNARY(atanh, std::atanh(x)) // Compute the inverse hyperbolic tangent for scalars and vector components.
981SHDR_DETAIL_FLOAT_UNARY(exp, std::exp(x)) // Raise e to the input power for scalars and vector components.
982SHDR_DETAIL_FLOAT_UNARY(log, std::log(x)) // Compute the natural logarithm for scalars and vector components.
983SHDR_DETAIL_FLOAT_UNARY(exp2, std::exp2(x)) // Raise two to the input power for scalars and vector components.
984SHDR_DETAIL_FLOAT_UNARY(log2, std::log2(x)) // Compute the base-two logarithm for scalars and vector components.
985SHDR_DETAIL_FLOAT_UNARY(sqrt, std::sqrt(x)) // Compute the square root for scalars and vector components.
986SHDR_DETAIL_FLOAT_UNARY(inversesqrt, T(1) / std::sqrt(x)) // Compute the reciprocal square root for scalars and vector components.
987SHDR_DETAIL_FLOAT_UNARY(floor, std::floor(x)) // Round toward negative infinity for scalars and vector components.
988SHDR_DETAIL_FLOAT_UNARY(trunc, std::trunc(x)) // Round toward zero for scalars and vector components.
989SHDR_DETAIL_FLOAT_UNARY(round, std::round(x)) // Round to the nearest integer for scalars and vector components.
990SHDR_DETAIL_FLOAT_UNARY(ceil, std::ceil(x)) // Round toward positive infinity for scalars and vector components.
991SHDR_DETAIL_FLOAT_UNARY(fract, x - std::floor(x)) // Keep the fraction above the floor for scalars and vector components.
992#undef SHDR_DETAIL_FLOAT_UNARY // Remove this local code generator macro.
993template <class T> typename std::enable_if<std::is_arithmetic<T>::value, T>::type abs(T x) { // Accept the matching input types and dimensions.
994 return x < T(0) ? -x : x; // Return a nonnegative magnitude.
995} // Finish the abs operation.
996template <class A> // Accept the matching input types and dimensions.
997typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
998abs(const A& a) { // Return a nonnegative magnitude.
999 typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1000 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1001 out[i] = glsl::abs(a[i]); // Store the computed component in the independent result.
1002 return out; // Return the completed result.
1003} // Finish the abs operation.
1004template <class T> typename std::enable_if<std::is_arithmetic<T>::value, T>::type sign(T x) { // Accept the matching input types and dimensions.
1005 return x > T(0) ? T(1) : (x < T(0) ? T(-1) : T(0)); // Return minus one, zero or one from the input sign.
1006} // Finish the sign operation.
1007template <class A> // Accept the matching input types and dimensions.
1008typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1009sign(const A& a) { // Return minus one, zero or one from the input sign.
1010 typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1011 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1012 out[i] = glsl::sign(a[i]); // Store the computed component in the independent result.
1013 return out; // Return the completed result.
1014} // Finish the sign operation.
1015/** @brief Round halfway cases to the nearest even integer, independent of the
1016 * host's floating-point rounding mode. Nonfinite inputs are preserved.
1017 */
1018template <class T> // Accept the matching input types and dimensions.
1019typename std::enable_if<std::is_floating_point<T>::value, T>::type roundEven(T x) { // Enable this overload only for compatible input types.
1020 if (!std::isfinite(x)) // Keep nonfinite inputs unchanged.
1021 return x; // Round halfway values to the nearest even integer.
1022 T lo = std::floor(x), fraction = x - lo; // Separate the lower integer from its fractional remainder.
1023 if (fraction < T(0.5)) // Choose the lower integer below the halfway point.
1024 return lo; // Round halfway values to the nearest even integer.
1025 if (fraction > T(0.5)) // Choose the upper integer above the halfway point.
1026 return lo + T(1); // Round halfway values to the nearest even integer.
1027 return std::fmod(lo, T(2)) == T(0) ? lo : lo + T(1); // Round halfway values to the nearest even integer.
1028} // Finish the roundEven operation.
1029template <class A> // Accept the matching input types and dimensions.
1030typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1031roundEven(const A& a) { // Round halfway values to the nearest even integer.
1032 typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1033 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1034 out[i] = glsl::roundEven(a[i]); // Store the computed component in the independent result.
1035 return out; // Return the completed result.
1036} // Finish the roundEven operation.
1037#define SHDR_DETAIL_MATH_BINARY(NAME, ENABLE, EXPR) /* Generate the matching scalar and vector overloads. */ \
1038 template <class T> typename std::enable_if<ENABLE, T>::type NAME(T x, T y) { /* Accept the matching input types and dimensions. */ \
1039 return static_cast<T>(EXPR); /* Round halfway values to the nearest even integer. */ \
1040 } /* Finish this generated overload. */ \
1041 template <class A, class B> /* Accept the matching input types and dimensions. */ \
1042 typename std::enable_if<detail::binary<A, B>::valid, /* Enable this overload only for compatible input types. */ \
1043 typename detail::binary<A, B>::result>::type /* Preserve the selected component type and result shape. */ \
1044 NAME(const A& a, const B& b) { /* Start the matching math overload. */ \
1045 typedef typename detail::binary<A, B>::scalar T; /* Keep the chosen component type for the calculation. */ \
1046 typename detail::binary<A, B>::result out; /* Allocate an independent result with the correct shape. */ \
1047 for (std::size_t i = 0; i < detail::binary<A, B>::size; ++i) { /* Visit each component needed by this calculation. */ \
1048 out[i] = glsl::NAME(static_cast<T>(detail::component(a, i)), /* Store the computed component in the independent result. */ \
1049 static_cast<T>(detail::component(b, i))); /* Convert the second operand component to the result type. */ \
1050 } /* Finish this component or matrix pass. */ \
1051 return out; /* Return the completed result. */ \
1052 } /* Finish this generated overload. */
1053SHDR_DETAIL_MATH_BINARY(atan, std::is_floating_point<T>::value, std::atan2(x, y)) // Compute the inverse tangent for scalars and vector components.
1054SHDR_DETAIL_MATH_BINARY(pow, std::is_floating_point<T>::value, std::pow(x, y)) // Raise each base to its exponent.
1055SHDR_DETAIL_MATH_BINARY(mod, std::is_floating_point<T>::value, x - y * std::floor(x / y)) // Use the GLSL floor-based remainder.
1056SHDR_DETAIL_MATH_BINARY(min, std::is_arithmetic<T>::value, y < x ? y : x) // Choose the smaller value.
1057SHDR_DETAIL_MATH_BINARY(max, std::is_arithmetic<T>::value, x < y ? y : x) // Choose the larger value.
1058SHDR_DETAIL_MATH_BINARY(step, std::is_floating_point<T>::value, y < x ? T(0) : T(1)) // Return zero below the edge and one otherwise.
1059#undef SHDR_DETAIL_MATH_BINARY // Remove this local code generator macro.
1060/** @brief Fused multiply-add. final rounding may differ across CPU/GPU. */
1061template <class T> // Accept the matching input types and dimensions.
1062typename std::enable_if<std::is_floating_point<T>::value, T>::type fma(T a, T b, T c) { // Enable this overload only for compatible input types.
1063 return std::fma(a, b, c); // Multiply and add with one final rounding.
1064} // Finish the fma operation.
1065template <class A, class B, class C> // Accept the matching input types and dimensions.
1066typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1067fma(const A& a, const B& b, const C& c) { // Multiply and add with one final rounding.
1068 static_assert(detail::binary<A, B>::valid && detail::binary<A, C>::valid, // Check this type or dimension requirement at compile time.
1069 "fma dimensions mismatch"); // Explain the rejected input: fma dimensions mismatch.
1070 typedef typename detail::traits<A>::scalar T; // Keep the chosen component type for the calculation.
1071 typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1072 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1073 out[i] = glsl::fma( // Store the computed component in the independent result.
1074 a[i], static_cast<T>(detail::component(b, i)), static_cast<T>(detail::component(c, i))); // Supply the matching three components to fused multiply-add.
1075 return out; // Return the completed result.
1076} // Finish the fma operation.
1077template <class T> // Accept the matching input types and dimensions.
1078typename std::enable_if<std::is_arithmetic<T>::value, T>::type clamp(T x, T lower, T upper) { // Enable this overload only for compatible input types.
1079 return glsl::min(glsl::max(x, lower), upper); // Keep a value between its lower and upper limits.
1080} // Finish the clamp operation.
1081template <class A, class B, class C> // Accept the matching input types and dimensions.
1082typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1083clamp(const A& a, const B& lower, const C& upper) { // Keep a value between its lower and upper limits.
1084 static_assert(detail::binary<A, B>::valid && detail::binary<A, C>::valid, // Check this type or dimension requirement at compile time.
1085 "clamp dimensions mismatch"); // Explain the rejected input: clamp dimensions mismatch.
1086 typedef typename detail::traits<A>::scalar T; // Keep the chosen component type for the calculation.
1087 typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1088 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1089 out[i] = glsl::clamp(a[i], // Store the computed component in the independent result.
1090 static_cast<T>(detail::component(lower, i)), // Use the matching lower bound component.
1091 static_cast<T>(detail::component(upper, i))); // Use the matching upper bound component.
1092 return out; // Return the completed result.
1093} // Finish the clamp operation.
1094template <class T, class U> // Accept the matching input types and dimensions.
1095typename std::enable_if<std::is_floating_point<T>::value && std::is_arithmetic<U>::value && // Enable this overload only for compatible input types.
1096 !std::is_same<U, bool>::value, // Complete the type and dimension rule for this overload.
1097 T>::type // Complete the type and dimension rule for this overload.
1098mix(T x, T y, U selector) { // Blend values or select one with a boolean.
1099 T a = static_cast<T>(selector); // Convert the interpolation amount to the component type.
1100 return x * (T(1) - a) + y * a; // Blend values or select one with a boolean.
1101} // Finish the mix operation.
1102template <class T, class B> // Accept the matching input types and dimensions.
1103typename std::enable_if<std::is_arithmetic<T>::value && std::is_same<B, bool>::value, T>::type // Enable this overload only for compatible input types.
1104mix(T x, T y, B a) { // Blend values or select one with a boolean.
1105 return a ? y : x; // Blend values or select one with a boolean.
1106} // Finish the mix operation.
1107template <class A, class B, class C> // Accept the matching input types and dimensions.
1108typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1109mix(const A& a, const B& b, const C& selector) { // Blend values or select one with a boolean.
1110 static_assert(detail::binary<A, B>::valid && detail::binary<A, C>::valid, // Check this type or dimension requirement at compile time.
1111 "mix dimensions mismatch"); // Explain the rejected input: mix dimensions mismatch.
1112 typedef typename detail::traits<A>::scalar T; // Keep the chosen component type for the calculation.
1113 typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1114 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1115 out[i] = glsl::mix( // Store the computed component in the independent result.
1116 a[i], static_cast<T>(detail::component(b, i)), detail::component(selector, i)); // Blend or select the matching input components.
1117 return out; // Return the completed result.
1118} // Finish the mix operation.
1119template <class T> // Accept the matching input types and dimensions.
1120typename std::enable_if<std::is_floating_point<T>::value, T>::type // Enable this overload only for compatible input types.
1121smoothstep(T lower, T upper, T x) { // Interpolate smoothly between two edges.
1122 T t = glsl::clamp((x - lower) / (upper - lower), T(0), T(1)); // Map the input into a clamped zero-to-one interval.
1123 return t * t * (T(3) - T(2) * t); // Interpolate smoothly between two edges.
1124} // Finish the smoothstep operation.
1125template <class A, class B, class C> // Accept the matching input types and dimensions.
1126typename std::enable_if<detail::traits<C>::vector, typename detail::result<C>::type>::type // Enable this overload only for compatible input types.
1127smoothstep(const A& lower, const B& upper, const C& x) { // Interpolate smoothly between two edges.
1128 static_assert(detail::binary<C, A>::valid && detail::binary<C, B>::valid, // Check this type or dimension requirement at compile time.
1129 "smoothstep dimensions mismatch"); // Explain the rejected input: smoothstep dimensions mismatch.
1130 typedef typename detail::traits<C>::scalar T; // Keep the chosen component type for the calculation.
1131 typename detail::result<C>::type out; // Allocate an independent result with the correct shape.
1132 for (std::size_t i = 0; i < detail::traits<C>::size; ++i) // Visit each component needed by this calculation.
1133 out[i] = glsl::smoothstep(static_cast<T>(detail::component(lower, i)), // Store the computed component in the independent result.
1134 static_cast<T>(detail::component(upper, i)), // Use the matching upper interpolation edge.
1135 x[i]); // Interpolate this input component between its edges.
1136 return out; // Return the completed result.
1137} // Finish the smoothstep operation.
1138template <class T> // Accept the matching input types and dimensions.
1139typename std::enable_if<std::is_floating_point<T>::value, bool>::type isnan(T x) { // Enable this overload only for compatible input types.
1140 return std::isnan(x); // Check whether the value is not a number.
1141} // Finish the isnan operation.
1142template <class T> // Accept the matching input types and dimensions.
1143typename std::enable_if<std::is_floating_point<T>::value, bool>::type isinf(T x) { // Enable this overload only for compatible input types.
1144 return std::isinf(x); // Check whether the value is infinite.
1145} // Finish the isinf operation.
1146#define SHDR_DETAIL_CLASSIFICATION(NAME) /* Generate the matching scalar and vector overloads. */ \
1147 template <class A> /* Accept the matching input types and dimensions. */ \
1148 typename std::enable_if<detail::traits<A>::vector, vec<bool, detail::traits<A>::size>>::type /* Enable this overload only for compatible input types. */ \
1149 NAME(const A& a) { /* Start the matching math overload. */ \
1150 vec<bool, detail::traits<A>::size> out; /* Keep an independent value for the result or aliased inputs. */ \
1151 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) /* Visit each component needed by this calculation. */ \
1152 out[i] = glsl::NAME(a[i]); /* Store the computed component in the independent result. */ \
1153 return out; /* Return the completed result. */ \
1154 } /* Finish this generated overload. */
1155SHDR_DETAIL_CLASSIFICATION(isnan) // Check whether the value is not a number.
1156SHDR_DETAIL_CLASSIFICATION(isinf) // Check whether the value is infinite.
1157#undef SHDR_DETAIL_CLASSIFICATION // Remove this local code generator macro.
1158template <class T> // Accept the matching input types and dimensions.
1159typename std::enable_if<std::is_floating_point<T>::value, T>::type modf(T x, T& integer) { // Enable this overload only for compatible input types.
1160 return std::modf(x, &integer); // Separate fractional and integral components.
1161} // Finish the modf operation.
1162/** @brief Split a vector into signed fractional and integer parts.
1163 * The return value contains fractional components. integer receives the
1164 * integral components. Both arguments may be swizzles, including selections
1165 * of the same vector, because the input is copied before output assignment.
1166 */
1167template <class A, class B> // Accept the matching input types and dimensions.
1168typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector, // Enable this overload only for compatible input types.
1169 typename detail::result<A>::type>::type // Preserve the selected component type and result shape.
1170modf(const A& x, B&& integer) { // Separate fractional and integral components.
1171 static_assert(detail::traits<A>::size == detail::traits<B>::size, "modf dimensions mismatch"); // Require matching component counts.
1172 static_assert( // Check this type or dimension requirement at compile time.
1173 std::is_same<typename detail::traits<A>::scalar, typename detail::traits<B>::scalar>::value, // Require the input and output component types to match.
1174 "modf component types must match"); // Explain the rejected input: modf component types must match.
1175 static_assert(detail::writable<B>::value, "modf output requires writable unique components"); // Prevent repeated destination components.
1176 typename detail::result<A>::type input(x), out, integral; // Preserve the selected component type and result shape.
1177 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1178 out[i] = glsl::modf(input[i], integral[i]); // Store the computed component in the independent result.
1179 integer = integral; // Publish all integral components after reading the input.
1180 return out; // Return the completed result.
1181} // Finish the modf operation.
1182template <class T> // Accept the matching input types and dimensions.
1183typename std::enable_if<std::is_floating_point<T>::value, T>::type frexp(T x, int& exponent) { // Enable this overload only for compatible input types.
1184 return std::frexp(x, &exponent); // Separate a significand and its binary exponent.
1185} // Finish the frexp operation.
1186/** @brief Return binary significands and write matching signed exponents.
1187 * Each nonzero component satisfies x = significand * 2^exponent. Output may be
1188 * an integer vector or a writable swizzle with matching component count.
1189 */
1190template <class A, class B> // Accept the matching input types and dimensions.
1191typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector, // Enable this overload only for compatible input types.
1192 typename detail::result<A>::type>::type // Preserve the selected component type and result shape.
1193frexp(const A& x, B&& exponent) { // Separate a significand and its binary exponent.
1194 static_assert(detail::traits<A>::size == detail::traits<B>::size, "frexp dimensions mismatch"); // Require matching component counts.
1195 static_assert(std::is_same<typename detail::traits<B>::scalar, std::int32_t>::value, // Check this type or dimension requirement at compile time.
1196 "frexp requires signed integer exponent components"); // Explain the rejected input: frexp requires signed integer exponent components.
1197 static_assert(detail::writable<B>::value, "frexp output requires writable unique components"); // Prevent repeated destination components.
1198 typename detail::result<A>::type input(x), out; // Allocate an independent result with the correct shape.
1199 vec<std::int32_t, detail::traits<A>::size> powers; // Use the selected vector or matrix shape for this value.
1200 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) { // Visit each component needed by this calculation.
1201 int e = 0; // Prepare a signed exponent for this component.
1202 out[i] = std::frexp(input[i], &e); // Store the computed component in the independent result.
1203 powers[i] = e; // Store the binary exponent for this component.
1204 } // Finish this component or matrix pass.
1205 exponent = powers; // Publish all exponents after reading the input.
1206 return out; // Return the completed result.
1207} // Finish the frexp operation.
1208template <class T> // Accept the matching input types and dimensions.
1209typename std::enable_if<std::is_floating_point<T>::value, T>::type ldexp(T x, int exponent) { // Enable this overload only for compatible input types.
1210 return std::ldexp(x, exponent); // Scale a significand by a power of two.
1211} // Finish the ldexp operation.
1212/** @brief Multiply each component by two raised to its signed integer exponent. */
1213template <class A, class B> // Accept the matching input types and dimensions.
1214typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector, // Enable this overload only for compatible input types.
1215 typename detail::result<A>::type>::type // Preserve the selected component type and result shape.
1216ldexp(const A& x, const B& exponent) { // Scale a significand by a power of two.
1217 static_assert(detail::traits<A>::size == detail::traits<B>::size, "ldexp dimensions mismatch"); // Require matching component counts.
1218 static_assert(std::is_same<typename detail::traits<B>::scalar, std::int32_t>::value, // Check this type or dimension requirement at compile time.
1219 "ldexp requires signed integer exponent components"); // Explain the rejected input: ldexp requires signed integer exponent components.
1220 typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1221 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1222 out[i] = std::ldexp(x[i], exponent[i]); // Store the computed component in the independent result.
1223 return out; // Return the completed result.
1224} // Finish the ldexp operation.
1225/** @} */
1226
1227/** @name Geometry
1228 * Geometry uses scalar dot products and GLSL's usual component formulas.
1229 * normalize requires nonzero length. Inputs to reflect, refract and faceforward
1230 * should obey GLSL's normalized-normal requirements.
1231 * @{ */
1232template <class T> // Accept the matching input types and dimensions.
1233typename std::enable_if<std::is_floating_point<T>::value, T>::type dot(T a, T b) { // Enable this overload only for compatible input types.
1234 return a * b; // Sum products of corresponding components.
1235} // Finish the dot operation.
1236template <class A, class B> // Accept the matching input types and dimensions.
1237typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector, // Enable this overload only for compatible input types.
1238 typename detail::traits<A>::scalar>::type // Preserve the selected component type and result shape.
1239dot(const A& a, const B& b) { // Sum products of corresponding components.
1240 static_assert(detail::traits<A>::size == detail::traits<B>::size, "dot dimensions mismatch"); // Require matching component counts.
1241 typedef typename detail::traits<A>::scalar T; // Keep the chosen component type for the calculation.
1242 T out(0); // Start the scalar accumulator at zero.
1243 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) { // Visit each component needed by this calculation.
1244 out += a[i] * b[i]; // Add this component product to the running total.
1245 } // Finish this component or matrix pass.
1246 return out; // Return the completed result.
1247} // Finish the dot operation.
1248template <class T> typename std::enable_if<std::is_floating_point<T>::value, T>::type length(T x) { // Accept the matching input types and dimensions.
1249 return glsl::abs(x); // Return the component count or geometric length.
1250} // Finish the length operation.
1251template <class A> // Accept the matching input types and dimensions.
1252typename std::enable_if<detail::traits<A>::vector, typename detail::traits<A>::scalar>::type // Enable this overload only for compatible input types.
1253length(const A& a) { // Return the component count or geometric length.
1254 return glsl::sqrt(glsl::dot(a, a)); // Return the component count or geometric length.
1255} // Finish the length operation.
1256template <class A, class B> auto distance(const A& a, const B& b) -> decltype(glsl::length(a - b)) { // Accept the matching input types and dimensions.
1257 return glsl::length(a - b); // Measure the length of the difference.
1258} // Finish the distance operation.
1259template <class A, class B> // Accept the matching input types and dimensions.
1260typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector && // Enable this overload only for compatible input types.
1261 detail::traits<A>::size == 3 && detail::traits<B>::size == 3, // Complete the type and dimension rule for this overload.
1262 vec<typename detail::traits<A>::scalar, 3>>::type // Preserve the selected component type and result shape.
1263cross(const A& a, const B& b) { // Compute the three-dimensional cross product.
1264 typedef typename detail::traits<A>::scalar T; // Keep the chosen component type for the calculation.
1265 return vec<T, 3>( // Compute the three-dimensional cross product.
1266 a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]); // Use the three signed two-by-two minors for the cross product.
1267} // Finish the cross operation.
1268template <class A> // Accept the matching input types and dimensions.
1269typename std::enable_if<detail::traits<A>::valid, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1270normalize(const A& a) { // Scale a nonzero value to unit length.
1271 return a / glsl::length(a); // Scale a nonzero value to unit length.
1272} // Finish the normalize operation.
1273template <class A, class B, class C> // Accept the matching input types and dimensions.
1274typename std::enable_if<detail::traits<A>::valid, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1275faceforward(const A& normal, const B& incident, const C& reference) { // Choose the normal direction facing the incident vector.
1276 return glsl::dot(reference, incident) < 0 ? normal : -normal; // Choose the normal direction facing the incident vector.
1277} // Finish the faceforward operation.
1278template <class A, class B> // Accept the matching input types and dimensions.
1279typename std::enable_if<detail::traits<A>::valid, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1280reflect(const A& incident, const B& normal) { // Reflect an incident vector around its normal.
1281 typedef typename detail::traits<A>::scalar T; // Keep the chosen component type for the calculation.
1282 return incident - T(2) * glsl::dot(normal, incident) * normal; // Reflect an incident vector around its normal.
1283} // Finish the reflect operation.
1284template <class A, class B> // Accept the matching input types and dimensions.
1285typename std::enable_if<detail::traits<A>::valid, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1286refract(const A& incident, const B& normal, typename detail::traits<A>::scalar eta) { // Refract an incident vector using the index ratio.
1287 typedef typename detail::traits<A>::scalar T; // Keep the chosen component type for the calculation.
1288 T d = glsl::dot(normal, incident); // Measure the incident component along the normal.
1289 T k = T(1) - eta * eta * (T(1) - d * d); // Compute the refraction discriminant before taking its root.
1290 return k < T(0) ? typename detail::result<A>::type(T(0)) // Refract an incident vector using the index ratio.
1291 : eta * incident - (eta * d + glsl::sqrt(k)) * normal; // Apply the transmitted-direction formula when refraction is possible.
1292} // Finish the refract operation.
1293/** @} */
1294
1295/** @name Vector relational functions
1296 * operator== compares the whole vector and returns bool. These builtins return
1297 * component masks. logicalNot is the C++ spelling of GLSL's reserved `not`.
1298 * @{ */
1299#define SHDR_DETAIL_RELATIONAL(NAME, OP) /* Generate the matching scalar and vector overloads. */ \
1300 template <class A, class B> /* Accept the matching input types and dimensions. */ \
1301 typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector, /* Enable this overload only for compatible input types. */ \
1302 vec<bool, detail::traits<A>::size>>::type /* Use the selected vector or matrix shape for this value. */ \
1303 NAME(const A& a, const B& b) { /* Start the matching math overload. */ \
1304 static_assert(detail::traits<A>::size == detail::traits<B>::size, /* Require matching component counts. */ \
1305 "relational dimensions mismatch"); /* Explain the rejected input: relational dimensions mismatch. */ \
1306 vec<bool, detail::traits<A>::size> out; /* Keep an independent value for the result or aliased inputs. */ \
1307 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) /* Visit each component needed by this calculation. */ \
1308 out[i] = a[i] OP b[i]; /* Store the computed component in the independent result. */ \
1309 return out; /* Return the completed result. */ \
1310 } /* Finish this generated overload. */
1311SHDR_DETAIL_RELATIONAL(lessThan, <) // Provide the requested component operation.
1312SHDR_DETAIL_RELATIONAL(lessThanEqual, <=) // Provide the requested component operation.
1313SHDR_DETAIL_RELATIONAL(greaterThan, >) // Provide the requested component operation.
1314SHDR_DETAIL_RELATIONAL(greaterThanEqual, >=) // Provide the requested component operation.
1315SHDR_DETAIL_RELATIONAL(equal, ==) // Provide the requested component operation.
1316SHDR_DETAIL_RELATIONAL(notEqual, !=) // Provide the requested component operation.
1317#undef SHDR_DETAIL_RELATIONAL // Remove this local code generator macro.
1318template <class A> typename std::enable_if<detail::traits<A>::vector, bool>::type any(const A& a) { // Accept the matching input types and dimensions.
1319 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1320 if (a[i]) // Handle the exceptional or boundary case before continuing.
1321 return true; // Report that every required component matched.
1322 return false; // Report that at least one component differs.
1323} // Finish the any operation.
1324template <class A> typename std::enable_if<detail::traits<A>::vector, bool>::type all(const A& a) { // Accept the matching input types and dimensions.
1325 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1326 if (!a[i]) // Handle the exceptional or boundary case before continuing.
1327 return false; // Report that at least one component differs.
1328 return true; // Report that every required component matched.
1329} // Finish the all operation.
1330template <class A> // Accept the matching input types and dimensions.
1331typename std::enable_if<detail::traits<A>::vector, vec<bool, detail::traits<A>::size>>::type // Enable this overload only for compatible input types.
1332logicalNot(const A& a) { // Invert each boolean component.
1333 vec<bool, detail::traits<A>::size> out; // Keep an independent value for the result or aliased inputs.
1334 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1335 out[i] = !a[i]; // Store the computed component in the independent result.
1336 return out; // Return the completed result.
1337} // Finish the logicalNot operation.
1338template <class A> // Accept the matching input types and dimensions.
1339typename std::enable_if<detail::traits<A>::vector, vec<bool, detail::traits<A>::size>>::type // Enable this overload only for compatible input types.
1340_not(const A& a) { // Start the matching math overload.
1341 return glsl::logicalNot(a); // Invert each boolean component.
1342} // Finish the _not operation.
1343/** @} */
1344/** @name 32-bit bit operations
1345 * Reinterpretation uses memcpy and requires IEEE binary32 floats and 32-bit
1346 * integers. Bitfield ranges must satisfy 0 <= offset,bits and offset+bits<=32.
1347 * The 64-bit host intermediates in extended multiplication are never exposed
1348 * to shared shaders. Bit searches and counts return signed integer results.
1349 * @{ */
1350namespace detail { // Keep these names inside the detail namespace.
1351template <class To, class From> To bit_copy(const From& value) { // Accept the matching input types and dimensions.
1352 static_assert(sizeof(To) == sizeof(From), "bit conversion requires equal sizes"); // Check this type or dimension requirement at compile time.
1353 To out; // Allocate a destination with the same bit width.
1354 std::memcpy(&out, &value, sizeof(out)); // Copy the bits with the alias-safe byte-copy operation.
1355 return out; // Return the completed result.
1356} // Finish the bit_copy operation.
1357inline std::uint32_t bit_mask(int bits) { // Start the matching math overload.
1358 return bits == 32 ? UINT32_MAX : (bits == 0 ? 0u : (std::uint32_t(1) << bits) - 1u); // Invert each boolean component.
1359} // Finish the bit_mask operation.
1360template <class T> // Accept the matching input types and dimensions.
1361struct integer32 : std::integral_constant<bool, // Describe this input or selection at compile time.
1362 std::is_integral<T>::value && // Require integer components for the bit operation.
1363 !std::is_same<T, bool>::value && sizeof(T) == 4> {}; // Complete the type and dimension rule for this overload.
1364} // namespace detail
1365inline std::uint32_t floatBitsToUint(float x) { // Copy float bits into an unsigned integer.
1366 static_assert(sizeof(float) == 4 && std::numeric_limits<float>::is_iec559, // Check this type or dimension requirement at compile time.
1367 "IEEE binary32 float required"); // Explain the rejected input: IEEE binary32 float required.
1368 return detail::bit_copy<std::uint32_t>(x); // Copy float bits into an unsigned integer.
1369} // Finish the floatBitsToUint operation.
1370inline std::int32_t floatBitsToInt(float x) { // Copy float bits into a signed integer.
1371 return detail::bit_copy<std::int32_t>(x); // Copy float bits into a signed integer.
1372} // Finish the floatBitsToInt operation.
1373inline float uintBitsToFloat(std::uint32_t x) { // Copy unsigned integer bits into a float.
1374 return detail::bit_copy<float>(x); // Copy unsigned integer bits into a float.
1375} // Finish the uintBitsToFloat operation.
1376inline float intBitsToFloat(std::int32_t x) { // Copy signed integer bits into a float.
1377 return detail::bit_copy<float>(x); // Copy signed integer bits into a float.
1378} // Finish the intBitsToFloat operation.
1379#define SHDR_DETAIL_BIT_VECTOR(NAME, OUT_T) /* Generate the matching scalar and vector overloads. */ \
1380 template <class A> /* Accept the matching input types and dimensions. */ \
1381 typename std::enable_if<detail::traits<A>::vector, vec<OUT_T, detail::traits<A>::size>>::type /* Enable this overload only for compatible input types. */ \
1382 NAME(const A& a) { /* Start the matching math overload. */ \
1383 vec<OUT_T, detail::traits<A>::size> out; /* Keep an independent value for the result or aliased inputs. */ \
1384 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) /* Visit each component needed by this calculation. */ \
1385 out[i] = glsl::NAME(a[i]); /* Store the computed component in the independent result. */ \
1386 return out; /* Return the completed result. */ \
1387 } /* Finish this generated overload. */
1388SHDR_DETAIL_BIT_VECTOR(floatBitsToUint, std::uint32_t) // Copy float bits into an unsigned integer.
1389SHDR_DETAIL_BIT_VECTOR(floatBitsToInt, std::int32_t) // Copy float bits into a signed integer.
1390SHDR_DETAIL_BIT_VECTOR(uintBitsToFloat, float) // Copy unsigned integer bits into a float.
1391SHDR_DETAIL_BIT_VECTOR(intBitsToFloat, float) // Copy signed integer bits into a float.
1392template <class T> // Accept the matching input types and dimensions.
1393typename std::enable_if<detail::integer32<T>::value, std::int32_t>::type bitCount(T x) { // Enable this overload only for compatible input types.
1394 std::uint32_t v = static_cast<std::uint32_t>(x); // Hold the exact integer bits used by this operation.
1395 std::int32_t count = 0; // Hold the exact integer bits used by this operation.
1396 while (v) { // Continue until the remaining bits reach the required form.
1397 v &= v - 1u; // Remove the least significant set bit.
1398 ++count; // Count the set bit that was removed.
1399 } // Finish this component or matrix pass.
1400 return count; // Count the set bits in a 32-bit value.
1401} // Finish the bitCount operation.
1402template <class T> // Accept the matching input types and dimensions.
1403typename std::enable_if<detail::integer32<T>::value, std::int32_t>::type findLSB(T x) { // Enable this overload only for compatible input types.
1404 std::uint32_t v = static_cast<std::uint32_t>(x); // Hold the exact integer bits used by this operation.
1405 if (!v) // Handle the exceptional or boundary case before continuing.
1406 return -1; // Find the first set bit from the least significant end.
1407 std::int32_t position = 0; // Hold the exact integer bits used by this operation.
1408 while (!(v & 1u)) { // Continue until the remaining bits reach the required form.
1409 v >>= 1; // Move the next bit into the least significant position.
1410 ++position; // Advance the bit position being tested.
1411 } // Finish this component or matrix pass.
1412 return position; // Find the first set bit from the least significant end.
1413} // Finish the findLSB operation.
1414template <class T> // Accept the matching input types and dimensions.
1415typename std::enable_if<detail::integer32<T>::value, std::int32_t>::type findMSB(T x) { // Enable this overload only for compatible input types.
1416 std::uint32_t v = static_cast<std::uint32_t>(x); // Hold the exact integer bits used by this operation.
1417 if (std::is_signed<T>::value && x < T(0)) // Handle the exceptional or boundary case before continuing.
1418 v = ~v; // For negative values, search for the highest zero bit.
1419 std::int32_t position = -1; // Hold the exact integer bits used by this operation.
1420 while (v) { // Continue until the remaining bits reach the required form.
1421 v >>= 1; // Move the next bit into the least significant position.
1422 ++position; // Advance the bit position being tested.
1423 } // Finish this component or matrix pass.
1424 return position; // Find the highest bit that differs from the sign bit.
1425} // Finish the findMSB operation.
1426SHDR_DETAIL_BIT_VECTOR(bitCount, std::int32_t) // Count the set bits in a 32-bit value.
1427SHDR_DETAIL_BIT_VECTOR(findLSB, std::int32_t) // Find the first set bit from the least significant end.
1428SHDR_DETAIL_BIT_VECTOR(findMSB, std::int32_t) // Find the highest bit that differs from the sign bit.
1429#undef SHDR_DETAIL_BIT_VECTOR // Remove this local code generator macro.
1430template <class T> // Accept the matching input types and dimensions.
1431typename std::enable_if<detail::integer32<T>::value, T>::type bitfieldReverse(T x) { // Enable this overload only for compatible input types.
1432 std::uint32_t v = static_cast<std::uint32_t>(x), out = 0; // Hold the exact integer bits used by this operation.
1433 for (int i = 0; i < 32; ++i) { // Visit all 32 bits of the value.
1434 out = (out << 1) | (v & 1u); // Append the current low bit in reversed order.
1435 v >>= 1; // Move the next bit into the least significant position.
1436 } // Finish this component or matrix pass.
1437 return detail::bit_copy<T>(out); // Reverse all 32 bits.
1438} // Finish the bitfieldReverse operation.
1439template <class A> // Accept the matching input types and dimensions.
1440typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1441bitfieldReverse(const A& a) { // Reverse all 32 bits.
1442 typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1443 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1444 out[i] = glsl::bitfieldReverse(a[i]); // Store the computed component in the independent result.
1445 return out; // Return the completed result.
1446} // Finish the bitfieldReverse operation.
1447template <class T> // Accept the matching input types and dimensions.
1448typename std::enable_if<detail::integer32<T>::value, T>::type // Enable this overload only for compatible input types.
1449bitfieldExtract(T value, int offset, int bits) { // Extract the requested bit range.
1450 if (bits == 0 || offset < 0 || bits < 0 || offset > 32 - bits) // Handle an empty bit field separately.
1451 return T(0); // Extract the requested bit range.
1452 std::uint32_t mask = detail::bit_mask(bits), // Prepare the mask for the requested bit range.
1453 out = (static_cast<std::uint32_t>(value) >> offset) & mask; // Shift the selected field down and discard other bits.
1454 if (std::is_signed<T>::value && bits < 32 && (out & (std::uint32_t(1) << (bits - 1)))) // Handle the exceptional or boundary case before continuing.
1455 out |= ~mask; // Add the encoded field to its packed bit position.
1456 return detail::bit_copy<T>(out); // Extract the requested bit range.
1457} // Finish the bitfieldExtract operation.
1458template <class A> // Accept the matching input types and dimensions.
1459typename std::enable_if<detail::traits<A>::vector, typename detail::result<A>::type>::type // Enable this overload only for compatible input types.
1460bitfieldExtract(const A& a, int offset, int bits) { // Extract the requested bit range.
1461 typename detail::result<A>::type out; // Allocate an independent result with the correct shape.
1462 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1463 out[i] = glsl::bitfieldExtract(a[i], offset, bits); // Store the computed component in the independent result.
1464 return out; // Return the completed result.
1465} // Finish the bitfieldExtract operation.
1466template <class T> // Accept the matching input types and dimensions.
1467typename std::enable_if<detail::integer32<T>::value, T>::type // Enable this overload only for compatible input types.
1468bitfieldInsert(T base, T insert, int offset, int bits) { // Replace the requested bit range.
1469 if (bits == 0 || offset < 0 || bits < 0 || offset > 32 - bits) // Handle an empty bit field separately.
1470 return base; // Replace the requested bit range.
1471 std::uint32_t mask = detail::bit_mask(bits) << offset; // Prepare the mask for the requested bit range.
1472 std::uint32_t out = (static_cast<std::uint32_t>(base) & ~mask) | // Prepare the mask for the requested bit range.
1473 ((static_cast<std::uint32_t>(insert) << offset) & mask); // Keep only insertion bits that belong to the selected field.
1474 return detail::bit_copy<T>(out); // Replace the requested bit range.
1475} // Finish the bitfieldInsert operation.
1476template <class A, class B> // Accept the matching input types and dimensions.
1477typename std::enable_if<detail::binary<A, B>::valid, typename detail::binary<A, B>::result>::type // Enable this overload only for compatible input types.
1478bitfieldInsert(const A& base, const B& insert, int offset, int bits) { // Replace the requested bit range.
1479 typedef typename detail::binary<A, B>::scalar T; // Keep the chosen component type for the calculation.
1480 typename detail::binary<A, B>::result out; // Allocate an independent result with the correct shape.
1481 for (std::size_t i = 0; i < detail::binary<A, B>::size; ++i) // Visit each component needed by this calculation.
1482 out[i] = glsl::bitfieldInsert(static_cast<T>(detail::component(base, i)), // Store the computed component in the independent result.
1483 static_cast<T>(detail::component(insert, i)), // Use this component as the replacement bit pattern.
1484 offset, // Use the requested first bit position.
1485 bits); // Use the requested number of replacement bits.
1486 return out; // Return the completed result.
1487} // Finish the bitfieldInsert operation.
1488inline std::uint32_t uaddCarry(std::uint32_t x, std::uint32_t y, std::uint32_t& carry) { // Add unsigned values and report the carry.
1489 std::uint64_t sum = std::uint64_t(x) + y; // Use a wider integer to retain carry or product bits.
1490 carry = std::uint32_t(sum >> 32); // Publish the extra word after the input values have been copied.
1491 return std::uint32_t(sum); // Add unsigned values and report the carry.
1492} // Finish the uaddCarry operation.
1493inline std::uint32_t usubBorrow(std::uint32_t x, std::uint32_t y, std::uint32_t& borrow) { // Subtract unsigned values and report the borrow.
1494 borrow = x < y ? 1u : 0u; // Publish the extra word after the input values have been copied.
1495 return x - y; // Subtract unsigned values and report the borrow.
1496} // Finish the usubBorrow operation.
1497inline void umulExtended(std::uint32_t x, std::uint32_t y, std::uint32_t& msb, std::uint32_t& lsb) { // Split a full unsigned product into two words.
1498 std::uint64_t product = std::uint64_t(x) * y; // Use a wider integer to retain carry or product bits.
1499 msb = std::uint32_t(product >> 32); // Publish the extra word after the input values have been copied.
1500 lsb = std::uint32_t(product); // Publish the extra word after the input values have been copied.
1501} // Finish the umulExtended operation.
1502inline void imulExtended(std::int32_t x, std::int32_t y, std::int32_t& msb, std::int32_t& lsb) { // Split a full signed product into two words.
1503 std::uint64_t product = static_cast<std::uint64_t>(std::int64_t(x) * y); // Use a wider integer to retain carry or product bits.
1504 msb = detail::bit_copy<std::int32_t>(std::uint32_t(product >> 32)); // Publish the extra word after the input values have been copied.
1505 lsb = detail::bit_copy<std::int32_t>(std::uint32_t(product)); // Publish the extra word after the input values have been copied.
1506} // Finish the imulExtended operation.
1507/** @brief Add unsigned vectors modulo 2^32 and write their carry flags. */
1508template <class A, class B, class C> // Accept the matching input types and dimensions.
1509typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector && // Enable this overload only for compatible input types.
1510 detail::traits<C>::vector, // Complete the type and dimension rule for this overload.
1511 vec<std::uint32_t, detail::traits<A>::size>>::type // Use the selected vector or matrix shape for this value.
1512uaddCarry(const A& x, const B& y, C&& carry) { // Add unsigned values and report the carry.
1513 static_assert(detail::traits<A>::size == detail::traits<B>::size && // Require matching component counts.
1514 detail::traits<A>::size == detail::traits<C>::size, // Complete the type and dimension rule for this overload.
1515 "uaddCarry dimensions mismatch"); // Explain the rejected input: uaddCarry dimensions mismatch.
1516 static_assert(std::is_same<typename detail::traits<A>::scalar, std::uint32_t>::value && // Check this type or dimension requirement at compile time.
1517 std::is_same<typename detail::traits<B>::scalar, std::uint32_t>::value && // Require the second input to contain unsigned 32-bit components.
1518 std::is_same<typename detail::traits<C>::scalar, std::uint32_t>::value, // Require an unsigned 32-bit carry or borrow output.
1519 "uaddCarry requires unsigned integer components"); // Explain the rejected input: uaddCarry requires unsigned integer components.
1520 static_assert(detail::writable<C>::value, // Require distinct writable output components.
1521 "uaddCarry output requires writable unique components"); // Explain the rejected input: uaddCarry output requires writable unique components.
1522 vec<std::uint32_t, detail::traits<A>::size> a(x), b(y), out, flags; // Keep an independent value for the result or aliased inputs.
1523 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1524 out[i] = glsl::uaddCarry(a[i], b[i], flags[i]); // Store the computed component in the independent result.
1525 carry = flags; // Publish the extra word after the input values have been copied.
1526 return out; // Return the completed result.
1527} // Finish the uaddCarry operation.
1528/** @brief Subtract unsigned vectors modulo 2^32 and write their borrow flags. */
1529template <class A, class B, class C> // Accept the matching input types and dimensions.
1530typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector && // Enable this overload only for compatible input types.
1531 detail::traits<C>::vector, // Complete the type and dimension rule for this overload.
1532 vec<std::uint32_t, detail::traits<A>::size>>::type // Use the selected vector or matrix shape for this value.
1533usubBorrow(const A& x, const B& y, C&& borrow) { // Subtract unsigned values and report the borrow.
1534 static_assert(detail::traits<A>::size == detail::traits<B>::size && // Require matching component counts.
1535 detail::traits<A>::size == detail::traits<C>::size, // Complete the type and dimension rule for this overload.
1536 "usubBorrow dimensions mismatch"); // Explain the rejected input: usubBorrow dimensions mismatch.
1537 static_assert(std::is_same<typename detail::traits<A>::scalar, std::uint32_t>::value && // Check this type or dimension requirement at compile time.
1538 std::is_same<typename detail::traits<B>::scalar, std::uint32_t>::value && // Require the second input to contain unsigned 32-bit components.
1539 std::is_same<typename detail::traits<C>::scalar, std::uint32_t>::value, // Require an unsigned 32-bit carry or borrow output.
1540 "usubBorrow requires unsigned integer components"); // Explain the rejected input: usubBorrow requires unsigned integer components.
1541 static_assert(detail::writable<C>::value, // Require distinct writable output components.
1542 "usubBorrow output requires writable unique components"); // Explain the rejected input: usubBorrow output requires writable unique components.
1543 vec<std::uint32_t, detail::traits<A>::size> a(x), b(y), out, flags; // Keep an independent value for the result or aliased inputs.
1544 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) // Visit each component needed by this calculation.
1545 out[i] = glsl::usubBorrow(a[i], b[i], flags[i]); // Store the computed component in the independent result.
1546 borrow = flags; // Publish the extra word after the input values have been copied.
1547 return out; // Return the completed result.
1548} // Finish the usubBorrow operation.
1549#define SHDR_DETAIL_EXTENDED(NAME, T) /* Generate the matching scalar and vector overloads. */ \
1550 template <class A, class B, class C, class D> /* Accept the matching input types and dimensions. */ \
1551 typename std::enable_if<detail::traits<A>::vector && detail::traits<B>::vector && /* Enable this overload only for compatible input types. */ \
1552 detail::traits<C>::vector && detail::traits<D>::vector>::type /* Complete the type and dimension rule for this overload. */ \
1553 NAME(const A& x, const B& y, C&& msb, D&& lsb) { /* Start the matching math overload. */ \
1554 static_assert(detail::traits<A>::size == detail::traits<B>::size && /* Require matching component counts. */ \
1555 detail::traits<A>::size == detail::traits<C>::size && /* Complete the type and dimension rule for this overload. */ \
1556 detail::traits<A>::size == detail::traits<D>::size, /* Complete the type and dimension rule for this overload. */ \
1557 "extended multiplication dimensions mismatch"); /* Explain the rejected input: extended multiplication dimensions mismatch. */ \
1558 static_assert(std::is_same<typename detail::traits<A>::scalar, T>::value && /* Check this type or dimension requirement at compile time. */ \
1559 std::is_same<typename detail::traits<B>::scalar, T>::value && /* Require the second input to use the selected integer type. */ \
1560 std::is_same<typename detail::traits<C>::scalar, T>::value && /* Require the high output word to use the selected integer type. */ \
1561 std::is_same<typename detail::traits<D>::scalar, T>::value, /* Require the low output word to use the selected integer type. */ \
1562 "extended multiplication component types must match"); /* Explain the rejected input: extended multiplication component types must match. */ \
1563 static_assert(detail::writable<C>::value && detail::writable<D>::value, /* Require distinct writable output components. */ \
1564 "extended multiplication requires writable unique output components"); /* Explain the rejected input: extended multiplication requires writable unique output components. */ \
1565 vec<T, detail::traits<A>::size> a(x), b(y), high, low; /* Keep an independent value for the result or aliased inputs. */ \
1566 for (std::size_t i = 0; i < detail::traits<A>::size; ++i) { /* Visit each component needed by this calculation. */ \
1567 glsl::NAME(a[i], b[i], high[i], low[i]); /* Compute both words for this pair of copied components. */ \
1568 } /* Finish this component or matrix pass. */ \
1569 msb = high; /* Publish the extra word after the input values have been copied. */ \
1570 lsb = low; /* Publish the extra word after the input values have been copied. */ \
1571 } /* Finish this generated overload. */
1572SHDR_DETAIL_EXTENDED(umulExtended, std::uint32_t) // Split a full unsigned product into two words.
1573SHDR_DETAIL_EXTENDED(imulExtended, std::int32_t) // Split a full signed product into two words.
1574#undef SHDR_DETAIL_EXTENDED // Remove this local code generator macro.
1575/** @} */
1576
1577/** @name Packing
1578 * Normalized packing follows the GLSL clamp-and-round formulas. unpacking
1579 * places the least significant byte/halfword in x. Half-float encoding rounds
1580 * to nearest even and preserves infinities and a quiet-NaN representation.
1581 * @{ */
1582inline std::uint32_t packUnorm2x16(const vec2& v) { // Pack two normalized values into 16-bit fields.
1583 std::uint32_t x = std::uint32_t(std::round(glsl::clamp(v.x, 0.0f, 1.0f) * 65535.0f)); // Hold the exact integer bits used by this operation.
1584 std::uint32_t y = std::uint32_t(std::round(glsl::clamp(v.y, 0.0f, 1.0f) * 65535.0f)); // Hold the exact integer bits used by this operation.
1585 return x | (y << 16); // Pack two normalized values into 16-bit fields.
1586} // Finish the packUnorm2x16 operation.
1587inline vec2 unpackUnorm2x16(std::uint32_t p) { // Decode two unsigned normalized 16-bit fields.
1588 return vec2(float(p & 65535u), float(p >> 16)) / 65535.0f; // Decode two unsigned normalized 16-bit fields.
1589} // Finish the unpackUnorm2x16 operation.
1590inline std::uint32_t packSnorm2x16(const vec2& v) { // Pack two signed normalized values into 16-bit fields.
1591 std::int32_t x = std::int32_t(std::round(glsl::clamp(v.x, -1.0f, 1.0f) * 32767.0f)); // Hold the exact integer bits used by this operation.
1592 std::int32_t y = std::int32_t(std::round(glsl::clamp(v.y, -1.0f, 1.0f) * 32767.0f)); // Hold the exact integer bits used by this operation.
1593 return (std::uint32_t(x) & 65535u) | (std::uint32_t(y) << 16); // Pack two signed normalized values into 16-bit fields.
1594} // Finish the packSnorm2x16 operation.
1595inline vec2 unpackSnorm2x16(std::uint32_t p) { // Decode two signed normalized 16-bit fields.
1596 std::int32_t x = std::int32_t(p & 65535u), y = std::int32_t(p >> 16); // Hold the exact integer bits used by this operation.
1597 if (x & 32768) // Handle the exceptional or boundary case before continuing.
1598 x -= 65536; // Extend the stored signed field into a signed scalar.
1599 if (y & 32768) // Handle the exceptional or boundary case before continuing.
1600 y -= 65536; // Extend the stored signed field into a signed scalar.
1601 return glsl::clamp(vec2(x, y) / 32767.0f, -1.0f, 1.0f); // Decode two signed normalized 16-bit fields.
1602} // Finish the unpackSnorm2x16 operation.
1603inline std::uint32_t packUnorm4x8(const vec4& v) { // Pack four normalized values into bytes.
1604 std::uint32_t out = 0; // Hold the exact integer bits used by this operation.
1605 for (std::size_t i = 0; i < 4; ++i) // Visit each component needed by this calculation.
1606 out |= std::uint32_t(std::round(glsl::clamp(v[i], 0.0f, 1.0f) * 255.0f)) << (i * 8); // Add the encoded field to its packed bit position.
1607 return out; // Return the completed result.
1608} // Finish the packUnorm4x8 operation.
1609inline vec4 unpackUnorm4x8(std::uint32_t p) { // Decode four unsigned normalized bytes.
1610 vec4 out; // Allocate four independent unpacked components.
1611 for (std::size_t i = 0; i < 4; ++i) // Visit each component needed by this calculation.
1612 out[i] = float((p >> (i * 8)) & 255u) / 255.0f; // Store the computed component in the independent result.
1613 return out; // Return the completed result.
1614} // Finish the unpackUnorm4x8 operation.
1615inline std::uint32_t packSnorm4x8(const vec4& v) { // Pack four signed normalized values into bytes.
1616 std::uint32_t out = 0; // Hold the exact integer bits used by this operation.
1617 for (std::size_t i = 0; i < 4; ++i) // Visit each component needed by this calculation.
1618 out |= (std::uint32_t(std::int32_t(std::round(glsl::clamp(v[i], -1.0f, 1.0f) * 127.0f))) & // Add the encoded field to its packed bit position.
1619 255u) // Keep only the low byte of the signed normalized encoding.
1620 << (i * 8); // Move that byte into its component position.
1621 return out; // Return the completed result.
1622} // Finish the packSnorm4x8 operation.
1623inline vec4 unpackSnorm4x8(std::uint32_t p) { // Decode four signed normalized bytes.
1624 vec4 out; // Allocate four independent unpacked components.
1625 for (std::size_t i = 0; i < 4; ++i) { // Visit each component needed by this calculation.
1626 int v = int((p >> (i * 8)) & 255u); // Extract this byte into a signed-capable scalar.
1627 if (v & 128) // Handle the exceptional or boundary case before continuing.
1628 v -= 256; // Extend an eight-bit negative value to the scalar type.
1629 out[i] = glsl::max(float(v) / 127.0f, -1.0f); // Store the computed component in the independent result.
1630 } // Finish this component or matrix pass.
1631 return out; // Return the completed result.
1632} // Finish the unpackSnorm4x8 operation.
1633namespace detail { // Keep these names inside the detail namespace.
1634inline std::uint16_t float_to_half(float value) { // Encode an IEEE half with ties rounded to even.
1635 std::uint32_t bits = glsl::floatBitsToUint(value), sign = (bits >> 16) & 32768u; // Separate the sign and payload bits for the conversion.
1636 int exponent = int((bits >> 23) & 255u) - 127 + 15; // Translate the exponent bias to the target float format.
1637 std::uint32_t mantissa = bits & 8388607u; // Keep the floating-point significand bits for encoding.
1638 if (((bits >> 23) & 255u) == 255u) // Handle the exceptional or boundary case before continuing.
1639 return std::uint16_t(sign | 31744u | (mantissa ? 512u : 0u)); // Encode an IEEE half with ties rounded to even.
1640 if (exponent >= 31) // Select the matching half-float exponent range.
1641 return std::uint16_t(sign | 31744u); // Encode an IEEE half with ties rounded to even.
1642 if (exponent <= 0) { // Select the matching half-float exponent range.
1643 if (exponent < -10) // Select the matching half-float exponent range.
1644 return std::uint16_t(sign); // Encode an IEEE half with ties rounded to even.
1645 mantissa |= 8388608u; // Restore the implicit leading significand bit.
1646 unsigned shift = unsigned(14 - exponent); // Choose the right shift for a half-float subnormal.
1647 std::uint32_t truncated = mantissa >> shift, remainder = mantissa & ((1u << shift) - 1u), // Keep the floating-point significand bits for encoding.
1648 halfway = 1u << (shift - 1); // Identify the exact halfway rounding bit.
1649 if (remainder > halfway || (remainder == halfway && (truncated & 1u))) // Round up above halfway or for an odd halfway result.
1650 ++truncated; // Round the retained encoding to the next representable value.
1651 return std::uint16_t(sign | truncated); // Encode an IEEE half with ties rounded to even.
1652 } // Finish handling this condition.
1653 std::uint32_t truncated = (std::uint32_t(exponent) << 10) | (mantissa >> 13), // Keep the floating-point significand bits for encoding.
1654 remainder = mantissa & 8191u; // Retain the discarded low bits for the rounding decision.
1655 if (remainder > 4096u || (remainder == 4096u && (truncated & 1u))) // Round up above halfway or for an odd halfway result.
1656 ++truncated; // Round the retained encoding to the next representable value.
1657 return std::uint16_t(sign | truncated); // Encode an IEEE half with ties rounded to even.
1658} // Finish the float_to_half operation.
1659inline float half_to_float(std::uint16_t h) { // Expand an IEEE half into a float.
1660 std::uint32_t sign = (std::uint32_t(h) & 32768u) << 16, mantissa = h & 1023u; // Separate the sign and payload bits for the conversion.
1661 int exponent = (h >> 10) & 31; // Translate the exponent bias to the target float format.
1662 if (exponent == 0) { // Select the matching half-float exponent range.
1663 if (!mantissa) // Handle the exceptional or boundary case before continuing.
1664 return glsl::uintBitsToFloat(sign); // Expand an IEEE half into a float.
1665 exponent = -14; // Set the exponent for a subnormal source value.
1666 while (!(mantissa & 1024u)) { // Continue until the remaining bits reach the required form.
1667 mantissa <<= 1; // Move the first significand bit toward the normalized position.
1668 --exponent; // Adjust the exponent while normalizing the significand.
1669 } // Finish this component or matrix pass.
1670 mantissa &= 1023u; // Remove the leading bit before storing the fraction.
1671 return glsl::uintBitsToFloat(sign | (std::uint32_t(exponent + 127) << 23) | // Expand an IEEE half into a float.
1672 (mantissa << 13)); // Place the expanded significand in the float fraction field.
1673 } // Finish handling this condition.
1674 if (exponent == 31) // Select the matching half-float exponent range.
1675 return glsl::uintBitsToFloat(sign | 2139095040u | (mantissa << 13)); // Expand an IEEE half into a float.
1676 return glsl::uintBitsToFloat(sign | (std::uint32_t(exponent - 15 + 127) << 23) | // Expand an IEEE half into a float.
1677 (mantissa << 13)); // Place the expanded significand in the float fraction field.
1678} // Finish the half_to_float operation.
1679} // namespace detail
1680inline std::uint32_t packHalf2x16(const vec2& v) { // Pack two IEEE half encodings into one word.
1681 return std::uint32_t(detail::float_to_half(v.x)) | // Pack two IEEE half encodings into one word.
1682 (std::uint32_t(detail::float_to_half(v.y)) << 16); // Place the second half encoding in the upper word.
1683} // Finish the packHalf2x16 operation.
1684inline vec2 unpackHalf2x16(std::uint32_t v) { // Expand the two IEEE half encodings.
1685 return vec2(detail::half_to_float(std::uint16_t(v)), // Expand the two IEEE half encodings.
1686 detail::half_to_float(std::uint16_t(v >> 16))); // Expand the upper half encoding into the second component.
1687} // Finish the unpackHalf2x16 operation.
1688/** @} */
1689} // namespace glsl
1690} // namespace shdr
1691#endif // Finish the math layer include guard.