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_floor {
623 template <class A>
624 constexpr auto operator()(A a) const -> decltype(std::floor(a)) {
625 return std::floor(a);
626 }
627};
628struct std_ceil {
629 template <class A>
630 constexpr auto operator()(A a) const -> decltype(std::ceil(a)) {
631 return std::ceil(a);
632 }
633};
634struct std_exp {
635 template <class A>
636 constexpr auto operator()(A a) const -> decltype(std::exp(a)) {
637 return std::exp(a);
638 }
639};
640struct std_log {
641 template <class A>
642 constexpr auto operator()(A a) const -> decltype(std::log(a)) {
643 return std::log(a);
644 }
645};
646struct std_log2 {
647 template <class A>
648 constexpr auto operator()(A a) const -> decltype(std::log2(a)) {
649 return std::log2(a);
650 }
651};
652struct std_log10 {
653 template <class A>
654 constexpr auto operator()(A a) const -> decltype(std::log10(a)) {
655 return std::log10(a);
656 }
657};
658struct std_sqrt {
659 template <class A>
660 constexpr auto operator()(A a) const -> decltype(std::sqrt(a)) {
661 return std::sqrt(a);
662 }
663};
664struct std_sin {
665 double operator()(double a) const { return manifold::math::sin(a); }
666};
667struct std_cos {
668 double operator()(double a) const { return manifold::math::cos(a); }
669};
670struct std_tan {
671 double operator()(double a) const { return manifold::math::tan(a); }
672};
673struct std_asin {
674 double operator()(double a) const { return manifold::math::asin(a); }
675};
676struct std_acos {
677 double operator()(double a) const { return manifold::math::acos(a); }
678};
679struct std_atan {
680 double operator()(double a) const { return manifold::math::atan(a); }
681};
682struct std_sinh {
683 template <class A>
684 constexpr auto operator()(A a) const -> decltype(std::sinh(a)) {
685 return std::sinh(a);
686 }
687};
688struct std_cosh {
689 template <class A>
690 constexpr auto operator()(A a) const -> decltype(std::cosh(a)) {
691 return std::cosh(a);
692 }
693};
694struct std_tanh {
695 template <class A>
696 constexpr auto operator()(A a) const -> decltype(std::tanh(a)) {
697 return std::tanh(a);
698 }
699};
700struct std_round {
701 template <class A>
702 constexpr auto operator()(A a) const -> decltype(std::round(a)) {
703 return std::round(a);
704 }
705};
706struct std_fmod {
707 template <class A, class B>
708 constexpr auto operator()(A a, B b) const -> decltype(std::fmod(a, b)) {
709 return std::fmod(a, b);
710 }
711};
712struct std_pow {
713 template <class A, class B>
714 constexpr auto operator()(A a, B b) const -> decltype(std::pow(a, b)) {
715 return std::pow(a, b);
716 }
717};
718struct std_atan2 {
719 double operator()(double a, double b) const {
720 return manifold::math::atan2(a, b);
721 }
722};
724 template <class A, class B>
725 constexpr auto operator()(A a, B b) const -> decltype(std::copysign(a, b)) {
726 return std::copysign(a, b);
727 }
728};
729} // namespace detail
730
734
830template <class T>
831struct vec<T, 1> {
832 T x;
833 constexpr vec() : x() {}
834 constexpr vec(const T& x_) : x(x_) {}
835 // NOTE: vec<T,1> does NOT have a constructor from pointer, this can conflict
836 // with initializing its single element from zero
837 template <class U>
838 constexpr explicit vec(const vec<U, 1>& v) : vec(static_cast<T>(v.x)) {}
839 constexpr const T& operator[](int) const { return x; }
840 LINALG_CONSTEXPR14 T& operator[](int) { return x; }
841
842 template <class U, class = detail::conv_t<vec, U>>
843 constexpr vec(const U& u) : vec(converter<vec, U>{}(u)) {}
844 template <class U, class = detail::conv_t<U, vec>>
845 constexpr operator U() const {
846 return converter<U, vec>{}(*this);
847 }
848};
849template <class T>
850struct vec<T, 2> {
851 T x, y;
852 constexpr vec() : x(), y() {}
853 constexpr vec(const T& x_, const T& y_) : x(x_), y(y_) {}
854 constexpr explicit vec(const T& s) : vec(s, s) {}
855 constexpr explicit vec(const T* p) : vec(p[0], p[1]) {}
856 template <class U, int N>
857 constexpr explicit vec(const vec<U, N>& v)
858 : vec(static_cast<T>(v.x), static_cast<T>(v.y)) {
859 static_assert(
860 N >= 2,
861 "You must give extra arguments if your input vector is shorter.");
862 }
863 constexpr const T& operator[](int i) const { return i == 0 ? x : y; }
864 LINALG_CONSTEXPR14 T& operator[](int i) { return i == 0 ? x : y; }
865
866 template <class U, class = detail::conv_t<vec, U>>
867 constexpr vec(const U& u) : vec(converter<vec, U>{}(u)) {}
868 template <class U, class = detail::conv_t<U, vec>>
869 constexpr operator U() const {
870 return converter<U, vec>{}(*this);
871 }
872};
873template <class T>
874struct vec<T, 3> {
875 T x, y, z;
876 constexpr vec() : x(), y(), z() {}
877 constexpr vec(const T& x_, const T& y_, const T& z_) : x(x_), y(y_), z(z_) {}
878 constexpr vec(const vec<T, 2>& xy, const T& z_) : vec(xy.x, xy.y, z_) {}
879 constexpr explicit vec(const T& s) : vec(s, s, s) {}
880 constexpr explicit vec(const T* p) : vec(p[0], p[1], p[2]) {}
881 template <class U, int N>
882 constexpr explicit vec(const vec<U, N>& v)
883 : vec(static_cast<T>(v.x), static_cast<T>(v.y), static_cast<T>(v.z)) {
884 static_assert(
885 N >= 3,
886 "You must give extra arguments if your input vector is shorter.");
887 }
888 constexpr const T& operator[](int i) const {
889 return i == 0 ? x : i == 1 ? y : z;
890 }
891 LINALG_CONSTEXPR14 T& operator[](int i) {
892 return i == 0 ? x : i == 1 ? y : z;
893 }
894 constexpr vec<T, 2> xy() const { return vec<T, 2>(x, y); }
895 constexpr vec<T, 2> yz() const { return vec<T, 2>(y, z); }
896
897 template <class U, class = detail::conv_t<vec, U>>
898 constexpr vec(const U& u) : vec(converter<vec, U>{}(u)) {}
899 template <class U, class = detail::conv_t<U, vec>>
900 constexpr operator U() const {
901 return converter<U, vec>{}(*this);
902 }
903};
904template <class T>
905struct vec<T, 4> {
906 T x, y, z, w;
907 constexpr vec() : x(), y(), z(), w() {}
908 constexpr vec(const T& x_, const T& y_, const T& z_, const T& w_)
909 : x(x_), y(y_), z(z_), w(w_) {}
910 constexpr vec(const vec<T, 2>& xy, const T& z_, const T& w_)
911 : vec(xy.x, xy.y, z_, w_) {}
912 constexpr vec(const vec<T, 3>& xyz, const T& w_)
913 : vec(xyz.x, xyz.y, xyz.z, w_) {}
914 constexpr explicit vec(const T& s) : vec(s, s, s, s) {}
915 constexpr explicit vec(const T* p) : vec(p[0], p[1], p[2], p[3]) {}
916 template <class U, int N>
917 constexpr explicit vec(const vec<U, N>& v)
918 : vec(static_cast<T>(v.x), static_cast<T>(v.y), static_cast<T>(v.z),
919 static_cast<T>(v.w)) {
920 static_assert(
921 N >= 4,
922 "You must give extra arguments if your input vector is shorter.");
923 }
924 constexpr const T& operator[](int i) const {
925 return i == 0 ? x : i == 1 ? y : i == 2 ? z : w;
926 }
927 LINALG_CONSTEXPR14 T& operator[](int i) {
928 return i == 0 ? x : i == 1 ? y : i == 2 ? z : w;
929 }
930 constexpr vec<T, 2> xy() const { return vec<T, 2>(x, y); }
931 constexpr vec<T, 3> xyz() const { return vec<T, 3>(x, y, z); }
932
933 template <class U, class = detail::conv_t<vec, U>>
934 constexpr vec(const U& u) : vec(converter<vec, U>{}(u)) {}
935 template <class U, class = detail::conv_t<U, vec>>
936 constexpr operator U() const {
937 return converter<U, vec>{}(*this);
938 }
939};
940
941
1036template <class T, int M>
1037struct mat<T, M, 1> {
1038 using V = vec<T, M>;
1039 V x;
1040 constexpr mat() : x() {}
1041 constexpr mat(const V& x_) : x(x_) {}
1042 constexpr explicit mat(const T& s) : x(s) {}
1043 constexpr explicit mat(const T* p) : x(p + M * 0) {}
1044 template <class U>
1045 constexpr explicit mat(const mat<U, M, 1>& m) : mat(V(m.x)) {}
1046 constexpr vec<T, 1> row(int i) const { return {x[i]}; }
1047 constexpr const V& operator[](int) const { return x; }
1048 LINALG_CONSTEXPR14 V& operator[](int) { return x; }
1049
1050 template <class U, class = detail::conv_t<mat, U>>
1051 constexpr mat(const U& u) : mat(converter<mat, U>{}(u)) {}
1052 template <class U, class = detail::conv_t<U, mat>>
1053 constexpr operator U() const {
1054 return converter<U, mat>{}(*this);
1055 }
1056};
1057template <class T, int M>
1058struct mat<T, M, 2> {
1059 using V = vec<T, M>;
1060 V x, y;
1061 constexpr mat() : x(), y() {}
1062 constexpr mat(const V& x_, const V& y_) : x(x_), y(y_) {}
1063 constexpr explicit mat(const T& s) : x(s), y(s) {}
1064 constexpr explicit mat(const T* p) : x(p + M * 0), y(p + M * 1) {}
1065 template <class U, int N, int P>
1066 constexpr explicit mat(const mat<U, N, P>& m) : mat(V(m.x), V(m.y)) {
1067 static_assert(P >= 2, "Input matrix dimensions must be at least as big.");
1068 }
1069 constexpr vec<T, 2> row(int i) const { return {x[i], y[i]}; }
1070 constexpr const V& operator[](int j) const { return j == 0 ? x : y; }
1071 LINALG_CONSTEXPR14 V& operator[](int j) { return j == 0 ? x : y; }
1072
1073 template <class U, class = detail::conv_t<mat, U>>
1074 constexpr mat(const U& u) : mat(converter<mat, U>{}(u)) {}
1075 template <class U, class = detail::conv_t<U, mat>>
1076 constexpr operator U() const {
1077 return converter<U, mat>{}(*this);
1078 }
1079};
1080template <class T, int M>
1081struct mat<T, M, 3> {
1082 using V = vec<T, M>;
1083 V x, y, z;
1084 constexpr mat() : x(), y(), z() {}
1085 constexpr mat(const V& x_, const V& y_, const V& z_) : x(x_), y(y_), z(z_) {}
1086 constexpr mat(const mat<T, M, 2>& m_, const V& z_)
1087 : x(m_.x), y(m_.y), z(z_) {}
1088 constexpr explicit mat(const T& s) : x(s), y(s), z(s) {}
1089 constexpr explicit mat(const T* p)
1090 : x(p + M * 0), y(p + M * 1), z(p + M * 2) {}
1091 template <class U, int N, int P>
1092 constexpr explicit mat(const mat<U, N, P>& m) : mat(V(m.x), V(m.y), V(m.z)) {
1093 static_assert(P >= 3, "Input matrix dimensions must be at least as big.");
1094 }
1095 constexpr vec<T, 3> row(int i) const { return {x[i], y[i], z[i]}; }
1096 constexpr const V& operator[](int j) const {
1097 return j == 0 ? x : j == 1 ? y : z;
1098 }
1099 LINALG_CONSTEXPR14 V& operator[](int j) {
1100 return j == 0 ? x : j == 1 ? y : z;
1101 }
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, 4> {
1112 using V = vec<T, M>;
1113 V x, y, z, w;
1114 constexpr mat() : x(), y(), z(), w() {}
1115 constexpr mat(const V& x_, const V& y_, const V& z_, const V& w_)
1116 : x(x_), y(y_), z(z_), w(w_) {}
1117 constexpr mat(const mat<T, M, 3>& m_, const V& w_)
1118 : x(m_.x), y(m_.y), z(m_.z), w(w_) {}
1119 constexpr explicit mat(const T& s) : x(s), y(s), z(s), w(s) {}
1120 constexpr explicit mat(const T* p)
1121 : x(p + M * 0), y(p + M * 1), z(p + M * 2), w(p + M * 3) {}
1122 template <class U, int N, int P>
1123 constexpr explicit mat(const mat<U, N, P>& m)
1124 : mat(V(m.x), V(m.y), V(m.z), V(m.w)) {
1125 static_assert(P >= 4, "Input matrix dimensions must be at least as big.");
1126 }
1127
1128 constexpr vec<T, 4> row(int i) const { return {x[i], y[i], z[i], w[i]}; }
1129 constexpr const V& operator[](int j) const {
1130 return j == 0 ? x : j == 1 ? y : j == 2 ? z : w;
1131 }
1132 LINALG_CONSTEXPR14 V& operator[](int j) {
1133 return j == 0 ? x : j == 1 ? y : j == 2 ? z : w;
1134 }
1135
1136 template <class U, class = detail::conv_t<mat, U>>
1137 constexpr mat(const U& u) : mat(converter<mat, U>{}(u)) {}
1138 template <class U, class = detail::conv_t<U, mat>>
1139 constexpr operator U() const {
1140 return converter<U, mat>{}(*this);
1141 }
1142};
1143
1144
1151struct identity_t {
1152 constexpr explicit identity_t(int) {}
1153};
1154template <class T>
1155struct converter<mat<T, 1, 1>, identity_t> {
1156 constexpr mat<T, 1, 1> operator()(identity_t) const { return {vec<T, 1>{1}}; }
1157};
1158template <class T>
1159struct converter<mat<T, 2, 2>, identity_t> {
1160 constexpr mat<T, 2, 2> operator()(identity_t) const {
1161 return {{1, 0}, {0, 1}};
1162 }
1163};
1164template <class T>
1165struct converter<mat<T, 2, 3>, identity_t> {
1166 constexpr mat<T, 2, 3> operator()(identity_t) const {
1167 return {{1, 0}, {0, 1}, {0, 0}};
1168 }
1169};
1170template <class T>
1171struct converter<mat<T, 3, 3>, identity_t> {
1172 constexpr mat<T, 3, 3> operator()(identity_t) const {
1173 return {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
1174 }
1175};
1176template <class T>
1177struct converter<mat<T, 3, 4>, identity_t> {
1178 constexpr mat<T, 3, 4> operator()(identity_t) const {
1179 return {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}, {0, 0, 0}};
1180 }
1181};
1182template <class T>
1183struct converter<mat<T, 4, 4>, identity_t> {
1184 constexpr mat<T, 4, 4> operator()(identity_t) const {
1185 return {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
1186 }
1187};
1188constexpr identity_t identity{1};
1190
1198template <class F, class A, class B>
1199constexpr A fold(F f, A a, const vec<B, 1>& b) {
1200 return f(a, b.x);
1201}
1202template <class F, class A, class B>
1203constexpr A fold(F f, A a, const vec<B, 2>& b) {
1204 return f(f(a, b.x), b.y);
1205}
1206template <class F, class A, class B>
1207constexpr A fold(F f, A a, const vec<B, 3>& b) {
1208 return f(f(f(a, b.x), b.y), b.z);
1209}
1210template <class F, class A, class B>
1211constexpr A fold(F f, A a, const vec<B, 4>& b) {
1212 return f(f(f(f(a, b.x), b.y), b.z), b.w);
1213}
1214template <class F, class A, class B, int M>
1215constexpr A fold(F f, A a, const mat<B, M, 1>& b) {
1216 return fold(f, a, b.x);
1217}
1218template <class F, class A, class B, int M>
1219constexpr A fold(F f, A a, const mat<B, M, 2>& b) {
1220 return fold(f, fold(f, a, b.x), b.y);
1221}
1222template <class F, class A, class B, int M>
1223constexpr A fold(F f, A a, const mat<B, M, 3>& b) {
1224 return fold(f, fold(f, fold(f, a, b.x), b.y), b.z);
1225}
1226template <class F, class A, class B, int M>
1227constexpr A fold(F f, A a, const mat<B, M, 4>& b) {
1228 return fold(f, fold(f, fold(f, fold(f, a, b.x), b.y), b.z), b.w);
1229}
1231
1238
1239// Type aliases for the result of calling apply(...) with various arguments, can
1240// be used with return type SFINAE to constrain overload sets
1241template <class F, class... A>
1242using apply_t = typename detail::apply<F, void, A...>::type;
1243template <class F, class... A>
1244using mm_apply_t = typename std::enable_if<detail::apply<F, void, A...>::mm,
1245 apply_t<F, A...>>::type;
1246template <class F, class... A>
1247using no_mm_apply_t = typename std::enable_if<!detail::apply<F, void, A...>::mm,
1248 apply_t<F, A...>>::type;
1249template <class A>
1250using scalar_t =
1251 typename detail::scalar_type<A>::type; // Underlying scalar type when
1252 // performing elementwise operations
1253
1254// apply(f,...) applies the provided function in an elementwise fashion to its
1255// arguments, producing an object of the same dimensions
1256template <class F, class... A>
1257constexpr apply_t<F, A...> apply(F func, const A&... args) {
1259 detail::make_seq<0, detail::apply<F, void, A...>::size>{}, func, args...);
1260}
1261
1262// map(a,f) is equivalent to apply(f,a)
1263template <class A, class F>
1264constexpr apply_t<F, A> map(const A& a, F func) {
1265 return apply(func, a);
1266}
1267
1268// zip(a,b,f) is equivalent to apply(f,a,b)
1269template <class A, class B, class F>
1270constexpr apply_t<F, A, B> zip(const A& a, const B& b, F func) {
1271 return apply(func, a, b);
1272}
1274
1281template <class A, class B>
1282constexpr typename detail::any_compare<A, B>::type compare(const A& a,
1283 const B& b) {
1284 return detail::any_compare<A, B>()(a, b);
1285}
1286template <class A, class B>
1287constexpr auto operator==(const A& a, const B& b)
1288 -> decltype(compare(a, b) == 0) {
1289 return compare(a, b) == 0;
1290}
1291template <class A, class B>
1292constexpr auto operator!=(const A& a, const B& b)
1293 -> decltype(compare(a, b) != 0) {
1294 return compare(a, b) != 0;
1295}
1296template <class A, class B>
1297constexpr auto operator<(const A& a, const B& b)
1298 -> decltype(compare(a, b) < 0) {
1299 return compare(a, b) < 0;
1300}
1301template <class A, class B>
1302constexpr auto operator>(const A& a, const B& b)
1303 -> decltype(compare(a, b) > 0) {
1304 return compare(a, b) > 0;
1305}
1306template <class A, class B>
1307constexpr auto operator<=(const A& a, const B& b)
1308 -> decltype(compare(a, b) <= 0) {
1309 return compare(a, b) <= 0;
1310}
1311template <class A, class B>
1312constexpr auto operator>=(const A& a, const B& b)
1313 -> decltype(compare(a, b) >= 0) {
1314 return compare(a, b) >= 0;
1315}
1317
1323template <class A>
1324constexpr bool any(const A& a) {
1325 return fold(detail::op_or{}, false, a);
1326}
1327template <class A>
1328constexpr bool all(const A& a) {
1329 return fold(detail::op_and{}, true, a);
1330}
1331template <class A>
1332constexpr scalar_t<A> sum(const A& a) {
1333 return fold(detail::op_add{}, scalar_t<A>(0), a);
1334}
1335template <class A>
1336constexpr scalar_t<A> product(const A& a) {
1337 return fold(detail::op_mul{}, scalar_t<A>(1), a);
1338}
1339template <class A>
1340constexpr scalar_t<A> minelem(const A& a) {
1341 return fold(detail::min{}, a.x, a);
1342}
1343template <class A>
1344constexpr scalar_t<A> maxelem(const A& a) {
1345 return fold(detail::max{}, a.x, a);
1346}
1347template <class T, int M>
1348int argmin(const vec<T, M>& a) {
1349 int j = 0;
1350 for (int i = 1; i < M; ++i)
1351 if (a[i] < a[j]) j = i;
1352 return j;
1353}
1354template <class T, int M>
1355int argmax(const vec<T, M>& a) {
1356 int j = 0;
1357 for (int i = 1; i < M; ++i)
1358 if (a[i] > a[j]) j = i;
1359 return j;
1360}
1362
1368template <class A>
1369constexpr apply_t<detail::op_pos, A> operator+(const A& a) {
1370 return apply(detail::op_pos{}, a);
1371}
1372template <class A>
1373constexpr apply_t<detail::op_neg, A> operator-(const A& a) {
1374 return apply(detail::op_neg{}, a);
1375}
1376template <class A>
1377constexpr apply_t<detail::op_cmp, A> operator~(const A& a) {
1378 return apply(detail::op_cmp{}, a);
1379}
1380template <class A>
1381constexpr apply_t<detail::op_not, A> operator!(const A& a) {
1382 return apply(detail::op_not{}, a);
1383}
1385
1394template <class A, class B>
1395constexpr apply_t<detail::op_add, A, B> operator+(const A& a, const B& b) {
1396 return apply(detail::op_add{}, a, b);
1397}
1398template <class A, class B>
1399constexpr apply_t<detail::op_sub, A, B> operator-(const A& a, const B& b) {
1400 return apply(detail::op_sub{}, a, b);
1401}
1402template <class A, class B>
1403constexpr apply_t<detail::op_mul, A, B> cmul(const A& a, const B& b) {
1404 return apply(detail::op_mul{}, a, b);
1405}
1406template <class A, class B>
1407constexpr apply_t<detail::op_div, A, B> operator/(const A& a, const B& b) {
1408 return apply(detail::op_div{}, a, b);
1409}
1410template <class A, class B>
1411constexpr apply_t<detail::op_mod, A, B> operator%(const A& a, const B& b) {
1412 return apply(detail::op_mod{}, a, b);
1413}
1414template <class A, class B>
1415constexpr apply_t<detail::op_un, A, B> operator|(const A& a, const B& b) {
1416 return apply(detail::op_un{}, a, b);
1417}
1418template <class A, class B>
1419constexpr apply_t<detail::op_xor, A, B> operator^(const A& a, const B& b) {
1420 return apply(detail::op_xor{}, a, b);
1421}
1422template <class A, class B>
1423constexpr apply_t<detail::op_int, A, B> operator&(const A& a, const B& b) {
1424 return apply(detail::op_int{}, a, b);
1425}
1426template <class A, class B>
1427constexpr apply_t<detail::op_lsh, A, B> operator<<(const A& a, const B& b) {
1428 return apply(detail::op_lsh{}, a, b);
1429}
1430template <class A, class B>
1431constexpr apply_t<detail::op_rsh, A, B> operator>>(const A& a, const B& b) {
1432 return apply(detail::op_rsh{}, a, b);
1433}
1434
1435// Binary `operator *` represents the algebraic matrix product - use cmul(a, b)
1436// for the Hadamard (component-wise) product.
1437template <class A, class B>
1438constexpr auto operator*(const A& a, const B& b) {
1439 return mul(a, b);
1440}
1441
1442// Binary assignment operators a $= b is always defined as though it were
1443// explicitly written a = a $ b
1444template <class A, class B>
1445constexpr auto operator+=(A& a, const B& b) -> decltype(a = a + b) {
1446 return a = a + b;
1447}
1448template <class A, class B>
1449constexpr auto operator-=(A& a, const B& b) -> decltype(a = a - b) {
1450 return a = a - b;
1451}
1452template <class A, class B>
1453constexpr auto operator*=(A& a, const B& b) -> decltype(a = a * b) {
1454 return a = a * b;
1455}
1456template <class A, class B>
1457constexpr auto operator/=(A& a, const B& b) -> decltype(a = a / b) {
1458 return a = a / b;
1459}
1460template <class A, class B>
1461constexpr auto operator%=(A& a, const B& b) -> decltype(a = a % b) {
1462 return a = a % b;
1463}
1464template <class A, class B>
1465constexpr auto operator|=(A& a, const B& b) -> decltype(a = a | b) {
1466 return a = a | b;
1467}
1468template <class A, class B>
1469constexpr auto operator^=(A& a, const B& b) -> decltype(a = a ^ b) {
1470 return a = a ^ b;
1471}
1472template <class A, class B>
1473constexpr auto operator&=(A& a, const B& b) -> decltype(a = a & b) {
1474 return a = a & b;
1475}
1476template <class A, class B>
1477constexpr auto operator<<=(A& a, const B& b) -> decltype(a = a << b) {
1478 return a = a << b;
1479}
1480template <class A, class B>
1481constexpr auto operator>>=(A& a, const B& b) -> decltype(a = a >> b) {
1482 return a = a >> b;
1483}
1485
1495template <int... I, class T, int M>
1496constexpr vec<T, sizeof...(I)> swizzle(const vec<T, M>& a) {
1497 return {detail::getter<I>{}(a)...};
1498}
1499
1503template <int I0, int I1, class T, int M>
1504constexpr vec<T, I1 - I0> subvec(const vec<T, M>& a) {
1505 return detail::swizzle(a, detail::make_seq<I0, I1>{});
1506}
1507
1511template <int I0, int J0, int I1, int J1, class T, int M, int N>
1512constexpr mat<T, I1 - I0, J1 - J0> submat(const mat<T, M, N>& a) {
1513 return detail::swizzle(a, detail::make_seq<I0, I1>{},
1514 detail::make_seq<J0, J1>{});
1515}
1516
1517
1523template <class A>
1524constexpr apply_t<detail::std_isfinite, A> isfinite(const A& a) {
1525 return apply(detail::std_isfinite{}, a);
1526}
1527template <class A>
1528constexpr apply_t<detail::std_abs, A> abs(const A& a) {
1529 return apply(detail::std_abs{}, a);
1530}
1531template <class A>
1532constexpr apply_t<detail::std_floor, A> floor(const A& a) {
1533 return apply(detail::std_floor{}, a);
1534}
1535template <class A>
1536constexpr apply_t<detail::std_ceil, A> ceil(const A& a) {
1537 return apply(detail::std_ceil{}, a);
1538}
1539template <class A>
1540constexpr apply_t<detail::std_exp, A> exp(const A& a) {
1541 return apply(detail::std_exp{}, a);
1542}
1543template <class A>
1544constexpr apply_t<detail::std_log, A> log(const A& a) {
1545 return apply(detail::std_log{}, a);
1546}
1547template <class A>
1548constexpr apply_t<detail::std_log2, A> log2(const A& a) {
1549 return apply(detail::std_log2{}, a);
1550}
1551template <class A>
1552constexpr apply_t<detail::std_log10, A> log10(const A& a) {
1553 return apply(detail::std_log10{}, a);
1554}
1555template <class A>
1556constexpr apply_t<detail::std_sqrt, A> sqrt(const A& a) {
1557 return apply(detail::std_sqrt{}, a);
1558}
1559template <class A>
1560constexpr apply_t<detail::std_sin, A> sin(const A& a) {
1561 return apply(detail::std_sin{}, a);
1562}
1563template <class A>
1564constexpr apply_t<detail::std_cos, A> cos(const A& a) {
1565 return apply(detail::std_cos{}, a);
1566}
1567template <class A>
1568constexpr apply_t<detail::std_tan, A> tan(const A& a) {
1569 return apply(detail::std_tan{}, a);
1570}
1571template <class A>
1572constexpr apply_t<detail::std_asin, A> asin(const A& a) {
1573 return apply(detail::std_asin{}, a);
1574}
1575template <class A>
1576constexpr apply_t<detail::std_acos, A> acos(const A& a) {
1577 return apply(detail::std_acos{}, a);
1578}
1579template <class A>
1580constexpr apply_t<detail::std_atan, A> atan(const A& a) {
1581 return apply(detail::std_atan{}, a);
1582}
1583template <class A>
1584constexpr apply_t<detail::std_sinh, A> sinh(const A& a) {
1585 return apply(detail::std_sinh{}, a);
1586}
1587template <class A>
1588constexpr apply_t<detail::std_cosh, A> cosh(const A& a) {
1589 return apply(detail::std_cosh{}, a);
1590}
1591template <class A>
1592constexpr apply_t<detail::std_tanh, A> tanh(const A& a) {
1593 return apply(detail::std_tanh{}, a);
1594}
1595template <class A>
1596constexpr apply_t<detail::std_round, A> round(const A& a) {
1597 return apply(detail::std_round{}, a);
1598}
1600
1607template <class A, class B>
1608constexpr apply_t<detail::std_fmod, A, B> fmod(const A& a, const B& b) {
1609 return apply(detail::std_fmod{}, a, b);
1610}
1611template <class A, class B>
1612constexpr apply_t<detail::std_pow, A, B> pow(const A& a, const B& b) {
1613 return apply(detail::std_pow{}, a, b);
1614}
1615template <class A, class B>
1616constexpr apply_t<detail::std_atan2, A, B> atan2(const A& a, const B& b) {
1617 return apply(detail::std_atan2{}, a, b);
1618}
1619template <class A, class B>
1620constexpr apply_t<detail::std_copysign, A, B> copysign(const A& a, const B& b) {
1621 return apply(detail::std_copysign{}, a, b);
1622}
1624
1631template <class A, class B>
1632constexpr apply_t<detail::op_eq, A, B> equal(const A& a, const B& b) {
1633 return apply(detail::op_eq{}, a, b);
1634}
1635template <class A, class B>
1636constexpr apply_t<detail::op_ne, A, B> nequal(const A& a, const B& b) {
1637 return apply(detail::op_ne{}, a, b);
1638}
1639template <class A, class B>
1640constexpr apply_t<detail::op_lt, A, B> less(const A& a, const B& b) {
1641 return apply(detail::op_lt{}, a, b);
1642}
1643template <class A, class B>
1644constexpr apply_t<detail::op_gt, A, B> greater(const A& a, const B& b) {
1645 return apply(detail::op_gt{}, a, b);
1646}
1647template <class A, class B>
1648constexpr apply_t<detail::op_le, A, B> lequal(const A& a, const B& b) {
1649 return apply(detail::op_le{}, a, b);
1650}
1651template <class A, class B>
1652constexpr apply_t<detail::op_ge, A, B> gequal(const A& a, const B& b) {
1653 return apply(detail::op_ge{}, a, b);
1654}
1656
1663template <class A, class B>
1664constexpr apply_t<detail::min, A, B> min(const A& a, const B& b) {
1665 return apply(detail::min{}, a, b);
1666}
1667template <class A, class B>
1668constexpr apply_t<detail::max, A, B> max(const A& a, const B& b) {
1669 return apply(detail::max{}, a, b);
1670}
1674template <class X, class L, class H>
1675constexpr apply_t<detail::clamp, X, L, H> clamp(const X& x, const L& l,
1676 const H& h) {
1677 return apply(detail::clamp{}, x, l, h);
1678}
1679
1683template <class P, class A, class B>
1684constexpr apply_t<detail::select, P, A, B> select(const P& p, const A& a,
1685 const B& b) {
1686 return apply(detail::select{}, p, a, b);
1687}
1688
1692template <class A, class B, class T>
1693constexpr apply_t<detail::lerp, A, B, T> lerp(const A& a, const B& b,
1694 const T& t) {
1695 return apply(detail::lerp{}, a, b, t);
1696}
1697
1698
1707template <class T>
1708constexpr T cross(const vec<T, 2>& a, const vec<T, 2>& b) {
1709 return a.x * b.y - a.y * b.x;
1710}
1711
1714template <class T>
1715constexpr vec<T, 2> cross(T a, const vec<T, 2>& b) {
1716 return {-a * b.y, a * b.x};
1717}
1718
1721template <class T>
1722constexpr vec<T, 2> cross(const vec<T, 2>& a, T b) {
1723 return {a.y * b, -a.x * b};
1724}
1725
1729template <class T>
1730constexpr vec<T, 3> cross(const vec<T, 3>& a, const vec<T, 3>& b) {
1731 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};
1732}
1733
1737template <class T, int M>
1738constexpr T dot(const vec<T, M>& a, const vec<T, M>& b) {
1739 return sum(a * b);
1740}
1741
1744template <class T, int M>
1745constexpr T length2(const vec<T, M>& a) {
1746 return dot(a, a);
1747}
1748
1751template <class T, int M>
1752T length(const vec<T, M>& a) {
1753 return std::sqrt(length2(a));
1754}
1755
1760template <class T, int M>
1762 return a / length(a);
1763}
1764
1769template <class T, int M>
1770constexpr T distance2(const vec<T, M>& a, const vec<T, M>& b) {
1771 return length2(b - a);
1772}
1773
1777template <class T, int M>
1778T distance(const vec<T, M>& a, const vec<T, M>& b) {
1779 return length(b - a);
1780}
1781
1784template <class T, int M>
1785T uangle(const vec<T, M>& a, const vec<T, M>& b) {
1786 T d = dot(a, b);
1787 return d > 1 ? 0 : linalg::acos(d < -1 ? -1 : d);
1788}
1789
1792template <class T, int M>
1793T angle(const vec<T, M>& a, const vec<T, M>& b) {
1794 return uangle(normalize(a), normalize(b));
1795}
1796
1800template <class T>
1801vec<T, 2> rot(T a, const vec<T, 2>& v) {
1802 const T s = linalg::sin(a), c = linalg::cos(a);
1803 return {v.x * c - v.y * s, v.x * s + v.y * c};
1804}
1805
1809template <class T>
1810vec<T, 3> rotx(T a, const vec<T, 3>& v) {
1811 const T s = linalg::sin(a), c = linalg::cos(a);
1812 return {v.x, v.y * c - v.z * s, v.y * s + v.z * c};
1813}
1814
1818template <class T>
1819vec<T, 3> roty(T a, const vec<T, 3>& v) {
1820 const T s = linalg::sin(a), c = linalg::cos(a);
1821 return {v.x * c + v.z * s, v.y, -v.x * s + v.z * c};
1822}
1823
1827template <class T>
1828vec<T, 3> rotz(T a, const vec<T, 3>& v) {
1829 const T s = linalg::sin(a), c = linalg::cos(a);
1830 return {v.x * c - v.y * s, v.x * s + v.y * c, v.z};
1831}
1832
1835template <class T, int M>
1836vec<T, M> nlerp(const vec<T, M>& a, const vec<T, M>& b, T t) {
1837 return normalize(lerp(a, b, t));
1838}
1839
1844template <class T, int M>
1845vec<T, M> slerp(const vec<T, M>& a, const vec<T, M>& b, T t) {
1846 T th = uangle(a, b);
1847 return th == 0 ? a
1848 : a * (linalg::sin(th * (1 - t)) / linalg::sin(th)) +
1849 b * (linalg::sin(th * t) / linalg::sin(th));
1850}
1851
1852
1864template <class T>
1865constexpr vec<T, 4> qconj(const vec<T, 4>& q) {
1866 return {-q.x, -q.y, -q.z, q.w};
1867}
1868
1873template <class T>
1875 return qconj(q) / length2(q);
1876}
1877
1882template <class T>
1884 const auto v = q.xyz();
1885 const auto vv = length(v);
1886 return std::exp(q.w) *
1887 vec<T, 4>{v * (vv > 0 ? linalg::sin(vv) / vv : 0), linalg::cos(vv)};
1888}
1889
1894template <class T>
1896 const auto v = q.xyz();
1897 const auto vv = length(v), qq = length(q);
1898 return {v * (vv > 0 ? linalg::acos(q.w / qq) / vv : 0), std::log(qq)};
1899}
1900
1903template <class T>
1904vec<T, 4> qpow(const vec<T, 4>& q, const T& p) {
1905 const auto v = q.xyz();
1906 const auto vv = length(v), qq = length(q), th = linalg::acos(q.w / qq);
1907 return std::pow(qq, p) *
1908 vec<T, 4>{v * (vv > 0 ? linalg::sin(p * th) / vv : 0),
1909 linalg::cos(p * th)};
1910}
1911
1916template <class T>
1917constexpr vec<T, 4> qmul(const vec<T, 4>& a, const vec<T, 4>& b) {
1918 return {a.x * b.w + a.w * b.x + a.y * b.z - a.z * b.y,
1919 a.y * b.w + a.w * b.y + a.z * b.x - a.x * b.z,
1920 a.z * b.w + a.w * b.z + a.x * b.y - a.y * b.x,
1921 a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z};
1922}
1923
1926template <class T, class... R>
1927constexpr vec<T, 4> qmul(const vec<T, 4>& a, R... r) {
1928 return qmul(a, qmul(r...));
1929}
1930
1931
1940template <class T>
1941constexpr vec<T, 3> qxdir(const vec<T, 4>& q) {
1942 return {q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z,
1943 (q.x * q.y + q.z * q.w) * 2, (q.z * q.x - q.y * q.w) * 2};
1944}
1945
1948template <class T>
1949constexpr vec<T, 3> qydir(const vec<T, 4>& q) {
1950 return {(q.x * q.y - q.z * q.w) * 2,
1951 q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z,
1952 (q.y * q.z + q.x * q.w) * 2};
1953}
1954
1957template <class T>
1958constexpr vec<T, 3> qzdir(const vec<T, 4>& q) {
1959 return {(q.z * q.x + q.y * q.w) * 2, (q.y * q.z - q.x * q.w) * 2,
1960 q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z};
1961}
1962
1965template <class T>
1966constexpr mat<T, 3, 3> qmat(const vec<T, 4>& q) {
1967 return {qxdir(q), qydir(q), qzdir(q)};
1968}
1969
1972template <class T>
1973constexpr vec<T, 3> qrot(const vec<T, 4>& q, const vec<T, 3>& v) {
1974 return qxdir(q) * v.x + qydir(q) * v.y + qzdir(q) * v.z;
1975}
1976
1980template <class T>
1981T qangle(const vec<T, 4>& q) {
1982 return linalg::atan2(length(q.xyz()), q.w) * 2;
1983}
1984
1988template <class T>
1990 return normalize(q.xyz());
1991}
1992
1996template <class T>
1997vec<T, 4> qnlerp(const vec<T, 4>& a, const vec<T, 4>& b, T t) {
1998 return nlerp(a, dot(a, b) < 0 ? -b : b, t);
1999}
2000
2003template <class T>
2004vec<T, 4> qslerp(const vec<T, 4>& a, const vec<T, 4>& b, T t) {
2005 return slerp(a, dot(a, b) < 0 ? -b : b, t);
2006}
2007
2011template <class T>
2012vec<T, 4> constexpr rotation_quat(const vec<T, 3>& axis, T angle) {
2013 return {axis * linalg::sin(angle / 2), linalg::cos(angle / 2)};
2014}
2015
2019template <class T>
2020vec<T, 4> rotation_quat(const vec<T, 3>& orig, const vec<T, 3>& dest);
2025template <class T>
2028
2034template <class T, int M>
2035constexpr vec<T, M> mul(const vec<T, M>& a, const T& b) {
2036 return cmul(a, b);
2037}
2038template <class T, int M>
2039constexpr vec<T, M> mul(const T& b, const vec<T, M>& a) {
2040 return cmul(b, a);
2041}
2042template <class T, int M, int N>
2043constexpr mat<T, M, N> mul(const mat<T, M, N>& a, const T& b) {
2044 return cmul(a, b);
2045}
2046template <class T, int M, int N>
2047constexpr mat<T, M, N> mul(const T& b, const mat<T, M, N>& a) {
2048 return cmul(b, a);
2049}
2050template <class T, int M>
2051constexpr vec<T, M> mul(const vec<T, M>& a, const vec<T, M>& b) {
2052 return cmul(a, b);
2053}
2054template <class T, int M>
2055constexpr vec<T, M> mul(const mat<T, M, 1>& a, const vec<T, 1>& b) {
2056 return a.x * b.x;
2057}
2058template <class T, int M>
2059constexpr vec<T, M> mul(const mat<T, M, 2>& a, const vec<T, 2>& b) {
2060 return a.x * b.x + a.y * b.y;
2061}
2062template <class T, int M>
2063constexpr vec<T, M> mul(const mat<T, M, 3>& a, const vec<T, 3>& b) {
2064 return a.x * b.x + a.y * b.y + a.z * b.z;
2065}
2066template <class T, int M>
2067constexpr vec<T, M> mul(const mat<T, M, 4>& a, const vec<T, 4>& b) {
2068 return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
2069}
2070template <class T, int M, int N>
2071constexpr mat<T, M, 1> mul(const mat<T, M, N>& a, const mat<T, N, 1>& b) {
2072 return {mul(a, b.x)};
2073}
2074template <class T, int M, int N>
2075constexpr mat<T, M, 2> mul(const mat<T, M, N>& a, const mat<T, N, 2>& b) {
2076 return {mul(a, b.x), mul(a, b.y)};
2077}
2078template <class T, int M, int N>
2079constexpr mat<T, M, 3> mul(const mat<T, M, N>& a, const mat<T, N, 3>& b) {
2080 return {mul(a, b.x), mul(a, b.y), mul(a, b.z)};
2081}
2082template <class T, int M, int N>
2083constexpr mat<T, M, 4> mul(const mat<T, M, N>& a, const mat<T, N, 4>& b) {
2084 return {mul(a, b.x), mul(a, b.y), mul(a, b.z), mul(a, b.w)};
2085}
2086template <class T, int M, int N, int P>
2087constexpr vec<T, M> mul(const mat<T, M, N>& a, const mat<T, N, P>& b,
2088 const vec<T, P>& c) {
2089 return mul(mul(a, b), c);
2090}
2091template <class T, int M, int N, int P, int Q>
2092constexpr mat<T, M, Q> mul(const mat<T, M, N>& a, const mat<T, N, P>& b,
2093 const mat<T, P, Q>& c) {
2094 return mul(mul(a, b), c);
2095}
2096template <class T, int M, int N, int P, int Q>
2097constexpr vec<T, M> mul(const mat<T, M, N>& a, const mat<T, N, P>& b,
2098 const mat<T, P, Q>& c, const vec<T, Q>& d) {
2099 return mul(mul(a, b, c), d);
2100}
2101template <class T, int M, int N, int P, int Q, int R>
2102constexpr mat<T, M, R> mul(const mat<T, M, N>& a, const mat<T, N, P>& b,
2103 const mat<T, P, Q>& c, const mat<T, Q, R>& d) {
2104 return mul(mul(a, b, c), d);
2105}
2106template <class T, int M>
2107constexpr mat<T, M, 1> outerprod(const vec<T, M>& a, const vec<T, 1>& b) {
2108 return {a * b.x};
2109}
2110template <class T, int M>
2111constexpr mat<T, M, 2> outerprod(const vec<T, M>& a, const vec<T, 2>& b) {
2112 return {a * b.x, a * b.y};
2113}
2114template <class T, int M>
2115constexpr mat<T, M, 3> outerprod(const vec<T, M>& a, const vec<T, 3>& b) {
2116 return {a * b.x, a * b.y, a * b.z};
2117}
2118template <class T, int M>
2119constexpr mat<T, M, 4> outerprod(const vec<T, M>& a, const vec<T, 4>& b) {
2120 return {a * b.x, a * b.y, a * b.z, a * b.w};
2121}
2122template <class T>
2123constexpr vec<T, 1> diagonal(const mat<T, 1, 1>& a) {
2124 return {a.x.x};
2125}
2126template <class T>
2127constexpr vec<T, 2> diagonal(const mat<T, 2, 2>& a) {
2128 return {a.x.x, a.y.y};
2129}
2130template <class T>
2131constexpr vec<T, 3> diagonal(const mat<T, 3, 3>& a) {
2132 return {a.x.x, a.y.y, a.z.z};
2133}
2134template <class T>
2135constexpr vec<T, 4> diagonal(const mat<T, 4, 4>& a) {
2136 return {a.x.x, a.y.y, a.z.z, a.w.w};
2137}
2138template <class T, int N>
2139constexpr T trace(const mat<T, N, N>& a) {
2140 return sum(diagonal(a));
2141}
2142template <class T, int M>
2143constexpr mat<T, M, 1> transpose(const mat<T, 1, M>& m) {
2144 return {m.row(0)};
2145}
2146template <class T, int M>
2147constexpr mat<T, M, 2> transpose(const mat<T, 2, M>& m) {
2148 return {m.row(0), m.row(1)};
2149}
2150template <class T, int M>
2151constexpr mat<T, M, 3> transpose(const mat<T, 3, M>& m) {
2152 return {m.row(0), m.row(1), m.row(2)};
2153}
2154template <class T, int M>
2155constexpr mat<T, M, 4> transpose(const mat<T, 4, M>& m) {
2156 return {m.row(0), m.row(1), m.row(2), m.row(3)};
2157}
2158template <class T, int M>
2159constexpr mat<T, 1, M> transpose(const vec<T, M>& m) {
2160 return transpose(mat<T, M, 1>(m));
2161}
2162template <class T>
2163constexpr mat<T, 1, 1> adjugate(const mat<T, 1, 1>&) {
2164 return {vec<T, 1>{1}};
2165}
2166template <class T>
2167constexpr mat<T, 2, 2> adjugate(const mat<T, 2, 2>& a) {
2168 return {{a.y.y, -a.x.y}, {-a.y.x, a.x.x}};
2169}
2170template <class T>
2171constexpr mat<T, 3, 3> adjugate(const mat<T, 3, 3>& a);
2172template <class T>
2173constexpr mat<T, 4, 4> adjugate(const mat<T, 4, 4>& a);
2174template <class T, int N>
2175constexpr mat<T, N, N> comatrix(const mat<T, N, N>& a) {
2176 return transpose(adjugate(a));
2177}
2178template <class T>
2179constexpr T determinant(const mat<T, 1, 1>& a) {
2180 return a.x.x;
2181}
2182template <class T>
2183constexpr T determinant(const mat<T, 2, 2>& a) {
2184 return a.x.x * a.y.y - a.x.y * a.y.x;
2185}
2186template <class T>
2187constexpr T determinant(const mat<T, 3, 3>& a) {
2188 return a.x.x * (a.y.y * a.z.z - a.z.y * a.y.z) +
2189 a.x.y * (a.y.z * a.z.x - a.z.z * a.y.x) +
2190 a.x.z * (a.y.x * a.z.y - a.z.x * a.y.y);
2191}
2192template <class T>
2193constexpr T determinant(const mat<T, 4, 4>& a);
2194template <class T, int N>
2195constexpr mat<T, N, N> inverse(const mat<T, N, N>& a) {
2196 return adjugate(a) / determinant(a);
2197}
2199
2205template <class T, int M>
2206T* begin(vec<T, M>& a) {
2207 return &a.x;
2208}
2209template <class T, int M>
2210const T* begin(const vec<T, M>& a) {
2211 return &a.x;
2212}
2213template <class T, int M>
2214T* end(vec<T, M>& a) {
2215 return begin(a) + M;
2216}
2217template <class T, int M>
2218const T* end(const vec<T, M>& a) {
2219 return begin(a) + M;
2220}
2221template <class T, int M, int N>
2222vec<T, M>* begin(mat<T, M, N>& a) {
2223 return &a.x;
2224}
2225template <class T, int M, int N>
2226const vec<T, M>* begin(const mat<T, M, N>& a) {
2227 return &a.x;
2228}
2229template <class T, int M, int N>
2230vec<T, M>* end(mat<T, M, N>& a) {
2231 return begin(a) + N;
2232}
2233template <class T, int M, int N>
2234const vec<T, M>* end(const mat<T, M, N>& a) {
2235 return begin(a) + N;
2236}
2238
2244enum fwd_axis {
2245 neg_z,
2246 pos_z
2247}; // Should projection matrices be generated assuming forward is {0,0,-1} or
2248 // {0,0,1}
2249enum z_range {
2250 neg_one_to_one,
2251 zero_to_one
2252}; // Should projection matrices map z into the range of [-1,1] or [0,1]?
2253template <class T>
2254mat<T, 4, 4> translation_matrix(const vec<T, 3>& translation) {
2255 return {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {translation, 1}};
2256}
2257template <class T>
2258mat<T, 4, 4> rotation_matrix(const vec<T, 4>& rotation) {
2259 return {{qxdir(rotation), 0},
2260 {qydir(rotation), 0},
2261 {qzdir(rotation), 0},
2262 {0, 0, 0, 1}};
2263}
2264template <class T>
2265mat<T, 4, 4> scaling_matrix(const vec<T, 3>& scaling) {
2266 return {{scaling.x, 0, 0, 0},
2267 {0, scaling.y, 0, 0},
2268 {0, 0, scaling.z, 0},
2269 {0, 0, 0, 1}};
2270}
2271template <class T>
2272mat<T, 4, 4> pose_matrix(const vec<T, 4>& q, const vec<T, 3>& p) {
2273 return {{qxdir(q), 0}, {qydir(q), 0}, {qzdir(q), 0}, {p, 1}};
2274}
2275template <class T>
2276mat<T, 4, 4> lookat_matrix(const vec<T, 3>& eye, const vec<T, 3>& center,
2277 const vec<T, 3>& view_y_dir, fwd_axis fwd = neg_z);
2278template <class T>
2279mat<T, 4, 4> frustum_matrix(T x0, T x1, T y0, T y1, T n, T f,
2280 fwd_axis a = neg_z, z_range z = neg_one_to_one);
2281template <class T>
2282mat<T, 4, 4> perspective_matrix(T fovy, T aspect, T n, T f, fwd_axis a = neg_z,
2283 z_range z = neg_one_to_one) {
2284 T y = n * linalg::tan(fovy / 2), x = y * aspect;
2285 return frustum_matrix(-x, x, -y, y, n, f, a, z);
2286}
2288
2295template <class T>
2296struct converter<vec<T, 1>, std::array<T, 1>> {
2297 vec<T, 1> operator()(const std::array<T, 1>& a) const { return {a[0]}; }
2298};
2299template <class T>
2300struct converter<vec<T, 2>, std::array<T, 2>> {
2301 vec<T, 2> operator()(const std::array<T, 2>& a) const { return {a[0], a[1]}; }
2302};
2303template <class T>
2304struct converter<vec<T, 3>, std::array<T, 3>> {
2305 vec<T, 3> operator()(const std::array<T, 3>& a) const {
2306 return {a[0], a[1], a[2]};
2307 }
2308};
2309template <class T>
2310struct converter<vec<T, 4>, std::array<T, 4>> {
2311 vec<T, 4> operator()(const std::array<T, 4>& a) const {
2312 return {a[0], a[1], a[2], a[3]};
2313 }
2314};
2315
2316template <class T>
2317struct converter<std::array<T, 1>, vec<T, 1>> {
2318 std::array<T, 1> operator()(const vec<T, 1>& a) const { return {a[0]}; }
2319};
2320template <class T>
2321struct converter<std::array<T, 2>, vec<T, 2>> {
2322 std::array<T, 2> operator()(const vec<T, 2>& a) const { return {a[0], a[1]}; }
2323};
2324template <class T>
2325struct converter<std::array<T, 3>, vec<T, 3>> {
2326 std::array<T, 3> operator()(const vec<T, 3>& a) const {
2327 return {a[0], a[1], a[2]};
2328 }
2329};
2330template <class T>
2331struct converter<std::array<T, 4>, vec<T, 4>> {
2332 std::array<T, 4> operator()(const vec<T, 4>& a) const {
2333 return {a[0], a[1], a[2], a[3]};
2334 }
2335};
2336
2337} // namespace linalg
2338
2339#ifdef MANIFOLD_DEBUG
2340#include <iostream>
2341
2342namespace linalg {
2343template <class T>
2344std::ostream& operator<<(std::ostream& out, const vec<T, 1>& v) {
2345 return out << '{' << v[0] << '}';
2346}
2347template <class T>
2348std::ostream& operator<<(std::ostream& out, const vec<T, 2>& v) {
2349 return out << '{' << v[0] << ',' << v[1] << '}';
2350}
2351template <class T>
2352std::ostream& operator<<(std::ostream& out, const vec<T, 3>& v) {
2353 return out << '{' << v[0] << ',' << v[1] << ',' << v[2] << '}';
2354}
2355template <class T>
2356std::ostream& operator<<(std::ostream& out, const vec<T, 4>& v) {
2357 return out << '{' << v[0] << ',' << v[1] << ',' << v[2] << ',' << v[3] << '}';
2358}
2359
2360template <class T, int M>
2361std::ostream& operator<<(std::ostream& out, const mat<T, M, 1>& m) {
2362 return out << '{' << m[0] << '}';
2363}
2364template <class T, int M>
2365std::ostream& operator<<(std::ostream& out, const mat<T, M, 2>& m) {
2366 return out << '{' << m[0] << ',' << m[1] << '}';
2367}
2368template <class T, int M>
2369std::ostream& operator<<(std::ostream& out, const mat<T, M, 3>& m) {
2370 return out << '{' << m[0] << ',' << m[1] << ',' << m[2] << '}';
2371}
2372template <class T, int M>
2373std::ostream& operator<<(std::ostream& out, const mat<T, M, 4>& m) {
2374 return out << '{' << m[0] << ',' << m[1] << ',' << m[2] << ',' << m[3] << '}';
2375}
2376} // namespace linalg
2377#endif
2378
2379namespace std {
2385template <class T>
2386struct hash<linalg::vec<T, 1>> {
2387 std::size_t operator()(const linalg::vec<T, 1>& v) const {
2388 std::hash<T> h;
2389 return h(v.x);
2390 }
2391};
2392template <class T>
2393struct hash<linalg::vec<T, 2>> {
2394 std::size_t operator()(const linalg::vec<T, 2>& v) const {
2395 std::hash<T> h;
2396 return h(v.x) ^ (h(v.y) << 1);
2397 }
2398};
2399template <class T>
2400struct hash<linalg::vec<T, 3>> {
2401 std::size_t operator()(const linalg::vec<T, 3>& v) const {
2402 std::hash<T> h;
2403 return h(v.x) ^ (h(v.y) << 1) ^ (h(v.z) << 2);
2404 }
2405};
2406template <class T>
2407struct hash<linalg::vec<T, 4>> {
2408 std::size_t operator()(const linalg::vec<T, 4>& v) const {
2409 std::hash<T> h;
2410 return h(v.x) ^ (h(v.y) << 1) ^ (h(v.z) << 2) ^ (h(v.w) << 3);
2411 }
2412};
2413
2414template <class T, int M>
2415struct hash<linalg::mat<T, M, 1>> {
2416 std::size_t operator()(const linalg::mat<T, M, 1>& v) const {
2417 std::hash<linalg::vec<T, M>> h;
2418 return h(v.x);
2419 }
2420};
2421template <class T, int M>
2422struct hash<linalg::mat<T, M, 2>> {
2423 std::size_t operator()(const linalg::mat<T, M, 2>& v) const {
2424 std::hash<linalg::vec<T, M>> h;
2425 return h(v.x) ^ (h(v.y) << M);
2426 }
2427};
2428template <class T, int M>
2429struct hash<linalg::mat<T, M, 3>> {
2430 std::size_t operator()(const linalg::mat<T, M, 3>& v) const {
2431 std::hash<linalg::vec<T, M>> h;
2432 return h(v.x) ^ (h(v.y) << M) ^ (h(v.z) << (M * 2));
2433 }
2434};
2435template <class T, int M>
2436struct hash<linalg::mat<T, M, 4>> {
2437 std::size_t operator()(const linalg::mat<T, M, 4>& v) const {
2438 std::hash<linalg::vec<T, M>> h;
2439 return h(v.x) ^ (h(v.y) << M) ^ (h(v.z) << (M * 2)) ^ (h(v.w) << (M * 3));
2440 }
2441};
2442
2443} // namespace std
2444
2445// Definitions of functions too long to be defined inline
2446template <class T>
2447constexpr linalg::mat<T, 3, 3> linalg::adjugate(const mat<T, 3, 3>& a) {
2448 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,
2449 a.x.y * a.y.z - a.y.y * a.x.z},
2450 {a.y.z * a.z.x - a.z.z * a.y.x, a.z.z * a.x.x - a.x.z * a.z.x,
2451 a.x.z * a.y.x - a.y.z * a.x.x},
2452 {a.y.x * a.z.y - a.z.x * a.y.y, a.z.x * a.x.y - a.x.x * a.z.y,
2453 a.x.x * a.y.y - a.y.x * a.x.y}};
2454}
2455
2456template <class T>
2457constexpr linalg::mat<T, 4, 4> linalg::adjugate(const mat<T, 4, 4>& a) {
2458 return {{a.y.y * a.z.z * a.w.w + a.w.y * a.y.z * a.z.w +
2459 a.z.y * a.w.z * a.y.w - a.y.y * a.w.z * a.z.w -
2460 a.z.y * a.y.z * a.w.w - a.w.y * a.z.z * a.y.w,
2461 a.x.y * a.w.z * a.z.w + a.z.y * a.x.z * a.w.w +
2462 a.w.y * a.z.z * a.x.w - a.w.y * a.x.z * a.z.w -
2463 a.z.y * a.w.z * a.x.w - a.x.y * a.z.z * a.w.w,
2464 a.x.y * a.y.z * a.w.w + a.w.y * a.x.z * a.y.w +
2465 a.y.y * a.w.z * a.x.w - a.x.y * a.w.z * a.y.w -
2466 a.y.y * a.x.z * a.w.w - a.w.y * a.y.z * a.x.w,
2467 a.x.y * a.z.z * a.y.w + a.y.y * a.x.z * a.z.w +
2468 a.z.y * a.y.z * a.x.w - a.x.y * a.y.z * a.z.w -
2469 a.z.y * a.x.z * a.y.w - a.y.y * a.z.z * a.x.w},
2470 {a.y.z * a.w.w * a.z.x + a.z.z * a.y.w * a.w.x +
2471 a.w.z * a.z.w * a.y.x - a.y.z * a.z.w * a.w.x -
2472 a.w.z * a.y.w * a.z.x - a.z.z * a.w.w * a.y.x,
2473 a.x.z * a.z.w * a.w.x + a.w.z * a.x.w * a.z.x +
2474 a.z.z * a.w.w * a.x.x - a.x.z * a.w.w * a.z.x -
2475 a.z.z * a.x.w * a.w.x - a.w.z * a.z.w * a.x.x,
2476 a.x.z * a.w.w * a.y.x + a.y.z * a.x.w * a.w.x +
2477 a.w.z * a.y.w * a.x.x - a.x.z * a.y.w * a.w.x -
2478 a.w.z * a.x.w * a.y.x - a.y.z * a.w.w * a.x.x,
2479 a.x.z * a.y.w * a.z.x + a.z.z * a.x.w * a.y.x +
2480 a.y.z * a.z.w * a.x.x - a.x.z * a.z.w * a.y.x -
2481 a.y.z * a.x.w * a.z.x - a.z.z * a.y.w * a.x.x},
2482 {a.y.w * a.z.x * a.w.y + a.w.w * a.y.x * a.z.y +
2483 a.z.w * a.w.x * a.y.y - a.y.w * a.w.x * a.z.y -
2484 a.z.w * a.y.x * a.w.y - a.w.w * a.z.x * a.y.y,
2485 a.x.w * a.w.x * a.z.y + a.z.w * a.x.x * a.w.y +
2486 a.w.w * a.z.x * a.x.y - a.x.w * a.z.x * a.w.y -
2487 a.w.w * a.x.x * a.z.y - a.z.w * a.w.x * a.x.y,
2488 a.x.w * a.y.x * a.w.y + a.w.w * a.x.x * a.y.y +
2489 a.y.w * a.w.x * a.x.y - a.x.w * a.w.x * a.y.y -
2490 a.y.w * a.x.x * a.w.y - a.w.w * a.y.x * a.x.y,
2491 a.x.w * a.z.x * a.y.y + a.y.w * a.x.x * a.z.y +
2492 a.z.w * a.y.x * a.x.y - a.x.w * a.y.x * a.z.y -
2493 a.z.w * a.x.x * a.y.y - a.y.w * a.z.x * a.x.y},
2494 {a.y.x * a.w.y * a.z.z + a.z.x * a.y.y * a.w.z +
2495 a.w.x * a.z.y * a.y.z - a.y.x * a.z.y * a.w.z -
2496 a.w.x * a.y.y * a.z.z - a.z.x * a.w.y * a.y.z,
2497 a.x.x * a.z.y * a.w.z + a.w.x * a.x.y * a.z.z +
2498 a.z.x * a.w.y * a.x.z - a.x.x * a.w.y * a.z.z -
2499 a.z.x * a.x.y * a.w.z - a.w.x * a.z.y * a.x.z,
2500 a.x.x * a.w.y * a.y.z + a.y.x * a.x.y * a.w.z +
2501 a.w.x * a.y.y * a.x.z - a.x.x * a.y.y * a.w.z -
2502 a.w.x * a.x.y * a.y.z - a.y.x * a.w.y * a.x.z,
2503 a.x.x * a.y.y * a.z.z + a.z.x * a.x.y * a.y.z +
2504 a.y.x * a.z.y * a.x.z - a.x.x * a.z.y * a.y.z -
2505 a.y.x * a.x.y * a.z.z - a.z.x * a.y.y * a.x.z}};
2506}
2507
2508template <class T>
2509constexpr T linalg::determinant(const mat<T, 4, 4>& a) {
2510 return a.x.x * (a.y.y * a.z.z * a.w.w + a.w.y * a.y.z * a.z.w +
2511 a.z.y * a.w.z * a.y.w - a.y.y * a.w.z * a.z.w -
2512 a.z.y * a.y.z * a.w.w - a.w.y * a.z.z * a.y.w) +
2513 a.x.y * (a.y.z * a.w.w * a.z.x + a.z.z * a.y.w * a.w.x +
2514 a.w.z * a.z.w * a.y.x - a.y.z * a.z.w * a.w.x -
2515 a.w.z * a.y.w * a.z.x - a.z.z * a.w.w * a.y.x) +
2516 a.x.z * (a.y.w * a.z.x * a.w.y + a.w.w * a.y.x * a.z.y +
2517 a.z.w * a.w.x * a.y.y - a.y.w * a.w.x * a.z.y -
2518 a.z.w * a.y.x * a.w.y - a.w.w * a.z.x * a.y.y) +
2519 a.x.w * (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}
2523
2524template <class T>
2525linalg::vec<T, 4> linalg::rotation_quat(const vec<T, 3>& orig,
2526 const vec<T, 3>& dest) {
2527 T cosTheta = dot(orig, dest);
2528 if (cosTheta >= 1 - std::numeric_limits<T>::epsilon()) {
2529 return {0, 0, 0, 1};
2530 }
2531 if (cosTheta < -1 + std::numeric_limits<T>::epsilon()) {
2532 vec<T, 3> axis = cross(vec<T, 3>(0, 0, 1), orig);
2533 if (length2(axis) < std::numeric_limits<T>::epsilon())
2534 axis = cross(vec<T, 3>(1, 0, 0), orig);
2535 return rotation_quat(normalize(axis),
2536 3.14159265358979323846264338327950288);
2537 }
2538 vec<T, 3> axis = cross(orig, dest);
2539 T s = std::sqrt((1 + cosTheta) * 2);
2540 return {axis * (1 / s), s * 0.5};
2541}
2542
2543template <class T>
2544linalg::vec<T, 4> linalg::rotation_quat(const mat<T, 3, 3>& m) {
2545 const vec<T, 4> q{m.x.x - m.y.y - m.z.z, m.y.y - m.x.x - m.z.z,
2546 m.z.z - m.x.x - m.y.y, m.x.x + m.y.y + m.z.z},
2547 s[]{{1, m.x.y + m.y.x, m.z.x + m.x.z, m.y.z - m.z.y},
2548 {m.x.y + m.y.x, 1, m.y.z + m.z.y, m.z.x - m.x.z},
2549 {m.x.z + m.z.x, m.y.z + m.z.y, 1, m.x.y - m.y.x},
2550 {m.y.z - m.z.y, m.z.x - m.x.z, m.x.y - m.y.x, 1}};
2551 return copysign(normalize(sqrt(max(T(0), T(1) + q))), s[argmax(q)]);
2552}
2553
2554template <class T>
2555linalg::mat<T, 4, 4> linalg::lookat_matrix(const vec<T, 3>& eye,
2556 const vec<T, 3>& center,
2557 const vec<T, 3>& view_y_dir,
2558 fwd_axis a) {
2559 const vec<T, 3> f = normalize(center - eye), z = a == pos_z ? f : -f,
2560 x = normalize(cross(view_y_dir, z)), y = cross(z, x);
2561 return inverse(mat<T, 4, 4>{{x, 0}, {y, 0}, {z, 0}, {eye, 1}});
2562}
2563
2564template <class T>
2565linalg::mat<T, 4, 4> linalg::frustum_matrix(T x0, T x1, T y0, T y1, T n, T f,
2566 fwd_axis a, z_range z) {
2567 const T s = a == pos_z ? T(1) : T(-1), o = z == neg_one_to_one ? n : 0;
2568 return {{2 * n / (x1 - x0), 0, 0, 0},
2569 {0, 2 * n / (y1 - y0), 0, 0},
2570 {-s * (x0 + x1) / (x1 - x0), -s * (y0 + y1) / (y1 - y0),
2571 s * (f + o) / (f - n), s},
2572 {0, 0, -(n + o) * f / (f - n), 0}};
2573}
2574#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:1966
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:2004
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:1981
constexpr vec< T, 3 > qzdir(const vec< T, 4 > &q)
efficient shorthand for qrot(q, {0,0,1})
Definition linalg.h:1958
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:1997
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:1989
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:2012
constexpr vec< T, 3 > qxdir(const vec< T, 4 > &q)
efficient shorthand for qrot(q, {1,0,0})
Definition linalg.h:1941
constexpr vec< T, 3 > qrot(const vec< T, 4 > &q, const vec< T, 3 > &v)
Rotate a vector by a quaternion.
Definition linalg.h:1973
constexpr vec< T, 3 > qydir(const vec< T, 4 > &q)
efficient shorthand for qrot(q, {0,1,0})
Definition linalg.h:1949
vec< T, 4 > qinv(const vec< T, 4 > &q)
inverse or reciprocal of quaternion q (undefined for zero-length quaternions)
Definition linalg.h:1874
vec< T, 4 > qexp(const vec< T, 4 > &q)
exponential of quaternion q
Definition linalg.h:1883
vec< T, 4 > qpow(const vec< T, 4 > &q, const T &p)
quaternion q raised to the exponent p
Definition linalg.h:1904
vec< T, 4 > qlog(const vec< T, 4 > &q)
logarithm of quaternion q
Definition linalg.h:1895
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:1917
constexpr vec< T, 4 > qconj(const vec< T, 4 > &q)
conjugate of quaternion q
Definition linalg.h:1865
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:1675
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:1684
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:1693
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:1496
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:1512
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:1504
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:1819
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:1801
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:1770
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:1810
constexpr T length2(const vec< T, M > &a)
square of the length or magnitude of vector a
Definition linalg.h:1745
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:1738
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:1836
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:1761
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:1845
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:1793
T uangle(const vec< T, M > &a, const vec< T, M > &b)
Return the angle in radians between two unit vectors.
Definition linalg.h:1785
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:1708
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:1828
T length(const vec< T, M > &a)
length or magnitude of a vector a
Definition linalg.h:1752
T distance(const vec< T, M > &a, const vec< T, M > &b)
Euclidean distance between points a and b
Definition linalg.h:1778
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:676
Definition linalg.h:673
Definition linalg.h:718
Definition linalg.h:679
Definition linalg.h:628
Definition linalg.h:723
Definition linalg.h:667
Definition linalg.h:688
Definition linalg.h:634
Definition linalg.h:622
Definition linalg.h:706
Definition linalg.h:610
Definition linalg.h:652
Definition linalg.h:646
Definition linalg.h:640
Definition linalg.h:712
Definition linalg.h:700
Definition linalg.h:664
Definition linalg.h:682
Definition linalg.h:658
Definition linalg.h:670
Definition linalg.h:694
Definition linalg.h:1151
Definition linalg.h:63
Definition linalg.h:58