blob: 43cefda562cd4f0cbd25acb6058dd99f4d0db5bb [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
2Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
3Netherlands.
4
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 Rossum85a5fbb1990-10-14 12:07:46 +000031
Guido van Rossumc211ee41990-12-20 23:06:26 +000032#include <errno.h>
33#ifndef errno
34extern int errno;
35#endif
36
Guido van Rossum3f5da241990-12-20 15:06:42 +000037#include <ctype.h>
38#include <math.h>
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000039
Guido van Rossum7fa52f81991-12-16 15:43:14 +000040#ifdef HUGE_VAL
41#define CHECK(x) if (errno != 0) ; \
42 else if (-HUGE_VAL <= (x) && (x) <= HUGE_VAL) ; \
43 else errno = ERANGE
44#else
45#define CHECK(x) /* Don't know how to check */
46#endif
47
Guido van Rossum6923e131990-11-02 17:50:43 +000048#ifndef THINK_C
49extern double fmod PROTO((double, double));
50extern double pow PROTO((double, double));
51#endif
52
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000053object *
54newfloatobject(fval)
55 double fval;
56{
57 /* For efficiency, this code is copied from newobject() */
58 register floatobject *op = (floatobject *) malloc(sizeof(floatobject));
Guido van Rossum2a9096b1990-10-21 22:15:08 +000059 if (op == NULL)
60 return err_nomem();
61 NEWREF(op);
62 op->ob_type = &Floattype;
63 op->ob_fval = fval;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000064 return (object *) op;
65}
66
67double
68getfloatvalue(op)
69 object *op;
70{
71 if (!is_floatobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000072 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000073 return -1;
74 }
75 else
76 return ((floatobject *)op) -> ob_fval;
77}
78
79/* Methods */
80
Guido van Rossum27dec7e1991-06-04 19:42:53 +000081void
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000082float_buf_repr(buf, v)
83 char *buf;
84 floatobject *v;
85{
86 register char *cp;
87 /* Subroutine for float_repr and float_print.
88 We want float numbers to be recognizable as such,
89 i.e., they should contain a decimal point or an exponent.
90 However, %g may print the number as an integer;
91 in such cases, we append ".0" to the string. */
92 sprintf(buf, "%.12g", v->ob_fval);
93 cp = buf;
94 if (*cp == '-')
95 cp++;
96 for (; *cp != '\0'; cp++) {
97 /* Any non-digit means it's not an integer;
98 this takes care of NAN and INF as well. */
99 if (!isdigit(*cp))
100 break;
101 }
102 if (*cp == '\0') {
103 *cp++ = '.';
104 *cp++ = '0';
105 *cp++ = '\0';
106 }
107}
108
Guido van Rossum90933611991-06-07 16:10:43 +0000109static int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000110float_print(v, fp, flags)
111 floatobject *v;
112 FILE *fp;
113 int flags;
114{
115 char buf[100];
116 float_buf_repr(buf, v);
117 fputs(buf, fp);
Guido van Rossum90933611991-06-07 16:10:43 +0000118 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000119}
120
121static object *
122float_repr(v)
123 floatobject *v;
124{
125 char buf[100];
126 float_buf_repr(buf, v);
127 return newstringobject(buf);
128}
129
130static int
131float_compare(v, w)
132 floatobject *v, *w;
133{
134 double i = v->ob_fval;
135 double j = w->ob_fval;
136 return (i < j) ? -1 : (i > j) ? 1 : 0;
137}
138
139static object *
140float_add(v, w)
141 floatobject *v;
142 object *w;
143{
144 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000145 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000146 return NULL;
147 }
148 return newfloatobject(v->ob_fval + ((floatobject *)w) -> ob_fval);
149}
150
151static object *
152float_sub(v, w)
153 floatobject *v;
154 object *w;
155{
156 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000157 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000158 return NULL;
159 }
160 return newfloatobject(v->ob_fval - ((floatobject *)w) -> ob_fval);
161}
162
163static object *
164float_mul(v, w)
165 floatobject *v;
166 object *w;
167{
168 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000169 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000170 return NULL;
171 }
172 return newfloatobject(v->ob_fval * ((floatobject *)w) -> ob_fval);
173}
174
175static object *
176float_div(v, w)
177 floatobject *v;
178 object *w;
179{
180 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000181 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000182 return NULL;
183 }
184 if (((floatobject *)w) -> ob_fval == 0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000185 err_setstr(ZeroDivisionError, "float division");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000186 return NULL;
187 }
188 return newfloatobject(v->ob_fval / ((floatobject *)w) -> ob_fval);
189}
190
191static object *
192float_rem(v, w)
193 floatobject *v;
194 object *w;
195{
196 double wx;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000197 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000198 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000199 return NULL;
200 }
201 wx = ((floatobject *)w) -> ob_fval;
202 if (wx == 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000203 err_setstr(ZeroDivisionError, "float remainder");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000204 return NULL;
205 }
206 return newfloatobject(fmod(v->ob_fval, wx));
207}
208
209static object *
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000210float_divmod(v, w)
211 floatobject *v;
212 object *w;
213{
Guido van Rossum15ecff41991-10-20 20:16:45 +0000214 double vx, wx;
215 double div, mod;
216 object *t;
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000217 if (!is_floatobject(w)) {
218 err_badarg();
219 return NULL;
220 }
Guido van Rossum15ecff41991-10-20 20:16:45 +0000221 wx = ((floatobject *)w) -> ob_fval;
222 if (wx == 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000223 err_setstr(ZeroDivisionError, "float divmod()");
Guido van Rossum15ecff41991-10-20 20:16:45 +0000224 return NULL;
225 }
226 vx = v->ob_fval;
227 mod = fmod(vx, wx);
228 div = (vx - mod) / wx;
229 if (wx*mod < 0) {
230 mod += wx;
231 div -= 1.0;
232 }
233 t = newtupleobject(2);
234 if (t != NULL) {
235 settupleitem(t, 0, newfloatobject(div));
236 settupleitem(t, 1, newfloatobject(mod));
237 if (err_occurred()) {
238 DECREF(t);
239 t = NULL;
240 }
241 }
242 return t;
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000243}
244
245static object *
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000246float_pow(v, w)
247 floatobject *v;
248 object *w;
249{
250 double iv, iw, ix;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000251 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000252 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000253 return NULL;
254 }
255 iv = v->ob_fval;
256 iw = ((floatobject *)w)->ob_fval;
Guido van Rossum70d93461991-05-28 21:57:39 +0000257 /* Sort out special cases here instead of relying on pow() */
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000258 if (iw == 0.0)
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000259 return newfloatobject(1.0); /* x**0 is 1, even 0**0 */
Guido van Rossum70d93461991-05-28 21:57:39 +0000260 if (iv == 0.0) {
261 if (iw < 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000262 err_setstr(ValueError, "0.0 to the negative power");
Guido van Rossum70d93461991-05-28 21:57:39 +0000263 return NULL;
264 }
265 return newfloatobject(0.0);
266 }
267 if (iv < 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000268 err_setstr(ValueError, "negative float to float power");
Guido van Rossum70d93461991-05-28 21:57:39 +0000269 return NULL;
270 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000271 errno = 0;
272 ix = pow(iv, iw);
Guido van Rossum7fa52f81991-12-16 15:43:14 +0000273 CHECK(ix);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000274 if (errno != 0) {
275 /* XXX could it be another type of error? */
276 err_errno(OverflowError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000277 return NULL;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000278 }
279 return newfloatobject(ix);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000280}
281
282static object *
283float_neg(v)
284 floatobject *v;
285{
286 return newfloatobject(-v->ob_fval);
287}
288
289static object *
290float_pos(v)
291 floatobject *v;
292{
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000293 INCREF(v);
294 return (object *)v;
295}
296
297static object *
298float_abs(v)
299 floatobject *v;
300{
301 if (v->ob_fval < 0)
302 return float_neg(v);
303 else
304 return float_pos(v);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000305}
306
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000307static int
308float_nonzero(v)
309 floatobject *v;
310{
311 return v->ob_fval != 0.0;
312}
313
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000314static number_methods float_as_number = {
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000315 float_add, /*nb_add*/
316 float_sub, /*nb_subtract*/
317 float_mul, /*nb_multiply*/
318 float_div, /*nb_divide*/
319 float_rem, /*nb_remainder*/
320 float_divmod, /*nb_divmod*/
321 float_pow, /*nb_power*/
322 float_neg, /*nb_negative*/
323 float_pos, /*nb_positive*/
324 float_abs, /*nb_absolute*/
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000325 float_nonzero, /*nb_nonzero*/
Guido van Rossum27acb331991-10-24 14:55:28 +0000326 0, /*nb_invert*/
327 0, /*nb_lshift*/
328 0, /*nb_rshift*/
329 0, /*nb_and*/
330 0, /*nb_xor*/
331 0, /*nb_or*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000332};
333
334typeobject Floattype = {
335 OB_HEAD_INIT(&Typetype)
336 0,
337 "float",
338 sizeof(floatobject),
339 0,
340 free, /*tp_dealloc*/
341 float_print, /*tp_print*/
342 0, /*tp_getattr*/
343 0, /*tp_setattr*/
344 float_compare, /*tp_compare*/
345 float_repr, /*tp_repr*/
346 &float_as_number, /*tp_as_number*/
347 0, /*tp_as_sequence*/
348 0, /*tp_as_mapping*/
349};
350
351/*
352XXX This is not enough. Need:
353- automatic casts for mixed arithmetic (3.1 * 4)
354- mixed comparisons (!)
355- look at other uses of ints that could be extended to floats
356*/