This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Patch] libstdc++/21193 (float, double, long double)


Hi,

the below are the float/double/long double bits, as per the discussions
with Gaby and Joe: basically, I'm using the approach suggested by Gaby
when safe and resort to frexp for long double (similarly to various
proposals on the web and python).

Tested x86-linux and, lightly, x86-64-linux.

Paolo.

////////////////
2005-07-14  Paolo Carlini  <pcarlini@suse.de>

	PR libstdc++/21193 (float, double, long double)
	* include/tr1/functional (hash<float>, hash<double>):
	Reimplement exploiting the Fnv_hash<>::hash helper.
	(hash<long double>): Reimplement using frexp (in this
	case, due to random padding bits, the former approach
	is not generally viable).
Index: functional
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/tr1/functional,v
retrieving revision 1.12
diff -u -r1.12 functional
--- functional	13 Jul 2005 10:47:40 -0000	1.12
+++ functional	13 Jul 2005 21:51:41 -0000
@@ -40,6 +40,7 @@
 #include <bits/cpp_type_traits.h>
 #include <string>               // for std::tr1::hash
 #include <cstdlib>              // for std::abort
+#include <cmath>                // for frexp
 #include <tr1/tuple>
 
 namespace std
@@ -1116,10 +1117,6 @@
   tr1_hashtable_define_trivial_hash(unsigned int);
   tr1_hashtable_define_trivial_hash(unsigned long);
 
-  tr1_hashtable_define_trivial_hash(float);
-  tr1_hashtable_define_trivial_hash(double);
-  tr1_hashtable_define_trivial_hash(long double);
-
 #undef tr1_hashtable_define_trivial_hash
 
   template<typename T>
@@ -1133,7 +1130,7 @@
   // Fowler / Noll / Vo (FNV) Hash (type FNV-1a)
   // (used by the next specializations of std::tr1::hash<>)
 
-  // Dummy generic implementation (for sizeof(size_t) != 4,8).
+  // Dummy generic implementation (for sizeof(size_t) != 4, 8).
   template<std::size_t = sizeof(std::size_t)>
     struct Fnv_hash
     {
@@ -1179,9 +1176,9 @@
       }
     };
 
-  // XXX String hash probably shouldn't be an inline member function,
-  // since it's nontrivial.  Once we have the framework for TR1 .cc
-  // files, this should go in one.
+  // XXX String and floating point hashes probably shouldn't be inline
+  // member functions, since are nontrivial.  Once we have the framework
+  // for TR1 .cc files, these should go in one.
   template<>
     struct hash<std::string>
     {
@@ -1203,6 +1200,61 @@
     };
 #endif
 
+  template<>
+    struct hash<float>
+    {
+      std::size_t
+      operator()(float fval) const
+      {
+	std::size_t result = 0;
+
+	// 0 and -0 both hash to zero.
+	if (fval != 0.0f)
+	  result = Fnv_hash<>::hash(reinterpret_cast<const char*>(&fval),
+				    sizeof(fval));
+	return result;
+      }
+    };
+
+  template<>
+    struct hash<double>
+    {
+      std::size_t
+      operator()(double dval) const
+      {
+	std::size_t result = 0;
+
+	// 0 and -0 both hash to zero.
+	if (dval != 0.0)
+	  result = Fnv_hash<>::hash(reinterpret_cast<const char*>(&dval),
+				    sizeof(dval));
+	return result;
+      }
+    };
+
+  // For long double, careful with random padding bits (e.g., on x86,
+  // 10 bytes -> 12 bytes) and resort to frexp.
+  template<>
+    struct hash<long double>
+    {
+      std::size_t
+      operator()(long double ldval) const
+      {
+	std::size_t result = 0;
+	
+	const long double mult = ((std::numeric_limits<std::size_t>::max()
+				   >> 1) + 1.0l);
+	int exponent;
+	ldval = std::frexp(ldval, &exponent);
+	ldval *= mult;
+	const std::size_t hibits = (std::size_t)ldval;
+	
+	ldval = (ldval - (long double)hibits) * mult;
+	result = hibits + (std::size_t)ldval + (exponent << 15);
+
+	return result;
+      }
+    };
 }
 }
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]