symbian-qemu-0.9.1-12/python-2.6.1/Objects/floatobject.c
changeset 1 2fb8b9db1c86
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symbian-qemu-0.9.1-12/python-2.6.1/Objects/floatobject.c	Fri Jul 31 15:01:17 2009 +0100
@@ -0,0 +1,2521 @@
+
+/* Float object implementation */
+
+/* XXX There should be overflow checks here, but it's hard to check
+   for any kind of float exception without losing portability. */
+
+#include "Python.h"
+#include "structseq.h"
+
+#include <ctype.h>
+#include <float.h>
+
+#undef MAX
+#undef MIN
+#define MAX(x, y) ((x) < (y) ? (y) : (x))
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
+
+#ifdef HAVE_IEEEFP_H
+#include <ieeefp.h>
+#endif
+
+#ifdef _OSF_SOURCE
+/* OSF1 5.1 doesn't make this available with XOPEN_SOURCE_EXTENDED defined */
+extern int finite(double);
+#endif
+
+/* Special free list -- see comments for same code in intobject.c. */
+#define BLOCK_SIZE	1000	/* 1K less typical malloc overhead */
+#define BHEAD_SIZE	8	/* Enough for a 64-bit pointer */
+#define N_FLOATOBJECTS	((BLOCK_SIZE - BHEAD_SIZE) / sizeof(PyFloatObject))
+
+struct _floatblock {
+	struct _floatblock *next;
+	PyFloatObject objects[N_FLOATOBJECTS];
+};
+
+typedef struct _floatblock PyFloatBlock;
+
+static PyFloatBlock *block_list = NULL;
+static PyFloatObject *free_list = NULL;
+
+static PyFloatObject *
+fill_free_list(void)
+{
+	PyFloatObject *p, *q;
+	/* XXX Float blocks escape the object heap. Use PyObject_MALLOC ??? */
+	p = (PyFloatObject *) PyMem_MALLOC(sizeof(PyFloatBlock));
+	if (p == NULL)
+		return (PyFloatObject *) PyErr_NoMemory();
+	((PyFloatBlock *)p)->next = block_list;
+	block_list = (PyFloatBlock *)p;
+	p = &((PyFloatBlock *)p)->objects[0];
+	q = p + N_FLOATOBJECTS;
+	while (--q > p)
+		Py_TYPE(q) = (struct _typeobject *)(q-1);
+	Py_TYPE(q) = NULL;
+	return p + N_FLOATOBJECTS - 1;
+}
+
+double
+PyFloat_GetMax(void)
+{
+	return DBL_MAX;
+}
+
+double
+PyFloat_GetMin(void)
+{
+	return DBL_MIN;
+}
+
+static PyTypeObject FloatInfoType = {0, 0, 0, 0, 0, 0};
+
+PyDoc_STRVAR(floatinfo__doc__,
+"sys.floatinfo\n\
+\n\
+A structseq holding information about the float type. It contains low level\n\
+information about the precision and internal representation. Please study\n\
+your system's :file:`float.h` for more information.");
+
+static PyStructSequence_Field floatinfo_fields[] = {
+	{"max",		"DBL_MAX -- maximum representable finite float"},
+	{"max_exp",	"DBL_MAX_EXP -- maximum int e such that radix**(e-1) "
+			"is representable"},
+	{"max_10_exp",	"DBL_MAX_10_EXP -- maximum int e such that 10**e "
+			"is representable"},
+	{"min",		"DBL_MIN -- Minimum positive normalizer float"},
+	{"min_exp",	"DBL_MIN_EXP -- minimum int e such that radix**(e-1) "
+			"is a normalized float"},
+	{"min_10_exp",	"DBL_MIN_10_EXP -- minimum int e such that 10**e is "
+			"a normalized"},
+	{"dig",		"DBL_DIG -- digits"},
+	{"mant_dig",	"DBL_MANT_DIG -- mantissa digits"},
+	{"epsilon",	"DBL_EPSILON -- Difference between 1 and the next "
+			"representable float"},
+	{"radix",	"FLT_RADIX -- radix of exponent"},
+	{"rounds",	"FLT_ROUNDS -- addition rounds"},
+	{0}
+};
+
+static PyStructSequence_Desc floatinfo_desc = {
+	"sys.floatinfo",	/* name */
+	floatinfo__doc__,	/* doc */
+	floatinfo_fields,	/* fields */
+	11
+};
+
+PyObject *
+PyFloat_GetInfo(void)
+{
+	PyObject* floatinfo;
+	int pos = 0;
+
+	floatinfo = PyStructSequence_New(&FloatInfoType);
+	if (floatinfo == NULL) {
+		return NULL;
+	}
+
+#define SetIntFlag(flag) \
+	PyStructSequence_SET_ITEM(floatinfo, pos++, PyInt_FromLong(flag))
+#define SetDblFlag(flag) \
+	PyStructSequence_SET_ITEM(floatinfo, pos++, PyFloat_FromDouble(flag))
+
+	SetDblFlag(DBL_MAX);
+	SetIntFlag(DBL_MAX_EXP);
+	SetIntFlag(DBL_MAX_10_EXP);
+	SetDblFlag(DBL_MIN);
+	SetIntFlag(DBL_MIN_EXP);
+	SetIntFlag(DBL_MIN_10_EXP);
+	SetIntFlag(DBL_DIG);
+	SetIntFlag(DBL_MANT_DIG);
+	SetDblFlag(DBL_EPSILON);
+	SetIntFlag(FLT_RADIX);
+	SetIntFlag(FLT_ROUNDS);
+#undef SetIntFlag
+#undef SetDblFlag
+	
+	if (PyErr_Occurred()) {
+		Py_CLEAR(floatinfo);
+		return NULL;
+	}
+	return floatinfo;
+}
+
+PyObject *
+PyFloat_FromDouble(double fval)
+{
+	register PyFloatObject *op;
+	if (free_list == NULL) {
+		if ((free_list = fill_free_list()) == NULL)
+			return NULL;
+	}
+	/* Inline PyObject_New */
+	op = free_list;
+	free_list = (PyFloatObject *)Py_TYPE(op);
+	PyObject_INIT(op, &PyFloat_Type);
+	op->ob_fval = fval;
+	return (PyObject *) op;
+}
+
+/**************************************************************************
+RED_FLAG 22-Sep-2000 tim
+PyFloat_FromString's pend argument is braindead.  Prior to this RED_FLAG,
+
+1.  If v was a regular string, *pend was set to point to its terminating
+    null byte.  That's useless (the caller can find that without any
+    help from this function!).
+
+2.  If v was a Unicode string, or an object convertible to a character
+    buffer, *pend was set to point into stack trash (the auto temp
+    vector holding the character buffer).  That was downright dangerous.
+
+Since we can't change the interface of a public API function, pend is
+still supported but now *officially* useless:  if pend is not NULL,
+*pend is set to NULL.
+**************************************************************************/
+PyObject *
+PyFloat_FromString(PyObject *v, char **pend)
+{
+	const char *s, *last, *end, *sp;
+	double x;
+	char buffer[256]; /* for errors */
+#ifdef Py_USING_UNICODE
+	char s_buffer[256]; /* for objects convertible to a char buffer */
+#endif
+	Py_ssize_t len;
+
+	if (pend)
+		*pend = NULL;
+	if (PyString_Check(v)) {
+		s = PyString_AS_STRING(v);
+		len = PyString_GET_SIZE(v);
+	}
+#ifdef Py_USING_UNICODE
+	else if (PyUnicode_Check(v)) {
+		if (PyUnicode_GET_SIZE(v) >= (Py_ssize_t)sizeof(s_buffer)) {
+			PyErr_SetString(PyExc_ValueError,
+				"Unicode float() literal too long to convert");
+			return NULL;
+		}
+		if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v),
+					    PyUnicode_GET_SIZE(v),
+					    s_buffer,
+					    NULL))
+			return NULL;
+		s = s_buffer;
+		len = strlen(s);
+	}
+#endif
+	else if (PyObject_AsCharBuffer(v, &s, &len)) {
+		PyErr_SetString(PyExc_TypeError,
+				"float() argument must be a string or a number");
+		return NULL;
+	}
+
+	last = s + len;
+	while (*s && isspace(Py_CHARMASK(*s)))
+		s++;
+	if (*s == '\0') {
+		PyErr_SetString(PyExc_ValueError, "empty string for float()");
+		return NULL;
+	}
+	sp = s;
+	/* We don't care about overflow or underflow.  If the platform supports
+	 * them, infinities and signed zeroes (on underflow) are fine.
+	 * However, strtod can return 0 for denormalized numbers, where atof
+	 * does not.  So (alas!) we special-case a zero result.  Note that
+	 * whether strtod sets errno on underflow is not defined, so we can't
+	 * key off errno.
+         */
+	PyFPE_START_PROTECT("strtod", return NULL)
+	x = PyOS_ascii_strtod(s, (char **)&end);
+	PyFPE_END_PROTECT(x)
+	errno = 0;
+	/* Believe it or not, Solaris 2.6 can move end *beyond* the null
+	   byte at the end of the string, when the input is inf(inity). */
+	if (end > last)
+		end = last;
+	/* Check for inf and nan. This is done late because it rarely happens. */
+	if (end == s) {
+		char *p = (char*)sp;
+		int sign = 1;
+
+		if (*p == '-') {
+			sign = -1;
+			p++;
+		}
+		if (*p == '+') {
+			p++;
+		}
+		if (PyOS_strnicmp(p, "inf", 4) == 0) {
+			Py_RETURN_INF(sign);
+		}
+		if (PyOS_strnicmp(p, "infinity", 9) == 0) {
+			Py_RETURN_INF(sign);
+		}
+#ifdef Py_NAN
+		if(PyOS_strnicmp(p, "nan", 4) == 0) {
+			Py_RETURN_NAN;
+		}
+#endif
+		PyOS_snprintf(buffer, sizeof(buffer),
+			      "invalid literal for float(): %.200s", s);
+		PyErr_SetString(PyExc_ValueError, buffer);
+		return NULL;
+	}
+	/* Since end != s, the platform made *some* kind of sense out
+	   of the input.  Trust it. */
+	while (*end && isspace(Py_CHARMASK(*end)))
+		end++;
+	if (*end != '\0') {
+		PyOS_snprintf(buffer, sizeof(buffer),
+			      "invalid literal for float(): %.200s", s);
+		PyErr_SetString(PyExc_ValueError, buffer);
+		return NULL;
+	}
+	else if (end != last) {
+		PyErr_SetString(PyExc_ValueError,
+				"null byte in argument for float()");
+		return NULL;
+	}
+	if (x == 0.0) {
+		/* See above -- may have been strtod being anal
+		   about denorms. */
+		PyFPE_START_PROTECT("atof", return NULL)
+		x = PyOS_ascii_atof(s);
+		PyFPE_END_PROTECT(x)
+		errno = 0;    /* whether atof ever set errno is undefined */
+	}
+	return PyFloat_FromDouble(x);
+}
+
+static void
+float_dealloc(PyFloatObject *op)
+{
+	if (PyFloat_CheckExact(op)) {
+		Py_TYPE(op) = (struct _typeobject *)free_list;
+		free_list = op;
+	}
+	else
+		Py_TYPE(op)->tp_free((PyObject *)op);
+}
+
+double
+PyFloat_AsDouble(PyObject *op)
+{
+	PyNumberMethods *nb;
+	PyFloatObject *fo;
+	double val;
+
+	if (op && PyFloat_Check(op))
+		return PyFloat_AS_DOUBLE((PyFloatObject*) op);
+
+	if (op == NULL) {
+		PyErr_BadArgument();
+		return -1;
+	}
+
+	if ((nb = Py_TYPE(op)->tp_as_number) == NULL || nb->nb_float == NULL) {
+		PyErr_SetString(PyExc_TypeError, "a float is required");
+		return -1;
+	}
+
+	fo = (PyFloatObject*) (*nb->nb_float) (op);
+	if (fo == NULL)
+		return -1;
+	if (!PyFloat_Check(fo)) {
+		PyErr_SetString(PyExc_TypeError,
+				"nb_float should return float object");
+		return -1;
+	}
+
+	val = PyFloat_AS_DOUBLE(fo);
+	Py_DECREF(fo);
+
+	return val;
+}
+
+/* Methods */
+
+static void
+format_float(char *buf, size_t buflen, PyFloatObject *v, int precision)
+{
+	register char *cp;
+	char format[32];
+	int i;
+
+	/* Subroutine for float_repr and float_print.
+	   We want float numbers to be recognizable as such,
+	   i.e., they should contain a decimal point or an exponent.
+	   However, %g may print the number as an integer;
+	   in such cases, we append ".0" to the string. */
+
+	assert(PyFloat_Check(v));
+	PyOS_snprintf(format, 32, "%%.%ig", precision);
+	PyOS_ascii_formatd(buf, buflen, format, v->ob_fval);
+	cp = buf;
+	if (*cp == '-')
+		cp++;
+	for (; *cp != '\0'; cp++) {
+		/* Any non-digit means it's not an integer;
+		   this takes care of NAN and INF as well. */
+		if (!isdigit(Py_CHARMASK(*cp)))
+			break;
+	}
+	if (*cp == '\0') {
+		*cp++ = '.';
+		*cp++ = '0';
+		*cp++ = '\0';
+		return;
+	}
+	/* Checking the next three chars should be more than enough to
+	 * detect inf or nan, even on Windows. We check for inf or nan
+	 * at last because they are rare cases.
+	 */
+	for (i=0; *cp != '\0' && i<3; cp++, i++) {
+		if (isdigit(Py_CHARMASK(*cp)) || *cp == '.')
+			continue;
+		/* found something that is neither a digit nor point
+		 * it might be a NaN or INF
+		 */
+#ifdef Py_NAN
+		if (Py_IS_NAN(v->ob_fval)) {
+			strcpy(buf, "nan");
+		}
+                else
+#endif
+		if (Py_IS_INFINITY(v->ob_fval)) {
+			cp = buf;
+			if (*cp == '-')
+				cp++;
+			strcpy(cp, "inf");
+		}
+		break;
+	}
+
+}
+
+/* XXX PyFloat_AsStringEx should not be a public API function (for one
+   XXX thing, its signature passes a buffer without a length; for another,
+   XXX it isn't useful outside this file).
+*/
+void
+PyFloat_AsStringEx(char *buf, PyFloatObject *v, int precision)
+{
+	format_float(buf, 100, v, precision);
+}
+
+/* Macro and helper that convert PyObject obj to a C double and store
+   the value in dbl; this replaces the functionality of the coercion
+   slot function.  If conversion to double raises an exception, obj is
+   set to NULL, and the function invoking this macro returns NULL.  If
+   obj is not of float, int or long type, Py_NotImplemented is incref'ed,
+   stored in obj, and returned from the function invoking this macro.
+*/
+#define CONVERT_TO_DOUBLE(obj, dbl)			\
+	if (PyFloat_Check(obj))				\
+		dbl = PyFloat_AS_DOUBLE(obj);		\
+	else if (convert_to_double(&(obj), &(dbl)) < 0)	\
+		return obj;
+
+static int
+convert_to_double(PyObject **v, double *dbl)
+{
+	register PyObject *obj = *v;
+
+	if (PyInt_Check(obj)) {
+		*dbl = (double)PyInt_AS_LONG(obj);
+	}
+	else if (PyLong_Check(obj)) {
+		*dbl = PyLong_AsDouble(obj);
+		if (*dbl == -1.0 && PyErr_Occurred()) {
+			*v = NULL;
+			return -1;
+		}
+	}
+	else {
+		Py_INCREF(Py_NotImplemented);
+		*v = Py_NotImplemented;
+		return -1;
+	}
+	return 0;
+}
+
+/* Precisions used by repr() and str(), respectively.
+
+   The repr() precision (17 significant decimal digits) is the minimal number
+   that is guaranteed to have enough precision so that if the number is read
+   back in the exact same binary value is recreated.  This is true for IEEE
+   floating point by design, and also happens to work for all other modern
+   hardware.
+
+   The str() precision is chosen so that in most cases, the rounding noise
+   created by various operations is suppressed, while giving plenty of
+   precision for practical use.
+
+*/
+
+#define PREC_REPR	17
+#define PREC_STR	12
+
+/* XXX PyFloat_AsString and PyFloat_AsReprString should be deprecated:
+   XXX they pass a char buffer without passing a length.
+*/
+void
+PyFloat_AsString(char *buf, PyFloatObject *v)
+{
+	format_float(buf, 100, v, PREC_STR);
+}
+
+void
+PyFloat_AsReprString(char *buf, PyFloatObject *v)
+{
+	format_float(buf, 100, v, PREC_REPR);
+}
+
+/* ARGSUSED */
+static int
+float_print(PyFloatObject *v, FILE *fp, int flags)
+{
+	char buf[100];
+	format_float(buf, sizeof(buf), v,
+		     (flags & Py_PRINT_RAW) ? PREC_STR : PREC_REPR);
+	Py_BEGIN_ALLOW_THREADS
+	fputs(buf, fp);
+	Py_END_ALLOW_THREADS
+	return 0;
+}
+
+static PyObject *
+float_repr(PyFloatObject *v)
+{
+	char buf[100];
+	format_float(buf, sizeof(buf), v, PREC_REPR);
+
+	return PyString_FromString(buf);
+}
+
+static PyObject *
+float_str(PyFloatObject *v)
+{
+	char buf[100];
+	format_float(buf, sizeof(buf), v, PREC_STR);
+	return PyString_FromString(buf);
+}
+
+/* Comparison is pretty much a nightmare.  When comparing float to float,
+ * we do it as straightforwardly (and long-windedly) as conceivable, so
+ * that, e.g., Python x == y delivers the same result as the platform
+ * C x == y when x and/or y is a NaN.
+ * When mixing float with an integer type, there's no good *uniform* approach.
+ * Converting the double to an integer obviously doesn't work, since we
+ * may lose info from fractional bits.  Converting the integer to a double
+ * also has two failure modes:  (1) a long int may trigger overflow (too
+ * large to fit in the dynamic range of a C double); (2) even a C long may have
+ * more bits than fit in a C double (e.g., on a a 64-bit box long may have
+ * 63 bits of precision, but a C double probably has only 53), and then
+ * we can falsely claim equality when low-order integer bits are lost by
+ * coercion to double.  So this part is painful too.
+ */
+
+static PyObject*
+float_richcompare(PyObject *v, PyObject *w, int op)
+{
+	double i, j;
+	int r = 0;
+
+	assert(PyFloat_Check(v));
+	i = PyFloat_AS_DOUBLE(v);
+
+	/* Switch on the type of w.  Set i and j to doubles to be compared,
+	 * and op to the richcomp to use.
+	 */
+	if (PyFloat_Check(w))
+		j = PyFloat_AS_DOUBLE(w);
+
+	else if (!Py_IS_FINITE(i)) {
+		if (PyInt_Check(w) || PyLong_Check(w))
+			/* If i is an infinity, its magnitude exceeds any
+			 * finite integer, so it doesn't matter which int we
+			 * compare i with.  If i is a NaN, similarly.
+			 */
+			j = 0.0;
+		else
+			goto Unimplemented;
+	}
+
+	else if (PyInt_Check(w)) {
+		long jj = PyInt_AS_LONG(w);
+		/* In the worst realistic case I can imagine, C double is a
+		 * Cray single with 48 bits of precision, and long has 64
+		 * bits.
+		 */
+#if SIZEOF_LONG > 6
+		unsigned long abs = (unsigned long)(jj < 0 ? -jj : jj);
+		if (abs >> 48) {
+			/* Needs more than 48 bits.  Make it take the
+			 * PyLong path.
+			 */
+			PyObject *result;
+			PyObject *ww = PyLong_FromLong(jj);
+
+			if (ww == NULL)
+				return NULL;
+			result = float_richcompare(v, ww, op);
+			Py_DECREF(ww);
+			return result;
+		}
+#endif
+		j = (double)jj;
+		assert((long)j == jj);
+	}
+
+	else if (PyLong_Check(w)) {
+		int vsign = i == 0.0 ? 0 : i < 0.0 ? -1 : 1;
+		int wsign = _PyLong_Sign(w);
+		size_t nbits;
+		int exponent;
+
+		if (vsign != wsign) {
+			/* Magnitudes are irrelevant -- the signs alone
+			 * determine the outcome.
+			 */
+			i = (double)vsign;
+			j = (double)wsign;
+			goto Compare;
+		}
+		/* The signs are the same. */
+		/* Convert w to a double if it fits.  In particular, 0 fits. */
+		nbits = _PyLong_NumBits(w);
+		if (nbits == (size_t)-1 && PyErr_Occurred()) {
+			/* This long is so large that size_t isn't big enough
+			 * to hold the # of bits.  Replace with little doubles
+			 * that give the same outcome -- w is so large that
+			 * its magnitude must exceed the magnitude of any
+			 * finite float.
+			 */
+			PyErr_Clear();
+			i = (double)vsign;
+			assert(wsign != 0);
+			j = wsign * 2.0;
+			goto Compare;
+		}
+		if (nbits <= 48) {
+			j = PyLong_AsDouble(w);
+			/* It's impossible that <= 48 bits overflowed. */
+			assert(j != -1.0 || ! PyErr_Occurred());
+			goto Compare;
+		}
+		assert(wsign != 0); /* else nbits was 0 */
+		assert(vsign != 0); /* if vsign were 0, then since wsign is
+		                     * not 0, we would have taken the
+		                     * vsign != wsign branch at the start */
+		/* We want to work with non-negative numbers. */
+		if (vsign < 0) {
+			/* "Multiply both sides" by -1; this also swaps the
+			 * comparator.
+			 */
+			i = -i;
+			op = _Py_SwappedOp[op];
+		}
+		assert(i > 0.0);
+		(void) frexp(i, &exponent);
+		/* exponent is the # of bits in v before the radix point;
+		 * we know that nbits (the # of bits in w) > 48 at this point
+		 */
+		if (exponent < 0 || (size_t)exponent < nbits) {
+			i = 1.0;
+			j = 2.0;
+			goto Compare;
+		}
+		if ((size_t)exponent > nbits) {
+			i = 2.0;
+			j = 1.0;
+			goto Compare;
+		}
+		/* v and w have the same number of bits before the radix
+		 * point.  Construct two longs that have the same comparison
+		 * outcome.
+		 */
+		{
+			double fracpart;
+			double intpart;
+			PyObject *result = NULL;
+			PyObject *one = NULL;
+			PyObject *vv = NULL;
+			PyObject *ww = w;
+
+			if (wsign < 0) {
+				ww = PyNumber_Negative(w);
+				if (ww == NULL)
+					goto Error;
+			}
+			else
+				Py_INCREF(ww);
+
+			fracpart = modf(i, &intpart);
+			vv = PyLong_FromDouble(intpart);
+			if (vv == NULL)
+				goto Error;
+
+			if (fracpart != 0.0) {
+				/* Shift left, and or a 1 bit into vv
+				 * to represent the lost fraction.
+				 */
+				PyObject *temp;
+
+				one = PyInt_FromLong(1);
+				if (one == NULL)
+					goto Error;
+
+				temp = PyNumber_Lshift(ww, one);
+				if (temp == NULL)
+					goto Error;
+				Py_DECREF(ww);
+				ww = temp;
+
+				temp = PyNumber_Lshift(vv, one);
+				if (temp == NULL)
+					goto Error;
+				Py_DECREF(vv);
+				vv = temp;
+
+				temp = PyNumber_Or(vv, one);
+				if (temp == NULL)
+					goto Error;
+				Py_DECREF(vv);
+				vv = temp;
+			}
+
+			r = PyObject_RichCompareBool(vv, ww, op);
+			if (r < 0)
+				goto Error;
+			result = PyBool_FromLong(r);
+ 		 Error:
+ 		 	Py_XDECREF(vv);
+ 		 	Py_XDECREF(ww);
+ 		 	Py_XDECREF(one);
+ 		 	return result;
+		}
+	} /* else if (PyLong_Check(w)) */
+
+	else	/* w isn't float, int, or long */
+		goto Unimplemented;
+
+ Compare:
+	PyFPE_START_PROTECT("richcompare", return NULL)
+	switch (op) {
+	case Py_EQ:
+		r = i == j;
+		break;
+	case Py_NE:
+		r = i != j;
+		break;
+	case Py_LE:
+		r = i <= j;
+		break;
+	case Py_GE:
+		r = i >= j;
+		break;
+	case Py_LT:
+		r = i < j;
+		break;
+	case Py_GT:
+		r = i > j;
+		break;
+	}
+	PyFPE_END_PROTECT(r)
+	return PyBool_FromLong(r);
+
+ Unimplemented:
+	Py_INCREF(Py_NotImplemented);
+	return Py_NotImplemented;
+}
+
+static long
+float_hash(PyFloatObject *v)
+{
+	return _Py_HashDouble(v->ob_fval);
+}
+
+static PyObject *
+float_add(PyObject *v, PyObject *w)
+{
+	double a,b;
+	CONVERT_TO_DOUBLE(v, a);
+	CONVERT_TO_DOUBLE(w, b);
+	PyFPE_START_PROTECT("add", return 0)
+	a = a + b;
+	PyFPE_END_PROTECT(a)
+	return PyFloat_FromDouble(a);
+}
+
+static PyObject *
+float_sub(PyObject *v, PyObject *w)
+{
+	double a,b;
+	CONVERT_TO_DOUBLE(v, a);
+	CONVERT_TO_DOUBLE(w, b);
+	PyFPE_START_PROTECT("subtract", return 0)
+	a = a - b;
+	PyFPE_END_PROTECT(a)
+	return PyFloat_FromDouble(a);
+}
+
+static PyObject *
+float_mul(PyObject *v, PyObject *w)
+{
+	double a,b;
+	CONVERT_TO_DOUBLE(v, a);
+	CONVERT_TO_DOUBLE(w, b);
+	PyFPE_START_PROTECT("multiply", return 0)
+	a = a * b;
+	PyFPE_END_PROTECT(a)
+	return PyFloat_FromDouble(a);
+}
+
+static PyObject *
+float_div(PyObject *v, PyObject *w)
+{
+	double a,b;
+	CONVERT_TO_DOUBLE(v, a);
+	CONVERT_TO_DOUBLE(w, b);
+#ifdef Py_NAN
+	if (b == 0.0) {
+		PyErr_SetString(PyExc_ZeroDivisionError,
+				"float division");
+		return NULL;
+	}
+#endif
+	PyFPE_START_PROTECT("divide", return 0)
+	a = a / b;
+	PyFPE_END_PROTECT(a)
+	return PyFloat_FromDouble(a);
+}
+
+static PyObject *
+float_classic_div(PyObject *v, PyObject *w)
+{
+	double a,b;
+	CONVERT_TO_DOUBLE(v, a);
+	CONVERT_TO_DOUBLE(w, b);
+	if (Py_DivisionWarningFlag >= 2 &&
+	    PyErr_Warn(PyExc_DeprecationWarning, "classic float division") < 0)
+		return NULL;
+#ifdef Py_NAN
+	if (b == 0.0) {
+		PyErr_SetString(PyExc_ZeroDivisionError,
+				"float division");
+		return NULL;
+	}
+#endif
+	PyFPE_START_PROTECT("divide", return 0)
+	a = a / b;
+	PyFPE_END_PROTECT(a)
+	return PyFloat_FromDouble(a);
+}
+
+static PyObject *
+float_rem(PyObject *v, PyObject *w)
+{
+	double vx, wx;
+	double mod;
+	CONVERT_TO_DOUBLE(v, vx);
+	CONVERT_TO_DOUBLE(w, wx);
+#ifdef Py_NAN
+	if (wx == 0.0) {
+		PyErr_SetString(PyExc_ZeroDivisionError,
+				"float modulo");
+		return NULL;
+	}
+#endif
+	PyFPE_START_PROTECT("modulo", return 0)
+	mod = fmod(vx, wx);
+	/* note: checking mod*wx < 0 is incorrect -- underflows to
+	   0 if wx < sqrt(smallest nonzero double) */
+	if (mod && ((wx < 0) != (mod < 0))) {
+		mod += wx;
+	}
+	PyFPE_END_PROTECT(mod)
+	return PyFloat_FromDouble(mod);
+}
+
+static PyObject *
+float_divmod(PyObject *v, PyObject *w)
+{
+	double vx, wx;
+	double div, mod, floordiv;
+ 	CONVERT_TO_DOUBLE(v, vx);
+ 	CONVERT_TO_DOUBLE(w, wx);
+	if (wx == 0.0) {
+		PyErr_SetString(PyExc_ZeroDivisionError, "float divmod()");
+		return NULL;
+	}
+	PyFPE_START_PROTECT("divmod", return 0)
+	mod = fmod(vx, wx);
+	/* fmod is typically exact, so vx-mod is *mathematically* an
+	   exact multiple of wx.  But this is fp arithmetic, and fp
+	   vx - mod is an approximation; the result is that div may
+	   not be an exact integral value after the division, although
+	   it will always be very close to one.
+	*/
+	div = (vx - mod) / wx;
+	if (mod) {
+		/* ensure the remainder has the same sign as the denominator */
+		if ((wx < 0) != (mod < 0)) {
+			mod += wx;
+			div -= 1.0;
+		}
+	}
+	else {
+		/* the remainder is zero, and in the presence of signed zeroes
+		   fmod returns different results across platforms; ensure
+		   it has the same sign as the denominator; we'd like to do
+		   "mod = wx * 0.0", but that may get optimized away */
+		mod *= mod;  /* hide "mod = +0" from optimizer */
+		if (wx < 0.0)
+			mod = -mod;
+	}
+	/* snap quotient to nearest integral value */
+	if (div) {
+		floordiv = floor(div);
+		if (div - floordiv > 0.5)
+			floordiv += 1.0;
+	}
+	else {
+		/* div is zero - get the same sign as the true quotient */
+		div *= div;	/* hide "div = +0" from optimizers */
+		floordiv = div * vx / wx; /* zero w/ sign of vx/wx */
+	}
+	PyFPE_END_PROTECT(floordiv)
+	return Py_BuildValue("(dd)", floordiv, mod);
+}
+
+static PyObject *
+float_floor_div(PyObject *v, PyObject *w)
+{
+	PyObject *t, *r;
+
+	t = float_divmod(v, w);
+	if (t == NULL || t == Py_NotImplemented)
+		return t;
+	assert(PyTuple_CheckExact(t));
+	r = PyTuple_GET_ITEM(t, 0);
+	Py_INCREF(r);
+	Py_DECREF(t);
+	return r;
+}
+
+static PyObject *
+float_pow(PyObject *v, PyObject *w, PyObject *z)
+{
+	double iv, iw, ix;
+
+	if ((PyObject *)z != Py_None) {
+		PyErr_SetString(PyExc_TypeError, "pow() 3rd argument not "
+			"allowed unless all arguments are integers");
+		return NULL;
+	}
+
+	CONVERT_TO_DOUBLE(v, iv);
+	CONVERT_TO_DOUBLE(w, iw);
+
+	/* Sort out special cases here instead of relying on pow() */
+	if (iw == 0) { 		/* v**0 is 1, even 0**0 */
+		return PyFloat_FromDouble(1.0);
+	}
+	if (iv == 0.0) {  /* 0**w is error if w<0, else 1 */
+		if (iw < 0.0) {
+			PyErr_SetString(PyExc_ZeroDivisionError,
+					"0.0 cannot be raised to a negative power");
+			return NULL;
+		}
+		return PyFloat_FromDouble(0.0);
+	}
+	if (iv == 1.0) { /* 1**w is 1, even 1**inf and 1**nan */
+		return PyFloat_FromDouble(1.0);
+	}
+	if (iv < 0.0) {
+		/* Whether this is an error is a mess, and bumps into libm
+		 * bugs so we have to figure it out ourselves.
+		 */
+		if (iw != floor(iw)) {
+			PyErr_SetString(PyExc_ValueError, "negative number "
+				"cannot be raised to a fractional power");
+			return NULL;
+		}
+		/* iw is an exact integer, albeit perhaps a very large one.
+		 * -1 raised to an exact integer should never be exceptional.
+		 * Alas, some libms (chiefly glibc as of early 2003) return
+		 * NaN and set EDOM on pow(-1, large_int) if the int doesn't
+		 * happen to be representable in a *C* integer.  That's a
+		 * bug; we let that slide in math.pow() (which currently
+		 * reflects all platform accidents), but not for Python's **.
+		 */
+		 if (iv == -1.0 && Py_IS_FINITE(iw)) {
+		 	/* Return 1 if iw is even, -1 if iw is odd; there's
+		 	 * no guarantee that any C integral type is big
+		 	 * enough to hold iw, so we have to check this
+		 	 * indirectly.
+		 	 */
+		 	ix = floor(iw * 0.5) * 2.0;
+			return PyFloat_FromDouble(ix == iw ? 1.0 : -1.0);
+		}
+		/* Else iv != -1.0, and overflow or underflow are possible.
+		 * Unless we're to write pow() ourselves, we have to trust
+		 * the platform to do this correctly.
+		 */
+	}
+	errno = 0;
+	PyFPE_START_PROTECT("pow", return NULL)
+	ix = pow(iv, iw);
+	PyFPE_END_PROTECT(ix)
+	Py_ADJUST_ERANGE1(ix);
+	if (errno != 0) {
+		/* We don't expect any errno value other than ERANGE, but
+		 * the range of libm bugs appears unbounded.
+		 */
+		PyErr_SetFromErrno(errno == ERANGE ? PyExc_OverflowError :
+						     PyExc_ValueError);
+		return NULL;
+	}
+	return PyFloat_FromDouble(ix);
+}
+
+static PyObject *
+float_neg(PyFloatObject *v)
+{
+	return PyFloat_FromDouble(-v->ob_fval);
+}
+
+static PyObject *
+float_abs(PyFloatObject *v)
+{
+	return PyFloat_FromDouble(fabs(v->ob_fval));
+}
+
+static int
+float_nonzero(PyFloatObject *v)
+{
+	return v->ob_fval != 0.0;
+}
+
+static int
+float_coerce(PyObject **pv, PyObject **pw)
+{
+	if (PyInt_Check(*pw)) {
+		long x = PyInt_AsLong(*pw);
+		*pw = PyFloat_FromDouble((double)x);
+		Py_INCREF(*pv);
+		return 0;
+	}
+	else if (PyLong_Check(*pw)) {
+		double x = PyLong_AsDouble(*pw);
+		if (x == -1.0 && PyErr_Occurred())
+			return -1;
+		*pw = PyFloat_FromDouble(x);
+		Py_INCREF(*pv);
+		return 0;
+	}
+	else if (PyFloat_Check(*pw)) {
+		Py_INCREF(*pv);
+		Py_INCREF(*pw);
+		return 0;
+	}
+	return 1; /* Can't do it */
+}
+
+static PyObject *
+float_is_integer(PyObject *v)
+{
+	double x = PyFloat_AsDouble(v);
+	PyObject *o;
+	
+	if (x == -1.0 && PyErr_Occurred())
+		return NULL;
+	if (!Py_IS_FINITE(x))
+		Py_RETURN_FALSE;
+	errno = 0;
+	PyFPE_START_PROTECT("is_integer", return NULL)
+	o = (floor(x) == x) ? Py_True : Py_False;
+	PyFPE_END_PROTECT(x)
+	if (errno != 0) {
+		PyErr_SetFromErrno(errno == ERANGE ? PyExc_OverflowError :
+						     PyExc_ValueError);
+		return NULL;
+	}
+	Py_INCREF(o);
+	return o;
+}
+
+#if 0
+static PyObject *
+float_is_inf(PyObject *v)
+{
+	double x = PyFloat_AsDouble(v);
+	if (x == -1.0 && PyErr_Occurred())
+		return NULL;
+	return PyBool_FromLong((long)Py_IS_INFINITY(x));
+}
+
+static PyObject *
+float_is_nan(PyObject *v)
+{
+	double x = PyFloat_AsDouble(v);
+	if (x == -1.0 && PyErr_Occurred())
+		return NULL;
+	return PyBool_FromLong((long)Py_IS_NAN(x));
+}
+
+static PyObject *
+float_is_finite(PyObject *v)
+{
+	double x = PyFloat_AsDouble(v);
+	if (x == -1.0 && PyErr_Occurred())
+		return NULL;
+	return PyBool_FromLong((long)Py_IS_FINITE(x));
+}
+#endif
+
+static PyObject *
+float_trunc(PyObject *v)
+{
+	double x = PyFloat_AsDouble(v);
+	double wholepart;	/* integral portion of x, rounded toward 0 */
+
+	(void)modf(x, &wholepart);
+	/* Try to get out cheap if this fits in a Python int.  The attempt
+	 * to cast to long must be protected, as C doesn't define what
+	 * happens if the double is too big to fit in a long.  Some rare
+	 * systems raise an exception then (RISCOS was mentioned as one,
+	 * and someone using a non-default option on Sun also bumped into
+	 * that).  Note that checking for >= and <= LONG_{MIN,MAX} would
+	 * still be vulnerable:  if a long has more bits of precision than
+	 * a double, casting MIN/MAX to double may yield an approximation,
+	 * and if that's rounded up, then, e.g., wholepart=LONG_MAX+1 would
+	 * yield true from the C expression wholepart<=LONG_MAX, despite
+	 * that wholepart is actually greater than LONG_MAX.
+	 */
+	if (LONG_MIN < wholepart && wholepart < LONG_MAX) {
+		const long aslong = (long)wholepart;
+		return PyInt_FromLong(aslong);
+	}
+	return PyLong_FromDouble(wholepart);
+}
+
+static PyObject *
+float_long(PyObject *v)
+{
+	double x = PyFloat_AsDouble(v);
+	return PyLong_FromDouble(x);
+}
+
+static PyObject *
+float_float(PyObject *v)
+{
+	if (PyFloat_CheckExact(v))
+		Py_INCREF(v);
+	else
+		v = PyFloat_FromDouble(((PyFloatObject *)v)->ob_fval);
+	return v;
+}
+
+/* turn ASCII hex characters into integer values and vice versa */
+
+static char
+char_from_hex(int x)
+{
+	assert(0 <= x && x < 16);
+	return "0123456789abcdef"[x];
+}
+
+static int
+hex_from_char(char c) {
+	int x;
+	switch(c) {
+	case '0':
+		x = 0;
+		break;
+	case '1':
+		x = 1;
+		break;
+	case '2':
+		x = 2;
+		break;
+	case '3':
+		x = 3;
+		break;
+	case '4':
+		x = 4;
+		break;
+	case '5':
+		x = 5;
+		break;
+	case '6':
+		x = 6;
+		break;
+	case '7':
+		x = 7;
+		break;
+	case '8':
+		x = 8;
+		break;
+	case '9':
+		x = 9;
+		break;
+	case 'a':
+	case 'A':
+		x = 10;
+		break;
+	case 'b':
+	case 'B':
+		x = 11;
+		break;
+	case 'c':
+	case 'C':
+		x = 12;
+		break;
+	case 'd':
+	case 'D':
+		x = 13;
+		break;
+	case 'e':
+	case 'E':
+		x = 14;
+		break;
+	case 'f':
+	case 'F':
+		x = 15;
+		break;
+	default:
+		x = -1;
+		break;
+	}
+	return x;
+}
+
+/* convert a float to a hexadecimal string */
+
+/* TOHEX_NBITS is DBL_MANT_DIG rounded up to the next integer
+   of the form 4k+1. */
+#define TOHEX_NBITS DBL_MANT_DIG + 3 - (DBL_MANT_DIG+2)%4
+
+static PyObject *
+float_hex(PyObject *v)
+{
+	double x, m;
+	int e, shift, i, si, esign;
+	/* Space for 1+(TOHEX_NBITS-1)/4 digits, a decimal point, and the
+	   trailing NUL byte. */
+	char s[(TOHEX_NBITS-1)/4+3];
+
+	CONVERT_TO_DOUBLE(v, x);
+
+	if (Py_IS_NAN(x) || Py_IS_INFINITY(x))
+		return float_str((PyFloatObject *)v);
+
+	if (x == 0.0) {
+		if(copysign(1.0, x) == -1.0)
+			return PyString_FromString("-0x0.0p+0");
+		else
+			return PyString_FromString("0x0.0p+0");
+	}
+
+	m = frexp(fabs(x), &e);
+	shift = 1 - MAX(DBL_MIN_EXP - e, 0);
+	m = ldexp(m, shift);
+	e -= shift;
+
+	si = 0;
+	s[si] = char_from_hex((int)m);
+	si++;
+	m -= (int)m;
+	s[si] = '.';
+	si++;
+	for (i=0; i < (TOHEX_NBITS-1)/4; i++) {
+		m *= 16.0;
+		s[si] = char_from_hex((int)m);
+		si++;
+		m -= (int)m;
+	}
+	s[si] = '\0';
+
+	if (e < 0) {
+		esign = (int)'-';
+		e = -e;
+	}
+	else
+		esign = (int)'+';
+
+	if (x < 0.0)
+		return PyString_FromFormat("-0x%sp%c%d", s, esign, e);
+	else
+		return PyString_FromFormat("0x%sp%c%d", s, esign, e);
+}
+
+PyDoc_STRVAR(float_hex_doc,
+"float.hex() -> string\n\
+\n\
+Return a hexadecimal representation of a floating-point number.\n\
+>>> (-0.1).hex()\n\
+'-0x1.999999999999ap-4'\n\
+>>> 3.14159.hex()\n\
+'0x1.921f9f01b866ep+1'");
+
+/* Convert a hexadecimal string to a float. */
+
+static PyObject *
+float_fromhex(PyObject *cls, PyObject *arg)
+{
+	PyObject *result_as_float, *result;
+	double x;
+	long exp, top_exp, lsb, key_digit;
+	char *s, *coeff_start, *s_store, *coeff_end, *exp_start, *s_end;
+	int half_eps, digit, round_up, sign=1;
+	Py_ssize_t length, ndigits, fdigits, i;
+
+	/*
+	 * For the sake of simplicity and correctness, we impose an artificial
+	 * limit on ndigits, the total number of hex digits in the coefficient
+	 * The limit is chosen to ensure that, writing exp for the exponent,
+	 *
+	 *   (1) if exp > LONG_MAX/2 then the value of the hex string is
+	 *   guaranteed to overflow (provided it's nonzero)
+	 *
+	 *   (2) if exp < LONG_MIN/2 then the value of the hex string is
+	 *   guaranteed to underflow to 0.
+	 *
+	 *   (3) if LONG_MIN/2 <= exp <= LONG_MAX/2 then there's no danger of
+	 *   overflow in the calculation of exp and top_exp below.
+	 *
+	 * More specifically, ndigits is assumed to satisfy the following
+	 * inequalities:
+	 *
+	 *   4*ndigits <= DBL_MIN_EXP - DBL_MANT_DIG - LONG_MIN/2
+	 *   4*ndigits <= LONG_MAX/2 + 1 - DBL_MAX_EXP
+	 *
+	 * If either of these inequalities is not satisfied, a ValueError is
+	 * raised.  Otherwise, write x for the value of the hex string, and
+	 * assume x is nonzero.  Then
+	 *
+	 *   2**(exp-4*ndigits) <= |x| < 2**(exp+4*ndigits).
+	 *
+	 * Now if exp > LONG_MAX/2 then:
+	 *
+	 *   exp - 4*ndigits >= LONG_MAX/2 + 1 - (LONG_MAX/2 + 1 - DBL_MAX_EXP)
+	 *                    = DBL_MAX_EXP
+	 *
+	 * so |x| >= 2**DBL_MAX_EXP, which is too large to be stored in C
+	 * double, so overflows.  If exp < LONG_MIN/2, then
+	 *
+	 *   exp + 4*ndigits <= LONG_MIN/2 - 1 + (
+	 *                      DBL_MIN_EXP - DBL_MANT_DIG - LONG_MIN/2)
+	 *                    = DBL_MIN_EXP - DBL_MANT_DIG - 1
+	 *
+	 * and so |x| < 2**(DBL_MIN_EXP-DBL_MANT_DIG-1), hence underflows to 0
+	 * when converted to a C double.
+	 *
+	 * It's easy to show that if LONG_MIN/2 <= exp <= LONG_MAX/2 then both
+	 * exp+4*ndigits and exp-4*ndigits are within the range of a long.
+	 */
+
+	if (PyString_AsStringAndSize(arg, &s, &length))
+		return NULL;
+	s_end = s + length;
+
+	/********************
+	 * Parse the string *
+	 ********************/
+
+	/* leading whitespace and optional sign */
+	while (isspace(*s))
+		s++;
+	if (*s == '-') {
+		s++;
+		sign = -1;
+	}
+	else if (*s == '+')
+		s++;
+
+	/* infinities and nans */
+	if (PyOS_strnicmp(s, "nan", 4) == 0) {
+		x = Py_NAN;
+		goto finished;
+	}
+	if (PyOS_strnicmp(s, "inf", 4) == 0 ||
+	    PyOS_strnicmp(s, "infinity", 9) == 0) {
+		x = sign*Py_HUGE_VAL;
+		goto finished;
+	}
+
+	/* [0x] */
+	s_store = s;
+	if (*s == '0') {
+		s++;
+		if (tolower(*s) == (int)'x')
+			s++;
+		else
+			s = s_store;
+	}
+
+	/* coefficient: <integer> [. <fraction>] */
+	coeff_start = s;
+	while (hex_from_char(*s) >= 0)
+		s++;
+	s_store = s;
+	if (*s == '.') {
+		s++;
+		while (hex_from_char(*s) >= 0)
+			s++;
+		coeff_end = s-1;
+	}
+	else
+		coeff_end = s;
+
+	/* ndigits = total # of hex digits; fdigits = # after point */
+	ndigits = coeff_end - coeff_start;
+	fdigits = coeff_end - s_store;
+	if (ndigits == 0)
+		goto parse_error;
+	if (ndigits > MIN(DBL_MIN_EXP - DBL_MANT_DIG - LONG_MIN/2,
+			  LONG_MAX/2 + 1 - DBL_MAX_EXP)/4)
+		goto insane_length_error;
+
+	/* [p <exponent>] */
+	if (tolower(*s) == (int)'p') {
+		s++;
+		exp_start = s;
+		if (*s == '-' || *s == '+')
+			s++;
+		if (!('0' <= *s && *s <= '9'))
+			goto parse_error;
+		s++;
+		while ('0' <= *s && *s <= '9')
+			s++;
+		exp = strtol(exp_start, NULL, 10);
+	}
+	else
+		exp = 0;
+
+	/* optional trailing whitespace leading to the end of the string */
+	while (isspace(*s))
+		s++;
+	if (s != s_end)
+		goto parse_error;
+
+/* for 0 <= j < ndigits, HEX_DIGIT(j) gives the jth most significant digit */
+#define HEX_DIGIT(j) hex_from_char(*((j) < fdigits ?		\
+				     coeff_end-(j) :			\
+				     coeff_end-1-(j)))
+
+	/*******************************************
+	 * Compute rounded value of the hex string *
+	 *******************************************/
+
+	/* Discard leading zeros, and catch extreme overflow and underflow */
+	while (ndigits > 0 && HEX_DIGIT(ndigits-1) == 0)
+		ndigits--;
+	if (ndigits == 0 || exp < LONG_MIN/2) {
+		x = sign * 0.0;
+		goto finished;
+	}
+	if (exp > LONG_MAX/2)
+		goto overflow_error;
+
+	/* Adjust exponent for fractional part. */
+	exp = exp - 4*((long)fdigits);
+
+	/* top_exp = 1 more than exponent of most sig. bit of coefficient */
+	top_exp = exp + 4*((long)ndigits - 1);
+	for (digit = HEX_DIGIT(ndigits-1); digit != 0; digit /= 2)
+		top_exp++;
+
+	/* catch almost all nonextreme cases of overflow and underflow here */
+	if (top_exp < DBL_MIN_EXP - DBL_MANT_DIG) {
+		x = sign * 0.0;
+		goto finished;
+	}
+	if (top_exp > DBL_MAX_EXP)
+		goto overflow_error;
+
+	/* lsb = exponent of least significant bit of the *rounded* value.
+	   This is top_exp - DBL_MANT_DIG unless result is subnormal. */
+	lsb = MAX(top_exp, (long)DBL_MIN_EXP) - DBL_MANT_DIG;
+
+	x = 0.0;
+	if (exp >= lsb) {
+		/* no rounding required */
+		for (i = ndigits-1; i >= 0; i--)
+			x = 16.0*x + HEX_DIGIT(i);
+		x = sign * ldexp(x, (int)(exp));
+		goto finished;
+	}
+	/* rounding required.  key_digit is the index of the hex digit
+	   containing the first bit to be rounded away. */
+	half_eps = 1 << (int)((lsb - exp - 1) % 4);
+	key_digit = (lsb - exp - 1) / 4;
+	for (i = ndigits-1; i > key_digit; i--)
+		x = 16.0*x + HEX_DIGIT(i);
+	digit = HEX_DIGIT(key_digit);
+	x = 16.0*x + (double)(digit & (16-2*half_eps));
+
+	/* round-half-even: round up if bit lsb-1 is 1 and at least one of
+	   bits lsb, lsb-2, lsb-3, lsb-4, ... is 1. */
+	if ((digit & half_eps) != 0) {
+		round_up = 0;
+		if ((digit & (3*half_eps-1)) != 0 ||
+		    (half_eps == 8 && (HEX_DIGIT(key_digit+1) & 1) != 0))
+			round_up = 1;
+		else
+			for (i = key_digit-1; i >= 0; i--)
+				if (HEX_DIGIT(i) != 0) {
+					round_up = 1;
+					break;
+				}
+		if (round_up == 1) {
+			x += 2*half_eps;
+			if (top_exp == DBL_MAX_EXP &&
+			    x == ldexp((double)(2*half_eps), DBL_MANT_DIG))
+				/* overflow corner case: pre-rounded value <
+				   2**DBL_MAX_EXP; rounded=2**DBL_MAX_EXP. */
+				goto overflow_error;
+		}
+	}
+	x = sign * ldexp(x, (int)(exp+4*key_digit));
+
+  finished:
+	result_as_float = Py_BuildValue("(d)", x);
+	if (result_as_float == NULL)
+		return NULL;
+	result = PyObject_CallObject(cls, result_as_float);
+	Py_DECREF(result_as_float);
+	return result;
+
+  overflow_error:
+	PyErr_SetString(PyExc_OverflowError,
+			"hexadecimal value too large to represent as a float");
+	return NULL;
+
+  parse_error:
+	PyErr_SetString(PyExc_ValueError,
+			"invalid hexadecimal floating-point string");
+	return NULL;
+
+  insane_length_error:
+	PyErr_SetString(PyExc_ValueError,
+			"hexadecimal string too long to convert");
+	return NULL;
+}
+
+PyDoc_STRVAR(float_fromhex_doc,
+"float.fromhex(string) -> float\n\
+\n\
+Create a floating-point number from a hexadecimal string.\n\
+>>> float.fromhex('0x1.ffffp10')\n\
+2047.984375\n\
+>>> float.fromhex('-0x1p-1074')\n\
+-4.9406564584124654e-324");
+
+
+static PyObject *
+float_as_integer_ratio(PyObject *v, PyObject *unused)
+{
+	double self;
+	double float_part;
+	int exponent;
+	int i;
+
+	PyObject *prev;
+	PyObject *py_exponent = NULL;
+	PyObject *numerator = NULL;
+	PyObject *denominator = NULL;
+	PyObject *result_pair = NULL;
+	PyNumberMethods *long_methods = PyLong_Type.tp_as_number;
+
+#define INPLACE_UPDATE(obj, call) \
+	prev = obj; \
+	obj = call; \
+	Py_DECREF(prev); \
+
+	CONVERT_TO_DOUBLE(v, self);
+
+	if (Py_IS_INFINITY(self)) {
+	  PyErr_SetString(PyExc_OverflowError,
+			  "Cannot pass infinity to float.as_integer_ratio.");
+	  return NULL;
+	}
+#ifdef Py_NAN
+	if (Py_IS_NAN(self)) {
+	  PyErr_SetString(PyExc_ValueError,
+			  "Cannot pass NaN to float.as_integer_ratio.");
+	  return NULL;
+	}
+#endif
+
+	PyFPE_START_PROTECT("as_integer_ratio", goto error);
+	float_part = frexp(self, &exponent);  	/* self == float_part * 2**exponent exactly */
+	PyFPE_END_PROTECT(float_part);
+	
+	for (i=0; i<300 && float_part != floor(float_part) ; i++) {
+		float_part *= 2.0;
+		exponent--;
+	}	
+	/* self == float_part * 2**exponent exactly and float_part is integral.
+           If FLT_RADIX != 2, the 300 steps may leave a tiny fractional part
+           to be truncated by PyLong_FromDouble(). */
+
+	numerator = PyLong_FromDouble(float_part);
+	if (numerator == NULL) goto error;
+
+	/* fold in 2**exponent */
+	denominator = PyLong_FromLong(1);
+	py_exponent = PyLong_FromLong(labs((long)exponent));
+	if (py_exponent == NULL) goto error;
+	INPLACE_UPDATE(py_exponent,
+		       long_methods->nb_lshift(denominator, py_exponent));
+	if (py_exponent == NULL) goto error;
+	if (exponent > 0) {
+		INPLACE_UPDATE(numerator,
+			       long_methods->nb_multiply(numerator, py_exponent));
+		if (numerator == NULL) goto error;
+	}
+	else {
+		Py_DECREF(denominator);
+		denominator = py_exponent;
+		py_exponent = NULL;
+	}
+
+	/* Returns ints instead of longs where possible */
+	INPLACE_UPDATE(numerator, PyNumber_Int(numerator));
+	if (numerator == NULL) goto error;
+	INPLACE_UPDATE(denominator, PyNumber_Int(denominator));
+	if (denominator == NULL) goto error;
+
+	result_pair = PyTuple_Pack(2, numerator, denominator);
+
+#undef INPLACE_UPDATE
+error:
+	Py_XDECREF(py_exponent);
+	Py_XDECREF(denominator);
+	Py_XDECREF(numerator);
+	return result_pair;
+}
+
+PyDoc_STRVAR(float_as_integer_ratio_doc,
+"float.as_integer_ratio() -> (int, int)\n"
+"\n"
+"Returns a pair of integers, whose ratio is exactly equal to the original\n"
+"float and with a positive denominator.\n"
+"Raises OverflowError on infinities and a ValueError on NaNs.\n"
+"\n"
+">>> (10.0).as_integer_ratio()\n"
+"(10, 1)\n"
+">>> (0.0).as_integer_ratio()\n"
+"(0, 1)\n"
+">>> (-.25).as_integer_ratio()\n"
+"(-1, 4)");
+
+
+static PyObject *
+float_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
+
+static PyObject *
+float_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+	PyObject *x = Py_False; /* Integer zero */
+	static char *kwlist[] = {"x", 0};
+
+	if (type != &PyFloat_Type)
+		return float_subtype_new(type, args, kwds); /* Wimp out */
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:float", kwlist, &x))
+		return NULL;
+	if (PyString_Check(x))
+		return PyFloat_FromString(x, NULL);
+	return PyNumber_Float(x);
+}
+
+/* Wimpy, slow approach to tp_new calls for subtypes of float:
+   first create a regular float from whatever arguments we got,
+   then allocate a subtype instance and initialize its ob_fval
+   from the regular float.  The regular float is then thrown away.
+*/
+static PyObject *
+float_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+	PyObject *tmp, *newobj;
+
+	assert(PyType_IsSubtype(type, &PyFloat_Type));
+	tmp = float_new(&PyFloat_Type, args, kwds);
+	if (tmp == NULL)
+		return NULL;
+	assert(PyFloat_CheckExact(tmp));
+	newobj = type->tp_alloc(type, 0);
+	if (newobj == NULL) {
+		Py_DECREF(tmp);
+		return NULL;
+	}
+	((PyFloatObject *)newobj)->ob_fval = ((PyFloatObject *)tmp)->ob_fval;
+	Py_DECREF(tmp);
+	return newobj;
+}
+
+static PyObject *
+float_getnewargs(PyFloatObject *v)
+{
+	return Py_BuildValue("(d)", v->ob_fval);
+}
+
+/* this is for the benefit of the pack/unpack routines below */
+
+typedef enum {
+	unknown_format, ieee_big_endian_format, ieee_little_endian_format
+} float_format_type;
+
+static float_format_type double_format, float_format;
+static float_format_type detected_double_format, detected_float_format;
+
+static PyObject *
+float_getformat(PyTypeObject *v, PyObject* arg)
+{
+	char* s;
+	float_format_type r;
+
+	if (!PyString_Check(arg)) {
+		PyErr_Format(PyExc_TypeError,
+	     "__getformat__() argument must be string, not %.500s",
+			     Py_TYPE(arg)->tp_name);
+		return NULL;
+	}
+	s = PyString_AS_STRING(arg);
+	if (strcmp(s, "double") == 0) {
+		r = double_format;
+	}
+	else if (strcmp(s, "float") == 0) {
+		r = float_format;
+	}
+	else {
+		PyErr_SetString(PyExc_ValueError,
+				"__getformat__() argument 1 must be "
+				"'double' or 'float'");
+		return NULL;
+	}
+	
+	switch (r) {
+	case unknown_format:
+		return PyString_FromString("unknown");
+	case ieee_little_endian_format:
+		return PyString_FromString("IEEE, little-endian");
+	case ieee_big_endian_format:
+		return PyString_FromString("IEEE, big-endian");
+	default:
+		Py_FatalError("insane float_format or double_format");
+		return NULL;
+	}
+}
+
+PyDoc_STRVAR(float_getformat_doc,
+"float.__getformat__(typestr) -> string\n"
+"\n"
+"You probably don't want to use this function.  It exists mainly to be\n"
+"used in Python's test suite.\n"
+"\n"
+"typestr must be 'double' or 'float'.  This function returns whichever of\n"
+"'unknown', 'IEEE, big-endian' or 'IEEE, little-endian' best describes the\n"
+"format of floating point numbers used by the C type named by typestr.");
+
+static PyObject *
+float_setformat(PyTypeObject *v, PyObject* args)
+{
+	char* typestr;
+	char* format;
+	float_format_type f;
+	float_format_type detected;
+	float_format_type *p;
+
+	if (!PyArg_ParseTuple(args, "ss:__setformat__", &typestr, &format))
+		return NULL;
+
+	if (strcmp(typestr, "double") == 0) {
+		p = &double_format;
+		detected = detected_double_format;
+	}
+	else if (strcmp(typestr, "float") == 0) {
+		p = &float_format;
+		detected = detected_float_format;
+	}
+	else {
+		PyErr_SetString(PyExc_ValueError,
+				"__setformat__() argument 1 must "
+				"be 'double' or 'float'");
+		return NULL;
+	}
+	
+	if (strcmp(format, "unknown") == 0) {
+		f = unknown_format;
+	}
+	else if (strcmp(format, "IEEE, little-endian") == 0) {
+		f = ieee_little_endian_format;
+	}
+	else if (strcmp(format, "IEEE, big-endian") == 0) {
+		f = ieee_big_endian_format;
+	}
+	else {
+		PyErr_SetString(PyExc_ValueError,
+				"__setformat__() argument 2 must be "
+				"'unknown', 'IEEE, little-endian' or "
+				"'IEEE, big-endian'");
+		return NULL;
+
+	}
+
+	if (f != unknown_format && f != detected) {
+		PyErr_Format(PyExc_ValueError,
+			     "can only set %s format to 'unknown' or the "
+			     "detected platform value", typestr);
+		return NULL;
+	}
+
+	*p = f;
+	Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(float_setformat_doc,
+"float.__setformat__(typestr, fmt) -> None\n"
+"\n"
+"You probably don't want to use this function.  It exists mainly to be\n"
+"used in Python's test suite.\n"
+"\n"
+"typestr must be 'double' or 'float'.  fmt must be one of 'unknown',\n"
+"'IEEE, big-endian' or 'IEEE, little-endian', and in addition can only be\n"
+"one of the latter two if it appears to match the underlying C reality.\n"
+"\n"
+"Overrides the automatic determination of C-level floating point type.\n"
+"This affects how floats are converted to and from binary strings.");
+
+static PyObject *
+float_getzero(PyObject *v, void *closure)
+{
+	return PyFloat_FromDouble(0.0);
+}
+
+static PyObject *
+float__format__(PyObject *self, PyObject *args)
+{
+	PyObject *format_spec;
+
+	if (!PyArg_ParseTuple(args, "O:__format__", &format_spec))
+		return NULL;
+	if (PyBytes_Check(format_spec))
+		return _PyFloat_FormatAdvanced(self,
+					       PyBytes_AS_STRING(format_spec),
+					       PyBytes_GET_SIZE(format_spec));
+	if (PyUnicode_Check(format_spec)) {
+		/* Convert format_spec to a str */
+		PyObject *result;
+		PyObject *str_spec = PyObject_Str(format_spec);
+
+		if (str_spec == NULL)
+			return NULL;
+
+		result = _PyFloat_FormatAdvanced(self,
+						 PyBytes_AS_STRING(str_spec),
+						 PyBytes_GET_SIZE(str_spec));
+
+		Py_DECREF(str_spec);
+		return result;
+	}
+	PyErr_SetString(PyExc_TypeError, "__format__ requires str or unicode");
+	return NULL;
+}
+
+PyDoc_STRVAR(float__format__doc,
+"float.__format__(format_spec) -> string\n"
+"\n"
+"Formats the float according to format_spec.");
+
+
+static PyMethodDef float_methods[] = {
+	{"conjugate",	(PyCFunction)float_float,	METH_NOARGS,
+	 "Returns self, the complex conjugate of any float."},
+	{"__trunc__",	(PyCFunction)float_trunc, METH_NOARGS,
+         "Returns the Integral closest to x between 0 and x."},
+	{"as_integer_ratio", (PyCFunction)float_as_integer_ratio, METH_NOARGS,
+	 float_as_integer_ratio_doc},
+	{"fromhex", (PyCFunction)float_fromhex,
+	 METH_O|METH_CLASS, float_fromhex_doc},
+	{"hex", (PyCFunction)float_hex,
+	 METH_NOARGS, float_hex_doc},
+	{"is_integer",	(PyCFunction)float_is_integer,	METH_NOARGS,
+	 "Returns True if the float is an integer."},
+#if 0
+	{"is_inf",	(PyCFunction)float_is_inf,	METH_NOARGS,
+	 "Returns True if the float is positive or negative infinite."},
+	{"is_finite",	(PyCFunction)float_is_finite,	METH_NOARGS,
+	 "Returns True if the float is finite, neither infinite nor NaN."},
+	{"is_nan",	(PyCFunction)float_is_nan,	METH_NOARGS,
+	 "Returns True if the float is not a number (NaN)."},
+#endif
+	{"__getnewargs__",	(PyCFunction)float_getnewargs,	METH_NOARGS},
+	{"__getformat__",	(PyCFunction)float_getformat,	
+	 METH_O|METH_CLASS,		float_getformat_doc},
+	{"__setformat__",	(PyCFunction)float_setformat,	
+	 METH_VARARGS|METH_CLASS,	float_setformat_doc},
+        {"__format__",          (PyCFunction)float__format__,
+         METH_VARARGS,                  float__format__doc},
+	{NULL,		NULL}		/* sentinel */
+};
+
+static PyGetSetDef float_getset[] = {
+    {"real", 
+     (getter)float_float, (setter)NULL,
+     "the real part of a complex number",
+     NULL},
+    {"imag", 
+     (getter)float_getzero, (setter)NULL,
+     "the imaginary part of a complex number",
+     NULL},
+    {NULL}  /* Sentinel */
+};
+
+PyDoc_STRVAR(float_doc,
+"float(x) -> floating point number\n\
+\n\
+Convert a string or number to a floating point number, if possible.");
+
+
+static PyNumberMethods float_as_number = {
+	float_add, 	/*nb_add*/
+	float_sub, 	/*nb_subtract*/
+	float_mul, 	/*nb_multiply*/
+	float_classic_div, /*nb_divide*/
+	float_rem, 	/*nb_remainder*/
+	float_divmod, 	/*nb_divmod*/
+	float_pow, 	/*nb_power*/
+	(unaryfunc)float_neg, /*nb_negative*/
+	(unaryfunc)float_float, /*nb_positive*/
+	(unaryfunc)float_abs, /*nb_absolute*/
+	(inquiry)float_nonzero, /*nb_nonzero*/
+	0,		/*nb_invert*/
+	0,		/*nb_lshift*/
+	0,		/*nb_rshift*/
+	0,		/*nb_and*/
+	0,		/*nb_xor*/
+	0,		/*nb_or*/
+	float_coerce, 	/*nb_coerce*/
+	float_trunc, 	/*nb_int*/
+	float_long, 	/*nb_long*/
+	float_float,	/*nb_float*/
+	0,		/* nb_oct */
+	0,		/* nb_hex */
+	0,		/* nb_inplace_add */
+	0,		/* nb_inplace_subtract */
+	0,		/* nb_inplace_multiply */
+	0,		/* nb_inplace_divide */
+	0,		/* nb_inplace_remainder */
+	0, 		/* nb_inplace_power */
+	0,		/* nb_inplace_lshift */
+	0,		/* nb_inplace_rshift */
+	0,		/* nb_inplace_and */
+	0,		/* nb_inplace_xor */
+	0,		/* nb_inplace_or */
+	float_floor_div, /* nb_floor_divide */
+	float_div,	/* nb_true_divide */
+	0,		/* nb_inplace_floor_divide */
+	0,		/* nb_inplace_true_divide */
+};
+
+PyTypeObject PyFloat_Type = {
+	PyVarObject_HEAD_INIT(&PyType_Type, 0)
+	"float",
+	sizeof(PyFloatObject),
+	0,
+	(destructor)float_dealloc,		/* tp_dealloc */
+	(printfunc)float_print, 		/* tp_print */
+	0,					/* tp_getattr */
+	0,					/* tp_setattr */
+	0,			 		/* tp_compare */
+	(reprfunc)float_repr,			/* tp_repr */
+	&float_as_number,			/* tp_as_number */
+	0,					/* tp_as_sequence */
+	0,					/* tp_as_mapping */
+	(hashfunc)float_hash,			/* tp_hash */
+	0,					/* tp_call */
+	(reprfunc)float_str,			/* tp_str */
+	PyObject_GenericGetAttr,		/* tp_getattro */
+	0,					/* tp_setattro */
+	0,					/* tp_as_buffer */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
+		Py_TPFLAGS_BASETYPE,		/* tp_flags */
+	float_doc,				/* tp_doc */
+ 	0,					/* tp_traverse */
+	0,					/* tp_clear */
+	float_richcompare,			/* tp_richcompare */
+	0,					/* tp_weaklistoffset */
+	0,					/* tp_iter */
+	0,					/* tp_iternext */
+	float_methods,				/* tp_methods */
+	0,					/* tp_members */
+	float_getset,				/* tp_getset */
+	0,					/* tp_base */
+	0,					/* tp_dict */
+	0,					/* tp_descr_get */
+	0,					/* tp_descr_set */
+	0,					/* tp_dictoffset */
+	0,					/* tp_init */
+	0,					/* tp_alloc */
+	float_new,				/* tp_new */
+};
+
+void
+_PyFloat_Init(void)
+{
+	/* We attempt to determine if this machine is using IEEE
+	   floating point formats by peering at the bits of some
+	   carefully chosen values.  If it looks like we are on an
+	   IEEE platform, the float packing/unpacking routines can
+	   just copy bits, if not they resort to arithmetic & shifts
+	   and masks.  The shifts & masks approach works on all finite
+	   values, but what happens to infinities, NaNs and signed
+	   zeroes on packing is an accident, and attempting to unpack
+	   a NaN or an infinity will raise an exception.
+
+	   Note that if we're on some whacked-out platform which uses
+	   IEEE formats but isn't strictly little-endian or big-
+	   endian, we will fall back to the portable shifts & masks
+	   method. */
+
+#if SIZEOF_DOUBLE == 8
+	{
+		double x = 9006104071832581.0;
+		if (memcmp(&x, "\x43\x3f\xff\x01\x02\x03\x04\x05", 8) == 0)
+			detected_double_format = ieee_big_endian_format;
+		else if (memcmp(&x, "\x05\x04\x03\x02\x01\xff\x3f\x43", 8) == 0)
+			detected_double_format = ieee_little_endian_format;
+		else 
+			detected_double_format = unknown_format;
+	}
+#else
+	detected_double_format = unknown_format;
+#endif
+
+#if SIZEOF_FLOAT == 4
+	{
+		float y = 16711938.0;
+		if (memcmp(&y, "\x4b\x7f\x01\x02", 4) == 0)
+			detected_float_format = ieee_big_endian_format;
+		else if (memcmp(&y, "\x02\x01\x7f\x4b", 4) == 0)
+			detected_float_format = ieee_little_endian_format;
+		else 
+			detected_float_format = unknown_format;
+	}
+#else
+	detected_float_format = unknown_format;
+#endif
+
+	double_format = detected_double_format;
+	float_format = detected_float_format;
+
+	/* Init float info */
+	if (FloatInfoType.tp_name == 0)
+		PyStructSequence_InitType(&FloatInfoType, &floatinfo_desc);
+}
+
+int
+PyFloat_ClearFreeList(void)
+{
+	PyFloatObject *p;
+	PyFloatBlock *list, *next;
+	int i;
+	int u;			/* remaining unfreed ints per block */
+	int freelist_size = 0;
+
+	list = block_list;
+	block_list = NULL;
+	free_list = NULL;
+	while (list != NULL) {
+		u = 0;
+		for (i = 0, p = &list->objects[0];
+		     i < N_FLOATOBJECTS;
+		     i++, p++) {
+			if (PyFloat_CheckExact(p) && Py_REFCNT(p) != 0)
+				u++;
+		}
+		next = list->next;
+		if (u) {
+			list->next = block_list;
+			block_list = list;
+			for (i = 0, p = &list->objects[0];
+			     i < N_FLOATOBJECTS;
+			     i++, p++) {
+				if (!PyFloat_CheckExact(p) ||
+				    Py_REFCNT(p) == 0) {
+					Py_TYPE(p) = (struct _typeobject *)
+						free_list;
+					free_list = p;
+				}
+			}
+		}
+		else {
+			PyMem_FREE(list);
+		}
+		freelist_size += u;
+		list = next;
+	}
+	return freelist_size;
+}
+
+void
+PyFloat_Fini(void)
+{
+	PyFloatObject *p;
+	PyFloatBlock *list;
+	int i;
+	int u;			/* total unfreed floats per block */
+
+	u = PyFloat_ClearFreeList();
+
+	if (!Py_VerboseFlag)
+		return;
+	fprintf(stderr, "# cleanup floats");
+	if (!u) {
+		fprintf(stderr, "\n");
+	}
+	else {
+		fprintf(stderr,
+			": %d unfreed float%s\n",
+			u, u == 1 ? "" : "s");
+	}
+	if (Py_VerboseFlag > 1) {
+		list = block_list;
+		while (list != NULL) {
+			for (i = 0, p = &list->objects[0];
+			     i < N_FLOATOBJECTS;
+			     i++, p++) {
+				if (PyFloat_CheckExact(p) &&
+				    Py_REFCNT(p) != 0) {
+					char buf[100];
+					PyFloat_AsString(buf, p);
+					/* XXX(twouters) cast refcount to
+					   long until %zd is universally
+					   available
+					 */
+					fprintf(stderr,
+			     "#   <float at %p, refcnt=%ld, val=%s>\n",
+						p, (long)Py_REFCNT(p), buf);
+				}
+			}
+			list = list->next;
+		}
+	}
+}
+
+/*----------------------------------------------------------------------------
+ * _PyFloat_{Pack,Unpack}{4,8}.  See floatobject.h.
+ */
+int
+_PyFloat_Pack4(double x, unsigned char *p, int le)
+{
+	if (float_format == unknown_format) {
+		unsigned char sign;
+		int e;
+		double f;
+		unsigned int fbits;
+		int incr = 1;
+
+		if (le) {
+			p += 3;
+			incr = -1;
+		}
+
+		if (x < 0) {
+			sign = 1;
+			x = -x;
+		}
+		else
+			sign = 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 = (unsigned int)(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 = (sign << 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;
+
+	}
+	else {
+		float y = (float)x;
+		const char *s = (char*)&y;
+		int i, incr = 1;
+
+		if (Py_IS_INFINITY(y) && !Py_IS_INFINITY(x))
+			goto Overflow;
+
+		if ((float_format == ieee_little_endian_format && !le)
+		    || (float_format == ieee_big_endian_format && le)) {
+			p += 3;
+			incr = -1;
+		}
+
+		for (i = 0; i < 4; i++) {
+			*p = *s++;
+			p += incr;
+		}
+		return 0;
+	}
+  Overflow:
+	PyErr_SetString(PyExc_OverflowError,
+			"float too large to pack with f format");
+	return -1;
+}
+
+int
+_PyFloat_Pack8(double x, unsigned char *p, int le)
+{
+	if (double_format == unknown_format) {
+		unsigned char sign;
+		int e;
+		double f;
+		unsigned int fhi, flo;
+		int incr = 1;
+
+		if (le) {
+			p += 7;
+			incr = -1;
+		}
+
+		if (x < 0) {
+			sign = 1;
+			x = -x;
+		}
+		else
+			sign = 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 = (unsigned int)f; /* Truncate */
+		assert(fhi < 268435456);
+
+		f -= (double)fhi;
+		f *= 16777216.0; /* 2**24 */
+		flo = (unsigned int)(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 = (sign << 7) | (e >> 4);
+		p += incr;
+
+		/* Second byte */
+		*p = (unsigned 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;
+	}
+	else {
+		const char *s = (char*)&x;
+		int i, incr = 1;
+
+		if ((double_format == ieee_little_endian_format && !le)
+		    || (double_format == ieee_big_endian_format && le)) {
+			p += 7;
+			incr = -1;
+		}
+		
+		for (i = 0; i < 8; i++) {
+			*p = *s++;
+			p += incr;
+		}
+		return 0;
+	}
+}
+
+double
+_PyFloat_Unpack4(const unsigned char *p, int le)
+{
+	if (float_format == unknown_format) {
+		unsigned char sign;
+		int e;
+		unsigned int f;
+		double x;
+		int incr = 1;
+
+		if (le) {
+			p += 3;
+			incr = -1;
+		}
+
+		/* First byte */
+		sign = (*p >> 7) & 1;
+		e = (*p & 0x7F) << 1;
+		p += incr;
+
+		/* Second byte */
+		e |= (*p >> 7) & 1;
+		f = (*p & 0x7F) << 16;
+		p += incr;
+
+		if (e == 255) {
+			PyErr_SetString(
+				PyExc_ValueError,
+				"can't unpack IEEE 754 special value "
+				"on non-IEEE platform");
+			return -1;
+		}
+
+		/* Third byte */
+		f |= *p << 8;
+		p += incr;
+
+		/* Fourth byte */
+		f |= *p;
+
+		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 (sign)
+			x = -x;
+
+		return x;
+	}
+	else {
+		float x;
+
+		if ((float_format == ieee_little_endian_format && !le)
+		    || (float_format == ieee_big_endian_format && le)) {
+			char buf[4];
+			char *d = &buf[3];
+			int i;
+
+			for (i = 0; i < 4; i++) {
+				*d-- = *p++;
+			}
+			memcpy(&x, buf, 4);
+		}
+		else {
+			memcpy(&x, p, 4);
+		}
+
+		return x;
+	}		
+}
+
+double
+_PyFloat_Unpack8(const unsigned char *p, int le)
+{
+	if (double_format == unknown_format) {
+		unsigned char sign;
+		int e;
+		unsigned int fhi, flo;
+		double x;
+		int incr = 1;
+
+		if (le) {
+			p += 7;
+			incr = -1;
+		}
+
+		/* First byte */
+		sign = (*p >> 7) & 1;
+		e = (*p & 0x7F) << 4;
+		
+		p += incr;
+
+		/* Second byte */
+		e |= (*p >> 4) & 0xF;
+		fhi = (*p & 0xF) << 24;
+		p += incr;
+
+		if (e == 2047) {
+			PyErr_SetString(
+				PyExc_ValueError,
+				"can't unpack IEEE 754 special value "
+				"on non-IEEE platform");
+			return -1.0;
+		}
+
+		/* Third byte */
+		fhi |= *p << 16;
+		p += incr;
+
+		/* Fourth byte */
+		fhi |= *p  << 8;
+		p += incr;
+
+		/* Fifth byte */
+		fhi |= *p;
+		p += incr;
+
+		/* Sixth byte */
+		flo = *p << 16;
+		p += incr;
+
+		/* Seventh byte */
+		flo |= *p << 8;
+		p += incr;
+
+		/* Eighth byte */
+		flo |= *p;
+
+		x = (double)fhi + (double)flo / 16777216.0; /* 2**24 */
+		x /= 268435456.0; /* 2**28 */
+
+		if (e == 0)
+			e = -1022;
+		else {
+			x += 1.0;
+			e -= 1023;
+		}
+		x = ldexp(x, e);
+
+		if (sign)
+			x = -x;
+
+		return x;
+	}
+	else {
+		double x;
+
+		if ((double_format == ieee_little_endian_format && !le)
+		    || (double_format == ieee_big_endian_format && le)) {
+			char buf[8];
+			char *d = &buf[7];
+			int i;
+			
+			for (i = 0; i < 8; i++) {
+				*d-- = *p++;
+			}
+			memcpy(&x, buf, 8);
+		}
+		else {
+			memcpy(&x, p, 8);
+		}
+
+		return x;
+	}
+}