我想存储一个非参数,解压缩的数据类型
data Point3D = Point3D {-# UNPACK #-} !Int {-# UNPACK #-} !Int {-# UNPACK #-} !Int
Run Code Online (Sandbox Code Playgroud)
在未装箱的矢量中.Data.Vector.Unboxed说:
特别地,对的未装箱的矢量表示为未装箱的矢量对.
这是为什么?我希望在内存中一个接一个地Point3D布局,以便在顺序迭代它们时获得快速缓存本地访问 - 相当于C语言.mystruct[1000]
使用Vector.Unboxed或以其他方式,我如何实现这一目标?
顺便说一句:使用vector-th-unbox也会发生同样的情况,因为只需将数据类型转换为(Unbox a, Unbox b) => Unbox (a, b) 实例.
我不知道为什么对的向量存储为向量对,但是您可以轻松地为您的数据类型编写实例以按顺序存储元素.
{-# LANGUAGE TypeFamilies, MultiParamTypeClasses #-}
import qualified Data.Vector.Generic as G
import qualified Data.Vector.Generic.Mutable as M
import Control.Monad (liftM, zipWithM_)
import Data.Vector.Unboxed.Base
data Point3D = Point3D {-# UNPACK #-} !Int {-# UNPACK #-} !Int {-# UNPACK #-} !Int
newtype instance MVector s Point3D = MV_Point3D (MVector s Int)
newtype instance Vector Point3D = V_Point3D (Vector Int)
instance Unbox Point3D
Run Code Online (Sandbox Code Playgroud)
此时,最后一行将导致错误,因为没有矢量类型的实例Point3D.它们可以写成如下:
instance M.MVector MVector Point3D where
basicLength (MV_Point3D v) = M.basicLength v `div` 3
basicUnsafeSlice a b (MV_Point3D v) = MV_Point3D $ M.basicUnsafeSlice (a*3) (b*3) v
basicOverlaps (MV_Point3D v0) (MV_Point3D v1) = M.basicOverlaps v0 v1
basicUnsafeNew n = liftM MV_Point3D (M.basicUnsafeNew (3*n))
basicUnsafeRead (MV_Point3D v) n = do
[a,b,c] <- mapM (M.basicUnsafeRead v) [3*n,3*n+1,3*n+2]
return $ Point3D a b c
basicUnsafeWrite (MV_Point3D v) n (Point3D a b c) = zipWithM_ (M.basicUnsafeWrite v) [3*n,3*n+1,3*n+2] [a,b,c]
instance G.Vector Vector Point3D where
basicUnsafeFreeze (MV_Point3D v) = liftM V_Point3D (G.basicUnsafeFreeze v)
basicUnsafeThaw (V_Point3D v) = liftM MV_Point3D (G.basicUnsafeThaw v)
basicLength (V_Point3D v) = G.basicLength v `div` 3
basicUnsafeSlice a b (V_Point3D v) = V_Point3D $ G.basicUnsafeSlice (a*3) (b*3) v
basicUnsafeIndexM (V_Point3D v) n = do
[a,b,c] <- mapM (G.basicUnsafeIndexM v) [3*n,3*n+1,3*n+2]
return $ Point3D a b c
Run Code Online (Sandbox Code Playgroud)
我认为大多数函数定义都是自解释的.点的矢量被存储为一个矢量IntS和n第点是3n,3n+1,3n+2 Int秒.