[pypy-svn] pypy jit-longlong: Write this logic in RPython. Using rffi.llexternal() doesn't work
arigo
commits-noreply at bitbucket.org
Tue Jan 25 18:00:49 CET 2011
Author: Armin Rigo <arigo at tunes.org>
Branch: jit-longlong
Changeset: r41319:2244f262ab9f
Date: 2011-01-24 22:55 +0100
http://bitbucket.org/pypy/pypy/changeset/2244f262ab9f/
Log: Write this logic in RPython. Using rffi.llexternal() doesn't work
because the called C function can set an OverflowError.
diff --git a/pypy/objspace/std/smalllongobject.py b/pypy/objspace/std/smalllongobject.py
--- a/pypy/objspace/std/smalllongobject.py
+++ b/pypy/objspace/std/smalllongobject.py
@@ -43,12 +43,29 @@
# ____________________________________________________________
-from pypy.rpython.lltypesystem import lltype, rffi
-llong_mul_ovf = rffi.llexternal("op_llong_mul_ovf",
- [lltype.SignedLongLong] * 2,
- lltype.SignedLongLong,
- _callable=lambda x, y: x * y,
- _nowrapper=True, pure_function=True)
+def llong_mul_ovf(a, b):
+ # xxx duplication of the logic from translator/c/src/int.h
+ longprod = a * b
+ doubleprod = float(a) * float(b)
+ doubled_longprod = float(longprod)
+
+ # Fast path for normal case: small multiplicands, and no info
+ # is lost in either method.
+ if doubled_longprod == doubleprod:
+ return longprod
+
+ # Somebody somewhere lost info. Close enough, or way off? Note
+ # that a != 0 and b != 0 (else doubled_longprod == doubleprod == 0).
+ # The difference either is or isn't significant compared to the
+ # true value (of which doubleprod is a good approximation).
+ diff = doubled_longprod - doubleprod
+ absdiff = abs(diff)
+ absprod = abs(doubleprod)
+ # absdiff/absprod <= 1/32 iff
+ # 32 * absdiff <= absprod -- 5 good bits is "close enough"
+ if 32.0 * absdiff <= absprod:
+ return longprod
+ raise OverflowError("integer multiplication")
# ____________________________________________________________
More information about the Pypy-commit
mailing list