packages feed

tensort-1.0.1.2: src/Data/Tensort/Utils/Render.hs

-- | Module for rendering a sorted list of Bits from a list of TensorStacks
--
--   Functions ending in "B" are for sorting Bits in a base (non-recursive)
--   Tensort variant
--
--   Functions ending in "R" are for sorting Records when used in a recursive
--   Tensort variant
--
--   TODO: See if we can clean up the type conversion here
module Data.Tensort.Utils.Render (getSortedBitsFromTensor) where

import Data.Maybe (isNothing)
import Data.Tensort.Utils.Compose (createTensor)
import Data.Tensort.Utils.Types
  ( Bit,
    BitR,
    Memory (..),
    MemoryR (..),
    SBit (..),
    SMemory (..),
    STensor (..),
    STensorStack,
    SortAlg,
    Sortable (..),
    Tensor,
    TensorR,
    TensorStack,
    TensorStackR,
    fromJust,
    fromSTensorBit,
    fromSTensorRec,
    fromSortBit,
    fromSortRec,
  )

-- | Compile a sorted list of Bits from a list of TensorStacks

-- | ==== __Examples__
-- >>> import Data.Tensort.Subalgorithms.Bubblesort (bubblesort)
-- >>> getSortedBitsFromTensor bubblesort (STensorBit ([(0,5),(1,7)],ByteMem [[1,5],[3,7]]))
-- [SBitBit 1,SBitBit 3,SBitBit 5,SBitBit 7]
-- >>> getSortedBitsFromTensor bubblesort (STensorBit ([(0,8),(1,18)],TensorMem [([(0,7),(1,8)],TensorMem [([(0,3),(1,7)],ByteMem [[1,3],[5,7]]),([(0,4),(1,8)],ByteMem [[2,4],[6,8]])]),([(1,17),(0,18)],TensorMem [([(0,13),(1,18)],ByteMem [[11,13],[15,18]]),([(0,14),(1,17)],ByteMem [[12,14],[16,17]])])]))
-- [SBitBit 1,SBitBit 2,SBitBit 3,SBitBit 4,SBitBit 5,SBitBit 6,SBitBit 7,SBitBit 8,SBitBit 11,SBitBit 12,SBitBit 13,SBitBit 14,SBitBit 15,SBitBit 16,SBitBit 17,SBitBit 18]
getSortedBitsFromTensor :: SortAlg -> STensorStack -> [SBit]
getSortedBitsFromTensor subAlg (STensorBit tensorRaw) =
  getSortedBitsFromTensorB subAlg tensorRaw
getSortedBitsFromTensor subAlg (STensorRec tensorRaw) =
  getSortedBitsFromTensorR subAlg tensorRaw

