tensort-1.1.0.0: src/Data/Tensort/Utils/Compose.hs
-- | Module for creating Tensors from Bytes and Tensors.
module Data.Tensort.Utils.Compose
( createInitialTensors,
createTensor,
)
where
import Data.Tensort.Utils.SortRecs (sortRecs)
import Data.Tensort.Utils.Split (splitEvery)
import Data.Tensort.Utils.Types
( Bit,
Byte,
Memory (..),
Record (..),
Register,
SortAlg,
Tensor (..),
TensortProps (..),
fromRecord,
fromTensor,
)
-- | Convert a list of Bytes to a list of TensorStacks.
-- | This is accomplished by making a Tensor for each Byte, converting that
-- Tensor into a TensorStack (these are equivalent terms - see type
-- definitions for more info) and collating the TensorStacks into a list.
-- | ==== __Examples__
-- >>> import Data.Tensort.Subalgorithms.Bubblesort (bubblesort)
-- >>> import Data.Tensort.Utils.MkTsProps (mkTsProps)
-- >>> createInitialTensors (mkTsProps 2 bubblesort) [[2,4] :: [Int],[6,8] :: [Int],[1,3] :: [Int],[5,7] :: [Int]]
-- [Tensor ([Record (3,0),Record (7,1)],ByteMem [[1,3],[5,7]]),Tensor ([Record (4,0),Record (8,1)],ByteMem [[2,4],[6,8]])]
createInitialTensors :: (Ord a) => TensortProps a -> [Byte a] -> [Tensor a]
createInitialTensors tsProps bytes =
foldr acc [] (splitEvery (bytesize tsProps) bytes)
where
acc byte tensorStacks =
tensorStacks
++ [tensorStack]
where
tensorStack = getTensorFromBytes subAlg byte
subAlg = subAlgorithm tsProps
-- | Create a Tensor from a Memory.
--
-- Aliases to getTensorFromBytes for ByteMem and getTensorFromTensors for
-- TensorMem.
createTensor :: (Ord a) => SortAlg a -> Memory a -> Tensor a
createTensor subAlg (ByteMem bytes) = getTensorFromBytes subAlg bytes
createTensor subAlg (TensorMem tensors) = getTensorFromTensors subAlg tensors
-- | Convert a list of Bytes to a Tensor.
-- | We do this by loading the list of Bytes into the new Tensor's Memory
-- and adding a sorted Register containing References to each Byte in Memory.
-- | Each Record contains an Address pointing to the index of the referenced
-- Byte and a TopBit containing the value of the last (i.e. highest) Bit in
-- the referenced Byte.
-- | The Register is sorted by the TopBits of each Record.
-- | ==== __Examples__
-- >>> import Data.Tensort.Subalgorithms.Bubblesort (bubblesort)
-- >>> getTensorFromBytes bubblesort [[2,4,6,8] :: [Int],[1,3,5,7] :: [Int]]
-- Tensor ([Record (7,1),Record (8,0)],ByteMem [[2,4,6,8],[1,3,5,7]])
getTensorFromBytes :: (Ord a) => SortAlg a -> [Byte a] -> Tensor a
getTensorFromBytes subAlg bytes = Tensor (register', ByteMem bytes)
where
register' = sortRecs subAlg $ map Record register
register = acc bytes [] 0
acc [] regi _ = regi
acc ([] : remainingBytes) regi i = acc remainingBytes regi (i + 1)
acc (byte : remainingBytes) regi i =
acc remainingBytes (regi ++ [record]) (i + 1)
where
record = (last byte, i :: Int)
-- | Create a TensorStack with the collated and sorted References from the
-- Tensors as its Register and the original Tensors as its Memory.
-- | ==== __Examples__
-- >>> import Data.Tensort.Subalgorithms.Bubblesort (bubblesort)
-- >>> getTensorFromTensors bubblesort [Tensor ([Record (0,13),Record (1,18)],ByteMem [[11,13] :: [Int],[15,18] :: [Int]]),Tensor ([Record (1,14),Record (0,17)],ByteMem [[16,17] :: [Int],[12,14] :: [Int]])]
-- Tensor ([Record (0,1),Record (1,0)],TensorMem [Tensor ([Record (0,13),Record (1,18)],ByteMem [[11,13],[15,18]]),Tensor ([Record (1,14),Record (0,17)],ByteMem [[16,17],[12,14]])])
getTensorFromTensors :: (Ord a) => SortAlg a -> [Tensor a] -> Tensor a
getTensorFromTensors subAlg tensors = Tensor (sortedRegister, TensorMem tensors)
where
sortedRegister = sortRecs subAlg unsortedRegister
unsortedRegister = getRegisterFromTensors tensors
-- | Used in creating a Register for a newly-created Tensor which encloses
-- other Tensors.
--
-- Takes a list of Tensors to be processed into the enclosing Tensor's
-- memory. For each Tensor in the list, produces a Record by combining the
-- top bit of the Tensor with an index value for its Address.
-- | Note that this output is not sorted. Sorting is done in the
-- getTensorFromTensors function.
-- | ==== __Examples__
-- >>> getRegisterFromTensors [Tensor ([Record (0 :: Int,13),Record (1 :: Int,18)],ByteMem [[11,13] :: [Int],[15,18] :: [Int]]),Tensor ([Record (0 :: Int,14),Record (1 :: Int,17)],ByteMem [[12,14] :: [Int],[16,17] :: [Int]]),Tensor ([Record (0 :: Int,3),Record (1 :: Int,7)],ByteMem [[1,3] :: [Int],[5,7] :: [Int]]),Tensor ([Record (0 :: Int,4),Record (1 :: Int,8)],ByteMem [[2,4] :: [Int],[6,8] :: [Int]])]
-- [Record (1,0),Record (1,1),Record (1,2),Record (1,3)]
getRegisterFromTensors :: [Tensor a] -> [Record a]
getRegisterFromTensors tensors = acc tensors []
where
acc :: [Tensor a] -> [Record a] -> [Record a]
acc [] records = records
acc (Tensor ([], _) : remainingTensors) records = acc remainingTensors records
acc (tensor : remainingTensors) records =
acc remainingTensors $ records ++ [Record record]
where
record = (topBit, i)
i = length records
topBit = getTopBitFromTensorStack (fromTensor tensor)
-- | Get the top Bit from a TensorStack.
-- | The top Bit is the last Bit in the last Byte referenced in the last record
-- of the Tensor referenced in the last record of the last Tensor of...
-- and so on until you reach the top level of the TensorStack.
-- | This is also expected to be the highest value in the TensorStack.
-- | ==== __Examples__
-- >>> getTopBitFromTensorStack ([Record (0 :: Int,28),Record (1 :: Int,38)],TensorMem [Tensor ([Record (0 :: Int,27),Record (1 :: Int,28)],TensorMem [Tensor ([Record (0 :: Int,23),Record (1 :: Int,27)],ByteMem [[21,23] :: [Int],[25,27] :: [Int]]),Tensor ([Record (0 :: Int,24),Record (1 :: Int,28)],ByteMem [[22,24] :: [Int],[26,28] :: [Int]])]),Tensor ([Record (1 :: Int,37),Record (0 :: Int,38)],TensorMem [Tensor ([Record (0 :: Int,33),Record (1 :: Int,38)],ByteMem [[31,33] :: [Int],[35,38] :: [Int]]),Tensor ([Record (0 :: Int,34),Record (1 :: Int,37)],ByteMem [[32,14] :: [Int],[36,37] :: [Int]])])])
-- 1
getTopBitFromTensorStack :: (Register a, Memory a) -> Bit a
getTopBitFromTensorStack tensor =
let register = fst tensor
topRecord = last register
topBit = fst (fromRecord topRecord)
in topBit