{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE DerivingStrategies #-}

-- | Specialized and inlined @V3 Float@.

module Geomancy.Vec3
  ( Vec3
  , vec3
  , withVec3
  , pattern WithVec3
  , fromVec2
  , fromTuple

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

  , cross
  , dot
  , normalize

  , Packed(..)
  , packed

  , emap2
  , emap3
  , emap4
  ) where

import Control.DeepSeq (NFData(rnf))
import Data.Coerce (Coercible, coerce)
import Data.MonoTraversable (Element, MonoFunctor(..), MonoPointed(..))
import Data.VectorSpace (VectorSpace)
import Foreign (Storable(..), castPtr)
import Foreign.Ptr.Diff (peekDiffOff, pokeDiffOff)
import qualified Data.VectorSpace as VectorSpace

import Geomancy.Elementwise (Elementwise(..))
import Geomancy.Gl.Block (Block(..))
import Geomancy.Gl.Funs (GlModf(..), GlNearest)
import Geomancy.Vec2 (Vec2, withVec2)

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

{-# INLINE vec3 #-}
vec3 :: Float -> Float -> Float -> Vec3
vec3 :: Float -> Float -> Float -> Vec3
vec3 = Float -> Float -> Float -> Vec3
Vec3

{-# INLINE withVec3 #-}
withVec3
  :: Vec3
  -> (Float -> Float -> Float -> r)
  -> r
withVec3 :: forall r. Vec3 -> (Float -> Float -> Float -> r) -> r
withVec3 (Vec3 Float
a Float
b Float
c) Float -> Float -> Float -> r
f = Float -> Float -> Float -> r
f Float
a Float
b Float
c

pattern WithVec3 :: Float -> Float -> Float -> Vec3
pattern $mWithVec3 :: forall {r}.
Vec3 -> (Float -> Float -> Float -> r) -> ((# #) -> r) -> r
WithVec3 a b c <- ((`withVec3` (,,)) -> (a, b, c))
{-# COMPLETE WithVec3 #-}

{-# INLINE fromVec2 #-}
fromVec2 :: Coercible Vec3 a => Vec2 -> Float -> a
fromVec2 :: forall a. Coercible Vec3 a => Vec2 -> Float -> a
fromVec2 Vec2
xy Float
z =
  forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
xy \Float
x Float
y ->
    coerce :: forall a b. Coercible a b => a -> b
coerce (Float -> Float -> Float -> Vec3
vec3 Float
x Float
y Float
z)

{-# INLINE fromTuple #-}
fromTuple :: Coercible Vec3 a => (Float, Float, Float) -> a
fromTuple :: forall a. Coercible Vec3 a => (Float, Float, Float) -> a
fromTuple (Float
x, Float
y, Float
z) = coerce :: forall a b. Coercible a b => a -> b
coerce (Float -> Float -> Float -> Vec3
vec3 Float
x Float
y Float
z)

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

type instance Element Vec3 = Float

instance MonoFunctor Vec3 where
  {-# INLINE omap #-}
  omap :: (Element Vec3 -> Element Vec3) -> Vec3 -> Vec3
omap Element Vec3 -> Element Vec3
f Vec3
v =
    forall r. Vec3 -> (Float -> Float -> Float -> r) -> r
withVec3 Vec3
v \Float
x Float
y Float
z ->
      Float -> Float -> Float -> Vec3
vec3 (Element Vec3 -> Element Vec3
f Float
x) (Element Vec3 -> Element Vec3
f Float
y) (Element Vec3 -> Element Vec3
f Float
z)

instance MonoPointed Vec3 where
  opoint :: Element Vec3 -> Vec3
opoint Element Vec3
x = Float -> Float -> Float -> Vec3
vec3 Element Vec3
x Element Vec3
x Element Vec3
x

instance Elementwise Vec3 where
  {-# INLINE emap2 #-}
  emap2 :: (Element Vec3 -> Element Vec3 -> Element Vec3)
-> Vec3 -> Vec3 -> Vec3
emap2 Element Vec3 -> Element Vec3 -> Element Vec3
f Vec3
p0 Vec3
p1 =
    forall r. Vec3 -> (Float -> Float -> Float -> r) -> r
withVec3 Vec3
p0 \Float
x0 Float
y0 Float
z0 ->
    forall r. Vec3 -> (Float -> Float -> Float -> r) -> r
withVec3 Vec3
p1 \Float
x1 Float
y1 Float
z1 ->
      Float -> Float -> Float -> Vec3
vec3
        (Element Vec3 -> Element Vec3 -> Element Vec3
f Float
x0 Float
x1)
        (Element Vec3 -> Element Vec3 -> Element Vec3
f Float
y0 Float
y1)
        (Element Vec3 -> Element Vec3 -> Element Vec3
f Float
z0 Float
z1)

  {-# INLINE emap3 #-}
  emap3 :: (Element Vec3 -> Element Vec3 -> Element Vec3 -> Element Vec3)
-> Vec3 -> Vec3 -> Vec3 -> Vec3
emap3 Element Vec3 -> Element Vec3 -> Element Vec3 -> Element Vec3
f Vec3
p0 Vec3
p1 Vec3
p2 =
    forall r. Vec3 -> (Float -> Float -> Float -> r) -> r
withVec3 Vec3
p0 \Float
x0 Float
y0 Float
z0 ->
    forall r. Vec3 -> (Float -> Float -> Float -> r) -> r
withVec3 Vec3
p1 \Float
x1 Float
y1 Float
z1 ->
    forall r. Vec3 -> (Float -> Float -> Float -> r) -> r
withVec3 Vec3
p2 \Float
x2 Float
y2 Float
z2 ->
      Float -> Float -> Float -> Vec3
vec3
        (Element Vec3 -> Element Vec3 -> Element Vec3 -> Element Vec3
f Float
x0 Float
x1 Float
x2)
        (Element Vec3 -> Element Vec3 -> Element Vec3 -> Element Vec3
f Float
y0 Float
y1 Float
y2)
        (Element Vec3 -> Element Vec3 -> Element Vec3 -> Element Vec3
f Float
z0 Float
z1 Float
z2)

  {-# INLINE emap4 #-}
  emap4 :: (Element Vec3
 -> Element Vec3 -> Element Vec3 -> Element Vec3 -> Element Vec3)
-> Vec3 -> Vec3 -> Vec3 -> Vec3 -> Vec3
emap4 Element Vec3
-> Element Vec3 -> Element Vec3 -> Element Vec3 -> Element Vec3
f Vec3
p0 Vec3
p1 Vec3
p2 Vec3
p3 =
    forall r. Vec3 -> (Float -> Float -> Float -> r) -> r
withVec3 Vec3
p0 \Float
x0 Float
y0 Float
z0 ->
    forall r. Vec3 -> (Float -> Float -> Float -> r) -> r
withVec3 Vec3
p1 \Float
x1 Float
y1 Float
z1 ->
    forall r. Vec3 -> (Float -> Float -> Float -> r) -> r
withVec3 Vec3
p2 \Float
x2 Float
y2 Float
z2 ->
    forall r. Vec3 -> (Float -> Float -> Float -> r) -> r
withVec3 Vec3
p3 \Float
x3 Float
y3 Float
z3 ->
      Float -> Float -> Float -> Vec3
vec3
        (Element Vec3
-> Element Vec3 -> Element Vec3 -> Element Vec3 -> Element Vec3
f Float
x0 Float
x1 Float
x2 Float
x3)
        (Element Vec3
-> Element Vec3 -> Element Vec3 -> Element Vec3 -> Element Vec3
f Float
y0 Float
y1 Float
y2 Float
y3)
        (Element Vec3
-> Element Vec3 -> Element Vec3 -> Element Vec3 -> Element Vec3
f Float
z0 Float
z1 Float
z2 Float
z3)

  {-# INLINE emap5 #-}
  emap5 :: (Element Vec3
 -> Element Vec3
 -> Element Vec3
 -> Element Vec3
 -> Element Vec3
 -> Element Vec3)
-> Vec3 -> Vec3 -> Vec3 -> Vec3 -> Vec3 -> Vec3
emap5 Element Vec3
-> Element Vec3
-> Element Vec3
-> Element Vec3
-> Element Vec3
-> Element Vec3
f Vec3
p0 Vec3
p1 Vec3
p2 Vec3
p3 Vec3
p4 =
    forall r. Vec3 -> (Float -> Float -> Float -> r) -> r
withVec3 Vec3
p0 \Float
x0 Float
y0 Float
z0 ->
    forall r. Vec3 -> (Float -> Float -> Float -> r) -> r
withVec3 Vec3
p1 \Float
x1 Float
y1 Float
z1 ->
    forall r. Vec3 -> (Float -> Float -> Float -> r) -> r
withVec3 Vec3
p2 \Float
x2 Float
y2 Float
z2 ->
    forall r. Vec3 -> (Float -> Float -> Float -> r) -> r
withVec3 Vec3
p3 \Float
x3 Float
y3 Float
z3 ->
    forall r. Vec3 -> (Float -> Float -> Float -> r) -> r
withVec3 Vec3
p4 \Float
x4 Float
y4 Float
z4 ->
      Float -> Float -> Float -> Vec3
vec3
        (Element Vec3
-> Element Vec3
-> Element Vec3
-> Element Vec3
-> Element Vec3
-> Element Vec3
f Float
x0 Float
x1 Float
x2 Float
x3 Float
x4)
        (Element Vec3
-> Element Vec3
-> Element Vec3
-> Element Vec3
-> Element Vec3
-> Element Vec3
f Float
y0 Float
y1 Float
y2 Float
y3 Float
y4)
        (Element Vec3
-> Element Vec3
-> Element Vec3
-> Element Vec3
-> Element Vec3
-> Element Vec3
f Float
z0 Float
z1 Float
z2 Float
z3 Float
z4)

instance Num Vec3 where
  {-# INLINE (+) #-}
  Vec3 Float
a Float
b Float
c + :: Vec3 -> Vec3 -> Vec3
+ Vec3 Float
d Float
e Float
f =
    Float -> Float -> Float -> Vec3
Vec3
      (Float
a forall a. Num a => a -> a -> a
+ Float
d)
      (Float
b forall a. Num a => a -> a -> a
+ Float
e)
      (Float
c forall a. Num a => a -> a -> a
+ Float
f)

  {-# INLINE (-) #-}
  Vec3 Float
a Float
b Float
c - :: Vec3 -> Vec3 -> Vec3
- Vec3 Float
d Float
e Float
f =
    Float -> Float -> Float -> Vec3
Vec3
      (Float
a forall a. Num a => a -> a -> a
- Float
d)
      (Float
b forall a. Num a => a -> a -> a
- Float
e)
      (Float
c forall a. Num a => a -> a -> a
- Float
f)

  {-# INLINE (*) #-}
  Vec3 Float
a Float
b Float
c * :: Vec3 -> Vec3 -> Vec3
* Vec3 Float
d Float
e Float
f =
    Float -> Float -> Float -> Vec3
Vec3
      (Float
a forall a. Num a => a -> a -> a
* Float
d)
      (Float
b forall a. Num a => a -> a -> a
* Float
e)
      (Float
c forall a. Num a => a -> a -> a
* Float
f)

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

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

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

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

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

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

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

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

  Vec3
a ** :: Vec3 -> Vec3 -> Vec3
** Vec3
b =
    forall r. Vec3 -> (Float -> Float -> Float -> r) -> r
withVec3 Vec3
a \Float
ax Float
ay Float
az ->
    forall r. Vec3 -> (Float -> Float -> Float -> r) -> r
withVec3 Vec3
b \Float
bx Float
by Float
bz ->
      Float -> Float -> Float -> Vec3
vec3
        (Float
ax forall a. Floating a => a -> a -> a
** Float
bx)
        (Float
ay forall a. Floating a => a -> a -> a
** Float
by)
        (Float
az forall a. Floating a => a -> a -> a
** Float
bz)

{-
  XXX: GPU layouts call for some padding.

  Maybe it would be worth it to flip the sizeOf-s.
-}
instance Storable Vec3 where
  {-# INLINE sizeOf #-}
  sizeOf :: Vec3 -> Int
sizeOf Vec3
_ = Int
16

  {-# INLINE alignment #-}
  alignment :: Vec3 -> Int
alignment Vec3
_ = Int
4

  {-# INLINE poke #-}
  poke :: Ptr Vec3 -> Vec3 -> IO ()
poke Ptr Vec3
ptr Vec3
v3 =
    forall r. Vec3 -> (Float -> Float -> Float -> r) -> r
withVec3 Vec3
v3 \Float
a Float
b Float
c -> do
      forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr Float
ptr' Float
a
      forall a. Storable a => Ptr a -> Int -> a -> IO ()
pokeElemOff Ptr Float
ptr' Int
1 Float
b
      forall a. Storable a => Ptr a -> Int -> a -> IO ()
pokeElemOff Ptr Float
ptr' Int
2 Float
c
      forall a. Storable a => Ptr a -> Int -> a -> IO ()
pokeElemOff Ptr Float
ptr' Int
3 (Float
1.0 :: Float)
    where
      ptr' :: Ptr Float
ptr' = forall a b. Ptr a -> Ptr b
castPtr Ptr Vec3
ptr

  {-# INLINE peek #-}
  peek :: Ptr Vec3 -> IO Vec3
peek Ptr Vec3
ptr =
    Float -> Float -> Float -> Vec3
vec3 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Storable a => Ptr a -> IO a
peek Ptr Float
ptr' forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Float
ptr' Int
1 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Float
ptr' Int
2
    where
      ptr' :: Ptr Float
ptr' = forall a b. Ptr a -> Ptr b
castPtr Ptr Vec3
ptr

instance Block Vec3 where
  sizeOfPacked :: forall (proxy :: * -> *). proxy Vec3 -> Int
sizeOfPacked proxy Vec3
_  = Int
12
  alignment140 :: forall (proxy :: * -> *). proxy Vec3 -> Int
alignment140 proxy Vec3
_  = Int
16
  sizeOf140 :: forall (proxy :: * -> *). proxy Vec3 -> Int
sizeOf140 proxy Vec3
_     = Int
16
  alignment430 :: forall (proxy :: * -> *). proxy Vec3 -> Int
alignment430    = forall b (proxy :: * -> *). Block b => proxy b -> Int
alignment140
  sizeOf430 :: forall (proxy :: * -> *). proxy Vec3 -> Int
sizeOf430       = forall b (proxy :: * -> *). Block b => proxy b -> Int
sizeOf140
  isStruct :: forall (proxy :: * -> *). proxy Vec3 -> Bool
isStruct proxy Vec3
_      = Bool
False
  read140 :: forall (m :: * -> *) a. MonadIO m => Ptr a -> Diff a Vec3 -> m Vec3
read140     = forall (m :: * -> *) b a.
(MonadIO m, Storable b) =>
Ptr a -> Diff a b -> m b
peekDiffOff
  write140 :: forall (m :: * -> *) a.
MonadIO m =>
Ptr a -> Diff a Vec3 -> Vec3 -> m ()
write140    = forall (m :: * -> *) b a.
(MonadIO m, Storable b) =>
Ptr a -> Diff a b -> b -> m ()
pokeDiffOff
  read430 :: forall (m :: * -> *) a. MonadIO m => Ptr a -> Diff a Vec3 -> m Vec3
read430     = forall b (m :: * -> *) a.
(Block b, MonadIO m) =>
Ptr a -> Diff a b -> m b
read140
  write430 :: forall (m :: * -> *) a.
MonadIO m =>
Ptr a -> Diff a Vec3 -> Vec3 -> m ()
write430    = forall b (m :: * -> *) a.
(Block b, MonadIO m) =>
Ptr a -> Diff a b -> b -> m ()
write140
  readPacked :: forall (m :: * -> *) a. MonadIO m => Ptr a -> Diff a Vec3 -> m Vec3
readPacked  = forall b (m :: * -> *) a.
(Block b, MonadIO m) =>
Ptr a -> Diff a b -> m b
read140
  writePacked :: forall (m :: * -> *) a.
MonadIO m =>
Ptr a -> Diff a Vec3 -> Vec3 -> m ()
writePacked = forall b (m :: * -> *) a.
(Block b, MonadIO m) =>
Ptr a -> Diff a b -> b -> m ()
write140
  {-# INLINE sizeOfPacked #-}
  {-# INLINE alignment140 #-}
  {-# INLINE sizeOf140 #-}
  {-# INLINE alignment430 #-}
  {-# INLINE sizeOf430 #-}
  {-# INLINE isStruct #-}
  {-# INLINE read140 #-}
  {-# INLINE write140 #-}
  {-# INLINE read430 #-}
  {-# INLINE write430 #-}
  {-# INLINE readPacked #-}
  {-# INLINE writePacked #-}

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

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

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

{-# INLINE cross #-}
cross :: Vec3 -> Vec3 -> Vec3
cross :: Vec3 -> Vec3 -> Vec3
cross (Vec3 Float
a Float
b Float
c) (Vec3 Float
d Float
e Float
f) =
  Float -> Float -> Float -> Vec3
Vec3
    (Float
b forall a. Num a => a -> a -> a
* Float
f forall a. Num a => a -> a -> a
- Float
c forall a. Num a => a -> a -> a
* Float
e)
    (Float
c forall a. Num a => a -> a -> a
* Float
d forall a. Num a => a -> a -> a
- Float
a forall a. Num a => a -> a -> a
* Float
f)
    (Float
a forall a. Num a => a -> a -> a
* Float
e forall a. Num a => a -> a -> a
- Float
b forall a. Num a => a -> a -> a
* Float
d)

{-# INLINE dot #-}
dot :: Vec3 -> Vec3 -> Float
dot :: Vec3 -> Vec3 -> Float
dot (Vec3 Float
a Float
b Float
c) (Vec3 Float
d Float
e Float
f) =
  Float
a forall a. Num a => a -> a -> a
* Float
d forall a. Num a => a -> a -> a
+
  Float
b forall a. Num a => a -> a -> a
* Float
e forall a. Num a => a -> a -> a
+
  Float
c forall a. Num a => a -> a -> a
* Float
f

{-# INLINE normalize #-}
normalize :: Vec3 -> Vec3
normalize :: Vec3 -> Vec3
normalize Vec3
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
1forall a. Num a => a -> a -> a
-Float
q) then
    Vec3
v
  else
    let
      Vec3 Float
x Float
y Float
z = Vec3
v
    in
      Float -> Float -> Float -> Vec3
Vec3 (Float
x forall a. Fractional a => a -> a -> a
/ Float
l) (Float
y forall a. Fractional a => a -> a -> a
/ Float
l) (Float
z forall a. Fractional a => a -> a -> a
/ Float
l)

  where
    q :: Float
q = Vec3 -> Vec3 -> Float
dot Vec3
v Vec3
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 VectorSpace Vec3 Float where
  zeroVector :: Vec3
zeroVector = forall a. Elementwise a => Element a -> a
epoint Float
0

  {-# INLINE (*^) #-}
  *^ :: Float -> Vec3 -> Vec3
(*^) = forall a b c. (a -> b -> c) -> b -> a -> c
flip Vec3 -> Float -> Vec3
(Geomancy.Vec3.^*)

  {-# INLINE (^/) #-}
  ^/ :: Vec3 -> Float -> Vec3
(^/) = Vec3 -> Float -> Vec3
(Geomancy.Vec3.^/)

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

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

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

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

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

-- * Unpadded

type instance Element Packed = Float

newtype Packed = Packed { Packed -> Vec3
unPacked :: Vec3 }
  deriving stock
    ( Packed -> Packed -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Packed -> Packed -> Bool
$c/= :: Packed -> Packed -> Bool
== :: Packed -> Packed -> Bool
$c== :: Packed -> Packed -> Bool
Eq, Eq Packed
Packed -> Packed -> Bool
Packed -> Packed -> Ordering
Packed -> Packed -> Packed
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 :: Packed -> Packed -> Packed
$cmin :: Packed -> Packed -> Packed
max :: Packed -> Packed -> Packed
$cmax :: Packed -> Packed -> Packed
>= :: Packed -> Packed -> Bool
$c>= :: Packed -> Packed -> Bool
> :: Packed -> Packed -> Bool
$c> :: Packed -> Packed -> Bool
<= :: Packed -> Packed -> Bool
$c<= :: Packed -> Packed -> Bool
< :: Packed -> Packed -> Bool
$c< :: Packed -> Packed -> Bool
compare :: Packed -> Packed -> Ordering
$ccompare :: Packed -> Packed -> Ordering
Ord, Int -> Packed -> ShowS
[Packed] -> ShowS
Packed -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Packed] -> ShowS
$cshowList :: [Packed] -> ShowS
show :: Packed -> String
$cshow :: Packed -> String
showsPrec :: Int -> Packed -> ShowS
$cshowsPrec :: Int -> Packed -> ShowS
Show
    )
  deriving newtype
    ( Packed -> ()
forall a. (a -> ()) -> NFData a
rnf :: Packed -> ()
$crnf :: Packed -> ()
NFData, Integer -> Packed
Packed -> Packed
Packed -> Packed -> Packed
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
fromInteger :: Integer -> Packed
$cfromInteger :: Integer -> Packed
signum :: Packed -> Packed
$csignum :: Packed -> Packed
abs :: Packed -> Packed
$cabs :: Packed -> Packed
negate :: Packed -> Packed
$cnegate :: Packed -> Packed
* :: Packed -> Packed -> Packed
$c* :: Packed -> Packed -> Packed
- :: Packed -> Packed -> Packed
$c- :: Packed -> Packed -> Packed
+ :: Packed -> Packed -> Packed
$c+ :: Packed -> Packed -> Packed
Num, Num Packed
Rational -> Packed
Packed -> Packed
Packed -> Packed -> Packed
forall a.
Num a
-> (a -> a -> a) -> (a -> a) -> (Rational -> a) -> Fractional a
fromRational :: Rational -> Packed
$cfromRational :: Rational -> Packed
recip :: Packed -> Packed
$crecip :: Packed -> Packed
/ :: Packed -> Packed -> Packed
$c/ :: Packed -> Packed -> Packed
Fractional, Fractional Packed
Packed
Packed -> Packed
Packed -> Packed -> Packed
forall a.
Fractional a
-> a
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> Floating a
log1mexp :: Packed -> Packed
$clog1mexp :: Packed -> Packed
log1pexp :: Packed -> Packed
$clog1pexp :: Packed -> Packed
expm1 :: Packed -> Packed
$cexpm1 :: Packed -> Packed
log1p :: Packed -> Packed
$clog1p :: Packed -> Packed
atanh :: Packed -> Packed
$catanh :: Packed -> Packed
acosh :: Packed -> Packed
$cacosh :: Packed -> Packed
asinh :: Packed -> Packed
$casinh :: Packed -> Packed
tanh :: Packed -> Packed
$ctanh :: Packed -> Packed
cosh :: Packed -> Packed
$ccosh :: Packed -> Packed
sinh :: Packed -> Packed
$csinh :: Packed -> Packed
atan :: Packed -> Packed
$catan :: Packed -> Packed
acos :: Packed -> Packed
$cacos :: Packed -> Packed
asin :: Packed -> Packed
$casin :: Packed -> Packed
tan :: Packed -> Packed
$ctan :: Packed -> Packed
cos :: Packed -> Packed
$ccos :: Packed -> Packed
sin :: Packed -> Packed
$csin :: Packed -> Packed
logBase :: Packed -> Packed -> Packed
$clogBase :: Packed -> Packed -> Packed
** :: Packed -> Packed -> Packed
$c** :: Packed -> Packed -> Packed
sqrt :: Packed -> Packed
$csqrt :: Packed -> Packed
log :: Packed -> Packed
$clog :: Packed -> Packed
exp :: Packed -> Packed
$cexp :: Packed -> Packed
pi :: Packed
$cpi :: Packed
Floating
    , (Element Packed -> Element Packed) -> Packed -> Packed
forall mono.
((Element mono -> Element mono) -> mono -> mono)
-> MonoFunctor mono
omap :: (Element Packed -> Element Packed) -> Packed -> Packed
$comap :: (Element Packed -> Element Packed) -> Packed -> Packed
MonoFunctor, Element Packed -> Packed
forall mono. (Element mono -> mono) -> MonoPointed mono
opoint :: Element Packed -> Packed
$copoint :: Element Packed -> Packed
MonoPointed
    , Element Packed -> Packed
(Element Packed -> Element Packed) -> Packed -> Packed
(Element Packed -> Element Packed -> Element Packed)
-> Packed -> Packed -> Packed
(Element Packed
 -> Element Packed -> Element Packed -> Element Packed)
-> Packed -> Packed -> Packed -> Packed
(Element Packed
 -> Element Packed
 -> Element Packed
 -> Element Packed
 -> Element Packed)
-> Packed -> Packed -> Packed -> Packed -> Packed
(Element Packed
 -> Element Packed
 -> Element Packed
 -> Element Packed
 -> Element Packed
 -> Element Packed)
-> Packed -> Packed -> Packed -> Packed -> Packed -> Packed
forall a.
(Element a -> a)
-> ((Element a -> Element a) -> a -> a)
-> ((Element a -> Element a -> Element a) -> a -> a -> a)
-> ((Element a -> Element a -> Element a -> Element a)
    -> a -> a -> a -> a)
-> ((Element a -> Element a -> Element a -> Element a -> Element a)
    -> a -> a -> a -> a -> a)
-> ((Element a
     -> Element a -> Element a -> Element a -> Element a -> Element a)
    -> a -> a -> a -> a -> a -> a)
-> Elementwise a
emap5 :: (Element Packed
 -> Element Packed
 -> Element Packed
 -> Element Packed
 -> Element Packed
 -> Element Packed)
-> Packed -> Packed -> Packed -> Packed -> Packed -> Packed
$cemap5 :: (Element Packed
 -> Element Packed
 -> Element Packed
 -> Element Packed
 -> Element Packed
 -> Element Packed)
-> Packed -> Packed -> Packed -> Packed -> Packed -> Packed
emap4 :: (Element Packed
 -> Element Packed
 -> Element Packed
 -> Element Packed
 -> Element Packed)
-> Packed -> Packed -> Packed -> Packed -> Packed
$cemap4 :: (Element Packed
 -> Element Packed
 -> Element Packed
 -> Element Packed
 -> Element Packed)
-> Packed -> Packed -> Packed -> Packed -> Packed
emap3 :: (Element Packed
 -> Element Packed -> Element Packed -> Element Packed)
-> Packed -> Packed -> Packed -> Packed
$cemap3 :: (Element Packed
 -> Element Packed -> Element Packed -> Element Packed)
-> Packed -> Packed -> Packed -> Packed
emap2 :: (Element Packed -> Element Packed -> Element Packed)
-> Packed -> Packed -> Packed
$cemap2 :: (Element Packed -> Element Packed -> Element Packed)
-> Packed -> Packed -> Packed
emap :: (Element Packed -> Element Packed) -> Packed -> Packed
$cemap :: (Element Packed -> Element Packed) -> Packed -> Packed
epoint :: Element Packed -> Packed
$cepoint :: Element Packed -> Packed
Elementwise
    )

{-# INLINE packed #-}
packed :: Float -> Float -> Float -> Packed
packed :: Float -> Float -> Float -> Packed
packed Float
x Float
y Float
z = Vec3 -> Packed
Packed (Float -> Float -> Float -> Vec3
vec3 Float
x Float
y Float
z)

instance Storable Packed where
  {-# INLINE sizeOf #-}
  sizeOf :: Packed -> Int
sizeOf Packed
_ = Int
12

  {-# INLINE alignment #-}
  alignment :: Packed -> Int
alignment Packed
_ = Int
4

  {-# INLINE poke #-}
  poke :: Ptr Packed -> Packed -> IO ()
poke Ptr Packed
ptr (Packed Vec3
v3) =
    forall r. Vec3 -> (Float -> Float -> Float -> r) -> r
withVec3 Vec3
v3 \Float
a Float
b Float
c -> do
      forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr Float
ptr' Float
a
      forall a. Storable a => Ptr a -> Int -> a -> IO ()
pokeElemOff Ptr Float
ptr' Int
1 Float
b
      forall a. Storable a => Ptr a -> Int -> a -> IO ()
pokeElemOff Ptr Float
ptr' Int
2 Float
c
    where
      ptr' :: Ptr Float
ptr' = forall a b. Ptr a -> Ptr b
castPtr Ptr Packed
ptr

  {-# INLINE peek #-}
  peek :: Ptr Packed -> IO Packed
peek Ptr Packed
ptr = Float -> Float -> Float -> Packed
packed
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Storable a => Ptr a -> IO a
peek Ptr Float
ptr'
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Float
ptr' Int
1
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Float
ptr' Int
2
    where
      ptr' :: Ptr Float
ptr' = forall a b. Ptr a -> Ptr b
castPtr Ptr Packed
ptr

instance Block Packed where
  sizeOfPacked :: forall (proxy :: * -> *). proxy Packed -> Int
sizeOfPacked proxy Packed
_  = Int
12
  alignment140 :: forall (proxy :: * -> *). proxy Packed -> Int
alignment140 proxy Packed
_  = Int
16
  sizeOf140 :: forall (proxy :: * -> *). proxy Packed -> Int
sizeOf140 proxy Packed
_     = Int
16
  alignment430 :: forall (proxy :: * -> *). proxy Packed -> Int
alignment430    = forall b (proxy :: * -> *). Block b => proxy b -> Int
alignment140
  sizeOf430 :: forall (proxy :: * -> *). proxy Packed -> Int
sizeOf430       = forall b (proxy :: * -> *). Block b => proxy b -> Int
sizeOf140
  isStruct :: forall (proxy :: * -> *). proxy Packed -> Bool
isStruct proxy Packed
_      = Bool
False
  read140 :: forall (m :: * -> *) a.
MonadIO m =>
Ptr a -> Diff a Packed -> m Packed
read140     = forall (m :: * -> *) b a.
(MonadIO m, Storable b) =>
Ptr a -> Diff a b -> m b
peekDiffOff
  write140 :: forall (m :: * -> *) a.
MonadIO m =>
Ptr a -> Diff a Packed -> Packed -> m ()
write140    = forall (m :: * -> *) b a.
(MonadIO m, Storable b) =>
Ptr a -> Diff a b -> b -> m ()
pokeDiffOff
  read430 :: forall (m :: * -> *) a.
MonadIO m =>
Ptr a -> Diff a Packed -> m Packed
read430     = forall b (m :: * -> *) a.
(Block b, MonadIO m) =>
Ptr a -> Diff a b -> m b
read140
  write430 :: forall (m :: * -> *) a.
MonadIO m =>
Ptr a -> Diff a Packed -> Packed -> m ()
write430    = forall b (m :: * -> *) a.
(Block b, MonadIO m) =>
Ptr a -> Diff a b -> b -> m ()
write140
  readPacked :: forall (m :: * -> *) a.
MonadIO m =>
Ptr a -> Diff a Packed -> m Packed
readPacked  = forall b (m :: * -> *) a.
(Block b, MonadIO m) =>
Ptr a -> Diff a b -> m b
read140
  writePacked :: forall (m :: * -> *) a.
MonadIO m =>
Ptr a -> Diff a Packed -> Packed -> m ()
writePacked = forall b (m :: * -> *) a.
(Block b, MonadIO m) =>
Ptr a -> Diff a b -> b -> m ()
write140
  {-# INLINE sizeOfPacked #-}
  {-# INLINE alignment140 #-}
  {-# INLINE sizeOf140 #-}
  {-# INLINE alignment430 #-}
  {-# INLINE sizeOf430 #-}
  {-# INLINE isStruct #-}
  {-# INLINE read140 #-}
  {-# INLINE write140 #-}
  {-# INLINE read430 #-}
  {-# INLINE write430 #-}
  {-# INLINE readPacked #-}
  {-# INLINE writePacked #-}

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

  {-# INLINE (*^) #-}
  *^ :: Float -> Packed -> Packed
(*^) = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a b. (a -> b) -> a -> b
$ coerce :: forall a b. Coercible a b => a -> b
coerce Vec3 -> Float -> Vec3
(Geomancy.Vec3.^*)

  {-# INLINE (^/) #-}
  ^/ :: Packed -> Float -> Packed
(^/) = coerce :: forall a b. Coercible a b => a -> b
coerce Vec3 -> Float -> Vec3
(Geomancy.Vec3.^/)

  {-# INLINE (^+^) #-}
  Packed
v1 ^+^ :: Packed -> Packed -> Packed
^+^ Packed
v2 = Packed
v1 forall a. Num a => a -> a -> a
+ Packed
v2

  {-# INLINE (^-^) #-}
  Packed
v1 ^-^ :: Packed -> Packed -> Packed
^-^ Packed
v2 = Packed
v1 forall a. Num a => a -> a -> a
- Packed
v2

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

  {-# INLINE dot #-}
  dot :: Packed -> Packed -> Float
dot = coerce :: forall a b. Coercible a b => a -> b
coerce Vec3 -> Vec3 -> Float
Geomancy.Vec3.dot

  {-# INLINE normalize #-}
  normalize :: Packed -> Packed
normalize = coerce :: forall a b. Coercible a b => a -> b
coerce Vec3 -> Vec3
Geomancy.Vec3.normalize

instance GlNearest Vec3

instance GlModf Vec3 Vec3 where
  glModf :: Vec3 -> (Vec3, Vec3)
glModf Vec3
v =
    forall r. Vec3 -> (Float -> Float -> Float -> r) -> r
withVec3 Vec3
v \Float
vx Float
vy Float
vz ->
      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
        (Integer
zi, Float
zf) = forall i f. GlModf i f => f -> (i, f)
glModf Float
vz
      in
        ( Float -> Float -> Float -> Vec3
vec3 (forall a. Num a => Integer -> a
fromInteger Integer
xi) (forall a. Num a => Integer -> a
fromInteger Integer
yi) (forall a. Num a => Integer -> a
fromInteger Integer
zi)
        , Float -> Float -> Float -> Vec3
vec3 Float
xf Float
yf Float
zf
        )