cleaned up nrand48 function please check results ;)

S

Skybuck Flying

Hi,

This is a somewhat cleaned up version 0.02 of the nrand48() routine.

There are still a few issues:

This code needs brackets but where ?

X = (uint64) xsubi[2] << 32 | (uint32) xsubi[1] << 16 | xsubi[0];

This code also needs brackets but where ?

*result = xsubi[2] << 15 | xsubi[1] >> 1;

Since operator precedence is different in other languages etc... so this
code needs brackets to be able to port/convert/translate it to any other
language, to prevent errors/bugs and for clearity sakes ;)

The last thing to check is the output.

Can somebody on a unix system... run this program... preferablly *without*
all the extra code... and use the original nrand48() function... and then
compare the unix output with this windows xp output to see if it's exactly
the same ? That would be great =D

#include <stdlib.h>
#include <stdio.h>

typedef signed __int8 sint8;
typedef unsigned __int8 uint8;
typedef signed __int16 sint16;
typedef unsigned __int16 uint16;
typedef signed __int32 sint32;
typedef unsigned __int32 uint32;
typedef signed __int64 sint64;
typedef unsigned __int64 uint64;

/* Data structure for communication with thread safe versions. This
type is to be regarded as opaque. It's only exported because users
have to allocate objects of this type. */
struct drand48_data
{
uint16 __x[3]; /* Current state. */
uint16 __old_x[3]; /* Old state. */
uint16 __c; /* Additive const. in congruential formula. */
uint16 __init; /* Flag for initializing. */
uint64 __a; /* Factor in congruential formula. */
};


/* Global state for non-reentrant functions. */
struct drand48_data __libc_drand48_data;


int __drand48_iterate ( uint16 xsubi[3], struct drand48_data *buffer )
{
uint64 X;
uint64 result;

/* Initialize buffer, if not yet done. */
if (buffer->__init == 0)
{
buffer->__a = 0x5deece66du;
buffer->__c = 0xb;
buffer->__init = 1;
}

/* Do the real work. We choose a data type which contains at least
48 bits. Because we compute the modulus it does not care how
many bits really are computed. */

// this code needs brackets ! ( ( ) ) etc but where ?
X = (uint64) xsubi[2] << 32 | (uint32) xsubi[1] << 16 | xsubi[0];

result = X * buffer->__a + buffer->__c;

// use typecast to surpress warnings
xsubi[0] = uint16( result & 0xffff );
xsubi[1] = uint16( (result >> 16) & 0xffff );
xsubi[2] = uint16( (result >> 32) & 0xffff );

return 0;
}


sint32 __nrand48_r ( uint16 xsubi[3], struct drand48_data *buffer, sint32
*result )
{

/* Compute next state. */
if (__drand48_iterate (xsubi, buffer) < 0)
{
return -1;
}

/* Store the result. */
if (sizeof (unsigned short int) == 2)
{
// this code needs brackets ! ( ( ) ) etc but where ?
*result = xsubi[2] << 15 | xsubi[1] >> 1;
}
else
{
*result = xsubi[2] >> 1;
}

return 0;
}



sint32 nrand48 (uint16 xsubi[3])
{
sint32 result;

(void) __nrand48_r (xsubi, &__libc_drand48_data, &result);

return result;
}


int main()
{
uint16 state48[3];

printf("%d \n", nrand48(state48) );
printf("%d \n", nrand48(state48) );
printf("%d \n", nrand48(state48) );
printf("%d \n", nrand48(state48) );
printf("%d \n", nrand48(state48) );

// the output is:

// 1288336289
// 893806678
// 810173679
// 37620279
// 474250687

return 0;
}

Bye,
Skybuck.
 
J

Jim

This code needs brackets but where ?

X = (uint64) xsubi[2] << 32 | (uint32) xsubi[1] << 16 | xsubi[0];

X = (uint64) (xsubi[2] << 32) | (uint32) (xsubi[1] << 16) | xsubi[0];
This code also needs brackets but where ?

*result = xsubi[2] << 15 | xsubi[1] >> 1;

*result = (xsubi[2] << 15) | (xsubi[1] >> 1);

These brackets will totally change your results.

Jim
 
D

Dave Thompson

This code needs brackets but where ?

X = (uint64) xsubi[2] << 32 | (uint32) xsubi[1] << 16 | xsubi[0];

X = (uint64) (xsubi[2] << 32) | (uint32) (xsubi[1] << 16) | xsubi[0];
Actually, it was correct before (assuming obvious meanings
for uint16,32,64 of course) and you've made it badly wrong except on a
(rare) system where signed int is at least 48 bits.
This code also needs brackets but where ?

*result = xsubi[2] << 15 | xsubi[1] >> 1;

*result = (xsubi[2] << 15) | (xsubi[1] >> 1);

These brackets will totally change your results.
No they won't. << and >> already have precedence above | and &.
And it was and remains UB unless signed int is more than 31 bits,
which is admittedly a good bit more common.


- David.Thompson1 at worldnet.att.net
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top