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 :: Sortable -> (SortAlg, SortAlg, SortAlg, SupersortStrat) -> Sortable
supersort Sortable
xs (SortAlg
subAlg1, SortAlg
subAlg2, SortAlg
subAlg3, SupersortStrat
superStrat) = do
  let result1 :: Sortable
result1 = SortAlg
subAlg1 Sortable
xs
  let result2 :: Sortable
result2 = SortAlg
subAlg2 Sortable
xs
  if Sortable
result1 Sortable -> Sortable -> Bool
forall a. Eq a => a -> a -> Bool
== Sortable
result2
    then Sortable
result1
    else SupersortStrat
superStrat (Sortable
result1, Sortable
result2, SortAlg
subAlg3 Sortable
xs)

mundaneSuperStrat :: SupersortStrat
mundaneSuperStrat :: SupersortStrat
mundaneSuperStrat (SortBit [Bit]
result1, SortBit [Bit]
result2, SortBit [Bit]
result3) = do
  if [Bit]
result1 [Bit] -> [Bit] -> Bool
forall a. Eq a => a -> a -> Bool
== [Bit]
result3 Bool -> Bool -> Bool
|| [Bit]
result2 [Bit] -> [Bit] -> Bool
forall a. Eq a => a -> a -> Bool
== [Bit]
result3
    then [Bit] -> Sortable
SortBit [Bit]
result3
    else
      if [Bit] -> Bit
forall a. HasCallStack => [a] -> a
last [Bit]
result1 Bit -> Bit -> Bool
forall a. Eq a => a -> a -> Bool
== [Bit] -> Bit
forall a. HasCallStack => [a] -> a
last [Bit]
result2 Bool -> Bool -> Bool
|| [Bit] -> Bit
forall a. HasCallStack => [a] -> a
last [Bit]
result1 Bit -> Bit -> Bool
forall a. Eq a => a -> a -> Bool
== [Bit] -> Bit
forall a. HasCallStack => [a] -> a
last [Bit]
result3
        then [Bit] -> Sortable
SortBit [Bit]
result1
        else
          if [Bit] -> Bit
forall a. HasCallStack => [a] -> a
last [Bit]
result2 Bit -> Bit -> Bool
forall a. Eq a => a -> a -> Bool
== [Bit] -> Bit
forall a. HasCallStack => [a] -> a
last [Bit]
result3
            then [Bit] -> Sortable
SortBit [Bit]
result2
            else [Bit] -> Sortable
SortBit [Bit]
result1
mundaneSuperStrat (SortRec [Record]
result1, SortRec [Record]
result2, SortRec [Record]
result3) = do
  if [Record]
result1 [Record] -> [Record] -> Bool
forall a. Eq a => a -> a -> Bool
== [Record]
result3 Bool -> Bool -> Bool
|| [Record]
result2 [Record] -> [Record] -> Bool
forall a. Eq a => a -> a -> Bool
== [Record]
result3
    then [Record] -> Sortable
SortRec [Record]
result3
    else
      if [Record] -> Record
forall a. HasCallStack => [a] -> a
last [Record]
result1 Record -> Record -> Bool
forall a. Eq a => a -> a -> Bool
== [Record] -> Record
forall a. HasCallStack => [a] -> a
last [Record]
result2 Bool -> Bool -> Bool
|| [Record] -> Record
forall a. HasCallStack => [a] -> a
last [Record]
result1 Record -> Record -> Bool
forall a. Eq a => a -> a -> Bool
== [Record] -> Record
forall a. HasCallStack => [a] -> a
last [Record]
result3
        then [Record] -> Sortable
SortRec [Record]
result1
        else
          if [Record] -> Record
forall a. HasCallStack => [a] -> a
last [Record]
result2 Record -> Record -> Bool
forall a. Eq a => a -> a -> Bool
== [Record] -> Record
forall a. HasCallStack => [a] -> a
last [Record]
result3
            then [Record] -> Sortable
SortRec [Record]
result2
            else [Record] -> Sortable
SortRec [Record]
result1
mundaneSuperStrat (Sortable
_, Sortable
_, Sortable
_) = [Char] -> Sortable
forall a. HasCallStack => [Char] -> a
error [Char]
"All three inputs must be of the same type."

magicSuperStrat :: SupersortStrat
magicSuperStrat :: SupersortStrat
magicSuperStrat (SortBit [Bit]
result1, SortBit [Bit]
result2, SortBit [Bit]
result3) = do
  if [Bit] -> Bit
forall a. HasCallStack => [a] -> a
last [Bit]
result1 Bit -> Bit -> Bool
forall a. Eq a => a -> a -> Bool
== [Bit] -> Bit
forall a. HasCallStack => [a] -> a
last [Bit]
result3 Bool -> Bool -> Bool
|| [Bit] -> Bit
forall a. HasCallStack => [a] -> a
last [Bit]
result2 Bit -> Bit -> Bool
forall a. Eq a => a -> a -> Bool
== [Bit] -> Bit
forall a. HasCallStack => [a] -> a
last [Bit]
result3
    then [Bit] -> Sortable
SortBit [Bit]
result3
    else
      if [Bit] -> Bit
forall a. HasCallStack => [a] -> a
last [Bit]
result1 Bit -> Bit -> Bool
forall a. Eq a => a -> a -> Bool
== [Bit] -> Bit
forall a. HasCallStack => [a] -> a
last [Bit]
result2
        then [Bit] -> Sortable
SortBit [Bit]
result1
        else [Bit] -> Sortable
SortBit [Bit]
result3
magicSuperStrat (SortRec [Record]
result1, SortRec [Record]
result2, SortRec [Record]
result3) = do
  if [Record] -> Record
forall a. HasCallStack => [a] -> a
last [Record]
result1 Record -> Record -> Bool
forall a. Eq a => a -> a -> Bool
== [Record] -> Record
forall a. HasCallStack => [a] -> a
last [Record]
result3 Bool -> Bool -> Bool
|| [Record] -> Record
forall a. HasCallStack => [a] -> a
last [Record]
result2 Record -> Record -> Bool
forall a. Eq a => a -> a -> Bool
== [Record] -> Record
forall a. HasCallStack => [a] -> a
last [Record]
result3
    then [Record] -> Sortable
SortRec [Record]
result3
    else
      if [Record] -> Record
forall a. HasCallStack => [a] -> a
last [Record]
result1 Record -> Record -> Bool
forall a. Eq a => a -> a -> Bool
== [Record] -> Record
forall a. HasCallStack => [a] -> a
last [Record]
result2
        then [Record] -> Sortable
SortRec [Record]
result1
        else [Record] -> Sortable
SortRec [Record]
result3
magicSuperStrat (Sortable
_, Sortable
_, Sortable
_) = [Char] -> Sortable
forall a. HasCallStack => [Char] -> a
error [Char]
"All three inputs must be of the same type."