blob: 6a95ebf82f986f4ca76785c49ebc458d9cfca180 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
Guido van Rossume5372401993-03-16 12:15:04 +00002Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3Amsterdam, The 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/* 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 Rossume5372401993-03-16 12:15:04 +000031#include "modsupport.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000032
Guido van Rossumc211ee41990-12-20 23:06:26 +000033#include <errno.h>
34#ifndef errno
35extern int errno;
36#endif
37
Guido van Rossum3f5da241990-12-20 15:06:42 +000038#include <ctype.h>
39#include <math.h>
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000040
Guido van Rossum9575a441993-04-07 14:06:14 +000041#ifdef i860
42/* Cray APP has bogus definition of HUGE_VAL in <math.h> */
43#undef HUGE_VAL
44#endif
45
Guido van Rossum7fa52f81991-12-16 15:43:14 +000046#ifdef HUGE_VAL
47#define CHECK(x) if (errno != 0) ; \
48 else if (-HUGE_VAL <= (x) && (x) <= HUGE_VAL) ; \
49 else errno = ERANGE
50#else
51#define CHECK(x) /* Don't know how to check */
52#endif
53
Guido van Rossum6923e131990-11-02 17:50:43 +000054#ifndef THINK_C
55extern double fmod PROTO((double, double));
56extern double pow PROTO((double, double));
57#endif
58
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000059object *
60newfloatobject(fval)
61 double fval;
62{
63 /* For efficiency, this code is copied from newobject() */
64 register floatobject *op = (floatobject *) malloc(sizeof(floatobject));
Guido van Rossum2a9096b1990-10-21 22:15:08 +000065 if (op == NULL)
66 return err_nomem();
67 NEWREF(op);
68 op->ob_type = &Floattype;
69 op->ob_fval = fval;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000070 return (object *) op;
71}
72
Guido van Rossum3132a5a1992-03-27 17:28:44 +000073void
74float_dealloc(op)
75 object *op;
76{
77 DEL(op);
78}
79
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000080double
81getfloatvalue(op)
82 object *op;
83{
84 if (!is_floatobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000085 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000086 return -1;
87 }
88 else
89 return ((floatobject *)op) -> ob_fval;
90}
91
92/* Methods */
93
Guido van Rossum27dec7e1991-06-04 19:42:53 +000094void
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000095float_buf_repr(buf, v)
96 char *buf;
97 floatobject *v;
98{
99 register char *cp;
100 /* Subroutine for float_repr and float_print.
101 We want float numbers to be recognizable as such,
102 i.e., they should contain a decimal point or an exponent.
103 However, %g may print the number as an integer;
104 in such cases, we append ".0" to the string. */
105 sprintf(buf, "%.12g", v->ob_fval);
106 cp = buf;
107 if (*cp == '-')
108 cp++;
109 for (; *cp != '\0'; cp++) {
110 /* Any non-digit means it's not an integer;
111 this takes care of NAN and INF as well. */
112 if (!isdigit(*cp))
113 break;
114 }
115 if (*cp == '\0') {
116 *cp++ = '.';
117 *cp++ = '0';
118 *cp++ = '\0';
119 }
120}
121
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000122/* ARGSUSED */
Guido van Rossum90933611991-06-07 16:10:43 +0000123static int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000124float_print(v, fp, flags)
125 floatobject *v;
126 FILE *fp;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000127 int flags; /* Not used but required by interface */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000128{
129 char buf[100];
130 float_buf_repr(buf, v);
131 fputs(buf, fp);
Guido van Rossum90933611991-06-07 16:10:43 +0000132 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000133}
134
135static object *
136float_repr(v)
137 floatobject *v;
138{
139 char buf[100];
140 float_buf_repr(buf, v);
141 return newstringobject(buf);
142}
143
144static int
145float_compare(v, w)
146 floatobject *v, *w;
147{
148 double i = v->ob_fval;
149 double j = w->ob_fval;
150 return (i < j) ? -1 : (i > j) ? 1 : 0;
151}
152
Guido van Rossum9bfef441993-03-29 10:43:31 +0000153static long
154float_hash(v)
155 floatobject *v;
156{
157 double intpart, fractpart;
158 int expo;
159 long x;
160 /* This is designed so that Python numbers with the same
161 value hash to the same value, otherwise comparisons
162 of mapping keys will turn out weird */
163 fractpart = modf(v->ob_fval, &intpart);
164 if (fractpart == 0.0) {
165 if (intpart > 0x7fffffffL || -intpart > 0x7fffffffL) {
166 /* Convert to long int and use its hash... */
167 object *w = dnewlongobject(v->ob_fval);
168 if (w == NULL)
169 return -1;
170 x = hashobject(w);
171 DECREF(w);
172 return x;
173 }
174 x = (long)intpart;
175 }
176 else {
177 fractpart = frexp(fractpart, &expo);
Guido van Rossum9575a441993-04-07 14:06:14 +0000178 fractpart = fractpart*4294967296.0; /* 2**32 */
Guido van Rossum9bfef441993-03-29 10:43:31 +0000179 x = (long) (intpart + fractpart) ^ expo; /* Rather arbitrary */
180 }
181 if (x == -1)
182 x = -2;
183 return x;
184}
185
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000186static object *
187float_add(v, w)
188 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000189 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000190{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000191 return newfloatobject(v->ob_fval + w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000192}
193
194static object *
195float_sub(v, w)
196 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000197 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000198{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000199 return newfloatobject(v->ob_fval - w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000200}
201
202static object *
203float_mul(v, w)
204 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000205 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000206{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000207 return newfloatobject(v->ob_fval * w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000208}
209
210static object *
211float_div(v, w)
212 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000213 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000214{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000215 if (w->ob_fval == 0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000216 err_setstr(ZeroDivisionError, "float division");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000217 return NULL;
218 }
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000219 return newfloatobject(v->ob_fval / w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000220}
221
222static object *
223float_rem(v, w)
224 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000225 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000226{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000227 double vx, wx;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000228 double /* div, */ mod;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000229 wx = w->ob_fval;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000230 if (wx == 0.0) {
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000231 err_setstr(ZeroDivisionError, "float modulo");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000232 return NULL;
233 }
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000234 vx = v->ob_fval;
235 mod = fmod(vx, wx);
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000236 /* div = (vx - mod) / wx; */
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000237 if (wx*mod < 0) {
238 mod += wx;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000239 /* div -= 1.0; */
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000240 }
241 return newfloatobject(mod);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000242}
243
244static object *
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000245float_divmod(v, w)
246 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000247 floatobject *w;
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000248{
Guido van Rossum15ecff41991-10-20 20:16:45 +0000249 double vx, wx;
250 double div, mod;
251 object *t;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000252 wx = w->ob_fval;
Guido van Rossum15ecff41991-10-20 20:16:45 +0000253 if (wx == 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000254 err_setstr(ZeroDivisionError, "float divmod()");
Guido van Rossum15ecff41991-10-20 20:16:45 +0000255 return NULL;
256 }
257 vx = v->ob_fval;
258 mod = fmod(vx, wx);
259 div = (vx - mod) / wx;
260 if (wx*mod < 0) {
261 mod += wx;
262 div -= 1.0;
263 }
Guido van Rossume5372401993-03-16 12:15:04 +0000264 return mkvalue("(dd)", div, mod);
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000265}
266
267static object *
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000268float_pow(v, w)
269 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000270 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000271{
272 double iv, iw, ix;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000273 iv = v->ob_fval;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000274 iw = w->ob_fval;
Guido van Rossum70d93461991-05-28 21:57:39 +0000275 /* Sort out special cases here instead of relying on pow() */
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000276 if (iw == 0.0)
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000277 return newfloatobject(1.0); /* x**0 is 1, even 0**0 */
Guido van Rossum70d93461991-05-28 21:57:39 +0000278 if (iv == 0.0) {
279 if (iw < 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000280 err_setstr(ValueError, "0.0 to the negative power");
Guido van Rossum70d93461991-05-28 21:57:39 +0000281 return NULL;
282 }
283 return newfloatobject(0.0);
284 }
285 if (iv < 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000286 err_setstr(ValueError, "negative float to float power");
Guido van Rossum70d93461991-05-28 21:57:39 +0000287 return NULL;
288 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000289 errno = 0;
290 ix = pow(iv, iw);
Guido van Rossum7fa52f81991-12-16 15:43:14 +0000291 CHECK(ix);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000292 if (errno != 0) {
293 /* XXX could it be another type of error? */
294 err_errno(OverflowError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000295 return NULL;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000296 }
297 return newfloatobject(ix);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000298}
299
300static object *
301float_neg(v)
302 floatobject *v;
303{
304 return newfloatobject(-v->ob_fval);
305}
306
307static object *
308float_pos(v)
309 floatobject *v;
310{
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000311 INCREF(v);
312 return (object *)v;
313}
314
315static object *
316float_abs(v)
317 floatobject *v;
318{
319 if (v->ob_fval < 0)
320 return float_neg(v);
321 else
322 return float_pos(v);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000323}
324
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000325static int
326float_nonzero(v)
327 floatobject *v;
328{
329 return v->ob_fval != 0.0;
330}
331
Guido van Rossume6eefc21992-08-14 12:06:52 +0000332int
333float_coerce(pv, pw)
334 object **pv;
335 object **pw;
336{
337 if (is_intobject(*pw)) {
338 long x = getintvalue(*pw);
339 *pw = newfloatobject((double)x);
340 INCREF(*pv);
341 return 0;
342 }
343 else if (is_longobject(*pw)) {
344 *pw = newfloatobject(dgetlongvalue(*pw));
345 INCREF(*pv);
346 return 0;
347 }
348 return 1; /* Can't do it */
349}
350
Guido van Rossum1899c2e1992-09-12 11:09:23 +0000351static object *
352float_int(v)
353 object *v;
354{
355 double x = getfloatvalue(v);
356 /* XXX should check for overflow */
357 /* XXX should define how we round */
358 return newintobject((long)x);
359}
360
361static object *
362float_long(v)
363 object *v;
364{
365 double x = getfloatvalue(v);
366 return dnewlongobject(x);
367}
368
369static object *
370float_float(v)
371 object *v;
372{
373 INCREF(v);
374 return v;
375}
376
377
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000378static number_methods float_as_number = {
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000379 float_add, /*nb_add*/
380 float_sub, /*nb_subtract*/
381 float_mul, /*nb_multiply*/
382 float_div, /*nb_divide*/
383 float_rem, /*nb_remainder*/
384 float_divmod, /*nb_divmod*/
385 float_pow, /*nb_power*/
386 float_neg, /*nb_negative*/
387 float_pos, /*nb_positive*/
388 float_abs, /*nb_absolute*/
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000389 float_nonzero, /*nb_nonzero*/
Guido van Rossum27acb331991-10-24 14:55:28 +0000390 0, /*nb_invert*/
391 0, /*nb_lshift*/
392 0, /*nb_rshift*/
393 0, /*nb_and*/
394 0, /*nb_xor*/
395 0, /*nb_or*/
Guido van Rossume6eefc21992-08-14 12:06:52 +0000396 float_coerce, /*nb_coerce*/
Guido van Rossum1899c2e1992-09-12 11:09:23 +0000397 float_int, /*nb_int*/
398 float_long, /*nb_long*/
399 float_float, /*nb_float*/
400 0, /*nb_oct*/
401 0, /*nb_hex*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000402};
403
404typeobject Floattype = {
405 OB_HEAD_INIT(&Typetype)
406 0,
407 "float",
408 sizeof(floatobject),
409 0,
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000410 float_dealloc, /*tp_dealloc*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000411 float_print, /*tp_print*/
412 0, /*tp_getattr*/
413 0, /*tp_setattr*/
414 float_compare, /*tp_compare*/
415 float_repr, /*tp_repr*/
416 &float_as_number, /*tp_as_number*/
417 0, /*tp_as_sequence*/
418 0, /*tp_as_mapping*/
Guido van Rossum9bfef441993-03-29 10:43:31 +0000419 float_hash, /*tp_hash */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000420};