1 /* Math module -- standard C math library functions, pi and e */
4 #include "longintrepr.h"
8 extern double fmod (double, double);
9 extern double frexp (double, int *);
10 extern double ldexp (double, int);
11 extern double modf (double, double *);
15 /* Call is_error when errno != 0, and where x is the result libm
16 * returned. is_error will usually set up an exception and return
17 * true (1), but may return false (0) without setting up an exception.
22 int result
= 1; /* presumption of guilt */
23 assert(errno
); /* non-zero errno is a precondition for calling */
25 PyErr_SetString(PyExc_ValueError
, "math domain error");
27 else if (errno
== ERANGE
) {
28 /* ANSI C generally requires libm functions to set ERANGE
29 * on overflow, but also generally *allows* them to set
30 * ERANGE on underflow too. There's no consistency about
31 * the latter across platforms.
32 * Alas, C99 never requires that errno be set.
33 * Here we suppress the underflow errors (libm functions
34 * should return a zero on underflow, and +- HUGE_VAL on
35 * overflow, so testing the result for zero suffices to
36 * distinguish the cases).
39 PyErr_SetString(PyExc_OverflowError
,
45 /* Unexpected math error */
46 PyErr_SetFromErrno(PyExc_ValueError
);
51 math_1(PyObject
*args
, double (*func
) (double), char *argsfmt
)
54 if (! PyArg_ParseTuple(args
, argsfmt
, &x
))
57 PyFPE_START_PROTECT("in math_1", return 0)
60 Py_SET_ERANGE_IF_OVERFLOW(x
);
61 if (errno
&& is_error(x
))
64 return PyFloat_FromDouble(x
);
68 math_2(PyObject
*args
, double (*func
) (double, double), char *argsfmt
)
71 if (! PyArg_ParseTuple(args
, argsfmt
, &x
, &y
))
74 PyFPE_START_PROTECT("in math_2", return 0)
77 Py_SET_ERANGE_IF_OVERFLOW(x
);
78 if (errno
&& is_error(x
))
81 return PyFloat_FromDouble(x
);
84 #define FUNC1(funcname, func, docstring) \
85 static PyObject * math_##funcname(PyObject *self, PyObject *args) { \
86 return math_1(args, func, "d:" #funcname); \
88 PyDoc_STRVAR(math_##funcname##_doc, docstring);
90 #define FUNC2(funcname, func, docstring) \
91 static PyObject * math_##funcname(PyObject *self, PyObject *args) { \
92 return math_2(args, func, "dd:" #funcname); \
94 PyDoc_STRVAR(math_##funcname##_doc, docstring);
97 "acos(x)\n\nReturn the arc cosine (measured in radians) of x.")
99 "asin(x)\n\nReturn the arc sine (measured in radians) of x.")
101 "atan(x)\n\nReturn the arc tangent (measured in radians) of x.")
103 "atan2(y, x)\n\nReturn the arc tangent (measured in radians) of y/x.\n"
104 "Unlike atan(y/x), the signs of both x and y are considered.")
106 "ceil(x)\n\nReturn the ceiling of x as a float.\n"
107 "This is the smallest integral value >= x.")
109 "cos(x)\n\nReturn the cosine of x (measured in radians).")
111 "cosh(x)\n\nReturn the hyperbolic cosine of x.")
113 "exp(x)\n\nReturn e raised to the power of x.")
115 "fabs(x)\n\nReturn the absolute value of the float x.")
117 "floor(x)\n\nReturn the floor of x as a float.\n"
118 "This is the largest integral value <= x.")
120 "fmod(x,y)\n\nReturn fmod(x, y), according to platform C."
121 " x % y may differ.")
123 "hypot(x,y)\n\nReturn the Euclidean distance, sqrt(x*x + y*y).")
124 #ifdef MPW_3_1 /* This hack is needed for MPW 3.1 but not for 3.2 ... */
126 "pow(x,y)\n\nReturn x**y (x to the power of y).")
129 "pow(x,y)\n\nReturn x**y (x to the power of y).")
132 "sin(x)\n\nReturn the sine of x (measured in radians).")
134 "sinh(x)\n\nReturn the hyperbolic sine of x.")
136 "sqrt(x)\n\nReturn the square root of x.")
138 "tan(x)\n\nReturn the tangent of x (measured in radians).")
140 "tanh(x)\n\nReturn the hyperbolic tangent of x.")
143 math_frexp(PyObject
*self
, PyObject
*args
)
147 if (! PyArg_ParseTuple(args
, "d:frexp", &x
))
151 Py_SET_ERANGE_IF_OVERFLOW(x
);
152 if (errno
&& is_error(x
))
155 return Py_BuildValue("(di)", x
, i
);
158 PyDoc_STRVAR(math_frexp_doc
,
161 "Return the mantissa and exponent of x, as pair (m, e).\n"
162 "m is a float and e is an int, such that x = m * 2.**e.\n"
163 "If x is 0, m and e are both 0. Else 0.5 <= abs(m) < 1.0.");
166 math_ldexp(PyObject
*self
, PyObject
*args
)
170 if (! PyArg_ParseTuple(args
, "di:ldexp", &x
, &exp
))
173 PyFPE_START_PROTECT("ldexp", return 0)
176 Py_SET_ERANGE_IF_OVERFLOW(x
);
177 if (errno
&& is_error(x
))
180 return PyFloat_FromDouble(x
);
183 PyDoc_STRVAR(math_ldexp_doc
,
184 "ldexp(x, i) -> x * (2**i)");
187 math_modf(PyObject
*self
, PyObject
*args
)
190 if (! PyArg_ParseTuple(args
, "d:modf", &x
))
193 #ifdef MPW /* MPW C modf expects pointer to extended as second argument */
202 Py_SET_ERANGE_IF_OVERFLOW(x
);
203 if (errno
&& is_error(x
))
206 return Py_BuildValue("(dd)", x
, y
);
209 PyDoc_STRVAR(math_modf_doc
,
212 "Return the fractional and integer parts of x. Both results carry the sign\n"
213 "of x. The integer part is returned as a real.");
215 /* A decent logarithm is easy to compute even for huge longs, but libm can't
216 do that by itself -- loghelper can. func is log or log10, and name is
217 "log" or "log10". Note that overflow isn't possible: a long can contain
218 no more than INT_MAX * SHIFT bits, so has value certainly less than
219 2**(2**64 * 2**16) == 2**2**80, and log2 of that is 2**80, which is
220 small enough to fit in an IEEE single. log and log10 are even smaller.
224 loghelper(PyObject
* args
, double (*func
)(double), char *name
)
229 /* See whether this is a long. */
232 strcpy(format
+ 2, name
);
233 if (! PyArg_ParseTuple(args
, format
, &arg
))
236 /* If it is long, do it ourselves. */
237 if (PyLong_Check(arg
)) {
240 x
= _PyLong_AsScaledDouble(arg
, &e
);
242 PyErr_SetString(PyExc_ValueError
,
243 "math domain error");
246 /* Value is ~= x * 2**(e*SHIFT), so the log ~=
247 log(x) + log(2) * e * SHIFT.
248 CAUTION: e*SHIFT may overflow using int arithmetic,
249 so force use of double. */
250 x
= func(x
) + (e
* (double)SHIFT
) * func(2.0);
251 return PyFloat_FromDouble(x
);
254 /* Else let libm handle it by itself. */
256 return math_1(args
, func
, format
);
260 math_log(PyObject
*self
, PyObject
*args
)
262 return loghelper(args
, log
, "log");
265 PyDoc_STRVAR(math_log_doc
,
266 "log(x) -> the natural logarithm (base e) of x.");
269 math_log10(PyObject
*self
, PyObject
*args
)
271 return loghelper(args
, log10
, "log10");
274 PyDoc_STRVAR(math_log10_doc
,
275 "log10(x) -> the base 10 logarithm of x.");
277 static const double degToRad
= 3.141592653589793238462643383 / 180.0;
280 math_degrees(PyObject
*self
, PyObject
*args
)
283 if (! PyArg_ParseTuple(args
, "d:degrees", &x
))
285 return PyFloat_FromDouble(x
/ degToRad
);
288 PyDoc_STRVAR(math_degrees_doc
,
289 "degrees(x) -> converts angle x from radians to degrees");
292 math_radians(PyObject
*self
, PyObject
*args
)
295 if (! PyArg_ParseTuple(args
, "d:radians", &x
))
297 return PyFloat_FromDouble(x
* degToRad
);
300 PyDoc_STRVAR(math_radians_doc
,
301 "radians(x) -> converts angle x from degrees to radians");
303 static PyMethodDef math_methods
[] = {
304 {"acos", math_acos
, METH_VARARGS
, math_acos_doc
},
305 {"asin", math_asin
, METH_VARARGS
, math_asin_doc
},
306 {"atan", math_atan
, METH_VARARGS
, math_atan_doc
},
307 {"atan2", math_atan2
, METH_VARARGS
, math_atan2_doc
},
308 {"ceil", math_ceil
, METH_VARARGS
, math_ceil_doc
},
309 {"cos", math_cos
, METH_VARARGS
, math_cos_doc
},
310 {"cosh", math_cosh
, METH_VARARGS
, math_cosh_doc
},
311 {"degrees", math_degrees
, METH_VARARGS
, math_degrees_doc
},
312 {"exp", math_exp
, METH_VARARGS
, math_exp_doc
},
313 {"fabs", math_fabs
, METH_VARARGS
, math_fabs_doc
},
314 {"floor", math_floor
, METH_VARARGS
, math_floor_doc
},
315 {"fmod", math_fmod
, METH_VARARGS
, math_fmod_doc
},
316 {"frexp", math_frexp
, METH_VARARGS
, math_frexp_doc
},
317 {"hypot", math_hypot
, METH_VARARGS
, math_hypot_doc
},
318 {"ldexp", math_ldexp
, METH_VARARGS
, math_ldexp_doc
},
319 {"log", math_log
, METH_VARARGS
, math_log_doc
},
320 {"log10", math_log10
, METH_VARARGS
, math_log10_doc
},
321 {"modf", math_modf
, METH_VARARGS
, math_modf_doc
},
322 {"pow", math_pow
, METH_VARARGS
, math_pow_doc
},
323 {"radians", math_radians
, METH_VARARGS
, math_radians_doc
},
324 {"sin", math_sin
, METH_VARARGS
, math_sin_doc
},
325 {"sinh", math_sinh
, METH_VARARGS
, math_sinh_doc
},
326 {"sqrt", math_sqrt
, METH_VARARGS
, math_sqrt_doc
},
327 {"tan", math_tan
, METH_VARARGS
, math_tan_doc
},
328 {"tanh", math_tanh
, METH_VARARGS
, math_tanh_doc
},
329 {NULL
, NULL
} /* sentinel */
333 PyDoc_STRVAR(module_doc
,
334 "This module is always available. It provides access to the\n"
335 "mathematical functions defined by the C standard.");
342 m
= Py_InitModule3("math", math_methods
, module_doc
);
343 d
= PyModule_GetDict(m
);
345 if (!(v
= PyFloat_FromDouble(atan(1.0) * 4.0)))
347 if (PyDict_SetItemString(d
, "pi", v
) < 0)
351 if (!(v
= PyFloat_FromDouble(exp(1.0))))
353 if (PyDict_SetItemString(d
, "e", v
) < 0)