{-# LANGUAGE FlexibleInstances #-}

module HaskellWorks.Data.Simd.Logical.Avx2 where

import Data.Word
import HaskellWorks.Data.Simd.Internal.Marshal

import qualified Data.Vector.Storable                    as DVS
import qualified Foreign.ForeignPtr                      as F
import qualified Foreign.Marshal.Unsafe                  as F
import qualified Foreign.Ptr                             as F
import qualified HaskellWorks.Data.Simd.Internal.Foreign as F

{- HLINT ignore "Redundant do"        -}
{- HLINT ignore "Reduce duplication"  -}

class XorBits a where
  xorBits :: a -> a -> a

instance XorBits (DVS.Vector Word64) where
  xorBits :: Vector Word64 -> Vector Word64 -> Vector Word64
xorBits Vector Word64
a Vector Word64
b = forall a. IO a -> a
F.unsafeLocalState forall a b. (a -> b) -> a -> b
$ do
    let (ForeignPtr Word8
srcAFptr, Int
srcAOffset, Int
srcALength) = Int -> Vector Word64 -> (ForeignPtr Word8, Int, Int)
unsafeToElemSizedForeignPtr Int
64 Vector Word64
a
    let (ForeignPtr Word8
srcBFptr, Int
srcBOffset, Int
srcBLength) = Int -> Vector Word64 -> (ForeignPtr Word8, Int, Int)
unsafeToElemSizedForeignPtr Int
64 Vector Word64
b
    ForeignPtr Word8
targetFptr <- forall a. Int -> IO (ForeignPtr a)
F.mallocForeignPtrBytes Int
srcALength
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
srcAFptr forall a b. (a -> b) -> a -> b
$ \Ptr Word8
srcAPtr -> do
      forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
srcBFptr forall a b. (a -> b) -> a -> b
$ \Ptr Word8
srcBPtr -> do
        forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
targetFptr forall a b. (a -> b) -> a -> b
$ \Ptr Word8
targetPtr -> do
          ()
_ <- Ptr UInt8 -> Size -> Ptr UInt8 -> Ptr UInt8 -> IO ()
F.avx2XorBits
            (forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
targetPtr)
            (forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
srcALength forall a. Ord a => a -> a -> a
`min` Int
srcBLength))
            (forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
srcAPtr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` Int
srcAOffset)
            (forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
srcBPtr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` Int
srcBOffset)
          forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. (Storable a, Storable b) => Vector a -> Vector b
