[gegl] GeglLookup: Made the precision/dimensions configurable
- From: Øyvind Kolås <ok src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gegl] GeglLookup: Made the precision/dimensions configurable
- Date: Fri, 4 Dec 2009 11:11:11 +0000 (UTC)
commit 432e13b696ef6086904973ee86ee7a60d8ea39b1
Author: �yvind Kolås <pippin gimp org>
Date: Fri Dec 4 00:29:23 2009 +0000
GeglLookup: Made the precision/dimensions configurable
examples/float-lookup.c | 60 +++++++++-------------
gegl/gegl-lookup.c | 128 +++++++++++++++++++++++++++++++++++++++++++++--
gegl/gegl-lookup.h | 75 ++++++++--------------------
3 files changed, 169 insertions(+), 94 deletions(-)
---
diff --git a/examples/float-lookup.c b/examples/float-lookup.c
index 9a4a8bc..bdfc01b 100644
--- a/examples/float-lookup.c
+++ b/examples/float-lookup.c
@@ -15,64 +15,54 @@ static gfloat passthrough (gfloat in, gpointer data)
glong gegl_ticks (void);
-static inline int gegl_float_16_indext (float f)
-{
- union
- {
- float f;
- unsigned int i;
- unsigned short s[2];
- } u;
- u.f = f;
- return u.s[1];
-}
-
-
+#define ITERATIONS 10
+#define SAMPLES 10000000
gint main (int argc, gchar **argv)
{
+ gint i,j = 0;
gfloat val;
gfloat foo;
gdouble sum = 0;
gint count=0;
GeglLookup *lookup;
gint ticks;
+ gfloat *rand = g_malloc (SAMPLES * sizeof (gfloat));
+ for (i=0;i<SAMPLES;i++)
+ {
+ rand[i]=g_random_double ();
+ }
+
lookup = gegl_lookup_new (wrapped_sqrt, NULL);
ticks = gegl_ticks ();
- for (val = 0; val < 1.0; val+=0.0000001)
- foo = gegl_lookup (lookup, val);
+ for (i=0;i<ITERATIONS;i++)
+ for (j=0;j<SAMPLES;j++)
+ foo = gegl_lookup (lookup, rand[j]);
ticks = gegl_ticks ()-ticks;
- g_print ("First run: %i\n", ticks);
+ g_print ("First run: %i\n", ticks);
ticks = gegl_ticks ();
- for (val = 0; val < 1.0; val+=0.0000001)
- foo = gegl_lookup (lookup, val);
+ for (i=0;i<ITERATIONS;i++)
+ for (j=0;j<SAMPLES;j++)
+ foo = gegl_lookup (lookup, rand[j]);
ticks = gegl_ticks ()-ticks;
g_print ("Second run: %i\n", ticks);
ticks = gegl_ticks ();
- for (val = 0; val < 1.0; val+=0.0000001)
- foo = gegl_lookup (lookup, val);
- ticks = gegl_ticks ()-ticks;
- g_print ("Third run: %i\n", ticks);
-
-
- ticks = gegl_ticks ();
- for (val = 0; val < 1.0; val+=0.0000001)
- foo = sqrt (val);
+ for (i=0;i<ITERATIONS;i++)
+ for (j=0;j<SAMPLES;j++)
+ foo = sqrt (rand[j]);
ticks = gegl_ticks ()-ticks;
g_print ("Just sqrt: %i\n", ticks);
gegl_lookup_free (lookup);
- {
- /* stack allocated */
- GeglLookup lookup = {passthrough, NULL, };
- for (val = 0.0, sum=0.0, count=0; val < 1.0; val+=0.000001, count++)
- sum += fabs (val-gegl_lookup (&lookup, val));
- g_printf ("Average error in range 0.0-1.0: %f\n", sum/count);
- foo = sqrt (val);
- }
+ lookup = gegl_lookup_new (passthrough, NULL);
+ for (val = 0.0, sum=0.0, count=0; val < 1.0; val+=0.000001, count++)
+ sum += fabs (val-gegl_lookup (lookup, val));
+ g_printf ("Average error in range 0.0-1.0: %f\n", sum/count);
+ foo = sqrt (val);
+ gegl_lookup_free (lookup);
return 0;
}
diff --git a/gegl/gegl-lookup.c b/gegl/gegl-lookup.c
index b11694f..5122f66 100644
--- a/gegl/gegl-lookup.c
+++ b/gegl/gegl-lookup.c
@@ -23,18 +23,136 @@
#include "gegl.h"
#include "gegl-lookup.h"
-GeglLookup *
-gegl_lookup_new (GeglLookupFunction *function,
- gpointer data)
+GeglLookup *gegl_lookup_new_full (GeglLookupFunction *function,
+ gpointer data,
+ gfloat start,
+ gfloat end,
+ gfloat precision)
{
- GeglLookup *lookup = g_slice_new0 (GeglLookup);
+ GeglLookup *lookup;
+ union
+ {
+ float f;
+ guint32 i;
+ } u;
+ gint positive_min, positive_max, negative_min, negative_max;
+ gint shift;
+
+ /* normalize input parameters */
+ if (start > end)
+ { /* swap */
+ u.f = start;
+ start = end;
+ end = u.f;
+ }
+
+ if (precision <= 0.000005) shift = 0; /* checked for later */
+ else if (precision <= 0.000010) shift = 8;
+ else if (precision <= 0.000020) shift = 9;
+ else if (precision <= 0.000040) shift = 10;
+ else if (precision <= 0.000081) shift = 11;
+ else if (precision <= 0.000161) shift = 12;
+ else if (precision <= 0.000324) shift = 14;
+ else if (precision <= 0.000649) shift = 15;
+ else shift = 16; /* a bit better than 8bit sRGB quality */
+
+ /* Adjust slightly away from 0.0, saving many entries close to 0, this
+ * causes lookups very close to zero to be passed directly to the
+ * function instead.
+ */
+ if (start == 0.0)
+ start = precision;
+ if (end == 0.0)
+ end = -precision;
+
+ /* Compute start and */
+
+ if (start < 0.0 || end < 0.0)
+ {
+ if (end < 0.0)
+ {
+ u.f = start;
+ positive_max = u.i >> shift;
+ u.f = end;
+ positive_min = u.i >> shift;
+ negative_min = positive_max;
+ negative_max = positive_max;
+ }
+ else
+ {
+ u.f = 0 - precision;
+ positive_min = u.i >> shift;
+ u.f = start;
+ positive_max = u.i >> shift;
+
+ u.f = 0 + precision;
+ negative_min = u.i >> shift;
+ u.f = end;
+ negative_max = u.i >> shift;
+ }
+ }
+ else
+ {
+ u.f = start;
+ positive_min = u.i >> shift;
+ u.f = end;
+ positive_max = u.i >> shift;
+ negative_min = positive_max;
+ negative_max = positive_max;
+ }
+
+ if (shift == 0) /* short circuit, do not use ranges */
+ {
+ positive_min = positive_max = negative_min = negative_max = 0;
+ }
+
+ if ((positive_max-positive_min)+ (negative_max-negative_min) > GEGL_LOOKUP_MAX_ENTRIES)
+ {
+ /* Reduce the size of the cache tables to fit within the bittable
+ * budget (the maximum allocation is around 2.18mb of memory
+ */
+
+ gint diff = (positive_max-positive_min)+ (negative_max-negative_min) - GEGL_LOOKUP_MAX_ENTRIES;
+
+ if (negative_max - negative_min > 0)
+ {
+ if (negative_max - negative_min >= diff)
+ {
+ negative_max -= diff;
+ diff = 0;
+ }
+ else
+ {
+ diff -= negative_max - negative_min;
+ negative_max = negative_min;
+ }
+ }
+ if (diff)
+ positive_max-=diff;
+ }
+
+ lookup = g_malloc0 (sizeof (GeglLookup) + sizeof (gfloat) *
+ ((positive_max-positive_min)+
+ (negative_max-negative_min)));
+
+ lookup->positive_min = positive_min;
+ lookup->positive_max = positive_max;
+ lookup->negative_min = negative_min;
+ lookup->negative_max = negative_max;
+ lookup->shift = shift;
lookup->function = function;
lookup->data = data;
return lookup;
}
+GeglLookup *gegl_lookup_new (GeglLookupFunction *function,
+ gpointer data)
+{
+ return gegl_lookup_new_full (function, data, 0, 1.0, 0.000010);
+}
+
void
gegl_lookup_free (GeglLookup *lookup)
{
- g_slice_free (GeglLookup, lookup);
+ g_free (lookup);
}
diff --git a/gegl/gegl-lookup.h b/gegl/gegl-lookup.h
index 96fbf3c..5d18525 100644
--- a/gegl/gegl-lookup.h
+++ b/gegl/gegl-lookup.h
@@ -21,65 +21,31 @@
G_BEGIN_DECLS
-/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- * NOTE! tweaking these values will change ABI for operations using GeglLookup
- */
-#define GEGL_LOOKUP_NEGATIVE 0 /* set to 1 to also cache range -1.0..-0.0 */
-#define GEGL_LOOKUP_SHIFT_RIGHT 14 /* Number of bits to shift integer right
- before computing lookup bits
-
- value tablesize average error
- 16 2554 0.001298
- 15 5108 0.000649
- 14 10216 0.000324
- */
-
-#if GEGL_LOOKUP_SHIFT_RIGHT == 16
-
-#define GEGL_LOOKUP_START_POSITIVE 13702
-#define GEGL_LOOKUP_END_POSITIVE 16256
-#define GEGL_LOOKUP_START_NEGATIVE 46470
-#define GEGL_LOOKUP_END_NEGATIVE 49024
-
-#elif GEGL_LOOKUP_SHIFT_RIGHT == 15
-
-#define GEGL_LOOKUP_START_POSITIVE 27404
-#define GEGL_LOOKUP_END_POSITIVE 32512
-#define GEGL_LOOKUP_START_NEGATIVE 92940
-#define GEGL_LOOKUP_END_NEGATIVE 98048
-
-#elif GEGL_LOOKUP_SHIFT_RIGHT == 14
-
-#define GEGL_LOOKUP_START_POSITIVE 54808
-#define GEGL_LOOKUP_END_POSITIVE 65024
-#define GEGL_LOOKUP_START_NEGATIVE 185880
-#define GEGL_LOOKUP_END_NEGATIVE 196096
-
-#endif
-
-#define GEGL_LOOKUP_SUM_POSITIVE (GEGL_LOOKUP_END_POSITIVE-GEGL_LOOKUP_START_POSITIVE)
-#define GEGL_LOOKUP_SUM_NEGATIVE (GEGL_LOOKUP_END_NEGATIVE-GEGL_LOOKUP_START_NEGATIVE)
-
-#if GEGL_LOOKUP_NEGATIVE
-#define GEGL_LOOKUP_SUM (GEGL_LOOKUP_SUM_POSITIVE+GEGL_LOOKUP_SUM_NEGATIVE)
-#else
-#define GEGL_LOOKUP_SUM (GEGL_LOOKUP_SUM_NEGATIVE)
-#endif
-
typedef gfloat (GeglLookupFunction) (float, gpointer data);
+#define GEGL_LOOKUP_MAX_ENTRIES (819200)
+
typedef struct GeglLookup
{
GeglLookupFunction *function;
gpointer data;
- guint32 bitmask[(GEGL_LOOKUP_SUM+31)/32];
- gfloat table[GEGL_LOOKUP_SUM];
+ gint shift;
+ guint32 positive_min, positive_max, negative_min, negative_max;
+ guint32 bitmask[GEGL_LOOKUP_MAX_ENTRIES/32];
+ gfloat table[];
} GeglLookup;
+
+GeglLookup *gegl_lookup_new_full (GeglLookupFunction *function,
+ gpointer data,
+ gfloat start,
+ gfloat end,
+ gfloat precision);
GeglLookup *gegl_lookup_new (GeglLookupFunction *function,
gpointer data);
void gegl_lookup_free (GeglLookup *lookup);
+
static inline gfloat
gegl_lookup (GeglLookup *lookup,
gfloat number)
@@ -92,13 +58,14 @@ gegl_lookup (GeglLookup *lookup,
guint index;
u.f = number;
- index = u.i >> GEGL_LOOKUP_SHIFT_RIGHT;
- if (index > GEGL_LOOKUP_START_POSITIVE && index < GEGL_LOOKUP_END_POSITIVE)
- index = index-GEGL_LOOKUP_START_POSITIVE;
-#if GEGL_LOOKUP_NEGATIVE
- else if (index > GEGL_LOOKUP_START_NEGATIVE && index < GEGL_LOOKUP_END_NEGATIVE)
- index = index-GEGL_LOOKUP_START_NEGATIVE+GEGL_LOOKUP_SUM_POSITIVE;
-#endif
+ index = u.i >> lookup->shift;
+
+ if (index > lookup->positive_min &&
+ index < lookup->positive_max)
+ index = index - lookup->positive_min;
+ else if (index > lookup->negative_min &&
+ index < lookup->negative_max)
+ index = index - lookup->negative_min + (lookup->positive_max - lookup->positive_min);
else
return lookup->function (number, lookup->data);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]