[Python-Dev] Caching float(0.0)

Josiah Carlson jcarlson at uci.edu
Wed Oct 4 07:35:43 CEST 2006


Steve Holden <steve at holdenweb.com> wrote:
> Josiah Carlson wrote:
> [yet more on this topic]
> 
> If the brainpower already expended on this issue were proportional to 
> its significance then we'd be reading about it on CNN news.

Goodness, I wasn't aware that pointer manipulation took that much
brainpower.  I presume you mean what others have spent time thinking
about with regards to this topic.


> This thread has disappeared down a rat-hole, never to re-emerge with 
> anything of significant benefit to users. C'mon, guys, implement a patch 
> or leave it alone :-)

Heh.  So be it.  The following is untested (I lack a build system for
the Python trunk).  It adds a new global cache for floats, a new 'fill
the global cache' function, and an updated PyFloat_FromDouble() function.

All in all, it took about 10 minutes to generate, and understands the
difference between fp +0.0 and -0.0 (assuming sane IEEE 754 fp double
behavior on non-x86 platforms).

 - Josiah


/* This should go into floatobject.c */


static PyFloatObject *cached_list = NULL;

static PyFloatObject *
fill_cached_list(void)
{
	cached_list = (PyFloatObject *) 1;
	PyFloatObject *p;
	int i;
	p = (PyFloatObject *) PyMem_MALLOC(sizeof(PyFloatObject)*22);
	if (p == NULL) {
		cached_list = NULL;
		return (PyFloatObject *) PyErr_NoMemory();
	}
	for (i=0;i<=10;i++) {
		p[i] = (PyFloatObject*) PyFloat_fromDouble((double) i);
		p[21-i] = (PyFloatObject*) PyFloat_fromDouble(-((double) i));
	}
	cached_list = NULL;
	return p;
}

PyObject *
PyFloat_FromDouble(double fval)
{
	register PyFloatObject *op;
	register long* fvali = (int*)(&fval);
	if (free_list == NULL) {
		if ((free_list = fill_free_list()) == NULL)
			return NULL;
	}
	
#ifdef LITTLE_ENDIAN
	if (!p[0])
#else
	if (!p[1])
#endif
	{
		if (cached_list == NULL) {
			if ((cached_list = fill_cached_list()) == NULL)
				return NULL;
		}
		if ((cached_list != 1) && (cached_list != NULL)) {
#ifdef LITTLE_ENDIAN
			switch p[1]
#else
			switch p[0]
#endif
			{
			case 0:  PY_INCREF(cached_list[0]); return cached_list[0];
			case 1072693248:  PY_INCREF(cached_list[1]); return cached_list[1];
			case 1073741824:  PY_INCREF(cached_list[2]); return cached_list[2];
			case 1074266112:  PY_INCREF(cached_list[3]); return cached_list[3];
			case 1074790400:  PY_INCREF(cached_list[4]); return cached_list[4];
			case 1075052544:  PY_INCREF(cached_list[5]); return cached_list[5];
			case 1075314688:  PY_INCREF(cached_list[6]); return cached_list[6];
			case 1075576832:  PY_INCREF(cached_list[7]); return cached_list[7];
			case 1075838976:  PY_INCREF(cached_list[8]); return cached_list[8];
			case 1075970048:  PY_INCREF(cached_list[9]); return cached_list[9];
			case 1076101120:  PY_INCREF(cached_list[10]); return cached_list[10];
			case -1071382528:  PY_INCREF(cached_list[11]); return cached_list[11];
			case -1071513600:  PY_INCREF(cached_list[12]); return cached_list[12];
			case -1071644672:  PY_INCREF(cached_list[13]); return cached_list[13];
			case -1071906816:  PY_INCREF(cached_list[14]); return cached_list[14];
			case -1072168960:  PY_INCREF(cached_list[15]); return cached_list[15];
			case -1072431104:  PY_INCREF(cached_list[16]); return cached_list[16];
			case -1072693248:  PY_INCREF(cached_list[17]); return cached_list[17];
			case -1073217536:  PY_INCREF(cached_list[18]); return cached_list[18];
			case -1073741824:  PY_INCREF(cached_list[19]); return cached_list[19];
			case -1074790400:  PY_INCREF(cached_list[20]); return cached_list[20];
			case -2147483648:  PY_INCREF(cached_list[21]); return cached_list[21];
			default:
			}
		}

	}
	
	/* Inline PyObject_New */
	op = free_list;
	free_list = (PyFloatObject *)op->ob_type;
	PyObject_INIT(op, &PyFloat_Type);
	op->ob_fval = fval;
	return (PyObject *) op;
}



More information about the Python-Dev mailing list