# Data.Quaternion

- Package
- purescript-quaternions
- Repository
- hdgarrood/purescript-quaternions

The quaternions are a number system which generalise the complex numbers, in a similar way to how the complex numbers generalise the real numbers. One interesting aspect of the quaternions is that they satisfy all but one of the requirements to be a field; they only fail to be a field because their multiplication is non-commutative.

Just as complex numbers can be thought of as pairs of real numbers, where the first is the "real part" and the second is the "imaginary part", quaternions can be thought of as a pair containing a "real part", which is again simply a real number, and a "vector part", which is a vector in R^3. Addition of quaternions is then easy to define: the sum of two quaternions has a real part equal to the sum of the operands' real parts, and a vector part equal to the sum of the operands' vector parts.

There are four particularly important quaternions, which are known as the
"basis elements". The first is `1`

, which (when considered as a
quaternion) has a real part of `1`

and a vector part of `0`

(i.e. the zero
vector). The standard basis vectors in R^3 are commonly written as `e_1`

,
`e_2`

, and `e_3`

; the quaternions with a real part of 0 and a vector part
of `e_1`

, `e_2`

, and `e_3`

are called `i`

, `j`

, and `k`

respectively, and
form the other three basis elements.

These four elements are called the basis elements because every quaternion
can be written as `a + bi + cj + dk`

for a choice of real numbers `a`

,
`b`

, `c`

, and `d`

.

Now, we can define multiplication on quaternions just by defining
multiplication on the basis elements `1`

, `i`

, `j`

, and `k`

, for which we
use the formula:

```
i^2 = j^2 = k^2 = ijk = -1
```

One of the first things we can deduce is that the multiplicative inverse
of `i`

is `-i`

(just as with complex numbers), and also that the inverses
of `j`

and `k`

are `-j`

and `-k`

respectively.

From here we can calculate products between any two basis elements. For
example, to calculate the product `jk`

, we notice that `i^2 = ijk`

and
therefore we can cancel `i`

on the left to yield `i = jk`

. As another
example, to calculate the product `ik`

, we may start with the equation
`i = jk`

and multiply both sides by `k`

, yielding `ik = jk^2 = -j`

. All
other products of basis elements may be obtained in a similar fashion.

Knowing the products of basis elements and using the distributive law, we can find the product of any two quaternions:

```
(a + bi + cj + dk) * (e + fi + gj + hk)
= ae + afi + agj + ahk
+ bei + bf(i^2) + bg(ij) + bh(ik)
+ cej + cf(ji) + cg(j^2) + ch(jk)
+ dek + df(ki) + dg(kj) + dh(k^2)
= ae - bf - cg - dh
+ (af + be + ch - dg) i
+ (ag - bh + ce + df) j
+ (ah + bg - cf + de) k
```

Note that quaternion multiplication is not commutative; that is, `p * q`

is usually not the same as `q * p`

. For example, `ij = k`

, but `ji = -k`

.

Like the real numbers, however, each quaternion does have a multiplicative
inverse, i.e. for each quaternion `p`

there exists a unique quaternion `q`

such that `p * q = q * p = 1`

.

This means that there are two ways of dividing quaternions. If we want to
divide a quaternion `p`

by another quaternion `q`

, we can multiply `p`

by
the multiplicative inverse of `q`

, which can be written `q^-1`

. Of course,
we have two ways of doing this; `p * q^-1`

and `q^-1 * p`

will not
necessarily be the same, so we are really dealing with two different
operations here. We call the operation taking `p`

and `q`

to `q^-1 * p`

"left-division", and the alternative operation which yields `p * q^-1`

"right-division".

The most important application of quaternions in computing is for representing orientations and rotations in 3D space; see the Data.Quaternion.Rotation module for more details of this.

### #Quaternion Source

`data Quaternion a`

A quaternion. The type parameter denotes the underlying type. Note that the underlying type should be a reasonable approximation of the real numbers; if this is not the case, some of the functions may exhibit strange behaviour.

