]> granicus.if.org Git - python/commitdiff
Make float a new style number type.
authorNeil Schemenauer <nascheme@enme.ucalgary.ca>
Thu, 4 Jan 2001 01:44:34 +0000 (01:44 +0000)
committerNeil Schemenauer <nascheme@enme.ucalgary.ca>
Thu, 4 Jan 2001 01:44:34 +0000 (01:44 +0000)
Objects/floatobject.c

index b58c7fd494f9f30658375c2ab5c707a972b0a952..c8414234220b02acf90f47305fe2dd8492397bd9 100644 (file)
@@ -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