```{- |
2-dimensional linear transformations.
-}

module Data.Vector.Transform.T2 where

import Data.Monoid

import Data.Vector.Class
import Data.Vector.V2

{- |
The type of 2D linear transformations.

Note the @Monoid@ instance, which gives you access to the identity transform (@mempty@) and the ability to combine a series of transforms into a single transform (@mappend@).
-}
data Transform2 =
Transform2
{
t2_XX, t2_YX, t2_1X,
t2_XY, t2_YY, t2_1Y :: {-# UNPACK #-} !Scalar
}
deriving (Eq, Show)

instance Monoid Transform2 where
mempty = Transform2  1 0 0  0 1 0
mappend a b =
Transform2
{
t2_XX = t2_XX a * t2_XX b  +  t2_XY a * t2_YX b,
t2_YX = t2_YX a * t2_XX b  +  t2_YY a * t2_YX b,
t2_1X = t2_1X a * t2_XX b  +  t2_1Y a * t2_YX b  +  t2_1X b,

t2_XY = t2_XX a * t2_XY b  +  t2_XY a * t2_YY b,
t2_YY = t2_YX a * t2_XY b  +  t2_YY a * t2_YY b,
t2_1Y = t2_1X a * t2_XY b  +  t2_1Y a * t2_YY b  +  t2_1Y b
}

-- | Apply a 2D transformation to a 2D point, yielding a new 2D point.
transformP2 :: Transform2 -> Vector2 -> Vector2
transformP2 a (Vector2 x y) =
Vector2
{
v2x = t2_XX a * x + t2_YX a * y + t2_1X a,
v2y = t2_XY a * x + t2_YY a * y + t2_1Y a
}
```