diff --git a/Modules/clinic/mathmodule.c.h b/Modules/clinic/mathmodule.c.h new file mode 100644 --- /dev/null +++ b/Modules/clinic/mathmodule.c.h @@ -0,0 +1,501 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(math_gcd__doc__, +"gcd($module, x, y, /)\n" +"--\n" +"\n" +"greatest common divisor of x and y"); + +#define MATH_GCD_METHODDEF \ + {"gcd", (PyCFunction)math_gcd, METH_VARARGS, math_gcd__doc__}, + +static PyObject * +math_gcd_impl(PyModuleDef *module, PyObject *a, PyObject *b); + +static PyObject * +math_gcd(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *a; + PyObject *b; + + if (!PyArg_UnpackTuple(args, "gcd", + 2, 2, + &a, &b)) + goto exit; + return_value = math_gcd_impl(module, a, b); + +exit: + return return_value; +} + +PyDoc_STRVAR(math_ceil__doc__, +"ceil($module, x, /)\n" +"--\n" +"\n" +"Return the ceiling of x as an int.\n" +"\n" +"This is the smallest integral value >= x."); + +#define MATH_CEIL_METHODDEF \ + {"ceil", (PyCFunction)math_ceil, METH_O, math_ceil__doc__}, + +PyDoc_STRVAR(math_floor__doc__, +"floor($module, x, /)\n" +"--\n" +"\n" +"Return the floor of x as an int.\n" +"\n" +"This is the largest integral value <= x."); + +#define MATH_FLOOR_METHODDEF \ + {"floor", (PyCFunction)math_floor, METH_O, math_floor__doc__}, + +PyDoc_STRVAR(math_fsum__doc__, +"fsum($module, seq, /)\n" +"--\n" +"\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__}, + +PyDoc_STRVAR(math_factorial__doc__, +"factorial($module, x, /)\n" +"--\n" +"\n" +"Find x!.\n" +"\n" +"Raise a ValueError if x is negative or non-integral."); + +#define MATH_FACTORIAL_METHODDEF \ + {"factorial", (PyCFunction)math_factorial, METH_O, math_factorial__doc__}, + +PyDoc_STRVAR(math_trunc__doc__, +"trunc($module, x, /)\n" +"--\n" +"\n" +"Truncates the Real x to the nearest Integral toward 0.\n" +"\n" +"Uses the __trunc__ magic method."); + +#define MATH_TRUNC_METHODDEF \ + {"trunc", (PyCFunction)math_trunc, METH_O, math_trunc__doc__}, + +PyDoc_STRVAR(math_frexp__doc__, +"frexp($module, x, /)\n" +"--\n" +"\n" +"Return the mantissa and exponent of x, as pair (m, e).\n" +"\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."); + +#define MATH_FREXP_METHODDEF \ + {"frexp", (PyCFunction)math_frexp, METH_O, math_frexp__doc__}, + +static PyObject * +math_frexp_impl(PyModuleDef *module, double x); + +static PyObject * +math_frexp(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + double x; + + if (!PyArg_Parse(arg, "d:frexp", &x)) + goto exit; + return_value = math_frexp_impl(module, x); + +exit: + return return_value; +} + +PyDoc_STRVAR(math_ldexp__doc__, +"ldexp($module, x, i, /)\n" +"--\n" +"\n" +"Return x * (2**i).\n" +"\n" +"This is essentially the inverse of frexp()."); + +#define MATH_LDEXP_METHODDEF \ + {"ldexp", (PyCFunction)math_ldexp, METH_VARARGS, math_ldexp__doc__}, + +static PyObject * +math_ldexp_impl(PyModuleDef *module, double x, PyObject *i); + +static PyObject * +math_ldexp(PyModuleDef *module, PyObject *args) +{ + 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; +} + +PyDoc_STRVAR(math_modf__doc__, +"modf($module, x, /)\n" +"--\n" +"\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_O, math_modf__doc__}, + +static PyObject * +math_modf_impl(PyModuleDef *module, double x); + +static PyObject * +math_modf(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + double x; + + if (!PyArg_Parse(arg, "d:modf", &x)) + goto exit; + return_value = math_modf_impl(module, x); + +exit: + return return_value; +} + +PyDoc_STRVAR(math_log__doc__, +"log(x, [base=math.e])\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_impl(PyModuleDef *module, PyObject *x, int group_right_1, + PyObject *base); + +static PyObject * +math_log(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *x; + int group_right_1 = 0; + PyObject *base = NULL; + + switch (PyTuple_GET_SIZE(args)) { + case 1: + if (!PyArg_ParseTuple(args, "O:log", &x)) + goto exit; + break; + case 2: + if (!PyArg_ParseTuple(args, "OO:log", &x, &base)) + goto exit; + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "math.log requires 1 to 2 arguments"); + goto exit; + } + return_value = math_log_impl(module, x, group_right_1, base); + +exit: + return return_value; +} + +PyDoc_STRVAR(math_log2__doc__, +"log2($module, x, /)\n" +"--\n" +"\n" +"Return the base 2 logarithm of x."); + +#define MATH_LOG2_METHODDEF \ + {"log2", (PyCFunction)math_log2, METH_O, math_log2__doc__}, + +PyDoc_STRVAR(math_log10__doc__, +"log10($module, x, /)\n" +"--\n" +"\n" +"Return the base 10 logarithm of x."); + +#define MATH_LOG10_METHODDEF \ + {"log10", (PyCFunction)math_log10, METH_O, math_log10__doc__}, + +PyDoc_STRVAR(math_fmod__doc__, +"fmod($module, x, y, /)\n" +"--\n" +"\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_impl(PyModuleDef *module, double x, double y); + +static PyObject * +math_fmod(PyModuleDef *module, PyObject *args) +{ + 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; +} + +PyDoc_STRVAR(math_hypot__doc__, +"hypot($module, x, y, /)\n" +"--\n" +"\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_impl(PyModuleDef *module, double x, double y); + +static PyObject * +math_hypot(PyModuleDef *module, PyObject *args) +{ + 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; +} + +PyDoc_STRVAR(math_pow__doc__, +"pow($module, x, y, /)\n" +"--\n" +"\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_impl(PyModuleDef *module, double x, double y); + +static PyObject * +math_pow(PyModuleDef *module, PyObject *args) +{ + 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; +} + +PyDoc_STRVAR(math_degrees__doc__, +"degrees($module, x, /)\n" +"--\n" +"\n" +"Convert angle x from radians to degrees."); + +#define MATH_DEGREES_METHODDEF \ + {"degrees", (PyCFunction)math_degrees, METH_O, math_degrees__doc__}, + +static PyObject * +math_degrees_impl(PyModuleDef *module, double x); + +static PyObject * +math_degrees(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + double x; + + if (!PyArg_Parse(arg, "d:degrees", &x)) + goto exit; + return_value = math_degrees_impl(module, x); + +exit: + return return_value; +} + +PyDoc_STRVAR(math_radians__doc__, +"radians($module, x, /)\n" +"--\n" +"\n" +"Convert angle x from degrees to radians."); + +#define MATH_RADIANS_METHODDEF \ + {"radians", (PyCFunction)math_radians, METH_O, math_radians__doc__}, + +static PyObject * +math_radians_impl(PyModuleDef *module, double x); + +static PyObject * +math_radians(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + double x; + + if (!PyArg_Parse(arg, "d:radians", &x)) + goto exit; + return_value = math_radians_impl(module, x); + +exit: + return return_value; +} + +PyDoc_STRVAR(math_isfinite__doc__, +"isfinite($module, x, /)\n" +"--\n" +"\n" +"Return True if x is neither an infinity nor a NaN, and False otherwise."); + +#define MATH_ISFINITE_METHODDEF \ + {"isfinite", (PyCFunction)math_isfinite, METH_O, math_isfinite__doc__}, + +static PyObject * +math_isfinite_impl(PyModuleDef *module, double x); + +static PyObject * +math_isfinite(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + double x; + + if (!PyArg_Parse(arg, "d:isfinite", &x)) + goto exit; + return_value = math_isfinite_impl(module, x); + +exit: + return return_value; +} + +PyDoc_STRVAR(math_isnan__doc__, +"isnan($module, x, /)\n" +"--\n" +"\n" +"Return True if x is a NaN (not a number), and False otherwise."); + +#define MATH_ISNAN_METHODDEF \ + {"isnan", (PyCFunction)math_isnan, METH_O, math_isnan__doc__}, + +static PyObject * +math_isnan_impl(PyModuleDef *module, double x); + +static PyObject * +math_isnan(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + double x; + + if (!PyArg_Parse(arg, "d:isnan", &x)) + goto exit; + return_value = math_isnan_impl(module, x); + +exit: + return return_value; +} + +PyDoc_STRVAR(math_isinf__doc__, +"isinf($module, x, /)\n" +"--\n" +"\n" +"Return True if x is a positive or negative infinity, and False otherwise."); + +#define MATH_ISINF_METHODDEF \ + {"isinf", (PyCFunction)math_isinf, METH_O, math_isinf__doc__}, + +static PyObject * +math_isinf_impl(PyModuleDef *module, double x); + +static PyObject * +math_isinf(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + double x; + + if (!PyArg_Parse(arg, "d:isinf", &x)) + goto exit; + return_value = math_isinf_impl(module, x); + +exit: + return return_value; +} + +PyDoc_STRVAR(math_isclose__doc__, +"isclose($module, /, a, b, *, rel_tol=1e-09, abs_tol=0.0)\n" +"--\n" +"\n" +"Determine whether two floating point numbers are close in value.\n" +"\n" +" rel_tol\n" +" maximum difference for being considered \"close\", relative to the\n" +" magnitude of the input values\n" +" abs_tol\n" +" maximum difference for being considered \"close\", regardless of the\n" +" magnitude of the input values\n" +"\n" +"Return True if a is close in value to b, and False otherwise.\n" +"\n" +"For the values to be considered close, the difference between them must be\n" +"smaller than at least one of the tolerances.\n" +"\n" +"-inf, inf and NaN behave similarly to the IEEE 754 Standard. That is, NaN is\n" +"not close to anything, even itself. inf and -inf are only close to themselves."); + +#define MATH_ISCLOSE_METHODDEF \ + {"isclose", (PyCFunction)math_isclose, METH_VARARGS|METH_KEYWORDS, math_isclose__doc__}, + +static int +math_isclose_impl(PyModuleDef *module, double a, double b, double rel_tol, + double abs_tol); + +static PyObject * +math_isclose(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"a", "b", "rel_tol", "abs_tol", NULL}; + double a; + double b; + double rel_tol = 1e-09; + double abs_tol = 0.0; + int _return_value; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "dd|$dd:isclose", _keywords, + &a, &b, &rel_tol, &abs_tol)) + goto exit; + _return_value = math_isclose_impl(module, a, b, rel_tol, abs_tol); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} +/*[clinic end generated code: output=d4f7e82e5d99baea input=a9049054013a1b77]*/ diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -55,6 +55,14 @@ #include "Python.h" #include "_math.h" +#include "clinic/mathmodule.c.h" + +/*[clinic input] +module math +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=76bc7002685dd942]*/ + + /* 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 @@ -685,13 +693,21 @@ } +/*[clinic input] +math.gcd + + x as a: object + y as b: object + / + +greatest common divisor of x and y +[clinic start generated code]*/ + static PyObject * -math_gcd(PyObject *self, PyObject *args) +math_gcd_impl(PyModuleDef *module, PyObject *a, PyObject *b) +/*[clinic end generated code: output=90fbefbfd5ce5536 input=c2691e57fb2a98fa]*/ { - PyObject *a, *b, *g; - - if (!PyArg_ParseTuple(args, "OO:gcd", &a, &b)) - return NULL; + PyObject *g; a = PyNumber_Index(a); if (a == NULL) @@ -707,10 +723,6 @@ return g; } -PyDoc_STRVAR(math_gcd_doc, -"gcd(x, y) -> int\n\ -greatest common divisor of x and y"); - /* Call is_error when errno != 0, and where x is the result libm * returned. is_error will usually set up an exception and return @@ -754,7 +766,7 @@ /* 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 @@ -927,22 +939,43 @@ PyDoc_STRVAR(math_##funcname##_doc, docstring); FUNC1(acos, acos, 0, - "acos(x)\n\nReturn the arc cosine (measured in radians) of x.") + "acos($module, x, /)\n--\n\n" + "Return the arc cosine (measured in radians) of x.") FUNC1(acosh, m_acosh, 0, - "acosh(x)\n\nReturn the inverse hyperbolic cosine of x.") + "acosh($module, x, /)\n--\n\n" + "Return the inverse hyperbolic cosine of x.") FUNC1(asin, asin, 0, - "asin(x)\n\nReturn the arc sine (measured in radians) of x.") + "asin($module, x, /)\n--\n\n" + "Return the arc sine (measured in radians) of x.") FUNC1(asinh, m_asinh, 0, - "asinh(x)\n\nReturn the inverse hyperbolic sine of x.") + "asinh($module, x, /)\n--\n\n" + "Return the inverse hyperbolic sine of x.") FUNC1(atan, atan, 0, - "atan(x)\n\nReturn the arc tangent (measured in radians) of x.") + "atan($module, x, /)\n--\n\n" + "Return the arc tangent (measured in radians) of x.") FUNC2(atan2, m_atan2, - "atan2(y, x)\n\nReturn the arc tangent (measured in radians) of y/x.\n" + "atan2($module, y, x, /)\n--\n\n" + "Return the arc tangent (measured in radians) of y/x.\n\n" "Unlike atan(y/x), the signs of both x and y are considered.") FUNC1(atanh, m_atanh, 0, - "atanh(x)\n\nReturn the inverse hyperbolic tangent of x.") + "atanh($module, x, /)\n--\n\n" + "Return the inverse hyperbolic tangent of x.") -static PyObject * math_ceil(PyObject *self, PyObject *number) { +/*[clinic input] +math.ceil + + x as number: object + / + +Return the ceiling of x as an int. + +This is the smallest integral value >= x. +[clinic start generated code]*/ + +static PyObject * +math_ceil(PyModuleDef *module, PyObject *number) +/*[clinic end generated code: output=f416ab67fe1622b4 input=2563726da385b11b]*/ +{ _Py_IDENTIFIER(__ceil__); PyObject *method, *result; @@ -957,32 +990,50 @@ return result; } -PyDoc_STRVAR(math_ceil_doc, - "ceil(x)\n\nReturn the ceiling of x as an int.\n" - "This is the smallest integral value >= x."); - FUNC2(copysign, copysign, - "copysign(x, y)\n\nReturn a float with the magnitude (absolute value) " - "of x but the sign \nof y. On platforms that support signed zeros, " - "copysign(1.0, -0.0) \nreturns -1.0.\n") + "copysign($module, x, y, /)\n--\n\n" + "Return a float with the magnitude (absolute value) of x but the sign of y.\n\n" + "On platforms that support signed zeros, copysign(1.0, -0.0)\n" + "returns -1.0.\n") FUNC1(cos, cos, 0, - "cos(x)\n\nReturn the cosine of x (measured in radians).") + "cos($module, x, /)\n--\n\n" + "Return the cosine of x (measured in radians).") FUNC1(cosh, cosh, 1, - "cosh(x)\n\nReturn the hyperbolic cosine of x.") + "cosh($module, x, /)\n--\n\n" + "Return the hyperbolic cosine of x.") FUNC1A(erf, m_erf, - "erf(x)\n\nError function at x.") + "erf($module, x, /)\n--\n\n" + "Error function at x.") FUNC1A(erfc, m_erfc, - "erfc(x)\n\nComplementary error function at x.") + "erfc($module, x, /)\n--\n\n" + "Complementary error function at x.") FUNC1(exp, exp, 1, - "exp(x)\n\nReturn e raised to the power of x.") + "exp($module, x, /)\n--\n\n" + "Return e raised to the power of x.") FUNC1(expm1, m_expm1, 1, - "expm1(x)\n\nReturn exp(x)-1.\n" + "expm1($module, x, /)\n--\n\n" + "Return exp(x)-1.\n\n" "This function avoids the loss of precision involved in the direct " "evaluation of exp(x)-1 for small x.") FUNC1(fabs, fabs, 0, - "fabs(x)\n\nReturn the absolute value of the float x.") + "fabs($module, x, /)\n--\n\n" + "Return the absolute value of the float x.") -static PyObject * math_floor(PyObject *self, PyObject *number) { +/*[clinic input] +math.floor + + x as number: object + / + +Return the floor of x as an int. + +This is the largest integral value <= x. +[clinic start generated code]*/ + +static PyObject * +math_floor(PyModuleDef *module, PyObject *number) +/*[clinic end generated code: output=8e3fcd6489ea9389 input=84bac07843042d6d]*/ +{ _Py_IDENTIFIER(__floor__); PyObject *method, *result; @@ -997,27 +1048,31 @@ return result; } -PyDoc_STRVAR(math_floor_doc, - "floor(x)\n\nReturn the floor of x as an int.\n" - "This is the largest integral value <= x."); - FUNC1A(gamma, m_tgamma, - "gamma(x)\n\nGamma function at x.") + "gamma($module, x, /)\n--\n\n" + "Gamma function at x.") FUNC1A(lgamma, m_lgamma, - "lgamma(x)\n\nNatural logarithm of absolute value of Gamma function at x.") + "lgamma($module, x, /)\n--\n\n" + "Natural logarithm of absolute value of Gamma function at x.") FUNC1(log1p, m_log1p, 0, - "log1p(x)\n\nReturn the natural logarithm of 1+x (base e).\n" + "log1p($module, x, /)\n--\n\n" + "Return the natural logarithm of 1+x (base e).\n\n" "The result is computed in a way which is accurate for x near zero.") FUNC1(sin, sin, 0, - "sin(x)\n\nReturn the sine of x (measured in radians).") + "sin($module, x, /)\n--\n\n" + "Return the sine of x (measured in radians).") FUNC1(sinh, sinh, 1, - "sinh(x)\n\nReturn the hyperbolic sine of x.") + "sinh($module, x, /)\n--\n\n" + "Return the hyperbolic sine of x.") FUNC1(sqrt, sqrt, 0, - "sqrt(x)\n\nReturn the square root of x.") + "sqrt($module, x, /)\n--\n\n" + "Return the square root of x.") FUNC1(tan, tan, 0, - "tan(x)\n\nReturn the tangent of x (measured in radians).") + "tan($module, x, /)\n--\n\n" + "Return the tangent of x (measured in radians).") FUNC1(tanh, tanh, 0, - "tanh(x)\n\nReturn the hyperbolic tangent of x.") + "tanh($module, x, /)\n--\n\n" + "Return the hyperbolic tangent of x.") /* Precision summation function as msum() by Raymond Hettinger in , @@ -1115,8 +1170,20 @@ Depends on IEEE 754 arithmetic guarantees and half-even rounding. */ -static PyObject* -math_fsum(PyObject *self, PyObject *seq) +/*[clinic input] +math.fsum + + seq: object + / + +Return an accurate floating point sum of values in the iterable seq. + +Assumes IEEE-754 floating point arithmetic. +[clinic start generated code]*/ + +static PyObject * +math_fsum(PyModuleDef *module, PyObject *seq) +/*[clinic end generated code: output=e17944a3cb32f4ce input=c51b7d8caf6f6e82]*/ { PyObject *item, *iter, *sum = NULL; Py_ssize_t i, j, n = 0, m = NUM_PARTIALS; @@ -1235,10 +1302,6 @@ #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 - @@ -1448,6 +1511,7 @@ return NULL; } + /* Lookup table for small factorial values */ static const unsigned long SmallFactorials[] = { @@ -1460,8 +1524,20 @@ #endif }; +/*[clinic input] +math.factorial + + x as arg: object + / + +Find x!. + +Raise a ValueError if x is negative or non-integral. +[clinic start generated code]*/ + static PyObject * -math_factorial(PyObject *self, PyObject *arg) +math_factorial(PyModuleDef *module, PyObject *arg) +/*[clinic end generated code: output=48d71574c6baca98 input=6d1c8105c0d91fb4]*/ { long x; int overflow; @@ -1519,28 +1595,36 @@ return result; } -PyDoc_STRVAR(math_factorial_doc, -"factorial(x) -> Integral\n" -"\n" -"Find x!. Raise a ValueError if x is negative or non-integral."); + +/*[clinic input] +math.trunc + + x: object + / + +Truncates the Real x to the nearest Integral toward 0. + +Uses the __trunc__ magic method. +[clinic start generated code]*/ static PyObject * -math_trunc(PyObject *self, PyObject *number) +math_trunc(PyModuleDef *module, PyObject *x) +/*[clinic end generated code: output=ca158c7ef25bea49 input=2168b34e0a09134d]*/ { _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); @@ -1548,18 +1632,24 @@ return result; } -PyDoc_STRVAR(math_trunc_doc, -"trunc(x:Real) -> Integral\n" -"\n" -"Truncates x to the nearest Integral toward 0. Uses the __trunc__ magic method."); + +/*[clinic input] +math.frexp + + x: double + / + +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]*/ static PyObject * -math_frexp(PyObject *self, PyObject *arg) +math_frexp_impl(PyModuleDef *module, double x) +/*[clinic end generated code: output=28f2b1dc479f8b48 input=96251c9e208bc6e9]*/ { 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) { @@ -1573,27 +1663,31 @@ return Py_BuildValue("(di)", x, i); } -PyDoc_STRVAR(math_frexp_doc, -"frexp(x)\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."); + +/*[clinic input] +math.ldexp + + x: double + i: object + / + +Return x * (2**i). + +This is essentially the inverse of frexp(). +[clinic start generated code]*/ static PyObject * -math_ldexp(PyObject *self, PyObject *args) +math_ldexp_impl(PyModuleDef *module, double x, PyObject *i) +/*[clinic end generated code: output=56e7549192c54a89 input=17d5970c1a40a8c1]*/ { - double x, r; - PyObject *oexp; + 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) @@ -1631,16 +1725,23 @@ return PyFloat_FromDouble(r); } -PyDoc_STRVAR(math_ldexp_doc, -"ldexp(x, i)\n\n\ -Return x * (2**i)."); + +/*[clinic input] +math.modf + + x: double + / + +Return the fractional and integer parts of x. + +Both results carry the sign of x and are floats. +[clinic start generated code]*/ static PyObject * -math_modf(PyObject *self, PyObject *arg) +math_modf_impl(PyModuleDef *module, double x) +/*[clinic end generated code: output=04e5baf6208ea16d input=b4cfb6786afd9035]*/ { - double y, x = PyFloat_AsDouble(arg); - if (x == -1.0 && PyErr_Occurred()) - return NULL; + 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)) { @@ -1657,11 +1758,6 @@ 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 @@ -1710,18 +1806,30 @@ return math_1(arg, func, 0); } + +/*[clinic input] +math.log + + x: object + [ + base: object(c_default="NULL") = math.e + ] + / + +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]*/ + static PyObject * -math_log(PyObject *self, PyObject *args) +math_log_impl(PyModuleDef *module, PyObject *x, int group_right_1, + PyObject *base) +/*[clinic end generated code: output=919e7ccd28f2a7a6 input=0f62d5726cbfebbd]*/ { - PyObject *arg; - PyObject *base = NULL; 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; @@ -1737,40 +1845,58 @@ 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: object + / + +Return the base 2 logarithm of x. +[clinic start generated code]*/ static PyObject * -math_log2(PyObject *self, PyObject *arg) +math_log2(PyModuleDef *module, PyObject *x) +/*[clinic end generated code: output=3c8869827b926642 input=08321262bae4f39b]*/ { - 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: object + / + +Return the base 10 logarithm of x. +[clinic start generated code]*/ static PyObject * -math_log10(PyObject *self, PyObject *arg) +math_log10(PyModuleDef *module, PyObject *x) +/*[clinic end generated code: output=bd8e9987b399e3bd input=b2469d02c6469e53]*/ { - 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: double + y: double + / + +Return fmod(x, y), according to platform C. + +x % y may differ. +[clinic start generated code]*/ static PyObject * -math_fmod(PyObject *self, PyObject *args) +math_fmod_impl(PyModuleDef *module, double x, double y) +/*[clinic end generated code: output=fea2017ce409fc45 input=4f84caa8cfc26a03]*/ { - 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; + double r; /* fmod(x, +/-Inf) returns x for finite x. */ if (Py_IS_INFINITY(y) && Py_IS_FINITE(x)) return PyFloat_FromDouble(x); @@ -1790,21 +1916,22 @@ 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: double + y: double + / + +Return the Euclidean distance, sqrt(x*x + y*y). +[clinic start generated code]*/ static PyObject * -math_hypot(PyObject *self, PyObject *args) +math_hypot_impl(PyModuleDef *module, double x, double y) +/*[clinic end generated code: output=2752ef898787df89 input=7f8eea70406474aa]*/ { - 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; + double r; /* hypot(x, +/-Inf) returns Inf, even if x is a NaN. */ if (Py_IS_INFINITY(x)) return PyFloat_FromDouble(fabs(x)); @@ -1832,8 +1959,6 @@ 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 @@ -1841,20 +1966,23 @@ e.g. 0.**-5. (for which ValueError needs to be raised.) */ +/*[clinic input] +math.pow + + x: double + y: double + / + +Return x**y (x to the power of y). +[clinic start generated code]*/ + static PyObject * -math_pow(PyObject *self, PyObject *args) +math_pow_impl(PyModuleDef *module, double x, double y) +/*[clinic end generated code: output=32d9d29e82ee87a0 input=c26f1f6075088bfd]*/ { - PyObject *ox, *oy; - double r, x, y; + 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 */ @@ -1919,107 +2047,138 @@ 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: double + / + +Convert angle x from radians to degrees. +[clinic start generated code]*/ + static PyObject * -math_degrees(PyObject *self, PyObject *arg) +math_degrees_impl(PyModuleDef *module, double x) +/*[clinic end generated code: output=e727185b39d59897 input=81e016555d6e3660]*/ { - double x = PyFloat_AsDouble(arg); - if (x == -1.0 && PyErr_Occurred()) - return NULL; 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: double + / + +Convert angle x from degrees to radians. +[clinic start generated code]*/ static PyObject * -math_radians(PyObject *self, PyObject *arg) +math_radians_impl(PyModuleDef *module, double x) +/*[clinic end generated code: output=351c276465c6b9f1 input=91626fc489fe3d63]*/ { - double x = PyFloat_AsDouble(arg); - if (x == -1.0 && PyErr_Occurred()) - return NULL; 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: double + / + +Return True if x is neither an infinity nor a NaN, and False otherwise. +[clinic start generated code]*/ static PyObject * -math_isfinite(PyObject *self, PyObject *arg) +math_isfinite_impl(PyModuleDef *module, double x) +/*[clinic end generated code: output=3c45bd856add7e7e input=46967d254812e54a]*/ { - double x = PyFloat_AsDouble(arg); - if (x == -1.0 && PyErr_Occurred()) - return NULL; 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: double + / + +Return True if x is a NaN (not a number), and False otherwise. +[clinic start generated code]*/ static PyObject * -math_isnan(PyObject *self, PyObject *arg) +math_isnan_impl(PyModuleDef *module, double x) +/*[clinic end generated code: output=d5ec770e66c2735b input=935891e66083f46a]*/ { - double x = PyFloat_AsDouble(arg); - if (x == -1.0 && PyErr_Occurred()) - return NULL; 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: double + / + +Return True if x is a positive or negative infinity, and False otherwise. +[clinic start generated code]*/ static PyObject * -math_isinf(PyObject *self, PyObject *arg) +math_isinf_impl(PyModuleDef *module, double x) +/*[clinic end generated code: output=5e127f74b7c09bb7 input=32630e4212cf961f]*/ { - double x = PyFloat_AsDouble(arg); - if (x == -1.0 && PyErr_Occurred()) - return NULL; 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 PyObject * -math_isclose(PyObject *self, PyObject *args, PyObject *kwargs) +/*[clinic input] +math.isclose -> bool + + a: double + b: double + * + rel_tol: double = 1e-09 + maximum difference for being considered "close", relative to the + magnitude of the input values + abs_tol: double = 0.0 + maximum difference for being considered "close", regardless of the + magnitude of the input values + +Determine whether two floating point numbers are close in value. + +Return True if a is close in value to b, and False otherwise. + +For the values to be considered close, the difference between them must be +smaller than at least one of the tolerances. + +-inf, inf and NaN behave similarly to the IEEE 754 Standard. That is, NaN is +not close to anything, even itself. inf and -inf are only close to themselves. +[clinic start generated code]*/ + +static int +math_isclose_impl(PyModuleDef *module, double a, double b, double rel_tol, + double abs_tol) +/*[clinic end generated code: output=2673fe6a3ea3f095 input=63cb8c0446a220fb]*/ { - double a, b; - double rel_tol = 1e-9; - double abs_tol = 0.0; double diff = 0.0; - long result = 0; - - static char *keywords[] = {"a", "b", "rel_tol", "abs_tol", NULL}; - - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "dd|$dd:isclose", - keywords, - &a, &b, &rel_tol, &abs_tol - )) - return NULL; /* sanity check on the inputs */ if (rel_tol < 0.0 || abs_tol < 0.0 ) { PyErr_SetString(PyExc_ValueError, "tolerances must be non-negative"); - return NULL; + return -1; } if ( a == b ) { /* short circuit exact equality -- needed to catch two infinities of the same sign. And perhaps speeds things up a bit sometimes. */ - Py_RETURN_TRUE; + return 1; } /* This catches the case of two infinities of opposite sign, or @@ -2030,7 +2189,7 @@ */ if (Py_IS_INFINITY(a) || Py_IS_INFINITY(b)) { - Py_RETURN_FALSE; + return 0; } /* now do the regular computation @@ -2039,33 +2198,11 @@ diff = fabs(b - a); - result = (((diff <= fabs(rel_tol * b)) || - (diff <= fabs(rel_tol * a))) || - (diff <= abs_tol)); - - return PyBool_FromLong(result); + return (((diff <= fabs(rel_tol * b)) || + (diff <= fabs(rel_tol * a))) || + (diff <= abs_tol)); } -PyDoc_STRVAR(math_isclose_doc, -"is_close(a, b, *, rel_tol=1e-09, abs_tol=0.0) -> bool\n" -"\n" -"Determine whether two floating point numbers are close in value.\n" -"\n" -" rel_tol\n" -" maximum difference for being considered \"close\", relative to the\n" -" magnitude of the input values\n" -" abs_tol\n" -" maximum difference for being considered \"close\", regardless of the\n" -" magnitude of the input values\n" -"\n" -"Return True if a is close in value to b, and False otherwise.\n" -"\n" -"For the values to be considered close, the difference between them\n" -"must be smaller than at least one of the tolerances.\n" -"\n" -"-inf, inf and NaN behave similarly to the IEEE 754 Standard. That\n" -"is, NaN is not close to anything, even itself. inf and -inf are\n" -"only close to themselves."); static PyMethodDef math_methods[] = { {"acos", math_acos, METH_O, math_acos_doc}, @@ -2075,44 +2212,43 @@ {"atan", math_atan, METH_O, math_atan_doc}, {"atan2", math_atan2, METH_VARARGS, math_atan2_doc}, {"atanh", math_atanh, METH_O, math_atanh_doc}, - {"ceil", math_ceil, METH_O, math_ceil_doc}, + MATH_CEIL_METHODDEF {"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}, - {"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_FACTORIAL_METHODDEF + MATH_FLOOR_METHODDEF + MATH_FMOD_METHODDEF + MATH_FREXP_METHODDEF + MATH_FSUM_METHODDEF {"gamma", math_gamma, METH_O, math_gamma_doc}, - {"gcd", math_gcd, METH_VARARGS, math_gcd_doc}, - {"hypot", math_hypot, METH_VARARGS, math_hypot_doc}, - {"isclose", (PyCFunction) math_isclose, METH_VARARGS | METH_KEYWORDS, - math_isclose_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_GCD_METHODDEF + MATH_HYPOT_METHODDEF + MATH_ISCLOSE_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 */ };