pachi_py/pachi/probdist.h (40 lines of code) (raw):

#ifndef PACHI_PROBDIST_H #define PACHI_PROBDIST_H /* Tools for picking an item according to a probability distribution. */ /* The probability distribution structure is designed to be once * initialized, then random items assigned a value repeatedly and * random items picked repeatedly as well. */ #include "fixp.h" #include "move.h" #include "util.h" struct board; /* The interface looks a bit funny-wrapped since we used to switch * between different probdist representations. */ struct probdist { struct board *b; fixp_t *items; // [bsize2], [i] = P(pick==i) fixp_t *rowtotals; // [bsize], [i] = sum of items in row i fixp_t total; // sum of all items }; /* Declare pd_ corresponding to board b_ in the local scope. */ #define probdist_alloca(pd_, b_) \ fixp_t pd_ ## __pdi[board_size2(b_)] __attribute__((aligned(32))); memset(pd_ ## __pdi, 0, sizeof(pd_ ## __pdi)); \ fixp_t pd_ ## __pdr[board_size(b_)] __attribute__((aligned(32))); memset(pd_ ## __pdr, 0, sizeof(pd_ ## __pdr)); \ struct probdist pd_ = { .b = b_, .items = pd_ ## __pdi, .rowtotals = pd_ ## __pdr, .total = 0 }; /* Get the value of given item. */ #define probdist_one(pd, c) ((pd)->items[c]) /* Get the cummulative probability value (normalizing constant). */ #define probdist_total(pd) ((pd)->total) /* Set the value of given item. */ static void probdist_set(struct probdist *pd, coord_t c, fixp_t val); /* Remove the item from the totals; this is used when you then * pass it in the ignore list to probdist_pick(). Of course you * must restore the totals afterwards. */ static void probdist_mute(struct probdist *pd, coord_t c); /* Pick a random item. ignore is a pass-terminated sorted array of items * that are not to be considered (and whose values are not in @total). */ coord_t probdist_pick(struct probdist *pd, coord_t *ignore); /* Now, we do something horrible - include board.h for the inline helpers. * Yay for us. */ #include "board.h" static inline void probdist_set(struct probdist *pd, coord_t c, fixp_t val) { /* We disable the assertions here since this is quite time-critical * part of code, and also the compiler is reluctant to inline the * functions otherwise. */ #if 0 assert(c >= 0 && c < board_size2(pd->b)); assert(val >= 0); #endif pd->total += val - pd->items[c]; pd->rowtotals[coord_y(c, pd->b)] += val - pd->items[c]; pd->items[c] = val; } static inline void probdist_mute(struct probdist *pd, coord_t c) { pd->total -= pd->items[c]; pd->rowtotals[coord_y(c, pd->b)] -= pd->items[c]; } #endif