{-# 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 = IO (Vector Word64) -> Vector Word64
forall a. IO a -> a
F.unsafeLocalState (IO (Vector Word64) -> Vector Word64)
-> IO (Vector Word64) -> Vector Word64
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 <- Int -> IO (ForeignPtr Word8)
forall a. Int -> IO (ForeignPtr a)
F.mallocForeignPtrBytes Int
srcALength
    ForeignPtr Word8
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
srcAFptr ((Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64))
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
srcAPtr -> do
      ForeignPtr Word8
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
srcBFptr ((Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64))
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
srcBPtr -> do
        ForeignPtr Word8
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
targetFptr ((Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64))
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
targetPtr -> do
          ()
_ <- Ptr UInt8 -> Size -> Ptr UInt8 -> Ptr UInt8 -> IO ()
F.avx2XorBits
            (Ptr Word8 -> Ptr UInt8
forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
targetPtr)
            (Int -> Size
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
srcALength Int -> Int -> Int
forall a. Ord a => a -> a -> a
`min` Int
srcBLength))
            (Ptr Word8 -> Ptr Any
forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
srcAPtr Ptr Any -> Int -> Ptr UInt8
forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` Int
srcAOffset)
            (Ptr Word8 -> Ptr Any
forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
srcBPtr Ptr Any -> Int -> Ptr UInt8
forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` Int
srcBOffset)
          Vector Word64 -> IO (Vector Word64)
forall (m :: * -> *) a. Monad m => a -> m a
return (Vector Word64 -> IO (Vector Word64))
-> Vector Word64 -> IO (Vector Word64)
forall a b. (a -> b) -> a -> b
$ Vector Word8 -> Vector Word64
forall a b. (Storable a, Storable b) => Vector a -> Vector b
DVS.unsafeCast (ForeignPtr Word8 -> Int -> Int -> Vector Word8
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 = (Vector Word64 -> Vector Word64 -> Vector Word64)
-> [Vector Word64] -> [Vector Word64] -> [Vector Word64]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Vector Word64 -> Vector Word64 -> Vector Word64
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 = IO (Vector Word64) -> Vector Word64
forall a. IO a -> a
F.unsafeLocalState (IO (Vector Word64) -> Vector Word64)
-> IO (Vector Word64) -> Vector Word64
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 <- Int -> IO (ForeignPtr Word8)
forall a. Int -> IO (ForeignPtr a)
F.mallocForeignPtrBytes Int
srcALength
    ForeignPtr Word8
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
srcAFptr ((Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64))
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
srcAPtr -> do
      ForeignPtr Word8
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
srcBFptr ((Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64))
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
srcBPtr -> do
        ForeignPtr Word8
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
targetFptr ((Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64))
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
targetPtr -> do
          ()
_ <- Ptr UInt8 -> Size -> Ptr UInt8 -> Ptr UInt8 -> IO ()
F.avx2OrBits
            (Ptr Word8 -> Ptr UInt8
forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
targetPtr)
            (Int -> Size
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
srcALength Int -> Int -> Int
forall a. Ord a => a -> a -> a
`min` Int
srcBLength))
            (Ptr Word8 -> Ptr Any
forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
srcAPtr Ptr Any -> Int -> Ptr UInt8
forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` Int
srcAOffset)
            (Ptr Word8 -> Ptr Any
forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
srcBPtr Ptr Any -> Int -> Ptr UInt8
forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` Int
srcBOffset)
          Vector Word64 -> IO (Vector Word64)
forall (m :: * -> *) a. Monad m => a -> m a
return (Vector Word64 -> IO (Vector Word64))
-> Vector Word64 -> IO (Vector Word64)
forall a b. (a -> b) -> a -> b
$ Vector Word8 -> Vector Word64
forall a b. (Storable a, Storable b) => Vector a -> Vector b
DVS.unsafeCast (ForeignPtr Word8 -> Int -> Int -> Vector Word8
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 = (Vector Word64 -> Vector Word64 -> Vector Word64)
-> [Vector Word64] -> [Vector Word64] -> [Vector Word64]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Vector Word64 -> Vector Word64 -> Vector Word64
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 = IO (Vector Word64) -> Vector Word64
forall a. IO a -> a
F.unsafeLocalState (IO (Vector Word64) -> Vector Word64)
-> IO (Vector Word64) -> Vector Word64
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 <- Int -> IO (ForeignPtr Word8)
forall a. Int -> IO (ForeignPtr a)
F.mallocForeignPtrBytes Int
srcALength
    ForeignPtr Word8
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
srcAFptr ((Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64))
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
srcAPtr -> do
      ForeignPtr Word8
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
srcBFptr ((Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64))
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
srcBPtr -> do
        ForeignPtr Word8
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
targetFptr ((Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64))
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
targetPtr -> do
          ()
_ <- Ptr UInt8 -> Size -> Ptr UInt8 -> Ptr UInt8 -> IO ()
F.avx2AndBits
            (Ptr Word8 -> Ptr UInt8
forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
targetPtr)
            (Int -> Size
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
srcALength Int -> Int -> Int
forall a. Ord a => a -> a -> a
`min` Int
srcBLength))
            (Ptr Word8 -> Ptr Any
forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
srcAPtr Ptr Any -> Int -> Ptr UInt8
forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` Int
srcAOffset)
            (Ptr Word8 -> Ptr Any
forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
srcBPtr Ptr Any -> Int -> Ptr UInt8
forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` Int
srcBOffset)
          Vector Word64 -> IO (Vector Word64)
