home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 15 / AACD15.ISO / AACD / Programming / Python2 / Python20_source / Modules / mathmodule.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-25  |  8.8 KB  |  317 lines

  1. /* Math module -- standard C math library functions, pi and e */
  2.  
  3. #include "Python.h"
  4.  
  5. #ifndef _MSC_VER
  6. #ifndef __STDC__
  7. extern double fmod (double, double);
  8. extern double frexp (double, int *);
  9. extern double ldexp (double, int);
  10. extern double modf (double, double *);
  11. #endif /* __STDC__ */
  12. #endif /* _MSC_VER */
  13.  
  14.  
  15. #ifdef i860
  16. /* Cray APP has bogus definition of HUGE_VAL in <math.h> */
  17. #undef HUGE_VAL
  18. #endif
  19.  
  20. /* RED_FLAG 12-Oct-2000 Tim
  21.  * What CHECK does if errno == 0 and x is a NaN is a platform-dependent crap
  22.  * shoot.  Most (but not all!) platforms will end up setting errno to ERANGE
  23.  * then, but EDOM is probably better.
  24.  */
  25. #ifdef HUGE_VAL
  26. #define CHECK(x) if (errno != 0) ; \
  27.     else if (-HUGE_VAL <= (x) && (x) <= HUGE_VAL) ; \
  28.     else errno = ERANGE
  29. #else
  30. #define CHECK(x) /* Don't know how to check */
  31. #endif
  32.  
  33. /* Call is_error when errno != 0, and where x is the result libm
  34.  * returned.  is_error will usually set up an exception and return
  35.  * true (1), but may return false (0) without setting up an exception.
  36.  */
  37. static int
  38. is_error(double x)
  39. {
  40.     int result = 1;    /* presumption of guilt */
  41.     assert(errno);    /* non-zero errno is a precondition for calling */
  42.     if (errno == EDOM)
  43.         PyErr_SetString(PyExc_ValueError, "math domain error");
  44.     else if (errno == ERANGE) {
  45.         /* ANSI C generally requires libm functions to set ERANGE
  46.          * on overflow, but also generally *allows* them to set
  47.          * ERANGE on underflow too.  There's no consistency about
  48.          * the latter across platforms.  Here we suppress the
  49.          * underflow errors (libm functions should return a zero
  50.          * on underflow, and +- HUGE_VAL on overflow, so testing
  51.          * the result for zero suffices to distinguish the cases).
  52.          */
  53.         if (x)
  54.             PyErr_SetString(PyExc_OverflowError, 
  55.                     "math range error");
  56.         else
  57.             result = 0;
  58.     }
  59.     else
  60.                 /* Unexpected math error */
  61.         PyErr_SetFromErrno(PyExc_ValueError);
  62.     return result;
  63. }
  64.  
  65. #ifdef __SASC
  66. static PyObject *math_post_f(double x)
  67. {
  68.     CHECK(x);
  69.     if(errno && is_error(x)) return NULL;
  70.     else return PyFloat_FromDouble(x);
  71. }
  72.  
  73. #define FUNC1(funcname, func, docstring) \
  74.     static PyObject * math_##funcname(PyObject *self, PyObject *args) { \
  75.     double x; if (!  PyArg_ParseTuple(args, "d:" #funcname, &x)) return NULL; \
  76.     errno = 0; PyFPE_START_PROTECT("in math_1", return 0) \
  77.     x = func(x); PyFPE_END_PROTECT(x)  return math_post_f(x); } \
  78.         static char math_##funcname##_doc [] = docstring;
  79.  
  80. #define FUNC2(funcname, func, docstring) \
  81.     static PyObject * math_##funcname(PyObject *self, PyObject *args) { \
  82.     double x, y; if (! PyArg_ParseTuple(args, "dd:" #funcname, &x, &y))    return NULL; \
  83.     errno = 0; PyFPE_START_PROTECT("in math_2", return 0) \
  84.     x = func(x, y);    PyFPE_END_PROTECT(x)  return math_post_f(x); } \
  85.         static char math_##funcname##_doc [] = docstring;
  86.  
  87. #else /* !__SASC */
  88. static PyObject *
  89. math_1(PyObject *args, double (*func) (double), char *argsfmt)
  90. {
  91.     double x;
  92.     if (!  PyArg_ParseTuple(args, argsfmt, &x))
  93.         return NULL;
  94.     errno = 0;
  95.     PyFPE_START_PROTECT("in math_1", return 0)
  96.     x = (*func)(x);
  97.     PyFPE_END_PROTECT(x)
  98.     CHECK(x);
  99.     if (errno && is_error(x))
  100.         return NULL;
  101.     else
  102.         return PyFloat_FromDouble(x);
  103. }
  104.  
  105. static PyObject *
  106. math_2(PyObject *args, double (*func) (double, double), char *argsfmt)
  107. {
  108.     double x, y;
  109.     if (! PyArg_ParseTuple(args, argsfmt, &x, &y))
  110.         return NULL;
  111.     errno = 0;
  112.     PyFPE_START_PROTECT("in math_2", return 0)
  113.     x = (*func)(x, y);
  114.     PyFPE_END_PROTECT(x)
  115.     CHECK(x);
  116.     if (errno && is_error(x))
  117.         return NULL;
  118.     else
  119.         return PyFloat_FromDouble(x);
  120. }
  121.  
  122. #define FUNC1(funcname, func, docstring) \
  123.     static PyObject * math_##funcname(PyObject *self, PyObject *args) { \
  124.         return math_1(args, func, "d:" #funcname); \
  125.     }\
  126.         static char math_##funcname##_doc [] = docstring;
  127.  
  128. #define FUNC2(funcname, func, docstring) \
  129.     static PyObject * math_##funcname(PyObject *self, PyObject *args) { \
  130.         return math_2(args, func, "dd:" #funcname); \
  131.     }\
  132.         static char math_##funcname##_doc [] = docstring;
  133.  
  134. #endif /* !__SASC */
  135.  
  136. FUNC1(acos, acos,
  137.       "acos(x)\n\nReturn the arc cosine of x.")
  138. FUNC1(asin, asin,
  139.       "asin(x)\n\nReturn the arc sine of x.")
  140. FUNC1(atan, atan,
  141.       "atan(x)\n\nReturn the arc tangent of x.")
  142. FUNC2(atan2, atan2,
  143.       "atan2(y, x)\n\nReturn atan(y/x).")
  144. FUNC1(ceil, ceil,
  145.       "ceil(x)\n\nReturn the ceiling of x as a real.")
  146. FUNC1(cos, cos,
  147.       "cos(x)\n\nReturn the cosine of x.")
  148. FUNC1(cosh, cosh,
  149.       "cosh(x)\n\nReturn the hyperbolic cosine of x.")
  150. FUNC1(exp, exp,
  151.       "exp(x)\n\nReturn e raised to the power of x.")
  152. FUNC1(fabs, fabs,
  153.       "fabs(x)\n\nReturn the absolute value of the real x.")
  154. FUNC1(floor, floor,
  155.       "floor(x)\n\nReturn the floor of x as a real.")
  156.      FUNC2(fmod, fmod,
  157.       "fmod(x,y)\n\nReturn fmod(x, y), according to platform C."
  158.       "  x % y may differ.")
  159. FUNC2(hypot, hypot,
  160.       "hypot(x,y)\n\nReturn the Euclidean distance, sqrt(x*x + y*y).")
  161. FUNC1(log, log,
  162.       "log(x)\n\nReturn the natural logarithm of x.")
  163. FUNC1(log10, log10,
  164.       "log10(x)\n\nReturn the base-10 logarithm of x.")
  165. #ifdef MPW_3_1 /* This hack is needed for MPW 3.1 but not for 3.2 ... */
  166. FUNC2(pow, power,
  167.       "pow(x,y)\n\nReturn x**y.")
  168. #else
  169. FUNC2(pow, pow,
  170.       "pow(x,y)\n\nReturn x**y.")
  171. #endif
  172. FUNC1(sin, sin,
  173.       "sin(x)\n\nReturn the sine of x.")
  174. FUNC1(sinh, sinh,
  175.       "sinh(x)\n\nReturn the hyperbolic sine of x.")
  176. FUNC1(sqrt, sqrt,
  177.       "sqrt(x)\n\nReturn the square root of x.")
  178. FUNC1(tan, tan,
  179.       "tan(x)\n\nReturn the tangent of x.")
  180. FUNC1(tanh, tanh,
  181.       "tanh(x)\n\nReturn the hyperbolic tangent of x.")
  182.  
  183.  
  184. static PyObject *
  185. math_frexp(PyObject *self, PyObject *args)
  186. {
  187.     double x;
  188.     int i;
  189.     if (! PyArg_ParseTuple(args, "d:frexp", &x))
  190.         return NULL;
  191.     errno = 0;
  192.     x = frexp(x, &i);
  193.     CHECK(x);
  194.     if (errno && is_error(x))
  195.         return NULL;
  196.     else
  197.         return Py_BuildValue("(di)", x, i);
  198. }
  199.  
  200. static char math_frexp_doc [] =
  201. "frexp(x)\n\
  202. \n\
  203. Return the mantissa and exponent of x, as pair (m, e).\n\
  204. m is a float and e is an int, such that x = m * 2.**e.\n\
  205. If x is 0, m and e are both 0.  Else 0.5 <= abs(m) < 1.0.";
  206.  
  207.  
  208. static PyObject *
  209. math_ldexp(PyObject *self, PyObject *args)
  210. {
  211.     double x;
  212.     int exp;
  213.     if (! PyArg_ParseTuple(args, "di:ldexp", &x, &exp))
  214.         return NULL;
  215.     errno = 0;
  216.     PyFPE_START_PROTECT("ldexp", return 0)
  217.     x = ldexp(x, exp);
  218.     PyFPE_END_PROTECT(x)
  219.     CHECK(x);
  220.     if (errno && is_error(x))
  221.         return NULL;
  222.     else
  223.         return PyFloat_FromDouble(x);
  224. }
  225.  
  226. static char math_ldexp_doc [] = 
  227. "ldexp_doc(x, i)\n\
  228. \n\
  229. Return x * (2**i).";
  230.  
  231.  
  232. static PyObject *
  233. math_modf(PyObject *self, PyObject *args)
  234. {
  235.     double x, y;
  236.     if (! PyArg_ParseTuple(args, "d:modf", &x))
  237.         return NULL;
  238.     errno = 0;
  239. #ifdef MPW /* MPW C modf expects pointer to extended as second argument */
  240.         {
  241.         extended e;
  242.         x = modf(x, &e);
  243.         y = e;
  244.         }
  245. #else
  246.     x = modf(x, &y);
  247. #endif
  248.     CHECK(x);
  249.     if (errno && is_error(x))
  250.         return NULL;
  251.     else
  252.         return Py_BuildValue("(dd)", x, y);
  253. }
  254.  
  255. static char math_modf_doc [] =
  256. "modf(x)\n\
  257. \n\
  258. Return the fractional and integer parts of x. Both results carry the sign\n\
  259. of x.  The integer part is returned as a real.";
  260.  
  261.  
  262. static PyMethodDef math_methods[] = {
  263.     {"acos",    math_acos,    METH_VARARGS,    math_acos_doc},
  264.     {"asin",    math_asin,    METH_VARARGS,    math_asin_doc},
  265.     {"atan",    math_atan,    METH_VARARGS,    math_atan_doc},
  266.     {"atan2",    math_atan2,    METH_VARARGS,    math_atan2_doc},
  267.     {"ceil",    math_ceil,    METH_VARARGS,    math_ceil_doc},
  268.     {"cos",        math_cos,    METH_VARARGS,    math_cos_doc},
  269.     {"cosh",    math_cosh,    METH_VARARGS,    math_cosh_doc},
  270.     {"exp",        math_exp,    METH_VARARGS,    math_exp_doc},
  271.     {"fabs",    math_fabs,    METH_VARARGS,    math_fabs_doc},
  272.     {"floor",    math_floor,    METH_VARARGS,    math_floor_doc},
  273.     {"fmod",    math_fmod,    METH_VARARGS,    math_fmod_doc},
  274.     {"frexp",    math_frexp,    METH_VARARGS,    math_frexp_doc},
  275.     {"hypot",    math_hypot,    METH_VARARGS,    math_hypot_doc},
  276.     {"ldexp",    math_ldexp,    METH_VARARGS,    math_ldexp_doc},
  277.     {"log",        math_log,    METH_VARARGS,    math_log_doc},
  278.     {"log10",    math_log10,    METH_VARARGS,    math_log10_doc},
  279.     {"modf",    math_modf,    METH_VARARGS,    math_modf_doc},
  280.     {"pow",        math_pow,    METH_VARARGS,    math_pow_doc},
  281.     {"sin",        math_sin,    METH_VARARGS,    math_sin_doc},
  282.     {"sinh",    math_sinh,    METH_VARARGS,    math_sinh_doc},
  283.     {"sqrt",    math_sqrt,    METH_VARARGS,    math_sqrt_doc},
  284.     {"tan",        math_tan,    METH_VARARGS,    math_tan_doc},
  285.     {"tanh",    math_tanh,    METH_VARARGS,    math_tanh_doc},
  286.     {NULL,        NULL}        /* sentinel */
  287. };
  288.  
  289.  
  290. static char module_doc [] =
  291. "This module is always available.  It provides access to the\n\
  292. mathematical functions defined by the C standard.";
  293.  
  294. DL_EXPORT(void)
  295. initmath(void)
  296. {
  297.     PyObject *m, *d, *v;
  298.     
  299.     m = Py_InitModule3("math", math_methods, module_doc);
  300.     d = PyModule_GetDict(m);
  301.  
  302.         if (!(v = PyFloat_FromDouble(atan(1.0) * 4.0)))
  303.                 goto finally;
  304.     if (PyDict_SetItemString(d, "pi", v) < 0)
  305.                 goto finally;
  306.     Py_DECREF(v);
  307.  
  308.         if (!(v = PyFloat_FromDouble(exp(1.0))))
  309.                 goto finally;
  310.     if (PyDict_SetItemString(d, "e", v) < 0)
  311.                 goto finally;
  312.     Py_DECREF(v);
  313.  
  314.   finally:
  315.     return;
  316. }
  317.