blob: d3a2c771b2a23a0781a1b74ea9734a7fde92d18f [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>
Guido van Rossum3f5da241990-12-20 15:06:42 +000034#include <ctype.h>
35#include <math.h>
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000036
Guido van Rossum9575a441993-04-07 14:06:14 +000037#ifdef i860
38/* Cray APP has bogus definition of HUGE_VAL in <math.h> */
39#undef HUGE_VAL
40#endif
41
Guido van Rossum7fa52f81991-12-16 15:43:14 +000042#ifdef HUGE_VAL
43#define CHECK(x) if (errno != 0) ; \
44 else if (-HUGE_VAL <= (x) && (x) <= HUGE_VAL) ; \
45 else errno = ERANGE
46#else
47#define CHECK(x) /* Don't know how to check */
48#endif
49
Guido van Rossum6923e131990-11-02 17:50:43 +000050#ifndef THINK_C
51extern double fmod PROTO((double, double));
52extern double pow PROTO((double, double));
53#endif
54
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000055object *
56newfloatobject(fval)
57 double fval;
58{
59 /* For efficiency, this code is copied from newobject() */
60 register floatobject *op = (floatobject *) malloc(sizeof(floatobject));
Guido van Rossum2a9096b1990-10-21 22:15:08 +000061 if (op == NULL)
62 return err_nomem();
Guido van Rossum2a9096b1990-10-21 22:15:08 +000063 op->ob_type = &Floattype;
64 op->ob_fval = fval;
Sjoerd Mullendera9c3c221993-10-11 12:54:31 +000065 NEWREF(op);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000066 return (object *) op;
67}
68
Guido van Rossum234f9421993-06-17 12:35:49 +000069static void
Guido van Rossum3132a5a1992-03-27 17:28:44 +000070float_dealloc(op)
71 object *op;
72{
73 DEL(op);
74}
75
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000076double
77getfloatvalue(op)
78 object *op;
79{
80 if (!is_floatobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000081 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000082 return -1;
83 }
84 else
85 return ((floatobject *)op) -> ob_fval;
86}
87
88/* Methods */
89
Guido van Rossum27dec7e1991-06-04 19:42:53 +000090void
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000091float_buf_repr(buf, v)
92 char *buf;
93 floatobject *v;
94{
95 register char *cp;
96 /* Subroutine for float_repr and float_print.
97 We want float numbers to be recognizable as such,
98 i.e., they should contain a decimal point or an exponent.
99 However, %g may print the number as an integer;
100 in such cases, we append ".0" to the string. */
101 sprintf(buf, "%.12g", v->ob_fval);
102 cp = buf;
103 if (*cp == '-')
104 cp++;
105 for (; *cp != '\0'; cp++) {
106 /* Any non-digit means it's not an integer;
107 this takes care of NAN and INF as well. */
108 if (!isdigit(*cp))
109 break;
110 }
111 if (*cp == '\0') {
112 *cp++ = '.';
113 *cp++ = '0';
114 *cp++ = '\0';
115 }
116}
117
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000118/* ARGSUSED */
Guido van Rossum90933611991-06-07 16:10:43 +0000119static int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000120float_print(v, fp, flags)
121 floatobject *v;
122 FILE *fp;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000123 int flags; /* Not used but required by interface */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000124{
125 char buf[100];
126 float_buf_repr(buf, v);
127 fputs(buf, fp);
Guido van Rossum90933611991-06-07 16:10:43 +0000128 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000129}
130
131static object *
132float_repr(v)
133 floatobject *v;
134{
135 char buf[100];
136 float_buf_repr(buf, v);
137 return newstringobject(buf);
138}
139
140static int
141float_compare(v, w)
142 floatobject *v, *w;
143{
144 double i = v->ob_fval;
145 double j = w->ob_fval;
146 return (i < j) ? -1 : (i > j) ? 1 : 0;
147}
148
Guido van Rossum9bfef441993-03-29 10:43:31 +0000149static long
150float_hash(v)
151 floatobject *v;
152{
153 double intpart, fractpart;
154 int expo;
155 long x;
156 /* This is designed so that Python numbers with the same
157 value hash to the same value, otherwise comparisons
158 of mapping keys will turn out weird */
159 fractpart = modf(v->ob_fval, &intpart);
160 if (fractpart == 0.0) {
161 if (intpart > 0x7fffffffL || -intpart > 0x7fffffffL) {
162 /* Convert to long int and use its hash... */
163 object *w = dnewlongobject(v->ob_fval);
164 if (w == NULL)
165 return -1;
166 x = hashobject(w);
167 DECREF(w);
168 return x;
169 }
170 x = (long)intpart;
171 }
172 else {
173 fractpart = frexp(fractpart, &expo);
Guido van Rossum9575a441993-04-07 14:06:14 +0000174 fractpart = fractpart*4294967296.0; /* 2**32 */
Guido van Rossum9bfef441993-03-29 10:43:31 +0000175 x = (long) (intpart + fractpart) ^ expo; /* Rather arbitrary */
176 }
177 if (x == -1)
178 x = -2;
179 return x;
180}
181
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000182static object *
183float_add(v, w)
184 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000185 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000186{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000187 return newfloatobject(v->ob_fval + w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000188}
189
190static object *
191float_sub(v, w)
192 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000193 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000194{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000195 return newfloatobject(v->ob_fval - w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000196}
197
198static object *
199float_mul(v, w)
200 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000201 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000202{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000203 return newfloatobject(v->ob_fval * w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000204}
205
206static object *
207float_div(v, w)
208 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000209 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000210{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000211 if (w->ob_fval == 0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000212 err_setstr(ZeroDivisionError, "float division");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000213 return NULL;
214 }
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000215 return newfloatobject(v->ob_fval / w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000216}
217
218static object *
219float_rem(v, w)
220 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000221 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000222{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000223 double vx, wx;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000224 double /* div, */ mod;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000225 wx = w->ob_fval;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000226 if (wx == 0.0) {
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000227 err_setstr(ZeroDivisionError, "float modulo");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000228 return NULL;
229 }
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000230 vx = v->ob_fval;
231 mod = fmod(vx, wx);
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000232 /* div = (vx - mod) / wx; */
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000233 if (wx*mod < 0) {
234 mod += wx;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000235 /* div -= 1.0; */
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000236 }
237 return newfloatobject(mod);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000238}
239
240static object *
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000241float_divmod(v, w)
242 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000243 floatobject *w;
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000244{
Guido van Rossum15ecff41991-10-20 20:16:45 +0000245 double vx, wx;
246 double div, mod;
247 object *t;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000248 wx = w->ob_fval;
Guido van Rossum15ecff41991-10-20 20:16:45 +0000249 if (wx == 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000250 err_setstr(ZeroDivisionError, "float divmod()");
Guido van Rossum15ecff41991-10-20 20:16:45 +0000251 return NULL;
252 }
253 vx = v->ob_fval;
254 mod = fmod(vx, wx);
255 div = (vx - mod) / wx;
256 if (wx*mod < 0) {
257 mod += wx;
258 div -= 1.0;
259 }
Guido van Rossume5372401993-03-16 12:15:04 +0000260 return mkvalue("(dd)", div, mod);
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000261}
262
263static object *
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000264float_pow(v, w)
265 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000266 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000267{
268 double iv, iw, ix;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000269 iv = v->ob_fval;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000270 iw = w->ob_fval;
Guido van Rossum70d93461991-05-28 21:57:39 +0000271 /* Sort out special cases here instead of relying on pow() */
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000272 if (iw == 0.0)
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000273 return newfloatobject(1.0); /* x**0 is 1, even 0**0 */
Guido van Rossum70d93461991-05-28 21:57:39 +0000274 if (iv == 0.0) {
275 if (iw < 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000276 err_setstr(ValueError, "0.0 to the negative power");
Guido van Rossum70d93461991-05-28 21:57:39 +0000277 return NULL;
278 }
279 return newfloatobject(0.0);
280 }
281 if (iv < 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000282 err_setstr(ValueError, "negative float to float power");
Guido van Rossum70d93461991-05-28 21:57:39 +0000283 return NULL;
284 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000285 errno = 0;
286 ix = pow(iv, iw);
Guido van Rossum7fa52f81991-12-16 15:43:14 +0000287 CHECK(ix);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000288 if (errno != 0) {
289 /* XXX could it be another type of error? */
290 err_errno(OverflowError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000291 return NULL;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000292 }
293 return newfloatobject(ix);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000294}
295
296static object *
297float_neg(v)
298 floatobject *v;
299{
300 return newfloatobject(-v->ob_fval);
301}
302
303static object *
304float_pos(v)
305 floatobject *v;
306{
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000307 INCREF(v);
308 return (object *)v;
309}
310
311static object *
312float_abs(v)
313 floatobject *v;
314{
315 if (v->ob_fval < 0)
316 return float_neg(v);
317 else
318 return float_pos(v);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000319}
320
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000321static int
322float_nonzero(v)
323 floatobject *v;
324{
325 return v->ob_fval != 0.0;
326}
327
Guido van Rossum234f9421993-06-17 12:35:49 +0000328static int
Guido van Rossume6eefc21992-08-14 12:06:52 +0000329float_coerce(pv, pw)
330 object **pv;
331 object **pw;
332{
333 if (is_intobject(*pw)) {
334 long x = getintvalue(*pw);
335 *pw = newfloatobject((double)x);
336 INCREF(*pv);
337 return 0;
338 }
339 else if (is_longobject(*pw)) {
340 *pw = newfloatobject(dgetlongvalue(*pw));
341 INCREF(*pv);
342 return 0;
343 }
344 return 1; /* Can't do it */
345}
346
Guido van Rossum1899c2e1992-09-12 11:09:23 +0000347static object *
348float_int(v)
349 object *v;
350{
351 double x = getfloatvalue(v);
352 /* XXX should check for overflow */
353 /* XXX should define how we round */
354 return newintobject((long)x);
355}
356
357static object *
358float_long(v)
359 object *v;
360{
361 double x = getfloatvalue(v);
362 return dnewlongobject(x);
363}
364
365static object *
366float_float(v)
367 object *v;
368{
369 INCREF(v);
370 return v;
371}
372
373
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000374static number_methods float_as_number = {
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000375 float_add, /*nb_add*/
376 float_sub, /*nb_subtract*/
377 float_mul, /*nb_multiply*/
378 float_div, /*nb_divide*/
379 float_rem, /*nb_remainder*/
380 float_divmod, /*nb_divmod*/
381 float_pow, /*nb_power*/
382 float_neg, /*nb_negative*/
383 float_pos, /*nb_positive*/
384 float_abs, /*nb_absolute*/
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000385 float_nonzero, /*nb_nonzero*/
Guido van Rossum27acb331991-10-24 14:55:28 +0000386 0, /*nb_invert*/
387 0, /*nb_lshift*/
388 0, /*nb_rshift*/
389 0, /*nb_and*/
390 0, /*nb_xor*/
391 0, /*nb_or*/
Guido van Rossume6eefc21992-08-14 12:06:52 +0000392 float_coerce, /*nb_coerce*/
Guido van Rossum1899c2e1992-09-12 11:09:23 +0000393 float_int, /*nb_int*/
394 float_long, /*nb_long*/
395 float_float, /*nb_float*/
396 0, /*nb_oct*/
397 0, /*nb_hex*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000398};
399
400typeobject Floattype = {
401 OB_HEAD_INIT(&Typetype)
402 0,
403 "float",
404 sizeof(floatobject),
405 0,
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000406 float_dealloc, /*tp_dealloc*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000407 float_print, /*tp_print*/
408 0, /*tp_getattr*/
409 0, /*tp_setattr*/
410 float_compare, /*tp_compare*/
411 float_repr, /*tp_repr*/
412 &float_as_number, /*tp_as_number*/
413 0, /*tp_as_sequence*/
414 0, /*tp_as_mapping*/
Guido van Rossum9bfef441993-03-29 10:43:31 +0000415 float_hash, /*tp_hash */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000416};