diff options
Diffstat (limited to 'Objects/floatobject.c')
| -rw-r--r-- | Objects/floatobject.c | 150 | 
1 files changed, 108 insertions, 42 deletions
diff --git a/Objects/floatobject.c b/Objects/floatobject.c index b58c7fd494..c841423422 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  | 
