[Python-checkins] CVS: python/dist/src/Objects longobject.c,1.96,1.97
Tim Peters
tim_one@users.sourceforge.net
Mon, 03 Sep 2001 19:50:51 -0700
Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv29765/python/Objects
Modified Files:
longobject.c
Log Message:
Introduce new private API function _PyLong_AsScaledDouble. Not used yet,
but will be the foundation for Good Things:
+ Speed PyLong_AsDouble.
+ Give PyLong_AsDouble the ability to detect overflow.
+ Make true division of long/long nearly as accurate as possible (no
spurious infinities or NaNs).
+ Return non-insane results from math.log and math.log10 when passing a
long that can't be approximated by a double better than HUGE_VAL.
Index: longobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v
retrieving revision 1.96
retrieving revision 1.97
diff -C2 -d -r1.96 -r1.97
*** longobject.c 2001/09/03 08:35:41 1.96
--- longobject.c 2001/09/04 02:50:49 1.97
***************
*** 475,478 ****
--- 475,530 ----
}
+ double
+ _PyLong_AsScaledDouble(PyObject *vv, int *exponent)
+ {
+ /* NBITS_WANTED should be > the number of bits in a double's precision,
+ but small enough so that 2**NBITS_WANTED is within the normal double
+ range. nbitsneeded is set to 1 less than that because the most-significant
+ Python digit contains at least 1 significant bit, but we don't want to
+ bother counting them (catering to the worst case cheaply).
+
+ 57 is one more than VAX-D double precision; I (Tim) don't know of a double
+ format with more precision than that; it's 1 larger so that we add in at
+ least one round bit to stand in for the ignored least-significant bits.
+ */
+ #define NBITS_WANTED 57
+ PyLongObject *v;
+ double x;
+ const double multiplier = (double)(1L << SHIFT);
+ int i, sign;
+ int nbitsneeded;
+
+ if (vv == NULL || !PyLong_Check(vv)) {
+ PyErr_BadInternalCall();
+ return -1;
+ }
+ v = (PyLongObject *)vv;
+ i = v->ob_size;
+ sign = 1;
+ if (i < 0) {
+ sign = -1;
+ i = -(i);
+ }
+ else if (i == 0) {
+ *exponent = 0;
+ return 0.0;
+ }
+ --i;
+ x = (double)v->ob_digit[i];
+ nbitsneeded = NBITS_WANTED - 1;
+ /* Invariant: i Python digits remain unaccounted for. */
+ while (i > 0 && nbitsneeded > 0) {
+ --i;
+ x = x * multiplier + (double)v->ob_digit[i];
+ nbitsneeded -= SHIFT;
+ }
+ /* There are i digits we didn't shift in. Pretending they're all
+ zeroes, the true value is x * 2**(i*SHIFT). */
+ *exponent = i;
+ assert(x > 0.0);
+ return x * sign;
+ #undef NBITS_WANTED
+ }
+
/* Get a C double from a long int object. */