blob: cbdcfd5fdfe58944e897027759e93e98ebf80fc4 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
Guido van Rossumb6775db1994-08-01 11:34:53 +00002Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Guido van Rossume5372401993-03-16 12:15:04 +00003Amsterdam, 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 Rossumb6775db1994-08-01 11:34:53 +000050#ifndef macintosh
Guido van Rossum6923e131990-11-02 17:50:43 +000051extern 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{
Guido van Rossumb6775db1994-08-01 11:34:53 +000080 number_methods *nb;
81 floatobject *fo;
82 double val;
83
84 if (op && is_floatobject(op))
85 return GETFLOATVALUE((floatobject*) op);
86
87 if (op == NULL || (nb = op->ob_type->tp_as_number) == NULL ||
88 nb->nb_float == NULL) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000089 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000090 return -1;
91 }
Guido van Rossumb6775db1994-08-01 11:34:53 +000092
93 fo = (floatobject*) (*nb->nb_float) (op);
94 if (fo == NULL)
95 return -1;
96 if (!is_floatobject(fo)) {
97 err_setstr(TypeError, "nb_float should return float object");
98 return -1;
99 }
100
101 val = GETFLOATVALUE(fo);
102 DECREF(fo);
103
104 return val;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000105}
106
107/* Methods */
108
Guido van Rossum27dec7e1991-06-04 19:42:53 +0000109void
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000110float_buf_repr(buf, v)
111 char *buf;
112 floatobject *v;
113{
114 register char *cp;
115 /* Subroutine for float_repr and float_print.
116 We want float numbers to be recognizable as such,
117 i.e., they should contain a decimal point or an exponent.
118 However, %g may print the number as an integer;
119 in such cases, we append ".0" to the string. */
120 sprintf(buf, "%.12g", v->ob_fval);
121 cp = buf;
122 if (*cp == '-')
123 cp++;
124 for (; *cp != '\0'; cp++) {
125 /* Any non-digit means it's not an integer;
126 this takes care of NAN and INF as well. */
127 if (!isdigit(*cp))
128 break;
129 }
130 if (*cp == '\0') {
131 *cp++ = '.';
132 *cp++ = '0';
133 *cp++ = '\0';
134 }
135}
136
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000137/* ARGSUSED */
Guido van Rossum90933611991-06-07 16:10:43 +0000138static int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000139float_print(v, fp, flags)
140 floatobject *v;
141 FILE *fp;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000142 int flags; /* Not used but required by interface */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000143{
144 char buf[100];
145 float_buf_repr(buf, v);
146 fputs(buf, fp);
Guido van Rossum90933611991-06-07 16:10:43 +0000147 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000148}
149
150static object *
151float_repr(v)
152 floatobject *v;
153{
154 char buf[100];
155 float_buf_repr(buf, v);
156 return newstringobject(buf);
157}
158
159static int
160float_compare(v, w)
161 floatobject *v, *w;
162{
163 double i = v->ob_fval;
164 double j = w->ob_fval;
165 return (i < j) ? -1 : (i > j) ? 1 : 0;
166}
167
Guido van Rossum9bfef441993-03-29 10:43:31 +0000168static long
169float_hash(v)
170 floatobject *v;
171{
172 double intpart, fractpart;
173 int expo;
174 long x;
175 /* This is designed so that Python numbers with the same
176 value hash to the same value, otherwise comparisons
177 of mapping keys will turn out weird */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000178
179#ifdef MPW /* MPW C modf expects pointer to extended as second argument */
180{
181 extended e;
182 fractpart = modf(v->ob_fval, &e);
183 intpart = e;
184}
185#else
Guido van Rossum9bfef441993-03-29 10:43:31 +0000186 fractpart = modf(v->ob_fval, &intpart);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000187#endif
188
Guido van Rossum9bfef441993-03-29 10:43:31 +0000189 if (fractpart == 0.0) {
190 if (intpart > 0x7fffffffL || -intpart > 0x7fffffffL) {
191 /* Convert to long int and use its hash... */
192 object *w = dnewlongobject(v->ob_fval);
193 if (w == NULL)
194 return -1;
195 x = hashobject(w);
196 DECREF(w);
197 return x;
198 }
199 x = (long)intpart;
200 }
201 else {
202 fractpart = frexp(fractpart, &expo);
Guido van Rossum9575a441993-04-07 14:06:14 +0000203 fractpart = fractpart*4294967296.0; /* 2**32 */
Guido van Rossum9bfef441993-03-29 10:43:31 +0000204 x = (long) (intpart + fractpart) ^ expo; /* Rather arbitrary */
205 }
206 if (x == -1)
207 x = -2;
208 return x;
209}
210
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000211static object *
212float_add(v, w)
213 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000214 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000215{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000216 return newfloatobject(v->ob_fval + w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000217}
218
219static object *
220float_sub(v, w)
221 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000222 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000223{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000224 return newfloatobject(v->ob_fval - w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000225}
226
227static object *
228float_mul(v, w)
229 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000230 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000231{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000232 return newfloatobject(v->ob_fval * w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000233}
234
235static object *
236float_div(v, w)
237 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000238 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000239{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000240 if (w->ob_fval == 0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000241 err_setstr(ZeroDivisionError, "float division");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000242 return NULL;
243 }
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_rem(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 double vx, wx;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000253 double /* div, */ mod;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000254 wx = w->ob_fval;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000255 if (wx == 0.0) {
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000256 err_setstr(ZeroDivisionError, "float modulo");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000257 return NULL;
258 }
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000259 vx = v->ob_fval;
260 mod = fmod(vx, wx);
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000261 /* div = (vx - mod) / wx; */
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000262 if (wx*mod < 0) {
263 mod += wx;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000264 /* div -= 1.0; */
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000265 }
266 return newfloatobject(mod);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000267}
268
269static object *
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000270float_divmod(v, w)
271 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000272 floatobject *w;
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000273{
Guido van Rossum15ecff41991-10-20 20:16:45 +0000274 double vx, wx;
275 double div, mod;
276 object *t;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000277 wx = w->ob_fval;
Guido van Rossum15ecff41991-10-20 20:16:45 +0000278 if (wx == 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000279 err_setstr(ZeroDivisionError, "float divmod()");
Guido van Rossum15ecff41991-10-20 20:16:45 +0000280 return NULL;
281 }
282 vx = v->ob_fval;
283 mod = fmod(vx, wx);
284 div = (vx - mod) / wx;
285 if (wx*mod < 0) {
286 mod += wx;
287 div -= 1.0;
288 }
Guido van Rossume5372401993-03-16 12:15:04 +0000289 return mkvalue("(dd)", div, mod);
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000290}
291
292static object *
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000293float_pow(v, w, z)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000294 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000295 floatobject *w;
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000296 floatobject *z;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000297{
298 double iv, iw, ix;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000299 iv = v->ob_fval;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000300 iw = w->ob_fval;
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000301 /* XXX Doesn't handle overflows if z!=None yet; it may never do so :(
302 * The z parameter is really only going to be useful for integers and
303 * long integers. Maybe something clever with logarithms could be done.
304 * [AMK]
305 */
Guido van Rossum70d93461991-05-28 21:57:39 +0000306 /* Sort out special cases here instead of relying on pow() */
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000307 if (iw == 0.0) { /* x**0 is 1, even 0**0 */
308 if ((object *)z!=None) {
309 ix=fmod(1.0, z->ob_fval);
310 if (ix!=0 && z->ob_fval<0) ix+=z->ob_fval;
311 }
312 else ix=1.0;
313 return newfloatobject(ix);
314 }
Guido van Rossum70d93461991-05-28 21:57:39 +0000315 if (iv == 0.0) {
316 if (iw < 0.0) {
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000317 err_setstr(ValueError, "0.0 to a negative power");
Guido van Rossum70d93461991-05-28 21:57:39 +0000318 return NULL;
319 }
320 return newfloatobject(0.0);
321 }
322 if (iv < 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000323 err_setstr(ValueError, "negative float to float power");
Guido van Rossum70d93461991-05-28 21:57:39 +0000324 return NULL;
325 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000326 errno = 0;
327 ix = pow(iv, iw);
Guido van Rossum7fa52f81991-12-16 15:43:14 +0000328 CHECK(ix);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000329 if (errno != 0) {
330 /* XXX could it be another type of error? */
331 err_errno(OverflowError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000332 return NULL;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000333 }
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000334 if ((object *)z!=None) {
335 ix=fmod(ix, z->ob_fval); /* XXX To Be Rewritten */
336 if ( ix!=0 &&
337 ((iv<0 && z->ob_fval>0) || (iv>0 && z->ob_fval<0) )) {
338 ix+=z->ob_fval;
339 }
340 }
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000341 return newfloatobject(ix);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000342}
343
344static object *
345float_neg(v)
346 floatobject *v;
347{
348 return newfloatobject(-v->ob_fval);
349}
350
351static object *
352float_pos(v)
353 floatobject *v;
354{
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000355 INCREF(v);
356 return (object *)v;
357}
358
359static object *
360float_abs(v)
361 floatobject *v;
362{
363 if (v->ob_fval < 0)
364 return float_neg(v);
365 else
366 return float_pos(v);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000367}
368
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000369static int
370float_nonzero(v)
371 floatobject *v;
372{
373 return v->ob_fval != 0.0;
374}
375
Guido van Rossum234f9421993-06-17 12:35:49 +0000376static int
Guido van Rossume6eefc21992-08-14 12:06:52 +0000377float_coerce(pv, pw)
378 object **pv;
379 object **pw;
380{
381 if (is_intobject(*pw)) {
382 long x = getintvalue(*pw);
383 *pw = newfloatobject((double)x);
384 INCREF(*pv);
385 return 0;
386 }
387 else if (is_longobject(*pw)) {
388 *pw = newfloatobject(dgetlongvalue(*pw));
389 INCREF(*pv);
390 return 0;
391 }
392 return 1; /* Can't do it */
393}
394
Guido van Rossum1899c2e1992-09-12 11:09:23 +0000395static object *
396float_int(v)
397 object *v;
398{
399 double x = getfloatvalue(v);
400 /* XXX should check for overflow */
401 /* XXX should define how we round */
402 return newintobject((long)x);
403}
404
405static object *
406float_long(v)
407 object *v;
408{
409 double x = getfloatvalue(v);
410 return dnewlongobject(x);
411}
412
413static object *
414float_float(v)
415 object *v;
416{
417 INCREF(v);
418 return v;
419}
420
421
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000422static number_methods float_as_number = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000423 (binaryfunc)float_add, /*nb_add*/
424 (binaryfunc)float_sub, /*nb_subtract*/
425 (binaryfunc)float_mul, /*nb_multiply*/
426 (binaryfunc)float_div, /*nb_divide*/
427 (binaryfunc)float_rem, /*nb_remainder*/
428 (binaryfunc)float_divmod, /*nb_divmod*/
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000429 (ternaryfunc)float_pow, /*nb_power*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000430 (unaryfunc)float_neg, /*nb_negative*/
431 (unaryfunc)float_pos, /*nb_positive*/
432 (unaryfunc)float_abs, /*nb_absolute*/
433 (inquiry)float_nonzero, /*nb_nonzero*/
Guido van Rossum27acb331991-10-24 14:55:28 +0000434 0, /*nb_invert*/
435 0, /*nb_lshift*/
436 0, /*nb_rshift*/
437 0, /*nb_and*/
438 0, /*nb_xor*/
439 0, /*nb_or*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000440 (coercion)float_coerce, /*nb_coerce*/
441 (unaryfunc)float_int, /*nb_int*/
442 (unaryfunc)float_long, /*nb_long*/
443 (unaryfunc)float_float, /*nb_float*/
Guido van Rossum1899c2e1992-09-12 11:09:23 +0000444 0, /*nb_oct*/
445 0, /*nb_hex*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000446};
447
448typeobject Floattype = {
449 OB_HEAD_INIT(&Typetype)
450 0,
451 "float",
452 sizeof(floatobject),
453 0,
Guido van Rossumb6775db1994-08-01 11:34:53 +0000454 (destructor)float_dealloc, /*tp_dealloc*/
455 (printfunc)float_print, /*tp_print*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000456 0, /*tp_getattr*/
457 0, /*tp_setattr*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000458 (cmpfunc)float_compare, /*tp_compare*/
459 (reprfunc)float_repr, /*tp_repr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000460 &float_as_number, /*tp_as_number*/
461 0, /*tp_as_sequence*/
462 0, /*tp_as_mapping*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000463 (hashfunc)float_hash, /*tp_hash*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000464};