diff options
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/floatobject.c | 106 | ||||
-rw-r--r-- | Objects/structseq.c | 82 |
2 files changed, 154 insertions, 34 deletions
diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 0989415..a832c5d 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -5,6 +5,7 @@ for any kind of float exception without losing portability. */ #include "Python.h" +#include "structseq.h" #include "formatter_unicode.h" @@ -61,39 +62,86 @@ PyFloat_GetMin(void) return DBL_MIN; } +static PyTypeObject FloatInfoType; + +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 *d, *tmp; - -#define SET_FLOAT_CONST(d, key, const) \ - tmp = PyFloat_FromDouble(const); \ - if (tmp == NULL) return NULL; \ - if (PyDict_SetItemString(d, key, tmp)) return NULL; \ - Py_DECREF(tmp) -#define SET_INT_CONST(d, key, const) \ - tmp = PyLong_FromLong(const); \ - if (tmp == NULL) return NULL; \ - if (PyDict_SetItemString(d, key, tmp)) return NULL; \ - Py_DECREF(tmp) - - d = PyDict_New(); - - SET_FLOAT_CONST(d, "max", DBL_MAX); - SET_INT_CONST(d, "max_exp", DBL_MAX_EXP); - SET_INT_CONST(d, "max_10_exp", DBL_MAX_10_EXP); - SET_FLOAT_CONST(d, "min", DBL_MIN); - SET_INT_CONST(d, "min_exp", DBL_MIN_EXP); - SET_INT_CONST(d, "min_10_exp", DBL_MIN_10_EXP); - SET_INT_CONST(d, "dig", DBL_DIG); - SET_INT_CONST(d, "mant_dig", DBL_MANT_DIG); - SET_FLOAT_CONST(d, "epsilon", DBL_EPSILON); - SET_INT_CONST(d, "radix", FLT_RADIX); - SET_INT_CONST(d, "rounds", FLT_ROUNDS); - - return d; -} + static PyObject* floatinfo; + int pos = 0; + if (floatinfo != NULL) { + Py_INCREF(floatinfo); + return floatinfo; + } + PyStructSequence_InitType(&FloatInfoType, &floatinfo_desc); + + floatinfo = PyStructSequence_New(&FloatInfoType); + if (floatinfo == NULL) { + return NULL; + } + +#define SetIntFlag(flag) \ + PyStructSequence_SET_ITEM(floatinfo, pos++, PyLong_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; + } + + Py_INCREF(floatinfo); + return floatinfo; +} PyObject * PyFloat_FromDouble(double fval) diff --git a/Objects/structseq.c b/Objects/structseq.c index 96026fc..56e885c 100644 --- a/Objects/structseq.c +++ b/Objects/structseq.c @@ -30,7 +30,7 @@ PyObject * PyStructSequence_New(PyTypeObject *type) { PyStructSequence *obj; - + obj = PyObject_New(PyStructSequence, type); Py_SIZE(obj) = VISIBLE_SIZE_TP(type); @@ -230,11 +230,83 @@ make_tuple(PyStructSequence *obj) static PyObject * structseq_repr(PyStructSequence *obj) { - PyObject *tup, *str; - tup = make_tuple(obj); - str = PyObject_Repr(tup); + /* buffer and type size were chosen well considered. */ +#define REPR_BUFFER_SIZE 512 +#define TYPE_MAXSIZE 100 + + PyObject *tup; + PyTypeObject *typ = Py_TYPE(obj); + int i, removelast = 0; + Py_ssize_t len; + char buf[REPR_BUFFER_SIZE]; + char *endofbuf, *pbuf = buf; + + /* pointer to end of writeable buffer; safes space for "...)\0" */ + endofbuf= &buf[REPR_BUFFER_SIZE-5]; + + if ((tup = make_tuple(obj)) == NULL) { + return NULL; + } + + /* "typename(", limited to TYPE_MAXSIZE */ + len = strlen(typ->tp_name) > TYPE_MAXSIZE ? TYPE_MAXSIZE : + strlen(typ->tp_name); + strncpy(pbuf, typ->tp_name, len); + pbuf += len; + *pbuf++ = '('; + + for (i=0; i < VISIBLE_SIZE(obj); i++) { + PyObject *val, *repr; + char *cname, *crepr; + + cname = typ->tp_members[i].name; + + val = PyTuple_GetItem(tup, i); + if (cname == NULL || val == NULL) { + return NULL; + } + repr = PyObject_Repr(val); + if (repr == NULL) { + Py_DECREF(tup); + return NULL; + } + crepr = PyUnicode_AsString(repr); + if (crepr == NULL) { + Py_DECREF(tup); + Py_DECREF(repr); + return NULL; + } + + /* + 3: keep space for "=" and ", " */ + len = strlen(cname) + strlen(crepr) + 3; + if ((pbuf+len) <= endofbuf) { + strcpy(pbuf, cname); + pbuf += strlen(cname); + *pbuf++ = '='; + strcpy(pbuf, crepr); + pbuf += strlen(crepr); + *pbuf++ = ','; + *pbuf++ = ' '; + removelast = 1; + Py_DECREF(repr); + } + else { + strcpy(pbuf, "..."); + pbuf += 3; + removelast = 0; + Py_DECREF(repr); + break; + } + } Py_DECREF(tup); - return str; + if (removelast) { + /* overwrite last ", " */ + pbuf-=2; + } + *pbuf++ = ')'; + *pbuf = '\0'; + + return PyUnicode_FromString(buf); } static PyObject * |