]> granicus.if.org Git - postgresql/blobdiff - src/backend/optimizer/geqo/geqo_selection.c
Run pgindent on 9.2 source tree in preparation for first 9.3
[postgresql] / src / backend / optimizer / geqo / geqo_selection.c
index 8c5301f10b7e36350f85587121e27820d879a3af..fbdcc5ff0c997651052c5b2191236aa4e0c2eec3 100644 (file)
@@ -3,9 +3,10 @@
  * geqo_selection.c
  *       linear selection scheme for the genetic query optimizer
  *
- * Copyright (c) 1994, Regents of the University of California
+ * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: geqo_selection.c,v 1.8 1999/07/15 15:19:15 momjian Exp $
+ * src/backend/optimizer/geqo/geqo_selection.c
  *
  *-------------------------------------------------------------------------
  */
 /*                                                                                                                      */
 /*************************************************************/
 
-#include <math.h>
-
 #include "postgres.h"
 
-#include "nodes/pg_list.h"
-#include "nodes/relation.h"
-#include "nodes/primnodes.h"
-
-
-#include "optimizer/internal.h"
-#include "optimizer/paths.h"
-#include "optimizer/pathnode.h"
-#include "optimizer/clauses.h"
-#include "optimizer/cost.h"
+#include <math.h>
 
-#include "optimizer/geqo_gene.h"
-#include "optimizer/geqo_selection.h"
 #include "optimizer/geqo_copy.h"
 #include "optimizer/geqo_random.h"
+#include "optimizer/geqo_selection.h"
 
-static int     linear(int max, double bias);
+static int     linear_rand(PlannerInfo *root, int max, double bias);
 
-/* geqo_selection
- *
+
+/*
+ * geqo_selection
  *      according to bias described by input parameters,
- *      second genes are selected from the pool
+ *      first and second genes are selected from the pool
  */
 void
-geqo_selection(Chromosome *momma, Chromosome *daddy, Pool *pool, double bias)
+geqo_selection(PlannerInfo *root, Chromosome *momma, Chromosome *daddy,
+                          Pool *pool, double bias)
 {
        int                     first,
                                second;
 
-       first = (int) linear(pool->size, bias);
-       second = (int) linear(pool->size, bias);
-
+       first = linear_rand(root, pool->size, bias);
+       second = linear_rand(root, pool->size, bias);
+
+       /*
+        * Ensure we have selected different genes, except if pool size is only
+        * one, when we can't.
+        *
+        * This code was observed to hang up in an infinite loop when the
+        * platform's implementation of erand48() was broken.  We now always use
+        * our own version.
+        */
        if (pool->size > 1)
        {
                while (first == second)
-                       second = (int) linear(pool->size, bias);
+                       second = linear_rand(root, pool->size, bias);
        }
 
-       geqo_copy(momma, &pool->data[first], pool->string_length);
-       geqo_copy(daddy, &pool->data[second], pool->string_length);
+       geqo_copy(root, momma, &pool->data[first], pool->string_length);
+       geqo_copy(root, daddy, &pool->data[second], pool->string_length);
 }
 
-/* linear
+/*
+ * linear_rand
  *       generates random integer between 0 and input max number
  *       using input linear bias
  *
+ *       bias is y-intercept of linear distribution
+ *
  *       probability distribution function is: f(x) = bias - 2(bias - 1)x
  *                      bias = (prob of first rule) / (prob of middle rule)
- *
  */
-
 static int
-linear(int pool_size, double bias)             /* bias is y-intercept of linear
-                                                                                * distribution */
+linear_rand(PlannerInfo *root, int pool_size, double bias)
 {
        double          index;                  /* index between 0 and pop_size */
        double          max = (double) pool_size;
 
-       index = max * (bias - sqrt((bias * bias) - 4.0 * (bias - 1.0) * geqo_rand()))
-               / 2.0 / (bias - 1.0);
+       /*
+        * If geqo_rand() returns exactly 1.0 then we will get exactly max from
+        * this equation, whereas we need 0 <= index < max.  Also it seems
+        * possible that roundoff error might deliver values slightly outside the
+        * range; in particular avoid passing a value slightly less than 0 to
+        * sqrt(). If we get a bad value just try again.
+        */
+       do
+       {
+               double          sqrtval;
+
+               sqrtval = (bias * bias) - 4.0 * (bias - 1.0) * geqo_rand(root);
+               if (sqrtval > 0.0)
+                       sqrtval = sqrt(sqrtval);
+               index = max * (bias - sqrtval) / 2.0 / (bias - 1.0);
+       } while (index < 0.0 || index >= max);
 
        return (int) index;
 }