blob: 5249db7f247e13f0cdaa8ae43df2962935549de7 [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
73static void
74float_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 Rossum2a9096b1990-10-21 22:15:08 +0000226 if (iw == 0.0)
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000227 return newfloatobject(1.0); /* x**0 is 1, even 0**0 */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000228 errno = 0;
229 ix = pow(iv, iw);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000230 if (errno != 0) {
231 /* XXX could it be another type of error? */
232 err_errno(OverflowError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000233 return NULL;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000234 }
235 return newfloatobject(ix);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000236}
237
238static object *
239float_neg(v)
240 floatobject *v;
241{
242 return newfloatobject(-v->ob_fval);
243}
244
245static object *
246float_pos(v)
247 floatobject *v;
248{
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000249 INCREF(v);
250 return (object *)v;
251}
252
253static object *
254float_abs(v)
255 floatobject *v;
256{
257 if (v->ob_fval < 0)
258 return float_neg(v);
259 else
260 return float_pos(v);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000261}
262
263static number_methods float_as_number = {
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000264 float_add, /*nb_add*/
265 float_sub, /*nb_subtract*/
266 float_mul, /*nb_multiply*/
267 float_div, /*nb_divide*/
268 float_rem, /*nb_remainder*/
269 float_divmod, /*nb_divmod*/
270 float_pow, /*nb_power*/
271 float_neg, /*nb_negative*/
272 float_pos, /*nb_positive*/
273 float_abs, /*nb_absolute*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000274};
275
276typeobject Floattype = {
277 OB_HEAD_INIT(&Typetype)
278 0,
279 "float",
280 sizeof(floatobject),
281 0,
282 free, /*tp_dealloc*/
283 float_print, /*tp_print*/
284 0, /*tp_getattr*/
285 0, /*tp_setattr*/
286 float_compare, /*tp_compare*/
287 float_repr, /*tp_repr*/
288 &float_as_number, /*tp_as_number*/
289 0, /*tp_as_sequence*/
290 0, /*tp_as_mapping*/
291};
292
293/*
294XXX This is not enough. Need:
295- automatic casts for mixed arithmetic (3.1 * 4)
296- mixed comparisons (!)
297- look at other uses of ints that could be extended to floats
298*/