```  #line 581 "/home/travis/build/felix-lang/felix/src/packages/numbers.fdoc"

class Quaternion
{
type quaternion = new double ^ 4;
ctor quaternion (x:double^4) => _make_quaternion x;
private typedef q = quaternion;
fun r(x:q)=> (_repr_ x) . 0;
fun i(x:q)=> (_repr_ x) . 1;
fun j(x:q)=> (_repr_ x) . 2;
fun k(x:q)=> (_repr_ x) . 3;

ctor q (x:double) => quaternion (x,0.0,0.0,0.0);

fun + (a:q,b:q):q =>
quaternion (a.r+ b.r, a.i + b.i, a.j + b.j, a.k+b.k)
;

fun * (a:q, b:q):q =>
quaternion (
a.r * b.r - a.i * b.i - a.j * b.j - a.k * b.k,
a.r * b.i + a.i * b.r + a.j * b.k - a.k * b.j,
a.r * b.j - a.i * b.k + a.j * b.r - a.k * b.i,
a.r * b.k + a.i * b.j - a.j * b.i + a.k * b.r
)
;

fun conj (a:q):q => quaternion (a.r, -a.i, -a.j, -a.k);
fun norm (a:q):double => sqrt (a.r * a.r + a.i * a.i + a.j * a.j +a.k * a.k);

fun * (a:q, b: double):q => quaternion (a.r * b, a.i * b, a.j * b, a.k * b);
fun * (a: double, b:q):q => a * b;

fun reciprocal (a:q):q => let n = norm a in conj a * (1.0/ (n * n));

// add more later, generalise scalar type
// Later, GET RID of complex and quaternions
// by introducing typeclasses for arbitrary R-modules
}

```