[gegl] GeglLookup: Made the precision/dimensions configurable



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]