mirror of
https://github.com/python/cpython.git
synced 2025-12-31 04:23:37 +00:00
gh-73468: Add math.fma() function (#116667)
Added new math.fma() function, wrapping C99's ``fma()`` operation: fused multiply-add function. Co-authored-by: Mark Dickinson <mdickinson@enthought.com>
This commit is contained in:
parent
b8d808ddd7
commit
8e3c953b3a
6 changed files with 371 additions and 1 deletions
63
Modules/clinic/mathmodule.c.h
generated
63
Modules/clinic/mathmodule.c.h
generated
|
|
@ -204,6 +204,67 @@ PyDoc_STRVAR(math_log10__doc__,
|
|||
#define MATH_LOG10_METHODDEF \
|
||||
{"log10", (PyCFunction)math_log10, METH_O, math_log10__doc__},
|
||||
|
||||
PyDoc_STRVAR(math_fma__doc__,
|
||||
"fma($module, x, y, z, /)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Fused multiply-add operation.\n"
|
||||
"\n"
|
||||
"Compute (x * y) + z with a single round.");
|
||||
|
||||
#define MATH_FMA_METHODDEF \
|
||||
{"fma", _PyCFunction_CAST(math_fma), METH_FASTCALL, math_fma__doc__},
|
||||
|
||||
static PyObject *
|
||||
math_fma_impl(PyObject *module, double x, double y, double z);
|
||||
|
||||
static PyObject *
|
||||
math_fma(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
|
||||
if (!_PyArg_CheckPositional("fma", nargs, 3, 3)) {
|
||||
goto exit;
|
||||
}
|
||||
if (PyFloat_CheckExact(args[0])) {
|
||||
x = PyFloat_AS_DOUBLE(args[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = PyFloat_AsDouble(args[0]);
|
||||
if (x == -1.0 && PyErr_Occurred()) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
if (PyFloat_CheckExact(args[1])) {
|
||||
y = PyFloat_AS_DOUBLE(args[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
y = PyFloat_AsDouble(args[1]);
|
||||
if (y == -1.0 && PyErr_Occurred()) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
if (PyFloat_CheckExact(args[2])) {
|
||||
z = PyFloat_AS_DOUBLE(args[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
z = PyFloat_AsDouble(args[2]);
|
||||
if (z == -1.0 && PyErr_Occurred()) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
return_value = math_fma_impl(module, x, y, z);
|
||||
|
||||
exit:
|
||||
return return_value;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(math_fmod__doc__,
|
||||
"fmod($module, x, y, /)\n"
|
||||
"--\n"
|
||||
|
|
@ -950,4 +1011,4 @@ math_ulp(PyObject *module, PyObject *arg)
|
|||
exit:
|
||||
return return_value;
|
||||
}
|
||||
/*[clinic end generated code: output=6b2eeaed8d8a76d5 input=a9049054013a1b77]*/
|
||||
/*[clinic end generated code: output=9fe3f007f474e015 input=a9049054013a1b77]*/
|
||||
|
|
|
|||
|
|
@ -2321,6 +2321,48 @@ math_log10(PyObject *module, PyObject *x)
|
|||
}
|
||||
|
||||
|
||||
/*[clinic input]
|
||||
math.fma
|
||||
|
||||
x: double
|
||||
y: double
|
||||
z: double
|
||||
/
|
||||
|
||||
Fused multiply-add operation.
|
||||
|
||||
Compute (x * y) + z with a single round.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
math_fma_impl(PyObject *module, double x, double y, double z)
|
||||
/*[clinic end generated code: output=4fc8626dbc278d17 input=e3ad1f4a4c89626e]*/
|
||||
{
|
||||
double r = fma(x, y, z);
|
||||
|
||||
/* Fast path: if we got a finite result, we're done. */
|
||||
if (Py_IS_FINITE(r)) {
|
||||
return PyFloat_FromDouble(r);
|
||||
}
|
||||
|
||||
/* Non-finite result. Raise an exception if appropriate, else return r. */
|
||||
if (Py_IS_NAN(r)) {
|
||||
if (!Py_IS_NAN(x) && !Py_IS_NAN(y) && !Py_IS_NAN(z)) {
|
||||
/* NaN result from non-NaN inputs. */
|
||||
PyErr_SetString(PyExc_ValueError, "invalid operation in fma");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (Py_IS_FINITE(x) && Py_IS_FINITE(y) && Py_IS_FINITE(z)) {
|
||||
/* Infinite result from finite inputs. */
|
||||
PyErr_SetString(PyExc_OverflowError, "overflow in fma");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return PyFloat_FromDouble(r);
|
||||
}
|
||||
|
||||
|
||||
/*[clinic input]
|
||||
math.fmod
|
||||
|
||||
|
|
@ -4094,6 +4136,7 @@ static PyMethodDef math_methods[] = {
|
|||
{"fabs", math_fabs, METH_O, math_fabs_doc},
|
||||
MATH_FACTORIAL_METHODDEF
|
||||
MATH_FLOOR_METHODDEF
|
||||
MATH_FMA_METHODDEF
|
||||
MATH_FMOD_METHODDEF
|
||||
MATH_FREXP_METHODDEF
|
||||
MATH_FSUM_METHODDEF
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue