blob: c2b132e93516568e397e2b1b8b0fd6caf88d242e [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 Rossum85a5fbb1990-10-14 12:07:46 +00006#include <stdio.h>
7#include <math.h>
8#include <ctype.h>
9
10#include "PROTO.h"
11#include "object.h"
12#include "floatobject.h"
13#include "stringobject.h"
14#include "objimpl.h"
Guido van Rossum2a9096b1990-10-21 22:15:08 +000015#include "errors.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000016
Guido van Rossum6923e131990-11-02 17:50:43 +000017#ifndef THINK_C
18extern double fmod PROTO((double, double));
19extern double pow PROTO((double, double));
20#endif
21
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000022object *
23newfloatobject(fval)
24 double fval;
25{
26 /* For efficiency, this code is copied from newobject() */
27 register floatobject *op = (floatobject *) malloc(sizeof(floatobject));
Guido van Rossum2a9096b1990-10-21 22:15:08 +000028 if (op == NULL)
29 return err_nomem();
30 NEWREF(op);
31 op->ob_type = &Floattype;
32 op->ob_fval = fval;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000033 return (object *) op;
34}
35
36double
37getfloatvalue(op)
38 object *op;
39{
40 if (!is_floatobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000041 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000042 return -1;
43 }
44 else
45 return ((floatobject *)op) -> ob_fval;
46}
47
48/* Methods */
49
50static void
51float_buf_repr(buf, v)
52 char *buf;
53 floatobject *v;
54{
55 register char *cp;
56 /* Subroutine for float_repr and float_print.
57 We want float numbers to be recognizable as such,
58 i.e., they should contain a decimal point or an exponent.
59 However, %g may print the number as an integer;
60 in such cases, we append ".0" to the string. */
61 sprintf(buf, "%.12g", v->ob_fval);
62 cp = buf;
63 if (*cp == '-')
64 cp++;
65 for (; *cp != '\0'; cp++) {
66 /* Any non-digit means it's not an integer;
67 this takes care of NAN and INF as well. */
68 if (!isdigit(*cp))
69 break;
70 }
71 if (*cp == '\0') {
72 *cp++ = '.';
73 *cp++ = '0';
74 *cp++ = '\0';
75 }
76}
77
78static void
79float_print(v, fp, flags)
80 floatobject *v;
81 FILE *fp;
82 int flags;
83{
84 char buf[100];
85 float_buf_repr(buf, v);
86 fputs(buf, fp);
87}
88
89static object *
90float_repr(v)
91 floatobject *v;
92{
93 char buf[100];
94 float_buf_repr(buf, v);
95 return newstringobject(buf);
96}
97
98static int
99float_compare(v, w)
100 floatobject *v, *w;
101{
102 double i = v->ob_fval;
103 double j = w->ob_fval;
104 return (i < j) ? -1 : (i > j) ? 1 : 0;
105}
106
107static object *
108float_add(v, w)
109 floatobject *v;
110 object *w;
111{
112 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000113 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000114 return NULL;
115 }
116 return newfloatobject(v->ob_fval + ((floatobject *)w) -> ob_fval);
117}
118
119static object *
120float_sub(v, w)
121 floatobject *v;
122 object *w;
123{
124 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000125 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000126 return NULL;
127 }
128 return newfloatobject(v->ob_fval - ((floatobject *)w) -> ob_fval);
129}
130
131static object *
132float_mul(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_div(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 if (((floatobject *)w) -> ob_fval == 0) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000153 err_setstr(ZeroDivisionError, "float division by zero");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000154 return NULL;
155 }
156 return newfloatobject(v->ob_fval / ((floatobject *)w) -> ob_fval);
157}
158
159static object *
160float_rem(v, w)
161 floatobject *v;
162 object *w;
163{
164 double wx;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000165 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000166 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000167 return NULL;
168 }
169 wx = ((floatobject *)w) -> ob_fval;
170 if (wx == 0.0) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000171 err_setstr(ZeroDivisionError, "float division by zero");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000172 return NULL;
173 }
174 return newfloatobject(fmod(v->ob_fval, wx));
175}
176
177static object *
178float_pow(v, w)
179 floatobject *v;
180 object *w;
181{
182 double iv, iw, ix;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000183 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000184 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000185 return NULL;
186 }
187 iv = v->ob_fval;
188 iw = ((floatobject *)w)->ob_fval;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000189 if (iw == 0.0)
190 return newfloatobject(1.0); /* x**0 is always 1, even 0**0 */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000191 errno = 0;
192 ix = pow(iv, iw);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000193 if (errno != 0) {
194 /* XXX could it be another type of error? */
195 err_errno(OverflowError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000196 return NULL;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000197 }
198 return newfloatobject(ix);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000199}
200
201static object *
202float_neg(v)
203 floatobject *v;
204{
205 return newfloatobject(-v->ob_fval);
206}
207
208static object *
209float_pos(v)
210 floatobject *v;
211{
212 return newfloatobject(v->ob_fval);
213}
214
215static number_methods float_as_number = {
216 float_add, /*tp_add*/
217 float_sub, /*tp_subtract*/
218 float_mul, /*tp_multiply*/
219 float_div, /*tp_divide*/
220 float_rem, /*tp_remainder*/
221 float_pow, /*tp_power*/
222 float_neg, /*tp_negate*/
223 float_pos, /*tp_plus*/
224};
225
226typeobject Floattype = {
227 OB_HEAD_INIT(&Typetype)
228 0,
229 "float",
230 sizeof(floatobject),
231 0,
232 free, /*tp_dealloc*/
233 float_print, /*tp_print*/
234 0, /*tp_getattr*/
235 0, /*tp_setattr*/
236 float_compare, /*tp_compare*/
237 float_repr, /*tp_repr*/
238 &float_as_number, /*tp_as_number*/
239 0, /*tp_as_sequence*/
240 0, /*tp_as_mapping*/
241};
242
243/*
244XXX This is not enough. Need:
245- automatic casts for mixed arithmetic (3.1 * 4)
246- mixed comparisons (!)
247- look at other uses of ints that could be extended to floats
248*/