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);
}
示例#2
0
static PyObject *
complex_pow(PyComplexObject *v, PyObject *w, PyComplexObject *z)
{
	Py_complex p;
	Py_complex exponent;
	long int_exponent;

 	if ((PyObject *)z!=Py_None) {
		PyErr_SetString(PyExc_ValueError, "complex modulo");
		return NULL;
	}
	PyFPE_START_PROTECT("complex_pow", return 0)
	errno = 0;
	exponent = ((PyComplexObject*)w)->cval;
	int_exponent = (long)exponent.real;
	if (exponent.imag == 0. && exponent.real == int_exponent)
		p = c_powi(v->cval,int_exponent);
	else
		p = c_pow(v->cval,exponent);

	PyFPE_END_PROTECT(p)
	Py_ADJUST_ERANGE2(p.real, p.imag);
	if (errno == EDOM) {
		PyErr_SetString(PyExc_ZeroDivisionError,
				"0.0 to a negative or complex power");
		return NULL;
	}
	else if (errno == ERANGE) {
		PyErr_SetString(PyExc_OverflowError,
				"complex exponentiation");
		return NULL;
	}
	return PyComplex_FromCComplex(p);
}
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 bool FLOAT_ADD_INCREMENTAL(PyObject **operand1, PyObject *operand2) {
    assert(PyFloat_CheckExact(*operand1));
    assert(PyFloat_CheckExact(operand2));

    PyFPE_START_PROTECT("add", return false);
    PyFloat_AS_DOUBLE(*operand1) += PyFloat_AS_DOUBLE(operand2);
    PyFPE_END_PROTECT(*operand1);

    return true;
}
示例#6
0
static PyObject *
math_1(PyObject *args, Py_complex (*func)(Py_complex))
{
	Py_complex x;
	if (!PyArg_ParseTuple(args, "D", &x))
		return NULL;
	errno = 0;
	PyFPE_START_PROTECT("complex function", return 0)
	x = (*func)(x);
	PyFPE_END_PROTECT(x)
	Py_ADJUST_ERANGE2(x.real, x.imag);
	if (errno != 0)
		return math_error();
	else
		return PyComplex_FromCComplex(x);
}
示例#7
0
static PyObject *
math_1(PyObject *args, double (*func) (double), char *argsfmt)
{
	double x;
	if (!  PyArg_ParseTuple(args, argsfmt, &x))
		return NULL;
	errno = 0;
	PyFPE_START_PROTECT("in math_1", return 0)
	x = (*func)(x);
	PyFPE_END_PROTECT(x)
	Py_SET_ERANGE_IF_OVERFLOW(x);
	if (errno && is_error(x))
		return NULL;
	else
		return PyFloat_FromDouble(x);
}
示例#8
0
static PyObject *
math_2(PyObject *args, double (*func) (double, double), char *argsfmt)
{
    double x, y;
    if (! PyArg_ParseTuple(args, argsfmt, &x, &y))
        return NULL;
    errno = 0;
    PyFPE_START_PROTECT("in math_2", return 0)
    x = (*func)(x, y);
    PyFPE_END_PROTECT(x)
    Py_SET_ERRNO_ON_MATH_ERROR(x);
    if (errno && is_error(x))
        return NULL;
    else
        return PyFloat_FromDouble(x);
}
示例#9
0
static PyObject *
math_ldexp(PyObject *self, PyObject *args)
{
	double x;
	int exp;
	if (! PyArg_ParseTuple(args, "di:ldexp", &x, &exp))
		return NULL;
	errno = 0;
	PyFPE_START_PROTECT("ldexp", return 0)
	x = ldexp(x, exp);
	PyFPE_END_PROTECT(x)
	Py_SET_ERANGE_IF_OVERFLOW(x);
	if (errno && is_error(x))
		return NULL;
	else
		return PyFloat_FromDouble(x);
}
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_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);
}
示例#13
0
static PyObject *bip_sum(term_t t) {
  PyObject *seq;
  PyObject *result = NULL;
  PyObject *temp, *item, *iter;

  if (!PL_get_arg(1, t, t))
    return NULL;
  seq = term_to_python(t, true);
  iter = PyObject_GetIter(seq);
  if (iter == NULL)
    return NULL;

  if (result == NULL) {
#if PY_MAJOR_VERSION < 3
    result = PyInt_FromLong(0);
#else
    result = PyLong_FromLong(0);
#endif
    if (result == NULL) {
      Py_DECREF(iter);
      return NULL;
    }
  } else {
#if PY_MAJOR_VERSION < 3
    /* reject string values for 'start' parameter */
    if (PyObject_TypeCheck(result, &PyBaseString_Type)) {
      PyErr_SetString(PyExc_TypeError,
                      "sum() can't sum strings [use ''.join(seq) instead]");
      Py_DECREF(iter);
      return NULL;
    }
    Py_INCREF(result);
#endif
  }

#ifndef SLOW_SUM
/* Fast addition by keeping temporary sums in C instead of new Python objects.
Assumes all inputs are the same type.  If the assumption fails, default
to the more general routine.
*/
#if PY_MAJOR_VERSION < 3
  if (PyInt_CheckExact(result)) {
    long i_result = PyInt_AS_LONG(result);
#else
  if (PyLong_CheckExact(result)) {
    long i_result = PyLong_AS_LONG(result);
#endif
    Py_DECREF(result);
    result = NULL;
    while (result == NULL) {
      item = PyIter_Next(iter);
      if (item == NULL) {
        Py_DECREF(iter);
        if (PyErr_Occurred())
          return NULL;
#if PY_MAJOR_VERSION < 3
        return PyInt_FromLong(i_result);
#else
        return PyLong_FromLong(i_result);
#endif
      }
#if PY_MAJOR_VERSION < 3
      if (PyInt_CheckExact(item)) {
        long b = PyInt_AS_LONG(item);
#else
      if (PyLong_CheckExact(item)) {
        long b = PyLong_AS_LONG(item);
#endif
        long x = i_result + b;
        if ((x ^ i_result) >= 0 || (x ^ b) >= 0) {
          i_result = x;
          Py_DECREF(item);
          continue;
        }
      }
/* Either overflowed or is not an int. Restore real objects and process normally
 */
#if PY_MAJOR_VERSION < 3
      result = PyInt_FromLong(i_result);
#else
      result = PyLong_FromLong(i_result);
#endif
      temp = PyNumber_Add(result, item);
      Py_DECREF(result);
      Py_DECREF(item);
      result = temp;
      if (result == NULL) {
        Py_DECREF(iter);
        return NULL;
      }
    }
  }

  if (PyFloat_CheckExact(result)) {
    double f_result = PyFloat_AS_DOUBLE(result);
    Py_DECREF(result);
    result = NULL;
    while (result == NULL) {
      item = PyIter_Next(iter);
      if (item == NULL) {
        Py_DECREF(iter);
        if (PyErr_Occurred())
          return NULL;
        return PyFloat_FromDouble(f_result);
      }
      if (PyFloat_CheckExact(item)) {
        PyFPE_START_PROTECT("add", Py_DECREF(item); Py_DECREF(iter); return 0)
            f_result += PyFloat_AS_DOUBLE(item);
        PyFPE_END_PROTECT(f_result) Py_DECREF(item);
        continue;
      }
#if PY_MAJOR_VERSION < 3
      if (PyInt_CheckExact(item)) {
        PyFPE_START_PROTECT("add", Py_DECREF(item); Py_DECREF(iter); return 0)
            f_result += (double)PyInt_AS_LONG(item);
        PyFPE_END_PROTECT(f_result) Py_DECREF(item);
        continue;
      }
#else
      if (PyLong_CheckExact(item)) {
        PyFPE_START_PROTECT("add", Py_DECREF(item); Py_DECREF(iter); return 0)
            f_result += PyLong_AsDouble(item);
        PyFPE_END_PROTECT(f_result) Py_DECREF(item);
        continue;
      }
#endif
      result = PyFloat_FromDouble(f_result);
      temp = PyNumber_Add(result, item);
      Py_DECREF(result);
      Py_DECREF(item);
      result = temp;
      if (result == NULL) {
        Py_DECREF(iter);
        return NULL;
      }
    }
#endif
  }

  for (;;) {
    item = PyIter_Next(iter);
    if (item == NULL) {
      /* error, or end-of-sequence */
      if (PyErr_Occurred()) {
        Py_DECREF(result);
        result = NULL;
      }
      break;
    }
    /* It's tempting to use PyNumber_InPlaceAdd instead of
    PyNumber_Add here, to avoid quadratic running time
    when doing 'sum(list_of_lists, [])'.  However, this
    would produce a change in behaviour: a snippet like

    empty = []
    sum([[x] for x in range(10)], empty)

    would change the value of empty. */
    temp = PyNumber_Add(result, item);
    Py_DECREF(result);
    Py_DECREF(item);
    result = temp;
    if (result == NULL)
      break;
  }
  Py_DECREF(iter);
  return result;
}

//@}

static long get_int(term_t arg, bool eval) {
  long low;

  if (!PL_get_long(arg, &low)) {
    PyObject *low = term_to_python(arg, eval);
    if (PyLong_Check(low)) {
      return PyLong_AsLong(low);
#if PY_MAJOR_VERSION < 3
    } else if (PyInt_Check(low)) {
      return PyInt_AsLong(low);
#endif
    } else {
      return 0;
    }
  }
  return low;
}

/* Return number of items in range/xrange (lo, hi, step).  step > 0
* required.  Return a value < 0 if & only if the true value is too
* large to fit in a signed long.
*/
static long get_len_of_range(long lo, long hi, long step) {
  /* -------------------------------------------------------------
  If lo >= hi, the range is empty.
  Else if n values are in the range, the last one is
  lo + (n-1)*step, which must be <= hi-1.  Rearranging,
  n <= (hi - lo - 1)/step + 1, so taking the floor of the RHS gives
  the proper value.  Since lo < hi in this case, hi-lo-1 >= 0, so
  the RHS is non-negative and so truncation is the same as the
  floor.  Letting M be the largest positive long, the worst case
  for the RHS numerator is hi=M, lo=-M-1, and then
  hi-lo-1 = M-(-M-1)-1 = 2*M.  Therefore unsigned long has enough
  precision to compute the RHS exactly.
  ---------------------------------------------------------------*/
  long n = 0;
  if (lo < hi) {
    unsigned long uhi = (unsigned long)hi;
    unsigned long ulo = (unsigned long)lo;
    unsigned long diff = uhi - ulo - 1;
    n = (long)(diff / (unsigned long)step + 1);
  }
  return n;
}
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;
}