---
title: "Complex arithmetic using Clifford algebra"
author: "Robin K. S. Hankin"
output: html_vignette
bibliography: clifford.bib
link-citations: true
vignette: >
  %\VignetteIndexEntry{Complex arithmetic using Clifford algebra}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---


```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library("clifford")
```

```{r out.width='20%', out.extra='style="float:right; padding:10px"',echo=FALSE}
knitr::include_graphics(system.file("help/figures/clifford.png", package = "clifford"))
```

To cite the `clifford` package in publications please use
@hankin2025_clifford_rmd.  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:

```{r label=coercionfuncs}
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:

```{r label=numversetup}
z1 <- 35 + 67i
z2 <- -2 + 12i
```

Then, for example:

```{r label=examplecoerce}
z1
complex_to_clifford(z1)
```

Checking that the coercion is a homomorphism is easy:


```{r label=numverdo}
complex_to_clifford(z1) * complex_to_clifford(z2) == complex_to_clifford(z1*z2)
```

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:


```{r label=otherway}
(C1 <- 23 + 7*e(1))
clifford_to_complex(C1)
C2 <- 2  - 8*e(1)
clifford_to_complex(C1)*clifford_to_complex(C2) == clifford_to_complex(C1*C2)
```

## 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}$.

```{r label=secondcoercions}
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:

```{r label=thennumver}
z1 <- 35 + 67i
z2 <- -2 + 12i
complex_to_clifford(z1) * complex_to_clifford(z2) == complex_to_clifford(z1*z2)
```

```{r label=gobackwards}
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)
```

### 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)$:

```{r label=useothersig}
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)
)
```


### Default

It is best to return the signature and `maxdim` to their default
values in order to prevent interference with other vignettes:

```{r label=restoresig}
options(maxdim=NULL)
signature(Inf)
```


## References