-- | This module provides variations of the Tensort algorithm using the
--   Sortable type
module Data.Tensort.Tensort
  ( tensort,
    tensortB4,
    tensortBN,
    tensortBL,
  )
where

import Data.Tensort.Subalgorithms.Bubblesort (bubblesort)
import Data.Tensort.Utils.Compose (createInitialTensors)
import Data.Tensort.Utils.Convert (rawToBytes)
import Data.Tensort.Utils.LogNat (getLnBytesize)
import Data.Tensort.Utils.MkTsProps (mkTsProps)
import Data.Tensort.Utils.RandomizeList (randomizeList)
import Data.Tensort.Utils.Reduce (reduceTensorStacks)
import Data.Tensort.Utils.Render (getSortedBitsFromTensor)
import Data.Tensort.Utils.Types
  ( Sortable (..),
    TensortProps (..),
    fromSBitBits,
    fromSBitRecs,
  )

-- | Sort a Sortable list using a custom Tensort algorithm
--
--   Takes TensortProps and a Sortable and returns a sorted Sortable

-- | ==== __Examples__
-- >>> import Data.Tensort.Subalgorithms.Bubblesort (bubblesort)
-- >>> import Data.Tensort.Utils.MkTsProps (mkTsProps)
-- >>> tensort (mkTsProps 2 bubblesort) (SortBit [16, 23, 4, 8, 15, 42])
-- SortBit [4,8,15,16,23,42]
--
-- >>> tensort (mkTsProps 2 bubblesort) (SortRec [(1, 16), (5, 23), (2, 4) ,(3, 8), (0, 15) , (4, 42)])
-- SortRec [(2,4),(3,8),(0,15),(1,16),(5,23),(4,42)]
tensort :: TensortProps -> Sortable -> Sortable
tensort :: TensortProps -> Sortable -> Sortable
tensort TensortProps
_ (SortBit []) = [Bit] -> Sortable
SortBit []
tensort TensortProps
_ (SortBit [Bit
x]) = [Bit] -> Sortable
SortBit [Bit
x]
tensort TensortProps
tsProps (SortBit [Bit
x, Bit
y]) = TensortProps -> Sortable -> Sortable
subAlgorithm TensortProps
tsProps ([Bit] -> Sortable
SortBit [Bit
x, Bit
y])
tensort TensortProps
tsProps (SortBit [Bit]
xs) = do
  let bits :: Sortable
bits = Bit -> Sortable -> Sortable
randomizeList Bit
143 ([Bit] -> Sortable
SortBit [Bit]
xs)
  let bytes :: SBytes
bytes = TensortProps -> Sortable -> SBytes
rawToBytes TensortProps
tsProps Sortable
bits
  let tensorStacks :: STensors
tensorStacks = TensortProps -> SBytes -> STensors
createInitialTensors TensortProps
tsProps SBytes
bytes
  let topTensor :: STensorStack
topTensor = TensortProps -> STensors -> STensorStack
reduceTensorStacks TensortProps
tsProps STensors
tensorStacks
  [SBit] -> Sortable
fromSBitBits ((Sortable -> Sortable) -> STensorStack -> [SBit]
getSortedBitsFromTensor (TensortProps -> Sortable -> Sortable
subAlgorithm TensortProps
tsProps) STensorStack
topTensor)
tensort TensortProps
_ (SortRec []) = [Record] -> Sortable
SortRec []
tensort TensortProps
_ (SortRec [Record
x]) = [Record] -> Sortable
SortRec [Record
x]
tensort TensortProps
tsProps (SortRec [Record
x, Record
y]) = TensortProps -> Sortable -> Sortable
subAlgorithm TensortProps
tsProps ([Record] -> Sortable
SortRec [Record
x, Record
y])
tensort TensortProps
tsProps (SortRec [Record]
xs) = do
  let recs :: Sortable
recs = Bit -> Sortable -> Sortable
randomizeList Bit
143 ([Record] -> Sortable
SortRec [Record]
xs)
  let bytes :: SBytes
bytes = TensortProps -> Sortable -> SBytes
rawToBytes TensortProps
tsProps Sortable
recs
  let tensorStacks :: STensors
tensorStacks = TensortProps -> SBytes -> STensors
createInitialTensors TensortProps
tsProps SBytes
bytes
  let topTensor :: STensorStack
topTensor = TensortProps -> STensors -> STensorStack
reduceTensorStacks TensortProps
tsProps STensors
tensorStacks
  [SBit] -> Sortable
fromSBitRecs ((Sortable -> Sortable) -> STensorStack -> [SBit]
getSortedBitsFromTensor (TensortProps -> Sortable -> Sortable
subAlgorithm TensortProps
tsProps) STensorStack
topTensor)

-- | Sort a Sortable list using a Standard Tensort algorithm with a 4-Bit
--   Bytesize

-- | ==== __Examples__
-- >>> tensortB4 (SortBit [16, 23, 4, 8, 15, 42])
-- SortBit [4,8,15,16,23,42]
--
-- >>> tensortB4 (SortRec [(1, 16), (5, 23), (2, 4) ,(3, 8), (0, 15) , (4, 42)])
-- SortRec [(2,4),(3,8),(0,15),(1,16),(5,23),(4,42)]
tensortB4 :: Sortable -> Sortable
tensortB4 :: Sortable -> Sortable
tensortB4 = TensortProps -> Sortable -> Sortable
tensort (Bit -> (Sortable -> Sortable) -> TensortProps
mkTsProps Bit
4 Sortable -> Sortable
bubblesort)

-- | Sort a Sortable list using a Standard Tensort algorithm with a custom
--   Bytesize

-- | ==== __Examples__
-- >>> tensortBN 3 (SortBit [16, 23, 4, 8, 15, 42])
-- SortBit [4,8,15,16,23,42]
--
-- >>> tensortBN 3 (SortRec [(1, 16), (5, 23), (2, 4) ,(3, 8), (0, 15) , (4, 42)])
-- SortRec [(2,4),(3,8),(0,15),(1,16),(5,23),(4,42)]
tensortBN :: Int -> Sortable -> Sortable
tensortBN :: Bit -> Sortable -> Sortable
tensortBN Bit
n = TensortProps -> Sortable -> Sortable
tensort (Bit -> (Sortable -> Sortable) -> TensortProps
mkTsProps Bit
n Sortable -> Sortable
bubblesort)

-- | Sort a Sortable list using a Standard Logarithmic Tensort algorithm

-- | ==== __Examples__
-- >>> tensortBL (SortBit [16, 23, 4, 8, 15, 42])
-- SortBit [4,8,15,16,23,42]
--
-- >>> tensortBL (SortRec [(1, 16), (5, 23), (2, 4) ,(3, 8), (0, 15) , (4, 42)])
-- SortRec [(2,4),(3,8),(0,15),(1,16),(5,23),(4,42)]
tensortBL :: Sortable -> Sortable
tensortBL :: Sortable -> Sortable
tensortBL Sortable
xs = TensortProps -> Sortable -> Sortable
tensort (Bit -> (Sortable -> Sortable) -> TensortProps
mkTsProps (Sortable -> Bit
getLnBytesize Sortable
xs) Sortable -> Sortable
bubblesort) Sortable
xs