2009-06-15 10 views
3

Ich habe den folgende C-Code:Pass Zeiger auf ein Array in Haskell zu einer C-Funktion

#include <sys/times.h> 
#include <time.h> 


float etime_(float *tarray) 
{ struct tms buf; 

    times(&buf); 

    tarray[0] = 1.0 * buf.tms_utime/CLOCKS_PER_SEC; 
    tarray[1] = 1.0 * buf.tms_stime/CLOCKS_PER_SEC; 

    return tarray[0] + tarray[1]; 
} 

diesen Fortran-Code zu Haskell zu Port Versuch:

PROGRAM Test 
    IMPLICIT NONE 

    REAL t, ta(2), etime 

    INTEGER i 
    DOUBLE PRECISION x 

    do i = 1, 10000 
     x = sin(cos(i * 1.0 d0)) 
     print *, x 
    enddo 

    ta(1) = 0.0d0 
    ta(2) = 0.0d0 

    t = etime(ta)  

    PRINT *, 'user time: ', ta(1) 
    PRINT *, 'system time: ', ta(2) 
    PRINT *, 'process time: ', t 

    END 

Wie kann ich Array definieren und ! oder !!! für den folgenden Code zu arbeiten?

module Main where 

import GHC.Ptr 
import GHC.Prim 
import System.IO.Unsafe 
import Control.Monad 

foreign import ccall etime_ :: Ptr Double → IO Double 
etime = etime_ 

main :: IO Int 
main = do 
    mapM_ (print . sin . cos . (* (1.0 :: Double)) . fromIntegral) [1..10000 :: Int] 
    ta ← array 2 
    t ← etime ta 
    putStrLn $ "user time: " ++ show (ta !!! 0) 
    putStrLn $ "system time: " ++ show (ta !!! 1) 
    putStrLn $ "process time: " ++ show t 
    return 0 

array :: Int → IO (Ptr a) 
array size = undefined 

(!) :: Ptr a → Int → IO a 
(!) = undefined 

(!!!) :: Ptr a → Int → a 
(!!!) = undefined 

Antwort

2

Ich schlage vor, diese:

