nearly finished init stuff (probs with rand function!)
[physik/posic.git] / random / random.c
1 /*
2  * random.c - basic random deviates
3  *
4  * author: Frank Zirkelbach <frank.zirkelbach@physik.uni-augsburg.de>
5  *
6  */
7
8 #define _GNU_SOURCE
9 #include <stdio.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <fcntl.h>
13 #include <unistd.h>
14 #include <stdlib.h>
15 #include <math.h>
16
17 #include "random.h"
18
19 int rand_init(t_random *random,char *randomfile,int logfd) {
20
21         random->status=0;
22
23         if(logfd) random->logfd=logfd;
24
25         if(randomfile==NULL) {
26                 random->fd=open("/dev/urandom",O_RDONLY);
27                 if(random->fd<0) {
28                         perror("open urandom");
29                         return -1;
30                 }
31                 random->status|=RAND_STAT_UDEV;
32         } else {
33                 random->fd=open(randomfile,O_RDONLY);
34                 if(random->fd<0) {
35                         perror("open randomfile");
36                         return -1;
37                 }
38         }
39         random->buffer=malloc(RAND_BUFSIZE*sizeof(unsigned int));
40         if(random->buffer==NULL) {
41                 perror("malloc random buffer");
42                 return -1;
43         }
44         random->b_ptr=random->buffer+RAND_BUFSIZE;
45
46         dprintf(random->logfd,"[random] init successfull\n");
47
48         return 0;
49 }
50
51
52 int rand_close(t_random *random) {
53
54         dprintf(random->logfd,"[random] shutdown\n");
55
56         if(random->buffer) free(random->buffer);
57         if(random->fd) close(random->fd);
58         if(random->logfd) close(random->logfd);
59
60         return 0;
61 }
62
63 unsigned int rand_get(t_random *random) {
64
65         if(random->b_ptr==random->buffer+RAND_BUFSIZE) {
66                 if(random->status&RAND_STAT_VERBOSE)
67                         dprintf(random->logfd,
68                                 "[random] getting new random numbers\n");
69                 random->b_ptr=random->buffer;
70                 if(!(random->status&RAND_STAT_UDEV)) {
71                         lseek(random->fd,0,SEEK_SET);
72                         dprintf(random->logfd,
73                                 "[random] warning, rereading random file\n");
74                 }
75                 read(random->fd,random->b_ptr,
76                      RAND_BUFSIZE*sizeof(unsigned int));
77                 if(random->status&RAND_STAT_VERBOSE)
78                         dprintf(random->logfd,
79                                 "[random] got new random numbers\n");
80         }
81
82         return(*(random->b_ptr++));
83 }
84
85 double rand_get_double(t_random *random) {
86
87         return(1.0*rand_get(random)/(double)(URAND_MAX+1));
88 }
89
90 double rand_get_double_linear(t_random *random,double a,double b) {
91
92         return((-b+sqrt(b*b+2*a*(b+a/2)*rand_get_double(random)))/a);
93 }
94
95 double rand_get_gauss(t_random *random) {
96
97         double a,b,w;
98
99         if(random->status&RAND_STAT_GAUSS) {
100                 random->status&=~RAND_STAT_GAUSS;
101                 return random->gauss;
102         }
103
104         w=0;
105         while((w>=1.0)||(w==0.0)) {
106                 a=-2.0*rand_get_double(random)+1.0;
107                 b=-2.0*rand_get_double(random)+1.0;
108                 w=a*a+b*b;
109         }
110
111         w=sqrt(-2.0*log(w)/w);
112
113         random->gauss=b*w;
114         random->status|=RAND_STAT_GAUSS;
115         
116         return(a*w);
117 }
118         
119 unsigned int rand_get_int_linear(t_random *random,unsigned int max,
120                              double a,double b) {
121
122         return((int)(rand_get_double_linear(random,a,b)*max));
123 }       
124
125 unsigned int rand_get_reject(t_random *random,unsigned int max_x,
126                              unsigned int max_y,unsigned int *graph) {
127
128         unsigned int x,y;
129         unsigned char ok;
130
131         ok=0;
132         while(!ok) {
133                 x=(max_x*rand_get_double(random));
134                 y=(max_y*rand_get_double(random));
135                 if(y<=graph[x]) ok=1;
136         }
137
138         return x;
139 }
140