/***********************************************************************
This C/C++ program reproduces the java.util.Random class behavior for
streams of 32-bit random numbers.  The generator is the same as that
for the Unix *rand48 generators, but the sequence from mrand48()
differs from that produced by nextInt(): documentation for mrand48()
does not specify how the 32-bit result is extracted from the 48-bit
intermediate results.

The output of nextInt() matches that of the companion Java program
TestRandom.

	% CC testrandom.c && ./a.out
	Java-style random numbers
	0       1767927761
	1       -1017979954
	2       1787195940
	3       16678428
	4       1249040075
	5       1743307782
	...

	% javac TestRandom.java ; java TestRandom
	0       1767927761
	1       -1017979954
	2       1787195940
	3       16678428
	4       1249040075
	5       1743307782
	...

[24-Mar-2004]
***********************************************************************/

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

static long long Random_seed = 0x12345678LL;
static long long multiplier = 0x5DEECE66DLL;
static long long addend = 0xBLL;
static long long mask = ((1LL << 48) - 1);
static const int max_random = 25;

int
setSeed(long long seed)
{
    long long old_seed;
    old_seed = Random_seed;
    Random_seed = (seed ^ multiplier) & mask;
    return (old_seed);
}

int
nextInt(void)
{
    Random_seed = ( multiplier * Random_seed + addend ) & mask;
    return ((int)(Random_seed >> 16));
}

int
main(int argc, char* argv[])
{
    int k;
    unsigned short seed16v[3];

    printf("Java-style random numbers\n");
    setSeed(0x12345678LL);
    for (k = 0; k < max_random; ++k)
	(void)printf("%d\t%d\n", k, nextInt());

    printf("C-style random numbers\n");

    seed16v[0] = 0x0000;
    seed16v[1] = 0x1234;
    seed16v[2] = 0x5678;
    (void)seed48(seed16v);

    for (k = 0; k < max_random; ++k)
	(void)printf("%d\t%d\n", k, mrand48());

    return (EXIT_SUCCESS);
}
