summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
Diffstat (limited to 'Objects')
-rw-r--r--Objects/floatobject.c106
-rw-r--r--Objects/structseq.c82
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 *