packages feed

sdp-0.2: src/SDP/Unrolled/Unlist.hs

{-# LANGUAGE Safe, MagicHash, MultiParamTypeClasses, FlexibleInstances #-}

{- |
    Module      :  SDP.Unrolled.Unlist
    Copyright   :  (c) Andrey Mulik 2019
    License     :  BSD-style
    Maintainer  :  work.a.mulik@gmail.com
    Portability :  portable
    
    "SDP.Unrolled.Unlist" provides 'Unlist' - lazy boxed unrolled linked list.
-}
module SDP.Unrolled.Unlist
(
  -- * Exports
  module SDP.Indexed,
  module SDP.Sort,
  module SDP.Scan,
  module SDP.Set,
  
  -- * Unlist
  Unlist
)
where

import Prelude ()
import SDP.SafePrelude
import SDP.Indexed
import SDP.Sort
import SDP.Scan
import SDP.Set

import SDP.Templates.AnyChunks
import SDP.Prim.SArray
import SDP.SortM.Tim

default ()

--------------------------------------------------------------------------------

-- | 'Unlist' is unrolled linked list of boxed values.
type Unlist = AnyChunks SArray#

--------------------------------------------------------------------------------

{- Eq1 and Ord1 instances. -}

instance Eq1 Unlist
  where
    liftEq _ Z Z = True
    liftEq _ Z _ = False
    liftEq _ _ Z = False
    liftEq f xs ys = if n1 > n2
        then liftEq f (take n2 x) y && liftEq f (drop n2 xs) (fromChunks ys')
        else liftEq f x (take n1 y) && liftEq f (fromChunks xs') (drop n1 ys)
      where
        (x : xs') = toChunks xs; n1 = sizeOf x
        (y : ys') = toChunks ys; n2 = sizeOf y

instance Ord1 Unlist
  where
    liftCompare _ Z Z = EQ
    liftCompare _ Z _ = LT
    liftCompare _ _ Z = GT
    liftCompare f xs ys = if n1 > n2
        then liftCompare f (take n2 x) y <> liftCompare f (drop n2 xs) (fromChunks ys')
        else liftCompare f x (take n1 y) <> liftCompare f (fromChunks xs') (drop n1 ys)
      where
        (x : xs') = toChunks xs; n1 = sizeOf x
        (y : ys') = toChunks ys; n2 = sizeOf y

instance Zip Unlist
  where
    all2 f as bs             = all2 f (listL as) (listL bs)
    any2 f as bs             = any2 f (listL as) (listL bs)
    all3 f as bs cs          = all3 f (listL as) (listL bs) (listL cs)
    any3 f as bs cs          = any3 f (listL as) (listL bs) (listL cs)
    all4 f as bs cs ds       = all4 f (listL as) (listL bs) (listL cs) (listL ds)
    any4 f as bs cs ds       = any4 f (listL as) (listL bs) (listL cs) (listL ds)
    all5 f as bs cs ds es    = all5 f (listL as) (listL bs) (listL cs) (listL ds) (listL es)
    any5 f as bs cs ds es    = any5 f (listL as) (listL bs) (listL cs) (listL ds) (listL es)
    all6 f as bs cs ds es fs = all6 f (listL as) (listL bs) (listL cs) (listL ds) (listL es) (listL fs)
    any6 f as bs cs ds es fs = any6 f (listL as) (listL bs) (listL cs) (listL ds) (listL es) (listL fs)
    
    zipWith  f as bs             = fromList $ zipWith  f (listL as) (listL bs)
    zipWith3 f as bs cs          = fromList $ zipWith3 f (listL as) (listL bs) (listL cs)
    zipWith4 f as bs cs ds       = fromList $ zipWith4 f (listL as) (listL bs) (listL cs) (listL ds)
    zipWith5 f as bs cs ds es    = fromList $ zipWith5 f (listL as) (listL bs) (listL cs) (listL ds) (listL es)
    zipWith6 f as bs cs ds es fs = fromList $ zipWith6 f (listL as) (listL bs) (listL cs) (listL ds) (listL es) (listL fs)

instance Sort (Unlist e) e
  where
    sortBy cmp es = runST $ do es' <- thaw es; timSortBy cmp es'; done es'
    
    sortedBy f = go . toChunks
      where
        go (x1 : x2 : xs) = sortedBy f x1 && last x1 `f` head x2 && go (x2 : xs)
        go      [x1]      = sortedBy f x1
        go       []       = True

--------------------------------------------------------------------------------

{-# INLINE done #-}
done :: STArray# s e -> ST s (Unlist e)
done =  unsafeFreeze