packages feed

vext-0.1.0.0: src-rep-eq-indef/EqVector.hs

{-# language BangPatterns #-}
{-# language BlockArguments #-}
{-# language DataKinds #-}
{-# language ExplicitNamespaces #-}
{-# language GADTs #-}
{-# language KindSignatures #-}
{-# language MagicHash #-}
{-# language PatternSynonyms #-}
{-# language UnliftedNewtypes #-}
{-# language RankNTypes #-}
{-# language ScopedTypeVariables #-}
{-# language TypeApplications #-}
{-# language TypeOperators #-}
{-# language UnboxedTuples #-}
{-# language UnboxedSums #-}

-- Turn this on when debugging performance.
-- OPTIONS_GHC -ddump-simpl -ddump-to-file -dsuppress-all -ddump-cmm -ddump-asm

module EqVector
  ( equals
  , elem
  , findIndexEq
  ) where

import Prelude hiding (Bounded,max,min,maximum,elem)

import Rep (R,eq)
import Vector (MutableVector(MutableVector),MutableVector#,Vector,Bounded(Bounded),index,write,write#,thaw,read#,unsafeShrinkFreeze,unsafeFreeze)
import GHC.ST (ST(ST),runST)
import Arithmetic.Types (type (<),Fin(Fin),Nat#)
import Arithmetic.Types (type (:=:),type (<=))
import Arithmetic.Types (type (<#),type (<=#))
import Arithmetic.Nat ((<?),(<?#))
import GHC.TypeNats (type (+))
import GHC.Exts (TYPE,State#)
import Data.Unlifted (Bool#,pattern True#,pattern False#)
import Arithmetic.Types (MaybeFin#,pattern MaybeFinNothing#,pattern MaybeFinJust#)
import Data.Maybe.Void (pattern JustVoid#)

import qualified GHC.TypeNats as GHC
import qualified Element
import qualified Arithmetic.Lt as Lt
import qualified Arithmetic.Lte as Lte
import qualified Arithmetic.Nat as Nat
import qualified Arithmetic.Fin as Fin
import qualified Vector
import qualified Vector as V

-- | Compare two vectors for equality.
equals :: Nat# n -> Vector n a -> Vector n a -> Bool
equals !n !v0 !v1 = Fin.descend (Nat.lift n) True $ \fin acc ->
  eq (index v0 (Fin.unlift fin)) (index v1 (Fin.unlift fin))
  &&
  acc

elem :: forall (n :: GHC.Nat) (a :: TYPE R). Nat# n -> a -> Vector n a -> Bool
elem !n !needle !v = go Nat.N0#
  where
  go :: Nat# k -> Bool
  go !ix = case ix <?# n of
    JustVoid# lt ->
      let !fin = Fin.construct# lt ix
       in if eq (V.index v fin) needle
            then True
            else go (Nat.succ# ix)
    _ -> False

findIndexEq :: forall (n :: GHC.Nat) (a :: TYPE R). Nat# n -> a -> Vector n a -> MaybeFin# n
findIndexEq !n !needle !v = go Nat.N0#
  where
  go :: Nat# k -> MaybeFin# n
  go !ix = case ix <?# n of
    JustVoid# lt ->
      let !fin = Fin.construct# lt ix
       in if eq (V.index v fin) needle
            then MaybeFinJust# fin
            else go (Nat.succ# ix)
    _ -> MaybeFinNothing#