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