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