gh-116417: Avoid PyFloat_AS_DOUBLE() in AC limited C API (#116568)

Argument Clinic no longer calls PyFloat_AS_DOUBLE() when the usage of
the limited C API is requested.
This commit is contained in:
Victor Stinner 2024-03-10 20:42:40 +01:00 committed by GitHub
parent 5b2f21faf3
commit 729bfb3105
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 155 additions and 19 deletions

View File

@ -72,10 +72,46 @@ my_int_sum_impl(PyObject *module, int x, int y)
}
/*[clinic input]
my_float_sum -> float
x: float
y: float
/
[clinic start generated code]*/
static float
my_float_sum_impl(PyObject *module, float x, float y)
/*[clinic end generated code: output=634f59a5a419cad7 input=d4b5313bdf4dc377]*/
{
return x + y;
}
/*[clinic input]
my_double_sum -> double
x: double
y: double
/
[clinic start generated code]*/
static double
my_double_sum_impl(PyObject *module, double x, double y)
/*[clinic end generated code: output=a75576d9e4d8557f input=16b11c8aba172801]*/
{
return x + y;
}
static PyMethodDef tester_methods[] = {
TEST_EMPTY_FUNCTION_METHODDEF
MY_INT_FUNC_METHODDEF
MY_INT_SUM_METHODDEF
MY_FLOAT_SUM_METHODDEF
MY_DOUBLE_SUM_METHODDEF
{NULL, NULL}
};

View File

@ -91,4 +91,86 @@ my_int_sum(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
exit:
return return_value;
}
/*[clinic end generated code: output=5cf64baf978d2288 input=a9049054013a1b77]*/
PyDoc_STRVAR(my_float_sum__doc__,
"my_float_sum($module, x, y, /)\n"
"--\n"
"\n");
#define MY_FLOAT_SUM_METHODDEF \
{"my_float_sum", (PyCFunction)(void(*)(void))my_float_sum, METH_FASTCALL, my_float_sum__doc__},
static float
my_float_sum_impl(PyObject *module, float x, float y);
static PyObject *
my_float_sum(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
float x;
float y;
float _return_value;
if (nargs != 2) {
PyErr_Format(PyExc_TypeError, "my_float_sum expected 2 arguments, got %zd", nargs);
goto exit;
}
x = (float) PyFloat_AsDouble(args[0]);
if (x == -1.0 && PyErr_Occurred()) {
goto exit;
}
y = (float) PyFloat_AsDouble(args[1]);
if (y == -1.0 && PyErr_Occurred()) {
goto exit;
}
_return_value = my_float_sum_impl(module, x, y);
if ((_return_value == -1.0) && PyErr_Occurred()) {
goto exit;
}
return_value = PyFloat_FromDouble((double)_return_value);
exit:
return return_value;
}
PyDoc_STRVAR(my_double_sum__doc__,
"my_double_sum($module, x, y, /)\n"
"--\n"
"\n");
#define MY_DOUBLE_SUM_METHODDEF \
{"my_double_sum", (PyCFunction)(void(*)(void))my_double_sum, METH_FASTCALL, my_double_sum__doc__},
static double
my_double_sum_impl(PyObject *module, double x, double y);
static PyObject *
my_double_sum(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
double x;
double y;
double _return_value;
if (nargs != 2) {
PyErr_Format(PyExc_TypeError, "my_double_sum expected 2 arguments, got %zd", nargs);
goto exit;
}
x = PyFloat_AsDouble(args[0]);
if (x == -1.0 && PyErr_Occurred()) {
goto exit;
}
y = PyFloat_AsDouble(args[1]);
if (y == -1.0 && PyErr_Occurred()) {
goto exit;
}
_return_value = my_double_sum_impl(module, x, y);
if ((_return_value == -1.0) && PyErr_Occurred()) {
goto exit;
}
return_value = PyFloat_FromDouble(_return_value);
exit:
return return_value;
}
/*[clinic end generated code: output=bb9f6b8c5d9e6a79 input=a9049054013a1b77]*/

View File

@ -3867,19 +3867,28 @@ class float_converter(CConverter):
def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None:
if self.format_unit == 'f':
return self.format_code("""
if (PyFloat_CheckExact({argname})) {{{{
{paramname} = (float) (PyFloat_AS_DOUBLE({argname}));
}}}}
else
{{{{
if not limited_capi:
return self.format_code("""
if (PyFloat_CheckExact({argname})) {{{{
{paramname} = (float) (PyFloat_AS_DOUBLE({argname}));
}}}}
else
{{{{
{paramname} = (float) PyFloat_AsDouble({argname});
if ({paramname} == -1.0 && PyErr_Occurred()) {{{{
goto exit;
}}}}
}}}}
""",
argname=argname)
else:
return self.format_code("""
{paramname} = (float) PyFloat_AsDouble({argname});
if ({paramname} == -1.0 && PyErr_Occurred()) {{{{
goto exit;
}}}}
}}}}
""",
argname=argname)
""",
argname=argname)
return super().parse_arg(argname, displayname, limited_capi=limited_capi)
class double_converter(CConverter):
@ -3890,19 +3899,28 @@ class double_converter(CConverter):
def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None:
if self.format_unit == 'd':
return self.format_code("""
if (PyFloat_CheckExact({argname})) {{{{
{paramname} = PyFloat_AS_DOUBLE({argname});
}}}}
else
{{{{
if not limited_capi:
return self.format_code("""
if (PyFloat_CheckExact({argname})) {{{{
{paramname} = PyFloat_AS_DOUBLE({argname});
}}}}
else
{{{{
{paramname} = PyFloat_AsDouble({argname});
if ({paramname} == -1.0 && PyErr_Occurred()) {{{{
goto exit;
}}}}
}}}}
""",
argname=argname)
else:
return self.format_code("""
{paramname} = PyFloat_AsDouble({argname});
if ({paramname} == -1.0 && PyErr_Occurred()) {{{{
goto exit;
}}}}
}}}}
""",
argname=argname)
""",
argname=argname)
return super().parse_arg(argname, displayname, limited_capi=limited_capi)