Manifold 1.0
Robust computational geometry
 
Loading...
Searching...
No Matches
linalg.h
1// linalg.h - 2.2 - Single-header public domain linear algebra library
2//
3// The intent of this library is to provide the bulk of the functionality
4// you need to write programs that frequently use small, fixed-size vectors
5// and matrices, in domains such as computational geometry or computer
6// graphics. It strives for terse, readable source code.
7//
8// The original author of this software is Sterling Orsten, and its permanent
9// home is <http://github.com/sgorsten/linalg/>. If you find this software
10// useful, an acknowledgement in your source text and/or product documentation
11// is appreciated, but not required.
12//
13// The author acknowledges significant insights and contributions by:
14// Stan Melax <http://github.com/melax/>
15// Dimitri Diakopoulos <http://github.com/ddiakopoulos/>
16//
17// Some features are deprecated. Define LINALG_FORWARD_COMPATIBLE to remove
18// them.
19
20// This is free and unencumbered software released into the public domain.
21//
22// Anyone is free to copy, modify, publish, use, compile, sell, or
23// distribute this software, either in source code form or as a compiled
24// binary, for any purpose, commercial or non-commercial, and by any
25// means.
26//
27// In jurisdictions that recognize copyright laws, the author or authors
28// of this software dedicate any and all copyright interest in the
29// software to the public domain. We make this dedication for the benefit
30// of the public at large and to the detriment of our heirs and
31// successors. We intend this dedication to be an overt act of
32// relinquishment in perpetuity of all present and future rights to this
33// software under copyright law.
34//
35// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
36// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
37// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
38// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
39// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
40// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
41// OTHER DEALINGS IN THE SOFTWARE.
42//
43// For more information, please refer to <http://unlicense.org/>
44
45#pragma once
46#ifndef LINALG_H
47#define LINALG_H
48
49#include <array> // For std::array
50#include <cmath> // For various unary math functions, such as std::sqrt
51#include <cstdint> // For implementing namespace linalg::aliases
52#include <cstdlib> // To resolve std::abs ambiguity on clang
53#include <functional> // For std::hash declaration
54#include <iosfwd> // For forward definitions of std::ostream
55#include <type_traits> // For std::enable_if, std::is_same, std::declval
56
57// In Visual Studio 2015, `constexpr` applied to a member function implies
58// `const`, which causes ambiguous overload resolution
59#if defined(_MSC_VER) && (_MSC_VER <= 1900)
60#define LINALG_CONSTEXPR14
61#else
62#define LINALG_CONSTEXPR14 constexpr
63#endif
64
65namespace linalg {
66// Small, fixed-length vector type, consisting of exactly M elements of type T,
67// and presumed to be a column-vector unless otherwise noted.
68template <class T, int M>
69struct vec;
70
71// Small, fixed-size matrix type, consisting of exactly M rows and N columns of
72// type T, stored in column-major order.
73template <class T, int M, int N>
74struct mat;
75
76// Specialize converter<T,U> with a function application operator that converts
77// type U to type T to enable implicit conversions
78template <class T, class U>
79struct converter {};
80namespace detail {
81template <class T, class U>
82using conv_t = typename std::enable_if<!std::is_same<T, U>::value,
83 decltype(converter<T, U>{}(
84 std::declval<U>()))>::type;
85
86// Trait for retrieving scalar type of any linear algebra object
87template <class A>
88struct scalar_type {};
89template <class T, int M>
90struct scalar_type<vec<T, M>> {
91 using type = T;
92};
93template <class T, int M, int N>
94struct scalar_type<mat<T, M, N>> {
95 using type = T;
96};
97
98// Type returned by the compare(...) function which supports all six comparison
99// operators against 0
100template <class T>
101struct ord {
102 T a, b;
103};
104template <class T>
105constexpr bool operator==(const ord<T> &o, std::nullptr_t) {
106 return o.a == o.b;
107}
108template <class T>
109constexpr bool operator!=(const ord<T> &o, std::nullptr_t) {
110 return !(o.a == o.b);
111}
112template <class T>
113constexpr bool operator<(const ord<T> &o, std::nullptr_t) {
114 return o.a < o.b;
115}
116template <class T>
117constexpr bool operator>(const ord<T> &o, std::nullptr_t) {
118 return o.b < o.a;
119}
120template <class T>
121constexpr bool operator<=(const ord<T> &o, std::nullptr_t) {
122 return !(o.b < o.a);
123}
124template <class T>
125constexpr bool operator>=(const ord<T> &o, std::nullptr_t) {
126 return !(o.a < o.b);
127}
128
129// Patterns which can be used with the compare(...) function
130template <class A, class B>
131struct any_compare {};
132template <class T>
133struct any_compare<vec<T, 1>, vec<T, 1>> {
134 using type = ord<T>;
135 constexpr ord<T> operator()(const vec<T, 1> &a, const vec<T, 1> &b) const {
136 return ord<T>{a.x, b.x};
137 }
138};
139template <class T>
140struct any_compare<vec<T, 2>, vec<T, 2>> {
141 using type = ord<T>;
142 constexpr ord<T> operator()(const vec<T, 2> &a, const vec<T, 2> &b) const {
143 return !(a.x == b.x) ? ord<T>{a.x, b.x} : ord<T>{a.y, b.y};
144 }
145};
146template <class T>
147struct any_compare<vec<T, 3>, vec<T, 3>> {
148 using type = ord<T>;
149 constexpr ord<T> operator()(const vec<T, 3> &a, const vec<T, 3> &b) const {
150 return !(a.x == b.x) ? ord<T>{a.x, b.x}
151 : !(a.y == b.y) ? ord<T>{a.y, b.y}
152 : ord<T>{a.z, b.z};
153 }
154};
155template <class T>
156struct any_compare<vec<T, 4>, vec<T, 4>> {
157 using type = ord<T>;
158 constexpr ord<T> operator()(const vec<T, 4> &a, const vec<T, 4> &b) const {
159 return !(a.x == b.x) ? ord<T>{a.x, b.x}
160 : !(a.y == b.y) ? ord<T>{a.y, b.y}
161 : !(a.z == b.z) ? ord<T>{a.z, b.z}
162 : ord<T>{a.w, b.w};
163 }
164};
165template <class T, int M>
166struct any_compare<mat<T, M, 1>, mat<T, M, 1>> {
167 using type = ord<T>;
168 constexpr ord<T> operator()(const mat<T, M, 1> &a,
169 const mat<T, M, 1> &b) const {
170 return compare(a.x, b.x);
171 }
172};
173template <class T, int M>
174struct any_compare<mat<T, M, 2>, mat<T, M, 2>> {
175 using type = ord<T>;
176 constexpr ord<T> operator()(const mat<T, M, 2> &a,
177 const mat<T, M, 2> &b) const {
178 return a.x != b.x ? compare(a.x, b.x) : compare(a.y, b.y);
179 }
180};
181template <class T, int M>
182struct any_compare<mat<T, M, 3>, mat<T, M, 3>> {
183 using type = ord<T>;
184 constexpr ord<T> operator()(const mat<T, M, 3> &a,
185 const mat<T, M, 3> &b) const {
186 return a.x != b.x ? compare(a.x, b.x)
187 : a.y != b.y ? compare(a.y, b.y)
188 : compare(a.z, b.z);
189 }
190};
191template <class T, int M>
192struct any_compare<mat<T, M, 4>, mat<T, M, 4>> {
193 using type = ord<T>;
194 constexpr ord<T> operator()(const mat<T, M, 4> &a,
195 const mat<T, M, 4> &b) const {
196 return a.x != b.x ? compare(a.x, b.x)
197 : a.y != b.y ? compare(a.y, b.y)
198 : a.z != b.z ? compare(a.z, b.z)
199 : compare(a.w, b.w);
200 }
201};
202
203// Helper for compile-time index-based access to members of vector and matrix
204// types
205template <int I>
206struct getter;
207template <>
208struct getter<0> {
209 template <class A>
210 constexpr auto operator()(A &a) const -> decltype(a.x) {
211 return a.x;
212 }
213};
214template <>
215struct getter<1> {
216 template <class A>
217 constexpr auto operator()(A &a) const -> decltype(a.y) {
218 return a.y;
219 }
220};
221template <>
222struct getter<2> {
223 template <class A>
224 constexpr auto operator()(A &a) const -> decltype(a.z) {
225 return a.z;
226 }
227};
228template <>
229struct getter<3> {
230 template <class A>
231 constexpr auto operator()(A &a) const -> decltype(a.w) {
232 return a.w;
233 }
234};
235
236// Stand-in for std::integer_sequence/std::make_integer_sequence
237template <int... I>
238struct seq {};
239template <int A, int N>
241template <int A>
242struct make_seq_impl<A, 0> {
243 using type = seq<>;
244};
245template <int A>
246struct make_seq_impl<A, 1> {
247 using type = seq<A + 0>;
248};
249template <int A>
250struct make_seq_impl<A, 2> {
251 using type = seq<A + 0, A + 1>;
252};
253template <int A>
254struct make_seq_impl<A, 3> {
256};
257template <int A>
258struct make_seq_impl<A, 4> {
260};
261template <int A, int B>
262using make_seq = typename make_seq_impl<A, B - A>::type;
263template <class T, int M, int... I>
264vec<T, sizeof...(I)> constexpr swizzle(const vec<T, M> &v, seq<I...> i) {
265 return {getter<I>{}(v)...};
266}
267template <class T, int M, int N, int... I, int... J>
268mat<T, sizeof...(I), sizeof...(J)> constexpr swizzle(const mat<T, M, N> &m,
269 seq<I...> i, seq<J...> j) {
270 return {swizzle(getter<J>{}(m), i)...};
271}
272
273// SFINAE helpers to determine result of function application
274template <class F, class... T>
275using ret_t = decltype(std::declval<F>()(std::declval<T>()...));
276
277// SFINAE helper which is defined if all provided types are scalars
278struct empty {};
279template <class... T>
280struct scalars;
281template <>
282struct scalars<> {
283 using type = void;
284};
285template <class T, class... U>
286struct scalars<T, U...> : std::conditional<std::is_arithmetic<T>::value,
287 scalars<U...>, empty>::type {};
288template <class... T>
289using scalars_t = typename scalars<T...>::type;
290
291// Helpers which indicate how apply(F, ...) should be called for various
292// arguments
293template <class F, class Void, class... T>
294struct apply {}; // Patterns which contain only vectors or scalars
295template <class F, int M, class A>
296struct apply<F, scalars_t<>, vec<A, M>> {
297 using type = vec<ret_t<F, A>, M>;
298 enum { size = M, mm = 0 };
299 template <int... I>
300 static constexpr type impl(seq<I...>, F f, const vec<A, M> &a) {
301 return {f(getter<I>{}(a))...};
302 }
303};
304template <class F, int M, class A, class B>
305struct apply<F, scalars_t<>, vec<A, M>, vec<B, M>> {
306 using type = vec<ret_t<F, A, B>, M>;
307 enum { size = M, mm = 0 };
308 template <int... I>
309 static constexpr type impl(seq<I...>, F f, const vec<A, M> &a,
310 const vec<B, M> &b) {
311 return {f(getter<I>{}(a), getter<I>{}(b))...};
312 }
313};
314template <class F, int M, class A, class B>
315struct apply<F, scalars_t<B>, vec<A, M>, B> {
316 using type = vec<ret_t<F, A, B>, M>;
317 enum { size = M, mm = 0 };
318 template <int... I>
319 static constexpr type impl(seq<I...>, F f, const vec<A, M> &a, B b) {
320 return {f(getter<I>{}(a), b)...};
321 }
322};
323template <class F, int M, class A, class B>
324struct apply<F, scalars_t<A>, A, vec<B, M>> {
325 using type = vec<ret_t<F, A, B>, M>;
326 enum { size = M, mm = 0 };
327 template <int... I>
328 static constexpr type impl(seq<I...>, F f, A a, const vec<B, M> &b) {
329 return {f(a, getter<I>{}(b))...};
330 }
331};
332template <class F, int M, class A, class B, class C>
333struct apply<F, scalars_t<>, vec<A, M>, vec<B, M>, vec<C, M>> {
334 using type = vec<ret_t<F, A, B, C>, M>;
335 enum { size = M, mm = 0 };
336 template <int... I>
337 static constexpr type impl(seq<I...>, F f, const vec<A, M> &a,
338 const vec<B, M> &b, const vec<C, M> &c) {
339 return {f(getter<I>{}(a), getter<I>{}(b), getter<I>{}(c))...};
340 }
341};
342template <class F, int M, class A, class B, class C>
343struct apply<F, scalars_t<C>, vec<A, M>, vec<B, M>, C> {
344 using type = vec<ret_t<F, A, B, C>, M>;
345 enum { size = M, mm = 0 };
346 template <int... I>
347 static constexpr type impl(seq<I...>, F f, const vec<A, M> &a,
348 const vec<B, M> &b, C c) {
349 return {f(getter<I>{}(a), getter<I>{}(b), c)...};
350 }
351};
352template <class F, int M, class A, class B, class C>
353struct apply<F, scalars_t<B>, vec<A, M>, B, vec<C, M>> {
354 using type = vec<ret_t<F, A, B, C>, M>;
355 enum { size = M, mm = 0 };
356 template <int... I>
357 static constexpr type impl(seq<I...>, F f, const vec<A, M> &a, B b,
358 const vec<C, M> &c) {
359 return {f(getter<I>{}(a), b, getter<I>{}(c))...};
360 }
361};
362template <class F, int M, class A, class B, class C>
363struct apply<F, scalars_t<B, C>, vec<A, M>, B, C> {
364 using type = vec<ret_t<F, A, B, C>, M>;
365 enum { size = M, mm = 0 };
366 template <int... I>
367 static constexpr type impl(seq<I...>, F f, const vec<A, M> &a, B b, C c) {
368 return {f(getter<I>{}(a), b, c)...};
369 }
370};
371template <class F, int M, class A, class B, class C>
372struct apply<F, scalars_t<A>, A, vec<B, M>, vec<C, M>> {
373 using type = vec<ret_t<F, A, B, C>, M>;
374 enum { size = M, mm = 0 };
375 template <int... I>
376 static constexpr type impl(seq<I...>, F f, A a, const vec<B, M> &b,
377 const vec<C, M> &c) {
378 return {f(a, getter<I>{}(b), getter<I>{}(c))...};
379 }
380};
381template <class F, int M, class A, class B, class C>
382struct apply<F, scalars_t<A, C>, A, vec<B, M>, C> {
383 using type = vec<ret_t<F, A, B, C>, M>;
384 enum { size = M, mm = 0 };
385 template <int... I>
386 static constexpr type impl(seq<I...>, F f, A a, const vec<B, M> &b, C c) {
387 return {f(a, getter<I>{}(b), c)...};
388 }
389};
390template <class F, int M, class A, class B, class C>
391struct apply<F, scalars_t<A, B>, A, B, vec<C, M>> {
392 using type = vec<ret_t<F, A, B, C>, M>;
393 enum { size = M, mm = 0 };
394 template <int... I>
395 static constexpr type impl(seq<I...>, F f, A a, B b, const vec<C, M> &c) {
396 return {f(a, b, getter<I>{}(c))...};
397 }
398};
399template <class F, int M, int N, class A>
400struct apply<F, scalars_t<>, mat<A, M, N>> {
401 using type = mat<ret_t<F, A>, M, N>;
402 enum { size = N, mm = 0 };
403 template <int... J>
404 static constexpr type impl(seq<J...>, F f, const mat<A, M, N> &a) {
405 return {apply<F, void, vec<A, M>>::impl(make_seq<0, M>{}, f,
406 getter<J>{}(a))...};
407 }
408};
409template <class F, int M, int N, class A, class B>
410struct apply<F, scalars_t<>, mat<A, M, N>, mat<B, M, N>> {
411 using type = mat<ret_t<F, A, B>, M, N>;
412 enum { size = N, mm = 1 };
413 template <int... J>
414 static constexpr type impl(seq<J...>, F f, const mat<A, M, N> &a,
415 const mat<B, M, N> &b) {
416 return {apply<F, void, vec<A, M>, vec<B, M>>::impl(
417 make_seq<0, M>{}, f, getter<J>{}(a), getter<J>{}(b))...};
418 }
419};
420template <class F, int M, int N, class A, class B>
421struct apply<F, scalars_t<B>, mat<A, M, N>, B> {
422 using type = mat<ret_t<F, A, B>, M, N>;
423 enum { size = N, mm = 0 };
424 template <int... J>
425 static constexpr type impl(seq<J...>, F f, const mat<A, M, N> &a, B b) {
426 return {apply<F, void, vec<A, M>, B>::impl(make_seq<0, M>{}, f,
427 getter<J>{}(a), b)...};
428 }
429};
430template <class F, int M, int N, class A, class B>
431struct apply<F, scalars_t<A>, A, mat<B, M, N>> {
432 using type = mat<ret_t<F, A, B>, M, N>;
433 enum { size = N, mm = 0 };
434 template <int... J>
435 static constexpr type impl(seq<J...>, F f, A a, const mat<B, M, N> &b) {
436 return {apply<F, void, A, vec<B, M>>::impl(make_seq<0, M>{}, f, a,
437 getter<J>{}(b))...};
438 }
439};
440template <class F, class... A>
441struct apply<F, scalars_t<A...>, A...> {
442 using type = ret_t<F, A...>;
443 enum { size = 0, mm = 0 };
444 static constexpr type impl(seq<>, F f, A... a) { return f(a...); }
445};
446
447// Function objects for selecting between alternatives
448struct min {
449 template <class A, class B>
450 constexpr auto operator()(A a, B b) const ->
451 typename std::remove_reference<decltype(a < b ? a : b)>::type {
452 return a < b ? a : b;
453 }
454};
455struct max {
456 template <class A, class B>
457 constexpr auto operator()(A a, B b) const ->
458 typename std::remove_reference<decltype(a < b ? b : a)>::type {
459 return a < b ? b : a;
460 }
461};
462struct clamp {
463 template <class A, class B, class C>
464 constexpr auto operator()(A a, B b, C c) const ->
465 typename std::remove_reference<decltype(a < b ? b
466 : a < c ? a
467 : c)>::type {
468 return a < b ? b : a < c ? a : c;
469 }
470};
471struct select {
472 template <class A, class B, class C>
473 constexpr auto operator()(A a, B b, C c) const ->
474 typename std::remove_reference<decltype(a ? b : c)>::type {
475 return a ? b : c;
476 }
477};
478struct lerp {
479 template <class A, class B, class C>
480 constexpr auto operator()(A a, B b,
481 C c) const -> decltype(a * (1 - c) + b * c) {
482 return a * (1 - c) + b * c;
483 }
484};
485
486// Function objects for applying operators
487struct op_pos {
488 template <class A>
489 constexpr auto operator()(A a) const -> decltype(+a) {
490 return +a;
491 }
492};
493struct op_neg {
494 template <class A>
495 constexpr auto operator()(A a) const -> decltype(-a) {
496 return -a;
497 }
498};
499struct op_not {
500 template <class A>
501 constexpr auto operator()(A a) const -> decltype(!a) {
502 return !a;
503 }
504};
505struct op_cmp {
506 template <class A>
507 constexpr auto operator()(A a) const -> decltype(~(a)) {
508 return ~a;
509 }
510};
511struct op_mul {
512 template <class A, class B>
513 constexpr auto operator()(A a, B b) const -> decltype(a * b) {
514 return a * b;
515 }
516};
517struct op_div {
518 template <class A, class B>
519 constexpr auto operator()(A a, B b) const -> decltype(a / b) {
520 return a / b;
521 }
522};
523struct op_mod {
524 template <class A, class B>
525 constexpr auto operator()(A a, B b) const -> decltype(a % b) {
526 return a % b;
527 }
528};
529struct op_add {
530 template <class A, class B>
531 constexpr auto operator()(A a, B b) const -> decltype(a + b) {
532 return a + b;
533 }
534};
535struct op_sub {
536 template <class A, class B>
537 constexpr auto operator()(A a, B b) const -> decltype(a - b) {
538 return a - b;
539 }
540};
541struct op_lsh {
542 template <class A, class B>
543 constexpr auto operator()(A a, B b) const -> decltype(a << b) {
544 return a << b;
545 }
546};
547struct op_rsh {
548 template <class A, class B>
549 constexpr auto operator()(A a, B b) const -> decltype(a >> b) {
550 return a >> b;
551 }
552};
553struct op_lt {
554 template <class A, class B>
555 constexpr auto operator()(A a, B b) const -> decltype(a < b) {
556 return a < b;
557 }
558};
559struct op_gt {
560 template <class A, class B>
561 constexpr auto operator()(A a, B b) const -> decltype(a > b) {
562 return a > b;
563 }
564};
565struct op_le {
566 template <class A, class B>
567 constexpr auto operator()(A a, B b) const -> decltype(a <= b) {
568 return a <= b;
569 }
570};
571struct op_ge {
572 template <class A, class B>
573 constexpr auto operator()(A a, B b) const -> decltype(a >= b) {
574 return a >= b;
575 }
576};
577struct op_eq {
578 template <class A, class B>
579 constexpr auto operator()(A a, B b) const -> decltype(a == b) {
580 return a == b;
581 }
582};
583struct op_ne {
584 template <class A, class B>
585 constexpr auto operator()(A a, B b) const -> decltype(a != b) {
586 return a != b;
587 }
588};
589struct op_int {
590 template <class A, class B>
591 constexpr auto operator()(A a, B b) const -> decltype(a & b) {
592 return a & b;
593 }
594};
595struct op_xor {
596 template <class A, class B>
597 constexpr auto operator()(A a, B b) const -> decltype(a ^ b) {
598 return a ^ b;
599 }
600};
601struct op_un {
602 template <class A, class B>
603 constexpr auto operator()(A a, B b) const -> decltype(a | b) {
604 return a | b;
605 }
606};
607struct op_and {
608 template <class A, class B>
609 constexpr auto operator()(A a, B b) const -> decltype(a && b) {
610 return a && b;
611 }
612};
613struct op_or {
614 template <class A, class B>
615 constexpr auto operator()(A a, B b) const -> decltype(a || b) {
616 return a || b;
617 }
618};
619
620// Function objects for applying standard library math functions
622 template <class A>
623 constexpr auto operator()(A a) const -> decltype(std::isfinite(a)) {
624 return std::isfinite(a);
625 }
626};
627struct std_abs {
628 template <class A>
629 constexpr auto operator()(A a) const -> decltype(std::abs(a)) {
630 return std::abs(a);
631 }
632};
633struct std_floor {
634 template <class A>
635 constexpr auto operator()(A a) const -> decltype(std::floor(a)) {
636 return std::floor(a);
637 }
638};
639struct std_ceil {
640 template <class A>
641 constexpr auto operator()(A a) const -> decltype(std::ceil(a)) {
642 return std::ceil(a);
643 }
644};
645struct std_exp {
646 template <class A>
647 constexpr auto operator()(A a) const -> decltype(std::exp(a)) {
648 return std::exp(a);
649 }
650};
651struct std_log {
652 template <class A>
653 constexpr auto operator()(A a) const -> decltype(std::log(a)) {
654 return std::log(a);
655 }
656};
657struct std_log2 {
658 template <class A>
659 constexpr auto operator()(A a) const -> decltype(std::log2(a)) {
660 return std::log2(a);
661 }
662};
663struct std_log10 {
664 template <class A>
665 constexpr auto operator()(A a) const -> decltype(std::log10(a)) {
666 return std::log10(a);
667 }
668};
669struct std_sqrt {
670 template <class A>
671 constexpr auto operator()(A a) const -> decltype(std::sqrt(a)) {
672 return std::sqrt(a);
673 }
674};
675struct std_sin {
676 template <class A>
677 constexpr auto operator()(A a) const -> decltype(std::sin(a)) {
678 return std::sin(a);
679 }
680};
681struct std_cos {
682 template <class A>
683 constexpr auto operator()(A a) const -> decltype(std::cos(a)) {
684 return std::cos(a);
685 }
686};
687struct std_tan {
688 template <class A>
689 constexpr auto operator()(A a) const -> decltype(std::tan(a)) {
690 return std::tan(a);
691 }
692};
693struct std_asin {
694 template <class A>
695 constexpr auto operator()(A a) const -> decltype(std::asin(a)) {
696 return std::asin(a);
697 }
698};
699struct std_acos {
700 template <class A>
701 constexpr auto operator()(A a) const -> decltype(std::acos(a)) {
702 return std::acos(a);
703 }
704};
705struct std_atan {
706 template <class A>
707 constexpr auto operator()(A a) const -> decltype(std::atan(a)) {
708 return std::atan(a);
709 }
710};
711struct std_sinh {
712 template <class A>
713 constexpr auto operator()(A a) const -> decltype(std::sinh(a)) {
714 return std::sinh(a);
715 }
716};
717struct std_cosh {
718 template <class A>
719 constexpr auto operator()(A a) const -> decltype(std::cosh(a)) {
720 return std::cosh(a);
721 }
722};
723struct std_tanh {
724 template <class A>
725 constexpr auto operator()(A a) const -> decltype(std::tanh(a)) {
726 return std::tanh(a);
727 }
728};
729struct std_round {
730 template <class A>
731 constexpr auto operator()(A a) const -> decltype(std::round(a)) {
732 return std::round(a);
733 }
734};
735struct std_fmod {
736 template <class A, class B>
737 constexpr auto operator()(A a, B b) const -> decltype(std::fmod(a, b)) {
738 return std::fmod(a, b);
739 }
740};
741struct std_pow {
742 template <class A, class B>
743 constexpr auto operator()(A a, B b) const -> decltype(std::pow(a, b)) {
744 return std::pow(a, b);
745 }
746};
747struct std_atan2 {
748 template <class A, class B>
749 constexpr auto operator()(A a, B b) const -> decltype(std::atan2(a, b)) {
750 return std::atan2(a, b);
751 }
752};
754 template <class A, class B>
755 constexpr auto operator()(A a, B b) const -> decltype(std::copysign(a, b)) {
756 return std::copysign(a, b);
757 }
758};
759} // namespace detail
760
761// Small, fixed-length vector type, consisting of exactly M elements of type T,
762// and presumed to be a column-vector unless otherwise noted
763template <class T>
764struct vec<T, 1> {
765 T x;
766 constexpr vec() : x() {}
767 constexpr vec(const T &x_) : x(x_) {}
768 // NOTE: vec<T,1> does NOT have a constructor from pointer, this can conflict
769 // with initializing its single element from zero
770 template <class U>
771 constexpr explicit vec(const vec<U, 1> &v) : vec(static_cast<T>(v.x)) {}
772 constexpr const T &operator[](int i) const { return x; }
773 LINALG_CONSTEXPR14 T &operator[](int i) { return x; }
774
775 template <class U, class = detail::conv_t<vec, U>>
776 constexpr vec(const U &u) : vec(converter<vec, U>{}(u)) {}
777 template <class U, class = detail::conv_t<U, vec>>
778 constexpr operator U() const {
779 return converter<U, vec>{}(*this);
780 }
781};
782template <class T>
783struct vec<T, 2> {
784 T x, y;
785 constexpr vec() : x(), y() {}
786 constexpr vec(const T &x_, const T &y_) : x(x_), y(y_) {}
787 constexpr explicit vec(const T &s) : vec(s, s) {}
788 constexpr explicit vec(const T *p) : vec(p[0], p[1]) {}
789 template <class U, int N>
790 constexpr explicit vec(const vec<U, N> &v)
791 : vec(static_cast<T>(v.x), static_cast<T>(v.y)) {
792 static_assert(
793 N >= 2,
794 "You must give extra arguments if your input vector is shorter.");
795 }
796 constexpr const T &operator[](int i) const { return i == 0 ? x : y; }
797 LINALG_CONSTEXPR14 T &operator[](int i) { return i == 0 ? x : y; }
798
799 template <class U, class = detail::conv_t<vec, U>>
800 constexpr vec(const U &u) : vec(converter<vec, U>{}(u)) {}
801 template <class U, class = detail::conv_t<U, vec>>
802 constexpr operator U() const {
803 return converter<U, vec>{}(*this);
804 }
805};
806template <class T>
807struct vec<T, 3> {
808 T x, y, z;
809 constexpr vec() : x(), y(), z() {}
810 constexpr vec(const T &x_, const T &y_, const T &z_) : x(x_), y(y_), z(z_) {}
811 constexpr vec(const vec<T, 2> &xy, const T &z_) : vec(xy.x, xy.y, z_) {}
812 constexpr explicit vec(const T &s) : vec(s, s, s) {}
813 constexpr explicit vec(const T *p) : vec(p[0], p[1], p[2]) {}
814 template <class U, int N>
815 constexpr explicit vec(const vec<U, N> &v)
816 : vec(static_cast<T>(v.x), static_cast<T>(v.y), static_cast<T>(v.z)) {
817 static_assert(
818 N >= 3,
819 "You must give extra arguments if your input vector is shorter.");
820 }
821 constexpr const T &operator[](int i) const {
822 return i == 0 ? x : i == 1 ? y : z;
823 }
824 LINALG_CONSTEXPR14 T &operator[](int i) {
825 return i == 0 ? x : i == 1 ? y : z;
826 }
827 constexpr const vec<T, 2> &xy() const {
828 return *reinterpret_cast<const vec<T, 2> *>(this);
829 }
830 vec<T, 2> &xy() { return *reinterpret_cast<vec<T, 2> *>(this); }
831
832 template <class U, class = detail::conv_t<vec, U>>
833 constexpr vec(const U &u) : vec(converter<vec, U>{}(u)) {}
834 template <class U, class = detail::conv_t<U, vec>>
835 constexpr operator U() const {
836 return converter<U, vec>{}(*this);
837 }
838};
839template <class T>
840struct vec<T, 4> {
841 T x, y, z, w;
842 constexpr vec() : x(), y(), z(), w() {}
843 constexpr vec(const T &x_, const T &y_, const T &z_, const T &w_)
844 : x(x_), y(y_), z(z_), w(w_) {}
845 constexpr vec(const vec<T, 2> &xy, const T &z_, const T &w_)
846 : vec(xy.x, xy.y, z_, w_) {}
847 constexpr vec(const vec<T, 3> &xyz, const T &w_)
848 : vec(xyz.x, xyz.y, xyz.z, w_) {}
849 constexpr explicit vec(const T &s) : vec(s, s, s, s) {}
850 constexpr explicit vec(const T *p) : vec(p[0], p[1], p[2], p[3]) {}
851 template <class U, int N>
852 constexpr explicit vec(const vec<U, N> &v)
853 : vec(static_cast<T>(v.x), static_cast<T>(v.y), static_cast<T>(v.z),
854 static_cast<T>(v.w)) {
855 static_assert(
856 N >= 4,
857 "You must give extra arguments if your input vector is shorter.");
858 }
859 constexpr const T &operator[](int i) const {
860 return i == 0 ? x : i == 1 ? y : i == 2 ? z : w;
861 }
862 LINALG_CONSTEXPR14 T &operator[](int i) {
863 return i == 0 ? x : i == 1 ? y : i == 2 ? z : w;
864 }
865 constexpr const vec<T, 2> &xy() const {
866 return *reinterpret_cast<const vec<T, 2> *>(this);
867 }
868 constexpr const vec<T, 3> &xyz() const {
869 return *reinterpret_cast<const vec<T, 3> *>(this);
870 }
871 vec<T, 2> &xy() { return *reinterpret_cast<vec<T, 2> *>(this); }
872 vec<T, 3> &xyz() { return *reinterpret_cast<vec<T, 3> *>(this); }
873
874 template <class U, class = detail::conv_t<vec, U>>
875 constexpr vec(const U &u) : vec(converter<vec, U>{}(u)) {}
876 template <class U, class = detail::conv_t<U, vec>>
877 constexpr operator U() const {
878 return converter<U, vec>{}(*this);
879 }
880};
881
882// Small, fixed-size matrix type, consisting of exactly M rows and N columns of
883// type T, stored in column-major order.
884template <class T, int M>
885struct mat<T, M, 1> {
886 typedef vec<T, M> V;
887 V x;
888 constexpr mat() : x() {}
889 constexpr mat(const V &x_) : x(x_) {}
890 constexpr explicit mat(const T &s) : x(s) {}
891 constexpr explicit mat(const T *p) : x(p + M * 0) {}
892 template <class U>
893 constexpr explicit mat(const mat<U, M, 1> &m) : mat(V(m.x)) {}
894 constexpr vec<T, 1> row(int i) const { return {x[i]}; }
895 constexpr const V &operator[](int j) const { return x; }
896 LINALG_CONSTEXPR14 V &operator[](int j) { return x; }
897
898 template <class U, class = detail::conv_t<mat, U>>
899 constexpr mat(const U &u) : mat(converter<mat, U>{}(u)) {}
900 template <class U, class = detail::conv_t<U, mat>>
901 constexpr operator U() const {
902 return converter<U, mat>{}(*this);
903 }
904};
905template <class T, int M>
906struct mat<T, M, 2> {
907 typedef vec<T, M> V;
908 V x, y;
909 constexpr mat() : x(), y() {}
910 constexpr mat(const V &x_, const V &y_) : x(x_), y(y_) {}
911 constexpr explicit mat(const T &s) : x(s), y(s) {}
912 constexpr explicit mat(const T *p) : x(p + M * 0), y(p + M * 1) {}
913 template <class U, int N, int P>
914 constexpr explicit mat(const mat<U, N, P> &m) : mat(V(m.x), V(m.y)) {
915 static_assert(P >= 2, "Input matrix dimensions must be at least as big.");
916 }
917 constexpr vec<T, 2> row(int i) const { return {x[i], y[i]}; }
918 constexpr const V &operator[](int j) const { return j == 0 ? x : y; }
919 LINALG_CONSTEXPR14 V &operator[](int j) { return j == 0 ? x : y; }
920
921 template <class U, class = detail::conv_t<mat, U>>
922 constexpr mat(const U &u) : mat(converter<mat, U>{}(u)) {}
923 template <class U, class = detail::conv_t<U, mat>>
924 constexpr operator U() const {
925 return converter<U, mat>{}(*this);
926 }
927};
928template <class T, int M>
929struct mat<T, M, 3> {
930 typedef vec<T, M> V;
931 V x, y, z;
932 constexpr mat() : x(), y(), z() {}
933 constexpr mat(const V &x_, const V &y_, const V &z_) : x(x_), y(y_), z(z_) {}
934 constexpr mat(const mat<T, M, 2> &m_, const V &z_)
935 : x(m_.x), y(m_.y), z(z_) {}
936 constexpr explicit mat(const T &s) : x(s), y(s), z(s) {}
937 constexpr explicit mat(const T *p)
938 : x(p + M * 0), y(p + M * 1), z(p + M * 2) {}
939 template <class U, int N, int P>
940 constexpr explicit mat(const mat<U, N, P> &m) : mat(V(m.x), V(m.y), V(m.z)) {
941 static_assert(P >= 3, "Input matrix dimensions must be at least as big.");
942 }
943 constexpr vec<T, 3> row(int i) const { return {x[i], y[i], z[i]}; }
944 constexpr const V &operator[](int j) const {
945 return j == 0 ? x : j == 1 ? y : z;
946 }
947 LINALG_CONSTEXPR14 V &operator[](int j) {
948 return j == 0 ? x : j == 1 ? y : z;
949 }
950
951 template <class U, class = detail::conv_t<mat, U>>
952 constexpr mat(const U &u) : mat(converter<mat, U>{}(u)) {}
953 template <class U, class = detail::conv_t<U, mat>>
954 constexpr operator U() const {
955 return converter<U, mat>{}(*this);
956 }
957};
958template <class T, int M>
959struct mat<T, M, 4> {
960 typedef vec<T, M> V;
961 V x, y, z, w;
962 constexpr mat() : x(), y(), z(), w() {}
963 constexpr mat(const V &x_, const V &y_, const V &z_, const V &w_)
964 : x(x_), y(y_), z(z_), w(w_) {}
965 constexpr mat(const mat<T, M, 3> &m_, const V &w_)
966 : x(m_.x), y(m_.y), z(m_.z), w(w_) {}
967 constexpr explicit mat(const T &s) : x(s), y(s), z(s), w(s) {}
968 constexpr explicit mat(const T *p)
969 : x(p + M * 0), y(p + M * 1), z(p + M * 2), w(p + M * 3) {}
970 template <class U, int N, int P>
971 constexpr explicit mat(const mat<U, N, P> &m)
972 : mat(V(m.x), V(m.y), V(m.z), V(m.w)) {
973 static_assert(P >= 4, "Input matrix dimensions must be at least as big.");
974 }
975
976 constexpr vec<T, 4> row(int i) const { return {x[i], y[i], z[i], w[i]}; }
977 constexpr const V &operator[](int j) const {
978 return j == 0 ? x : j == 1 ? y : j == 2 ? z : w;
979 }
980 LINALG_CONSTEXPR14 V &operator[](int j) {
981 return j == 0 ? x : j == 1 ? y : j == 2 ? z : w;
982 }
983
984 template <class U, class = detail::conv_t<mat, U>>
985 constexpr mat(const U &u) : mat(converter<mat, U>{}(u)) {}
986 template <class U, class = detail::conv_t<U, mat>>
987 constexpr operator U() const {
988 return converter<U, mat>{}(*this);
989 }
990};
991
992// Define a type which will convert to the multiplicative identity of any square
993// matrix
995 constexpr explicit identity_t(int) {}
996};
997template <class T>
998struct converter<mat<T, 1, 1>, identity_t> {
999 constexpr mat<T, 1, 1> operator()(identity_t) const { return {vec<T, 1>{1}}; }
1000};
1001template <class T>
1002struct converter<mat<T, 2, 2>, identity_t> {
1003 constexpr mat<T, 2, 2> operator()(identity_t) const {
1004 return {{1, 0}, {0, 1}};
1005 }
1006};
1007template <class T>
1008struct converter<mat<T, 3, 3>, identity_t> {
1009 constexpr mat<T, 3, 3> operator()(identity_t) const {
1010 return {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
1011 }
1012};
1013template <class T>
1014struct converter<mat<T, 4, 4>, identity_t> {
1015 constexpr mat<T, 4, 4> operator()(identity_t) const {
1016 return {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
1017 }
1018};
1019constexpr identity_t identity{1};
1020
1021// Produce a scalar by applying f(A,B) -> A to adjacent pairs of elements from a
1022// vec/mat in left-to-right/column-major order (matching the associativity of
1023// arithmetic and logical operators)
1024template <class F, class A, class B>
1025constexpr A fold(F f, A a, const vec<B, 1> &b) {
1026 return f(a, b.x);
1027}
1028template <class F, class A, class B>
1029constexpr A fold(F f, A a, const vec<B, 2> &b) {
1030 return f(f(a, b.x), b.y);
1031}
1032template <class F, class A, class B>
1033constexpr A fold(F f, A a, const vec<B, 3> &b) {
1034 return f(f(f(a, b.x), b.y), b.z);
1035}
1036template <class F, class A, class B>
1037constexpr A fold(F f, A a, const vec<B, 4> &b) {
1038 return f(f(f(f(a, b.x), b.y), b.z), b.w);
1039}
1040template <class F, class A, class B, int M>
1041constexpr A fold(F f, A a, const mat<B, M, 1> &b) {
1042 return fold(f, a, b.x);
1043}
1044template <class F, class A, class B, int M>
1045constexpr A fold(F f, A a, const mat<B, M, 2> &b) {
1046 return fold(f, fold(f, a, b.x), b.y);
1047}
1048template <class F, class A, class B, int M>
1049constexpr A fold(F f, A a, const mat<B, M, 3> &b) {
1050 return fold(f, fold(f, fold(f, a, b.x), b.y), b.z);
1051}
1052template <class F, class A, class B, int M>
1053constexpr A fold(F f, A a, const mat<B, M, 4> &b) {
1054 return fold(f, fold(f, fold(f, fold(f, a, b.x), b.y), b.z), b.w);
1055}
1056
1057// Type aliases for the result of calling apply(...) with various arguments, can
1058// be used with return type SFINAE to constrian overload sets
1059template <class F, class... A>
1060using apply_t = typename detail::apply<F, void, A...>::type;
1061template <class F, class... A>
1062using mm_apply_t = typename std::enable_if<detail::apply<F, void, A...>::mm,
1063 apply_t<F, A...>>::type;
1064template <class F, class... A>
1065using no_mm_apply_t = typename std::enable_if<!detail::apply<F, void, A...>::mm,
1066 apply_t<F, A...>>::type;
1067template <class A>
1068using scalar_t =
1069 typename detail::scalar_type<A>::type; // Underlying scalar type when
1070 // performing elementwise operations
1071
1072// apply(f,...) applies the provided function in an elementwise fashion to its
1073// arguments, producing an object of the same dimensions
1074template <class F, class... A>
1075constexpr apply_t<F, A...> apply(F func, const A &...args) {
1076 return detail::apply<F, void, A...>::impl(
1077 detail::make_seq<0, detail::apply<F, void, A...>::size>{}, func, args...);
1078}
1079
1080// map(a,f) is equivalent to apply(f,a)
1081template <class A, class F>
1082constexpr apply_t<F, A> map(const A &a, F func) {
1083 return apply(func, a);
1084}
1085
1086// zip(a,b,f) is equivalent to apply(f,a,b)
1087template <class A, class B, class F>
1088constexpr apply_t<F, A, B> zip(const A &a, const B &b, F func) {
1089 return apply(func, a, b);
1090}
1091
1092// Relational operators are defined to compare the elements of two vectors or
1093// matrices lexicographically, in column-major order
1094template <class A, class B>
1095constexpr typename detail::any_compare<A, B>::type compare(const A &a,
1096 const B &b) {
1097 return detail::any_compare<A, B>()(a, b);
1098}
1099template <class A, class B>
1100constexpr auto operator==(const A &a,
1101 const B &b) -> decltype(compare(a, b) == 0) {
1102 return compare(a, b) == 0;
1103}
1104template <class A, class B>
1105constexpr auto operator!=(const A &a,
1106 const B &b) -> decltype(compare(a, b) != 0) {
1107 return compare(a, b) != 0;
1108}
1109template <class A, class B>
1110constexpr auto operator<(const A &a,
1111 const B &b) -> decltype(compare(a, b) < 0) {
1112 return compare(a, b) < 0;
1113}
1114template <class A, class B>
1115constexpr auto operator>(const A &a,
1116 const B &b) -> decltype(compare(a, b) > 0) {
1117 return compare(a, b) > 0;
1118}
1119template <class A, class B>
1120constexpr auto operator<=(const A &a,
1121 const B &b) -> decltype(compare(a, b) <= 0) {
1122 return compare(a, b) <= 0;
1123}
1124template <class A, class B>
1125constexpr auto operator>=(const A &a,
1126 const B &b) -> decltype(compare(a, b) >= 0) {
1127 return compare(a, b) >= 0;
1128}
1129
1130// Functions for coalescing scalar values
1131template <class A>
1132constexpr bool any(const A &a) {
1133 return fold(detail::op_or{}, false, a);
1134}
1135template <class A>
1136constexpr bool all(const A &a) {
1137 return fold(detail::op_and{}, true, a);
1138}
1139template <class A>
1140constexpr scalar_t<A> sum(const A &a) {
1141 return fold(detail::op_add{}, scalar_t<A>(0), a);
1142}
1143template <class A>
1144constexpr scalar_t<A> product(const A &a) {
1145 return fold(detail::op_mul{}, scalar_t<A>(1), a);
1146}
1147template <class A>
1148constexpr scalar_t<A> minelem(const A &a) {
1149 return fold(detail::min{}, a.x, a);
1150}
1151template <class A>
1152constexpr scalar_t<A> maxelem(const A &a) {
1153 return fold(detail::max{}, a.x, a);
1154}
1155template <class T, int M>
1156int argmin(const vec<T, M> &a) {
1157 int j = 0;
1158 for (int i = 1; i < M; ++i)
1159 if (a[i] < a[j]) j = i;
1160 return j;
1161}
1162template <class T, int M>
1163int argmax(const vec<T, M> &a) {
1164 int j = 0;
1165 for (int i = 1; i < M; ++i)
1166 if (a[i] > a[j]) j = i;
1167 return j;
1168}
1169
1170// Unary operators are defined component-wise for linalg types
1171template <class A>
1172constexpr apply_t<detail::op_pos, A> operator+(const A &a) {
1173 return apply(detail::op_pos{}, a);
1174}
1175template <class A>
1176constexpr apply_t<detail::op_neg, A> operator-(const A &a) {
1177 return apply(detail::op_neg{}, a);
1178}
1179template <class A>
1180constexpr apply_t<detail::op_cmp, A> operator~(const A &a) {
1181 return apply(detail::op_cmp{}, a);
1182}
1183template <class A>
1184constexpr apply_t<detail::op_not, A> operator!(const A &a) {
1185 return apply(detail::op_not{}, a);
1186}
1187
1188// Binary operators are defined component-wise for linalg types, EXCEPT for
1189// `operator *`
1190template <class A, class B>
1191constexpr apply_t<detail::op_add, A, B> operator+(const A &a, const B &b) {
1192 return apply(detail::op_add{}, a, b);
1193}
1194template <class A, class B>
1195constexpr apply_t<detail::op_sub, A, B> operator-(const A &a, const B &b) {
1196 return apply(detail::op_sub{}, a, b);
1197}
1198template <class A, class B>
1199constexpr apply_t<detail::op_mul, A, B> cmul(const A &a, const B &b) {
1200 return apply(detail::op_mul{}, a, b);
1201}
1202template <class A, class B>
1203constexpr apply_t<detail::op_div, A, B> operator/(const A &a, const B &b) {
1204 return apply(detail::op_div{}, a, b);
1205}
1206template <class A, class B>
1207constexpr apply_t<detail::op_mod, A, B> operator%(const A &a, const B &b) {
1208 return apply(detail::op_mod{}, a, b);
1209}
1210template <class A, class B>
1211constexpr apply_t<detail::op_un, A, B> operator|(const A &a, const B &b) {
1212 return apply(detail::op_un{}, a, b);
1213}
1214template <class A, class B>
1215constexpr apply_t<detail::op_xor, A, B> operator^(const A &a, const B &b) {
1216 return apply(detail::op_xor{}, a, b);
1217}
1218template <class A, class B>
1219constexpr apply_t<detail::op_int, A, B> operator&(const A &a, const B &b) {
1220 return apply(detail::op_int{}, a, b);
1221}
1222template <class A, class B>
1223constexpr apply_t<detail::op_lsh, A, B> operator<<(const A &a, const B &b) {
1224 return apply(detail::op_lsh{}, a, b);
1225}
1226template <class A, class B>
1227constexpr apply_t<detail::op_rsh, A, B> operator>>(const A &a, const B &b) {
1228 return apply(detail::op_rsh{}, a, b);
1229}
1230
1231// Binary `operator *` represents the algebraic matrix product - use cmul(a, b)
1232// for the Hadamard (component-wise) product.
1233template <class A, class B>
1234constexpr auto operator*(const A &a, const B &b) {
1235 return mul(a, b);
1236}
1237
1238// Binary assignment operators a $= b is always defined as though it were
1239// explicitly written a = a $ b
1240template <class A, class B>
1241constexpr auto operator+=(A &a, const B &b) -> decltype(a = a + b) {
1242 return a = a + b;
1243}
1244template <class A, class B>
1245constexpr auto operator-=(A &a, const B &b) -> decltype(a = a - b) {
1246 return a = a - b;
1247}
1248template <class A, class B>
1249constexpr auto operator*=(A &a, const B &b) -> decltype(a = a * b) {
1250 return a = a * b;
1251}
1252template <class A, class B>
1253constexpr auto operator/=(A &a, const B &b) -> decltype(a = a / b) {
1254 return a = a / b;
1255}
1256template <class A, class B>
1257constexpr auto operator%=(A &a, const B &b) -> decltype(a = a % b) {
1258 return a = a % b;
1259}
1260template <class A, class B>
1261constexpr auto operator|=(A &a, const B &b) -> decltype(a = a | b) {
1262 return a = a | b;
1263}
1264template <class A, class B>
1265constexpr auto operator^=(A &a, const B &b) -> decltype(a = a ^ b) {
1266 return a = a ^ b;
1267}
1268template <class A, class B>
1269constexpr auto operator&=(A &a, const B &b) -> decltype(a = a & b) {
1270 return a = a & b;
1271}
1272template <class A, class B>
1273constexpr auto operator<<=(A &a, const B &b) -> decltype(a = a << b) {
1274 return a = a << b;
1275}
1276template <class A, class B>
1277constexpr auto operator>>=(A &a, const B &b) -> decltype(a = a >> b) {
1278 return a = a >> b;
1279}
1280
1281// Swizzles and subobjects
1282template <int... I, class T, int M>
1283constexpr vec<T, sizeof...(I)> swizzle(const vec<T, M> &a) {
1284 return {detail::getter<I>{}(a)...};
1285}
1286template <int I0, int I1, class T, int M>
1287constexpr vec<T, I1 - I0> subvec(const vec<T, M> &a) {
1288 return detail::swizzle(a, detail::make_seq<I0, I1>{});
1289}
1290template <int I0, int J0, int I1, int J1, class T, int M, int N>
1291constexpr mat<T, I1 - I0, J1 - J0> submat(const mat<T, M, N> &a) {
1292 return detail::swizzle(a, detail::make_seq<I0, I1>{},
1293 detail::make_seq<J0, J1>{});
1294}
1295
1296// Component-wise standard library math functions
1297template <class A>
1298constexpr apply_t<detail::std_isfinite, A> isfinite(const A &a) {
1299 return apply(detail::std_isfinite{}, a);
1300}
1301template <class A>
1302constexpr apply_t<detail::std_abs, A> abs(const A &a) {
1303 return apply(detail::std_abs{}, a);
1304}
1305template <class A>
1306constexpr apply_t<detail::std_floor, A> floor(const A &a) {
1307 return apply(detail::std_floor{}, a);
1308}
1309template <class A>
1310constexpr apply_t<detail::std_ceil, A> ceil(const A &a) {
1311 return apply(detail::std_ceil{}, a);
1312}
1313template <class A>
1314constexpr apply_t<detail::std_exp, A> exp(const A &a) {
1315 return apply(detail::std_exp{}, a);
1316}
1317template <class A>
1318constexpr apply_t<detail::std_log, A> log(const A &a) {
1319 return apply(detail::std_log{}, a);
1320}
1321template <class A>
1322constexpr apply_t<detail::std_log2, A> log2(const A &a) {
1323 return apply(detail::std_log2{}, a);
1324}
1325template <class A>
1326constexpr apply_t<detail::std_log10, A> log10(const A &a) {
1327 return apply(detail::std_log10{}, a);
1328}
1329template <class A>
1330constexpr apply_t<detail::std_sqrt, A> sqrt(const A &a) {
1331 return apply(detail::std_sqrt{}, a);
1332}
1333template <class A>
1334constexpr apply_t<detail::std_sin, A> sin(const A &a) {
1335 return apply(detail::std_sin{}, a);
1336}
1337template <class A>
1338constexpr apply_t<detail::std_cos, A> cos(const A &a) {
1339 return apply(detail::std_cos{}, a);
1340}
1341template <class A>
1342constexpr apply_t<detail::std_tan, A> tan(const A &a) {
1343 return apply(detail::std_tan{}, a);
1344}
1345template <class A>
1346constexpr apply_t<detail::std_asin, A> asin(const A &a) {
1347 return apply(detail::std_asin{}, a);
1348}
1349template <class A>
1350constexpr apply_t<detail::std_acos, A> acos(const A &a) {
1351 return apply(detail::std_acos{}, a);
1352}
1353template <class A>
1354constexpr apply_t<detail::std_atan, A> atan(const A &a) {
1355 return apply(detail::std_atan{}, a);
1356}
1357template <class A>
1358constexpr apply_t<detail::std_sinh, A> sinh(const A &a) {
1359 return apply(detail::std_sinh{}, a);
1360}
1361template <class A>
1362constexpr apply_t<detail::std_cosh, A> cosh(const A &a) {
1363 return apply(detail::std_cosh{}, a);
1364}
1365template <class A>
1366constexpr apply_t<detail::std_tanh, A> tanh(const A &a) {
1367 return apply(detail::std_tanh{}, a);
1368}
1369template <class A>
1370constexpr apply_t<detail::std_round, A> round(const A &a) {
1371 return apply(detail::std_round{}, a);
1372}
1373
1374template <class A, class B>
1375constexpr apply_t<detail::std_fmod, A, B> fmod(const A &a, const B &b) {
1376 return apply(detail::std_fmod{}, a, b);
1377}
1378template <class A, class B>
1379constexpr apply_t<detail::std_pow, A, B> pow(const A &a, const B &b) {
1380 return apply(detail::std_pow{}, a, b);
1381}
1382template <class A, class B>
1383constexpr apply_t<detail::std_atan2, A, B> atan2(const A &a, const B &b) {
1384 return apply(detail::std_atan2{}, a, b);
1385}
1386template <class A, class B>
1387constexpr apply_t<detail::std_copysign, A, B> copysign(const A &a, const B &b) {
1388 return apply(detail::std_copysign{}, a, b);
1389}
1390
1391// Component-wise relational functions on vectors
1392template <class A, class B>
1393constexpr apply_t<detail::op_eq, A, B> equal(const A &a, const B &b) {
1394 return apply(detail::op_eq{}, a, b);
1395}
1396template <class A, class B>
1397constexpr apply_t<detail::op_ne, A, B> nequal(const A &a, const B &b) {
1398 return apply(detail::op_ne{}, a, b);
1399}
1400template <class A, class B>
1401constexpr apply_t<detail::op_lt, A, B> less(const A &a, const B &b) {
1402 return apply(detail::op_lt{}, a, b);
1403}
1404template <class A, class B>
1405constexpr apply_t<detail::op_gt, A, B> greater(const A &a, const B &b) {
1406 return apply(detail::op_gt{}, a, b);
1407}
1408template <class A, class B>
1409constexpr apply_t<detail::op_le, A, B> lequal(const A &a, const B &b) {
1410 return apply(detail::op_le{}, a, b);
1411}
1412template <class A, class B>
1413constexpr apply_t<detail::op_ge, A, B> gequal(const A &a, const B &b) {
1414 return apply(detail::op_ge{}, a, b);
1415}
1416
1417// Component-wise selection functions on vectors
1418template <class A, class B>
1419constexpr apply_t<detail::min, A, B> min(const A &a, const B &b) {
1420 return apply(detail::min{}, a, b);
1421}
1422template <class A, class B>
1423constexpr apply_t<detail::max, A, B> max(const A &a, const B &b) {
1424 return apply(detail::max{}, a, b);
1425}
1426template <class X, class L, class H>
1427constexpr apply_t<detail::clamp, X, L, H> clamp(const X &x, const L &l,
1428 const H &h) {
1429 return apply(detail::clamp{}, x, l, h);
1430}
1431template <class P, class A, class B>
1432constexpr apply_t<detail::select, P, A, B> select(const P &p, const A &a,
1433 const B &b) {
1434 return apply(detail::select{}, p, a, b);
1435}
1436template <class A, class B, class T>
1437constexpr apply_t<detail::lerp, A, B, T> lerp(const A &a, const B &b,
1438 const T &t) {
1439 return apply(detail::lerp{}, a, b, t);
1440}
1441
1442// Support for vector algebra
1443template <class T>
1444constexpr T cross(const vec<T, 2> &a, const vec<T, 2> &b) {
1445 return a.x * b.y - a.y * b.x;
1446}
1447template <class T>
1448constexpr vec<T, 2> cross(T a, const vec<T, 2> &b) {
1449 return {-a * b.y, a * b.x};
1450}
1451template <class T>
1452constexpr vec<T, 2> cross(const vec<T, 2> &a, T b) {
1453 return {a.y * b, -a.x * b};
1454}
1455template <class T>
1456constexpr vec<T, 3> cross(const vec<T, 3> &a, const vec<T, 3> &b) {
1457 return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x};
1458}
1459template <class T, int M>
1460constexpr T dot(const vec<T, M> &a, const vec<T, M> &b) {
1461 return sum(a * b);
1462}
1463template <class T, int M>
1464constexpr T length2(const vec<T, M> &a) {
1465 return dot(a, a);
1466}
1467template <class T, int M>
1468T length(const vec<T, M> &a) {
1469 return std::sqrt(length2(a));
1470}
1471template <class T, int M>
1472vec<T, M> normalize(const vec<T, M> &a) {
1473 return a / length(a);
1474}
1475template <class T, int M>
1476constexpr T distance2(const vec<T, M> &a, const vec<T, M> &b) {
1477 return length2(b - a);
1478}
1479template <class T, int M>
1480T distance(const vec<T, M> &a, const vec<T, M> &b) {
1481 return length(b - a);
1482}
1483template <class T, int M>
1484T uangle(const vec<T, M> &a, const vec<T, M> &b) {
1485 T d = dot(a, b);
1486 return d > 1 ? 0 : std::acos(d < -1 ? -1 : d);
1487}
1488template <class T, int M>
1489T angle(const vec<T, M> &a, const vec<T, M> &b) {
1490 return uangle(normalize(a), normalize(b));
1491}
1492template <class T>
1493vec<T, 2> rot(T a, const vec<T, 2> &v) {
1494 const T s = std::sin(a), c = std::cos(a);
1495 return {v.x * c - v.y * s, v.x * s + v.y * c};
1496}
1497template <class T>
1498vec<T, 3> rotx(T a, const vec<T, 3> &v) {
1499 const T s = std::sin(a), c = std::cos(a);
1500 return {v.x, v.y * c - v.z * s, v.y * s + v.z * c};
1501}
1502template <class T>
1503vec<T, 3> roty(T a, const vec<T, 3> &v) {
1504 const T s = std::sin(a), c = std::cos(a);
1505 return {v.x * c + v.z * s, v.y, -v.x * s + v.z * c};
1506}
1507template <class T>
1508vec<T, 3> rotz(T a, const vec<T, 3> &v) {
1509 const T s = std::sin(a), c = std::cos(a);
1510 return {v.x * c - v.y * s, v.x * s + v.y * c, v.z};
1511}
1512template <class T, int M>
1513vec<T, M> nlerp(const vec<T, M> &a, const vec<T, M> &b, T t) {
1514 return normalize(lerp(a, b, t));
1515}
1516template <class T, int M>
1517vec<T, M> slerp(const vec<T, M> &a, const vec<T, M> &b, T t) {
1518 T th = uangle(a, b);
1519 return th == 0 ? a
1520 : a * (std::sin(th * (1 - t)) / std::sin(th)) +
1521 b * (std::sin(th * t) / std::sin(th));
1522}
1523
1524// Support for quaternion algebra using 4D vectors, representing xi + yj + zk +
1525// w
1526template <class T>
1527constexpr vec<T, 4> qconj(const vec<T, 4> &q) {
1528 return {-q.x, -q.y, -q.z, q.w};
1529}
1530template <class T>
1531vec<T, 4> qinv(const vec<T, 4> &q) {
1532 return qconj(q) / length2(q);
1533}
1534template <class T>
1535vec<T, 4> qexp(const vec<T, 4> &q) {
1536 const auto v = q.xyz();
1537 const auto vv = length(v);
1538 return std::exp(q.w) *
1539 vec<T, 4>{v * (vv > 0 ? std::sin(vv) / vv : 0), std::cos(vv)};
1540}
1541template <class T>
1542vec<T, 4> qlog(const vec<T, 4> &q) {
1543 const auto v = q.xyz();
1544 const auto vv = length(v), qq = length(q);
1545 return {v * (vv > 0 ? std::acos(q.w / qq) / vv : 0), std::log(qq)};
1546}
1547template <class T>
1548vec<T, 4> qpow(const vec<T, 4> &q, const T &p) {
1549 const auto v = q.xyz();
1550 const auto vv = length(v), qq = length(q), th = std::acos(q.w / qq);
1551 return std::pow(qq, p) *
1552 vec<T, 4>{v * (vv > 0 ? std::sin(p * th) / vv : 0), std::cos(p * th)};
1553}
1554template <class T>
1555constexpr vec<T, 4> qmul(const vec<T, 4> &a, const vec<T, 4> &b) {
1556 return {a.x * b.w + a.w * b.x + a.y * b.z - a.z * b.y,
1557 a.y * b.w + a.w * b.y + a.z * b.x - a.x * b.z,
1558 a.z * b.w + a.w * b.z + a.x * b.y - a.y * b.x,
1559 a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z};
1560}
1561template <class T, class... R>
1562constexpr vec<T, 4> qmul(const vec<T, 4> &a, R... r) {
1563 return qmul(a, qmul(r...));
1564}
1565
1566// Support for 3D spatial rotations using quaternions, via qmul(qmul(q, v),
1567// qconj(q))
1568template <class T>
1569constexpr vec<T, 3> qxdir(const vec<T, 4> &q) {
1570 return {q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z,
1571 (q.x * q.y + q.z * q.w) * 2, (q.z * q.x - q.y * q.w) * 2};
1572}
1573template <class T>
1574constexpr vec<T, 3> qydir(const vec<T, 4> &q) {
1575 return {(q.x * q.y - q.z * q.w) * 2,
1576 q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z,
1577 (q.y * q.z + q.x * q.w) * 2};
1578}
1579template <class T>
1580constexpr vec<T, 3> qzdir(const vec<T, 4> &q) {
1581 return {(q.z * q.x + q.y * q.w) * 2, (q.y * q.z - q.x * q.w) * 2,
1582 q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z};
1583}
1584template <class T>
1585constexpr mat<T, 3, 3> qmat(const vec<T, 4> &q) {
1586 return {qxdir(q), qydir(q), qzdir(q)};
1587}
1588template <class T>
1589constexpr vec<T, 3> qrot(const vec<T, 4> &q, const vec<T, 3> &v) {
1590 return qxdir(q) * v.x + qydir(q) * v.y + qzdir(q) * v.z;
1591}
1592template <class T>
1593T qangle(const vec<T, 4> &q) {
1594 return std::atan2(length(q.xyz()), q.w) * 2;
1595}
1596template <class T>
1597vec<T, 3> qaxis(const vec<T, 4> &q) {
1598 return normalize(q.xyz());
1599}
1600template <class T>
1601vec<T, 4> qnlerp(const vec<T, 4> &a, const vec<T, 4> &b, T t) {
1602 return nlerp(a, dot(a, b) < 0 ? -b : b, t);
1603}
1604template <class T>
1605vec<T, 4> qslerp(const vec<T, 4> &a, const vec<T, 4> &b, T t) {
1606 return slerp(a, dot(a, b) < 0 ? -b : b, t);
1607}
1608
1609// Support for matrix algebra
1610template <class T, int M>
1611constexpr vec<T, M> mul(const vec<T, M> &a, const T &b) {
1612 return cmul(a, b);
1613}
1614template <class T, int M>
1615constexpr vec<T, M> mul(const T &b, const vec<T, M> &a) {
1616 return cmul(b, a);
1617}
1618template <class T, int M, int N>
1619constexpr mat<T, M, N> mul(const mat<T, M, N> &a, const T &b) {
1620 return cmul(a, b);
1621}
1622template <class T, int M, int N>
1623constexpr mat<T, M, N> mul(const T &b, const mat<T, M, N> &a) {
1624 return cmul(b, a);
1625}
1626template <class T, int M>
1627constexpr vec<T, M> mul(const vec<T, M> &a, const vec<T, M> &b) {
1628 return cmul(a, b);
1629}
1630template <class T, int M>
1631constexpr vec<T, M> mul(const mat<T, M, 1> &a, const vec<T, 1> &b) {
1632 return a.x * b.x;
1633}
1634template <class T, int M>
1635constexpr vec<T, M> mul(const mat<T, M, 2> &a, const vec<T, 2> &b) {
1636 return a.x * b.x + a.y * b.y;
1637}
1638template <class T, int M>
1639constexpr vec<T, M> mul(const mat<T, M, 3> &a, const vec<T, 3> &b) {
1640 return a.x * b.x + a.y * b.y + a.z * b.z;
1641}
1642template <class T, int M>
1643constexpr vec<T, M> mul(const mat<T, M, 4> &a, const vec<T, 4> &b) {
1644 return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
1645}
1646template <class T, int M, int N>
1647constexpr mat<T, M, 1> mul(const mat<T, M, N> &a, const mat<T, N, 1> &b) {
1648 return {mul(a, b.x)};
1649}
1650template <class T, int M, int N>
1651constexpr mat<T, M, 2> mul(const mat<T, M, N> &a, const mat<T, N, 2> &b) {
1652 return {mul(a, b.x), mul(a, b.y)};
1653}
1654template <class T, int M, int N>
1655constexpr mat<T, M, 3> mul(const mat<T, M, N> &a, const mat<T, N, 3> &b) {
1656 return {mul(a, b.x), mul(a, b.y), mul(a, b.z)};
1657}
1658template <class T, int M, int N>
1659constexpr mat<T, M, 4> mul(const mat<T, M, N> &a, const mat<T, N, 4> &b) {
1660 return {mul(a, b.x), mul(a, b.y), mul(a, b.z), mul(a, b.w)};
1661}
1662template <class T, int M, int N, int P>
1663constexpr vec<T, M> mul(const mat<T, M, N> &a, const mat<T, N, P> &b,
1664 const vec<T, P> &c) {
1665 return mul(mul(a, b), c);
1666}
1667template <class T, int M, int N, int P, int Q>
1668constexpr mat<T, M, Q> mul(const mat<T, M, N> &a, const mat<T, N, P> &b,
1669 const mat<T, P, Q> &c) {
1670 return mul(mul(a, b), c);
1671}
1672template <class T, int M, int N, int P, int Q>
1673constexpr vec<T, M> mul(const mat<T, M, N> &a, const mat<T, N, P> &b,
1674 const mat<T, P, Q> &c, const vec<T, Q> &d) {
1675 return mul(mul(a, b, c), d);
1676}
1677template <class T, int M, int N, int P, int Q, int R>
1678constexpr mat<T, M, R> mul(const mat<T, M, N> &a, const mat<T, N, P> &b,
1679 const mat<T, P, Q> &c, const mat<T, Q, R> &d) {
1680 return mul(mul(a, b, c), d);
1681}
1682template <class T, int M>
1683constexpr mat<T, M, 1> outerprod(const vec<T, M> &a, const vec<T, 1> &b) {
1684 return {a * b.x};
1685}
1686template <class T, int M>
1687constexpr mat<T, M, 2> outerprod(const vec<T, M> &a, const vec<T, 2> &b) {
1688 return {a * b.x, a * b.y};
1689}
1690template <class T, int M>
1691constexpr mat<T, M, 3> outerprod(const vec<T, M> &a, const vec<T, 3> &b) {
1692 return {a * b.x, a * b.y, a * b.z};
1693}
1694template <class T, int M>
1695constexpr mat<T, M, 4> outerprod(const vec<T, M> &a, const vec<T, 4> &b) {
1696 return {a * b.x, a * b.y, a * b.z, a * b.w};
1697}
1698template <class T>
1699constexpr vec<T, 1> diagonal(const mat<T, 1, 1> &a) {
1700 return {a.x.x};
1701}
1702template <class T>
1703constexpr vec<T, 2> diagonal(const mat<T, 2, 2> &a) {
1704 return {a.x.x, a.y.y};
1705}
1706template <class T>
1707constexpr vec<T, 3> diagonal(const mat<T, 3, 3> &a) {
1708 return {a.x.x, a.y.y, a.z.z};
1709}
1710template <class T>
1711constexpr vec<T, 4> diagonal(const mat<T, 4, 4> &a) {
1712 return {a.x.x, a.y.y, a.z.z, a.w.w};
1713}
1714template <class T, int N>
1715constexpr T trace(const mat<T, N, N> &a) {
1716 return sum(diagonal(a));
1717}
1718template <class T, int M>
1719constexpr mat<T, M, 1> transpose(const mat<T, 1, M> &m) {
1720 return {m.row(0)};
1721}
1722template <class T, int M>
1723constexpr mat<T, M, 2> transpose(const mat<T, 2, M> &m) {
1724 return {m.row(0), m.row(1)};
1725}
1726template <class T, int M>
1727constexpr mat<T, M, 3> transpose(const mat<T, 3, M> &m) {
1728 return {m.row(0), m.row(1), m.row(2)};
1729}
1730template <class T, int M>
1731constexpr mat<T, M, 4> transpose(const mat<T, 4, M> &m) {
1732 return {m.row(0), m.row(1), m.row(2), m.row(3)};
1733}
1734template <class T, int M>
1735constexpr mat<T, 1, M> transpose(const vec<T, M> &m) {
1736 return transpose(mat<T, M, 1>(m));
1737}
1738template <class T>
1739constexpr mat<T, 1, 1> adjugate(const mat<T, 1, 1> &a) {
1740 return {vec<T, 1>{1}};
1741}
1742template <class T>
1743constexpr mat<T, 2, 2> adjugate(const mat<T, 2, 2> &a) {
1744 return {{a.y.y, -a.x.y}, {-a.y.x, a.x.x}};
1745}
1746template <class T>
1747constexpr mat<T, 3, 3> adjugate(const mat<T, 3, 3> &a);
1748template <class T>
1749constexpr mat<T, 4, 4> adjugate(const mat<T, 4, 4> &a);
1750template <class T, int N>
1751constexpr mat<T, N, N> comatrix(const mat<T, N, N> &a) {
1752 return transpose(adjugate(a));
1753}
1754template <class T>
1755constexpr T determinant(const mat<T, 1, 1> &a) {
1756 return a.x.x;
1757}
1758template <class T>
1759constexpr T determinant(const mat<T, 2, 2> &a) {
1760 return a.x.x * a.y.y - a.x.y * a.y.x;
1761}
1762template <class T>
1763constexpr T determinant(const mat<T, 3, 3> &a) {
1764 return a.x.x * (a.y.y * a.z.z - a.z.y * a.y.z) +
1765 a.x.y * (a.y.z * a.z.x - a.z.z * a.y.x) +
1766 a.x.z * (a.y.x * a.z.y - a.z.x * a.y.y);
1767}
1768template <class T>
1769constexpr T determinant(const mat<T, 4, 4> &a);
1770template <class T, int N>
1771constexpr mat<T, N, N> inverse(const mat<T, N, N> &a) {
1772 return adjugate(a) / determinant(a);
1773}
1774
1775// Vectors and matrices can be used as ranges
1776template <class T, int M>
1777T *begin(vec<T, M> &a) {
1778 return &a.x;
1779}
1780template <class T, int M>
1781const T *begin(const vec<T, M> &a) {
1782 return &a.x;
1783}
1784template <class T, int M>
1785T *end(vec<T, M> &a) {
1786 return begin(a) + M;
1787}
1788template <class T, int M>
1789const T *end(const vec<T, M> &a) {
1790 return begin(a) + M;
1791}
1792template <class T, int M, int N>
1793vec<T, M> *begin(mat<T, M, N> &a) {
1794 return &a.x;
1795}
1796template <class T, int M, int N>
1797const vec<T, M> *begin(const mat<T, M, N> &a) {
1798 return &a.x;
1799}
1800template <class T, int M, int N>
1801vec<T, M> *end(mat<T, M, N> &a) {
1802 return begin(a) + N;
1803}
1804template <class T, int M, int N>
1805const vec<T, M> *end(const mat<T, M, N> &a) {
1806 return begin(a) + N;
1807}
1808
1809// Factory functions for 3D spatial transformations (will possibly be removed or
1810// changed in a future version)
1811enum fwd_axis {
1812 neg_z,
1813 pos_z
1814}; // Should projection matrices be generated assuming forward is {0,0,-1} or
1815 // {0,0,1}
1816enum z_range {
1817 neg_one_to_one,
1818 zero_to_one
1819}; // Should projection matrices map z into the range of [-1,1] or [0,1]?
1820template <class T>
1821vec<T, 4> constexpr rotation_quat(const vec<T, 3> &axis, T angle) {
1822 return {axis * std::sin(angle / 2), std::cos(angle / 2)};
1823}
1824template <class T>
1825vec<T, 4> constexpr rotation_quat(const vec<T, 3> &orig,
1826 const vec<T, 3> &dest) {
1827 T cosTheta = dot(orig, dest);
1828 if (cosTheta >= 1 - std::numeric_limits<T>::epsilon()) {
1829 return {0, 0, 0, 1};
1830 }
1831 if (cosTheta < -1 + std::numeric_limits<T>::epsilon()) {
1832 vec<T, 3> axis = cross(vec<T, 3>(0, 0, 1), orig);
1833 if (length2(axis) < std::numeric_limits<T>::epsilon())
1834 axis = cross(vec<T, 3>(1, 0, 0), orig);
1835 return rotation_quat(normalize(axis),
1836 3.14159265358979323846264338327950288);
1837 }
1838 vec<T, 3> axis = cross(orig, dest);
1839 T s = std::sqrt((1 + cosTheta) * 2);
1840 return {axis * (1 / s), s * 0.5};
1841}
1842template <class T>
1843vec<T, 4> rotation_quat(const mat<T, 3, 3> &m);
1844template <class T>
1845mat<T, 4, 4> translation_matrix(const vec<T, 3> &translation) {
1846 return {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {translation, 1}};
1847}
1848template <class T>
1849mat<T, 4, 4> rotation_matrix(const vec<T, 4> &rotation) {
1850 return {{qxdir(rotation), 0},
1851 {qydir(rotation), 0},
1852 {qzdir(rotation), 0},
1853 {0, 0, 0, 1}};
1854}
1855template <class T>
1856mat<T, 4, 4> scaling_matrix(const vec<T, 3> &scaling) {
1857 return {{scaling.x, 0, 0, 0},
1858 {0, scaling.y, 0, 0},
1859 {0, 0, scaling.z, 0},
1860 {0, 0, 0, 1}};
1861}
1862template <class T>
1863mat<T, 4, 4> pose_matrix(const vec<T, 4> &q, const vec<T, 3> &p) {
1864 return {{qxdir(q), 0}, {qydir(q), 0}, {qzdir(q), 0}, {p, 1}};
1865}
1866template <class T>
1867mat<T, 4, 4> lookat_matrix(const vec<T, 3> &eye, const vec<T, 3> &center,
1868 const vec<T, 3> &view_y_dir, fwd_axis fwd = neg_z);
1869template <class T>
1870mat<T, 4, 4> frustum_matrix(T x0, T x1, T y0, T y1, T n, T f,
1871 fwd_axis a = neg_z, z_range z = neg_one_to_one);
1872template <class T>
1873mat<T, 4, 4> perspective_matrix(T fovy, T aspect, T n, T f, fwd_axis a = neg_z,
1874 z_range z = neg_one_to_one) {
1875 T y = n * std::tan(fovy / 2), x = y * aspect;
1876 return frustum_matrix(-x, x, -y, y, n, f, a, z);
1877}
1878
1879// Provide implicit conversion between linalg::vec<T,M> and std::array<T,M>
1880template <class T>
1881struct converter<vec<T, 1>, std::array<T, 1>> {
1882 vec<T, 1> operator()(const std::array<T, 1> &a) const { return {a[0]}; }
1883};
1884template <class T>
1885struct converter<vec<T, 2>, std::array<T, 2>> {
1886 vec<T, 2> operator()(const std::array<T, 2> &a) const { return {a[0], a[1]}; }
1887};
1888template <class T>
1889struct converter<vec<T, 3>, std::array<T, 3>> {
1890 vec<T, 3> operator()(const std::array<T, 3> &a) const {
1891 return {a[0], a[1], a[2]};
1892 }
1893};
1894template <class T>
1895struct converter<vec<T, 4>, std::array<T, 4>> {
1896 vec<T, 4> operator()(const std::array<T, 4> &a) const {
1897 return {a[0], a[1], a[2], a[3]};
1898 }
1899};
1900
1901template <class T>
1902struct converter<std::array<T, 1>, vec<T, 1>> {
1903 std::array<T, 1> operator()(const vec<T, 1> &a) const { return {a[0]}; }
1904};
1905template <class T>
1906struct converter<std::array<T, 2>, vec<T, 2>> {
1907 std::array<T, 2> operator()(const vec<T, 2> &a) const { return {a[0], a[1]}; }
1908};
1909template <class T>
1910struct converter<std::array<T, 3>, vec<T, 3>> {
1911 std::array<T, 3> operator()(const vec<T, 3> &a) const {
1912 return {a[0], a[1], a[2]};
1913 }
1914};
1915template <class T>
1916struct converter<std::array<T, 4>, vec<T, 4>> {
1917 std::array<T, 4> operator()(const vec<T, 4> &a) const {
1918 return {a[0], a[1], a[2], a[3]};
1919 }
1920};
1921} // namespace linalg
1922
1923namespace std {
1924// Provide specializations for std::hash<...> with linalg types
1925template <class T>
1926struct hash<linalg::vec<T, 1>> {
1927 std::size_t operator()(const linalg::vec<T, 1> &v) const {
1928 std::hash<T> h;
1929 return h(v.x);
1930 }
1931};
1932template <class T>
1933struct hash<linalg::vec<T, 2>> {
1934 std::size_t operator()(const linalg::vec<T, 2> &v) const {
1935 std::hash<T> h;
1936 return h(v.x) ^ (h(v.y) << 1);
1937 }
1938};
1939template <class T>
1940struct hash<linalg::vec<T, 3>> {
1941 std::size_t operator()(const linalg::vec<T, 3> &v) const {
1942 std::hash<T> h;
1943 return h(v.x) ^ (h(v.y) << 1) ^ (h(v.z) << 2);
1944 }
1945};
1946template <class T>
1947struct hash<linalg::vec<T, 4>> {
1948 std::size_t operator()(const linalg::vec<T, 4> &v) const {
1949 std::hash<T> h;
1950 return h(v.x) ^ (h(v.y) << 1) ^ (h(v.z) << 2) ^ (h(v.w) << 3);
1951 }
1952};
1953
1954template <class T, int M>
1955struct hash<linalg::mat<T, M, 1>> {
1956 std::size_t operator()(const linalg::mat<T, M, 1> &v) const {
1957 std::hash<linalg::vec<T, M>> h;
1958 return h(v.x);
1959 }
1960};
1961template <class T, int M>
1962struct hash<linalg::mat<T, M, 2>> {
1963 std::size_t operator()(const linalg::mat<T, M, 2> &v) const {
1964 std::hash<linalg::vec<T, M>> h;
1965 return h(v.x) ^ (h(v.y) << M);
1966 }
1967};
1968template <class T, int M>
1969struct hash<linalg::mat<T, M, 3>> {
1970 std::size_t operator()(const linalg::mat<T, M, 3> &v) const {
1971 std::hash<linalg::vec<T, M>> h;
1972 return h(v.x) ^ (h(v.y) << M) ^ (h(v.z) << (M * 2));
1973 }
1974};
1975template <class T, int M>
1976struct hash<linalg::mat<T, M, 4>> {
1977 std::size_t operator()(const linalg::mat<T, M, 4> &v) const {
1978 std::hash<linalg::vec<T, M>> h;
1979 return h(v.x) ^ (h(v.y) << M) ^ (h(v.z) << (M * 2)) ^ (h(v.w) << (M * 3));
1980 }
1981};
1982} // namespace std
1983
1984// Definitions of functions too long to be defined inline
1985template <class T>
1986constexpr linalg::mat<T, 3, 3> linalg::adjugate(const mat<T, 3, 3> &a) {
1987 return {{a.y.y * a.z.z - a.z.y * a.y.z, a.z.y * a.x.z - a.x.y * a.z.z,
1988 a.x.y * a.y.z - a.y.y * a.x.z},
1989 {a.y.z * a.z.x - a.z.z * a.y.x, a.z.z * a.x.x - a.x.z * a.z.x,
1990 a.x.z * a.y.x - a.y.z * a.x.x},
1991 {a.y.x * a.z.y - a.z.x * a.y.y, a.z.x * a.x.y - a.x.x * a.z.y,
1992 a.x.x * a.y.y - a.y.x * a.x.y}};
1993}
1994
1995template <class T>
1996constexpr linalg::mat<T, 4, 4> linalg::adjugate(const mat<T, 4, 4> &a) {
1997 return {{a.y.y * a.z.z * a.w.w + a.w.y * a.y.z * a.z.w +
1998 a.z.y * a.w.z * a.y.w - a.y.y * a.w.z * a.z.w -
1999 a.z.y * a.y.z * a.w.w - a.w.y * a.z.z * a.y.w,
2000 a.x.y * a.w.z * a.z.w + a.z.y * a.x.z * a.w.w +
2001 a.w.y * a.z.z * a.x.w - a.w.y * a.x.z * a.z.w -
2002 a.z.y * a.w.z * a.x.w - a.x.y * a.z.z * a.w.w,
2003 a.x.y * a.y.z * a.w.w + a.w.y * a.x.z * a.y.w +
2004 a.y.y * a.w.z * a.x.w - a.x.y * a.w.z * a.y.w -
2005 a.y.y * a.x.z * a.w.w - a.w.y * a.y.z * a.x.w,
2006 a.x.y * a.z.z * a.y.w + a.y.y * a.x.z * a.z.w +
2007 a.z.y * a.y.z * a.x.w - a.x.y * a.y.z * a.z.w -
2008 a.z.y * a.x.z * a.y.w - a.y.y * a.z.z * a.x.w},
2009 {a.y.z * a.w.w * a.z.x + a.z.z * a.y.w * a.w.x +
2010 a.w.z * a.z.w * a.y.x - a.y.z * a.z.w * a.w.x -
2011 a.w.z * a.y.w * a.z.x - a.z.z * a.w.w * a.y.x,
2012 a.x.z * a.z.w * a.w.x + a.w.z * a.x.w * a.z.x +
2013 a.z.z * a.w.w * a.x.x - a.x.z * a.w.w * a.z.x -
2014 a.z.z * a.x.w * a.w.x - a.w.z * a.z.w * a.x.x,
2015 a.x.z * a.w.w * a.y.x + a.y.z * a.x.w * a.w.x +
2016 a.w.z * a.y.w * a.x.x - a.x.z * a.y.w * a.w.x -
2017 a.w.z * a.x.w * a.y.x - a.y.z * a.w.w * a.x.x,
2018 a.x.z * a.y.w * a.z.x + a.z.z * a.x.w * a.y.x +
2019 a.y.z * a.z.w * a.x.x - a.x.z * a.z.w * a.y.x -
2020 a.y.z * a.x.w * a.z.x - a.z.z * a.y.w * a.x.x},
2021 {a.y.w * a.z.x * a.w.y + a.w.w * a.y.x * a.z.y +
2022 a.z.w * a.w.x * a.y.y - a.y.w * a.w.x * a.z.y -
2023 a.z.w * a.y.x * a.w.y - a.w.w * a.z.x * a.y.y,
2024 a.x.w * a.w.x * a.z.y + a.z.w * a.x.x * a.w.y +
2025 a.w.w * a.z.x * a.x.y - a.x.w * a.z.x * a.w.y -
2026 a.w.w * a.x.x * a.z.y - a.z.w * a.w.x * a.x.y,
2027 a.x.w * a.y.x * a.w.y + a.w.w * a.x.x * a.y.y +
2028 a.y.w * a.w.x * a.x.y - a.x.w * a.w.x * a.y.y -
2029 a.y.w * a.x.x * a.w.y - a.w.w * a.y.x * a.x.y,
2030 a.x.w * a.z.x * a.y.y + a.y.w * a.x.x * a.z.y +
2031 a.z.w * a.y.x * a.x.y - a.x.w * a.y.x * a.z.y -
2032 a.z.w * a.x.x * a.y.y - a.y.w * a.z.x * a.x.y},
2033 {a.y.x * a.w.y * a.z.z + a.z.x * a.y.y * a.w.z +
2034 a.w.x * a.z.y * a.y.z - a.y.x * a.z.y * a.w.z -
2035 a.w.x * a.y.y * a.z.z - a.z.x * a.w.y * a.y.z,
2036 a.x.x * a.z.y * a.w.z + a.w.x * a.x.y * a.z.z +
2037 a.z.x * a.w.y * a.x.z - a.x.x * a.w.y * a.z.z -
2038 a.z.x * a.x.y * a.w.z - a.w.x * a.z.y * a.x.z,
2039 a.x.x * a.w.y * a.y.z + a.y.x * a.x.y * a.w.z +
2040 a.w.x * a.y.y * a.x.z - a.x.x * a.y.y * a.w.z -
2041 a.w.x * a.x.y * a.y.z - a.y.x * a.w.y * a.x.z,
2042 a.x.x * a.y.y * a.z.z + a.z.x * a.x.y * a.y.z +
2043 a.y.x * a.z.y * a.x.z - a.x.x * a.z.y * a.y.z -
2044 a.y.x * a.x.y * a.z.z - a.z.x * a.y.y * a.x.z}};
2045}
2046
2047template <class T>
2048constexpr T linalg::determinant(const mat<T, 4, 4> &a) {
2049 return a.x.x * (a.y.y * a.z.z * a.w.w + a.w.y * a.y.z * a.z.w +
2050 a.z.y * a.w.z * a.y.w - a.y.y * a.w.z * a.z.w -
2051 a.z.y * a.y.z * a.w.w - a.w.y * a.z.z * a.y.w) +
2052 a.x.y * (a.y.z * a.w.w * a.z.x + a.z.z * a.y.w * a.w.x +
2053 a.w.z * a.z.w * a.y.x - a.y.z * a.z.w * a.w.x -
2054 a.w.z * a.y.w * a.z.x - a.z.z * a.w.w * a.y.x) +
2055 a.x.z * (a.y.w * a.z.x * a.w.y + a.w.w * a.y.x * a.z.y +
2056 a.z.w * a.w.x * a.y.y - a.y.w * a.w.x * a.z.y -
2057 a.z.w * a.y.x * a.w.y - a.w.w * a.z.x * a.y.y) +
2058 a.x.w * (a.y.x * a.w.y * a.z.z + a.z.x * a.y.y * a.w.z +
2059 a.w.x * a.z.y * a.y.z - a.y.x * a.z.y * a.w.z -
2060 a.w.x * a.y.y * a.z.z - a.z.x * a.w.y * a.y.z);
2061}
2062
2063template <class T>
2064linalg::vec<T, 4> linalg::rotation_quat(const mat<T, 3, 3> &m) {
2065 const vec<T, 4> q{m.x.x - m.y.y - m.z.z, m.y.y - m.x.x - m.z.z,
2066 m.z.z - m.x.x - m.y.y, m.x.x + m.y.y + m.z.z},
2067 s[]{{1, m.x.y + m.y.x, m.z.x + m.x.z, m.y.z - m.z.y},
2068 {m.x.y + m.y.x, 1, m.y.z + m.z.y, m.z.x - m.x.z},
2069 {m.x.z + m.z.x, m.y.z + m.z.y, 1, m.x.y - m.y.x},
2070 {m.y.z - m.z.y, m.z.x - m.x.z, m.x.y - m.y.x, 1}};
2071 return copysign(normalize(sqrt(max(T(0), T(1) + q))), s[argmax(q)]);
2072}
2073
2074template <class T>
2075linalg::mat<T, 4, 4> linalg::lookat_matrix(const vec<T, 3> &eye,
2076 const vec<T, 3> &center,
2077 const vec<T, 3> &view_y_dir,
2078 fwd_axis a) {
2079 const vec<T, 3> f = normalize(center - eye), z = a == pos_z ? f : -f,
2080 x = normalize(cross(view_y_dir, z)), y = cross(z, x);
2081 return inverse(mat<T, 4, 4>{{x, 0}, {y, 0}, {z, 0}, {eye, 1}});
2082}
2083
2084template <class T>
2085linalg::mat<T, 4, 4> linalg::frustum_matrix(T x0, T x1, T y0, T y1, T n, T f,
2086 fwd_axis a, z_range z) {
2087 const T s = a == pos_z ? T(1) : T(-1), o = z == neg_one_to_one ? n : 0;
2088 return {{2 * n / (x1 - x0), 0, 0, 0},
2089 {0, 2 * n / (y1 - y0), 0, 0},
2090 {-s * (x0 + x1) / (x1 - x0), -s * (y0 + y1) / (y1 - y0),
2091 s * (f + o) / (f - n), s},
2092 {0, 0, -(n + o) * f / (f - n), 0}};
2093}
2094
2095#endif
Definition linalg.h:79
Definition linalg.h:131
Definition linalg.h:294
Definition linalg.h:462
Definition linalg.h:278
Definition linalg.h:206
Definition linalg.h:478
Definition linalg.h:240
Definition linalg.h:455
Definition linalg.h:448
Definition linalg.h:529
Definition linalg.h:607
Definition linalg.h:505
Definition linalg.h:517
Definition linalg.h:577
Definition linalg.h:571
Definition linalg.h:559
Definition linalg.h:589
Definition linalg.h:565
Definition linalg.h:541
Definition linalg.h:553
Definition linalg.h:523
Definition linalg.h:511
Definition linalg.h:583
Definition linalg.h:493
Definition linalg.h:499
Definition linalg.h:613
Definition linalg.h:487
Definition linalg.h:547
Definition linalg.h:535
Definition linalg.h:601
Definition linalg.h:595
Definition linalg.h:101
Definition linalg.h:88
Definition linalg.h:280
Definition linalg.h:471
Definition linalg.h:238
Definition linalg.h:627
Definition linalg.h:699
Definition linalg.h:693
Definition linalg.h:747
Definition linalg.h:705
Definition linalg.h:639
Definition linalg.h:753
Definition linalg.h:681
Definition linalg.h:717
Definition linalg.h:645
Definition linalg.h:633
Definition linalg.h:735
Definition linalg.h:621
Definition linalg.h:663
Definition linalg.h:657
Definition linalg.h:651
Definition linalg.h:741
Definition linalg.h:729
Definition linalg.h:675
Definition linalg.h:711
Definition linalg.h:669
Definition linalg.h:687
Definition linalg.h:723
Definition linalg.h:994
Definition linalg.h:74
Definition linalg.h:69