/*
* @file main.c
* @author Piotr Gregor <piotrek.gregor gmail com>
* @brief Bernoulli distribution.
* @details Calls random device kernel module to get
* sample of random bits and draws a Bernoulli
* distribution from it.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h> /* O_RDONLY */
#define BITS_PER_BYTE 0x8u
#define BIT_0 0x1u
#define BIT_1 0x2u
#define BIT_2 0x4u
#define BIT_3 0x8u
#define BIT_4 0x10u
#define BIT_5 0x20u
#define BIT_6 0x40u
#define BIT_7 0x80u
/* if defined use /dev/urandom (will not block),
* if not defined use /dev/random (may block)*/
#define URANDOM_DEVICE 1
int
log_int(uint32_t x)
{
int8_t y; /* = log(x) */
switch (x)
{
case 0:
y = -1;
break;
case 1:
y = 0;
break;
case 2:
y = 1;
break;
case 4:
y = 2;
break;
case 8:
y = 3;
break;
case 16:
y = 4;
break;
case 32:
y = 5;
break;
case 64:
y = 6;
break;
case 128:
y = 7;
break;
case 256:
y = 8;
break;
case 512:
y = 9;
break;
case 1024:
y = 10;
break;
case 2048:
y = 11;
break;
case 4096:
y = 12;
break;
case 8192:
y = 13;
break;
case 16384:
y = 14;
break;
case 32768:
y = 15;
break;
case 65536:
y = 16;
break;
case 131072:
y = 17;
break;
case 262144:
y = 18;
break;
case 524288:
y = 19;
break;
case 1048576:
y = 20;
break;
case 2097152:
y = 21;
break;
case 4194304:
y = 22;
break;
case 8388608:
y = 23;
break;
case 16777216:
y = 24;
break;
}
return y;
}
/*
* @brief Read @outlen bytes from random device
* to array @out.
*/
int
get_random_samples(unsigned char *out, size_t outlen)
{
ssize_t res;
#ifdef URANDOM_DEVICE
int fd = open("/dev/urandom", O_RDONLY);
if (fd == -1)
return -1;
res = read(fd, out, outlen);
if (res < 0)
{
// error, unable to read /dev/urandom
close(fd);
return -2;
}
#else
size_t read_n;
int fd = open("/dev/random", O_RDONLY);
if (fd == -1)
return -1;
read_n = 0;
while (read_n < outlen)
{
res = read(fd, out + read_n, outlen - read_n);
if (res < 0)
{
// error, unable to read /dev/random
close(fd);
return -3;
}
read_n += res;
}
#endif /* URANDOM_DEVICE */
close(fd);
return 0;
}
/*
* @brief Draw vector of Bernoulli samples.
* @details @x and @resolution determines probability
* of success in Bernoulli distribution
* and accuracy of results: p = x/resolution.
* @param resolution: number of segments per sample of output array
* as power of 2: max resolution supported is 2^24=16777216
* @param x: determines used probability, x = [0, resolution - 1]
* @param n: number of samples in result vector
*/
int
get_bernoulli_samples(char *out, uint32_t n, uint32_t resolution, uint32_t x)
{
int res;
size_t i, j;
uint32_t bytes_per_byte, word;
unsigned char *rnd_bytes;
uint32_t uniform_byte;
uint8_t bits_per_byte;
if (out == NULL || n == 0 || resolution == 0 || x > (resolution -1))
return -1;
bits_per_byte = log_int(resolution);
bytes_per_byte = bits_per_byte / BITS_PER_BYTE +
(bits_per_byte % BITS_PER_BYTE ? 1 : 0);
rnd_bytes
= malloc(n
* bytes_per_byte
); if (rnd_bytes == NULL)
return -2;
res = get_random_samples(rnd_bytes, n * bytes_per_byte);
if (res < 0)
{
return -3;
}
i = 0;
while (i < n)
{
/* get Bernoulli sample */
/* read byte */
j = 0;
word = 0;
while (j < bytes_per_byte)
{
word |= (rnd_bytes[i * bytes_per_byte + j] << (BITS_PER_BYTE * j));
++j;
}
uniform_byte = word & ((1u << bits_per_byte) - 1);
/* decision */
if (uniform_byte < x)
out[i] = 1;
else
out[i] = 0;
++i;
}
return 0;
}
void
print_c(char *c, int n)
{
int i = 0;
while (i < n)
{
++i;
}
}
int
main(void)
{
int res;
char c[256];
res = get_bernoulli_samples(c, 256, 256, 1); /* 1/256 = 0.0039 */
if (res < 0) return -1;
print_c(c, 40);
res = get_bernoulli_samples(c, sizeof(c), 256, 2); /* 2/256 = 0.0078 */
if (res < 0) return -1;
print_c(c, 40);
res = get_bernoulli_samples(c, sizeof(c), 256, 13); /* 13/256 = 0.0508 */
if (res < 0) return -1;
print_c(c, 40);
res = get_bernoulli_samples(c, sizeof(c), 256*256, 328); /* 328/256^2 = 0.0050 */
if (res < 0) return -1;
print_c(c, 40);
res = get_bernoulli_samples(c, sizeof(c), 256, 200); /* 200/256 = 0.7813 */
if (res < 0) return -1;
print_c(c, 40);
res = get_bernoulli_samples(c, sizeof(c), 256*256, 200); /* 200/256^2 = 0.0031 */
if (res < 0) return -1;
print_c(c, 40);
return 0;
}
LyoKICogQGZpbGUgICAgbWFpbi5jCiAqIEBhdXRob3IgIFBpb3RyIEdyZWdvciA8cGlvdHJlay5ncmVnb3IgZ21haWwgY29tPgogKiBAYnJpZWYgICBCZXJub3VsbGkgZGlzdHJpYnV0aW9uLgogKiBAZGV0YWlscyBDYWxscyByYW5kb20gZGV2aWNlIGtlcm5lbCBtb2R1bGUgdG8gZ2V0CiAqICAgICAgICAgIHNhbXBsZSBvZiByYW5kb20gYml0cyBhbmQgZHJhd3MgYSBCZXJub3VsbGkKICogICAgICAgICAgZGlzdHJpYnV0aW9uIGZyb20gaXQuCiovCgoKI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0ZGludC5oPgojaW5jbHVkZSA8dW5pc3RkLmg+CiNpbmNsdWRlIDxmY250bC5oPiAvKiBPX1JET05MWSAqLwoKCiNkZWZpbmUgQklUU19QRVJfQllURSAweDh1CiNkZWZpbmUgQklUXzAgMHgxdQojZGVmaW5lIEJJVF8xIDB4MnUKI2RlZmluZSBCSVRfMiAweDR1CiNkZWZpbmUgQklUXzMgMHg4dQojZGVmaW5lIEJJVF80IDB4MTB1CiNkZWZpbmUgQklUXzUgMHgyMHUKI2RlZmluZSBCSVRfNiAweDQwdQojZGVmaW5lIEJJVF83IDB4ODB1CgoKLyogaWYgZGVmaW5lZCB1c2UgL2Rldi91cmFuZG9tICh3aWxsIG5vdCBibG9jayksCiAqIGlmIG5vdCBkZWZpbmVkIHVzZSAvZGV2L3JhbmRvbSAobWF5IGJsb2NrKSovCiNkZWZpbmUgVVJBTkRPTV9ERVZJQ0UgMQoKaW50CmxvZ19pbnQodWludDMyX3QgeCkKewogICAgaW50OF90IHk7IC8qID0gbG9nKHgpICovCiAgICBzd2l0Y2ggKHgpCiAgICB7CiAgICAgICAgY2FzZSAwOgogICAgICAgICAgICB5ID0gLTE7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMToKICAgICAgICAgICAgeSA9IDA7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMjoKICAgICAgICAgICAgeSA9IDE7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgNDoKICAgICAgICAgICAgeSA9IDI7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgODoKICAgICAgICAgICAgeSA9IDM7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMTY6CiAgICAgICAgICAgIHkgPSA0OwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDMyOgogICAgICAgICAgICB5ID0gNTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA2NDoKICAgICAgICAgICAgeSA9IDY7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMTI4OgogICAgICAgICAgICB5ID0gNzsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAyNTY6CiAgICAgICAgICAgIHkgPSA4OwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDUxMjoKICAgICAgICAgICAgeSA9IDk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMTAyNDoKICAgICAgICAgICAgeSA9IDEwOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDIwNDg6CiAgICAgICAgICAgIHkgPSAxMTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA0MDk2OgogICAgICAgICAgICB5ID0gMTI7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgODE5MjoKICAgICAgICAgICAgeSA9IDEzOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDE2Mzg0OgogICAgICAgICAgICB5ID0gMTQ7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMzI3Njg6CiAgICAgICAgICAgIHkgPSAxNTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA2NTUzNjoKICAgICAgICAgICAgeSA9IDE2OwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDEzMTA3MjoKICAgICAgICAgICAgeSA9IDE3OwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDI2MjE0NDoKICAgICAgICAgICAgeSA9IDE4OwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDUyNDI4ODoKICAgICAgICAgICAgeSA9IDE5OwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDEwNDg1NzY6CiAgICAgICAgICAgIHkgPSAyMDsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAyMDk3MTUyOgogICAgICAgICAgICB5ID0gMjE7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgNDE5NDMwNDoKICAgICAgICAgICAgeSA9IDIyOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDgzODg2MDg6CiAgICAgICAgICAgIHkgPSAyMzsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAxNjc3NzIxNjoKICAgICAgICAgICAgeSA9IDI0OwogICAgICAgICAgICBicmVhazsKICAgIH0KICAgIHJldHVybiB5Owp9Ci8qCiAqIEBicmllZiAgIFJlYWQgQG91dGxlbiBieXRlcyBmcm9tIHJhbmRvbSBkZXZpY2UKICogICAgICAgICAgdG8gYXJyYXkgQG91dC4KICovCmludApnZXRfcmFuZG9tX3NhbXBsZXModW5zaWduZWQgY2hhciAqb3V0LCBzaXplX3Qgb3V0bGVuKQp7CiAgICBzc2l6ZV90IHJlczsKCiNpZmRlZiBVUkFORE9NX0RFVklDRQogICAgaW50IGZkID0gb3BlbigiL2Rldi91cmFuZG9tIiwgT19SRE9OTFkpOwogICAgaWYgKGZkID09IC0xKQogICAgICAgIHJldHVybiAtMTsKICAgICAgIHJlcyA9IHJlYWQoZmQsIG91dCwgb3V0bGVuKTsKICAgICAgIGlmIChyZXMgPCAwKQogICAgICAgewogICAgICAgICAgIC8vIGVycm9yLCB1bmFibGUgdG8gcmVhZCAvZGV2L3VyYW5kb20KICAgICAgICAgICBjbG9zZShmZCk7CiAgICAgICAgICAgcmV0dXJuIC0yOwogICAgICAgfQojZWxzZQogICAgc2l6ZV90IHJlYWRfbjsKICAgIGludCBmZCA9IG9wZW4oIi9kZXYvcmFuZG9tIiwgT19SRE9OTFkpOwogICAgaWYgKGZkID09IC0xKQogICAgICAgIHJldHVybiAtMTsKICAgIHJlYWRfbiA9IDA7CiAgICB3aGlsZSAocmVhZF9uIDwgb3V0bGVuKQogICAgewogICAgICAgcmVzID0gcmVhZChmZCwgb3V0ICsgcmVhZF9uLCBvdXRsZW4gLSByZWFkX24pOwogICAgICAgaWYgKHJlcyA8IDApCiAgICAgICB7CiAgICAgICAgICAgLy8gZXJyb3IsIHVuYWJsZSB0byByZWFkIC9kZXYvcmFuZG9tCiAgICAgICAgICAgY2xvc2UoZmQpOwogICAgICAgICAgIHJldHVybiAtMzsKICAgICAgIH0KICAgICAgIHJlYWRfbiArPSByZXM7CiAgICB9CiNlbmRpZiAvKiBVUkFORE9NX0RFVklDRSAqLwogICAgY2xvc2UoZmQpOwogICAgcmV0dXJuIDA7Cn0KCi8qCiAqIEBicmllZiAgIERyYXcgdmVjdG9yIG9mIEJlcm5vdWxsaSBzYW1wbGVzLgogKiBAZGV0YWlscyBAeCBhbmQgQHJlc29sdXRpb24gZGV0ZXJtaW5lcyBwcm9iYWJpbGl0eQogKiAgICAgICAgICBvZiBzdWNjZXNzIGluIEJlcm5vdWxsaSBkaXN0cmlidXRpb24KICogICAgICAgICAgYW5kIGFjY3VyYWN5IG9mIHJlc3VsdHM6IHAgPSB4L3Jlc29sdXRpb24uCiAqIEBwYXJhbSAgIHJlc29sdXRpb246IG51bWJlciBvZiBzZWdtZW50cyBwZXIgc2FtcGxlIG9mIG91dHB1dCBhcnJheSAKICogICAgICAgICAgYXMgcG93ZXIgb2YgMjogbWF4IHJlc29sdXRpb24gc3VwcG9ydGVkIGlzIDJeMjQ9MTY3NzcyMTYKICogQHBhcmFtICAgeDogZGV0ZXJtaW5lcyB1c2VkIHByb2JhYmlsaXR5LCB4ID0gWzAsIHJlc29sdXRpb24gLSAxXQogKiBAcGFyYW0gICBuOiBudW1iZXIgb2Ygc2FtcGxlcyBpbiByZXN1bHQgdmVjdG9yCiAqLwppbnQKZ2V0X2Jlcm5vdWxsaV9zYW1wbGVzKGNoYXIgKm91dCwgdWludDMyX3QgbiwgdWludDMyX3QgcmVzb2x1dGlvbiwgdWludDMyX3QgeCkKewogICAgaW50IHJlczsKICAgIHNpemVfdCBpLCBqOwogICAgdWludDMyX3QgYnl0ZXNfcGVyX2J5dGUsIHdvcmQ7CiAgICB1bnNpZ25lZCBjaGFyICpybmRfYnl0ZXM7CiAgICB1aW50MzJfdCB1bmlmb3JtX2J5dGU7CiAgICB1aW50OF90IGJpdHNfcGVyX2J5dGU7CgogICAgaWYgKG91dCA9PSBOVUxMIHx8IG4gPT0gMCB8fCByZXNvbHV0aW9uID09IDAgfHwgeCA+IChyZXNvbHV0aW9uIC0xKSkKICAgICAgICByZXR1cm4gLTE7CgogICAgYml0c19wZXJfYnl0ZSA9IGxvZ19pbnQocmVzb2x1dGlvbik7CiAgICBieXRlc19wZXJfYnl0ZSA9IGJpdHNfcGVyX2J5dGUgLyBCSVRTX1BFUl9CWVRFICsgCiAgICAgICAgICAgICAgICAgICAgICAgIChiaXRzX3Blcl9ieXRlICUgQklUU19QRVJfQllURSA/IDEgOiAwKTsKICAgIHJuZF9ieXRlcyA9IG1hbGxvYyhuICogYnl0ZXNfcGVyX2J5dGUpOwogICAgaWYgKHJuZF9ieXRlcyA9PSBOVUxMKQogICAgICAgIHJldHVybiAtMjsKICAgIHJlcyA9IGdldF9yYW5kb21fc2FtcGxlcyhybmRfYnl0ZXMsIG4gKiBieXRlc19wZXJfYnl0ZSk7CiAgICBpZiAocmVzIDwgMCkKICAgIHsKICAgICAgICBmcmVlKHJuZF9ieXRlcyk7CiAgICAgICAgcmV0dXJuIC0zOwogICAgfQoKICAgIGkgPSAwOwogICAgd2hpbGUgKGkgPCBuKQogICAgewogICAgICAgIC8qIGdldCBCZXJub3VsbGkgc2FtcGxlICovCiAgICAgICAgLyogcmVhZCBieXRlICovCiAgICAgICAgaiA9IDA7CiAgICAgICAgd29yZCA9IDA7CiAgICAgICAgd2hpbGUgKGogPCBieXRlc19wZXJfYnl0ZSkKICAgICAgICB7CiAgICAgICAgICAgIHdvcmQgfD0gKHJuZF9ieXRlc1tpICogYnl0ZXNfcGVyX2J5dGUgKyBqXSA8PCAoQklUU19QRVJfQllURSAqIGopKTsKICAgICAgICAgICAgKytqOwogICAgICAgIH0KICAgICAgICB1bmlmb3JtX2J5dGUgPSB3b3JkICYgKCgxdSA8PCBiaXRzX3Blcl9ieXRlKSAtIDEpOwogICAgICAgIC8qIGRlY2lzaW9uICovCiAgICAgICAgaWYgKHVuaWZvcm1fYnl0ZSA8IHgpCiAgICAgICAgICAgIG91dFtpXSA9IDE7CiAgICAgICAgZWxzZQogICAgICAgICAgICBvdXRbaV0gPSAwOwogICAgICAgICsraTsKICAgIH0KCiAgICBmcmVlKHJuZF9ieXRlcyk7ICAgIAogICAgcmV0dXJuIDA7Cn0KCnZvaWQKcHJpbnRfYyhjaGFyICpjLCBpbnQgbikKewogICAgaW50IGkgPSAwOwogICAgd2hpbGUgKGkgPCBuKQogICAgewogICAgICAgIHByaW50ZiggIlslZF0iLCAoaW50KWNbaV0pOwogICAgICAgICsraTsKICAgIH0KICAgIHByaW50ZigiXG4iKTsKfQoKaW50Cm1haW4odm9pZCkKewogICAgaW50IHJlczsKICAgIGNoYXIgY1syNTZdOwoKICAgIHJlcyA9IGdldF9iZXJub3VsbGlfc2FtcGxlcyhjLCAyNTYsIDI1NiwgMSk7IC8qIDEvMjU2ID0gMC4wMDM5ICovCiAgICBpZiAocmVzIDwgMCkgcmV0dXJuIC0xOwogICAgcHJpbnRfYyhjLCA0MCk7CgogICAgcmVzID0gZ2V0X2Jlcm5vdWxsaV9zYW1wbGVzKGMsIHNpemVvZihjKSwgMjU2LCAyKTsgLyogMi8yNTYgPSAwLjAwNzggKi8gCiAgICBpZiAocmVzIDwgMCkgcmV0dXJuIC0xOwogICAgcHJpbnRfYyhjLCA0MCk7CgogICAgcmVzID0gZ2V0X2Jlcm5vdWxsaV9zYW1wbGVzKGMsIHNpemVvZihjKSwgMjU2LCAxMyk7IC8qIDEzLzI1NiA9IDAuMDUwOCAqLwogICAgaWYgKHJlcyA8IDApIHJldHVybiAtMTsKICAgIHByaW50X2MoYywgNDApOwoKICAgIHJlcyA9IGdldF9iZXJub3VsbGlfc2FtcGxlcyhjLCBzaXplb2YoYyksIDI1NioyNTYsIDMyOCk7IC8qIDMyOC8yNTZeMiA9IDAuMDA1MCAqLwogICAgaWYgKHJlcyA8IDApIHJldHVybiAtMTsKICAgIHByaW50X2MoYywgNDApOwoKICAgIHJlcyA9IGdldF9iZXJub3VsbGlfc2FtcGxlcyhjLCBzaXplb2YoYyksIDI1NiwgMjAwKTsgLyogMjAwLzI1NiA9IDAuNzgxMyAqLwogICAgaWYgKHJlcyA8IDApIHJldHVybiAtMTsKICAgIHByaW50X2MoYywgNDApOwoKICAgIHJlcyA9IGdldF9iZXJub3VsbGlfc2FtcGxlcyhjLCBzaXplb2YoYyksIDI1NioyNTYsIDIwMCk7IC8qIDIwMC8yNTZeMiA9IDAuMDAzMSAqLwogICAgaWYgKHJlcyA8IDApIHJldHVybiAtMTsKICAgIHByaW50X2MoYywgNDApOwoKICAgIHJldHVybiAwOwp9