{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ViewPatterns #-}

-- | Specialized and inlined @V2 Float@.

module Geomancy.Vec2
  ( Vec2
  , vec2
  , withVec2
  , pattern WithVec2
  , fromTuple

  , (^*)
  , (^/)
  , lerp

  , dot
  , normalize
  ) where

import Control.DeepSeq (NFData(rnf))
import Data.MonoTraversable (Element, MonoFunctor(..), MonoPointed(..))
import Data.VectorSpace (VectorSpace)
import Foreign (Storable(..))
import qualified Data.VectorSpace as VectorSpace

import Geomancy.Elementwise (Elementwise(..))
import Geomancy.Gl.Funs (GlModf(..), GlNearest)

data Vec2 = Vec2
  {-# UNPACK #-} !Float
  {-# UNPACK #-} !Float
  deriving (Vec2 -> Vec2 -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Vec2 -> Vec2 -> Bool
$c/= :: Vec2 -> Vec2 -> Bool
== :: Vec2 -> Vec2 -> Bool
$c== :: Vec2 -> Vec2 -> Bool
Eq, Eq Vec2
Vec2 -> Vec2 -> Bool
Vec2 -> Vec2 -> Ordering
Vec2 -> Vec2 -> Vec2
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Vec2 -> Vec2 -> Vec2
$cmin :: Vec2 -> Vec2 -> Vec2
max :: Vec2 -> Vec2 -> Vec2
$cmax :: Vec2 -> Vec2 -> Vec2
>= :: Vec2 -> Vec2 -> Bool
$c>= :: Vec2 -> Vec2 -> Bool
> :: Vec2 -> Vec2 -> Bool
$c> :: Vec2 -> Vec2 -> Bool
<= :: Vec2 -> Vec2 -> Bool
$c<= :: Vec2 -> Vec2 -> Bool
< :: Vec2 -> Vec2 -> Bool
$c< :: Vec2 -> Vec2 -> Bool
compare :: Vec2 -> Vec2 -> Ordering
$ccompare :: Vec2 -> Vec2 -> Ordering
Ord, Int -> Vec2 -> ShowS
[Vec2] -> ShowS
Vec2 -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Vec2] -> ShowS
$cshowList :: [Vec2] -> ShowS
show :: Vec2 -> String
$cshow :: Vec2 -> String
showsPrec :: Int -> Vec2 -> ShowS
$cshowsPrec :: Int -> Vec2 -> ShowS
Show)

{-# INLINE vec2 #-}
vec2 :: Float -> Float -> Vec2
vec2 :: Float -> Float -> Vec2
vec2 = Float -> Float -> Vec2
Vec2

{-# INLINE withVec2 #-}
withVec2
  :: Vec2
  -> (Float -> Float -> r)
  -> r
withVec2 :: forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 (Vec2 Float
a Float
b) Float -> Float -> r
f = Float -> Float -> r
f Float
a Float
b

pattern WithVec2 :: Float -> Float -> Vec2
pattern $mWithVec2 :: forall {r}. Vec2 -> (Float -> Float -> r) -> ((# #) -> r) -> r
WithVec2 a b <- ((`withVec2` (,)) -> (a, b))
{-# COMPLETE WithVec2 #-}

{-# INLINE fromTuple #-}
fromTuple :: (Float, Float) -> Vec2
fromTuple :: (Float, Float) -> Vec2
fromTuple (Float
x, Float
y) = Float -> Float -> Vec2
vec2 Float
x Float
y

instance NFData Vec2 where
  rnf :: Vec2 -> ()
rnf Vec2{} = ()

type instance Element Vec2 = Float

instance MonoFunctor Vec2 where
  {-# INLINE omap #-}
  omap :: (Element Vec2 -> Element Vec2) -> Vec2 -> Vec2
omap Element Vec2 -> Element Vec2
f Vec2
v =
    forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
v \Float
x Float
y ->
      Float -> Float -> Vec2
vec2 (Element Vec2 -> Element Vec2
f Float
x) (Element Vec2 -> Element Vec2
f Float
y)

instance MonoPointed Vec2 where
  opoint :: Element Vec2 -> Vec2
opoint Element Vec2
x = Float -> Float -> Vec2
vec2 Element Vec2
x Element Vec2
x

instance Elementwise Vec2 where
  {-# INLINE emap2 #-}
  emap2 :: (Element Vec2 -> Element Vec2 -> Element Vec2)
-> Vec2 -> Vec2 -> Vec2
emap2 Element Vec2 -> Element Vec2 -> Element Vec2
f Vec2
p0 Vec2
p1 =
    forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
p0 \Float
x0 Float
y0 ->
    forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
p1 \Float
x1 Float
y1 ->
      Float -> Float -> Vec2
vec2
        (Element Vec2 -> Element Vec2 -> Element Vec2
f Float
x0 Float
x1)
        (Element Vec2 -> Element Vec2 -> Element Vec2
f Float
y0 Float
y1)

  {-# INLINE emap3 #-}
  emap3 :: (Element Vec2 -> Element Vec2 -> Element Vec2 -> Element Vec2)
-> Vec2 -> Vec2 -> Vec2 -> Vec2
emap3 Element Vec2 -> Element Vec2 -> Element Vec2 -> Element Vec2
f Vec2
p0 Vec2
p1 Vec2
p2 =
    forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
p0 \Float
x0 Float
y0 ->
    forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
p1 \Float
x1 Float
y1 ->
    forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
p2 \Float
x2 Float
y2 ->
      Float -> Float -> Vec2
vec2
        (Element Vec2 -> Element Vec2 -> Element Vec2 -> Element Vec2
f Float
x0 Float
x1 Float
x2)
        (Element Vec2 -> Element Vec2 -> Element Vec2 -> Element Vec2
f Float
y0 Float
y1 Float
y2)

  {-# INLINE emap4 #-}
  emap4 :: (Element Vec2
 -> Element Vec2 -> Element Vec2 -> Element Vec2 -> Element Vec2)
-> Vec2 -> Vec2 -> Vec2 -> Vec2 -> Vec2
emap4 Element Vec2
-> Element Vec2 -> Element Vec2 -> Element Vec2 -> Element Vec2
f Vec2
p0 Vec2
p1 Vec2
p2 Vec2
p3 =
    forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
p0 \Float
x0 Float
y0 ->
    forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
p1 \Float
x1 Float
y1 ->
    forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
p2 \Float
x2 Float
y2 ->
    forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
p3 \Float
x3 Float
y3 ->
      Float -> Float -> Vec2
vec2
        (Element Vec2
-> Element Vec2 -> Element Vec2 -> Element Vec2 -> Element Vec2
f Float
x0 Float
x1 Float
x2 Float
x3)
        (Element Vec2
-> Element Vec2 -> Element Vec2 -> Element Vec2 -> Element Vec2
f Float
y0 Float
y1 Float
y2 Float
y3)

  {-# INLINE emap5 #-}
  emap5 :: (Element Vec2
 -> Element Vec2
 -> Element Vec2
 -> Element Vec2
 -> Element Vec2
 -> Element Vec2)
-> Vec2 -> Vec2 -> Vec2 -> Vec2 -> Vec2 -> Vec2
emap5 Element Vec2
-> Element Vec2
-> Element Vec2
-> Element Vec2
-> Element Vec2
-> Element Vec2
f Vec2
p0 Vec2
p1 Vec2
p2 Vec2
p3 Vec2
p4 =
    forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
p0 \Float
x0 Float
y0 ->
    forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
p1 \Float
x1 Float
y1 ->
    forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
p2 \Float
x2 Float
y2 ->
    forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
p3 \Float
x3 Float
y3 ->
    forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
p4 \Float
x4 Float
y4 ->
      Float -> Float -> Vec2
vec2
        (Element Vec2
-> Element Vec2
-> Element Vec2
-> Element Vec2
-> Element Vec2
-> Element Vec2
f Float
x0 Float
x1 Float
x2 Float
x3 Float
x4)
        (Element Vec2
-> Element Vec2
-> Element Vec2
-> Element Vec2
-> Element Vec2
-> Element Vec2
f Float
y0 Float
y1 Float
y2 Float
y3 Float
y4)

instance Num Vec2 where
  {-# INLINE (+) #-}
  Vec2 Float
l1 Float
l2 + :: Vec2 -> Vec2 -> Vec2
+ Vec2 Float
r1 Float
r2 =
    Float -> Float -> Vec2
Vec2
      (Float
l1 forall a. Num a => a -> a -> a
+ Float
r1)
      (Float
l2 forall a. Num a => a -> a -> a
+ Float
r2)

  {-# INLINE (-) #-}
  Vec2 Float
l1 Float
l2 - :: Vec2 -> Vec2 -> Vec2
- Vec2 Float
r1 Float
r2 =
    Float -> Float -> Vec2
Vec2
      (Float
l1 forall a. Num a => a -> a -> a
- Float
r1)
      (Float
l2 forall a. Num a => a -> a -> a
- Float
r2)

  {-# INLINE (*) #-}
  Vec2 Float
l1 Float
l2 * :: Vec2 -> Vec2 -> Vec2
* Vec2 Float
r1 Float
r2 =
    Float -> Float -> Vec2
Vec2
      (Float
l1 forall a. Num a => a -> a -> a
* Float
r1)
      (Float
l2 forall a. Num a => a -> a -> a
* Float
r2)

  {-# INLINE abs #-}
  abs :: Vec2 -> Vec2
abs (Vec2 Float
a Float
b) =
    Float -> Float -> Vec2
Vec2 (forall a. Num a => a -> a
abs Float
a) (forall a. Num a => a -> a
abs Float
b)

  {-# INLINE signum #-}
  signum :: Vec2 -> Vec2
signum (Vec2 Float
a Float
b) =
    Float -> Float -> Vec2
Vec2 (forall a. Num a => a -> a
signum Float
a) (forall a. Num a => a -> a
signum Float
b)

  {-# INLINE fromInteger #-}
  fromInteger :: Integer -> Vec2
fromInteger Integer
x = Float -> Float -> Vec2
Vec2 Float
x' Float
x'
    where
      x' :: Float
x' = forall a. Num a => Integer -> a
fromInteger Integer
x

instance Fractional Vec2 where
  {-# INLINE (/) #-}
  Vec2 Float
l1 Float
l2 / :: Vec2 -> Vec2 -> Vec2
/ Vec2 Float
r1 Float
r2 =
    Float -> Float -> Vec2
Vec2 (Float
l1 forall a. Fractional a => a -> a -> a
/ Float
r1) (Float
l2 forall a. Fractional a => a -> a -> a
/ Float
r2)

  {-# INLINE recip #-}
  recip :: Vec2 -> Vec2
recip (Vec2 Float
a Float
b) =
    Float -> Float -> Vec2
Vec2 (forall a. Fractional a => a -> a
recip Float
a) (forall a. Fractional a => a -> a
recip Float
b)

  {-# INLINE fromRational #-}
  fromRational :: Rational -> Vec2
fromRational Rational
x = Float -> Float -> Vec2
Vec2 Float
x' Float
x'
    where
      x' :: Float
x' = forall a. Fractional a => Rational -> a
fromRational Rational
x

instance Floating Vec2 where
  pi :: Vec2
pi = forall mono. MonoPointed mono => Element mono -> mono
opoint forall a. Floating a => a
pi

  exp :: Vec2 -> Vec2
exp = forall mono.
MonoFunctor mono =>
(Element mono -> Element mono) -> mono -> mono
omap forall a. Floating a => a -> a
exp
  log :: Vec2 -> Vec2
log = forall mono.
MonoFunctor mono =>
(Element mono -> Element mono) -> mono -> mono
omap forall a. Floating a => a -> a
log
  sqrt :: Vec2 -> Vec2
sqrt = forall mono.
MonoFunctor mono =>
(Element mono -> Element mono) -> mono -> mono
omap forall a. Floating a => a -> a
sqrt
  sin :: Vec2 -> Vec2
sin = forall mono.
MonoFunctor mono =>
(Element mono -> Element mono) -> mono -> mono
omap forall a. Floating a => a -> a
sin
  cos :: Vec2 -> Vec2
cos = forall mono.
MonoFunctor mono =>
(Element mono -> Element mono) -> mono -> mono
omap forall a. Floating a => a -> a
cos
  asin :: Vec2 -> Vec2
asin = forall mono.
MonoFunctor mono =>
(Element mono -> Element mono) -> mono -> mono
omap forall a. Floating a => a -> a
asin
  acos :: Vec2 -> Vec2
acos = forall mono.
MonoFunctor mono =>
(Element mono -> Element mono) -> mono -> mono
omap forall a. Floating a => a -> a
acos
  atan :: Vec2 -> Vec2
atan = forall mono.
MonoFunctor mono =>
(Element mono -> Element mono) -> mono -> mono
omap forall a. Floating a => a -> a
atan
  sinh :: Vec2 -> Vec2
sinh = forall mono.
MonoFunctor mono =>
(Element mono -> Element mono) -> mono -> mono
omap forall a. Floating a => a -> a
sinh
  cosh :: Vec2 -> Vec2
cosh = forall mono.
MonoFunctor mono =>
(Element mono -> Element mono) -> mono -> mono
omap forall a. Floating a => a -> a
cosh
  asinh :: Vec2 -> Vec2
asinh = forall mono.
MonoFunctor mono =>
(Element mono -> Element mono) -> mono -> mono
omap forall a. Floating a => a -> a
asinh
  acosh :: Vec2 -> Vec2
acosh = forall mono.
MonoFunctor mono =>
(Element mono -> Element mono) -> mono -> mono
omap forall a. Floating a => a -> a
acosh
  atanh :: Vec2 -> Vec2
atanh = forall mono.
MonoFunctor mono =>
(Element mono -> Element mono) -> mono -> mono
omap forall a. Floating a => a -> a
atanh

  ** :: Vec2 -> Vec2 -> Vec2
(**) = forall a.
Elementwise a =>
(Element a -> Element a -> Element a) -> a -> a -> a
emap2 forall a. Floating a => a -> a -> a
(**)

{-# INLINE (^*) #-}
(^*) :: Vec2 -> Float -> Vec2
Vec2 Float
a Float
b ^* :: Vec2 -> Float -> Vec2
^* Float
x =
  Float -> Float -> Vec2
Vec2
    (Float
a forall a. Num a => a -> a -> a
* Float
x)
    (Float
b forall a. Num a => a -> a -> a
* Float
x)

{-# INLINE (^/) #-}
(^/) :: Vec2 -> Float -> Vec2
Vec2 Float
a Float
b ^/ :: Vec2 -> Float -> Vec2
^/ Float
x =
  Float -> Float -> Vec2
Vec2
    (Float
a forall a. Fractional a => a -> a -> a
/ Float
x)
    (Float
b forall a. Fractional a => a -> a -> a
/ Float
x)

{-# INLINE lerp #-}
lerp :: Float -> Vec2 -> Vec2 -> Vec2
lerp :: Float -> Vec2 -> Vec2 -> Vec2
lerp Float
alpha Vec2
u Vec2
v = Vec2
u Vec2 -> Float -> Vec2
^* Float
alpha forall a. Num a => a -> a -> a
+ Vec2
v Vec2 -> Float -> Vec2
^* (Float
1 forall a. Num a => a -> a -> a
- Float
alpha)

{-# INLINE dot #-}
dot :: Vec2 -> Vec2 -> Float
dot :: Vec2 -> Vec2 -> Float
dot (Vec2 Float
l1 Float
l2) (Vec2 Float
r1 Float
r2) =
  Float
l1 forall a. Num a => a -> a -> a
* Float
r1 forall a. Num a => a -> a -> a
+ Float
l2 forall a. Num a => a -> a -> a
* Float
r2

{-# INLINE normalize #-}
normalize :: Vec2 -> Vec2
normalize :: Vec2 -> Vec2
normalize Vec2
v =
  if forall {a}. (Ord a, Fractional a) => a -> Bool
nearZero Float
q Bool -> Bool -> Bool
|| forall {a}. (Ord a, Fractional a) => a -> Bool
nearZero (Float
1 forall a. Num a => a -> a -> a
- Float
q) then
    Vec2
v
  else
    let
      Vec2 Float
x Float
y = Vec2
v
    in
      Float -> Float -> Vec2
Vec2 (Float
x forall a. Fractional a => a -> a -> a
/ Float
l) (Float
y forall a. Fractional a => a -> a -> a
/ Float
l)

  where
    q :: Float
q = Vec2 -> Vec2 -> Float
dot Vec2
v Vec2
v
    l :: Float
l = forall a. Floating a => a -> a
sqrt Float
q

    nearZero :: a -> Bool
nearZero a
a = forall a. Num a => a -> a
abs a
a forall a. Ord a => a -> a -> Bool
<= a
1e-6

instance Storable Vec2 where
  {-# INLINE sizeOf #-}
  sizeOf :: Vec2 -> Int
sizeOf Vec2
_ = Int
8

  {-# INLINE alignment #-}
  alignment :: Vec2 -> Int
alignment Vec2
_ = Int
8

  {-# INLINE poke #-}
  poke :: Ptr Vec2 -> Vec2 -> IO ()
poke Ptr Vec2
ptr Vec2
v4 =
    forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
v4 \Float
a Float
b -> do
      forall a b. Storable a => Ptr b -> Int -> a -> IO ()
pokeByteOff Ptr Vec2
ptr Int
0 Float
a
      forall a b. Storable a => Ptr b -> Int -> a -> IO ()
pokeByteOff Ptr Vec2
ptr Int
4 Float
b

  {-# INLINE peek #-}
  peek :: Ptr Vec2 -> IO Vec2
peek Ptr Vec2
ptr = Float -> Float -> Vec2
vec2
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a b. Storable a => Ptr b -> Int -> IO a
peekByteOff Ptr Vec2
ptr Int
0
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a b. Storable a => Ptr b -> Int -> IO a
peekByteOff Ptr Vec2
ptr Int
4

instance VectorSpace Vec2 Float where
  zeroVector :: Vec2
zeroVector = forall a. Elementwise a => Element a -> a
epoint Float
0

  {-# INLINE (*^) #-}
  Float
a *^ :: Float -> Vec2 -> Vec2
*^ Vec2
v = Vec2
v Vec2 -> Float -> Vec2
Geomancy.Vec2.^* Float
a

  {-# INLINE (^/) #-}
  Vec2
v ^/ :: Vec2 -> Float -> Vec2
^/ Float
a = Vec2
v Vec2 -> Float -> Vec2
Geomancy.Vec2.^/ Float
a

  {-# INLINE (^+^) #-}
  ^+^ :: Vec2 -> Vec2 -> Vec2
(^+^) = forall a.
Elementwise a =>
(Element a -> Element a -> Element a) -> a -> a -> a
emap2 forall a. Num a => a -> a -> a
(+)

  {-# INLINE (^-^) #-}
  ^-^ :: Vec2 -> Vec2 -> Vec2
(^-^) = forall a.
Elementwise a =>
(Element a -> Element a -> Element a) -> a -> a -> a
emap2 (-)

  {-# INLINE negateVector #-}
  negateVector :: Vec2 -> Vec2
negateVector = forall a. Elementwise a => (Element a -> Element a) -> a -> a
emap forall a. Num a => a -> a
negate

  {-# INLINE dot #-}
  dot :: Vec2 -> Vec2 -> Float
dot = Vec2 -> Vec2 -> Float
Geomancy.Vec2.dot

  {-# INLINE normalize #-}
  normalize :: Vec2 -> Vec2
normalize = Vec2 -> Vec2
Geomancy.Vec2.normalize

instance GlNearest Vec2

instance GlModf Vec2 Vec2 where
  glModf :: Vec2 -> (Vec2, Vec2)
glModf Vec2
v =
    forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
v \Float
vx Float
vy ->
      let
        (Integer
xi, Float
xf) = forall i f. GlModf i f => f -> (i, f)
glModf Float
vx
        (Integer
yi, Float
yf) = forall i f. GlModf i f => f -> (i, f)
glModf Float
vy
      in
        ( Float -> Float -> Vec2
vec2 (forall a. Num a => Integer -> a
fromInteger Integer
xi) (forall a. Num a => Integer -> a
fromInteger Integer
yi)
        , Float -> Float -> Vec2
vec2 Float
xf Float
yf
        )