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

-- | Specialized and inlined @V2 Word32@.

module Geomancy.UVec2
  ( UVec2
  , uvec2
  , withUVec2
  , pattern WithUVec2
  , fromTuple
  ) where

import Control.DeepSeq (NFData(rnf))
import Data.Word (Word32)
import Foreign (Storable(..))

data UVec2 = UVec2
  {-# UNPACK #-} !Word32
  {-# UNPACK #-} !Word32
  deriving (UVec2 -> UVec2 -> Bool
(UVec2 -> UVec2 -> Bool) -> (UVec2 -> UVec2 -> Bool) -> Eq UVec2
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: UVec2 -> UVec2 -> Bool
$c/= :: UVec2 -> UVec2 -> Bool
== :: UVec2 -> UVec2 -> Bool
$c== :: UVec2 -> UVec2 -> Bool
Eq, Eq UVec2
Eq UVec2
-> (UVec2 -> UVec2 -> Ordering)
-> (UVec2 -> UVec2 -> Bool)
-> (UVec2 -> UVec2 -> Bool)
-> (UVec2 -> UVec2 -> Bool)
-> (UVec2 -> UVec2 -> Bool)
-> (UVec2 -> UVec2 -> UVec2)
-> (UVec2 -> UVec2 -> UVec2)
-> Ord UVec2
UVec2 -> UVec2 -> Bool
UVec2 -> UVec2 -> Ordering
UVec2 -> UVec2 -> UVec2
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 :: UVec2 -> UVec2 -> UVec2
$cmin :: UVec2 -> UVec2 -> UVec2
max :: UVec2 -> UVec2 -> UVec2
$cmax :: UVec2 -> UVec2 -> UVec2
>= :: UVec2 -> UVec2 -> Bool
$c>= :: UVec2 -> UVec2 -> Bool
> :: UVec2 -> UVec2 -> Bool
$c> :: UVec2 -> UVec2 -> Bool
<= :: UVec2 -> UVec2 -> Bool
$c<= :: UVec2 -> UVec2 -> Bool
< :: UVec2 -> UVec2 -> Bool
$c< :: UVec2 -> UVec2 -> Bool
compare :: UVec2 -> UVec2 -> Ordering
$ccompare :: UVec2 -> UVec2 -> Ordering
$cp1Ord :: Eq UVec2
Ord, Int -> UVec2 -> ShowS
[UVec2] -> ShowS
UVec2 -> String
(Int -> UVec2 -> ShowS)
-> (UVec2 -> String) -> ([UVec2] -> ShowS) -> Show UVec2
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [UVec2] -> ShowS
$cshowList :: [UVec2] -> ShowS
show :: UVec2 -> String
$cshow :: UVec2 -> String
showsPrec :: Int -> UVec2 -> ShowS
$cshowsPrec :: Int -> UVec2 -> ShowS
Show)

{-# INLINE uvec2 #-}
uvec2 :: Word32 -> Word32 -> UVec2
uvec2 :: Word32 -> Word32 -> UVec2
uvec2 = Word32 -> Word32 -> UVec2
UVec2

{-# INLINE withUVec2 #-}
withUVec2
  :: UVec2
  -> (Word32 -> Word32 -> r)
  -> r
withUVec2 :: UVec2 -> (Word32 -> Word32 -> r) -> r
withUVec2 (UVec2 Word32
a Word32
b) Word32 -> Word32 -> r
f = Word32 -> Word32 -> r
f Word32
a Word32
b

pattern WithUVec2 :: Word32 -> Word32 -> UVec2
pattern $mWithUVec2 :: forall r. UVec2 -> (Word32 -> Word32 -> r) -> (Void# -> r) -> r
WithUVec2 a b <- ((`withUVec2` (,)) -> (a, b))
{-# COMPLETE WithUVec2 #-}

{-# INLINE fromTuple #-}
fromTuple :: (Word32, Word32) -> UVec2
fromTuple :: (Word32, Word32) -> UVec2
fromTuple (Word32
x, Word32
y) = Word32 -> Word32 -> UVec2
uvec2 Word32
x Word32
y

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

-- XXX: That's one nasty instance...
instance Num UVec2 where
  {-# INLINE (+) #-}
  UVec2 Word32
l1 Word32
l2 + :: UVec2 -> UVec2 -> UVec2
+ UVec2 Word32
r1 Word32
r2 =
    Word32 -> Word32 -> UVec2
UVec2
      (Word32
l1 Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ Word32
r1)
      (Word32
l2 Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ Word32
r2)

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

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

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

  {-# INLINE signum #-}
  signum :: UVec2 -> UVec2
signum UVec2
v2 = UVec2 -> (Word32 -> Word32 -> UVec2) -> UVec2
forall r. UVec2 -> (Word32 -> Word32 -> r) -> r
withUVec2 UVec2
v2 \Word32
a Word32
b ->
    Word32 -> Word32 -> UVec2
uvec2 (Word32 -> Word32
forall a. Num a => a -> a
signum Word32
a) (Word32 -> Word32
forall a. Num a => a -> a
signum Word32
b)

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

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

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

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

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