blob: 5ff67dbbd497dfb5292f08e1284c1d54a9f9aa2f [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 Rossum85a5fbb1990-10-14 12:07:46 +0000293float_pow(v, w)
294 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000295 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000296{
297 double iv, iw, ix;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000298 iv = v->ob_fval;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000299 iw = w->ob_fval;
Guido van Rossum70d93461991-05-28 21:57:39 +0000300 /* Sort out special cases here instead of relying on pow() */
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000301 if (iw == 0.0)
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000302 return newfloatobject(1.0); /* x**0 is 1, even 0**0 */
Guido van Rossum70d93461991-05-28 21:57:39 +0000303 if (iv == 0.0) {
304 if (iw < 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000305 err_setstr(ValueError, "0.0 to the negative power");
Guido van Rossum70d93461991-05-28 21:57:39 +0000306 return NULL;
307 }
308 return newfloatobject(0.0);
309 }
310 if (iv < 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000311 err_setstr(ValueError, "negative float to float power");
Guido van Rossum70d93461991-05-28 21:57:39 +0000312 return NULL;
313 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000314 errno = 0;
315 ix = pow(iv, iw);
Guido van Rossum7fa52f81991-12-16 15:43:14 +0000316 CHECK(ix);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000317 if (errno != 0) {
318 /* XXX could it be another type of error? */
319 err_errno(OverflowError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000320 return NULL;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000321 }
322 return newfloatobject(ix);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000323}
324
325static object *
326float_neg(v)
327 floatobject *v;
328{
329 return newfloatobject(-v->ob_fval);
330}
331
332static object *
333float_pos(v)
334 floatobject *v;
335{
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000336 INCREF(v);
337 return (object *)v;
338}
339
340static object *
341float_abs(v)
342 floatobject *v;
343{
344 if (v->ob_fval < 0)
345 return float_neg(v);
346 else
347 return float_pos(v);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000348}
349
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000350static int
351float_nonzero(v)
352 floatobject *v;
353{
354 return v->ob_fval != 0.0;
355}
356
Guido van Rossum234f9421993-06-17 12:35:49 +0000357static int
Guido van Rossume6eefc21992-08-14 12:06:52 +0000358float_coerce(pv, pw)
359 object **pv;
360 object **pw;
361{
362 if (is_intobject(*pw)) {
363 long x = getintvalue(*pw);
364 *pw = newfloatobject((double)x);
365 INCREF(*pv);
366 return 0;
367 }
368 else if (is_longobject(*pw)) {
369 *pw = newfloatobject(dgetlongvalue(*pw));
370 INCREF(*pv);
371 return 0;
372 }
373 return 1; /* Can't do it */
374}
375
Guido van Rossum1899c2e1992-09-12 11:09:23 +0000376static object *
377float_int(v)
378 object *v;
379{
380 double x = getfloatvalue(v);
381 /* XXX should check for overflow */
382 /* XXX should define how we round */
383 return newintobject((long)x);
384}
385
386static object *
387float_long(v)
388 object *v;
389{
390 double x = getfloatvalue(v);
391 return dnewlongobject(x);
392}
393
394static object *
395float_float(v)
396 object *v;
397{
398 INCREF(v);
399 return v;
400}
401
402
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000403static number_methods float_as_number = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000404 (binaryfunc)float_add, /*nb_add*/
405 (binaryfunc)float_sub, /*nb_subtract*/
406 (binaryfunc)float_mul, /*nb_multiply*/
407 (binaryfunc)float_div, /*nb_divide*/
408 (binaryfunc)float_rem, /*nb_remainder*/
409 (binaryfunc)float_divmod, /*nb_divmod*/
410 (binaryfunc)float_pow, /*nb_power*/
411 (unaryfunc)float_neg, /*nb_negative*/
412 (unaryfunc)float_pos, /*nb_positive*/
413 (unaryfunc)float_abs, /*nb_absolute*/
414 (inquiry)float_nonzero, /*nb_nonzero*/
Guido van Rossum27acb331991-10-24 14:55:28 +0000415 0, /*nb_invert*/
416 0, /*nb_lshift*/
417 0, /*nb_rshift*/
418 0, /*nb_and*/
419 0, /*nb_xor*/
420 0, /*nb_or*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000421 (coercion)float_coerce, /*nb_coerce*/
422 (unaryfunc)float_int, /*nb_int*/
423 (unaryfunc)float_long, /*nb_long*/
424 (unaryfunc)float_float, /*nb_float*/
Guido van Rossum1899c2e1992-09-12 11:09:23 +0000425 0, /*nb_oct*/
426 0, /*nb_hex*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000427};
428
429typeobject Floattype = {
430 OB_HEAD_INIT(&Typetype)
431 0,
432 "float",
433 sizeof(floatobject),
434 0,
Guido van Rossumb6775db1994-08-01 11:34:53 +0000435 (destructor)float_dealloc, /*tp_dealloc*/
436 (printfunc)float_print, /*tp_print*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000437 0, /*tp_getattr*/
438 0, /*tp_setattr*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000439 (cmpfunc)float_compare, /*tp_compare*/
440 (reprfunc)float_repr, /*tp_repr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000441 &float_as_number, /*tp_as_number*/
442 0, /*tp_as_sequence*/
443 0, /*tp_as_mapping*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000444 (hashfunc)float_hash, /*tp_hash*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000445};