summaryrefslogtreecommitdiff
path: root/other/burneye2/utility.c
blob: a23e414ab781b332b698719a6407a961b7513cde (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* utility.c - burneye2 supporting functions
 *
 * by scut
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>

#include <utility.h>

int	quiet = 0;
int	rand_fd = -1;


int
fnote (const char *fmt, ...)
{
	int	len;
	va_list	ap;


	if (quiet)
		return (0);

	va_start (ap, fmt);
	len = vfprintf (stderr, fmt, ap);
	va_end (ap);

	return (len);
}


void
be_randinit_file (const char *filename)
{
	if (rand_fd != -1)
		return;

	rand_fd = open (filename, 0);
	if (rand_fd < 0)
		exit (EXIT_FAILURE);
}

void
be_randinit (void)
{
	be_randinit_file ("/dev/urandom");
}


void
be_randend (void)
{
	close (rand_fd);
	rand_fd = -1;
}


unsigned int
be_random (unsigned int max)
{
	ssize_t		nret;
	unsigned int	tmp;


	if (rand_fd == -1)
		be_randinit ();

	nret = read (rand_fd, &tmp, sizeof (tmp));
	if (nret != sizeof (tmp)) {
		if (nret < 0)
			perror ("be_random, read random-file");
		else
			fprintf (stderr, "be_random, random data depleted\n");

		exit (EXIT_FAILURE);
	}

	/* 0 denotes special 0 to 2^32 - 1 range
	 */
	if (max == 0)
		return (tmp);

	return (tmp % max);
}


int
be_random_coin (double prob)
{
	double	rand;

	rand = (double) be_random (UINT_MAX);
	rand /= (double) UINT_MAX;
	if (rand <= prob)
		return (1);

	return (0);
}


unsigned int
be_random_prob (unsigned int items_count, double *items_prob)
{
	double		sum = 0.0,
			rand;
	unsigned int	in;

	for (in = 0 ; in < items_count ; ++in)
		sum += items_prob[in];

	in = be_random (UINT_MAX);
	rand = in;
	rand /= (double) UINT_MAX;
	rand *= sum;

	sum = 0.0;
	for (in = 0 ; sum < rand && in < items_count ; ++in)
		sum += items_prob[in];

	if (in > 0)
		in -= 1;

	return (in);
}