diff options
author | Matthias Görgens <matthias.goergens@gmail.com> | 2023-05-19 20:03:49 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-19 20:03:49 (GMT) |
commit | 6e39fa19555043588910d10f1fe677cf6b04d77e (patch) | |
tree | 04f9df16fd8871323c195e79f2afc251c2882410 /Modules/clinic | |
parent | c3f43bfb4bec39ff8f2c36d861a3c3a243bcb3af (diff) | |
download | cpython-6e39fa19555043588910d10f1fe677cf6b04d77e.zip cpython-6e39fa19555043588910d10f1fe677cf6b04d77e.tar.gz cpython-6e39fa19555043588910d10f1fe677cf6b04d77e.tar.bz2 |
gh-94906: Support multiple steps in math.nextafter (#103881)
This PR updates `math.nextafter` to add a new `steps` argument. The behaviour is as though `math.nextafter` had been called `steps` times in succession.
---------
Co-authored-by: Mark Dickinson <mdickinson@enthought.com>
Diffstat (limited to 'Modules/clinic')
-rw-r--r-- | Modules/clinic/mathmodule.c.h | 55 |
1 files changed, 47 insertions, 8 deletions
diff --git a/Modules/clinic/mathmodule.c.h b/Modules/clinic/mathmodule.c.h index bc5bbce..c16c1b0 100644 --- a/Modules/clinic/mathmodule.c.h +++ b/Modules/clinic/mathmodule.c.h @@ -826,25 +826,59 @@ exit: } PyDoc_STRVAR(math_nextafter__doc__, -"nextafter($module, x, y, /)\n" +"nextafter($module, x, y, /, *, steps=None)\n" "--\n" "\n" -"Return the next floating-point value after x towards y."); +"Return the floating-point value the given number of steps after x towards y.\n" +"\n" +"If steps is not specified or is None, it defaults to 1.\n" +"\n" +"Raises a TypeError, if x or y is not a double, or if steps is not an integer.\n" +"Raises ValueError if steps is negative."); #define MATH_NEXTAFTER_METHODDEF \ - {"nextafter", _PyCFunction_CAST(math_nextafter), METH_FASTCALL, math_nextafter__doc__}, + {"nextafter", _PyCFunction_CAST(math_nextafter), METH_FASTCALL|METH_KEYWORDS, math_nextafter__doc__}, static PyObject * -math_nextafter_impl(PyObject *module, double x, double y); +math_nextafter_impl(PyObject *module, double x, double y, PyObject *steps); static PyObject * -math_nextafter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +math_nextafter(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(steps), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"", "", "steps", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "nextafter", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; double x; double y; + PyObject *steps = Py_None; - if (!_PyArg_CheckPositional("nextafter", nargs, 2, 2)) { + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { goto exit; } if (PyFloat_CheckExact(args[0])) { @@ -867,7 +901,12 @@ math_nextafter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } } - return_value = math_nextafter_impl(module, x, y); + if (!noptargs) { + goto skip_optional_kwonly; + } + steps = args[2]; +skip_optional_kwonly: + return_value = math_nextafter_impl(module, x, y, steps); exit: return return_value; @@ -911,4 +950,4 @@ math_ulp(PyObject *module, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=a6437a3ba18c486a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=91a0357265a2a553 input=a9049054013a1b77]*/ |