bpo-39648: Expand math.gcd() and math.lcm() to handle multiple arguments. (GH-18604)
* bpo-39648: Expand math.gcd() and math.lcm() to handle multiple arguments. * Simplify fast path. * Difine lcm() without arguments returning 1. * Apply suggestions from code review Co-Authored-By: Mark Dickinson <dickinsm@gmail.com> Co-authored-by: Mark Dickinson <dickinsm@gmail.com>
This commit is contained in:
parent
fbe2e0bb8a
commit
559e7f165a
|
@ -126,23 +126,19 @@ Number-theoretic and representation functions
|
||||||
<https://code.activestate.com/recipes/393090/>`_\.
|
<https://code.activestate.com/recipes/393090/>`_\.
|
||||||
|
|
||||||
|
|
||||||
.. function:: gcd(a, b)
|
.. function:: gcd(*integers)
|
||||||
|
|
||||||
Return the greatest common divisor of the integers *a* and *b*. If either
|
Return the greatest common divisor of the specified integer arguments.
|
||||||
*a* or *b* is nonzero, then the value of ``gcd(a, b)`` is the largest
|
If any of the arguments is nonzero, then the returned value is the largest
|
||||||
positive integer that divides both *a* and *b*. ``gcd(0, 0)`` returns
|
positive integer that is a divisor af all arguments. If all arguments
|
||||||
``0``.
|
are zero, then the returned value is ``0``. ``gcd()`` without arguments
|
||||||
|
returns ``0``.
|
||||||
|
|
||||||
.. versionadded:: 3.5
|
.. versionadded:: 3.5
|
||||||
|
|
||||||
|
.. versionchanged:: 3.9
|
||||||
.. function:: lcm(a, b)
|
Added support for an arbitrary number of arguments. Formerly, only two
|
||||||
|
arguments were supported.
|
||||||
Return the least common multiple of integers *a* and *b*. The value of
|
|
||||||
``lcm(a, b)`` is the smallest nonnegative integer that is a multiple of
|
|
||||||
both *a* and *b*. If either *a* or *b* is zero then ``lcm(a, b)`` is zero.
|
|
||||||
|
|
||||||
.. versionadded:: 3.9
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: isclose(a, b, *, rel_tol=1e-09, abs_tol=0.0)
|
.. function:: isclose(a, b, *, rel_tol=1e-09, abs_tol=0.0)
|
||||||
|
@ -210,6 +206,17 @@ Number-theoretic and representation functions
|
||||||
.. versionadded:: 3.8
|
.. versionadded:: 3.8
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: lcm(*integers)
|
||||||
|
|
||||||
|
Return the least common multiple of the specified integer arguments.
|
||||||
|
If all arguments are nonzero, then the returned value is the smallest
|
||||||
|
positive integer that is a multiple of all arguments. If any of the arguments
|
||||||
|
is zero, then the returned value is ``0``. ``lcm()`` without arguments
|
||||||
|
returns ``1``.
|
||||||
|
|
||||||
|
.. versionadded:: 3.9
|
||||||
|
|
||||||
|
|
||||||
.. function:: ldexp(x, i)
|
.. function:: ldexp(x, i)
|
||||||
|
|
||||||
Return ``x * (2**i)``. This is essentially the inverse of function
|
Return ``x * (2**i)``. This is essentially the inverse of function
|
||||||
|
|
|
@ -216,8 +216,13 @@ import attempts.
|
||||||
math
|
math
|
||||||
----
|
----
|
||||||
|
|
||||||
Add :func:`math.lcm`: return the least common multiple of *a* and *b*.
|
Expanded the :func:`math.gcd` function to handle multiple arguments.
|
||||||
(Contributed by Ananthakrishnan in :issue:`39479`.)
|
Formerly, it only supported two arguments.
|
||||||
|
(Contributed by Serhiy Storchaka in :issue:`39648`.)
|
||||||
|
|
||||||
|
Add :func:`math.lcm`: return the least common multiple of specified arguments.
|
||||||
|
(Contributed by Mark Dickinson, Ananthakrishnan and Serhiy Storchaka in
|
||||||
|
:issue:`39479` and :issue:`39648`.)
|
||||||
|
|
||||||
Add :func:`math.nextafter`: return the next floating-point value after *x*
|
Add :func:`math.nextafter`: return the next floating-point value after *x*
|
||||||
towards *y*.
|
towards *y*.
|
||||||
|
|
|
@ -705,20 +705,11 @@ class MathTests(unittest.TestCase):
|
||||||
self.assertEqual(gcd(84, -120), 12)
|
self.assertEqual(gcd(84, -120), 12)
|
||||||
self.assertEqual(gcd(1216342683557601535506311712,
|
self.assertEqual(gcd(1216342683557601535506311712,
|
||||||
436522681849110124616458784), 32)
|
436522681849110124616458784), 32)
|
||||||
c = 652560
|
|
||||||
x = 434610456570399902378880679233098819019853229470286994367836600566
|
x = 434610456570399902378880679233098819019853229470286994367836600566
|
||||||
y = 1064502245825115327754847244914921553977
|
y = 1064502245825115327754847244914921553977
|
||||||
a = x * c
|
for c in (652560,
|
||||||
b = y * c
|
576559230871654959816130551884856912003141446781646602790216406874):
|
||||||
self.assertEqual(gcd(a, b), c)
|
|
||||||
self.assertEqual(gcd(b, a), c)
|
|
||||||
self.assertEqual(gcd(-a, b), c)
|
|
||||||
self.assertEqual(gcd(b, -a), c)
|
|
||||||
self.assertEqual(gcd(a, -b), c)
|
|
||||||
self.assertEqual(gcd(-b, a), c)
|
|
||||||
self.assertEqual(gcd(-a, -b), c)
|
|
||||||
self.assertEqual(gcd(-b, -a), c)
|
|
||||||
c = 576559230871654959816130551884856912003141446781646602790216406874
|
|
||||||
a = x * c
|
a = x * c
|
||||||
b = y * c
|
b = y * c
|
||||||
self.assertEqual(gcd(a, b), c)
|
self.assertEqual(gcd(a, b), c)
|
||||||
|
@ -730,8 +721,16 @@ class MathTests(unittest.TestCase):
|
||||||
self.assertEqual(gcd(-a, -b), c)
|
self.assertEqual(gcd(-a, -b), c)
|
||||||
self.assertEqual(gcd(-b, -a), c)
|
self.assertEqual(gcd(-b, -a), c)
|
||||||
|
|
||||||
|
self.assertEqual(gcd(), 0)
|
||||||
|
self.assertEqual(gcd(120), 120)
|
||||||
|
self.assertEqual(gcd(-120), 120)
|
||||||
|
self.assertEqual(gcd(120, 84, 102), 6)
|
||||||
|
self.assertEqual(gcd(120, 1, 84), 1)
|
||||||
|
|
||||||
|
self.assertRaises(TypeError, gcd, 120.0)
|
||||||
self.assertRaises(TypeError, gcd, 120.0, 84)
|
self.assertRaises(TypeError, gcd, 120.0, 84)
|
||||||
self.assertRaises(TypeError, gcd, 120, 84.0)
|
self.assertRaises(TypeError, gcd, 120, 84.0)
|
||||||
|
self.assertRaises(TypeError, gcd, 120, 1, 84.0)
|
||||||
self.assertEqual(gcd(MyIndexable(120), MyIndexable(84)), 12)
|
self.assertEqual(gcd(MyIndexable(120), MyIndexable(84)), 12)
|
||||||
|
|
||||||
def testHypot(self):
|
def testHypot(self):
|
||||||
|
@ -989,9 +988,9 @@ class MathTests(unittest.TestCase):
|
||||||
self.assertEqual(lcm(1216342683557601535506311712,
|
self.assertEqual(lcm(1216342683557601535506311712,
|
||||||
436522681849110124616458784),
|
436522681849110124616458784),
|
||||||
16592536571065866494401400422922201534178938447014944)
|
16592536571065866494401400422922201534178938447014944)
|
||||||
|
|
||||||
x = 43461045657039990237
|
x = 43461045657039990237
|
||||||
y = 10645022458251153277
|
y = 10645022458251153277
|
||||||
|
|
||||||
for c in (652560,
|
for c in (652560,
|
||||||
57655923087165495981):
|
57655923087165495981):
|
||||||
a = x * c
|
a = x * c
|
||||||
|
@ -1005,9 +1004,18 @@ class MathTests(unittest.TestCase):
|
||||||
self.assertEqual(lcm(-b, a), d)
|
self.assertEqual(lcm(-b, a), d)
|
||||||
self.assertEqual(lcm(-a, -b), d)
|
self.assertEqual(lcm(-a, -b), d)
|
||||||
self.assertEqual(lcm(-b, -a), d)
|
self.assertEqual(lcm(-b, -a), d)
|
||||||
self.assertEqual(lcm(MyIndexable(120), MyIndexable(84)), 840)
|
|
||||||
|
self.assertEqual(lcm(), 1)
|
||||||
|
self.assertEqual(lcm(120), 120)
|
||||||
|
self.assertEqual(lcm(-120), 120)
|
||||||
|
self.assertEqual(lcm(120, 84, 102), 14280)
|
||||||
|
self.assertEqual(lcm(120, 0, 84), 0)
|
||||||
|
|
||||||
|
self.assertRaises(TypeError, lcm, 120.0)
|
||||||
self.assertRaises(TypeError, lcm, 120.0, 84)
|
self.assertRaises(TypeError, lcm, 120.0, 84)
|
||||||
self.assertRaises(TypeError, lcm, 120, 84.0)
|
self.assertRaises(TypeError, lcm, 120, 84.0)
|
||||||
|
self.assertRaises(TypeError, lcm, 120, 0, 84.0)
|
||||||
|
self.assertEqual(lcm(MyIndexable(120), MyIndexable(84)), 840)
|
||||||
|
|
||||||
def testLdexp(self):
|
def testLdexp(self):
|
||||||
self.assertRaises(TypeError, math.ldexp)
|
self.assertRaises(TypeError, math.ldexp)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Expanded :func:`math.gcd` and :func:`math.lcm` to handle multiple arguments.
|
|
@ -2,36 +2,6 @@
|
||||||
preserve
|
preserve
|
||||||
[clinic start generated code]*/
|
[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)(void(*)(void))math_gcd, METH_FASTCALL, math_gcd__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
math_gcd_impl(PyObject *module, PyObject *a, PyObject *b);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
math_gcd(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
|
||||||
{
|
|
||||||
PyObject *return_value = NULL;
|
|
||||||
PyObject *a;
|
|
||||||
PyObject *b;
|
|
||||||
|
|
||||||
if (!_PyArg_CheckPositional("gcd", nargs, 2, 2)) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
a = args[0];
|
|
||||||
b = args[1];
|
|
||||||
return_value = math_gcd_impl(module, a, b);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return return_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(math_ceil__doc__,
|
PyDoc_STRVAR(math_ceil__doc__,
|
||||||
"ceil($module, x, /)\n"
|
"ceil($module, x, /)\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
|
@ -85,36 +55,6 @@ PyDoc_STRVAR(math_factorial__doc__,
|
||||||
#define MATH_FACTORIAL_METHODDEF \
|
#define MATH_FACTORIAL_METHODDEF \
|
||||||
{"factorial", (PyCFunction)math_factorial, METH_O, math_factorial__doc__},
|
{"factorial", (PyCFunction)math_factorial, METH_O, math_factorial__doc__},
|
||||||
|
|
||||||
PyDoc_STRVAR(math_lcm__doc__,
|
|
||||||
"lcm($module, x, y, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"least common multiple of x and y");
|
|
||||||
|
|
||||||
#define MATH_LCM_METHODDEF \
|
|
||||||
{"lcm", (PyCFunction)(void(*)(void))math_lcm, METH_FASTCALL, math_lcm__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
math_lcm_impl(PyObject *module, PyObject *a, PyObject *b);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
math_lcm(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
|
||||||
{
|
|
||||||
PyObject *return_value = NULL;
|
|
||||||
PyObject *a;
|
|
||||||
PyObject *b;
|
|
||||||
|
|
||||||
if (!_PyArg_CheckPositional("lcm", nargs, 2, 2)) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
a = args[0];
|
|
||||||
b = args[1];
|
|
||||||
return_value = math_lcm_impl(module, a, b);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return return_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(math_trunc__doc__,
|
PyDoc_STRVAR(math_trunc__doc__,
|
||||||
"trunc($module, x, /)\n"
|
"trunc($module, x, /)\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
|
@ -925,4 +865,4 @@ math_ulp(PyObject *module, PyObject *arg)
|
||||||
exit:
|
exit:
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
/*[clinic end generated code: output=f8daa185c043a7b7 input=a9049054013a1b77]*/
|
/*[clinic end generated code: output=1eae2b3ef19568fa input=a9049054013a1b77]*/
|
||||||
|
|
|
@ -826,35 +826,123 @@ m_log10(double x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*[clinic input]
|
static PyObject *
|
||||||
math.gcd
|
math_gcd(PyObject *module, PyObject * const *args, Py_ssize_t nargs)
|
||||||
|
{
|
||||||
|
PyObject *res, *x;
|
||||||
|
Py_ssize_t i;
|
||||||
|
|
||||||
x as a: object
|
if (nargs == 0) {
|
||||||
y as b: object
|
return PyLong_FromLong(0);
|
||||||
/
|
}
|
||||||
|
res = PyNumber_Index(args[0]);
|
||||||
|
if (res == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (nargs == 1) {
|
||||||
|
Py_SETREF(res, PyNumber_Absolute(res));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
for (i = 1; i < nargs; i++) {
|
||||||
|
x = PyNumber_Index(args[i]);
|
||||||
|
if (x == NULL) {
|
||||||
|
Py_DECREF(res);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (res == _PyLong_One) {
|
||||||
|
/* Fast path: just check arguments.
|
||||||
|
It is okay to use identity comparison here. */
|
||||||
|
Py_DECREF(x);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Py_SETREF(res, _PyLong_GCD(res, x));
|
||||||
|
Py_DECREF(x);
|
||||||
|
if (res == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(math_gcd_doc,
|
||||||
|
"gcd($module, *integers)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"Greatest Common Divisor.");
|
||||||
|
|
||||||
greatest common divisor of x and y
|
|
||||||
[clinic start generated code]*/
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
math_gcd_impl(PyObject *module, PyObject *a, PyObject *b)
|
long_lcm(PyObject *a, PyObject *b)
|
||||||
/*[clinic end generated code: output=7b2e0c151bd7a5d8 input=c2691e57fb2a98fa]*/
|
|
||||||
{
|
{
|
||||||
PyObject *g;
|
PyObject *g, *m, *f, *ab;
|
||||||
|
|
||||||
a = PyNumber_Index(a);
|
if (Py_SIZE(a) == 0 || Py_SIZE(b) == 0) {
|
||||||
if (a == NULL)
|
return PyLong_FromLong(0);
|
||||||
return NULL;
|
|
||||||
b = PyNumber_Index(b);
|
|
||||||
if (b == NULL) {
|
|
||||||
Py_DECREF(a);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
g = _PyLong_GCD(a, b);
|
g = _PyLong_GCD(a, b);
|
||||||
Py_DECREF(a);
|
if (g == NULL) {
|
||||||
Py_DECREF(b);
|
return NULL;
|
||||||
return g;
|
|
||||||
}
|
}
|
||||||
|
f = PyNumber_FloorDivide(a, g);
|
||||||
|
Py_DECREF(g);
|
||||||
|
if (f == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
m = PyNumber_Multiply(f, b);
|
||||||
|
Py_DECREF(f);
|
||||||
|
if (m == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ab = PyNumber_Absolute(m);
|
||||||
|
Py_DECREF(m);
|
||||||
|
return ab;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
math_lcm(PyObject *module, PyObject * const *args, Py_ssize_t nargs)
|
||||||
|
{
|
||||||
|
PyObject *res, *x;
|
||||||
|
Py_ssize_t i;
|
||||||
|
|
||||||
|
if (nargs == 0) {
|
||||||
|
return PyLong_FromLong(1);
|
||||||
|
}
|
||||||
|
res = PyNumber_Index(args[0]);
|
||||||
|
if (res == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (nargs == 1) {
|
||||||
|
Py_SETREF(res, PyNumber_Absolute(res));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
for (i = 1; i < nargs; i++) {
|
||||||
|
x = PyNumber_Index(args[i]);
|
||||||
|
if (x == NULL) {
|
||||||
|
Py_DECREF(res);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (res == _PyLong_Zero) {
|
||||||
|
/* Fast path: just check arguments.
|
||||||
|
It is okay to use identity comparison here. */
|
||||||
|
Py_DECREF(x);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Py_SETREF(res, long_lcm(res, x));
|
||||||
|
Py_DECREF(x);
|
||||||
|
if (res == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PyDoc_STRVAR(math_lcm_doc,
|
||||||
|
"lcm($module, *integers)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"Least Common Multiple.");
|
||||||
|
|
||||||
|
|
||||||
/* Call is_error when errno != 0, and where x is the result libm
|
/* Call is_error when errno != 0, and where x is the result libm
|
||||||
|
@ -2017,59 +2105,6 @@ math_factorial(PyObject *module, PyObject *arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*[clinic input]
|
|
||||||
math.lcm
|
|
||||||
x as a: object
|
|
||||||
y as b: object
|
|
||||||
/
|
|
||||||
least common multiple of x and y
|
|
||||||
[clinic start generated code]*/
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
math_lcm_impl(PyObject *module, PyObject *a, PyObject *b)
|
|
||||||
/*[clinic end generated code: output=6f83fb6d671074ba input=efb3d7b7334b7118]*/
|
|
||||||
{
|
|
||||||
PyObject *g, *m, *f, *ab;
|
|
||||||
|
|
||||||
a = PyNumber_Index(a);
|
|
||||||
if (a == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
b = PyNumber_Index(b);
|
|
||||||
if (b == NULL) {
|
|
||||||
Py_DECREF(a);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (_PyLong_Sign(a) == 0 || _PyLong_Sign(b) == 0) {
|
|
||||||
Py_DECREF(a);
|
|
||||||
Py_DECREF(b);
|
|
||||||
return PyLong_FromLong(0);
|
|
||||||
}
|
|
||||||
g = _PyLong_GCD(a, b);
|
|
||||||
if (g == NULL) {
|
|
||||||
Py_DECREF(a);
|
|
||||||
Py_DECREF(b);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
f = PyNumber_FloorDivide(a, g);
|
|
||||||
Py_DECREF(g);
|
|
||||||
Py_DECREF(a);
|
|
||||||
if (f == NULL) {
|
|
||||||
Py_DECREF(b);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
m = PyNumber_Multiply(f, b);
|
|
||||||
Py_DECREF(f);
|
|
||||||
Py_DECREF(b);
|
|
||||||
if (m == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
ab = PyNumber_Absolute(m);
|
|
||||||
Py_DECREF(m);
|
|
||||||
return ab;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
math.trunc
|
math.trunc
|
||||||
|
|
||||||
|
@ -3408,14 +3443,14 @@ static PyMethodDef math_methods[] = {
|
||||||
MATH_FREXP_METHODDEF
|
MATH_FREXP_METHODDEF
|
||||||
MATH_FSUM_METHODDEF
|
MATH_FSUM_METHODDEF
|
||||||
{"gamma", math_gamma, METH_O, math_gamma_doc},
|
{"gamma", math_gamma, METH_O, math_gamma_doc},
|
||||||
MATH_GCD_METHODDEF
|
{"gcd", (PyCFunction)(void(*)(void))math_gcd, METH_FASTCALL, math_gcd_doc},
|
||||||
{"hypot", (PyCFunction)(void(*)(void))math_hypot, METH_FASTCALL, math_hypot_doc},
|
{"hypot", (PyCFunction)(void(*)(void))math_hypot, METH_FASTCALL, math_hypot_doc},
|
||||||
MATH_ISCLOSE_METHODDEF
|
MATH_ISCLOSE_METHODDEF
|
||||||
MATH_ISFINITE_METHODDEF
|
MATH_ISFINITE_METHODDEF
|
||||||
MATH_ISINF_METHODDEF
|
MATH_ISINF_METHODDEF
|
||||||
MATH_ISNAN_METHODDEF
|
MATH_ISNAN_METHODDEF
|
||||||
MATH_ISQRT_METHODDEF
|
MATH_ISQRT_METHODDEF
|
||||||
MATH_LCM_METHODDEF
|
{"lcm", (PyCFunction)(void(*)(void))math_lcm, METH_FASTCALL, math_lcm_doc},
|
||||||
MATH_LDEXP_METHODDEF
|
MATH_LDEXP_METHODDEF
|
||||||
{"lgamma", math_lgamma, METH_O, math_lgamma_doc},
|
{"lgamma", math_lgamma, METH_O, math_lgamma_doc},
|
||||||
MATH_LOG_METHODDEF
|
MATH_LOG_METHODDEF
|
||||||
|
|
Loading…
Reference in New Issue