static PyObject *
math_2(PyObject *args, double (*func) (double, double), char *funcname)
{
	PyObject *ox, *oy;
	double x, y, r;
	if (! PyArg_UnpackTuple(args, funcname, 2, 2, &ox, &oy))
		return NULL;
	x = PyFloat_AsDouble(ox);
	y = PyFloat_AsDouble(oy);
	if ((x == -1.0 || y == -1.0) && PyErr_Occurred())
		return NULL;
	errno = 0;
	PyFPE_START_PROTECT("in math_2", return 0);
	r = (*func)(x, y);
	PyFPE_END_PROTECT(r);
	if (Py_IS_NAN(r)) {
		if (!Py_IS_NAN(x) && !Py_IS_NAN(y))
			errno = EDOM;
		else
			errno = 0;
	}
	else if (Py_IS_INFINITY(r)) {
		if (Py_IS_FINITE(x) && Py_IS_FINITE(y))
			errno = ERANGE;
		else
			errno = 0;
	}
	if (errno && is_error(r))
		return NULL;
	else
		return PyFloat_FromDouble(r);
}
示例#2
0
double
c_abs(Py_complex z)
{
	/* sets errno = ERANGE on overflow;  otherwise errno = 0 */
	double result;

	if (!Py_IS_FINITE(z.real) || !Py_IS_FINITE(z.imag)) {
		/* C99 rules: if either the real or the imaginary part is an
		   infinity, return infinity, even if the other part is a
		   NaN. */
		if (Py_IS_INFINITY(z.real)) {
			result = fabs(z.real);
			errno = 0;
			return result;
		}
		if (Py_IS_INFINITY(z.imag)) {
			result = fabs(z.imag);
			errno = 0;
			return result;
		}
		/* either the real or imaginary part is a NaN,
		   and neither is infinite. Result should be NaN. */
		return Py_NAN;
	}
	result = hypot(z.real, z.imag);
	if (!Py_IS_FINITE(result))
		errno = ERANGE;
	else
		errno = 0;
	return result;
}
static PyObject *
math_1_to_whatever(PyObject *arg, double (*func) (double),
                   PyObject *(*from_double_func) (double),
                   int can_overflow)
{
	double x, r;
	x = PyFloat_AsDouble(arg);
	if (x == -1.0 && PyErr_Occurred())
		return NULL;
	errno = 0;
	PyFPE_START_PROTECT("in math_1", return 0);
	r = (*func)(x);
	PyFPE_END_PROTECT(r);
	if (Py_IS_NAN(r) && !Py_IS_NAN(x)) {
		PyErr_SetString(PyExc_ValueError,
				"math domain error"); /* invalid arg */
		return NULL;
	}
	if (Py_IS_INFINITY(r) && Py_IS_FINITE(x)) {
			if (can_overflow)
				PyErr_SetString(PyExc_OverflowError,
					"math range error"); /* overflow */
			else
				PyErr_SetString(PyExc_ValueError,
					"math domain error"); /* singularity */
			return NULL;
	}
	if (Py_IS_FINITE(r) && errno && is_error(r))
		/* this branch unnecessary on most platforms */
		return NULL;

	return (*from_double_func)(r);
}
示例#4
0
static PyObject *
complex_is_finite(PyObject *self)
{
	Py_complex c;
	c = ((PyComplexObject *)self)->cval;
	return PyBool_FromLong((long)(Py_IS_FINITE(c.real) &&
				      Py_IS_FINITE(c.imag)));
}
示例#5
0
static void
complex_to_buf(char *buf, int bufsz, PyComplexObject *v, int precision)
{
	char format[32];
	if (v->cval.real == 0.) {
		if (!Py_IS_FINITE(v->cval.imag)) {
			if (Py_IS_NAN(v->cval.imag))
				strncpy(buf, "nan*j", 6);
			else if (copysign(1, v->cval.imag) == 1)
				strncpy(buf, "inf*j", 6);
			else
				strncpy(buf, "-inf*j", 7);
		}
		else {
			PyOS_snprintf(format, sizeof(format), "%%.%ig", precision);
			PyOS_ascii_formatd(buf, bufsz - 1, format, v->cval.imag);
			strncat(buf, "j", 1);
		}
	} else {
		char re[64], im[64];
		/* Format imaginary part with sign, real part without */
		if (!Py_IS_FINITE(v->cval.real)) {
			if (Py_IS_NAN(v->cval.real))
				strncpy(re, "nan", 4);
			/* else if (copysign(1, v->cval.real) == 1) */
			else if (v->cval.real > 0)
				strncpy(re, "inf", 4);
			else
				strncpy(re, "-inf", 5);
		}
		else {
			PyOS_snprintf(format, sizeof(format), "%%.%ig", precision);
			PyOS_ascii_formatd(re, sizeof(re), format, v->cval.real);
		}
		if (!Py_IS_FINITE(v->cval.imag)) {
			if (Py_IS_NAN(v->cval.imag))
				strncpy(im, "+nan*", 6);
			/* else if (copysign(1, v->cval.imag) == 1) */
			else if (v->cval.imag > 0)
				strncpy(im, "+inf*", 6);
			else
				strncpy(im, "-inf*", 6);
		}
		else {
			PyOS_snprintf(format, sizeof(format), "%%+.%ig", precision);
			PyOS_ascii_formatd(im, sizeof(im), format, v->cval.imag);
		}
		PyOS_snprintf(buf, bufsz, "(%s%sj)", re, im);
	}
}
static PyObject *
math_fmod(PyObject *self, PyObject *args)
{
	PyObject *ox, *oy;
	double r, x, y;
	if (! PyArg_UnpackTuple(args, "fmod", 2, 2, &ox, &oy))
		return NULL;
	x = PyFloat_AsDouble(ox);
	y = PyFloat_AsDouble(oy);
	if ((x == -1.0 || y == -1.0) && PyErr_Occurred())
		return NULL;
	/* fmod(x, +/-Inf) returns x for finite x. */
	if (Py_IS_INFINITY(y) && Py_IS_FINITE(x))
		return PyFloat_FromDouble(x);
	errno = 0;
	PyFPE_START_PROTECT("in math_fmod", return 0);
	r = fmod(x, y);
	PyFPE_END_PROTECT(r);
	if (Py_IS_NAN(r)) {
		if (!Py_IS_NAN(x) && !Py_IS_NAN(y))
			errno = EDOM;
		else
			errno = 0;
	}
	if (errno && is_error(r))
		return NULL;
	else
		return PyFloat_FromDouble(r);
}
static PyObject *
math_hypot(PyObject *self, PyObject *args)
{
	PyObject *ox, *oy;
	double r, x, y;
	if (! PyArg_UnpackTuple(args, "hypot", 2, 2, &ox, &oy))
		return NULL;
	x = PyFloat_AsDouble(ox);
	y = PyFloat_AsDouble(oy);
	if ((x == -1.0 || y == -1.0) && PyErr_Occurred())
		return NULL;
	/* hypot(x, +/-Inf) returns Inf, even if x is a NaN. */
	if (Py_IS_INFINITY(x))
		return PyFloat_FromDouble(fabs(x));
	if (Py_IS_INFINITY(y))
		return PyFloat_FromDouble(fabs(y));
	errno = 0;
	PyFPE_START_PROTECT("in math_hypot", return 0);
	r = hypot(x, y);
	PyFPE_END_PROTECT(r);
	if (Py_IS_NAN(r)) {
		if (!Py_IS_NAN(x) && !Py_IS_NAN(y))
			errno = EDOM;
		else
			errno = 0;
	}
	else if (Py_IS_INFINITY(r)) {
		if (Py_IS_FINITE(x) && Py_IS_FINITE(y))
			errno = ERANGE;
		else
			errno = 0;
	}
	if (errno && is_error(r))
		return NULL;
	else
		return PyFloat_FromDouble(r);
}
static PyObject *
math_modf(PyObject *self, PyObject *arg)
{
	double y, x = PyFloat_AsDouble(arg);
	if (x == -1.0 && PyErr_Occurred())
		return NULL;
	/* some platforms don't do the right thing for NaNs and
	   infinities, so we take care of special cases directly. */
	if (!Py_IS_FINITE(x)) {
		if (Py_IS_INFINITY(x))
			return Py_BuildValue("(dd)", copysign(0., x), x);
		else if (Py_IS_NAN(x))
			return Py_BuildValue("(dd)", x, x);
	}          

	errno = 0;
	PyFPE_START_PROTECT("in math_modf", return 0);
	x = modf(x, &y);
	PyFPE_END_PROTECT(x);
	return Py_BuildValue("(dd)", x, y);
}
static PyObject *
math_pow(PyObject *self, PyObject *args)
{
	PyObject *ox, *oy;
	double r, x, y;
	int odd_y;

	if (! PyArg_UnpackTuple(args, "pow", 2, 2, &ox, &oy))
		return NULL;
	x = PyFloat_AsDouble(ox);
	y = PyFloat_AsDouble(oy);
	if ((x == -1.0 || y == -1.0) && PyErr_Occurred())
		return NULL;

	/* deal directly with IEEE specials, to cope with problems on various
	   platforms whose semantics don't exactly match C99 */
	r = 0.; /* silence compiler warning */
	if (!Py_IS_FINITE(x) || !Py_IS_FINITE(y)) {
		errno = 0;
		if (Py_IS_NAN(x))
			r = y == 0. ? 1. : x; /* NaN**0 = 1 */
		else if (Py_IS_NAN(y))
			r = x == 1. ? 1. : y; /* 1**NaN = 1 */
		else if (Py_IS_INFINITY(x)) {
			odd_y = Py_IS_FINITE(y) && fmod(fabs(y), 2.0) == 1.0;
			if (y > 0.)
				r = odd_y ? x : fabs(x);
			else if (y == 0.)
				r = 1.;
			else /* y < 0. */
				r = odd_y ? copysign(0., x) : 0.;
		}
		else if (Py_IS_INFINITY(y)) {
			if (fabs(x) == 1.0)
				r = 1.;
			else if (y > 0. && fabs(x) > 1.0)
				r = y;
			else if (y < 0. && fabs(x) < 1.0) {
				r = -y; /* result is +inf */
				if (x == 0.) /* 0**-inf: divide-by-zero */
					errno = EDOM;
			}
			else
				r = 0.;
		}
	}
	else {
		/* let libm handle finite**finite */
		errno = 0;
		PyFPE_START_PROTECT("in math_pow", return 0);
		r = pow(x, y);
		PyFPE_END_PROTECT(r);
		/* a NaN result should arise only from (-ve)**(finite
		   non-integer); in this case we want to raise ValueError. */
		if (!Py_IS_FINITE(r)) {
			if (Py_IS_NAN(r)) {
				errno = EDOM;
			}
			/* 
			   an infinite result here arises either from:
			   (A) (+/-0.)**negative (-> divide-by-zero)
			   (B) overflow of x**y with x and y finite
			*/
			else if (Py_IS_INFINITY(r)) {
				if (x == 0.)
					errno = EDOM;
				else
					errno = ERANGE;
			}
		}
	}

	if (errno && is_error(r))
		return NULL;
	else
		return PyFloat_FromDouble(r);
}
static PyObject *
math_ldexp(PyObject *self, PyObject *args)
{
	double x, r;
	PyObject *oexp;
	long exp;
	if (! PyArg_ParseTuple(args, "dO:ldexp", &x, &oexp))
		return NULL;

	if (PyLong_Check(oexp)) {
		/* on overflow, replace exponent with either LONG_MAX
		   or LONG_MIN, depending on the sign. */
		exp = PyLong_AsLong(oexp);
		if (exp == -1 && PyErr_Occurred()) {
			if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
				if (Py_SIZE(oexp) < 0) {
					exp = LONG_MIN;
				}
				else {
					exp = LONG_MAX;
				}
				PyErr_Clear();
			}
			else {
				/* propagate any unexpected exception */
				return NULL;
			}
		}
	}
	else {
		PyErr_SetString(PyExc_TypeError,
				"Expected an int or long as second argument "
				"to ldexp.");
		return NULL;
	}

	if (x == 0. || !Py_IS_FINITE(x)) {
		/* NaNs, zeros and infinities are returned unchanged */
		r = x;
		errno = 0;
	} else if (exp > INT_MAX) {
		/* overflow */
		r = copysign(Py_HUGE_VAL, x);
		errno = ERANGE;
	} else if (exp < INT_MIN) {
		/* underflow to +-0 */
		r = copysign(0., x);
		errno = 0;
	} else {
		errno = 0;
		PyFPE_START_PROTECT("in math_ldexp", return 0);
		r = ldexp(x, (int)exp);
		PyFPE_END_PROTECT(r);
		if (Py_IS_INFINITY(r))
			errno = ERANGE;
	}

	if (errno && is_error(r))
		return NULL;
	return PyFloat_FromDouble(r);
}
static PyObject*
math_fsum(PyObject *self, PyObject *seq)
{
	PyObject *item, *iter, *sum = NULL;
	Py_ssize_t i, j, n = 0, m = NUM_PARTIALS;
	double x, y, t, ps[NUM_PARTIALS], *p = ps;
	double xsave, special_sum = 0.0, inf_sum = 0.0;
	volatile double hi, yr, lo;

	iter = PyObject_GetIter(seq);
	if (iter == NULL)
		return NULL;

	PyFPE_START_PROTECT("fsum", Py_DECREF(iter); return NULL)

	for(;;) {           /* for x in iterable */
		assert(0 <= n && n <= m);
		assert((m == NUM_PARTIALS && p == ps) ||
		       (m >  NUM_PARTIALS && p != NULL));

		item = PyIter_Next(iter);
		if (item == NULL) {
			if (PyErr_Occurred())
				goto _fsum_error;
			break;
		}
		x = PyFloat_AsDouble(item);
		Py_DECREF(item);
		if (PyErr_Occurred())
			goto _fsum_error;

		xsave = x;
		for (i = j = 0; j < n; j++) {       /* for y in partials */
			y = p[j];
			if (fabs(x) < fabs(y)) {
				t = x; x = y; y = t;
			}
			hi = x + y;
			yr = hi - x;
			lo = y - yr;
			if (lo != 0.0)
				p[i++] = lo;
			x = hi;
		}

		n = i;                              /* ps[i:] = [x] */
		if (x != 0.0) {
			if (! Py_IS_FINITE(x)) {
				/* a nonfinite x could arise either as
				   a result of intermediate overflow, or
				   as a result of a nan or inf in the
				   summands */
				if (Py_IS_FINITE(xsave)) {
					PyErr_SetString(PyExc_OverflowError,
					      "intermediate overflow in fsum");
					goto _fsum_error;
				}
				if (Py_IS_INFINITY(xsave))
					inf_sum += xsave;
				special_sum += xsave;
				/* reset partials */
				n = 0;
			}
			else if (n >= m && _fsum_realloc(&p, n, ps, &m))
				goto _fsum_error;
			else
				p[n++] = x;
		}
	}

	if (special_sum != 0.0) {
		if (Py_IS_NAN(inf_sum))
			PyErr_SetString(PyExc_ValueError,
					"-inf + inf in fsum");
		else
			sum = PyFloat_FromDouble(special_sum);
		goto _fsum_error;
	}

	hi = 0.0;
	if (n > 0) {
		hi = p[--n];
		/* sum_exact(ps, hi) from the top, stop when the sum becomes
		   inexact. */
		while (n > 0) {
			x = hi;
			y = p[--n];
			assert(fabs(y) < fabs(x));
			hi = x + y;
			yr = hi - x;
			lo = y - yr;
			if (lo != 0.0)
				break;
		}
		/* Make half-even rounding work across multiple partials.
		   Needed so that sum([1e-16, 1, 1e16]) will round-up the last
		   digit to two instead of down to zero (the 1e-16 makes the 1
		   slightly closer to two).  With a potential 1 ULP rounding
		   error fixed-up, math.fsum() can guarantee commutativity. */
		if (n > 0 && ((lo < 0.0 && p[n-1] < 0.0) ||
			      (lo > 0.0 && p[n-1] > 0.0))) {
			y = lo * 2.0;
			x = hi + y;
			yr = x - hi;
			if (y == yr)
				hi = x;
		}
	}
	sum = PyFloat_FromDouble(hi);

_fsum_error:
	PyFPE_END_PROTECT(hi)
	Py_DECREF(iter);
	if (p != ps)
		PyMem_Free(p);
	return sum;
}