1
%operation %virtual expression* optimize(expression *this)
8
#define MINFLOAT 0.0000001
11
// this is taken from http://en.wikipedia.org/wiki/Dice
12
// calculates the probability for value "pos" in the sum of "num"
13
// dice with "sides" faces
14
double Fsumdice(double *cache, int mnum, int num, int sides, int pos) {
15
if (pos > ((num*sides-num)/2)+num) {
16
pos = num*sides - pos + num;
20
if ((pos < 1) || (pos > sides)) {
30
if (cache[mnum*(pos-num)+num] < -0.5) {
32
for (i = 1; i < min(pos, sides+1); i++) {
33
ret += Fsumdice(cache, mnum, 1, sides, i)
34
* Fsumdice(cache, mnum, num-1, sides, pos-i);
36
cache[mnum*(pos-num)+num] = ret;
39
return cache[mnum*(pos-num)+num];
43
// calculates the probability that the sum of "num" rolls of
44
// distribution "dist" have the value "pos"
45
double Fsumany(double *cache, int mnum, int minval, int maxval, int num,
46
struct val_list *dist, int pos) {
47
struct val_list *cdist = dist;
50
if (cdist->values[0] == pos) {
58
int cpos = pos*mnum+num;
59
if ((pos < minval * num) || (pos > maxval * pos)) {
62
if (cache[cpos] < -0.5) {
65
ret += cdist->prob * Fsumany(cache, mnum, minval, maxval,
66
num - 1, dist, pos - cdist->values[0]);
78
// optimized version of sum N#dM
79
%node sumrepdice expression =
81
struct val_list *num_dice;
86
// unsupported, only used in eval
89
printtree(sumrepdice) {
90
// unsupported, only used in eval
93
set_symtab(sumrepdice) {
94
// not needed, don't use symtab
99
struct val_list *ret = NULL;
100
struct val_list *cnum = this->num_dice;
102
if (cnum->count != 1) {
103
yyerror("Argument 1 to sumrep operator is not scalar");
104
list_free(this->num_dice);
108
int num_dice_val = cnum->values[0];
109
if (num_dice_val > 0) {
110
int expected = num_dice_val*
111
((num_dice_val*this->num_sides-num_dice_val)/2)
113
double *cache = malloc(sizeof(double) * expected);
114
for (n = 0; n < expected; n++) {
117
for (n = num_dice_val * this->num_sides;
118
n >= num_dice_val; n--) {
119
struct val_list *cret =
120
(struct val_list*)malloc(sizeof(struct val_list));
123
cret->prob = Fsumdice(cache, num_dice_val, num_dice_val,
124
this->num_sides, n) * cnum->prob;
125
cret->values = (int*)malloc(sizeof(int));
127
list_add(&ret, cret, this->ordering);
134
return list_new(1, 1.0);
139
%node sumrepany expression =
141
struct val_list *number;
142
struct val_list *data;
146
// unsupported, only used in eval
149
printtree(sumrepany) {
150
// unsupported, only used in eval
153
set_symtab(sumrepany) {
154
// not needed, don't use symtab
159
struct val_list *ret = NULL;
160
struct val_list *cnum = this->number;
163
struct val_list *cval = this->data;
165
if ((minval == -1) || (cval->values[0] < minval)) {
166
minval = cval->values[0];
168
if (cval->values[0] > maxval) {
169
maxval = cval->values[0];
174
if (cnum->count != 1) {
175
yyerror("Argument 1 to sumrep operator is not scalar");
176
list_free(this->number);
177
list_free(this->data);
181
if (cnum->values[0] == 0) {
182
struct val_list *cret =
183
(struct val_list*)malloc(sizeof(struct val_list));
186
cret->prob = cnum->prob;
187
cret->values = (int*)malloc(sizeof(int));
189
list_add(&ret, cret, this->ordering);
192
int expected = (cnum->values[0] * maxval + 1) * cnum->values[0] + 1;
193
double *cache = malloc(sizeof(double) * expected);
194
for (n = 0; n < expected; n++) {
197
for (n = cnum->values[0] * minval; n <= cnum->values[0] * maxval; n++) {
198
struct val_list *cret =
199
(struct val_list*)malloc(sizeof(struct val_list));
202
cret->prob = Fsumany(cache, cnum->values[0], minval, maxval,
203
cnum->values[0], this->data, n) * cnum->prob;
204
cret->values = (int*)malloc(sizeof(int));
206
if (cret->prob > MINFLOAT) {
207
list_add(&ret, cret, this->ordering);
218
return list_new(1, 1.0);
223
// optimization fuctions, replaces the tree with a different version
231
this->expr1 = optimize(this->expr1);
232
this->expr2 = optimize(this->expr2);
233
return (expression*)this;
238
this->expr = optimize(this->expr);
239
return (expression*)this;
244
this->if_expr = optimize(this->if_expr);
245
this->then_expr = optimize(this->then_expr);
246
this->else_expr = optimize(this->else_expr);
247
return (expression*)this;
252
if (yykind(this->expr) == rep_kind) {
253
rep *crep = (rep*)this->expr;
254
if (yykind(crep->expr2) == dice_kind) {
255
dice *cdice = (dice*)crep->expr2;
256
if (yykind(cdice->expr) == number_kind) {
258
expression *replace = sumrepdice_create(
260
((number*)cdice->expr)->num);
266
expression *replace = sumrepany_create(
268
eval(sum_create(crep->expr2)));
272
return (expression*)this;