mathmodule.c 8.38 KB
Newer Older
1
/***********************************************************
2 3
Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
The Netherlands.
4 5 6

                        All Rights Reserved

7 8
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
9
provided that the above copyright notice appear in all copies and that
10
both that copyright notice and this permission notice appear in
11
supporting documentation, and that the names of Stichting Mathematisch
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
Centrum or CWI or Corporation for National Research Initiatives or
CNRI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.

While CWI is the initial source for this software, a modified version
is made available by the Corporation for National Research Initiatives
(CNRI) at the Internet address ftp://ftp.python.org.

STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
29 30 31

******************************************************************/

Guido van Rossum's avatar
Guido van Rossum committed
32 33
/* Math module -- standard C math library functions, pi and e */

Barry Warsaw's avatar
Barry Warsaw committed
34
#include "Python.h"
Guido van Rossum's avatar
Guido van Rossum committed
35

Guido van Rossum's avatar
Guido van Rossum committed
36
#include "mymath.h"
Guido van Rossum's avatar
Guido van Rossum committed
37

Guido van Rossum's avatar
Guido van Rossum committed
38
#ifndef _MSC_VER
39
#ifndef __STDC__
Barry Warsaw's avatar
Barry Warsaw committed
40 41 42 43
extern double fmod Py_PROTO((double, double));
extern double frexp Py_PROTO((double, int *));
extern double ldexp Py_PROTO((double, int));
extern double modf Py_PROTO((double, double *));
Guido van Rossum's avatar
Guido van Rossum committed
44 45 46
#endif /* __STDC__ */
#endif /* _MSC_VER */

47 48 49 50

#ifdef i860
/* Cray APP has bogus definition of HUGE_VAL in <math.h> */
#undef HUGE_VAL
51
#endif
52

53 54 55 56 57 58 59 60
#ifdef HUGE_VAL
#define CHECK(x) if (errno != 0) ; \
	else if (-HUGE_VAL <= (x) && (x) <= HUGE_VAL) ; \
	else errno = ERANGE
#else
#define CHECK(x) /* Don't know how to check */
#endif

Barry Warsaw's avatar
Barry Warsaw committed
61
static PyObject *
62 63 64
math_error()
{
	if (errno == EDOM)
Barry Warsaw's avatar
Barry Warsaw committed
65
		PyErr_SetString(PyExc_ValueError, "math domain error");
66
	else if (errno == ERANGE)
Barry Warsaw's avatar
Barry Warsaw committed
67
		PyErr_SetString(PyExc_OverflowError, "math range error");
68
	else
Barry Warsaw's avatar
Barry Warsaw committed
69 70
                /* Unexpected math error */
		PyErr_SetFromErrno(PyExc_ValueError);
71 72 73
	return NULL;
}

Barry Warsaw's avatar
Barry Warsaw committed
74
static PyObject *
Guido van Rossum's avatar
Guido van Rossum committed
75
math_1(args, func)
Barry Warsaw's avatar
Barry Warsaw committed
76 77
	PyObject *args;
	double (*func) Py_FPROTO((double));
Guido van Rossum's avatar
Guido van Rossum committed
78 79
{
	double x;
80
	if (!  PyArg_Parse(args, "d", &x))
Guido van Rossum's avatar
Guido van Rossum committed
81 82
		return NULL;
	errno = 0;
83
	PyFPE_START_PROTECT("in math_1", return 0)
Guido van Rossum's avatar
Guido van Rossum committed
84
	x = (*func)(x);
85
	PyFPE_END_PROTECT(x)
86
	CHECK(x);
Guido van Rossum's avatar
Guido van Rossum committed
87
	if (errno != 0)
88
		return math_error();
Guido van Rossum's avatar
Guido van Rossum committed
89
	else
Barry Warsaw's avatar
Barry Warsaw committed
90
		return PyFloat_FromDouble(x);
Guido van Rossum's avatar
Guido van Rossum committed
91 92
}

Barry Warsaw's avatar
Barry Warsaw committed
93
static PyObject *
Guido van Rossum's avatar
Guido van Rossum committed
94
math_2(args, func)
Barry Warsaw's avatar
Barry Warsaw committed
95 96
	PyObject *args;
	double (*func) Py_FPROTO((double, double));
Guido van Rossum's avatar
Guido van Rossum committed
97 98
{
	double x, y;
99
	if (! PyArg_Parse(args, "(dd)", &x, &y))
Guido van Rossum's avatar
Guido van Rossum committed
100 101
		return NULL;
	errno = 0;
102
	PyFPE_START_PROTECT("in math_2", return 0)
Guido van Rossum's avatar
Guido van Rossum committed
103
	x = (*func)(x, y);
104
	PyFPE_END_PROTECT(x)
105
	CHECK(x);
Guido van Rossum's avatar
Guido van Rossum committed
106
	if (errno != 0)
107
		return math_error();
Guido van Rossum's avatar
Guido van Rossum committed
108
	else
Barry Warsaw's avatar
Barry Warsaw committed
109
		return PyFloat_FromDouble(x);
Guido van Rossum's avatar
Guido van Rossum committed
110 111
}

