From 32117e5c290daeb44629eb613321959a0d8ae516 Mon Sep 17 00:00:00 2001 From: Neil Schemenauer Date: Thu, 4 Jan 2001 01:44:34 +0000 Subject: Make float a new style number type. --- Objects/floatobject.c | 150 ++++++++++++++++++++++++++++++++++++-------------- 1 file 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 -- cgit v0.12