{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE UnliftedFFITypes #-}
{-# LANGUAGE ViewPatterns #-}

{-# OPTIONS_GHC -Wno-orphans #-} -- XXX: until there are order-specific types

-- | General matrix storage and operations.

module Geomancy.Mat4
  ( Mat4
    -- * Operations
  , identity
  , transpose
  , inverse
  , det
  , pointwise
  , zipWith
  , matrixProduct
  , scalarMultiply
  , (!*)

    -- * Construction

    -- ** Col-major
  , colMajor
  , withColMajor
  , toListColMajor
  , toListColMajor2d
  , showColumns

    -- ** Row-major
  , rowMajor
  , withRowMajor
  , toListRowMajor
  , toListRowMajor2d
  , fromRowMajor2d
  , showRows
  ) where

import Prelude hiding (zipWith)
import GHC.Exts hiding (VecCount(..), toList)
import Geomancy.Mat4.Internal

import System.IO.Unsafe (unsafePerformIO)
import Text.Printf (printf)

import qualified Data.Foldable as Foldable

import Geomancy.Vec4 (Vec4(..), newVec4)

toListColMajor :: Coercible a Mat4 => a -> [Float]
toListColMajor :: forall a. Coercible a Mat4 => a -> [Float]
toListColMajor = Mat4 -> [Float]
toListTrans (Mat4 -> [Float]) -> (a -> Mat4) -> a -> [Float]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Mat4
forall a b. Coercible a b => a -> b
coerce

toListColMajor2d :: Coercible a Mat4 => a -> [[Float]]
toListColMajor2d :: forall a. Coercible a Mat4 => a -> [[Float]]
toListColMajor2d = Mat4 -> [[Float]]
toList2dTrans (Mat4 -> [[Float]]) -> (a -> Mat4) -> a -> [[Float]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Mat4
forall a b. Coercible a b => a -> b
coerce

{- | Construct 'Mat4' from @row@ notation.
-}
rowMajor
  :: Coercible Mat4 a
  => Float -> Float -> Float -> Float
  -> Float -> Float -> Float -> Float
  -> Float -> Float -> Float -> Float
  -> Float -> Float -> Float -> Float
  -> a
rowMajor :: forall a.
Coercible Mat4 a =>
Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> a
rowMajor
  Float
e0 Float
e1 Float
e2 Float
e3
  Float
e4 Float
e5 Float
e6 Float
e7
  Float
e8 Float
e9 Float
eA Float
eB
  Float
eC Float
eD Float
eE Float
eF =
    -- just store
    Mat4 -> a
forall a b. Coercible a b => a -> b
coerce (Mat4 -> a) -> Mat4 -> a
forall a b. (a -> b) -> a -> b
$ Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Mat4
fromMemory
      Float
e0 Float
e1 Float
e2 Float
e3
      Float
e4 Float
e5 Float
e6 Float
e7
      Float
e8 Float
e9 Float
eA Float
eB
      Float
eC Float
eD Float
eE Float
eF

{- |
  Build a Mat4 from a list-of-lists kind of container
  with row-major ordering of elements.

@
  fromRowMajor2d (Linear.mkTransformation dir pos) :: Transform
@
-}
fromRowMajor2d
  :: forall t a
  .  ( Foldable t
     , Coercible Mat4 a
     )
  => t (t Float)
  -> Maybe a
fromRowMajor2d :: forall (t :: * -> *) a.
(Foldable t, Coercible Mat4 a) =>
t (t Float) -> Maybe a
fromRowMajor2d t (t Float)
rows =
  case t (t Float) -> [t Float]
forall a. t a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
Foldable.toList t (t Float)
rows of
    [t Float
r0, t Float
r1, t Float
r2, t Float
r3] ->
      t Float -> (Float -> Float -> Float -> Float -> Maybe a) -> Maybe a
forall {t :: * -> *} {t} {a}.
Foldable t =>
t t -> (t -> t -> t -> t -> Maybe a) -> Maybe a
withRow t Float
r0 \Float
e0 Float
e1 Float
e2 Float
e3 ->
      t Float -> (Float -> Float -> Float -> Float -> Maybe a) -> Maybe a
forall {t :: * -> *} {t} {a}.
Foldable t =>
t t -> (t -> t -> t -> t -> Maybe a) -> Maybe a
withRow t Float
r1 \Float
e4 Float
e5 Float
e6 Float
e7 ->
      t Float -> (Float -> Float -> Float -> Float -> Maybe a) -> Maybe a
forall {t :: * -> *} {t} {a}.
Foldable t =>
t t -> (t -> t -> t -> t -> Maybe a) -> Maybe a
withRow t Float
r2 \Float
e8 Float
e9 Float
eA Float
eB ->
      t Float -> (Float -> Float -> Float -> Float -> Maybe a) -> Maybe a
forall {t :: * -> *} {t} {a}.
Foldable t =>
t t -> (t -> t -> t -> t -> Maybe a) -> Maybe a
withRow t Float
r3 \Float
eC Float
eD Float
eE Float
eF ->
        a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> (a -> a) -> a -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce @a (a -> Maybe a) -> a -> Maybe a
forall a b. (a -> b) -> a -> b
$ Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> a
forall a.
Coercible Mat4 a =>
Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> a
rowMajor
          Float
e0 Float
e1 Float
e2 Float
e3
          Float
e4 Float
e5 Float
e6 Float
e7
          Float
e8 Float
e9 Float
eA Float
eB
          Float
eC Float
eD Float
eE Float
eF
    [t Float]
_ ->
      Maybe a
forall a. Maybe a
Nothing
  where
    withRow :: t t -> (t -> t -> t -> t -> Maybe a) -> Maybe a
withRow t t
row t -> t -> t -> t -> Maybe a
f =
      case t t -> [t]
forall a. t a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
Foldable.toList t t
row of
        [t
c0, t
c1, t
c2, t
c3] ->
          t -> t -> t -> t -> Maybe a
f t
c0 t
c1 t
c2 t
c3
        [t]
_ ->
          Maybe a
forall a. Maybe a
Nothing

{- | Reduce 'Mat4' with a function with @row@ notation for arguments.
-}
{-# INLINE withRowMajor #-}
withRowMajor
  :: Coercible a Mat4
  => a
  ->
    ( Float -> Float -> Float -> Float ->
      Float -> Float -> Float -> Float ->
      Float -> Float -> Float -> Float ->
      Float -> Float -> Float -> Float ->
      r
    )
  -> r
withRowMajor :: forall a r.
Coercible a Mat4 =>
a
-> (Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> r)
-> r
withRowMajor a
m Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> r
f = Mat4
-> (Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> r)
-> r
forall r.
Mat4
-> (Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> r)
-> r
withMemory (a -> Mat4
forall a b. Coercible a b => a -> b
coerce a
m)
  \ Float
e0 Float
e1 Float
e2 Float
e3
    Float
e4 Float
e5 Float
e6 Float
e7
    Float
e8 Float
e9 Float
eA Float
eB
    Float
eC Float
eD Float
eE Float
eF ->
  Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> r
f -- preserved element order
    Float
e0 Float
e1 Float
e2 Float
e3
    Float
e4 Float
e5 Float
e6 Float
e7
    Float
e8 Float
e9 Float
eA Float
eB
    Float
eC Float
eD Float
eE Float
eF

{- | Construct a 'Mat4' from @column@ notation.
-}
{-# INLINE colMajor #-}
colMajor
  :: forall a . Coercible Mat4 a
  => Float -> Float -> Float -> Float
  -> Float -> Float -> Float -> Float
  -> Float -> Float -> Float -> Float
  -> Float -> Float -> Float -> Float
  -> a
colMajor :: forall a.
Coercible Mat4 a =>
Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> a
colMajor
  Float
e0 Float
e4 Float
e8 Float
eC
  Float
e1 Float
e5 Float
e9 Float
eD
  Float
e2 Float
e6 Float
eA Float
eE
  Float
e3 Float
e7 Float
eB Float
eF =
    Mat4 -> a
forall a b. Coercible a b => a -> b
coerce (Mat4 -> a) -> Mat4 -> a
forall a b. (a -> b) -> a -> b
$ Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Mat4
fromMemory
      Float
e0 Float
e1 Float
e2 Float
e3
      Float
e4 Float
e5 Float
e6 Float
e7
      Float
e8 Float
e9 Float
eA Float
eB
      Float
eC Float
eD Float
eE Float
eF

{- | Reduce 'Mat4' with a function with @column@ notation for arguments.
-}
{-# INLINE withColMajor #-}
withColMajor
  :: Coercible a Mat4
  => a
  ->
    ( Float -> Float -> Float -> Float ->
      Float -> Float -> Float -> Float ->
      Float -> Float -> Float -> Float ->
      Float -> Float -> Float -> Float ->
      r
    )
  -> r
withColMajor :: forall a r.
Coercible a Mat4 =>
a
-> (Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> r)
-> r
withColMajor a
m Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> r
f = Mat4
-> (Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> r)
-> r
forall r.
Mat4
-> (Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> r)
-> r
withMemory (a -> Mat4
forall a b. Coercible a b => a -> b
coerce a
m)
  \ Float
e0 Float
e4 Float
e8 Float
eC
    Float
e1 Float
e5 Float
e9 Float
eD
    Float
e2 Float
e6 Float
eA Float
eE
    Float
e3 Float
e7 Float
eB Float
eF ->
  Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> r
f -- transposed element order
    Float
e0 Float
e1 Float
e2 Float
e3
    Float
e4 Float
e5 Float
e6 Float
e7
    Float
e8 Float
e9 Float
eA Float
eB
    Float
eC Float
eD Float
eE Float
eF

toListRowMajor :: Coercible a Mat4 => a -> [Float]
toListRowMajor :: forall a. Coercible a Mat4 => a -> [Float]
toListRowMajor = Mat4 -> [Float]
toListMemory (Mat4 -> [Float]) -> (a -> Mat4) -> a -> [Float]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Mat4
forall a b. Coercible a b => a -> b
coerce

toListRowMajor2d :: Coercible a Mat4 => a -> [[Float]]
toListRowMajor2d :: forall a. Coercible a Mat4 => a -> [[Float]]
toListRowMajor2d = Mat4 -> [[Float]]
toList2dMemory (Mat4 -> [[Float]]) -> (a -> Mat4) -> a -> [[Float]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Mat4
forall a b. Coercible a b => a -> b
coerce

det :: forall a . (Coercible Mat4 a, Coercible Mat4 a) => a -> Float
det :: forall a. (Coercible Mat4 a, Coercible Mat4 a) => a -> Float
det a
m =
  a
-> (Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float)
-> Float
forall a r.
Coercible a Mat4 =>
a
-> (Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> r)
-> r
withRowMajor (forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce @_ @a a
m)
    \ Float
m00 Float
m01 Float
m02 Float
m03
      Float
m10 Float
m11 Float
m12 Float
m13
      Float
m20 Float
m21 Float
m22 Float
m23
      Float
m30 Float
m31 Float
m32 Float
m33 ->
        let
          s0 :: Float
s0 = Float
m00 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m11 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m10 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m01
          s1 :: Float
s1 = Float
m00 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m12 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m10 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m02
          s2 :: Float
s2 = Float
m00 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m13 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m10 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m03
          s3 :: Float
s3 = Float
m01 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m12 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m11 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m02
          s4 :: Float
s4 = Float
m01 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m13 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m11 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m03
          s5 :: Float
s5 = Float
m02 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m13 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m12 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m03

          c5 :: Float
c5 = Float
m22 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m33 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m32 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m23
          c4 :: Float
c4 = Float
m21 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m33 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m31 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m23
          c3 :: Float
c3 = Float
m21 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m32 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m31 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m22
          c2 :: Float
c2 = Float
m20 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m33 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m30 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m23
          c1 :: Float
c1 = Float
m20 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m32 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m30 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m22
          c0 :: Float
c0 = Float
m20 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m31 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m30 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m21
        in
            Float
s0 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c5
          Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
s1 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c4
          Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
s2 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c3
          Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
s3 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c2
          Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
s4 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c1
          Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
s5 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c0

{- | Compute an inverse matrix, slowly.
-}
inverse :: forall a . (Coercible Mat4 a, Coercible Mat4 a) => a -> a
inverse :: forall a. (Coercible Mat4 a, Coercible Mat4 a) => a -> a
inverse a
m =
  forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce @a (a -> a) -> a -> a
forall a b. (a -> b) -> a -> b
$ a
-> (Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> a)
-> a
forall a r.
Coercible a Mat4 =>
a
-> (Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> r)
-> r
withRowMajor (forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce @_ @a a
m)
    \ Float
m00 Float
m01 Float
m02 Float
m03
      Float
m10 Float
m11 Float
m12 Float
m13
      Float
m20 Float
m21 Float
m22 Float
m23
      Float
m30 Float
m31 Float
m32 Float
m33 ->
        let
          invDet :: Float
invDet = Float -> Float
forall a. Fractional a => a -> a
recip (Float -> Float) -> Float -> Float
forall a b. (a -> b) -> a -> b
$
              Float
s0 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c5
            Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
s1 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c4
            Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
s2 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c3
            Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
s3 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c2
            Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
s4 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c1
            Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
s5 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c0

          s0 :: Float
s0 = Float
m00 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m11 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m10 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m01
          s1 :: Float
s1 = Float
m00 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m12 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m10 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m02
          s2 :: Float
s2 = Float
m00 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m13 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m10 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m03
          s3 :: Float
s3 = Float
m01 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m12 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m11 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m02
          s4 :: Float
s4 = Float
m01 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m13 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m11 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m03
          s5 :: Float
s5 = Float
m02 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m13 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m12 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m03

          c5 :: Float
c5 = Float
m22 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m33 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m32 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m23
          c4 :: Float
c4 = Float
m21 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m33 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m31 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m23
          c3 :: Float
c3 = Float
m21 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m32 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m31 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m22
          c2 :: Float
c2 = Float
m20 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m33 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m30 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m23
          c1 :: Float
c1 = Float
m20 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m32 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m30 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m22
          c0 :: Float
c0 = Float
m20 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m31 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m30 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m21

          i00 :: Float
i00 = ( Float
m11 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c5 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m12 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c4 Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
m13 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c3) Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
invDet
          i01 :: Float
i01 = (-Float
m01 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c5 Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
m02 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c4 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m03 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c3) Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
invDet
          i02 :: Float
i02 = ( Float
m31 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s5 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m32 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s4 Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
m33 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s3) Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
invDet
          i03 :: Float
i03 = (-Float
m21 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s5 Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
m22 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s4 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m23 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s3) Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
invDet

          i10 :: Float
i10 = (-Float
m10 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c5 Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
m12 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c2 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m13 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c1) Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
invDet
          i11 :: Float
i11 = ( Float
m00 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c5 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m02 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c2 Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
m03 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c1) Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
invDet
          i12 :: Float
i12 = (-Float
m30 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s5 Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
m32 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s2 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m33 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s1) Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
invDet
          i13 :: Float
i13 = ( Float
m20 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s5 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m22 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s2 Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
m23 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s1) Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
invDet

          i20 :: Float
i20 = ( Float
m10 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c4 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m11 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c2 Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
m13 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c0) Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
invDet
          i21 :: Float
i21 = (-Float
m00 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c4 Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
m01 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c2 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m03 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c0) Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
invDet
          i22 :: Float
i22 = ( Float
m30 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s4 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m31 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s2 Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
m33 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s0) Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
invDet
          i23 :: Float
i23 = (-Float
m20 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s4 Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
m21 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s2 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m23 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s0) Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
invDet

          i30 :: Float
i30 = (-Float
m10 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c3 Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
m11 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c1 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m12 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c0) Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
invDet
          i31 :: Float
i31 = ( Float
m00 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c3 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m01 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c1 Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
m02 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c0) Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
invDet
          i32 :: Float
i32 = (-Float
m30 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s3 Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
m31 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s1 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m32 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s0) Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
invDet
          i33 :: Float
i33 = ( Float
m20 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s3 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
m21 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s1 Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
m22 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
s0) Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
invDet
        in
          Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> a
forall a.
Coercible Mat4 a =>
Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> Float
-> a
rowMajor
            Float
i00 Float
i01 Float
i02 Float
i03
            Float
i10 Float
i11 Float
i12 Float
i13
            Float
i20 Float
i21 Float
i22 Float
i23
            Float
i30 Float
i31 Float
i32 Float
i33

foreign import ccall unsafe "Mat4xMat4_SIMD" m4m4simd :: ByteArray# -> ByteArray# -> ByteArray# -> IO ()

{-# INLINE matrixProduct #-}
matrixProduct :: Mat4 -> Mat4 -> Mat4
matrixProduct :: Mat4 -> Mat4 -> Mat4
matrixProduct (Mat4 ByteArray#
l) (Mat4 ByteArray#
r) = IO Mat4 -> Mat4
forall a. IO a -> a
unsafePerformIO do
  result :: Mat4
result@(Mat4 ByteArray#
m) <- IO Mat4
newMat4
  ByteArray# -> ByteArray# -> ByteArray# -> IO ()
m4m4simd ByteArray#
l ByteArray#
r ByteArray#
m
  Mat4 -> IO Mat4
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Mat4
result

foreign import ccall unsafe "Mat4xVec4_SIMD" m4v4simd :: ByteArray# -> ByteArray# -> ByteArray# -> IO ()

{- | Matrix - column vector multiplication (post)

@
vOut = p <> v <> m !* vIn
@
-}
(!*) :: Coercible a Mat4 => a -> Vec4 -> Vec4
!* :: forall a. Coercible a Mat4 => a -> Vec4 -> Vec4
(!*) (a -> Mat4
forall a b. Coercible a b => a -> b
coerce -> Mat4 ByteArray#
m) (Vec4 ByteArray#
v) = IO Vec4 -> Vec4
forall a. IO a -> a
unsafePerformIO do
  result :: Vec4
result@(Vec4 ByteArray#
o) <- IO Vec4
newVec4
  !() <- ByteArray# -> ByteArray# -> ByteArray# -> IO ()
m4v4simd ByteArray#
m ByteArray#
v ByteArray#
o
  Vec4 -> IO Vec4
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Vec4
result

infixr 5 !*

instance Semigroup Mat4 where
  {-# INLINE (<>) #-}
  <> :: Mat4 -> Mat4 -> Mat4
(<>) = Mat4 -> Mat4 -> Mat4
matrixProduct

instance Monoid Mat4 where
  {-# INLINE mempty #-}
  mempty :: Mat4
mempty = Mat4
identity

instance Show Mat4 where
  show :: Mat4 -> String
show = Mat4 -> String
showColumns

showColumns :: Mat4 -> String
showColumns :: Mat4 -> String
showColumns Mat4
cm = Mat4
-> (Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> String)
-> String
forall a r.
Coercible a Mat4 =>
a
-> (Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> r)
-> r
withColMajor Mat4
cm
  \ Float
e0 Float
e4 Float
e8 Float
eC
    Float
e1 Float
e5 Float
e9 Float
eD
    Float
e2 Float
e6 Float
eA Float
eE
    Float
e3 Float
e7 Float
eB Float
eF ->
  [String] -> String
unlines
    [ String -> Float -> Float -> Float -> Float -> String
forall r. PrintfType r => String -> r
printf  String
"/ %.4f %.4f %.4f %.4f \\" Float
e0 Float
e4 Float
e8 Float
eC
    , String -> Float -> Float -> Float -> Float -> String
forall r. PrintfType r => String -> r
printf  String
"| %.4f %.4f %.4f %.4f |"  Float
e1 Float
e5 Float
e9 Float
eD
    , String -> Float -> Float -> Float -> Float -> String
forall r. PrintfType r => String -> r
printf  String
"| %.4f %.4f %.4f %.4f |"  Float
e2 Float
e6 Float
eA Float
eE
    , String -> Float -> Float -> Float -> Float -> String
forall r. PrintfType r => String -> r
printf String
"\\ %.4f %.4f %.4f %.4f /"  Float
e3 Float
e7 Float
eB Float
eF
    ]

showRows :: Mat4 -> String
showRows :: Mat4 -> String
showRows Mat4
rm = Mat4
-> (Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> String)
-> String
forall a r.
Coercible a Mat4 =>
a
-> (Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> Float
    -> r)
-> r
withRowMajor Mat4
rm
  \ Float
e0 Float
e1 Float
e2 Float
e3
    Float
e4 Float
e5 Float
e6 Float
e7
    Float
e8 Float
e9 Float
eA Float
eB
    Float
eC Float
eD Float
eE Float
eF ->
  [String] -> String
unlines
    [ String -> Float -> Float -> Float -> Float -> String
forall r. PrintfType r => String -> r
printf String
"[ %.4f %.4f %.4f %.4f |" Float
e0 Float
e1 Float
e2 Float
e3
    , String -> Float -> Float -> Float -> Float -> String
forall r. PrintfType r => String -> r
printf String
"| %.4f %.4f %.4f %.4f |" Float
e4 Float
e5 Float
e6 Float
e7
    , String -> Float -> Float -> Float -> Float -> String
forall r. PrintfType r => String -> r
printf String
"| %.4f %.4f %.4f %.4f |" Float
e8 Float
e9 Float
eA Float
eB
    , String -> Float -> Float -> Float -> Float -> String
forall r. PrintfType r => String -> r
printf String
"| %.4f %.4f %.4f %.4f ]" Float
eC Float
eD Float
eE Float
eF
    ]