blob: 82d464327d1541359dd11eb508c58bd91e61908e [file] [log] [blame]
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001/* Float object implementation */
2
Guido van Rossum2a9096b1990-10-21 22:15:08 +00003/* XXX There should be overflow checks here, but it's hard to check
4 for any kind of float exception without losing portability. */
5
Guido van Rossum3f5da241990-12-20 15:06:42 +00006#include "allobjects.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00007
Guido van Rossum3f5da241990-12-20 15:06:42 +00008#include <ctype.h>
9#include <math.h>
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000010
Guido van Rossum6923e131990-11-02 17:50:43 +000011#ifndef THINK_C
12extern double fmod PROTO((double, double));
13extern double pow PROTO((double, double));
14#endif
15
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000016object *
17newfloatobject(fval)
18 double fval;
19{
20 /* For efficiency, this code is copied from newobject() */
21 register floatobject *op = (floatobject *) malloc(sizeof(floatobject));
Guido van Rossum2a9096b1990-10-21 22:15:08 +000022 if (op == NULL)
23 return err_nomem();
24 NEWREF(op);
25 op->ob_type = &Floattype;
26 op->ob_fval = fval;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000027 return (object *) op;
28}
29
30double
31getfloatvalue(op)
32 object *op;
33{
34 if (!is_floatobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000035 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000036 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)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000107 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000108 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)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000119 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000120 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)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000131 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000132 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)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000143 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000144 return NULL;
145 }
146 if (((floatobject *)w) -> ob_fval == 0) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000147 err_setstr(ZeroDivisionError, "float division by zero");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000148 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;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000159 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 wx = ((floatobject *)w) -> ob_fval;
164 if (wx == 0.0) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000165 err_setstr(ZeroDivisionError, "float division by zero");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000166 return NULL;
167 }
168 return newfloatobject(fmod(v->ob_fval, wx));
169}
170
171static object *
172float_pow(v, w)
173 floatobject *v;
174 object *w;
175{
176 double iv, iw, ix;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000177 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000178 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000179 return NULL;
180 }
181 iv = v->ob_fval;
182 iw = ((floatobject *)w)->ob_fval;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000183 if (iw == 0.0)
184 return newfloatobject(1.0); /* x**0 is always 1, even 0**0 */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000185 errno = 0;
186 ix = pow(iv, iw);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000187 if (errno != 0) {
188 /* XXX could it be another type of error? */
189 err_errno(OverflowError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000190 return NULL;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000191 }
192 return newfloatobject(ix);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000193}
194
195static object *
196float_neg(v)
197 floatobject *v;
198{
199 return newfloatobject(-v->ob_fval);
200}
201
202static object *
203float_pos(v)
204 floatobject *v;
205{
206 return newfloatobject(v->ob_fval);
207}
208
209static number_methods float_as_number = {
210 float_add, /*tp_add*/
211 float_sub, /*tp_subtract*/
212 float_mul, /*tp_multiply*/
213 float_div, /*tp_divide*/
214 float_rem, /*tp_remainder*/
215 float_pow, /*tp_power*/
216 float_neg, /*tp_negate*/
217 float_pos, /*tp_plus*/
218};
219
220typeobject Floattype = {
221 OB_HEAD_INIT(&Typetype)
222 0,
223 "float",
224 sizeof(floatobject),
225 0,
226 free, /*tp_dealloc*/
227 float_print, /*tp_print*/
228 0, /*tp_getattr*/
229 0, /*tp_setattr*/
230 float_compare, /*tp_compare*/
231 float_repr, /*tp_repr*/
232 &float_as_number, /*tp_as_number*/
233 0, /*tp_as_sequence*/
234 0, /*tp_as_mapping*/
235};
236
237/*
238XXX This is not enough. Need:
239- automatic casts for mixed arithmetic (3.1 * 4)
240- mixed comparisons (!)
241- look at other uses of ints that could be extended to floats
242*/