Class around PixMap objects that allows more python-like access. By Joe Strout.
[python/dscho.git] / Objects / floatobject.c
blob120b561a598bf28b6b60a9e569be6a1624b0f3cf
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 or Corporation for National Research Initiatives or
13 CNRI not be used in advertising or publicity pertaining to
14 distribution of the software without specific, written prior
15 permission.
17 While CWI is the initial source for this software, a modified version
18 is made available by the Corporation for National Research Initiatives
19 (CNRI) at the Internet address ftp://ftp.python.org.
21 STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22 REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23 MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24 CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28 PERFORMANCE OF THIS SOFTWARE.
30 ******************************************************************/
32 /* Float object implementation */
34 /* XXX There should be overflow checks here, but it's hard to check
35 for any kind of float exception without losing portability. */
37 #include "Python.h"
39 #include <ctype.h>
40 #include "mymath.h"
42 #ifdef i860
43 /* Cray APP has bogus definition of HUGE_VAL in <math.h> */
44 #undef HUGE_VAL
45 #endif
47 #if defined(HUGE_VAL) && !defined(CHECK)
48 #define CHECK(x) if (errno != 0) ; \
49 else if (-HUGE_VAL <= (x) && (x) <= HUGE_VAL) ; \
50 else errno = ERANGE
51 #endif
53 #ifndef CHECK
54 #define CHECK(x) /* Don't know how to check */
55 #endif
57 #ifdef HAVE_LIMITS_H
58 #include <limits.h>
59 #endif
61 #ifndef LONG_MAX
62 #define LONG_MAX 0X7FFFFFFFL
63 #endif
65 #ifndef LONG_MIN
66 #define LONG_MIN (-LONG_MAX-1)
67 #endif
69 #ifdef __NeXT__
70 #ifdef __sparc__
72 * This works around a bug in the NS/Sparc 3.3 pre-release
73 * limits.h header file.
74 * 10-Feb-1995 bwarsaw@cnri.reston.va.us
76 #undef LONG_MIN
77 #define LONG_MIN (-LONG_MAX-1)
78 #endif
79 #endif
81 #if !defined(__STDC__) && !defined(macintosh)
82 extern double fmod Py_PROTO((double, double));
83 extern double pow Py_PROTO((double, double));
84 #endif
86 #ifdef sun
87 /* On SunOS4.1 only libm.a exists. Make sure that references to all
88 needed math functions exist in the executable, so that dynamic
89 loading of mathmodule does not fail. */
90 double (*_Py_math_funcs_hack[])() = {
91 acos, asin, atan, atan2, ceil, cos, cosh, exp, fabs, floor,
92 fmod, log, log10, pow, sin, sinh, sqrt, tan, tanh
94 #endif
96 /* Special free list -- see comments for same code in intobject.c. */
97 #define BLOCK_SIZE 1000 /* 1K less typical malloc overhead */
98 #define BHEAD_SIZE 8 /* Enough for a 64-bit pointer */
99 #define N_FLOATOBJECTS ((BLOCK_SIZE - BHEAD_SIZE) / sizeof(PyFloatObject))
101 #define PyMem_MALLOC malloc
102 #define PyMem_FREE free
104 struct _floatblock {
105 struct _floatblock *next;
106 PyFloatObject objects[N_FLOATOBJECTS];
109 typedef struct _floatblock PyFloatBlock;
111 static PyFloatBlock *block_list = NULL;
112 static PyFloatObject *free_list = NULL;
114 static PyFloatObject *
115 fill_free_list()
117 PyFloatObject *p, *q;
118 p = (PyFloatObject *)PyMem_MALLOC(sizeof(PyFloatBlock));
119 if (p == NULL)
120 return (PyFloatObject *)PyErr_NoMemory();
121 ((PyFloatBlock *)p)->next = block_list;
122 block_list = (PyFloatBlock *)p;
123 p = &((PyFloatBlock *)p)->objects[0];
124 q = p + N_FLOATOBJECTS;
125 while (--q > p)
126 q->ob_type = (struct _typeobject *)(q-1);
127 q->ob_type = NULL;
128 return p + N_FLOATOBJECTS - 1;
131 PyObject *
132 #ifdef __SC__
133 PyFloat_FromDouble(double fval)
134 #else
135 PyFloat_FromDouble(fval)
136 double fval;
137 #endif
139 register PyFloatObject *op;
140 if (free_list == NULL) {
141 if ((free_list = fill_free_list()) == NULL)
142 return NULL;
144 op = free_list;
145 free_list = (PyFloatObject *)op->ob_type;
146 op->ob_type = &PyFloat_Type;
147 op->ob_fval = fval;
148 _Py_NewReference(op);
149 return (PyObject *) op;
152 static void
153 float_dealloc(op)
154 PyFloatObject *op;
156 op->ob_type = (struct _typeobject *)free_list;
157 free_list = op;
160 double
161 PyFloat_AsDouble(op)
162 PyObject *op;
164 PyNumberMethods *nb;
165 PyFloatObject *fo;
166 double val;
168 if (op && PyFloat_Check(op))
169 return PyFloat_AS_DOUBLE((PyFloatObject*) op);
171 if (op == NULL || (nb = op->ob_type->tp_as_number) == NULL ||
172 nb->nb_float == NULL) {
173 PyErr_BadArgument();
174 return -1;
177 fo = (PyFloatObject*) (*nb->nb_float) (op);
178 if (fo == NULL)
179 return -1;
180 if (!PyFloat_Check(fo)) {
181 PyErr_SetString(PyExc_TypeError,
182 "nb_float should return float object");
183 return -1;
186 val = PyFloat_AS_DOUBLE(fo);
187 Py_DECREF(fo);
189 return val;
192 /* Methods */
194 void
195 PyFloat_AsString(buf, v)
196 char *buf;
197 PyFloatObject *v;
199 register char *cp;
200 /* Subroutine for float_repr and float_print.
201 We want float numbers to be recognizable as such,
202 i.e., they should contain a decimal point or an exponent.
203 However, %g may print the number as an integer;
204 in such cases, we append ".0" to the string. */
205 sprintf(buf, "%.12g", v->ob_fval);
206 cp = buf;
207 if (*cp == '-')
208 cp++;
209 for (; *cp != '\0'; cp++) {
210 /* Any non-digit means it's not an integer;
211 this takes care of NAN and INF as well. */
212 if (!isdigit(Py_CHARMASK(*cp)))
213 break;
215 if (*cp == '\0') {
216 *cp++ = '.';
217 *cp++ = '0';
218 *cp++ = '\0';
222 /* ARGSUSED */
223 static int
224 float_print(v, fp, flags)
225 PyFloatObject *v;
226 FILE *fp;
227 int flags; /* Not used but required by interface */
229 char buf[100];
230 PyFloat_AsString(buf, v);
231 fputs(buf, fp);
232 return 0;
235 static PyObject *
236 float_repr(v)
237 PyFloatObject *v;
239 char buf[100];
240 PyFloat_AsString(buf, v);
241 return PyString_FromString(buf);
244 static int
245 float_compare(v, w)
246 PyFloatObject *v, *w;
248 double i = v->ob_fval;
249 double j = w->ob_fval;
250 return (i < j) ? -1 : (i > j) ? 1 : 0;
253 static long
254 float_hash(v)
255 PyFloatObject *v;
257 double intpart, fractpart;
258 int expo;
259 long x;
260 /* This is designed so that Python numbers with the same
261 value hash to the same value, otherwise comparisons
262 of mapping keys will turn out weird */
264 #ifdef MPW /* MPW C modf expects pointer to extended as second argument */
266 extended e;
267 fractpart = modf(v->ob_fval, &e);
268 intpart = e;
270 #else
271 fractpart = modf(v->ob_fval, &intpart);
272 #endif
274 if (fractpart == 0.0) {
275 if (intpart > 0x7fffffffL || -intpart > 0x7fffffffL) {
276 /* Convert to long int and use its hash... */
277 PyObject *w = PyLong_FromDouble(v->ob_fval);
278 if (w == NULL)
279 return -1;
280 x = PyObject_Hash(w);
281 Py_DECREF(w);
282 return x;
284 x = (long)intpart;
286 else {
287 /* Note -- if you change this code, also change the copy
288 in complexobject.c */
289 long hipart;
290 fractpart = frexp(fractpart, &expo);
291 fractpart = fractpart * 2147483648.0; /* 2**31 */
292 hipart = (long)fractpart; /* Take the top 32 bits */
293 fractpart = (fractpart - (double)hipart) * 2147483648.0;
294 /* Get the next 32 bits */
295 x = hipart + (long)fractpart + (long)intpart + (expo << 15);
296 /* Combine everything */
298 if (x == -1)
299 x = -2;
300 return x;
303 static PyObject *
304 float_add(v, w)
305 PyFloatObject *v;
306 PyFloatObject *w;
308 double result;
309 PyFPE_START_PROTECT("add", return 0)
310 result = v->ob_fval + w->ob_fval;
311 PyFPE_END_PROTECT(result)
312 return PyFloat_FromDouble(result);
315 static PyObject *
316 float_sub(v, w)
317 PyFloatObject *v;
318 PyFloatObject *w;
320 double result;
321 PyFPE_START_PROTECT("subtract", return 0)
322 result = v->ob_fval - w->ob_fval;
323 PyFPE_END_PROTECT(result)
324 return PyFloat_FromDouble(result);
327 static PyObject *
328 float_mul(v, w)
329 PyFloatObject *v;
330 PyFloatObject *w;
332 double result;
334 PyFPE_START_PROTECT("multiply", return 0)
335 result = v->ob_fval * w->ob_fval;
336 PyFPE_END_PROTECT(result)
337 return PyFloat_FromDouble(result);
340 static PyObject *
341 float_div(v, w)
342 PyFloatObject *v;
343 PyFloatObject *w;
345 double result;
346 if (w->ob_fval == 0) {
347 PyErr_SetString(PyExc_ZeroDivisionError, "float division");
348 return NULL;
350 PyFPE_START_PROTECT("divide", return 0)
351 result = v->ob_fval / w->ob_fval;
352 PyFPE_END_PROTECT(result)
353 return PyFloat_FromDouble(result);
356 static PyObject *
357 float_rem(v, w)
358 PyFloatObject *v;
359 PyFloatObject *w;
361 double vx, wx;
362 double /* div, */ mod;
363 wx = w->ob_fval;
364 if (wx == 0.0) {
365 PyErr_SetString(PyExc_ZeroDivisionError, "float modulo");
366 return NULL;
368 PyFPE_START_PROTECT("modulo", return 0)
369 vx = v->ob_fval;
370 mod = fmod(vx, wx);
371 /* div = (vx - mod) / wx; */
372 if (wx*mod < 0) {
373 mod += wx;
374 /* div -= 1.0; */
376 PyFPE_END_PROTECT(mod)
377 return PyFloat_FromDouble(mod);
380 static PyObject *
381 float_divmod(v, w)
382 PyFloatObject *v;
383 PyFloatObject *w;
385 double vx, wx;
386 double div, mod;
387 wx = w->ob_fval;
388 if (wx == 0.0) {
389 PyErr_SetString(PyExc_ZeroDivisionError, "float divmod()");
390 return NULL;
392 PyFPE_START_PROTECT("divmod", return 0)
393 vx = v->ob_fval;
394 mod = fmod(vx, wx);
395 div = (vx - mod) / wx;
396 if (wx*mod < 0) {
397 mod += wx;
398 div -= 1.0;
400 PyFPE_END_PROTECT(div)
401 return Py_BuildValue("(dd)", div, mod);
404 static double powu(x, n)
405 double x;
406 long n;
408 double r = 1.;
409 double p = x;
410 long mask = 1;
411 while (mask > 0 && n >= mask) {
412 if (n & mask)
413 r *= p;
414 mask <<= 1;
415 p *= p;
417 return r;
420 static PyObject *
421 float_pow(v, w, z)
422 PyFloatObject *v;
423 PyObject *w;
424 PyFloatObject *z;
426 double iv, iw, ix;
427 long intw;
428 /* XXX Doesn't handle overflows if z!=None yet; it may never do so :(
429 * The z parameter is really only going to be useful for integers and
430 * long integers. Maybe something clever with logarithms could be done.
431 * [AMK]
433 iv = v->ob_fval;
434 iw = ((PyFloatObject *)w)->ob_fval;
435 intw = (long)iw;
436 if (iw == intw && -10000 < intw && intw < 10000) {
437 /* Sort out special cases here instead of relying on pow() */
438 if (intw == 0) { /* x**0 is 1, even 0**0 */
439 PyFPE_START_PROTECT("pow", return 0)
440 if ((PyObject *)z!=Py_None) {
441 ix=fmod(1.0, z->ob_fval);
442 if (ix!=0 && z->ob_fval<0) ix+=z->ob_fval;
444 else ix=1.0;
445 PyFPE_END_PROTECT(ix)
446 return PyFloat_FromDouble(ix);
448 errno = 0;
449 PyFPE_START_PROTECT("pow", return 0)
450 if (intw > 0)
451 ix = powu(iv, intw);
452 else
453 ix = 1./powu(iv, -intw);
454 PyFPE_END_PROTECT(ix)
456 else {
457 /* Sort out special cases here instead of relying on pow() */
458 if (iv == 0.0) {
459 if (iw < 0.0) {
460 PyErr_SetString(PyExc_ValueError,
461 "0.0 to a negative power");
462 return NULL;
464 return PyFloat_FromDouble(0.0);
466 if (iv < 0.0) {
467 PyErr_SetString(PyExc_ValueError,
468 "negative number to a float power");
469 return NULL;
471 errno = 0;
472 PyFPE_START_PROTECT("pow", return 0)
473 ix = pow(iv, iw);
474 PyFPE_END_PROTECT(ix)
476 CHECK(ix);
477 if (errno != 0) {
478 /* XXX could it be another type of error? */
479 PyErr_SetFromErrno(PyExc_OverflowError);
480 return NULL;
482 if ((PyObject *)z!=Py_None) {
483 PyFPE_START_PROTECT("pow", return 0)
484 ix=fmod(ix, z->ob_fval); /* XXX To Be Rewritten */
485 if ( ix!=0 &&
486 ((iv<0 && z->ob_fval>0) || (iv>0 && z->ob_fval<0) )) {
487 ix+=z->ob_fval;
489 PyFPE_END_PROTECT(ix)
491 return PyFloat_FromDouble(ix);
494 static PyObject *
495 float_neg(v)
496 PyFloatObject *v;
498 return PyFloat_FromDouble(-v->ob_fval);
501 static PyObject *
502 float_pos(v)
503 PyFloatObject *v;
505 Py_INCREF(v);
506 return (PyObject *)v;
509 static PyObject *
510 float_abs(v)
511 PyFloatObject *v;
513 if (v->ob_fval < 0)
514 return float_neg(v);
515 else
516 return float_pos(v);
519 static int
520 float_nonzero(v)
521 PyFloatObject *v;
523 return v->ob_fval != 0.0;
526 static int
527 float_coerce(pv, pw)
528 PyObject **pv;
529 PyObject **pw;
531 if (PyInt_Check(*pw)) {
532 long x = PyInt_AsLong(*pw);
533 *pw = PyFloat_FromDouble((double)x);
534 Py_INCREF(*pv);
535 return 0;
537 else if (PyLong_Check(*pw)) {
538 *pw = PyFloat_FromDouble(PyLong_AsDouble(*pw));
539 Py_INCREF(*pv);
540 return 0;
542 return 1; /* Can't do it */
545 static PyObject *
546 float_int(v)
547 PyObject *v;
549 double x = PyFloat_AsDouble(v);
550 if (x < 0 ? (x = ceil(x)) < (double)LONG_MIN
551 : (x = floor(x)) > (double)LONG_MAX) {
552 PyErr_SetString(PyExc_OverflowError,
553 "float too large to convert");
554 return NULL;
556 return PyInt_FromLong((long)x);
559 static PyObject *
560 float_long(v)
561 PyObject *v;
563 double x = PyFloat_AsDouble(v);
564 return PyLong_FromDouble(x);
567 static PyObject *
568 float_float(v)
569 PyObject *v;
571 Py_INCREF(v);
572 return v;
576 static PyNumberMethods float_as_number = {
577 (binaryfunc)float_add, /*nb_add*/
578 (binaryfunc)float_sub, /*nb_subtract*/
579 (binaryfunc)float_mul, /*nb_multiply*/
580 (binaryfunc)float_div, /*nb_divide*/
581 (binaryfunc)float_rem, /*nb_remainder*/
582 (binaryfunc)float_divmod, /*nb_divmod*/
583 (ternaryfunc)float_pow, /*nb_power*/
584 (unaryfunc)float_neg, /*nb_negative*/
585 (unaryfunc)float_pos, /*nb_positive*/
586 (unaryfunc)float_abs, /*nb_absolute*/
587 (inquiry)float_nonzero, /*nb_nonzero*/
588 0, /*nb_invert*/
589 0, /*nb_lshift*/
590 0, /*nb_rshift*/
591 0, /*nb_and*/
592 0, /*nb_xor*/
593 0, /*nb_or*/
594 (coercion)float_coerce, /*nb_coerce*/
595 (unaryfunc)float_int, /*nb_int*/
596 (unaryfunc)float_long, /*nb_long*/
597 (unaryfunc)float_float, /*nb_float*/
598 0, /*nb_oct*/
599 0, /*nb_hex*/
602 PyTypeObject PyFloat_Type = {
603 PyObject_HEAD_INIT(&PyType_Type)
605 "float",
606 sizeof(PyFloatObject),
608 (destructor)float_dealloc, /*tp_dealloc*/
609 (printfunc)float_print, /*tp_print*/
610 0, /*tp_getattr*/
611 0, /*tp_setattr*/
612 (cmpfunc)float_compare, /*tp_compare*/
613 (reprfunc)float_repr, /*tp_repr*/
614 &float_as_number, /*tp_as_number*/
615 0, /*tp_as_sequence*/
616 0, /*tp_as_mapping*/
617 (hashfunc)float_hash, /*tp_hash*/
620 void
621 PyFloat_Fini()
623 PyFloatObject *p;
624 PyFloatBlock *list, *next;
625 int i;
626 int bc, bf; /* block count, number of freed blocks */
627 int frem, fsum; /* remaining unfreed floats per block, total */
629 bc = 0;
630 bf = 0;
631 fsum = 0;
632 list = block_list;
633 block_list = NULL;
634 free_list = NULL;
635 while (list != NULL) {
636 bc++;
637 frem = 0;
638 for (i = 0, p = &list->objects[0];
639 i < N_FLOATOBJECTS;
640 i++, p++) {
641 if (PyFloat_Check(p) && p->ob_refcnt != 0)
642 frem++;
644 next = list->next;
645 if (frem) {
646 list->next = block_list;
647 block_list = list;
648 for (i = 0, p = &list->objects[0];
649 i < N_FLOATOBJECTS;
650 i++, p++) {
651 if (!PyFloat_Check(p) || p->ob_refcnt == 0) {
652 p->ob_type = (struct _typeobject *)
653 free_list;
654 free_list = p;
658 else {
659 PyMem_FREE(list);
660 bf++;
662 fsum += frem;
663 list = next;
665 if (!Py_VerboseFlag)
666 return;
667 fprintf(stderr, "# cleanup floats");
668 if (!fsum) {
669 fprintf(stderr, "\n");
671 else {
672 fprintf(stderr,
673 ": %d unfreed float%s in %d out of %d block%s\n",
674 fsum, fsum == 1 ? "" : "s",
675 bc - bf, bc, bc == 1 ? "" : "s");
677 if (Py_VerboseFlag > 1) {
678 list = block_list;
679 while (list != NULL) {
680 for (i = 0, p = &list->objects[0];
681 i < N_FLOATOBJECTS;
682 i++, p++) {
683 if (PyFloat_Check(p) && p->ob_refcnt != 0) {
684 char buf[100];
685 PyFloat_AsString(buf, p);
686 fprintf(stderr,
687 "# <float at %lx, refcnt=%d, val=%s>\n",
688 p, p->ob_refcnt, buf);
691 list = list->next;