gnumeric r16495 - in trunk: . plugins/fn-lookup src



Author: mortenw
Date: Wed Apr  9 00:48:18 2008
New Revision: 16495
URL: http://svn.gnome.org/viewvc/gnumeric?rev=16495&view=rev

Log:
Fix float case of VLOOKUP/HLOOKUP/MATCH too.

2008-04-08  Morten Welinder  <terra gnome org>

	* src/mathfunc.c (gnm_float_hash, gnm_float_equal): Moved from
	rangefunc.c.  Made public.




Modified:
   trunk/ChangeLog
   trunk/NEWS
   trunk/plugins/fn-lookup/functions.c
   trunk/src/mathfunc.c
   trunk/src/mathfunc.h
   trunk/src/rangefunc.c

Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS	(original)
+++ trunk/NEWS	Wed Apr  9 00:48:18 2008
@@ -65,7 +65,8 @@
 	* Fix check for bogus xls files.  [#524926]
 	* Fix CONCATENATE's empty case.
 	* Improve performance of analysis tools for large ranges.
-	* Fix performance of repeated [VH]LOOKUP with constant data range.  [#525875]
+	* Fix performance repeated VLOOKUP/HLOOKUP/MATCH with constant
+	  data range.  [#525875]
 
 Nick Lamb:
 	* Honour detachable-toolbar preference.  [#321867]

Modified: trunk/plugins/fn-lookup/functions.c
==============================================================================
--- trunk/plugins/fn-lookup/functions.c	(original)
+++ trunk/plugins/fn-lookup/functions.c	Wed Apr  9 00:48:18 2008
@@ -38,6 +38,7 @@
 #include <expr-impl.h>
 #include <application.h>
 #include <expr-name.h>
+#include <mathfunc.h>
 #include <parse-util.h>
 #include <gnm-i18n.h>
 
@@ -50,6 +51,7 @@
 GNM_PLUGIN_MODULE_HEADER;
 
 static GHashTable *lookup_string_cache;
+static GHashTable *lookup_float_cache;
 
 static void
 clear_caches (void)
@@ -58,12 +60,27 @@
 		g_hash_table_destroy (lookup_string_cache);
 		lookup_string_cache = NULL;
 	}
+	if (lookup_float_cache) {
+		g_hash_table_destroy (lookup_float_cache);
+		lookup_float_cache = NULL;
+	}
 }
 
 static GHashTable *
-get_string_cache (const GnmSheetRange *sr)
+get_cache (GnmFuncEvalInfo *ei, GnmValue const *data, gboolean stringp)
 {
+	GnmSheetRange sr;
 	GHashTable *h;
+	Sheet *end_sheet;
+	GnmRangeRef const *rr;
+
+	if (data->type != VALUE_CELLRANGE)
+		return NULL;
+	rr = value_get_rangeref (data);
+
+        gnm_rangeref_normalize (rr, ei->pos, &sr.sheet, &end_sheet, &sr.range);
+	if (sr.sheet != end_sheet)
+		return NULL;
 
 	if (!lookup_string_cache) {
 		lookup_string_cache = g_hash_table_new_full
@@ -73,12 +90,18 @@
 			 (GDestroyNotify)g_hash_table_destroy);
 	}
 
-	h = g_hash_table_lookup (lookup_string_cache, sr);
+	h = g_hash_table_lookup (lookup_string_cache, &sr);
 	if (!h) {
-		h = g_hash_table_new_full (g_str_hash, g_str_equal,
-					   g_free, NULL);
+		if (stringp)
+			h = g_hash_table_new_full (g_str_hash,
+						   g_str_equal,
+						   g_free, NULL);
+		else
+			h = g_hash_table_new_full ((GHashFunc)gnm_float_hash,
+						   (GEqualFunc)gnm_float_equal,
+						   g_free, NULL);
 		g_hash_table_insert (lookup_string_cache,
-				     gnm_sheet_range_dup (sr), h);
+				     gnm_sheet_range_dup (&sr), h);
 	}
 
 	return h;
@@ -198,25 +221,15 @@
 	gpointer pres;
 	char *sc;
 	gboolean found;
-	GnmRangeRef const *rr;
-	Sheet *start_sheet, *end_sheet;
-	GnmSheetRange sr;
 
-	if (data->type != VALUE_CELLRANGE)
-		return -2;
-	rr = value_get_rangeref (data);
-
-        gnm_rangeref_normalize (rr, ei->pos, &start_sheet, &end_sheet, &sr.range);
-	if (start_sheet != end_sheet)
+	h = get_cache (ei, data, TRUE);
+	if (!h)
 		return -2;
 
 	/* We need to do this early before calls to value_peek_string gets
 	   called too often.  */
 	sc = g_utf8_casefold (s, -1);
 
-	sr.sheet = start_sheet;
-	h = get_string_cache (&sr);
-
 	if (g_hash_table_size (h) == 0) {
 		int lp, length = calc_length (data, ei->pos, vertical);
 
@@ -224,7 +237,7 @@
 			GnmValue const *v = get_elem (data, lp, ei->pos, vertical);
 			char *vc;
 
-			if (!VALUE_IS_STRING (v))
+			if (!v || !VALUE_IS_STRING (v))
 				continue;
 
 			vc = g_utf8_casefold (value_peek_string (v), -1);
@@ -242,6 +255,44 @@
 }
 
 static int
+find_index_linear_equal_float (GnmFuncEvalInfo *ei,
+			       gnm_float f, GnmValue const *data,
+			       gboolean vertical)
+{
+	GHashTable *h;
+	gpointer pres;
+	gboolean found;
+
+	h = get_cache (ei, data, FALSE);
+	if (!h)
+		return -2;
+
+	if (g_hash_table_size (h) == 0) {
+		int lp, length = calc_length (data, ei->pos, vertical);
+
+		for (lp = 0; lp < length; lp++) {
+			GnmValue const *v = get_elem (data, lp, ei->pos, vertical);
+			gnm_float f2;
+
+			if (!v || !VALUE_IS_NUMBER (v))
+				continue;
+
+			f2 = value_get_as_float (v);
+
+			if (!g_hash_table_lookup_extended (h, &f2, NULL, NULL))
+				g_hash_table_insert
+					(h,
+					 g_memdup (&f2, sizeof (f2)),
+					 GINT_TO_POINTER (lp));
+		}
+	}
+
+	found = g_hash_table_lookup_extended (h, &f, NULL, &pres);
+
+	return found ? GPOINTER_TO_INT (pres) : -1;
+}
+
+static int
 find_index_linear (GnmFuncEvalInfo *ei,
 		   GnmValue const *find, GnmValue const *data,
 		   gint type, gboolean vertical)
@@ -257,6 +308,13 @@
 			return i;
 	}
 
