{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FlexibleContexts #-} module Data.Primitive.SIMD.Class where -- This code was AUTOMATICALLY generated, DO NOT EDIT! import Control.Monad.Primitive import Data.Primitive -- | The compiler only supports tuples up to 62 elements, so we have to use our own data type. data Tuple64 a = Tuple64 a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a -- * SIMD type classes -- | This class provides basic operations to create and consume SIMD types. -- Numeric operations on members of this class should compile to single -- SIMD instructions although not all operations are (yet) supported by -- GHC (e.g. 'sqrt', it is currently implemented as @mapVector sqrt@ which -- has to unpack the vector, compute the results and pack them again). class (Num v, Real (Elem v)) => SIMDVector v where -- | Type of the elements in the vector type Elem v -- | Type used to pack or unpack the vector type ElemTuple v -- | Vector with all elements initialized to zero. nullVector :: v -- | Number of components (scalar elements) in the vector. The argument is not evaluated. vectorSize :: v -> Int -- | Size of each (scalar) element in the vector in bytes. The argument is not evaluated. elementSize :: v -> Int -- | Broadcast a scalar to all elements of a vector. broadcastVector :: Elem v -> v -- | Insert a scalar at the given position (starting from 0) in a vector. If the index is outside of the range an exception is thrown. insertVector :: v -> Elem v -> Int -> v insertVector v e i | i < 0 = error $ "insertVector: negative argument: " ++ show i | i < vectorSize v = unsafeInsertVector v e i | otherwise = error $ "insertVector: argument too large: " ++ show i -- | Insert a scalar at the given position (starting from 0) in a vector. If the index is outside of the range the behavior is undefined. unsafeInsertVector :: v -> Elem v -> Int -> v -- | Apply a function to each element of a vector. Be very careful not to map -- branching functions over a vector as they could lead to quite a bit of -- code bloat (or make sure they are tagged with NOINLINE). mapVector :: (Elem v -> Elem v) -> v -> v -- | Zip two vectors together using a combining function. zipVector :: (Elem v -> Elem v -> Elem v) -> v -> v -> v -- | Fold the elements of a vector to a single value. The order in which -- the elements are combined is not specified. foldVector :: (Elem v -> Elem v -> Elem v) -> v -> Elem v -- | Sum up the components of the vector. Equivalent to @foldVector (+)@. sumVector :: v -> Elem v sumVector = foldVector (+) -- | Pack some elements to a vector. packVector :: ElemTuple v -> v -- | Unpack a vector. unpackVector :: v -> ElemTuple v -- | Provides vectorized versions of 'quot' and 'rem'. Implementing their -- type class is not possible for SIMD types as it would require -- implementing 'toInteger'. class SIMDVector v => SIMDIntVector v where -- | Rounds towards zero element-wise. quotVector :: v -> v -> v -- | Satisfies @(quotVector x y) * y + (remVector x y) == x@. remVector :: v -> v -> v {-# INLINE setByteArrayGeneric #-} setByteArrayGeneric :: (Prim a, PrimMonad m) => MutableByteArray (PrimState m) -> Int -> Int -> a -> m () setByteArrayGeneric mba off n v | n <= 0 = return () | otherwise = do writeByteArray mba off v setByteArrayGeneric mba (off + 1) (n - 1) v {-# INLINE setOffAddrGeneric #-} setOffAddrGeneric :: (Prim a, PrimMonad m) => Addr -> Int -> Int -> a -> m () setOffAddrGeneric addr off n v | n <= 0 = return () | otherwise = do writeOffAddr addr off v setOffAddrGeneric addr (off + 1) (n - 1) v