[gegl] gegl-random: fix signedness overflow issue
- From: Ãyvind KolÃs <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] gegl-random: fix signedness overflow issue
- Date: Tue, 11 Dec 2012 12:42:41 +0000 (UTC)
commit a8af40c06f84c25a926aaf0f6c8caa16d8ee8f93
Author: Ãyvind KolÃs <pippin gimp org>
Date: Tue Dec 11 23:40:57 2012 +1100
gegl-random: fix signedness overflow issue
gegl/gegl-random.c | 46 ++++++++++++++++++++++++++++++++++++----------
1 files changed, 36 insertions(+), 10 deletions(-)
---
diff --git a/gegl/gegl-random.c b/gegl/gegl-random.c
index b2d0436..8c4e82b 100644
--- a/gegl/gegl-random.c
+++ b/gegl/gegl-random.c
@@ -17,6 +17,7 @@
*/
#include <glib.h>
+#include <gegl.h>
/* a set of reasonably large primes to choose from for array sizes
*/
@@ -47,18 +48,17 @@ static long primes[]={
#define XPRIME 103423
#define ZPRIME 101359
#define NPRIME 101111
-#define MAX_TABLES 4
+#define MAX_TABLES 3
typedef struct GeglRandomSet
{
- int last_use;
int seed;
int tables;
gint64 *table[MAX_TABLES];
long prime[MAX_TABLES];
} GeglRandomSet;
-#define make_index(x,y,n) ((x) * XPRIME + (z) * ZPRIME + (n) * NPRIME)
+#define make_index(x,y,n) ((x) * XPRIME + (z) * ZPRIME * XPRIME + (n) * NPRIME * ZPRIME * XPRIME)
static GeglRandomSet *gegl_random_set_new (int seed)
{
@@ -72,14 +72,14 @@ static GeglRandomSet *gegl_random_set_new (int seed)
for (i = 0; i < set->tables; i++)
{
int j;
- set->prime[i] = primes[g_rand_int_range (gr, 0, N_PRIMES-1)];
+ set->prime[i] = primes[g_rand_int_range (gr, 0, N_PRIMES-2)];
/*
* it might be possible to share a set of random data between sets
* and rejuggle the prime sizes chosen and keep an additional offset
* for feeding randomness.
*
*/
- set->table[i] = g_malloc0 (sizeof (guint64) * set->prime[i]);
+ set->table[i] = g_malloc0 (sizeof (gint64) * set->prime[i]);
for (j = 0; j < set->prime[i]; j++)
set->table[i][j] = (((gint64)g_rand_int (gr)) << 32) + g_rand_int(gr);
}
@@ -97,7 +97,18 @@ static void gegl_random_set_free (GeglRandomSet *set)
/* a better cache with more entries would be nice ;) */
static GeglRandomSet *cached = NULL;
-static long cachetime = 0;
+static GList *cache = NULL;
+
+static void trim_cache_to_length (int length)
+{
+ while (g_list_length (cache) > length)
+ {
+ GeglRandomSet *last = g_list_last (cache)->data;
+ cache = g_list_remove (cache, last);
+ gegl_random_set_free (last);
+ }
+}
+
static inline GeglRandomSet *gegl_random_get_set_for_seed (int seed)
{
if (cached && cached->seed == seed)
@@ -106,11 +117,26 @@ static inline GeglRandomSet *gegl_random_get_set_for_seed (int seed)
}
else
{
+ GList *l;
if (cached)
- gegl_random_set_free (cached);
+ {
+ cache = g_list_prepend (cache, cached);
+ cached = NULL;
+ trim_cache_to_length (10);
+ }
+
+ for (l = cache; l; l=l->next)
+ {
+ GeglRandomSet *s = l->data;
+ if (s->seed == seed)
+ {
+ cached = s;
+ cache = g_list_remove (cache, cached);
+ return cached;
+ }
+ }
cached = gegl_random_set_new (seed);
}
- cached->last_use = cachetime++;
return cached;
}
@@ -121,11 +147,11 @@ gegl_random_int (int seed, int x, int y, int z, int n)
/* XXX: z is unhandled, it should average like a mipmap - or even
* use mipmap versions of random set
*/
- long idx = make_index(x,y,n);
+ unsigned long idx = make_index(x,y,n);
gint64 ret = 0;
int i;
for (i = 0; i < set->tables; i++)
- ret ^= set->table[i][idx % set->prime[i]];
+ ret ^= set->table[i][idx % (set->prime[i])];
return ret;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]