DVS.unsafeCast (forall a. Storable a => ForeignPtr a -> Int -> Int -> Vector a
DVS.unsafeFromForeignPtr ForeignPtr Word8
targetFptr Int
0 Int
srcALength :: DVS.Vector Word8)
  {-# INLINE xorBits #-}

instance XorBits [DVS.Vector Word64] where
  xorBits :: [Vector Word64] -> [Vector Word64] -> [Vector Word64]
xorBits = forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith forall a. XorBits a => a -> a -> a
xorBits
  {-# INLINE xorBits #-}

class OrBits a where
  orBits :: a -> a -> a

instance OrBits (DVS.Vector Word64) where
  orBits :: Vector Word64 -> Vector Word64 -> Vector Word64
orBits Vector Word64
a Vector Word64
b = forall a. IO a -> a
F.unsafeLocalState forall a b. (a -> b) -> a -> b
$ do
    let (ForeignPtr Word8
srcAFptr, Int
srcAOffset, Int
srcALength) = Int -> Vector Word64 -> (ForeignPtr Word8, Int, Int)
unsafeToElemSizedForeignPtr Int
64 Vector Word64
a
    let (ForeignPtr Word8
srcBFptr, Int
srcBOffset, Int
srcBLength) = Int -> Vector Word64 -> (ForeignPtr Word8, Int, Int)
unsafeToElemSizedForeignPtr Int
64 Vector Word64
b
    ForeignPtr Word8
targetFptr <- forall a. Int -> IO (ForeignPtr a)
F.mallocForeignPtrBytes Int
srcALength
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
srcAFptr forall a b. (a -> b) -> a -> b
$ \Ptr Word8
srcAPtr -> do
      forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
srcBFptr forall a b. (a -> b) -> a -> b
$ \Ptr Word8
srcBPtr -> do
        forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
targetFptr forall a b. (a -> b) -> a -> b
$ \Ptr Word8
targetPtr -> do
          ()
_ <- Ptr UInt8 -> Size -> Ptr UInt8 -> Ptr UInt8 -> IO ()
F.avx2OrBits
            (forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
targetPtr)
            (forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
srcALength forall a. Ord a => a -> a -> a
`min` Int
srcBLength))
            (forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
srcAPtr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` Int
srcAOffset)
            (forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
srcBPtr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` Int
srcBOffset)
          forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. (Storable a, Storable b) => Vector a -> Vector b
DVS.unsafeCast (forall a. Storable a => ForeignPtr a -> Int -> Int -> Vector a
DVS.unsafeFromForeignPtr ForeignPtr Word8
targetFptr Int
0 Int
srcALength :: DVS.Vector Word8)
  {-# INLINE orBits #-}

instance OrBits [DVS.Vector Word64] where
  orBits :: [Vector Word64] -> [Vector Word64] -> [Vector Word64]
orBits = forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith forall a. OrBits a => a -> a -> a
orBits
  {-# INLINE orBits #-}

class AndBits a where
  andBits :: a -> a -> a

instance AndBits (DVS.Vector Word64) where
  andBits :: Vector Word64 -> Vector Word64 -> Vector Word64
andBits Vector Word64
a Vector Word64
b = forall a. IO a -> a
F.unsafeLocalState forall a b. (a -> b) -> a -> b
$ do
    let (ForeignPtr Word8
srcAFptr, Int
srcAOffset, Int
srcALength) = Int -> Vector Word64 -> (ForeignPtr Word8, Int, Int)
unsafeToElemSizedForeignPtr Int
64 Vector Word64
a
    let (ForeignPtr Word8
srcBFptr, Int
srcBOffset, Int
srcBLength) = Int -> Vector Word64 -> (ForeignPtr Word8, Int, Int)
unsafeToElemSizedForeignPtr Int
64 Vector Word64
b
    ForeignPtr Word8
targetFptr <- forall a. Int -> IO (ForeignPtr a)
F.mallocForeignPtrBytes Int
srcALength
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
srcAFptr forall a b. (a -> b) -> a -> b
$ \Ptr Word8
srcAPtr -> do
      forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
srcBFptr forall a b. (a -> b) -> a -> b
$ \Ptr Word8
srcBPtr -> do
        forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
targetFptr forall a b. (a -> b) -> a -> b
$ \Ptr Word8
targetPtr -> do
          ()
_ <- Ptr UInt8 -> Size -> Ptr UInt8 -> Ptr UInt8 -> IO ()
F.avx2AndBits
            (forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
targetPtr)
            (forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
srcALength forall a. Ord a => a -> a -> a
`min` Int
srcBLength))
            (forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
srcAPtr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` Int
srcAOffset)
            (forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
srcBPtr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` Int
srcBOffset)
          forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. (Storable a, Storable b) => Vector a -> Vector b
DVS.unsafeCast (forall a. Storable a => ForeignPtr a -> Int -> Int -> Vector a
DVS.unsafeFromForeignPtr ForeignPtr Word8
targetFptr Int
0 Int
srcALength :: DVS.Vector Word8)
  {-# INLINE andBits #-}

instance AndBits [DVS.Vector Word64] where
  andBits :: [Vector Word64] -> [Vector Word64] -> [Vector Word64]
andBits = forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith forall a. AndBits a => a -> a -> a
andBits
  {-# INLINE andBits #-}

class AndNotBits a where
  andNotBits :: a -> a -> a

instance AndNotBits (DVS.Vector Word64) where
  andNotBits :: Vector Word64 -> Vector Word64 -> Vector Word64
andNotBits Vector Word64
a Vector Word64
b = forall a. IO a -> a
F.unsafeLocalState forall a b. (a -> b) -> a -> b
$ do
    let (ForeignPtr Word8
srcAFptr, Int
srcAOffset, Int
srcALength) = Int -> Vector Word64 -> (ForeignPtr Word8, Int, Int)
unsafeToElemSizedForeignPtr Int
64 Vector Word64
a
    let (ForeignPtr Word8
srcBFptr, Int
srcBOffset, Int
srcBLength) = Int -> Vector Word64 -> (ForeignPtr Word8, Int, Int)
unsafeToElemSizedForeignPtr Int
64 Vector Word64
b
    ForeignPtr Word8
targetFptr <- forall a. Int -> IO (ForeignPtr a)
F.mallocForeignPtrBytes Int
srcALength
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
srcAFptr forall a b. (a -> b) -> a -> b
$ \Ptr Word8
srcAPtr -> do
      forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
srcBFptr forall a b. (a -> b) -> a -> b
$ \Ptr Word8
srcBPtr -> do
        forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
targetFptr forall a b. (a -> b) -> a -> b
$ \Ptr Word8
targetPtr -> do
          ()
_ <- Ptr UInt8 -> Size -> Ptr UInt8 -> Ptr UInt8 -> IO ()
F.avx2AndNotBits
            (forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
targetPtr)
            (forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
srcALength forall a. Ord a => a -> a -> a
`min` Int
srcBLength))
            (forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
srcAPtr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` Int
srcAOffset)
            (forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
srcBPtr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` Int
srcBOffset)
          forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. (Storable a, Storable b) => Vector a -> Vector b
DVS.unsafeCast (forall a. Storable a => ForeignPtr a -> Int -> Int -> Vector a
DVS.unsafeFromForeignPtr ForeignPtr Word8
targetFptr Int
0 Int
srcALength :: DVS.Vector Word8)
  {-# INLINE andNotBits #-}

instance AndNotBits [DVS.Vector Word64] where
  andNotBits :: [Vector Word64] -> [Vector Word64] -> [Vector Word64]
andNotBits = forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith forall a. AndBits a => a -> a -> a
andBits
  {-# INLINE andNotBits #-}

class NotBits a where
  notBits :: a -> a

instance NotBits (DVS.Vector Word64) where
  notBits :: Vector Word64 -> Vector Word64
notBits Vector Word64
a = forall a. IO a -> a
F.unsafeLocalState forall a b. (a -> b) -> a -> b
$ do
    let (ForeignPtr Word8
srcFptr, Int
srcOffset, Int
srcLength) = Int -> Vector Word64 -> (ForeignPtr Word8, Int, Int)
unsafeToElemSizedForeignPtr Int
64 Vector Word64
a
    ForeignPtr Word8
targetFptr <- forall a. Int -> IO (ForeignPtr a)
F.mallocForeignPtrBytes Int
srcLength
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
srcFptr forall a b. (a -> b) -> a -> b
$ \Ptr Word8
srcPtr -> do
      forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
targetFptr forall a b. (a -> b) -> a -> b
$ \Ptr Word8
targetPtr -> do
        ()
_ <- Ptr UInt8 -> Size -> Ptr UInt8 -> IO ()
F.avx2NotBits
          (forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
targetPtr)
          (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
srcLength)
          (forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
srcPtr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` Int
srcOffset)
        forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. (Storable a, Storable b) => Vector a -> Vector b
DVS.unsafeCast (forall a. Storable a => ForeignPtr a -> Int -> Int -> Vector a
DVS.unsafeFromForeignPtr ForeignPtr Word8
targetFptr Int
0 Int
srcLength :: DVS.Vector Word8)
  {-# INLINE notBits #-}

instance NotBits [DVS.Vector Word64] where
  notBits :: [Vector Word64] -> [Vector Word64]
notBits = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. NotBits a => a -> a
notBits
  {-# INLINE notBits #-}