Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Precision issue of double and uint64_t of xorshift64* #1

Open
jj1bdx opened this issue Nov 13, 2014 · 4 comments
Open

Precision issue of double and uint64_t of xorshift64* #1

jj1bdx opened this issue Nov 13, 2014 · 4 comments
Assignees

Comments

@jj1bdx
Copy link

jj1bdx commented Nov 13, 2014

On https://github.com/darach/jch-erl/blob/master/c_src/jch.c, a uint64_t (not necesarily unsigned long) seed is converted to double. An IEEE 754 floating point number only has 53-bit mantissa digits; dividing the seed is redundant and misleading (ULONG_MAX is also converted to an inaccurate 53-bit number).

An example of more efficient algorithm, using the higher 52 bits (discarding the lower 12 bits) of the 64-bit random unsigned integer to double precision floating point number is:

// uint_64 *x
// Forced casting of a 64-bit unsigned integer to double
// results in [1.0, 2.0) double numbers
return ((double)((*x >> 12) | 0x3ff0000000000000LL) - 1.0)

See http://en.wikipedia.org/wiki/Double-precision_floating-point_format for the details.

@jj1bdx
Copy link
Author

jj1bdx commented Nov 13, 2014

I also suggest you to use uint64_t instead of unsigned long. See https://github.com/jj1bdx/exs64/blob/master/c-example/xorshift64star.c

@darach
Copy link
Owner

darach commented Nov 13, 2014

I'll take a look this evening. Thanks for the pointers! Always a pleasure to learn from a PRNG geek... .:)

@darach darach self-assigned this Nov 13, 2014
@jj1bdx
Copy link
Author

jj1bdx commented Nov 13, 2014

@darach It's just some C tips :) , but will be effective on C. (I even tried these on Erlang, but using bitstrings did not make the code faster.)

@darach
Copy link
Owner

darach commented Nov 14, 2014

@jj1bdx I've changed unsigned long to uint64_t. I've left the PRNG as is for now as the overhead is dominated by the usual suspects, xorshift64* works well with the hash algorithm, and its fast enough for the use cases I have in mind. On the other hand, if you can make beam.smp process_main 5x faster I might have to revisit! ;)

# Overhead   Command         Shared Object                                      
Symbol
#
    50.70%  beam.smp  beam.smp              [.] process_main                    

     7.98%  beam.smp  jch_nif.so            [.] _jch_chash                      

     5.41%  beam.smp  jch_nif.so            [.] lcg_next                        

     3.75%  beam.smp  beam.smp              [.] erts_gc_mixed_times  

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants