blob: 04d80b165f71ad700a4382922f597ba7a1ed8dbe [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 Rossum67ca7011995-02-13 16:38:41 +000062#ifdef __NeXT__
63#ifdef __sparc__
64/*
65 * This works around a bug in the NS/Sparc 3.3 pre-release
66 * limits.h header file.
67 * 10-Feb-1995 bwarsaw@cnri.reston.va.us
68 */
69#undef LONG_MIN
70#define LONG_MIN (-LONG_MAX-1)
71#endif
72#endif
73
Guido van Rossum4d3468d1995-01-17 16:33:14 +000074#ifndef __STDC__
Guido van Rossum6923e131990-11-02 17:50:43 +000075extern double fmod PROTO((double, double));
76extern double pow PROTO((double, double));
77#endif
78
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000079object *
80newfloatobject(fval)
81 double fval;
82{
83 /* For efficiency, this code is copied from newobject() */
84 register floatobject *op = (floatobject *) malloc(sizeof(floatobject));
Guido van Rossum2a9096b1990-10-21 22:15:08 +000085 if (op == NULL)
86 return err_nomem();
Guido van Rossum2a9096b1990-10-21 22:15:08 +000087 op->ob_type = &Floattype;
88 op->ob_fval = fval;
Sjoerd Mullendera9c3c221993-10-11 12:54:31 +000089 NEWREF(op);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000090 return (object *) op;
91}
92
Guido van Rossum234f9421993-06-17 12:35:49 +000093static void
Guido van Rossum3132a5a1992-03-27 17:28:44 +000094float_dealloc(op)
95 object *op;
96{
97 DEL(op);
98}
99
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000100double
101getfloatvalue(op)
102 object *op;
103{
Guido van Rossumb6775db1994-08-01 11:34:53 +0000104 number_methods *nb;
105 floatobject *fo;
106 double val;
107
108 if (op && is_floatobject(op))
109 return GETFLOATVALUE((floatobject*) op);
110
111 if (op == NULL || (nb = op->ob_type->tp_as_number) == NULL ||
112 nb->nb_float == NULL) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000113 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000114 return -1;
115 }
Guido van Rossumb6775db1994-08-01 11:34:53 +0000116
117 fo = (floatobject*) (*nb->nb_float) (op);
118 if (fo == NULL)
119 return -1;
120 if (!is_floatobject(fo)) {
121 err_setstr(TypeError, "nb_float should return float object");
122 return -1;
123 }
124
125 val = GETFLOATVALUE(fo);
126 DECREF(fo);
127
128 return val;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000129}
130
131/* Methods */
132
Guido van Rossum27dec7e1991-06-04 19:42:53 +0000133void
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000134float_buf_repr(buf, v)
135 char *buf;
136 floatobject *v;
137{
138 register char *cp;
139 /* Subroutine for float_repr and float_print.
140 We want float numbers to be recognizable as such,
141 i.e., they should contain a decimal point or an exponent.
142 However, %g may print the number as an integer;
143 in such cases, we append ".0" to the string. */
144 sprintf(buf, "%.12g", v->ob_fval);
145 cp = buf;
146 if (*cp == '-')
147 cp++;
148 for (; *cp != '\0'; cp++) {
149 /* Any non-digit means it's not an integer;
150 this takes care of NAN and INF as well. */
Guido van Rossum9fa2c111995-02-10 17:00:37 +0000151 if (!isdigit(Py_CHARMASK(*cp)))
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000152 break;
153 }
154 if (*cp == '\0') {
155 *cp++ = '.';
156 *cp++ = '0';
157 *cp++ = '\0';
158 }
159}
160
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000161/* ARGSUSED */
Guido van Rossum90933611991-06-07 16:10:43 +0000162static int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000163float_print(v, fp, flags)
164 floatobject *v;
165 FILE *fp;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000166 int flags; /* Not used but required by interface */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000167{
168 char buf[100];
169 float_buf_repr(buf, v);
170 fputs(buf, fp);
Guido van Rossum90933611991-06-07 16:10:43 +0000171 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000172}
173
174static object *
175float_repr(v)
176 floatobject *v;
177{
178 char buf[100];
179 float_buf_repr(buf, v);
180 return newstringobject(buf);
181}
182
183static int
184float_compare(v, w)
185 floatobject *v, *w;
186{
187 double i = v->ob_fval;
188 double j = w->ob_fval;
189 return (i < j) ? -1 : (i > j) ? 1 : 0;
190}
191
Guido van Rossum9bfef441993-03-29 10:43:31 +0000192static long
193float_hash(v)
194 floatobject *v;
195{
196 double intpart, fractpart;
197 int expo;
198 long x;
199 /* This is designed so that Python numbers with the same
200 value hash to the same value, otherwise comparisons
201 of mapping keys will turn out weird */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000202
203#ifdef MPW /* MPW C modf expects pointer to extended as second argument */
204{
205 extended e;
206 fractpart = modf(v->ob_fval, &e);
207 intpart = e;
208}
209#else
Guido van Rossum9bfef441993-03-29 10:43:31 +0000210 fractpart = modf(v->ob_fval, &intpart);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000211#endif
212
Guido van Rossum9bfef441993-03-29 10:43:31 +0000213 if (fractpart == 0.0) {
214 if (intpart > 0x7fffffffL || -intpart > 0x7fffffffL) {
215 /* Convert to long int and use its hash... */
216 object *w = dnewlongobject(v->ob_fval);
217 if (w == NULL)
218 return -1;
219 x = hashobject(w);
220 DECREF(w);
221 return x;
222 }
223 x = (long)intpart;
224 }
225 else {
226 fractpart = frexp(fractpart, &expo);
Guido van Rossum6610ad91995-01-04 19:07:38 +0000227 fractpart = fractpart*2147483648.0; /* 2**31 */
Guido van Rossum9bfef441993-03-29 10:43:31 +0000228 x = (long) (intpart + fractpart) ^ expo; /* Rather arbitrary */
229 }
230 if (x == -1)
231 x = -2;
232 return x;
233}
234
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000235static object *
236float_add(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 return newfloatobject(v->ob_fval + w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000241}
242
243static object *
244float_sub(v, w)
245 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000246 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000247{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000248 return newfloatobject(v->ob_fval - w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000249}
250
251static object *
252float_mul(v, w)
253 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000254 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000255{
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_div(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 if (w->ob_fval == 0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000265 err_setstr(ZeroDivisionError, "float division");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000266 return NULL;
267 }
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000268 return newfloatobject(v->ob_fval / w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000269}
270
271static object *
272float_rem(v, w)
273 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000274 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000275{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000276 double vx, wx;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000277 double /* div, */ mod;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000278 wx = w->ob_fval;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000279 if (wx == 0.0) {
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000280 err_setstr(ZeroDivisionError, "float modulo");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000281 return NULL;
282 }
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000283 vx = v->ob_fval;
284 mod = fmod(vx, wx);
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000285 /* div = (vx - mod) / wx; */
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000286 if (wx*mod < 0) {
287 mod += wx;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000288 /* div -= 1.0; */
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000289 }
290 return newfloatobject(mod);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000291}
292
293static object *
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000294float_divmod(v, w)
295 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000296 floatobject *w;
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000297{
Guido van Rossum15ecff41991-10-20 20:16:45 +0000298 double vx, wx;
299 double div, mod;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000300 wx = w->ob_fval;
Guido van Rossum15ecff41991-10-20 20:16:45 +0000301 if (wx == 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000302 err_setstr(ZeroDivisionError, "float divmod()");
Guido van Rossum15ecff41991-10-20 20:16:45 +0000303 return NULL;
304 }
305 vx = v->ob_fval;
306 mod = fmod(vx, wx);
307 div = (vx - mod) / wx;
308 if (wx*mod < 0) {
309 mod += wx;
310 div -= 1.0;
311 }
Guido van Rossume5372401993-03-16 12:15:04 +0000312 return mkvalue("(dd)", div, mod);
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000313}
314
315static object *
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000316float_pow(v, w, z)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000317 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000318 floatobject *w;
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000319 floatobject *z;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000320{
321 double iv, iw, ix;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000322 iv = v->ob_fval;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000323 iw = w->ob_fval;
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000324 /* XXX Doesn't handle overflows if z!=None yet; it may never do so :(
325 * The z parameter is really only going to be useful for integers and
326 * long integers. Maybe something clever with logarithms could be done.
327 * [AMK]
328 */
Guido van Rossum70d93461991-05-28 21:57:39 +0000329 /* Sort out special cases here instead of relying on pow() */
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000330 if (iw == 0.0) { /* x**0 is 1, even 0**0 */
331 if ((object *)z!=None) {
332 ix=fmod(1.0, z->ob_fval);
333 if (ix!=0 && z->ob_fval<0) ix+=z->ob_fval;
334 }
335 else ix=1.0;
336 return newfloatobject(ix);
337 }
Guido van Rossum70d93461991-05-28 21:57:39 +0000338 if (iv == 0.0) {
339 if (iw < 0.0) {
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000340 err_setstr(ValueError, "0.0 to a negative power");
Guido van Rossum70d93461991-05-28 21:57:39 +0000341 return NULL;
342 }
343 return newfloatobject(0.0);
344 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000345 errno = 0;
346 ix = pow(iv, iw);
Guido van Rossum7fa52f81991-12-16 15:43:14 +0000347 CHECK(ix);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000348 if (errno != 0) {
349 /* XXX could it be another type of error? */
350 err_errno(OverflowError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000351 return NULL;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000352 }
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000353 if ((object *)z!=None) {
354 ix=fmod(ix, z->ob_fval); /* XXX To Be Rewritten */
355 if ( ix!=0 &&
356 ((iv<0 && z->ob_fval>0) || (iv>0 && z->ob_fval<0) )) {
357 ix+=z->ob_fval;
358 }
359 }
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000360 return newfloatobject(ix);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000361}
362
363static object *
364float_neg(v)
365 floatobject *v;
366{
367 return newfloatobject(-v->ob_fval);
368}
369
370static object *
371float_pos(v)
372 floatobject *v;
373{
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000374 INCREF(v);
375 return (object *)v;
376}
377
378static object *
379float_abs(v)
380 floatobject *v;
381{
382 if (v->ob_fval < 0)
383 return float_neg(v);
384 else
385 return float_pos(v);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000386}
387
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000388static int
389float_nonzero(v)
390 floatobject *v;
391{
392 return v->ob_fval != 0.0;
393}
394
Guido van Rossum234f9421993-06-17 12:35:49 +0000395static int
Guido van Rossume6eefc21992-08-14 12:06:52 +0000396float_coerce(pv, pw)
397 object **pv;
398 object **pw;
399{
400 if (is_intobject(*pw)) {
401 long x = getintvalue(*pw);
402 *pw = newfloatobject((double)x);
403 INCREF(*pv);
404 return 0;
405 }
406 else if (is_longobject(*pw)) {
407 *pw = newfloatobject(dgetlongvalue(*pw));
408 INCREF(*pv);
409 return 0;
410 }
411 return 1; /* Can't do it */
412}
413
Guido van Rossum1899c2e1992-09-12 11:09:23 +0000414static object *
415float_int(v)
416 object *v;
417{
418 double x = getfloatvalue(v);
Guido van Rossum03093a21994-09-28 15:51:32 +0000419 if (x < 0 ? (x = ceil(x)) < (double)LONG_MIN
420 : (x = floor(x)) > (double)LONG_MAX) {
Guido van Rossum67ca7011995-02-13 16:38:41 +0000421 err_setstr(OverflowError, "float too large to convert");
Guido van Rossum03093a21994-09-28 15:51:32 +0000422 return NULL;
423 }
Guido van Rossum1899c2e1992-09-12 11:09:23 +0000424 return newintobject((long)x);
425}
426
427static object *
428float_long(v)
429 object *v;
430{
431 double x = getfloatvalue(v);
432 return dnewlongobject(x);
433}
434
435static object *
436float_float(v)
437 object *v;
438{
439 INCREF(v);
440 return v;
441}
442
443
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000444static number_methods float_as_number = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000445 (binaryfunc)float_add, /*nb_add*/
446 (binaryfunc)float_sub, /*nb_subtract*/
447 (binaryfunc)float_mul, /*nb_multiply*/
448 (binaryfunc)float_div, /*nb_divide*/
449 (binaryfunc)float_rem, /*nb_remainder*/
450 (binaryfunc)float_divmod, /*nb_divmod*/
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000451 (ternaryfunc)float_pow, /*nb_power*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000452 (unaryfunc)float_neg, /*nb_negative*/
453 (unaryfunc)float_pos, /*nb_positive*/
454 (unaryfunc)float_abs, /*nb_absolute*/
455 (inquiry)float_nonzero, /*nb_nonzero*/
Guido van Rossum27acb331991-10-24 14:55:28 +0000456 0, /*nb_invert*/
457 0, /*nb_lshift*/
458 0, /*nb_rshift*/
459 0, /*nb_and*/
460 0, /*nb_xor*/
461 0, /*nb_or*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000462 (coercion)float_coerce, /*nb_coerce*/
463 (unaryfunc)float_int, /*nb_int*/
464 (unaryfunc)float_long, /*nb_long*/
465 (unaryfunc)float_float, /*nb_float*/
Guido van Rossum1899c2e1992-09-12 11:09:23 +0000466 0, /*nb_oct*/
467 0, /*nb_hex*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000468};
469
470typeobject Floattype = {
471 OB_HEAD_INIT(&Typetype)
472 0,
473 "float",
474 sizeof(floatobject),
475 0,
Guido van Rossumb6775db1994-08-01 11:34:53 +0000476 (destructor)float_dealloc, /*tp_dealloc*/
477 (printfunc)float_print, /*tp_print*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000478 0, /*tp_getattr*/
479 0, /*tp_setattr*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000480 (cmpfunc)float_compare, /*tp_compare*/
481 (reprfunc)float_repr, /*tp_repr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000482 &float_as_number, /*tp_as_number*/
483 0, /*tp_as_sequence*/
484 0, /*tp_as_mapping*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000485 (hashfunc)float_hash, /*tp_hash*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000486};