+ fromInteger x = Scalar (fromIntegral x)
+
+
+-- | Like the Num instance, the 'Fractional' instance allows us to
+-- take quotients of directions.
+instance Fractional Cardinal where
+ x / y = Quotient x y
+ recip = Quotient (Scalar 1)
+ fromRational x = Scalar (fromRational x)
+
+
+
+instance Arbitrary Cardinal where
+ arbitrary = oneof [f,b,l,r,d,t,fl,fr,fd,ft,bl,br,bd,bt,ld,lt,
+ rd,rt,fld,flt,frd,frt,bld,blt,brd,brt,i,
+ scalar,csum,cdiff,cprod,cquot]
+ where
+ f = return F
+ b = return B
+ l = return L
+ r = return R
+ d = return D
+ t = return T
+ fl = return FL
+ fr = return FR
+ fd = return FD
+ ft = return FT
+ bl = return BL
+ br = return BR
+ bd = return BD
+ bt = return BT
+ ld = return LD
+ lt = return LT
+ rd = return RD
+ rt = return RT
+ fld = return FLD
+ flt = return FLT
+ frd = return FRD
+ frt = return FRT
+ bld = return BLD
+ blt = return BLT
+ brd = return BRD
+ brt = return BRT
+ i = return I
+ scalar = liftM Scalar arbitrary
+ csum = liftM2 Sum arbitrary arbitrary
+ cdiff = liftM2 Difference arbitrary arbitrary
+ cprod = liftM2 Product arbitrary arbitrary
+ cquot = liftM2 Quotient arbitrary arbitrary
+
+
+-- | Rotate a cardinal direction counter-clockwise about the x-axis.
+ccwx :: Cardinal -> Cardinal
+ccwx F = F
+ccwx B = B
+ccwx L = T
+ccwx R = D
+ccwx D = L
+ccwx T = R
+ccwx FL = FT
+ccwx FR = FD
+ccwx FD = FL
+ccwx FT = FR
+ccwx BL = BT
+ccwx BR = BD
+ccwx BD = BL
+ccwx BT = BR
+ccwx LD = LT
+ccwx LT = RT
+ccwx RD = LD
+ccwx RT = RD
+ccwx FLD = FLT
+ccwx FLT = FRT
+ccwx FRD = FLD
+ccwx FRT = FRD
+ccwx BLD = BLT
+ccwx BLT = BRT
+ccwx BRD = BLD
+ccwx BRT = BRD
+ccwx I = I
+ccwx (Scalar s) = (Scalar s)
+ccwx (Sum c0 c1) = Sum (ccwx c0) (ccwx c1)
+ccwx (Difference c0 c1) = Difference (ccwx c0) (ccwx c1)
+ccwx (Product c0 c1) = Product (ccwx c0) (ccwx c1)
+ccwx (Quotient c0 c1) = Quotient (ccwx c0) (ccwx c1)
+
+-- | Rotate a cardinal direction clockwise about the x-axis.
+cwx :: Cardinal -> Cardinal
+cwx = ccwx . ccwx . ccwx
+
+
+-- | Rotate a cardinal direction counter-clockwise about the y-axis.
+ccwy :: Cardinal -> Cardinal
+ccwy F = D
+ccwy B = T
+ccwy L = L
+ccwy R = R
+ccwy D = B
+ccwy T = F
+ccwy FL = LD
+ccwy FR = RD
+ccwy FD = BD
+ccwy FT = FD
+ccwy BL = LT
+ccwy BR = RT
+ccwy BD = BT
+ccwy BT = FT
+ccwy LD = BL
+ccwy LT = FL
+ccwy RD = BR
+ccwy RT = FR
+ccwy FLD = BLD
+ccwy FLT = FLD
+ccwy FRD = BRD
+ccwy FRT = FRD
+ccwy BLD = BLT
+ccwy BLT = FLT
+ccwy BRD = BRT
+ccwy BRT = FRT
+ccwy I = I
+ccwy (Scalar s) = (Scalar s)
+ccwy (Sum c0 c1) = Sum (ccwy c0) (ccwy c1)
+ccwy (Difference c0 c1) = Difference (ccwy c0) (ccwy c1)
+ccwy (Product c0 c1) = Product (ccwy c0) (ccwy c1)
+ccwy (Quotient c0 c1) = Quotient (ccwy c0) (ccwy c1)
+
+-- | Rotate a cardinal direction clockwise about the y-axis.
+cwy :: Cardinal -> Cardinal
+cwy = ccwy . ccwy . ccwy
+
+
+-- | Rotate a cardinal direction counter-clockwise about the z-axis.
+ccwz :: Cardinal -> Cardinal
+ccwz F = R
+ccwz B = L
+ccwz L = F
+ccwz R = B
+ccwz D = D
+ccwz T = T
+ccwz FL = FR
+ccwz FR = BR
+ccwz FD = RD
+ccwz FT = RT
+ccwz BL = FL
+ccwz BR = BL
+ccwz BD = LD
+ccwz BT = LT
+ccwz LD = FD
+ccwz LT = FT
+ccwz RD = BD
+ccwz RT = BT
+ccwz FLD = FRD
+ccwz FLT = FRT
+ccwz FRD = BRD
+ccwz FRT = BRT
+ccwz BLD = FLD
+ccwz BLT = FLT
+ccwz BRD = BLD
+ccwz BRT = BLT
+ccwz I = I
+ccwz (Scalar s) = (Scalar s)
+ccwz (Sum c0 c1) = Sum (ccwz c0) (ccwz c1)
+ccwz (Difference c0 c1) = Difference (ccwz c0) (ccwz c1)
+ccwz (Product c0 c1) = Product (ccwz c0) (ccwz c1)
+ccwz (Quotient c0 c1) = Quotient (ccwz c0) (ccwz c1)
+
+-- | Rotate a cardinal direction clockwise about the z-axis.
+cwz :: Cardinal -> Cardinal
+cwz = ccwz . ccwz . ccwz