getSortedBitsFromTensorB :: SortAlg -> TensorStack -> [SBit]
getSortedBitsFromTensorB subAlg tensorRaw = acc tensorRaw []
  where
    acc :: TensorStack -> [SBit] -> [SBit]
    acc tensor sortedBits = do
      let (nextBit, tensor') = removeTopBitFromTensorB subAlg tensor
      let nextBit' = SBitBit nextBit
      if isNothing tensor'
        then nextBit' : sortedBits
        else do
          acc (fromJust tensor') (nextBit' : sortedBits)

getSortedBitsFromTensorR :: SortAlg -> TensorStackR -> [SBit]
getSortedBitsFromTensorR subAlg tensorRaw = acc tensorRaw []
  where
    acc :: TensorStackR -> [SBit] -> [SBit]
    acc tensor sortedBits = do
      let (nextBit, tensor') = removeTopBitFromTensorR subAlg tensor
      let nextBit' = SBitRec nextBit
      if isNothing tensor'
        then nextBit' : sortedBits
        else do
          acc (fromJust tensor') (nextBit' : sortedBits)

-- | For use in compiling a list of Tensors into a sorted list of Bits
--
-- | Removes the top Bit from a Tensor, rebalances the Tensor and returns
--   the removed Bit along with the rebalanced Tensor

-- | ==== __Examples__
--   >>> import Data.Tensort.Subalgorithms.Bubblesort (bubblesort)
--   >>> removeTopBitFromTensorB bubblesort ([(0,5),(1,7)],ByteMem [[1,5],[3,7]])
--   (7,Just ([(1,3),(0,5)],ByteMem [[1,5],[3]]))
removeTopBitFromTensorB :: SortAlg -> Tensor -> (Bit, Maybe Tensor)
removeTopBitFromTensorB subAlg (register, memory) = do
  let topRecord = last register
  let topAddress = fst topRecord
  let (topBit, memory') = removeBitFromMemoryB subAlg memory topAddress
  if isNothing memory'
    then (topBit, Nothing)
    else
      ( topBit,
        Just
          ( fromSTensorBit
              ( createTensor
                  subAlg
                  (SMemoryBit (fromJust memory'))
              )
          )
      )

removeTopBitFromTensorR :: SortAlg -> TensorR -> (BitR, Maybe TensorR)
removeTopBitFromTensorR subAlg (register, memory) = do
  let topRecord = last register
  let topAddress = fst topRecord
  let (topBit, memory') = removeBitFromMemoryR subAlg memory topAddress
  if isNothing memory'
    then (topBit, Nothing)
    else
      ( topBit,
        Just
          ( fromSTensorRec
              ( createTensor
                  subAlg
                  (SMemoryRec (fromJust memory'))
              )
          )
      )

removeBitFromMemoryB :: SortAlg -> Memory -> Int -> (Bit, Maybe Memory)
removeBitFromMemoryB subAlg (ByteMem bytes) i = do
  let topByte = bytes !! i
  let topBit = last topByte
  let topByte' = init topByte
  case length topByte' of
    0 -> do
      let bytes' = take i bytes ++ drop (i + 1) bytes
      if null bytes'
        then (topBit, Nothing)
        else (topBit, Just (ByteMem bytes'))
    1 -> do
      let bytes' = take i bytes ++ [topByte'] ++ drop (i + 1) bytes
      (topBit, Just (ByteMem bytes'))
    _ -> do
      let topByte'' = fromSortBit (subAlg (SortBit topByte'))
      let bytes' = take i bytes ++ [topByte''] ++ drop (i + 1) bytes
      (topBit, Just (ByteMem bytes'))
removeBitFromMemoryB subAlg (TensorMem tensors) i = do
  let topTensor = tensors !! i
  let (topBit, topTensor') = removeTopBitFromTensorB subAlg topTensor
  if isNothing topTensor'
    then do
      let tensors' = take i tensors ++ drop (i + 1) tensors
      if null tensors'
        then (topBit, Nothing)
        else (topBit, Just (TensorMem tensors'))
    else do
      let tensors' =
            take i tensors ++ [fromJust topTensor'] ++ drop (i + 1) tensors
      (topBit, Just (TensorMem tensors'))

removeBitFromMemoryR :: SortAlg -> MemoryR -> Int -> (BitR, Maybe MemoryR)
removeBitFromMemoryR subAlg (ByteMemR bytesR) i = do
  let topByteR = bytesR !! i
  let topBitR = last topByteR
  let topByteR' = init topByteR
  case length topByteR' of
    0 -> do
      let bytesR' = take i bytesR ++ drop (i + 1) bytesR
      if null bytesR'
        then (topBitR, Nothing)
        else (topBitR, Just (ByteMemR bytesR'))
    1 -> do
      let bytesR' = take i bytesR ++ [topByteR'] ++ drop (i + 1) bytesR
      (topBitR, Just (ByteMemR bytesR'))
    _ -> do
      let topByteR'' = fromSortRec (subAlg (SortRec topByteR'))
      let bytesR' = take i bytesR ++ [topByteR''] ++ drop (i + 1) bytesR
      (topBitR, Just (ByteMemR bytesR'))
removeBitFromMemoryR subAlg (TensorMemR tensorsR) i = do
  let topTensorR = tensorsR !! i
  let (topBitR, topTensorR') = removeTopBitFromTensorR subAlg topTensorR
  if isNothing topTensorR'
    then do
      let tensorsR' = take i tensorsR ++ drop (i + 1) tensorsR
      if null tensorsR'
        then (topBitR, Nothing)
        else (topBitR, Just (TensorMemR tensorsR'))
    else do
      let tensorsR' =
            take i tensorsR ++ [fromJust topTensorR'] ++ drop (i + 1) tensorsR
      (topBitR, Just (TensorMemR tensorsR'))