    {-# OPTIONS -fno-spec-constr-count #-}
    module Bench.Vector.Algo.AwShCC (awshcc) where

    import Data.Vector.Unboxed as V

    awshcc :: (Int, Vector Int, Vector Int) -> Vector Int
    {-# NOINLINE awshcc #-}
    awshcc :: (Int, Vector Int, Vector Int) -> Vector Int
    awshcc (Int
    n, Vector Int
    es1, Vector Int
    es2) = Vector Int -> Vector Int -> Vector Int -> Vector Int
    concomp Vector Int
    ds Vector Int
    es1' Vector Int
    es2'
        where
          ds :: Vector Int
    ds = Int -> Int -> Vector Int
    forall a. (Unbox a, Enum a) => a -> a -> Vector a
    V.enumFromTo Int
    0 (Int
    nInt -> Int -> Int
    forall a. Num a => a -> a -> a
    -Int
    1) Vector Int -> Vector Int -> Vector Int
    forall a. Unbox a => Vector a -> Vector a -> Vector a
    V.++ Int -> Int -> Vector Int
    forall a. (Unbox a, Enum a) => a -> a -> Vector a
    V.enumFromTo Int
    0 (Int
    nInt -> Int -> Int
    forall a. Num a => a -> a -> a
    -Int
    1)
          es1' :: Vector Int
    es1' = Vector Int
    es1 Vector Int -> Vector Int -> Vector Int
    forall a. Unbox a => Vector a -> Vector a -> Vector a
    V.++ Vector Int
    es2
          es2' :: Vector Int
    es2' = Vector Int
    es2 Vector Int -> Vector Int -> Vector Int
    forall a. Unbox a => Vector a -> Vector a -> Vector a
    V.++ Vector Int
    es1

          starCheck :: Vector Int -> Vector Bool
    starCheck Vector Int
    ds = Vector Bool -> Vector Int -> Vector Bool
    forall a. Unbox a => Vector a -> Vector Int -> Vector a
    V.backpermute Vector Bool
    st' Vector Int
    gs
            where
              gs :: Vector Int
    gs  = Vector Int -> Vector Int -> Vector Int
    forall a. Unbox a => Vector a -> Vector Int -> Vector a
    V.backpermute Vector Int
    ds Vector Int
    ds
              st :: Vector Bool
    st  = (Int -> Int -> Bool) -> Vector Int -> Vector Int -> Vector Bool
    forall a b c.
    (Unbox a, Unbox b, Unbox c) =>
    (a -> b -> c) -> Vector a -> Vector b -> Vector c
    V.zipWith Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    (==) Vector Int
    ds Vector Int
    gs
              st' :: Vector Bool
    st' = Vector Bool -> Vector (Int, Bool) -> Vector Bool
    forall a. Unbox a => Vector a -> Vector (Int, a) -> Vector a
    V.update Vector Bool
    st (Vector (Int, Bool) -> Vector Bool)
    -> (Vector (Int, Bool) -> Vector (Int, Bool))
    -> Vector (Int, Bool)
    -> Vector Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ((Int, Bool) -> Bool) -> Vector (Int, Bool) -> Vector (Int, Bool)
    forall a. Unbox a => (a -> Bool) -> Vector a -> Vector a
    V.filter (Bool -> Bool
    not (Bool -> Bool) -> ((Int, Bool) -> Bool) -> (Int, Bool) -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Int, Bool) -> Bool
    forall a b. (a, b) -> b
    snd)
                                (Vector (Int, Bool) -> Vector Bool)
    -> Vector (Int, Bool) -> Vector Bool
    forall a b. (a -> b) -> a -> b
    $ Vector Int -> Vector Bool -> Vector (Int, Bool)
    forall a b.
    (Unbox a, Unbox b) =>
    Vector a -> Vector b -> Vector (a, b)
    V.zip Vector Int
    gs Vector Bool
    st

          concomp :: Vector Int -> Vector Int -> Vector Int -> Vector Int
    concomp Vector Int
    ds Vector Int
    es1 Vector Int
    es2
            | Vector Bool -> Bool
    V.and (Vector Int -> Vector Bool
    starCheck Vector Int
    ds'') = Vector Int
    ds''
            | Bool
    otherwise              = Vector Int -> Vector Int -> Vector Int -> Vector Int
    concomp (Vector Int -> Vector Int -> Vector Int
    forall a. Unbox a => Vector a -> Vector Int -> Vector a
    V.backpermute Vector Int
    ds'' Vector Int
    ds'') Vector Int
    es1 Vector Int
    es2
            where
              ds' :: Vector Int
    ds'  = Vector Int -> Vector (Int, Int) -> Vector Int
    forall a. Unbox a => Vector a -> Vector (Int, a) -> Vector a
    V.update Vector Int
    ds
                   (Vector (Int, Int) -> Vector Int)
    -> (Vector (Int, Int, Int) -> Vector (Int, Int))
    -> Vector (Int, Int, Int)
    -> Vector Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ((Int, Int, Int) -> (Int, Int))
    -> Vector (Int, Int, Int) -> Vector (Int, Int)
    forall a b. (Unbox a, Unbox b) => (a -> b) -> Vector a -> Vector b
    V.map (\(Int
    di, Int
    dj, Int
    gi) -> (Int
    di, Int
    dj))
                   (Vector (Int, Int, Int) -> Vector (Int, Int))
    -> (Vector (Int, Int, Int) -> Vector (Int, Int, Int))
    -> Vector (Int, Int, Int)
    -> Vector (Int, Int)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ((Int, Int, Int) -> Bool)
    -> Vector (Int, Int, Int) -> Vector (Int, Int, Int)
    forall a. Unbox a => (a -> Bool) -> Vector a -> Vector a
    V.filter (\(Int
    di, Int
    dj, Int
    gi) -> Int
    gi Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    di Bool -> Bool -> Bool
    && Int
    di Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > Int
    dj)
                   (Vector (Int, Int, Int) -> Vector Int)
    -> Vector (Int, Int, Int) -> Vector Int
    forall a b. (a -> b) -> a -> b
    $ Vector Int -> Vector Int -> Vector Int -> Vector (Int, Int, Int)
    forall a b c.
    (Unbox a, Unbox b, Unbox c) =>
    Vector a -> Vector b -> Vector c -> Vector (a, b, c)
    V.zip3 (Vector Int -> Vector Int -> Vector Int
    forall a. Unbox a => Vector a -> Vector Int -> Vector a
    V.backpermute Vector Int
    ds Vector Int
    es1)
                            (Vector Int -> Vector Int -> Vector Int
    forall a. Unbox a => Vector a -> Vector Int -> Vector a
    V.backpermute Vector Int
    ds Vector Int
    es2)
                            (Vector Int -> Vector Int -> Vector Int
    forall a. Unbox a => Vector a -> Vector Int -> Vector a
    V.backpermute Vector Int
    ds (Vector Int -> Vector Int -> Vector Int
    forall a. Unbox a => Vector a -> Vector Int -> Vector a
    V.backpermute Vector Int
    ds Vector Int
    es1))

              ds'' :: Vector Int
    ds'' = Vector Int -> Vector (Int, Int) -> Vector Int
    forall a. Unbox a => Vector a -> Vector (Int, a) -> Vector a
    V.update Vector Int
    ds'
                   (Vector (Int, Int) -> Vector Int)
    -> (Vector (Int, Int, Bool) -> Vector (Int, Int))
    -> Vector (Int, Int, Bool)
    -> Vector Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ((Int, Int, Bool) -> (Int, Int))
    -> Vector (Int, Int, Bool) -> Vector (Int, Int)
    forall a b. (Unbox a, Unbox b) => (a -> b) -> Vector a -> Vector b
    V.map (\(Int
    di, Int
    dj, Bool
    st) -> (Int
    di, Int
    dj))
                   (Vector (Int, Int, Bool) -> Vector (Int, Int))
    -> (Vector (Int, Int, Bool) -> Vector (Int, Int, Bool))
    -> Vector (Int, Int, Bool)
    -> Vector (Int, Int)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ((Int, Int, Bool) -> Bool)
    -> Vector (Int, Int, Bool) -> Vector (Int, Int, Bool)
    forall a. Unbox a => (a -> Bool) -> Vector a -> Vector a
    V.filter (\(Int
    di, Int
    dj, Bool
    st) -> Bool
    st Bool -> Bool -> Bool
    && Int
    di Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Int
    dj)
                   (Vector (Int, Int, Bool) -> Vector Int)
    -> Vector (Int, Int, Bool) -> Vector Int
    forall a b. (a -> b) -> a -> b
    $ Vector Int -> Vector Int -> Vector Bool -> Vector (Int, Int, Bool)
    forall a b c.
    (Unbox a, Unbox b, Unbox c) =>
    Vector a -> Vector b -> Vector c -> Vector (a, b, c)
    V.zip3 (Vector Int -> Vector Int -> Vector Int
    forall a. Unbox a => Vector a -> Vector Int -> Vector a
    V.backpermute Vector Int
    ds' Vector Int
    es1)
                            (Vector Int -> Vector Int -> Vector Int
    forall a. Unbox a => Vector a -> Vector Int -> Vector a
    V.backpermute Vector Int
    ds' Vector Int
    es2)
                            (Vector Bool -> Vector Int -> Vector Bool
    forall a. Unbox a => Vector a -> Vector Int -> Vector a
    V.backpermute (Vector Int -> Vector Bool
    starCheck Vector Int
    ds') Vector Int
    es1)