112
#define FUNC1(stubname, func, docstring_name, docstring) \
Barry Warsaw's avatar
Barry Warsaw committed
113
	static PyObject * stubname(self, args) PyObject *self, *args; { \
Guido van Rossum's avatar
Guido van Rossum committed
114
		return math_1(args, func); \
115 116
	}\
        static char docstring_name [] = docstring;
Guido van Rossum's avatar
Guido van Rossum committed
117

118
#define FUNC2(stubname, func, docstring_name, docstring) \
Barry Warsaw's avatar
Barry Warsaw committed
119
	static PyObject * stubname(self, args) PyObject *self, *args; { \
Guido van Rossum's avatar
Guido van Rossum committed
120
		return math_2(args, func); \
121 122 123 124 125 126 127 128 129 130
	}\
        static char docstring_name [] = docstring;

FUNC1(math_acos, acos, math_acos_doc,
      "acos(x)\n\nReturn the arc cosine of x.")
FUNC1(math_asin, asin, math_asin_doc,
      "asin(x)\n\nReturn the arc sine of x.")
FUNC1(math_atan, atan, math_atan_doc,
      "atan(x)\n\nReturn the arc tangent of x.")
FUNC2(math_atan2, atan2, math_atan2_doc,
131
      "atan2(y, x)\n\nReturn atan(y/x).")
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
FUNC1(math_ceil, ceil, math_ceil_doc,
      "ceil(x)\n\nReturn the ceiling of x as a real.")
FUNC1(math_cos, cos, math_cos_doc,
      "cos(x)\n\nReturn the cosine of x.")
FUNC1(math_cosh, cosh, math_cosh_doc,
      "cosh(x)\n\nReturn the hyperbolic cosine of x.")
FUNC1(math_exp, exp, math_exp_doc,
      "exp(x)\n\nReturn e raised to the power of x.")
FUNC1(math_fabs, fabs, math_fabs_doc,
      "fabs(x)\n\nReturn the absolute value of the real x.")
FUNC1(math_floor, floor, math_floor_doc,
      "floor(x)\n\nReturn the floor of x as a real.")
FUNC2(math_fmod, fmod, math_fmod_doc,
      "fmod(x,y)\n\nReturn x % y.")
FUNC2(math_hypot, hypot, math_hypot_doc,
      "hypot(x,y)\n\nReturn the Euclidean distance, sqrt(x*x + y*y).")
FUNC1(math_log, log, math_log_doc,
      "log(x)\n\nReturn the natural logarithm of x.")
FUNC1(math_log10, log10, math_log10_doc,
      "log10(x)\n\nReturn the base-10 logarithm of x.")
152
#ifdef MPW_3_1 /* This hack is needed for MPW 3.1 but not for 3.2 ... */
153 154
FUNC2(math_pow, power, math_pow_doc,
      "power(x,y)\n\nReturn x**y.")
155
#else
156 157
FUNC2(math_pow, pow, math_pow_doc,
      "pow(x,y)\n\nReturn x**y.")
158
#endif
159 160 161 162 163 164 165 166 167 168
FUNC1(math_sin, sin, math_sin_doc,
      "sin(x)\n\nReturn the sine of x.")
FUNC1(math_sinh, sinh, math_sinh_doc,
      "sinh(x)\n\nReturn the hyperbolic sine of x.")
FUNC1(math_sqrt, sqrt, math_sqrt_doc,
      "sqrt(x)\n\nReturn the square root of x.")
FUNC1(math_tan, tan, math_tan_doc,
      "tan(x)\n\nReturn the tangent of x.")
FUNC1(math_tanh, tanh, math_tanh_doc,
      "tanh(x)\n\nReturn the hyperbolic tangent of x.")
Guido van Rossum's avatar
Guido van Rossum committed
169

170

Barry Warsaw's avatar
Barry Warsaw committed
171
static PyObject *
172
math_frexp(self, args)
Barry Warsaw's avatar
Barry Warsaw committed
173 174
	PyObject *self;
	PyObject *args;
175 176 177
{
	double x;
	int i;
178
	if (! PyArg_Parse(args, "d", &x))
179 180 181
		return NULL;
	errno = 0;
	x = frexp(x, &i);
182
	CHECK(x);
183
	if (errno != 0)
184
		return math_error();
Barry Warsaw's avatar
Barry Warsaw committed
185
	return Py_BuildValue("(di)", x, i);
186 187
}

188 189 190 191 192 193
static char math_frexp_doc [] =
"frexp(x)\n\
\n\
Return the matissa and exponent for x. The mantissa is positive.";


Barry Warsaw's avatar
Barry Warsaw committed
194
static PyObject *
195
math_ldexp(self, args)
Barry Warsaw's avatar
Barry Warsaw committed
196 197
	PyObject *self;
	PyObject *args;
