diff options
Diffstat (limited to 'lib/Data/Packed/Foreign.hs')
-rw-r--r-- | lib/Data/Packed/Foreign.hs | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/lib/Data/Packed/Foreign.hs b/lib/Data/Packed/Foreign.hs new file mode 100644 index 0000000..efa51ca --- /dev/null +++ b/lib/Data/Packed/Foreign.hs | |||
@@ -0,0 +1,99 @@ | |||
1 | {-# LANGUAGE MagicHash, UnboxedTuples #-} | ||
2 | -- | FFI and hmatrix helpers. | ||
3 | -- | ||
4 | -- Sample usage, to upload a perspective matrix to a shader. | ||
5 | -- | ||
6 | -- @ glUniformMatrix4fv 0 1 (fromIntegral gl_TRUE) \`appMatrix\` perspective 0.01 100 (pi\/2) (4\/3) | ||
7 | -- @ | ||
8 | -- | ||
9 | module Data.Packed.Foreign | ||
10 | ( app | ||
11 | , appVector, appVectorLen | ||
12 | , appMatrix, appMatrixLen, appMatrixRaw, appMatrixRawLen | ||
13 | , unsafeMatrixToVector, unsafeMatrixToForeignPtr | ||
14 | ) where | ||
15 | import Data.Packed.Internal | ||
16 | import qualified Data.Vector.Storable as S | ||
17 | import Foreign (Ptr, ForeignPtr, Storable) | ||
18 | import Foreign.C.Types (CInt) | ||
19 | import GHC.Base (IO(..), realWorld#) | ||
20 | |||
21 | {-# INLINE unsafeInlinePerformIO #-} | ||
22 | -- | If we use unsafePerformIO, it may not get inlined, so in a function that returns IO (which are all safe uses of app* in this module), there would be | ||
23 | -- unecessary calls to unsafePerformIO or its internals. | ||
24 | unsafeInlinePerformIO :: IO a -> a | ||
25 | unsafeInlinePerformIO (IO f) = case f realWorld# of | ||
26 | (# _, x #) -> x | ||
27 | |||
28 | {-# INLINE app #-} | ||
29 | -- | Only useful since it is left associated with a precedence of 1, unlike 'Prelude.$', which is right associative. | ||
30 | -- e.g. | ||
31 | -- | ||
32 | -- @ | ||
33 | -- someFunction | ||
34 | -- \`appMatrixLen\` m | ||
35 | -- \`appVectorLen\` v | ||
36 | -- \`app\` other | ||
37 | -- \`app\` arguments | ||
38 | -- \`app\` go here | ||
39 | -- @ | ||
40 | -- | ||
41 | -- One could also write: | ||
42 | -- | ||
43 | -- @ | ||
44 | -- (someFunction | ||
45 | -- \`appMatrixLen\` m | ||
46 | -- \`appVectorLen\` v) | ||
47 | -- other | ||
48 | -- arguments | ||
49 | -- (go here) | ||
50 | -- @ | ||
51 | -- | ||
52 | app :: (a -> b) -> a -> b | ||
53 | app f = f | ||
54 | |||
55 | {-# INLINE appVector #-} | ||
56 | appVector :: Storable a => (Ptr a -> b) -> Vector a -> b | ||
57 | appVector f x = unsafeInlinePerformIO (S.unsafeWith x (return . f)) | ||
58 | |||
59 | {-# INLINE appVectorLen #-} | ||
60 | appVectorLen :: Storable a => (CInt -> Ptr a -> b) -> Vector a -> b | ||
61 | appVectorLen f x = unsafeInlinePerformIO (S.unsafeWith x (return . f (fromIntegral (S.length x)))) | ||
62 | |||
63 | {-# INLINE appMatrix #-} | ||
64 | appMatrix :: Element a => (Ptr a -> b) -> Matrix a -> b | ||
65 | appMatrix f x = unsafeInlinePerformIO (S.unsafeWith (flatten x) (return . f)) | ||
66 | |||
67 | {-# INLINE appMatrixLen #-} | ||
68 | appMatrixLen :: Element a => (CInt -> CInt -> Ptr a -> b) -> Matrix a -> b | ||
69 | appMatrixLen f x = unsafeInlinePerformIO (S.unsafeWith (flatten x) (return . f r c)) | ||
70 | where | ||
71 | r = fromIntegral (rows x) | ||
72 | c = fromIntegral (cols x) | ||
73 | |||
74 | {-# INLINE appMatrixRaw #-} | ||
75 | appMatrixRaw :: Storable a => (Ptr a -> b) -> Matrix a -> b | ||
76 | appMatrixRaw f x = unsafeInlinePerformIO (S.unsafeWith (xdat x) (return . f)) | ||
77 | |||
78 | {-# INLINE appMatrixRawLen #-} | ||
79 | appMatrixRawLen :: Element a => (CInt -> CInt -> Ptr a -> b) -> Matrix a -> b | ||
80 | appMatrixRawLen f x = unsafeInlinePerformIO (S.unsafeWith (xdat x) (return . f r c)) | ||
81 | where | ||
82 | r = fromIntegral (rows x) | ||
83 | c = fromIntegral (cols x) | ||
84 | |||
85 | infixl 1 `app` | ||
86 | infixl 1 `appVector` | ||
87 | infixl 1 `appMatrix` | ||
88 | infixl 1 `appMatrixRaw` | ||
89 | |||
90 | {-# INLINE unsafeMatrixToVector #-} | ||
91 | -- | This will disregard the order of the matrix, and simply return it as-is. | ||
92 | -- If the order of the matrix is RowMajor, this function is identical to 'flatten'. | ||
93 | unsafeMatrixToVector :: Matrix a -> Vector a | ||
94 | unsafeMatrixToVector = xdat | ||
95 | |||
96 | {-# INLINE unsafeMatrixToForeignPtr #-} | ||
97 | unsafeMatrixToForeignPtr :: Storable a => Matrix a -> (ForeignPtr a, Int) | ||
98 | unsafeMatrixToForeignPtr m = S.unsafeToForeignPtr0 (xdat m) | ||
99 | |||