-- | Same as 'zipWithTo' but does not range-check dimensions.
unsafeZipWithTo :: (RVector v1, RVector v2, Storable e1, Storable e2, Storable f)
                => STVector s f
                -> (e1 -> e2 -> f)
                -> v1 e1
                -> v2 e2
                -> ST s ()
unsafeZipWithTo dst f src1 src2 =
    let go end pdst psrc1 psrc2 
            | pdst == end = 
                return ()
            | otherwise = do
                e1 <- peek psrc1
                e2 <- peek psrc2
                poke pdst (f e1 e2)
                go end (pdst `advancePtr` 1) (psrc1 `advancePtr` 1)
                   (psrc2 `advancePtr` 1)
    in do
        ndst <- getDim dst
        unsafeIOToST $
           unsafeWith dst $ \pdst ->
           unsafeWith src1 $ \psrc1 ->
           unsafeWith src2 $ \psrc2 -> 
               go (pdst `advancePtr` ndst) pdst psrc1 psrc2

unsafeZipWithTo :: (RVector v1, RVector v2, Storable e1, Storable e2, Storable f)
                => STVector s f
                -> (e1 -> e2 -> f)
                -> v1 e1
                -> v2 e2
                -> ST s ()
unsafeZipWithTo dst f src1 src2 =
    let go end pdst psrc1 psrc2 
            | pdst == end = 
                return ()
            | otherwise = do
                e1 <- peek psrc1
                e2 <- peek psrc2
                poke pdst (f e1 e2)
                go end (pdst `advancePtr` 1) (psrc1 `advancePtr` 1)
                   (psrc2 `advancePtr` 1)
    in do
        ndst <- getDim dst
        unsafeIOToST $
           unsafeWith dst $ \pdst ->
           unsafeWith src1 $ \psrc1 ->
           unsafeWith src2 $ \psrc2 -> 
               go (pdst `advancePtr` ndst) pdst psrc1 psrc2

unsafeZipWithTo dst f src1 src2 =
    let go end pdst psrc1 psrc2 
            | pdst == end = 
                return ()
            | otherwise = do
                e1 <- peek psrc1
                e2 <- peek psrc2
                poke pdst (f e1 e2)
                go end (pdst `advancePtr` 1) (psrc1 `advancePtr` 1)
                   (psrc2 `advancePtr` 1)
    in do
        ndst <- getDim dst
        unsafeIOToST $
           unsafeWith dst $ \pdst ->
           unsafeWith src1 $ \psrc1 ->
           unsafeWith src2 $ \psrc2 -> 
               go (pdst `advancePtr` ndst) pdst psrc1 psrc2
