blob: d1ed9b9706d0ea25eeb4de794af8ed06ced35947 [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
17object *
18newfloatobject(fval)
19 double fval;
20{
21 /* For efficiency, this code is copied from newobject() */
22 register floatobject *op = (floatobject *) malloc(sizeof(floatobject));
Guido van Rossum2a9096b1990-10-21 22:15:08 +000023 if (op == NULL)
24 return err_nomem();
25 NEWREF(op);
26 op->ob_type = &Floattype;
27 op->ob_fval = fval;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000028 return (object *) op;
29}
30
31double
32getfloatvalue(op)
33 object *op;
34{
35 if (!is_floatobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000036 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000037 return -1;
38 }
39 else
40 return ((floatobject *)op) -> ob_fval;
41}
42
43/* Methods */
44
45static void
46float_buf_repr(buf, v)
47 char *buf;
48 floatobject *v;
49{
50 register char *cp;
51 /* Subroutine for float_repr and float_print.
52 We want float numbers to be recognizable as such,
53 i.e., they should contain a decimal point or an exponent.
54 However, %g may print the number as an integer;
55 in such cases, we append ".0" to the string. */
56 sprintf(buf, "%.12g", v->ob_fval);
57 cp = buf;
58 if (*cp == '-')
59 cp++;
60 for (; *cp != '\0'; cp++) {
61 /* Any non-digit means it's not an integer;
62 this takes care of NAN and INF as well. */
63 if (!isdigit(*cp))
64 break;
65 }
66 if (*cp == '\0') {
67 *cp++ = '.';
68 *cp++ = '0';
69 *cp++ = '\0';
70 }
71}
72
73static void
74float_print(v, fp, flags)
75 floatobject *v;
76 FILE *fp;
77 int flags;
78{
79 char buf[100];
80 float_buf_repr(buf, v);
81 fputs(buf, fp);
82}
83
84static object *
85float_repr(v)
86 floatobject *v;
87{
88 char buf[100];
89 float_buf_repr(buf, v);
90 return newstringobject(buf);
91}
92
93static int
94float_compare(v, w)
95 floatobject *v, *w;
96{
97 double i = v->ob_fval;
98 double j = w->ob_fval;
99 return (i < j) ? -1 : (i > j) ? 1 : 0;
100}
101
102static object *
103float_add(v, w)
104 floatobject *v;
105 object *w;
106{
107 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000108 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000109 return NULL;
110 }
111 return newfloatobject(v->ob_fval + ((floatobject *)w) -> ob_fval);
112}
113
114static object *
115float_sub(v, w)
116 floatobject *v;
117 object *w;
118{
119 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000120 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000121 return NULL;
122 }
123 return newfloatobject(v->ob_fval - ((floatobject *)w) -> ob_fval);
124}
125
126static object *
127float_mul(v, w)
128 floatobject *v;
129 object *w;
130{
131 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000132 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000133 return NULL;
134 }
135 return newfloatobject(v->ob_fval * ((floatobject *)w) -> ob_fval);
136}
137
138static object *
139float_div(v, w)
140 floatobject *v;
141 object *w;
142{
143 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000144 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000145 return NULL;
146 }
147 if (((floatobject *)w) -> ob_fval == 0) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000148 err_setstr(ZeroDivisionError, "float division by zero");
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_rem(v, w)
156 floatobject *v;
157 object *w;
158{
159 double wx;
160 extern double fmod();
161 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000162 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000163 return NULL;
164 }
165 wx = ((floatobject *)w) -> ob_fval;
166 if (wx == 0.0) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000167 err_setstr(ZeroDivisionError, "float division by zero");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000168 return NULL;
169 }
170 return newfloatobject(fmod(v->ob_fval, wx));
171}
172
173static object *
174float_pow(v, w)
175 floatobject *v;
176 object *w;
177{
178 double iv, iw, ix;
179 extern double pow();
180 if (!is_floatobject(w)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000181 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000182 return NULL;
183 }
184 iv = v->ob_fval;
185 iw = ((floatobject *)w)->ob_fval;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000186 if (iw == 0.0)
187 return newfloatobject(1.0); /* x**0 is always 1, even 0**0 */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000188 errno = 0;
189 ix = pow(iv, iw);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000190 if (errno != 0) {
191 /* XXX could it be another type of error? */
192 err_errno(OverflowError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000193 return NULL;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000194 }
195 return newfloatobject(ix);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000196}
197
198static object *
199float_neg(v)
200 floatobject *v;
201{
202 return newfloatobject(-v->ob_fval);
203}
204
205static object *
206float_pos(v)
207 floatobject *v;
208{
209 return newfloatobject(v->ob_fval);
210}
211
212static number_methods float_as_number = {
213 float_add, /*tp_add*/
214 float_sub, /*tp_subtract*/
215 float_mul, /*tp_multiply*/
216 float_div, /*tp_divide*/
217 float_rem, /*tp_remainder*/
218 float_pow, /*tp_power*/
219 float_neg, /*tp_negate*/
220 float_pos, /*tp_plus*/
221};
222
223typeobject Floattype = {
224 OB_HEAD_INIT(&Typetype)
225 0,
226 "float",
227 sizeof(floatobject),
228 0,
229 free, /*tp_dealloc*/
230 float_print, /*tp_print*/
231 0, /*tp_getattr*/
232 0, /*tp_setattr*/
233 float_compare, /*tp_compare*/
234 float_repr, /*tp_repr*/
235 &float_as_number, /*tp_as_number*/
236 0, /*tp_as_sequence*/
237 0, /*tp_as_mapping*/
238};
239
240/*
241XXX This is not enough. Need:
242- automatic casts for mixed arithmetic (3.1 * 4)
243- mixed comparisons (!)
244- look at other uses of ints that could be extended to floats
245*/