summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/Objects/floatobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tools/python3/Objects/floatobject.c')
-rw-r--r--contrib/tools/python3/Objects/floatobject.c171
1 files changed, 70 insertions, 101 deletions
diff --git a/contrib/tools/python3/Objects/floatobject.c b/contrib/tools/python3/Objects/floatobject.c
index 92d40e8acad..986edd597d6 100644
--- a/contrib/tools/python3/Objects/floatobject.c
+++ b/contrib/tools/python3/Objects/floatobject.c
@@ -4,18 +4,19 @@
for any kind of float exception without losing portability. */
#include "Python.h"
+#include "pycore_abstract.h" // _PyNumber_Index()
#include "pycore_dtoa.h" // _Py_dg_dtoa()
#include "pycore_floatobject.h" // _PyFloat_FormatAdvancedWriter()
#include "pycore_initconfig.h" // _PyStatus_OK()
-#include "pycore_interp.h" // _PyInterpreterState.float_state
+#include "pycore_interp.h" // _Py_float_freelist
#include "pycore_long.h" // _PyLong_GetOne()
-#include "pycore_object.h" // _PyObject_Init()
+#include "pycore_modsupport.h" // _PyArg_NoKwnames()
+#include "pycore_object.h" // _PyObject_Init(), _PyDebugAllocatorStats()
#include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "pycore_structseq.h" // _PyStructSequence_FiniBuiltin()
-#include <ctype.h>
-#include <float.h>
+#include <float.h> // DBL_MAX
#include <stdlib.h> // strtol()
/*[clinic input]
@@ -25,17 +26,13 @@ class float "PyObject *" "&PyFloat_Type"
#include "clinic/floatobject.c.h"
-#ifndef PyFloat_MAXFREELIST
-# define PyFloat_MAXFREELIST 100
-#endif
-
-
-#if PyFloat_MAXFREELIST > 0
-static struct _Py_float_state *
-get_float_state(void)
+#ifdef WITH_FREELISTS
+static struct _Py_float_freelist *
+get_float_freelist(void)
{
- PyInterpreterState *interp = _PyInterpreterState_GET();
- return &interp->float_state;
+ struct _Py_object_freelists *freelists = _Py_object_freelists_GET();
+ assert(freelists != NULL);
+ return &freelists->floats;
}
#endif
@@ -136,16 +133,12 @@ PyObject *
PyFloat_FromDouble(double fval)
{
PyFloatObject *op;
-#if PyFloat_MAXFREELIST > 0
- struct _Py_float_state *state = get_float_state();
- op = state->free_list;
+#ifdef WITH_FREELISTS
+ struct _Py_float_freelist *float_freelist = get_float_freelist();
+ op = float_freelist->items;
if (op != NULL) {
-#ifdef Py_DEBUG
- // PyFloat_FromDouble() must not be called after _PyFloat_Fini()
- assert(state->numfree != -1);
-#endif
- state->free_list = (PyFloatObject *) Py_TYPE(op);
- state->numfree--;
+ float_freelist->items = (PyFloatObject *) Py_TYPE(op);
+ float_freelist->numfree--;
OBJECT_STAT_INC(from_freelist);
}
else
@@ -256,19 +249,15 @@ _PyFloat_ExactDealloc(PyObject *obj)
{
assert(PyFloat_CheckExact(obj));
PyFloatObject *op = (PyFloatObject *)obj;
-#if PyFloat_MAXFREELIST > 0
- struct _Py_float_state *state = get_float_state();
-#ifdef Py_DEBUG
- // float_dealloc() must not be called after _PyFloat_Fini()
- assert(state->numfree != -1);
-#endif
- if (state->numfree >= PyFloat_MAXFREELIST) {
+#ifdef WITH_FREELISTS
+ struct _Py_float_freelist *float_freelist = get_float_freelist();
+ if (float_freelist->numfree >= PyFloat_MAXFREELIST || float_freelist->numfree < 0) {
PyObject_Free(op);
return;
}
- state->numfree++;
- Py_SET_TYPE(op, (PyTypeObject *)state->free_list);
- state->free_list = op;
+ float_freelist->numfree++;
+ Py_SET_TYPE(op, (PyTypeObject *)float_freelist->items);
+ float_freelist->items = op;
OBJECT_STAT_INC(to_freelist);
#else
PyObject_Free(op);
@@ -279,7 +268,7 @@ static void
float_dealloc(PyObject *op)
{
assert(PyFloat_Check(op));
-#if PyFloat_MAXFREELIST > 0
+#ifdef WITH_FREELISTS
if (PyFloat_CheckExact(op)) {
_PyFloat_ExactDealloc(op);
}
@@ -480,82 +469,67 @@ float_richcompare(PyObject *v, PyObject *w, int op)
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;
+ j = i;
+ i = 0.0;
goto Compare;
}
if ((size_t)exponent > nbits) {
- i = 2.0;
- j = 1.0;
+ j = 0.0;
goto Compare;
}
/* v and w have the same number of bits before the radix
- * point. Construct two ints that have the same comparison
- * outcome.
+ * point. Construct an int from the integer part of v and
+ * update op if necessary, so comparing two ints has the same outcome.
*/
{
double fracpart;
double intpart;
PyObject *result = NULL;
PyObject *vv = NULL;
- PyObject *ww = w;
- if (wsign < 0) {
- ww = PyNumber_Negative(w);
- if (ww == NULL)
- goto Error;
+ fracpart = modf(i, &intpart);
+ if (fracpart != 0.0) {
+ switch (op) {
+ /* Non-integer float never equals to an int. */
+ case Py_EQ:
+ Py_RETURN_FALSE;
+ case Py_NE:
+ Py_RETURN_TRUE;
+ /* For non-integer float, v <= w <=> v < w.
+ * If v > 0: trunc(v) < v < trunc(v) + 1
+ * v < w => trunc(v) < w
+ * trunc(v) < w => trunc(v) + 1 <= w => v < w
+ * If v < 0: trunc(v) - 1 < v < trunc(v)
+ * v < w => trunc(v) - 1 < w => trunc(v) <= w
+ * trunc(v) <= w => v < w
+ */
+ case Py_LT:
+ case Py_LE:
+ op = vsign > 0 ? Py_LT : Py_LE;
+ break;
+ /* The same as above, but with opposite directions. */
+ case Py_GT:
+ case Py_GE:
+ op = vsign > 0 ? Py_GE : Py_GT;
+ break;
+ }
}
- 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;
-
- temp = _PyLong_Lshift(ww, 1);
- if (temp == NULL)
- goto Error;
- Py_SETREF(ww, temp);
-
- temp = _PyLong_Lshift(vv, 1);
- if (temp == NULL)
- goto Error;
- Py_SETREF(vv, temp);
-
- temp = PyNumber_Or(vv, _PyLong_GetOne());
- if (temp == NULL)
- goto Error;
- Py_SETREF(vv, temp);
- }
-
- r = PyObject_RichCompareBool(vv, ww, op);
+ r = PyObject_RichCompareBool(vv, w, op);
if (r < 0)
goto Error;
result = PyBool_FromLong(r);
Error:
Py_XDECREF(vv);
- Py_XDECREF(ww);
return result;
}
} /* else if (PyLong_Check(w)) */
@@ -650,7 +624,7 @@ float_rem(PyObject *v, PyObject *w)
CONVERT_TO_DOUBLE(w, wx);
if (wx == 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError,
- "float modulo");
+ "float modulo by zero");
return NULL;
}
mod = fmod(vx, wx);
@@ -2006,28 +1980,23 @@ _PyFloat_InitTypes(PyInterpreterState *interp)
}
void
-_PyFloat_ClearFreeList(PyInterpreterState *interp)
+_PyFloat_ClearFreeList(struct _Py_object_freelists *freelists, int is_finalization)
{
-#if PyFloat_MAXFREELIST > 0
- struct _Py_float_state *state = &interp->float_state;
- PyFloatObject *f = state->free_list;
+#ifdef WITH_FREELISTS
+ struct _Py_float_freelist *state = &freelists->floats;
+ PyFloatObject *f = state->items;
while (f != NULL) {
PyFloatObject *next = (PyFloatObject*) Py_TYPE(f);
PyObject_Free(f);
f = next;
}
- state->free_list = NULL;
- state->numfree = 0;
-#endif
-}
-
-void
-_PyFloat_Fini(PyInterpreterState *interp)
-{
- _PyFloat_ClearFreeList(interp);
-#if defined(Py_DEBUG) && PyFloat_MAXFREELIST > 0
- struct _Py_float_state *state = &interp->float_state;
- state->numfree = -1;
+ state->items = NULL;
+ if (is_finalization) {
+ state->numfree = -1;
+ }
+ else {
+ state->numfree = 0;
+ }
#endif
}
@@ -2041,11 +2010,11 @@ _PyFloat_FiniType(PyInterpreterState *interp)
void
_PyFloat_DebugMallocStats(FILE *out)
{
-#if PyFloat_MAXFREELIST > 0
- struct _Py_float_state *state = get_float_state();
+#ifdef WITH_FREELISTS
+ struct _Py_float_freelist *float_freelist = get_float_freelist();
_PyDebugAllocatorStats(out,
"free PyFloatObject",
- state->numfree, sizeof(PyFloatObject));
+ float_freelist->numfree, sizeof(PyFloatObject));
#endif
}