Skip to content

Commit b99a2e9

Browse files
committed
use uint32_t
1 parent efb00f1 commit b99a2e9

File tree

6 files changed

+48
-42
lines changed

6 files changed

+48
-42
lines changed

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ $n$-sided die with rational probabilities.
88

99
The library can be built by running
1010

11-
$ make all
11+
```sh
12+
make all
13+
```
1214

1315
This command creates the following artifacts in the `build/` directory:
1416

@@ -22,7 +24,8 @@ This command creates the following artifacts in the `build/` directory:
2224
## Usage
2325

2426
The following code from [examples/example.c](examples/example.c)
25-
shows how to use ALDR to sample from a distribution with given integer weights.
27+
shows how to use ALDR to sample from a distribution
28+
defined by a list of nonnegative integer weights.
2629

2730
```c
2831
#include <stdlib.h>

aldr.c

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,35 +17,37 @@ void aldr_free (struct aldr_s x) {
1717
free(x.leaves_flat);
1818
}
1919

20-
struct aldr_s aldr_preprocess(int* a, int n) {
21-
// assume k <= 31
22-
int m = 0;
23-
for (int i = 0; i < n; ++i) {
20+
struct aldr_s aldr_preprocess(uint32_t* a, uint32_t n) {
21+
// this algorithm requires that
22+
// 0 < n < (1 << 32) - 1
23+
// 0 < sum(a) < (1 << 31) - 1
24+
uint32_t m = 0;
25+
for (uint32_t i = 0; i < n; ++i) {
2426
m += a[i];
2527
}
26-
int k = 32 - __builtin_clz(m) - (1 == __builtin_popcount(m));
27-
int K = k << 1; // depth
28-
long long c = (1ll << K) / m; // amplification factor
29-
long long r = (1ll << K) % m; // reject weight
28+
uint32_t k = 32 - __builtin_clz(m-1);
29+
uint32_t K = k << 1; // depth
30+
uint64_t c = (1ll << K) / m; // amplification factor
31+
uint64_t r = (1ll << K) % m; // reject weight
3032

31-
int num_leaves = __builtin_popcountll(r);
32-
for (int i = 0; i < n; ++i) {
33+
uint32_t num_leaves = __builtin_popcountll(r);
34+
for (uint32_t i = 0; i < n; ++i) {
3335
num_leaves += __builtin_popcountll(c * a[i]);
3436
}
3537

36-
int *breadths = calloc(K + 1, sizeof(int));
37-
int *leaves_flat = calloc(num_leaves, sizeof(int));
38+
uint32_t *breadths = calloc(K + 1, sizeof(*breadths));
39+
uint32_t *leaves_flat = calloc(num_leaves, sizeof(*leaves_flat));
3840

39-
int location = 0;
40-
for(int j = 0; j <= K; j++) {
41-
long long bit = (1ll << (K - j));
41+
uint32_t location = 0;
42+
for(uint32_t j = 0; j <= K; j++) {
43+
uint64_t bit = (1ll << (K - j));
4244
if (r & bit) {
4345
leaves_flat[location] = 0;
4446
++breadths[j];
4547
++location;
4648
}
47-
for (int i = 0; i < n; ++i) {
48-
long long Qi = c*a[i];
49+
for (uint32_t i = 0; i < n; ++i) {
50+
uint64_t Qi = c*a[i];
4951
if (Qi & bit) {
5052
leaves_flat[location] = i + 1;
5153
++breadths[j];
@@ -62,14 +64,14 @@ struct aldr_s aldr_preprocess(int* a, int n) {
6264
};
6365
}
6466

65-
int aldr_sample(struct aldr_s* f) {
67+
uint32_t aldr_sample(struct aldr_s* f) {
6668
for (;;) {
67-
int depth = 0;
68-
int location = 0;
69-
int val = 0;
69+
uint32_t depth = 0;
70+
uint32_t location = 0;
71+
uint32_t val = 0;
7072
for (;;) {
7173
if (val < f->breadths[depth]) {
72-
int ans = f->leaves_flat[location + val];
74+
uint32_t ans = f->leaves_flat[location + val];
7375
if (ans) return ans - 1;
7476
else break;
7577
}

aldr.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,18 @@
1010
#ifndef ALDR_H
1111
#define ALDR_H
1212

13+
#include <stdint.h>
14+
1315
// flattened ALDR tree
1416
struct aldr_s {
15-
int length_breadths;
16-
int length_leaves_flat;
17-
int *breadths;
18-
int *leaves_flat;
17+
uint32_t length_breadths;
18+
uint32_t length_leaves_flat;
19+
uint32_t *breadths;
20+
uint32_t *leaves_flat;
1921
};
2022

2123
void aldr_free (struct aldr_s x);
22-
struct aldr_s aldr_preprocess(int* a, int n);
23-
int aldr_sample(struct aldr_s *x);
24+
struct aldr_s aldr_preprocess(uint32_t* a, uint32_t n);
25+
uint32_t aldr_sample(struct aldr_s *x);
2426

2527
#endif

examples/example.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@
1313
#include "aldr.h"
1414

1515
int main(int argc, char **argv) {
16-
int num_samples = 90;
17-
int *samples = calloc(num_samples, sizeof(*samples));
16+
uint32_t num_samples = 90;
17+
uint32_t *samples = calloc(num_samples, sizeof(*samples));
1818

19-
int distribution[5] = { 1, 1, 2, 3, 2 };
19+
uint32_t distribution[5] = { 1, 1, 2, 3, 2 };
2020
struct aldr_s x = aldr_preprocess(distribution, 5);
21-
for (int i = 0; i < num_samples; ++i) {
21+
for (uint32_t i = 0; i < num_samples; ++i) {
2222
samples[i] = aldr_sample(&x);
2323
printf("%d ", samples[i]);
2424
}

flip.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
*/
99

1010
#include <stdlib.h>
11-
#include <stdint.h>
1211
#include <sys/random.h>
1312

1413
#include "flip.h"

sample.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,19 @@ int main(int argc, char **argv) {
1717
printf("usage: %s <num_samples> <distribution>\n", argv[0]);
1818
exit(0);
1919
}
20-
int num_samples = atoi(argv[1]);
20+
uint32_t num_samples = strtoul(argv[1], NULL, 10);
2121

2222
// Parse the distribution.
23-
int n = argc - 2;
24-
int *a = calloc(n, sizeof(*a));
25-
for (int i = 0; i < n; ++i) {
26-
a[i] = atoi(argv[i + 2]);
23+
uint32_t n = argc - 2;
24+
uint32_t *a = calloc(n, sizeof(*a));
25+
for (uint32_t i = 0; i < n; ++i) {
26+
a[i] = strtoul(argv[i + 2], NULL, 10);
2727
}
2828

2929
// Obtain the samples.
30-
int sample;
30+
uint32_t sample;
3131
struct aldr_s x = aldr_preprocess(a, n);
32-
for (int i = 0; i < num_samples; ++i) {
32+
for (uint32_t i = 0; i < num_samples; ++i) {
3333
printf("%d ", aldr_sample(&x));
3434
}
3535
printf("\n");

0 commit comments

Comments
 (0)