Manifold 3.0
Robust geometry
 
Loading...
Searching...
No Matches
linalg.h
1// Copyright 2024 The Manifold Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// Based on linalg.h - 2.2 - Single-header public domain linear algebra library
16//
17// The intent of this library is to provide the bulk of the functionality
18// you need to write programs that frequently use small, fixed-size vectors
19// and matrices, in domains such as computational geometry or computer
20// graphics. It strives for terse, readable source code.
21//
22// The original author of this software is Sterling Orsten, and its permanent
23// home is <http://github.com/sgorsten/linalg/>. If you find this software
24// useful, an acknowledgement in your source text and/or product documentation
25// is appreciated, but not required.
26//
27// The author acknowledges significant insights and contributions by:
28// Stan Melax <http://github.com/melax/>
29// Dimitri Diakopoulos <http://github.com/ddiakopoulos/>
30//
31// Some features are deprecated. Define LINALG_FORWARD_COMPATIBLE to remove
32// them.
33
34#pragma once
35#ifndef LINALG_H
36#define LINALG_H
37
38#include <array> // For std::array
39#include <cmath> // For various unary math functions, such as std::sqrt
40#include <cstdint> // For implementing namespace linalg::aliases
41#include <cstdlib> // To resolve std::abs ambiguity on clang
42#include <functional> // For std::hash declaration
43#include <iosfwd> // For forward definitions of std::ostream
44#include <type_traits> // For std::enable_if, std::is_same, std::declval
45
46#ifdef MANIFOLD_DEBUG
47#include <iomanip>
48#include <iostream>
49#endif
50
51// In Visual Studio 2015, `constexpr` applied to a member function implies
52// `const`, which causes ambiguous overload resolution
53#if defined(_MSC_VER) && (_MSC_VER <= 1900)
54#define LINALG_CONSTEXPR14
55#else
56#define LINALG_CONSTEXPR14 constexpr
57#endif
58
59namespace linalg {
60// Small, fixed-length vector type, consisting of exactly M elements of type T,
61// and presumed to be a column-vector unless otherwise noted.
62template <class T, int M>
63struct vec;
64
65// Small, fixed-size matrix type, consisting of exactly M rows and N columns of
66// type T, stored in column-major order.
67template <class T, int M, int N>
68struct mat;
69
70// Specialize converter<T,U> with a function application operator that converts
71// type U to type T to enable implicit conversions
72template <class T, class U>
73struct converter {};
74namespace detail {
75template <class T, class U>
76using conv_t = typename std::enable_if<!std::is_same<T, U>::value,
77 decltype(converter<T, U>{}(
78 std::declval<U>()))>::type;
79
80// Trait for retrieving scalar type of any linear algebra object
81template <class A>
82struct scalar_type {};
83template <class T, int M>
84struct scalar_type<vec<T, M>> {
85 using type = T;
86};
87template <class T, int M, int N>
88struct scalar_type<mat<T, M, N>> {
89 using type = T;
90};
91
92// Type returned by the compare(...) function which supports all six comparison
93// operators against 0
94template <class T>
95struct ord {
96 T a, b;
97};
98template <class T>
99constexpr bool operator==(const ord<T> &o, std::nullptr_t) {
100 return o.a == o.b;
101}
102template <class T>
103constexpr bool operator!=(const ord<T> &o, std::nullptr_t) {
104 return !(o.a == o.b);
105}
106template <class T>
107constexpr bool operator<(const ord<T> &o, std::nullptr_t) {
108 return o.a < o.b;
109}
110template <class T>
111constexpr bool operator>(const ord<T> &o, std::nullptr_t) {
112 return o.b < o.a;
113}
114template <class T>
115constexpr bool operator<=(const ord<T> &o, std::nullptr_t) {
116 return !(o.b < o.a);
117}
118template <class T>
119constexpr bool operator>=(const ord<T> &o, std::nullptr_t) {
120 return !(o.a < o.b);
121}
122
123// Patterns which can be used with the compare(...) function
124template <class A, class B>
125struct any_compare {};
126template <class T>
127struct any_compare<vec<T, 1>, vec<T, 1>> {
128 using type = ord<T>;
129 constexpr ord<T> operator()(const vec<T, 1> &a, const vec<T, 1> &b) const {
130 return ord<T>{a.x, b.x};
131 }
132};
133template <class T>
134struct any_compare<vec<T, 2>, vec<T, 2>> {
135 using type = ord<T>;
136 constexpr ord<T> operator()(const vec<T, 2> &a, const vec<T, 2> &b) const {
137 return !(a.x == b.x) ? ord<T>{a.x, b.x} : ord<T>{a.y, b.y};
138 }
139};
140template <class T>
141struct any_compare<vec<T, 3>, vec<T, 3>> {
142 using type = ord<T>;
143 constexpr ord<T> operator()(const vec<T, 3> &a, const vec<T, 3> &b) const {
144 return !(a.x == b.x) ? ord<T>{a.x, b.x}
145 : !(a.y == b.y) ? ord<T>{a.y, b.y}
146 : ord<T>{a.z, b.z};
147 }
148};
149template <class T>
150struct any_compare<vec<T, 4>, vec<T, 4>> {
151 using type = ord<T>;
152 constexpr ord<T> operator()(const vec<T, 4> &a, const vec<T, 4> &b) const {
153 return !(a.x == b.x) ? ord<T>{a.x, b.x}
154 : !(a.y == b.y) ? ord<T>{a.y, b.y}
155 : !(a.z == b.z) ? ord<T>{a.z, b.z}
156 : ord<T>{a.w, b.w};
157 }
158};
159template <class T, int M>
160struct any_compare<mat<T, M, 1>, mat<T, M, 1>> {
161 using type = ord<T>;
162 constexpr ord<T> operator()(const mat<T, M, 1> &a,
163 const mat<T, M, 1> &b) const {
164 return compare(a.x, b.x);
165 }
166};
167template <class T, int M>
168struct any_compare<mat<T, M, 2>, mat<T, M, 2>> {
169 using type = ord<T>;
170 constexpr ord<T> operator()(const mat<T, M, 2> &a,
171 const mat<T, M, 2> &b) const {
172 return a.x != b.x ? compare(a.x, b.x) : compare(a.y, b.y);
173 }
174};
175template <class T, int M>
176struct any_compare<mat<T, M, 3>, mat<T, M, 3>> {
177 using type = ord<T>;
178 constexpr ord<T> operator()(const mat<T, M, 3> &a,
179 const mat<T, M, 3> &b) const {
180 return a.x != b.x ? compare(a.x, b.x)
181 : a.y != b.y ? compare(a.y, b.y)
182 : compare(a.z, b.z);
183 }
184};
185template <class T, int M>
186struct any_compare<mat<T, M, 4>, mat<T, M, 4>> {
187 using type = ord<T>;
188 constexpr ord<T> operator()(const mat<T, M, 4> &a,
189 const mat<T, M, 4> &b) const {
190 return a.x != b.x ? compare(a.x, b.x)
191 : a.y != b.y ? compare(a.y, b.y)
192 : a.z != b.z ? compare(a.z, b.z)
193 : compare(a.w, b.w);
194 }
195};
196
197// Helper for compile-time index-based access to members of vector and matrix
198// types
199template <int I>
200struct getter;
201template <>
202struct getter<0> {
203 template <class A>
204 constexpr auto operator()(A &a) const -> decltype(a.x) {
205 return a.x;
206 }
207};
208template <>
209struct getter<1> {
210 template <class A>
211 constexpr auto operator()(A &a) const -> decltype(a.y) {
212 return a.y;
213 }
214};
215template <>
216struct getter<2> {
217 template <class A>
218 constexpr auto operator()(A &a) const -> decltype(a.z) {
219 return a.z;
220 }
221};
222template <>
223struct getter<3> {
224 template <class A>
225 constexpr auto operator()(A &a) const -> decltype(a.w) {
226 return a.w;
227 }
228};
229
230// Stand-in for std::integer_sequence/std::make_integer_sequence
231template <int... I>
232struct seq {};
233template <int A, int N>
235template <int A>
236struct make_seq_impl<A, 0> {
237 using type = seq<>;
238};
239template <int A>
240struct make_seq_impl<A, 1> {
241 using type = seq<A + 0>;
242};
243template <int A>
244struct make_seq_impl<A, 2> {
245 using type = seq<A + 0, A + 1>;
246};
247template <int A>
248struct make_seq_impl<A, 3> {
250};
251template <int A>
252struct make_seq_impl<A, 4> {
254};
255template <int A, int B>
256using make_seq = typename make_seq_impl<A, B - A>::type;
257template <class T, int M, int... I>
258vec<T, sizeof...(I)> constexpr swizzle(const vec<T, M> &v, seq<I...> i) {
259 return {getter<I>{}(v)...};
260}
261template <class T, int M, int N, int... I, int... J>
262mat<T, sizeof...(I), sizeof...(J)> constexpr swizzle(const mat<T, M, N> &m,
263 seq<I...> i, seq<J...> j) {
264 return {swizzle(getter<J>{}(m), i)...};
265}
266
267// SFINAE helpers to determine result of function application
268template <class F, class... T>
269using ret_t = decltype(std::declval<F>()(std::declval<T>()...));
270
271// SFINAE helper which is defined if all provided types are scalars
272struct empty {};
273template <class... T>
274struct scalars;
275template <>
276struct scalars<> {
277 using type = void;
278};
279template <class T, class... U>
280struct scalars<T, U...> : std::conditional<std::is_arithmetic<T>::value,
281 scalars<U...>, empty>::type {};
282template <class... T>
283using scalars_t = typename scalars<T...>::type;
284
285// Helpers which indicate how apply(F, ...) should be called for various
286// arguments
287template <class F, class Void, class... T>
288struct apply {}; // Patterns which contain only vectors or scalars
289template <class F, int M, class A>
290struct apply<F, scalars_t<>, vec<A, M>> {
291 using type = vec<ret_t<F, A>, M>;
292 enum { size = M, mm = 0 };
293 template <int... I>
294 static constexpr type impl(seq<I...>, F f, const vec<A, M> &a) {
295 return {f(getter<I>{}(a))...};
296 }
297};
298template <class F, int M, class A, class B>
299struct apply<F, scalars_t<>, vec<A, M>, vec<B, M>> {
300 using type = vec<ret_t<F, A, B>, M>;
301 enum { size = M, mm = 0 };
302 template <int... I>
303 static constexpr type impl(seq<I...>, F f, const vec<A, M> &a,
304 const vec<B, M> &b) {
305 return {f(getter<I>{}(a), getter<I>{}(b))...};
306 }
307};
308template <class F, int M, class A, class B>
309struct apply<F, scalars_t<B>, vec<A, M>, B> {
310 using type = vec<ret_t<F, A, B>, M>;
311 enum { size = M, mm = 0 };
312 template <int... I>
313 static constexpr type impl(seq<I...>, F f, const vec<A, M> &a, B b) {
314 return {f(getter<I>{}(a), b)...};
315 }
316};
317template <class F, int M, class A, class B>
318struct apply<F, scalars_t<A>, A, vec<B, M>> {
319 using type = vec<ret_t<F, A, B>, M>;
320 enum { size = M, mm = 0 };
321 template <int... I>
322 static constexpr type impl(seq<I...>, F f, A a, const vec<B, M> &b) {
323 return {f(a, getter<I>{}(b))...};
324 }
325};
326template <class F, int M, class A, class B, class C>
327struct apply<F, scalars_t<>, vec<A, M>, vec<B, M>, vec<C, M>> {
328 using type = vec<ret_t<F, A, B, C>, M>;
329 enum { size = M, mm = 0 };
330 template <int... I>
331 static constexpr type impl(seq<I...>, F f, const vec<A, M> &a,
332 const vec<B, M> &b, const vec<C, M> &c) {
333 return {f(getter<I>{}(a), getter<I>{}(b), getter<I>{}(c))...};
334 }
335};
336template <class F, int M, class A, class B, class C>
337struct apply<F, scalars_t<C>, vec<A, M>, vec<B, M>, C> {
338 using type = vec<ret_t<F, A, B, C>, M>;
339 enum { size = M, mm = 0 };
340 template <int... I>
341 static constexpr type impl(seq<I...>, F f, const vec<A, M> &a,
342 const vec<B, M> &b, C c) {
343 return {f(getter<I>{}(a), getter<I>{}(b), c)...};
344 }
345};
346template <class F, int M, class A, class B, class C>
347struct apply<F, scalars_t<B>, vec<A, M>, B, vec<C, M>> {
348 using type = vec<ret_t<F, A, B, C>, M>;
349 enum { size = M, mm = 0 };
350 template <int... I>
351 static constexpr type impl(seq<I...>, F f, const vec<A, M> &a, B b,
352 const vec<C, M> &c) {
353 return {f(getter<I>{}(a), b, getter<I>{}(c))...};
354 }
355};
356template <class F, int M, class A, class B, class C>
357struct apply<F, scalars_t<B, C>, vec<A, M>, B, C> {
358 using type = vec<ret_t<F, A, B, C>, M>;
359 enum { size = M, mm = 0 };
360 template <int... I>
361 static constexpr type impl(seq<I...>, F f, const vec<A, M> &a, B b, C c) {
362 return {f(getter<I>{}(a), b, c)...};
363 }
364};
365template <class F, int M, class A, class B, class C>
366struct apply<F, scalars_t<A>, A, vec<B, M>, vec<C, M>> {
367 using type = vec<ret_t<F, A, B, C>, M>;
368 enum { size = M, mm = 0 };
369 template <int... I>
370 static constexpr type impl(seq<I...>, F f, A a, const vec<B, M> &b,
371 const vec<C, M> &c) {
372 return {f(a, getter<I>{}(b), getter<I>{}(c))...};
373 }
374};
375template <class F, int M, class A, class B, class C>
376struct apply<F, scalars_t<A, C>, A, vec<B, M>, C> {
377 using type = vec<ret_t<F, A, B, C>, M>;
378 enum { size = M, mm = 0 };
379 template <int... I>
380 static constexpr type impl(seq<I...>, F f, A a, const vec<B, M> &b, C c) {
381 return {f(a, getter<I>{}(b), c)...};
382 }
383};
384template <class F, int M, class A, class B, class C>
385struct apply<F, scalars_t<A, B>, A, B, vec<C, M>> {
386 using type = vec<ret_t<F, A, B, C>, M>;
387 enum { size = M, mm = 0 };
388 template <int... I>
389 static constexpr type impl(seq<I...>, F f, A a, B b, const vec<C, M> &c) {
390 return {f(a, b, getter<I>{}(c))...};
391 }
392};
393template <class F, int M, int N, class A>
394struct apply<F, scalars_t<>, mat<A, M, N>> {
395 using type = mat<ret_t<F, A>, M, N>;
396 enum { size = N, mm = 0 };
397 template <int... J>
398 static constexpr type impl(seq<J...>, F f, const mat<A, M, N> &a) {
399 return {apply<F, void, vec<A, M>>::impl(make_seq<0, M>{}, f,
400 getter<J>{}(a))...};
401 }
402};
403template <class F, int M, int N, class A, class B>
404struct apply<F, scalars_t<>, mat<A, M, N>, mat<B, M, N>> {
405 using type = mat<ret_t<F, A, B>, M, N>;
406 enum { size = N, mm = 1 };
407 template <int... J>
408 static constexpr type impl(seq<J...>, F f, const mat<A, M, N> &a,
409 const mat<B, M, N> &b) {
410 return {apply<F, void, vec<A, M>, vec<B, M>>::impl(
411 make_seq<0, M>{}, f, getter<J>{}(a), getter<J>{}(b))...};
412 }
413};
414template <class F, int M, int N, class A, class B>
415struct apply<F, scalars_t<B>, mat<A, M, N>, B> {
416 using type = mat<ret_t<F, A, B>, M, N>;
417 enum { size = N, mm = 0 };
418 template <int... J>
419 static constexpr type impl(seq<J...>, F f, const mat<A, M, N> &a, B b) {
420 return {apply<F, void, vec<A, M>, B>::impl(make_seq<0, M>{}, f,
421 getter<J>{}(a), b)...};
422 }
423};
424template <class F, int M, int N, class A, class B>
425struct apply<F, scalars_t<A>, A, mat<B, M, N>> {
426 using type = mat<ret_t<F, A, B>, M, N>;
427 enum { size = N, mm = 0 };
428 template <int... J>
429 static constexpr type impl(seq<J...>, F f, A a, const mat<B, M, N> &b) {
430 return {apply<F, void, A, vec<B, M>>::impl(make_seq<0, M>{}, f, a,
431 getter<J>{}(b))...};
432 }
433};
434template <class F, class... A>
435struct apply<F, scalars_t<A...>, A...> {
436 using type = ret_t<F, A...>;
437 enum { size = 0, mm = 0 };
438 static constexpr type impl(seq<>, F f, A... a) { return f(a...); }
439};
440
441// Function objects for selecting between alternatives
442struct min {
443 template <class A, class B>
444 constexpr auto operator()(A a, B b) const ->
445 typename std::remove_reference<decltype(a < b ? a : b)>::type {
446 return a < b ? a : b;
447 }
448};
449struct max {
450 template <class A, class B>
451 constexpr auto operator()(A a, B b) const ->
452 typename std::remove_reference<decltype(a < b ? b : a)>::type {
453 return a < b ? b : a;
454 }
455};
456struct clamp {
457 template <class A, class B, class C>
458 constexpr auto operator()(A a, B b, C c) const ->
459 typename std::remove_reference<decltype(a < b ? b
460 : a < c ? a
461 : c)>::type {
462 return a < b ? b : a < c ? a : c;
463 }
464};
465struct select {
466 template <class A, class B, class C>
467 constexpr auto operator()(A a, B b, C c) const ->
468 typename std::remove_reference<decltype(a ? b : c)>::type {
469 return a ? b : c;
470 }
471};
472struct lerp {
473 template <class A, class B, class C>
474 constexpr auto operator()(A a, B b,
475 C c) const -> decltype(a * (1 - c) + b * c) {
476 return a * (1 - c) + b * c;
477 }
478};
479
480// Function objects for applying operators
481struct op_pos {
482 template <class A>
483 constexpr auto operator()(A a) const -> decltype(+a) {
484 return +a;
485 }
486};
487struct op_neg {
488 template <class A>
489 constexpr auto operator()(A a) const -> decltype(-a) {
490 return -a;
491 }
492};
493struct op_not {
494 template <class A>
495 constexpr auto operator()(A a) const -> decltype(!a) {
496 return !a;
497 }
498};
499struct op_cmp {
500 template <class A>
501 constexpr auto operator()(A a) const -> decltype(~(a)) {
502 return ~a;
503 }
504};
505struct op_mul {
506 template <class A, class B>
507 constexpr auto operator()(A a, B b) const -> decltype(a * b) {
508 return a * b;
509 }
510};
511struct op_div {
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_mod {
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_add {
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_sub {
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_lsh {
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_rsh {
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_lt {
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_gt {
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_le {
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_ge {
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_eq {
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_ne {
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_int {
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_xor {
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_un {
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_and {
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_or {
608 template <class A, class B>
609 constexpr auto operator()(A a, B b) const -> decltype(a || b) {
610 return a || b;
611 }
612};
613
614// Function objects for applying standard library math functions
616 template <class A>
617 constexpr auto operator()(A a) const -> decltype(std::isfinite(a)) {
618 return std::isfinite(a);
619 }
620};
621struct std_abs {
622 template <class A>
623 constexpr auto operator()(A a) const -> decltype(std::abs(a)) {
624 return std::abs(a);
625 }
626};
627struct std_floor {
628 template <class A>
629 constexpr auto operator()(A a) const -> decltype(std::floor(a)) {
630 return std::floor(a);
631 }
632};
633struct std_ceil {
634 template <class A>
635 constexpr auto operator()(A a) const -> decltype(std::ceil(a)) {
636 return std::ceil(a);
637 }
638};
639struct std_exp {
640 template <class A>
641 constexpr auto operator()(A a) const -> decltype(std::exp(a)) {
642 return std::exp(a);
643 }
644};
645struct std_log {
646 template <class A>
647 constexpr auto operator()(A a) const -> decltype(std::log(a)) {
648 return std::log(a);
649 }
650};
651struct std_log2 {
652 template <class A>
653 constexpr auto operator()(A a) const -> decltype(std::log2(a)) {
654 return std::log2(a);
655 }
656};
657struct std_log10 {
658 template <class A>
659 constexpr auto operator()(A a) const -> decltype(std::log10(a)) {
660 return std::log10(a);
661 }
662};
663struct std_sqrt {
664 template <class A>
665 constexpr auto operator()(A a) const -> decltype(std::sqrt(a)) {
666 return std::sqrt(a);
667 }
668};
669struct std_sin {
670 template <class A>
671 constexpr auto operator()(A a) const -> decltype(std::sin(a)) {
672 return std::sin(a);
673 }
674};
675struct std_cos {
676 template <class A>
677 constexpr auto operator()(A a) const -> decltype(std::cos(a)) {
678 return std::cos(a);
679 }
680};
681struct std_tan {
682 template <class A>
683 constexpr auto operator()(A a) const -> decltype(std::tan(a)) {
684 return std::tan(a);
685 }
686};
687struct std_asin {
688 template <class A>
689 constexpr auto operator()(A a) const -> decltype(std::asin(a)) {
690 return std::asin(a);
691 }
692};
693struct std_acos {
694 template <class A>
695 constexpr auto operator()(A a) const -> decltype(std::acos(a)) {
696 return std::acos(a);
697 }
698};
699struct std_atan {
700 template <class A>
701 constexpr auto operator()(A a) const -> decltype(std::atan(a)) {
702 return std::atan(a);
703 }
704};
705struct std_sinh {
706 template <class A>
707 constexpr auto operator()(A a) const -> decltype(std::sinh(a)) {
708 return std::sinh(a);
709 }
710};
711struct std_cosh {
712 template <class A>
713 constexpr auto operator()(A a) const -> decltype(std::cosh(a)) {
714 return std::cosh(a);
715 }
716};
717struct std_tanh {
718 template <class A>
719 constexpr auto operator()(A a) const -> decltype(std::tanh(a)) {
720 return std::tanh(a);
721 }
722};
723struct std_round {
724 template <class A>
725 constexpr auto operator()(A a) const -> decltype(std::round(a)) {
726 return std::round(a);
727 }
728};
729struct std_fmod {
730 template <class A, class B>
731 constexpr auto operator()(A a, B b) const -> decltype(std::fmod(a, b)) {
732 return std::fmod(a, b);
733 }
734};
735struct std_pow {
736 template <class A, class B>
737 constexpr auto operator()(A a, B b) const -> decltype(std::pow(a, b)) {
738 return std::pow(a, b);
739 }
740};
741struct std_atan2 {
742 template <class A, class B>
743 constexpr auto operator()(A a, B b) const -> decltype(std::atan2(a, b)) {
744 return std::atan2(a, b);
745 }
746};
748 template <class A, class B>
749 constexpr auto operator()(A a, B b) const -> decltype(std::copysign(a, b)) {
750 return std::copysign(a, b);
751 }
752};
753} // namespace detail
754
854template <class T>
855struct vec<T, 1> {
856 T x;
857 constexpr vec() : x() {}
858 constexpr vec(const T &x_) : x(x_) {}
859 // NOTE: vec<T,1> does NOT have a constructor from pointer, this can conflict
860 // with initializing its single element from zero
861 template <class U>
862 constexpr explicit vec(const vec<U, 1> &v) : vec(static_cast<T>(v.x)) {}
863 constexpr const T &operator[](int i) const { return x; }
864 LINALG_CONSTEXPR14 T &operator[](int i) { return x; }
865
866 template <class U, class = detail::conv_t<vec, U>>
867 constexpr vec(const U &u) : vec(converter<vec, U>{}(u)) {}
868 template <class U, class = detail::conv_t<U, vec>>
869 constexpr operator U() const {
870 return converter<U, vec>{}(*this);
871 }
872};
873template <class T>
874struct vec<T, 2> {
875 T x, y;
876 constexpr vec() : x(), y() {}
877 constexpr vec(const T &x_, const T &y_) : x(x_), y(y_) {}
878 constexpr explicit vec(const T &s) : vec(s, s) {}
879 constexpr explicit vec(const T *p) : vec(p[0], p[1]) {}
880 template <class U, int N>
881 constexpr explicit vec(const vec<U, N> &v)
882 : vec(static_cast<T>(v.x), static_cast<T>(v.y)) {
883 static_assert(
884 N >= 2,
885 "You must give extra arguments if your input vector is shorter.");
886 }
887 constexpr const T &operator[](int i) const { return i == 0 ? x : y; }
888 LINALG_CONSTEXPR14 T &operator[](int i) { return i == 0 ? x : y; }
889
890 template <class U, class = detail::conv_t<vec, U>>
891 constexpr vec(const U &u) : vec(converter<vec, U>{}(u)) {}
892 template <class U, class = detail::conv_t<U, vec>>
893 constexpr operator U() const {
894 return converter<U, vec>{}(*this);
895 }
896};
897template <class T>
898struct vec<T, 3> {
899 T x, y, z;
900 constexpr vec() : x(), y(), z() {}
901 constexpr vec(const T &x_, const T &y_, const T &z_) : x(x_), y(y_), z(z_) {}
902 constexpr vec(const vec<T, 2> &xy, const T &z_) : vec(xy.x, xy.y, z_) {}
903 constexpr explicit vec(const T &s) : vec(s, s, s) {}
904 constexpr explicit vec(const T *p) : vec(p[0], p[1], p[2]) {}
905 template <class U, int N>
906 constexpr explicit vec(const vec<U, N> &v)
907 : vec(static_cast<T>(v.x), static_cast<T>(v.y), static_cast<T>(v.z)) {
908 static_assert(
909 N >= 3,
910 "You must give extra arguments if your input vector is shorter.");
911 }
912 constexpr const T &operator[](int i) const {
913 return i == 0 ? x : i == 1 ? y : z;
914 }
915 LINALG_CONSTEXPR14 T &operator[](int i) {
916 return i == 0 ? x : i == 1 ? y : z;
917 }
918 constexpr const vec<T, 2> &xy() const {
919 return *reinterpret_cast<const vec<T, 2> *>(this);
920 }
921 vec<T, 2> &xy() { return *reinterpret_cast<vec<T, 2> *>(this); }
922
923 template <class U, class = detail::conv_t<vec, U>>
924 constexpr vec(const U &u) : vec(converter<vec, U>{}(u)) {}
925 template <class U, class = detail::conv_t<U, vec>>
926 constexpr operator U() const {
927 return converter<U, vec>{}(*this);
928 }
929};
930template <class T>
931struct vec<T, 4> {
932 T x, y, z, w;
933 constexpr vec() : x(), y(), z(), w() {}
934 constexpr vec(const T &x_, const T &y_, const T &z_, const T &w_)
935 : x(x_), y(y_), z(z_), w(w_) {}
936 constexpr vec(const vec<T, 2> &xy, const T &z_, const T &w_)
937 : vec(xy.x, xy.y, z_, w_) {}
938 constexpr vec(const vec<T, 3> &xyz, const T &w_)
939 : vec(xyz.x, xyz.y, xyz.z, w_) {}
940 constexpr explicit vec(const T &s) : vec(s, s, s, s) {}
941 constexpr explicit vec(const T *p) : vec(p[0], p[1], p[2], p[3]) {}
942 template <class U, int N>
943 constexpr explicit vec(const vec<U, N> &v)
944 : vec(static_cast<T>(v.x), static_cast<T>(v.y), static_cast<T>(v.z),
945 static_cast<T>(v.w)) {
946 static_assert(
947 N >= 4,
948 "You must give extra arguments if your input vector is shorter.");
949 }
950 constexpr const T &operator[](int i) const {
951 return i == 0 ? x : i == 1 ? y : i == 2 ? z : w;
952 }
953 LINALG_CONSTEXPR14 T &operator[](int i) {
954 return i == 0 ? x : i == 1 ? y : i == 2 ? z : w;
955 }
956 constexpr const vec<T, 2> &xy() const {
957 return *reinterpret_cast<const vec<T, 2> *>(this);
958 }
959 constexpr const vec<T, 3> &xyz() const {
960 return *reinterpret_cast<const vec<T, 3> *>(this);
961 }
962 vec<T, 2> &xy() { return *reinterpret_cast<vec<T, 2> *>(this); }
963 vec<T, 3> &xyz() { return *reinterpret_cast<vec<T, 3> *>(this); }
964
965 template <class U, class = detail::conv_t<vec, U>>
966 constexpr vec(const U &u) : vec(converter<vec, U>{}(u)) {}
967 template <class U, class = detail::conv_t<U, vec>>
968 constexpr operator U() const {
969 return converter<U, vec>{}(*this);
970 }
971};
1068template <class T, int M>
1069struct mat<T, M, 1> {
1070 typedef vec<T, M> V;
1071 V x;
1072 constexpr mat() : x() {}
1073 constexpr mat(const V &x_) : x(x_) {}
1074 constexpr explicit mat(const T &s) : x(s) {}
1075 constexpr explicit mat(const T *p) : x(p + M * 0) {}
1076 template <class U>
1077 constexpr explicit mat(const mat<U, M, 1> &m) : mat(V(m.x)) {}
1078 constexpr vec<T, 1> row(int i) const { return {x[i]}; }
1079 constexpr const V &operator[](int j) const { return x; }
1080 LINALG_CONSTEXPR14 V &operator[](int j) { return x; }
1081
1082 template <class U, class = detail::conv_t<mat, U>>
1083 constexpr mat(const U &u) : mat(converter<mat, U>{}(u)) {}
1084 template <class U, class = detail::conv_t<U, mat>>
1085 constexpr operator U() const {
1086 return converter<U, mat>{}(*this);
1087 }
1088};
1089template <class T, int M>
1090struct mat<T, M, 2> {
1091 typedef vec<T, M> V;
1092 V x, y;
1093 constexpr mat() : x(), y() {}
1094 constexpr mat(const V &x_, const V &y_) : x(x_), y(y_) {}
1095 constexpr explicit mat(const T &s) : x(s), y(s) {}
1096 constexpr explicit mat(const T *p) : x(p + M * 0), y(p + M * 1) {}
1097 template <class U, int N, int P>
1098 constexpr explicit mat(const mat<U, N, P> &m) : mat(V(m.x), V(m.y)) {
1099 static_assert(P >= 2, "Input matrix dimensions must be at least as big.");
1100 }
1101 constexpr vec<T, 2> row(int i) const { return {x[i], y[i]}; }
1102 constexpr const V &operator[](int j) const { return j == 0 ? x : y; }
1103 LINALG_CONSTEXPR14 V &operator[](int j) { return j == 0 ? x : y; }
1104
1105 template <class U, class = detail::conv_t<mat, U>>
1106 constexpr mat(const U &u) : mat(converter<mat, U>{}(u)) {}
1107 template <class U, class = detail::conv_t<U, mat>>
1108 constexpr operator U() const {
1109 return converter<U, mat>{}(*this);
1110 }
1111};
1112template <class T, int M>
1113struct mat<T, M, 3> {
1114 typedef vec<T, M> V;
1115 V x, y, z;
1116 constexpr mat() : x(), y(), z() {}
1117 constexpr mat(const V &x_, const V &y_, const V &z_) : x(x_), y(y_), z(z_) {}
1118 constexpr mat(const mat<T, M, 2> &m_, const V &z_)
1119 : x(m_.x), y(m_.y), z(z_) {}
1120 constexpr explicit mat(const T &s) : x(s), y(s), z(s) {}
1121 constexpr explicit mat(const T *p)
1122 : x(p + M * 0), y(p + M * 1), z(p + M * 2) {}
1123 template <class U, int N, int P>
1124 constexpr explicit mat(const mat<U, N, P> &m) : mat(V(m.x), V(m.y), V(m.z)) {
1125 static_assert(P >= 3, "Input matrix dimensions must be at least as big.");
1126 }
1127 constexpr vec<T, 3> row(int i) const { return {x[i], y[i], z[i]}; }
1128 constexpr const V &operator[](int j) const {
1129 return j == 0 ? x : j == 1 ? y : z;
1130 }
1131 LINALG_CONSTEXPR14 V &operator[](int j) {
1132 return j == 0 ? x : j == 1 ? y : z;
1133 }
1134
1135 template <class U, class = detail::conv_t<mat, U>>
1136 constexpr mat(const U &u) : mat(converter<mat, U>{}(u)) {}
1137 template <class U, class = detail::conv_t<U, mat>>
1138 constexpr operator U() const {
1139 return converter<U, mat>{}(*this);
1140 }
1141};
1142template <class T, int M>
1143struct mat<T, M, 4> {
1144 typedef vec<T, M> V;
1145 V x, y, z, w;
1146 constexpr mat() : x(), y(), z(), w() {}
1147 constexpr mat(const V &x_, const V &y_, const V &z_, const V &w_)
1148 : x(x_), y(y_), z(z_), w(w_) {}
1149 constexpr mat(const mat<T, M, 3> &m_, const V &w_)
1150 : x(m_.x), y(m_.y), z(m_.z), w(w_) {}
1151 constexpr explicit mat(const T &s) : x(s), y(s), z(s), w(s) {}
1152 constexpr explicit mat(const T *p)
1153 : x(p + M * 0), y(p + M * 1), z(p + M * 2), w(p + M * 3) {}
1154 template <class U, int N, int P>
1155 constexpr explicit mat(const mat<U, N, P> &m)
1156 : mat(V(m.x), V(m.y), V(m.z), V(m.w)) {
1157 static_assert(P >= 4, "Input matrix dimensions must be at least as big.");
1158 }
1159
1160 constexpr vec<T, 4> row(int i) const { return {x[i], y[i], z[i], w[i]}; }
1161 constexpr const V &operator[](int j) const {
1162 return j == 0 ? x : j == 1 ? y : j == 2 ? z : w;
1163 }
1164 LINALG_CONSTEXPR14 V &operator[](int j) {
1165 return j == 0 ? x : j == 1 ? y : j == 2 ? z : w;
1166 }
1167
1168 template <class U, class = detail::conv_t<mat, U>>
1169 constexpr mat(const U &u) : mat(converter<mat, U>{}(u)) {}
1170 template <class U, class = detail::conv_t<U, mat>>
1171 constexpr operator U() const {
1172 return converter<U, mat>{}(*this);
1173 }
1174};
1184 constexpr explicit identity_t(int) {}
1185};
1186template <class T>
1187struct converter<mat<T, 1, 1>, identity_t> {
1188 constexpr mat<T, 1, 1> operator()(identity_t) const { return {vec<T, 1>{1}}; }
1189};
1190template <class T>
1191struct converter<mat<T, 2, 2>, identity_t> {
1192 constexpr mat<T, 2, 2> operator()(identity_t) const {
1193 return {{1, 0}, {0, 1}};
1194 }
1195};
1196template <class T>
1197struct converter<mat<T, 2, 3>, identity_t> {
1198 constexpr mat<T, 2, 3> operator()(identity_t) const {
1199 return {{1, 0}, {0, 1}, {0, 0}};
1200 }
1201};
1202template <class T>
1203struct converter<mat<T, 3, 3>, identity_t> {
1204 constexpr mat<T, 3, 3> operator()(identity_t) const {
1205 return {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
1206 }
1207};
1208template <class T>
1209struct converter<mat<T, 3, 4>, identity_t> {
1210 constexpr mat<T, 3, 4> operator()(identity_t) const {
1211 return {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}, {0, 0, 0}};
1212 }
1213};
1214template <class T>
1215struct converter<mat<T, 4, 4>, identity_t> {
1216 constexpr mat<T, 4, 4> operator()(identity_t) const {
1217 return {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
1218 }
1219};
1220constexpr identity_t identity{1};
1230template <class F, class A, class B>
1231constexpr A fold(F f, A a, const vec<B, 1> &b) {
1232 return f(a, b.x);
1233}
1234template <class F, class A, class B>
1235constexpr A fold(F f, A a, const vec<B, 2> &b) {
1236 return f(f(a, b.x), b.y);
1237}
1238template <class F, class A, class B>
1239constexpr A fold(F f, A a, const vec<B, 3> &b) {
1240 return f(f(f(a, b.x), b.y), b.z);
1241}
1242template <class F, class A, class B>
1243constexpr A fold(F f, A a, const vec<B, 4> &b) {
1244 return f(f(f(f(a, b.x), b.y), b.z), b.w);
1245}
1246template <class F, class A, class B, int M>
1247constexpr A fold(F f, A a, const mat<B, M, 1> &b) {
1248 return fold(f, a, b.x);
1249}
1250template <class F, class A, class B, int M>
1251constexpr A fold(F f, A a, const mat<B, M, 2> &b) {
1252 return fold(f, fold(f, a, b.x), b.y);
1253}
1254template <class F, class A, class B, int M>
1255constexpr A fold(F f, A a, const mat<B, M, 3> &b) {
1256 return fold(f, fold(f, fold(f, a, b.x), b.y), b.z);
1257}
1258template <class F, class A, class B, int M>
1259constexpr A fold(F f, A a, const mat<B, M, 4> &b) {
1260 return fold(f, fold(f, fold(f, fold(f, a, b.x), b.y), b.z), b.w);
1261}
1271// Type aliases for the result of calling apply(...) with various arguments, can
1272// be used with return type SFINAE to constrain overload sets
1273template <class F, class... A>
1274using apply_t = typename detail::apply<F, void, A...>::type;
1275template <class F, class... A>
1276using mm_apply_t = typename std::enable_if<detail::apply<F, void, A...>::mm,
1277 apply_t<F, A...>>::type;
1278template <class F, class... A>
1279using no_mm_apply_t = typename std::enable_if<!detail::apply<F, void, A...>::mm,
1280 apply_t<F, A...>>::type;
1281template <class A>
1282using scalar_t =
1283 typename detail::scalar_type<A>::type; // Underlying scalar type when
1284 // performing elementwise operations
1285
1286// apply(f,...) applies the provided function in an elementwise fashion to its
1287// arguments, producing an object of the same dimensions
1288template <class F, class... A>
1289constexpr apply_t<F, A...> apply(F func, const A &...args) {
1290 return detail::apply<F, void, A...>::impl(
1291 detail::make_seq<0, detail::apply<F, void, A...>::size>{}, func, args...);
1292}
1293
1294// map(a,f) is equivalent to apply(f,a)
1295template <class A, class F>
1296constexpr apply_t<F, A> map(const A &a, F func) {
1297 return apply(func, a);
1298}
1299
1300// zip(a,b,f) is equivalent to apply(f,a,b)
1301template <class A, class B, class F>
1302constexpr apply_t<F, A, B> zip(const A &a, const B &b, F func) {
1303 return apply(func, a, b);
1304}
1313template <class A, class B>
1314constexpr typename detail::any_compare<A, B>::type compare(const A &a,
1315 const B &b) {
1316 return detail::any_compare<A, B>()(a, b);
1317}
1318template <class A, class B>
1319constexpr auto operator==(const A &a,
1320 const B &b) -> decltype(compare(a, b) == 0) {
1321 return compare(a, b) == 0;
1322}
1323template <class A, class B>
1324constexpr auto operator!=(const A &a,
1325 const B &b) -> decltype(compare(a, b) != 0) {
1326 return compare(a, b) != 0;
1327}
1328template <class A, class B>
1329constexpr auto operator<(const A &a,
1330 const B &b) -> decltype(compare(a, b) < 0) {
1331 return compare(a, b) < 0;
1332}
1333template <class A, class B>
1334constexpr auto operator>(const A &a,
1335 const B &b) -> decltype(compare(a, b) > 0) {
1336 return compare(a, b) > 0;
1337}
1338template <class A, class B>
1339constexpr auto operator<=(const A &a,
1340 const B &b) -> decltype(compare(a, b) <= 0) {
1341 return compare(a, b) <= 0;
1342}
1343template <class A, class B>
1344constexpr auto operator>=(const A &a,
1345 const B &b) -> decltype(compare(a, b) >= 0) {
1346 return compare(a, b) >= 0;
1347}
1355template <class A>
1356constexpr bool any(const A &a) {
1357 return fold(detail::op_or{}, false, a);
1358}
1359template <class A>
1360constexpr bool all(const A &a) {
1361 return fold(detail::op_and{}, true, a);
1362}
1363template <class A>
1364constexpr scalar_t<A> sum(const A &a) {
1365 return fold(detail::op_add{}, scalar_t<A>(0), a);
1366}
1367template <class A>
1368constexpr scalar_t<A> product(const A &a) {
1369 return fold(detail::op_mul{}, scalar_t<A>(1), a);
1370}
1371template <class A>
1372constexpr scalar_t<A> minelem(const A &a) {
1373 return fold(detail::min{}, a.x, a);
1374}
1375template <class A>
1376constexpr scalar_t<A> maxelem(const A &a) {
1377 return fold(detail::max{}, a.x, a);
1378}
1379template <class T, int M>
1380int argmin(const vec<T, M> &a) {
1381 int j = 0;
1382 for (int i = 1; i < M; ++i)
1383 if (a[i] < a[j]) j = i;
1384 return j;
1385}
1386template <class T, int M>
1387int argmax(const vec<T, M> &a) {
1388 int j = 0;
1389 for (int i = 1; i < M; ++i)
1390 if (a[i] > a[j]) j = i;
1391 return j;
1392}
1400template <class A>
1401constexpr apply_t<detail::op_pos, A> operator+(const A &a) {
1402 return apply(detail::op_pos{}, a);
1403}
1404template <class A>
1405constexpr apply_t<detail::op_neg, A> operator-(const A &a) {
1406 return apply(detail::op_neg{}, a);
1407}
1408template <class A>
1409constexpr apply_t<detail::op_cmp, A> operator~(const A &a) {
1410 return apply(detail::op_cmp{}, a);
1411}
1412template <class A>
1413constexpr apply_t<detail::op_not, A> operator!(const A &a) {
1414 return apply(detail::op_not{}, a);
1415}
1426template <class A, class B>
1427constexpr apply_t<detail::op_add, A, B> operator+(const A &a, const B &b) {
1428 return apply(detail::op_add{}, a, b);
1429}
1430template <class A, class B>
1431constexpr apply_t<detail::op_sub, A, B> operator-(const A &a, const B &b) {
1432 return apply(detail::op_sub{}, a, b);
1433}
1434template <class A, class B>
1435constexpr apply_t<detail::op_mul, A, B> cmul(const A &a, const B &b) {
1436 return apply(detail::op_mul{}, a, b);
1437}
1438template <class A, class B>
1439constexpr apply_t<detail::op_div, A, B> operator/(const A &a, const B &b) {
1440 return apply(detail::op_div{}, a, b);
1441}
1442template <class A, class B>
1443constexpr apply_t<detail::op_mod, A, B> operator%(const A &a, const B &b) {
1444 return apply(detail::op_mod{}, a, b);
1445}
1446template <class A, class B>
1447constexpr apply_t<detail::op_un, A, B> operator|(const A &a, const B &b) {
1448 return apply(detail::op_un{}, a, b);
1449}
1450template <class A, class B>
1451constexpr apply_t<detail::op_xor, A, B> operator^(const A &a, const B &b) {
1452 return apply(detail::op_xor{}, a, b);
1453}
1454template <class A, class B>
1455constexpr apply_t<detail::op_int, A, B> operator&(const A &a, const B &b) {
1456 return apply(detail::op_int{}, a, b);
1457}
1458template <class A, class B>
1459constexpr apply_t<detail::op_lsh, A, B> operator<<(const A &a, const B &b) {
1460 return apply(detail::op_lsh{}, a, b);
1461}
1462template <class A, class B>
1463constexpr apply_t<detail::op_rsh, A, B> operator>>(const A &a, const B &b) {
1464 return apply(detail::op_rsh{}, a, b);
1465}
1466
1467// Binary `operator *` represents the algebraic matrix product - use cmul(a, b)
1468// for the Hadamard (component-wise) product.
1469template <class A, class B>
1470constexpr auto operator*(const A &a, const B &b) {
1471 return mul(a, b);
1472}
1473
1474// Binary assignment operators a $= b is always defined as though it were
1475// explicitly written a = a $ b
1476template <class A, class B>
1477constexpr auto operator+=(A &a, const B &b) -> decltype(a = a + b) {
1478 return a = a + b;
1479}
1480template <class A, class B>
1481constexpr auto operator-=(A &a, const B &b) -> decltype(a = a - b) {
1482 return a = a - b;
1483}
1484template <class A, class B>
1485constexpr auto operator*=(A &a, const B &b) -> decltype(a = a * b) {
1486 return a = a * b;
1487}
1488template <class A, class B>
1489constexpr auto operator/=(A &a, const B &b) -> decltype(a = a / b) {
1490 return a = a / b;
1491}
1492template <class A, class B>
1493constexpr auto operator%=(A &a, const B &b) -> decltype(a = a % b) {
1494 return a = a % b;
1495}
1496template <class A, class B>
1497constexpr auto operator|=(A &a, const B &b) -> decltype(a = a | b) {
1498 return a = a | b;
1499}
1500template <class A, class B>
1501constexpr auto operator^=(A &a, const B &b) -> decltype(a = a ^ b) {
1502 return a = a ^ b;
1503}
1504template <class A, class B>
1505constexpr auto operator&=(A &a, const B &b) -> decltype(a = a & b) {
1506 return a = a & b;
1507}
1508template <class A, class B>
1509constexpr auto operator<<=(A &a, const B &b) -> decltype(a = a << b) {
1510 return a = a << b;
1511}
1512template <class A, class B>
1513constexpr auto operator>>=(A &a, const B &b) -> decltype(a = a >> b) {
1514 return a = a >> b;
1515}
1527template <int... I, class T, int M>
1528constexpr vec<T, sizeof...(I)> swizzle(const vec<T, M> &a) {
1529 return {detail::getter<I>{}(a)...};
1530}
1535template <int I0, int I1, class T, int M>
1536constexpr vec<T, I1 - I0> subvec(const vec<T, M> &a) {
1537 return detail::swizzle(a, detail::make_seq<I0, I1>{});
1538}
1543template <int I0, int J0, int I1, int J1, class T, int M, int N>
1544constexpr mat<T, I1 - I0, J1 - J0> submat(const mat<T, M, N> &a) {
1545 return detail::swizzle(a, detail::make_seq<I0, I1>{},
1546 detail::make_seq<J0, J1>{});
1547}
1555template <class A>
1556constexpr apply_t<detail::std_isfinite, A> isfinite(const A &a) {
1557 return apply(detail::std_isfinite{}, a);
1558}
1559template <class A>
1560constexpr apply_t<detail::std_abs, A> abs(const A &a) {
1561 return apply(detail::std_abs{}, a);
1562}
1563template <class A>
1564constexpr apply_t<detail::std_floor, A> floor(const A &a) {
1565 return apply(detail::std_floor{}, a);
1566}
1567template <class A>
1568constexpr apply_t<detail::std_ceil, A> ceil(const A &a) {
1569 return apply(detail::std_ceil{}, a);
1570}
1571template <class A>
1572constexpr apply_t<detail::std_exp, A> exp(const A &a) {
1573 return apply(detail::std_exp{}, a);
1574}
1575template <class A>
1576constexpr apply_t<detail::std_log, A> log(const A &a) {
1577 return apply(detail::std_log{}, a);
1578}
1579template <class A>
1580constexpr apply_t<detail::std_log2, A> log2(const A &a) {
1581 return apply(detail::std_log2{}, a);
1582}
1583template <class A>
1584constexpr apply_t<detail::std_log10, A> log10(const A &a) {
1585 return apply(detail::std_log10{}, a);
1586}
1587template <class A>
1588constexpr apply_t<detail::std_sqrt, A> sqrt(const A &a) {
1589 return apply(detail::std_sqrt{}, a);
1590}
1591template <class A>
1592constexpr apply_t<detail::std_sin, A> sin(const A &a) {
1593 return apply(detail::std_sin{}, a);
1594}
1595template <class A>
1596constexpr apply_t<detail::std_cos, A> cos(const A &a) {
1597 return apply(detail::std_cos{}, a);
1598}
1599template <class A>
1600constexpr apply_t<detail::std_tan, A> tan(const A &a) {
1601 return apply(detail::std_tan{}, a);
1602}
1603template <class A>
1604constexpr apply_t<detail::std_asin, A> asin(const A &a) {
1605 return apply(detail::std_asin{}, a);
1606}
1607template <class A>
1608constexpr apply_t<detail::std_acos, A> acos(const A &a) {
1609 return apply(detail::std_acos{}, a);
1610}
1611template <class A>
1612constexpr apply_t<detail::std_atan, A> atan(const A &a) {
1613 return apply(detail::std_atan{}, a);
1614}
1615template <class A>
1616constexpr apply_t<detail::std_sinh, A> sinh(const A &a) {
1617 return apply(detail::std_sinh{}, a);
1618}
1619template <class A>
1620constexpr apply_t<detail::std_cosh, A> cosh(const A &a) {
1621 return apply(detail::std_cosh{}, a);
1622}
1623template <class A>
1624constexpr apply_t<detail::std_tanh, A> tanh(const A &a) {
1625 return apply(detail::std_tanh{}, a);
1626}
1627template <class A>
1628constexpr apply_t<detail::std_round, A> round(const A &a) {
1629 return apply(detail::std_round{}, a);
1630}
1639template <class A, class B>
1640constexpr apply_t<detail::std_fmod, A, B> fmod(const A &a, const B &b) {
1641 return apply(detail::std_fmod{}, a, b);
1642}
1643template <class A, class B>
1644constexpr apply_t<detail::std_pow, A, B> pow(const A &a, const B &b) {
1645 return apply(detail::std_pow{}, a, b);
1646}
1647template <class A, class B>
1648constexpr apply_t<detail::std_atan2, A, B> atan2(const A &a, const B &b) {
1649 return apply(detail::std_atan2{}, a, b);
1650}
1651template <class A, class B>
1652constexpr apply_t<detail::std_copysign, A, B> copysign(const A &a, const B &b) {
1653 return apply(detail::std_copysign{}, a, b);
1654}
1663template <class A, class B>
1664constexpr apply_t<detail::op_eq, A, B> equal(const A &a, const B &b) {
1665 return apply(detail::op_eq{}, a, b);
1666}
1667template <class A, class B>
1668constexpr apply_t<detail::op_ne, A, B> nequal(const A &a, const B &b) {
1669 return apply(detail::op_ne{}, a, b);
1670}
1671template <class A, class B>
1672constexpr apply_t<detail::op_lt, A, B> less(const A &a, const B &b) {
1673 return apply(detail::op_lt{}, a, b);
1674}
1675template <class A, class B>
1676constexpr apply_t<detail::op_gt, A, B> greater(const A &a, const B &b) {
1677 return apply(detail::op_gt{}, a, b);
1678}
1679template <class A, class B>
1680constexpr apply_t<detail::op_le, A, B> lequal(const A &a, const B &b) {
1681 return apply(detail::op_le{}, a, b);
1682}
1683template <class A, class B>
1684constexpr apply_t<detail::op_ge, A, B> gequal(const A &a, const B &b) {
1685 return apply(detail::op_ge{}, a, b);
1686}
1695template <class A, class B>
1696constexpr apply_t<detail::min, A, B> min(const A &a, const B &b) {
1697 return apply(detail::min{}, a, b);
1698}
1699template <class A, class B>
1700constexpr apply_t<detail::max, A, B> max(const A &a, const B &b) {
1701 return apply(detail::max{}, a, b);
1702}
1706template <class X, class L, class H>
1707constexpr apply_t<detail::clamp, X, L, H> clamp(const X &x, const L &l,
1708 const H &h) {
1709 return apply(detail::clamp{}, x, l, h);
1710}
1715template <class P, class A, class B>
1716constexpr apply_t<detail::select, P, A, B> select(const P &p, const A &a,
1717 const B &b) {
1718 return apply(detail::select{}, p, a, b);
1719}
1724template <class A, class B, class T>
1725constexpr apply_t<detail::lerp, A, B, T> lerp(const A &a, const B &b,
1726 const T &t) {
1727 return apply(detail::lerp{}, a, b, t);
1728}
1739template <class T>
1740constexpr T cross(const vec<T, 2> &a, const vec<T, 2> &b) {
1741 return a.x * b.y - a.y * b.x;
1742}
1746template <class T>
1747constexpr vec<T, 2> cross(T a, const vec<T, 2> &b) {
1748 return {-a * b.y, a * b.x};
1749}
1753template <class T>
1754constexpr vec<T, 2> cross(const vec<T, 2> &a, T b) {
1755 return {a.y * b, -a.x * b};
1756}
1761template <class T>
1762constexpr vec<T, 3> cross(const vec<T, 3> &a, const vec<T, 3> &b) {
1763 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};
1764}
1769template <class T, int M>
1770constexpr T dot(const vec<T, M> &a, const vec<T, M> &b) {
1771 return sum(a * b);
1772}
1776template <class T, int M>
1777constexpr T length2(const vec<T, M> &a) {
1778 return dot(a, a);
1779}
1783template <class T, int M>
1784T length(const vec<T, M> &a) {
1785 return std::sqrt(length2(a));
1786}
1792template <class T, int M>
1794 return a / length(a);
1795}
1801template <class T, int M>
1802constexpr T distance2(const vec<T, M> &a, const vec<T, M> &b) {
1803 return length2(b - a);
1804}
1809template <class T, int M>
1810T distance(const vec<T, M> &a, const vec<T, M> &b) {
1811 return length(b - a);
1812}
1816template <class T, int M>
1817T uangle(const vec<T, M> &a, const vec<T, M> &b) {
1818 T d = dot(a, b);
1819 return d > 1 ? 0 : std::acos(d < -1 ? -1 : d);
1820}
1824template <class T, int M>
1825T angle(const vec<T, M> &a, const vec<T, M> &b) {
1826 return uangle(normalize(a), normalize(b));
1827}
1832template <class T>
1833vec<T, 2> rot(T a, const vec<T, 2> &v) {
1834 const T s = std::sin(a), c = std::cos(a);
1835 return {v.x * c - v.y * s, v.x * s + v.y * c};
1836}
1841template <class T>
1842vec<T, 3> rotx(T a, const vec<T, 3> &v) {
1843 const T s = std::sin(a), c = std::cos(a);
1844 return {v.x, v.y * c - v.z * s, v.y * s + v.z * c};
1845}
1850template <class T>
1851vec<T, 3> roty(T a, const vec<T, 3> &v) {
1852 const T s = std::sin(a), c = std::cos(a);
1853 return {v.x * c + v.z * s, v.y, -v.x * s + v.z * c};
1854}
1859template <class T>
1860vec<T, 3> rotz(T a, const vec<T, 3> &v) {
1861 const T s = std::sin(a), c = std::cos(a);
1862 return {v.x * c - v.y * s, v.x * s + v.y * c, v.z};
1863}
1867template <class T, int M>
1868vec<T, M> nlerp(const vec<T, M> &a, const vec<T, M> &b, T t) {
1869 return normalize(lerp(a, b, t));
1870}
1876template <class T, int M>
1877vec<T, M> slerp(const vec<T, M> &a, const vec<T, M> &b, T t) {
1878 T th = uangle(a, b);
1879 return th == 0 ? a
1880 : a * (std::sin(th * (1 - t)) / std::sin(th)) +
1881 b * (std::sin(th * t) / std::sin(th));
1882}
1896template <class T>
1897constexpr vec<T, 4> qconj(const vec<T, 4> &q) {
1898 return {-q.x, -q.y, -q.z, q.w};
1899}
1905template <class T>
1907 return qconj(q) / length2(q);
1908}
1914template <class T>
1916 const auto v = q.xyz();
1917 const auto vv = length(v);
1918 return std::exp(q.w) *
1919 vec<T, 4>{v * (vv > 0 ? std::sin(vv) / vv : 0), std::cos(vv)};
1920}
1926template <class T>
1928 const auto v = q.xyz();
1929 const auto vv = length(v), qq = length(q);
1930 return {v * (vv > 0 ? std::acos(q.w / qq) / vv : 0), std::log(qq)};
1931}
1935template <class T>
1936vec<T, 4> qpow(const vec<T, 4> &q, const T &p) {
1937 const auto v = q.xyz();
1938 const auto vv = length(v), qq = length(q), th = std::acos(q.w / qq);
1939 return std::pow(qq, p) *
1940 vec<T, 4>{v * (vv > 0 ? std::sin(p * th) / vv : 0), std::cos(p * th)};
1941}
1947template <class T>
1948constexpr vec<T, 4> qmul(const vec<T, 4> &a, const vec<T, 4> &b) {
1949 return {a.x * b.w + a.w * b.x + a.y * b.z - a.z * b.y,
1950 a.y * b.w + a.w * b.y + a.z * b.x - a.x * b.z,
1951 a.z * b.w + a.w * b.z + a.x * b.y - a.y * b.x,
1952 a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z};
1953}
1957template <class T, class... R>
1958constexpr vec<T, 4> qmul(const vec<T, 4> &a, R... r) {
1959 return qmul(a, qmul(r...));
1960}
1971template <class T>
1972constexpr vec<T, 3> qxdir(const vec<T, 4> &q) {
1973 return {q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z,
1974 (q.x * q.y + q.z * q.w) * 2, (q.z * q.x - q.y * q.w) * 2};
1975}
1979template <class T>
1980constexpr vec<T, 3> qydir(const vec<T, 4> &q) {
1981 return {(q.x * q.y - q.z * q.w) * 2,
1982 q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z,
1983 (q.y * q.z + q.x * q.w) * 2};
1984}
1988template <class T>
1989constexpr vec<T, 3> qzdir(const vec<T, 4> &q) {
1990 return {(q.z * q.x + q.y * q.w) * 2, (q.y * q.z - q.x * q.w) * 2,
1991 q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z};
1992}
1996template <class T>
1997constexpr mat<T, 3, 3> qmat(const vec<T, 4> &q) {
1998 return {qxdir(q), qydir(q), qzdir(q)};
1999}
2003template <class T>
2004constexpr vec<T, 3> qrot(const vec<T, 4> &q, const vec<T, 3> &v) {
2005 return qxdir(q) * v.x + qydir(q) * v.y + qzdir(q) * v.z;
2006}
2011template <class T>
2012T qangle(const vec<T, 4> &q) {
2013 return std::atan2(length(q.xyz()), q.w) * 2;
2014}
2019template <class T>
2021 return normalize(q.xyz());
2022}
2027template <class T>
2028vec<T, 4> qnlerp(const vec<T, 4> &a, const vec<T, 4> &b, T t) {
2029 return nlerp(a, dot(a, b) < 0 ? -b : b, t);
2030}
2034template <class T>
2035vec<T, 4> qslerp(const vec<T, 4> &a, const vec<T, 4> &b, T t) {
2036 return slerp(a, dot(a, b) < 0 ? -b : b, t);
2037}
2042template <class T>
2043vec<T, 4> constexpr rotation_quat(const vec<T, 3> &axis, T angle) {
2044 return {axis * std::sin(angle / 2), std::cos(angle / 2)};
2045}
2050template <class T>
2051vec<T, 4> rotation_quat(const vec<T, 3> &orig, const vec<T, 3> &dest);
2056template <class T>
2065template <class T, int M>
2066constexpr vec<T, M> mul(const vec<T, M> &a, const T &b) {
2067 return cmul(a, b);
2068}
2069template <class T, int M>
2070constexpr vec<T, M> mul(const T &b, const vec<T, M> &a) {
2071 return cmul(b, a);
2072}
2073template <class T, int M, int N>
2074constexpr mat<T, M, N> mul(const mat<T, M, N> &a, const T &b) {
2075 return cmul(a, b);
2076}
2077template <class T, int M, int N>
2078constexpr mat<T, M, N> mul(const T &b, const mat<T, M, N> &a) {
2079 return cmul(b, a);
2080}
2081template <class T, int M>
2082constexpr vec<T, M> mul(const vec<T, M> &a, const vec<T, M> &b) {
2083 return cmul(a, b);
2084}
2085template <class T, int M>
2086constexpr vec<T, M> mul(const mat<T, M, 1> &a, const vec<T, 1> &b) {
2087 return a.x * b.x;
2088}
2089template <class T, int M>
2090constexpr vec<T, M> mul(const mat<T, M, 2> &a, const vec<T, 2> &b) {
2091 return a.x * b.x + a.y * b.y;
2092}
2093template <class T, int M>
2094constexpr vec<T, M> mul(const mat<T, M, 3> &a, const vec<T, 3> &b) {
2095 return a.x * b.x + a.y * b.y + a.z * b.z;
2096}
2097template <class T, int M>
2098constexpr vec<T, M> mul(const mat<T, M, 4> &a, const vec<T, 4> &b) {
2099 return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
2100}
2101template <class T, int M, int N>
2102constexpr mat<T, M, 1> mul(const mat<T, M, N> &a, const mat<T, N, 1> &b) {
2103 return {mul(a, b.x)};
2104}
2105template <class T, int M, int N>
2106constexpr mat<T, M, 2> mul(const mat<T, M, N> &a, const mat<T, N, 2> &b) {
2107 return {mul(a, b.x), mul(a, b.y)};
2108}
2109template <class T, int M, int N>
2110constexpr mat<T, M, 3> mul(const mat<T, M, N> &a, const mat<T, N, 3> &b) {
2111 return {mul(a, b.x), mul(a, b.y), mul(a, b.z)};
2112}
2113template <class T, int M, int N>
2114constexpr mat<T, M, 4> mul(const mat<T, M, N> &a, const mat<T, N, 4> &b) {
2115 return {mul(a, b.x), mul(a, b.y), mul(a, b.z), mul(a, b.w)};
2116}
2117template <class T, int M, int N, int P>
2118constexpr vec<T, M> mul(const mat<T, M, N> &a, const mat<T, N, P> &b,
2119 const vec<T, P> &c) {
2120 return mul(mul(a, b), c);
2121}
2122template <class T, int M, int N, int P, int Q>
2123constexpr mat<T, M, Q> mul(const mat<T, M, N> &a, const mat<T, N, P> &b,
2124 const mat<T, P, Q> &c) {
2125 return mul(mul(a, b), c);
2126}
2127template <class T, int M, int N, int P, int Q>
2128constexpr vec<T, M> mul(const mat<T, M, N> &a, const mat<T, N, P> &b,
2129 const mat<T, P, Q> &c, const vec<T, Q> &d) {
2130 return mul(mul(a, b, c), d);
2131}
2132template <class T, int M, int N, int P, int Q, int R>
2133constexpr mat<T, M, R> mul(const mat<T, M, N> &a, const mat<T, N, P> &b,
2134 const mat<T, P, Q> &c, const mat<T, Q, R> &d) {
2135 return mul(mul(a, b, c), d);
2136}
2137template <class T, int M>
2138constexpr mat<T, M, 1> outerprod(const vec<T, M> &a, const vec<T, 1> &b) {
2139 return {a * b.x};
2140}
2141template <class T, int M>
2142constexpr mat<T, M, 2> outerprod(const vec<T, M> &a, const vec<T, 2> &b) {
2143 return {a * b.x, a * b.y};
2144}
2145template <class T, int M>
2146constexpr mat<T, M, 3> outerprod(const vec<T, M> &a, const vec<T, 3> &b) {
2147 return {a * b.x, a * b.y, a * b.z};
2148}
2149template <class T, int M>
2150constexpr mat<T, M, 4> outerprod(const vec<T, M> &a, const vec<T, 4> &b) {
2151 return {a * b.x, a * b.y, a * b.z, a * b.w};
2152}
2153template <class T>
2154constexpr vec<T, 1> diagonal(const mat<T, 1, 1> &a) {
2155 return {a.x.x};
2156}
2157template <class T>
2158constexpr vec<T, 2> diagonal(const mat<T, 2, 2> &a) {
2159 return {a.x.x, a.y.y};
2160}
2161template <class T>
2162constexpr vec<T, 3> diagonal(const mat<T, 3, 3> &a) {
2163 return {a.x.x, a.y.y, a.z.z};
2164}
2165template <class T>
2166constexpr vec<T, 4> diagonal(const mat<T, 4, 4> &a) {
2167 return {a.x.x, a.y.y, a.z.z, a.w.w};
2168}
2169template <class T, int N>
2170constexpr T trace(const mat<T, N, N> &a) {
2171 return sum(diagonal(a));
2172}
2173template <class T, int M>
2174constexpr mat<T, M, 1> transpose(const mat<T, 1, M> &m) {
2175 return {m.row(0)};
2176}
2177template <class T, int M>
2178constexpr mat<T, M, 2> transpose(const mat<T, 2, M> &m) {
2179 return {m.row(0), m.row(1)};
2180}
2181template <class T, int M>
2182constexpr mat<T, M, 3> transpose(const mat<T, 3, M> &m) {
2183 return {m.row(0), m.row(1), m.row(2)};
2184}
2185template <class T, int M>
2186constexpr mat<T, M, 4> transpose(const mat<T, 4, M> &m) {
2187 return {m.row(0), m.row(1), m.row(2), m.row(3)};
2188}
2189template <class T, int M>
2190constexpr mat<T, 1, M> transpose(const vec<T, M> &m) {
2191 return transpose(mat<T, M, 1>(m));
2192}
2193template <class T>
2194constexpr mat<T, 1, 1> adjugate(const mat<T, 1, 1> &a) {
2195 return {vec<T, 1>{1}};
2196}
2197template <class T>
2198constexpr mat<T, 2, 2> adjugate(const mat<T, 2, 2> &a) {
2199 return {{a.y.y, -a.x.y}, {-a.y.x, a.x.x}};
2200}
2201template <class T>
2202constexpr mat<T, 3, 3> adjugate(const mat<T, 3, 3> &a);
2203template <class T>
2204constexpr mat<T, 4, 4> adjugate(const mat<T, 4, 4> &a);
2205template <class T, int N>
2206constexpr mat<T, N, N> comatrix(const mat<T, N, N> &a) {
2207 return transpose(adjugate(a));
2208}
2209template <class T>
2210constexpr T determinant(const mat<T, 1, 1> &a) {
2211 return a.x.x;
2212}
2213template <class T>
2214constexpr T determinant(const mat<T, 2, 2> &a) {
2215 return a.x.x * a.y.y - a.x.y * a.y.x;
2216}
2217template <class T>
2218constexpr T determinant(const mat<T, 3, 3> &a) {
2219 return a.x.x * (a.y.y * a.z.z - a.z.y * a.y.z) +
2220 a.x.y * (a.y.z * a.z.x - a.z.z * a.y.x) +
2221 a.x.z * (a.y.x * a.z.y - a.z.x * a.y.y);
2222}
2223template <class T>
2224constexpr T determinant(const mat<T, 4, 4> &a);
2225template <class T, int N>
2226constexpr mat<T, N, N> inverse(const mat<T, N, N> &a) {
2227 return adjugate(a) / determinant(a);
2228}
2236template <class T, int M>
2237T *begin(vec<T, M> &a) {
2238 return &a.x;
2239}
2240template <class T, int M>
2241const T *begin(const vec<T, M> &a) {
2242 return &a.x;
2243}
2244template <class T, int M>
2245T *end(vec<T, M> &a) {
2246 return begin(a) + M;
2247}
2248template <class T, int M>
2249const T *end(const vec<T, M> &a) {
2250 return begin(a) + M;
2251}
2252template <class T, int M, int N>
2253vec<T, M> *begin(mat<T, M, N> &a) {
2254 return &a.x;
2255}
2256template <class T, int M, int N>
2257const vec<T, M> *begin(const mat<T, M, N> &a) {
2258 return &a.x;
2259}
2260template <class T, int M, int N>
2261vec<T, M> *end(mat<T, M, N> &a) {
2262 return begin(a) + N;
2263}
2264template <class T, int M, int N>
2265const vec<T, M> *end(const mat<T, M, N> &a) {
2266 return begin(a) + N;
2267}
2275enum fwd_axis {
2276 neg_z,
2277 pos_z
2278}; // Should projection matrices be generated assuming forward is {0,0,-1} or
2279 // {0,0,1}
2280enum z_range {
2281 neg_one_to_one,
2282 zero_to_one
2283}; // Should projection matrices map z into the range of [-1,1] or [0,1]?
2284template <class T>
2285mat<T, 4, 4> translation_matrix(const vec<T, 3> &translation) {
2286 return {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {translation, 1}};
2287}
2288template <class T>
2289mat<T, 4, 4> rotation_matrix(const vec<T, 4> &rotation) {
2290 return {{qxdir(rotation), 0},
2291 {qydir(rotation), 0},
2292 {qzdir(rotation), 0},
2293 {0, 0, 0, 1}};
2294}
2295template <class T>
2296mat<T, 4, 4> scaling_matrix(const vec<T, 3> &scaling) {
2297 return {{scaling.x, 0, 0, 0},
2298 {0, scaling.y, 0, 0},
2299 {0, 0, scaling.z, 0},
2300 {0, 0, 0, 1}};
2301}
2302template <class T>
2303mat<T, 4, 4> pose_matrix(const vec<T, 4> &q, const vec<T, 3> &p) {
2304 return {{qxdir(q), 0}, {qydir(q), 0}, {qzdir(q), 0}, {p, 1}};
2305}
2306template <class T>
2307mat<T, 4, 4> lookat_matrix(const vec<T, 3> &eye, const vec<T, 3> &center,
2308 const vec<T, 3> &view_y_dir, fwd_axis fwd = neg_z);
2309template <class T>
2310mat<T, 4, 4> frustum_matrix(T x0, T x1, T y0, T y1, T n, T f,
2311 fwd_axis a = neg_z, z_range z = neg_one_to_one);
2312template <class T>
2313mat<T, 4, 4> perspective_matrix(T fovy, T aspect, T n, T f, fwd_axis a = neg_z,
2314 z_range z = neg_one_to_one) {
2315 T y = n * std::tan(fovy / 2), x = y * aspect;
2316 return frustum_matrix(-x, x, -y, y, n, f, a, z);
2317}
2326template <class T>
2327struct converter<vec<T, 1>, std::array<T, 1>> {
2328 vec<T, 1> operator()(const std::array<T, 1> &a) const { return {a[0]}; }
2329};
2330template <class T>
2331struct converter<vec<T, 2>, std::array<T, 2>> {
2332 vec<T, 2> operator()(const std::array<T, 2> &a) const { return {a[0], a[1]}; }
2333};
2334template <class T>
2335struct converter<vec<T, 3>, std::array<T, 3>> {
2336 vec<T, 3> operator()(const std::array<T, 3> &a) const {
2337 return {a[0], a[1], a[2]};
2338 }
2339};
2340template <class T>
2341struct converter<vec<T, 4>, std::array<T, 4>> {
2342 vec<T, 4> operator()(const std::array<T, 4> &a) const {
2343 return {a[0], a[1], a[2], a[3]};
2344 }
2345};
2346
2347template <class T>
2348struct converter<std::array<T, 1>, vec<T, 1>> {
2349 std::array<T, 1> operator()(const vec<T, 1> &a) const { return {a[0]}; }
2350};
2351template <class T>
2352struct converter<std::array<T, 2>, vec<T, 2>> {
2353 std::array<T, 2> operator()(const vec<T, 2> &a) const { return {a[0], a[1]}; }
2354};
2355template <class T>
2356struct converter<std::array<T, 3>, vec<T, 3>> {
2357 std::array<T, 3> operator()(const vec<T, 3> &a) const {
2358 return {a[0], a[1], a[2]};
2359 }
2360};
2361template <class T>
2362struct converter<std::array<T, 4>, vec<T, 4>> {
2363 std::array<T, 4> operator()(const vec<T, 4> &a) const {
2364 return {a[0], a[1], a[2], a[3]};
2365 }
2366};
2369#ifdef MANIFOLD_DEBUG
2370template <class T>
2371std::ostream &operator<<(std::ostream &out, const vec<T, 1> &v) {
2372 return out << '{' << v[0] << '}';
2373}
2374template <class T>
2375std::ostream &operator<<(std::ostream &out, const vec<T, 2> &v) {
2376 return out << '{' << v[0] << ',' << v[1] << '}';
2377}
2378template <class T>
2379std::ostream &operator<<(std::ostream &out, const vec<T, 3> &v) {
2380 return out << '{' << v[0] << ',' << v[1] << ',' << v[2] << '}';
2381}
2382template <class T>
2383std::ostream &operator<<(std::ostream &out, const vec<T, 4> &v) {
2384 return out << '{' << v[0] << ',' << v[1] << ',' << v[2] << ',' << v[3] << '}';
2385}
2386
2387template <class T, int M>
2388std::ostream &operator<<(std::ostream &out, const mat<T, M, 1> &m) {
2389 return out << '{' << m[0] << '}';
2390}
2391template <class T, int M>
2392std::ostream &operator<<(std::ostream &out, const mat<T, M, 2> &m) {
2393 return out << '{' << m[0] << ',' << m[1] << '}';
2394}
2395template <class T, int M>
2396std::ostream &operator<<(std::ostream &out, const mat<T, M, 3> &m) {
2397 return out << '{' << m[0] << ',' << m[1] << ',' << m[2] << '}';
2398}
2399template <class T, int M>
2400std::ostream &operator<<(std::ostream &out, const mat<T, M, 4> &m) {
2401 return out << '{' << m[0] << ',' << m[1] << ',' << m[2] << ',' << m[3] << '}';
2402}
2403#endif
2404} // namespace linalg
2405
2406namespace std {
2412template <class T>
2413struct hash<linalg::vec<T, 1>> {
2414 std::size_t operator()(const linalg::vec<T, 1> &v) const {
2415 std::hash<T> h;
2416 return h(v.x);
2417 }
2418};
2419template <class T>
2420struct hash<linalg::vec<T, 2>> {
2421 std::size_t operator()(const linalg::vec<T, 2> &v) const {
2422 std::hash<T> h;
2423 return h(v.x) ^ (h(v.y) << 1);
2424 }
2425};
2426template <class T>
2427struct hash<linalg::vec<T, 3>> {
2428 std::size_t operator()(const linalg::vec<T, 3> &v) const {
2429 std::hash<T> h;
2430 return h(v.x) ^ (h(v.y) << 1) ^ (h(v.z) << 2);
2431 }
2432};
2433template <class T>
2434struct hash<linalg::vec<T, 4>> {
2435 std::size_t operator()(const linalg::vec<T, 4> &v) const {
2436 std::hash<T> h;
2437 return h(v.x) ^ (h(v.y) << 1) ^ (h(v.z) << 2) ^ (h(v.w) << 3);
2438 }
2439};
2440
2441template <class T, int M>
2442struct hash<linalg::mat<T, M, 1>> {
2443 std::size_t operator()(const linalg::mat<T, M, 1> &v) const {
2444 std::hash<linalg::vec<T, M>> h;
2445 return h(v.x);
2446 }
2447};
2448template <class T, int M>
2449struct hash<linalg::mat<T, M, 2>> {
2450 std::size_t operator()(const linalg::mat<T, M, 2> &v) const {
2451 std::hash<linalg::vec<T, M>> h;
2452 return h(v.x) ^ (h(v.y) << M);
2453 }
2454};
2455template <class T, int M>
2456struct hash<linalg::mat<T, M, 3>> {
2457 std::size_t operator()(const linalg::mat<T, M, 3> &v) const {
2458 std::hash<linalg::vec<T, M>> h;
2459 return h(v.x) ^ (h(v.y) << M) ^ (h(v.z) << (M * 2));
2460 }
2461};
2462template <class T, int M>
2463struct hash<linalg::mat<T, M, 4>> {
2464 std::size_t operator()(const linalg::mat<T, M, 4> &v) const {
2465 std::hash<linalg::vec<T, M>> h;
2466 return h(v.x) ^ (h(v.y) << M) ^ (h(v.z) << (M * 2)) ^ (h(v.w) << (M * 3));
2467 }
2468};
2470} // namespace std
2471
2472// Definitions of functions too long to be defined inline
2473template <class T>
2474constexpr linalg::mat<T, 3, 3> linalg::adjugate(const mat<T, 3, 3> &a) {
2475 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,
2476 a.x.y * a.y.z - a.y.y * a.x.z},
2477 {a.y.z * a.z.x - a.z.z * a.y.x, a.z.z * a.x.x - a.x.z * a.z.x,
2478 a.x.z * a.y.x - a.y.z * a.x.x},
2479 {a.y.x * a.z.y - a.z.x * a.y.y, a.z.x * a.x.y - a.x.x * a.z.y,
2480 a.x.x * a.y.y - a.y.x * a.x.y}};
2481}
2482
2483template <class T>
2484constexpr linalg::mat<T, 4, 4> linalg::adjugate(const mat<T, 4, 4> &a) {
2485 return {{a.y.y * a.z.z * a.w.w + a.w.y * a.y.z * a.z.w +
2486 a.z.y * a.w.z * a.y.w - a.y.y * a.w.z * a.z.w -
2487 a.z.y * a.y.z * a.w.w - a.w.y * a.z.z * a.y.w,
2488 a.x.y * a.w.z * a.z.w + a.z.y * a.x.z * a.w.w +
2489 a.w.y * a.z.z * a.x.w - a.w.y * a.x.z * a.z.w -
2490 a.z.y * a.w.z * a.x.w - a.x.y * a.z.z * a.w.w,
2491 a.x.y * a.y.z * a.w.w + a.w.y * a.x.z * a.y.w +
2492 a.y.y * a.w.z * a.x.w - a.x.y * a.w.z * a.y.w -
2493 a.y.y * a.x.z * a.w.w - a.w.y * a.y.z * a.x.w,
2494 a.x.y * a.z.z * a.y.w + a.y.y * a.x.z * a.z.w +
2495 a.z.y * a.y.z * a.x.w - a.x.y * a.y.z * a.z.w -
2496 a.z.y * a.x.z * a.y.w - a.y.y * a.z.z * a.x.w},
2497 {a.y.z * a.w.w * a.z.x + a.z.z * a.y.w * a.w.x +
2498 a.w.z * a.z.w * a.y.x - a.y.z * a.z.w * a.w.x -
2499 a.w.z * a.y.w * a.z.x - a.z.z * a.w.w * a.y.x,
2500 a.x.z * a.z.w * a.w.x + a.w.z * a.x.w * a.z.x +
2501 a.z.z * a.w.w * a.x.x - a.x.z * a.w.w * a.z.x -
2502 a.z.z * a.x.w * a.w.x - a.w.z * a.z.w * a.x.x,
2503 a.x.z * a.w.w * a.y.x + a.y.z * a.x.w * a.w.x +
2504 a.w.z * a.y.w * a.x.x - a.x.z * a.y.w * a.w.x -
2505 a.w.z * a.x.w * a.y.x - a.y.z * a.w.w * a.x.x,
2506 a.x.z * a.y.w * a.z.x + a.z.z * a.x.w * a.y.x +
2507 a.y.z * a.z.w * a.x.x - a.x.z * a.z.w * a.y.x -
2508 a.y.z * a.x.w * a.z.x - a.z.z * a.y.w * a.x.x},
2509 {a.y.w * a.z.x * a.w.y + a.w.w * a.y.x * a.z.y +
2510 a.z.w * a.w.x * a.y.y - a.y.w * a.w.x * a.z.y -
2511 a.z.w * a.y.x * a.w.y - a.w.w * a.z.x * a.y.y,
2512 a.x.w * a.w.x * a.z.y + a.z.w * a.x.x * a.w.y +
2513 a.w.w * a.z.x * a.x.y - a.x.w * a.z.x * a.w.y -
2514 a.w.w * a.x.x * a.z.y - a.z.w * a.w.x * a.x.y,
2515 a.x.w * a.y.x * a.w.y + a.w.w * a.x.x * a.y.y +
2516 a.y.w * a.w.x * a.x.y - a.x.w * a.w.x * a.y.y -
2517 a.y.w * a.x.x * a.w.y - a.w.w * a.y.x * a.x.y,
2518 a.x.w * a.z.x * a.y.y + a.y.w * a.x.x * a.z.y +
2519 a.z.w * a.y.x * a.x.y - a.x.w * a.y.x * a.z.y -
2520 a.z.w * a.x.x * a.y.y - a.y.w * a.z.x * a.x.y},
2521 {a.y.x * a.w.y * a.z.z + a.z.x * a.y.y * a.w.z +
2522 a.w.x * a.z.y * a.y.z - a.y.x * a.z.y * a.w.z -
2523 a.w.x * a.y.y * a.z.z - a.z.x * a.w.y * a.y.z,
2524 a.x.x * a.z.y * a.w.z + a.w.x * a.x.y * a.z.z +
2525 a.z.x * a.w.y * a.x.z - a.x.x * a.w.y * a.z.z -
2526 a.z.x * a.x.y * a.w.z - a.w.x * a.z.y * a.x.z,
2527 a.x.x * a.w.y * a.y.z + a.y.x * a.x.y * a.w.z +
2528 a.w.x * a.y.y * a.x.z - a.x.x * a.y.y * a.w.z -
2529 a.w.x * a.x.y * a.y.z - a.y.x * a.w.y * a.x.z,
2530 a.x.x * a.y.y * a.z.z + a.z.x * a.x.y * a.y.z +
2531 a.y.x * a.z.y * a.x.z - a.x.x * a.z.y * a.y.z -
2532 a.y.x * a.x.y * a.z.z - a.z.x * a.y.y * a.x.z}};
2533}
2534
2535template <class T>
2536constexpr T linalg::determinant(const mat<T, 4, 4> &a) {
2537 return a.x.x * (a.y.y * a.z.z * a.w.w + a.w.y * a.y.z * a.z.w +
2538 a.z.y * a.w.z * a.y.w - a.y.y * a.w.z * a.z.w -
2539 a.z.y * a.y.z * a.w.w - a.w.y * a.z.z * a.y.w) +
2540 a.x.y * (a.y.z * a.w.w * a.z.x + a.z.z * a.y.w * a.w.x +
2541 a.w.z * a.z.w * a.y.x - a.y.z * a.z.w * a.w.x -
2542 a.w.z * a.y.w * a.z.x - a.z.z * a.w.w * a.y.x) +
2543 a.x.z * (a.y.w * a.z.x * a.w.y + a.w.w * a.y.x * a.z.y +
2544 a.z.w * a.w.x * a.y.y - a.y.w * a.w.x * a.z.y -
2545 a.z.w * a.y.x * a.w.y - a.w.w * a.z.x * a.y.y) +
2546 a.x.w * (a.y.x * a.w.y * a.z.z + a.z.x * a.y.y * a.w.z +
2547 a.w.x * a.z.y * a.y.z - a.y.x * a.z.y * a.w.z -
2548 a.w.x * a.y.y * a.z.z - a.z.x * a.w.y * a.y.z);
2549}
2550
2551template <class T>
2552linalg::vec<T, 4> linalg::rotation_quat(const vec<T, 3> &orig,
2553 const vec<T, 3> &dest) {
2554 T cosTheta = dot(orig, dest);
2555 if (cosTheta >= 1 - std::numeric_limits<T>::epsilon()) {
2556 return {0, 0, 0, 1};
2557 }
2558 if (cosTheta < -1 + std::numeric_limits<T>::epsilon()) {
2559 vec<T, 3> axis = cross(vec<T, 3>(0, 0, 1), orig);
2560 if (length2(axis) < std::numeric_limits<T>::epsilon())
2561 axis = cross(vec<T, 3>(1, 0, 0), orig);
2562 return rotation_quat(normalize(axis),
2563 3.14159265358979323846264338327950288);
2564 }
2565 vec<T, 3> axis = cross(orig, dest);
2566 T s = std::sqrt((1 + cosTheta) * 2);
2567 return {axis * (1 / s), s * 0.5};
2568}
2569
2570template <class T>
2571linalg::vec<T, 4> linalg::rotation_quat(const mat<T, 3, 3> &m) {
2572 const vec<T, 4> q{m.x.x - m.y.y - m.z.z, m.y.y - m.x.x - m.z.z,
2573 m.z.z - m.x.x - m.y.y, m.x.x + m.y.y + m.z.z},
2574 s[]{{1, m.x.y + m.y.x, m.z.x + m.x.z, m.y.z - m.z.y},
2575 {m.x.y + m.y.x, 1, m.y.z + m.z.y, m.z.x - m.x.z},
2576 {m.x.z + m.z.x, m.y.z + m.z.y, 1, m.x.y - m.y.x},
2577 {m.y.z - m.z.y, m.z.x - m.x.z, m.x.y - m.y.x, 1}};
2578 return copysign(normalize(sqrt(max(T(0), T(1) + q))), s[argmax(q)]);
2579}
2580
2581template <class T>
2582linalg::mat<T, 4, 4> linalg::lookat_matrix(const vec<T, 3> &eye,
2583 const vec<T, 3> &center,
2584 const vec<T, 3> &view_y_dir,
2585 fwd_axis a) {
2586 const vec<T, 3> f = normalize(center - eye), z = a == pos_z ? f : -f,
2587 x = normalize(cross(view_y_dir, z)), y = cross(z, x);
2588 return inverse(mat<T, 4, 4>{{x, 0}, {y, 0}, {z, 0}, {eye, 1}});
2589}
2590
2591template <class T>
2592linalg::mat<T, 4, 4> linalg::frustum_matrix(T x0, T x1, T y0, T y1, T n, T f,
2593 fwd_axis a, z_range z) {
2594 const T s = a == pos_z ? T(1) : T(-1), o = z == neg_one_to_one ? n : 0;
2595 return {{2 * n / (x1 - x0), 0, 0, 0},
2596 {0, 2 * n / (y1 - y0), 0, 0},
2597 {-s * (x0 + x1) / (x1 - x0), -s * (y0 + y1) / (y1 - y0),
2598 s * (f + o) / (f - n), s},
2599 {0, 0, -(n + o) * f / (f - n), 0}};
2600}
2601#endif
constexpr mat< T, 3, 3 > qmat(const vec< T, 4 > &q)
Create an equivalent mat3 rotation matrix from the input quaternion.
Definition linalg.h:1997
vec< T, 4 > qslerp(const vec< T, 4 > &a, const vec< T, 4 > &b, T t)
Spherical linear interpolation that takes the shortest path.
Definition linalg.h:2035
T qangle(const vec< T, 4 > &q)
Return the angle in radians of the axis-angle representation of the input normalized quaternion.
Definition linalg.h:2012
constexpr vec< T, 3 > qzdir(const vec< T, 4 > &q)
efficient shorthand for qrot(q, {0,0,1})
Definition linalg.h:1989
vec< T, 4 > qnlerp(const vec< T, 4 > &a, const vec< T, 4 > &b, T t)
Linear interpolation that takes the shortest path - this is not geometrically sensible,...
Definition linalg.h:2028
vec< T, 3 > qaxis(const vec< T, 4 > &q)
Return the normalized axis of the axis-angle representation of the input normalized quaternion.
Definition linalg.h:2020
vec< T, 4 > constexpr rotation_quat(const vec< T, 3 > &axis, T angle)
Returns a normalized quaternion representing a rotation by angle in radians about the provided axis.
Definition linalg.h:2043
constexpr vec< T, 3 > qxdir(const vec< T, 4 > &q)
efficient shorthand for qrot(q, {1,0,0})
Definition linalg.h:1972
constexpr vec< T, 3 > qrot(const vec< T, 4 > &q, const vec< T, 3 > &v)
Rotate a vector by a quaternion.
Definition linalg.h:2004
constexpr vec< T, 3 > qydir(const vec< T, 4 > &q)
efficient shorthand for qrot(q, {0,1,0})
Definition linalg.h:1980
vec< T, 4 > qinv(const vec< T, 4 > &q)
inverse or reciprocal of quaternion q (undefined for zero-length quaternions)
Definition linalg.h:1906
vec< T, 4 > qexp(const vec< T, 4 > &q)
exponential of quaternion q
Definition linalg.h:1915
vec< T, 4 > qpow(const vec< T, 4 > &q, const T &p)
quaternion q raised to the exponent p
Definition linalg.h:1936
vec< T, 4 > qlog(const vec< T, 4 > &q)
logarithm of quaternion q
Definition linalg.h:1927
constexpr vec< T, 4 > qmul(const vec< T, 4 > &a, const vec< T, 4 > &b)
Hamilton product of quaternions a and b
Definition linalg.h:1948
constexpr vec< T, 4 > qconj(const vec< T, 4 > &q)
conjugate of quaternion q
Definition linalg.h:1897
constexpr apply_t< detail::clamp, X, L, H > clamp(const X &x, const L &l, const H &h)
Clamps the components of x between l and h, provided l[i] < h[i].
Definition linalg.h:1707
constexpr apply_t< detail::select, P, A, B > select(const P &p, const A &a, const B &b)
Returns the component from a if the corresponding component of p is true and from b otherwise.
Definition linalg.h:1716
constexpr apply_t< detail::lerp, A, B, T > lerp(const A &a, const B &b, const T &t)
Linear interpolation from a to b as t goes from 0 -> 1. Values beyond [a, b] will result if t is outs...
Definition linalg.h:1725
constexpr vec< T, sizeof...(I)> swizzle(const vec< T, M > &a)
Returns a vector containing the specified ordered indices, e.g. linalg::swizzle<1,...
Definition linalg.h:1528
constexpr mat< T, I1 - I0, J1 - J0 > submat(const mat< T, M, N > &a)
Returns a matrix containing the specified row and column range: linalg::submat<rowStart,...
Definition linalg.h:1544
constexpr vec< T, I1 - I0 > subvec(const vec< T, M > &a)
Returns a vector containing the specified index range, e.g. linalg::subvec<1, 4>(vec4(4,...
Definition linalg.h:1536
vec< T, 3 > roty(T a, const vec< T, 3 > &v)
vector v rotated counter-clockwise by the angle a in radians around the Y axis
Definition linalg.h:1851
vec< T, 2 > rot(T a, const vec< T, 2 > &v)
vector v rotated counter-clockwise by the angle a in radians
Definition linalg.h:1833
constexpr T distance2(const vec< T, M > &a, const vec< T, M > &b)
square of the Euclidean distance between points a and b
Definition linalg.h:1802
vec< T, 3 > rotx(T a, const vec< T, 3 > &v)
vector v rotated counter-clockwise by the angle a in radians around the X axis
Definition linalg.h:1842
constexpr T length2(const vec< T, M > &a)
square of the length or magnitude of vector a
Definition linalg.h:1777
constexpr T dot(const vec< T, M > &a, const vec< T, M > &b)
dot or inner product of vectors a and b
Definition linalg.h:1770
vec< T, M > nlerp(const vec< T, M > &a, const vec< T, M > &b, T t)
shorthand for normalize(lerp(a,b,t))
Definition linalg.h:1868
vec< T, M > normalize(const vec< T, M > &a)
unit length vector in the same direction as a (undefined for zero-length vectors)
Definition linalg.h:1793
vec< T, M > slerp(const vec< T, M > &a, const vec< T, M > &b, T t)
spherical linear interpolation between unit vectors a and b (undefined for non-unit vectors) by param...
Definition linalg.h:1877
T angle(const vec< T, M > &a, const vec< T, M > &b)
Return the angle in radians between two non-unit vectors.
Definition linalg.h:1825
T uangle(const vec< T, M > &a, const vec< T, M > &b)
Return the angle in radians between two unit vectors.
Definition linalg.h:1817
constexpr T cross(const vec< T, 2 > &a, const vec< T, 2 > &b)
shorthand for cross({a.x,a.y,0}, {b.x,b.y,0}).z
Definition linalg.h:1740
vec< T, 3 > rotz(T a, const vec< T, 3 > &v)
vector v rotated counter-clockwise by the angle a in radians around the Z axis
Definition linalg.h:1860
T length(const vec< T, M > &a)
length or magnitude of a vector a
Definition linalg.h:1784
T distance(const vec< T, M > &a, const vec< T, M > &b)
Euclidean distance between points a and b
Definition linalg.h:1810
Definition linalg.h:73
Definition linalg.h:125
Definition linalg.h:288
Definition linalg.h:456
Definition linalg.h:272
Definition linalg.h:200
Definition linalg.h:472
Definition linalg.h:234
Definition linalg.h:449
Definition linalg.h:442
Definition linalg.h:523
Definition linalg.h:601
Definition linalg.h:499
Definition linalg.h:511
Definition linalg.h:571
Definition linalg.h:565
Definition linalg.h:553
Definition linalg.h:583
Definition linalg.h:559
Definition linalg.h:535
Definition linalg.h:547
Definition linalg.h:517
Definition linalg.h:505
Definition linalg.h:577
Definition linalg.h:487
Definition linalg.h:493
Definition linalg.h:607
Definition linalg.h:481
Definition linalg.h:541
Definition linalg.h:529
Definition linalg.h:595
Definition linalg.h:589
Definition linalg.h:95
Definition linalg.h:82
Definition linalg.h:274
Definition linalg.h:465
Definition linalg.h:232
Definition linalg.h:621
Definition linalg.h:693
Definition linalg.h:687
Definition linalg.h:741
Definition linalg.h:699
Definition linalg.h:633
Definition linalg.h:747
Definition linalg.h:675
Definition linalg.h:711
Definition linalg.h:639
Definition linalg.h:627
Definition linalg.h:729
Definition linalg.h:615
Definition linalg.h:657
Definition linalg.h:651
Definition linalg.h:645
Definition linalg.h:735
Definition linalg.h:723
Definition linalg.h:669
Definition linalg.h:705
Definition linalg.h:663
Definition linalg.h:681
Definition linalg.h:717
Definition linalg.h:1183
Definition linalg.h:68
Definition linalg.h:63