blob: 4e704bfa95338666eab0ccf1f9e06a42dc64a738 [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 Rossumb9418681995-01-12 11:28:16 +000036#ifndef __STDC__
37extern double fmod PROTO((double, double));
38extern double frexp PROTO((double, int *));
39extern double ldexp PROTO((double, int));
40extern double modf PROTO((double, double *));
41#endif
42
Guido van Rossum9caac911995-06-14 22:17:37 +000043#if defined(HAVE_HYPOT) && !defined(NeXT)
Guido van Rossumb9418681995-01-12 11:28:16 +000044extern double hypot PROTO((double, double));
Guido van Rossum32062681996-01-12 01:39:11 +000045#else
46double hypot(x,y)
47 double x;
48 double y;
49{
50 double yx;
51
52 x = fabs(x);
53 y = fabs(y);
54 if (x < y) {
55 double temp = x;
56 x = y;
57 y = temp;
58 }
59 if (x == 0.)
60 return 0.;
61 else {
62 yx = y/x;
63 return x*sqrt(1.+yx*yx);
64 }
65}
Guido van Rossumb9418681995-01-12 11:28:16 +000066#endif
67
Guido van Rossum9575a441993-04-07 14:06:14 +000068#ifdef i860
69/* Cray APP has bogus definition of HUGE_VAL in <math.h> */
70#undef HUGE_VAL
71#endif
72
Guido van Rossum8832b621991-12-16 15:44:24 +000073#ifdef HUGE_VAL
74#define CHECK(x) if (errno != 0) ; \
75 else if (-HUGE_VAL <= (x) && (x) <= HUGE_VAL) ; \
76 else errno = ERANGE
77#else
78#define CHECK(x) /* Don't know how to check */
79#endif
80
81static object *
82math_error()
83{
84 if (errno == EDOM)
85 err_setstr(ValueError, "math domain error");
86 else if (errno == ERANGE)
87 err_setstr(OverflowError, "math range error");
88 else
Guido van Rossum444db071992-02-26 15:26:56 +000089 err_errno(ValueError); /* Unexpected math error */
Guido van Rossum8832b621991-12-16 15:44:24 +000090 return NULL;
91}
92
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000093static object *
94math_1(args, func)
95 object *args;
96 double (*func) FPROTO((double));
97{
98 double x;
99 if (!getdoublearg(args, &x))
100 return NULL;
101 errno = 0;
102 x = (*func)(x);
Guido van Rossum8832b621991-12-16 15:44:24 +0000103 CHECK(x);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000104 if (errno != 0)
Guido van Rossum8832b621991-12-16 15:44:24 +0000105 return math_error();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000106 else
107 return newfloatobject(x);
108}
109
110static object *
111math_2(args, func)
112 object *args;
113 double (*func) FPROTO((double, double));
114{
115 double x, y;
116 if (!get2doublearg(args, &x, &y))
117 return NULL;
118 errno = 0;
119 x = (*func)(x, y);
Guido van Rossum8832b621991-12-16 15:44:24 +0000120 CHECK(x);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000121 if (errno != 0)
Guido van Rossum8832b621991-12-16 15:44:24 +0000122 return math_error();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000123 else
124 return newfloatobject(x);
125}
126
127#define FUNC1(stubname, func) \
128 static object * stubname(self, args) object *self, *args; { \
129 return math_1(args, func); \
130 }
131
132#define FUNC2(stubname, func) \
133 static object * stubname(self, args) object *self, *args; { \
134 return math_2(args, func); \
135 }
136
137FUNC1(math_acos, acos)
138FUNC1(math_asin, asin)
139FUNC1(math_atan, atan)
140FUNC2(math_atan2, atan2)
141FUNC1(math_ceil, ceil)
142FUNC1(math_cos, cos)
143FUNC1(math_cosh, cosh)
144FUNC1(math_exp, exp)
145FUNC1(math_fabs, fabs)
146FUNC1(math_floor, floor)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000147FUNC2(math_fmod, fmod)
Guido van Rossum411a8bd1994-10-20 22:00:28 +0000148FUNC2(math_hypot, hypot)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000149FUNC1(math_log, log)
150FUNC1(math_log10, log10)
Guido van Rossum1492c271991-07-27 21:38:43 +0000151#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 +0000152FUNC2(math_pow, power)
153#else
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000154FUNC2(math_pow, pow)
Guido van Rossum76f2f2e1991-06-24 22:23:10 +0000155#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000156FUNC1(math_sin, sin)
157FUNC1(math_sinh, sinh)
158FUNC1(math_sqrt, sqrt)
159FUNC1(math_tan, tan)
160FUNC1(math_tanh, tanh)
161
Guido van Rossumb6775db1994-08-01 11:34:53 +0000162
Guido van Rossumd18ad581991-10-24 14:57:21 +0000163static object *
164math_frexp(self, args)
165 object *self;
166 object *args;
167{
Guido van Rossumd18ad581991-10-24 14:57:21 +0000168 double x;
169 int i;
170 if (!getdoublearg(args, &x))
171 return NULL;
172 errno = 0;
173 x = frexp(x, &i);
Guido van Rossum8832b621991-12-16 15:44:24 +0000174 CHECK(x);
Guido van Rossumd18ad581991-10-24 14:57:21 +0000175 if (errno != 0)
Guido van Rossum8832b621991-12-16 15:44:24 +0000176 return math_error();
Guido van Rossume5372401993-03-16 12:15:04 +0000177 return mkvalue("(di)", x, i);
Guido van Rossumd18ad581991-10-24 14:57:21 +0000178}
179
180static object *
181math_ldexp(self, args)
182 object *self;
183 object *args;
184{
185 double x, y;
186 /* Cheat -- allow float as second argument */
187 if (!get2doublearg(args, &x, &y))
188 return NULL;
189 errno = 0;
190 x = ldexp(x, (int)y);
Guido van Rossum8832b621991-12-16 15:44:24 +0000191 CHECK(x);
Guido van Rossumd18ad581991-10-24 14:57:21 +0000192 if (errno != 0)
Guido van Rossum8832b621991-12-16 15:44:24 +0000193 return math_error();
Guido van Rossumd18ad581991-10-24 14:57:21 +0000194 else
195 return newfloatobject(x);
196}
197
198static object *
199math_modf(self, args)
200 object *self;
201 object *args;
202{
Guido van Rossumd18ad581991-10-24 14:57:21 +0000203 double x, y;
204 if (!getdoublearg(args, &x))
205 return NULL;
206 errno = 0;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000207#ifdef MPW /* MPW C modf expects pointer to extended as second argument */
208{
209 extended e;
210 x = modf(x, &e);
211 y = e;
212}
213#else
Guido van Rossumd18ad581991-10-24 14:57:21 +0000214 x = modf(x, &y);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000215#endif
Guido van Rossum8832b621991-12-16 15:44:24 +0000216 CHECK(x);
Guido van Rossumd18ad581991-10-24 14:57:21 +0000217 if (errno != 0)
Guido van Rossum8832b621991-12-16 15:44:24 +0000218 return math_error();
Guido van Rossume5372401993-03-16 12:15:04 +0000219 return mkvalue("(dd)", x, y);
Guido van Rossumd18ad581991-10-24 14:57:21 +0000220}
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000221
222static struct methodlist math_methods[] = {
223 {"acos", math_acos},
224 {"asin", math_asin},
225 {"atan", math_atan},
226 {"atan2", math_atan2},
227 {"ceil", math_ceil},
228 {"cos", math_cos},
229 {"cosh", math_cosh},
230 {"exp", math_exp},
231 {"fabs", math_fabs},
232 {"floor", math_floor},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000233 {"fmod", math_fmod},
Guido van Rossumd18ad581991-10-24 14:57:21 +0000234 {"frexp", math_frexp},
Guido van Rossum411a8bd1994-10-20 22:00:28 +0000235 {"hypot", math_hypot},
Guido van Rossumd18ad581991-10-24 14:57:21 +0000236 {"ldexp", math_ldexp},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000237 {"log", math_log},
238 {"log10", math_log10},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000239 {"modf", math_modf},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000240 {"pow", math_pow},
241 {"sin", math_sin},
242 {"sinh", math_sinh},
243 {"sqrt", math_sqrt},
244 {"tan", math_tan},
245 {"tanh", math_tanh},
246 {NULL, NULL} /* sentinel */
247};
248
249void
250initmath()
251{
252 object *m, *d, *v;
Guido van Rossum738d4dd1990-10-26 14:59:30 +0000253
254 m = initmodule("math", math_methods);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000255 d = getmoduledict(m);
Guido van Rossumeb38d241990-11-18 17:36:45 +0000256 dictinsert(d, "pi", v = newfloatobject(atan(1.0) * 4.0));
257 DECREF(v);
258 dictinsert(d, "e", v = newfloatobject(exp(1.0)));
259 DECREF(v);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000260}