Because multiplication of quaternions is non-commutative, there is no
`CommutativeRing`

instance, and consequently no `EuclideanRing`

or `Field`

instance either.

This means, amongst other things, that the `(/)`

operator from Prelude
cannot be used with `Quaternion`

values. However, `Quaternion`

does have
a `DivisionRing`

instance, so you can use `leftDiv`

and `rightDiv`

from
the module `Data.DivisionRing`

from the `prelude`

library instead. These
functions are also re-exported from this module for convenience.

#### Constructors

`Quaternion a a a a`

#### Instances

`(Eq a) => Eq (Quaternion a)`

`(Show a) => Show (Quaternion a)`

`(Ring a) => Semiring (Quaternion a)`

`(Ring a) => Ring (Quaternion a)`

`Functor Quaternion`

`(DivisionRing a) => DivisionRing (Quaternion a)`

### #approxEq Source

`approxEq :: forall a. Ord a => Ring a => a -> Quaternion a -> Quaternion a -> Boolean`

Approximate equality of quaternions, given an epsilon value specifying the maximum amount that any of the four components is allowed to differ by.

### #conjugate Source

`conjugate :: forall a. Ring a => Quaternion a -> Quaternion a`

The conjugate of a quaternion. This operation negates the vector part of the quaternion.

### #conjugateBy Source

`conjugateBy :: forall a. DivisionRing a => Quaternion a -> Quaternion a -> Quaternion a`

The conjugate of a quaternion by another quaternion. Defined as

```
\p q -> q * p * recip q
```

### #i Source

`i :: forall a. Semiring a => Quaternion a`

### #j Source

`j :: forall a. Semiring a => Quaternion a`

### #k Source

`k :: forall a. Semiring a => Quaternion a`

### #normSquare Source

`normSquare :: forall a. Semiring a => Quaternion a -> a`

The square of the norm of a quaternion. This is slightly easier to compute than the actual norm, so may be useful in cases where you are worried about performance.

### #realPart Source

`realPart :: forall a. Quaternion a -> a`

The real part of the quaternion, that is, the first component. Defined as

```
\(Quaternion a _ _ _) -> a
```

### #scalarMul Source

`scalarMul :: forall a. Semiring a => a -> Quaternion a -> Quaternion a`

Multiplies both the real part and the vector part by the given scalar.

### #vectorPart Source

`vectorPart :: forall a. Quaternion a -> Vec3 a`

The vector part of the quaternion, that is, the second, third, and fourth components, represented as an array with exactly 3 elements. Defined as

```
\(Quaternion _ x y z) -> vec3 x y z
```

### #versor Source

`versor :: Quaternion Number -> Quaternion Number`

Scales the given quaternion, returning a quaternion pointing in the same direction of unit norm; multiplying this by the original quaternion's norm will give you back the original quaternion.

## Re-exports from **Data.**DivisionRing

### #rightDiv Source

`rightDiv :: forall a. DivisionRing a => a -> a -> a`

Right division, defined as `rightDiv a b = a * recip b`

. Left and right
division are distinct in this module because a `DivisionRing`

is not
necessarily commutative.

If the type `a`

is also a `EuclideanRing`

, then this function is
equivalent to `div`

from the `EuclideanRing`

class. When working
abstractly, `div`

should generally be preferred, unless you know that you
need your code to work with noncommutative rings.

### #leftDiv Source

`leftDiv :: forall a. DivisionRing a => a -> a -> a`

Left division, defined as `leftDiv a b = recip b * a`

. Left and right
division are distinct in this module because a `DivisionRing`

is not
necessarily commutative.

If the type `a`

is also a `EuclideanRing`

, then this function is
equivalent to `div`

from the `EuclideanRing`

class. When working
abstractly, `div`

should generally be preferred, unless you know that you
need your code to work with noncommutative rings.