[Patches] fix float_hash and complex_hash for 64-bit *nix

Trent Mick trentm@activestate.com
Tue, 9 May 2000 16:25:04 -0700


Discussion:

Okay, it is debatable to call float_hash and complex_hash broken, but their
code presumed that sizeof(long) was 32-bits. As a result the hashed values
for floats and complex values were not the same on a 64-bit *nix system as on
a 32-bit *nix system. With this patch they are.


Legal:

I confirm that, to the best of my knowledge and belief, this
contribution is free of any claims of third parties under
copyright, patent or other rights or interests ("claims").  To
the extent that I have any such claims, I hereby grant to CNRI a
nonexclusive, irrevocable, royalty-free, worldwide license to
reproduce, distribute, perform and/or display publicly, prepare
derivative versions, and otherwise use this contribution as part
of the Python software and its related documentation, or any
derivative versions thereof, at no cost to CNRI or its licensed
users, and to authorize others to do so.

I acknowledge that CNRI may, at its sole discretion, decide
whether or not to incorporate this contribution in the Python
software and its related documentation.  I further grant CNRI
permission to use my name and other identifying information
provided to CNRI by me for use in connection with the Python
software and its related documentation.

Patch:


diff -c3  /home/trentm/main/contrib/python/dist/src/Objects/floatobject.c ./Objects/floatobject.c
*** /home/trentm/main/contrib/python/dist/src/Objects/floatobject.c	Fri May  5 10:53:34 2000
--- ./Objects/floatobject.c	Tue May  9 14:52:46 2000
***************
*** 59,65 ****
--- 59,71 ----
  #endif
  
  #ifndef LONG_MAX
+ #if SIZEOF_LONG == 4
  #define LONG_MAX 0X7FFFFFFFL
+ #elif SIZEOF_LONG == 8
+ #define LONG_MAX 0X7FFFFFFFFFFFFFFFL
+ #else
+ #error "could not set LONG_MAX"
+ #endif
  #endif
  
  #ifndef LONG_MIN
***************
*** 379,385 ****
  #endif
  
  	if (fractpart == 0.0) {
! 		if (intpart > 0x7fffffffL || -intpart > 0x7fffffffL) {
  			/* Convert to long int and use its hash... */
  			PyObject *w = PyLong_FromDouble(v->ob_fval);
  			if (w == NULL)
--- 385,391 ----
  #endif
  
  	if (fractpart == 0.0) {
! 		if (intpart > LONG_MAX || -intpart > LONG_MAX) {
  			/* Convert to long int and use its hash... */
  			PyObject *w = PyLong_FromDouble(v->ob_fval);
  			if (w == NULL)
***************
*** 393,405 ****
  	else {
  		/* Note -- if you change this code, also change the copy
  		   in complexobject.c */
! 		long hipart;
  		fractpart = frexp(fractpart, &expo);
  		fractpart = fractpart * 2147483648.0; /* 2**31 */
! 		hipart = (long)fractpart; /* Take the top 32 bits */
  		fractpart = (fractpart - (double)hipart) * 2147483648.0;
  						/* Get the next 32 bits */
! 		x = hipart + (long)fractpart + (long)intpart + (expo << 15);
  						/* Combine everything */
  	}
  	if (x == -1)
--- 399,411 ----
  	else {
  		/* Note -- if you change this code, also change the copy
  		   in complexobject.c */
! 		int hipart; /* algorithm expects this to be 32-bits */
  		fractpart = frexp(fractpart, &expo);
  		fractpart = fractpart * 2147483648.0; /* 2**31 */
! 		hipart = (int)fractpart; /* Take the top 32 bits */
  		fractpart = (fractpart - (double)hipart) * 2147483648.0;
  						/* Get the next 32 bits */
! 		x = hipart + (int)fractpart + (int)intpart + (expo << 15);
  						/* Combine everything */
  	}
  	if (x == -1)
***************
*** 805,812 ****
  					char buf[100];
  					PyFloat_AsString(buf, p);
  					fprintf(stderr,
! 			     "#   <float at %lx, refcnt=%d, val=%s>\n",
! 						(long)p, p->ob_refcnt, buf);
  				}
  			}
  			list = list->next;
--- 811,818 ----
  					char buf[100];
  					PyFloat_AsString(buf, p);
  					fprintf(stderr,
! 			     "#   <float at %p, refcnt=%d, val=%s>\n",
! 						p, p->ob_refcnt, buf);
  				}
  			}
  			list = list->next;
