cinap_lenrekadd hg and python4bb9e2215 years agoHistory
1748 lines · 40.3 KB · C
RawDownload
		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__(tstr) -> 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""tstr 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 tstr."); static PyObject *float_setformat(PyTypeObject *v, PyObject* args){	char* tstr;	char* format;	float_format_type f;	float_format_type detected;	float_format_type *p; 	if (!PyArg_ParseTuple(args, "ss:__setformat__", &tstr, &format))		return NULL; 	if (strcmp(tstr, "double") == 0) {		p = &double_format;		detected = detected_double_format;	}	else if (strcmp(tstr, "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", tstr);		return NULL;	} 	*p = f;	Py_RETURN_NONE;} PyDoc_STRVAR(float_setformat_doc,"float.__setformat__(tstr, 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""tstr 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 PyMethodDef float_methods[] = {	{"__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},	{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_pos, /*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_int, 	/*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 = {	PyObject_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 */	0,					/* 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;} voidPyFloat_Fini(void){	PyFloatObject *p;	PyFloatBlock *list, *next;	unsigned i;	int bc, bf;	/* block count, number of freed blocks */	int frem, fsum;	/* remaining unfreed floats per block, total */ 	bc = 0;	bf = 0;	fsum = 0;	list = block_list;	block_list = NULL;	free_list = NULL;	while (list != NULL) {		bc++;		frem = 0;		for (i = 0, p = &list->objects[0];		     i < N_FLOATOBJECTS;		     i++, p++) {			if (PyFloat_CheckExact(p) && p->ob_refcnt != 0)				frem++;		}		next = list->next;		if (frem) {			list->next = block_list;			block_list = list;			for (i = 0, p = &list->objects[0];			     i < N_FLOATOBJECTS;			     i++, p++) {				if (!PyFloat_CheckExact(p) ||				    p->ob_refcnt == 0) {					p->ob_type = (struct _typeobject *)						free_list;					free_list = p;				}			}		}		else {			PyMem_FREE(list); /* XXX PyObject_FREE ??? */			bf++;		}		fsum += frem;		list = next;	}	if (!Py_VerboseFlag)		return;	fprintf(stderr, "# cleanup floats");	if (!fsum) {		fprintf(stderr, "\n");	}	else {		fprintf(stderr,			": %d unfreed float%s in %d out of %d block%s\n",			fsum, fsum == 1 ? "" : "s",			bc - bf, bc, bc == 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) &&				    p->ob_refcnt != 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)p->ob_refcnt, buf);				}			}			list = list->next;		}	}} /*---------------------------------------------------------------------------- * _PyFloat_{Pack,Unpack}{4,8}.  See floatobject.h. * * TODO:  On platforms that use the standard IEEE-754 single and double * formats natively, these routines could simply copy the bytes. */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; 	  Overflow:		PyErr_SetString(PyExc_OverflowError,				"float too large to pack with f format");		return -1;	}	else {		float y = (float)x;		const char *s = (char*)&y;		int i, incr = 1; 		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;	}} 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);

Lines 1001–1500 of 1748. Previous lines