packages feed

tensort (empty) → 0.1.0.0

raw patch · 25 files changed

+930/−0 lines, 25 filesdep +basedep +mtldep +random

Dependencies added: base, mtl, random, random-shuffle, tensort, time

Files

+ CHANGELOG.md view
@@ -0,0 +1,5 @@+# Revision history for tensort++## 0.1.0.0 -- 2024-05-30++* First version. Released to an eager world.
+ LICENSE view
@@ -0,0 +1,21 @@+MIT License++Copyright (c) 2024 Kyle Beechly++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.
+ app/Main.hs view
@@ -0,0 +1,74 @@+module Main where++import Data.Tensort.OtherSorts.Mergesort (mergesort)+import Data.Tensort.OtherSorts.Quicksort (quicksort)+import Data.Tensort.Robustsort (robustsortB, robustsortM, robustsortP)+import Data.Tensort.Subalgorithms.Bubblesort (bubblesort)+import Data.Tensort.Tensort (tensortBasic2Bit, tensortBasic3Bit, tensortBasic4Bit)+import Data.Tensort.Utils.RandomizeList (randomizeList)+import Data.Tensort.Utils.Types (Sortable (..), fromSortInt)+import Data.Time.Clock++unsortedInts :: [Int]+unsortedInts = [2, 5, 10, 4, 15, 11, 7, 14, 16, 6, 13, 3, 8, 9, 12, 1]++unsortedInts52 :: Sortable+unsortedInts52 = randomizeList (SortInt [1 .. 52]) 143++unsortedInts1000 :: Sortable+unsortedInts1000 = randomizeList (SortInt [1 .. 1000]) 143++unsortedInts10000 :: Sortable+unsortedInts10000 = randomizeList (SortInt [1 .. 10000]) 143++unsortedInts100000 :: Sortable+unsortedInts100000 = randomizeList (SortInt [1 .. 100000]) 143++main :: IO ()+main = do+  printTime unsortedInts52+  printTime unsortedInts1000+  printTime unsortedInts10000+  printTime unsortedInts100000++printTime :: Sortable -> IO ()+printTime l = do+  putStr " Algorithm   | Time         | n ="+  startTensort2Bit <- getCurrentTime+  putStrLn (" " ++ show (length (tensortBasic2Bit (fromSortInt l))))+  endTensort2Bit <- getCurrentTime+  putStr (" Tensort2Bit | " ++ show (diffUTCTime endTensort2Bit startTensort2Bit) ++ " | ")+  startTensort3Bit <- getCurrentTime+  putStrLn ("    " ++ show (length (tensortBasic3Bit (fromSortInt l))))+  endTensort3Bit <- getCurrentTime+  putStr (" Tensort3Bit | " ++ show (diffUTCTime endTensort3Bit startTensort3Bit) ++ " | ")+  startTensort4Bit <- getCurrentTime+  putStrLn ("    " ++ show (length (tensortBasic4Bit (fromSortInt l))))+  endTensort4Bit <- getCurrentTime+  putStr (" Tensort4Bit | " ++ show (diffUTCTime endTensort4Bit startTensort4Bit) ++ " | ")+  startRSortP <- getCurrentTime+  putStrLn ("    " ++ show (length (robustsortP (fromSortInt l))))+  endRSortP <- getCurrentTime+  putStr (" RobustsortP | " ++ show (diffUTCTime endRSortP startRSortP) ++ " | ")+  startRSortB <- getCurrentTime+  putStrLn ("    " ++ show (length (robustsortB (fromSortInt l))))+  endRSortB <- getCurrentTime+  putStr (" RobustsortB | " ++ show (diffUTCTime endRSortB startRSortB) ++ " | ")+  startRSortM <- getCurrentTime+  putStrLn ("    " ++ show (length (robustsortM (fromSortInt l))))+  endRSortM <- getCurrentTime+  putStr (" RobustsortM | " ++ show (diffUTCTime endRSortM startRSortM) ++ " | ")+  startMergesort <- getCurrentTime+  putStrLn ("    " ++ show (length (fromSortInt (mergesort l))))+  endMergesort <- getCurrentTime+  putStr (" Mergesort   | " ++ show (diffUTCTime endMergesort startMergesort) ++ " | ")+  startQuicksort <- getCurrentTime+  putStrLn ("    " ++ show (length (fromSortInt (quicksort l))))+  endQuicksort <- getCurrentTime+  putStr (" Quicksort   | " ++ show (diffUTCTime endQuicksort startQuicksort) ++ " | ")+  startBubblesort <- getCurrentTime+  putStrLn ("    " ++ show (length (fromSortInt (bubblesort l))))+  endBubblesort <- getCurrentTime+  putStr (" Bubblesort  | " ++ show (diffUTCTime endBubblesort startBubblesort) ++ " | ")+  putStrLn ("    " ++ show (length (fromSortInt (bubblesort l))))+  putStrLn "----------------------------------------------------------"
+ src/Data/Tensort.hs view
@@ -0,0 +1,6 @@+module Data.Tensort+  ( module Data.Tensort.Tensort,+  )+where++import Data.Tensort.Tensort
+ src/Data/Tensort/OtherSorts/Mergesort.hs view
@@ -0,0 +1,44 @@+module Data.Tensort.OtherSorts.Mergesort (mergesort) where++import Data.Tensort.Utils.ComparisonFunctions (lessThanInt, lessThanRecord)+import Data.Tensort.Utils.Types (Record, Sortable (..))++mergesort :: Sortable -> Sortable+mergesort (SortInt xs) = SortInt (mergesortInts xs)+mergesort (SortRec xs) = SortRec (mergesortRecs xs)++mergesortInts :: [Int] -> [Int]+mergesortInts = mergeAllInts . map (: [])+  where+    mergeAllInts [] = []+    mergeAllInts [x] = x+    mergeAllInts [x, y] = mergeInts x y+    mergeAllInts remaningElements = mergeAllInts (mergePairs remaningElements)++    mergePairs (x : y : remaningElements) = mergeInts x y : mergePairs remaningElements+    mergePairs x = x++mergeInts :: [Int] -> [Int] -> [Int]+mergeInts [] y = y+mergeInts x [] = x+mergeInts (x : xs) (y : ys)+  | lessThanInt x y = x : mergeInts xs (y : ys)+  | otherwise = y : mergeInts (x : xs) ys++mergesortRecs :: [Record] -> [Record]+mergesortRecs = mergeAllRecs . map (: [])+  where+    mergeAllRecs [] = []+    mergeAllRecs [x] = x+    mergeAllRecs [x, y] = mergeRecs x y+    mergeAllRecs remaningElements = mergeAllRecs (mergePairs remaningElements)++    mergePairs (x : y : remaningElements) = mergeRecs x y : mergePairs remaningElements+    mergePairs x = x++mergeRecs :: [Record] -> [Record] -> [Record]+mergeRecs [] y = y+mergeRecs x [] = x+mergeRecs (x : xs) (y : ys)+  | lessThanRecord x y = x : mergeRecs xs (y : ys)+  | otherwise = y : mergeRecs (x : xs) ys
+ src/Data/Tensort/OtherSorts/Quicksort.hs view
@@ -0,0 +1,16 @@+module Data.Tensort.OtherSorts.Quicksort (quicksort) where++import Data.Tensort.Utils.ComparisonFunctions (greaterThanInt, greaterThanRecord, lessThanOrEqualInt, lessThanOrEqualRecord)+import Data.Tensort.Utils.Types (Sortable (..), fromSortInt, fromSortRec)++quicksort :: Sortable -> Sortable+quicksort (SortInt []) = SortInt []+quicksort (SortInt (x : xs)) =+  let lowerPartition = quicksort (SortInt [a | a <- xs, lessThanOrEqualInt a x])+      upperPartition = quicksort (SortInt [a | a <- xs, greaterThanInt a x])+   in SortInt (fromSortInt lowerPartition ++ [x] ++ fromSortInt upperPartition)+quicksort (SortRec []) = SortRec []+quicksort (SortRec (x : xs)) =+  let lowerPartition = quicksort (SortRec [a | a <- xs, lessThanOrEqualRecord a x])+      upperPartition = quicksort (SortRec [a | a <- xs, greaterThanRecord a x])+   in SortRec (fromSortRec lowerPartition ++ [x] ++ fromSortRec upperPartition)
+ src/Data/Tensort/Robustsort.hs view
@@ -0,0 +1,33 @@+module Data.Tensort.Robustsort+  ( robustsortP,+    robustsortB,+    robustsortM,+  )+where++import Data.Tensort.Subalgorithms.Bogosort (bogosort)+import Data.Tensort.Subalgorithms.Bubblesort (bubblesort)+import Data.Tensort.Subalgorithms.Magicsort (magicsort)+import Data.Tensort.Subalgorithms.Permutationsort (permutationsort)+import Data.Tensort.Subalgorithms.ReverseExchangesort (reverseExchangesort)+import Data.Tensort.Subalgorithms.Supersort (magicSuperStrat, mundaneSuperStrat, supersort)+import Data.Tensort.Tensort (mkTSProps, tensort)+import Data.Tensort.Utils.Types (Sortable)++robustsortP :: [Int] -> [Int]+robustsortP xs = tensort xs (mkTSProps 3 supersortP)++supersortP :: Sortable -> Sortable+supersortP xs = supersort xs (bubblesort, reverseExchangesort, permutationsort, mundaneSuperStrat)++robustsortB :: [Int] -> [Int]+robustsortB xs = tensort xs (mkTSProps 3 supersortB)++supersortB :: Sortable -> Sortable+supersortB xs = supersort xs (bubblesort, reverseExchangesort, bogosort, mundaneSuperStrat)++robustsortM :: [Int] -> [Int]+robustsortM xs = tensort xs (mkTSProps 3 supersortM)++supersortM :: Sortable -> Sortable+supersortM xs = supersort xs (bubblesort, reverseExchangesort, magicsort, magicSuperStrat)
+ src/Data/Tensort/Subalgorithms/Bogosort.hs view
@@ -0,0 +1,13 @@+module Data.Tensort.Subalgorithms.Bogosort (bogosort, bogosortSeeded) where++import Data.Tensort.Utils.Check (isSorted)+import Data.Tensort.Utils.RandomizeList (randomizeList)+import Data.Tensort.Utils.Types (Sortable (..))++bogosort :: Sortable -> Sortable+bogosort xs = bogosortSeeded xs 143++bogosortSeeded :: Sortable -> Int -> Sortable+bogosortSeeded xs seed+  | isSorted xs = xs+  | otherwise = bogosortSeeded (randomizeList xs seed) (seed + 1)
+ src/Data/Tensort/Subalgorithms/Bubblesort.hs view
@@ -0,0 +1,21 @@+module Data.Tensort.Subalgorithms.Bubblesort (bubblesort) where++import Data.Tensort.Utils.ComparisonFunctions (lessThanInt, lessThanRecord)+import Data.Tensort.Utils.Types (Record, Sortable (..))++bubblesort :: Sortable -> Sortable+bubblesort (SortInt ints) = SortInt (foldr acc [] ints)+  where+    acc :: Int -> [Int] -> [Int]+    acc x xs = bubblesortSinglePass x xs lessThanInt+bubblesort (SortRec recs) = SortRec (foldr acc [] recs)+  where+    acc :: Record -> [Record] -> [Record]+    acc x xs = bubblesortSinglePass x xs lessThanRecord++bubblesortSinglePass :: a -> [a] -> (a -> a -> Bool) -> [a]+bubblesortSinglePass x [] _ = [x]+bubblesortSinglePass x (y : remaningElements) lessThan = do+  if lessThan x y+    then x : bubblesortSinglePass y remaningElements lessThan+    else y : bubblesortSinglePass x remaningElements lessThan
+ src/Data/Tensort/Subalgorithms/Magicsort.hs view
@@ -0,0 +1,16 @@+module Data.Tensort.Subalgorithms.Magicsort+  ( magicsort,+  )+where++import Data.Tensort.Subalgorithms.Bogosort (bogosort)+import Data.Tensort.Subalgorithms.Permutationsort (permutationsort)+import Data.Tensort.Utils.Types (Sortable)++magicsort :: Sortable -> Sortable+magicsort xs = do+  let result1 = permutationsort xs+  let result2 = bogosort xs+  if result1 == result2+    then result1+    else magicsort xs
+ src/Data/Tensort/Subalgorithms/Permutationsort.hs view
@@ -0,0 +1,23 @@+module Data.Tensort.Subalgorithms.Permutationsort (permutationsort) where++import Data.List (permutations)+import Data.Tensort.Utils.Check (isSorted)+import Data.Tensort.Utils.Types (Record, Sortable (..), fromSortInt, fromSortRec)++permutationsort :: Sortable -> Sortable+permutationsort (SortInt xs) = SortInt (acc (permutations x) [])+  where+    x = xs+    acc :: [[Int]] -> [Int] -> [Int]+    acc [] unsortedPermutations = fromSortInt (permutationsort (SortInt unsortedPermutations))+    acc (permutation : remainingPermutations) unsortedPermutations+      | isSorted (SortInt permutation) = permutation+      | otherwise = acc remainingPermutations unsortedPermutations+permutationsort (SortRec xs) = SortRec (acc (permutations x) [])+  where+    x = xs+    acc :: [[Record]] -> [Record] -> [Record]+    acc [] unsortedPermutations = fromSortRec (permutationsort (SortRec unsortedPermutations))+    acc (permutation : remainingPermutations) unsortedPermutations+      | isSorted (SortRec permutation) = permutation+      | otherwise = acc remainingPermutations unsortedPermutations
+ src/Data/Tensort/Subalgorithms/ReverseExchangesort.hs view
@@ -0,0 +1,29 @@+module Data.Tensort.Subalgorithms.ReverseExchangesort (reverseExchangesort) where++import Data.Tensort.Utils.ComparisonFunctions (greaterThanInt, greaterThanRecord)+import Data.Tensort.Utils.Types (Sortable (..))++reverseExchangesort :: Sortable -> Sortable+reverseExchangesort (SortInt ints) = SortInt (reverseExchangesortIterable ints (length ints - 1) (length ints - 2) greaterThanInt)+reverseExchangesort (SortRec recs) = SortRec (reverseExchangesortIterable recs (length recs - 1) (length recs - 2) greaterThanRecord)++reverseExchangesortIterable :: [a] -> Int -> Int -> (a -> a -> Bool) -> [a]+reverseExchangesortIterable xs i j greaterThan = do+  if i < 1+    then xs+    else+      if j < 0+        then reverseExchangesortIterable xs (i - 1) (i - 2) greaterThan+        else+          if greaterThan (xs !! j) (xs !! i)+            then reverseExchangesortIterable (swap xs i j) i (j - 1) greaterThan+            else reverseExchangesortIterable xs i (j - 1) greaterThan++swap :: [a] -> Int -> Int -> [a]+swap xs i j = do+  let x = xs !! i+  let y = xs !! j+  let left = take j xs+  let middle = take (i - j - 1) (drop (j + 1) xs)+  let right = drop (i + 1) xs+  left ++ [y] ++ middle ++ [x] ++ right
+ src/Data/Tensort/Subalgorithms/Supersort.hs view
@@ -0,0 +1,56 @@+module Data.Tensort.Subalgorithms.Supersort+  ( supersort,+    mundaneSuperStrat,+    magicSuperStrat,+  )+where++import Data.Tensort.Utils.Types (SortAlg, Sortable (..), SupersortStrat)++supersort :: Sortable -> (SortAlg, SortAlg, SortAlg, SupersortStrat) -> Sortable+supersort xs (subAlg1, subAlg2, subAlg3, superStrat) = do+  let result1 = subAlg1 xs+  let result2 = subAlg2 xs+  if result1 == result2+    then result1+    else superStrat (result1, result2, subAlg3 xs)++mundaneSuperStrat :: SupersortStrat+mundaneSuperStrat (SortInt result1, SortInt result2, SortInt result3) = do+  if result1 == result3 || result2 == result3+    then SortInt result3+    else+      if last result1 == last result2 || last result1 == last result3+        then SortInt result1+        else+          if last result2 == last result3+            then SortInt result2+            else SortInt result1+mundaneSuperStrat (SortRec result1, SortRec result2, SortRec result3) = do+  if result1 == result3 || result2 == result3+    then SortRec result3+    else+      if last result1 == last result2 || last result1 == last result3+        then SortRec result1+        else+          if last result2 == last result3+            then SortRec result2+            else SortRec result1+mundaneSuperStrat (_, _, _) = error "All three inputs must be of the same type."++magicSuperStrat :: SupersortStrat+magicSuperStrat (SortInt result1, SortInt result2, SortInt result3) = do+  if last result1 == last result3 || last result2 == last result3+    then SortInt result3+    else+      if last result1 == last result2+        then SortInt result1+        else SortInt result3+magicSuperStrat (SortRec result1, SortRec result2, SortRec result3) = do+  if last result1 == last result3 || last result2 == last result3+    then SortRec result3+    else+      if last result1 == last result2+        then SortRec result1+        else SortRec result3+magicSuperStrat (_, _, _) = error "All three inputs must be of the same type."
+ src/Data/Tensort/Tensort.hs view
@@ -0,0 +1,41 @@+module Data.Tensort.Tensort+  ( tensort,+    tensortBasic2Bit,+    tensortBasic3Bit,+    tensortBasic4Bit,+    mkTSProps,+  )+where++import Data.Tensort.Subalgorithms.Bubblesort (bubblesort)+import Data.Tensort.Utils.Convert (rawBitsToBytes)+import Data.Tensort.Utils.RandomizeList (randomizeList)+import Data.Tensort.Utils.Reduce (reduceTensorStacks)+import Data.Tensort.Utils.Render (getSortedBitsFromMetastack)+import Data.Tensort.Utils.Tensor (getTensorStacksFromBytes)+import Data.Tensort.Utils.Types (Sortable (..), TensortProps (..), fromSortInt)++mkTSProps :: Int -> (Sortable -> Sortable) -> TensortProps+mkTSProps bSize subAlg = TensortProps {bytesize = bSize, subAlgorithm = subAlg}++tensortBasic2Bit :: [Int] -> [Int]+tensortBasic2Bit xs = tensort xs (mkTSProps 2 bubblesort)++tensortBasic3Bit :: [Int] -> [Int]+tensortBasic3Bit xs = tensort xs (mkTSProps 3 bubblesort)++tensortBasic4Bit :: [Int] -> [Int]+tensortBasic4Bit xs = tensort xs (mkTSProps 4 bubblesort)++-- | Sort a list of Ints using the Tensort algorithm++-- | ==== __Examples__+-- >>> tensort (randomizeList [1..100] 143) 2+-- [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100]+tensort :: [Int] -> TensortProps -> [Int]+tensort xs tsProps = do+  let bits = randomizeList (SortInt xs) 143+  let bytes = rawBitsToBytes (fromSortInt bits) tsProps+  let tensorStacks = getTensorStacksFromBytes bytes tsProps+  let metastack = reduceTensorStacks tensorStacks tsProps+  getSortedBitsFromMetastack metastack (subAlgorithm tsProps)
+ src/Data/Tensort/Utils/Check.hs view
@@ -0,0 +1,12 @@+module Data.Tensort.Utils.Check (isSorted) where++import Data.Tensort.Utils.ComparisonFunctions (lessThanInt, lessThanRecord)+import Data.Tensort.Utils.Types (Sortable (..))++isSorted :: Sortable -> Bool+isSorted (SortInt []) = True+isSorted (SortInt [_]) = True+isSorted (SortInt (x : y : remainingElements)) = lessThanInt x y && isSorted (SortInt (y : remainingElements))+isSorted (SortRec []) = True+isSorted (SortRec [_]) = True+isSorted (SortRec (x : y : remainingElements)) = lessThanRecord x y && isSorted (SortRec (y : remainingElements))
+ src/Data/Tensort/Utils/ComparisonFunctions.hs view
@@ -0,0 +1,29 @@+module Data.Tensort.Utils.ComparisonFunctions+  ( lessThanInt,+    lessThanRecord,+    greaterThanInt,+    greaterThanRecord,+    lessThanOrEqualInt,+    lessThanOrEqualRecord,+  )+where++import Data.Tensort.Utils.Types (Record)++lessThanInt :: Int -> Int -> Bool+lessThanInt x y = x < y++lessThanRecord :: Record -> Record -> Bool+lessThanRecord x y = snd x < snd y++greaterThanInt :: Int -> Int -> Bool+greaterThanInt x y = x > y++greaterThanRecord :: Record -> Record -> Bool+greaterThanRecord x y = snd x > snd y++lessThanOrEqualInt :: Int -> Int -> Bool+lessThanOrEqualInt x y = x <= y++lessThanOrEqualRecord :: Record -> Record -> Bool+lessThanOrEqualRecord x y = snd x <= snd y
+ src/Data/Tensort/Utils/Convert.hs view
@@ -0,0 +1,21 @@+module Data.Tensort.Utils.Convert (rawBitsToBytes) where++import Data.Tensort.Utils.Split (splitEvery)+import Data.Tensort.Utils.Types (Byte, Sortable (..), TensortProps (..), fromSortInt)++-- | Convert a list of Bits to a list of Bytes of given bytesize, bubblesorting+--   each byte.++-- | ==== __Examples__+--   >>> rawBitsToBytes [5,1,3,7,8,2,4,6] 4+--   [[2,4,6,8],[1,3,5,7]]+-- rawBitsToBytes :: [Int] -> Int -> [Byte]+-- rawBitsToBytes bits bytesize = foldr acc [] (splitEvery bytesize bits)+--   where+--     acc :: [Int] -> [Byte] -> [Byte]+--     acc byte bytes = bytes ++ [fromSortInt (bubblesort (SortInt byte))]+rawBitsToBytes :: [Int] -> TensortProps -> [Byte]+rawBitsToBytes bits tsProps = foldr acc [] (splitEvery (bytesize tsProps) bits)+  where+    acc :: [Int] -> [Byte] -> [Byte]+    acc byte bytes = bytes ++ [fromSortInt (subAlgorithm tsProps (SortInt byte))]
+ src/Data/Tensort/Utils/RandomizeList.hs view
@@ -0,0 +1,9 @@+module Data.Tensort.Utils.RandomizeList (randomizeList) where++import Data.Tensort.Utils.Types (Sortable (..))+import System.Random (mkStdGen)+import System.Random.Shuffle (shuffle')++randomizeList :: Sortable -> Int -> Sortable+randomizeList (SortInt xs) seed = SortInt (shuffle' xs (length xs) (mkStdGen seed))+randomizeList (SortRec xs) seed = SortRec (shuffle' xs (length xs) (mkStdGen seed))
+ src/Data/Tensort/Utils/Reduce.hs view
@@ -0,0 +1,35 @@+module Data.Tensort.Utils.Reduce (reduceTensorStacks) where++import Data.Tensort.Utils.Split (splitEvery)+import Data.Tensort.Utils.Tensor (createTensorStack)+import Data.Tensort.Utils.Types (TensorStack, TensortProps (..))++-- | Take a list of TensorStacks and group them together in new+--   TensorStacks, each containing bytesize number of Tensors (former+--   TensorStacks), until the number of TensorStacks is equal to the bytesize++-- | The Registers of the new TensorStacks are bubblesorted, as usual++-- | ==== __Examples__+-- >>> reduceTensorStacks [([(0, 33), (1, 38)], ByteMem [[31, 33], [35, 38]]), ([(0, 34), (1, 37)], ByteMem [[32, 14], [36, 37]]), ([(0, 23), (1, 27)], ByteMem [[21, 23], [25, 27]]), ([(0, 24), (1, 28)], ByteMem [[22, 24], [26, 28]]),([(0,13),(1,18)],ByteMem [[11,13],[15,18]]),([(0,14),(1,17)],ByteMem [[12,14],[16,17]]),([(0,3),(1,7)],ByteMem [[1,3],[5,7]]),([(0,4),(1,8)],ByteMem [[2,4],[6,8]])] 2+-- ([(1,18),(0,38)],TensorMem [([(0,28),(1,38)],TensorMem [([(0,27),(1,28)],TensorMem [([(0,23),(1,27)],ByteMem [[21,23],[25,27]]),([(0,24),(1,28)],ByteMem [[22,24],[26,28]])]),([(1,37),(0,38)],TensorMem [([(0,33),(1,38)],ByteMem [[31,33],[35,38]]),([(0,34),(1,37)],ByteMem [[32,14],[36,37]])])]),([(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]])])])])+reduceTensorStacks :: [TensorStack] -> TensortProps -> TensorStack+reduceTensorStacks tensorStacks tsProps = do+  let newTensorStacks = reduceTensorStacksSinglePass tensorStacks tsProps+  if length newTensorStacks <= bytesize tsProps+    then createTensorStack newTensorStacks (subAlgorithm tsProps)+    else reduceTensorStacks newTensorStacks tsProps++-- | Take a list of TensorStacks  and group them together in new+--   TensorStacks each containing bytesize number of Tensors (former TensorStacks)++-- | The Registers of the new TensorStacks are bubblesorted, as usual++-- | ==== __Examples__+-- >>> reduceTensorStacksSinglePass [([(0,13),(1,18)],ByteMem [[11,13],[15,18]]),([(0,14),(1,17)],ByteMem [[12,14],[16,17]]),([(0,3),(1,7)],ByteMem [[1,3],[5,7]]),([(0,4),(1,8)],ByteMem [[2,4],[6,8]])] 2+-- [([(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]])])]+reduceTensorStacksSinglePass :: [TensorStack] -> TensortProps -> [TensorStack]+reduceTensorStacksSinglePass tensorStacks tsProps = foldr acc [] (splitEvery (bytesize tsProps) tensorStacks)+  where+    acc :: [TensorStack] -> [TensorStack] -> [TensorStack]+    acc tensorStack newTensorStacks = newTensorStacks ++ [createTensorStack tensorStack (subAlgorithm tsProps)]
+ src/Data/Tensort/Utils/Render.hs view
@@ -0,0 +1,71 @@+module Data.Tensort.Utils.Render (getSortedBitsFromMetastack) where++import Data.Maybe (isNothing)+import Data.Tensort.Utils.Tensor (createTensor)+import Data.Tensort.Utils.Types (Memory (..), SortAlg, Sortable (..), Tensor, TensorStack, fromJust, fromSortInt)++-- | Compile a sorted list of Bits from a list of TensorStacks++-- | ==== __Examples__+--  >>> getSortedBitsFromMetastack ([(0,5),(1,7)],ByteMem [[1,5],[3,7]])+--  [1,3,5,7]+--  >>> getSortedBitsFromMetastack ([(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]])])])+--  [1,2,3,4,5,6,7,8,11,12,13,14,15,16,17,18]+getSortedBitsFromMetastack :: TensorStack -> SortAlg -> [Int]+getSortedBitsFromMetastack metastackRaw subAlg = acc metastackRaw []+  where+    acc :: TensorStack -> [Int] -> [Int]+    acc metastack sortedBits = do+      let (nextBit, metastack') = removeTopBitFromTensor metastack subAlg+      if isNothing metastack'+        then nextBit : sortedBits+        else do+          acc (fromJust metastack') (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__+--   >>> removeTopBitFromTensor  ([(0,5),(1,7)],ByteMem [[1,5],[3,7]])+--   (7,Just ([(1,3),(0,5)],ByteMem [[1,5],[3]]))+removeTopBitFromTensor :: Tensor -> SortAlg -> (Int, Maybe Tensor)+removeTopBitFromTensor (register, memory) tsProps = do+  let topRecord = last register+  let topAddress = fst topRecord+  let (topBit, memory') = removeBitFromMemory memory topAddress tsProps+  if isNothing memory'+    then (topBit, Nothing)+    else (topBit, Just (createTensor (fromJust memory') tsProps))++removeBitFromMemory :: Memory -> Int -> SortAlg -> (Int, Maybe Memory)+removeBitFromMemory (ByteMem bytes) i subAlg = 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'' = fromSortInt (subAlg (SortInt topByte'))+      let bytes' = take i bytes ++ [topByte''] ++ drop (i + 1) bytes+      (topBit, Just (ByteMem bytes'))+removeBitFromMemory (TensorMem tensors) i subAlg = do+  let topTensor = tensors !! i+  let (topBit, topTensor') = removeTopBitFromTensor topTensor subAlg+  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'))
+ src/Data/Tensort/Utils/Split.hs view
@@ -0,0 +1,6 @@+module Data.Tensort.Utils.Split (splitEvery) where++-- | Split a list into chunks of a given size.+splitEvery :: Int -> [a] -> [[a]]+splitEvery _ [] = []+splitEvery n xs = take n xs : splitEvery n (drop n xs)
+ src/Data/Tensort/Utils/Tensor.hs view
@@ -0,0 +1,101 @@+module Data.Tensort.Utils.Tensor+  ( getTensorStacksFromBytes,+    createTensor,+    getTensorFromBytes,+    createTensorStack,+  )+where++import Data.Tensort.Utils.Split (splitEvery)+import Data.Tensort.Utils.Types (Byte, Memory (..), Record, SortAlg, Sortable (..), Tensor, TensorStack, TensortProps (..), fromSortRec)++-- | 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__+--  >>> getTensorStacksFromBytes [[2,4],[6,8],[1,3],[5,7]] 2+--  [([(0,3),(1,7)],ByteMem [[1,3],[5,7]]),([(0,4),(1,8)],ByteMem [[2,4],[6,8]])]+getTensorStacksFromBytes :: [Byte] -> TensortProps -> [TensorStack]+getTensorStacksFromBytes bytes tsProps = foldr acc [] (splitEvery (bytesize tsProps) bytes)+  where+    acc :: [Byte] -> [TensorStack] -> [TensorStack]+    acc byte tensorStacks = tensorStacks ++ [getTensorFromBytes byte (subAlgorithm tsProps)]++-- | Create a Tensor from a Memory+--   Aliases to getTensorFromBytes for ByteMem and createTensorStack for+--   TensorMem++-- | I expect to refactor to simplify this before initial release+createTensor :: Memory -> SortAlg -> Tensor+createTensor (ByteMem bytes) subAlg = getTensorFromBytes bytes subAlg+createTensor (TensorMem tensors) subAlg = createTensorStack tensors subAlg++-- | 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 bubblesorted by the TopBits of each Record++-- | ==== __Examples__+--  >>> getTensorFromBytes [[2,4,6,8],[1,3,5,7]]+--  ([(1,7),(0,8)],ByteMem [[2,4,6,8],[1,3,5,7]])+getTensorFromBytes :: [Byte] -> SortAlg -> Tensor+getTensorFromBytes bytes subAlg = do+  let register = acc bytes [] 0+  let register' = fromSortRec (subAlg (SortRec register))+  (register', ByteMem bytes)+  where+    acc :: [Byte] -> [Record] -> Int -> [Record]+    acc [] register _ = register+    acc ([] : remainingBytes) register i = acc remainingBytes register (i + 1)+    acc (byte : remainingBytes) register i = acc remainingBytes (register ++ [(i, last byte)]) (i + 1)++-- | Create a TensorStack with the collated and bubblesorted References from the+--   Tensors as the Register and the original Tensors as the data++-- | ==== __Examples__+-- >>> createTensorStack [([(0,13),(1,18)],ByteMem [[11,13],[15,18]]),([(1,14),(0,17)],ByteMem [[16,17],[12,14]])]+-- ([(1,17),(0,18)],TensorMem [([(0,13),(1,18)],ByteMem [[11,13],[15,18]]),([(1,14),(0,17)],ByteMem [[16,17],[12,14]])])+createTensorStack :: [Tensor] -> SortAlg -> TensorStack+createTensorStack tensors subAlg = (fromSortRec (subAlg (SortRec (getRegisterFromTensors tensors))), TensorMem tensors)++-- | For each Tensor, 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+--   createTensorStack function++-- | ==== __Examples__+-- >>> getRegisterFromTensors [([(0,13),(1,18)],ByteMem [[11,13],[15,18]]),([(0,14),(1,17)],ByteMem [[12,14],[16,17]]),([(0,3),(1,7)],ByteMem [[1,3],[5,7]]),([(0,4),(1,8)],ByteMem [[2,4],[6,8]])]+-- [(0,18),(1,17),(2,7),(3,8)]+getRegisterFromTensors :: [Tensor] -> [Record]+getRegisterFromTensors tensors = acc tensors []+  where+    acc :: [Tensor] -> [Record] -> [Record]+    acc [] records = records+    acc (([], _) : remainingTensors) records = acc remainingTensors records+    acc (tensor : remainingTensors) records = acc remainingTensors (records ++ [(i, getTopBitFromTensorStack tensor)])+      where+        i = length records++-- | 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 (([(0,28),(1,38)],TensorMem [([(0,27),(1,28)],TensorMem [([(0,23),(1,27)],ByteMem [[21,23],[25,27]]),([(0,24),(1,28)],ByteMem [[22,24],[26,28]])]),([(1,37),(0,38)],TensorMem [([(0,33),(1,38)],ByteMem [[31,33],[35,38]]),([(0,34),(1,37)],ByteMem [[32,14],[36,37]])])]))+-- 38+getTopBitFromTensorStack :: Tensor -> Int+getTopBitFromTensorStack (register, _) = snd (last register)
+ src/Data/Tensort/Utils/Types.hs view
@@ -0,0 +1,91 @@+{-# LANGUAGE GADTs #-}++module Data.Tensort.Utils.Types where++data TensortProps = TensortProps {bytesize :: Int, subAlgorithm :: SortAlg}++--   All the data types used in the Tensort and Tensort algorithms are+--   defined here. Since these packages are only for sorting Ints currently,+--   every data type is a structure of Ints++--   I know this might sound confusing, but in a recursive algorithm like this+--   it's helpful to have different names for the same type of data depending+--   on how it's being used, while still being able to use the same data in+--   multiple contexts++-- | A Bit is a single element of the list to be sorted. For+--   our current purposes that means it is an Int+type Bit = Int++-- | A Byte is a list of Bits standardized to a fixed maximum length (Bytesize)++-- | The length should be set either in or upstream of any function that uses+--   Bytes+type Byte = [Bit]++-- | An Address is a index number pointing to data stored in Memory+type Address = Int++-- | A TopBit contains a copy of the last (i.e. highest) Bit in a Byte or+--   Tensor+type TopBit = Bit++-- | A Record is an element in a Tensor or Metatensor's Register+--   containing an Address pointer and a TopBit value++-- | A Record's Address is an index number pointing to a Byte or Tensor in+--   the Tensor/Metatensor's Memory++-- | A Record's TopBit is a copy of the last (i.e. highest) Bit in the Byte or+--   Tensor that the Record references+type Record = (Address, TopBit)++-- | A Register is a list of Records allowing for easy access to data in a+--   Tensor or Metatensor's Memory+type Register = [Record]++-- | We use a Sortable type sort between Ints and Records++-- | In the future this may be expanded to include other data types and allow+--   for sorting other types of besides Ints+data Sortable+  = SortInt [Int]+  | SortRec [Record]+  deriving (Show, Eq, Ord)++fromSortInt :: Sortable -> [Int]+fromSortInt (SortInt ints) = ints+fromSortInt (SortRec _) = error "This is for sorting Integers - you gave me Records"++fromSortRec :: Sortable -> [Record]+fromSortRec (SortRec recs) = recs+fromSortRec (SortInt _) = error "This is for sorting Records - you gave me Integers"++type SortAlg = Sortable -> Sortable++type SupersortProps = (SortAlg, SortAlg, SortAlg, SupersortStrat)++type SupersortStrat = (Sortable, Sortable, Sortable) -> Sortable++-- | A Memory contains the data to be sorted, either in the form of Bytes or+--   Tensors+data Memory+  = ByteMem [Byte]+  | TensorMem [Tensor]+  deriving (Show, Eq, Ord)++-- | A Tensor is a Metatensor that only contains Bytes in its memory+-- | The Memory is a list of the Bytes or Tensors that the Tensor+--   contains.++-- | The Register is a list of Records referencing the top Bits in Memory+type Tensor = (Register, Memory)++-- | A TensorStack is a top-level Tensor. In the final stages of Tensort, the+--   number of TensorStacks will equal the bytesize, but before that time there+--   are expected to be many more TensorStacks+type TensorStack = Tensor++fromJust :: Maybe a -> a+fromJust (Just x) = x+fromJust Nothing = error "fromJust: Nothing"
+ tensort.cabal view
@@ -0,0 +1,153 @@+cabal-version:      3.4+-- The cabal-version field refers to the version of the .cabal specification,+-- and can be different from the cabal-install (the tool) version and the+-- Cabal (the library) version you are using. As such, the Cabal (the library)+-- version used must be equal or greater than the version stated in this field.+-- Starting from the specification version 2.2, the cabal-version field must be+-- the first thing in the cabal file.++-- Initial package description 'tensort' generated by+-- 'cabal init'. For further documentation, see:+--   http://haskell.org/cabal/users-guide/+--+-- The name of the package.+name:               tensort++-- The package version.+-- See the Haskell package versioning policy (PVP) for standards+-- guiding when and how versions should be incremented.+-- https://pvp.haskell.org+-- PVP summary:     +-+------- breaking API changes+--                  | | +----- non-breaking API additions+--                  | | | +--- code changes with no API change+version:            0.1.0.0++-- A short (one-line) description of the package.+synopsis:           Reasonably robust sorting in O(n log n) time++-- A longer description of the package.+description:        An exploration of robustness in algorithms for sorting integers, inspired by [Beyond Efficiency](https://www.cs.unm.edu/~ackley/be-201301131528.pdf) by David H. Ackley++-- The license under which the package is released.+license:            MIT++-- The file containing the license text.+license-file:       LICENSE++-- The package author(s).+author:             Kyle Beechly++-- An email address to which users can send suggestions, bug reports, and patches.+maintainer:         contact@kaBeech.com++-- A copyright notice.+copyright:          2024 Kyle Beechly++category:           Math,+                    Data++build-type:         Simple++-- Extra doc files to be distributed with the package, such as a CHANGELOG or a README.+extra-doc-files:    CHANGELOG.md++-- Extra source files to be distributed with the package, such as examples, or a tutorial module.+-- extra-source-files:++common warnings+    ghc-options: -Wall++library+    -- Import common warning flags.+    import:           warnings++    -- Modules exported by the library.+    exposed-modules:  Data.Tensort,+                      Data.Tensort.Tensort,+                      Data.Tensort.Robustsort,+                      Data.Tensort.Utils.Types,+                      Data.Tensort.Subalgorithms.Bubblesort,+                      Data.Tensort.Subalgorithms.ReverseExchangesort,+                      Data.Tensort.Subalgorithms.Permutationsort,+                      Data.Tensort.Subalgorithms.Bogosort,+                      Data.Tensort.Subalgorithms.Supersort,+                      Data.Tensort.Subalgorithms.Magicsort,+                      Data.Tensort.OtherSorts.Mergesort,+                      Data.Tensort.OtherSorts.Quicksort,+                      Data.Tensort.Utils.RandomizeList,++    -- Modules included in this library but not exported.+    other-modules:    Data.Tensort.Utils.Check,+                      Data.Tensort.Utils.Split,+                      Data.Tensort.Utils.ComparisonFunctions,+                      Data.Tensort.Utils.Convert,+                      Data.Tensort.Utils.Tensor,+                      Data.Tensort.Utils.Reduce,+                      Data.Tensort.Utils.Render,++    -- LANGUAGE extensions used by modules in this package.+    -- other-extensions:++    -- Other library packages from which modules are imported.+    build-depends:    base ^>=4.18.2.0,+                      mtl >= 2.3.1 && < 2.4,+                      random >= 1.2.1 && < 1.3,+                      random-shuffle >= 0.0.4 && < 0.1,++    -- Directories containing source files.+    hs-source-dirs:   src++    -- Base language which the package is written in.+    default-language: Haskell2010++executable tensort+    -- Import common warning flags.+    import:           warnings++    -- .hs or .lhs file containing the Main module.+    main-is:          Main.hs++    -- Modules included in this executable, other than Main.+    -- other-modules:++    -- LANGUAGE extensions used by modules in this package.+    -- other-extensions:++    -- Other library packages from which modules are imported.+    build-depends:+        base ^>=4.18.2.0,+        tensort,+        time >= 1.12.2 && < 1.13,++    -- Directories containing source files.+    hs-source-dirs:   app++    -- Base language which the package is written in.+    default-language: Haskell2010++test-suite tensort-test+    -- Import common warning flags.+    import:           warnings++    -- Base language which the package is written in.+    default-language: Haskell2010++    -- Modules included in this executable, other than Main.+    -- other-modules:++    -- LANGUAGE extensions used by modules in this package.+    -- other-extensions:++    -- The interface type and version of the test suite.+    type:             exitcode-stdio-1.0++    -- Directories containing source files.+    hs-source-dirs:   test++    -- The entrypoint to the test suite.+    main-is:          Main.hs++    -- Test dependencies.+    build-depends:+        base ^>=4.18.2.0,+        tensort
+ test/Main.hs view
@@ -0,0 +1,4 @@+module Main (main) where++main :: IO ()+main = putStrLn "Test suite not yet implemented."