diff -c3  /home/trentm/main/contrib/python/dist/src/Objects/complexobject.c ./Objects/complexobject.c
*** /home/trentm/main/contrib/python/dist/src/Objects/complexobject.c	Fri May  5 10:53:34 2000
--- ./Objects/complexobject.c	Tue May  9 16:01:28 2000
***************
*** 286,292 ****
  {
  	double intpart, fractpart;
  	int expo;
! 	long hipart, x;
  	/* This is designed so that Python numbers with the same
  	   value hash to the same value, otherwise comparisons
  	   of mapping keys will turn out weird */
--- 286,292 ----
  {
  	double intpart, fractpart;
  	int expo;
! 	long x;
  	/* This is designed so that Python numbers with the same
  	   value hash to the same value, otherwise comparisons
  	   of mapping keys will turn out weird */
***************
*** 302,308 ****
  #endif
  
  	if (fractpart == 0.0 && v->cval.imag == 0.0) {
! 		if (intpart > 0x7fffffffL || -intpart > 0x7fffffffL) {
  			/* Convert to long int and use its hash... */
  			PyObject *w = PyLong_FromDouble(v->cval.real);
  			if (w == NULL)
--- 302,308 ----
  #endif
  
  	if (fractpart == 0.0 && v->cval.imag == 0.0) {
! 		if (intpart > LONG_MAX || -intpart > LONG_MAX) {
  			/* Convert to long int and use its hash... */
  			PyObject *w = PyLong_FromDouble(v->cval.real);
  			if (w == NULL)
***************
*** 314,325 ****
  		x = (long)intpart;
  	}
  	else {
  		fractpart = frexp(fractpart, &expo);
  		fractpart = fractpart * 2147483648.0; /* 2**31 */
! 		hipart = (long)fractpart; /* Take the top 32 bits */
  		fractpart = (fractpart - (double)hipart) * 2147483648.0;
  						/* Get the next 32 bits */
! 		x = hipart + (long)fractpart + (long)intpart + (expo << 15);
  						/* Combine everything */
  
  		if (v->cval.imag != 0.0) { /* Hash the imaginary part */
--- 314,326 ----
  		x = (long)intpart;
  	}
  	else {
+         int hipart; /* algorithm expects this to be 32-bits */
  		fractpart = frexp(fractpart, &expo);
  		fractpart = fractpart * 2147483648.0; /* 2**31 */
! 		hipart = (int)fractpart; /* Take the top 32 bits */
  		fractpart = (fractpart - (double)hipart) * 2147483648.0;
  						/* Get the next 32 bits */
! 		x = hipart + (int)fractpart + (int)intpart + (expo << 15);
  						/* Combine everything */
  
  		if (v->cval.imag != 0.0) { /* Hash the imaginary part */
***************
*** 336,348 ****
  			fractpart = modf(v->cval.imag, &intpart);
  #endif
  			fractpart = frexp(fractpart, &expo);
! 			fractpart = fractpart * 2147483648.0; /* 2**31 */
! 			hipart = (long)fractpart; /* Take the top 32 bits */
  			fractpart =
  				(fractpart - (double)hipart) * 2147483648.0;
  						/* Get the next 32 bits */
! 			x ^= hipart + (long)fractpart +
! 				(long)intpart + (expo << 15);
  						/* Combine everything */
  		}
  	}
--- 337,349 ----
  			fractpart = modf(v->cval.imag, &intpart);
  #endif
  			fractpart = frexp(fractpart, &expo);
! 			fractpart = fractpart * 2147483648.0;
! 			hipart = (int)fractpart;
  			fractpart =
  				(fractpart - (double)hipart) * 2147483648.0;
  						/* Get the next 32 bits */
! 			x ^= hipart + (int)fractpart +
! 				(int)intpart + (expo << 15);
  						/* Combine everything */
  		}
  	}



-- 
Trent Mick
trentm@activestate.com