blob: a386e0c2f15eacacdbaa8168097766a1d0690fa9 [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 Rossum6923e131990-11-02 17:50:43 +000040#ifndef THINK_C
41extern double fmod PROTO((double, double));
42extern double pow PROTO((double, double));
43#endif
44
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000045object *
46newfloatobject(fval)
47 double fval;
48{
49 /* For efficiency, this code is copied from newobject() */
50 register floatobject *op = (floatobject *) malloc(sizeof(floatobject));
Guido van Rossum2a9096b1990-10-21 22:15:08 +000051 if (op == NULL)
52 return err_nomem();
53 NEWREF(op);
54 op->ob_type = &Floattype;
55 op->ob_fval = fval;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000056 return (object *) op;
57}
58
59double
60getfloatvalue(op)
61 object *op;
62{
63 if (!is_floatobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000064 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000065 return -1;
66 }
67 else
68 return ((floatobject *)op) -> ob_fval;
69}
70
71/* Methods */
72
Guido van Rossum27dec7e1991-06-04 19:42:53 +000073void
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000074float_buf_repr(buf, v)
75 char *buf;
76 floatobject *v;
77{
78 register char *cp;
79 /* Subroutine for float_repr and float_print.
80 We want float numbers to be recognizable as such,
81 i.e., they should contain a decimal point or an exponent.
82 However, %g may print the number as an integer;
83 in such cases, we append ".0" to the string. */
84 sprintf(buf, "%.12g", v->ob_fval);
85 cp = buf;
86 if (*cp == '-')
87 cp++;
88 for (; *cp != '\0'; cp++) {
89 /* Any non-digit means it's not an integer;
90 this takes care of NAN and INF as well. */
91 if (!isdigit(*cp))
92 break;
93 }
94 if (*cp == '\0') {
95 *cp++ = '.';
96 *cp++ = '0';
97 *cp++ = '\0';
98 }
99}
100
Guido van Rossum90933611991-06-07 16:10:43 +0000101static int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000102float_print(v, fp, flags)
103 floatobject *v;
104 FILE *fp;
105 int flags;
106{
107 char buf[100];
108 float_buf_repr(buf, v);
109 fputs(buf, fp);
Guido van Rossum90933611991-06-07 16:10:43 +0000110 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000111}
112
113static object *
114float_repr(v)
115 floatobject *v;
116{
117 char buf[100];
118 float_buf_repr(buf, v);
119 return newstringobject(buf);
120}
121
122static int
123float_compare(v, w)
124 floatobject *v, *w;
125{
126 double i = v->ob_fval;
127 double j = w->ob_fval;
128 return (i < j) ? -1 : (i > j) ? 1 : 0;
129}
130
131static object *
132float_add(v, w)
133 floatobject *v;
134 object *w;
135{
136 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000137 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000138 return NULL;
139 }
140 return newfloatobject(v->ob_fval + ((floatobject *)w) -> ob_fval);
141}
142
143static object *
144float_sub(v, w)
145 floatobject *v;
146 object *w;
147{
148 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000149 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000150 return NULL;
151 }
152 return newfloatobject(v->ob_fval - ((floatobject *)w) -> ob_fval);
153}
154
155static object *
156float_mul(v, w)
157 floatobject *v;
158 object *w;
159{
160 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000161 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000162 return NULL;
163 }
164 return newfloatobject(v->ob_fval * ((floatobject *)w) -> ob_fval);
165}
166
167static object *
168float_div(v, w)
169 floatobject *v;
170 object *w;
171{
172 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000173 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000174 return NULL;
175 }
176 if (((floatobject *)w) -> ob_fval == 0) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000177 err_setstr(ZeroDivisionError, "float division by zero");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000178 return NULL;
179 }
180 return newfloatobject(v->ob_fval / ((floatobject *)w) -> ob_fval);
181}
182
183static object *
184float_rem(v, w)
185 floatobject *v;
186 object *w;
187{
188 double wx;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000189 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000190 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000191 return NULL;
192 }
193 wx = ((floatobject *)w) -> ob_fval;
194 if (wx == 0.0) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000195 err_setstr(ZeroDivisionError, "float division by zero");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000196 return NULL;
197 }
198 return newfloatobject(fmod(v->ob_fval, wx));
199}
200
201static object *
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000202float_divmod(v, w)
203 floatobject *v;
204 object *w;
205{
206 double wx;
207 if (!is_floatobject(w)) {
208 err_badarg();
209 return NULL;
210 }
211 err_setstr(RuntimeError, "divmod() on float not implemented");
212 return NULL;
213}
214
215static object *
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000216float_pow(v, w)
217 floatobject *v;
218 object *w;
219{
220 double iv, iw, ix;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000221 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000222 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000223 return NULL;
224 }
225 iv = v->ob_fval;
226 iw = ((floatobject *)w)->ob_fval;
Guido van Rossum70d93461991-05-28 21:57:39 +0000227 /* Sort out special cases here instead of relying on pow() */
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000228 if (iw == 0.0)
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000229 return newfloatobject(1.0); /* x**0 is 1, even 0**0 */
Guido van Rossum70d93461991-05-28 21:57:39 +0000230 if (iv == 0.0) {
231 if (iw < 0.0) {
232 err_setstr(RuntimeError, "0.0 to the negative power");
233 return NULL;
234 }
235 return newfloatobject(0.0);
236 }
237 if (iv < 0.0) {
238 err_setstr(RuntimeError, "negative float to float power");
239 return NULL;
240 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000241 errno = 0;
242 ix = pow(iv, iw);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000243 if (errno != 0) {
244 /* XXX could it be another type of error? */
245 err_errno(OverflowError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000246 return NULL;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000247 }
248 return newfloatobject(ix);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000249}
250
251static object *
252float_neg(v)
253 floatobject *v;
254{
255 return newfloatobject(-v->ob_fval);
256}
257
258static object *
259float_pos(v)
260 floatobject *v;
261{
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000262 INCREF(v);
263 return (object *)v;
264}
265
266static object *
267float_abs(v)
268 floatobject *v;
269{
270 if (v->ob_fval < 0)
271 return float_neg(v);
272 else
273 return float_pos(v);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000274}
275
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000276static int
277float_nonzero(v)
278 floatobject *v;
279{
280 return v->ob_fval != 0.0;
281}
282
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000283static number_methods float_as_number = {
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000284 float_add, /*nb_add*/
285 float_sub, /*nb_subtract*/
286 float_mul, /*nb_multiply*/
287 float_div, /*nb_divide*/
288 float_rem, /*nb_remainder*/
289 float_divmod, /*nb_divmod*/
290 float_pow, /*nb_power*/
291 float_neg, /*nb_negative*/
292 float_pos, /*nb_positive*/
293 float_abs, /*nb_absolute*/
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000294 float_nonzero, /*nb_nonzero*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000295};
296
297typeobject Floattype = {
298 OB_HEAD_INIT(&Typetype)
299 0,
300 "float",
301 sizeof(floatobject),
302 0,
303 free, /*tp_dealloc*/
304 float_print, /*tp_print*/
305 0, /*tp_getattr*/
306 0, /*tp_setattr*/
307 float_compare, /*tp_compare*/
308 float_repr, /*tp_repr*/
309 &float_as_number, /*tp_as_number*/
310 0, /*tp_as_sequence*/
311 0, /*tp_as_mapping*/
312};
313
314/*
315XXX This is not enough. Need:
316- automatic casts for mixed arithmetic (3.1 * 4)
317- mixed comparisons (!)
318- look at other uses of ints that could be extended to floats
319*/