Parcourir la source

Replace GRASS_RND_SEED with seed= option and -s flag
Use lib/gis PRNG
Store seed in history


git-svn-id: https://svn.osgeo.org/grass/grass/trunk@61353 15284696-431f-4ddb-bdfa-cd5b030d7da7

Glynn Clements il y a 10 ans
Parent
commit
29b99eb65f

+ 0 - 21
raster/r.mapcalc/evaluate.c

@@ -254,26 +254,6 @@ static void error_handler(void *p)
     }
     }
 }
 }
 
 
-static void setup_rand(void)
-{
-    /* Read PRNG seed from environment variable if available */
-    /* GRASS_RND_SEED */
-    const char *random_seed = getenv("GRASS_RND_SEED");
-    long seed_value;
-
-    if (!random_seed)
-	return;
-
-    seed_value = atol(random_seed);
-    G_debug(3, "Read random seed from environment: %ld", seed_value);
-
-#if defined(HAVE_DRAND48)
-    srand48(seed_value);
-#else
-    srand((unsigned int)seed_value);
-#endif
-}
-
 void execute(expr_list * ee)
 void execute(expr_list * ee)
 {
 {
     int verbose = isatty(2);
     int verbose = isatty(2);
@@ -281,7 +261,6 @@ void execute(expr_list * ee)
     int count, n;
     int count, n;
 
 
     setup_region();
     setup_region();
-    setup_rand();
 
 
     exprs = ee;
     exprs = ee;
     G_add_error_handler(error_handler, NULL);
     G_add_error_handler(error_handler, NULL);

+ 2 - 0
raster/r.mapcalc/globals.h

@@ -6,6 +6,8 @@ extern volatile int floating_point_exception;
 extern volatile int floating_point_exception_occurred;
 extern volatile int floating_point_exception_occurred;
 extern int overflow_occurred;
 extern int overflow_occurred;
 extern int overwrite_flag;
 extern int overwrite_flag;
+extern long seed_value;
+extern long seeded;
 
 
 extern int current_depth, current_row;
 extern int current_depth, current_row;
 extern int depths, rows, columns;
 extern int depths, rows, columns;

+ 32 - 1
raster/r.mapcalc/main.c

@@ -31,6 +31,9 @@ int overwrite_flag;
 volatile int floating_point_exception;
 volatile int floating_point_exception;
 volatile int floating_point_exception_occurred;
 volatile int floating_point_exception_occurred;
 
 
+long seed_value;
+long seeded;
+
 /****************************************************************************/
 /****************************************************************************/
 
 
 static expr_list *result;
 static expr_list *result;
@@ -102,7 +105,8 @@ static expr_list *parse_file(const char *filename)
 int main(int argc, char **argv)
 int main(int argc, char **argv)
 {
 {
     struct GModule *module;
     struct GModule *module;
-    struct Option *expr, *file;
+    struct Option *expr, *file, *seed;
+    struct Flag *random;
     int all_ok;
     int all_ok;
 
 
     G_gisinit(argv[0]);
     G_gisinit(argv[0]);
@@ -126,6 +130,16 @@ int main(int argc, char **argv)
     file->description = _("File containing expression(s) to evaluate");
     file->description = _("File containing expression(s) to evaluate");
     file->guisection = _("Expression");
     file->guisection = _("Expression");
 
 
+    seed = G_define_option();
+    seed->key = "seed";
+    seed->type = TYPE_INTEGER;
+    seed->required = NO;
+    seed->description = _("Seed for rand() function");
+
+    random = G_define_flag();
+    random->key = 's';
+    random->description = _("Generate random seed (result is non-deterministic)");
+
     if (argc == 1)
     if (argc == 1)
     {
     {
 	char **p = G_malloc(3 * sizeof(char *));
 	char **p = G_malloc(3 * sizeof(char *));
@@ -145,6 +159,10 @@ int main(int argc, char **argv)
 	G_fatal_error(_("%s= and %s= are mutually exclusive"),
 	G_fatal_error(_("%s= and %s= are mutually exclusive"),
 			expr->key, file->key);
 			expr->key, file->key);
 
 
+    if (seed->answer && random->answer)
+	G_fatal_error(_("%s= and -%c are mutually exclusive"),
+		      seed->key, random->key);
+
     if (expr->answer)
     if (expr->answer)
 	result = parse_string(expr->answer);
 	result = parse_string(expr->answer);
     else if (file->answer)
     else if (file->answer)
@@ -155,6 +173,19 @@ int main(int argc, char **argv)
     if (!result)
     if (!result)
 	G_fatal_error(_("parse error"));
 	G_fatal_error(_("parse error"));
 
 
+    if (seed->answer) {
+	seed_value = atol(seed->answer);
+	G_srand48(seed_value);
+	seeded = 1;
+	G_debug(3, "Read random seed from seed=: %ld", seed_value);
+    }
+
+    if (random->answer) {
+	seed_value = G_srand48_auto();
+	seeded = 1;
+	G_debug(3, "Generated random seed (-s): %ld", seed_value);
+    }
+
     pre_exec();
     pre_exec();
     execute(result);
     execute(result);
     post_exec();
     post_exec();

+ 6 - 0
raster/r.mapcalc/map.c

@@ -740,6 +740,12 @@ void create_history(const char *dst, expression * e)
 	len -= n;
 	len -= n;
     }
     }
 
 
+    if (seeded) {
+	char buf[RECORD_LEN];
+	sprintf(buf, "random seed = %ld", seed_value);
+	Rast_append_history(&hist, buf);
+    }
+
     Rast_write_history(dst, &hist);
     Rast_write_history(dst, &hist);
 
 
     G_free(expr);
     G_free(expr);

+ 14 - 2
raster/r.mapcalc/r.mapcalc.html

@@ -609,8 +609,20 @@ If a user want to use the existing map, the name of the temporary variable
 (map) must be changed.
 (map) must be changed.
 
 
 <h3>Random number generator initialization</h3>
 <h3>Random number generator initialization</h3>
-<p>The environment variable GRASS_RND_SEED is read to initialize the
-random number generator.
+<p>The pseudo-random number generator used by the rand() function can
+be initialised to a specific value using the <em>seed</em> option. 
+This can be used to replicate a previous calculation.
+<p>Alternatively, it can be initialised from the system time and the
+PID using the <em>-r</em> flag. This should result in a different seed
+being used each time.
+<p>In either case, the seed will be written to the map's history, and
+can be seen using <em>r.info</em>.
+<p>If you want other people to be able to verify your results, it's
+preferable to use the <em>seed</em> option to supply a seed which is
+either specified in the script or generated from a determenistic process
+such as a pseudo-random number generator given an explicit seed.
+<p>Note that the rand() function will generate a fatal error if neither
+the <em>seed</em> option nor the <em>-s</em> flag are given.
 
 
 <h2>EXAMPLES</h2>
 <h2>EXAMPLES</h2>
 To compute the average of two raster map layers
 To compute the average of two raster map layers

+ 14 - 2
raster/r.mapcalc/r3.mapcalc.html

@@ -470,8 +470,20 @@ you don't see data in masked areas even if they are not NULL.
 See <em><a href="r.mask.html">r.mask</a></em> for details.
 See <em><a href="r.mask.html">r.mask</a></em> for details.
 
 
 <h3>Random number generator initialization</h3>
 <h3>Random number generator initialization</h3>
-<p>The environment variable GRASS_RND_SEED is read to initialize the
-random number generator.
+<p>The pseudo-random number generator used by the rand() function can
+be initialised to a specific value using the <em>seed</em> option. 
+This can be used to replicate a previous calculation.
+<p>Alternatively, it can be initialised from the system time and the
+PID using the <em>-r</em> flag. This should result in a different seed
+being used each time.
+<p>In either case, the seed will be written to the map's history, and
+can be seen using <em>r.info</em>.
+<p>If you want other people to be able to verify your results, it's
+preferable to use the <em>seed</em> option to supply a seed which is
+either specified in the script or generated from a determenistic process
+such as a pseudo-random number generator given an explicit seed.
+<p>Note that the rand() function will generate a fatal error if neither
+the <em>seed</em> option nor the <em>-s</em> flag are given.
 
 
 <h2>EXAMPLES</h2>
 <h2>EXAMPLES</h2>
 To compute the average of two 3D grids
 To compute the average of two 3D grids

+ 3 - 8
raster/r.mapcalc/xrand.c

@@ -12,11 +12,6 @@
 rand(lo,hi) random values between a and b
 rand(lo,hi) random values between a and b
 ****************************************************************/
 ****************************************************************/
 
 
-#if !defined(HAVE_DRAND48)
-#define drand48() ((double)rand()/((double)RAND_MAX + 1))
-#define mrand48() ((long)rand())
-#endif
-
 int f_rand(int argc, const int *argt, void **args)
 int f_rand(int argc, const int *argt, void **args)
 {
 {
     int i;
     int i;
@@ -34,7 +29,7 @@ int f_rand(int argc, const int *argt, void **args)
 	    CELL *arg2 = args[2];
 	    CELL *arg2 = args[2];
 
 
 	    for (i = 0; i < columns; i++) {
 	    for (i = 0; i < columns; i++) {
-		unsigned long x = (unsigned long)mrand48();
+		unsigned long x = (unsigned long)G_mrand48();
 		int lo = arg1[i];
 		int lo = arg1[i];
 		int hi = arg2[i];
 		int hi = arg2[i];
 
 
@@ -55,7 +50,7 @@ int f_rand(int argc, const int *argt, void **args)
 	    FCELL *arg2 = args[2];
 	    FCELL *arg2 = args[2];
 
 
 	    for (i = 0; i < columns; i++) {
 	    for (i = 0; i < columns; i++) {
-		double x = drand48();
+		double x = G_drand48();
 		FCELL lo = arg1[i];
 		FCELL lo = arg1[i];
 		FCELL hi = arg2[i];
 		FCELL hi = arg2[i];
 
 
@@ -76,7 +71,7 @@ int f_rand(int argc, const int *argt, void **args)
 	    DCELL *arg2 = args[2];
 	    DCELL *arg2 = args[2];
 
 
 	    for (i = 0; i < columns; i++) {
 	    for (i = 0; i < columns; i++) {
-		double x = drand48();
+		double x = G_drand48();
 		DCELL lo = arg1[i];
 		DCELL lo = arg1[i];
 		DCELL hi = arg2[i];
 		DCELL hi = arg2[i];