[Python-checkins] python/dist/src/Modules cPickle.c,2.141,2.142 structmodule.c,2.58,2.59

tim_one@users.sourceforge.net tim_one@users.sourceforge.net
Thu, 20 Mar 2003 12:53:34 -0800


Update of /cvsroot/python/python/dist/src/Modules
In directory sc8-pr-cvs1:/tmp/cvs-serv6732/python/Modules

Modified Files:
	cPickle.c structmodule.c 
Log Message:
New private API functions _PyFloat_{Pack,Unpack}(4,8}.  This is a
refactoring to get all the duplicates of this delicate code out of the
cPickle and struct modules.


Index: cPickle.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/cPickle.c,v
retrieving revision 2.141
retrieving revision 2.142
diff -C2 -d -r2.141 -r2.142
*** cPickle.c	20 Mar 2003 18:32:08 -0000	2.141
--- cPickle.c	20 Mar 2003 20:53:30 -0000	2.142
***************
*** 1125,1228 ****
  
  	if (self->bin) {
- 		int s, e;
- 		double f;
- 		long fhi, flo;
  		char str[9];
! 		unsigned char *p = (unsigned char *)str;
! 
! 		*p = BINFLOAT;
! 		p++;
! 
! 		if (x < 0) {
! 			s = 1;
! 			x = -x;
! 		}
! 		else
! 			s = 0;
! 
! 		f = frexp(x, &e);
! 
! 		/* Normalize f to be in the range [1.0, 2.0) */
! 		if (0.5 <= f && f < 1.0) {
! 			f *= 2.0;
! 			e--;
! 		}
! 		else if (f == 0.0) {
! 			e = 0;
! 		}
! 		else {
! 			PyErr_SetString(PyExc_SystemError,
! 					"frexp() result out of range");
  			return -1;
- 		}
- 
- 		if (e >= 1024)
- 			goto Overflow;
- 		else if (e < -1022) {
- 			/* Gradual underflow */
- 			f = ldexp(f, 1022 + e);
- 			e = 0;
- 		}
- 		else if (!(e == 0 && f == 0.0)) {
- 			e += 1023;
- 			f -= 1.0; /* Get rid of leading 1 */
- 		}
- 
- 		/* fhi receives the high 28 bits;
- 		   flo the low 24 bits (== 52 bits) */
- 		f *= 268435456.0; /* 2**28 */
- 		fhi = (long) floor(f); /* Truncate */
- 		assert(fhi < 268435456);
- 
- 		f -= (double)fhi;
- 		f *= 16777216.0; /* 2**24 */
- 		flo = (long) floor(f + 0.5); /* Round */
- 		assert(flo <= 16777216);
- 		if (flo >> 24) {
- 			/* The carry propagated out of a string of 24 1 bits. */
- 			flo = 0;
- 			++fhi;
- 			if (fhi >> 28) {
- 				/* And it also progagated out of the next
- 				 * 28 bits.
- 				 */
- 				fhi = 0;
- 				++e;
- 				if (e >= 2047)
- 					goto Overflow;
- 			}
- 		}
- 
- 		/* First byte */
- 		*p = (s<<7) | (e>>4);
- 		p++;
- 
- 		/* Second byte */
- 		*p = (unsigned char) (((e&0xF)<<4) | (fhi>>24));
- 		p++;
- 
- 		/* Third byte */
- 		*p = (unsigned char) ((fhi>>16) & 0xFF);
- 		p++;
- 
- 		/* Fourth byte */
- 		*p = (unsigned char) ((fhi>>8) & 0xFF);
- 		p++;
- 
- 		/* Fifth byte */
- 		*p = (unsigned char) (fhi & 0xFF);
- 		p++;
- 
- 		/* Sixth byte */
- 		*p = (unsigned char) ((flo>>16) & 0xFF);
- 		p++;
- 
- 		/* Seventh byte */
- 		*p = (unsigned char) ((flo>>8) & 0xFF);
- 		p++;
- 
- 		/* Eighth byte */
- 		*p = (unsigned char) (flo & 0xFF);
- 
  		if (self->write_func(self, str, 9) < 0)
  			return -1;
--- 1125,1132 ----
  
  	if (self->bin) {
  		char str[9];
! 		str[0] = BINFLOAT;
! 		if (_PyFloat_Pack8(x, (unsigned char *)&str[1], 0) < 0)
  			return -1;
  		if (self->write_func(self, str, 9) < 0)
  			return -1;
***************
*** 1238,1246 ****
  
  	return 0;
- 
-  Overflow:
- 	PyErr_SetString(PyExc_OverflowError,
- 			"float too large to pack with d format");
- 	return -1;
  }
  
--- 1142,1145 ----
***************
*** 3373,3379 ****
  load_binfloat(Unpicklerobject *self)
  {
! 	PyObject *py_float = 0;
! 	int s, e;
! 	long fhi, flo;
  	double x;
  	char *p;
--- 3272,3276 ----
  load_binfloat(Unpicklerobject *self)
  {
! 	PyObject *py_float;
  	double x;
  	char *p;
***************
*** 3382,3434 ****
  		return -1;
  
! 	/* First byte */
! 	s = (*p>>7) & 1;
! 	e = (*p & 0x7F) << 4;
! 	p++;
! 
! 	/* Second byte */
! 	e |= (*p>>4) & 0xF;
! 	fhi = (*p & 0xF) << 24;
! 	p++;
! 
! 	/* Third byte */
! 	fhi |= (*p & 0xFF) << 16;
! 	p++;
! 
! 	/* Fourth byte */
! 	fhi |= (*p & 0xFF) << 8;
! 	p++;
! 
! 	/* Fifth byte */
! 	fhi |= *p & 0xFF;
! 	p++;
! 
! 	/* Sixth byte */
! 	flo = (*p & 0xFF) << 16;
! 	p++;
! 
! 	/* Seventh byte */
! 	flo |= (*p & 0xFF) << 8;
! 	p++;
! 
! 	/* Eighth byte */
! 	flo |= *p & 0xFF;
! 
! 	x = (double)fhi + (double)flo / 16777216.0; /* 2**24 */
! 	x /= 268435456.0; /* 2**28 */
! 
! 	/* XXX This sadly ignores Inf/NaN */
! 	if (e == 0)
! 		e = -1022;
! 	else {
! 		x += 1.0;
! 		e -= 1023;
! 	}
! 	x = ldexp(x, e);
! 
! 	if (s)
! 		x = -x;
  
! 	if (!( py_float = PyFloat_FromDouble(x)))  return -1;
  
  	PDATA_PUSH(self->stack, py_float, -1);
--- 3279,3289 ----
  		return -1;
  
! 	x = _PyFloat_Unpack8((unsigned char *)p, 0);
! 	if (x == -1.0 && PyErr_Occurred())
! 		return -1;
  
! 	py_float = PyFloat_FromDouble(x);
! 	if (py_float == NULL)
! 		return -1;
  
  	PDATA_PUSH(self->stack, py_float, -1);

Index: structmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/structmodule.c,v
retrieving revision 2.58
retrieving revision 2.59
diff -C2 -d -r2.58 -r2.59
*** structmodule.c	20 Mar 2003 18:32:13 -0000	2.58
--- structmodule.c	20 Mar 2003 20:53:31 -0000	2.59
***************
*** 186,484 ****
  /* Floating point helpers */
  
- /* These use ANSI/IEEE Standard 754-1985 (Standard for Binary Floating
-    Point Arithmetic).  See the following URL:
-    http://www.psc.edu/general/software/packages/ieee/ieee.html */
- 
- /* XXX Inf/NaN are not handled quite right (but underflow is!) */
- 
- static int
- pack_float(double x, /* The number to pack */
-            char *p,  /* Where to pack the high order byte */
-            int incr) /* 1 for big-endian; -1 for little-endian */
- {
- 	int s;
- 	int e;
- 	double f;
- 	long fbits;
- 
- 	if (x < 0) {
- 		s = 1;
- 		x = -x;
- 	}
- 	else
- 		s = 0;
- 
- 	f = frexp(x, &e);
- 
- 	/* Normalize f to be in the range [1.0, 2.0) */
- 	if (0.5 <= f && f < 1.0) {
- 		f *= 2.0;
- 		e--;
- 	}
- 	else if (f == 0.0) {
- 		e = 0;
- 	}
- 	else {
- 		PyErr_SetString(PyExc_SystemError,
- 				"frexp() result out of range");
- 		return -1;
- 	}
- 
- 	if (e >= 128)
- 		goto Overflow;
- 	else if (e < -126) {
- 		/* Gradual underflow */
- 		f = ldexp(f, 126 + e);
- 		e = 0;
- 	}
- 	else if (!(e == 0 && f == 0.0)) {
- 		e += 127;
- 		f -= 1.0; /* Get rid of leading 1 */
- 	}
- 
- 	f *= 8388608.0; /* 2**23 */
- 	fbits = (long) floor(f + 0.5); /* Round */
- 	assert(fbits <= 8388608);
- 	if (fbits >> 23) {
- 		/* The carry propagated out of a string of 23 1 bits. */
- 		fbits = 0;
- 		++e;
- 		if (e >= 255)
- 			goto Overflow;
- 	}
- 
- 	/* First byte */
- 	*p = (s<<7) | (e>>1);
- 	p += incr;
- 
- 	/* Second byte */
- 	*p = (char) (((e&1)<<7) | (fbits>>16));
- 	p += incr;
- 
- 	/* Third byte */
- 	*p = (fbits>>8) & 0xFF;
- 	p += incr;
- 
- 	/* Fourth byte */
- 	*p = fbits&0xFF;
- 
- 	/* Done */
- 	return 0;
- 
-  Overflow:
- 	PyErr_SetString(PyExc_OverflowError,
- 			"float too large to pack with f format");
- 	return -1;
- }
- 
- static int
- pack_double(double x, /* The number to pack */
-             char *p,  /* Where to pack the high order byte */
-             int incr) /* 1 for big-endian; -1 for little-endian */
- {
- 	int s;
- 	int e;
- 	double f;
- 	long fhi, flo;
- 
- 	if (x < 0) {
- 		s = 1;
- 		x = -x;
- 	}
- 	else
- 		s = 0;
- 
- 	f = frexp(x, &e);
- 
- 	/* Normalize f to be in the range [1.0, 2.0) */
- 	if (0.5 <= f && f < 1.0) {
- 		f *= 2.0;
- 		e--;
- 	}
- 	else if (f == 0.0) {
- 		e = 0;
- 	}
- 	else {
- 		PyErr_SetString(PyExc_SystemError,
- 				"frexp() result out of range");
- 		return -1;
- 	}
- 
- 	if (e >= 1024)
- 		goto Overflow;
- 	else if (e < -1022) {
- 		/* Gradual underflow */
- 		f = ldexp(f, 1022 + e);
- 		e = 0;
- 	}
- 	else if (!(e == 0 && f == 0.0)) {
- 		e += 1023;
- 		f -= 1.0; /* Get rid of leading 1 */
- 	}
- 
- 	/* fhi receives the high 28 bits; flo the low 24 bits (== 52 bits) */
- 	f *= 268435456.0; /* 2**28 */
- 	fhi = (long) floor(f); /* Truncate */
- 	assert(fhi < 268435456);
- 
- 	f -= (double)fhi;
- 	f *= 16777216.0; /* 2**24 */
- 	flo = (long) floor(f + 0.5); /* Round */
- 	assert(flo <= 16777216);
- 	if (flo >> 24) {
- 		/* The carry propagated out of a string of 24 1 bits. */
- 		flo = 0;
- 		++fhi;
- 		if (fhi >> 28) {
- 			/* And it also progagated out of the next 28 bits. */
- 			fhi = 0;
- 			++e;
- 			if (e >= 2047)
- 				goto Overflow;
- 		}
- 	}
- 
- 	/* First byte */
- 	*p = (s<<7) | (e>>4);
- 	p += incr;
- 
- 	/* Second byte */
- 	*p = (char) (((e&0xF)<<4) | (fhi>>24));
- 	p += incr;
- 
- 	/* Third byte */
- 	*p = (fhi>>16) & 0xFF;
- 	p += incr;
- 
- 	/* Fourth byte */
- 	*p = (fhi>>8) & 0xFF;
- 	p += incr;
- 
- 	/* Fifth byte */
- 	*p = fhi & 0xFF;
- 	p += incr;
- 
- 	/* Sixth byte */
- 	*p = (flo>>16) & 0xFF;
- 	p += incr;
- 
- 	/* Seventh byte */
- 	*p = (flo>>8) & 0xFF;
- 	p += incr;
- 
- 	/* Eighth byte */
- 	*p = flo & 0xFF;
- 	p += incr;
- 
- 	/* Done */
- 	return 0;
- 
-  Overflow:
- 	PyErr_SetString(PyExc_OverflowError,
- 			"float too large to pack with d format");
- 	return -1;
- }
- 
  static PyObject *
! unpack_float(const char *p,  /* Where the high order byte is */
!              int incr)       /* 1 for big-endian; -1 for little-endian */
  {
- 	int s;
- 	int e;
- 	long f;
  	double x;
  
! 	/* First byte */
! 	s = (*p>>7) & 1;
! 	e = (*p & 0x7F) << 1;
! 	p += incr;
! 
! 	/* Second byte */
! 	e |= (*p>>7) & 1;
! 	f = (*p & 0x7F) << 16;
! 	p += incr;
! 
! 	/* Third byte */
! 	f |= (*p & 0xFF) << 8;
! 	p += incr;
! 
! 	/* Fourth byte */
! 	f |= *p & 0xFF;
! 
! 	x = (double)f / 8388608.0;
! 
! 	/* XXX This sadly ignores Inf/NaN issues */
! 	if (e == 0)
! 		e = -126;
! 	else {
! 		x += 1.0;
! 		e -= 127;
! 	}
! 	x = ldexp(x, e);
! 
! 	if (s)
! 		x = -x;
! 
  	return PyFloat_FromDouble(x);
  }
  
  static PyObject *
! unpack_double(const char *p,  /* Where the high order byte is */
!               int incr)       /* 1 for big-endian; -1 for little-endian */
  {
- 	int s;
- 	int e;
- 	long fhi, flo;
  	double x;
  
! 	/* First byte */
! 	s = (*p>>7) & 1;
! 	e = (*p & 0x7F) << 4;
! 	p += incr;
! 
! 	/* Second byte */
! 	e |= (*p>>4) & 0xF;
! 	fhi = (*p & 0xF) << 24;
! 	p += incr;
! 
! 	/* Third byte */
! 	fhi |= (*p & 0xFF) << 16;
! 	p += incr;
! 
! 	/* Fourth byte */
! 	fhi |= (*p & 0xFF) << 8;
! 	p += incr;
! 
! 	/* Fifth byte */
! 	fhi |= *p & 0xFF;
! 	p += incr;
! 
! 	/* Sixth byte */
! 	flo = (*p & 0xFF) << 16;
! 	p += incr;
! 
! 	/* Seventh byte */
! 	flo |= (*p & 0xFF) << 8;
! 	p += incr;
! 
! 	/* Eighth byte */
! 	flo |= *p & 0xFF;
! 	p += incr;
! 
! 	x = (double)fhi + (double)flo / 16777216.0; /* 2**24 */
! 	x /= 268435456.0; /* 2**28 */
! 
! 	/* XXX This sadly ignores Inf/NaN */
! 	if (e == 0)
! 		e = -1022;
! 	else {
! 		x += 1.0;
! 		e -= 1023;
! 	}
! 	x = ldexp(x, e);
! 
! 	if (s)
! 		x = -x;
! 
  	return PyFloat_FromDouble(x);
  }
--- 186,210 ----
  /* Floating point helpers */
  
  static PyObject *
! unpack_float(const char *p,  /* start of 4-byte string */
!              int le)	     /* true for little-endian, false for big-endian */
  {
  	double x;
  
! 	x = _PyFloat_Unpack4((unsigned char *)p, le);
! 	if (x == -1.0 && PyErr_Occurred())
! 		return NULL;
  	return PyFloat_FromDouble(x);
  }
  
  static PyObject *
! unpack_double(const char *p,  /* start of 8-byte string */
!               int le)         /* true for little-endian, false for big-endian */
  {
  	double x;
  
! 	x = _PyFloat_Unpack8((unsigned char *)p, le);
! 	if (x == -1.0 && PyErr_Occurred())
! 		return NULL;
  	return PyFloat_FromDouble(x);
  }
***************
*** 888,892 ****
  bu_float(const char *p, const formatdef *f)
  {
! 	return unpack_float(p, 1);
  }
  
--- 614,618 ----
  bu_float(const char *p, const formatdef *f)
  {
! 	return unpack_float(p, 0);
  }
  
***************
*** 894,898 ****
  bu_double(const char *p, const formatdef *f)
  {
! 	return unpack_double(p, 1);
  }
  
--- 620,624 ----
  bu_double(const char *p, const formatdef *f)
  {
! 	return unpack_double(p, 0);
  }
  
***************
*** 968,972 ****
  		return -1;
  	}
! 	return pack_float(x, p, 1);
  }
  
--- 694,698 ----
  		return -1;
  	}
