diff options
author | Téo Mazars <teomazars@gmail.com> | 2013-11-14 13:21:07 +0100 |
---|---|---|
committer | Téo Mazars <teomazars@gmail.com> | 2013-11-14 19:17:34 +0100 |
commit | 57af178e6b5a018ef68a3d2d1d99926b1b866f91 (patch) | |
tree | ac26d8f010f07399c86b6ae42b9c48eedda0d496 | |
parent | ffb882f152c058353e1b33db639584a9b01e2146 (diff) |
random: improve gegl-random implementation
- introduce a GeglRandom structure instead of accessing the LUT each time
- make a larger cycle for the seed
- avoid segfault when a negative seed is given
- use g(u)int64 instead of long to avoid plaform-dependant behavior
- make opencl and operations follow that api change
- build the GeglRandom structure in the gegl-chant machinery when using
gegl_chant_seed
- make sure the pointer gegl_random_data is 32bits aligned when used with
CL_MEM_USE_HOST_PTR
-rw-r--r-- | gegl/Makefile.am | 1 | ||||
-rw-r--r-- | gegl/gegl-chant.h | 30 | ||||
-rw-r--r-- | gegl/gegl-init.c | 2 | ||||
-rw-r--r-- | gegl/gegl-random-priv.h | 15 | ||||
-rw-r--r-- | gegl/gegl-random.c | 266 | ||||
-rw-r--r-- | gegl/gegl-random.h | 131 | ||||
-rw-r--r-- | gegl/gegl-types.h | 4 | ||||
-rw-r--r-- | gegl/gegl.h | 61 | ||||
-rw-r--r-- | gegl/opencl/gegl-cl-random.c | 32 | ||||
-rw-r--r-- | gegl/opencl/gegl-cl-random.h | 5 | ||||
-rw-r--r-- | opencl/noise-hurl.cl | 35 | ||||
-rw-r--r-- | opencl/noise-hurl.cl.h | 35 | ||||
-rw-r--r-- | opencl/random.cl | 111 | ||||
-rw-r--r-- | opencl/random.cl.h | 107 | ||||
-rw-r--r-- | operations/common/cubism.c | 2 | ||||
-rw-r--r-- | operations/common/mosaic.c | 38 | ||||
-rw-r--r-- | operations/common/noise-cie-lch.c | 39 | ||||
-rw-r--r-- | operations/common/noise-hsv.c | 38 | ||||
-rw-r--r-- | operations/common/noise-hurl.c | 47 | ||||
-rw-r--r-- | operations/common/noise-pick.c | 4 | ||||
-rw-r--r-- | operations/common/noise-rgb.c | 10 | ||||
-rw-r--r-- | operations/common/noise-slur.c | 4 | ||||
-rw-r--r-- | operations/common/noise-spread.c | 24 | ||||
-rw-r--r-- | operations/common/plasma.c | 2 | ||||
-rw-r--r-- | operations/common/shift.c | 4 | ||||
-rw-r--r-- | operations/common/wind.c | 2 |
26 files changed, 609 insertions, 440 deletions
diff --git a/gegl/Makefile.am b/gegl/Makefile.am index e779ab01..c998f8c6 100644 --- a/gegl/Makefile.am +++ b/gegl/Makefile.am @@ -45,6 +45,7 @@ GEGL_introspectable_headers = \ gegl-utils.h \ gegl-matrix.h \ gegl-lookup.h \ + gegl-random.h \ gegl-version.h \ buffer/gegl-buffer.h \ buffer/gegl-buffer-iterator.h \ diff --git a/gegl/gegl-chant.h b/gegl/gegl-chant.h index 4920dee0..007bc2d1 100644 --- a/gegl/gegl-chant.h +++ b/gegl/gegl-chant.h @@ -349,7 +349,7 @@ gegl_module_register (GTypeModule *module) #define gegl_chant_format(name, nick, blurb) #define gegl_chant_color(name, nick, def, blurb) #define gegl_chant_curve(name, nick, blurb) -#define gegl_chant_seed(name, nick, blurb) +#define gegl_chant_seed(name, rand_name, nick, blurb) #define gegl_chant_path(name, nick, blurb) #define gegl_chant_register_enum(enum_name) \ typedef enum { @@ -434,7 +434,8 @@ struct _GeglChantO #define gegl_chant_format(name, nick, blurb) gpointer name; #define gegl_chant_color(name, nick, def, blurb) GeglColor *name; #define gegl_chant_curve(name, nick, blurb) GeglCurve *name; -#define gegl_chant_seed(name, nick, blurb) gint name; +#define gegl_chant_seed(name, rand_name, nick, blurb) gint name;\ + GeglRandom *rand_name; #define gegl_chant_path(name, nick, blurb) GeglPath *name;\ gulong path_changed_handler; @@ -477,7 +478,7 @@ enum #define gegl_chant_format(name, nick, blurb) PROP_##name, #define gegl_chant_color(name, nick, def, blurb) PROP_##name, #define gegl_chant_curve(name, nick, blurb) PROP_##name, -#define gegl_chant_seed(name, nick, blurb) PROP_##name, +#define gegl_chant_seed(name, rand_name, nick, blurb) PROP_##name, #define gegl_chant_path(name, nick, blurb) PROP_##name, #include GEGL_CHANT_C_FILE @@ -569,7 +570,7 @@ get_property (GObject *gobject, case PROP_##name: \ g_value_set_object (value, properties->name); \ break; -#define gegl_chant_seed(name, nick, blurb) \ +#define gegl_chant_seed(name, rand_name, nick, blurb) \ case PROP_##name: \ g_value_set_int (value, properties->name); \ break; @@ -683,10 +684,14 @@ set_property (GObject *gobject, g_object_unref (properties->name); \ properties->name = g_value_dup_object (value); \ break; -#define gegl_chant_seed(name, nick, blurb) \ +#define gegl_chant_seed(name, rand_name, nick, blurb) \ case PROP_##name: \ properties->name = g_value_get_int (value); \ - break; + if (!properties->rand_name) \ + properties->rand_name = gegl_random_new_with_seed (properties->name);\ + else \ + gegl_random_set_seed (properties->rand_name, properties->name);\ + break; #define gegl_chant_path(name, nick, blurb) \ case PROP_##name: \ if (properties->name != NULL) \ @@ -781,7 +786,12 @@ static void gegl_chant_destroy_notify (gpointer data) g_object_unref (properties->name); \ properties->name = NULL; \ } -#define gegl_chant_seed(name, nick, blurb) +#define gegl_chant_seed(name, rand_name, nick, blurb)\ + if (properties->rand_name) \ + { \ + gegl_random_free (properties->rand_name); \ + properties->rand_name = NULL; \ + } #define gegl_chant_path(name, nick, blurb) \ if (properties->name) \ { \ @@ -840,7 +850,9 @@ gegl_chant_constructor (GType type, #define gegl_chant_color(name, nick, def, blurb) \ if (properties->name == NULL) \ {properties->name = gegl_color_new(def?def:"black");} -#define gegl_chant_seed(name, nick, blurb) +#define gegl_chant_seed(name, rand_name, nick, blurb) \ + if (properties->rand_name == NULL) \ + {properties->rand_name = gegl_random_new_with_seed (0);} #define gegl_chant_path(name, nick, blurb) #define gegl_chant_curve(name, nick, blurb) @@ -981,7 +993,7 @@ gegl_chant_class_intern_init (gpointer klass) G_PARAM_READWRITE |\ G_PARAM_CONSTRUCT | \ GEGL_PARAM_PAD_INPUT))); -#define gegl_chant_seed(name, nick, blurb) \ +#define gegl_chant_seed(name, rand_name, nick, blurb) \ g_object_class_install_property (object_class, PROP_##name, \ gegl_param_spec_seed (#name, nick, blurb, \ (GParamFlags) ( \ diff --git a/gegl/gegl-init.c b/gegl/gegl-init.c index 2fd52757..9c3723b1 100644 --- a/gegl/gegl-init.c +++ b/gegl/gegl-init.c @@ -103,6 +103,7 @@ guint gegl_debug_flags = 0; #include "buffer/gegl-tile-backend-file.h" #include "gegl-config.h" #include "graph/gegl-node.h" +#include "gegl-random-priv.h" static const gchar *makefile (void); @@ -450,6 +451,7 @@ gegl_exit (void) gegl_tile_cache_destroy (); gegl_operation_gtype_cleanup (); gegl_extension_handler_cleanup (); + gegl_random_cleanup (); if (module_db != NULL) { diff --git a/gegl/gegl-random-priv.h b/gegl/gegl-random-priv.h index c5e23912..0442dd99 100644 --- a/gegl/gegl-random-priv.h +++ b/gegl/gegl-random-priv.h @@ -19,10 +19,19 @@ #ifndef __GEGL_RANDOM_PRIV_H__ #define __GEGL_RANDOM_PRIV_H__ -#define PRIMES_SIZE 533 -#define RANDOM_DATA_SIZE (15083+15091+15101) +#define RANDOM_DATA_SIZE (15101 * 3) + +struct _GeglRandom +{ + guint16 prime0; + guint16 prime1; + guint16 prime2; +}; + +guint32* +gegl_random_get_data (void); void -gegl_random_init (void); +gegl_random_cleanup (void); #endif /* __GEGL_RANDOM_PRIV_H__ */ diff --git a/gegl/gegl-random.c b/gegl/gegl-random.c index 52a4135d..a81f97a2 100644 --- a/gegl/gegl-random.c +++ b/gegl/gegl-random.c @@ -14,6 +14,7 @@ * License along with GEGL; if not, see <http://www.gnu.org/licenses/>. * * Copyright 2012, 2013 Øyvind Kolås + * Copyright 2013 Téo Mazars <teomazars@gmail.com> */ /* This file provides random access - reproducable random numbers in three @@ -24,25 +25,24 @@ * it is there in the API to provide for mip-map behavior later. * * The way it works is by xoring three lookup tables that are iterated - * cyclically, each LUT has a prime number as a size, thus the combination - * of the three values xored will have a period of prime1 * prime2 * prime3, - * with the primes used this yields roughly 3TB of random, non-repeating - * data from ~300kb of lookup data. + * cyclically, each LUT has a different prime number as a size, thus + * the combination of the three values xored will have a period of + * prime1 * prime2 * prime3, with the primes used this yields more than + * 1TB of random, non-repeating data from ~180kb of lookup data. * * The data for the LUTs is shared between different random seeds, it - * is just the sizes of the LUTs that change, currently with 468 primes - * there is about 101847096 different seeds achivable (with 45 primes - * only 83160 combinations are possible (maybe this would have been enough - * though) + * is just the sizes of the LUTs that change, currently with 533 primes + * there is about 533 * 532 * 531 different seeds achivable. */ #include <glib.h> #include <gegl.h> +#include "gegl-random.h" #include "gegl-random-priv.h" /* a set of reasonably large primes to choose from for array sizes */ -long gegl_random_primes[PRIMES_SIZE]={ +guint16 gegl_random_primes[533]={ 10007,10009,10037,10039,10061,10067,10069,10079,10091,10093,10099,10103,10111, 10133,10139,10141,10151,10159,10163,10169,10177,10181,10193,10211,10223,10243, 10247,10253,10259,10267,10271,10273,10289,10301,10303,10313,10321,10331,10333, @@ -87,119 +87,191 @@ long gegl_random_primes[PRIMES_SIZE]={ }; /* these primes should not exist in the above set */ -#define XPRIME 103423 -#define YPRIME 101359 -#define NPRIME 101111 -#define MAX_TABLES 3 +#define XPRIME 103423LL +#define YPRIME 101359LL +#define NPRIME 101111LL -gint32 gegl_random_data[RANDOM_DATA_SIZE]; -static gboolean random_data_inited = FALSE; +#define SQR(x) ((x)*(x)) -void +static guint32 *gegl_random_data; +static gboolean random_data_inited = FALSE; + +static void gegl_random_init (void) { - if (G_LIKELY (random_data_inited)) + if (random_data_inited) return; + else + { + GRand *gr = g_rand_new_with_seed (42); + gint i; + + /* Ensure alignment, needed with the use of CL_MEM_USE_HOST_PTR */ + gegl_random_data = gegl_malloc (RANDOM_DATA_SIZE * sizeof (guint32)); - { - GRand *gr = g_rand_new_with_seed (42); - int i; - for (i = 0; i < RANDOM_DATA_SIZE; i++) - gegl_random_data[i] = g_rand_int (gr); - g_rand_free (gr); - random_data_inited = TRUE; - } + for (i = 0; i < RANDOM_DATA_SIZE; i++) + gegl_random_data[i] = g_rand_int (gr); + + g_rand_free (gr); + random_data_inited = TRUE; + } } +void +gegl_random_cleanup (void) +{ + if (random_data_inited) + { + gegl_free (gegl_random_data); + gegl_random_data = NULL; + random_data_inited = FALSE; + } +} -static inline guint32 -_gegl_random_int (int seed, - int x, - int y, - int z, - int n) +guint32* +gegl_random_get_data (void) { - unsigned long idx = x * XPRIME + - y * YPRIME * XPRIME + - n * NPRIME * YPRIME * XPRIME; -#define ROUNDS 3 - /* 3 rounds gives a reasonably high cycle for */ - /* our synthesized larger random set. */ - long * prime = &gegl_random_primes[seed % (G_N_ELEMENTS (gegl_random_primes) - - 1 - ROUNDS)]; gegl_random_init (); -#define UNROLLED - -#ifdef UNROLLED - - { - int prime0 = prime[0], - prime1 = prime[1], - prime2 = prime[2]; - return - gegl_random_data[idx % prime0] ^ - gegl_random_data[prime0 + (idx % (prime1))] ^ - gegl_random_data[prime0 + prime1 + (idx % (prime2))]; - } -#else - { - gint32 ret = 0; - int i; - int offset = 0; - - for (i = 0; i < ROUNDS; i++) - ret ^= gegl_random_data[offset + (idx % (prime[i]))]; - offset += prime[i]; - - - return ret; - } -#endif + return gegl_random_data; +} + +GeglRandom* +gegl_random_new (void) +{ + guint seed = (guint) g_random_int(); + + return gegl_random_new_with_seed (seed); +} + +GeglRandom* +gegl_random_new_with_seed (guint32 seed) +{ + GeglRandom *rand = g_new (GeglRandom, 1); + + gegl_random_set_seed (rand, seed); + + return rand; +} + +void +gegl_random_free (GeglRandom *rand) +{ + g_free (rand); +} + +void +gegl_random_set_seed (GeglRandom *rand, + guint32 seed) +{ + guint number_elem = G_N_ELEMENTS (gegl_random_primes); + guint id0, id1, id2; + + /* XXX: Probably needs to be done at gegl-init */ + gegl_random_init (); + + /* gives roughly number_elem^3 different sets */ + id0 = seed % number_elem; + id1 = (seed / number_elem) % number_elem; + id2 = (seed / SQR (number_elem)) % number_elem; + + /* Shuffle a bit to avoid to hit edge cases near 0 */ + id0 = (id0 + 42) % number_elem; + id1 = (id1 + 212) % number_elem; + id2 = (id2 + 17) % number_elem; + + /* all primes numbers must be distincts */ + while (id0 == id1 || id0 == id2) + id0 = (id0 + 1) % number_elem; + + while (id1 == id0 || id1 == id2) + id1 = (id1 + 1) % number_elem; + + rand->prime0 = gegl_random_primes[id0]; + rand->prime1 = gegl_random_primes[id1]; + rand->prime2 = gegl_random_primes[id2]; +} + +GeglRandom* +gegl_random_duplicate (GeglRandom *gegl_random) +{ + GeglRandom *result = g_new (GeglRandom, 1); + + *result = *gegl_random; + + return result; +} + +GType +gegl_random_get_type (void) +{ + static GType our_type = 0; + + if (our_type == 0) + our_type = g_boxed_type_register_static (g_intern_static_string ("GeglRandom"), + (GBoxedCopyFunc) gegl_random_duplicate, + (GBoxedFreeFunc) g_free); + return our_type; +} + +static inline guint32 +_gegl_random_int (const GeglRandom *rand, + gint x, + gint y, + gint z, + gint n) +{ + guint64 idx = x * XPRIME + + y * YPRIME * XPRIME + + n * NPRIME * YPRIME * XPRIME; + return + gegl_random_data[idx % rand->prime0] ^ + gegl_random_data[rand->prime0 + (idx % (rand->prime1))] ^ + gegl_random_data[rand->prime0 + rand->prime1 + (idx % (rand->prime2))]; } guint32 -gegl_random_int (int seed, - int x, - int y, - int z, - int n) +gegl_random_int (const GeglRandom *rand, + gint x, + gint y, + gint z, + gint n) { - return _gegl_random_int (seed, x, y, z, n); + return _gegl_random_int (rand, x, y, z, n); } gint32 -gegl_random_int_range (int seed, - int x, - int y, - int z, - int n, - int min, - int max) +gegl_random_int_range (const GeglRandom *rand, + gint x, + gint y, + gint z, + gint n, + gint min, + gint max) { - guint32 ret = _gegl_random_int (seed, x, y, z, n); - return (ret % (max-min)) + min; + guint32 ret = _gegl_random_int (rand, x, y, z, n); + return (ret % (max - min)) + min; } #define G_RAND_FLOAT_TRANSFORM 0.00001525902189669642175 -float -gegl_random_float (int seed, - int x, - int y, - int z, - int n) +gfloat +gegl_random_float (const GeglRandom *rand, + gint x, + gint y, + gint z, + gint n) { - return (_gegl_random_int (seed, x, y, z, n) & 0xffff) * G_RAND_FLOAT_TRANSFORM; + return (_gegl_random_int (rand, x, y, z, n) & 0xffff) * G_RAND_FLOAT_TRANSFORM; } -float -gegl_random_float_range (int seed, - int x, - int y, - int z, - int n, - float min, - float max) +gfloat +gegl_random_float_range (const GeglRandom *rand, + gint x, + gint y, + gint z, + gint n, + gfloat min, + gfloat max) { - return gegl_random_float (seed, x, y, z, n) * (max - min) + min; + return gegl_random_float (rand, x, y, z, n) * (max - min) + min; } diff --git a/gegl/gegl-random.h b/gegl/gegl-random.h new file mode 100644 index 00000000..d7f3dfc9 --- /dev/null +++ b/gegl/gegl-random.h @@ -0,0 +1,131 @@ +/* This file is part of GEGL + * + * GEGL is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * GEGL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with GEGL; if not, see <http://www.gnu.org/licenses/>. + * + * Copyright 2006 Øyvind Kolås + * Copyright 2013 Téo Mazars <teomazars@gmail.com> + */ + +#ifndef __GEGL_RANDOM_H__ +#define __GEGL_RANDOM_H__ + +#include "gegl-types.h" + +G_BEGIN_DECLS + +/** + * gegl_random_new_with_seed: + * @seed: an integer seed, change for different permutation. + * + * Return an opaque structure associated to the seed. + * This structure needs to be freed by the user with gegl_random_free(); + */ +GeglRandom* gegl_random_new_with_seed (guint32 seed); + +/** + * gegl_random_new: + * + * Creates a new random number generator initialized with a random seed. + * This structure needs to be freed by the user with gegl_random_free(); + */ +GeglRandom* gegl_random_new (void); + +/** + * gegl_random_duplicate: + * @rand: The GeglRandom to duplicate + * + * Return a new copy of an existing GeglRandom + */ +GeglRandom* gegl_random_duplicate (GeglRandom *rand); + +/** + * gegl_random_free: + * @rand: The GeglRandom structure to free + * + * Free a GeglRandom structure created with gegl_random_new() or gegl_random_new_with_seed() + */ +void gegl_random_free (GeglRandom *rand); + +/** + * gegl_random_set_seed: + * @rand: The GeglRandom to set + * @seed: an integer seed, change for different permutation. + * + * Change the seed of an existing GeglRandom. + */ +void gegl_random_set_seed (GeglRandom *rand, guint32 seed); + +/** + * gegl_random_float_range: + * @rand: a GeglRandom + * @x: x coordinate + * @y: y coordinate + * @z: z coordinate (mipmap level) + * @n: number no (each x,y coordinate provides its own sequence of + * numbers + * @min: minimum value + * @max: maxmimum value + * + * Return a random floating point number in the range specified, + * for the given x,y coordinates and GeglRandom provided, if multiple different + * numbers are needed pass in incrementing n's. + */ +gfloat gegl_random_float_range (const GeglRandom *rand, gint x, gint y, gint z, gint n, gfloat min, gfloat max); + +/** + * gegl_random_int_range: + * @rand: a GeglRandom + * @x: x coordinate + * @y: y coordinate + * @z: z coordinate (mipmap level) + * @n: number no (each x,y coordinate provides its own sequence of + * numbers + * @min: minimum value + * @max: maxmimum value+1 + * + * Return a random integer point number in the range specified, + * for the given x,y coordinates and GeglRandom provided, if multiple different + * numbers are needed pass in incrementing n's. + */ +gint32 gegl_random_int_range (const GeglRandom *rand, gint x, gint y, gint z, gint n, gint min, gint max); + +/** + * gegl_random_int: + * @rand: a GeglRandom + * @x: x coordinate + * @y: y coordinate + * @z: z coordinate (mipmap level) + * @n: number no (each x,y coordinate provides its own sequence of + * numbers + * + * Return a random integer number in range 0 .. MAX_UINT + */ +guint32 gegl_random_int (const GeglRandom *rand, gint x, gint y, gint z, gint n); + +/** + * gegl_random_float: + * @rand: a GeglRandom + * @x: x coordinate + * @y: y coordinate + * @z: z coordinate (mipmap level) + * @n: number no (each x,y coordinate provides its own sequence of + * numbers + * + * Return a random floating point number in range 0.0 .. 1.0. + */ +gfloat gegl_random_float (const GeglRandom *rand, gint x, gint y, gint z, gint n); + +G_END_DECLS + +#endif /* __GEGL_RANDOM_H__ */ diff --git a/gegl/gegl-types.h b/gegl/gegl-types.h index 58fdde6e..aa87ea4d 100644 --- a/gegl/gegl-types.h +++ b/gegl/gegl-types.h @@ -77,6 +77,10 @@ GType gegl_processor_get_type (void) G_GNUC_CONST; #define GEGL_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEGL_TYPE_PROCESSOR, GeglProcessor)) #define GEGL_IS_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEGL_TYPE_PROCESSOR)) +typedef struct _GeglRandom GeglRandom; +GType gegl_random_get_type (void) G_GNUC_CONST; +#define GEGL_TYPE_RANDOM (gegl_random_get_type()) + G_END_DECLS #endif /* __GEGL_TYPES_H__ */ diff --git a/gegl/gegl.h b/gegl/gegl.h index b5421adc..af36f254 100644 --- a/gegl/gegl.h +++ b/gegl/gegl.h @@ -31,6 +31,7 @@ #include <gegl-matrix.h> #include <gegl-utils.h> #include <gegl-version.h> +#include <gegl-random.h> /*** @@ -995,66 +996,6 @@ GeglNode *gegl_node (const gchar *op_type, */ GeglNode *gegl_graph (GeglNode *node); -/** - * gegl_random_float_range: - * @seed: an integer seed, change for different permutation - * @x: x coordinate - * @y: y coordinate - * @z: z coordinate (mipmap level) - * @n: number no (each x,y coordinate provides its own sequence of - * numbers - * @min: minimum value - * @max: maxmimum value - * - * Return a random floating point number in the range specified, - * for the given x,y coordinates and seed provided, if multiple different - * numbers are needed pass in incrementing n's. - */ -float gegl_random_float_range (int seed, int x, int y, int z, int n, float min, float max); - - -/** - * gegl_random_int_range: - * @seed: an integer seed, change for different permutation - * @x: x coordinate - * @y: y coordinate - * @z: z coordinate (mipmap level) - * @n: number no (each x,y coordinate provides its own sequence of - * numbers - * @min: minimum value - * @max: maxmimum value+1 - * - * Return a random integer point number in the range specified, - * for the given x,y coordinates and seed provided, if multiple different - * numbers are needed pass in incrementing n's. - */ -gint32 gegl_random_int_range (int seed, int x, int y, int z, int n, int min, int max); - -/** - * gegl_random_int: - * @seed: an integer seed, change for different permutation - * @x: x coordinate - * @y: y coordinate - * @z: z coordinate (mipmap level) - * @n: number no (each x,y coordinate provides its own sequence of - * numbers - * - * Return a random integer number in range 0 .. MAX_UINT - */ -guint32 gegl_random_int (int seed, int x, int y, int z, int n); - -/** - * gegl_random_float: - * @seed: an integer seed, change for different permutation - * @x: x coordinate - * @y: y coordinate - * @z: z coordinate (mipmap level) - * @n: number no (each x,y coordinate provides its own sequence of - * numbers - * - * Return a random floating point number in range 0.0 .. 1.0. - */ -float gegl_random_float (int seed, int x, int y, int z, int n); #define GEGL_ALIGNED __restrict__ __attribute__((__aligned__ (16))) diff --git a/gegl/opencl/gegl-cl-random.c b/gegl/opencl/gegl-cl-random.c index 4724cd54..46e88a05 100644 --- a/gegl/opencl/gegl-cl-random.c +++ b/gegl/opencl/gegl-cl-random.c @@ -21,33 +21,27 @@ #include "opencl/gegl-cl.h" #include "gegl-random-priv.h" -/*XXX: defined in gegl-random.c*/ - -extern gint32 *gegl_random_data; -extern long *gegl_random_primes; - cl_mem gegl_cl_load_random_data (gint *cl_err) { - cl_mem cl_random_data; - gegl_random_init (); + cl_mem cl_random_data; + guint32 *random_data; + + random_data = gegl_random_get_data (); cl_random_data = gegl_clCreateBuffer (gegl_cl_get_context (), CL_MEM_USE_HOST_PTR | CL_MEM_READ_ONLY, - RANDOM_DATA_SIZE * sizeof (gint32), - (void*) &gegl_random_data, + RANDOM_DATA_SIZE * sizeof (guint32), + (void*) random_data, cl_err); return cl_random_data; } -cl_mem -gegl_cl_load_random_primes (gint *cl_err) +void +gegl_cl_random_get_ushort4 (const GeglRandom *in_rand, + cl_ushort4 *out_rand) { - cl_mem cl_random_primes; - cl_random_primes = gegl_clCreateBuffer (gegl_cl_get_context (), - CL_MEM_USE_HOST_PTR | CL_MEM_READ_ONLY, - PRIMES_SIZE * sizeof (long), - (void*) &gegl_random_primes, - cl_err); - return cl_random_primes; + out_rand->x = in_rand->prime0; + out_rand->y = in_rand->prime1; + out_rand->z = in_rand->prime2; + out_rand->w = 0; } - diff --git a/gegl/opencl/gegl-cl-random.h b/gegl/opencl/gegl-cl-random.h index 186827d6..33b7bdae 100644 --- a/gegl/opencl/gegl-cl-random.h +++ b/gegl/opencl/gegl-cl-random.h @@ -20,10 +20,11 @@ #define __GEGL_CL_RANDOM_H__ #include "gegl-cl-types.h" +#include "gegl-types.h" /** Load the random data needed to generate random numbers in the GPU*/ cl_mem gegl_cl_load_random_data (int *cl_err); -/** Load the primes needed to generate random numbers in the GPU*/ -cl_mem gegl_cl_load_random_primes (int *cl_err); +void +gegl_cl_random_get_ushort4 (const GeglRandom *in_rand, cl_ushort4 *out_rand); #endif diff --git a/opencl/noise-hurl.cl b/opencl/noise-hurl.cl index 6cc04122..ccb44be2 100644 --- a/opencl/noise-hurl.cl +++ b/opencl/noise-hurl.cl @@ -16,16 +16,15 @@ * Copyright 2013 Carlos Zubieta <czubieta.dev@gmail.com> */ -__kernel void cl_noise_hurl(__global float4 *src, - __global const int *random_data, - __global const long *random_primes, - int x_offset, - int y_offset, - int roi_width, - int whole_region_width, - int seed, - float pct_random, - int offset) +__kernel void cl_noise_hurl(__global float4 *src, + __global const int *random_data, + int x_offset, + int y_offset, + int roi_width, + int whole_region_width, + GeglRandom rand, + float pct_random, + int offset) { int gid = get_global_id(0); int gidy = gid / roi_width; @@ -37,14 +36,14 @@ __kernel void cl_noise_hurl(__global float4 *src, float4 src_v = src[gid]; - float pc = gegl_cl_random_float_range (random_data, random_primes, - seed, x, y, 0, n, 0, 100); - float red_noise = gegl_cl_random_float (random_data, random_primes, - seed, x, y, 0, n+1); - float green_noise = gegl_cl_random_float (random_data, random_primes, - seed, x, y, 0, n+2); - float blue_noise = gegl_cl_random_float (random_data, random_primes, - seed, x, y, 0, n+3); + float pc = gegl_cl_random_float_range (random_data, + rand, x, y, 0, n, 0, 100); + float red_noise = gegl_cl_random_float (random_data, + rand, x, y, 0, n+1); + float green_noise = gegl_cl_random_float (random_data, + rand, x, y, 0, n+2); + float blue_noise = gegl_cl_random_float (random_data, + rand, x, y, 0, n+3); if(pc <= pct_random) { diff --git a/opencl/noise-hurl.cl.h b/opencl/noise-hurl.cl.h index 9cc9f78a..b57b32bc 100644 --- a/opencl/noise-hurl.cl.h +++ b/opencl/noise-hurl.cl.h @@ -17,16 +17,15 @@ static const char* noise_hurl_cl_source = " * Copyright 2013 Carlos Zubieta <czubieta.dev@gmail.com> \n" " */ \n" " \n" -"__kernel void cl_noise_hurl(__global float4 *src, \n" -" __global const int *random_data, \n" -" __global const long *random_primes, \n" -" int x_offset, \n" -" int y_offset, \n" -" int roi_width, \n" -" int whole_region_width, \n" -" int seed, \n" -" float pct_random, \n" -" int offset) \n" +"__kernel void cl_noise_hurl(__global float4 *src, \n" +" __global const int *random_data, \n" +" int x_offset, \n" +" int y_offset, \n" +" int roi_width, \n" +" int whole_region_width, \n" +" GeglRandom rand, \n" +" float pct_random, \n" +" int offset) \n" "{ \n" " int gid = get_global_id(0); \n" " int gidy = gid / roi_width; \n" @@ -38,14 +37,14 @@ static const char* noise_hurl_cl_source = " \n" " float4 src_v = src[gid]; \n" " \n" -" float pc = gegl_cl_random_float_range (random_data, random_primes, \n" -" seed, x, y, 0, n, 0, 100); \n" -" float red_noise = gegl_cl_random_float (random_data, random_primes, \n" -" seed, x, y, 0, n+1); \n" -" float green_noise = gegl_cl_random_float (random_data, random_primes, \n" -" seed, x, y, 0, n+2); \n" -" float blue_noise = gegl_cl_random_float (random_data, random_primes, \n" -" seed, x, y, 0, n+3); \n" +" float pc = gegl_cl_random_float_range (random_data, \n" +" rand, x, y, 0, n, 0, 100); \n" +" float red_noise = gegl_cl_random_float (random_data, \n" +" rand, x, y, 0, n+1); \n" +" float green_noise = gegl_cl_random_float (random_data, \n" +" rand, x, y, 0, n+2); \n" +" float blue_noise = gegl_cl_random_float (random_data, \n" +" rand, x, y, 0, n+3); \n" " \n" " if(pc <= pct_random) \n" " { \n" diff --git a/opencl/random.cl b/opencl/random.cl index e6e33405..b900b379 100644 --- a/opencl/random.cl +++ b/opencl/random.cl @@ -17,77 +17,85 @@ */ /* XXX: this file should be kept in sync with gegl-random. */ -#define XPRIME 103423 -#define YPRIME 101359 -#define NPRIME 101111 +__constant const long XPRIME = 103423; +__constant const long YPRIME = 101359; +__constant const long NPRIME = 101111; -#define RANDOM_DATA_SIZE (15083+15091+15101) -#define PRIME_SIZE 533u +#define RANDOM_DATA_SIZE (15101 * 3) -inline uint _gegl_cl_random_int (__global const int *cl_random_data, - __global const long *cl_random_primes, - int seed, int x, int y, int z, int n); +typedef ushort4 GeglRandom; -uint gegl_cl_random_int (__global const int *cl_random_data, - __global const long *cl_random_primes, - int seed, int x, int y, int z, int n); +unsigned int _gegl_cl_random_int (__global const int *cl_random_data, + const GeglRandom rand, + int x, + int y, + int z, + int n); + +unsigned int gegl_cl_random_int (__global const int *cl_random_data, + const GeglRandom rand, + int x, + int y, + int z, + int n); int gegl_cl_random_int_range (__global const int *cl_random_data, - __global const long *cl_random_primes, - int seed, int x, int y, int z, int n, - int min, int max); + const GeglRandom rand, + int x, + int y, + int z, + int n, + int min, + int max); float gegl_cl_random_float (__global const int *cl_random_data, - __global const long *cl_random_primes, - int seed, int x, int y, int z, int n); + const GeglRandom rand, + int x, + int y, + int z, + int n); float gegl_cl_random_float_range (__global const int *cl_random_data, - __global const long *cl_random_primes, - int seed, int x, int y, int z, int n, - float min, float max); + const GeglRandom rand, + int x, + int y, + int z, + int n, + float min, + float max); -inline uint +unsigned int _gegl_cl_random_int (__global const int *cl_random_data, - __global const long *cl_random_primes, - int seed, + const GeglRandom rand, int x, int y, int z, int n) { - unsigned long idx = x * XPRIME + - y * YPRIME * XPRIME + + unsigned long idx = x * XPRIME + + y * YPRIME * XPRIME + n * NPRIME * YPRIME * XPRIME; -#define ROUNDS 3 - /* 3 rounds gives a reasonably high cycle for */ - /* our synthesized larger random set. */ - unsigned long seed_idx = seed % (PRIME_SIZE - 1 - ROUNDS); - int prime0 = cl_random_primes[seed_idx], - prime1 = cl_random_primes[seed_idx+1], - prime2 = cl_random_primes[seed_idx+2]; - int r0 = cl_random_data[idx % prime0], - r1 = cl_random_data[prime0 + (idx % (prime1))], - r2 = cl_random_data[prime0 + prime1 + (idx % (prime2))]; + + int r0 = cl_random_data[idx % rand.x], + r1 = cl_random_data[rand.x + (idx % rand.y)], + r2 = cl_random_data[rand.x + rand.y + (idx % rand.z)]; return r0 ^ r1 ^ r2; } -uint -gegl_cl_random_int (__global const int *cl_random_data, - __global const long *cl_random_primes, - int seed, +unsigned int +gegl_cl_random_int (__global const int *cl_random_data, + const GeglRandom rand, int x, int y, int z, int n) { - return _gegl_cl_random_int (cl_random_data, cl_random_primes, - seed, x, y, z, n); + return _gegl_cl_random_int (cl_random_data, rand, x, y, z, n); } int gegl_cl_random_int_range (__global const int *cl_random_data, - __global const long *cl_random_primes, - int seed, + const GeglRandom rand, int x, int y, int z, @@ -95,8 +103,7 @@ gegl_cl_random_int_range (__global const int *cl_random_data, int min, int max) { - uint ret = _gegl_cl_random_int (cl_random_data, cl_random_primes, - seed, x, y, z, n); + int ret = _gegl_cl_random_int (cl_random_data, rand, x, y, z, n); return (ret % (max-min)) + min; } @@ -104,23 +111,20 @@ gegl_cl_random_int_range (__global const int *cl_random_data, #define G_RAND_FLOAT_TRANSFORM 0.00001525902189669642175f float -gegl_cl_random_float (__global const int *cl_random_data, - __global const long *cl_random_primes, - int seed, +gegl_cl_random_float (__global const int *cl_random_data, + const GeglRandom rand, int x, int y, int z, int n) { - uint u = _gegl_cl_random_int (cl_random_data, cl_random_primes, - seed, x, y, z, n); + int u = _gegl_cl_random_int (cl_random_data, rand, x, y, z, n); return (u & 0xffff) * G_RAND_FLOAT_TRANSFORM; } float -gegl_cl_random_float_range (__global const int *cl_random_data, - __global const long *cl_random_primes, - int seed, +gegl_cl_random_float_range (__global const int *cl_random_data, + const GeglRandom rand, int x, int y, int z, @@ -128,7 +132,6 @@ gegl_cl_random_float_range (__global const int *cl_random_data, float min, float max) { - float f = gegl_cl_random_float (cl_random_data, cl_random_primes, - seed, x, y, z, n); + float f = gegl_cl_random_float (cl_random_data, rand, x, y, z, n); return f * (max - min) + min; } diff --git a/opencl/random.cl.h b/opencl/random.cl.h index 6b789514..d48e087e 100644 --- a/opencl/random.cl.h +++ b/opencl/random.cl.h @@ -18,39 +18,56 @@ static const char* random_cl_source = " */ \n" " \n" "/* XXX: this file should be kept in sync with gegl-random. */ \n" -"#define XPRIME 103423 \n" -"#define YPRIME 101359 \n" -"#define NPRIME 101111 \n" +"__constant const long XPRIME = 103423; \n" +"__constant const long YPRIME = 101359; \n" +"__constant const long NPRIME = 101111; \n" " \n" -"#define RANDOM_DATA_SIZE (15083+15091+15101) \n" -"#define PRIME_SIZE 533u \n" +"#define RANDOM_DATA_SIZE (15101 * 3) \n" " \n" -"inline uint _gegl_cl_random_int (__global const int *cl_random_data, \n" -" __global const long *cl_random_primes, \n" -" int seed, int x, int y, int z, int n); \n" +"typedef ushort4 GeglRandom; \n" " \n" -"uint gegl_cl_random_int (__global const int *cl_random_data, \n" -" __global const long *cl_random_primes, \n" -" int seed, int x, int y, int z, int n); \n" +"unsigned int _gegl_cl_random_int (__global const int *cl_random_data, \n" +" const GeglRandom rand, \n" +" int x, \n" +" int y, \n" +" int z, \n" +" int n); \n" +" \n" +"unsigned int gegl_cl_random_int (__global const int *cl_random_data, \n" +" const GeglRandom rand, \n" +" int x, \n" +" int y, \n" +" int z, \n" +" int n); \n" " \n" "int gegl_cl_random_int_range (__global const int *cl_random_data, \n" -" __global const long *cl_random_primes, \n" -" int seed, int x, int y, int z, int n, \n" -" int min, int max); \n" +" const GeglRandom rand, \n" +" int x, \n" +" int y, \n" +" int z, \n" +" int n, \n" +" int min, \n" +" int max); \n" " \n" "float gegl_cl_random_float (__global const int *cl_random_data, \n" -" __global const long *cl_random_primes, \n" -" int seed, int x, int y, int z, int n); \n" +" const GeglRandom rand, \n" +" int x, \n" +" int y, \n" +" int z, \n" +" int n); \n" " \n" "float gegl_cl_random_float_range (__global const int *cl_random_data, \n" -" __global const long *cl_random_primes, \n" -" int seed, int x, int y, int z, int n, \n" -" float min, float max); \n" +" const GeglRandom rand, \n" +" int x, \n" +" int y, \n" +" int z, \n" +" int n, \n" +" float min, \n" +" float max); \n" " \n" -"inline uint \n" +"unsigned int \n" "_gegl_cl_random_int (__global const int *cl_random_data, \n" -" __global const long *cl_random_primes, \n" -" int seed, \n" +" const GeglRandom rand, \n" " int x, \n" " int y, \n" " int z, \n" @@ -59,36 +76,27 @@ static const char* random_cl_source = " unsigned long idx = x * XPRIME + \n" " y * YPRIME * XPRIME + \n" " n * NPRIME * YPRIME * XPRIME; \n" -"#define ROUNDS 3 \n" -" /* 3 rounds gives a reasonably high cycle for */ \n" -" /* our synthesized larger random set. */ \n" -" unsigned long seed_idx = seed % (PRIME_SIZE - 1 - ROUNDS); \n" -" int prime0 = cl_random_primes[seed_idx], \n" -" prime1 = cl_random_primes[seed_idx+1], \n" -" prime2 = cl_random_primes[seed_idx+2]; \n" -" int r0 = cl_random_data[idx % prime0], \n" -" r1 = cl_random_data[prime0 + (idx % (prime1))], \n" -" r2 = cl_random_data[prime0 + prime1 + (idx % (prime2))]; \n" +" \n" +" int r0 = cl_random_data[idx % rand.x], \n" +" r1 = cl_random_data[rand.x + (idx % rand.y)], \n" +" r2 = cl_random_data[rand.x + rand.y + (idx % rand.z)]; \n" " return r0 ^ r1 ^ r2; \n" "} \n" " \n" -"uint \n" -"gegl_cl_random_int (__global const int *cl_random_data, \n" -" __global const long *cl_random_primes, \n" -" int seed, \n" +"unsigned int \n" +"gegl_cl_random_int (__global const int *cl_random_data, \n" +" const GeglRandom rand, \n" " int x, \n" " int y, \n" " int z, \n" " int n) \n" "{ \n" -" return _gegl_cl_random_int (cl_random_data, cl_random_primes, \n" -" seed, x, y, z, n); \n" +" return _gegl_cl_random_int (cl_random_data, rand, x, y, z, n); \n" "} \n" " \n" "int \n" "gegl_cl_random_int_range (__global const int *cl_random_data, \n" -" __global const long *cl_random_primes, \n" -" int seed, \n" +" const GeglRandom rand, \n" " int x, \n" " int y, \n" " int z, \n" @@ -96,8 +104,7 @@ static const char* random_cl_source = " int min, \n" " int max) \n" "{ \n" -" uint ret = _gegl_cl_random_int (cl_random_data, cl_random_primes, \n" -" seed, x, y, z, n); \n" +" int ret = _gegl_cl_random_int (cl_random_data, rand, x, y, z, n); \n" " return (ret % (max-min)) + min; \n" "} \n" " \n" @@ -105,23 +112,20 @@ static const char* random_cl_source = "#define G_RAND_FLOAT_TRANSFORM 0.00001525902189669642175f \n" " \n" "float \n" -"gegl_cl_random_float (__global const int *cl_random_data, \n" -" __global const long *cl_random_primes, \n" -" int seed, \n" +"gegl_cl_random_float (__global const int *cl_random_data, \n" +" const GeglRandom rand, \n" " int x, \n" " int y, \n" " int z, \n" " int n) \n" "{ \n" -" uint u = _gegl_cl_random_int (cl_random_data, cl_random_primes, \n" -" seed, x, y, z, n); \n" +" int u = _gegl_cl_random_int (cl_random_data, rand, x, y, z, n); \n" " return (u & 0xffff) * G_RAND_FLOAT_TRANSFORM; \n" "} \n" " \n" "float \n" -"gegl_cl_random_float_range (__global const int *cl_random_data, \n" -" __global const long *cl_random_primes, \n" -" int seed, \n" +"gegl_cl_random_float_range (__global const int *cl_random_data, \n" +" const GeglRandom rand, \n" " int x, \n" " int y, \n" " int z, \n" @@ -129,8 +133,7 @@ static const char* random_cl_source = " float min, \n" " float max) \n" "{ \n" -" float f = gegl_cl_random_float (cl_random_data, cl_random_primes, \n" -" seed, x, y, z, n); \n" +" float f = gegl_cl_random_float (cl_random_data, rand, x, y, z, n); \n" " return f * (max - min) + min; \n" "} \n" ; diff --git a/operations/common/cubism.c b/operations/common/cubism.c index 68149070..e6c9a46d 100644 --- a/operations/common/cubism.c +++ b/operations/common/cubism.c @@ -39,7 +39,7 @@ gegl_chant_color (bg_color, _("Background Color"), "rgba(0.0, 0.0, 0.0, 0.0)", _("The tiles' background color")) -gegl_chant_seed (seed, _("Seed"), +gegl_chant_seed (seed, rand, _("Seed"), _("Random seed")) #else diff --git a/operations/common/mosaic.c b/operations/common/mosaic.c index 5c345804..6205f947 100644 --- a/operations/common/mosaic.c +++ b/operations/common/mosaic.c @@ -70,7 +70,7 @@ gegl_chant_color (light_color, _("Light color"), "white", _("Light color")) gegl_chant_double (light_dir, _("Light direction"), 0.0, 360.0, 135, _("Direction of light-source (in degrees)")) -gegl_chant_seed (seed, _("Random seed"), _("Random seed")) +gegl_chant_seed (seed, rand, _("Random seed"), _("Random seed")) gegl_chant_boolean (antialiasing, _("Antialiasing"), TRUE, _("Enables smoother tile output")) @@ -310,12 +310,12 @@ static gboolean polygon_extents (Polygon *poly, gdouble *max_x, gdouble *max_y); static void polygon_reset (Polygon *poly); -static gfloat rand_f (gint seed, +static gfloat rand_f (GeglRandom *rand, gfloat pos_x, gfloat pos_y, gfloat min, gfloat max); -static gint rand_i (gint seed, +static gint rand_i (GeglRandom *rand, gfloat pos_x, gfloat pos_y, gint min, @@ -331,24 +331,24 @@ static gfloat distance (SpecVec *vec, #define SQR(v) ((v)*(v)) static gfloat -rand_f (gint seed, - gfloat pos_x, - gfloat pos_y, - gfloat min, - gfloat max) +rand_f (GeglRandom *rand, + gfloat pos_x, + gfloat pos_y, + gfloat min, + gfloat max) { - return gegl_random_float_range (seed, ROUND (pos_x), ROUND (pos_y), + return gegl_random_float_range (rand, ROUND (pos_x), ROUND (pos_y), 0, 0, min, max); } static gint -rand_i (gint seed, - gfloat pos_x, - gfloat pos_y, - gint min, - gint max) +rand_i (GeglRandom *rand, + gfloat pos_x, + gfloat pos_y, + gint min, + gint max) { - return gegl_random_int_range (seed, ROUND (pos_x), ROUND (pos_y), + return gegl_random_int_range (rand, ROUND (pos_x), ROUND (pos_y), 0, 0, min, max); } @@ -1042,10 +1042,10 @@ grid_localize (const GeglRectangle *result, if (rand_localize > EPSILON) { /* Rely on global values to make gegl's tiles seamless */ - max_x = pt->x + (gint) rand_f (o->seed, + max_x = pt->x + (gint) rand_f (o->rand, result->x + pt->x, result->y + pt->y, - rand_localize / 2.0, rand_localize / 2.0); - max_y = pt->y + (gint) rand_f (o->seed, + max_y = pt->y + (gint) rand_f (o->rand, result->y + pt->y, result->x + pt->x, /*sic*/ - rand_localize / 2.0, rand_localize / 2.0); } @@ -1357,12 +1357,12 @@ process_poly (Polygon *poly, size = (mdatas->width * mdatas->height); frac_size = size * o->color_variation; - vary = rand_i (o->seed, result->x + cx, result->y + cy, 0, size) < frac_size; + vary = rand_i (o->rand, result->x + cx, result->y + cy, 0, size) < frac_size; /* determine the variation of tile color based on tile number */ if (vary) { - color_vary = rand_f (o->seed, result->x + cx, result->y + cy, + color_vary = rand_f (o->rand, result->x + cx, result->y + cy, - o->color_variation * 0.5, o->color_variation * 0.5); } diff --git a/operations/common/noise-cie-lch.c b/operations/common/noise-cie-lch.c index 48746535..1b98bf3a 100644 --- a/operations/common/noise-cie-lch.c +++ b/operations/common/noise-cie-lch.c @@ -38,6 +38,9 @@ gegl_chant_double (hue_distance, _("Hue"), 0.0, 180.0, 3.0, _("Hue")) +gegl_chant_seed (seed, rand, _("Seed"), + _("Random seed")) + #else #define GEGL_CHANT_TYPE_POINT_FILTER @@ -49,33 +52,32 @@ gegl_chant_double (hue_distance, _("Hue"), #include <math.h> #include <stdlib.h> -#define SEED 1913 - static gfloat -randomize_value (gfloat now, - gfloat min, - gfloat max, - gboolean wraps_around, - gfloat rand_max, - gint holdness, - gint x, - gint y, - gint n) +randomize_value (gfloat now, + gfloat min, + gfloat max, + gboolean wraps_around, + gfloat rand_max, + gint holdness, + gint x, + gint y, + gint n, + GeglRandom *rand) { gint flag, i; gfloat rand_val, new_val, steps; steps = max - min + 0.5; - rand_val = gegl_random_float (SEED, x, y, 0, n++); + rand_val = gegl_random_float (rand, x, y, 0, n++); for (i = 1; i < holdness; i++) { - float tmp = gegl_random_float (SEED, x, y, 0, n++); + float tmp = gegl_random_float (rand, x, y, 0, n++); if (tmp < rand_val) rand_val = tmp; } - flag = (gegl_random_float (SEED, x, y, 0, n) < 0.5) ? -1 : 1; + flag = (gegl_random_float (rand, x, y, 0, n) < 0.5) ? -1 : 1; new_val = now + flag * fmod (rand_max * rand_val, steps); if (new_val < min) @@ -142,20 +144,21 @@ process (GeglOperation *operation, if ((o->hue_distance > 0) && (chroma > 0)) hue = randomize_value (hue, 0.0, 359.0, TRUE, o->hue_distance, - o->holdness, x, y, n); + o->holdness, x, y, n, o->rand); n += o->holdness + 1; if (o->chroma_distance > 0) { if (chroma == 0) - hue = gegl_random_float_range (SEED, x, y, 0, n, 0.0, 360.0); + hue = gegl_random_float_range (o->rand, x, y, 0, n, 0.0, 360.0); chroma = randomize_value (chroma, 0.0, 100.0, FALSE, o->chroma_distance, - o->holdness, x, y, n+1); + o->holdness, x, y, n+1, o->rand); } n += o->holdness + 2; if (o->lightness_distance > 0) lightness = randomize_value (lightness, 0.0, 100.0, FALSE, - o->lightness_distance, o->holdness, x, y, n); + o->lightness_distance, o->holdness, + x, y, n, o->rand); /*n += o->holdness + 1*/ out_pixel[0] = lightness; diff --git a/operations/common/noise-hsv.c b/operations/common/noise-hsv.c index 90bbd5a2..9d358b68 100644 --- a/operations/common/noise-hsv.c +++ b/operations/common/noise-hsv.c @@ -40,6 +40,9 @@ gegl_chant_double (value_distance, _("Value"), 0.0, 1.0, 0.04, _("Value")) +gegl_chant_seed (seed, rand, _("Seed"), + _("Random seed")) + #else #define GEGL_CHANT_TYPE_POINT_FILTER @@ -50,33 +53,32 @@ gegl_chant_double (value_distance, _("Value"), #include <math.h> #include <stdlib.h> -#define SEED 1913 - static gfloat -randomize_value (gfloat now, - gfloat min, - gfloat max, - gboolean wraps_around, - gfloat rand_max, - gint holdness, - gint x, - gint y, - gint n) +randomize_value (gfloat now, + gfloat min, + gfloat max, + gboolean wraps_around, + gfloat rand_max, + gint holdness, + gint x, + gint y, + gint n, + GeglRandom *rand) { gint flag, i; gfloat rand_val, new_val, steps; steps = max - min; - rand_val = gegl_random_float (SEED, x, y, 0, n++); + rand_val = gegl_random_float (rand, x, y, 0, n++); for (i = 1; i < holdness; i++) { - gfloat tmp = gegl_random_float (SEED, x, y, 0, n++); + gfloat tmp = gegl_random_float (rand, x, y, 0, n++); if (tmp < rand_val) rand_val = tmp; } - flag = (gegl_random_float (SEED, x, y, 0, n) < 0.5) ? -1 : 1; + flag = (gegl_random_float (rand, x, y, 0, n) < 0.5) ? -1 : 1; new_val = now + flag * fmod (rand_max * rand_val, steps); if (new_val < min) @@ -144,22 +146,22 @@ process (GeglOperation *operation, /* there is no need for scattering hue of desaturated pixels here */ if ((o->hue_distance > 0) && (saturation > 0)) hue = randomize_value (hue, 0.0, 1.0, TRUE, o->hue_distance / 360.0, - o->holdness, x, y, n); + o->holdness, x, y, n, o->rand); n += o->holdness + 1; /* desaturated pixels get random hue before increasing saturation */ if (o->saturation_distance > 0) { if (saturation == 0) - hue = gegl_random_float_range (SEED, x, y, 0, n, 0.0, 1.0); + hue = gegl_random_float_range (o->rand, x, y, 0, n, 0.0, 1.0); saturation = randomize_value (saturation, 0.0, 1.0, FALSE, o->saturation_distance, o->holdness, - x, y, n+1); + x, y, n+1, o->rand); } n += o->holdness + 2; if (o->value_distance > 0) value = randomize_value (value, 0.0, 1.0, FALSE, o->value_distance, - o->holdness, x, y, n); + o->holdness, x, y, n, o->rand); out_pixel[0] = hue; out_pixel[1] = saturation; diff --git a/operations/common/noise-hurl.c b/operations/common/noise-hurl.c index a8692dd7..9c9f560c 100644 --- a/operations/common/noise-hurl.c +++ b/operations/common/noise-hurl.c @@ -28,7 +28,7 @@ #ifdef GEGL_CHANT_PROPERTIES -gegl_chant_seed (seed, _("Seed"), +gegl_chant_seed (seed, rand, _("Seed"), _("Random seed")) gegl_chant_double (pct_random, _("Randomization (%)"), @@ -86,12 +86,12 @@ process (GeglOperation *operation, { gint n = 4 * (idx + cnt * total_size); - if (gegl_random_float_range (o->seed, x, y, 0, n, 0.0, 100.0) <= + if (gegl_random_float_range (o->rand, x, y, 0, n, 0.0, 100.0) <= o->pct_random) { - red = gegl_random_float (o->seed, x, y, 0, n+1); - green = gegl_random_float (o->seed, x, y, 0, n+2); - blue = gegl_random_float (o->seed, x, y, 0, n+3); + red = gegl_random_float (o->rand, x, y, 0, n+1); + green = gegl_random_float (o->rand, x, y, 0, n+2); + blue = gegl_random_float (o->rand, x, y, 0, n+3); break; } } @@ -124,18 +124,19 @@ cl_process (GeglOperation *operation, GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); GeglRectangle *wr = gegl_operation_source_get_bounding_box (operation, "input"); - cl_int cl_err = 0; - cl_mem cl_random_data = NULL; - cl_mem cl_random_primes = NULL; - cl_float pct_random = o->pct_random; - cl_int seed = o->seed; - cl_int x_offset = roi->x; - cl_int y_offset = roi->y; - cl_int roi_width = roi->width; - cl_int wr_width = wr->width; - int total_size = wr->width*wr->height; - cl_int offset; - int it; + cl_int cl_err = 0; + cl_mem cl_random_data = NULL; + cl_float pct_random = o->pct_random; + cl_int x_offset = roi->x; + cl_int y_offset = roi->y; + cl_int roi_width = roi->width; + cl_int wr_width = wr->width; + int total_size = wr->width*wr->height; + cl_int offset; + int it; + cl_ushort4 rand; + + gegl_cl_random_get_ushort4 (o->rand, &rand); if (!cl_data) { @@ -149,8 +150,6 @@ cl_process (GeglOperation *operation, { cl_random_data = gegl_cl_load_random_data (&cl_err); CL_CHECK; - cl_random_primes = gegl_cl_load_random_primes (&cl_err); - CL_CHECK; cl_err = gegl_clEnqueueCopyBuffer (gegl_cl_get_command_queue(), in , out , 0 , 0 , @@ -161,12 +160,11 @@ cl_process (GeglOperation *operation, gegl_cl_set_kernel_args (cl_data->kernel[0], sizeof(cl_mem), &out, sizeof(cl_mem), &cl_random_data, - sizeof(cl_mem), &cl_random_primes, sizeof(cl_int), &x_offset, sizeof(cl_int), &y_offset, sizeof(cl_int), &roi_width, sizeof(cl_int), &wr_width, - sizeof(cl_int), &seed, + sizeof(cl_ushort4), &rand, sizeof(cl_float), &pct_random, NULL); CL_CHECK; @@ -175,7 +173,7 @@ cl_process (GeglOperation *operation, for(it = 0; it < o->repeat; ++it) { - cl_err = gegl_clSetKernelArg (cl_data->kernel[0], 9, sizeof(cl_int), + cl_err = gegl_clSetKernelArg (cl_data->kernel[0], 8, sizeof(cl_int), (void*)&offset); CL_CHECK; cl_err = gegl_clEnqueueNDRangeKernel (gegl_cl_get_command_queue (), @@ -192,9 +190,6 @@ cl_process (GeglOperation *operation, cl_err = gegl_clReleaseMemObject (cl_random_data); CL_CHECK_ONLY (cl_err); - - cl_err = gegl_clReleaseMemObject (cl_random_primes); - CL_CHECK_ONLY (cl_err); } return FALSE; @@ -202,8 +197,6 @@ cl_process (GeglOperation *operation, error: if (cl_random_data) gegl_clReleaseMemObject (cl_random_data); - if (cl_random_primes) - gegl_clReleaseMemObject (cl_random_primes); return TRUE; } diff --git a/operations/common/noise-pick.c b/operations/common/noise-pick.c index 2cb85631..3c70d1ba 100644 --- a/operations/common/noise-pick.c +++ b/operations/common/noise-pick.c @@ -29,7 +29,7 @@ #ifdef GEGL_CHANT_PROPERTIES -gegl_chant_seed (seed, _("Seed"), +gegl_chant_seed (seed, rand, _("Seed"), _("Random seed")) gegl_chant_double (pct_random, _("Randomization (%)"), @@ -105,7 +105,7 @@ process (GeglOperation *operation, for (r = 0; r < o->repeat; r++) { - guint rand = gegl_random_int (o->seed, pos_x, pos_y, 0, r); + guint rand = gegl_random_int (o->rand, pos_x, pos_y, 0, r); gfloat pct = RAND_UINT_TO_FLOAT (rand) * 100.0; if (pct <= o->pct_random) diff --git a/operations/common/noise-rgb.c b/operations/common/noise-rgb.c index 1bd8c61e..1566be93 100644 --- a/operations/common/noise-rgb.c +++ b/operations/common/noise-rgb.c @@ -49,7 +49,7 @@ gegl_chant_double (alpha, _("Alpha"), 0.0, 1.0, 0.00, _("Alpha")) -gegl_chant_seed (seed, _("Seed"), +gegl_chant_seed (seed, rand, _("Seed"), _("Random seed")) #else @@ -71,16 +71,16 @@ gegl_chant_seed (seed, _("Seed"), * K+M, ACM Trans Math Software 3 (1977) 257-260. */ static gdouble -gauss (int seed, int *i, int xx, int yy) +gauss (GeglRandom *rand, int *i, int xx, int yy) { gdouble u, v, x; do { - v = gegl_random_float (seed, xx, yy, 0, (*i)++); + v = gegl_random_float (rand, xx, yy, 0, (*i)++); do - u = gegl_random_float (seed, xx, yy, 0, (*i)++); + u = gegl_random_float (rand, xx, yy, 0, (*i)++); while (u == 0); /* Const 1.715... = sqrt(8/e) */ @@ -133,7 +133,7 @@ process (GeglOperation *operation, for (b = 0; b < 4; b++) { if (b == 0 || o->independent || b == 3 ) - noise_coeff = noise[b] * gauss (o->seed, &rint, x, y) * 0.5; + noise_coeff = noise[b] * gauss (o->rand, &rint, x, y) * 0.5; if (noise[b] > 0.0) { diff --git a/operations/common/noise-slur.c b/operations/common/noise-slur.c index f9f4ad7a..4c73b7f4 100644 --- a/operations/common/noise-slur.c +++ b/operations/common/noise-slur.c @@ -31,7 +31,7 @@ #ifdef GEGL_CHANT_PROPERTIES -gegl_chant_seed (seed, _("Seed"), +gegl_chant_seed (seed, rand, _("Seed"), _("Random seed")) gegl_chant_double (pct_random, _("Randomization (%)"), @@ -106,7 +106,7 @@ process (GeglOperation *operation, for (r = 0; r < o->repeat; r++) { - guint rand = gegl_random_int (o->seed, pos_x, pos_y, 0, r); + guint rand = gegl_random_int (o->rand, pos_x, pos_y, 0, r); gfloat pct = RAND_UINT_TO_FLOAT (rand) * 100.0; if (pct <= o->pct_random) diff --git a/operations/common/noise-spread.c b/operations/common/noise-spread.c index 7f543c33..f4acb292 100644 --- a/operations/common/noise-spread.c +++ b/operations/common/noise-spread.c @@ -34,7 +34,7 @@ gegl_chant_int (amount_y, _("Vertical"), 0, 256, 5, _("Vertical spread amount")) -gegl_chant_seed (seed, _("Seed"), +gegl_chant_seed (seed, rand, _("Seed"), _("Random seed")) #else @@ -46,23 +46,23 @@ gegl_chant_seed (seed, _("Seed"), #include <math.h> static inline void -calc_sample_coords (gint src_x, - gint src_y, - gint amount_x, - gint amount_y, - gint seed, - gint *x, - gint *y) +calc_sample_coords (gint src_x, + gint src_y, + gint amount_x, + gint amount_y, + GeglRandom *rand, + gint *x, + gint *y) { gdouble angle; gint xdist, ydist; /* get random angle, x distance, and y distance */ - xdist = amount_x > 0 ? gegl_random_int_range (seed, src_x, src_y, 0, 0, + xdist = amount_x > 0 ? gegl_random_int_range (rand, src_x, src_y, 0, 0, -amount_x, amount_x + 1) : 0; - ydist = amount_y > 0 ? gegl_random_int_range (seed, src_x, src_y, 0, 1, + ydist = amount_y > 0 ? gegl_random_int_range (rand, src_x, src_y, 0, 1, -amount_y, amount_y + 1) : 0; - angle = gegl_random_float_range (seed, src_x, src_y, 0, 2, -G_PI, G_PI); + angle = gegl_random_float_range (rand, src_x, src_y, 0, 2, -G_PI, G_PI); *x = src_x + floor (sin (angle) * xdist); *y = src_y + floor (cos (angle) * ydist); @@ -123,7 +123,7 @@ process (GeglOperation *operation, { gint x, y; - calc_sample_coords (i, j, amount_x, amount_y, o->seed, &x, &y); + calc_sample_coords (i, j, amount_x, amount_y, o->rand, &x, &y); gegl_buffer_sample (input, x, y, NULL, data, format, GEGL_SAMPLER_NEAREST, GEGL_ABYSS_CLAMP); diff --git a/operations/common/plasma.c b/operations/common/plasma.c index 24d5f25a..028307d9 100644 --- a/operations/common/plasma.c +++ b/operations/common/plasma.c @@ -33,7 +33,7 @@ #ifdef GEGL_CHANT_PROPERTIES -gegl_chant_seed (seed, _("Random seed"), _("Random seed")) +gegl_chant_seed (seed, rand, _("Random seed"), _("Random seed")) gegl_chant_double (turbulence, _("Turbulence"), 0.0, 7.0, 1.0, _("The value of the turbulence")) diff --git a/operations/common/shift.c b/operations/common/shift.c index bea7baa4..86a53487 100644 --- a/operations/common/shift.c +++ b/operations/common/shift.c @@ -32,7 +32,7 @@ gegl_chant_int (shift, _("Shift"), 1, 200, 5, _("Maximum amount to shift")) -gegl_chant_seed (seed, _("Seed"), +gegl_chant_seed (seed, rand, _("Seed"), _("Random seed")) gegl_chant_enum (direction, _("Direction"), @@ -133,7 +133,7 @@ process (GeglOperation *operation, for (i = 0; i < array_size; i++) { - r = gegl_random_int_range (o->seed, i, 0, 0, 0, -s, s + 1); + r = gegl_random_int_range (o->rand, i, 0, 0, 0, -s, s + 1); g_array_append_val (offsets, r); } o->chant_data = offsets; diff --git a/operations/common/wind.c b/operations/common/wind.c index b10ef414..46a3c310 100644 --- a/operations/common/wind.c +++ b/operations/common/wind.c @@ -30,7 +30,7 @@ gegl_chant_double (threshold, _("Threshold"), 0.0, 100.0, 10.0, gegl_chant_int (strength, _("Strength"), 1, 1000, 40, _("Higher values increase the magnitude of the effect")) -gegl_chant_seed (seed, _("Seed"), _("Random seed")) +gegl_chant_seed (seed, rand, _("Seed"), _("Random seed")) #else |