blob: f176333758e62706d5819ad09b0e930f55027269 [file] [log] [blame]
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001/* Float object implementation */
2
3#include <stdio.h>
4#include <math.h>
5#include <ctype.h>
6
7#include "PROTO.h"
8#include "object.h"
9#include "floatobject.h"
10#include "stringobject.h"
11#include "objimpl.h"
12
13object *
14newfloatobject(fval)
15 double fval;
16{
17 /* For efficiency, this code is copied from newobject() */
18 register floatobject *op = (floatobject *) malloc(sizeof(floatobject));
19 if (op == NULL) {
20 errno = ENOMEM;
21 }
22 else {
23 NEWREF(op);
24 op->ob_type = &Floattype;
25 op->ob_fval = fval;
26 }
27 return (object *) op;
28}
29
30double
31getfloatvalue(op)
32 object *op;
33{
34 if (!is_floatobject(op)) {
35 errno = EBADF;
36 return -1;
37 }
38 else
39 return ((floatobject *)op) -> ob_fval;
40}
41
42/* Methods */
43
44static void
45float_buf_repr(buf, v)
46 char *buf;
47 floatobject *v;
48{
49 register char *cp;
50 /* Subroutine for float_repr and float_print.
51 We want float numbers to be recognizable as such,
52 i.e., they should contain a decimal point or an exponent.
53 However, %g may print the number as an integer;
54 in such cases, we append ".0" to the string. */
55 sprintf(buf, "%.12g", v->ob_fval);
56 cp = buf;
57 if (*cp == '-')
58 cp++;
59 for (; *cp != '\0'; cp++) {
60 /* Any non-digit means it's not an integer;
61 this takes care of NAN and INF as well. */
62 if (!isdigit(*cp))
63 break;
64 }
65 if (*cp == '\0') {
66 *cp++ = '.';
67 *cp++ = '0';
68 *cp++ = '\0';
69 }
70}
71
72static void
73float_print(v, fp, flags)
74 floatobject *v;
75 FILE *fp;
76 int flags;
77{
78 char buf[100];
79 float_buf_repr(buf, v);
80 fputs(buf, fp);
81}
82
83static object *
84float_repr(v)
85 floatobject *v;
86{
87 char buf[100];
88 float_buf_repr(buf, v);
89 return newstringobject(buf);
90}
91
92static int
93float_compare(v, w)
94 floatobject *v, *w;
95{
96 double i = v->ob_fval;
97 double j = w->ob_fval;
98 return (i < j) ? -1 : (i > j) ? 1 : 0;
99}
100
101static object *
102float_add(v, w)
103 floatobject *v;
104 object *w;
105{
106 if (!is_floatobject(w)) {
107 errno = EINVAL;
108 return NULL;
109 }
110 return newfloatobject(v->ob_fval + ((floatobject *)w) -> ob_fval);
111}
112
113static object *
114float_sub(v, w)
115 floatobject *v;
116 object *w;
117{
118 if (!is_floatobject(w)) {
119 errno = EINVAL;
120 return NULL;
121 }
122 return newfloatobject(v->ob_fval - ((floatobject *)w) -> ob_fval);
123}
124
125static object *
126float_mul(v, w)
127 floatobject *v;
128 object *w;
129{
130 if (!is_floatobject(w)) {
131 errno = EINVAL;
132 return NULL;
133 }
134 return newfloatobject(v->ob_fval * ((floatobject *)w) -> ob_fval);
135}
136
137static object *
138float_div(v, w)
139 floatobject *v;
140 object *w;
141{
142 if (!is_floatobject(w)) {
143 errno = EINVAL;
144 return NULL;
145 }
146 if (((floatobject *)w) -> ob_fval == 0) {
147 errno = EDOM;
148 return NULL;
149 }
150 return newfloatobject(v->ob_fval / ((floatobject *)w) -> ob_fval);
151}
152
153static object *
154float_rem(v, w)
155 floatobject *v;
156 object *w;
157{
158 double wx;
159 extern double fmod();
160 if (!is_floatobject(w)) {
161 errno = EINVAL;
162 return NULL;
163 }
164 wx = ((floatobject *)w) -> ob_fval;
165 if (wx == 0.0) {
166 errno = EDOM;
167 return NULL;
168 }
169 return newfloatobject(fmod(v->ob_fval, wx));
170}
171
172static object *
173float_pow(v, w)
174 floatobject *v;
175 object *w;
176{
177 double iv, iw, ix;
178 extern double pow();
179 if (!is_floatobject(w)) {
180 errno = EINVAL;
181 return NULL;
182 }
183 iv = v->ob_fval;
184 iw = ((floatobject *)w)->ob_fval;
185 errno = 0;
186 ix = pow(iv, iw);
187 if (errno != 0)
188 return NULL;
189 else
190 return newfloatobject(ix);
191}
192
193static object *
194float_neg(v)
195 floatobject *v;
196{
197 return newfloatobject(-v->ob_fval);
198}
199
200static object *
201float_pos(v)
202 floatobject *v;
203{
204 return newfloatobject(v->ob_fval);
205}
206
207static number_methods float_as_number = {
208 float_add, /*tp_add*/
209 float_sub, /*tp_subtract*/
210 float_mul, /*tp_multiply*/
211 float_div, /*tp_divide*/
212 float_rem, /*tp_remainder*/
213 float_pow, /*tp_power*/
214 float_neg, /*tp_negate*/
215 float_pos, /*tp_plus*/
216};
217
218typeobject Floattype = {
219 OB_HEAD_INIT(&Typetype)
220 0,
221 "float",
222 sizeof(floatobject),
223 0,
224 free, /*tp_dealloc*/
225 float_print, /*tp_print*/
226 0, /*tp_getattr*/
227 0, /*tp_setattr*/
228 float_compare, /*tp_compare*/
229 float_repr, /*tp_repr*/
230 &float_as_number, /*tp_as_number*/
231 0, /*tp_as_sequence*/
232 0, /*tp_as_mapping*/
233};
234
235/*
236XXX This is not enough. Need:
237- automatic casts for mixed arithmetic (3.1 * 4)
238- mixed comparisons (!)
239- look at other uses of ints that could be extended to floats
240*/