blob: e5635837d075f4a95f56e5e7af31f29237a87a4d [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
148static object *
149float_add(v, w)
150 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000151 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000152{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000153 return newfloatobject(v->ob_fval + w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000154}
155
156static object *
157float_sub(v, w)
158 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000159 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000160{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000161 return newfloatobject(v->ob_fval - w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000162}
163
164static object *
165float_mul(v, w)
166 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000167 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000168{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000169 return newfloatobject(v->ob_fval * w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000170}
171
172static object *
173float_div(v, w)
174 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000175 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000176{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000177 if (w->ob_fval == 0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000178 err_setstr(ZeroDivisionError, "float division");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000179 return NULL;
180 }
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000181 return newfloatobject(v->ob_fval / w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000182}
183
184static object *
185float_rem(v, w)
186 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000187 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000188{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000189 double vx, wx;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000190 double /* div, */ mod;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000191 wx = w->ob_fval;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000192 if (wx == 0.0) {
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000193 err_setstr(ZeroDivisionError, "float modulo");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000194 return NULL;
195 }
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000196 vx = v->ob_fval;
197 mod = fmod(vx, wx);
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000198 /* div = (vx - mod) / wx; */
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000199 if (wx*mod < 0) {
200 mod += wx;
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000201 /* div -= 1.0; */
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000202 }
203 return newfloatobject(mod);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000204}
205
206static object *
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000207float_divmod(v, w)
208 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000209 floatobject *w;
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000210{
Guido van Rossum15ecff41991-10-20 20:16:45 +0000211 double vx, wx;
212 double div, mod;
213 object *t;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000214 wx = w->ob_fval;
Guido van Rossum15ecff41991-10-20 20:16:45 +0000215 if (wx == 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000216 err_setstr(ZeroDivisionError, "float divmod()");
Guido van Rossum15ecff41991-10-20 20:16:45 +0000217 return NULL;
218 }
219 vx = v->ob_fval;
220 mod = fmod(vx, wx);
221 div = (vx - mod) / wx;
222 if (wx*mod < 0) {
223 mod += wx;
224 div -= 1.0;
225 }
Guido van Rossume5372401993-03-16 12:15:04 +0000226 return mkvalue("(dd)", div, mod);
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000227}
228
229static object *
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000230float_pow(v, w)
231 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000232 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000233{
234 double iv, iw, ix;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000235 iv = v->ob_fval;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000236 iw = w->ob_fval;
Guido van Rossum70d93461991-05-28 21:57:39 +0000237 /* Sort out special cases here instead of relying on pow() */
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000238 if (iw == 0.0)
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000239 return newfloatobject(1.0); /* x**0 is 1, even 0**0 */
Guido van Rossum70d93461991-05-28 21:57:39 +0000240 if (iv == 0.0) {
241 if (iw < 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000242 err_setstr(ValueError, "0.0 to the negative power");
Guido van Rossum70d93461991-05-28 21:57:39 +0000243 return NULL;
244 }
245 return newfloatobject(0.0);
246 }
247 if (iv < 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000248 err_setstr(ValueError, "negative float to float power");
Guido van Rossum70d93461991-05-28 21:57:39 +0000249 return NULL;
250 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000251 errno = 0;
252 ix = pow(iv, iw);
Guido van Rossum7fa52f81991-12-16 15:43:14 +0000253 CHECK(ix);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000254 if (errno != 0) {
255 /* XXX could it be another type of error? */
256 err_errno(OverflowError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000257 return NULL;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000258 }
259 return newfloatobject(ix);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000260}
261
262static object *
263float_neg(v)
264 floatobject *v;
265{
266 return newfloatobject(-v->ob_fval);
267}
268
269static object *
270float_pos(v)
271 floatobject *v;
272{
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000273 INCREF(v);
274 return (object *)v;
275}
276
277static object *
278float_abs(v)
279 floatobject *v;
280{
281 if (v->ob_fval < 0)
282 return float_neg(v);
283 else
284 return float_pos(v);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000285}
286
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000287static int
288float_nonzero(v)
289 floatobject *v;
290{
291 return v->ob_fval != 0.0;
292}
293
Guido van Rossume6eefc21992-08-14 12:06:52 +0000294int
295float_coerce(pv, pw)
296 object **pv;
297 object **pw;
298{
299 if (is_intobject(*pw)) {
300 long x = getintvalue(*pw);
301 *pw = newfloatobject((double)x);
302 INCREF(*pv);
303 return 0;
304 }
305 else if (is_longobject(*pw)) {
306 *pw = newfloatobject(dgetlongvalue(*pw));
307 INCREF(*pv);
308 return 0;
309 }
310 return 1; /* Can't do it */
311}
312
Guido van Rossum1899c2e1992-09-12 11:09:23 +0000313static object *
314float_int(v)
315 object *v;
316{
317 double x = getfloatvalue(v);
318 /* XXX should check for overflow */
319 /* XXX should define how we round */
320 return newintobject((long)x);
321}
322
323static object *
324float_long(v)
325 object *v;
326{
327 double x = getfloatvalue(v);
328 return dnewlongobject(x);
329}
330
331static object *
332float_float(v)
333 object *v;
334{
335 INCREF(v);
336 return v;
337}
338
339
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000340static number_methods float_as_number = {
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000341 float_add, /*nb_add*/
342 float_sub, /*nb_subtract*/
343 float_mul, /*nb_multiply*/
344 float_div, /*nb_divide*/
345 float_rem, /*nb_remainder*/
346 float_divmod, /*nb_divmod*/
347 float_pow, /*nb_power*/
348 float_neg, /*nb_negative*/
349 float_pos, /*nb_positive*/
350 float_abs, /*nb_absolute*/
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000351 float_nonzero, /*nb_nonzero*/
Guido van Rossum27acb331991-10-24 14:55:28 +0000352 0, /*nb_invert*/
353 0, /*nb_lshift*/
354 0, /*nb_rshift*/
355 0, /*nb_and*/
356 0, /*nb_xor*/
357 0, /*nb_or*/
Guido van Rossume6eefc21992-08-14 12:06:52 +0000358 float_coerce, /*nb_coerce*/
Guido van Rossum1899c2e1992-09-12 11:09:23 +0000359 float_int, /*nb_int*/
360 float_long, /*nb_long*/
361 float_float, /*nb_float*/
362 0, /*nb_oct*/
363 0, /*nb_hex*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000364};
365
366typeobject Floattype = {
367 OB_HEAD_INIT(&Typetype)
368 0,
369 "float",
370 sizeof(floatobject),
371 0,
Guido van Rossum3132a5a1992-03-27 17:28:44 +0000372 float_dealloc, /*tp_dealloc*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000373 float_print, /*tp_print*/
374 0, /*tp_getattr*/
375 0, /*tp_setattr*/
376 float_compare, /*tp_compare*/
377 float_repr, /*tp_repr*/
378 &float_as_number, /*tp_as_number*/
379 0, /*tp_as_sequence*/
380 0, /*tp_as_mapping*/
381};