blob: 0966752313888feca4c4416adaed42a1e378f68a [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{
Guido van Rossum15ecff41991-10-20 20:16:45 +0000206 double vx, wx;
207 double div, mod;
208 object *t;
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000209 if (!is_floatobject(w)) {
210 err_badarg();
211 return NULL;
212 }
Guido van Rossum15ecff41991-10-20 20:16:45 +0000213 wx = ((floatobject *)w) -> ob_fval;
214 if (wx == 0.0) {
215 err_setstr(ZeroDivisionError, "float division by zero");
216 return NULL;
217 }
218 vx = v->ob_fval;
219 mod = fmod(vx, wx);
220 div = (vx - mod) / wx;
221 if (wx*mod < 0) {
222 mod += wx;
223 div -= 1.0;
224 }
225 t = newtupleobject(2);
226 if (t != NULL) {
227 settupleitem(t, 0, newfloatobject(div));
228 settupleitem(t, 1, newfloatobject(mod));
229 if (err_occurred()) {
230 DECREF(t);
231 t = NULL;
232 }
233 }
234 return t;
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000235}
236
237static object *
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000238float_pow(v, w)
239 floatobject *v;
240 object *w;
241{
242 double iv, iw, ix;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000243 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000244 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000245 return NULL;
246 }
247 iv = v->ob_fval;
248 iw = ((floatobject *)w)->ob_fval;
Guido van Rossum70d93461991-05-28 21:57:39 +0000249 /* Sort out special cases here instead of relying on pow() */
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000250 if (iw == 0.0)
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000251 return newfloatobject(1.0); /* x**0 is 1, even 0**0 */
Guido van Rossum70d93461991-05-28 21:57:39 +0000252 if (iv == 0.0) {
253 if (iw < 0.0) {
254 err_setstr(RuntimeError, "0.0 to the negative power");
255 return NULL;
256 }
257 return newfloatobject(0.0);
258 }
259 if (iv < 0.0) {
260 err_setstr(RuntimeError, "negative float to float power");
261 return NULL;
262 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000263 errno = 0;
264 ix = pow(iv, iw);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000265 if (errno != 0) {
266 /* XXX could it be another type of error? */
267 err_errno(OverflowError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000268 return NULL;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000269 }
270 return newfloatobject(ix);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000271}
272
273static object *
274float_neg(v)
275 floatobject *v;
276{
277 return newfloatobject(-v->ob_fval);
278}
279
280static object *
281float_pos(v)
282 floatobject *v;
283{
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000284 INCREF(v);
285 return (object *)v;
286}
287
288static object *
289float_abs(v)
290 floatobject *v;
291{
292 if (v->ob_fval < 0)
293 return float_neg(v);
294 else
295 return float_pos(v);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000296}
297
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000298static int
299float_nonzero(v)
300 floatobject *v;
301{
302 return v->ob_fval != 0.0;
303}
304
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000305static number_methods float_as_number = {
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000306 float_add, /*nb_add*/
307 float_sub, /*nb_subtract*/
308 float_mul, /*nb_multiply*/
309 float_div, /*nb_divide*/
310 float_rem, /*nb_remainder*/
311 float_divmod, /*nb_divmod*/
312 float_pow, /*nb_power*/
313 float_neg, /*nb_negative*/
314 float_pos, /*nb_positive*/
315 float_abs, /*nb_absolute*/
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000316 float_nonzero, /*nb_nonzero*/
Guido van Rossum27acb331991-10-24 14:55:28 +0000317 0, /*nb_invert*/
318 0, /*nb_lshift*/
319 0, /*nb_rshift*/
320 0, /*nb_and*/
321 0, /*nb_xor*/
322 0, /*nb_or*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000323};
324
325typeobject Floattype = {
326 OB_HEAD_INIT(&Typetype)
327 0,
328 "float",
329 sizeof(floatobject),
330 0,
331 free, /*tp_dealloc*/
332 float_print, /*tp_print*/
333 0, /*tp_getattr*/
334 0, /*tp_setattr*/
335 float_compare, /*tp_compare*/
336 float_repr, /*tp_repr*/
337 &float_as_number, /*tp_as_number*/
338 0, /*tp_as_sequence*/
339 0, /*tp_as_mapping*/
340};
341
342/*
343XXX This is not enough. Need:
344- automatic casts for mixed arithmetic (3.1 * 4)
345- mixed comparisons (!)
346- look at other uses of ints that could be extended to floats
347*/