+	if (VALUE_IS_NUMBER (find) && type == 0) {
+		gnm_float f = value_get_as_float (find);
+		int i = find_index_linear_equal_float (ei, f, data, vertical);
+		if (i != -2)
+			return i;
+	}
+
 	length = calc_length (data, ei->pos, vertical);
 
 	for (lp = 0; lp < length; lp++) {

Modified: trunk/src/mathfunc.c
==============================================================================
--- trunk/src/mathfunc.c	(original)
+++ trunk/src/mathfunc.c	Wed Apr  9 00:48:18 2008
@@ -7760,3 +7760,22 @@
 #endif
 
 /* ------------------------------------------------------------------------- */
+
+gint
+gnm_float_equal (gnm_float const *a, const gnm_float *b)
+{
+	return (*a == *b);
+}
+
+guint
+gnm_float_hash (gnm_float const *d)
+{
+	int expt;
+	gnm_float mant = gnm_frexp (gnm_abs (*d), &expt);
+	guint h = ((guint)(0x80000000u * mant)) ^ expt;
+	if (*d >= 0)
+		h ^= 0x55555555;
+	return h;
+}
+
+/* ------------------------------------------------------------------------- */

Modified: trunk/src/mathfunc.h
==============================================================================
--- trunk/src/mathfunc.h	(original)
+++ trunk/src/mathfunc.h	Wed Apr  9 00:48:18 2008
@@ -183,6 +183,9 @@
 gnm_float permut (gnm_float n, gnm_float k);
 gnm_float fact   (int n);
 
+gint gnm_float_equal (gnm_float const *a, const gnm_float *b);
+guint gnm_float_hash (gnm_float const *d);
+
 void mathfunc_init (void);
 
 /* ------------------------------------------------------------------------- */

Modified: trunk/src/rangefunc.c
==============================================================================
--- trunk/src/rangefunc.c	(original)
+++ trunk/src/rangefunc.c	Wed Apr  9 00:48:18 2008
@@ -424,25 +424,6 @@
 	return 0;
 }
 
-static guint
-float_hash (gnm_float const *d)
-{
-	int expt;
-	gnm_float mant = gnm_frexp (gnm_abs (*d), &expt);
-	guint h = ((guint)(0x80000000u * mant)) ^ expt;
-	if (*d >= 0)
-		h ^= 0x55555555;
-	return h;
-}
-
-static gint
-float_equal (gnm_float const *a, const gnm_float *b)
-{
-	if (*a == *b)
-	        return 1;
-	return 0;
-}
-
 /* Most-common element.  (The one whose first occurrence comes first in
    case of several equally common.  */
 int
@@ -456,8 +437,8 @@
 
 	if (n <= 1) return 1;
 
-	h = g_hash_table_new_full ((GHashFunc)float_hash,
-				   (GCompareFunc)float_equal,
+	h = g_hash_table_new_full ((GHashFunc)gnm_float_hash,
+				   (GCompareFunc)gnm_float_equal,
 				   NULL,
 				   (GDestroyNotify)g_free);
 	for (i = 0; i < n; i++) {



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