mirror of
https://github.com/python/cpython
synced 2026-09-29 12:10:30 +03:00
Issue #11888: Add log2 function to math module. Patch written by Mark
Dickinson.
This commit is contained in:
parent
3de49192aa
commit
fa0e3d52d6
6 changed files with 234 additions and 16 deletions
|
|
@ -577,6 +577,55 @@ m_log(double x)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
log2: log to base 2.
|
||||
|
||||
Uses an algorithm that should:
|
||||
(a) produce exact results for powers of 2, and
|
||||
(b) be monotonic, assuming that the system log is monotonic.
|
||||
*/
|
||||
|
||||
static double
|
||||
m_log2(double x)
|
||||
{
|
||||
if (!Py_IS_FINITE(x)) {
|
||||
if (Py_IS_NAN(x))
|
||||
return x; /* log2(nan) = nan */
|
||||
else if (x > 0.0)
|
||||
return x; /* log2(+inf) = +inf */
|
||||
else {
|
||||
errno = EDOM;
|
||||
return Py_NAN; /* log2(-inf) = nan, invalid-operation */
|
||||
}
|
||||
}
|
||||
|
||||
if (x > 0.0) {
|
||||
double m;
|
||||
int e;
|
||||
m = frexp(x, &e);
|
||||
/* We want log2(m * 2**e) == log(m) / log(2) + e. Care is needed when
|
||||
* x is just greater than 1.0: in that case e is 1, log(m) is negative,
|
||||
* and we get significant cancellation error from the addition of
|
||||
* log(m) / log(2) to e. The slight rewrite of the expression below
|
||||
* avoids this problem.
|
||||
*/
|
||||
if (x >= 1.0) {
|
||||
return log(2.0 * m) / log(2.0) + (e - 1);
|
||||
}
|
||||
else {
|
||||
return log(m) / log(2.0) + e;
|
||||
}
|
||||
}
|
||||
else if (x == 0.0) {
|
||||
errno = EDOM;
|
||||
return -Py_HUGE_VAL; /* log2(0) = -inf, divide-by-zero */
|
||||
}
|
||||
else {
|
||||
errno = EDOM;
|
||||
return Py_NAN; /* log10(-inf) = nan, invalid-operation */
|
||||
}
|
||||
}
|
||||
|
||||
static double
|
||||
m_log10(double x)
|
||||
{
|
||||
|
|
@ -1622,6 +1671,15 @@ PyDoc_STRVAR(math_log_doc,
|
|||
Return the logarithm of x to the given base.\n\
|
||||
If the base not specified, returns the natural logarithm (base e) of x.");
|
||||
|
||||
static PyObject *
|
||||
math_log2(PyObject *self, PyObject *arg)
|
||||
{
|
||||
return loghelper(arg, m_log2, "log2");
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(math_log2_doc,
|
||||
"log2(x)\n\nReturn the base 2 logarithm of x.");
|
||||
|
||||
static PyObject *
|
||||
math_log10(PyObject *self, PyObject *arg)
|
||||
{
|
||||
|
|
@ -1894,6 +1952,7 @@ static PyMethodDef math_methods[] = {
|
|||
{"log", math_log, METH_VARARGS, math_log_doc},
|
||||
{"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},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue