module Data.Vector.Coerce.Word
( downcast
, upcast
, upcast'
, CmpWord
) where
import qualified Data.Vector.Storable as V
import Data.Vector.Storable (Vector)
import Data.Word
import Foreign.Storable
import Foreign.ForeignPtr
downcast :: (CmpWord a b ~ 'GT, Storable a, Storable b) => Vector a -> Vector b
downcast = V.unsafeCast
upcast :: (CmpWord a b ~ 'LT, Storable a, Storable b) => Vector a -> Vector b
upcast = V.unsafeCast
upcast' :: forall a b. (CmpWord a b ~ 'LT, Storable a, Storable b) => Vector a -> (Vector b, Vector a)
upcast' v =
if leftoverElems == 0
then (upcast v, V.empty)
else (upcast v, V.drop takenElems v)
where
n = V.length v
newToOldRatio = bSize `quot` aSize
leftoverElems = n `rem` newToOldRatio
takenElems = n leftoverElems
aSize = sizeOf (undefined :: a)
bSize = sizeOf (undefined :: b)
type family CmpWord (a :: *) (b :: *) :: Ordering where
CmpWord Word8 Word8 = 'EQ
CmpWord Word8 Word16 = 'LT
CmpWord Word8 Word32 = 'LT
CmpWord Word8 Word64 = 'LT
CmpWord Word16 Word8 = 'GT
CmpWord Word16 Word16 = 'EQ
CmpWord Word16 Word32 = 'LT
CmpWord Word16 Word64 = 'LT
CmpWord Word32 Word8 = 'GT
CmpWord Word32 Word16 = 'GT
CmpWord Word32 Word32 = 'EQ
CmpWord Word32 Word64 = 'LT
CmpWord Word64 Word8 = 'GT
CmpWord Word64 Word16 = 'GT
CmpWord Word64 Word32 = 'GT
CmpWord Word64 Word64 = 'EQ