This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

drand48() (and erand48) returns only zeros


I am working with cygwin environment (Cygwin 1.7.7 + Newlib 1.18)
where drand48 function returns always zero values.

The problem was reported in 2004 at cygwin mailist:
     1) http://cygwin.com/ml/cygwin/2004-11/msg00488.html
     2) http://cygwin.com/ml/cygwin/2004-11/msg00513.html

It seems the problem is at drand48 internal initialization. As a
workaround if srand48 is called at program beginning, future drand48
calls works ok, but this srand48 call is not mandatory:

 From the Single Unix Specification V2:

	The srand48(), seed48(), and lcong48() functions are initialization
	entry points, one of which should be invoked before either drand48(),
	lrand48(), or mrand48() is called.  (Although it is not recommended
	practice, constant default initializer values shall be supplied
	automatically if drand48(), lrand48(), or mrand48() is called without a
	prior call to an initialization entry point.) The erand48(), nrand48(),
	and jrand48() functions do not require an initialization entry point to
	be called first.


A simple test case is

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

int main(int argc, char *argv[])
{
	int i;
	for(i=0; i<10; i++)
	{
		printf("%i drand48: %f\n",i,drand48());
	}
}

The output is:

==> Cygwin 1.7.7 + Newlib 1.18

$ ./drand48simpletest
0 drand48: 0.000000
1 drand48: 0.000000
2 drand48: 0.000000
3 drand48: 0.000000
4 drand48: 0.000000
5 drand48: 0.000000
6 drand48: 0.000000
7 drand48: 0.000000
8 drand48: 0.000000
9 drand48: 0.000000

==> Linux and Solaris environments:

# ./drand48simpletest
0 drand48: 0.396465
1 drand48: 0.840485
2 drand48: 0.353336
3 drand48: 0.446583
4 drand48: 0.318693
5 drand48: 0.886428
6 drand48: 0.015583
7 drand48: 0.584090
8 drand48: 0.159369
9 drand48: 0.383716


As a second problem related with drand48 returning only zeros is
cygwin pthread applications.

We execute srand48 initialization as a workaround of drand48 problems
in main function.
After this, if we create several threads, the new threads created in
application, has the same zeros problem, but we called srand48 in main
function.


The output is:

==> Cygwin 1.7.7 + Newlib 1.18

$ ./drand48threadtest.exe 1 5
Init srand48 with: 1
Start main
Main: Creating thread #0 - drand48: 0.041630
Main: Creating thread #1 - drand48: 0.454492
        Executing thread #0.0 - drand48: 0.000000
        Executing thread #1.0 - drand48: 0.000000
Main: Creating thread #2 - drand48: 0.834817
        Executing thread #0.1 - drand48: 0.000000
        Executing thread #1.1 - drand48: 0.000000
Main: Creating thread #3 - drand48: 0.335986
        Executing thread #2.0 - drand48: 0.000000
        Executing thread #0.2 - drand48: 0.000000
        Executing thread #1.2 - drand48: 0.000000
        Executing thread #2.1 - drand48: 0.000000
        Executing thread #3.0 - drand48: 0.000000
Main: Creating thread #4 - drand48: 0.565489
        Executing thread #2.2 - drand48: 0.000000
        Executing thread #3.1 - drand48: 0.000000
        Executing thread #3.2 - drand48: 0.000000
        Executing thread #4.0 - drand48: 0.000000
        Executing thread #4.1 - drand48: 0.000000
        Executing thread #4.2 - drand48: 0.000000
End main

==> Linux and Solaris environments:

# drand48threadtest 1 5
Init srand48 with: 1
Start main
Main: Creating thread #0 - drand48: 0.041630
Main: Creating thread #1 - drand48: 0.454492
        Executing thread #0.0 - drand48: 0.834817
        Executing thread #0.1 - drand48: 0.335986
        Executing thread #0.2 - drand48: 0.565489
Main: Creating thread #2 - drand48: 0.001767
        Executing thread #1.0 - drand48: 0.187590
        Executing thread #1.1 - drand48: 0.990434
Main: Creating thread #3 - drand48: 0.750497
        Executing thread #2.0 - drand48: 0.351209
        Executing thread #2.1 - drand48: 0.573345
        Executing thread #2.2 - drand48: 0.132554
Main: Creating thread #4 - drand48: 0.064166
        Executing thread #3.0 - drand48: 0.950854
End main
        Executing thread #1.2 - drand48: 0.366274
        Executing thread #4.0 - drand48: 0.584649
        Executing thread #4.1 - drand48: 0.216588
        Executing thread #4.2 - drand48: 0.806502
        Executing thread #3.1 - drand48: 0.153560
        Executing thread #3.2 - drand48: 0.140473
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
	int i;
	for(i=0; i<10; i++)
	{
		printf("%i drand48: %f\n",i,drand48());
	}
}
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

int seed=1;
int num_threads=10;

void init_random()
{
	printf("Init srand48 with: %i\n",seed);
	srand48(seed);
}

void *thread_function(void *threadid)
{
	long tid;
	tid = (long)threadid;
	printf("\tExecuting thread #%ld.0 - drand48: %f\n", tid,drand48());
	printf("\tExecuting thread #%ld.1 - drand48: %f\n", tid,drand48());
	printf("\tExecuting thread #%ld.2 - drand48: %f\n", tid,drand48());
	pthread_exit(NULL);
}

int main(int argc, char *argv[])
{
	if(argc!=3)
	{
		printf("%s <seed> <num_threads>\n",argv[0]);
		return;
	}
	else
	{
		seed=atoi(argv[1]);
		num_threads=atoi(argv[2]);
	}
	init_random();
	pthread_t threads[num_threads];
	int rc;
	long t;
	printf("Start main\n");
	for(t=0;t<num_threads;t++)
	{
		printf("Main: Creating thread #%ld - drand48: %f\n", t,drand48());
		rc = pthread_create(&threads[t], NULL, thread_function, (void *)t);
		if (rc)
		{
			printf("ERROR; return code from pthread_create() is %d\n", rc);
			exit(-1);
		}
	}
	printf("End main\n");
	pthread_exit(NULL);
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]