blob: bbf785f03c26f6a42b07f268ecbd1627479e88aa [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 *
201float_pow(v, w)
202 floatobject *v;
203 object *w;
204{
205 double iv, iw, ix;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000206 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000207 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000208 return NULL;
209 }
210 iv = v->ob_fval;
211 iw = ((floatobject *)w)->ob_fval;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000212 if (iw == 0.0)
213 return newfloatobject(1.0); /* x**0 is always 1, even 0**0 */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000214 errno = 0;
215 ix = pow(iv, iw);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000216 if (errno != 0) {
217 /* XXX could it be another type of error? */
218 err_errno(OverflowError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000219 return NULL;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000220 }
221 return newfloatobject(ix);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000222}
223
224static object *
225float_neg(v)
226 floatobject *v;
227{
228 return newfloatobject(-v->ob_fval);
229}
230
231static object *
232float_pos(v)
233 floatobject *v;
234{
235 return newfloatobject(v->ob_fval);
236}
237
238static number_methods float_as_number = {
239 float_add, /*tp_add*/
240 float_sub, /*tp_subtract*/
241 float_mul, /*tp_multiply*/
242 float_div, /*tp_divide*/
243 float_rem, /*tp_remainder*/
244 float_pow, /*tp_power*/
245 float_neg, /*tp_negate*/
246 float_pos, /*tp_plus*/
247};
248
249typeobject Floattype = {
250 OB_HEAD_INIT(&Typetype)
251 0,
252 "float",
253 sizeof(floatobject),
254 0,
255 free, /*tp_dealloc*/
256 float_print, /*tp_print*/
257 0, /*tp_getattr*/
258 0, /*tp_setattr*/
259 float_compare, /*tp_compare*/
260 float_repr, /*tp_repr*/
261 &float_as_number, /*tp_as_number*/
262 0, /*tp_as_sequence*/
263 0, /*tp_as_mapping*/
264};
265
266/*
267XXX This is not enough. Need:
268- automatic casts for mixed arithmetic (3.1 * 4)
269- mixed comparisons (!)
270- look at other uses of ints that could be extended to floats
271*/