summaryrefslogtreecommitdiffstats
path: root/Objects/floatobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/floatobject.c')
-rw-r--r--Objects/floatobject.c150
1 files changed, 108 insertions, 42 deletions
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index b58c7fd..c841423 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -256,6 +256,38 @@ PyFloat_AsStringEx(char *buf, PyFloatObject *v, int precision)
}
}
+/* 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 */
+
+#define CONVERT_TO_DOUBLE(obj, dbl) \
+ if (PyFloat_Check(obj)) \
+ dbl = PyFloat_AS_DOUBLE(obj); \
+ else if (convert_to_double(&(obj), &(dbl)) < 0) \
+ return obj;
+
+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)) {
+ PyFPE_START_PROTECT("convert_to_double", {*v=NULL;return -1;})
+ *dbl = PyLong_AsDouble(obj);
+ PyFPE_END_PROTECT(result)
+ }
+ else {
+ Py_INCREF(Py_NotImplemented);
+ *v = Py_NotImplemented;
+ return -1;
+ }
+ return 0;
+}
+
/* Precisions used by repr() and str(), respectively.
The repr() precision (17 significant decimal digits) is the minimal number
@@ -314,6 +346,15 @@ float_compare(PyFloatObject *v, PyFloatObject *w)
return (i < j) ? -1 : (i > j) ? 1 : 0;
}
+/* Needed for the new style number compare slots */
+static PyObject *
+float_cmp(PyObject *v, PyObject *w)
+{
+ double a,b;
+ CONVERT_TO_DOUBLE(v, a);
+ CONVERT_TO_DOUBLE(w, b);
+ return PyInt_FromLong((a < b) ? -1 : (a > b) ? 1 : 0);
+}
static long
float_hash(PyFloatObject *v)
@@ -322,62 +363,69 @@ float_hash(PyFloatObject *v)
}
static PyObject *
-float_add(PyFloatObject *v, PyFloatObject *w)
+float_add(PyObject *v, PyObject *w)
{
- double result;
+ double a,b;
+ CONVERT_TO_DOUBLE(v, a);
+ CONVERT_TO_DOUBLE(w, b);
PyFPE_START_PROTECT("add", return 0)
- result = v->ob_fval + w->ob_fval;
- PyFPE_END_PROTECT(result)
- return PyFloat_FromDouble(result);
+ a = a + b;
+ PyFPE_END_PROTECT(a)
+ return PyFloat_FromDouble(a);
}
static PyObject *
-float_sub(PyFloatObject *v, PyFloatObject *w)
+float_sub(PyObject *v, PyObject *w)
{
- double result;
+ double a,b;
+ CONVERT_TO_DOUBLE(v, a);
+ CONVERT_TO_DOUBLE(w, b);
PyFPE_START_PROTECT("subtract", return 0)
- result = v->ob_fval - w->ob_fval;
- PyFPE_END_PROTECT(result)
- return PyFloat_FromDouble(result);
+ a = a - b;
+ PyFPE_END_PROTECT(a)
+ return PyFloat_FromDouble(a);
}
static PyObject *
-float_mul(PyFloatObject *v, PyFloatObject *w)
+float_mul(PyObject *v, PyObject *w)
{
- double result;
-
+ double a,b;
+ CONVERT_TO_DOUBLE(v, a);
+ CONVERT_TO_DOUBLE(w, b);
PyFPE_START_PROTECT("multiply", return 0)
- result = v->ob_fval * w->ob_fval;
- PyFPE_END_PROTECT(result)
- return PyFloat_FromDouble(result);
+ a = a * b;
+ PyFPE_END_PROTECT(a)
+ return PyFloat_FromDouble(a);
}
static PyObject *
-float_div(PyFloatObject *v, PyFloatObject *w)
+float_div(PyObject *v, PyObject *w)
{
- double result;
- if (w->ob_fval == 0) {
+ double a,b;
+ CONVERT_TO_DOUBLE(v, a);
+ CONVERT_TO_DOUBLE(w, b);
+ if (b == 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError, "float division");
return NULL;
}
PyFPE_START_PROTECT("divide", return 0)
- result = v->ob_fval / w->ob_fval;
- PyFPE_END_PROTECT(result)
- return PyFloat_FromDouble(result);
+ a = a / b;
+ PyFPE_END_PROTECT(a)
+ return PyFloat_FromDouble(a);
}
static PyObject *
-float_rem(PyFloatObject *v, PyFloatObject *w)
+float_rem(PyObject *v, PyObject *w)
{
double vx, wx;
double mod;
- wx = w->ob_fval;
+ CONVERT_TO_DOUBLE(v, vx);
+ CONVERT_TO_DOUBLE(w, wx);
if (wx == 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError, "float modulo");
return NULL;
}
PyFPE_START_PROTECT("modulo", return 0)
- vx = v->ob_fval;
mod = fmod(vx, wx);
/* note: checking mod*wx < 0 is incorrect -- underflows to
0 if wx < sqrt(smallest nonzero double) */
@@ -389,17 +437,17 @@ float_rem(PyFloatObject *v, PyFloatObject *w)
}
static PyObject *
-float_divmod(PyFloatObject *v, PyFloatObject *w)
+float_divmod(PyObject *v, PyObject *w)
{
double vx, wx;
double div, mod, floordiv;
- wx = w->ob_fval;
+ CONVERT_TO_DOUBLE(v, vx);
+ CONVERT_TO_DOUBLE(w, wx);
if (wx == 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError, "float divmod()");
return NULL;
}
PyFPE_START_PROTECT("divmod", return 0)
- vx = v->ob_fval;
mod = fmod(vx, wx);
/* fmod is typically exact, so vx-mod is *mathematically* an
exact multiple of wx. But this is fp arithmetic, and fp
@@ -437,7 +485,7 @@ static double powu(double x, long n)
}
static PyObject *
-float_pow(PyFloatObject *v, PyObject *w, PyFloatObject *z)
+float_pow(PyObject *v, PyObject *w, PyObject *z)
{
double iv, iw, ix;
long intw;
@@ -446,17 +494,18 @@ float_pow(PyFloatObject *v, PyObject *w, PyFloatObject *z)
* long integers. Maybe something clever with logarithms could be done.
* [AMK]
*/
- iv = v->ob_fval;
- iw = ((PyFloatObject *)w)->ob_fval;
+ CONVERT_TO_DOUBLE(v, iv);
+ CONVERT_TO_DOUBLE(w, iw);
intw = (long)iw;
/* Sort out special cases here instead of relying on pow() */
if (iw == 0) { /* x**0 is 1, even 0**0 */
PyFPE_START_PROTECT("pow", return NULL)
if ((PyObject *)z != Py_None) {
- ix = fmod(1.0, z->ob_fval);
- if (ix != 0 && z->ob_fval < 0)
- ix += z->ob_fval;
+ double iz;
+ CONVERT_TO_DOUBLE(w, iz);
+ ix=fmod(1.0, iz);
+ if (ix!=0 && iz<0) ix+=iz;
}
else
ix = 1.0;
@@ -501,15 +550,14 @@ float_pow(PyFloatObject *v, PyObject *w, PyFloatObject *z)
return NULL;
}
if ((PyObject *)z != Py_None) {
- PyFPE_START_PROTECT("pow", return NULL)
- ix = fmod(ix, z->ob_fval); /* XXX To Be Rewritten */
- if (ix != 0 &&
- ((iv < 0 && z->ob_fval > 0) ||
- (iv > 0 && z->ob_fval < 0)
- )) {
- ix += z->ob_fval;
+ double iz;
+ CONVERT_TO_DOUBLE(z, iz);
+ PyFPE_START_PROTECT("pow", return 0)
+ ix=fmod(ix, iz); /* XXX To Be Rewritten */
+ if (ix!=0 && ((iv<0 && iz>0) || (iv>0 && iz<0) )) {
+ ix+=iz;
}
- PyFPE_END_PROTECT(ix)
+ PyFPE_END_PROTECT(ix)
}
return PyFloat_FromDouble(ix);
}
@@ -611,6 +659,20 @@ static PyNumberMethods float_as_number = {
(unaryfunc)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*/
+
+ /* New style slots: */
+ (binaryfunc)float_cmp, /*nb_cmp*/
};
PyTypeObject PyFloat_Type = {
@@ -631,6 +693,10 @@ PyTypeObject PyFloat_Type = {
(hashfunc)float_hash, /*tp_hash*/
0, /*tp_call*/
(reprfunc)float_str, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_NEWSTYLENUMBER /*tp_flags*/
};
void