packages feed

apecs-0.1.0.0: src/Apecs/Vector.hs

-- | A lightweight version of Edward Kmett's linear, included for convenience' sake

{-# LANGUAGE TypeFamilyDependencies, ScopedTypeVariables, FlexibleContexts #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}

module Apecs.Vector where

import Control.Applicative

{-# INLINE dot #-}
dot :: (Num (v a), Num a, Foldable v) => v a -> v a -> a
dot a b = sum $ a * b

{-# INLINE vlength #-}
vlength :: (Foldable v, Num (v a), Floating a) => v a -> a
vlength a = sqrt (dot a a)

{-# INLINE setLength #-}
setLength :: (Num (f b), Functor f, Floating b, Foldable f) => b -> f b -> f b
setLength r v = let l = vlength v in fmap ((*r).(/l)) v

{-# INLINE normalize #-}
normalize :: (Num (v b), Floating b, Foldable v, Functor f) => v b -> f b -> f b
normalize v = fmap (/vlength v)


-- V2
data V2 a = V2 !a !a deriving (Eq, Show)

instance Functor V2 where
  {-# INLINE fmap #-}
  fmap f (V2 a b) = V2 (f a) (f b)

instance Applicative V2 where
  {-# INLINE (<*>) #-}
  V2 fx fy <*> V2 x y = V2 (fx x) (fy y)
  {-# INLINE pure #-}
  pure x = V2 x x

instance Num a => Num (V2 a) where
  (+) = liftA2 (+)
  {-# INLINE (+) #-}
  (-) = liftA2 (-)
  {-# INLINE (-) #-}
  (*) = liftA2 (*)
  {-# INLINE (*) #-}
  negate = fmap negate
  {-# INLINE negate #-}
  abs = fmap abs
  {-# INLINE abs #-}
  signum = fmap signum
  {-# INLINE signum #-}
  fromInteger = pure . fromInteger
  {-# INLINE fromInteger #-}

instance Fractional a => Fractional (V2 a) where
  (/) = liftA2 (/)
  {-# INLINE (/) #-}
  fromRational = pure . fromRational
  {-# INLINE fromRational #-}

instance Foldable V2 where
  foldMap f (V2 x y)    = f x `mappend` f y
  foldr f seed (V2 x y) = f x (f y seed)
  foldr1 f (V2 x y)     = f x y
  foldl f seed (V2 x y) = f (f seed x) y
  foldl1 f (V2 x y)     = f x y
  null _                = False
  length _              = 2
  elem a (V2 x y)       = x == a || y == a
  minimum (V2 x y)      = min x y
  maximum (V2 x y)      = max x y
  sum (V2 x y)          = x + y
  product (V2 x y)      = x * y
  {-# INLINE foldMap #-}
  {-# INLINE foldr #-}
  {-# INLINE foldr1 #-}
  {-# INLINE foldl #-}
  {-# INLINE foldl1 #-}
  {-# INLINE null #-}
  {-# INLINE length #-}
  {-# INLINE elem #-}
  {-# INLINE minimum #-}
  {-# INLINE maximum #-}
  {-# INLINE product #-}
  {-# INLINE sum #-}

-- V3
data V3 a = V3 !a !a !a deriving (Eq, Show)

instance Functor V3 where
  {-# INLINE fmap #-}
  fmap f (V3 a b c) = V3 (f a) (f b) (f c)

instance Applicative V3 where
  {-# INLINE (<*>) #-}
  V3 fx fy fz <*> V3 x y z = V3 (fx x) (fy y) (fz z)
  {-# INLINE pure #-}
  pure x = V3 x x x

instance Num a => Num (V3 a) where
  (+) = liftA2 (+)
  {-# INLINE (+) #-}
  (-) = liftA2 (-)
  {-# INLINE (-) #-}
  (*) = liftA2 (*)
  {-# INLINE (*) #-}
  negate = fmap negate
  {-# INLINE negate #-}
  abs = fmap abs
  {-# INLINE abs #-}
  signum = fmap signum
  {-# INLINE signum #-}
  fromInteger = pure . fromInteger
  {-# INLINE fromInteger #-}

instance Fractional a => Fractional (V3 a) where
  (/) = liftA2 (/)
  {-# INLINE (/) #-}
  fromRational = pure . fromRational
  {-# INLINE fromRational #-}

instance Foldable V3 where
  foldMap f (V3 x y z)    = f x `mappend` f y `mappend` f z
  foldr f seed (V3 x y z) = f x (f y (f z seed))
  foldr1 f (V3 x y z)     = f x (f y z)
  foldl f seed (V3 x y z) = f (f (f seed x) y) z
  foldl1 f (V3 x y z)     = f (f x y) z
  null _                  = False
  length _                = 3
  elem a (V3 x y z)       = x == a || y == a || z == a
  minimum (V3 x y z)      = min (min x y) z
  maximum (V3 x y z)      = max (max x y) z
  sum (V3 x y z)          = x + y + z
  product (V3 x y z)      = x * y * z
  {-# INLINE foldMap #-}
  {-# INLINE foldr #-}
  {-# INLINE foldr1 #-}
  {-# INLINE foldl #-}
  {-# INLINE foldl1 #-}
  {-# INLINE null #-}
  {-# INLINE length #-}
  {-# INLINE elem #-}
  {-# INLINE minimum #-}
  {-# INLINE maximum #-}
  {-# INLINE product #-}
  {-# INLINE sum #-}

{-# INLINE outer #-}
outer :: Num a => V3 a -> V3 a -> V3 a
V3 a b c `outer` V3 d e f = V3 (b*f - e*c) (c*d - a*f) (a*e - b*d)