-- |
-- Module:     Data.Vector.Algorithms.Quicksort.Predefined.SortTriple
-- Copyright:  (c) Sergey Vinokurov 2023
-- License:    Apache-2.0 (see LICENSE)
-- Maintainer: serg.foo@gmail.com

{-# LANGUAGE DerivingVia   #-}
{-# LANGUAGE InstanceSigs  #-}
{-# LANGUAGE MagicHash     #-}
{-# LANGUAGE TypeFamilies  #-}
{-# LANGUAGE UnboxedTuples #-}

module Data.Vector.Algorithms.Quicksort.Predefined.SortTriple
  ( SortTriple(..)
  , U.MVector(..)
  , U.Vector(..)
  ) where

import Data.Word
import Data.Vector.Generic qualified as G
import Data.Vector.Generic.Mutable qualified as GM
import Data.Vector.Unboxed qualified as U

import Data.Primitive.Types
import GHC.Exts
import GHC.Word

data SortTriple = SortTriple !Double !Double !Word64

instance Eq SortTriple where
  SortTriple Double
_ Double
_ Word64
c == :: SortTriple -> SortTriple -> Bool
== SortTriple Double
_ Double
_ Word64
c' = Word64
c Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
c'

instance Ord SortTriple where
  SortTriple Double
_ Double
_ Word64
c compare :: SortTriple -> SortTriple -> Ordering
`compare` SortTriple Double
_ Double
_ Word64
c' = Word64 -> Word64 -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Word64
c Word64
c'

instance U.IsoUnbox SortTriple (Double, Double, Word64) where
  toURepr :: SortTriple -> (Double, Double, Word64)
toURepr (SortTriple Double
a Double
b Word64
c) = (Double
a, Double
b, Word64
c)
  fromURepr :: (Double, Double, Word64) -> SortTriple
fromURepr (Double
a, Double
b, Word64
c) = Double -> Double -> Word64 -> SortTriple
SortTriple Double
a Double
b Word64
c
  {-# INLINE toURepr   #-}
  {-# INLINE fromURepr #-}

newtype instance U.MVector s SortTriple = MV_TestPair (U.MVector s (Double, Double, Word64))
newtype instance U.Vector    SortTriple = V_TestPair  (U.Vector    (Double, Double, Word64))
deriving via (SortTriple `U.As` (Double, Double, Word64)) instance GM.MVector U.MVector SortTriple
deriving via (SortTriple `U.As` (Double, Double, Word64)) instance G.Vector   U.Vector  SortTriple
instance U.Unbox SortTriple

idxs :: Int# -> (# Int#, Int#, Int# #)
idxs :: Int# -> (# Int#, Int#, Int# #)
idxs Int#
idx =
  (# Int#
start
  , Int#
start Int# -> Int# -> Int#
+# Double -> Int#
forall a. Prim a => a -> Int#
sizeOf# (Double
forall a. HasCallStack => a
undefined :: Double)
  , Int#
start Int# -> Int# -> Int#
+# Double -> Int#
forall a. Prim a => a -> Int#
sizeOf# (Double
forall a. HasCallStack => a
undefined :: Double) Int# -> Int# -> Int#
+# Double -> Int#
forall a. Prim a => a -> Int#
sizeOf# (Double
forall a. HasCallStack => a
undefined :: Double)
  #)
  where
    start :: Int#
start = Int#
idx Int# -> Int# -> Int#
*# SortTriple -> Int#
forall a. Prim a => a -> Int#
sizeOf# (SortTriple
forall a. HasCallStack => a
undefined :: SortTriple)

instance Prim SortTriple where
  sizeOf# :: SortTriple -> Int#
sizeOf# SortTriple
_
    =  Double -> Int#
forall a. Prim a => a -> Int#
sizeOf# (Double
forall a. HasCallStack => a
undefined :: Double)
    Int# -> Int# -> Int#
+# Double -> Int#
forall a. Prim a => a -> Int#
sizeOf# (Double
forall a. HasCallStack => a
undefined :: Double)
    Int# -> Int# -> Int#
+# Word64 -> Int#
forall a. Prim a => a -> Int#
sizeOf# (Word64
forall a. HasCallStack => a
undefined :: Word64)

  alignment# :: SortTriple -> Int#
alignment# SortTriple
_
    = Word64 -> Int#
forall a. Prim a => a -> Int#
alignment# (Word64
forall a. HasCallStack => a
undefined :: Word64)

  indexByteArray# :: ByteArray# -> Int# -> SortTriple
  indexByteArray# :: ByteArray# -> Int# -> SortTriple
