blob: cd7d084c7529401bae508ddbac0dd7504d95bc22 [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
101static void
102float_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);
110}
111
112static object *
113float_repr(v)
114 floatobject *v;
115{
116 char buf[100];
117 float_buf_repr(buf, v);
118 return newstringobject(buf);
119}
120
121static int
122float_compare(v, w)
123 floatobject *v, *w;
124{
125 double i = v->ob_fval;
126 double j = w->ob_fval;
127 return (i < j) ? -1 : (i > j) ? 1 : 0;
128}
129
130static object *
131float_add(v, w)
132 floatobject *v;
133 object *w;
134{
135 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000136 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000137 return NULL;
138 }
139 return newfloatobject(v->ob_fval + ((floatobject *)w) -> ob_fval);
140}
141
142static object *
143float_sub(v, w)
144 floatobject *v;
145 object *w;
146{
147 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000148 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000149 return NULL;
150 }
151 return newfloatobject(v->ob_fval - ((floatobject *)w) -> ob_fval);
152}
153
154static object *
155float_mul(v, w)
156 floatobject *v;
157 object *w;
158{
159 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000160 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000161 return NULL;
162 }
163 return newfloatobject(v->ob_fval * ((floatobject *)w) -> ob_fval);
164}
165
166static object *
167float_div(v, w)
168 floatobject *v;
169 object *w;
170{
171 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000172 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000173 return NULL;
174 }
175 if (((floatobject *)w) -> ob_fval == 0) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000176 err_setstr(ZeroDivisionError, "float division by zero");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000177 return NULL;
178 }
179 return newfloatobject(v->ob_fval / ((floatobject *)w) -> ob_fval);
180}
181
182static object *
183float_rem(v, w)
184 floatobject *v;
185 object *w;
186{
187 double wx;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000188 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000189 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000190 return NULL;
191 }
192 wx = ((floatobject *)w) -> ob_fval;
193 if (wx == 0.0) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000194 err_setstr(ZeroDivisionError, "float division by zero");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000195 return NULL;
196 }
197 return newfloatobject(fmod(v->ob_fval, wx));
198}
199
200static object *
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000201float_divmod(v, w)
202 floatobject *v;
203 object *w;
204{
205 double wx;
206 if (!is_floatobject(w)) {
207 err_badarg();
208 return NULL;
209 }
210 err_setstr(RuntimeError, "divmod() on float not implemented");
211 return NULL;
212}
213
214static object *
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000215float_pow(v, w)
216 floatobject *v;
217 object *w;
218{
219 double iv, iw, ix;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000220 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000221 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000222 return NULL;
223 }
224 iv = v->ob_fval;
225 iw = ((floatobject *)w)->ob_fval;
Guido van Rossum70d93461991-05-28 21:57:39 +0000226 /* Sort out special cases here instead of relying on pow() */
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000227 if (iw == 0.0)
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000228 return newfloatobject(1.0); /* x**0 is 1, even 0**0 */
Guido van Rossum70d93461991-05-28 21:57:39 +0000229 if (iv == 0.0) {
230 if (iw < 0.0) {
231 err_setstr(RuntimeError, "0.0 to the negative power");
232 return NULL;
233 }
234 return newfloatobject(0.0);
235 }
236 if (iv < 0.0) {
237 err_setstr(RuntimeError, "negative float to float power");
238 return NULL;
239 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000240 errno = 0;
241 ix = pow(iv, iw);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000242 if (errno != 0) {
243 /* XXX could it be another type of error? */
244 err_errno(OverflowError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000245 return NULL;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000246 }
247 return newfloatobject(ix);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000248}
249
250static object *
251float_neg(v)
252 floatobject *v;
253{
254 return newfloatobject(-v->ob_fval);
255}
256
257static object *
258float_pos(v)
259 floatobject *v;
260{
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000261 INCREF(v);
262 return (object *)v;
263}
264
265static object *
266float_abs(v)
267 floatobject *v;
268{
269 if (v->ob_fval < 0)
270 return float_neg(v);
271 else
272 return float_pos(v);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000273}
274
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000275static int
276float_nonzero(v)
277 floatobject *v;
278{
279 return v->ob_fval != 0.0;
280}
281
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000282static number_methods float_as_number = {
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000283 float_add, /*nb_add*/
284 float_sub, /*nb_subtract*/
285 float_mul, /*nb_multiply*/
286 float_div, /*nb_divide*/
287 float_rem, /*nb_remainder*/
288 float_divmod, /*nb_divmod*/
289 float_pow, /*nb_power*/
290 float_neg, /*nb_negative*/
291 float_pos, /*nb_positive*/
292 float_abs, /*nb_absolute*/
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000293 float_nonzero, /*nb_nonzero*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000294};
295
296typeobject Floattype = {
297 OB_HEAD_INIT(&Typetype)
298 0,
299 "float",
300 sizeof(floatobject),
301 0,
302 free, /*tp_dealloc*/
303 float_print, /*tp_print*/
304 0, /*tp_getattr*/
305 0, /*tp_setattr*/
306 float_compare, /*tp_compare*/
307 float_repr, /*tp_repr*/
308 &float_as_number, /*tp_as_number*/
309 0, /*tp_as_sequence*/
310 0, /*tp_as_mapping*/
311};
312
313/*
314XXX This is not enough. Need:
315- automatic casts for mixed arithmetic (3.1 * 4)
316- mixed comparisons (!)
317- look at other uses of ints that could be extended to floats
318*/