nearly finished init stuff (probs with rand function!)
[physik/posic.git] / random / random.c
diff --git a/random/random.c b/random/random.c
new file mode 100644 (file)
index 0000000..c06b98a
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * random.c - basic random deviates
+ *
+ * author: Frank Zirkelbach <frank.zirkelbach@physik.uni-augsburg.de>
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "random.h"
+
+int rand_init(t_random *random,char *randomfile,int logfd) {
+
+       random->status=0;
+
+       if(logfd) random->logfd=logfd;
+
+       if(randomfile==NULL) {
+               random->fd=open("/dev/urandom",O_RDONLY);
+               if(random->fd<0) {
+                       perror("open urandom");
+                       return -1;
+               }
+               random->status|=RAND_STAT_UDEV;
+       } else {
+               random->fd=open(randomfile,O_RDONLY);
+               if(random->fd<0) {
+                       perror("open randomfile");
+                       return -1;
+               }
+       }
+       random->buffer=malloc(RAND_BUFSIZE*sizeof(unsigned int));
+       if(random->buffer==NULL) {
+               perror("malloc random buffer");
+               return -1;
+       }
+       random->b_ptr=random->buffer+RAND_BUFSIZE;
+
+       dprintf(random->logfd,"[random] init successfull\n");
+
+       return 0;
+}
+
+
+int rand_close(t_random *random) {
+
+       dprintf(random->logfd,"[random] shutdown\n");
+
+       if(random->buffer) free(random->buffer);
+       if(random->fd) close(random->fd);
+       if(random->logfd) close(random->logfd);
+
+       return 0;
+}
+
+unsigned int rand_get(t_random *random) {
+
+       if(random->b_ptr==random->buffer+RAND_BUFSIZE) {
+               if(random->status&RAND_STAT_VERBOSE)
+                       dprintf(random->logfd,
+                               "[random] getting new random numbers\n");
+               random->b_ptr=random->buffer;
+               if(!(random->status&RAND_STAT_UDEV)) {
+                       lseek(random->fd,0,SEEK_SET);
+                       dprintf(random->logfd,
+                               "[random] warning, rereading random file\n");
+               }
+               read(random->fd,random->b_ptr,
+                    RAND_BUFSIZE*sizeof(unsigned int));
+               if(random->status&RAND_STAT_VERBOSE)
+                       dprintf(random->logfd,
+                               "[random] got new random numbers\n");
+       }
+
+       return(*(random->b_ptr++));
+}
+
+double rand_get_double(t_random *random) {
+
+       return(1.0*rand_get(random)/(double)(URAND_MAX+1));
+}
+
+double rand_get_double_linear(t_random *random,double a,double b) {
+
+       return((-b+sqrt(b*b+2*a*(b+a/2)*rand_get_double(random)))/a);
+}
+
+double rand_get_gauss(t_random *random) {
+
+       double a,b,w;
+
+       if(random->status&RAND_STAT_GAUSS) {
+               random->status&=~RAND_STAT_GAUSS;
+               return random->gauss;
+       }
+
+       w=0;
+       while((w>=1.0)||(w==0.0)) {
+               a=-2.0*rand_get_double(random)+1.0;
+               b=-2.0*rand_get_double(random)+1.0;
+               w=a*a+b*b;
+       }
+
+       w=sqrt(-2.0*log(w)/w);
+
+       random->gauss=b*w;
+       random->status|=RAND_STAT_GAUSS;
+       
+       return(a*w);
+}
+       
+unsigned int rand_get_int_linear(t_random *random,unsigned int max,
+                             double a,double b) {
+
+       return((int)(rand_get_double_linear(random,a,b)*max));
+}      
+
+unsigned int rand_get_reject(t_random *random,unsigned int max_x,
+                             unsigned int max_y,unsigned int *graph) {
+
+       unsigned int x,y;
+       unsigned char ok;
+
+       ok=0;
+       while(!ok) {
+               x=(max_x*rand_get_double(random));
+               y=(max_y*rand_get_double(random));
+               if(y<=graph[x]) ok=1;
+       }
+
+       return x;
+}
+