diff -r 90cd87f64632 Modules/mathmodule.c --- a/Modules/mathmodule.c Sat Jan 11 20:04:29 2014 +0100 +++ b/Modules/mathmodule.c Sat Jan 11 22:56:02 2014 +0100 @@ -55,6 +55,12 @@ raised for division by zero and mod by z #include "Python.h" #include "_math.h" +/*[clinic input] +module math +[clinic start generated code]*/ +/*[clinic end generated code: checksum=da39a3ee5e6b4b0d3255bfef95601890afd80709]*/ + + /* sin(pi*x), giving accurate results for all finite x (especially x integral or close to an integer). This is here for use in the @@ -698,7 +704,7 @@ is_error(double x) /* math_1 is used to wrap a libm function f that takes a double - arguments and returns a double. + argument and returns a double. The error reporting follows these rules, which are designed to do the right thing on C89/C99 platforms and IEEE 754/non IEEE 754 @@ -1057,8 +1063,29 @@ static int /* n Depends on IEEE 754 arithmetic guarantees and half-even rounding. */ -static PyObject* -math_fsum(PyObject *self, PyObject *seq) +/*[clinic input] +math.fsum + + seq: 'O' + / + +Return an accurate floating point sum of values in the iterable seq. + +Assumes IEEE-754 floating point arithmetic. +[clinic start generated code]*/ + +PyDoc_STRVAR(math_fsum__doc__, +"fsum(seq)\n" +"Return an accurate floating point sum of values in the iterable seq.\n" +"\n" +"Assumes IEEE-754 floating point arithmetic."); + +#define MATH_FSUM_METHODDEF \ + {"fsum", (PyCFunction)math_fsum, METH_O, math_fsum__doc__}, + +static PyObject * +math_fsum(PyModuleDef *module, PyObject *seq) +/*[clinic end generated code: checksum=525313075ab3cf5f677644c60f26c8d5f96545db]*/ { PyObject *item, *iter, *sum = NULL; Py_ssize_t i, j, n = 0, m = NUM_PARTIALS; @@ -1177,10 +1204,6 @@ math_fsum(PyObject *self, PyObject *seq) #undef NUM_PARTIALS -PyDoc_STRVAR(math_fsum_doc, -"fsum(iterable)\n\n\ -Return an accurate floating point sum of values in the iterable.\n\ -Assumes IEEE-754 floating point arithmetic."); /* Return the smallest integer k such that n < 2**k, or 0 if n == 0. * Equivalent to floor(lg(x))+1. Also equivalent to: bitwidth_of_type - @@ -1390,6 +1413,7 @@ factorial_odd_part(unsigned long n) return NULL; } + /* Lookup table for small factorial values */ static const unsigned long SmallFactorials[] = { @@ -1402,47 +1426,64 @@ static const unsigned long SmallFactoria #endif }; +/*[clinic input] +math.factorial + + x: 'O' + / + +Find x!. Raise a ValueError if x is negative or non-integral. +[clinic start generated code]*/ + +PyDoc_STRVAR(math_factorial__doc__, +"factorial(x)\n" +"Find x!. Raise a ValueError if x is negative or non-integral."); + +#define MATH_FACTORIAL_METHODDEF \ + {"factorial", (PyCFunction)math_factorial, METH_O, math_factorial__doc__}, + static PyObject * -math_factorial(PyObject *self, PyObject *arg) +math_factorial(PyModuleDef *module, PyObject *x) +/*[clinic end generated code: checksum=365207eff1f89c43a76608a65fb0a68932ba20a4]*/ { - long x; + long lx; PyObject *result, *odd_part, *two_valuation; - if (PyFloat_Check(arg)) { - PyObject *lx; - double dx = PyFloat_AS_DOUBLE((PyFloatObject *)arg); + if (PyFloat_Check(x)) { + PyObject *olx; + double dx = PyFloat_AS_DOUBLE((PyFloatObject *)x); if (!(Py_IS_FINITE(dx) && dx == floor(dx))) { PyErr_SetString(PyExc_ValueError, "factorial() only accepts integral values"); return NULL; } - lx = PyLong_FromDouble(dx); - if (lx == NULL) + olx = PyLong_FromDouble(dx); + if (olx == NULL) return NULL; - x = PyLong_AsLong(lx); - Py_DECREF(lx); + lx = PyLong_AsLong(olx); + Py_DECREF(olx); } else - x = PyLong_AsLong(arg); + lx = PyLong_AsLong(x); - if (x == -1 && PyErr_Occurred()) + if (lx == -1 && PyErr_Occurred()) return NULL; - if (x < 0) { + if (lx < 0) { PyErr_SetString(PyExc_ValueError, "factorial() not defined for negative values"); return NULL; } - /* use lookup table if x is small */ - if (x < (long)Py_ARRAY_LENGTH(SmallFactorials)) - return PyLong_FromUnsignedLong(SmallFactorials[x]); + /* use lookup table if lx is small */ + if (lx < (long)Py_ARRAY_LENGTH(SmallFactorials)) + return PyLong_FromUnsignedLong(SmallFactorials[lx]); /* else express in the form odd_part * 2**two_valuation, and compute as odd_part << two_valuation. */ - odd_part = factorial_odd_part(x); + odd_part = factorial_odd_part(lx); if (odd_part == NULL) return NULL; - two_valuation = PyLong_FromLong(x - count_set_bits(x)); + two_valuation = PyLong_FromLong(lx - count_set_bits(lx)); if (two_valuation == NULL) { Py_DECREF(odd_part); return NULL; @@ -1453,28 +1494,45 @@ math_factorial(PyObject *self, PyObject return result; } -PyDoc_STRVAR(math_factorial_doc, -"factorial(x) -> Integral\n" + +/*[clinic input] +math.trunc + + x: 'O' + / + +Truncates the Real x to the nearest Integral toward 0. + +Uses the __trunc__ magic method. +[clinic start generated code]*/ + +PyDoc_STRVAR(math_trunc__doc__, +"trunc(x)\n" +"Truncates the Real x to the nearest Integral toward 0.\n" "\n" -"Find x!. Raise a ValueError if x is negative or non-integral."); +"Uses the __trunc__ magic method."); + +#define MATH_TRUNC_METHODDEF \ + {"trunc", (PyCFunction)math_trunc, METH_O, math_trunc__doc__}, static PyObject * -math_trunc(PyObject *self, PyObject *number) +math_trunc(PyModuleDef *module, PyObject *x) +/*[clinic end generated code: checksum=e2fe12a1ffcf1a5bb72bd904715f8dbcabb91bdf]*/ { _Py_IDENTIFIER(__trunc__); PyObject *trunc, *result; - if (Py_TYPE(number)->tp_dict == NULL) { - if (PyType_Ready(Py_TYPE(number)) < 0) + if (Py_TYPE(x)->tp_dict == NULL) { + if (PyType_Ready(Py_TYPE(x)) < 0) return NULL; } - trunc = _PyObject_LookupSpecial(number, &PyId___trunc__); + trunc = _PyObject_LookupSpecial(x, &PyId___trunc__); if (trunc == NULL) { if (!PyErr_Occurred()) PyErr_Format(PyExc_TypeError, "type %.100s doesn't define __trunc__ method", - Py_TYPE(number)->tp_name); + Py_TYPE(x)->tp_name); return NULL; } result = PyObject_CallFunctionObjArgs(trunc, NULL); @@ -1482,18 +1540,53 @@ math_trunc(PyObject *self, PyObject *num return result; } -PyDoc_STRVAR(math_trunc_doc, -"trunc(x:Real) -> Integral\n" + +/*[clinic input] +math.frexp + + x: 'd' + / + +Return the mantissa and exponent of x, as pair (m, e). + +m is a float and e is an int, such that x = m * 2.**e. +If x is 0, m and e are both 0. Else 0.5 <= abs(m) < 1.0. +[clinic start generated code]*/ + +PyDoc_STRVAR(math_frexp__doc__, +"frexp(x)\n" +"Return the mantissa and exponent of x, as pair (m, e).\n" "\n" -"Truncates x to the nearest Integral toward 0. Uses the __trunc__ magic method."); +"m is a float and e is an int, such that x = m * 2.**e.\n" +"If x is 0, m and e are both 0. Else 0.5 <= abs(m) < 1.0."); + +#define MATH_FREXP_METHODDEF \ + {"frexp", (PyCFunction)math_frexp, METH_VARARGS, math_frexp__doc__}, static PyObject * -math_frexp(PyObject *self, PyObject *arg) +math_frexp_impl(PyModuleDef *module, double x); + +static PyObject * +math_frexp(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + double x; + + if (!PyArg_ParseTuple(args, + "d:frexp", + &x)) + goto exit; + return_value = math_frexp_impl(module, x); + +exit: + return return_value; +} + +static PyObject * +math_frexp_impl(PyModuleDef *module, double x) +/*[clinic end generated code: checksum=e5447c29622eb9306d0bc9effc8b9e0ff2bfa0d1]*/ { 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) { @@ -1507,27 +1600,60 @@ math_frexp(PyObject *self, PyObject *arg return Py_BuildValue("(di)", x, i); } -PyDoc_STRVAR(math_frexp_doc, -"frexp(x)\n" + +/*[clinic input] +math.ldexp + + x: 'd' + i: 'O' + / + +Return x * (2**i). + +This is essentially the inverse of frexp(). +[clinic start generated code]*/ + +PyDoc_STRVAR(math_ldexp__doc__, +"ldexp(x, i)\n" +"Return x * (2**i).\n" "\n" -"Return the mantissa and exponent of x, as pair (m, e).\n" -"m is a float and e is an int, such that x = m * 2.**e.\n" -"If x is 0, m and e are both 0. Else 0.5 <= abs(m) < 1.0."); +"This is essentially the inverse of frexp()."); + +#define MATH_LDEXP_METHODDEF \ + {"ldexp", (PyCFunction)math_ldexp, METH_VARARGS, math_ldexp__doc__}, static PyObject * -math_ldexp(PyObject *self, PyObject *args) +math_ldexp_impl(PyModuleDef *module, double x, PyObject *i); + +static PyObject * +math_ldexp(PyModuleDef *module, PyObject *args) { - double x, r; - PyObject *oexp; + PyObject *return_value = NULL; + double x; + PyObject *i; + + if (!PyArg_ParseTuple(args, + "dO:ldexp", + &x, &i)) + goto exit; + return_value = math_ldexp_impl(module, x, i); + +exit: + return return_value; +} + +static PyObject * +math_ldexp_impl(PyModuleDef *module, double x, PyObject *i) +/*[clinic end generated code: checksum=f9e76dfeba901b55df962428a806e63cf34db46f]*/ +{ + double r; long exp; int overflow; - if (! PyArg_ParseTuple(args, "dO:ldexp", &x, &oexp)) - return NULL; - if (PyLong_Check(oexp)) { + if (PyLong_Check(i)) { /* on overflow, replace exponent with either LONG_MAX or LONG_MIN, depending on the sign. */ - exp = PyLong_AsLongAndOverflow(oexp, &overflow); + exp = PyLong_AsLongAndOverflow(i, &overflow); if (exp == -1 && PyErr_Occurred()) return NULL; if (overflow) @@ -1565,16 +1691,51 @@ math_ldexp(PyObject *self, PyObject *arg return PyFloat_FromDouble(r); } -PyDoc_STRVAR(math_ldexp_doc, -"ldexp(x, i)\n\n\ -Return x * (2**i)."); + +/*[clinic input] +math.modf + + x: 'd' + / + +Return the fractional and integer parts of x. + +Both results carry the sign of x and are floats. +[clinic start generated code]*/ + +PyDoc_STRVAR(math_modf__doc__, +"modf(x)\n" +"Return the fractional and integer parts of x.\n" +"\n" +"Both results carry the sign of x and are floats."); + +#define MATH_MODF_METHODDEF \ + {"modf", (PyCFunction)math_modf, METH_VARARGS, math_modf__doc__}, static PyObject * -math_modf(PyObject *self, PyObject *arg) +math_modf_impl(PyModuleDef *module, double x); + +static PyObject * +math_modf(PyModuleDef *module, PyObject *args) { - double y, x = PyFloat_AsDouble(arg); - if (x == -1.0 && PyErr_Occurred()) - return NULL; + PyObject *return_value = NULL; + double x; + + if (!PyArg_ParseTuple(args, + "d:modf", + &x)) + goto exit; + return_value = math_modf_impl(module, x); + +exit: + return return_value; +} + +static PyObject * +math_modf_impl(PyModuleDef *module, double x) +/*[clinic end generated code: checksum=60e120a350cbb87449cc8601141d3c3a91c6b922]*/ +{ + double y; /* 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)) { @@ -1591,11 +1752,6 @@ math_modf(PyObject *self, PyObject *arg) return Py_BuildValue("(dd)", x, y); } -PyDoc_STRVAR(math_modf_doc, -"modf(x)\n" -"\n" -"Return the fractional and integer parts of x. Both results carry the sign\n" -"of x and are floats."); /* A decent logarithm is easy to compute even for huge ints, but libm can't do that by itself -- loghelper can. func is log or log10, and name is @@ -1644,18 +1800,56 @@ loghelper(PyObject* arg, double (*func)( return math_1(arg, func, 0); } + +/*[clinic input] +math.log + + x: 'O' + base: 'O' = NULL + / + +Return the logarithm of x to the given base. + +If the base not specified, returns the natural logarithm (base e) of x. +[clinic start generated code]*/ + +PyDoc_STRVAR(math_log__doc__, +"log(x, base=None)\n" +"Return the logarithm of x to the given base.\n" +"\n" +"If the base not specified, returns the natural logarithm (base e) of x."); + +#define MATH_LOG_METHODDEF \ + {"log", (PyCFunction)math_log, METH_VARARGS, math_log__doc__}, + static PyObject * -math_log(PyObject *self, PyObject *args) +math_log_impl(PyModuleDef *module, PyObject *x, PyObject *base); + +static PyObject * +math_log(PyModuleDef *module, PyObject *args) { - PyObject *arg; + PyObject *return_value = NULL; + PyObject *x; PyObject *base = NULL; + + if (!PyArg_ParseTuple(args, + "O|O:log", + &x, &base)) + goto exit; + return_value = math_log_impl(module, x, base); + +exit: + return return_value; +} + +static PyObject * +math_log_impl(PyModuleDef *module, PyObject *x, PyObject *base) +/*[clinic end generated code: checksum=9745a04130f8d75236553afa6a0a5f6695a4eff6]*/ +{ PyObject *num, *den; PyObject *ans; - if (!PyArg_UnpackTuple(args, "log", 1, 2, &arg, &base)) - return NULL; - - num = loghelper(arg, m_log, "log"); + num = loghelper(x, m_log, "log"); if (num == NULL || base == NULL) return num; @@ -1671,40 +1865,101 @@ math_log(PyObject *self, PyObject *args) return ans; } -PyDoc_STRVAR(math_log_doc, -"log(x[, base])\n\n\ -Return the logarithm of x to the given base.\n\ -If the base not specified, returns the natural logarithm (base e) of x."); + +/*[clinic input] +math.log2 + + x: 'O' + / + +Return the base 2 logarithm of x. +[clinic start generated code]*/ + +PyDoc_STRVAR(math_log2__doc__, +"log2(x)\n" +"Return the base 2 logarithm of x."); + +#define MATH_LOG2_METHODDEF \ + {"log2", (PyCFunction)math_log2, METH_O, math_log2__doc__}, static PyObject * -math_log2(PyObject *self, PyObject *arg) +math_log2(PyModuleDef *module, PyObject *x) +/*[clinic end generated code: checksum=66b8d96da6c0838ece32b73aeebbd7fb4197d089]*/ { - return loghelper(arg, m_log2, "log2"); + return loghelper(x, m_log2, "log2"); } -PyDoc_STRVAR(math_log2_doc, -"log2(x)\n\nReturn the base 2 logarithm of x."); + +/*[clinic input] +math.log10 + + x: 'O' + / + +Return the base 10 logarithm of x. +[clinic start generated code]*/ + +PyDoc_STRVAR(math_log10__doc__, +"log10(x)\n" +"Return the base 10 logarithm of x."); + +#define MATH_LOG10_METHODDEF \ + {"log10", (PyCFunction)math_log10, METH_O, math_log10__doc__}, static PyObject * -math_log10(PyObject *self, PyObject *arg) +math_log10(PyModuleDef *module, PyObject *x) +/*[clinic end generated code: checksum=03f64b254a474e33cf36a9eb06a0d1a01e70d556]*/ { - return loghelper(arg, m_log10, "log10"); + return loghelper(x, m_log10, "log10"); } -PyDoc_STRVAR(math_log10_doc, -"log10(x)\n\nReturn the base 10 logarithm of x."); + +/*[clinic input] +math.fmod + + x: 'd' + y: 'd' + / + +Return fmod(x, y), according to platform C. + +x % y may differ. +[clinic start generated code]*/ + +PyDoc_STRVAR(math_fmod__doc__, +"fmod(x, y)\n" +"Return fmod(x, y), according to platform C.\n" +"\n" +"x % y may differ."); + +#define MATH_FMOD_METHODDEF \ + {"fmod", (PyCFunction)math_fmod, METH_VARARGS, math_fmod__doc__}, static PyObject * -math_fmod(PyObject *self, PyObject *args) +math_fmod_impl(PyModuleDef *module, double x, double y); + +static PyObject * +math_fmod(PyModuleDef *module, 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; + PyObject *return_value = NULL; + double x; + double y; + + if (!PyArg_ParseTuple(args, + "dd:fmod", + &x, &y)) + goto exit; + return_value = math_fmod_impl(module, x, y); + +exit: + return return_value; +} + +static PyObject * +math_fmod_impl(PyModuleDef *module, double x, double y) +/*[clinic end generated code: checksum=d1a5eaf7b35abb104bbdfe4a270a0dc078a3f906]*/ +{ + double r; /* fmod(x, +/-Inf) returns x for finite x. */ if (Py_IS_INFINITY(y) && Py_IS_FINITE(x)) return PyFloat_FromDouble(x); @@ -1724,21 +1979,49 @@ math_fmod(PyObject *self, PyObject *args return PyFloat_FromDouble(r); } -PyDoc_STRVAR(math_fmod_doc, -"fmod(x, y)\n\nReturn fmod(x, y), according to platform C." -" x % y may differ."); + +/*[clinic input] +math.hypot + + x: 'd' + y: 'd' + / + +Return the Euclidean distance, sqrt(x*x + y*y). +[clinic start generated code]*/ + +PyDoc_STRVAR(math_hypot__doc__, +"hypot(x, y)\n" +"Return the Euclidean distance, sqrt(x*x + y*y)."); + +#define MATH_HYPOT_METHODDEF \ + {"hypot", (PyCFunction)math_hypot, METH_VARARGS, math_hypot__doc__}, static PyObject * -math_hypot(PyObject *self, PyObject *args) +math_hypot_impl(PyModuleDef *module, double x, double y); + +static PyObject * +math_hypot(PyModuleDef *module, 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; + PyObject *return_value = NULL; + double x; + double y; + + if (!PyArg_ParseTuple(args, + "dd:hypot", + &x, &y)) + goto exit; + return_value = math_hypot_impl(module, x, y); + +exit: + return return_value; +} + +static PyObject * +math_hypot_impl(PyModuleDef *module, double x, double y) +/*[clinic end generated code: checksum=3f9cd5b0fd9182f8d80949347a4f05e32200fff1]*/ +{ + double r; /* hypot(x, +/-Inf) returns Inf, even if x is a NaN. */ if (Py_IS_INFINITY(x)) return PyFloat_FromDouble(fabs(x)); @@ -1766,8 +2049,6 @@ math_hypot(PyObject *self, PyObject *arg return PyFloat_FromDouble(r); } -PyDoc_STRVAR(math_hypot_doc, -"hypot(x, y)\n\nReturn the Euclidean distance, sqrt(x*x + y*y)."); /* pow can't use math_2, but needs its own wrapper: the problem is that an infinite result can arise either as a result of overflow @@ -1775,20 +2056,50 @@ PyDoc_STRVAR(math_hypot_doc, e.g. 0.**-5. (for which ValueError needs to be raised.) */ +/*[clinic input] +math.pow + + x: 'd' + y: 'd' + / + +Return x**y (x to the power of y). +[clinic start generated code]*/ + +PyDoc_STRVAR(math_pow__doc__, +"pow(x, y)\n" +"Return x**y (x to the power of y)."); + +#define MATH_POW_METHODDEF \ + {"pow", (PyCFunction)math_pow, METH_VARARGS, math_pow__doc__}, + static PyObject * -math_pow(PyObject *self, PyObject *args) +math_pow_impl(PyModuleDef *module, double x, double y); + +static PyObject * +math_pow(PyModuleDef *module, PyObject *args) { - PyObject *ox, *oy; - double r, x, y; + PyObject *return_value = NULL; + double x; + double y; + + if (!PyArg_ParseTuple(args, + "dd:pow", + &x, &y)) + goto exit; + return_value = math_pow_impl(module, x, y); + +exit: + return return_value; +} + +static PyObject * +math_pow_impl(PyModuleDef *module, double x, double y) +/*[clinic end generated code: checksum=13c5b8080403c6d80426125678c21de0fe143399]*/ +{ + double r; 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 */ @@ -1853,76 +2164,224 @@ math_pow(PyObject *self, PyObject *args) return PyFloat_FromDouble(r); } -PyDoc_STRVAR(math_pow_doc, -"pow(x, y)\n\nReturn x**y (x to the power of y)."); static const double degToRad = Py_MATH_PI / 180.0; static const double radToDeg = 180.0 / Py_MATH_PI; +/*[clinic input] +math.degrees + + x: 'd' + / + +Convert angle x from radians to degrees. +[clinic start generated code]*/ + +PyDoc_STRVAR(math_degrees__doc__, +"degrees(x)\n" +"Convert angle x from radians to degrees."); + +#define MATH_DEGREES_METHODDEF \ + {"degrees", (PyCFunction)math_degrees, METH_VARARGS, math_degrees__doc__}, + static PyObject * -math_degrees(PyObject *self, PyObject *arg) +math_degrees_impl(PyModuleDef *module, double x); + +static PyObject * +math_degrees(PyModuleDef *module, PyObject *args) { - double x = PyFloat_AsDouble(arg); - if (x == -1.0 && PyErr_Occurred()) - return NULL; + PyObject *return_value = NULL; + double x; + + if (!PyArg_ParseTuple(args, + "d:degrees", + &x)) + goto exit; + return_value = math_degrees_impl(module, x); + +exit: + return return_value; +} + +static PyObject * +math_degrees_impl(PyModuleDef *module, double x) +/*[clinic end generated code: checksum=472eeb3affd8396f151fd35a62f44dad554b3b91]*/ +{ return PyFloat_FromDouble(x * radToDeg); } -PyDoc_STRVAR(math_degrees_doc, -"degrees(x)\n\n\ -Convert angle x from radians to degrees."); + +/*[clinic input] +math.radians + + x: 'd' + / + +Convert angle x from degrees to radians. +[clinic start generated code]*/ + +PyDoc_STRVAR(math_radians__doc__, +"radians(x)\n" +"Convert angle x from degrees to radians."); + +#define MATH_RADIANS_METHODDEF \ + {"radians", (PyCFunction)math_radians, METH_VARARGS, math_radians__doc__}, static PyObject * -math_radians(PyObject *self, PyObject *arg) +math_radians_impl(PyModuleDef *module, double x); + +static PyObject * +math_radians(PyModuleDef *module, PyObject *args) { - double x = PyFloat_AsDouble(arg); - if (x == -1.0 && PyErr_Occurred()) - return NULL; + PyObject *return_value = NULL; + double x; + + if (!PyArg_ParseTuple(args, + "d:radians", + &x)) + goto exit; + return_value = math_radians_impl(module, x); + +exit: + return return_value; +} + +static PyObject * +math_radians_impl(PyModuleDef *module, double x) +/*[clinic end generated code: checksum=070ef2c3da4fb6f91326423cf57ea94756240093]*/ +{ return PyFloat_FromDouble(x * degToRad); } -PyDoc_STRVAR(math_radians_doc, -"radians(x)\n\n\ -Convert angle x from degrees to radians."); + +/*[clinic input] +math.isfinite + + x: 'd' + / + +Return True if x is neither an infinity nor a NaN, and False otherwise. +[clinic start generated code]*/ + +PyDoc_STRVAR(math_isfinite__doc__, +"isfinite(x)\n" +"Return True if x is neither an infinity nor a NaN, and False otherwise."); + +#define MATH_ISFINITE_METHODDEF \ + {"isfinite", (PyCFunction)math_isfinite, METH_VARARGS, math_isfinite__doc__}, static PyObject * -math_isfinite(PyObject *self, PyObject *arg) +math_isfinite_impl(PyModuleDef *module, double x); + +static PyObject * +math_isfinite(PyModuleDef *module, PyObject *args) { - double x = PyFloat_AsDouble(arg); - if (x == -1.0 && PyErr_Occurred()) - return NULL; + PyObject *return_value = NULL; + double x; + + if (!PyArg_ParseTuple(args, + "d:isfinite", + &x)) + goto exit; + return_value = math_isfinite_impl(module, x); + +exit: + return return_value; +} + +static PyObject * +math_isfinite_impl(PyModuleDef *module, double x) +/*[clinic end generated code: checksum=38cc520053185db5841f7484e7552c053fea6ee6]*/ +{ return PyBool_FromLong((long)Py_IS_FINITE(x)); } -PyDoc_STRVAR(math_isfinite_doc, -"isfinite(x) -> bool\n\n\ -Return True if x is neither an infinity nor a NaN, and False otherwise."); + +/*[clinic input] +math.isnan + + x: 'd' + / + +Return True if x is a NaN (not a number), and False otherwise. +[clinic start generated code]*/ + +PyDoc_STRVAR(math_isnan__doc__, +"isnan(x)\n" +"Return True if x is a NaN (not a number), and False otherwise."); + +#define MATH_ISNAN_METHODDEF \ + {"isnan", (PyCFunction)math_isnan, METH_VARARGS, math_isnan__doc__}, static PyObject * -math_isnan(PyObject *self, PyObject *arg) +math_isnan_impl(PyModuleDef *module, double x); + +static PyObject * +math_isnan(PyModuleDef *module, PyObject *args) { - double x = PyFloat_AsDouble(arg); - if (x == -1.0 && PyErr_Occurred()) - return NULL; + PyObject *return_value = NULL; + double x; + + if (!PyArg_ParseTuple(args, + "d:isnan", + &x)) + goto exit; + return_value = math_isnan_impl(module, x); + +exit: + return return_value; +} + +static PyObject * +math_isnan_impl(PyModuleDef *module, double x) +/*[clinic end generated code: checksum=74e3d28b5f36a0560f01fc2cd862835afb0a0848]*/ +{ return PyBool_FromLong((long)Py_IS_NAN(x)); } -PyDoc_STRVAR(math_isnan_doc, -"isnan(x) -> bool\n\n\ -Return True if x is a NaN (not a number), and False otherwise."); + +/*[clinic input] +math.isinf + + x: 'd' + / + +Return True if x is a positive or negative infinity, and False otherwise. +[clinic start generated code]*/ + +PyDoc_STRVAR(math_isinf__doc__, +"isinf(x)\n" +"Return True if x is a positive or negative infinity, and False otherwise."); + +#define MATH_ISINF_METHODDEF \ + {"isinf", (PyCFunction)math_isinf, METH_VARARGS, math_isinf__doc__}, static PyObject * -math_isinf(PyObject *self, PyObject *arg) +math_isinf_impl(PyModuleDef *module, double x); + +static PyObject * +math_isinf(PyModuleDef *module, PyObject *args) { - double x = PyFloat_AsDouble(arg); - if (x == -1.0 && PyErr_Occurred()) - return NULL; + PyObject *return_value = NULL; + double x; + + if (!PyArg_ParseTuple(args, + "d:isinf", + &x)) + goto exit; + return_value = math_isinf_impl(module, x); + +exit: + return return_value; +} + +static PyObject * +math_isinf_impl(PyModuleDef *module, double x) +/*[clinic end generated code: checksum=2bf1422fdc9b522b641c770ad8f1463464fd8027]*/ +{ return PyBool_FromLong((long)Py_IS_INFINITY(x)); } -PyDoc_STRVAR(math_isinf_doc, -"isinf(x) -> bool\n\n\ -Return True if x is a positive or negative infinity, and False otherwise."); static PyMethodDef math_methods[] = { {"acos", math_acos, METH_O, math_acos_doc}, @@ -1936,37 +2395,37 @@ static PyMethodDef math_methods[] = { {"copysign", math_copysign, METH_VARARGS, math_copysign_doc}, {"cos", math_cos, METH_O, math_cos_doc}, {"cosh", math_cosh, METH_O, math_cosh_doc}, - {"degrees", math_degrees, METH_O, math_degrees_doc}, + MATH_DEGREES_METHODDEF {"erf", math_erf, METH_O, math_erf_doc}, {"erfc", math_erfc, METH_O, math_erfc_doc}, {"exp", math_exp, METH_O, math_exp_doc}, {"expm1", math_expm1, METH_O, math_expm1_doc}, {"fabs", math_fabs, METH_O, math_fabs_doc}, - {"factorial", math_factorial, METH_O, math_factorial_doc}, + MATH_FACTORIAL_METHODDEF {"floor", math_floor, METH_O, math_floor_doc}, - {"fmod", math_fmod, METH_VARARGS, math_fmod_doc}, - {"frexp", math_frexp, METH_O, math_frexp_doc}, - {"fsum", math_fsum, METH_O, math_fsum_doc}, + MATH_FMOD_METHODDEF + MATH_FREXP_METHODDEF + MATH_FSUM_METHODDEF {"gamma", math_gamma, METH_O, math_gamma_doc}, - {"hypot", math_hypot, METH_VARARGS, math_hypot_doc}, - {"isfinite", math_isfinite, METH_O, math_isfinite_doc}, - {"isinf", math_isinf, METH_O, math_isinf_doc}, - {"isnan", math_isnan, METH_O, math_isnan_doc}, - {"ldexp", math_ldexp, METH_VARARGS, math_ldexp_doc}, + MATH_HYPOT_METHODDEF + MATH_ISFINITE_METHODDEF + MATH_ISINF_METHODDEF + MATH_ISNAN_METHODDEF + MATH_LDEXP_METHODDEF {"lgamma", math_lgamma, METH_O, math_lgamma_doc}, - {"log", math_log, METH_VARARGS, math_log_doc}, + MATH_LOG_METHODDEF {"log1p", math_log1p, METH_O, math_log1p_doc}, - {"log10", math_log10, METH_O, math_log10_doc}, - {"log2", math_log2, METH_O, math_log2_doc}, - {"modf", math_modf, METH_O, math_modf_doc}, - {"pow", math_pow, METH_VARARGS, math_pow_doc}, - {"radians", math_radians, METH_O, math_radians_doc}, + MATH_LOG10_METHODDEF + MATH_LOG2_METHODDEF + MATH_MODF_METHODDEF + MATH_POW_METHODDEF + MATH_RADIANS_METHODDEF {"sin", math_sin, METH_O, math_sin_doc}, {"sinh", math_sinh, METH_O, math_sinh_doc}, {"sqrt", math_sqrt, METH_O, math_sqrt_doc}, {"tan", math_tan, METH_O, math_tan_doc}, {"tanh", math_tanh, METH_O, math_tanh_doc}, - {"trunc", math_trunc, METH_O, math_trunc_doc}, + MATH_TRUNC_METHODDEF {NULL, NULL} /* sentinel */ };