summaryrefslogtreecommitdiffstats
path: root/Objects/floatobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/floatobject.c')
-rw-r--r--Objects/floatobject.c634
1 files changed, 190 insertions, 444 deletions
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index ba867ef..e146a4f 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -5,7 +5,6 @@
for any kind of float exception without losing portability. */
#include "Python.h"
-#include "structseq.h"
#include <ctype.h>
#include <float.h>
@@ -15,12 +14,28 @@
#define MAX(x, y) ((x) < (y) ? (y) : (x))
#define MIN(x, y) ((x) < (y) ? (x) : (y))
+
#ifdef _OSF_SOURCE
/* OSF1 5.1 doesn't make this available with XOPEN_SOURCE_EXTENDED defined */
extern int finite(double);
#endif
-/* Special free list -- see comments for same code in intobject.c. */
+/* Special free list
+
+ Since some Python programs can spend much of their time allocating
+ and deallocating floats, these operations should be very fast.
+ Therefore we use a dedicated allocation scheme with a much lower
+ overhead (in space and time) than straight malloc(): a simple
+ dedicated free list, filled when necessary with memory from malloc().
+
+ block_list is a singly-linked list of all PyFloatBlocks ever allocated,
+ linked via their next members. PyFloatBlocks are never returned to the
+ system before shutdown (PyFloat_Fini).
+
+ free_list is a singly-linked list of available PyFloatObjects, linked
+ via abuse of their ob_type members.
+*/
+
#define BLOCK_SIZE 1000 /* 1K less typical malloc overhead */
#define BHEAD_SIZE 8 /* Enough for a 64-bit pointer */
#define N_FLOATOBJECTS ((BLOCK_SIZE - BHEAD_SIZE) / sizeof(PyFloatObject))
@@ -65,7 +80,7 @@ PyFloat_GetMin(void)
return DBL_MIN;
}
-static PyTypeObject FloatInfoType = {0, 0, 0, 0, 0, 0};
+static PyTypeObject FloatInfoType;
PyDoc_STRVAR(floatinfo__doc__,
"sys.float_info\n\
@@ -113,7 +128,7 @@ PyFloat_GetInfo(void)
}
#define SetIntFlag(flag) \
- PyStructSequence_SET_ITEM(floatinfo, pos++, PyInt_FromLong(flag))
+ PyStructSequence_SET_ITEM(floatinfo, pos++, PyLong_FromLong(flag))
#define SetDblFlag(flag) \
PyStructSequence_SET_ITEM(floatinfo, pos++, PyFloat_FromDouble(flag))
@@ -154,85 +169,63 @@ PyFloat_FromDouble(double fval)
return (PyObject *) op;
}
-/**************************************************************************
-RED_FLAG 22-Sep-2000 tim
-PyFloat_FromString's pend argument is braindead. Prior to this RED_FLAG,
-
-1. If v was a regular string, *pend was set to point to its terminating
- null byte. That's useless (the caller can find that without any
- help from this function!).
-
-2. If v was a Unicode string, or an object convertible to a character
- buffer, *pend was set to point into stack trash (the auto temp
- vector holding the character buffer). That was downright dangerous.
-
-Since we can't change the interface of a public API function, pend is
-still supported but now *officially* useless: if pend is not NULL,
-*pend is set to NULL.
-**************************************************************************/
PyObject *
-PyFloat_FromString(PyObject *v, char **pend)
+PyFloat_FromString(PyObject *v)
{
const char *s, *last, *end;
double x;
- char buffer[256]; /* for errors */
-#ifdef Py_USING_UNICODE
- char *s_buffer = NULL;
-#endif
+ PyObject *s_buffer = NULL;
Py_ssize_t len;
PyObject *result = NULL;
- if (pend)
- *pend = NULL;
- if (PyString_Check(v)) {
- s = PyString_AS_STRING(v);
- len = PyString_GET_SIZE(v);
- }
-#ifdef Py_USING_UNICODE
- else if (PyUnicode_Check(v)) {
- s_buffer = (char *)PyMem_MALLOC(PyUnicode_GET_SIZE(v)+1);
+ if (PyUnicode_Check(v)) {
+ Py_ssize_t i, buflen = PyUnicode_GET_SIZE(v);
+ Py_UNICODE *bufptr;
+ s_buffer = PyUnicode_TransformDecimalToASCII(
+ PyUnicode_AS_UNICODE(v), buflen);
if (s_buffer == NULL)
- return PyErr_NoMemory();
- if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v),
- PyUnicode_GET_SIZE(v),
- s_buffer,
- NULL))
- goto error;
- s = s_buffer;
- len = strlen(s);
+ return NULL;
+ /* Replace non-ASCII whitespace with ' ' */
+ bufptr = PyUnicode_AS_UNICODE(s_buffer);
+ for (i = 0; i < buflen; i++) {
+ Py_UNICODE ch = bufptr[i];
+ if (ch > 127 && Py_UNICODE_ISSPACE(ch))
+ bufptr[i] = ' ';
+ }
+ s = _PyUnicode_AsStringAndSize(s_buffer, &len);
+ if (s == NULL) {
+ Py_DECREF(s_buffer);
+ return NULL;
+ }
+ last = s + len;
}
-#endif
else if (PyObject_AsCharBuffer(v, &s, &len)) {
PyErr_SetString(PyExc_TypeError,
"float() argument must be a string or a number");
return NULL;
}
last = s + len;
-
- while (Py_ISSPACE(*s))
+ /* strip space */
+ while (s < last && Py_ISSPACE(*s))
s++;
+ while (s < last - 1 && Py_ISSPACE(last[-1]))
+ last--;
/* We don't care about overflow or underflow. If the platform
* supports them, infinities and signed zeroes (on underflow) are
* fine. */
x = PyOS_string_to_double(s, (char **)&end, NULL);
- if (x == -1.0 && PyErr_Occurred())
- goto error;
- while (Py_ISSPACE(*end))
- end++;
- if (end == last)
- result = PyFloat_FromDouble(x);
- else {
- PyOS_snprintf(buffer, sizeof(buffer),
- "invalid literal for float(): %.200s", s);
- PyErr_SetString(PyExc_ValueError, buffer);
+ if (end != last) {
+ PyErr_Format(PyExc_ValueError,
+ "could not convert string to float: "
+ "%R", v);
result = NULL;
}
+ else if (x == -1.0 && PyErr_Occurred())
+ result = NULL;
+ else
+ result = PyFloat_FromDouble(x);
- error:
-#ifdef Py_USING_UNICODE
- if (s_buffer)
- PyMem_FREE(s_buffer);
-#endif
+ Py_XDECREF(s_buffer);
return result;
}
@@ -282,11 +275,8 @@ PyFloat_AsDouble(PyObject *op)
return val;
}
-/* Methods */
-
/* Macro and helper that convert PyObject obj to a C double and store
- the value in dbl; this replaces the functionality of the coercion
- slot function. If conversion to double raises an exception, obj is
+ the value in dbl. If conversion to double raises an exception, obj is
set to NULL, and the function invoking this macro returns NULL. If
obj is not of float, int or long type, Py_NotImplemented is incref'ed,
stored in obj, and returned from the function invoking this macro.
@@ -297,15 +287,14 @@ PyFloat_AsDouble(PyObject *op)
else if (convert_to_double(&(obj), &(dbl)) < 0) \
return obj;
+/* Methods */
+
static int
convert_to_double(PyObject **v, double *dbl)
{
register PyObject *obj = *v;
- if (PyInt_Check(obj)) {
- *dbl = (double)PyInt_AS_LONG(obj);
- }
- else if (PyLong_Check(obj)) {
+ if (PyLong_Check(obj)) {
*dbl = PyLong_AsDouble(obj);
if (*dbl == -1.0 && PyErr_Occurred()) {
*v = NULL;
@@ -320,74 +309,21 @@ convert_to_double(PyObject **v, double *dbl)
return 0;
}
-/* XXX PyFloat_AsString and PyFloat_AsReprString are deprecated:
- XXX they pass a char buffer without passing a length.
-*/
-void
-PyFloat_AsString(char *buf, PyFloatObject *v)
-{
- char *tmp = PyOS_double_to_string(v->ob_fval, 'g',
- PyFloat_STR_PRECISION,
- Py_DTSF_ADD_DOT_0, NULL);
- strcpy(buf, tmp);
- PyMem_Free(tmp);
-}
-
-void
-PyFloat_AsReprString(char *buf, PyFloatObject *v)
-{
- char * tmp = PyOS_double_to_string(v->ob_fval, 'r', 0,
- Py_DTSF_ADD_DOT_0, NULL);
- strcpy(buf, tmp);
- PyMem_Free(tmp);
-}
-
-/* ARGSUSED */
-static int
-float_print(PyFloatObject *v, FILE *fp, int flags)
-{
- char *buf;
- if (flags & Py_PRINT_RAW)
- buf = PyOS_double_to_string(v->ob_fval,
- 'g', PyFloat_STR_PRECISION,
- Py_DTSF_ADD_DOT_0, NULL);
- else
- buf = PyOS_double_to_string(v->ob_fval,
- 'r', 0, Py_DTSF_ADD_DOT_0, NULL);
- Py_BEGIN_ALLOW_THREADS
- fputs(buf, fp);
- Py_END_ALLOW_THREADS
- PyMem_Free(buf);
- return 0;
-}
-
static PyObject *
-float_str_or_repr(PyFloatObject *v, int precision, char format_code)
+float_repr(PyFloatObject *v)
{
PyObject *result;
char *buf = PyOS_double_to_string(PyFloat_AS_DOUBLE(v),
- format_code, precision,
- Py_DTSF_ADD_DOT_0,
- NULL);
+ 'r', 0,
+ Py_DTSF_ADD_DOT_0,
+ NULL);
if (!buf)
return PyErr_NoMemory();
- result = PyString_FromString(buf);
+ result = PyUnicode_FromString(buf);
PyMem_Free(buf);
return result;
}
-static PyObject *
-float_repr(PyFloatObject *v)
-{
- return float_str_or_repr(v, 0, 'r');
-}
-
-static PyObject *
-float_str(PyFloatObject *v)
-{
- return float_str_or_repr(v, PyFloat_STR_PRECISION, 'g');
-}
-
/* Comparison is pretty much a nightmare. When comparing float to float,
* we do it as straightforwardly (and long-windedly) as conceivable, so
* that, e.g., Python x == y delivers the same result as the platform
@@ -419,7 +355,7 @@ float_richcompare(PyObject *v, PyObject *w, int op)
j = PyFloat_AS_DOUBLE(w);
else if (!Py_IS_FINITE(i)) {
- if (PyInt_Check(w) || PyLong_Check(w))
+ if (PyLong_Check(w))
/* If i is an infinity, its magnitude exceeds any
* finite integer, so it doesn't matter which int we
* compare i with. If i is a NaN, similarly.
@@ -429,32 +365,6 @@ float_richcompare(PyObject *v, PyObject *w, int op)
goto Unimplemented;
}
- else if (PyInt_Check(w)) {
- long jj = PyInt_AS_LONG(w);
- /* In the worst realistic case I can imagine, C double is a
- * Cray single with 48 bits of precision, and long has 64
- * bits.
- */
-#if SIZEOF_LONG > 6
- unsigned long abs = (unsigned long)(jj < 0 ? -jj : jj);
- if (abs >> 48) {
- /* Needs more than 48 bits. Make it take the
- * PyLong path.
- */
- PyObject *result;
- PyObject *ww = PyLong_FromLong(jj);
-
- if (ww == NULL)
- return NULL;
- result = float_richcompare(v, ww, op);
- Py_DECREF(ww);
- return result;
- }
-#endif
- j = (double)jj;
- assert((long)j == jj);
- }
-
else if (PyLong_Check(w)) {
int vsign = i == 0.0 ? 0 : i < 0.0 ? -1 : 1;
int wsign = _PyLong_Sign(w);
@@ -549,7 +459,7 @@ float_richcompare(PyObject *v, PyObject *w, int op)
*/
PyObject *temp;
- one = PyInt_FromLong(1);
+ one = PyLong_FromLong(1);
if (one == NULL)
goto Error;
@@ -617,7 +527,7 @@ float_richcompare(PyObject *v, PyObject *w, int op)
return Py_NotImplemented;
}
-static long
+static Py_hash_t
float_hash(PyFloatObject *v)
{
return _Py_HashDouble(v->ob_fval);
@@ -665,35 +575,11 @@ float_div(PyObject *v, PyObject *w)
double a,b;
CONVERT_TO_DOUBLE(v, a);
CONVERT_TO_DOUBLE(w, b);
-#ifdef Py_NAN
if (b == 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError,
"float division by zero");
return NULL;
}
-#endif
- PyFPE_START_PROTECT("divide", return 0)
- a = a / b;
- PyFPE_END_PROTECT(a)
- return PyFloat_FromDouble(a);
-}
-
-static PyObject *
-float_classic_div(PyObject *v, PyObject *w)
-{
- double a,b;
- CONVERT_TO_DOUBLE(v, a);
- CONVERT_TO_DOUBLE(w, b);
- if (Py_DivisionWarningFlag >= 2 &&
- PyErr_Warn(PyExc_DeprecationWarning, "classic float division") < 0)
- return NULL;
-#ifdef Py_NAN
- if (b == 0.0) {
- PyErr_SetString(PyExc_ZeroDivisionError,
- "float division by zero");
- return NULL;
- }
-#endif
PyFPE_START_PROTECT("divide", return 0)
a = a / b;
PyFPE_END_PROTECT(a)
@@ -707,13 +593,11 @@ float_rem(PyObject *v, PyObject *w)
double mod;
CONVERT_TO_DOUBLE(v, vx);
CONVERT_TO_DOUBLE(w, wx);
-#ifdef Py_NAN
if (wx == 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError,
"float modulo");
return NULL;
}
-#endif
PyFPE_START_PROTECT("modulo", return 0)
mod = fmod(vx, wx);
if (mod) {
@@ -725,11 +609,8 @@ float_rem(PyObject *v, PyObject *w)
else {
/* the remainder is zero, and in the presence of signed zeroes
fmod returns different results across platforms; ensure
- it has the same sign as the denominator; we'd like to do
- "mod = wx * 0.0", but that may get optimized away */
- mod *= mod; /* hide "mod = +0" from optimizer */
- if (wx < 0.0)
- mod = -mod;
+ it has the same sign as the denominator. */
+ mod = copysign(0.0, wx);
}
PyFPE_END_PROTECT(mod)
return PyFloat_FromDouble(mod);
@@ -765,11 +646,8 @@ float_divmod(PyObject *v, PyObject *w)
else {
/* the remainder is zero, and in the presence of signed zeroes
fmod returns different results across platforms; ensure
- it has the same sign as the denominator; we'd like to do
- "mod = wx * 0.0", but that may get optimized away */
- mod *= mod; /* hide "mod = +0" from optimizer */
- if (wx < 0.0)
- mod = -mod;
+ it has the same sign as the denominator. */
+ mod = copysign(0.0, wx);
}
/* snap quotient to nearest integral value */
if (div) {
@@ -779,8 +657,7 @@ float_divmod(PyObject *v, PyObject *w)
}
else {
/* div is zero - get the same sign as the true quotient */
- div *= div; /* hide "div = +0" from optimizers */
- floordiv = div * vx / wx; /* zero w/ sign of vx/wx */
+ floordiv = copysign(0.0, vx / wx); /* zero w/ sign of vx/wx */
}
PyFPE_END_PROTECT(floordiv)
return Py_BuildValue("(dd)", floordiv, mod);
@@ -876,9 +753,10 @@ float_pow(PyObject *v, PyObject *w, PyObject *z)
* bugs so we have to figure it out ourselves.
*/
if (iw != floor(iw)) {
- PyErr_SetString(PyExc_ValueError, "negative number "
- "cannot be raised to a fractional power");
- return NULL;
+ /* Negative numbers raised to fractional powers
+ * become complex.
+ */
+ return PyComplex_Type.tp_as_number->nb_power(v, w, z);
}
/* iw is an exact integer, albeit perhaps a very large
* one. Replace iv by its absolute value and remember
@@ -941,36 +819,11 @@ float_abs(PyFloatObject *v)
}
static int
-float_nonzero(PyFloatObject *v)
+float_bool(PyFloatObject *v)
{
return v->ob_fval != 0.0;
}
-static int
-float_coerce(PyObject **pv, PyObject **pw)
-{
- if (PyInt_Check(*pw)) {
- long x = PyInt_AsLong(*pw);
- *pw = PyFloat_FromDouble((double)x);
- Py_INCREF(*pv);
- return 0;
- }
- else if (PyLong_Check(*pw)) {
- double x = PyLong_AsDouble(*pw);
- if (x == -1.0 && PyErr_Occurred())
- return -1;
- *pw = PyFloat_FromDouble(x);
- Py_INCREF(*pv);
- return 0;
- }
- else if (PyFloat_Check(*pw)) {
- Py_INCREF(*pv);
- Py_INCREF(*pw);
- return 0;
- }
- return 1; /* Can't do it */
-}
-
static PyObject *
float_is_integer(PyObject *v)
{
@@ -1035,155 +888,51 @@ float_trunc(PyObject *v)
* happens if the double is too big to fit in a long. Some rare
* systems raise an exception then (RISCOS was mentioned as one,
* and someone using a non-default option on Sun also bumped into
- * that). Note that checking for <= LONG_MAX is unsafe: if a long
- * has more bits of precision than a double, casting LONG_MAX to
- * double may yield an approximation, and if that's rounded up,
- * then, e.g., wholepart=LONG_MAX+1 would yield true from the C
- * expression wholepart<=LONG_MAX, despite that wholepart is
- * actually greater than LONG_MAX. However, assuming a two's complement
- * machine with no trap representation, LONG_MIN will be a power of 2 (and
- * hence exactly representable as a double), and LONG_MAX = -1-LONG_MIN, so
- * the comparisons with (double)LONG_MIN below should be safe.
+ * that). Note that checking for >= and <= LONG_{MIN,MAX} would
+ * still be vulnerable: if a long has more bits of precision than
+ * a double, casting MIN/MAX to double may yield an approximation,
+ * and if that's rounded up, then, e.g., wholepart=LONG_MAX+1 would
+ * yield true from the C expression wholepart<=LONG_MAX, despite
+ * that wholepart is actually greater than LONG_MAX.
*/
- if ((double)LONG_MIN <= wholepart && wholepart < -(double)LONG_MIN) {
+ if (LONG_MIN < wholepart && wholepart < LONG_MAX) {
const long aslong = (long)wholepart;
- return PyInt_FromLong(aslong);
+ return PyLong_FromLong(aslong);
}
return PyLong_FromDouble(wholepart);
}
-static PyObject *
-float_long(PyObject *v)
-{
- double x = PyFloat_AsDouble(v);
- return PyLong_FromDouble(x);
-}
-
-/* _Py_double_round: rounds a finite nonzero double to the closest multiple of
+/* double_round: rounds a finite double to the closest multiple of
10**-ndigits; here ndigits is within reasonable bounds (typically, -308 <=
ndigits <= 323). Returns a Python float, or sets a Python error and
returns NULL on failure (OverflowError and memory errors are possible). */
#ifndef PY_NO_SHORT_FLOAT_REPR
-/* version of _Py_double_round that uses the correctly-rounded string<->double
+/* version of double_round that uses the correctly-rounded string<->double
conversions from Python/dtoa.c */
-/* FIVE_POW_LIMIT is the largest k such that 5**k is exactly representable as
- a double. Since we're using the code in Python/dtoa.c, it should be safe
- to assume that C doubles are IEEE 754 binary64 format. To be on the safe
- side, we check this. */
-#if DBL_MANT_DIG == 53
-#define FIVE_POW_LIMIT 22
-#else
-#error "C doubles do not appear to be IEEE 754 binary64 format"
-#endif
-
-PyObject *
-_Py_double_round(double x, int ndigits) {
+static PyObject *
+double_round(double x, int ndigits) {
- double rounded, m;
+ double rounded;
Py_ssize_t buflen, mybuflen=100;
char *buf, *buf_end, shortbuf[100], *mybuf=shortbuf;
- int decpt, sign, val, halfway_case;
+ int decpt, sign;
PyObject *result = NULL;
_Py_SET_53BIT_PRECISION_HEADER;
- /* Easy path for the common case ndigits == 0. */
- if (ndigits == 0) {
- rounded = round(x);
- if (fabs(rounded - x) == 0.5)
- /* halfway between two integers; use round-away-from-zero */
- rounded = x + (x > 0.0 ? 0.5 : -0.5);
- return PyFloat_FromDouble(rounded);
- }
-
- /* The basic idea is very simple: convert and round the double to a
- decimal string using _Py_dg_dtoa, then convert that decimal string
- back to a double with _Py_dg_strtod. There's one minor difficulty:
- Python 2.x expects round to do round-half-away-from-zero, while
- _Py_dg_dtoa does round-half-to-even. So we need some way to detect
- and correct the halfway cases.
-
- Detection: a halfway value has the form k * 0.5 * 10**-ndigits for
- some odd integer k. Or in other words, a rational number x is
- exactly halfway between two multiples of 10**-ndigits if its
- 2-valuation is exactly -ndigits-1 and its 5-valuation is at least
- -ndigits. For ndigits >= 0 the latter condition is automatically
- satisfied for a binary float x, since any such float has
- nonnegative 5-valuation. For 0 > ndigits >= -22, x needs to be an
- integral multiple of 5**-ndigits; we can check this using fmod.
- For -22 > ndigits, there are no halfway cases: 5**23 takes 54 bits
- to represent exactly, so any odd multiple of 0.5 * 10**n for n >=
- 23 takes at least 54 bits of precision to represent exactly.
-
- Correction: a simple strategy for dealing with halfway cases is to
- (for the halfway cases only) call _Py_dg_dtoa with an argument of
- ndigits+1 instead of ndigits (thus doing an exact conversion to
- decimal), round the resulting string manually, and then convert
- back using _Py_dg_strtod.
- */
-
- /* nans, infinities and zeros should have already been dealt
- with by the caller (in this case, builtin_round) */
- assert(Py_IS_FINITE(x) && x != 0.0);
-
- /* find 2-valuation val of x */
- m = frexp(x, &val);
- while (m != floor(m)) {
- m *= 2.0;
- val--;
- }
-
- /* determine whether this is a halfway case */
- if (val == -ndigits-1) {
- if (ndigits >= 0)
- halfway_case = 1;
- else if (ndigits >= -FIVE_POW_LIMIT) {
- double five_pow = 1.0;
- int i;
- for (i=0; i < -ndigits; i++)
- five_pow *= 5.0;
- halfway_case = fmod(x, five_pow) == 0.0;
- }
- else
- halfway_case = 0;
- }
- else
- halfway_case = 0;
-
- /* round to a decimal string; use an extra place for halfway case */
+ /* round to a decimal string */
_Py_SET_53BIT_PRECISION_START;
- buf = _Py_dg_dtoa(x, 3, ndigits+halfway_case, &decpt, &sign, &buf_end);
+ buf = _Py_dg_dtoa(x, 3, ndigits, &decpt, &sign, &buf_end);
_Py_SET_53BIT_PRECISION_END;
if (buf == NULL) {
PyErr_NoMemory();
return NULL;
}
- buflen = buf_end - buf;
-
- /* in halfway case, do the round-half-away-from-zero manually */
- if (halfway_case) {
- int i, carry;
- /* sanity check: _Py_dg_dtoa should not have stripped
- any zeros from the result: there should be exactly
- ndigits+1 places following the decimal point, and
- the last digit in the buffer should be a '5'.*/
- assert(buflen - decpt == ndigits+1);
- assert(buf[buflen-1] == '5');
-
- /* increment and shift right at the same time. */
- decpt += 1;
- carry = 1;
- for (i=buflen-1; i-- > 0;) {
- carry += buf[i] - '0';
- buf[i+1] = carry % 10 + '0';
- carry /= 10;
- }
- buf[0] = carry + '0';
- }
/* Get new buffer if shortbuf is too small. Space needed <= buf_end -
- buf + 8: (1 extra for '0', 1 for sign, 5 for exp, 1 for '\0'). */
+ buf + 8: (1 extra for '0', 1 for sign, 5 for exp, 1 for '\0'). */
+ buflen = buf_end - buf;
if (buflen + 8 > mybuflen) {
mybuflen = buflen+8;
mybuf = (char *)PyMem_Malloc(mybuflen);
@@ -1215,15 +964,13 @@ _Py_double_round(double x, int ndigits) {
return result;
}
-#undef FIVE_POW_LIMIT
-
#else /* PY_NO_SHORT_FLOAT_REPR */
/* fallback version, to be used when correctly rounded binary<->decimal
conversions aren't available */
-PyObject *
-_Py_double_round(double x, int ndigits) {
+static PyObject *
+double_round(double x, int ndigits) {
double pow1, pow2, y, z;
if (ndigits >= 0) {
if (ndigits > 22) {
@@ -1249,8 +996,8 @@ _Py_double_round(double x, int ndigits) {
z = round(y);
if (fabs(y-z) == 0.5)
- /* halfway between two integers; use round-away-from-zero */
- z = y + copysign(0.5, y);
+ /* halfway between two integers; use round-half-even */
+ z = 2.0*round(y/2.0);
if (ndigits >= 0)
z = (z / pow2) / pow1;
@@ -1269,6 +1016,54 @@ _Py_double_round(double x, int ndigits) {
#endif /* PY_NO_SHORT_FLOAT_REPR */
+/* round a Python float v to the closest multiple of 10**-ndigits */
+
+static PyObject *
+float_round(PyObject *v, PyObject *args)
+{
+ double x, rounded;
+ PyObject *o_ndigits = NULL;
+ Py_ssize_t ndigits;
+
+ x = PyFloat_AsDouble(v);
+ if (!PyArg_ParseTuple(args, "|O", &o_ndigits))
+ return NULL;
+ if (o_ndigits == NULL) {
+ /* single-argument round: round to nearest integer */
+ rounded = round(x);
+ if (fabs(x-rounded) == 0.5)
+ /* halfway case: round to even */
+ rounded = 2.0*round(x/2.0);
+ return PyLong_FromDouble(rounded);
+ }
+
+ /* interpret second argument as a Py_ssize_t; clips on overflow */
+ ndigits = PyNumber_AsSsize_t(o_ndigits, NULL);
+ if (ndigits == -1 && PyErr_Occurred())
+ return NULL;
+
+ /* nans and infinities round to themselves */
+ if (!Py_IS_FINITE(x))
+ return PyFloat_FromDouble(x);
+
+ /* Deal with extreme values for ndigits. For ndigits > NDIGITS_MAX, x
+ always rounds to itself. For ndigits < NDIGITS_MIN, x always
+ rounds to +-0.0. Here 0.30103 is an upper bound for log10(2). */
+#define NDIGITS_MAX ((int)((DBL_MANT_DIG-DBL_MIN_EXP) * 0.30103))
+#define NDIGITS_MIN (-(int)((DBL_MAX_EXP + 1) * 0.30103))
+ if (ndigits > NDIGITS_MAX)
+ /* return x */
+ return PyFloat_FromDouble(x);
+ else if (ndigits < NDIGITS_MIN)
+ /* return 0.0, but with sign of x */
+ return PyFloat_FromDouble(0.0*x);
+ else
+ /* finite x, and ndigits is not unreasonably large */
+ return double_round(x, (int)ndigits);
+#undef NDIGITS_MAX
+#undef NDIGITS_MIN
+}
+
static PyObject *
float_float(PyObject *v)
{
@@ -1371,13 +1166,13 @@ float_hex(PyObject *v)
CONVERT_TO_DOUBLE(v, x);
if (Py_IS_NAN(x) || Py_IS_INFINITY(x))
- return float_str((PyFloatObject *)v);
+ return float_repr((PyFloatObject *)v);
if (x == 0.0) {
if (copysign(1.0, x) == -1.0)
- return PyString_FromString("-0x0.0p+0");
+ return PyUnicode_FromString("-0x0.0p+0");
else
- return PyString_FromString("0x0.0p+0");
+ return PyUnicode_FromString("0x0.0p+0");
}
m = frexp(fabs(x), &e);
@@ -1407,9 +1202,9 @@ float_hex(PyObject *v)
esign = (int)'+';
if (x < 0.0)
- return PyString_FromFormat("-0x%sp%c%d", s, esign, e);
+ return PyUnicode_FromFormat("-0x%sp%c%d", s, esign, e);
else
- return PyString_FromFormat("0x%sp%c%d", s, esign, e);
+ return PyUnicode_FromFormat("0x%sp%c%d", s, esign, e);
}
PyDoc_STRVAR(float_hex_doc,
@@ -1421,20 +1216,6 @@ Return a hexadecimal representation of a floating-point number.\n\
>>> 3.14159.hex()\n\
'0x1.921f9f01b866ep+1'");
-/* Case-insensitive locale-independent string match used for nan and inf
- detection. t should be lower-case and null-terminated. Return a nonzero
- result if the first strlen(t) characters of s match t and 0 otherwise. */
-
-static int
-case_insensitive_match(const char *s, const char *t)
-{
- while(*t && Py_TOLOWER(*s) == *t) {
- s++;
- t++;
- }
- return *t ? 0 : 1;
-}
-
/* Convert a hexadecimal string to a float. */
static PyObject *
@@ -1444,7 +1225,7 @@ float_fromhex(PyObject *cls, PyObject *arg)
double x;
long exp, top_exp, lsb, key_digit;
char *s, *coeff_start, *s_store, *coeff_end, *exp_start, *s_end;
- int half_eps, digit, round_up, sign=1;
+ int half_eps, digit, round_up, negate=0;
Py_ssize_t length, ndigits, fdigits, i;
/*
@@ -1492,7 +1273,8 @@ float_fromhex(PyObject *cls, PyObject *arg)
* exp+4*ndigits and exp-4*ndigits are within the range of a long.
*/
- if (PyString_AsStringAndSize(arg, &s, &length))
+ s = _PyUnicode_AsStringAndSize(arg, &length);
+ if (s == NULL)
return NULL;
s_end = s + length;
@@ -1500,33 +1282,24 @@ float_fromhex(PyObject *cls, PyObject *arg)
* Parse the string *
********************/
- /* leading whitespace and optional sign */
+ /* leading whitespace */
while (Py_ISSPACE(*s))
s++;
- if (*s == '-') {
- s++;
- sign = -1;
- }
- else if (*s == '+')
- s++;
/* infinities and nans */
- if (*s == 'i' || *s == 'I') {
- if (!case_insensitive_match(s+1, "nf"))
- goto parse_error;
- s += 3;
- x = Py_HUGE_VAL;
- if (case_insensitive_match(s, "inity"))
- s += 5;
+ x = _Py_parse_inf_or_nan(s, &coeff_end);
+ if (coeff_end != s) {
+ s = coeff_end;
goto finished;
}
- if (*s == 'n' || *s == 'N') {
- if (!case_insensitive_match(s+1, "an"))
- goto parse_error;
- s += 3;
- x = Py_NAN;
- goto finished;
+
+ /* optional sign */
+ if (*s == '-') {
+ s++;
+ negate = 1;
}
+ else if (*s == '+')
+ s++;
/* [0x] */
s_store = s;
@@ -1646,7 +1419,7 @@ float_fromhex(PyObject *cls, PyObject *arg)
round_up = 1;
break;
}
- if (round_up == 1) {
+ if (round_up) {
x += 2*half_eps;
if (top_exp == DBL_MAX_EXP &&
x == ldexp((double)(2*half_eps), DBL_MANT_DIG))
@@ -1663,7 +1436,7 @@ float_fromhex(PyObject *cls, PyObject *arg)
s++;
if (s != s_end)
goto parse_error;
- result_as_float = Py_BuildValue("(d)", sign * x);
+ result_as_float = Py_BuildValue("(d)", negate ? -x : x);
if (result_as_float == NULL)
return NULL;
result = PyObject_CallObject(cls, result_as_float);
@@ -1723,13 +1496,11 @@ float_as_integer_ratio(PyObject *v, PyObject *unused)
"Cannot pass infinity to float.as_integer_ratio.");
return NULL;
}
-#ifdef Py_NAN
if (Py_IS_NAN(self)) {
PyErr_SetString(PyExc_ValueError,
"Cannot pass NaN to float.as_integer_ratio.");
return NULL;
}
-#endif
PyFPE_START_PROTECT("as_integer_ratio", goto error);
float_part = frexp(self, &exponent); /* self == float_part * 2**exponent exactly */
@@ -1764,12 +1535,6 @@ float_as_integer_ratio(PyObject *v, PyObject *unused)
py_exponent = NULL;
}
- /* Returns ints instead of longs where possible */
- INPLACE_UPDATE(numerator, PyNumber_Int(numerator));
- if (numerator == NULL) goto error;
- INPLACE_UPDATE(denominator, PyNumber_Int(denominator));
- if (denominator == NULL) goto error;
-
result_pair = PyTuple_Pack(2, numerator, denominator);
#undef INPLACE_UPDATE
@@ -1810,8 +1575,8 @@ float_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return NULL;
/* If it's a string, but not a string subclass, use
PyFloat_FromString. */
- if (PyString_CheckExact(x))
- return PyFloat_FromString(x, NULL);
+ if (PyUnicode_CheckExact(x))
+ return PyFloat_FromString(x);
return PyNumber_Float(x);
}
@@ -1861,13 +1626,15 @@ float_getformat(PyTypeObject *v, PyObject* arg)
char* s;
float_format_type r;
- if (!PyString_Check(arg)) {
+ if (!PyUnicode_Check(arg)) {
PyErr_Format(PyExc_TypeError,
"__getformat__() argument must be string, not %.500s",
Py_TYPE(arg)->tp_name);
return NULL;
}
- s = PyString_AS_STRING(arg);
+ s = _PyUnicode_AsString(arg);
+ if (s == NULL)
+ return NULL;
if (strcmp(s, "double") == 0) {
r = double_format;
}
@@ -1883,11 +1650,11 @@ float_getformat(PyTypeObject *v, PyObject* arg)
switch (r) {
case unknown_format:
- return PyString_FromString("unknown");
+ return PyUnicode_FromString("unknown");
case ieee_little_endian_format:
- return PyString_FromString("IEEE, little-endian");
+ return PyUnicode_FromString("IEEE, little-endian");
case ieee_big_endian_format:
- return PyString_FromString("IEEE, big-endian");
+ return PyUnicode_FromString("IEEE, big-endian");
default:
Py_FatalError("insane float_format or double_format");
return NULL;
@@ -1984,29 +1751,11 @@ float__format__(PyObject *self, PyObject *args)
{
PyObject *format_spec;
- if (!PyArg_ParseTuple(args, "O:__format__", &format_spec))
+ if (!PyArg_ParseTuple(args, "U:__format__", &format_spec))
return NULL;
- if (PyBytes_Check(format_spec))
- return _PyFloat_FormatAdvanced(self,
- PyBytes_AS_STRING(format_spec),
- PyBytes_GET_SIZE(format_spec));
- if (PyUnicode_Check(format_spec)) {
- /* Convert format_spec to a str */
- PyObject *result;
- PyObject *str_spec = PyObject_Str(format_spec);
-
- if (str_spec == NULL)
- return NULL;
-
- result = _PyFloat_FormatAdvanced(self,
- PyBytes_AS_STRING(str_spec),
- PyBytes_GET_SIZE(str_spec));
-
- Py_DECREF(str_spec);
- return result;
- }
- PyErr_SetString(PyExc_TypeError, "__format__ requires str or unicode");
- return NULL;
+ return _PyFloat_FormatAdvanced(self,
+ PyUnicode_AS_UNICODE(format_spec),
+ PyUnicode_GET_SIZE(format_spec));
}
PyDoc_STRVAR(float__format__doc,
@@ -2020,6 +1769,9 @@ static PyMethodDef float_methods[] = {
"Returns self, the complex conjugate of any float."},
{"__trunc__", (PyCFunction)float_trunc, METH_NOARGS,
"Returns the Integral closest to x between 0 and x."},
+ {"__round__", (PyCFunction)float_round, METH_VARARGS,
+ "Returns the Integral closest to x, rounding half toward even.\n"
+ "When an argument is passed, works like built-in round(x, ndigits)."},
{"as_integer_ratio", (PyCFunction)float_as_integer_ratio, METH_NOARGS,
float_as_integer_ratio_doc},
{"fromhex", (PyCFunction)float_fromhex,
@@ -2068,30 +1820,25 @@ 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_float, /*nb_positive*/
(unaryfunc)float_abs, /*nb_absolute*/
- (inquiry)float_nonzero, /*nb_nonzero*/
+ (inquiry)float_bool, /*nb_bool*/
0, /*nb_invert*/
0, /*nb_lshift*/
0, /*nb_rshift*/
0, /*nb_and*/
0, /*nb_xor*/
0, /*nb_or*/
- float_coerce, /*nb_coerce*/
float_trunc, /*nb_int*/
- float_long, /*nb_long*/
+ 0, /*nb_reserved*/
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 */
@@ -2111,22 +1858,21 @@ PyTypeObject PyFloat_Type = {
sizeof(PyFloatObject),
0,
(destructor)float_dealloc, /* tp_dealloc */
- (printfunc)float_print, /* tp_print */
+ 0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
- 0, /* tp_compare */
+ 0, /* tp_reserved */
(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 */
+ (reprfunc)float_repr, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
- Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
float_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
@@ -2207,7 +1953,7 @@ PyFloat_ClearFreeList(void)
PyFloatObject *p;
PyFloatBlock *list, *next;
int i;
- int u; /* remaining unfreed ints per block */
+ int u; /* remaining unfreed floats per block */
int freelist_size = 0;
list = block_list;
@@ -2505,7 +2251,7 @@ _PyFloat_Pack8(double x, unsigned char *p, int le)
/* Eighth byte */
*p = flo & 0xFF;
- /* p += incr; Unneeded (for now) */
+ p += incr;
/* Done */
return 0;