{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UndecidableInstances #-}
module Data.Geometry.Vector.VectorFixed where
import Control.DeepSeq
import Control.Lens hiding (element)
import Data.Aeson
import qualified Data.Foldable as F
import Data.Proxy
import qualified Data.Vector.Fixed as V
import Data.Vector.Fixed (Arity)
import Data.Vector.Fixed.Boxed
import Data.Vector.Fixed.Cont (Peano, PeanoNum(..))
import GHC.Generics (Generic)
import GHC.TypeLits
import Linear.Affine (Affine(..))
import Linear.Metric
import qualified Linear.V2 as L2
import qualified Linear.V3 as L3
import Linear.Vector
data C (n :: Nat) = C deriving (Show,Read,Eq,Ord)
newtype Vector (d :: Nat) (r :: *) = Vector { _unV :: Vec d r }
deriving (Generic)
unV :: Lens' (Vector d r) (Vec d r)
unV = lens _unV (const Vector)
element :: forall proxy i d r. (Arity d, Arity i, (i + 1) <= d)
=> proxy i -> Lens' (Vector d r) r
element _ = V.elementTy (Proxy :: Proxy i)
element' :: forall d r. Arity d => Int -> Traversal' (Vector d r) r
element' i f v
| 0 <= i && i < fromInteger (natVal (C :: C d)) = f (v V.! i)
<&> \a -> (v&V.element i .~ a)
| otherwise = pure v
vectorFromList :: Arity d => [a] -> Maybe (Vector d a)
vectorFromList = fmap Vector . V.fromListM
vectorFromListUnsafe :: Arity d => [a] -> Vector d a
vectorFromListUnsafe = Vector . V.fromList
instance (Show r, Arity d) => Show (Vector d r) where
show (Vector v) = mconcat [ "Vector", show $ V.length v , " "
, show $ F.toList v
]
deriving instance (Eq r, Arity d) => Eq (Vector d r)
deriving instance (Ord r, Arity d) => Ord (Vector d r)
instance Arity d => Functor (Vector d) where
fmap f (Vector v) = Vector $ fmap f v
deriving instance Arity d => Foldable (Vector d)
deriving instance Arity d => Applicative (Vector d)
instance Arity d => Traversable (Vector d) where
traverse f (Vector v) = Vector <$> traverse f v
deriving instance (Arity d, NFData r) => NFData (Vector d r)
instance Arity d => Additive (Vector d) where
zero = pure 0
(Vector u) ^+^ (Vector v) = Vector $ V.zipWith (+) u v
instance Arity d => Affine (Vector d) where
type Diff (Vector d) = Vector d
u .-. v = u ^-^ v
p .+^ v = p ^+^ v
instance Arity d => Metric (Vector d)
type instance V.Dim (Vector d) = d
instance Arity d => V.Vector (Vector d) r where
construct = Vector <$> V.construct
inspect = V.inspect . _unV
basicIndex = V.basicIndex . _unV
instance (FromJSON r, Arity d, KnownNat d) => FromJSON (Vector d r) where
parseJSON y = parseJSON y >>= \xs -> case vectorFromList xs of
Nothing -> fail . mconcat $
[ "FromJSON (Vector d a), wrong number of elements. Expected "
, show $ natVal (Proxy :: Proxy d)
, " elements but found "
, show $ length xs
, "."
]
Just v -> pure v
instance (ToJSON r, Arity d) => ToJSON (Vector d r) where
toJSON = toJSON . F.toList
toEncoding = toEncoding . F.toList
destruct :: (Arity d, Arity (d + 1), 1 <= (d + 1))
=> Vector (d + 1) r -> (r, Vector d r)
destruct (Vector v) = (V.head v, Vector $ V.tail v)
cross :: Num r => Vector 3 r -> Vector 3 r -> Vector 3 r
u `cross` v = fromV3 $ (toV3 u) `L3.cross` (toV3 v)
toV2 :: Vector 2 a -> L2.V2 a
toV2 ~(Vector2 a b) = L2.V2 a b
toV3 :: Vector 3 a -> L3.V3 a
toV3 ~(Vector3 a b c) = L3.V3 a b c
fromV3 :: L3.V3 a -> Vector 3 a
fromV3 (L3.V3 a b c) = v3 a b c
snoc :: (Arity (d + 1), Arity d) => Vector d r -> r -> Vector (d + 1) r
snoc = flip V.snoc
init :: (Arity d, Arity (d + 1)) => Vector (d + 1) r -> Vector d r
init = Vector . V.reverse . V.tail . V.reverse . _unV
last :: forall d r. (Arity d, Arity (d + 1)) => Vector (d + 1) r -> r
last = view $ element (Proxy :: Proxy d)
prefix :: forall i d r. (Arity d, Arity i, i <= d)
=> Vector d r -> Vector i r
prefix = let i = fromInteger . natVal $ (Proxy :: Proxy i)
in V.fromList . take i . V.toList
v2 :: r -> r -> Vector 2 r
v2 a b = Vector $ V.mk2 a b
v3 :: r -> r -> r -> Vector 3 r
v3 a b c = Vector $ V.mk3 a b c
_unV2 :: Vector 2 r -> (r,r)
_unV2 v = let [x,y] = V.toList v in (x,y)
_unV3 :: Vector 3 r -> (r,r,r)
_unV3 v = let [x,y,z] = V.toList v in (x,y,z)
pattern Vector2 :: r -> r -> Vector 2 r
pattern Vector2 x y <- (_unV2 -> (x,y))
where
Vector2 x y = v2 x y
{-# COMPLETE Vector2 #-}
pattern Vector3 :: r -> r -> r -> Vector 3 r
pattern Vector3 x y z <- (_unV3 -> (x,y,z))
where
Vector3 x y z = v3 x y z
{-# COMPLETE Vector3 #-}
pattern Vector4 :: r -> r -> r -> r -> Vector 4 r
pattern Vector4 x y z a <- (V.toList -> [x,y,z,a])
where
Vector4 x y z a = V.mk4 x y z a
{-# COMPLETE Vector4 #-}