198
{
Guido van Rossum's avatar
Guido van Rossum committed
199 200 201
	double x;
	int exp;
	if (! PyArg_Parse(args, "(di)", &x, &exp))
202 203
		return NULL;
	errno = 0;
204
	PyFPE_START_PROTECT("ldexp", return 0)
Guido van Rossum's avatar
Guido van Rossum committed
205
	x = ldexp(x, exp);
206
	PyFPE_END_PROTECT(x)
207
	CHECK(x);
208
	if (errno != 0)
209
		return math_error();
210
	else
Barry Warsaw's avatar
Barry Warsaw committed
211
		return PyFloat_FromDouble(x);
212 213
}

214 215 216 217 218 219
static char math_ldexp_doc [] = 
"ldexp_doc(x, i)\n\
\n\
Return x * (2**i).";


Barry Warsaw's avatar
Barry Warsaw committed
220
static PyObject *
221
math_modf(self, args)
Barry Warsaw's avatar
Barry Warsaw committed
222 223
	PyObject *self;
	PyObject *args;
224 225
{
	double x, y;
226
	if (! PyArg_Parse(args, "d", &x))
227 228
		return NULL;
	errno = 0;
229 230 231 232 233 234 235
#ifdef MPW /* MPW C modf expects pointer to extended as second argument */
{
	extended e;
	x = modf(x, &e);
	y = e;
}
#else
236
	x = modf(x, &y);
237
#endif
238
	CHECK(x);
239
	if (errno != 0)
240
		return math_error();
Barry Warsaw's avatar
Barry Warsaw committed
241
	return Py_BuildValue("(dd)", x, y);
242
}
Guido van Rossum's avatar
Guido van Rossum committed
243

244 245 246 247 248 249 250
static char math_modf_doc [] =
"modf(x)\n\
\n\
Return the fractional and integer parts of x. Both results carry the sign\n\
of x.  The integer part is returned as a real.";


Barry Warsaw's avatar
Barry Warsaw committed
251
static PyMethodDef math_methods[] = {
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
	{"acos",	math_acos,	0,	math_acos_doc},
	{"asin",	math_asin,	0,	math_asin_doc},
	{"atan",	math_atan,	0,	math_atan_doc},
	{"atan2",	math_atan2,	0,	math_atan2_doc},
	{"ceil",	math_ceil,	0,	math_ceil_doc},
	{"cos",		math_cos,	0,	math_cos_doc},
	{"cosh",	math_cosh,	0,	math_cosh_doc},
	{"exp",		math_exp,	0,	math_exp_doc},
	{"fabs",	math_fabs,	0,	math_fabs_doc},
	{"floor",	math_floor,	0,	math_floor_doc},
	{"fmod",	math_fmod,	0,	math_fmod_doc},
	{"frexp",	math_frexp,	0,	math_frexp_doc},
	{"hypot",	math_hypot,	0,	math_hypot_doc},
	{"ldexp",	math_ldexp,	0,	math_ldexp_doc},
	{"log",		math_log,	0,	math_log_doc},
	{"log10",	math_log10,	0,	math_log10_doc},
	{"modf",	math_modf,	0,	math_modf_doc},
	{"pow",		math_pow,	0,	math_pow_doc},
	{"sin",		math_sin,	0,	math_sin_doc},
	{"sinh",	math_sinh,	0,	math_sinh_doc},
	{"sqrt",	math_sqrt,	0,	math_sqrt_doc},
	{"tan",		math_tan,	0,	math_tan_doc},
	{"tanh",	math_tanh,	0,	math_tanh_doc},
Guido van Rossum's avatar
Guido van Rossum committed
275 276 277
	{NULL,		NULL}		/* sentinel */
};

278 279 280 281 282

static char module_doc [] =
"This module is always available.  It provides access to the\n\
mathematical functions defined by the C standard.";

283
DL_EXPORT(void)
Guido van Rossum's avatar
Guido van Rossum committed
284 285
initmath()
{
Barry Warsaw's avatar
Barry Warsaw committed
286
	PyObject *m, *d, *v;
287
	
288
	m = Py_InitModule3("math", math_methods, module_doc);
Barry Warsaw's avatar
Barry Warsaw committed
289
	d = PyModule_GetDict(m);
290 291 292 293 294

        if (!(v = PyFloat_FromDouble(atan(1.0) * 4.0)))
                goto finally;
	if (PyDict_SetItemString(d, "pi", v) < 0)
                goto finally;
Barry Warsaw's avatar
Barry Warsaw committed
295
	Py_DECREF(v);
296 297 298

        if (!(v = PyFloat_FromDouble(exp(1.0))))
                goto finally;
299
	if (PyDict_SetItemString(d, "e", v) < 0)
300
                goto finally;
Barry Warsaw's avatar
Barry Warsaw committed
301
	Py_DECREF(v);
302
	return;
303 304 305

  finally:
        Py_FatalError("can't initialize math module");
Guido van Rossum's avatar
Guido van Rossum committed
306
}