erthalion
erthalion

Reputation: 3244

Haskell: read [Double] from binary file

I have a file with binary data (more precisely, it's a npy file = header data + raw binary data). This data ([0.1, 0.2, 0.3, 0.4] for tests) can be successfully readed by this code in C++ (skipped):

int word_size = 8;
double *data;
arr = new char[size*word_size];
size_t nread = fread(arr, word_size, size, file);
if(nread != size)
    *data = reinterpret_cast<double *>(arr);

I'm trying to implement this in Haskell:

data Header = Header {
    {- other fields -}
    npyData         :: [Double]
    } deriving (Show)

getNpyData = do
    empty <- isEmpty
    if empty
        then return []
        else do 
            v <- getWord64be
            rest <- getNpyData
            return (fromIntegral v : rest)

npyHeader :: Get Header
npyHeader = do
    {-other fields -}
    npyData <- getNpyData
    return Header {
        {- other fields -}
        npyData=npyData
    }


main = do
    file <- openBinaryFile "test.npy" ReadMode
    input <- BL.hGetContents file
    let npyParsedData = runGet npyHeader input
    print $ npyData npyParsedData

This gives to me incorrect results for npyData (other variables are ok):

[1.1140104038263667e19,1.114010403826367e19,3.6893488147419515e18,1.1140104038263675e19]

Can anybody tell me, what is wrong in this code?

Upvotes: 0

Views: 326

Answers (2)

Tim
Tim

Reputation: 2796

Unfortunately, what should work

     v <- get :: Double

doesn't since Data.Binary doesn't use an IEEE754 encoding of doubles (it stores the result of decodeFloat). Hence a good choice is to use the cereal package. At least within GHC I've gotten unsafeCoerce on a Word64 to work for similar tasks as well.

    bitsToDouble :: Word64 -> Double
    bitsToDouble = unsafeCoerce

Probably cereal is a safer way of doing this.

Upvotes: 1

ErikR
ErikR

Reputation: 52039

You should try the getFloat... and getDouble... functions from the cereal package (link).

What your code is doing is reading a 64-bit integer value and converting that do a Double.

Upvotes: 2

Related Questions