forall (m :: * -> *) a. Monad m => a -> m a
return (Vector Word64 -> IO (Vector Word64))
-> Vector Word64 -> IO (Vector Word64)
forall a b. (a -> b) -> a -> b
$ Vector Word8 -> Vector Word64
forall a b. (Storable a, Storable b) => Vector a -> Vector b
DVS.unsafeCast (ForeignPtr Word8 -> Int -> Int -> Vector Word8
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 = (Vector Word64 -> Vector Word64 -> Vector Word64)
-> [Vector Word64] -> [Vector Word64] -> [Vector Word64]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Vector Word64 -> Vector Word64 -> Vector Word64
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 = IO (Vector Word64) -> Vector Word64
forall a. IO a -> a
F.unsafeLocalState (IO (Vector Word64) -> Vector Word64)
-> IO (Vector Word64) -> Vector Word64
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 <- Int -> IO (ForeignPtr Word8)
forall a. Int -> IO (ForeignPtr a)
F.mallocForeignPtrBytes Int
srcALength
    ForeignPtr Word8
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
srcAFptr ((Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64))
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
srcAPtr -> do
      ForeignPtr Word8
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
srcBFptr ((Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64))
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
srcBPtr -> do
        ForeignPtr Word8
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
targetFptr ((Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64))
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
targetPtr -> do
          ()
_ <- Ptr UInt8 -> Size -> Ptr UInt8 -> Ptr UInt8 -> IO ()
F.avx2AndNotBits
            (Ptr Word8 -> Ptr UInt8
forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
targetPtr)
            (Int -> Size
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
srcALength Int -> Int -> Int
forall a. Ord a => a -> a -> a
`min` Int
srcBLength))
            (Ptr Word8 -> Ptr Any
forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
srcAPtr Ptr Any -> Int -> Ptr UInt8
forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` Int
srcAOffset)
            (Ptr Word8 -> Ptr Any
forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
srcBPtr Ptr Any -> Int -> Ptr UInt8
forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` Int
srcBOffset)
          Vector Word64 -> IO (Vector Word64)
forall (m :: * -> *) a. Monad m => a -> m a
return (Vector Word64 -> IO (Vector Word64))
-> Vector Word64 -> IO (Vector Word64)
forall a b. (a -> b) -> a -> b
$ Vector Word8 -> Vector Word64
forall a b. (Storable a, Storable b) => Vector a -> Vector b
DVS.unsafeCast (ForeignPtr Word8 -> Int -> Int -> Vector Word8
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 = (Vector Word64 -> Vector Word64 -> Vector Word64)
-> [Vector Word64] -> [Vector Word64] -> [Vector Word64]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Vector Word64 -> Vector Word64 -> Vector Word64
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 = IO (Vector Word64) -> Vector Word64
forall a. IO a -> a
F.unsafeLocalState (IO (Vector Word64) -> Vector Word64)
-> IO (Vector Word64) -> Vector Word64
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 <- Int -> IO (ForeignPtr Word8)
forall a. Int -> IO (ForeignPtr a)
F.mallocForeignPtrBytes Int
srcLength
    ForeignPtr Word8
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
srcFptr ((Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64))
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
srcPtr -> do
      ForeignPtr Word8
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
targetFptr ((Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64))
-> (Ptr Word8 -> IO (Vector Word64)) -> IO (Vector Word64)
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
targetPtr -> do
        ()
_ <- Ptr UInt8 -> Size -> Ptr UInt8 -> IO ()
F.avx2NotBits
          (Ptr Word8 -> Ptr UInt8
forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
targetPtr)
          (Int -> Size
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
srcLength)
          (Ptr Word8 -> Ptr Any
forall a b. Ptr a -> Ptr b
F.castPtr Ptr Word8
srcPtr Ptr Any -> Int -> Ptr UInt8
forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` Int
srcOffset)
        Vector Word64 -> IO (Vector Word64)
forall (m :: * -> *) a. Monad m => a -> m a
return (Vector Word64 -> IO (Vector Word64))
-> Vector Word64 -> IO (Vector Word64)
forall a b. (a -> b) -> a -> b
$ Vector Word8 -> Vector Word64
forall a b. (Storable a, Storable b) => Vector a -> Vector b
DVS.unsafeCast (ForeignPtr Word8 -> Int -> Int -> Vector Word8
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 = (Vector Word64 -> Vector Word64)
-> [Vector Word64] -> [Vector Word64]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Vector Word64 -> Vector Word64
forall a. NotBits a => a -> a
notBits
  {-# INLINE notBits #-}