1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
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"
38 /* Cray APP has bogus definition of HUGE_VAL in <math.h> */
43 #define CHECK(x) if (errno != 0) ; \
44 else if (-HUGE_VAL <= (x) && (x) <= HUGE_VAL) ; \
47 #define CHECK(x) /* Don't know how to check */
55 #define LONG_MAX 0X7FFFFFFFL
59 #define LONG_MIN (-LONG_MAX-1)
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
70 #define LONG_MIN (-LONG_MAX-1)
74 #if !defined(__STDC__) && !defined(macintosh)
75 extern double fmod
PROTO((double, double));
76 extern double pow
PROTO((double, double));
81 newfloatobject(double fval
)
87 /* For efficiency, this code is copied from newobject() */
88 register floatobject
*op
= (floatobject
*) malloc(sizeof(floatobject
));
91 op
->ob_type
= &Floattype
;
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
) {
121 fo
= (floatobject
*) (*nb
->nb_float
) (op
);
124 if (!is_floatobject(fo
)) {
125 err_setstr(TypeError
, "nb_float should return float object");
129 val
= GETFLOATVALUE(fo
);
138 float_buf_repr(buf
, v
)
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
);
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
)))
167 float_print(v
, fp
, flags
)
170 int flags
; /* Not used but required by interface */
173 float_buf_repr(buf
, v
);
183 float_buf_repr(buf
, v
);
184 return newstringobject(buf
);
191 double i
= v
->ob_fval
;
192 double j
= w
->ob_fval
;
193 return (i
< j
) ? -1 : (i
> j
) ? 1 : 0;
200 double intpart
, fractpart
;
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 */
210 fractpart
= modf(v
->ob_fval
, &e
);
214 fractpart
= modf(v
->ob_fval
, &intpart
);
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
);
230 fractpart
= frexp(fractpart
, &expo
);
231 fractpart
= fractpart
*2147483648.0; /* 2**31 */
232 x
= (long) (intpart
+ fractpart
) ^ expo
; /* Rather arbitrary */
244 return newfloatobject(v
->ob_fval
+ w
->ob_fval
);
252 return newfloatobject(v
->ob_fval
- w
->ob_fval
);
260 return newfloatobject(v
->ob_fval
* w
->ob_fval
);
268 if (w
->ob_fval
== 0) {
269 err_setstr(ZeroDivisionError
, "float division");
272 return newfloatobject(v
->ob_fval
/ w
->ob_fval
);
281 double /* div, */ mod
;
284 err_setstr(ZeroDivisionError
, "float modulo");
289 /* div = (vx - mod) / wx; */
294 return newfloatobject(mod
);
306 err_setstr(ZeroDivisionError
, "float divmod()");
311 div
= (vx
- mod
) / wx
;
316 return mkvalue("(dd)", div
, mod
);
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.
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
;
340 return newfloatobject(ix
);
344 err_setstr(ValueError
, "0.0 to a negative power");
347 return newfloatobject(0.0);
353 /* XXX could it be another type of error? */
354 err_errno(OverflowError
);
357 if ((object
*)z
!=None
) {
358 ix
=fmod(ix
, z
->ob_fval
); /* XXX To Be Rewritten */
360 ((iv
<0 && z
->ob_fval
>0) || (iv
>0 && z
->ob_fval
<0) )) {
364 return newfloatobject(ix
);
371 return newfloatobject(-v
->ob_fval
);
396 return v
->ob_fval
!= 0.0;
404 if (is_intobject(*pw
)) {
405 long x
= getintvalue(*pw
);
406 *pw
= newfloatobject((double)x
);
410 else if (is_longobject(*pw
)) {
411 *pw
= newfloatobject(dgetlongvalue(*pw
));
415 return 1; /* Can't do it */
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");
428 return newintobject((long)x
);
435 double x
= getfloatvalue(v
);
436 return dnewlongobject(x
);
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*/
466 (coercion
)float_coerce
, /*nb_coerce*/
467 (unaryfunc
)float_int
, /*nb_int*/
468 (unaryfunc
)float_long
, /*nb_long*/
469 (unaryfunc
)float_float
, /*nb_float*/
474 typeobject Floattype
= {
475 OB_HEAD_INIT(&Typetype
)
480 (destructor
)float_dealloc
, /*tp_dealloc*/
481 (printfunc
)float_print
, /*tp_print*/
484 (cmpfunc
)float_compare
, /*tp_compare*/
485 (reprfunc
)float_repr
, /*tp_repr*/
486 &float_as_number
, /*tp_as_number*/
487 0, /*tp_as_sequence*/
489 (hashfunc
)float_hash
, /*tp_hash*/