! 	return _PyFloat_Pack4(x, (unsigned char *)p, 0);
  }
  
***************
*** 980,984 ****
  		return -1;
  	}
! 	return pack_double(x, p, 1);
  }
  
--- 706,710 ----
  		return -1;
  	}
! 	return _PyFloat_Pack8(x, (unsigned char *)p, 0);
  }
  
***************
*** 1054,1058 ****
  lu_float(const char *p, const formatdef *f)
  {
! 	return unpack_float(p+3, -1);
  }
  
--- 780,784 ----
  lu_float(const char *p, const formatdef *f)
  {
! 	return unpack_float(p, 1);
  }
  
***************
*** 1060,1064 ****
  lu_double(const char *p, const formatdef *f)
  {
! 	return unpack_double(p+7, -1);
  }
  
--- 786,790 ----
  lu_double(const char *p, const formatdef *f)
  {
! 	return unpack_double(p, 1);
  }
  
***************
*** 1134,1138 ****
  		return -1;
  	}
! 	return pack_float(x, p+3, -1);
  }
  
--- 860,864 ----
  		return -1;
  	}
! 	return _PyFloat_Pack4(x, (unsigned char *)p, 1);
  }
  
***************
*** 1146,1150 ****
  		return -1;
  	}
! 	return pack_double(x, p+7, -1);
  }
  
--- 872,876 ----
  		return -1;
  	}
! 	return _PyFloat_Pack8(x, (unsigned char *)p, 1);
  }