summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorMark Dickinson <dickinsm@gmail.com>2009-12-16 20:23:42 (GMT)
committerMark Dickinson <dickinsm@gmail.com>2009-12-16 20:23:42 (GMT)
commit664b511c0acdfdecdec92d2255ffd94c4e6d5f7a (patch)
tree075cdf8651d66f24e42c1b87e57e7423e3e7a9d3 /Modules
parentef1992b9fbcfb1dae7e946bfc42403fcaae9f044 (diff)
downloadcpython-664b511c0acdfdecdec92d2255ffd94c4e6d5f7a.zip
cpython-664b511c0acdfdecdec92d2255ffd94c4e6d5f7a.tar.gz
cpython-664b511c0acdfdecdec92d2255ffd94c4e6d5f7a.tar.bz2
Merged revisions 76861 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r76861 | mark.dickinson | 2009-12-16 20:13:40 +0000 (Wed, 16 Dec 2009) | 3 lines Issue #3366: Add expm1 function to math module. Thanks Eric Smith for testing on Windows. ........
Diffstat (limited to 'Modules')
-rw-r--r--Modules/Setup.dist2
-rw-r--r--Modules/_math.c31
-rw-r--r--Modules/_math.h9
-rw-r--r--Modules/mathmodule.c6
4 files changed, 47 insertions, 1 deletions
diff --git a/Modules/Setup.dist b/Modules/Setup.dist
index 9f189de..e1cb235 100644
--- a/Modules/Setup.dist
+++ b/Modules/Setup.dist
@@ -158,7 +158,7 @@ _symtable symtablemodule.c
#array arraymodule.c # array objects
#cmath cmathmodule.c # -lm # complex math library functions
-#math mathmodule.c # -lm # math library functions, e.g. sin()
+#math mathmodule.c _math.c # -lm # math library functions, e.g. sin()
#_struct _struct.c # binary structure packing/unpacking
#time timemodule.c # -lm # time operations and variables
#operator operator.c # operator.add() and similar goodies
diff --git a/Modules/_math.c b/Modules/_math.c
new file mode 100644
index 0000000..9d330aa
--- /dev/null
+++ b/Modules/_math.c
@@ -0,0 +1,31 @@
+/* Definitions of some C99 math library functions, for those platforms
+ that don't implement these functions already. */
+
+#include <float.h>
+#include <math.h>
+
+/* Mathematically, expm1(x) = exp(x) - 1. The expm1 function is designed
+ to avoid the significant loss of precision that arises from direct
+ evaluation of the expression exp(x) - 1, for x near 0. */
+
+double
+_Py_expm1(double x)
+{
+ /* For abs(x) >= log(2), it's safe to evaluate exp(x) - 1 directly; this
+ also works fine for infinities and nans.
+
+ For smaller x, we can use a method due to Kahan that achieves close to
+ full accuracy.
+ */
+
+ if (fabs(x) < 0.7) {
+ double u;
+ u = exp(x);
+ if (u == 1.0)
+ return x;
+ else
+ return (u - 1.0) * x / log(u);
+ }
+ else
+ return exp(x) - 1.0;
+}
diff --git a/Modules/_math.h b/Modules/_math.h
new file mode 100644
index 0000000..69c96b5
--- /dev/null
+++ b/Modules/_math.h
@@ -0,0 +1,9 @@
+double _Py_expm1(double x);
+
+#ifdef HAVE_EXPM1
+#define m_expm1 expm1
+#else
+/* if the system doesn't have expm1, use the substitute
+ function defined in Modules/_math.c. */
+#define m_expm1 _Py_expm1
+#endif
diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c
index ece68a7..ef84298 100644
--- a/Modules/mathmodule.c
+++ b/Modules/mathmodule.c
@@ -53,6 +53,7 @@ raised for division by zero and mod by zero.
*/
#include "Python.h"
+#include "_math.h"
#include "longintrepr.h" /* just for SHIFT */
#ifdef _OSF_SOURCE
@@ -722,6 +723,10 @@ FUNC1(cosh, cosh, 1,
"cosh(x)\n\nReturn the hyperbolic cosine of x.")
FUNC1(exp, exp, 1,
"exp(x)\n\nReturn e raised to the power of x.")
+FUNC1(expm1, m_expm1, 1,
+ "expm1(x)\n\nReturn exp(x)-1.\n"
+ "This function avoids the loss of precision involved in the direct "
+ "evaluation of exp(x)-1 for small x.")
FUNC1(fabs, fabs, 0,
"fabs(x)\n\nReturn the absolute value of the float x.")
@@ -1493,6 +1498,7 @@ static PyMethodDef math_methods[] = {
{"cosh", math_cosh, METH_O, math_cosh_doc},
{"degrees", math_degrees, METH_O, math_degrees_doc},
{"exp", math_exp, METH_O, math_exp_doc},
+ {"expm1", math_expm1, METH_O, math_expm1_doc},
{"fabs", math_fabs, METH_O, math_fabs_doc},
{"factorial", math_factorial, METH_O, math_factorial_doc},
{"floor", math_floor, METH_O, math_floor_doc},