Skip to content
This repository was archived by the owner on Aug 2, 2024. It is now read-only.

Commit 77d9353

Browse files
committed
Add rotor exp/log and optimize exterior/regressive product
1 parent bab36b2 commit 77d9353

File tree

16 files changed

+552
-91
lines changed

16 files changed

+552
-91
lines changed

Doxyfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ DISTRIBUTE_GROUP_DOC = NO
399399
# is disabled and one has to add nested compounds explicitly via \ingroup.
400400
# The default value is: NO.
401401

402-
GROUP_NESTED_COMPOUNDS = NO
402+
GROUP_NESTED_COMPOUNDS = YES
403403

404404
# Set the SUBGROUPING tag to YES to allow class member groups of the same type
405405
# (for instance a group of public functions) to be put as a subgroup of that

docs/api/kln_direction.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Directions in $\mathbf{P}(\mathbb{R}^3_{3, 0, 1})$ are represented using points
1414
`public ` [`direction`](#structkln_1_1direction_1a6d22510e72f67516a65a2ee39a5591a3)`() = default` |
1515
`public ` [`direction`](#structkln_1_1direction_1a8fc796733d32a69230136b8376003fca)`(float x,float y,float z) noexcept` | Create a normalized direction.
1616
`public ` [`direction`](#structkln_1_1direction_1a81cd76b26d928f02e830d8c0175157d6)`(` [`entity`](../../api/kln_entity#structkln_1_1entity)`< 0b1000 > const & e) noexcept` |
17+
`public explicit ` [`direction`](#structkln_1_1direction_1a42ce139ace571176acabbce21d6c64b2)`(float * data) noexcept` | Data should point to four floats with memory layout `(0.f, x, y, z)` where the zero occupies the lowest address in memory.
1718
`public constexpr float ` [`operator[]`](#structkln_1_1direction_1a8fa09342bff2583a7f29d04adf6dd3c2)`(size_t i) const noexcept` |
1819
`public constexpr float & ` [`operator[]`](#structkln_1_1direction_1a67a82ca405563ca75b7f8a84842e42c0)`(size_t i) noexcept` |
1920
`public float ` [`x`](#structkln_1_1direction_1a721087c2056a33cd780c678ae0ec39dd)`() const noexcept` |
@@ -34,6 +35,10 @@ Create a normalized direction.
3435

3536
#### [direction](#structkln_1_1direction_1a81cd76b26d928f02e830d8c0175157d6)( [entity](../../api/kln_entity#structkln_1_1entity)< 0b1000 > const & e) noexcept {#structkln_1_1direction_1a81cd76b26d928f02e830d8c0175157d6}
3637

38+
#### explicit [direction](#structkln_1_1direction_1a42ce139ace571176acabbce21d6c64b2)(float * data) noexcept {#structkln_1_1direction_1a42ce139ace571176acabbce21d6c64b2}
39+
40+
Data should point to four floats with memory layout `(0.f, x, y, z)` where the zero occupies the lowest address in memory.
41+
3742
#### float [operator[]](#structkln_1_1direction_1a8fa09342bff2583a7f29d04adf6dd3c2)(size_t i) const noexcept {#structkln_1_1direction_1a8fa09342bff2583a7f29d04adf6dd3c2}
3843

3944
#### float & [operator[]](#structkln_1_1direction_1a67a82ca405563ca75b7f8a84842e42c0)(size_t i) noexcept {#structkln_1_1direction_1a67a82ca405563ca75b7f8a84842e42c0}
@@ -56,6 +61,6 @@ Normalize this direction by dividing all components by the square magnitude
5661

5762
!!! tip
5863
Direction normalization divides the coordinates by the quantity
59-
a^2 + b^2 + c^2. This is done using the `rcpps` instruction with a
64+
x^2 + y^2 + z^2. This is done using the `rcpps` instruction with a
6065
maximum relative error of $1.5\times 2^{-12}$.
6166

docs/api/kln_entity.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ To compute PGA elements using SSE, we partition the basis into four partitions c
99
```cpp
1010
LSB --> MSB
1111
p0: (e_0, e_1, e_2, e_3)
12-
p1: (1, e_12, e_31, e_23)
12+
p1: (1, e_23, e_31, e_12)
1313
p2: (e_0123, e_01, e_02, e_03)
14-
p3: (e_123, e_021, e_013, e_032)
14+
p3: (e_123, e_032, e_013, e_021)
1515
```
1616

1717
The scalar and pseudoscalar are packed in partitions $p_1$ and $p_2$ along with the 6 bivector elements. The scheme groups, for the most part, elements of similar grade and the presence of the degenerate generator. When non-uniformity exists within a partition (mixed degenerate and non-degenerate components, or mixed grade), the "exception" is housed in the first component so that the same swizzle masks can be used.

docs/api/kln_line.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ struct kln::line
2626

2727
A line is specifed by 6 coordinates which correspond to the line's [Plücker coordinates](https://en.wikipedia.org/wiki/Pl%C3%BCcker_coordinates). The coordinates specified in this way correspond to the following multivector:
2828

29-
$$a\mathbf{e}_{01} + b\mathbf{e}_{02} + c\mathbf{e}_{03} +\ d\mathbf{e}_{12} + e\mathbf{e}_{31} + f\mathbf{e}_{23}$$
29+
$$a\mathbf{e}_{01} + b\mathbf{e}_{02} + c\mathbf{e}_{03} +\ d\mathbf{e}_{23} + e\mathbf{e}_{31} + f\mathbf{e}_{12}$$
3030

3131
#### [line](#structkln_1_1line_1af9e56edfe5fe537ef21dd76c1927c5fe)( [entity](../../api/kln_entity#structkln_1_1entity)< 0b110 > const & e) {#structkln_1_1line_1af9e56edfe5fe537ef21dd76c1927c5fe}
3232

docs/api/kln_motor.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ A demonstration of using the exponential and logarithmic map to blend between tw
5050
Members | Descriptions
5151
--------------------------------|---------------------------------------------
5252
`public ` [`motor`](#structkln_1_1motor_1af185a86b951973e31cd16398845f73bf)`() = default` |
53-
`public ` [`motor`](#structkln_1_1motor_1a0fc9829b8e6323e3ae2cc583361ce3d5)`(float a,float b,float c,float d,float e,float f,float g,float h) noexcept` | Direct initialization from components. A more common way of creating a motor is to take a product between a rotor and a translator. The arguments coorespond to the multivector $a + b\mathbf{e}_{12} + c\mathbf{e}_{31} + d\mathbf{e}_{23} +\ e\mathbf{e}_{01} + f\mathbf{e}_{02} + g\mathbf{e}_{03} +\ h\mathbf{e}_{0123}$
53+
`public ` [`motor`](#structkln_1_1motor_1a0fc9829b8e6323e3ae2cc583361ce3d5)`(float a,float b,float c,float d,float e,float f,float g,float h) noexcept` | Direct initialization from components. A more common way of creating a motor is to take a product between a rotor and a translator. The arguments coorespond to the multivector $a + b\mathbf{e}_{23} + c\mathbf{e}_{31} + d\mathbf{e}_{12} +\ e\mathbf{e}_{01} + f\mathbf{e}_{02} + g\mathbf{e}_{03} +\ h\mathbf{e}_{0123}$.
5454
`public ` [`motor`](#structkln_1_1motor_1a3c24baaa74a00bbc2cf64729916498b8)`(` [`entity`](../../api/kln_entity#structkln_1_1entity)`< 0b110 > const & e) noexcept` |
5555
`public void ` [`load`](#structkln_1_1motor_1a3a048b8d0f35322259f8f1cbaad88cab)`(float * in) noexcept` | Load motor data using two unaligned loads. This routine does *not* assume the data passed in this way is normalized.
5656
`public void ` [`normalize`](#structkln_1_1motor_1a8af12b78c4e98b84c51f605b47dbc0a1)`() noexcept` | Normalizes this motor $m$ such that $m\widetilde{m} = 1$.
@@ -72,7 +72,7 @@ A demonstration of using the exponential and logarithmic map to blend between tw
7272

7373
#### [motor](#structkln_1_1motor_1a0fc9829b8e6323e3ae2cc583361ce3d5)(float a,float b,float c,float d,float e,float f,float g,float h) noexcept {#structkln_1_1motor_1a0fc9829b8e6323e3ae2cc583361ce3d5}
7474

75-
Direct initialization from components. A more common way of creating a motor is to take a product between a rotor and a translator. The arguments coorespond to the multivector $a + b\mathbf{e}_{12} + c\mathbf{e}_{31} + d\mathbf{e}_{23} +\ e\mathbf{e}_{01} + f\mathbf{e}_{02} + g\mathbf{e}_{03} +\ h\mathbf{e}_{0123}$
75+
Direct initialization from components. A more common way of creating a motor is to take a product between a rotor and a translator. The arguments coorespond to the multivector $a + b\mathbf{e}_{23} + c\mathbf{e}_{31} + d\mathbf{e}_{12} +\ e\mathbf{e}_{01} + f\mathbf{e}_{02} + g\mathbf{e}_{03} +\ h\mathbf{e}_{0123}$.
7676

7777
#### [motor](#structkln_1_1motor_1a3c24baaa74a00bbc2cf64729916498b8)( [entity](../../api/kln_entity#structkln_1_1entity)< 0b110 > const & e) noexcept {#structkln_1_1motor_1a3c24baaa74a00bbc2cf64729916498b8}
7878

docs/api/kln_plane.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ The plane multivector in PGA looks like $d\mathbf{e}_0 + a\mathbf{e}_1 + b\mathb
1515
--------------------------------|---------------------------------------------
1616
`public ` [`plane`](#structkln_1_1plane_1a0ab245bca0c1ad3aca86b9ceeab3fe42)`() = default` | The default constructor leaves memory uninitialized.
1717
`public ` [`plane`](#structkln_1_1plane_1a51933d8d8853797034621ce41ad34a8e)`(float a,float b,float c,float d) noexcept` | The constructor performs the rearrangement so the plane can be specified in the familiar form: ax + by + cz + d
18-
`public ` [`plane`](#structkln_1_1plane_1a29dbb1804fa3ec402f901ca8049d60bc)`(float * data) noexcept` | Data should point to four floats with memory layout `(d, a, b, c)` where `d` occupies the lowest address in memory.
18+
`public explicit ` [`plane`](#structkln_1_1plane_1a29dbb1804fa3ec402f901ca8049d60bc)`(float * data) noexcept` | Data should point to four floats with memory layout `(d, a, b, c)` where `d` occupies the lowest address in memory.
1919
`public explicit ` [`plane`](#structkln_1_1plane_1a4fe52a0426bc881947909d0d9b1745d0)`(` [`entity`](../../api/kln_entity#structkln_1_1entity)`< 0b1001 > const & other) noexcept` | Line to plane cast.
2020
`public void ` [`load`](#structkln_1_1plane_1a5a00871dbe19d7658b7e8cda71b326f2)`(float * data) noexcept` | Unaligned load of data. The `data` argument should point to 4 floats corresponding to the `(d, a, b, c)` components of the plane multivector where `d` occupies the lowest address in memory.
21+
`public void ` [`normalize`](#structkln_1_1plane_1ae5e1e0af05e84799d27d7b8782fe5f22)`() noexcept` | Normalize this plane $p$ such that $p \cdot p = 1$.
2122
`public ` [`plane`](#structkln_1_1plane)` KLN_VEC_CALL ` [`operator()`](#structkln_1_1plane_1a1c7a11e35d91c2aee88a4152b1799ca9)`(` [`plane`](#structkln_1_1plane)` const & p) const noexcept` | Reflect another plane $p_2$ through this plane $p_1$. The operation performed via this call operator is an optimized routine equivalent to the expression $p_1 p_2 p_1$.
2223
`public ` [`line`](../../api/kln_line#structkln_1_1line)` KLN_VEC_CALL ` [`operator()`](#structkln_1_1plane_1a782e4e0b1b93ab5bffb2c972f6d7acfa)`(` [`line`](../../api/kln_line#structkln_1_1line)` const & l) const noexcept` | Reflect line $\ell$ through this plane $p$. The operation performed via this call operator is an optimized routine equivalent to the expression $p \ell p$.
2324
`public ` [`point`](../../api/kln_point#structkln_1_1point)` KLN_VEC_CALL ` [`operator()`](#structkln_1_1plane_1a20b6577f6d1717e1ec086314d3ebd497)`(` [`point`](../../api/kln_point#structkln_1_1point)` const & p) const noexcept` | Reflect the point $P$ through this plane $p$. The operation performed via this call operator is an optimized routine equivalent to the expression $p P p$.
@@ -40,7 +41,7 @@ The default constructor leaves memory uninitialized.
4041

4142
The constructor performs the rearrangement so the plane can be specified in the familiar form: ax + by + cz + d
4243

43-
#### [plane](#structkln_1_1plane_1a29dbb1804fa3ec402f901ca8049d60bc)(float * data) noexcept {#structkln_1_1plane_1a29dbb1804fa3ec402f901ca8049d60bc}
44+
#### explicit [plane](#structkln_1_1plane_1a29dbb1804fa3ec402f901ca8049d60bc)(float * data) noexcept {#structkln_1_1plane_1a29dbb1804fa3ec402f901ca8049d60bc}
4445

4546
Data should point to four floats with memory layout `(d, a, b, c)` where `d` occupies the lowest address in memory.
4647

@@ -67,6 +68,12 @@ Unaligned load of data. The `data` argument should point to 4 floats correspond
6768
This is a faster mechanism for setting data compared to setting
6869
components one at a time.
6970

71+
#### void [normalize](#structkln_1_1plane_1ae5e1e0af05e84799d27d7b8782fe5f22)() noexcept {#structkln_1_1plane_1ae5e1e0af05e84799d27d7b8782fe5f22}
72+
73+
Normalize this plane $p$ such that $p \cdot p = 1$.
74+
75+
In order to compute the cosine of the angle between planes via the inner product operator `|` , the planes must be normalized. Producing a normalized rotor between two planes with the geometric product `*` also requires that the planes are normalized.
76+
7077
#### [plane](#structkln_1_1plane) KLN_VEC_CALL [operator()](#structkln_1_1plane_1a1c7a11e35d91c2aee88a4152b1799ca9)( [plane](#structkln_1_1plane) const & p) const noexcept {#structkln_1_1plane_1a1c7a11e35d91c2aee88a4152b1799ca9}
7178

7279
Reflect another plane $p_2$ through this plane $p_1$. The operation performed via this call operator is an optimized routine equivalent to the expression $p_1 p_2 p_1$.

docs/api/kln_point.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ A point is represented as the multivector $x\mathbf{e}_{032} + y\mathbf{e}_{013}
1515
`public ` [`point`](#structkln_1_1point_1adc78c30fe71a140259dd7add02d36df8)`(float x,float y,float z) noexcept` | Component-wise constructor (homogeneous coordinate is automatically initialized to 1)
1616
`public ` [`point`](#structkln_1_1point_1a9b3754f1b4479d862d026cf55b91f7be)`(` [`entity`](../../api/kln_entity#structkln_1_1entity)`< 0b1000 > const & e) noexcept` |
1717
`public explicit ` [`point`](#structkln_1_1point_1ad149cbbf9e9a7e77fc680b808e971ee0)`(` [`entity`](../../api/kln_entity#structkln_1_1entity)`< 0b1001 > const & e) noexcept` | A point projected onto a line will have an extinguished partition-0, which necessitates this explicit cast when it is known to be safe.
18-
`public void ` [`load`](#structkln_1_1point_1a805739dde6d772f5b228cce5b95ef13f)`(float * data) noexcept` | Fast load from a pointer to an array of four floats with layout `(w, z, y, x)` where `w` occupies the lowest address in memory.
18+
`public void ` [`load`](#structkln_1_1point_1a805739dde6d772f5b228cce5b95ef13f)`(float * data) noexcept` | Fast load from a pointer to an array of four floats with layout `(w, x, y, z)` where `w` occupies the lowest address in memory.
1919
`public float ` [`x`](#structkln_1_1point_1a0c100888d1b7edc3fdb81f8b7c22feb1)`() const noexcept` |
2020
`public float & ` [`x`](#structkln_1_1point_1a47e6deddfdd3939952ef80bb33236bfc)`() noexcept` |
2121
`public float ` [`y`](#structkln_1_1point_1ae413703952e1a6e15b401d2620f6ae93)`() const noexcept` |
@@ -44,7 +44,7 @@ A point projected onto a line will have an extinguished partition-0, which neces
4444

4545
#### void [load](#structkln_1_1point_1a805739dde6d772f5b228cce5b95ef13f)(float * data) noexcept {#structkln_1_1point_1a805739dde6d772f5b228cce5b95ef13f}
4646

47-
Fast load from a pointer to an array of four floats with layout `(w, z, y, x)` where `w` occupies the lowest address in memory.
47+
Fast load from a pointer to an array of four floats with layout `(w, x, y, z)` where `w` occupies the lowest address in memory.
4848

4949
!!! tip
5050
This load operation is more efficient that modifying individual

docs/api/kln_rotor.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,10 @@ The same `*` operator can be used to compose the rotor's action with other tran
5050
`public ` [`rotor`](#structkln_1_1rotor_1a3d3e11652d0c83a5f86de0d33b259be4)`() = default` | Default constructor leaves memory uninitialized.
5151
`public ` [`rotor`](#structkln_1_1rotor_1a1ed5b58579ef482f98fcd019476f883c)`(float ang_rad,float x,float y,float z)` | Convenience constructor. Computes transcendentals and normalizes rotation axis.
5252
`public ` [`rotor`](#structkln_1_1rotor_1aa14da87f8cbcddbd997fb29738214298)`(` [`entity`](../../api/kln_entity#structkln_1_1entity)`< 0b10 > const & other)` |
53-
`public void ` [`load_normalized`](#structkln_1_1rotor_1ab063d72ca484de581a78ebd7b49e41da)`(float * data) noexcept` | Fast load operation for packed data that is already normalized. The argument `data` should point to a set of 4 float values with layout `(a, b, c, d)` corresponding to the multivector $a + b\mathbf{e}_{12} + c\mathbf{e}_{31} + d\mathbf{e}_{23}$.
53+
`public void ` [`load_normalized`](#structkln_1_1rotor_1ab063d72ca484de581a78ebd7b49e41da)`(float * data) noexcept` | Fast load operation for packed data that is already normalized. The argument `data` should point to a set of 4 float values with layout `(a, b, c, d)` corresponding to the multivector $a + b\mathbf{e}_{23} + c\mathbf{e}_{31} + d\mathbf{e}_{12}$.
5454
`public void ` [`normalize`](#structkln_1_1rotor_1a4c9b04d0a4119e7d6b56b9e1478db5d4)`() noexcept` | Normalize a rotor such that $\mathbf{r}\widetilde{\mathbf{r}} = 1$.
5555
`public ` [`mat4x4`](../../api/kln_mat4x4#structkln_1_1mat4x4)` ` [`as_matrix`](#structkln_1_1rotor_1a0f13d2649e679220fc79ee7bc0bbea11)`() const noexcept` | Converts the rotor to a 4x4 column-major matrix.
56+
`public ` [`branch`](../../api/kln_rotor::branch#structkln_1_1rotor_1_1branch)` ` [`log`](#structkln_1_1rotor_1abdb39aa5e358dd4ceef256b48ef91e81)`() const noexcept` | Returns the principal branch of this rotor's logarithm. Invoking `exp` on the returned result maps back to this rotor.
5657
`public ` [`plane`](../../api/kln_plane#structkln_1_1plane)` KLN_VEC_CALL ` [`operator()`](#structkln_1_1rotor_1ae9e58f02352f5241dd94d22353a5e9ec)`(` [`plane`](../../api/kln_plane#structkln_1_1plane)` const & p) const noexcept` | Conjugates a plane $p$ with this rotor and returns the result $rp\widetilde{r}$.
5758
`public void KLN_VEC_CALL ` [`operator()`](#structkln_1_1rotor_1a491f6f2264c6ecf180664e75fc4a159b)`(` [`plane`](../../api/kln_plane#structkln_1_1plane)` * in,` [`plane`](../../api/kln_plane#structkln_1_1plane)` * out,size_t count) const noexcept` | Conjugates an array of planes with this rotor in the input array and stores the result in the output array. Aliasing is only permitted when `in == out` (in place motor application).
5859
`public ` [`line`](../../api/kln_line#structkln_1_1line)` KLN_VEC_CALL ` [`operator()`](#structkln_1_1rotor_1ac4d044ea5b98ba540fc5da8d75f43ccc)`(` [`line`](../../api/kln_line#structkln_1_1line)` const & l) const noexcept` | Conjugates a line $\ell$ with this rotor and returns the result $r\ell \widetilde{r}$.
@@ -76,7 +77,7 @@ Convenience constructor. Computes transcendentals and normalizes rotation axis.
7677

7778
#### void [load_normalized](#structkln_1_1rotor_1ab063d72ca484de581a78ebd7b49e41da)(float * data) noexcept {#structkln_1_1rotor_1ab063d72ca484de581a78ebd7b49e41da}
7879

79-
Fast load operation for packed data that is already normalized. The argument `data` should point to a set of 4 float values with layout `(a, b, c, d)` corresponding to the multivector $a + b\mathbf{e}_{12} + c\mathbf{e}_{31} + d\mathbf{e}_{23}$.
80+
Fast load operation for packed data that is already normalized. The argument `data` should point to a set of 4 float values with layout `(a, b, c, d)` corresponding to the multivector $a + b\mathbf{e}_{23} + c\mathbf{e}_{31} + d\mathbf{e}_{12}$.
8081

8182
!!! danger
8283
The rotor data loaded this way *must* be normalized. That is, the
@@ -90,6 +91,12 @@ Normalize a rotor such that $\mathbf{r}\widetilde{\mathbf{r}} = 1$.
9091

9192
Converts the rotor to a 4x4 column-major matrix.
9293

94+
#### [branch](../../api/kln_rotor::branch#structkln_1_1rotor_1_1branch) [log](#structkln_1_1rotor_1abdb39aa5e358dd4ceef256b48ef91e81)() const noexcept {#structkln_1_1rotor_1abdb39aa5e358dd4ceef256b48ef91e81}
95+
96+
Returns the principal branch of this rotor's logarithm. Invoking `exp` on the returned result maps back to this rotor.
97+
98+
Given a rotor $\cos\alpha + \sin\alpha\left[a\ee_{23} + b\ee_{31} +\ c\ee_{23}\right]$, the log is computed as simply $\alpha\left[a\ee_{23} + b\ee_{31} + c\ee_{23}\right]$. This map is only well-defined if the rotor is normalized such that $a^2 + b^2 + c^2 = 1$.
99+
93100
#### [plane](../../api/kln_plane#structkln_1_1plane) KLN_VEC_CALL [operator()](#structkln_1_1rotor_1ae9e58f02352f5241dd94d22353a5e9ec)( [plane](../../api/kln_plane#structkln_1_1plane) const & p) const noexcept {#structkln_1_1rotor_1ae9e58f02352f5241dd94d22353a5e9ec}
94101

95102
Conjugates a plane $p$ with this rotor and returns the result $rp\widetilde{r}$.

0 commit comments

Comments
 (0)