blob: 4ebb26e45e752a8da352f46df56459b55d56518f [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
Guido van Rossum524b5881995-01-04 19:10:35 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossumf70e43a1991-02-19 12:39:46 +00004
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000025/* Math module -- standard C math library functions, pi and e */
26
Guido van Rossum3f5da241990-12-20 15:06:42 +000027#include "allobjects.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000028
Guido van Rossum801f4731990-12-20 23:09:14 +000029#include <errno.h>
Guido van Rossum801f4731990-12-20 23:09:14 +000030
Guido van Rossum234f9421993-06-17 12:35:49 +000031#define getdoublearg(v, a) getargs(v, "d", a)
32#define get2doublearg(v, a, b) getargs(v, "(dd)", a, b)
33
Guido van Rossum6964f731995-03-01 10:34:29 +000034#include "mymath.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +000035
Guido van Rossum7081cf51996-05-23 22:56:19 +000036#ifndef _MSC_VER
Guido van Rossumb9418681995-01-12 11:28:16 +000037#ifndef __STDC__
38extern double fmod PROTO((double, double));
39extern double frexp PROTO((double, int *));
40extern double ldexp PROTO((double, int));
41extern double modf PROTO((double, double *));
Guido van Rossum7081cf51996-05-23 22:56:19 +000042#endif /* __STDC__ */
43#endif /* _MSC_VER */
44
Guido van Rossumb9418681995-01-12 11:28:16 +000045
Guido van Rossum557d6d61996-07-30 20:44:31 +000046#if defined(HAVE_HYPOT)
Guido van Rossum3bcf7d21996-08-21 20:36:52 +000047#ifndef _MSC_VER
Guido van Rossumb9418681995-01-12 11:28:16 +000048extern double hypot PROTO((double, double));
Guido van Rossum3bcf7d21996-08-21 20:36:52 +000049#endif
Guido van Rossum32062681996-01-12 01:39:11 +000050#else
51double hypot(x,y)
52 double x;
53 double y;
54{
55 double yx;
56
57 x = fabs(x);
58 y = fabs(y);
59 if (x < y) {
60 double temp = x;
61 x = y;
62 y = temp;
63 }
64 if (x == 0.)
65 return 0.;
66 else {
67 yx = y/x;
68 return x*sqrt(1.+yx*yx);
69 }
70}
Guido van Rossumb9418681995-01-12 11:28:16 +000071#endif
72
Guido van Rossum9575a441993-04-07 14:06:14 +000073#ifdef i860
74/* Cray APP has bogus definition of HUGE_VAL in <math.h> */
75#undef HUGE_VAL
76#endif
77
Guido van Rossum8832b621991-12-16 15:44:24 +000078#ifdef HUGE_VAL
79#define CHECK(x) if (errno != 0) ; \
80 else if (-HUGE_VAL <= (x) && (x) <= HUGE_VAL) ; \
81 else errno = ERANGE
82#else
83#define CHECK(x) /* Don't know how to check */
84#endif
85
86static object *
87math_error()
88{
89 if (errno == EDOM)
90 err_setstr(ValueError, "math domain error");
91 else if (errno == ERANGE)
92 err_setstr(OverflowError, "math range error");
93 else
Guido van Rossum444db071992-02-26 15:26:56 +000094 err_errno(ValueError); /* Unexpected math error */
Guido van Rossum8832b621991-12-16 15:44:24 +000095 return NULL;
96}
97
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000098static object *
99math_1(args, func)
100 object *args;
101 double (*func) FPROTO((double));
102{
103 double x;
104 if (!getdoublearg(args, &x))
105 return NULL;
106 errno = 0;
107 x = (*func)(x);
Guido van Rossum8832b621991-12-16 15:44:24 +0000108 CHECK(x);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000109 if (errno != 0)
Guido van Rossum8832b621991-12-16 15:44:24 +0000110 return math_error();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000111 else
112 return newfloatobject(x);
113}
114
115static object *
116math_2(args, func)
117 object *args;
118 double (*func) FPROTO((double, double));
119{
120 double x, y;
121 if (!get2doublearg(args, &x, &y))
122 return NULL;
123 errno = 0;
124 x = (*func)(x, y);
Guido van Rossum8832b621991-12-16 15:44:24 +0000125 CHECK(x);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000126 if (errno != 0)
Guido van Rossum8832b621991-12-16 15:44:24 +0000127 return math_error();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000128 else
129 return newfloatobject(x);
130}
131
132#define FUNC1(stubname, func) \
133 static object * stubname(self, args) object *self, *args; { \
134 return math_1(args, func); \
135 }
136
137#define FUNC2(stubname, func) \
138 static object * stubname(self, args) object *self, *args; { \
139 return math_2(args, func); \
140 }
141
142FUNC1(math_acos, acos)
143FUNC1(math_asin, asin)
144FUNC1(math_atan, atan)
145FUNC2(math_atan2, atan2)
146FUNC1(math_ceil, ceil)
147FUNC1(math_cos, cos)
148FUNC1(math_cosh, cosh)
149FUNC1(math_exp, exp)
Guido van Rossum6412b1d1996-08-08 19:10:21 +0000150#ifdef __MWERKS__
151double myfabs(double x) { return fabs(x); }
152FUNC1(math_fabs, myfabs)
153#else
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000154FUNC1(math_fabs, fabs)
Guido van Rossum6412b1d1996-08-08 19:10:21 +0000155#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000156FUNC1(math_floor, floor)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000157FUNC2(math_fmod, fmod)
Guido van Rossum411a8bd1994-10-20 22:00:28 +0000158FUNC2(math_hypot, hypot)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000159FUNC1(math_log, log)
160FUNC1(math_log10, log10)
Guido van Rossum1492c271991-07-27 21:38:43 +0000161#ifdef MPW_3_1 /* This hack is needed for MPW 3.1 but not for 3.2 ... */
Guido van Rossum76f2f2e1991-06-24 22:23:10 +0000162FUNC2(math_pow, power)
163#else
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000164FUNC2(math_pow, pow)
Guido van Rossum76f2f2e1991-06-24 22:23:10 +0000165#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000166FUNC1(math_sin, sin)
167FUNC1(math_sinh, sinh)
168FUNC1(math_sqrt, sqrt)
169FUNC1(math_tan, tan)
170FUNC1(math_tanh, tanh)
171
Guido van Rossumb6775db1994-08-01 11:34:53 +0000172
Guido van Rossumd18ad581991-10-24 14:57:21 +0000173static object *
174math_frexp(self, args)
175 object *self;
176 object *args;
177{
Guido van Rossumd18ad581991-10-24 14:57:21 +0000178 double x;
179 int i;
180 if (!getdoublearg(args, &x))
181 return NULL;
182 errno = 0;
183 x = frexp(x, &i);
Guido van Rossum8832b621991-12-16 15:44:24 +0000184 CHECK(x);
Guido van Rossumd18ad581991-10-24 14:57:21 +0000185 if (errno != 0)
Guido van Rossum8832b621991-12-16 15:44:24 +0000186 return math_error();
Guido van Rossume5372401993-03-16 12:15:04 +0000187 return mkvalue("(di)", x, i);
Guido van Rossumd18ad581991-10-24 14:57:21 +0000188}
189
190static object *
191math_ldexp(self, args)
192 object *self;
193 object *args;
194{
195 double x, y;
196 /* Cheat -- allow float as second argument */
197 if (!get2doublearg(args, &x, &y))
198 return NULL;
199 errno = 0;
200 x = ldexp(x, (int)y);
Guido van Rossum8832b621991-12-16 15:44:24 +0000201 CHECK(x);
Guido van Rossumd18ad581991-10-24 14:57:21 +0000202 if (errno != 0)
Guido van Rossum8832b621991-12-16 15:44:24 +0000203 return math_error();
Guido van Rossumd18ad581991-10-24 14:57:21 +0000204 else
205 return newfloatobject(x);
206}
207
208static object *
209math_modf(self, args)
210 object *self;
211 object *args;
212{
Guido van Rossumd18ad581991-10-24 14:57:21 +0000213 double x, y;
214 if (!getdoublearg(args, &x))
215 return NULL;
216 errno = 0;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000217#ifdef MPW /* MPW C modf expects pointer to extended as second argument */
218{
219 extended e;
220 x = modf(x, &e);
221 y = e;
222}
223#else
Guido van Rossumd18ad581991-10-24 14:57:21 +0000224 x = modf(x, &y);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000225#endif
Guido van Rossum8832b621991-12-16 15:44:24 +0000226 CHECK(x);
Guido van Rossumd18ad581991-10-24 14:57:21 +0000227 if (errno != 0)
Guido van Rossum8832b621991-12-16 15:44:24 +0000228 return math_error();
Guido van Rossume5372401993-03-16 12:15:04 +0000229 return mkvalue("(dd)", x, y);
Guido van Rossumd18ad581991-10-24 14:57:21 +0000230}
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000231
232static struct methodlist math_methods[] = {
233 {"acos", math_acos},
234 {"asin", math_asin},
235 {"atan", math_atan},
236 {"atan2", math_atan2},
237 {"ceil", math_ceil},
238 {"cos", math_cos},
239 {"cosh", math_cosh},
240 {"exp", math_exp},
241 {"fabs", math_fabs},
242 {"floor", math_floor},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000243 {"fmod", math_fmod},
Guido van Rossumd18ad581991-10-24 14:57:21 +0000244 {"frexp", math_frexp},
Guido van Rossum411a8bd1994-10-20 22:00:28 +0000245 {"hypot", math_hypot},
Guido van Rossumd18ad581991-10-24 14:57:21 +0000246 {"ldexp", math_ldexp},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000247 {"log", math_log},
248 {"log10", math_log10},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000249 {"modf", math_modf},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000250 {"pow", math_pow},
251 {"sin", math_sin},
252 {"sinh", math_sinh},
253 {"sqrt", math_sqrt},
254 {"tan", math_tan},
255 {"tanh", math_tanh},
256 {NULL, NULL} /* sentinel */
257};
258
259void
260initmath()
261{
262 object *m, *d, *v;
Guido van Rossum738d4dd1990-10-26 14:59:30 +0000263
264 m = initmodule("math", math_methods);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000265 d = getmoduledict(m);
Guido van Rossumeb38d241990-11-18 17:36:45 +0000266 dictinsert(d, "pi", v = newfloatobject(atan(1.0) * 4.0));
267 DECREF(v);
268 dictinsert(d, "e", v = newfloatobject(exp(1.0)));
269 DECREF(v);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000270}