Don't reference removed files in Makefile
[python/dscho.git] / Objects / floatobject.c
bloba2eba51aec97a9502ac39c2f6132cb677fa1bbc7
1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
25 /* Float object implementation */
27 /* XXX There should be overflow checks here, but it's hard to check
28 for any kind of float exception without losing portability. */
30 #include "allobjects.h"
31 #include "modsupport.h"
33 #include <errno.h>
34 #include <ctype.h>
35 #include "mymath.h"
37 #ifdef i860
38 /* Cray APP has bogus definition of HUGE_VAL in <math.h> */
39 #undef HUGE_VAL
40 #endif
42 #ifdef HUGE_VAL
43 #define CHECK(x) if (errno != 0) ; \
44 else if (-HUGE_VAL <= (x) && (x) <= HUGE_VAL) ; \
45 else errno = ERANGE
46 #else
47 #define CHECK(x) /* Don't know how to check */
48 #endif
50 #ifdef HAVE_LIMITS_H
51 #include <limits.h>
52 #endif
54 #ifndef LONG_MAX
55 #define LONG_MAX 0X7FFFFFFFL
56 #endif
58 #ifndef LONG_MIN
59 #define LONG_MIN (-LONG_MAX-1)
60 #endif
62 #ifdef __NeXT__
63 #ifdef __sparc__
65 * This works around a bug in the NS/Sparc 3.3 pre-release
66 * limits.h header file.
67 * 10-Feb-1995 bwarsaw@cnri.reston.va.us
69 #undef LONG_MIN
70 #define LONG_MIN (-LONG_MAX-1)
71 #endif
72 #endif
74 #if !defined(__STDC__) && !defined(macintosh)
75 extern double fmod PROTO((double, double));
76 extern double pow PROTO((double, double));
77 #endif
79 object *
80 #ifdef __SC__
81 newfloatobject(double fval)
82 #else
83 newfloatobject(fval)
84 double fval;
85 #endif
87 /* For efficiency, this code is copied from newobject() */
88 register floatobject *op = (floatobject *) malloc(sizeof(floatobject));
89 if (op == NULL)
90 return err_nomem();
91 op->ob_type = &Floattype;
92 op->ob_fval = fval;
93 NEWREF(op);
94 return (object *) op;
97 static void
98 float_dealloc(op)
99 object *op;
101 DEL(op);
104 double
105 getfloatvalue(op)
106 object *op;
108 number_methods *nb;
109 floatobject *fo;
110 double val;
112 if (op && is_floatobject(op))
113 return GETFLOATVALUE((floatobject*) op);
115 if (op == NULL || (nb = op->ob_type->tp_as_number) == NULL ||
116 nb->nb_float == NULL) {
117 err_badarg();
118 return -1;
121 fo = (floatobject*) (*nb->nb_float) (op);
122 if (fo == NULL)
123 return -1;
124 if (!is_floatobject(fo)) {
125 err_setstr(TypeError, "nb_float should return float object");
126 return -1;
129 val = GETFLOATVALUE(fo);
130 DECREF(fo);
132 return val;
135 /* Methods */
137 void
138 float_buf_repr(buf, v)
139 char *buf;
140 floatobject *v;
142 register char *cp;
143 /* Subroutine for float_repr and float_print.
144 We want float numbers to be recognizable as such,
145 i.e., they should contain a decimal point or an exponent.
146 However, %g may print the number as an integer;
147 in such cases, we append ".0" to the string. */
148 sprintf(buf, "%.12g", v->ob_fval);
149 cp = buf;
150 if (*cp == '-')
151 cp++;
152 for (; *cp != '\0'; cp++) {
153 /* Any non-digit means it's not an integer;
154 this takes care of NAN and INF as well. */
155 if (!isdigit(Py_CHARMASK(*cp)))
156 break;
158 if (*cp == '\0') {
159 *cp++ = '.';
160 *cp++ = '0';
161 *cp++ = '\0';
165 /* ARGSUSED */
166 static int
167 float_print(v, fp, flags)
168 floatobject *v;
169 FILE *fp;
170 int flags; /* Not used but required by interface */
172 char buf[100];
173 float_buf_repr(buf, v);
174 fputs(buf, fp);
175 return 0;
178 static object *
179 float_repr(v)
180 floatobject *v;
182 char buf[100];
183 float_buf_repr(buf, v);
184 return newstringobject(buf);
187 static int
188 float_compare(v, w)
189 floatobject *v, *w;
191 double i = v->ob_fval;
192 double j = w->ob_fval;
193 return (i < j) ? -1 : (i > j) ? 1 : 0;
196 static long
197 float_hash(v)
198 floatobject *v;
200 double intpart, fractpart;
201 int expo;
202 long x;
203 /* This is designed so that Python numbers with the same
204 value hash to the same value, otherwise comparisons
205 of mapping keys will turn out weird */
207 #ifdef MPW /* MPW C modf expects pointer to extended as second argument */
209 extended e;
210 fractpart = modf(v->ob_fval, &e);
211 intpart = e;
213 #else
214 fractpart = modf(v->ob_fval, &intpart);
215 #endif
217 if (fractpart == 0.0) {
218 if (intpart > 0x7fffffffL || -intpart > 0x7fffffffL) {
219 /* Convert to long int and use its hash... */
220 object *w = dnewlongobject(v->ob_fval);
221 if (w == NULL)
222 return -1;
223 x = hashobject(w);
224 DECREF(w);
225 return x;
227 x = (long)intpart;
229 else {
230 fractpart = frexp(fractpart, &expo);
231 fractpart = fractpart*2147483648.0; /* 2**31 */
232 x = (long) (intpart + fractpart) ^ expo; /* Rather arbitrary */
234 if (x == -1)
235 x = -2;
236 return x;
239 static object *
240 float_add(v, w)
241 floatobject *v;
242 floatobject *w;
244 return newfloatobject(v->ob_fval + w->ob_fval);
247 static object *
248 float_sub(v, w)
249 floatobject *v;
250 floatobject *w;
252 return newfloatobject(v->ob_fval - w->ob_fval);
255 static object *
256 float_mul(v, w)
257 floatobject *v;
258 floatobject *w;
260 return newfloatobject(v->ob_fval * w->ob_fval);
263 static object *
264 float_div(v, w)
265 floatobject *v;
266 floatobject *w;
268 if (w->ob_fval == 0) {
269 err_setstr(ZeroDivisionError, "float division");
270 return NULL;
272 return newfloatobject(v->ob_fval / w->ob_fval);
275 static object *
276 float_rem(v, w)
277 floatobject *v;
278 floatobject *w;
280 double vx, wx;
281 double /* div, */ mod;
282 wx = w->ob_fval;
283 if (wx == 0.0) {
284 err_setstr(ZeroDivisionError, "float modulo");
285 return NULL;
287 vx = v->ob_fval;
288 mod = fmod(vx, wx);
289 /* div = (vx - mod) / wx; */
290 if (wx*mod < 0) {
291 mod += wx;
292 /* div -= 1.0; */
294 return newfloatobject(mod);
297 static object *
298 float_divmod(v, w)
299 floatobject *v;
300 floatobject *w;
302 double vx, wx;
303 double div, mod;
304 wx = w->ob_fval;
305 if (wx == 0.0) {
306 err_setstr(ZeroDivisionError, "float divmod()");
307 return NULL;
309 vx = v->ob_fval;
310 mod = fmod(vx, wx);
311 div = (vx - mod) / wx;
312 if (wx*mod < 0) {
313 mod += wx;
314 div -= 1.0;
316 return mkvalue("(dd)", div, mod);
319 static object *
320 float_pow(v, w, z)
321 floatobject *v;
322 floatobject *w;
323 floatobject *z;
325 double iv, iw, ix;
326 iv = v->ob_fval;
327 iw = w->ob_fval;
328 /* XXX Doesn't handle overflows if z!=None yet; it may never do so :(
329 * The z parameter is really only going to be useful for integers and
330 * long integers. Maybe something clever with logarithms could be done.
331 * [AMK]
333 /* Sort out special cases here instead of relying on pow() */
334 if (iw == 0.0) { /* x**0 is 1, even 0**0 */
335 if ((object *)z!=None) {
336 ix=fmod(1.0, z->ob_fval);
337 if (ix!=0 && z->ob_fval<0) ix+=z->ob_fval;
339 else ix=1.0;
340 return newfloatobject(ix);
342 if (iv == 0.0) {
343 if (iw < 0.0) {
344 err_setstr(ValueError, "0.0 to a negative power");
345 return NULL;
347 return newfloatobject(0.0);
349 errno = 0;
350 ix = pow(iv, iw);
351 CHECK(ix);
352 if (errno != 0) {
353 /* XXX could it be another type of error? */
354 err_errno(OverflowError);
355 return NULL;
357 if ((object *)z!=None) {
358 ix=fmod(ix, z->ob_fval); /* XXX To Be Rewritten */
359 if ( ix!=0 &&
360 ((iv<0 && z->ob_fval>0) || (iv>0 && z->ob_fval<0) )) {
361 ix+=z->ob_fval;
364 return newfloatobject(ix);
367 static object *
368 float_neg(v)
369 floatobject *v;
371 return newfloatobject(-v->ob_fval);
374 static object *
375 float_pos(v)
376 floatobject *v;
378 INCREF(v);
379 return (object *)v;
382 static object *
383 float_abs(v)
384 floatobject *v;
386 if (v->ob_fval < 0)
387 return float_neg(v);
388 else
389 return float_pos(v);
392 static int
393 float_nonzero(v)
394 floatobject *v;
396 return v->ob_fval != 0.0;
399 static int
400 float_coerce(pv, pw)
401 object **pv;
402 object **pw;
404 if (is_intobject(*pw)) {
405 long x = getintvalue(*pw);
406 *pw = newfloatobject((double)x);
407 INCREF(*pv);
408 return 0;
410 else if (is_longobject(*pw)) {
411 *pw = newfloatobject(dgetlongvalue(*pw));
412 INCREF(*pv);
413 return 0;
415 return 1; /* Can't do it */
418 static object *
419 float_int(v)
420 object *v;
422 double x = getfloatvalue(v);
423 if (x < 0 ? (x = ceil(x)) < (double)LONG_MIN
424 : (x = floor(x)) > (double)LONG_MAX) {
425 err_setstr(OverflowError, "float too large to convert");
426 return NULL;
428 return newintobject((long)x);
431 static object *
432 float_long(v)
433 object *v;
435 double x = getfloatvalue(v);
436 return dnewlongobject(x);
439 static object *
440 float_float(v)
441 object *v;
443 INCREF(v);
444 return v;
448 static number_methods float_as_number = {
449 (binaryfunc)float_add, /*nb_add*/
450 (binaryfunc)float_sub, /*nb_subtract*/
451 (binaryfunc)float_mul, /*nb_multiply*/
452 (binaryfunc)float_div, /*nb_divide*/
453 (binaryfunc)float_rem, /*nb_remainder*/
454 (binaryfunc)float_divmod, /*nb_divmod*/
455 (ternaryfunc)float_pow, /*nb_power*/
456 (unaryfunc)float_neg, /*nb_negative*/
457 (unaryfunc)float_pos, /*nb_positive*/
458 (unaryfunc)float_abs, /*nb_absolute*/
459 (inquiry)float_nonzero, /*nb_nonzero*/
460 0, /*nb_invert*/
461 0, /*nb_lshift*/
462 0, /*nb_rshift*/
463 0, /*nb_and*/
464 0, /*nb_xor*/
465 0, /*nb_or*/
466 (coercion)float_coerce, /*nb_coerce*/
467 (unaryfunc)float_int, /*nb_int*/
468 (unaryfunc)float_long, /*nb_long*/
469 (unaryfunc)float_float, /*nb_float*/
470 0, /*nb_oct*/
471 0, /*nb_hex*/
474 typeobject Floattype = {
475 OB_HEAD_INIT(&Typetype)
477 "float",
478 sizeof(floatobject),
480 (destructor)float_dealloc, /*tp_dealloc*/
481 (printfunc)float_print, /*tp_print*/
482 0, /*tp_getattr*/
483 0, /*tp_setattr*/
484 (cmpfunc)float_compare, /*tp_compare*/
485 (reprfunc)float_repr, /*tp_repr*/
486 &float_as_number, /*tp_as_number*/
487 0, /*tp_as_sequence*/
488 0, /*tp_as_mapping*/
489 (hashfunc)float_hash, /*tp_hash*/