{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UndecidableInstances #-}
module Data.Geometry.Vector.VectorFamily where
import Control.DeepSeq
import Control.Lens hiding (element)
import Data.Aeson
import qualified Data.Foldable as F
import qualified Data.List as L
import Data.Geometry.Vector.VectorFixed (C(..))
import qualified Data.Geometry.Vector.VectorFamilyPeano as Fam
import Data.Geometry.Vector.VectorFamilyPeano ( VectorFamily(..)
, VectorFamilyF
, ImplicitArity
)
import Data.Semigroup
import qualified Data.Vector.Fixed as V
import Data.Vector.Fixed.Cont (Peano)
import GHC.TypeLits
import Linear.Affine (Affine(..))
import Linear.Metric
import qualified Linear.V2 as L2
import qualified Linear.V3 as L3
import qualified Linear.V4 as L4
import Linear.Vector
newtype Vector (d :: Nat) (r :: *) = MKVector { _unV :: VectorFamily (Peano d) r }
type instance V.Dim (Vector d) = Fam.FromPeano (Peano d)
type instance Index (Vector d r) = Int
type instance IxValue (Vector d r) = r
unV :: Lens (Vector d r) (Vector d s) (VectorFamily (Peano d) r) (VectorFamily (Peano d) s)
unV = lens _unV (const MKVector)
{-# INLINE unV #-}
type Arity d = (ImplicitArity (Peano d), KnownNat d)
deriving instance (Eq r, Arity d) => Eq (Vector d r)
deriving instance (Ord r, Arity d) => Ord (Vector d r)
deriving instance Arity d => Functor (Vector d)
deriving instance Arity d => Foldable (Vector d)
deriving instance Arity d => Traversable (Vector d)
deriving instance Arity d => Applicative (Vector d)
deriving instance Arity d => Additive (Vector d)
deriving instance Arity d => Metric (Vector d)
deriving instance Arity d => Affine (Vector d)
instance Arity d => Ixed (Vector d r) where
ix = element'
instance Arity d => V.Vector (Vector d) r where
construct = MKVector <$> V.construct
inspect = V.inspect . _unV
basicIndex = V.basicIndex . _unV
instance (Arity d, Show r) => Show (Vector d r) where
show v = mconcat [ "Vector", show $ F.length v , " "
, show $ F.toList v ]
deriving instance (FromJSON r, Arity d) => FromJSON (Vector d r)
instance (ToJSON r, Arity d) => ToJSON (Vector d r) where
toJSON = toJSON . _unV
toEncoding = toEncoding . _unV
deriving instance (NFData r, Arity d) => NFData (Vector d r)
pattern Vector :: VectorFamilyF (Peano d) r -> Vector d r
pattern Vector v = MKVector (VectorFamily v)
pattern Vector1 :: r -> Vector 1 r
pattern Vector1 x = (Vector (Identity x))
pattern Vector2 :: r -> r -> Vector 2 r
pattern Vector2 x y = (Vector (L2.V2 x y))
pattern Vector3 :: r -> r -> r -> Vector 3 r
pattern Vector3 x y z = (Vector (L3.V3 x y z))
pattern Vector4 :: r -> r -> r -> r -> Vector 4 r
pattern Vector4 x y z w = (Vector (L4.V4 x y z w))
vectorFromList :: Arity d => [r] -> Maybe (Vector d r)
vectorFromList = V.fromListM
vectorFromListUnsafe :: Arity d => [r] -> Vector d r
vectorFromListUnsafe = V.fromList
destruct :: (Arity d, Arity (d + 1))
=> Vector (d + 1) r -> (r, Vector d r)
destruct v = (head $ F.toList v, vectorFromListUnsafe . tail $ F.toList v)
element :: forall proxy i d r. (Arity d, KnownNat i, (i + 1) <= d)
=> proxy i -> Lens' (Vector d r) r
element _ = singular . element' . fromInteger $ natVal (C :: C i)
{-# INLINE element #-}
element' :: forall d r. Arity d => Int -> Traversal' (Vector d r) r
element' i = unV.(e (C :: C d) i)
where
e :: Arity d => proxy d -> Int -> Traversal' (VectorFamily (Peano d) r) r
e _ = Fam.element'
{-# INLINE element' #-}
snoc :: (Arity (d + 1), Arity d) => Vector d r -> r -> Vector (d + 1) r
snoc v x = vectorFromListUnsafe . (++ [x]) $ F.toList v
init :: (Arity d, Arity (d + 1)) => Vector (d + 1) r -> Vector d r
init = vectorFromListUnsafe . L.init . F.toList
last :: forall d r. (KnownNat d, Arity (d + 1)) => Vector (d + 1) r -> r
last = view $ element (C :: C d)
prefix :: forall i d r. (Arity d, Arity i, i <= d)
=> Vector d r -> Vector i r
prefix = let i = fromInteger . natVal $ (C :: C i)
in vectorFromListUnsafe . take i . F.toList
cross :: Num r => Vector 3 r -> Vector 3 r -> Vector 3 r
(Vector u) `cross` (Vector v) = Vector $ u `L3.cross` v