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_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);
}
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);
}
static double
m_atan2(double y, double x)
{
	if (Py_IS_NAN(x) || Py_IS_NAN(y))
		return Py_NAN;
	if (Py_IS_INFINITY(y)) {
		if (Py_IS_INFINITY(x)) {
			if (copysign(1., x) == 1.)
				/* atan2(+-inf, +inf) == +-pi/4 */
				return copysign(0.25*Py_MATH_PI, y);
			else
				/* atan2(+-inf, -inf) == +-pi*3/4 */
				return copysign(0.75*Py_MATH_PI, y);
		}
		/* atan2(+-inf, x) == +-pi/2 for finite x */
		return copysign(0.5*Py_MATH_PI, y);
	}
	if (Py_IS_INFINITY(x) || y == 0.) {
		if (copysign(1., x) == 1.)
			/* atan2(+-y, +inf) = atan2(+-0, +x) = +-0. */
			return copysign(0., y);
		else
			/* atan2(+-y, -inf) = atan2(+-0., -x) = +-pi. */
			return copysign(Py_MATH_PI, y);
	}
	return atan2(y, x);
}
Exemple #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);
	}
}
Exemple #6
0
double
_Py_asinh(double x)
{
    double w;
    double absx = fabs(x);

    if (Py_IS_NAN(x) || Py_IS_INFINITY(x)) {
        return x+x;
    }
    if (absx < two_pow_m28) {           /* |x| < 2**-28 */
        return x;                       /* return x inexact except 0 */
    }
    if (absx > two_pow_p28) {           /* |x| > 2**28 */
        w = log(absx)+ln2;
    }
    else if (absx > 2.0) {              /* 2 < |x| < 2**28 */
        w = log(2.0*absx + 1.0 / (sqrt(x*x + 1.0) + absx));
    }
    else {                              /* 2**-28 <= |x| < 2= */
        double t = x*x;
        w = m_log1p(absx + t / (1.0 + sqrt(1.0 + t)));
    }
    return copysign(w, x);

}
Exemple #7
0
double
_Py_acosh(double x)
{
    if (Py_IS_NAN(x)) {
        return x+x;
    }
    if (x < 1.) {                       /* x < 1;  return a signaling NaN */
        errno = EDOM;
#ifdef Py_NAN
        return Py_NAN;
#else
        return (x-x)/(x-x);
#endif
    }
    else if (x >= two_pow_p28) {        /* x > 2**28 */
        if (Py_IS_INFINITY(x)) {
            return x+x;
        }
        else {
            return log(x)+ln2;          /* acosh(huge)=log(2x) */
        }
    }
    else if (x == 1.) {
        return 0.0;                     /* acosh(1) = 0 */
    }
    else if (x > 2.) {                  /* 2 < x < 2**28 */
        double t = x*x;
        return log(2.0*x - 1.0 / (x + sqrt(t - 1.0)));
    }
    else {                              /* 1 < x <= 2 */
        double t = x - 1.0;
        return m_log1p(t + sqrt(2.0*t + t*t));
    }
}
Exemple #8
0
double
_Py_atanh(double x)
{
    double absx;
    double t;

    if (Py_IS_NAN(x)) {
        return x+x;
    }
    absx = fabs(x);
    if (absx >= 1.) {                   /* |x| >= 1 */
        errno = EDOM;
#ifdef Py_NAN
        return Py_NAN;
#else
        return x/zero;
#endif
    }
    if (absx < two_pow_m28) {           /* |x| < 2**-28 */
        return x;
    }
    if (absx < 0.5) {                   /* |x| < 0.5 */
        t = absx+absx;
        t = 0.5 * m_log1p(t + t*absx / (1.0 - absx));
    }
    else {                              /* 0.5 <= |x| <= 1.0 */
        t = 0.5 * m_log1p((absx + absx) / (1.0 - absx));
    }
    return copysign(t, x);
}
static PyObject *
math_isnan(PyObject *self, PyObject *arg)
{
	double x = PyFloat_AsDouble(arg);
	if (x == -1.0 && PyErr_Occurred())
		return NULL;
	return PyBool_FromLong((long)Py_IS_NAN(x));
}
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_frexp(PyObject *self, PyObject *arg)
{
	int i;
	double x = PyFloat_AsDouble(arg);
	if (x == -1.0 && PyErr_Occurred())
		return NULL;
	/* deal with special cases directly, to sidestep platform
	   differences */
	if (Py_IS_NAN(x) || Py_IS_INFINITY(x) || !x) {
		i = 0;
	}
	else {
		PyFPE_START_PROTECT("in math_frexp", return 0);
		x = frexp(x, &i);
		PyFPE_END_PROTECT(x);
	}
	return Py_BuildValue("(di)", x, i);
}
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_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;
}