Complex arithmetic using Clifford algebra
Robin K. S. Hankin
Source:vignettes/complex_clifford.Rmd
complex_clifford.Rmd
To cite the clifford
package in publications please use
Hankin (2022). This short document shows
how complex arithmetic may be implemented using Clifford algebra (of
course, if one really wants to use complex numbers, base R is much more
efficient and uses nicer idiom than the methods presented here). Recall
that complex numbers are a two-dimensional algebra over the reals, with
\((a,b)\cdot(c,d)=(ac-bd,ad+bc)\); we
usually write \((a,b)\) as \(a+bi\). There are two natural ways to
identify complex numbers with Clifford objects; but because they use
different signatures it is more convenient to treat them separately.
First method
We use \(\operatorname{Cl}(0,1)\), so \(e_1^2=-1\). Package idiom is straightforward; to coerce complex numbers to Clifford objects and vice versa, we need a couple of functions:
signature(0,1)
options(maxdim=1) # paranoid-level safety measure
complex_to_clifford <- function(z){Re(z) + e(1)*Im(z)}
clifford_to_complex <- function(C){const(C) + 1i*getcoeffs(C,1)}
clifford_to_complex <- function(C){const(C) + 1i*coeffs(Im(C))}
Then numerical verification is immediate. First we choose some complex numbers:
z1 <- 35 + 67i
z2 <- -2 + 12i
Then, for example:
z1
## [1] 35+67i
complex_to_clifford(z1)
## Element of a Clifford algebra, equal to
## + 35 + 67e_1
Checking that the coercion is a homomorphism is easy:
complex_to_clifford(z1) * complex_to_clifford(z2) == complex_to_clifford(z1*z2)
## [1] TRUE
Above, note that the *
on the left is the geometric
product, while the *
on the right is the usual complex
multiplication. And because the map is invertible we can check the other
way too:
(C1 <- 23 + 7*e(1))
## Element of a Clifford algebra, equal to
## + 23 + 7e_1
clifford_to_complex(C1)
## [1] 23+7i
C2 <- 2 - 8*e(1)
clifford_to_complex(C1)*clifford_to_complex(C2) == clifford_to_complex(C1*C2)
## [1] TRUE
Second method
We use \(\operatorname{Cl}(2)\), so \(e_1^2=e_2^2=1\), and identify the imaginary unit \(i\) with \(e_{12}\) (thus \(e_{12}^2=e_{12}e_{12}=e_{1212}=-e_{1122}=-e_1^2e_2^2=-1\)). A general complex number \(z=x+iy\) maps to Clifford object \(x + ye_{12}\).
options(maxdim=2) # paranoid-level safety measure
signature(2)
complex_to_clifford <- function(z){Re(z) + e(1:2)*Im(z)}
clifford_to_complex <- function(C){const(C) + 1i*coeffs(Im(C))}
Then numerical verification:
z1 <- 35 + 67i
z2 <- -2 + 12i
complex_to_clifford(z1) * complex_to_clifford(z2) == complex_to_clifford(z1*z2)
## [1] TRUE
C1 <- 23 + 7*e(1:2)
C2 <- 2 - 8*e(1:2)
clifford_to_complex(C1)*clifford_to_complex(C2) == clifford_to_complex(C1*C2)
## [1] TRUE
Note
The identification \(x+iy\longrightarrow x+ye_{12}\) is a homomorphism whenever \(e_1^2e_2^2=1\); above we used \(\operatorname{Cl}(2,0)\) so \(e_1^2=e_2^2=1\). However, the relation is also satisfied if \(e_1^2=e_2^2=-1\), so we can equally well use \(\operatorname{Cl}(0,2)\):
signature(0,2)
c(
complex_to_clifford(z1)*complex_to_clifford(z2) == complex_to_clifford(z1*z2),
clifford_to_complex(C1)*clifford_to_complex(C2) == clifford_to_complex(C1*C2)
)
## [1] TRUE TRUE