blob: b1bb96821fd36d6e3fdbf6ae5e97dc89831e6962 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
Guido van Rossum6610ad91995-01-04 19:07:38 +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/* 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 Rossum03093a21994-09-28 15:51:32 +000050#ifdef HAVE_LIMITS_H
51#include <limits.h>
52#endif
53
54#ifndef LONG_MAX
55#define LONG_MAX 0X7FFFFFFFL
56#endif
57
58#ifndef LONG_MIN
59#define LONG_MIN (-LONG_MAX-1)
60#endif
61
Guido van Rossumb6775db1994-08-01 11:34:53 +000062#ifndef macintosh
Guido van Rossum6923e131990-11-02 17:50:43 +000063extern double fmod PROTO((double, double));
64extern double pow PROTO((double, double));
65#endif
66
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000067object *
68newfloatobject(fval)
69 double fval;
70{
71 /* For efficiency, this code is copied from newobject() */
72 register floatobject *op = (floatobject *) malloc(sizeof(floatobject));
Guido van Rossum2a9096b1990-10-21 22:15:08 +000073 if (op == NULL)
74 return err_nomem();
Guido van Rossum2a9096b1990-10-21 22:15:08 +000075 op->ob_type = &Floattype;
76 op->ob_fval = fval;
Sjoerd Mullendera9c3c221993-10-11 12:54:31 +000077 NEWREF(op);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000078 return (object *) op;
79}
80
Guido van Rossum234f9421993-06-17 12:35:49 +000081static void
Guido van Rossum3132a5a1992-03-27 17:28:44 +000082float_dealloc(op)
83 object *op;
84{
85 DEL(op);
86}
87
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000088double
89getfloatvalue(op)
90 object *op;
91{
Guido van Rossumb6775db1994-08-01 11:34:53 +000092 number_methods *nb;
93 floatobject *fo;
94 double val;
95
96 if (op && is_floatobject(op))
97 return GETFLOATVALUE((floatobject*) op);
98
99 if (op == NULL || (nb = op->ob_type->tp_as_number) == NULL ||
100 nb->nb_float == NULL) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000101 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000102 return -1;
103 }
Guido van Rossumb6775db1994-08-01 11:34:53 +0000104
105 fo = (floatobject*) (*nb->nb_float) (op);
106 if (fo == NULL)
107 return -1;
108 if (!is_floatobject(fo)) {
109 err_setstr(TypeError, "nb_float should return float object");
110 return -1;
111 }
112
113 val = GETFLOATVALUE(fo);
114 DECREF(fo);
115
116 return val;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000117}
118
119/* Methods */
120
Guido van Rossum27dec7e1991-06-04 19:42:53 +0000121void
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000122float_buf_repr(buf, v)
123 char *buf;
124 floatobject *v;
125{
126 register char *cp;
127 /* Subroutine for float_repr and float_print.
128 We want float numbers to be recognizable as such,
129 i.e., they should contain a decimal point or an exponent.
130 However, %g may print the number as an integer;
131 in such cases, we append ".0" to the string. */
132 sprintf(buf, "%.12g", v->ob_fval);
133 cp = buf;
134 if (*cp == '-')
135 cp++;
136 for (; *cp != '\0'; cp++) {
137 /* Any non-digit means it's not an integer;
138 this takes care of NAN and INF as well. */
139 if (!isdigit(*cp))
140 break;
141 }
142 if (*cp == '\0') {
143 *cp++ = '.';
144 *cp++ = '0';
145 *cp++ = '\0';
146 }
147}
148
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000149/* ARGSUSED */
Guido van Rossum90933611991-06-07 16:10:43 +0000150static int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000151float_print(v, fp, flags)
152 floatobject *v;
153 FILE *fp;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000154 int flags; /* Not used but required by interface */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000155{
156 char buf[100];
157 float_buf_repr(buf, v);
158 fputs(buf, fp);
Guido van Rossum90933611991-06-07 16:10:43 +0000159 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000160}
161
162static object *
163float_repr(v)
164 floatobject *v;
165{
166 char buf[100];
167 float_buf_repr(buf, v);
168 return newstringobject(buf);
169}
170
171static int
172float_compare(v, w)
173 floatobject *v, *w;
174{
175 double i = v->ob_fval;
176 double j = w->ob_fval;
177 return (i < j) ? -1 : (i > j) ? 1 : 0;
178}
179
Guido van Rossum9bfef441993-03-29 10:43:31 +0000180static long
181float_hash(v)
182 floatobject *v;
183{
184 double intpart, fractpart;
185 int expo;
186 long x;
187 /* This is designed so that Python numbers with the same
188 value hash to the same value, otherwise comparisons
189 of mapping keys will turn out weird */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000190
191#ifdef MPW /* MPW C modf expects pointer to extended as second argument */
192{
193 extended e;
194 fractpart = modf(v->ob_fval, &e);
195 intpart = e;
196}
197#else
Guido van Rossum9bfef441993-03-29 10:43:31 +0000198 fractpart = modf(v->ob_fval, &intpart);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000199#endif
200
Guido van Rossum9bfef441993-03-29 10:43:31 +0000201 if (fractpart == 0.0) {
202 if (intpart > 0x7fffffffL || -intpart > 0x7fffffffL) {
203 /* Convert to long int and use its hash... */
204 object *w = dnewlongobject(v->ob_fval);
205 if (w == NULL)
206 return -1;
207 x = hashobject(w);
208 DECREF(w);
209 return x;
210 }
211 x = (long)intpart;
212 }
213 else {
214 fractpart = frexp(fractpart, &expo);
Guido van Rossum6610ad91995-01-04 19:07:38 +0000215 fractpart = fractpart*2147483648.0; /* 2**31 */
Guido van Rossum9bfef441993-03-29 10:43:31 +0000216 x = (long) (intpart + fractpart) ^ expo; /* Rather arbitrary */
217 }
218 if (x == -1)
219 x = -2;
220 return x;
221}
222
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000223static object *
224float_add(v, w)
225 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000226 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000227{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000228 return newfloatobject(v->ob_fval + w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000229}
230
231static object *
232float_sub(v, w)
233 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000234 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000235{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000236 return newfloatobject(v->ob_fval - w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000237}
238
239static object *
240float_mul(v, w)
241 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000242 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000243{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000244 return newfloatobject(v->ob_fval * w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000245}
246
247static object *
248float_div(v, w)
249 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000250 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000251{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000252 if (w->ob_fval == 0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000253 err_setstr(ZeroDivisionError, "float division");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000254 return NULL;
255 }
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000256 return newfloatobject(v->ob_fval / w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000257}
258
259static object *
260float_rem(v, w)
261 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000262 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000263{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000264 double vx, wx;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000265 double /* div, */ mod;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000266 wx = w->ob_fval;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000267 if (wx == 0.0) {
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000268 err_setstr(ZeroDivisionError, "float modulo");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000269 return NULL;
270 }
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000271 vx = v->ob_fval;
272 mod = fmod(vx, wx);
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000273 /* div = (vx - mod) / wx; */
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000274 if (wx*mod < 0) {
275 mod += wx;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000276 /* div -= 1.0; */
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000277 }
278 return newfloatobject(mod);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000279}
280
281static object *
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000282float_divmod(v, w)
283 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000284 floatobject *w;
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000285{
Guido van Rossum15ecff41991-10-20 20:16:45 +0000286 double vx, wx;
287 double div, mod;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000288 wx = w->ob_fval;
Guido van Rossum15ecff41991-10-20 20:16:45 +0000289 if (wx == 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000290 err_setstr(ZeroDivisionError, "float divmod()");
Guido van Rossum15ecff41991-10-20 20:16:45 +0000291 return NULL;
292 }
293 vx = v->ob_fval;
294 mod = fmod(vx, wx);
295 div = (vx - mod) / wx;
296 if (wx*mod < 0) {
297 mod += wx;
298 div -= 1.0;
299 }
Guido van Rossume5372401993-03-16 12:15:04 +0000300 return mkvalue("(dd)", div, mod);
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000301}
302
303static object *
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000304float_pow(v, w, z)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000305 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000306 floatobject *w;
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000307 floatobject *z;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000308{
309 double iv, iw, ix;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000310 iv = v->ob_fval;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000311 iw = w->ob_fval;
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000312 /* XXX Doesn't handle overflows if z!=None yet; it may never do so :(
313 * The z parameter is really only going to be useful for integers and
314 * long integers. Maybe something clever with logarithms could be done.
315 * [AMK]
316 */
Guido van Rossum70d93461991-05-28 21:57:39 +0000317 /* Sort out special cases here instead of relying on pow() */
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000318 if (iw == 0.0) { /* x**0 is 1, even 0**0 */
319 if ((object *)z!=None) {
320 ix=fmod(1.0, z->ob_fval);
321 if (ix!=0 && z->ob_fval<0) ix+=z->ob_fval;
322 }
323 else ix=1.0;
324 return newfloatobject(ix);
325 }
Guido van Rossum70d93461991-05-28 21:57:39 +0000326 if (iv == 0.0) {
327 if (iw < 0.0) {
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000328 err_setstr(ValueError, "0.0 to a negative power");
Guido van Rossum70d93461991-05-28 21:57:39 +0000329 return NULL;
330 }
331 return newfloatobject(0.0);
332 }
333 if (iv < 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000334 err_setstr(ValueError, "negative float to float power");
Guido van Rossum70d93461991-05-28 21:57:39 +0000335 return NULL;
336 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000337 errno = 0;
338 ix = pow(iv, iw);
Guido van Rossum7fa52f81991-12-16 15:43:14 +0000339 CHECK(ix);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000340 if (errno != 0) {
341 /* XXX could it be another type of error? */
342 err_errno(OverflowError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000343 return NULL;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000344 }
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000345 if ((object *)z!=None) {
346 ix=fmod(ix, z->ob_fval); /* XXX To Be Rewritten */
347 if ( ix!=0 &&
348 ((iv<0 && z->ob_fval>0) || (iv>0 && z->ob_fval<0) )) {
349 ix+=z->ob_fval;
350 }
351 }
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000352 return newfloatobject(ix);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000353}
354
355static object *
356float_neg(v)
357 floatobject *v;
358{
359 return newfloatobject(-v->ob_fval);
360}
361
362static object *
363float_pos(v)
364 floatobject *v;
365{
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000366 INCREF(v);
367 return (object *)v;
368}
369
370static object *
371float_abs(v)
372 floatobject *v;
373{
374 if (v->ob_fval < 0)
375 return float_neg(v);
376 else
377 return float_pos(v);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000378}
379
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000380static int
381float_nonzero(v)
382 floatobject *v;
383{
384 return v->ob_fval != 0.0;
385}
386
Guido van Rossum234f9421993-06-17 12:35:49 +0000387static int
Guido van Rossume6eefc21992-08-14 12:06:52 +0000388float_coerce(pv, pw)
389 object **pv;
390 object **pw;
391{
392 if (is_intobject(*pw)) {
393 long x = getintvalue(*pw);
394 *pw = newfloatobject((double)x);
395 INCREF(*pv);
396 return 0;
397 }
398 else if (is_longobject(*pw)) {
399 *pw = newfloatobject(dgetlongvalue(*pw));
400 INCREF(*pv);
401 return 0;
402 }
403 return 1; /* Can't do it */
404}
405
Guido van Rossum1899c2e1992-09-12 11:09:23 +0000406static object *
407float_int(v)
408 object *v;
409{
410 double x = getfloatvalue(v);
Guido van Rossum03093a21994-09-28 15:51:32 +0000411 if (x < 0 ? (x = ceil(x)) < (double)LONG_MIN
412 : (x = floor(x)) > (double)LONG_MAX) {
413 err_setstr(OverflowError, "float to large to convert");
414 return NULL;
415 }
Guido van Rossum1899c2e1992-09-12 11:09:23 +0000416 return newintobject((long)x);
417}
418
419static object *
420float_long(v)
421 object *v;
422{
423 double x = getfloatvalue(v);
424 return dnewlongobject(x);
425}
426
427static object *
428float_float(v)
429 object *v;
430{
431 INCREF(v);
432 return v;
433}
434
435
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000436static number_methods float_as_number = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000437 (binaryfunc)float_add, /*nb_add*/
438 (binaryfunc)float_sub, /*nb_subtract*/
439 (binaryfunc)float_mul, /*nb_multiply*/
440 (binaryfunc)float_div, /*nb_divide*/
441 (binaryfunc)float_rem, /*nb_remainder*/
442 (binaryfunc)float_divmod, /*nb_divmod*/
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000443 (ternaryfunc)float_pow, /*nb_power*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000444 (unaryfunc)float_neg, /*nb_negative*/
445 (unaryfunc)float_pos, /*nb_positive*/
446 (unaryfunc)float_abs, /*nb_absolute*/
447 (inquiry)float_nonzero, /*nb_nonzero*/
Guido van Rossum27acb331991-10-24 14:55:28 +0000448 0, /*nb_invert*/
449 0, /*nb_lshift*/
450 0, /*nb_rshift*/
451 0, /*nb_and*/
452 0, /*nb_xor*/
453 0, /*nb_or*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000454 (coercion)float_coerce, /*nb_coerce*/
455 (unaryfunc)float_int, /*nb_int*/
456 (unaryfunc)float_long, /*nb_long*/
457 (unaryfunc)float_float, /*nb_float*/
Guido van Rossum1899c2e1992-09-12 11:09:23 +0000458 0, /*nb_oct*/
459 0, /*nb_hex*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000460};
461
462typeobject Floattype = {
463 OB_HEAD_INIT(&Typetype)
464 0,
465 "float",
466 sizeof(floatobject),
467 0,
Guido van Rossumb6775db1994-08-01 11:34:53 +0000468 (destructor)float_dealloc, /*tp_dealloc*/
469 (printfunc)float_print, /*tp_print*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000470 0, /*tp_getattr*/
471 0, /*tp_setattr*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000472 (cmpfunc)float_compare, /*tp_compare*/
473 (reprfunc)float_repr, /*tp_repr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000474 &float_as_number, /*tp_as_number*/
475 0, /*tp_as_sequence*/
476 0, /*tp_as_mapping*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000477 (hashfunc)float_hash, /*tp_hash*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000478};