8000 The random selection in function linear() could deliver a value equal… · larkly/postgres-docker@2b91c8c · GitHub
[go: up one dir, main page]

Skip to content

Commit 2b91c8c

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 e4ce3e7 commit 2b91c8c

File tree

1 file changed

+25
-12
lines changed

1 file changed

+25
-12
lines changed

src/backend/optimizer/geqo/geqo_selection.c

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Id: geqo_selection.c,v 1.12 2001/01/24 19:42:57 momjian Exp $
9+
* $Id: geqo_selection.c,v 1.12.4.1 2005/06/14 14:21:43 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -43,48 +43,61 @@
4343

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

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

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

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

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

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

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

89102
return (int) index;
90103
}

0 commit comments

Comments
 (0)
0