blob: fdc576d60987c4c2e62e75aa6b6d33377b95e787 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
2Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
3Netherlands.
4
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>
30#ifndef errno
31extern int errno;
32#endif
33
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000034#include "modsupport.h"
35
Guido van Rossum3f5da241990-12-20 15:06:42 +000036#include <math.h>
37
Guido van Rossum8832b621991-12-16 15:44:24 +000038#ifdef HUGE_VAL
39#define CHECK(x) if (errno != 0) ; \
40 else if (-HUGE_VAL <= (x) && (x) <= HUGE_VAL) ; \
41 else errno = ERANGE
42#else
43#define CHECK(x) /* Don't know how to check */
44#endif
45
46static object *
47math_error()
48{
49 if (errno == EDOM)
50 err_setstr(ValueError, "math domain error");
51 else if (errno == ERANGE)
52 err_setstr(OverflowError, "math range error");
53 else
54 err_errno(RuntimeError);
55 return NULL;
56}
57
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000058static object *
59math_1(args, func)
60 object *args;
61 double (*func) FPROTO((double));
62{
63 double x;
64 if (!getdoublearg(args, &x))
65 return NULL;
66 errno = 0;
67 x = (*func)(x);
Guido van Rossum8832b621991-12-16 15:44:24 +000068 CHECK(x);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000069 if (errno != 0)
Guido van Rossum8832b621991-12-16 15:44:24 +000070 return math_error();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000071 else
72 return newfloatobject(x);
73}
74
75static object *
76math_2(args, func)
77 object *args;
78 double (*func) FPROTO((double, double));
79{
80 double x, y;
81 if (!get2doublearg(args, &x, &y))
82 return NULL;
83 errno = 0;
84 x = (*func)(x, y);
Guido van Rossum8832b621991-12-16 15:44:24 +000085 CHECK(x);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000086 if (errno != 0)
Guido van Rossum8832b621991-12-16 15:44:24 +000087 return math_error();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000088 else
89 return newfloatobject(x);
90}
91
92#define FUNC1(stubname, func) \
93 static object * stubname(self, args) object *self, *args; { \
94 return math_1(args, func); \
95 }
96
97#define FUNC2(stubname, func) \
98 static object * stubname(self, args) object *self, *args; { \
99 return math_2(args, func); \
100 }
101
102FUNC1(math_acos, acos)
103FUNC1(math_asin, asin)
104FUNC1(math_atan, atan)
105FUNC2(math_atan2, atan2)
106FUNC1(math_ceil, ceil)
107FUNC1(math_cos, cos)
108FUNC1(math_cosh, cosh)
109FUNC1(math_exp, exp)
110FUNC1(math_fabs, fabs)
111FUNC1(math_floor, floor)
Guido van Rossumd18ad581991-10-24 14:57:21 +0000112#ifndef AMOEBA
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000113/* XXX This one is not in the Amoeba library yet, so what the heck... */
114FUNC2(math_fmod, fmod)
115#endif
116FUNC1(math_log, log)
117FUNC1(math_log10, log10)
Guido van Rossum1492c271991-07-27 21:38:43 +0000118#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 +0000119FUNC2(math_pow, power)
120#else
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000121FUNC2(math_pow, pow)
Guido van Rossum76f2f2e1991-06-24 22:23:10 +0000122#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000123FUNC1(math_sin, sin)
124FUNC1(math_sinh, sinh)
125FUNC1(math_sqrt, sqrt)
126FUNC1(math_tan, tan)
127FUNC1(math_tanh, tanh)
128
Guido van Rossum98d54331991-11-12 15:44:14 +0000129double frexp PROTO((double, int *));
130double ldexp PROTO((double, int));
131double modf PROTO((double, double *));
Guido van Rossumd18ad581991-10-24 14:57:21 +0000132
133static object *
134math_frexp(self, args)
135 object *self;
136 object *args;
137{
138 object *v;
139 double x;
140 int i;
141 if (!getdoublearg(args, &x))
142 return NULL;
143 errno = 0;
144 x = frexp(x, &i);
Guido van Rossum8832b621991-12-16 15:44:24 +0000145 CHECK(x);
Guido van Rossumd18ad581991-10-24 14:57:21 +0000146 if (errno != 0)
Guido van Rossum8832b621991-12-16 15:44:24 +0000147 return math_error();
Guido van Rossumd18ad581991-10-24 14:57:21 +0000148 v = newtupleobject(2);
149 if (v != NULL) {
150 settupleitem(v, 0, newfloatobject(x));
151 settupleitem(v, 1, newintobject((long)i));
152 if (err_occurred()) {
153 DECREF(v);
154 v = NULL;
155 }
156 }
157 return v;
158}
159
160static object *
161math_ldexp(self, args)
162 object *self;
163 object *args;
164{
165 double x, y;
166 /* Cheat -- allow float as second argument */
167 if (!get2doublearg(args, &x, &y))
168 return NULL;
169 errno = 0;
170 x = ldexp(x, (int)y);
Guido van Rossum8832b621991-12-16 15:44:24 +0000171 CHECK(x);
Guido van Rossumd18ad581991-10-24 14:57:21 +0000172 if (errno != 0)
Guido van Rossum8832b621991-12-16 15:44:24 +0000173 return math_error();
Guido van Rossumd18ad581991-10-24 14:57:21 +0000174 else
175 return newfloatobject(x);
176}
177
178static object *
179math_modf(self, args)
180 object *self;
181 object *args;
182{
183 object *v;
184 double x, y;
185 if (!getdoublearg(args, &x))
186 return NULL;
187 errno = 0;
188 x = modf(x, &y);
Guido van Rossum8832b621991-12-16 15:44:24 +0000189 CHECK(x);
Guido van Rossumd18ad581991-10-24 14:57:21 +0000190 if (errno != 0)
Guido van Rossum8832b621991-12-16 15:44:24 +0000191 return math_error();
Guido van Rossumd18ad581991-10-24 14:57:21 +0000192 v = newtupleobject(2);
193 if (v != NULL) {
194 settupleitem(v, 0, newfloatobject(x));
195 settupleitem(v, 1, newfloatobject(y));
196 if (err_occurred()) {
197 DECREF(v);
198 v = NULL;
199 }
200 }
201 return v;
202}
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000203
204static struct methodlist math_methods[] = {
205 {"acos", math_acos},
206 {"asin", math_asin},
207 {"atan", math_atan},
208 {"atan2", math_atan2},
209 {"ceil", math_ceil},
210 {"cos", math_cos},
211 {"cosh", math_cosh},
212 {"exp", math_exp},
213 {"fabs", math_fabs},
214 {"floor", math_floor},
Guido van Rossumd18ad581991-10-24 14:57:21 +0000215#ifndef AMOEBA
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000216 {"fmod", math_fmod},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000217#endif
Guido van Rossumd18ad581991-10-24 14:57:21 +0000218 {"frexp", math_frexp},
219 {"ldexp", math_ldexp},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000220 {"log", math_log},
221 {"log10", math_log10},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000222 {"modf", math_modf},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000223 {"pow", math_pow},
224 {"sin", math_sin},
225 {"sinh", math_sinh},
226 {"sqrt", math_sqrt},
227 {"tan", math_tan},
228 {"tanh", math_tanh},
229 {NULL, NULL} /* sentinel */
230};
231
232void
233initmath()
234{
235 object *m, *d, *v;
Guido van Rossum738d4dd1990-10-26 14:59:30 +0000236
237 m = initmodule("math", math_methods);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000238 d = getmoduledict(m);
Guido van Rossumeb38d241990-11-18 17:36:45 +0000239 dictinsert(d, "pi", v = newfloatobject(atan(1.0) * 4.0));
240 DECREF(v);
241 dictinsert(d, "e", v = newfloatobject(exp(1.0)));
242 DECREF(v);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000243}