Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6895561
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 27, 20262026-05-27T06:55:29+00:00 2026-05-27T06:55:29+00:00

I wrote a function to convert 64-bit Double to ByteString (architecture/type safety is not

  • 0

I wrote a function to convert 64-bit Double to ByteString (architecture/type safety is not really an issue – let us assume for now that the Double is 64-bit Word). While the function below works well, I am wondering if there is a faster way to convert the Double to ByteString. In the code below, there is one unpack of Word64 into Word8 list, followed by reverse (to make it little endian format), and then packing into ByteString. The code is below:

{-# LANGUAGE MagicHash #-}
import GHC.Prim
import GHC.Types
import GHC.Word
import Data.Bits (shiftR)
import Data.ByteString (pack, unpack)
import Data.ByteString.Internal (ByteString)
import Text.Printf (printf)

encodeDouble :: Double -> ByteString
encodeDouble (D# x) = pack $ reverse $ unpack64 $ W64# (unsafeCoerce# x)

unpack64 :: Word64 -> [Word8]
unpack64 x = map (fromIntegral.(shiftR x)) [56,48..0]

-- function to convert list of bytestring into hex digits - for debugging
bprint :: ByteString -> String
bprint x = ("0x" ++ ) $ foldl (++) "" $ fmap (printf "%02x") $ unpack x

main = putStrLn $ bprint $ encodeDouble 7234.4

A sample GHCi output on Mac x86:

*Main> bprint $ encodeDouble 7234.4
"0x666666666642bc40"

While the code seems to work well, I plan to use it for encoding lot of Double values into ByteString before sending it over IPC. So, I will appreciate pointers on making it faster, if there are any.

It does seem to me that double must be unpacked into Word8, and then packed into ByteString. So, may be the overall algorithm as it is, can’t be improved upon much. But, using a more efficient unpack/pack function will probably make a difference, if there were one.

EDIT1:
I just discovered another complication on Mac (GHC 7.0.3) – the code above won’t compile in GHC because of this error – I was testing in GHCi so far:

$ ghc -O --make t.hs
[1 of 1] Compiling Main             ( t.hs, t.o )

/var/folders/_q/33htc59519b3xq7y6xv100z40000gp/T/ghc6976_0/ghc6976_0.s:285:0:
    suffix or operands invalid for `movsd'

/var/folders/_q/33htc59519b3xq7y6xv100z40000gp/T/ghc6976_0/ghc6976_0.s:304:0:
    suffix or operands invalid for `movsd'

So, it looks like I have to fall back on FFI (cereal/data-binary-ieee754 package) until this bug is fixed, or until I find a workaround. Looks like related to GHC Ticket 4092. Please correct me if this is a new bug, or a different bug. For now, I can’t compile it 🙁

EDIT2:
Updating the code to use unsafeCoerce fixes the compilation issue. Code below with Criterion benchmark:

{-# LANGUAGE MagicHash #-}
import GHC.Prim
import GHC.Types
import GHC.Word
import Data.Bits (shiftR)
import Data.ByteString (pack, unpack)
import Data.ByteString.Internal (ByteString)
import Text.Printf (printf)
import Unsafe.Coerce
import Criterion.Main

--encodeDouble :: Double -> ByteString
encodeDouble  x = pack $ reverse $ unpack64 $ unsafeCoerce x

unpack64 :: Word64 -> [Word8]
unpack64 x = map (fromIntegral.(shiftR x)) [56,48..0]

main = defaultMain [
        bgroup "encodeDouble" [
          bench "78901.234"  $ whnf encodeDouble 78901.234
          , bench "789.01" $ whnf encodeDouble 789.01
          ]
       ]

Criterion Output (truncated):

estimating cost of a clock call...
mean is 46.09080 ns (36 iterations)

benchmarking encodeDouble/78901.234
mean: 218.8732 ns, lb 218.4946 ns, ub 219.3389 ns, ci 0.950
std dev: 2.134809 ns, lb 1.757455 ns, ub 2.568828 ns, ci 0.950

benchmarking encodeDouble/789.01
mean: 219.5382 ns, lb 219.0744 ns, ub 220.1296 ns, ci 0.950
std dev: 2.675674 ns, lb 2.197591 ns, ub 3.451464 ns, ci 0.950

On further analysis, most of the bottleneck seems to be in unpack64. Coercion takes ~6ns. unpack64 takes ~195ns. Unpacking the word64 as a list of word8 is quite expensive here.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-27T06:55:30+00:00Added an answer on May 27, 2026 at 6:55 am

    Note that the use of unsafeCoerce# is dangerous here, the docs say

    Casting an unboxed type to another unboxed type of the same size (but not coercions between floating-point and integral types)

    Concerning the speed, it may be faster to avoid the intermediate list and directly write to the memory via unsafeCreate from Data.ByteString.Internal.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I wrote a SQL function to convert a datetime value in SQL to a
I want to convert function object to function. I wrote this code, but it
I wrote a function in bash script. However, it's complaining about syntax. I really
I wrote a function to match fingerprint templates using VC++.NET. Now I want to
I wrote the following function to convert a time in milliseconds to a string
I wanted to write a function that would take an object and convert it
I wrote this function that's supposed to do StringPadRight("Hello", 10, "0") -> "Hello00000" .
I wrote this function for filling closed loop, pixvali is declared globally to store
I wrote this function to get the unread count of google reader items. function
I wrote this function to get a pseudo random float between 0 .. 1

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.