Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 1265724

Browse files
committed
The random selection in function linear() could deliver a value equal to max
if geqo_rand() returns exactly 1.0, resulting in failure due to indexing off the end of the pool array. Also, since this is using inexact float math, it seems wise to guard against roundoff error producing values slightly outside the expected range. Per report from bug@zedware.org.
1 parent 37c8393 commit 1265724

File tree

1 file changed

+25
-12
lines changed

1 file changed

+25
-12
lines changed

src/backend/optimizer/geqo/geqo_selection.c

+25-12
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_selection.c,v 1.18 2004/12/31 21:59:58 pgsql Exp $
9+
* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_selection.c,v 1.19 2005/06/14 14:21:16 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -44,48 +44,61 @@
4444

4545
static int linear(int max, double bias);
4646

47-
/* geqo_selection
48-
*
47+
48+
/*
49+
* geqo_selection
4950
* according to bias described by input parameters,
50-
* second genes are selected from the pool
51+
* first and second genes are selected from the pool
5152
*/
5253
void
5354
geqo_selection(Chromosome *momma, Chromosome *daddy, Pool *pool, double bias)
5455
{
5556
int first,
5657
second;
5758

58-
first = (int) linear(pool->size, bias);
59-
second = (int) linear(pool->size, bias);
59+
first = linear(pool->size, bias);
60+
second = linear(pool->size, bias);
6061

6162
if (pool->size > 1)
6263
{
6364
while (first == second)
64-
second = (int) linear(pool->size, bias);
65+
second = linear(pool->size, bias);
6566
}
6667

6768
geqo_copy(momma, &pool->data[first], pool->string_length);
6869
geqo_copy(daddy, &pool->data[second], pool->string_length);
6970
}
7071

71-
/* linear
72+
/*
73+
* linear
7274
* generates random integer between 0 and input max number
7375
* using input linear bias
7476
*
7577
* probability distribution function is: f(x) = bias - 2(bias - 1)x
7678
* bias = (prob of first rule) / (prob of middle rule)
77-
*
7879
*/
79-
8080
static int
8181
linear(int pool_size, double bias) /* bias is y-intercept of linear
8282
* distribution */
8383
{
8484
double index; /* index between 0 and pop_size */
8585
double max = (double) pool_size;
8686

87-
index = max * (bias - sqrt((bias * bias) - 4.0 * (bias - 1.0) * geqo_rand()))
88-
/ 2.0 / (bias - 1.0);
87+
/*
88+
* If geqo_rand() returns exactly 1.0 then we will get exactly max from
89+
* this equation, whereas we need 0 <= index < max. Also it seems possible
90+
* that roundoff error might deliver values slightly outside the range;
91+
* in particular avoid passing a value slightly less than 0 to sqrt().
92+
* If we get a bad value just try again.
93+
*/
94+
do {
95+
double sqrtval;
96+
97+
sqrtval = (bias * bias) - 4.0 * (bias - 1.0) * geqo_rand();
98+
if (sqrtval > 0.0)
99+
sqrtval = sqrt(sqrtval);
100+
index = max * (bias - sqrtval) / 2.0 / (bias - 1.0);
101+
} while (index < 0.0 || index >= max);
89102

90103
return (int) index;
91104
}

0 commit comments

Comments
 (0)