blob: 7af5cd1ed497eac42e6243b8dc94c17517b681c2 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
2Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
3Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000025/* Float object implementation */
26
Guido van Rossum2a9096b1990-10-21 22:15:08 +000027/* XXX There should be overflow checks here, but it's hard to check
28 for any kind of float exception without losing portability. */
29
Guido van Rossum3f5da241990-12-20 15:06:42 +000030#include "allobjects.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000031
Guido van Rossumc211ee41990-12-20 23:06:26 +000032#include <errno.h>
33#ifndef errno
34extern int errno;
35#endif
36
Guido van Rossum3f5da241990-12-20 15:06:42 +000037#include <ctype.h>
38#include <math.h>
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000039
Guido van Rossum7fa52f81991-12-16 15:43:14 +000040#ifdef HUGE_VAL
41#define CHECK(x) if (errno != 0) ; \
42 else if (-HUGE_VAL <= (x) && (x) <= HUGE_VAL) ; \
43 else errno = ERANGE
44#else
45#define CHECK(x) /* Don't know how to check */
46#endif
47
Guido van Rossum6923e131990-11-02 17:50:43 +000048#ifndef THINK_C
49extern double fmod PROTO((double, double));
50extern double pow PROTO((double, double));
51#endif
52
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000053object *
54newfloatobject(fval)
55 double fval;
56{
57 /* For efficiency, this code is copied from newobject() */
58 register floatobject *op = (floatobject *) malloc(sizeof(floatobject));
Guido van Rossum2a9096b1990-10-21 22:15:08 +000059 if (op == NULL)
60 return err_nomem();
61 NEWREF(op);
62 op->ob_type = &Floattype;
63 op->ob_fval = fval;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000064 return (object *) op;
65}
66
67double
68getfloatvalue(op)
69 object *op;
70{
71 if (!is_floatobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000072 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000073 return -1;
74 }
75 else
76 return ((floatobject *)op) -> ob_fval;
77}
78
79/* Methods */
80
Guido van Rossum27dec7e1991-06-04 19:42:53 +000081void
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000082float_buf_repr(buf, v)
83 char *buf;
84 floatobject *v;
85{
86 register char *cp;
87 /* Subroutine for float_repr and float_print.
88 We want float numbers to be recognizable as such,
89 i.e., they should contain a decimal point or an exponent.
90 However, %g may print the number as an integer;
91 in such cases, we append ".0" to the string. */
92 sprintf(buf, "%.12g", v->ob_fval);
93 cp = buf;
94 if (*cp == '-')
95 cp++;
96 for (; *cp != '\0'; cp++) {
97 /* Any non-digit means it's not an integer;
98 this takes care of NAN and INF as well. */
99 if (!isdigit(*cp))
100 break;
101 }
102 if (*cp == '\0') {
103 *cp++ = '.';
104 *cp++ = '0';
105 *cp++ = '\0';
106 }
107}
108
Guido van Rossum90933611991-06-07 16:10:43 +0000109static int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000110float_print(v, fp, flags)
111 floatobject *v;
112 FILE *fp;
113 int flags;
114{
115 char buf[100];
116 float_buf_repr(buf, v);
117 fputs(buf, fp);
Guido van Rossum90933611991-06-07 16:10:43 +0000118 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000119}
120
121static object *
122float_repr(v)
123 floatobject *v;
124{
125 char buf[100];
126 float_buf_repr(buf, v);
127 return newstringobject(buf);
128}
129
130static int
131float_compare(v, w)
132 floatobject *v, *w;
133{
134 double i = v->ob_fval;
135 double j = w->ob_fval;
136 return (i < j) ? -1 : (i > j) ? 1 : 0;
137}
138
139static object *
140float_add(v, w)
141 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000142 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000143{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000144 return newfloatobject(v->ob_fval + w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000145}
146
147static object *
148float_sub(v, w)
149 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000150 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000151{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000152 return newfloatobject(v->ob_fval - w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000153}
154
155static object *
156float_mul(v, w)
157 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000158 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000159{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000160 return newfloatobject(v->ob_fval * w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000161}
162
163static object *
164float_div(v, w)
165 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000166 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000167{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000168 if (w->ob_fval == 0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000169 err_setstr(ZeroDivisionError, "float division");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000170 return NULL;
171 }
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000172 return newfloatobject(v->ob_fval / w->ob_fval);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000173}
174
175static object *
176float_rem(v, w)
177 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000178 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000179{
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000180 double vx, wx;
181 double div, mod;
182 wx = w->ob_fval;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000183 if (wx == 0.0) {
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000184 err_setstr(ZeroDivisionError, "float modulo");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000185 return NULL;
186 }
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000187 vx = v->ob_fval;
188 mod = fmod(vx, wx);
189 div = (vx - mod) / wx;
190 if (wx*mod < 0) {
191 mod += wx;
192 div -= 1.0;
193 }
194 return newfloatobject(mod);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000195}
196
197static object *
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000198float_divmod(v, w)
199 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000200 floatobject *w;
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000201{
Guido van Rossum15ecff41991-10-20 20:16:45 +0000202 double vx, wx;
203 double div, mod;
204 object *t;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000205 wx = w->ob_fval;
Guido van Rossum15ecff41991-10-20 20:16:45 +0000206 if (wx == 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000207 err_setstr(ZeroDivisionError, "float divmod()");
Guido van Rossum15ecff41991-10-20 20:16:45 +0000208 return NULL;
209 }
210 vx = v->ob_fval;
211 mod = fmod(vx, wx);
212 div = (vx - mod) / wx;
213 if (wx*mod < 0) {
214 mod += wx;
215 div -= 1.0;
216 }
217 t = newtupleobject(2);
218 if (t != NULL) {
219 settupleitem(t, 0, newfloatobject(div));
220 settupleitem(t, 1, newfloatobject(mod));
221 if (err_occurred()) {
222 DECREF(t);
223 t = NULL;
224 }
225 }
226 return t;
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000227}
228
229static object *
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000230float_pow(v, w)
231 floatobject *v;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000232 floatobject *w;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000233{
234 double iv, iw, ix;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000235 iv = v->ob_fval;
Guido van Rossum56cd67a1992-01-26 18:16:35 +0000236 iw = w->ob_fval;
Guido van Rossum70d93461991-05-28 21:57:39 +0000237 /* Sort out special cases here instead of relying on pow() */
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000238 if (iw == 0.0)
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000239 return newfloatobject(1.0); /* x**0 is 1, even 0**0 */
Guido van Rossum70d93461991-05-28 21:57:39 +0000240 if (iv == 0.0) {
241 if (iw < 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000242 err_setstr(ValueError, "0.0 to the negative power");
Guido van Rossum70d93461991-05-28 21:57:39 +0000243 return NULL;
244 }
245 return newfloatobject(0.0);
246 }
247 if (iv < 0.0) {
Guido van Rossum9a9fadd1991-12-10 13:56:55 +0000248 err_setstr(ValueError, "negative float to float power");
Guido van Rossum70d93461991-05-28 21:57:39 +0000249 return NULL;
250 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000251 errno = 0;
252 ix = pow(iv, iw);
Guido van Rossum7fa52f81991-12-16 15:43:14 +0000253 CHECK(ix);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000254 if (errno != 0) {
255 /* XXX could it be another type of error? */
256 err_errno(OverflowError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000257 return NULL;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000258 }
259 return newfloatobject(ix);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000260}
261
262static object *
263float_neg(v)
264 floatobject *v;
265{
266 return newfloatobject(-v->ob_fval);
267}
268
269static object *
270float_pos(v)
271 floatobject *v;
272{
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000273 INCREF(v);
274 return (object *)v;
275}
276
277static object *
278float_abs(v)
279 floatobject *v;
280{
281 if (v->ob_fval < 0)
282 return float_neg(v);
283 else
284 return float_pos(v);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000285}
286
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000287static int
288float_nonzero(v)
289 floatobject *v;
290{
291 return v->ob_fval != 0.0;
292}
293
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000294static number_methods float_as_number = {
Guido van Rossumeba1b5e1991-05-05 20:07:00 +0000295 float_add, /*nb_add*/
296 float_sub, /*nb_subtract*/
297 float_mul, /*nb_multiply*/
298 float_div, /*nb_divide*/
299 float_rem, /*nb_remainder*/
300 float_divmod, /*nb_divmod*/
301 float_pow, /*nb_power*/
302 float_neg, /*nb_negative*/
303 float_pos, /*nb_positive*/
304 float_abs, /*nb_absolute*/
Guido van Rossum50b4ef61991-05-14 11:57:01 +0000305 float_nonzero, /*nb_nonzero*/
Guido van Rossum27acb331991-10-24 14:55:28 +0000306 0, /*nb_invert*/
307 0, /*nb_lshift*/
308 0, /*nb_rshift*/
309 0, /*nb_and*/
310 0, /*nb_xor*/
311 0, /*nb_or*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000312};
313
314typeobject Floattype = {
315 OB_HEAD_INIT(&Typetype)
316 0,
317 "float",
318 sizeof(floatobject),
319 0,
320 free, /*tp_dealloc*/
321 float_print, /*tp_print*/
322 0, /*tp_getattr*/
323 0, /*tp_setattr*/
324 float_compare, /*tp_compare*/
325 float_repr, /*tp_repr*/
326 &float_as_number, /*tp_as_number*/
327 0, /*tp_as_sequence*/
328 0, /*tp_as_mapping*/
329};