blob: a2eba51aec97a9502ac39c2f6132cb677fa1bbc7 [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>
Guido van Rossum07e3a7e1995-02-27 10:13:37 +000035#include "mymath.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 Rossum07e3a7e1995-02-27 10:13:37 +000074#if !defined(__STDC__) && !defined(macintosh)
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 *
Guido van Rossum07e3a7e1995-02-27 10:13:37 +000080#ifdef __SC__
81newfloatobject(double fval)
82#else
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000083newfloatobject(fval)
84 double fval;
Guido van Rossum07e3a7e1995-02-27 10:13:37 +000085#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000086{
87 /* For efficiency, this code is copied from newobject() */
88 register floatobject *op = (floatobject *) malloc(sizeof(floatobject));
Guido van Rossum2a9096b1990-10-21 22:15:08 +000089 if (op == NULL)
90 return err_nomem();
Guido van Rossum2a9096b1990-10-21 22:15:08 +000091 op->ob_type = &Floattype;
92 op->ob_fval = fval;
Sjoerd Mullendera9c3c221993-10-11 12:54:31 +000093 NEWREF(op);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000094 return (object *) op;
95}
96
Guido van Rossum234f9421993-06-17 12:35:49 +000097static void
Guido van Rossum3132a5a1992-03-27 17:28:44 +000098float_dealloc(op)
99 object *op;
100{
101 DEL(op);
102}
103
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000104double
105getfloatvalue(op)
106 object *op;
107{
Guido van Rossumb6775db1994-08-01 11:34:53 +0000108 number_methods *nb;
109 floatobject *fo;
110 double val;
111
112 if (op && is_floatobject(op))
113 return GETFLOATVALUE((floatobject*) op);
114
115 if (op == NULL || (nb = op->ob_type->tp_as_number) == NULL ||
116 nb->nb_float == NULL) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000117 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000118 return -1;
119 }
Guido van Rossumb6775db1994-08-01 11:34:53 +0000120
121 fo = (floatobject*) (*nb->nb_float) (op);
122 if (fo == NULL)
123 return -1;
124 if (!is_floatobject(fo)) {
125 err_setstr(TypeError, "nb_float should return float object");
126 return -1;
127 }
128
129 val = GETFLOATVALUE(fo);
130 DECREF(fo);
131
132 return val;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000133}
134
135/* Methods */
136
Guido van Rossum27dec7e1991-06-04 19:42:53 +0000137void
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000138float_buf_repr(buf, v)
139 char *buf;
140 floatobject *v;
141{
142 register char *cp;
143 /* Subroutine for float_repr and float_print.
144 We want float numbers to be recognizable as such,
145 i.e., they should contain a decimal point or an exponent.
146 However, %g may print the number as an integer;
147 in such cases, we append ".0" to the string. */
148 sprintf(buf, "%.12g", v->ob_fval);
149 cp = buf;
150 if (*cp == '-')
151 cp++;
152 for (; *cp != '\0'; cp++) {
153 /* Any non-digit means it's not an integer;
154 this takes care of NAN and INF as well. */
Guido van Rossum9fa2c111995-02-10 17:00:37 +0000155 if (!isdigit(Py_CHARMASK(*cp)))
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000156 break;
157 }
158 if (*cp == '\0') {
159 *cp++ = '.';
160 *cp++ = '0';
161 *cp++ = '\0';
162 }
163}
164
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000165/* ARGSUSED */
Guido van Rossum90933611991-06-07 16:10:43 +0000166static int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000167float_print(v, fp, flags)
168 floatobject *v;
169 FILE *fp;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000170 int flags; /* Not used but required by interface */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000171{
172 char buf[100];
173 float_buf_repr(buf, v);
174 fputs(buf, fp);
Guido van Rossum90933611991-06-07 16:10:43 +0000175 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000176}
177
178static object *
179float_repr(v)
180 floatobject *v;
181{
182 char buf[100];
183 float_buf_repr(buf, v);
184 return newstringobject(buf);
185}
186
187static int
188float_compare(v, w)
189 floatobject *v, *w;
190{
191 double i = v->ob_fval;
192 double j = w->ob_fval;
193 return (i < j) ? -1 : (i > j) ? 1 : 0;
194}
195
Guido van Rossum9bfef441993-03-29 10:43:31 +0000196static long
197float_hash(v)
198 floatobject *v;
199{
200 double intpart, fractpart;
201 int expo;
202 long x;
203 /* This is designed so that Python numbers with the same
204 value hash to the same value, otherwise comparisons
205 of mapping keys will turn out weird */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000206
207#ifdef MPW /* MPW C modf expects pointer to extended as second argument */
208{
209 extended e;
210 fractpart = modf(v->ob_fval, &e);
211 intpart = e;
212}
213#else
Guido van Rossum9bfef441993-03-29 10:43:31 +0000214 fractpart = modf(v->ob_fval, &intpart);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000215#endif
216
Guido van Rossum9bfef441993-03-29 10:43:31 +0000217 if (fractpart == 0.0) {
218 if (intpart > 0x7fffffffL || -intpart > 0x7fffffffL) {
219 /* Convert to long int and use its hash... */
220 object *w = dnewlongobject(v->ob_fval);
221 if (w == NULL)
222 return -1;
223 x = hashobject(w);
224 DECREF(w);
225 return x;
226 }
227 x = (long)intpart;
228 }
229 else {
230 fractpart = frexp(fractpart, &expo);
Guido van Rossum6610ad91995-01-04 19:07:38 +0000231 fractpart = fractpart*2147483648.0; /* 2**31 */
Guido van Rossum9bfef441993-03-29 10:43:31 +0000232 x = (long) (intpart + fractpart) ^ expo; /* Rather arbitrary */
233 }
234 if (x == -1)
235 x = -2;
236 return x;
237}
238
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000239static object *
240float_add(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_sub(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 return newfloatobject(v->ob_fval - w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000253}
254
255static object *
256float_mul(v, w)
257 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000258 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000259{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000260 return newfloatobject(v->ob_fval * w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000261}
262
263static object *
264float_div(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{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000268 if (w->ob_fval == 0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000269 err_setstr(ZeroDivisionError, "float division");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000270 return NULL;
271 }
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000272 return newfloatobject(v->ob_fval / w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000273}
274
275static object *
276float_rem(v, w)
277 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000278 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000279{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000280 double vx, wx;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000281 double /* div, */ mod;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000282 wx = w->ob_fval;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000283 if (wx == 0.0) {
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000284 err_setstr(ZeroDivisionError, "float modulo");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000285 return NULL;
286 }
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000287 vx = v->ob_fval;
288 mod = fmod(vx, wx);
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000289 /* div = (vx - mod) / wx; */
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000290 if (wx*mod < 0) {
291 mod += wx;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000292 /* div -= 1.0; */
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000293 }
294 return newfloatobject(mod);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000295}
296
297static object *
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000298float_divmod(v, w)
299 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000300 floatobject *w;
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000301{
Guido van Rossum15ecff41991-10-20 20:16:45 +0000302 double vx, wx;
303 double div, mod;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000304 wx = w->ob_fval;
Guido van Rossum15ecff41991-10-20 20:16:45 +0000305 if (wx == 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000306 err_setstr(ZeroDivisionError, "float divmod()");
Guido van Rossum15ecff41991-10-20 20:16:45 +0000307 return NULL;
308 }
309 vx = v->ob_fval;
310 mod = fmod(vx, wx);
311 div = (vx - mod) / wx;
312 if (wx*mod < 0) {
313 mod += wx;
314 div -= 1.0;
315 }
Guido van Rossume5372401993-03-16 12:15:04 +0000316 return mkvalue("(dd)", div, mod);
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000317}
318
319static object *
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000320float_pow(v, w, z)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000321 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000322 floatobject *w;
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000323 floatobject *z;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000324{
325 double iv, iw, ix;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000326 iv = v->ob_fval;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000327 iw = w->ob_fval;
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000328 /* XXX Doesn't handle overflows if z!=None yet; it may never do so :(
329 * The z parameter is really only going to be useful for integers and
330 * long integers. Maybe something clever with logarithms could be done.
331 * [AMK]
332 */
Guido van Rossum70d93461991-05-28 21:57:39 +0000333 /* Sort out special cases here instead of relying on pow() */
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000334 if (iw == 0.0) { /* x**0 is 1, even 0**0 */
335 if ((object *)z!=None) {
336 ix=fmod(1.0, z->ob_fval);
337 if (ix!=0 && z->ob_fval<0) ix+=z->ob_fval;
338 }
339 else ix=1.0;
340 return newfloatobject(ix);
341 }
Guido van Rossum70d93461991-05-28 21:57:39 +0000342 if (iv == 0.0) {
343 if (iw < 0.0) {
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000344 err_setstr(ValueError, "0.0 to a negative power");
Guido van Rossum70d93461991-05-28 21:57:39 +0000345 return NULL;
346 }
347 return newfloatobject(0.0);
348 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000349 errno = 0;
350 ix = pow(iv, iw);
Guido van Rossum7fa52f81991-12-16 15:43:14 +0000351 CHECK(ix);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000352 if (errno != 0) {
353 /* XXX could it be another type of error? */
354 err_errno(OverflowError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000355 return NULL;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000356 }
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000357 if ((object *)z!=None) {
358 ix=fmod(ix, z->ob_fval); /* XXX To Be Rewritten */
359 if ( ix!=0 &&
360 ((iv<0 && z->ob_fval>0) || (iv>0 && z->ob_fval<0) )) {
361 ix+=z->ob_fval;
362 }
363 }
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000364 return newfloatobject(ix);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000365}
366
367static object *
368float_neg(v)
369 floatobject *v;
370{
371 return newfloatobject(-v->ob_fval);
372}
373
374static object *
375float_pos(v)
376 floatobject *v;
377{
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000378 INCREF(v);
379 return (object *)v;
380}
381
382static object *
383float_abs(v)
384 floatobject *v;
385{
386 if (v->ob_fval < 0)
387 return float_neg(v);
388 else
389 return float_pos(v);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000390}
391
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000392static int
393float_nonzero(v)
394 floatobject *v;
395{
396 return v->ob_fval != 0.0;
397}
398
Guido van Rossum234f9421993-06-17 12:35:49 +0000399static int
Guido van Rossume6eefc21992-08-14 12:06:52 +0000400float_coerce(pv, pw)
401 object **pv;
402 object **pw;
403{
404 if (is_intobject(*pw)) {
405 long x = getintvalue(*pw);
406 *pw = newfloatobject((double)x);
407 INCREF(*pv);
408 return 0;
409 }
410 else if (is_longobject(*pw)) {
411 *pw = newfloatobject(dgetlongvalue(*pw));
412 INCREF(*pv);
413 return 0;
414 }
415 return 1; /* Can't do it */
416}
417
Guido van Rossum1899c2e1992-09-12 11:09:23 +0000418static object *
419float_int(v)
420 object *v;
421{
422 double x = getfloatvalue(v);
Guido van Rossum03093a21994-09-28 15:51:32 +0000423 if (x < 0 ? (x = ceil(x)) < (double)LONG_MIN
424 : (x = floor(x)) > (double)LONG_MAX) {
Guido van Rossum67ca7011995-02-13 16:38:41 +0000425 err_setstr(OverflowError, "float too large to convert");
Guido van Rossum03093a21994-09-28 15:51:32 +0000426 return NULL;
427 }
Guido van Rossum1899c2e1992-09-12 11:09:23 +0000428 return newintobject((long)x);
429}
430
431static object *
432float_long(v)
433 object *v;
434{
435 double x = getfloatvalue(v);
436 return dnewlongobject(x);
437}
438
439static object *
440float_float(v)
441 object *v;
442{
443 INCREF(v);
444 return v;
445}
446
447
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000448static number_methods float_as_number = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000449 (binaryfunc)float_add, /*nb_add*/
450 (binaryfunc)float_sub, /*nb_subtract*/
451 (binaryfunc)float_mul, /*nb_multiply*/
452 (binaryfunc)float_div, /*nb_divide*/
453 (binaryfunc)float_rem, /*nb_remainder*/
454 (binaryfunc)float_divmod, /*nb_divmod*/
Guido van Rossum0b7d02a1994-08-12 12:52:35 +0000455 (ternaryfunc)float_pow, /*nb_power*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000456 (unaryfunc)float_neg, /*nb_negative*/
457 (unaryfunc)float_pos, /*nb_positive*/
458 (unaryfunc)float_abs, /*nb_absolute*/
459 (inquiry)float_nonzero, /*nb_nonzero*/
Guido van Rossum27acb331991-10-24 14:55:28 +0000460 0, /*nb_invert*/
461 0, /*nb_lshift*/
462 0, /*nb_rshift*/
463 0, /*nb_and*/
464 0, /*nb_xor*/
465 0, /*nb_or*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000466 (coercion)float_coerce, /*nb_coerce*/
467 (unaryfunc)float_int, /*nb_int*/
468 (unaryfunc)float_long, /*nb_long*/
469 (unaryfunc)float_float, /*nb_float*/
Guido van Rossum1899c2e1992-09-12 11:09:23 +0000470 0, /*nb_oct*/
471 0, /*nb_hex*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000472};
473
474typeobject Floattype = {
475 OB_HEAD_INIT(&Typetype)
476 0,
477 "float",
478 sizeof(floatobject),
479 0,
Guido van Rossumb6775db1994-08-01 11:34:53 +0000480 (destructor)float_dealloc, /*tp_dealloc*/
481 (printfunc)float_print, /*tp_print*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000482 0, /*tp_getattr*/
483 0, /*tp_setattr*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000484 (cmpfunc)float_compare, /*tp_compare*/
485 (reprfunc)float_repr, /*tp_repr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000486 &float_as_number, /*tp_as_number*/
487 0, /*tp_as_sequence*/
488 0, /*tp_as_mapping*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000489 (hashfunc)float_hash, /*tp_hash*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000490};