[gegl] Added general caching floating point lookup table code.



commit a7e87a3c0409ea32f933b55c0678606ad03fa322
Author: �yvind Kolås <pippin gimp org>
Date:   Thu Dec 3 12:21:50 2009 +0000

    Added general caching floating point lookup table code.

 examples/float-lookup.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++
 gegl/gegl-types.h       |    1 +
 gegl/gegl-utils.h       |   79 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 158 insertions(+), 0 deletions(-)
---
diff --git a/examples/float-lookup.c b/examples/float-lookup.c
new file mode 100644
index 0000000..e554ee3
--- /dev/null
+++ b/examples/float-lookup.c
@@ -0,0 +1,78 @@
+#include <gegl.h>
+#include <gegl/gegl-utils.h>
+#include <math.h>
+
+static gfloat wrapped_sqrt (gfloat   in,
+                            gpointer data) /* we could have used the user data */
+{
+  return sqrt (in);
+}
+
+static gfloat passthrough (gfloat in, gpointer data)
+{
+  return in;
+}
+
+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];
+}
+
+
+
+gint main (int argc, gchar **argv)
+{
+  gfloat val;
+  gfloat foo;
+  gdouble sum = 0;
+  gint    count=0;
+  GeglLookup *lookup;
+  gint ticks;
+  
+  lookup = gegl_lookup_new (wrapped_sqrt, NULL);
+  ticks = gegl_ticks ();
+  for (val = 0; val < 1.0; val+=0.0000001)
+    foo = gegl_lookup (lookup, val);
+  ticks = gegl_ticks ()-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);
+  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);
+  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);
+  }
+
+  return 0;
+}
diff --git a/gegl/gegl-types.h b/gegl/gegl-types.h
index f42e6ca..935baa5 100644
--- a/gegl/gegl-types.h
+++ b/gegl/gegl-types.h
@@ -64,6 +64,7 @@ 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 _GeglLookup  GeglLookup;
 
 G_END_DECLS
 
diff --git a/gegl/gegl-utils.h b/gegl/gegl-utils.h
index 886984d..eb3b435 100644
--- a/gegl/gegl-utils.h
+++ b/gegl/gegl-utils.h
@@ -203,6 +203,85 @@ gint        _gegl_float_epsilon_equal (float     v1,
                                        float     v2);
 
 
+typedef     gfloat (GeglLookupFunction) (float, gpointer data);
+
+GeglLookup *gegl_lookup_new  (GeglLookupFunction   *function,
+                              gpointer              data);
+void        gegl_lookup_free (GeglLookup           *lookup);
+
+#define INDEX_SHIFT  14 /* 
+                        Valid values here are:
+                        value  tablesize          average error 
+                          16    5108              0.001298
+                          15   10316              0.000649
+                          14   20432              0.000324
+                         */
+
+#if INDEX_SHIFT == 16
+
+#define INDEX_START_POSITIVE   13702
+#define INDEX_END_POSITIVE     16256
+#define INDEX_START_NEGATIVE   46470
+#define INDEX_END_NEGATIVE     49024
+
+#elif INDEX_SHIFT == 15
+
+#define INDEX_START_POSITIVE   27404
+#define INDEX_END_POSITIVE     32512
+#define INDEX_START_NEGATIVE   92940
+#define INDEX_END_NEGATIVE     98048
+
+#elif INDEX_SHIFT == 14
+
+#define INDEX_START_POSITIVE   54808
+#define INDEX_END_POSITIVE     65024
+#define INDEX_START_NEGATIVE   185880
+#define INDEX_END_NEGATIVE     196096
+
+#endif
+
+#define INDEX_SUM_POSITIVE    (INDEX_END_POSITIVE-INDEX_START_POSITIVE)
+#define INDEX_SUM_NEGATIVE    (INDEX_END_NEGATIVE-INDEX_START_NEGATIVE)
+#define INDEX_SUM             (INDEX_SUM_POSITIVE+INDEX_SUM_NEGATIVE)
+
+typedef struct _GeglLookup
+{
+  GeglLookupFunction *function;     /* the lookup function to execute */
+  gpointer            data;
+  guint32             bitmask[(INDEX_SUM+31)/32];
+  gfloat              table[INDEX_SUM];
+} _GeglLookup;
+
+static inline gfloat
+gegl_lookup (GeglLookup *lookup,
+             gfloat      number)
+{
+  union
+  {
+    float   f;
+    guint32 i;
+  } u;
+  guint index;
+
+  u.f = number;
+  index = u.i >> INDEX_SHIFT;
+  if (index > INDEX_START_POSITIVE && index < INDEX_END_POSITIVE)
+    index = index-INDEX_START_POSITIVE;
+  else if (index > INDEX_START_NEGATIVE && index < INDEX_END_NEGATIVE)
+    index = index-INDEX_START_NEGATIVE+INDEX_SUM_POSITIVE;
+  else
+    return lookup->function (number, lookup->data);
+
+  g_assert (index >= 0 && index < INDEX_SUM);
+
+  if (!(lookup->bitmask[index/32] & (1<<(index & 31))))
+    {
+      lookup->table[index]= lookup->function (number, lookup->data);
+      lookup->bitmask[index/32] |= (1<<(index & 31));
+    } 
+  return lookup->table[index];
+}
+
 G_END_DECLS
 
 #endif /* __GEGL_UTILS_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]