[m-dev.] Re: pragma fact_table

David Matthew OVERTON dmo at students.cs.mu.oz.au
Thu Feb 27 13:33:13 AEDT 1997


Hi Fergus,

I've left the non-negative stuff in for now.  I didn't see much point
in changing it while there is still disagreement about whether
negative hash values should be allowed.

David.

Estimated hours taken: 2

Add new predicate `float__hash' to the standard library for computing a
non-negative integer hash value for a float.

Add a C function to the runtime to do the actual hashing.  This
function is in the runtime so that it can be called from both
the library and from C code generated for `pragma fact_table'
indexing.

library/float.m
        Add a new predicate `float__hash' that calls the runtime
	function `hash_float()'.

library/float.nu.nl
	Add a new predicate `float__hash'.  Note: this one computes a
	different hash value to the one in `float.m'.

runtime/Mmakefile
	Add `mercury_float.c' to the list of C files.

runtime/mercury_float.h
	Add a declaration for `hash_float()'.

runtime/mercury_float.c
	Add new file `mercury_float.c' for runtime code related to
	floats.
	Add a new function `hash_float()' for hashing floats.

Index: library/float.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/float.m,v
retrieving revision 1.20
diff -u -r1.20 float.m
--- 1.20	1996/07/26 06:00:14
+++ float.m	1997/02/26 07:08:23
@@ -156,7 +156,15 @@
 :- mode float__epsilon(out) is det.
 
 %---------------------------------------------------------------------------%
+% Compute a non-negative integer hash value for a float.
+% Note: the hash value computed is different to that computed in the 
+% Prolog code in float.nu.nl.
 
+:- pred float__hash(float, int).
+:- mode float__hash(in, out) is det.
+
+%---------------------------------------------------------------------------%
+
 :- implementation.
 :- import_module int, require.
 
@@ -288,4 +296,12 @@
 :- pragma(c_code, float__epsilon(Eps::out), "Eps = MERCURY_FLOAT_EPSILON;").
 
 %---------------------------------------------------------------------------%
+
+:- pragma c_code(float__hash(F::in, H::out), will_not_call_mercury, "
+
+	H = hash_float(F);
+
+").
+
+%---------------------------------------------------------------------------%
 %---------------------------------------------------------------------------%
Index: library/float.nu.nl
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/float.nu.nl,v
retrieving revision 1.3
diff -u -r1.3 float.nu.nl
--- 1.3	1996/11/24 14:25:39
+++ float.nu.nl	1997/02/27 02:05:50
@@ -49,4 +49,19 @@
 
 float__epsilon(2.2204460492503131e-16).
 
+	% Note:  This hash function is different to the one defined in
+	% float.m.
+float__hash(Float, Hash) :-
+	float__abs(Float, Abs),
+	( Abs = 0.0 -> Abs2 = 1e-15 ; Abs2 = Abs ),
+	math__ln(Abs2, Log),
+	math__ceiling(Log, TruncLog),
+	math__exp(TruncLog, Pow),
+	Float2 is Abs2 / Pow * 2147483647.0,   % 2147483647 = (2^31)-1
+	float__truncate_to_int(Float2, N1),
+	float__abs(TruncLog, Log2),
+	float__truncate_to_int(Log2, N2),
+	Hash0 is N1 ^ N2,
+	int__abs(Hash0, Hash).
+
 %-----------------------------------------------------------------------------%
Index: runtime/Mmakefile
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/Mmakefile,v
retrieving revision 1.2
diff -u -r1.2 Mmakefile
--- 1.2	1997/02/19 05:47:54
+++ Mmakefile	1997/02/26 07:04:22
@@ -40,7 +40,7 @@
 MOD_OS		= $(MOD_CS:.c=.o)
 ORIG_CS		= deep_copy.c dlist.c dummy.c label.c \
 		  memory.c misc.c regs.c table.c timing.c prof.c prof_mem.c \
-		  spinlock.c
+		  spinlock.c mercury_float.c
 ORIG_OS		= $(ORIG_CS:.c=.o)
 OBJS		= $(MOD_OS) $(ORIG_OS)
 # OBJS		= engine.o wrapper.o call.o \
Index: runtime/mercury_float.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_float.h,v
retrieving revision 1.3
diff -u -r1.3 mercury_float.h
--- 1.3	1997/02/12 02:15:50
+++ mercury_float.h	1997/02/26 06:56:02
@@ -72,4 +72,8 @@
 
 #endif /* not BOXED_FLOAT */
 
+/* hash_float() is defined in mercury_float.c */
+
+Integer hash_float(Float);
+
 #endif /* not MERCURY_FLOAT_H */
===================================================================
new file: runtime/mercury_float.c
===================================================================

/*
** Copyright (C) 1996-1997 University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
*/

#include	"imp.h"
#include	"conf.h"


/*
** The function `hash_float()' is used by the library predicate `float__hash'
** and also for hashing floats for `pragma fact_table' indexing.
** It computes a non-negative Integer hash value for a Float.
*/

#ifndef BOXED_FLOAT  /* sizeof(Float) <= sizeof(Integer) */

union FloatInteger {
	Float f;
	Integer i;
};

Integer
hash_float(Float f)
{
	union FloatInteger fi;

	/*
	** Just in case sizeof(Float) < sizeof(Integer), initialise 
	** fi.i to 0 so we don't get garbage in the result.
	*/
	fi.i = 0;
	fi.f = f;
	return (fi.i >= 0 ? fi.i : -fi.i);
}

#else /* BOXED_FLOAT -- sizeof(Float) > sizeof(Integer) */

union FloatInteger {
	Float f;
	Integer i[sizeof(Float)/sizeof(Integer)];
};

Integer
hash_float(Float f)
{
	union FloatInteger fi;
	size_t i;
	Integer h = 0;

	fi.f = f;

	for (i = 0; i < sizeof(Float)/sizeof(Integer); i++)
		h ^= fi.i[i];

	return (h >= 0 ? h : -h);
}

#endif /* BOXED_FLOAT */



More information about the developers mailing list