module Biobase.Primary.Hashed where
import Data.Ix
import Data.Primitive.Types
import Data.Vector.Unboxed.Deriving
import qualified Data.Vector.Generic as VG
import qualified Data.Vector.Generic.Mutable as VGM
import qualified Data.Vector.Unboxed as VU
import Biobase.Primary.Letter
newtype HashedPrimary t n = HashedPrimary { unHashedPrimary :: Int }
deriving (Eq,Ord,Ix,Read,Show,Enum,Bounded)
derivingUnbox "HashedPrimary"
[t| forall t n . HashedPrimary t n -> Int |] [| unHashedPrimary |] [| HashedPrimary |]
mkHashedPrimary :: forall t n . (VU.Unbox (Letter t n), Bounded (Letter t n), Enum (Letter t n)) => Primary t n -> HashedPrimary t n
mkHashedPrimary = HashedPrimary . fst . VU.foldl' f (0, 1) where
f (z, c) n = (z + c * (fromEnum n +1), c * (fromEnum (maxBound :: Letter t n) + 1))
{-# INLINE mkHashedPrimary #-}
hash2primary :: forall t n . (VU.Unbox (Letter t n), Bounded (Letter t n), Enum (Letter t n)) => HashedPrimary t n -> Primary t n
hash2primary (HashedPrimary h) = VU.unfoldrN l f h where
m = fromEnum (maxBound :: Letter t n) +1
l = VU.length . VU.takeWhile (>0) . VU.iterateN 100 (`div` m) $ h
f k = if k>0 then Just (toEnum $ ((k-1) `mod` m) , (k-1) `div` m)
else Nothing
{-# INLINE hash2primary #-}