[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. */