[Python-checkins] CVS: python/dist/src/Modules mathmodule.c,2.61,2.62
Tim Peters
tim_one@users.sourceforge.net
Tue, 04 Sep 2001 17:53:47 -0700
Update of /cvsroot/python/python/dist/src/Modules
In directory usw-pr-cvs1:/tmp/cvs-serv17117/python/Modules
Modified Files:
mathmodule.c
Log Message:
Return reasonable results for math.log(long) and math.log10(long) (we were
getting Infs, NaNs, or nonsense in 2.1 and before; in yesterday's CVS we
were getting OverflowError; but these functions always make good sense
for positive arguments, no matter how large).
Index: mathmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/mathmodule.c,v
retrieving revision 2.61
retrieving revision 2.62
diff -C2 -d -r2.61 -r2.62
*** mathmodule.c 2001/09/04 23:17:42 2.61
--- mathmodule.c 2001/09/05 00:53:45 2.62
***************
*** 2,5 ****
--- 2,6 ----
#include "Python.h"
+ #include "longintrepr.h"
#ifndef _MSC_VER
***************
*** 137,144 ****
FUNC2(hypot, hypot,
"hypot(x,y)\n\nReturn the Euclidean distance, sqrt(x*x + y*y).")
- FUNC1(log, log,
- "log(x)\n\nReturn the natural logarithm of x.")
- FUNC1(log10, log10,
- "log10(x)\n\nReturn the base-10 logarithm of x.")
#ifdef MPW_3_1 /* This hack is needed for MPW 3.1 but not for 3.2 ... */
FUNC2(pow, power,
--- 138,141 ----
***************
*** 231,234 ****
--- 228,294 ----
"Return the fractional and integer parts of x. Both results carry the sign\n"
"of x. The integer part is returned as a real.";
+
+ /* A decent logarithm is easy to compute even for huge longs, but libm can't
+ do that by itself -- loghelper can. func is log or log10, and name is
+ "log" or "log10". Note that overflow isn't possible: a long can contain
+ no more than INT_MAX * SHIFT bits, so has value certainly less than
+ 2**(2**64 * 2**16) == 2**2**80, and log2 of that is 2**80, which is
+ small enough to fit in an IEEE single. log and log10 are even smaller.
+ */
+
+ static PyObject*
+ loghelper(PyObject* args, double (*func)(double), char *name)
+ {
+ PyObject *arg;
+ char format[16];
+
+ /* See whether this is a long. */
+ format[0] = 'O';
+ format[1] = ':';
+ strcpy(format + 2, name);
+ if (! PyArg_ParseTuple(args, format, &arg))
+ return NULL;
+
+ /* If it is long, do it ourselves. */
+ if (PyLong_Check(arg)) {
+ double x;
+ int e;
+ x = _PyLong_AsScaledDouble(arg, &e);
+ if (x <= 0.0) {
+ PyErr_SetString(PyExc_ValueError,
+ "math domain error");
+ return NULL;
+ }
+ /* Value is ~= x * 2**(e*SHIFT), so the log ~=
+ log(x) + log(2) * e * SHIFT.
+ CAUTION: e*SHIFT may overflow using int arithmetic,
+ so force use of double. */
+ x = func(x) + func(2.0) * (double)e * (double)SHIFT;
+ return PyFloat_FromDouble(x);
+ }
+
+ /* Else let libm handle it by itself. */
+ format[0] = 'd';
+ return math_1(args, func, format);
+ }
+
+ static PyObject *
+ math_log(PyObject *self, PyObject *args)
+ {
+ return loghelper(args, log, "log");
+ }
+
+ static char math_log_doc[] =
+ "log(x) -> the natural logarithm (base e) of x.";
+
+ static PyObject *
+ math_log10(PyObject *self, PyObject *args)
+ {
+ return loghelper(args, log10, "log10");
+ }
+
+ static char math_log10_doc[] =
+ "log10(x) -> the base 10 logarithm of x.";
+
static PyMethodDef math_methods[] = {