blob: 8533e0e7be453fee04afaa25fadef57f7169b866 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
Guido van Rossume5372401993-03-16 12:15:04 +00002Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3Amsterdam, 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>
34#ifndef errno
35extern int errno;
36#endif
37
Guido van Rossum3f5da241990-12-20 15:06:42 +000038#include <ctype.h>
39#include <math.h>
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000040
Guido van Rossum7fa52f81991-12-16 15:43:14 +000041#ifdef HUGE_VAL
42#define CHECK(x) if (errno != 0) ; \
43 else if (-HUGE_VAL <= (x) && (x) <= HUGE_VAL) ; \
44 else errno = ERANGE
45#else
46#define CHECK(x) /* Don't know how to check */
47#endif
48
Guido van Rossum6923e131990-11-02 17:50:43 +000049#ifndef THINK_C
50extern double fmod PROTO((double, double));
51extern double pow PROTO((double, double));
52#endif
53
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000054object *
55newfloatobject(fval)
56 double fval;
57{
58 /* For efficiency, this code is copied from newobject() */
59 register floatobject *op = (floatobject *) malloc(sizeof(floatobject));
Guido van Rossum2a9096b1990-10-21 22:15:08 +000060 if (op == NULL)
61 return err_nomem();
62 NEWREF(op);
63 op->ob_type = &Floattype;
64 op->ob_fval = fval;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000065 return (object *) op;
66}
67
Guido van Rossum3132a5a1992-03-27 17:28:44 +000068void
69float_dealloc(op)
70 object *op;
71{
72 DEL(op);
73}
74
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000075double
76getfloatvalue(op)
77 object *op;
78{
79 if (!is_floatobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000080 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000081 return -1;
82 }
83 else
84 return ((floatobject *)op) -> ob_fval;
85}
86
87/* Methods */
88
Guido van Rossum27dec7e1991-06-04 19:42:53 +000089void
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000090float_buf_repr(buf, v)
91 char *buf;
92 floatobject *v;
93{
94 register char *cp;
95 /* Subroutine for float_repr and float_print.
96 We want float numbers to be recognizable as such,
97 i.e., they should contain a decimal point or an exponent.
98 However, %g may print the number as an integer;
99 in such cases, we append ".0" to the string. */
100 sprintf(buf, "%.12g", v->ob_fval);
101 cp = buf;
102 if (*cp == '-')
103 cp++;
104 for (; *cp != '\0'; cp++) {
105 /* Any non-digit means it's not an integer;
106 this takes care of NAN and INF as well. */
107 if (!isdigit(*cp))
108 break;
109 }
110 if (*cp == '\0') {
111 *cp++ = '.';
112 *cp++ = '0';
113 *cp++ = '\0';
114 }
115}
116
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000117/* ARGSUSED */
Guido van Rossum90933611991-06-07 16:10:43 +0000118static int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000119float_print(v, fp, flags)
120 floatobject *v;
121 FILE *fp;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000122 int flags; /* Not used but required by interface */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000123{
124 char buf[100];
125 float_buf_repr(buf, v);
126 fputs(buf, fp);
Guido van Rossum90933611991-06-07 16:10:43 +0000127 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000128}
129
130static object *
131float_repr(v)
132 floatobject *v;
133{
134 char buf[100];
135 float_buf_repr(buf, v);
136 return newstringobject(buf);
137}
138
139static int
140float_compare(v, w)
141 floatobject *v, *w;
142{
143 double i = v->ob_fval;
144 double j = w->ob_fval;
145 return (i < j) ? -1 : (i > j) ? 1 : 0;
146}
147
Guido van Rossum9bfef441993-03-29 10:43:31 +0000148static long
149float_hash(v)
150 floatobject *v;
151{
152 double intpart, fractpart;
153 int expo;
154 long x;
155 /* This is designed so that Python numbers with the same
156 value hash to the same value, otherwise comparisons
157 of mapping keys will turn out weird */
158 fractpart = modf(v->ob_fval, &intpart);
159 if (fractpart == 0.0) {
160 if (intpart > 0x7fffffffL || -intpart > 0x7fffffffL) {
161 /* Convert to long int and use its hash... */
162 object *w = dnewlongobject(v->ob_fval);
163 if (w == NULL)
164 return -1;
165 x = hashobject(w);
166 DECREF(w);
167 return x;
168 }
169 x = (long)intpart;
170 }
171 else {
172 fractpart = frexp(fractpart, &expo);
173 x = (long) (intpart + fractpart) ^ expo; /* Rather arbitrary */
174 }
175 if (x == -1)
176 x = -2;
177 return x;
178}
179
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000180static object *
181float_add(v, w)
182 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000183 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000184{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000185 return newfloatobject(v->ob_fval + w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000186}
187
188static object *
189float_sub(v, w)
190 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000191 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000192{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000193 return newfloatobject(v->ob_fval - w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000194}
195
196static object *
197float_mul(v, w)
198 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000199 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000200{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000201 return newfloatobject(v->ob_fval * w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000202}
203
204static object *
205float_div(v, w)
206 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000207 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000208{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000209 if (w->ob_fval == 0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000210 err_setstr(ZeroDivisionError, "float division");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000211 return NULL;
212 }
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000213 return newfloatobject(v->ob_fval / w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000214}
215
216static object *
217float_rem(v, w)
218 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000219 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000220{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000221 double vx, wx;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000222 double /* div, */ mod;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000223 wx = w->ob_fval;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000224 if (wx == 0.0) {
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000225 err_setstr(ZeroDivisionError, "float modulo");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000226 return NULL;
227 }
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000228 vx = v->ob_fval;
229 mod = fmod(vx, wx);
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000230 /* div = (vx - mod) / wx; */
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000231 if (wx*mod < 0) {
232 mod += wx;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000233 /* div -= 1.0; */
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000234 }
235 return newfloatobject(mod);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000236}
237
238static object *
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000239float_divmod(v, w)
240 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000241 floatobject *w;
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000242{
Guido van Rossum15ecff41991-10-20 20:16:45 +0000243 double vx, wx;
244 double div, mod;
245 object *t;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000246 wx = w->ob_fval;
Guido van Rossum15ecff41991-10-20 20:16:45 +0000247 if (wx == 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000248 err_setstr(ZeroDivisionError, "float divmod()");
Guido van Rossum15ecff41991-10-20 20:16:45 +0000249 return NULL;
250 }
251 vx = v->ob_fval;
252 mod = fmod(vx, wx);
253 div = (vx - mod) / wx;
254 if (wx*mod < 0) {
255 mod += wx;
256 div -= 1.0;
257 }
Guido van Rossume5372401993-03-16 12:15:04 +0000258 return mkvalue("(dd)", div, mod);
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000259}
260
261static object *
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000262float_pow(v, w)
263 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000264 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000265{
266 double iv, iw, ix;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000267 iv = v->ob_fval;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000268 iw = w->ob_fval;
Guido van Rossum70d93461991-05-28 21:57:39 +0000269 /* Sort out special cases here instead of relying on pow() */
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000270 if (iw == 0.0)
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000271 return newfloatobject(1.0); /* x**0 is 1, even 0**0 */
Guido van Rossum70d93461991-05-28 21:57:39 +0000272 if (iv == 0.0) {
273 if (iw < 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000274 err_setstr(ValueError, "0.0 to the negative power");
Guido van Rossum70d93461991-05-28 21:57:39 +0000275 return NULL;
276 }
277 return newfloatobject(0.0);
278 }
279 if (iv < 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000280 err_setstr(ValueError, "negative float to float power");
Guido van Rossum70d93461991-05-28 21:57:39 +0000281 return NULL;
282 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000283 errno = 0;
284 ix = pow(iv, iw);
Guido van Rossum7fa52f81991-12-16 15:43:14 +0000285 CHECK(ix);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000286 if (errno != 0) {
287 /* XXX could it be another type of error? */
288 err_errno(OverflowError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000289 return NULL;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000290 }
291 return newfloatobject(ix);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000292}
293
294static object *
295float_neg(v)
296 floatobject *v;
297{
298 return newfloatobject(-v->ob_fval);
299}
300
301static object *
302float_pos(v)
303 floatobject *v;
304{
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000305 INCREF(v);
306 return (object *)v;
307}
308
309static object *
310float_abs(v)
311 floatobject *v;
312{
313 if (v->ob_fval < 0)
314 return float_neg(v);
315 else
316 return float_pos(v);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000317}
318
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000319static int
320float_nonzero(v)
321 floatobject *v;
322{
323 return v->ob_fval != 0.0;
324}
325
Guido van Rossume6eefc21992-08-14 12:06:52 +0000326int
327float_coerce(pv, pw)
328 object **pv;
329 object **pw;
330{
331 if (is_intobject(*pw)) {
332 long x = getintvalue(*pw);
333 *pw = newfloatobject((double)x);
334 INCREF(*pv);
335 return 0;
336 }
337 else if (is_longobject(*pw)) {
338 *pw = newfloatobject(dgetlongvalue(*pw));
339 INCREF(*pv);
340 return 0;
341 }
342 return 1; /* Can't do it */
343}
344
Guido van Rossum1899c2e1992-09-12 11:09:23 +0000345static object *
346float_int(v)
347 object *v;
348{
349 double x = getfloatvalue(v);
350 /* XXX should check for overflow */
351 /* XXX should define how we round */
352 return newintobject((long)x);
353}
354
355static object *
356float_long(v)
357 object *v;
358{
359 double x = getfloatvalue(v);
360 return dnewlongobject(x);
361}
362
363static object *
364float_float(v)
365 object *v;
366{
367 INCREF(v);
368 return v;
369}
370
371
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000372static number_methods float_as_number = {
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000373 float_add, /*nb_add*/
374 float_sub, /*nb_subtract*/
375 float_mul, /*nb_multiply*/
376 float_div, /*nb_divide*/
377 float_rem, /*nb_remainder*/
378 float_divmod, /*nb_divmod*/
379 float_pow, /*nb_power*/
380 float_neg, /*nb_negative*/
381 float_pos, /*nb_positive*/
382 float_abs, /*nb_absolute*/
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000383 float_nonzero, /*nb_nonzero*/
Guido van Rossum27acb331991-10-24 14:55:28 +0000384 0, /*nb_invert*/
385 0, /*nb_lshift*/
386 0, /*nb_rshift*/
387 0, /*nb_and*/
388 0, /*nb_xor*/
389 0, /*nb_or*/
Guido van Rossume6eefc21992-08-14 12:06:52 +0000390 float_coerce, /*nb_coerce*/
Guido van Rossum1899c2e1992-09-12 11:09:23 +0000391 float_int, /*nb_int*/
392 float_long, /*nb_long*/
393 float_float, /*nb_float*/
394 0, /*nb_oct*/
395 0, /*nb_hex*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000396};
397
398typeobject Floattype = {
399 OB_HEAD_INIT(&Typetype)
400 0,
401 "float",
402 sizeof(floatobject),
403 0,
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000404 float_dealloc, /*tp_dealloc*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000405 float_print, /*tp_print*/
406 0, /*tp_getattr*/
407 0, /*tp_setattr*/
408 float_compare, /*tp_compare*/
409 float_repr, /*tp_repr*/
410 &float_as_number, /*tp_as_number*/
411 0, /*tp_as_sequence*/
412 0, /*tp_as_mapping*/
Guido van Rossum9bfef441993-03-29 10:43:31 +0000413 float_hash, /*tp_hash */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000414};