Manifold 3.0
Robust geometry
Loading...
Searching...
No Matches
linalg.h
1// Copyright 2026 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 <cstdlib> // To resolve std::abs ambiguity on clang
41#include <functional> // For std::hash declaration
42#include <type_traits> // For std::enable_if, std::is_same, std::declval
43
44#include "./math.h"
45
46// In Visual Studio 2015, `constexpr` applied to a member function implies
47// `const`, which causes ambiguous overload resolution
48#if defined(_MSC_VER) && (_MSC_VER <= 1900)
49#define LINALG_CONSTEXPR14
50#else
51#define LINALG_CONSTEXPR14 constexpr
52#endif
53
54namespace linalg {
55// Small, fixed-length vector type, consisting of exactly M elements of type T,
56// and presumed to be a column-vector unless otherwise noted.
57template <class T, int M>
58struct vec;
59
60// Small, fixed-size matrix type, consisting of exactly M rows and N columns of
61// type T, stored in column-major order.
62template <class T, int M, int N>
63struct mat;
64
65// Specialize converter<T,U> with a function application operator that converts
66// type U to type T to enable implicit conversions
67template <class T, class U>
68struct converter {};
69namespace detail {
70template <class T, class U>
71using conv_t = typename std::enable_if<!std::is_same<T, U>::value,
72 decltype(converter<T, U>{}(
73 std::declval<U>()))>::type;
74
75// Trait for retrieving scalar type of any linear algebra object
76template <class A>
77struct scalar_type {};
78template <class T, int M>
79struct scalar_type<vec<T, M>> {
80 using type = T;
81};
82template <class T, int M, int N>
83struct scalar_type<mat<T, M, N>> {
84 using type = T;
85};
86
87// Type returned by the compare(...) function which supports all six comparison
88// operators against 0
89template <class T>
90struct ord {
91 T a, b;
92};
93template <class T>
94constexpr bool operator==(const ord<T>& o, std::nullptr_t) {
95 return o.a == o.b;
96}
97template <class T>
98constexpr bool operator!=(const ord<T>& o, std::nullptr_t) {
99 return !(o.a == o.b);
100}
101template <class T>
102constexpr bool operator<(const ord<T>& o, std::nullptr_t) {
103 return o.a < o.b;
104}
105template <class T>
106constexpr bool operator>(const ord<T>& o, std::nullptr_t) {
107 return o.b < o.a;
108}
109template <class T>
110constexpr bool operator<=(const ord<T>& o, std::nullptr_t) {
111 return !(o.b < o.a);
112}
113template <class T>
114constexpr bool operator>=(const ord<T>& o, std::nullptr_t) {
115 return !(o.a < o.b);
116}
117
118// Patterns which can be used with the compare(...) function
119template <class A, class B>
120struct any_compare {};
121template <class T>
122struct any_compare<vec<T, 1>, vec<T, 1>> {
123 using type = ord<T>;
124 constexpr ord<T> operator()(const vec<T, 1>& a, const vec<T, 1>& b) const {
125 return ord<T>{a.x, b.x};
126 }
127};
128template <class T>
129struct any_compare<vec<T, 2>, vec<T, 2>> {
130 using type = ord<T>;
131 constexpr ord<T> operator()(const vec<T, 2>& a, const vec<T, 2>& b) const {
132 return !(a.x == b.x) ? ord<T>{a.x, b.x} : ord<T>{a.y, b.y};
133 }
134};
135template <class T>
136struct any_compare<vec<T, 3>, vec<T, 3>> {
137 using type = ord<T>;
138 constexpr ord<T> operator()(const vec<T, 3>& a, const vec<T, 3>& b) const {
139 return !(a.x == b.x) ? ord<T>{a.x, b.x}
140 : !(a.y == b.y) ? ord<T>{a.y, b.y}
141 : ord<T>{a.z, b.z};
142 }
143};
144template <class T>
145struct any_compare<vec<T, 4>, vec<T, 4>> {
146 using type = ord<T>;
147 constexpr ord<T> operator()(const vec<T, 4>& a, const vec<T, 4>& b) const {
148 return !(a.x == b.x) ? ord<T>{a.x, b.x}
149 : !(a.y == b.y) ? ord<T>{a.y, b.y}
150 : !(a.z == b.z) ? ord<T>{a.z, b.z}
151 : ord<T>{a.w, b.w};
152 }
153};
154template <class T, int M>
155struct any_compare<mat<T, M, 1>, mat<T, M, 1>> {
156 using type = ord<T>;
157 constexpr ord<T> operator()(const mat<T, M, 1>& a,
158 const mat<T, M, 1>& b) const {
159 return compare(a.x, b.x);
160 }
161};
162template <class T, int M>
163struct any_compare<mat<T, M, 2>, mat<T, M, 2>> {
164 using type = ord<T>;
165 constexpr ord<T> operator()(const mat<T, M, 2>& a,
166 const mat<T, M, 2>& b) const {
167 return a.x != b.x ? compare(a.x, b.x) : compare(a.y, b.y);
168 }
169};
170template <class T, int M>
171struct any_compare<mat<T, M, 3>, mat<T, M, 3>> {
172 using type = ord<T>;
173 constexpr ord<T> operator()(const mat<T, M, 3>& a,
174 const mat<T, M, 3>& b) const {
175 return a.x != b.x ? compare(a.x, b.x)
176 : a.y != b.y ? compare(a.y, b.y)
177 : compare(a.z, b.z);
178 }
179};
180template <class T, int M>
181struct any_compare<mat<T, M, 4>, mat<T, M, 4>> {
182 using type = ord<T>;
183 constexpr ord<T> operator()(const mat<T, M, 4>& a,
184 const mat<T, M, 4>& b) const {
185 return a.x != b.x ? compare(a.x, b.x)
186 : a.y != b.y ? compare(a.y, b.y)
187 : a.z != b.z ? compare(a.z, b.z)
188 : compare(a.w, b.w);
189 }
190};
191
192// Helper for compile-time index-based access to members of vector and matrix
193// types
194template <int I>
195struct getter;
196template <>
197struct getter<0> {
198 template <class A>
199 constexpr auto operator()(A& a) const -> decltype(a.x) {
200 return a.x;
201 }
202};
203template <>
204struct getter<1> {
205 template <class A>
206 constexpr auto operator()(A& a) const -> decltype(a.y) {
207 return a.y;
208 }
209};
210template <>
211struct getter<2> {
212 template <class A>
213 constexpr auto operator()(A& a) const -> decltype(a.z) {
214 return a.z;
215 }
216};
217template <>
218struct getter<3> {
219 template <class A>
220 constexpr auto operator()(A& a) const -> decltype(a.w) {
221 return a.w;
222 }
223};
224
225// Stand-in for std::integer_sequence/std::make_integer_sequence
226template <int... I>
227struct seq {};
228template <int A, int N>
230template <int A>
231struct make_seq_impl<A, 0> {
232 using type = seq<>;
233};
234template <int A>
235struct make_seq_impl<A, 1> {
236 using type = seq<A + 0>;
237};
238template <int A>
239struct make_seq_impl<A, 2> {
240 using type = seq<A + 0, A + 1>;
241};
242template <int A>
243struct make_seq_impl<A, 3> {
244 using type = seq<A + 0, A + 1, A + 2>;
245};
246template <int A>
247struct make_seq_impl<A, 4> {
249};
250template <int A, int B>
251using make_seq = typename make_seq_impl<A, B - A>::type;
252template <class T, int M, int... I>
253vec<T, sizeof...(I)> constexpr swizzle(const vec<T, M>& v, seq<I...>) {
254 return {getter<I>{}(v)...};
255}
256template <class T, int M, int N, int... I, int... J>
257mat<T, sizeof...(I), sizeof...(J)> constexpr swizzle(const mat<T, M, N>& m,
258 seq<I...> i, seq<J...>) {
259 return {swizzle(getter<J>{}(m), i)...};
260}
261
262// SFINAE helpers to determine result of function application
263template <class F, class... T>
264using ret_t = decltype(std::declval<F>()(std::declval<T>()...));
265
266// SFINAE helper which is defined if all provided types are scalars
267struct empty {};
268template <class... T>
269struct scalars;
270template <>
271struct scalars<> {
272 using type = void;
273};
274template <class T, class... U>
275struct scalars<T, U...> : std::conditional<std::is_arithmetic<T>::value,
276 scalars<U...>, empty>::type {};
277template <class... T>
278using scalars_t = typename scalars<T...>::type;
279
280// Helpers which indicate how apply(F, ...) should be called for various
281// arguments
282template <class F, class Void, class... T>
283struct apply {}; // Patterns which contain only vectors or scalars
284template <class F, int M, class A>
285struct apply<F, scalars_t<>, vec<A, M>> {
286 using type = vec<ret_t<F, A>, M>;
287 enum { size = M, mm = 0 };
288 template <int... I>
289 static constexpr type impl(seq<I...>, F f, const vec<A, M>& a) {
290 return {f(getter<I>{}(a))...};
291 }
292};
293template <class F, int M, class A, class B>
294struct apply<F, scalars_t<>, vec<A, M>, vec<B, M>> {
295 using type = vec<ret_t<F, A, B>, M>;
296 enum { size = M, mm = 0 };
297 template <int... I>
298 static constexpr type impl(seq<I...>, F f, const vec<A, M>& a,
299 const vec<B, M>& b) {
300 return {f(getter<I>{}(a), getter<I>{}(b))...};
301 }
302};
303template <class F, int M, class A, class B>
304struct apply<F, scalars_t<B>, vec<A, M>, B> {
305 using type = vec<ret_t<F, A, B>, M>;
306 enum { size = M, mm = 0 };
307 template <int... I>
308 static constexpr type impl(seq<I...>, F f, const vec<A, M>& a, B b) {
309 return {f(getter<I>{}(a), b)...};
310 }
311};
312template <class F, int M, class A, class B>
313struct apply<F, scalars_t<A>, A, vec<B, M>> {
314 using type = vec<ret_t<F, A, B>, M>;
315 enum { size = M, mm = 0 };
316 template <int... I>
317 static constexpr type impl(seq<I...>, F f, A a, const vec<B, M>& b) {
318 return {f(a, getter<I>{}(b))...};
319 }
320};
321template <class F, int M, class A, class B, class C>
322struct apply<F, scalars_t<>, vec<A, M>, vec<B, M>, vec<C, M>> {
323 using type = vec<ret_t<F, A, B, C>, M>;
324 enum { size = M, mm = 0 };
325 template <int... I>
326 static constexpr type impl(seq<I...>, F f, const vec<A, M>& a,
327 const vec<B, M>& b, const vec<C, M>& c) {
328 return {f(getter<I>{}(a), getter<I>{}(b), getter<I>{}(c))...};
329 }
330};
331template <class F, int M, class A, class B, class C>
332struct apply<F, scalars_t<C>, vec<A, M>, vec<B, M>, C> {
333 using type = vec<ret_t<F, A, B, C>, M>;
334 enum { size = M, mm = 0 };
335 template <int... I>
336 static constexpr type impl(seq<I...>, F f, const vec<A, M>& a,
337 const vec<B, M>& b, C c) {
338 return {f(getter<I>{}(a), getter<I>{}(b), c)...};
339 }
340};
341template <class F, int M, class A, class B, class C>
342struct apply<F, scalars_t<B>, vec<A, M>, B, vec<C, M>> {
343 using type = vec<ret_t<F, A, B, C>, M>;
344 enum { size = M, mm = 0 };
345 template <int... I>
346 static constexpr type impl(seq<I...>, F f, const vec<A, M>& a, B b,
347 const vec<C, M>& c) {
348 return {f(getter<I>{}(a), b, getter<I>{}(c))...};
349 }
350};
351template <class F, int M, class A, class B, class C>
352struct apply<F, scalars_t<B, C>, vec<A, M>, B, C> {
353 using type = vec<ret_t<F, A, B, C>, M>;
354 enum { size = M, mm = 0 };
355 template <int... I>
356 static constexpr type impl(seq<I...>, F f, const vec<A, M>& a, B b, C c) {
357 return {f(getter<I>{}(a), b, c)...};
358 }
359};
360template <class F, int M, class A, class B, class C>
361struct apply<F, scalars_t<A>, A, vec<B, M>, vec<C, M>> {
362 using type = vec<ret_t<F, A, B, C>, M>;
363 enum { size = M, mm = 0 };
364 template <int... I>
365 static constexpr type impl(seq<I...>, F f, A a, const vec<B, M>& b,
366 const vec<C, M>& c) {
367 return {f(a, getter<I>{}(b), getter<I>{}(c))...};
368 }
369};
370template <class F, int M, class A, class B, class C>
371struct apply<F, scalars_t<A, C>, A, vec<B, M>, C> {
372 using type = vec<ret_t<F, A, B, C>, M>;
373 enum { size = M, mm = 0 };
374 template <int... I>
375 static constexpr type impl(seq<I...>, F f, A a, const vec<B, M>& b, C c) {
376 return {f(a, getter<I>{}(b), c)...};
377 }
378};
379template <class F, int M, class A, class B, class C>
380struct apply<F, scalars_t<A, B>, A, B, vec<C, M>> {
381 using type = vec<ret_t<F, A, B, C>, M>;
382 enum { size = M, mm = 0 };
383 template <int... I>
384 static constexpr type impl(seq<I...>, F f, A a, B b, const vec<C, M>& c) {
385 return {f(a, b, getter<I>{}(c))...};
386 }
387};
388template <class F, int M, int N, class A>
389struct apply<F, scalars_t<>, mat<A, M, N>> {
390 using type = mat<ret_t<F, A>, M, N>;
391 enum { size = N, mm = 0 };
392 template <int... J>
393 static constexpr type impl(seq<J...>, F f, const mat<A, M, N>& a) {
394 return {apply<F, void, vec<A, M>>::impl(make_seq<0, M>{}, f,
395 getter<J>{}(a))...};
396 }
397};
398template <class F, int M, int N, class A, class B>
399struct apply<F, scalars_t<>, mat<A, M, N>, mat<B, M, N>> {
400 using type = mat<ret_t<F, A, B>, M, N>;
401 enum { size = N, mm = 1 };
402 template <int... J>
403 static constexpr type impl(seq<J...>, F f, const mat<A, M, N>& a,
404 const mat<B, M, N>& b) {
405 return {apply<F, void, vec<A, M>, vec<B, M>>::impl(
406 make_seq<0, M>{}, f, getter<J>{}(a), getter<J>{}(b))...};
407 }
408};
409template <class F, int M, int N, class A, class B>
410struct apply<F, scalars_t<B>, mat<A, M, N>, B> {
411 using type = mat<ret_t<F, A, B>, M, N>;
412 enum { size = N, mm = 0 };
413 template <int... J>
414 static constexpr type impl(seq<J...>, F f, const mat<A, M, N>& a, B b) {
415 return {apply<F, void, vec<A, M>, B>::impl(make_seq<0, M>{}, f,
416 getter<J>{}(a), b)...};
417 }
418};
419template <class F, int M, int N, class A, class B>
420struct apply<F, scalars_t<A>, A, mat<B, M, N>> {
421 using type = mat<ret_t<F, A, B>, M, N>;
422 enum { size = N, mm = 0 };
423 template <int... J>
424 static constexpr type impl(seq<J...>, F f, A a, const mat<B, M, N>& b) {
425 return {apply<F, void, A, vec<B, M>>::impl(make_seq<0, M>{}, f, a,
426 getter<J>{}(b))...};
427 }
428};
429template <class F, class... A>
430struct apply<F, scalars_t<A...>, A...> {
431 using type = ret_t<F, A...>;
432 enum { size = 0, mm = 0 };
433 static constexpr type impl(seq<>, F f, A... a) { return f(a...); }
434};
435
436// Function objects for selecting between alternatives
437struct min {
438 template <class A, class B>
439 constexpr auto operator()(A a, B b) const ->
440 typename std::remove_reference<decltype(a < b ? a : b)>::type {
441 return a < b ? a : b;
442 }
443};
444struct max {
445 template <class A, class B>
446 constexpr auto operator()(A a, B b) const ->
447 typename std::remove_reference<decltype(a < b ? b : a)>::type {
448 return a < b ? b : a;
449 }
450};
451struct clamp {
452 template <class A, class B, class C>
453 constexpr auto operator()(A a, B b, C c) const ->
454 typename std::remove_reference<decltype(a < b ? b
455 : a < c ? a
456 : c)>::type {
457 return a < b ? b : a < c ? a : c;
458 }
459};
460struct select {
461 template <class A, class B, class C>
462 constexpr auto operator()(A a, B b, C c) const ->
463 typename std::remove_reference<decltype(a ? b : c)>::type {
464 return a ? b : c;
465 }
466};
467struct lerp {
468 template <class A, class B, class C>
469 constexpr auto operator()(A a, B b, C c) const
470 -> decltype(a * (1 - c) + b * c) {
471 return a * (1 - c) + b * c;
472 }
473};
474
475// Function objects for applying operators
476struct op_pos {
477 template <class A>
478 constexpr auto operator()(A a) const -> decltype(+a) {
479 return +a;
480 }
481};
482struct op_neg {
483 template <class A>
484 constexpr auto operator()(A a) const -> decltype(-a) {
485 return -a;
486 }
487};
488struct op_not {
489 template <class A>
490 constexpr auto operator()(A a) const -> decltype(!a) {
491 return !a;
492 }
493};
494struct op_cmp {
495 template <class A>
496 constexpr auto operator()(A a) const -> decltype(~(a)) {
497 return ~a;
498 }
499};
500struct op_mul {
501 template <class A, class B>
502 constexpr auto operator()(A a, B b) const -> decltype(a * b) {
503 return a * b;
504 }
505};
506struct op_div {
507 template <class A, class B>
508 constexpr auto operator()(A a, B b) const -> decltype(a / b) {
509 return a / b;
510 }
511};
512struct op_mod {
513 template <class A, class B>
514 constexpr auto operator()(A a, B b) const -> decltype(a % b) {
515 return a % b;
516 }
517};
518struct op_add {
519 template <class A, class B>
520 constexpr auto operator()(A a, B b) const -> decltype(a + b) {
521 return a + b;
522 }
523};
524struct op_sub {
525 template <class A, class B>
526 constexpr auto operator()(A a, B b) const -> decltype(a - b) {
527 return a - b;
528 }
529};
530struct op_lsh {
531 template <class A, class B>
532 constexpr auto operator()(A a, B b) const -> decltype(a << b) {
533 return a << b;
534 }
535};
536struct op_rsh {
537 template <class A, class B>
538 constexpr auto operator()(A a, B b) const -> decltype(a >> b) {
539 return a >> b;
540 }
541};
542struct op_lt {
543 template <class A, class B>
544 constexpr auto operator()(A a, B b) const -> decltype(a < b) {
545 return a < b;
546 }
547};
548struct op_gt {
549 template <class A, class B>
550 constexpr auto operator()(A a, B b) const -> decltype(a > b) {
551 return a > b;
552 }
553};
554struct op_le {
555 template <class A, class B>
556 constexpr auto operator()(A a, B b) const -> decltype(a <= b) {
557 return a <= b;
558 }
559};
560struct op_ge {
561 template <class A, class B>
562 constexpr auto operator()(A a, B b) const -> decltype(a >= b) {
563 return a >= b;
564 }
565};
566struct op_eq {
567 template <class A, class B>
568 constexpr auto operator()(A a, B b) const -> decltype(a == b) {
569 return a == b;
570 }
571};
572struct op_ne {
573 template <class A, class B>
574 constexpr auto operator()(A a, B b) const -> decltype(a != b) {
575 return a != b;
576 }
577};
578struct op_int {
579 template <class A, class B>
580 constexpr auto operator()(A a, B b) const -> decltype(a & b) {
581 return a & b;
582 }
583};
584struct op_xor {
585 template <class A, class B>
586 constexpr auto operator()(A a, B b) const -> decltype(a ^ b) {
587 return a ^ b;
588 }
589};
590struct op_un {
591 template <class A, class B>
592 constexpr auto operator()(A a, B b) const -> decltype(a | b) {
593 return a | b;
594 }
595};
596struct op_and {
597 template <class A, class B>
598 constexpr auto operator()(A a, B b) const -> decltype(a && b) {
599 return a && b;
600 }
601};
602struct op_or {
603 template <class A, class B>
604 constexpr auto operator()(A a, B b) const -> decltype(a || b) {
605 return a || b;
606 }
607};
608
609// Function objects for applying standard library math functions
611 template <class A>
612 constexpr auto operator()(A a) const -> decltype(std::isfinite(a)) {
613 return std::isfinite(a);
614 }
615};
616struct std_abs {
617 template <class A>
618 constexpr auto operator()(A a) const -> decltype(std::abs(a)) {
619 return std::abs(a);
620 }
621};
622struct std_sqrt {
623 template <class A>
624 constexpr auto operator()(A a) const -> decltype(std::sqrt(a)) {
625 return std::sqrt(a);
626 }
627};
628struct std_sin {
629 double operator()(double a) const { return manifold::math::sin(a); }
630};
631struct std_cos {
632 double operator()(double a) const { return manifold::math::cos(a); }
633};
634struct std_tan {
635 double operator()(double a) const { return manifold::math::tan(a); }
636};
637struct std_asin {
638 double operator()(double a) const { return manifold::math::asin(a); }
639};
640struct std_acos {
641 double operator()(double a) const { return manifold::math::acos(a); }
642};
643struct std_atan {
644 double operator()(double a) const { return manifold::math::atan(a); }
645};
646struct std_atan2 {
647 double operator()(double a, double b) const {
648 return manifold::math::atan2(a, b);
649 }
650};
652 template <class A, class B>
653 constexpr auto operator()(A a, B b) const -> decltype(std::copysign(a, b)) {
654 return std::copysign(a, b);
655 }
656};
657} // namespace detail
658
662
758template <class T>
759struct vec<T, 1> {
760 T x;
761 constexpr vec() : x() {}
762 constexpr vec(const T& x_) : x(x_) {}
763 // NOTE: vec<T,1> does NOT have a constructor from pointer, this can conflict
764 // with initializing its single element from zero
765 template <class U>
766 constexpr explicit vec(const vec<U, 1>& v) : vec(static_cast<T>(v.x)) {}
767 constexpr const T& operator[](int) const { return x; }
768 LINALG_CONSTEXPR14 T& operator[](int) { return x; }
769
770 template <class U, class = detail::conv_t<vec, U>>
771 constexpr vec(const U& u) : vec(converter<vec, U>{}(u)) {}
772 template <class U, class = detail::conv_t<U, vec>>
773 constexpr operator U() const {
774 return converter<U, vec>{}(*this);
775 }
776};
777template <class T>
778struct vec<T, 2> {
779 T x, y;
780 constexpr vec() : x(), y() {}
781 constexpr vec(const T& x_, const T& y_) : x(x_), y(y_) {}
782 constexpr explicit vec(const T& s) : vec(s, s) {}
783 constexpr explicit vec(const T* p) : vec(p[0], p[1]) {}
784 template <class U, int N>
785 constexpr explicit vec(const vec<U, N>& v)
786 : vec(static_cast<T>(v.x), static_cast<T>(v.y)) {
787 static_assert(
788 N >= 2,
789 "You must give extra arguments if your input vector is shorter.");
790 }
791 constexpr const T& operator[](int i) const { return i == 0 ? x : y; }
792 LINALG_CONSTEXPR14 T& operator[](int i) { return i == 0 ? x : y; }
793
794 template <class U, class = detail::conv_t<vec, U>>
795 constexpr vec(const U& u) : vec(converter<vec, U>{}(u)) {}
796 template <class U, class = detail::conv_t<U, vec>>
797 constexpr operator U() const {
798 return converter<U, vec>{}(*this);
799 }
800};
801template <class T>
802struct vec<T, 3> {
803 T x, y, z;
804 constexpr vec() : x(), y(), z() {}
805 constexpr vec(const T& x_, const T& y_, const T& z_) : x(x_), y(y_), z(z_) {}
806 constexpr vec(const vec<T, 2>& xy, const T& z_) : vec(xy.x, xy.y, z_) {}
807 constexpr explicit vec(const T& s) : vec(s, s, s) {}
808 constexpr explicit vec(const T* p) : vec(p[0], p[1], p[2]) {}
809 template <class U, int N>
810 constexpr explicit vec(const vec<U, N>& v)
811 : vec(static_cast<T>(v.x), static_cast<T>(v.y), static_cast<T>(v.z)) {
812 static_assert(
813 N >= 3,
814 "You must give extra arguments if your input vector is shorter.");
815 }
816 constexpr const T& operator[](int i) const {
817 return i == 0 ? x : i == 1 ? y : z;
818 }
819 LINALG_CONSTEXPR14 T& operator[](int i) {
820 return i == 0 ? x : i == 1 ? y : z;
821 }
822 constexpr vec<T, 2> xy() const { return vec<T, 2>(x, y); }
823 constexpr vec<T, 2> yz() const { return vec<T, 2>(y, z); }
824
825 template <class U, class = detail::conv_t<vec, U>>
826 constexpr vec(const U& u) : vec(converter<vec, U>{}(u)) {}
827 template <class U, class = detail::conv_t<U, vec>>
828 constexpr operator U() const {
829 return converter<U, vec>{}(*this);
830 }
831};
832template <class T>
833struct vec<T, 4> {
834 T x, y, z, w;
835 constexpr vec() : x(), y(), z(), w() {}
836 constexpr vec(const T& x_, const T& y_, const T& z_, const T& w_)
837 : x(x_), y(y_), z(z_), w(w_) {}
838 constexpr vec(const vec<T, 2>& xy, const T& z_, const T& w_)
839 : vec(xy.x, xy.y, z_, w_) {}
840 constexpr vec(const vec<T, 3>& xyz, const T& w_)
841 : vec(xyz.x, xyz.y, xyz.z, w_) {}
842 constexpr explicit vec(const T& s) : vec(s, s, s, s) {}
843 constexpr explicit vec(const T* p) : vec(p[0], p[1], p[2], p[3]) {}
844 template <class U, int N>
845 constexpr explicit vec(const vec<U, N>& v)
846 : vec(static_cast<T>(v.x), static_cast<T>(v.y), static_cast<T>(v.z),
847 static_cast<T>(v.w)) {
848 static_assert(
849 N >= 4,
850 "You must give extra arguments if your input vector is shorter.");
851 }
852 constexpr const T& operator[](int i) const {
853 return i == 0 ? x : i == 1 ? y : i == 2 ? z : w;
854 }
855 LINALG_CONSTEXPR14 T& operator[](int i) {
856 return i == 0 ? x : i == 1 ? y : i == 2 ? z : w;
857 }
858 constexpr vec<T, 2> xy() const { return vec<T, 2>(x, y); }
859 constexpr vec<T, 3> xyz() const { return vec<T, 3>(x, y, z); }
860
861 template <class U, class = detail::conv_t<vec, U>>
862 constexpr vec(const U& u) : vec(converter<vec, U>{}(u)) {}
863 template <class U, class = detail::conv_t<U, vec>>
864 constexpr operator U() const {
865 return converter<U, vec>{}(*this);
866 }
867};
868
869
964template <class T, int M>
965struct mat<T, M, 1> {
966 using V = vec<T, M>;
967 V x;
968 constexpr mat() : x() {}
969 constexpr mat(const V& x_) : x(x_) {}
970 constexpr explicit mat(const T& s) : x(s) {}
971 constexpr explicit mat(const T* p) : x(p + M * 0) {}
972 template <class U>
973 constexpr explicit mat(const mat<U, M, 1>& m) : mat(V(m.x)) {}
974 constexpr vec<T, 1> row(int i) const { return {x[i]}; }
975 constexpr const V& operator[](int) const { return x; }
976 LINALG_CONSTEXPR14 V& operator[](int) { return x; }
977
978 template <class U, class = detail::conv_t<mat, U>>
979 constexpr mat(const U& u) : mat(converter<mat, U>{}(u)) {}
980 template <class U, class = detail::conv_t<U, mat>>
981 constexpr operator U() const {
982 return converter<U, mat>{}(*this);
983 }
984};
985template <class T, int M>
986struct mat<T, M, 2> {
987 using V = vec<T, M>;
988 V x, y;
989 constexpr mat() : x(), y() {}
990 constexpr mat(const V& x_, const V& y_) : x(x_), y(y_) {}
991 constexpr explicit mat(const T& s) : x(s), y(s) {}
992 constexpr explicit mat(const T* p) : x(p + M * 0), y(p + M * 1) {}
993 template <class U, int N, int P>
994 constexpr explicit mat(const mat<U, N, P>& m) : mat(V(m.x), V(m.y)) {
995 static_assert(P >= 2, "Input matrix dimensions must be at least as big.");
996 }
997 constexpr vec<T, 2> row(int i) const { return {x[i], y[i]}; }
998 constexpr const V& operator[](int j) const { return j == 0 ? x : y; }
999 LINALG_CONSTEXPR14 V& operator[](int j) { return j == 0 ? x : y; }
1000
1001 template <class U, class = detail::conv_t<mat, U>>
1002 constexpr mat(const U& u) : mat(converter<mat, U>{}(u)) {}
1003 template <class U, class = detail::conv_t<U, mat>>
1004 constexpr operator U() const {
1005 return converter<U, mat>{}(*this);
1006 }
1007};
1008template <class T, int M>
1009struct mat<T, M, 3> {
1010 using V = vec<T, M>;
1011 V x, y, z;
1012 constexpr mat() : x(), y(), z() {}
1013 constexpr mat(const V& x_, const V& y_, const V& z_) : x(x_), y(y_), z(z_) {}
1014 constexpr mat(const mat<T, M, 2>& m_, const V& z_)
1015 : x(m_.x), y(m_.y), z(z_) {}
1016 constexpr explicit mat(const T& s) : x(s), y(s), z(s) {}
1017 constexpr explicit mat(const T* p)
1018 : x(p + M * 0), y(p + M * 1), z(p + M * 2) {}
1019 template <class U, int N, int P>
1020 constexpr explicit mat(const mat<U, N, P>& m) : mat(V(m.x), V(m.y), V(m.z)) {
1021 static_assert(P >= 3, "Input matrix dimensions must be at least as big.");
1022 }
1023 constexpr vec<T, 3> row(int i) const { return {x[i], y[i], z[i]}; }
1024 constexpr const V& operator[](int j) const {
1025 return j == 0 ? x : j == 1 ? y : z;
1026 }
1027 LINALG_CONSTEXPR14 V& operator[](int j) {
1028 return j == 0 ? x : j == 1 ? y : z;
1029 }
1030
1031 template <class U, class = detail::conv_t<mat, U>>
1032 constexpr mat(const U& u) : mat(converter<mat, U>{}(u)) {}
1033 template <class U, class = detail::conv_t<U, mat>>
1034 constexpr operator U() const {
1035 return converter<U, mat>{}(*this);
1036 }
1037};
1038template <class T, int M>
1039struct mat<T, M, 4> {
1040 using V = vec<T, M>;
1041 V x, y, z, w;
1042 constexpr mat() : x(), y(), z(), w() {}
1043 constexpr mat(const V& x_, const V& y_, const V& z_, const V& w_)
1044 : x(x_), y(y_), z(z_), w(w_) {}
1045 constexpr mat(const mat<T, M, 3>& m_, const V& w_)
1046 : x(m_.x), y(m_.y), z(m_.z), w(w_) {}
1047 constexpr explicit mat(const T& s) : x(s), y(s), z(s), w(s) {}
1048 constexpr explicit mat(const T* p)
1049 : x(p + M * 0), y(p + M * 1), z(p + M * 2), w(p + M * 3) {}
1050 template <class U, int N, int P>
1051 constexpr explicit mat(const mat<U, N, P>& m)
1052 : mat(V(m.x), V(m.y), V(m.z), V(m.w)) {
1053 static_assert(P >= 4, "Input matrix dimensions must be at least as big.");
1054 }
1055
1056 constexpr vec<T, 4> row(int i) const { return {x[i], y[i], z[i], w[i]}; }
1057 constexpr const V& operator[](int j) const {
1058 return j == 0 ? x : j == 1 ? y : j == 2 ? z : w;
1059 }
1060 LINALG_CONSTEXPR14 V& operator[](int j) {
1061 return j == 0 ? x : j == 1 ? y : j == 2 ? z : w;
1062 }
1063
1064 template <class U, class = detail::conv_t<mat, U>>
1065 constexpr mat(const U& u) : mat(converter<mat, U>{}(u)) {}
1066 template <class U, class = detail::conv_t<U, mat>>
1067 constexpr operator U() const {
1068 return converter<U, mat>{}(*this);
1069 }
1070};
1071
1072
1079struct identity_t {
1080 constexpr explicit identity_t(int) {}
1081};
1082template <class T>
1083struct converter<mat<T, 1, 1>, identity_t> {
1084 constexpr mat<T, 1, 1> operator()(identity_t) const { return {vec<T, 1>{1}}; }
1085};
1086template <class T>
1087struct converter<mat<T, 2, 2>, identity_t> {
1088 constexpr mat<T, 2, 2> operator()(identity_t) const {
1089 return {{1, 0}, {0, 1}};
1090 }
1091};
1092template <class T>
1093struct converter<mat<T, 2, 3>, identity_t> {
1094 constexpr mat<T, 2, 3> operator()(identity_t) const {
1095 return {{1, 0}, {0, 1}, {0, 0}};
1096 }
1097};
1098template <class T>
1099struct converter<mat<T, 3, 3>, identity_t> {
1100 constexpr mat<T, 3, 3> operator()(identity_t) const {
1101 return {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
1102 }
1103};
1104template <class T>
1105struct converter<mat<T, 3, 4>, identity_t> {
1106 constexpr mat<T, 3, 4> operator()(identity_t) const {
1107 return {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}, {0, 0, 0}};
1108 }
1109};
1110template <class T>
1111struct converter<mat<T, 4, 4>, identity_t> {
1112 constexpr mat<T, 4, 4> operator()(identity_t) const {
1113 return {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
1114 }
1115};
1116constexpr identity_t identity{1};
1118
1126template <class F, class A, class B>
1127constexpr A fold(F f, A a, const vec<B, 1>& b) {
1128 return f(a, b.x);
1129}
1130template <class F, class A, class B>
1131constexpr A fold(F f, A a, const vec<B, 2>& b) {
1132 return f(f(a, b.x), b.y);
1133}
1134template <class F, class A, class B>
1135constexpr A fold(F f, A a, const vec<B, 3>& b) {
1136 return f(f(f(a, b.x), b.y), b.z);
1137}
1138template <class F, class A, class B>
1139constexpr A fold(F f, A a, const vec<B, 4>& b) {
1140 return f(f(f(f(a, b.x), b.y), b.z), b.w);
1141}
1142template <class F, class A, class B, int M>
1143constexpr A fold(F f, A a, const mat<B, M, 1>& b) {
1144 return fold(f, a, b.x);
1145}
1146template <class F, class A, class B, int M>
1147constexpr A fold(F f, A a, const mat<B, M, 2>& b) {
1148 return fold(f, fold(f, a, b.x), b.y);
1149}
1150template <class F, class A, class B, int M>
1151constexpr A fold(F f, A a, const mat<B, M, 3>& b) {
1152 return fold(f, fold(f, fold(f, a, b.x), b.y), b.z);
1153}
1154template <class F, class A, class B, int M>
1155constexpr A fold(F f, A a, const mat<B, M, 4>& b) {
1156 return fold(f, fold(f, fold(f, fold(f, a, b.x), b.y), b.z), b.w);
1157}
1159
1166
1167// Type aliases for the result of calling apply(...) with various arguments, can
1168// be used with return type SFINAE to constrain overload sets
1169template <class F, class... A>
1170using apply_t = typename detail::apply<F, void, A...>::type;
1171template <class F, class... A>
1172using mm_apply_t = typename std::enable_if<detail::apply<F, void, A...>::mm,
1173 apply_t<F, A...>>::type;
1174template <class F, class... A>
1175using no_mm_apply_t = typename std::enable_if<!detail::apply<F, void, A...>::mm,
1176 apply_t<F, A...>>::type;
1177template <class A>
1178using scalar_t =
1179 typename detail::scalar_type<A>::type; // Underlying scalar type when
1180 // performing elementwise operations
1181
1182// apply(f,...) applies the provided function in an elementwise fashion to its
1183// arguments, producing an object of the same dimensions
1184template <class F, class... A>
1185constexpr apply_t<F, A...> apply(F func, const A&... args) {
1187 detail::make_seq<0, detail::apply<F, void, A...>::size>{}, func, args...);
1188}
1189
1190// map(a,f) is equivalent to apply(f,a)
1191template <class A, class F>
1192constexpr apply_t<F, A> map(const A& a, F func) {
1193 return apply(func, a);
1194}
1195
1196// zip(a,b,f) is equivalent to apply(f,a,b)
1197template <class A, class B, class F>
1198constexpr apply_t<F, A, B> zip(const A& a, const B& b, F func) {
1199 return apply(func, a, b);
1200}
1202
1209template <class A, class B>
1210constexpr typename detail::any_compare<A, B>::type compare(const A& a,
1211 const B& b) {
1212 return detail::any_compare<A, B>()(a, b);
1213}
1214template <class A, class B>
1215constexpr auto operator==(const A& a, const B& b)
1216 -> decltype(compare(a, b) == 0) {
1217 return compare(a, b) == 0;
1218}
1219template <class A, class B>
1220constexpr auto operator!=(const A& a, const B& b)
1221 -> decltype(compare(a, b) != 0) {
1222 return compare(a, b) != 0;
1223}
1224template <class A, class B>
1225constexpr auto operator<(const A& a, const B& b)
1226 -> decltype(compare(a, b) < 0) {
1227 return compare(a, b) < 0;
1228}
1229template <class A, class B>
1230constexpr auto operator>(const A& a, const B& b)
1231 -> decltype(compare(a, b) > 0) {
1232 return compare(a, b) > 0;
1233}
1234template <class A, class B>
1235constexpr auto operator<=(const A& a, const B& b)
1236 -> decltype(compare(a, b) <= 0) {
1237 return compare(a, b) <= 0;
1238}
1239template <class A, class B>
1240constexpr auto operator>=(const A& a, const B& b)
1241 -> decltype(compare(a, b) >= 0) {
1242 return compare(a, b) >= 0;
1243}
1245
1251template <class A>
1252constexpr bool any(const A& a) {
1253 return fold(detail::op_or{}, false, a);
1254}
1255template <class A>
1256constexpr bool all(const A& a) {
1257 return fold(detail::op_and{}, true, a);
1258}
1259template <class A>
1260constexpr scalar_t<A> sum(const A& a) {
1261 return fold(detail::op_add{}, scalar_t<A>(0), a);
1262}
1263template <class A>
1264constexpr scalar_t<A> product(const A& a) {
1265 return fold(detail::op_mul{}, scalar_t<A>(1), a);
1266}
1267template <class A>
1268constexpr scalar_t<A> minelem(const A& a) {
1269 return fold(detail::min{}, a.x, a);
1270}
1271template <class A>
1272constexpr scalar_t<A> maxelem(const A& a) {
1273 return fold(detail::max{}, a.x, a);
1274}
1275template <class T, int M>
1276int argmin(const vec<T, M>& a) {
1277 int j = 0;
1278 for (int i = 1; i < M; ++i)
1279 if (a[i] < a[j]) j = i;
1280 return j;
1281}
1282template <class T, int M>
1283int argmax(const vec<T, M>& a) {
1284 int j = 0;
1285 for (int i = 1; i < M; ++i)
1286 if (a[i] > a[j]) j = i;
1287 return j;
1288}
1290
1296template <class A>
1297constexpr apply_t<detail::op_pos, A> operator+(const A& a) {
1298 return apply(detail::op_pos{}, a);
1299}
1300template <class A>
1301constexpr apply_t<detail::op_neg, A> operator-(const A& a) {
1302 return apply(detail::op_neg{}, a);
1303}
1304template <class A>
1305constexpr apply_t<detail::op_cmp, A> operator~(const A& a) {
1306 return apply(detail::op_cmp{}, a);
1307}
1308template <class A>
1309constexpr apply_t<detail::op_not, A> operator!(const A& a) {
1310 return apply(detail::op_not{}, a);
1311}
1313
1322template <class A, class B>
1323constexpr apply_t<detail::op_add, A, B> operator+(const A& a, const B& b) {
1324 return apply(detail::op_add{}, a, b);
1325}
1326template <class A, class B>
1327constexpr apply_t<detail::op_sub, A, B> operator-(const A& a, const B& b) {
1328 return apply(detail::op_sub{}, a, b);
1329}
1330template <class A, class B>
1331constexpr apply_t<detail::op_mul, A, B> cmul(const A& a, const B& b) {
1332 return apply(detail::op_mul{}, a, b);
1333}
1334template <class A, class B>
1335constexpr apply_t<detail::op_div, A, B> operator/(const A& a, const B& b) {
1336 return apply(detail::op_div{}, a, b);
1337}
1338template <class A, class B>
1339constexpr apply_t<detail::op_mod, A, B> operator%(const A& a, const B& b) {
1340 return apply(detail::op_mod{}, a, b);
1341}
1342template <class A, class B>
1343constexpr apply_t<detail::op_un, A, B> operator|(const A& a, const B& b) {
1344 return apply(detail::op_un{}, a, b);
1345}
1346template <class A, class B>
1347constexpr apply_t<detail::op_xor, A, B> operator^(const A& a, const B& b) {
1348 return apply(detail::op_xor{}, a, b);
1349}
1350template <class A, class B>
1351constexpr apply_t<detail::op_int, A, B> operator&(const A& a, const B& b) {
1352 return apply(detail::op_int{}, a, b);
1353}
1354template <class A, class B>
1355constexpr apply_t<detail::op_lsh, A, B> operator<<(const A& a, const B& b) {
1356 return apply(detail::op_lsh{}, a, b);
1357}
1358template <class A, class B>
1359constexpr apply_t<detail::op_rsh, A, B> operator>>(const A& a, const B& b) {
1360 return apply(detail::op_rsh{}, a, b);
1361}
1362
1363// Binary `operator *` represents the algebraic matrix product - use cmul(a, b)
1364// for the Hadamard (component-wise) product.
1365template <class A, class B>
1366constexpr auto operator*(const A& a, const B& b) {
1367 return mul(a, b);
1368}
1369
1370// Binary assignment operators a $= b is always defined as though it were
1371// explicitly written a = a $ b
1372template <class A, class B>
1373constexpr auto operator+=(A& a, const B& b) -> decltype(a = a + b) {
1374 return a = a + b;
1375}
1376template <class A, class B>
1377constexpr auto operator-=(A& a, const B& b) -> decltype(a = a - b) {
1378 return a = a - b;
1379}
1380template <class A, class B>
1381constexpr auto operator*=(A& a, const B& b) -> decltype(a = a * b) {
1382 return a = a * b;
1383}
1384template <class A, class B>
1385constexpr auto operator/=(A& a, const B& b) -> decltype(a = a / b) {
1386 return a = a / b;
1387}
1388template <class A, class B>
1389constexpr auto operator%=(A& a, const B& b) -> decltype(a = a % b) {
1390 return a = a % b;
1391}
1392template <class A, class B>
1393constexpr auto operator|=(A& a, const B& b) -> decltype(a = a | b) {
1394 return a = a | b;
1395}
1396template <class A, class B>
1397constexpr auto operator^=(A& a, const B& b) -> decltype(a = a ^ b) {
1398 return a = a ^ b;
1399}
1400template <class A, class B>
1401constexpr auto operator&=(A& a, const B& b) -> decltype(a = a & b) {
1402 return a = a & b;
1403}
1404template <class A, class B>
1405constexpr auto operator<<=(A& a, const B& b) -> decltype(a = a << b) {
1406 return a = a << b;
1407}
1408template <class A, class B>
1409constexpr auto operator>>=(A& a, const B& b) -> decltype(a = a >> b) {
1410 return a = a >> b;
1411}
1413
1423template <int... I, class T, int M>
1424constexpr vec<T, sizeof...(I)> swizzle(const vec<T, M>& a) {
1425 return {detail::getter<I>{}(a)...};
1426}
1427
1431template <int I0, int I1, class T, int M>
1432constexpr vec<T, I1 - I0> subvec(const vec<T, M>& a) {
1433 return detail::swizzle(a, detail::make_seq<I0, I1>{});
1434}
1435
1439template <int I0, int J0, int I1, int J1, class T, int M, int N>
1440constexpr mat<T, I1 - I0, J1 - J0> submat(const mat<T, M, N>& a) {
1441 return detail::swizzle(a, detail::make_seq<I0, I1>{},
1442 detail::make_seq<J0, J1>{});
1443}
1444
1445
1451template <class A>
1452constexpr apply_t<detail::std_isfinite, A> isfinite(const A& a) {
1453 return apply(detail::std_isfinite{}, a);
1454}
1455template <class A>
1456constexpr apply_t<detail::std_abs, A> abs(const A& a) {
1457 return apply(detail::std_abs{}, a);
1458}
1459template <class A>
1460constexpr apply_t<detail::std_sqrt, A> sqrt(const A& a) {
1461 return apply(detail::std_sqrt{}, a);
1462}
1463template <class A>
1464constexpr apply_t<detail::std_sin, A> sin(const A& a) {
1465 return apply(detail::std_sin{}, a);
1466}
1467template <class A>
1468constexpr apply_t<detail::std_cos, A> cos(const A& a) {
1469 return apply(detail::std_cos{}, a);
1470}
1471template <class A>
1472constexpr apply_t<detail::std_tan, A> tan(const A& a) {
1473 return apply(detail::std_tan{}, a);
1474}
1475template <class A>
1476constexpr apply_t<detail::std_asin, A> asin(const A& a) {
1477 return apply(detail::std_asin{}, a);
1478}
1479template <class A>
1480constexpr apply_t<detail::std_acos, A> acos(const A& a) {
1481 return apply(detail::std_acos{}, a);
1482}
1483template <class A>
1484constexpr apply_t<detail::std_atan, A> atan(const A& a) {
1485 return apply(detail::std_atan{}, a);
1486}
1488
1495template <class A, class B>
1496constexpr apply_t<detail::std_atan2, A, B> atan2(const A& a, const B& b) {
1497 return apply(detail::std_atan2{}, a, b);
1498}
1499template <class A, class B>
1500constexpr apply_t<detail::std_copysign, A, B> copysign(const A& a, const B& b) {
1501 return apply(detail::std_copysign{}, a, b);
1502}
1504
1511template <class A, class B>
1512constexpr apply_t<detail::op_eq, A, B> equal(const A& a, const B& b) {
1513 return apply(detail::op_eq{}, a, b);
1514}
1515template <class A, class B>
1516constexpr apply_t<detail::op_ne, A, B> nequal(const A& a, const B& b) {
1517 return apply(detail::op_ne{}, a, b);
1518}
1519template <class A, class B>
1520constexpr apply_t<detail::op_lt, A, B> less(const A& a, const B& b) {
1521 return apply(detail::op_lt{}, a, b);
1522}
1523template <class A, class B>
1524constexpr apply_t<detail::op_gt, A, B> greater(const A& a, const B& b) {
1525 return apply(detail::op_gt{}, a, b);
1526}
1527template <class A, class B>
1528constexpr apply_t<detail::op_le, A, B> lequal(const A& a, const B& b) {
1529 return apply(detail::op_le{}, a, b);
1530}
1531template <class A, class B>
1532constexpr apply_t<detail::op_ge, A, B> gequal(const A& a, const B& b) {
1533 return apply(detail::op_ge{}, a, b);
1534}
1536
1543template <class A, class B>
1544constexpr apply_t<detail::min, A, B> min(const A& a, const B& b) {
1545 return apply(detail::min{}, a, b);
1546}
1547template <class A, class B>
1548constexpr apply_t<detail::max, A, B> max(const A& a, const B& b) {
1549 return apply(detail::max{}, a, b);
1550}
1554template <class X, class L, class H>
1555constexpr apply_t<detail::clamp, X, L, H> clamp(const X& x, const L& l,
1556 const H& h) {
1557 return apply(detail::clamp{}, x, l, h);
1558}
1559
1563template <class P, class A, class B>
1564constexpr apply_t<detail::select, P, A, B> select(const P& p, const A& a,
1565 const B& b) {
1566 return apply(detail::select{}, p, a, b);
1567}
1568
1572template <class A, class B, class T>
1573constexpr apply_t<detail::lerp, A, B, T> lerp(const A& a, const B& b,
1574 const T& t) {
1575 return apply(detail::lerp{}, a, b, t);
1576}
1577
1578
1587template <class T>
1588constexpr T cross(const vec<T, 2>& a, const vec<T, 2>& b) {
1589 return a.x * b.y - a.y * b.x;
1590}
1591
1594template <class T>
1595constexpr vec<T, 2> cross(T a, const vec<T, 2>& b) {
1596 return {-a * b.y, a * b.x};
1597}
1598
1601template <class T>
1602constexpr vec<T, 2> cross(const vec<T, 2>& a, T b) {
1603 return {a.y * b, -a.x * b};
1604}
1605
1609template <class T>
1610constexpr vec<T, 3> cross(const vec<T, 3>& a, const vec<T, 3>& b) {
1611 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};
1612}
1613
1617template <class T, int M>
1618constexpr T dot(const vec<T, M>& a, const vec<T, M>& b) {
1619 return sum(a * b);
1620}
1621
1624template <class T, int M>
1625constexpr T length2(const vec<T, M>& a) {
1626 return dot(a, a);
1627}
1628
1631template <class T, int M>
1632T length(const vec<T, M>& a) {
1633 return std::sqrt(length2(a));
1634}
1635
1640template <class T, int M>
1642 return a / length(a);
1643}
1644
1649template <class T, int M>
1650constexpr T distance2(const vec<T, M>& a, const vec<T, M>& b) {
1651 return length2(b - a);
1652}
1653
1657template <class T, int M>
1658T distance(const vec<T, M>& a, const vec<T, M>& b) {
1659 return length(b - a);
1660}
1661
1664template <class T, int M>
1665T uangle(const vec<T, M>& a, const vec<T, M>& b) {
1666 T d = dot(a, b);
1667 return d > 1 ? 0 : linalg::acos(d < -1 ? -1 : d);
1668}
1669
1672template <class T, int M>
1673T angle(const vec<T, M>& a, const vec<T, M>& b) {
1674 return uangle(normalize(a), normalize(b));
1675}
1676
1680template <class T>
1681vec<T, 2> rot(T a, const vec<T, 2>& v) {
1682 const T s = linalg::sin(a), c = linalg::cos(a);
1683 return {v.x * c - v.y * s, v.x * s + v.y * c};
1684}
1685
1689template <class T>
1690vec<T, 3> rotx(T a, const vec<T, 3>& v) {
1691 const T s = linalg::sin(a), c = linalg::cos(a);
1692 return {v.x, v.y * c - v.z * s, v.y * s + v.z * c};
1693}
1694
1698template <class T>
1699vec<T, 3> roty(T a, const vec<T, 3>& v) {
1700 const T s = linalg::sin(a), c = linalg::cos(a);
1701 return {v.x * c + v.z * s, v.y, -v.x * s + v.z * c};
1702}
1703
1707template <class T>
1708vec<T, 3> rotz(T a, const vec<T, 3>& v) {
1709 const T s = linalg::sin(a), c = linalg::cos(a);
1710 return {v.x * c - v.y * s, v.x * s + v.y * c, v.z};
1711}
1712
1715template <class T, int M>
1716vec<T, M> nlerp(const vec<T, M>& a, const vec<T, M>& b, T t) {
1717 return normalize(lerp(a, b, t));
1718}
1719
1724template <class T, int M>
1725vec<T, M> slerp(const vec<T, M>& a, const vec<T, M>& b, T t) {
1726 T th = uangle(a, b);
1727 return th == 0 ? a
1728 : a * (linalg::sin(th * (1 - t)) / linalg::sin(th)) +
1729 b * (linalg::sin(th * t) / linalg::sin(th));
1730}
1731
1732
1744template <class T>
1745constexpr vec<T, 4> qconj(const vec<T, 4>& q) {
1746 return {-q.x, -q.y, -q.z, q.w};
1747}
1748
1753template <class T>
1755 return qconj(q) / length2(q);
1756}
1757
1762template <class T>
1764 const auto v = q.xyz();
1765 const auto vv = length(v);
1766 return std::exp(q.w) *
1767 vec<T, 4>{v * (vv > 0 ? linalg::sin(vv) / vv : 0), linalg::cos(vv)};
1768}
1769
1774template <class T>
1776 const auto v = q.xyz();
1777 const auto vv = length(v), qq = length(q);
1778 return {v * (vv > 0 ? linalg::acos(q.w / qq) / vv : 0), std::log(qq)};
1779}
1780
1783template <class T>
1784vec<T, 4> qpow(const vec<T, 4>& q, const T& p) {
1785 const auto v = q.xyz();
1786 const auto vv = length(v), qq = length(q), th = linalg::acos(q.w / qq);
1787 return std::pow(qq, p) *
1788 vec<T, 4>{v * (vv > 0 ? linalg::sin(p * th) / vv : 0),
1789 linalg::cos(p * th)};
1790}
1791
1796template <class T>
1797constexpr vec<T, 4> qmul(const vec<T, 4>& a, const vec<T, 4>& b) {
1798 return {a.x * b.w + a.w * b.x + a.y * b.z - a.z * b.y,
1799 a.y * b.w + a.w * b.y + a.z * b.x - a.x * b.z,
1800 a.z * b.w + a.w * b.z + a.x * b.y - a.y * b.x,
1801 a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z};
1802}
1803
1806template <class T, class... R>
1807constexpr vec<T, 4> qmul(const vec<T, 4>& a, R... r) {
1808 return qmul(a, qmul(r...));
1809}
1810
1811
1820template <class T>
1821constexpr vec<T, 3> qxdir(const vec<T, 4>& q) {
1822 return {q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z,
1823 (q.x * q.y + q.z * q.w) * 2, (q.z * q.x - q.y * q.w) * 2};
1824}
1825
1828template <class T>
1829constexpr vec<T, 3> qydir(const vec<T, 4>& q) {
1830 return {(q.x * q.y - q.z * q.w) * 2,
1831 q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z,
1832 (q.y * q.z + q.x * q.w) * 2};
1833}
1834
1837template <class T>
1838constexpr vec<T, 3> qzdir(const vec<T, 4>& q) {
1839 return {(q.z * q.x + q.y * q.w) * 2, (q.y * q.z - q.x * q.w) * 2,
1840 q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z};
1841}
1842
1845template <class T>
1846constexpr mat<T, 3, 3> qmat(const vec<T, 4>& q) {
1847 return {qxdir(q), qydir(q), qzdir(q)};
1848}
1849
1852template <class T>
1853constexpr vec<T, 3> qrot(const vec<T, 4>& q, const vec<T, 3>& v) {
1854 return qxdir(q) * v.x + qydir(q) * v.y + qzdir(q) * v.z;
1855}
1856
1860template <class T>
1861T qangle(const vec<T, 4>& q) {
1862 return linalg::atan2(length(q.xyz()), q.w) * 2;
1863}
1864
1868template <class T>
1870 return normalize(q.xyz());
1871}
1872
1876template <class T>
1877vec<T, 4> qnlerp(const vec<T, 4>& a, const vec<T, 4>& b, T t) {
1878 return nlerp(a, dot(a, b) < 0 ? -b : b, t);
1879}
1880
1883template <class T>
1884vec<T, 4> qslerp(const vec<T, 4>& a, const vec<T, 4>& b, T t) {
1885 return slerp(a, dot(a, b) < 0 ? -b : b, t);
1886}
1887
1891template <class T>
1892vec<T, 4> constexpr rotation_quat(const vec<T, 3>& axis, T angle) {
1893 return {axis * linalg::sin(angle / 2), linalg::cos(angle / 2)};
1894}
1895
1899template <class T>
1900vec<T, 4> rotation_quat(const vec<T, 3>& orig, const vec<T, 3>& dest);
1905template <class T>
1908
1914template <class T, int M>
1915constexpr vec<T, M> mul(const vec<T, M>& a, const T& b) {
1916 return cmul(a, b);
1917}
1918template <class T, int M>
1919constexpr vec<T, M> mul(const T& b, const vec<T, M>& a) {
1920 return cmul(b, a);
1921}
1922template <class T, int M, int N>
1923constexpr mat<T, M, N> mul(const mat<T, M, N>& a, const T& b) {
1924 return cmul(a, b);
1925}
1926template <class T, int M, int N>
1927constexpr mat<T, M, N> mul(const T& b, const mat<T, M, N>& a) {
1928 return cmul(b, a);
1929}
1930template <class T, int M>
1931constexpr vec<T, M> mul(const vec<T, M>& a, const vec<T, M>& b) {
1932 return cmul(a, b);
1933}
1934template <class T, int M>
1935constexpr vec<T, M> mul(const mat<T, M, 1>& a, const vec<T, 1>& b) {
1936 return a.x * b.x;
1937}
1938template <class T, int M>
1939constexpr vec<T, M> mul(const mat<T, M, 2>& a, const vec<T, 2>& b) {
1940 return a.x * b.x + a.y * b.y;
1941}
1942template <class T, int M>
1943constexpr vec<T, M> mul(const mat<T, M, 3>& a, const vec<T, 3>& b) {
1944 return a.x * b.x + a.y * b.y + a.z * b.z;
1945}
1946template <class T, int M>
1947constexpr vec<T, M> mul(const mat<T, M, 4>& a, const vec<T, 4>& b) {
1948 return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
1949}
1950template <class T, int M, int N>
1951constexpr mat<T, M, 1> mul(const mat<T, M, N>& a, const mat<T, N, 1>& b) {
1952 return {mul(a, b.x)};
1953}
1954template <class T, int M, int N>
1955constexpr mat<T, M, 2> mul(const mat<T, M, N>& a, const mat<T, N, 2>& b) {
1956 return {mul(a, b.x), mul(a, b.y)};
1957}
1958template <class T, int M, int N>
1959constexpr mat<T, M, 3> mul(const mat<T, M, N>& a, const mat<T, N, 3>& b) {
1960 return {mul(a, b.x), mul(a, b.y), mul(a, b.z)};
1961}
1962template <class T, int M, int N>
1963constexpr mat<T, M, 4> mul(const mat<T, M, N>& a, const mat<T, N, 4>& b) {
1964 return {mul(a, b.x), mul(a, b.y), mul(a, b.z), mul(a, b.w)};
1965}
1966template <class T, int M, int N, int P>
1967constexpr vec<T, M> mul(const mat<T, M, N>& a, const mat<T, N, P>& b,
1968 const vec<T, P>& c) {
1969 return mul(mul(a, b), c);
1970}
1971template <class T, int M, int N, int P, int Q>
1972constexpr mat<T, M, Q> mul(const mat<T, M, N>& a, const mat<T, N, P>& b,
1973 const mat<T, P, Q>& c) {
1974 return mul(mul(a, b), c);
1975}
1976template <class T, int M, int N, int P, int Q>
1977constexpr vec<T, M> mul(const mat<T, M, N>& a, const mat<T, N, P>& b,
1978 const mat<T, P, Q>& c, const vec<T, Q>& d) {
1979 return mul(mul(a, b, c), d);
1980}
1981template <class T, int M, int N, int P, int Q, int R>
1982constexpr mat<T, M, R> mul(const mat<T, M, N>& a, const mat<T, N, P>& b,
1983 const mat<T, P, Q>& c, const mat<T, Q, R>& d) {
1984 return mul(mul(a, b, c), d);
1985}
1986template <class T, int M>
1987constexpr mat<T, M, 1> outerprod(const vec<T, M>& a, const vec<T, 1>& b) {
1988 return {a * b.x};
1989}
1990template <class T, int M>
1991constexpr mat<T, M, 2> outerprod(const vec<T, M>& a, const vec<T, 2>& b) {
1992 return {a * b.x, a * b.y};
1993}
1994template <class T, int M>
1995constexpr mat<T, M, 3> outerprod(const vec<T, M>& a, const vec<T, 3>& b) {
1996 return {a * b.x, a * b.y, a * b.z};
1997}
1998template <class T, int M>
1999constexpr mat<T, M, 4> outerprod(const vec<T, M>& a, const vec<T, 4>& b) {
2000 return {a * b.x, a * b.y, a * b.z, a * b.w};
2001}
2002template <class T>
2003constexpr vec<T, 1> diagonal(const mat<T, 1, 1>& a) {
2004 return {a.x.x};
2005}
2006template <class T>
2007constexpr vec<T, 2> diagonal(const mat<T, 2, 2>& a) {
2008 return {a.x.x, a.y.y};
2009}
2010template <class T>
2011constexpr vec<T, 3> diagonal(const mat<T, 3, 3>& a) {
2012 return {a.x.x, a.y.y, a.z.z};
2013}
2014template <class T>
2015constexpr vec<T, 4> diagonal(const mat<T, 4, 4>& a) {
2016 return {a.x.x, a.y.y, a.z.z, a.w.w};
2017}
2018template <class T, int N>
2019constexpr T trace(const mat<T, N, N>& a) {
2020 return sum(diagonal(a));
2021}
2022template <class T, int M>
2023constexpr mat<T, M, 1> transpose(const mat<T, 1, M>& m) {
2024 return {m.row(0)};
2025}
2026template <class T, int M>
2027constexpr mat<T, M, 2> transpose(const mat<T, 2, M>& m) {
2028 return {m.row(0), m.row(1)};
2029}
2030template <class T, int M>
2031constexpr mat<T, M, 3> transpose(const mat<T, 3, M>& m) {
2032 return {m.row(0), m.row(1), m.row(2)};
2033}
2034template <class T, int M>
2035constexpr mat<T, M, 4> transpose(const mat<T, 4, M>& m) {
2036 return {m.row(0), m.row(1), m.row(2), m.row(3)};
2037}
2038template <class T, int M>
2039constexpr mat<T, 1, M> transpose(const vec<T, M>& m) {
2040 return transpose(mat<T, M, 1>(m));
2041}
2042template <class T>
2043constexpr mat<T, 1, 1> adjugate(const mat<T, 1, 1>&) {
2044 return {vec<T, 1>{1}};
2045}
2046template <class T>
2047constexpr mat<T, 2, 2> adjugate(const mat<T, 2, 2>& a) {
2048 return {{a.y.y, -a.x.y}, {-a.y.x, a.x.x}};
2049}
2050template <class T>
2051constexpr mat<T, 3, 3> adjugate(const mat<T, 3, 3>& a);
2052template <class T>
2053constexpr mat<T, 4, 4> adjugate(const mat<T, 4, 4>& a);
2054template <class T, int N>
2055constexpr mat<T, N, N> comatrix(const mat<T, N, N>& a) {
2056 return transpose(adjugate(a));
2057}
2058template <class T>
2059constexpr T determinant(const mat<T, 1, 1>& a) {
2060 return a.x.x;
2061}
2062template <class T>
2063constexpr T determinant(const mat<T, 2, 2>& a) {
2064 return a.x.x * a.y.y - a.x.y * a.y.x;
2065}
2066template <class T>
2067constexpr T determinant(const mat<T, 3, 3>& a) {
2068 return a.x.x * (a.y.y * a.z.z - a.z.y * a.y.z) +
2069 a.x.y * (a.y.z * a.z.x - a.z.z * a.y.x) +
2070 a.x.z * (a.y.x * a.z.y - a.z.x * a.y.y);
2071}
2072template <class T>
2073constexpr T determinant(const mat<T, 4, 4>& a);
2074template <class T, int N>
2075constexpr mat<T, N, N> inverse(const mat<T, N, N>& a) {
2076 return adjugate(a) / determinant(a);
2077}
2079
2085template <class T, int M>
2086T* begin(vec<T, M>& a) {
2087 return &a.x;
2088}
2089template <class T, int M>
2090const T* begin(const vec<T, M>& a) {
2091 return &a.x;
2092}
2093template <class T, int M>
2094T* end(vec<T, M>& a) {
2095 return begin(a) + M;
2096}
2097template <class T, int M>
2098const T* end(const vec<T, M>& a) {
2099 return begin(a) + M;
2100}
2101template <class T, int M, int N>
2102vec<T, M>* begin(mat<T, M, N>& a) {
2103 return &a.x;
2104}
2105template <class T, int M, int N>
2106const vec<T, M>* begin(const mat<T, M, N>& a) {
2107 return &a.x;
2108}
2109template <class T, int M, int N>
2110vec<T, M>* end(mat<T, M, N>& a) {
2111 return begin(a) + N;
2112}
2113template <class T, int M, int N>
2114const vec<T, M>* end(const mat<T, M, N>& a) {
2115 return begin(a) + N;
2116}
2118
2124enum fwd_axis {
2125 neg_z,
2126 pos_z
2127}; // Should projection matrices be generated assuming forward is {0,0,-1} or
2128 // {0,0,1}
2129enum z_range {
2130 neg_one_to_one,
2131 zero_to_one
2132}; // Should projection matrices map z into the range of [-1,1] or [0,1]?
2133template <class T>
2134mat<T, 4, 4> translation_matrix(const vec<T, 3>& translation) {
2135 return {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {translation, 1}};
2136}
2137template <class T>
2138mat<T, 4, 4> rotation_matrix(const vec<T, 4>& rotation) {
2139 return {{qxdir(rotation), 0},
2140 {qydir(rotation), 0},
2141 {qzdir(rotation), 0},
2142 {0, 0, 0, 1}};
2143}
2144template <class T>
2145mat<T, 4, 4> scaling_matrix(const vec<T, 3>& scaling) {
2146 return {{scaling.x, 0, 0, 0},
2147 {0, scaling.y, 0, 0},
2148 {0, 0, scaling.z, 0},
2149 {0, 0, 0, 1}};
2150}
2151template <class T>
2152mat<T, 4, 4> pose_matrix(const vec<T, 4>& q, const vec<T, 3>& p) {
2153 return {{qxdir(q), 0}, {qydir(q), 0}, {qzdir(q), 0}, {p, 1}};
2154}
2155template <class T>
2156mat<T, 4, 4> lookat_matrix(const vec<T, 3>& eye, const vec<T, 3>& center,
2157 const vec<T, 3>& view_y_dir, fwd_axis fwd = neg_z);
2158template <class T>
2159mat<T, 4, 4> frustum_matrix(T x0, T x1, T y0, T y1, T n, T f,
2160 fwd_axis a = neg_z, z_range z = neg_one_to_one);
2161template <class T>
2162mat<T, 4, 4> perspective_matrix(T fovy, T aspect, T n, T f, fwd_axis a = neg_z,
2163 z_range z = neg_one_to_one) {
2164 T y = n * linalg::tan(fovy / 2), x = y * aspect;
2165 return frustum_matrix(-x, x, -y, y, n, f, a, z);
2166}
2168
2175template <class T>
2176struct converter<vec<T, 1>, std::array<T, 1>> {
2177 vec<T, 1> operator()(const std::array<T, 1>& a) const { return {a[0]}; }
2178};
2179template <class T>
2180struct converter<vec<T, 2>, std::array<T, 2>> {
2181 vec<T, 2> operator()(const std::array<T, 2>& a) const { return {a[0], a[1]}; }
2182};
2183template <class T>
2184struct converter<vec<T, 3>, std::array<T, 3>> {
2185 vec<T, 3> operator()(const std::array<T, 3>& a) const {
2186 return {a[0], a[1], a[2]};
2187 }
2188};
2189template <class T>
2190struct converter<vec<T, 4>, std::array<T, 4>> {
2191 vec<T, 4> operator()(const std::array<T, 4>& a) const {
2192 return {a[0], a[1], a[2], a[3]};
2193 }
2194};
2195
2196template <class T>
2197struct converter<std::array<T, 1>, vec<T, 1>> {
2198 std::array<T, 1> operator()(const vec<T, 1>& a) const { return {a[0]}; }
2199};
2200template <class T>
2201struct converter<std::array<T, 2>, vec<T, 2>> {
2202 std::array<T, 2> operator()(const vec<T, 2>& a) const { return {a[0], a[1]}; }
2203};
2204template <class T>
2205struct converter<std::array<T, 3>, vec<T, 3>> {
2206 std::array<T, 3> operator()(const vec<T, 3>& a) const {
2207 return {a[0], a[1], a[2]};
2208 }
2209};
2210template <class T>
2211struct converter<std::array<T, 4>, vec<T, 4>> {
2212 std::array<T, 4> operator()(const vec<T, 4>& a) const {
2213 return {a[0], a[1], a[2], a[3]};
2214 }
2215};
2216
2217} // namespace linalg
2218
2219#ifdef MANIFOLD_DEBUG
2220#include <iostream>
2221
2222namespace linalg {
2223template <class T>
2224std::ostream& operator<<(std::ostream& out, const vec<T, 1>& v) {
2225 return out << '{' << v[0] << '}';
2226}
2227template <class T>
2228std::ostream& operator<<(std::ostream& out, const vec<T, 2>& v) {
2229 return out << '{' << v[0] << ',' << v[1] << '}';
2230}
2231template <class T>
2232std::ostream& operator<<(std::ostream& out, const vec<T, 3>& v) {
2233 return out << '{' << v[0] << ',' << v[1] << ',' << v[2] << '}';
2234}
2235template <class T>
2236std::ostream& operator<<(std::ostream& out, const vec<T, 4>& v) {
2237 return out << '{' << v[0] << ',' << v[1] << ',' << v[2] << ',' << v[3] << '}';
2238}
2239
2240template <class T, int M>
2241std::ostream& operator<<(std::ostream& out, const mat<T, M, 1>& m) {
2242 return out << '{' << m[0] << '}';
2243}
2244template <class T, int M>
2245std::ostream& operator<<(std::ostream& out, const mat<T, M, 2>& m) {
2246 return out << '{' << m[0] << ',' << m[1] << '}';
2247}
2248template <class T, int M>
2249std::ostream& operator<<(std::ostream& out, const mat<T, M, 3>& m) {
2250 return out << '{' << m[0] << ',' << m[1] << ',' << m[2] << '}';
2251}
2252template <class T, int M>
2253std::ostream& operator<<(std::ostream& out, const mat<T, M, 4>& m) {
2254 return out << '{' << m[0] << ',' << m[1] << ',' << m[2] << ',' << m[3] << '}';
2255}
2256} // namespace linalg
2257#endif
2258
2259namespace std {
2265template <class T>
2266struct hash<linalg::vec<T, 1>> {
2267 std::size_t operator()(const linalg::vec<T, 1>& v) const {
2268 std::hash<T> h;
2269 return h(v.x);
2270 }
2271};
2272template <class T>
2273struct hash<linalg::vec<T, 2>> {
2274 std::size_t operator()(const linalg::vec<T, 2>& v) const {
2275 std::hash<T> h;
2276 return h(v.x) ^ (h(v.y) << 1);
2277 }
2278};
2279template <class T>
2280struct hash<linalg::vec<T, 3>> {
2281 std::size_t operator()(const linalg::vec<T, 3>& v) const {
2282 std::hash<T> h;
2283 return h(v.x) ^ (h(v.y) << 1) ^ (h(v.z) << 2);
2284 }
2285};
2286template <class T>
2287struct hash<linalg::vec<T, 4>> {
2288 std::size_t operator()(const linalg::vec<T, 4>& v) const {
2289 std::hash<T> h;
2290 return h(v.x) ^ (h(v.y) << 1) ^ (h(v.z) << 2) ^ (h(v.w) << 3);
2291 }
2292};
2293
2294template <class T, int M>
2295struct hash<linalg::mat<T, M, 1>> {
2296 std::size_t operator()(const linalg::mat<T, M, 1>& v) const {
2297 std::hash<linalg::vec<T, M>> h;
2298 return h(v.x);
2299 }
2300};
2301template <class T, int M>
2302struct hash<linalg::mat<T, M, 2>> {
2303 std::size_t operator()(const linalg::mat<T, M, 2>& v) const {
2304 std::hash<linalg::vec<T, M>> h;
2305 return h(v.x) ^ (h(v.y) << M);
2306 }
2307};
2308template <class T, int M>
2309struct hash<linalg::mat<T, M, 3>> {
2310 std::size_t operator()(const linalg::mat<T, M, 3>& v) const {
2311 std::hash<linalg::vec<T, M>> h;
2312 return h(v.x) ^ (h(v.y) << M) ^ (h(v.z) << (M * 2));
2313 }
2314};
2315template <class T, int M>
2316struct hash<linalg::mat<T, M, 4>> {
2317 std::size_t operator()(const linalg::mat<T, M, 4>& v) const {
2318 std::hash<linalg::vec<T, M>> h;
2319 return h(v.x) ^ (h(v.y) << M) ^ (h(v.z) << (M * 2)) ^ (h(v.w) << (M * 3));
2320 }
2321};
2322
2323} // namespace std
2324
2325// Definitions of functions too long to be defined inline
2326template <class T>
2327constexpr linalg::mat<T, 3, 3> linalg::adjugate(const mat<T, 3, 3>& a) {
2328 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,
2329 a.x.y * a.y.z - a.y.y * a.x.z},
2330 {a.y.z * a.z.x - a.z.z * a.y.x, a.z.z * a.x.x - a.x.z * a.z.x,
2331 a.x.z * a.y.x - a.y.z * a.x.x},
2332 {a.y.x * a.z.y - a.z.x * a.y.y, a.z.x * a.x.y - a.x.x * a.z.y,
2333 a.x.x * a.y.y - a.y.x * a.x.y}};
2334}
2335
2336template <class T>
2337constexpr linalg::mat<T, 4, 4> linalg::adjugate(const mat<T, 4, 4>& a) {
2338 return {{a.y.y * a.z.z * a.w.w + a.w.y * a.y.z * a.z.w +
2339 a.z.y * a.w.z * a.y.w - a.y.y * a.w.z * a.z.w -
2340 a.z.y * a.y.z * a.w.w - a.w.y * a.z.z * a.y.w,
2341 a.x.y * a.w.z * a.z.w + a.z.y * a.x.z * a.w.w +
2342 a.w.y * a.z.z * a.x.w - a.w.y * a.x.z * a.z.w -
2343 a.z.y * a.w.z * a.x.w - a.x.y * a.z.z * a.w.w,
2344 a.x.y * a.y.z * a.w.w + a.w.y * a.x.z * a.y.w +
2345 a.y.y * a.w.z * a.x.w - a.x.y * a.w.z * a.y.w -
2346 a.y.y * a.x.z * a.w.w - a.w.y * a.y.z * a.x.w,
2347 a.x.y * a.z.z * a.y.w + a.y.y * a.x.z * a.z.w +
2348 a.z.y * a.y.z * a.x.w - a.x.y * a.y.z * a.z.w -
2349 a.z.y * a.x.z * a.y.w - a.y.y * a.z.z * a.x.w},
2350 {a.y.z * a.w.w * a.z.x + a.z.z * a.y.w * a.w.x +
2351 a.w.z * a.z.w * a.y.x - a.y.z * a.z.w * a.w.x -
2352 a.w.z * a.y.w * a.z.x - a.z.z * a.w.w * a.y.x,
2353 a.x.z * a.z.w * a.w.x + a.w.z * a.x.w * a.z.x +
2354 a.z.z * a.w.w * a.x.x - a.x.z * a.w.w * a.z.x -
2355 a.z.z * a.x.w * a.w.x - a.w.z * a.z.w * a.x.x,
2356 a.x.z * a.w.w * a.y.x + a.y.z * a.x.w * a.w.x +
2357 a.w.z * a.y.w * a.x.x - a.x.z * a.y.w * a.w.x -
2358 a.w.z * a.x.w * a.y.x - a.y.z * a.w.w * a.x.x,
2359 a.x.z * a.y.w * a.z.x + a.z.z * a.x.w * a.y.x +
2360 a.y.z * a.z.w * a.x.x - a.x.z * a.z.w * a.y.x -
2361 a.y.z * a.x.w * a.z.x - a.z.z * a.y.w * a.x.x},
2362 {a.y.w * a.z.x * a.w.y + a.w.w * a.y.x * a.z.y +
2363 a.z.w * a.w.x * a.y.y - a.y.w * a.w.x * a.z.y -
2364 a.z.w * a.y.x * a.w.y - a.w.w * a.z.x * a.y.y,
2365 a.x.w * a.w.x * a.z.y + a.z.w * a.x.x * a.w.y +
2366 a.w.w * a.z.x * a.x.y - a.x.w * a.z.x * a.w.y -
2367 a.w.w * a.x.x * a.z.y - a.z.w * a.w.x * a.x.y,
2368 a.x.w * a.y.x * a.w.y + a.w.w * a.x.x * a.y.y +
2369 a.y.w * a.w.x * a.x.y - a.x.w * a.w.x * a.y.y -
2370 a.y.w * a.x.x * a.w.y - a.w.w * a.y.x * a.x.y,
2371 a.x.w * a.z.x * a.y.y + a.y.w * a.x.x * a.z.y +
2372 a.z.w * a.y.x * a.x.y - a.x.w * a.y.x * a.z.y -
2373 a.z.w * a.x.x * a.y.y - a.y.w * a.z.x * a.x.y},
2374 {a.y.x * a.w.y * a.z.z + a.z.x * a.y.y * a.w.z +
2375 a.w.x * a.z.y * a.y.z - a.y.x * a.z.y * a.w.z -
2376 a.w.x * a.y.y * a.z.z - a.z.x * a.w.y * a.y.z,
2377 a.x.x * a.z.y * a.w.z + a.w.x * a.x.y * a.z.z +
2378 a.z.x * a.w.y * a.x.z - a.x.x * a.w.y * a.z.z -
2379 a.z.x * a.x.y * a.w.z - a.w.x * a.z.y * a.x.z,
2380 a.x.x * a.w.y * a.y.z + a.y.x * a.x.y * a.w.z +
2381 a.w.x * a.y.y * a.x.z - a.x.x * a.y.y * a.w.z -
2382 a.w.x * a.x.y * a.y.z - a.y.x * a.w.y * a.x.z,
2383 a.x.x * a.y.y * a.z.z + a.z.x * a.x.y * a.y.z +
2384 a.y.x * a.z.y * a.x.z - a.x.x * a.z.y * a.y.z -
2385 a.y.x * a.x.y * a.z.z - a.z.x * a.y.y * a.x.z}};
2386}
2387
2388template <class T>
2389constexpr T linalg::determinant(const mat<T, 4, 4>& a) {
2390 return a.x.x * (a.y.y * a.z.z * a.w.w + a.w.y * a.y.z * a.z.w +
2391 a.z.y * a.w.z * a.y.w - a.y.y * a.w.z * a.z.w -
2392 a.z.y * a.y.z * a.w.w - a.w.y * a.z.z * a.y.w) +
2393 a.x.y * (a.y.z * a.w.w * a.z.x + a.z.z * a.y.w * a.w.x +
2394 a.w.z * a.z.w * a.y.x - a.y.z * a.z.w * a.w.x -
2395 a.w.z * a.y.w * a.z.x - a.z.z * a.w.w * a.y.x) +
2396 a.x.z * (a.y.w * a.z.x * a.w.y + a.w.w * a.y.x * a.z.y +
2397 a.z.w * a.w.x * a.y.y - a.y.w * a.w.x * a.z.y -
2398 a.z.w * a.y.x * a.w.y - a.w.w * a.z.x * a.y.y) +
2399 a.x.w * (a.y.x * a.w.y * a.z.z + a.z.x * a.y.y * a.w.z +
2400 a.w.x * a.z.y * a.y.z - a.y.x * a.z.y * a.w.z -
2401 a.w.x * a.y.y * a.z.z - a.z.x * a.w.y * a.y.z);
2402}
2403
2404template <class T>
2405linalg::vec<T, 4> linalg::rotation_quat(const vec<T, 3>& orig,
2406 const vec<T, 3>& dest) {
2407 T cosTheta = dot(orig, dest);
2408 if (cosTheta >= 1 - std::numeric_limits<T>::epsilon()) {
2409 return {0, 0, 0, 1};
2410 }
2411 if (cosTheta < -1 + std::numeric_limits<T>::epsilon()) {
2412 vec<T, 3> axis = cross(vec<T, 3>(0, 0, 1), orig);
2413 if (length2(axis) < std::numeric_limits<T>::epsilon())
2414 axis = cross(vec<T, 3>(1, 0, 0), orig);
2415 return rotation_quat(normalize(axis),
2416 3.14159265358979323846264338327950288);
2417 }
2418 vec<T, 3> axis = cross(orig, dest);
2419 T s = std::sqrt((1 + cosTheta) * 2);
2420 return {axis * (1 / s), s * 0.5};
2421}
2422
2423template <class T>
2424linalg::vec<T, 4> linalg::rotation_quat(const mat<T, 3, 3>& m) {
2425 const vec<T, 4> q{m.x.x - m.y.y - m.z.z, m.y.y - m.x.x - m.z.z,
2426 m.z.z - m.x.x - m.y.y, m.x.x + m.y.y + m.z.z},
2427 s[]{{1, m.x.y + m.y.x, m.z.x + m.x.z, m.y.z - m.z.y},
2428 {m.x.y + m.y.x, 1, m.y.z + m.z.y, m.z.x - m.x.z},
2429 {m.x.z + m.z.x, m.y.z + m.z.y, 1, m.x.y - m.y.x},
2430 {m.y.z - m.z.y, m.z.x - m.x.z, m.x.y - m.y.x, 1}};
2431 return copysign(normalize(sqrt(max(T(0), T(1) + q))), s[argmax(q)]);
2432}
2433
2434template <class T>
2435linalg::mat<T, 4, 4> linalg::lookat_matrix(const vec<T, 3>& eye,
2436 const vec<T, 3>& center,
2437 const vec<T, 3>& view_y_dir,
2438 fwd_axis a) {
2439 const vec<T, 3> f = normalize(center - eye), z = a == pos_z ? f : -f,
2440 x = normalize(cross(view_y_dir, z)), y = cross(z, x);
2441 return inverse(mat<T, 4, 4>{{x, 0}, {y, 0}, {z, 0}, {eye, 1}});
2442}
2443
2444template <class T>
2445linalg::mat<T, 4, 4> linalg::frustum_matrix(T x0, T x1, T y0, T y1, T n, T f,
2446 fwd_axis a, z_range z) {
2447 const T s = a == pos_z ? T(1) : T(-1), o = z == neg_one_to_one ? n : 0;
2448 return {{2 * n / (x1 - x0), 0, 0, 0},
2449 {0, 2 * n / (y1 - y0), 0, 0},
2450 {-s * (x0 + x1) / (x1 - x0), -s * (y0 + y1) / (y1 - y0),
2451 s * (f + o) / (f - n), s},
2452 {0, 0, -(n + o) * f / (f - n), 0}};
2453}
2454#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:1846
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:1884
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:1861
constexpr vec< T, 3 > qzdir(const vec< T, 4 > &q)
efficient shorthand for qrot(q, {0,0,1})
Definition linalg.h:1838
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:1877
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:1869
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:1892
constexpr vec< T, 3 > qxdir(const vec< T, 4 > &q)
efficient shorthand for qrot(q, {1,0,0})
Definition linalg.h:1821
constexpr vec< T, 3 > qrot(const vec< T, 4 > &q, const vec< T, 3 > &v)
Rotate a vector by a quaternion.
Definition linalg.h:1853
constexpr vec< T, 3 > qydir(const vec< T, 4 > &q)
efficient shorthand for qrot(q, {0,1,0})
Definition linalg.h:1829
vec< T, 4 > qinv(const vec< T, 4 > &q)
inverse or reciprocal of quaternion q (undefined for zero-length quaternions)
Definition linalg.h:1754
vec< T, 4 > qexp(const vec< T, 4 > &q)
exponential of quaternion q
Definition linalg.h:1763
vec< T, 4 > qpow(const vec< T, 4 > &q, const T &p)
quaternion q raised to the exponent p
Definition linalg.h:1784
vec< T, 4 > qlog(const vec< T, 4 > &q)
logarithm of quaternion q
Definition linalg.h:1775
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:1797
constexpr vec< T, 4 > qconj(const vec< T, 4 > &q)
conjugate of quaternion q
Definition linalg.h:1745
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:1555
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:1564
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:1573
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:1424
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:1440
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:1432
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:1699
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:1681
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:1650
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:1690
constexpr T length2(const vec< T, M > &a)
square of the length or magnitude of vector a
Definition linalg.h:1625
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:1618
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:1716
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:1641
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:1725
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:1673
T uangle(const vec< T, M > &a, const vec< T, M > &b)
Return the angle in radians between two unit vectors.
Definition linalg.h:1665
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:1588
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:1708
T length(const vec< T, M > &a)
length or magnitude of a vector a
Definition linalg.h:1632
T distance(const vec< T, M > &a, const vec< T, M > &b)
Euclidean distance between points a and b
Definition linalg.h:1658
Definition linalg.h:68
Definition linalg.h:120
Definition linalg.h:283
Definition linalg.h:451
Definition linalg.h:267
Definition linalg.h:195
Definition linalg.h:467
Definition linalg.h:229
Definition linalg.h:444
Definition linalg.h:437
Definition linalg.h:518
Definition linalg.h:596
Definition linalg.h:494
Definition linalg.h:506
Definition linalg.h:566
Definition linalg.h:560
Definition linalg.h:548
Definition linalg.h:578
Definition linalg.h:554
Definition linalg.h:530
Definition linalg.h:542
Definition linalg.h:512
Definition linalg.h:500
Definition linalg.h:572
Definition linalg.h:482
Definition linalg.h:488
Definition linalg.h:602
Definition linalg.h:476
Definition linalg.h:536
Definition linalg.h:524
Definition linalg.h:590
Definition linalg.h:584
Definition linalg.h:90
Definition linalg.h:77
Definition linalg.h:269
Definition linalg.h:460
Definition linalg.h:227
Definition linalg.h:616
Definition linalg.h:640
Definition linalg.h:637
Definition linalg.h:646
Definition linalg.h:643
Definition linalg.h:651
Definition linalg.h:631
Definition linalg.h:610
Definition linalg.h:628
Definition linalg.h:622
Definition linalg.h:634
Definition linalg.h:1079
Definition linalg.h:63
Definition linalg.h:58