{-# LANGUAGE ForeignFunctionInterface #-} 

import Foreign.Marshal.Array (allocaArray, peekArray) 
import Foreign.Ptr (Ptr) 

foreign import ccall etime_ :: Ptr Float -> IO Float 

main :: IO() 
main = do 
    mapM_ (print . sin . cos . (* (1.0 :: Double)) . fromIntegral) [1..10000 :: Int] 
    allocaArray 2 $ \ta -> do 
    ptime <- etime_ ta 
    [utime, stime] <- peekArray 2 ta 
    putStrLn $ "user time: " ++ show utime 
    putStrLn $ "system time: " ++ show stime 
    putStrLn $ "process time: " ++ show ptime 

aber, spezifische Fragen zu beantworten:

array :: Storable a => Int -> IO (Ptr a) 
array = mallocArray 

(!) :: Storable a => Ptr a -> Int -> IO a 
(!) = peekElemOff 

(!!!) :: Storable a => Ptr a -> Int -> a 
(!!!) ptr = unsafePerformIO . peekElemOff ptr 

Ich schlage vor, die Funktionen zu finden, zu verwenden Hoogle Sie benötigen.

0

Geben Sie die Summe, die Benutzerzeit und die Systemzeit als Tupel ein. Beachten Sie nimmt, dass etime einen Zeiger zu schweben, nicht zu verdoppeln, so machen Sie Ihre Arten einig:

{-# LANGUAGE ForeignFunctionInterface #-} 

module Main where 

import Foreign (Ptr) 
import Foreign.Marshal.Array (allocaArray,peekArray) 
import Control.Monad (mapM_) 

foreign import ccall etime_ :: Ptr Float -> IO Float 

etime :: IO (Float, Float, Float) 
etime = do 
    allocaArray 2 $ \ta -> do 
    t <- etime_ ta 
    [user,sys] <- peekArray 2 ta 
    return (t,user,sys) 

main :: IO Int 
main = do 
    mapM_ (print . sin . cos . (* (1.0 :: Double)) . fromIntegral) [1..10000 :: Int] 
    (t,user,sys) <- etime 
    putStrLn $ "user time: " ++ show user 
    putStrLn $ "system time: " ++ show sys 
    putStrLn $ "process time: " ++ show t 
    return 0 
+0

Gibt es einen Präzisionsunterschied zwischen Float und Double in Haskell? sind beide Primitive oder float zu double wie ganze Zahl zu int? –

+0

Ja: Das Prelude definiert Float und Double für Gleitkommazahlen mit einfacher und doppelter Genauigkeit. Siehe Abschnitt "Zahlen" des Haskell-Berichts: http://www.haskell.org/onlinereport/basic.html#sect6.4 –

-2

die folgenden zusätzlichen Haskell Modul Gegeben:

module AllocSymbols (

    (↑≣), -- mallocArray 
    (≣⊠), -- free 

    (≣→), -- peekElemOff 
    (≣←), -- pokeElemOff 

    (⥱), -- peekElemOff unsafe 

    (⥅), -- advancePtr 

) where 

import GHC.Ptr 
import System.IO.Unsafe 
import Foreign.Storable 
import Foreign.Marshal.Alloc (free) 
import Foreign.Marshal.Array 

(↑≣) :: Storable a ⇒ Int → IO (Ptr a) 
(↑≣) = mallocArray 

(⥱) :: Storable a ⇒ Ptr a → Int → a 
a ⥱ i = unsafePerformIO $ peekElemOff a i 

(≣→) :: Storable a ⇒ Ptr a → Int → IO a 
(≣→) = peekElemOff 

(≣←) :: Storable a ⇒ Ptr a → Int → a → IO() 
(≣←) = pokeElemOff 

(⥅) :: Storable a ⇒ Ptr a → Int → Ptr a 
(⥅) = advancePtr 

(≣⊠) :: Ptr a → IO() 
(≣⊠) = Foreign.Marshal.Alloc.free 

Und wir können Port dieses Stück Fortran-Code:

PROGRAM Test 
    IMPLICIT NONE 

    REAL t, ta(2), etime 

    INTEGER i 
    DOUBLE PRECISION x 

    do i = 1, 10000 
     x = sin(cos(i * 1.0 d0)) 
     print *, x 
    enddo 

    ta(1) = 0.0d0 
    ta(2) = 0.0d0 

    t = etime(ta)  

    PRINT *, 'user time: ', ta(1) 
    PRINT *, 'system time: ', ta(2) 
    PRINT *, 'process time: ', t 

    END 

Wort für Wort zu Haskell:

module Main where 

import GHC.Ptr 
import AllocSymbols 
import Control.Monad 

foreign import ccall etime_ :: Ptr Float → IO Float 

main :: IO() 
main = do 
    mapM_ (print . sin . cos . (* (1.0 :: Double)) . fromIntegral) [1 .. 10000 :: Int] 

    ta ← (2 ↑≣) -- ta :: Ptr Float 

    (ta ≣← 0) 0.0 
    (ta ≣← 1) 0.0 

    t ← etime_ ta 

    putStrLn $ " user time: " ++ show (ta ⥱ 0) 
    putStrLn $ " system time: " ++ show (ta ⥱ 1) 
    putStrLn $ " process time: " ++ show t 

    (ta ≣⊠) -- optional in this case 
+1

Mögen Sie Betreiber so sehr? Ich denke, der Code wäre mehr Newbie-freundlich mit den Standard-Funktionsnamen .. – yairchu

+0

Ich denke, ich bin ziemlich seltsam und seltsam o__O. Ich liebe sie so ~~~ viel !! Und weil mein Haskell Code hauptsächlich für mich selbst ist, benutze ich sie großzügig *^o^* !! Wenn ich jemals mit anderen bei einem gemeinsamen Projekt zusammenarbeite, werde ich auf jeden Fall dafür sorgen, dass die Dinge freundlich und wartungsfreundlich bleiben, und werde es vermeiden, so viele Rückseiten einzuführen. –