|
1 | 1 | /* Math module -- standard C math library functions, pi and e */
|
2 | 2 |
|
3 | 3 | #include "Python.h"
|
| 4 | +#include "longintrepr.h" |
4 | 5 |
|
5 | 6 | #ifndef _MSC_VER
|
6 | 7 | #ifndef __STDC__
|
@@ -136,10 +137,6 @@ FUNC2(fmod, fmod,
|
136 | 137 | " x % y may differ.")
|
137 | 138 | FUNC2(hypot, hypot,
|
138 | 139 | "hypot(x,y)\n\nReturn the Euclidean distance, sqrt(x*x + y*y).")
|
139 |
| -FUNC1(log, log, |
140 |
| - "log(x)\n\nReturn the natural logarithm of x.") |
141 |
| -FUNC1(log10, log10, |
142 |
| - "log10(x)\n\nReturn the base-10 logarithm of x.") |
143 | 140 | #ifdef MPW_3_1 /* This hack is needed for MPW 3.1 but not for 3.2 ... */
|
144 | 141 | FUNC2(pow, power,
|
145 | 142 | "pow(x,y)\n\nReturn x**y (x to the power of y).")
|
@@ -231,6 +228,69 @@ static char math_modf_doc [] =
|
231 | 228 | "Return the fractional and integer parts of x. Both results carry the sign\n"
|
232 | 229 | "of x. The integer part is returned as a real.";
|
233 | 230 |
|
| 231 | +/* A decent logarithm is easy to compute even for huge longs, but libm can't |
| 232 | + do that by itself -- loghelper can. func is log or log10, and name is |
| 233 | + "log" or "log10". Note that overflow isn't possible: a long can contain |
| 234 | + no more than INT_MAX * SHIFT bits, so has value certainly less than |
| 235 | + 2**(2**64 * 2**16) == 2**2**80, and log2 of that is 2**80, which is |
| 236 | + small enough to fit in an IEEE single. log and log10 are even smaller. |
| 237 | +*/ |
| 238 | + |
| 239 | +static PyObject* |
| 240 | +loghelper(PyObject* args, double (*func)(double), char *name) |
| 241 | +{ |
| 242 | + PyObject *arg; |
| 243 | + char format[16]; |
| 244 | + |
| 245 | + /* See whether this is a long. */ |
| 246 | + format[0] = 'O'; |
| 247 | + format[1] = ':'; |
| 248 | + strcpy(format + 2, name); |
| 249 | + if (! PyArg_ParseTuple(args, format, &arg)) |
| 250 | + return NULL; |
| 251 | + |
| 252 | + /* If it is long, do it ourselves. */ |
| 253 | + if (PyLong_Check(arg)) { |
| 254 | + double x; |
| 255 | + int e; |
| 256 | + x = _PyLong_AsScaledDouble(arg, &e); |
| 257 | + if (x <= 0.0) { |
| 258 | + PyErr_SetString(PyExc_ValueError, |
| 259 | + "math domain error"); |
| 260 | + return NULL; |
| 261 | + } |
| 262 | + /* Value is ~= x * 2**(e*SHIFT), so the log ~= |
| 263 | + log(x) + log(2) * e * SHIFT. |
| 264 | + CAUTION: e*SHIFT may overflow using int arithmetic, |
| 265 | + so force use of double. */ |
| 266 | + x = func(x) + func(2.0) * (double)e * (double)SHIFT; |
| 267 | + return PyFloat_FromDouble(x); |
| 268 | + } |
| 269 | + |
| 270 | + /* Else let libm handle it by itself. */ |
| 271 | + format[0] = 'd'; |
| 272 | + return math_1(args, func, format); |
| 273 | +} |
| 274 | + |
| 275 | +static PyObject * |
| 276 | +math_log(PyObject *self, PyObject *args) |
| 277 | +{ |
| 278 | + return loghelper(args, log, "log"); |
| 279 | +} |
| 280 | + |
| 281 | +static char math_log_doc[] = |
| 282 | +"log(x) -> the natural logarithm (base e) of x."; |
| 283 | + |
| 284 | +static PyObject * |
| 285 | +math_log10(PyObject *self, PyObject *args) |
| 286 | +{ |
| 287 | + return loghelper(args, log10, "log10"); |
| 288 | +} |
| 289 | + |
| 290 | +static char math_log10_doc[] = |
| 291 | +"log10(x) -> the base 10 logarithm of x."; |
| 292 | + |
| 293 | + |
234 | 294 | static PyMethodDef math_methods[] = {
|
235 | 295 | {"acos", math_acos, METH_VARARGS, math_acos_doc},
|
236 | 296 | {"asin", math_asin, METH_VARARGS, math_asin_doc},
|
|
0 commit comments