blob: 1a1598c91e2b40118088270d89da52e9f00ef929 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
Guido van Rossumbab9d031992-04-05 14:26:55 +00002Copyright 1991, 1992 by Stichting Mathematisch Centrum, Amsterdam, The
Guido van Rossumf70e43a1991-02-19 12:39:46 +00003Netherlands.
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/* Float object implementation */
26
Guido van Rossum2a9096b1990-10-21 22:15:08 +000027/* XXX There should be overflow checks here, but it's hard to check
28 for any kind of float exception without losing portability. */
29
Guido van Rossum3f5da241990-12-20 15:06:42 +000030#include "allobjects.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000031
Guido van Rossumc211ee41990-12-20 23:06:26 +000032#include <errno.h>
33#ifndef errno
34extern int errno;
35#endif
36
Guido van Rossum3f5da241990-12-20 15:06:42 +000037#include <ctype.h>
38#include <math.h>
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000039
Guido van Rossum7fa52f81991-12-16 15:43:14 +000040#ifdef HUGE_VAL
41#define CHECK(x) if (errno != 0) ; \
42 else if (-HUGE_VAL <= (x) && (x) <= HUGE_VAL) ; \
43 else errno = ERANGE
44#else
45#define CHECK(x) /* Don't know how to check */
46#endif
47
Guido van Rossum6923e131990-11-02 17:50:43 +000048#ifndef THINK_C
49extern double fmod PROTO((double, double));
50extern double pow PROTO((double, double));
51#endif
52
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000053object *
54newfloatobject(fval)
55 double fval;
56{
57 /* For efficiency, this code is copied from newobject() */
58 register floatobject *op = (floatobject *) malloc(sizeof(floatobject));
Guido van Rossum2a9096b1990-10-21 22:15:08 +000059 if (op == NULL)
60 return err_nomem();
61 NEWREF(op);
62 op->ob_type = &Floattype;
63 op->ob_fval = fval;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000064 return (object *) op;
65}
66
Guido van Rossum3132a5a1992-03-27 17:28:44 +000067void
68float_dealloc(op)
69 object *op;
70{
71 DEL(op);
72}
73
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000074double
75getfloatvalue(op)
76 object *op;
77{
78 if (!is_floatobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000079 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000080 return -1;
81 }
82 else
83 return ((floatobject *)op) -> ob_fval;
84}
85
86/* Methods */
87
Guido van Rossum27dec7e1991-06-04 19:42:53 +000088void
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000089float_buf_repr(buf, v)
90 char *buf;
91 floatobject *v;
92{
93 register char *cp;
94 /* Subroutine for float_repr and float_print.
95 We want float numbers to be recognizable as such,
96 i.e., they should contain a decimal point or an exponent.
97 However, %g may print the number as an integer;
98 in such cases, we append ".0" to the string. */
99 sprintf(buf, "%.12g", v->ob_fval);
100 cp = buf;
101 if (*cp == '-')
102 cp++;
103 for (; *cp != '\0'; cp++) {
104 /* Any non-digit means it's not an integer;
105 this takes care of NAN and INF as well. */
106 if (!isdigit(*cp))
107 break;
108 }
109 if (*cp == '\0') {
110 *cp++ = '.';
111 *cp++ = '0';
112 *cp++ = '\0';
113 }
114}
115
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000116/* ARGSUSED */
Guido van Rossum90933611991-06-07 16:10:43 +0000117static int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000118float_print(v, fp, flags)
119 floatobject *v;
120 FILE *fp;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000121 int flags; /* Not used but required by interface */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000122{
123 char buf[100];
124 float_buf_repr(buf, v);
125 fputs(buf, fp);
Guido van Rossum90933611991-06-07 16:10:43 +0000126 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000127}
128
129static object *
130float_repr(v)
131 floatobject *v;
132{
133 char buf[100];
134 float_buf_repr(buf, v);
135 return newstringobject(buf);
136}
137
138static int
139float_compare(v, w)
140 floatobject *v, *w;
141{
142 double i = v->ob_fval;
143 double j = w->ob_fval;
144 return (i < j) ? -1 : (i > j) ? 1 : 0;
145}
146
147static object *
148float_add(v, w)
149 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000150 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000151{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000152 return newfloatobject(v->ob_fval + w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000153}
154
155static object *
156float_sub(v, w)
157 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000158 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000159{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000160 return newfloatobject(v->ob_fval - w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000161}
162
163static object *
164float_mul(v, w)
165 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000166 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000167{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000168 return newfloatobject(v->ob_fval * w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000169}
170
171static object *
172float_div(v, w)
173 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000174 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000175{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000176 if (w->ob_fval == 0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000177 err_setstr(ZeroDivisionError, "float division");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000178 return NULL;
179 }
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000180 return newfloatobject(v->ob_fval / w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000181}
182
183static object *
184float_rem(v, w)
185 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000186 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000187{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000188 double vx, wx;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000189 double /* div, */ mod;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000190 wx = w->ob_fval;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000191 if (wx == 0.0) {
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000192 err_setstr(ZeroDivisionError, "float modulo");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000193 return NULL;
194 }
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000195 vx = v->ob_fval;
196 mod = fmod(vx, wx);
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000197 /* div = (vx - mod) / wx; */
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000198 if (wx*mod < 0) {
199 mod += wx;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000200 /* div -= 1.0; */
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000201 }
202 return newfloatobject(mod);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000203}
204
205static object *
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000206float_divmod(v, w)
207 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000208 floatobject *w;
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000209{
Guido van Rossum15ecff41991-10-20 20:16:45 +0000210 double vx, wx;
211 double div, mod;
212 object *t;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000213 wx = w->ob_fval;
Guido van Rossum15ecff41991-10-20 20:16:45 +0000214 if (wx == 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000215 err_setstr(ZeroDivisionError, "float divmod()");
Guido van Rossum15ecff41991-10-20 20:16:45 +0000216 return NULL;
217 }
218 vx = v->ob_fval;
219 mod = fmod(vx, wx);
220 div = (vx - mod) / wx;
221 if (wx*mod < 0) {
222 mod += wx;
223 div -= 1.0;
224 }
225 t = newtupleobject(2);
226 if (t != NULL) {
227 settupleitem(t, 0, newfloatobject(div));
228 settupleitem(t, 1, newfloatobject(mod));
229 if (err_occurred()) {
230 DECREF(t);
231 t = NULL;
232 }
233 }
234 return t;
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000235}
236
237static object *
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000238float_pow(v, w)
239 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000240 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000241{
242 double iv, iw, ix;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000243 iv = v->ob_fval;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000244 iw = w->ob_fval;
Guido van Rossum70d93461991-05-28 21:57:39 +0000245 /* Sort out special cases here instead of relying on pow() */
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000246 if (iw == 0.0)
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000247 return newfloatobject(1.0); /* x**0 is 1, even 0**0 */
Guido van Rossum70d93461991-05-28 21:57:39 +0000248 if (iv == 0.0) {
249 if (iw < 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000250 err_setstr(ValueError, "0.0 to the negative power");
Guido van Rossum70d93461991-05-28 21:57:39 +0000251 return NULL;
252 }
253 return newfloatobject(0.0);
254 }
255 if (iv < 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000256 err_setstr(ValueError, "negative float to float power");
Guido van Rossum70d93461991-05-28 21:57:39 +0000257 return NULL;
258 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000259 errno = 0;
260 ix = pow(iv, iw);
Guido van Rossum7fa52f81991-12-16 15:43:14 +0000261 CHECK(ix);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000262 if (errno != 0) {
263 /* XXX could it be another type of error? */
264 err_errno(OverflowError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000265 return NULL;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000266 }
267 return newfloatobject(ix);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000268}
269
270static object *
271float_neg(v)
272 floatobject *v;
273{
274 return newfloatobject(-v->ob_fval);
275}
276
277static object *
278float_pos(v)
279 floatobject *v;
280{
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000281 INCREF(v);
282 return (object *)v;
283}
284
285static object *
286float_abs(v)
287 floatobject *v;
288{
289 if (v->ob_fval < 0)
290 return float_neg(v);
291 else
292 return float_pos(v);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000293}
294
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000295static int
296float_nonzero(v)
297 floatobject *v;
298{
299 return v->ob_fval != 0.0;
300}
301
Guido van Rossume6eefc21992-08-14 12:06:52 +0000302int
303float_coerce(pv, pw)
304 object **pv;
305 object **pw;
306{
307 if (is_intobject(*pw)) {
308 long x = getintvalue(*pw);
309 *pw = newfloatobject((double)x);
310 INCREF(*pv);
311 return 0;
312 }
313 else if (is_longobject(*pw)) {
314 *pw = newfloatobject(dgetlongvalue(*pw));
315 INCREF(*pv);
316 return 0;
317 }
318 return 1; /* Can't do it */
319}
320
Guido van Rossum1899c2e1992-09-12 11:09:23 +0000321static object *
322float_int(v)
323 object *v;
324{
325 double x = getfloatvalue(v);
326 /* XXX should check for overflow */
327 /* XXX should define how we round */
328 return newintobject((long)x);
329}
330
331static object *
332float_long(v)
333 object *v;
334{
335 double x = getfloatvalue(v);
336 return dnewlongobject(x);
337}
338
339static object *
340float_float(v)
341 object *v;
342{
343 INCREF(v);
344 return v;
345}
346
347
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000348static number_methods float_as_number = {
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000349 float_add, /*nb_add*/
350 float_sub, /*nb_subtract*/
351 float_mul, /*nb_multiply*/
352 float_div, /*nb_divide*/
353 float_rem, /*nb_remainder*/
354 float_divmod, /*nb_divmod*/
355 float_pow, /*nb_power*/
356 float_neg, /*nb_negative*/
357 float_pos, /*nb_positive*/
358 float_abs, /*nb_absolute*/
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000359 float_nonzero, /*nb_nonzero*/
Guido van Rossum27acb331991-10-24 14:55:28 +0000360 0, /*nb_invert*/
361 0, /*nb_lshift*/
362 0, /*nb_rshift*/
363 0, /*nb_and*/
364 0, /*nb_xor*/
365 0, /*nb_or*/
Guido van Rossume6eefc21992-08-14 12:06:52 +0000366 float_coerce, /*nb_coerce*/
Guido van Rossum1899c2e1992-09-12 11:09:23 +0000367 float_int, /*nb_int*/
368 float_long, /*nb_long*/
369 float_float, /*nb_float*/
370 0, /*nb_oct*/
371 0, /*nb_hex*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000372};
373
374typeobject Floattype = {
375 OB_HEAD_INIT(&Typetype)
376 0,
377 "float",
378 sizeof(floatobject),
379 0,
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000380 float_dealloc, /*tp_dealloc*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000381 float_print, /*tp_print*/
382 0, /*tp_getattr*/
383 0, /*tp_setattr*/
384 float_compare, /*tp_compare*/
385 float_repr, /*tp_repr*/
386 &float_as_number, /*tp_as_number*/
387 0, /*tp_as_sequence*/
388 0, /*tp_as_mapping*/
389};