1 #ifndef ZZGO_PROBDIST_H
2 #define ZZGO_PROBDIST_H
4 /* Tools for picking an item according to a probability distribution. */
6 /* The probability distribution structure is designed to be once
7 * initialized, then random items assigned a value repeatedly and
8 * random items picked repeatedly as well. */
13 /* The interface looks a bit funny-wrapped since we used to switch
14 * between different probdist representations. */
18 double *items
; // [bsize2], [i] = P(pick==i)
19 double *rowtotals
; // [bsize], [i] = sum of items in row i
20 double total
; // sum of all items
22 #define probdist_total(pd) ((pd)->total)
23 #define probdist_one(pd, c) ((pd)->items[c])
24 /* Probability so small that it's same as zero; used to compensate
25 * for probdist.total inaccuracies. */
26 #define PROBDIST_EPSILON 0.05
28 static void probdist_set(struct probdist
*pd
, coord_t c
, double val
);
29 static void probdist_mute(struct probdist
*pd
, coord_t c
);
31 /* Pick a random item. ignore is a pass-terminated sorted array of items
32 * that are not to be considered (and whose values are not in @total). */
33 coord_t
probdist_pick(struct probdist
*pd
, coord_t
*ignore
);
36 /* We disable the assertions here since this is quite time-critical
37 * part of code, and also the compiler is reluctant to inline the
38 * functions otherwise. */
40 probdist_set(struct probdist
*pd
, coord_t c
, double val
)
43 assert(c
>= 0 && c
< board_size2(pd
->b
));
46 pd
->total
+= val
- pd
->items
[c
];
47 pd
->rowtotals
[c
/ pd
->n1
] += val
- pd
->items
[c
];
51 /* Remove the item from the totals; this is used when you then
52 * pass it in the ignore list to probdist_pick(). Of course you
53 * must restore the totals afterwards. */
55 probdist_mute(struct probdist
*pd
, coord_t c
)
57 pd
->total
-= pd
->items
[c
];
58 pd
->rowtotals
[c
/ pd
->n1
] -= pd
->items
[c
];