indexByteArray# ByteArray#
arr Int#
idx =
    Double -> Double -> Word64 -> SortTriple
SortTriple
      (Double# -> Double
D#   (ByteArray# -> Int# -> Double#
indexWord8ArrayAsDouble# ByteArray#
arr Int#
ia))
      (Double# -> Double
D#   (ByteArray# -> Int# -> Double#
indexWord8ArrayAsDouble# ByteArray#
arr Int#
ib))
      (Word64# -> Word64
W64# (ByteArray# -> Int# -> Word64#
indexWord8ArrayAsWord64# ByteArray#
arr Int#
ic))
    where
      !(# Int#
ia, Int#
ib, Int#
ic #) = Int# -> (# Int#, Int#, Int# #)
idxs Int#
idx

  readByteArray# :: MutableByteArray# s -> Int# -> State# s -> (# State# s, SortTriple #)
  readByteArray# :: forall s.
MutableByteArray# s
-> Int# -> State# s -> (# State# s, SortTriple #)
readByteArray# MutableByteArray# s
arr Int#
idx State# s
s1 =
    case MutableByteArray# s -> Int# -> State# s -> (# State# s, Double# #)
forall d.
MutableByteArray# d -> Int# -> State# d -> (# State# d, Double# #)
readWord8ArrayAsDouble# MutableByteArray# s
arr Int#
ia State# s
s1 of
      (# State# s
s2, Double#
a #) ->
        case MutableByteArray# s -> Int# -> State# s -> (# State# s, Double# #)
forall d.
MutableByteArray# d -> Int# -> State# d -> (# State# d, Double# #)
readWord8ArrayAsDouble# MutableByteArray# s
arr Int#
ib State# s
s2 of
          (# State# s
s3, Double#
b #) ->
            case MutableByteArray# s -> Int# -> State# s -> (# State# s, Word64# #)
forall d.
MutableByteArray# d -> Int# -> State# d -> (# State# d, Word64# #)
readWord8ArrayAsWord64# MutableByteArray# s
arr Int#
ic State# s
s3 of
              (# State# s
s4, Word64#
c #) -> (# State# s
s4, Double -> Double -> Word64 -> SortTriple
SortTriple (Double# -> Double
D# Double#
a) (Double# -> Double
D# Double#
b) (Word64# -> Word64
W64# Word64#
c) #)
    where
      !(# Int#
ia, Int#
ib, Int#
ic #) = Int# -> (# Int#, Int#, Int# #)
idxs Int#
idx

  writeByteArray# :: MutableByteArray# s -> Int# -> SortTriple -> State# s -> State# s
  writeByteArray# :: forall s.
MutableByteArray# s -> Int# -> SortTriple -> State# s -> State# s
writeByteArray# MutableByteArray# s
arr Int#
idx (SortTriple (D# Double#
a) (D# Double#
b) (W64# Word64#
c)) State# s
s1 =
    case MutableByteArray# s -> Int# -> Double# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Double# -> State# d -> State# d
writeWord8ArrayAsDouble# MutableByteArray# s
arr Int#
ia Double#
a State# s
s1 of
      State# s
s2 ->
        case MutableByteArray# s -> Int# -> Double# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Double# -> State# d -> State# d
writeWord8ArrayAsDouble# MutableByteArray# s
arr Int#
ib Double#
b State# s
s2 of
          State# s
s3 ->
            MutableByteArray# s -> Int# -> Word64# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word64# -> State# d -> State# d
writeWord8ArrayAsWord64# MutableByteArray# s
arr Int#
ic Word64#
c State# s
s3
    where
      !(# Int#
ia, Int#
ib, Int#
ic #) = Int# -> (# Int#, Int#, Int# #)
idxs Int#
idx

  setByteArray#
    :: MutableByteArray# s
    -> Int# -- ^ offset
    -> Int# -- ^ length
    -> SortTriple
    -> State# s
    -> State# s
  setByteArray# :: forall s.
MutableByteArray# s
-> Int# -> Int# -> SortTriple -> State# s -> State# s
setByteArray# = MutableByteArray# s
-> Int# -> Int# -> SortTriple -> State# s -> State# s
forall a s.
Prim a =>
MutableByteArray# s -> Int# -> Int# -> a -> State# s -> State# s
defaultSetByteArray#

  indexOffAddr# :: Addr# -> Int# -> SortTriple
  indexOffAddr# :: Addr# -> Int# -> SortTriple
indexOffAddr# Addr#
addr Int#
idx =
    Double -> Double -> Word64 -> SortTriple
SortTriple
      (Double# -> Double
D#   (Addr# -> Int# -> Double#
indexDoubleOffAddr# Addr#
addr Int#
ia))
      (Double# -> Double
D#   (Addr# -> Int# -> Double#
indexDoubleOffAddr# Addr#
addr Int#
ib))
      (Word64# -> Word64
W64# (Addr# -> Int# -> Word64#
indexWord64OffAddr# Addr#
addr Int#
ic))
    where
      !(# Int#
ia, Int#
ib, Int#
ic #) = Int# -> (# Int#, Int#, Int# #)
idxs Int#
idx

  readOffAddr# :: Addr# -> Int# -> State# s -> (# State# s, SortTriple #)
  readOffAddr# :: forall s. Addr# -> Int# -> State# s -> (# State# s, SortTriple #)
readOffAddr# Addr#
addr Int#
idx State# s
s1 =
    case Addr# -> Int# -> State# s -> (# State# s, Double# #)
forall d. Addr# -> Int# -> State# d -> (# State# d, Double# #)
readDoubleOffAddr# Addr#
addr Int#
ia State# s
s1 of
      (# State# s
s2, Double#
a #) ->
        case Addr# -> Int# -> State# s -> (# State# s, Double# #)
forall d. Addr# -> Int# -> State# d -> (# State# d, Double# #)
readDoubleOffAddr# Addr#
addr Int#
ib State# s
s2 of
          (# State# s
s3, Double#
b #) ->
            case Addr# -> Int# -> State# s -> (# State# s, Word64# #)
forall d. Addr# -> Int# -> State# d -> (# State# d, Word64# #)
readWord64OffAddr# Addr#
addr Int#
ic State# s
s3 of
              (# State# s
s4, Word64#
c #) -> (# State# s
s4, Double -> Double -> Word64 -> SortTriple
SortTriple (Double# -> Double
D# Double#
a) (Double# -> Double
D# Double#
b) (Word64# -> Word64
W64# Word64#
c) #)
    where
      !(# Int#
ia, Int#
ib, Int#
ic #) = Int# -> (# Int#, Int#, Int# #)
idxs Int#
idx

  writeOffAddr# :: Addr# -> Int# -> SortTriple -> State# s -> State# s
  writeOffAddr# :: forall s. Addr# -> Int# -> SortTriple -> State# s -> State# s
writeOffAddr# Addr#
addr Int#
idx (SortTriple (D# Double#
a) (D# Double#
b) (W64# Word64#
c)) State# s
s1 =
    case Addr# -> Int# -> Double# -> State# s -> State# s
forall d. Addr# -> Int# -> Double# -> State# d -> State# d
writeDoubleOffAddr# Addr#
addr Int#
ia Double#
a State# s
s1 of
      State# s
s2 ->
        case Addr# -> Int# -> Double# -> State# s -> State# s
forall d. Addr# -> Int# -> Double# -> State# d -> State# d
writeDoubleOffAddr# Addr#
addr Int#
ib Double#
b State# s
s2 of
          State# s
s3 ->
            Addr# -> Int# -> Word64# -> State# s -> State# s
forall d. Addr# -> Int# -> Word64# -> State# d -> State# d
writeWord64OffAddr# Addr#
addr Int#
ic Word64#
c State# s
s3
    where
      !(# Int#
ia, Int#
ib, Int#
ic #) = Int# -> (# Int#, Int#, Int# #)
idxs Int#
idx

  setOffAddr#
    :: Addr#
    -> Int# -- ^ offset
    -> Int# -- ^ length
    -> SortTriple
    -> State# s
    -> State# s
  setOffAddr# :: forall s.
Addr# -> Int# -> Int# -> SortTriple -> State# s -> State# s
setOffAddr# = Addr# -> Int# -> Int# -> SortTriple -> State# s -> State# s
forall a s.
Prim a =>
Addr# -> Int# -> Int# -> a -> State# s -> State# s
defaultSetOffAddr#