[pypy-commit] pypy py3k: hg merge default

amauryfa noreply at buildbot.pypy.org
Sun Mar 3 16:05:58 CET 2013


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3k
Changeset: r61952:0bbb8eab0776
Date: 2013-03-03 15:57 +0100
http://bitbucket.org/pypy/pypy/changeset/0bbb8eab0776/

Log:	hg merge default

diff --git a/_pytest/pdb.py b/_pytest/pdb.py
--- a/_pytest/pdb.py
+++ b/_pytest/pdb.py
@@ -72,10 +72,10 @@
         tw.sep(">", "entering PDB")
         # A doctest.UnexpectedException is not useful for post_mortem.
         # Use the underlying exception instead:
-        if isinstance(call.excinfo.value, py.std.doctest.UnexpectedException):
-            tb = call.excinfo.value.exc_info[2]
-        else:
-            tb = call.excinfo._excinfo[2]
+        #if isinstance(call.excinfo.value, py.std.doctest.UnexpectedException):
+        #    tb = call.excinfo.value.exc_info[2]
+        #else:
+        tb = call.excinfo._excinfo[2]
         post_mortem(tb)
         rep._pdbshown = True
         return rep
diff --git a/dotviewer/drawgraph.py b/dotviewer/drawgraph.py
--- a/dotviewer/drawgraph.py
+++ b/dotviewer/drawgraph.py
@@ -7,9 +7,9 @@
 import re, os, math
 import pygame
 from pygame.locals import *
+from strunicode import forceunicode
 
 
-RAW_ENCODING = "utf-8"
 this_dir = os.path.dirname(os.path.abspath(__file__))
 FONT = os.path.join(this_dir, 'font', 'DroidSans.ttf')
 FIXEDFONT = os.path.join(this_dir, 'font', 'DroidSansMono.ttf')
@@ -52,12 +52,6 @@
     else:
         return default
 
-def forceunicode(name):
-    return name if isinstance(name, unicode) else name.decode(RAW_ENCODING)
-
-def forcestr(name):
-    return name if isinstance(name, str) else name.encode(RAW_ENCODING)
-
 
 class GraphLayout:
     fixedfont = False
diff --git a/dotviewer/graphclient.py b/dotviewer/graphclient.py
--- a/dotviewer/graphclient.py
+++ b/dotviewer/graphclient.py
@@ -1,6 +1,7 @@
 import os, sys, re
 import subprocess
 import msgstruct
+from strunicode import forcestr
 
 this_dir = os.path.dirname(os.path.abspath(__file__))
 GRAPHSERVER = os.path.join(this_dir, 'graphserver.py')
@@ -33,7 +34,6 @@
     def reload(graph_id):
         page = getpage(graph_id)
         if save_tmp_file:
-            from drawgraph import forcestr
             f = open(save_tmp_file, 'w')
             f.write(forcestr(page.source))
             f.close()
@@ -76,7 +76,6 @@
 
 def page_messages(page, graph_id):
     import graphparse
-    from drawgraph import forcestr
     return graphparse.parse_dot(graph_id, forcestr(page.source), page.links,
                                 getattr(page, 'fixedfont', False))
 
diff --git a/dotviewer/graphdisplay.py b/dotviewer/graphdisplay.py
--- a/dotviewer/graphdisplay.py
+++ b/dotviewer/graphdisplay.py
@@ -4,7 +4,8 @@
 from pygame.locals import *
 from drawgraph import GraphRenderer, FIXEDFONT
 from drawgraph import Node, Edge
-from drawgraph import EventQueue, wait_for_events, forceunicode, forcestr
+from drawgraph import EventQueue, wait_for_events
+from strunicode import forceunicode, forcestr
 
 
 METAKEYS = dict([
diff --git a/dotviewer/graphpage.py b/dotviewer/graphpage.py
--- a/dotviewer/graphpage.py
+++ b/dotviewer/graphpage.py
@@ -45,7 +45,7 @@
 class DotFileGraphPage(GraphPage):
     def compute(self, dotfile):
         import codecs
-        from drawgraph import RAW_ENCODING
+        from strunicode import RAW_ENCODING
         f = codecs.open(dotfile, 'r', RAW_ENCODING)
         self.source = f.read()
         f.close()
diff --git a/dotviewer/msgstruct.py b/dotviewer/msgstruct.py
--- a/dotviewer/msgstruct.py
+++ b/dotviewer/msgstruct.py
@@ -24,9 +24,15 @@
 long_max = 2147483647
 
 
+def _encodeme(x):
+    if type(x) is unicode:
+        x = x.encode('utf-8')
+    return x
+
 def message(tp, *values):
     #print >> sys.stderr, tp, values
     typecodes = ['']
+    values = map(_encodeme, values)
     for v in values:
         if type(v) is str:
             typecodes.append('%ds' % len(v))
diff --git a/pypy/doc/project-ideas.rst b/pypy/doc/project-ideas.rst
--- a/pypy/doc/project-ideas.rst
+++ b/pypy/doc/project-ideas.rst
@@ -88,7 +88,7 @@
 
 PyPy has pluggable garbage collection policy. This means that various garbage
 collectors can be written for specialized purposes, or even various
-experiments can be done for the general purpose. Examples
+experiments can be done for the general purpose. Examples:
 
 * An incremental garbage collector that has specified maximal pause times,
   crucial for games
@@ -97,6 +97,9 @@
 
 * A concurrent garbage collector (a lot of work)
 
+* A collector that keeps object flags in separate memory pages, to avoid
+  un-sharing all pages between several fork()ed processes
+
 STM (Software Transactional Memory)
 -----------------------------------
 
diff --git a/pypy/interpreter/app_main.py b/pypy/interpreter/app_main.py
--- a/pypy/interpreter/app_main.py
+++ b/pypy/interpreter/app_main.py
@@ -589,7 +589,7 @@
                 # banner (unless "-q" was specified) and run
                 # $PYTHONSTARTUP.
                 if not quiet:
-                    print_banner()
+                    print_banner(not no_site)
                 python_startup = readenv and os.getenv('PYTHONSTARTUP')
                 if python_startup:
                     try:
@@ -679,10 +679,11 @@
 
     return status
 
-def print_banner():
+def print_banner(copyright):
     print('Python %s on %s' % (sys.version, sys.platform))
-    print('Type "help", "copyright", "credits" or '
-          '"license" for more information.')
+    if copyright:
+        print('Type "help", "copyright", "credits" or '
+              '"license" for more information.')
 
 STDLIB_WARNING = """\
 debug: WARNING: Library path not found, using compiled-in sys.path.
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1687,6 +1687,8 @@
     'UnicodeTranslateError',
     'ValueError',
     'ZeroDivisionError',
+    'RuntimeWarning',
+    'PendingDeprecationWarning',
     ]
 
 if sys.platform.startswith("win"):
diff --git a/pypy/interpreter/test2/test_app_main.py b/pypy/interpreter/test2/test_app_main.py
--- a/pypy/interpreter/test2/test_app_main.py
+++ b/pypy/interpreter/test2/test_app_main.py
@@ -757,6 +757,10 @@
                         expect_prompt=True, expect_banner=False)
         assert '42\n' in data
 
+    def test_option_S_copyright(self):
+        data = self.run('-S -i', expect_prompt=True, expect_banner=True)
+        assert 'copyright' not in data
+
     def test_non_interactive_stdout_fully_buffered(self):
         path = getscript(r"""
             import sys, time
diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py
--- a/pypy/module/_cffi_backend/cdataobj.py
+++ b/pypy/module/_cffi_backend/cdataobj.py
@@ -92,15 +92,20 @@
             cdata1 = self._cdata
             other = space.interpclass_w(w_other)
             if isinstance(other, W_CData):
+                if requires_ordering:
+                    if (isinstance(self.ctype, W_CTypePrimitive) or
+                        isinstance(other.ctype, W_CTypePrimitive)):
+                        raise OperationError(space.w_TypeError,
+                            space.wrap("cannot do comparison on a "
+                                       "primitive cdata"))
                 cdata2 = other._cdata
+            elif (misc.is_zero(space, w_other) and
+                     not isinstance(self.ctype, W_CTypePrimitive)):
+                cdata2 = lltype.nullptr(rffi.CCHARP.TO)
             else:
                 return space.w_NotImplemented
 
             if requires_ordering:
-                if (isinstance(self.ctype, W_CTypePrimitive) or
-                    isinstance(other.ctype, W_CTypePrimitive)):
-                    raise OperationError(space.w_TypeError,
-                        space.wrap("cannot do comparison on a primitive cdata"))
                 cdata1 = rffi.cast(lltype.Unsigned, cdata1)
                 cdata2 = rffi.cast(lltype.Unsigned, cdata2)
             return space.newbool(op(cdata1, cdata2))
diff --git a/pypy/module/_cffi_backend/ctypeptr.py b/pypy/module/_cffi_backend/ctypeptr.py
--- a/pypy/module/_cffi_backend/ctypeptr.py
+++ b/pypy/module/_cffi_backend/ctypeptr.py
@@ -156,6 +156,10 @@
         space = self.space
         ob = space.interpclass_w(w_ob)
         if not isinstance(ob, cdataobj.W_CData):
+            if misc.is_zero(space, w_ob):
+                NULL = lltype.nullptr(rffi.CCHARP.TO)
+                rffi.cast(rffi.CCHARPP, cdata)[0] = NULL
+                return
             raise self._convert_error("cdata pointer", w_ob)
         other = ob.ctype
         if not isinstance(other, W_CTypePtrBase):
@@ -258,7 +262,12 @@
 
     def _prepare_pointer_call_argument(self, w_init, cdata):
         space = self.space
-        if space.is_w(w_init, space.w_None):
+        if misc.is_zero(space, w_init):
+            # Convert 0 to NULL.  Note that passing 0 is not ambigous,
+            # despite the potential confusion: as a 'T*' argument, 0 means
+            # NULL, but as a 'T[]' argument it would mean "array of size 0"
+            # --- except that we specifically refuse to interpret numbers
+            # as the array size when passing arguments.
             rffi.cast(rffi.CCHARPP, cdata)[0] = lltype.nullptr(rffi.CCHARP.TO)
             return 3
         elif (space.isinstance_w(w_init, space.w_list) or
diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py
--- a/pypy/module/_cffi_backend/misc.py
+++ b/pypy/module/_cffi_backend/misc.py
@@ -209,6 +209,11 @@
 neg_msg = "can't convert negative number to unsigned"
 ovf_msg = "long too big to convert"
 
+def is_zero(space, w_ob):
+    return ((space.isinstance_w(w_ob, space.w_int) or
+             space.isinstance_w(w_ob, space.w_long))
+            and not space.is_true(w_ob))
+
 # ____________________________________________________________
 
 class _NotStandardObject(Exception):
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -388,6 +388,19 @@
     assert (x == ["hello"]) is False
     assert (x != ["hello"]) is True
 
+def test_cmp_pointer_with_0():
+    p = new_pointer_type(new_primitive_type("int"))
+    x = cast(p, 0)
+    assert (x == 0) is True
+    assert (x != 0) is False
+    assert (0 == x) is True
+    assert (0 != x) is False
+    y = cast(p, 42)
+    assert (y == 0) is False
+    assert (y != 0) is True
+    assert (0 == y) is False
+    assert (0 != y) is True
+
 def test_invalid_indexing():
     p = new_primitive_type("int")
     x = cast(p, 42)
@@ -766,6 +779,7 @@
     assert s.a2 == 456
     assert s.a3 == 0
     assert s.p4 == cast(BVoidP, 0)
+    assert s.p4 == 0
     #
     s = newp(BStructPtr, {'a2': 41122, 'a3': -123})
     assert s.a1 == 0
@@ -778,8 +792,13 @@
     p = newp(BIntPtr, 14141)
     s = newp(BStructPtr, [12, 34, 56, p])
     assert s.p4 == p
+    s.p4 = 0
+    assert s.p4 == 0
     #
     s = newp(BStructPtr, [12, 34, 56, cast(BVoidP, 0)])
+    assert s.p4 == 0
+    #
+    s = newp(BStructPtr, [12, 34, 56, 0])
     assert s.p4 == cast(BVoidP, 0)
     #
     py.test.raises(TypeError, newp, BStructPtr, [12, 34, 56, None])
@@ -998,8 +1017,12 @@
     f = cast(BFunc23, _testfunc(23))
     res = f(b"foo")
     assert res == 1000 * ord(b'f')
-    res = f(None)
+    res = f(0)          # NULL
     assert res == -42
+    res = f(long(0))    # NULL
+    assert res == -42
+    py.test.raises(TypeError, f, None)
+    py.test.raises(TypeError, f, 0.0)
 
 def test_call_function_23_bis():
     # declaring the function as int(unsigned char*)
diff --git a/pypy/module/_minimal_curses/fficurses.py b/pypy/module/_minimal_curses/fficurses.py
--- a/pypy/module/_minimal_curses/fficurses.py
+++ b/pypy/module/_minimal_curses/fficurses.py
@@ -35,7 +35,7 @@
 c_tigetstr = rffi.llexternal('tigetstr', [rffi.CCHARP], rffi.CCHARP,
                              compilation_info=eci)
 c_tparm = rffi.llexternal('tparm', [rffi.CCHARP, INT, INT, INT, INT, INT,
-                                    INT, INT, INT, INT, INT], rffi.CCHARP,
+                                    INT, INT, INT, INT], rffi.CCHARP,
                           compilation_info=eci)
 
 ERR = rffi.CConstant('ERR', lltype.Signed)
@@ -97,13 +97,13 @@
 
 def tparm_llimpl(s, args):
     check_setup_invoked()
-    l = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
-    for i in range(min(len(args), 10)):
+    l = [0, 0, 0, 0, 0, 0, 0, 0, 0]
+    for i in range(min(len(args), 9)):
         l[i] = args[i]
     ll_s = rffi.str2charp(s)
     # XXX nasty trick stolen from CPython
     ll_res = c_tparm(ll_s, l[0], l[1], l[2], l[3], l[4], l[5], l[6],
-                     l[7], l[8], l[9])
+                     l[7], l[8])
     rffi.free_charp(ll_s)
     res = rffi.charp2str(ll_res)
     return res
diff --git a/pypy/module/math/interp_math.py b/pypy/module/math/interp_math.py
--- a/pypy/module/math/interp_math.py
+++ b/pypy/module/math/interp_math.py
@@ -416,210 +416,17 @@
 
 def erf(space, w_x):
     """The error function"""
-    return math1(space, _erf, w_x)
+    return math1(space, rfloat.erf, w_x)
 
 def erfc(space, w_x):
     """The complementary error function"""
-    return math1(space, _erfc, w_x)
+    return math1(space, rfloat.erfc, w_x)
 
 def gamma(space, w_x):
     """Compute the gamma function for x."""
-    return math1(space, _gamma, w_x)
+    return math1(space, rfloat.gamma, w_x)
 
 def lgamma(space, w_x):
     """Compute the natural logarithm of the gamma function for x."""
-    return math1(space, _lgamma, w_x)
+    return math1(space, rfloat.lgamma, w_x)
 
-# Implementation of the error function, the complimentary error function, the
-# gamma function, and the natural log of the gamma function.  These exist in
-# libm, but I hear those implementations are horrible.
-
-ERF_SERIES_CUTOFF = 1.5
-ERF_SERIES_TERMS = 25
-ERFC_CONTFRAC_CUTOFF = 30.
-ERFC_CONTFRAC_TERMS = 50
-_sqrtpi = 1.772453850905516027298167483341145182798
-
-def _erf_series(x):
-    x2 = x * x
-    acc = 0.
-    fk = ERF_SERIES_TERMS + .5
-    for i in range(ERF_SERIES_TERMS):
-        acc = 2.0 + x2 * acc / fk
-        fk -= 1.
-    return acc * x * math.exp(-x2) / _sqrtpi
-
-def _erfc_contfrac(x):
-    if x >= ERFC_CONTFRAC_CUTOFF:
-        return 0.
-    x2 = x * x
-    a = 0.
-    da = .5
-    p = 1.
-    p_last = 0.
-    q = da + x2
-    q_last = 1.
-    for i in range(ERFC_CONTFRAC_TERMS):
-        a += da
-        da += 2.
-        b = da + x2
-        p_last, p = p, b * p - a * p_last
-        q_last, q = q, b * q - a * q_last
-    return p / q * x * math.exp(-x2) / _sqrtpi
-
-def _erf(x):
-    if rfloat.isnan(x):
-        return x
-    absx = abs(x)
-    if absx < ERF_SERIES_CUTOFF:
-        return _erf_series(x)
-    else:
-        cf = _erfc_contfrac(absx)
-        return 1. - cf if x > 0. else cf - 1.
-
-def _erfc(x):
-    if rfloat.isnan(x):
-        return x
-    absx = abs(x)
-    if absx < ERF_SERIES_CUTOFF:
-        return 1. - _erf_series(x)
-    else:
-        cf = _erfc_contfrac(absx)
-        return cf if x > 0. else 2. - cf
-
-def _sinpi(x):
-    y = math.fmod(abs(x), 2.)
-    n = int(rfloat.round_away(2. * y))
-    if n == 0:
-        r = math.sin(math.pi * y)
-    elif n == 1:
-        r = math.cos(math.pi * (y - .5))
-    elif n == 2:
-        r = math.sin(math.pi * (1. - y))
-    elif n == 3:
-        r = -math.cos(math.pi * (y - 1.5))
-    elif n == 4:
-        r = math.sin(math.pi * (y - 2.))
-    else:
-        raise AssertionError("should not reach")
-    return rfloat.copysign(1., x) * r
-
-_lanczos_g = 6.024680040776729583740234375
-_lanczos_g_minus_half = 5.524680040776729583740234375
-_lanczos_num_coeffs = [
-    23531376880.410759688572007674451636754734846804940,
-    42919803642.649098768957899047001988850926355848959,
-    35711959237.355668049440185451547166705960488635843,
-    17921034426.037209699919755754458931112671403265390,
-    6039542586.3520280050642916443072979210699388420708,
-    1439720407.3117216736632230727949123939715485786772,
-    248874557.86205415651146038641322942321632125127801,
-    31426415.585400194380614231628318205362874684987640,
-    2876370.6289353724412254090516208496135991145378768,
-    186056.26539522349504029498971604569928220784236328,
-    8071.6720023658162106380029022722506138218516325024,
-    210.82427775157934587250973392071336271166969580291,
-    2.5066282746310002701649081771338373386264310793408
-]
-_lanczos_den_coeffs = [
-    0.0, 39916800.0, 120543840.0, 150917976.0, 105258076.0, 45995730.0,
-    13339535.0, 2637558.0, 357423.0, 32670.0, 1925.0, 66.0, 1.0]
-LANCZOS_N = len(_lanczos_den_coeffs)
-_lanczos_n_iter = unroll.unrolling_iterable(range(LANCZOS_N))
-_lanczos_n_iter_back = unroll.unrolling_iterable(range(LANCZOS_N - 1, -1, -1))
-_gamma_integrals = [
-    1.0, 1.0, 2.0, 6.0, 24.0, 120.0, 720.0, 5040.0, 40320.0, 362880.0,
-    3628800.0, 39916800.0, 479001600.0, 6227020800.0, 87178291200.0,
-    1307674368000.0, 20922789888000.0, 355687428096000.0,
-    6402373705728000.0, 121645100408832000.0, 2432902008176640000.0,
-    51090942171709440000.0, 1124000727777607680000.0]
-
-def _lanczos_sum(x):
-    num = 0.
-    den = 0.
-    assert x > 0.
-    if x < 5.:
-        for i in _lanczos_n_iter_back:
-            num = num * x + _lanczos_num_coeffs[i]
-            den = den * x + _lanczos_den_coeffs[i]
-    else:
-        for i in _lanczos_n_iter:
-            num = num / x + _lanczos_num_coeffs[i]
-            den = den / x + _lanczos_den_coeffs[i]
-    return num / den
-
-def _gamma(x):
-    if rfloat.isnan(x) or (rfloat.isinf(x) and x > 0.):
-        return x
-    if rfloat.isinf(x):
-        raise ValueError("math domain error")
-    if x == 0.:
-        raise ValueError("math domain error")
-    if x == math.floor(x):
-        if x < 0.:
-            raise ValueError("math domain error")
-        if x < len(_gamma_integrals):
-            return _gamma_integrals[int(x) - 1]
-    absx = abs(x)
-    if absx < 1e-20:
-        r = 1. / x
-        if rfloat.isinf(r):
-            raise OverflowError("math range error")
-        return r
-    if absx > 200.:
-        if x < 0.:
-            return 0. / -_sinpi(x)
-        else:
-            raise OverflowError("math range error")
-    y = absx + _lanczos_g_minus_half
-    if absx > _lanczos_g_minus_half:
-        q = y - absx
-        z = q - _lanczos_g_minus_half
-    else:
-        q = y - _lanczos_g_minus_half
-        z = q - absx
-    z = z * _lanczos_g / y
-    if x < 0.:
-        r = -math.pi / _sinpi(absx) / absx * math.exp(y) / _lanczos_sum(absx)
-        r -= z * r
-        if absx < 140.:
-            r /= math.pow(y, absx - .5)
-        else:
-            sqrtpow = math.pow(y, absx / 2. - .25)
-            r /= sqrtpow
-            r /= sqrtpow
-    else:
-        r = _lanczos_sum(absx) / math.exp(y)
-        r += z * r
-        if absx < 140.:
-            r *= math.pow(y, absx - .5)
-        else:
-            sqrtpow = math.pow(y, absx / 2. - .25)
-            r *= sqrtpow
-            r *= sqrtpow
-    if rfloat.isinf(r):
-        raise OverflowError("math range error")
-    return r
-
-def _lgamma(x):
-    if rfloat.isnan(x):
-        return x
-    if rfloat.isinf(x):
-        return rfloat.INFINITY
-    if x == math.floor(x) and x <= 2.:
-        if x <= 0.:
-            raise ValueError("math range error")
-        return 0.
-    absx = abs(x)
-    if absx < 1e-20:
-        return -math.log(absx)
-    if x > 0.:
-        r = (math.log(_lanczos_sum(x)) - _lanczos_g + (x - .5) *
-             (math.log(x + _lanczos_g - .5) - 1))
-    else:
-        r = (math.log(math.pi) - math.log(abs(_sinpi(absx))) - math.log(absx) -
-             (math.log(_lanczos_sum(absx)) - _lanczos_g +
-              (absx - .5) * (math.log(absx + _lanczos_g - .5) - 1)))
-    if rfloat.isinf(r):
-        raise OverflowError("math domain error")
-    return r
diff --git a/pypy/module/math/test/test_math.py b/pypy/module/math/test/test_math.py
--- a/pypy/module/math/test/test_math.py
+++ b/pypy/module/math/test/test_math.py
@@ -170,139 +170,6 @@
         raises(ValueError, math.atanh, 1.)
         assert math.isnan(math.atanh(float("nan")))
 
-    def test_mtestfile(self):
-        import math
-        import zipfile
-        import os
-        import struct
-        def _parse_mtestfile(fname):
-            """Parse a file with test values
-
-            -- starts a comment
-            blank lines, or lines containing only a comment, are ignored
-            other lines are expected to have the form
-              id fn arg -> expected [flag]*
-
-            """
-            with open(fname) as fp:
-                for line in fp:
-                    # strip comments, and skip blank lines
-                    if '--' in line:
-                        line = line[:line.index('--')]
-                    if not line.strip():
-                        continue
-
-                    lhs, rhs = line.split('->')
-                    id, fn, arg = lhs.split()
-                    rhs_pieces = rhs.split()
-                    exp = rhs_pieces[0]
-                    flags = rhs_pieces[1:]
-
-                    yield (id, fn, float(arg), float(exp), flags)
-        def to_ulps(x):
-            """Convert a non-NaN float x to an integer, in such a way that
-            adjacent floats are converted to adjacent integers.  Then
-            abs(ulps(x) - ulps(y)) gives the difference in ulps between two
-            floats.
-
-            The results from this function will only make sense on platforms
-            where C doubles are represented in IEEE 754 binary64 format.
-
-            """
-            n = struct.unpack('<q', struct.pack('<d', x))[0]
-            if n < 0:
-                n = ~(n+2**63)
-            return n
-
-        def ulps_check(expected, got, ulps=20):
-            """Given non-NaN floats `expected` and `got`,
-            check that they're equal to within the given number of ulps.
-
-            Returns None on success and an error message on failure."""
-
-            ulps_error = to_ulps(got) - to_ulps(expected)
-            if abs(ulps_error) <= ulps:
-                return None
-            return "error = {} ulps; permitted error = {} ulps".format(ulps_error,
-                                                                       ulps)
-
-        def acc_check(expected, got, rel_err=2e-15, abs_err = 5e-323):
-            """Determine whether non-NaN floats a and b are equal to within a
-            (small) rounding error.  The default values for rel_err and
-            abs_err are chosen to be suitable for platforms where a float is
-            represented by an IEEE 754 double.  They allow an error of between
-            9 and 19 ulps."""
-
-            # need to special case infinities, since inf - inf gives nan
-            if math.isinf(expected) and got == expected:
-                return None
-
-            error = got - expected
-
-            permitted_error = max(abs_err, rel_err * abs(expected))
-            if abs(error) < permitted_error:
-                return None
-            return "error = {}; permitted error = {}".format(error,
-                                                             permitted_error)
-
-        ALLOWED_ERROR = 20  # permitted error, in ulps
-        fail_fmt = "{}:{}({!r}): expected {!r}, got {!r}"
-
-        failures = []
-        math_testcases = os.path.join(os.path.dirname(zipfile.__file__), "test",
-                                      "math_testcases.txt")
-        for id, fn, arg, expected, flags in _parse_mtestfile(math_testcases):
-            func = getattr(math, fn)
-
-            if 'invalid' in flags or 'divide-by-zero' in flags:
-                expected = 'ValueError'
-            elif 'overflow' in flags:
-                expected = 'OverflowError'
-
-            try:
-                got = func(arg)
-            except ValueError:
-                got = 'ValueError'
-            except OverflowError:
-                got = 'OverflowError'
-
-            accuracy_failure = None
-            if isinstance(got, float) and isinstance(expected, float):
-                if math.isnan(expected) and math.isnan(got):
-                    continue
-                if not math.isnan(expected) and not math.isnan(got):
-                    if fn == 'lgamma':
-                        # we use a weaker accuracy test for lgamma;
-                        # lgamma only achieves an absolute error of
-                        # a few multiples of the machine accuracy, in
-                        # general.
-                        accuracy_failure = acc_check(expected, got,
-                                                  rel_err = 5e-15,
-                                                  abs_err = 5e-15)
-                    elif fn == 'erfc':
-                        # erfc has less-than-ideal accuracy for large
-                        # arguments (x ~ 25 or so), mainly due to the
-                        # error involved in computing exp(-x*x).
-                        #
-                        # XXX Would be better to weaken this test only
-                        # for large x, instead of for all x.
-                        accuracy_failure = ulps_check(expected, got, 2000)
-
-                    else:
-                        accuracy_failure = ulps_check(expected, got, 20)
-                    if accuracy_failure is None:
-                        continue
-
-            if isinstance(got, str) and isinstance(expected, str):
-                if got == expected:
-                    continue
-
-            fail_msg = fail_fmt.format(id, fn, arg, expected, got)
-            if accuracy_failure is not None:
-                fail_msg += ' ({})'.format(accuracy_failure)
-            failures.append(fail_msg)
-        assert not failures
-
     def test_trunc(self):
         import math
         assert math.trunc(1.9) == 1.0
@@ -420,3 +287,40 @@
                 return 99.9
 
         assert math.floor(CustomFloat()) == 99
+
+    def test_erf(self):
+        import math
+        assert math.erf(100.0) == 1.0
+        assert math.erf(-1000.0) == -1.0
+        assert math.erf(float("inf")) == 1.0
+        assert math.erf(float("-inf")) == -1.0
+        assert math.isnan(math.erf(float("nan")))
+        # proper tests are in rpython/rlib/test/test_rfloat
+        assert round(math.erf(1.0), 9) == 0.842700793
+
+    def test_erfc(self):
+        import math
+        assert math.erfc(0.0) == 1.0
+        assert math.erfc(-0.0) == 1.0
+        assert math.erfc(float("inf")) == 0.0
+        assert math.erfc(float("-inf")) == 2.0
+        assert math.isnan(math.erf(float("nan")))
+        assert math.erfc(1e-308) == 1.0
+
+    def test_gamma(self):
+        import math
+        assert raises(ValueError, math.gamma, 0.0)
+        assert math.gamma(5.0) == 24.0
+        assert math.gamma(6.0) == 120.0
+        assert raises(ValueError, math.gamma, -1)
+        assert math.gamma(0.5) == math.pi ** 0.5
+
+    def test_lgamma(self):
+        import math
+        math.lgamma(1.0) == 0.0
+        math.lgamma(2.0) == 0.0
+        # proper tests are in rpython/rlib/test/test_rfloat
+        assert round(math.lgamma(5.0), 9) == round(math.log(24.0), 9)
+        assert round(math.lgamma(6.0), 9) == round(math.log(120.0), 9)
+        assert raises(ValueError, math.gamma, -1)
+        assert round(math.lgamma(0.5), 9) == round(math.log(math.pi ** 0.5), 9)
diff --git a/pypy/module/math/test/test_translated.py b/pypy/module/math/test/test_translated.py
deleted file mode 100644
--- a/pypy/module/math/test/test_translated.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from rpython.translator.c.test.test_genc import compile
-from pypy.module.math.interp_math import _gamma
-
-
-def test_gamma_overflow():
-    def wrapper(arg):
-        try:
-            return _gamma(arg)
-        except OverflowError:
-            return -42
-    
-    f = compile(wrapper, [float])
-    assert f(10.0) == 362880.0
-    assert f(1720.0) == -42
-    assert f(172.0) == -42
diff --git a/pypy/module/micronumpy/arrayimpl/concrete.py b/pypy/module/micronumpy/arrayimpl/concrete.py
--- a/pypy/module/micronumpy/arrayimpl/concrete.py
+++ b/pypy/module/micronumpy/arrayimpl/concrete.py
@@ -416,8 +416,8 @@
         return raw_storage_getitem(lltype.Char, self.impl.storage, item)
 
     def setitem(self, item, v):
-        return raw_storage_setitem(self.impl.storage, item,
-                                   rffi.cast(lltype.Char, v))
+        raw_storage_setitem(self.impl.storage, item,
+                            rffi.cast(lltype.Char, v))
 
     def getlength(self):
         return self.impl.size
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -304,10 +304,11 @@
             reference = [0, -1, 0, 1, 0]
             if dtype[0] == 'u':
                 reference[1] = 0
-            elif dtype == 'int32':
-                    reference[2] = -2147483648
-            elif dtype == 'int64':
-                    reference[2] = -9223372036854775808
+            # XXX need to fix specialization issue in types.py first
+            #elif dtype == 'int32':
+            #        reference[2] = -2147483648
+            #elif dtype == 'int64':
+            #        reference[2] = -9223372036854775808
             a = array([-2, -1, 0, 1, 2], dtype)
             b = reciprocal(a)
             assert (b == reference).all()
diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py
--- a/pypy/module/micronumpy/types.py
+++ b/pypy/module/micronumpy/types.py
@@ -502,17 +502,18 @@
     def invert(self, v):
         return ~v
 
-    if 0: # XXX breaks translation
-        @simple_unary_op
-        def reciprocal(self, v):
-            if v == 0:
-                # XXX good place to warn
-                if self.T in (rffi.INT, rffi.LONG):
-                    return most_neg_value_of(self.T)
-                return 0
-            if v == 1 or v == -1:
-                return v
+    @simple_unary_op
+    def reciprocal(self, v):
+        if v == 0:
+            # XXX good place to warn
+            # XXX can't do the following, func is specialized only on argtype(v)
+            # (which is the same for all int classes)
+            #if self.T in (rffi.INT, rffi.LONG):
+            #    return most_neg_value_of(self.T)
             return 0
+        if abs(v) == 1:
+            return v
+        return 0
 
     @raw_unary_op
     def signbit(self, v):
diff --git a/pypy/module/pypyjit/test_pypy_c/test_min_max.py b/pypy/module/pypyjit/test_pypy_c/test_min_max.py
--- a/pypy/module/pypyjit/test_pypy_c/test_min_max.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_min_max.py
@@ -24,27 +24,42 @@
             --TICK--
             jump(p0, p1, p2, p3, i11, i9, descr=...)
         """)
+        
 
     def test_silly_max(self):
         def main():
-            i = 2
+            i = 13
             sa = 0
-            while i < 300:
-                lst = range(i)
+            while i < 30000:
+                lst = range(i % 1000 + 2)
                 sa += max(*lst) # ID: max
                 i += 1
             return sa
         log = self.run(main, [])
         assert log.result == main()
         loop, = log.loops_by_filename(self.filepath)
-        # We dont want too many guards, but a residual call to min_max_loop
-        guards = [n for n in log.opnames(loop.ops_by_id("max")) if n.startswith('guard')]
-        assert len(guards) < 20
-        assert loop.match_by_id('max',"""
+        assert loop.match("""
             ...
-            p76 = call_may_force(ConstClass(min_max_trampoline), _, _, descr=...)
+            p76 = call_assembler(_, _, _, _, descr=...)
             ...
         """)
+        loop2 = log.loops[0]
+        loop2.match('''
+        ...
+        label(..., descr=...)
+        ...
+        label(..., descr=...)
+        i17 = int_ge(i11, i7)
+        guard_false(i17, descr=...)
+        p18 = getarrayitem_gc(p5, i11, descr=...)
+        i19 = int_add(i11, 1)
+        setfield_gc(p2, i19, descr=...)
+        guard_class(p18, ConstClass(W_IntObject), descr=...)
+        i20 = getfield_gc_pure(p18, descr=...)
+        i21 = int_gt(i20, i14)
+        guard_true(i21, descr=...)
+        jump(..., descr=...)
+        ''')
 
     def test_iter_max(self):
         def main():
@@ -61,8 +76,8 @@
         # We dont want too many guards, but a residual call to min_max_loop
         guards = [n for n in log.opnames(loop.ops_by_id("max")) if n.startswith('guard')]
         assert len(guards) < 20
-        assert loop.match_by_id('max',"""
+        assert loop.match("""
             ...
-            p76 = call_may_force(ConstClass(min_max_trampoline), _, _, descr=...)
+            p76 = call_assembler(_, _, _, _, descr=...)
             ...
         """)
diff --git a/pypy/objspace/fake/checkmodule.py b/pypy/objspace/fake/checkmodule.py
--- a/pypy/objspace/fake/checkmodule.py
+++ b/pypy/objspace/fake/checkmodule.py
@@ -5,16 +5,18 @@
 def checkmodule(*modnames):
     config = get_pypy_config(translating=True)
     space = FakeObjSpace(config)
+    seeobj_w = []
     for modname in modnames:
         mod = __import__('pypy.module.%s' % modname, None, None, ['__doc__'])
         # force computation and record what we wrap
         module = mod.Module(space, W_Root())
         for name in module.loaders:
-            module._load_lazily(space, name)
+            seeobj_w.append(module._load_lazily(space, name))
         if hasattr(module, 'submodules'):
             for cls in module.submodules.itervalues():
                 submod = cls(space, W_Root())
                 for name in submod.loaders:
-                    submod._load_lazily(space, name)
+                    seeobj_w.append(submod._load_lazily(space, name))
     #
-    space.translates(**{'translation.list_comprehension_operations': True})
+    space.translates(seeobj_w=seeobj_w,
+                     **{'translation.list_comprehension_operations': True})
diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py
--- a/pypy/objspace/fake/objspace.py
+++ b/pypy/objspace/fake/objspace.py
@@ -2,7 +2,9 @@
 from pypy.interpreter import argument, gateway
 from pypy.interpreter.baseobjspace import W_Root, ObjSpace, Wrappable, SpaceCache
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
-from rpython.rlib.objectmodel import instantiate, we_are_translated
+from pypy.objspace.std.stdtypedef import StdTypeDef
+from pypy.objspace.std.sliceobject import W_SliceObject
+from rpython.rlib.objectmodel import instantiate, we_are_translated, specialize
 from rpython.rlib.nonconst import NonConstant
 from rpython.rlib.rarithmetic import r_uint, r_singlefloat
 from rpython.rtyper.extregistry import ExtRegistryEntry
@@ -133,11 +135,15 @@
         is_root(w_start)
         is_root(w_end)
         is_root(w_step)
+        W_SliceObject(w_start, w_end, w_step)
         return w_some_obj()
 
     def newint(self, x):
         return w_some_obj()
 
+    def newlong(self, x):
+        return w_some_obj()
+
     def newfloat(self, x):
         return w_some_obj()
 
@@ -147,6 +153,9 @@
     def newlong_from_rbigint(self, x):
         return w_some_obj()
 
+    def newseqiter(self, x):
+        return w_some_obj()
+
     def marshal_w(self, w_obj):
         "NOT_RPYTHON"
         raise NotImplementedError
@@ -231,7 +240,8 @@
 
     def gettypeobject(self, typedef):
         assert typedef is not None
-        return self.fromcache(TypeCache).getorbuild(typedef)
+        see_typedef(self, typedef)
+        return w_some_type()
 
     def type(self, w_obj):
         return w_some_type()
@@ -270,7 +280,7 @@
 
     # ----------
 
-    def translates(self, func=None, argtypes=None, **kwds):
+    def translates(self, func=None, argtypes=None, seeobj_w=[], **kwds):
         config = make_config(None, **kwds)
         if func is not None:
             if argtypes is None:
@@ -282,6 +292,10 @@
         ann = t.buildannotator()
         if func is not None:
             ann.build_types(func, argtypes, complete_now=False)
+        if seeobj_w:
+            def seeme(n):
+                return seeobj_w[n]
+            ann.build_types(seeme, [int], complete_now=False)
         #
         # annotate all _seen_extras, knowing that annotating some may
         # grow the list
@@ -290,8 +304,10 @@
             #print self._seen_extras
             ann.build_types(self._seen_extras[done], [],
                             complete_now=False)
+            ann.complete_pending_blocks()
             done += 1
         ann.complete()
+        assert done == len(self._seen_extras)
         #t.viewcg()
         t.buildrtyper().specialize()
         t.checkgraphs()
@@ -331,12 +347,12 @@
 
 # ____________________________________________________________
 
-class TypeCache(SpaceCache):
-    def build(cache, typedef):
-        assert isinstance(typedef, TypeDef)
-        for value in typedef.rawdict.values():
-            cache.space.wrap(value)
-        return w_some_obj()
+ at specialize.memo()
+def see_typedef(space, typedef):
+    assert isinstance(typedef, TypeDef)
+    if not isinstance(typedef, StdTypeDef):
+        for name, value in typedef.rawdict.items():
+            space.wrap(value)
 
 class FakeCompiler(object):
     pass
diff --git a/pypy/objspace/fake/test/test_checkmodule.py b/pypy/objspace/fake/test/test_checkmodule.py
--- a/pypy/objspace/fake/test/test_checkmodule.py
+++ b/pypy/objspace/fake/test/test_checkmodule.py
@@ -3,6 +3,7 @@
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from pypy.interpreter.gateway import interp2app, W_Root, ObjSpace
+from rpython.rlib.objectmodel import specialize
 from rpython.rtyper.test.test_llinterp import interpret
 
 def make_checker():
@@ -34,6 +35,22 @@
     space.translates()
     assert check
 
+def test_wrap_interp2app_later():
+    see, check = make_checker()
+    #
+    @specialize.memo()
+    def hithere(space):
+        space.wrap(interp2app(foobar2))
+    #
+    def foobar(space):
+        hithere(space)
+    def foobar2(space):
+        see()
+    space = FakeObjSpace()
+    space.wrap(interp2app(foobar))
+    space.translates()
+    assert check
+
 def test_wrap_GetSetProperty():
     see, check = make_checker()
     def foobar(w_obj, space):
@@ -76,3 +93,23 @@
         return len(w_type.mro_w)
 
     assert interpret(f, [1]) == 2
+
+def test_see_objects():
+    see, check = make_checker()
+    class W_Foo(Wrappable):
+        def __init__(self, x):
+            self.x = x
+        def do_it(self):
+            if self.x == 42:
+                return
+            see()
+    def f():
+        W_Foo(42).do_it()
+    #
+    space = FakeObjSpace()
+    space.translates(f)
+    assert not check
+    #
+    space = FakeObjSpace()
+    space.translates(f, seeobj_w=[W_Foo(15)])
+    assert check
diff --git a/rpython/annotator/annrpython.py b/rpython/annotator/annrpython.py
--- a/rpython/annotator/annrpython.py
+++ b/rpython/annotator/annrpython.py
@@ -192,12 +192,15 @@
             if not self.annotated[block]:
                 self.pendingblocks[block] = graph
 
+    def complete_pending_blocks(self):
+        while self.pendingblocks:
+            block, graph = self.pendingblocks.popitem()
+            self.processblock(graph, block)
+
     def complete(self):
         """Process pending blocks until none is left."""
         while True:
-            while self.pendingblocks:
-                block, graph = self.pendingblocks.popitem()
-                self.processblock(graph, block)
+            self.complete_pending_blocks()
             self.policy.no_more_blocks_to_annotate(self)
             if not self.pendingblocks:
                 break   # finished
diff --git a/rpython/annotator/description.py b/rpython/annotator/description.py
--- a/rpython/annotator/description.py
+++ b/rpython/annotator/description.py
@@ -351,6 +351,7 @@
                 row[desc.rowkey()] = graph
                 return s_ImpossibleValue   # meaningless
             desc.pycall(enlist, args, s_ImpossibleValue, op)
+            assert row
         return row
     row_to_consider = staticmethod(row_to_consider)
 
diff --git a/rpython/annotator/specialize.py b/rpython/annotator/specialize.py
--- a/rpython/annotator/specialize.py
+++ b/rpython/annotator/specialize.py
@@ -111,7 +111,8 @@
 
     def absorb(self, other):
         self.table.update(other.table)
-        self.graph = None   # just in case
+        assert self.graph is None, "too late for MemoTable merge!"
+        del other.graph   # just in case
         other.do_not_process = True
 
     fieldnamecounter = 0
diff --git a/rpython/jit/codewriter/test/test_flatten.py b/rpython/jit/codewriter/test/test_flatten.py
--- a/rpython/jit/codewriter/test/test_flatten.py
+++ b/rpython/jit/codewriter/test/test_flatten.py
@@ -137,7 +137,8 @@
         if liveness:
             from rpython.jit.codewriter.liveness import compute_liveness
             compute_liveness(ssarepr)
-        assert_format(ssarepr, expected)
+        if expected is not None:
+            assert_format(ssarepr, expected)
 
     def test_simple(self):
         def f(n):
@@ -322,6 +323,15 @@
             int_return $54
         """)
 
+    def test_switch_longlong(self):
+        def f(n):
+            n = r_longlong(n)
+            if n == r_longlong(-5):  return 12
+            elif n == r_longlong(2): return 51
+            elif n == r_longlong(7): return 1212
+            else:                    return 42
+        self.encoding_test(f, [65], None)
+
     def test_exc_exitswitch(self):
         def g(i):
             pass
diff --git a/rpython/rlib/rfloat.py b/rpython/rlib/rfloat.py
--- a/rpython/rlib/rfloat.py
+++ b/rpython/rlib/rfloat.py
@@ -1,9 +1,9 @@
 """Float constants"""
 
-import math
+import math, struct
 
 from rpython.annotator.model import SomeString, SomeChar
-from rpython.rlib import objectmodel
+from rpython.rlib import objectmodel, unroll
 from rpython.rtyper.extfunc import register_external
 from rpython.rtyper.tool import rffi_platform
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
@@ -441,3 +441,250 @@
     else:
         den = exp
     return num, den
+
+
+
+# Implementation of the error function, the complimentary error function, the
+# gamma function, and the natural log of the gamma function.  These exist in
+# libm, but I hear those implementations are horrible.
+
+ERF_SERIES_CUTOFF = 1.5
+ERF_SERIES_TERMS = 25
+ERFC_CONTFRAC_CUTOFF = 30.
+ERFC_CONTFRAC_TERMS = 50
+_sqrtpi = 1.772453850905516027298167483341145182798
+
+def _erf_series(x):
+    x2 = x * x
+    acc = 0.
+    fk = ERF_SERIES_TERMS + .5
+    for i in range(ERF_SERIES_TERMS):
+        acc = 2.0 + x2 * acc / fk
+        fk -= 1.
+    return acc * x * math.exp(-x2) / _sqrtpi
+
+def _erfc_contfrac(x):
+    if x >= ERFC_CONTFRAC_CUTOFF:
+        return 0.
+    x2 = x * x
+    a = 0.
+    da = .5
+    p = 1.
+    p_last = 0.
+    q = da + x2
+    q_last = 1.
+    for i in range(ERFC_CONTFRAC_TERMS):
+        a += da
+        da += 2.
+        b = da + x2
+        p_last, p = p, b * p - a * p_last
+        q_last, q = q, b * q - a * q_last
+    return p / q * x * math.exp(-x2) / _sqrtpi
+
+def erf(x):
+    """The error function at x."""
+    if isnan(x):
+        return x
+    absx = abs(x)
+    if absx < ERF_SERIES_CUTOFF:
+        return _erf_series(x)
+    else:
+        cf = _erfc_contfrac(absx)
+        return 1. - cf if x > 0. else cf - 1.
+
+def erfc(x):
+    """The complementary error function at x."""
+    if isnan(x):
+        return x
+    absx = abs(x)
+    if absx < ERF_SERIES_CUTOFF:
+        return 1. - _erf_series(x)
+    else:
+        cf = _erfc_contfrac(absx)
+        return cf if x > 0. else 2. - cf
+
+def _sinpi(x):
+    y = math.fmod(abs(x), 2.)
+    n = int(round_away(2. * y))
+    if n == 0:
+        r = math.sin(math.pi * y)
+    elif n == 1:
+        r = math.cos(math.pi * (y - .5))
+    elif n == 2:
+        r = math.sin(math.pi * (1. - y))
+    elif n == 3:
+        r = -math.cos(math.pi * (y - 1.5))
+    elif n == 4:
+        r = math.sin(math.pi * (y - 2.))
+    else:
+        raise AssertionError("should not reach")
+    return copysign(1., x) * r
+
+_lanczos_g = 6.024680040776729583740234375
+_lanczos_g_minus_half = 5.524680040776729583740234375
+_lanczos_num_coeffs = [
+    23531376880.410759688572007674451636754734846804940,
+    42919803642.649098768957899047001988850926355848959,
+    35711959237.355668049440185451547166705960488635843,
+    17921034426.037209699919755754458931112671403265390,
+    6039542586.3520280050642916443072979210699388420708,
+    1439720407.3117216736632230727949123939715485786772,
+    248874557.86205415651146038641322942321632125127801,
+    31426415.585400194380614231628318205362874684987640,
+    2876370.6289353724412254090516208496135991145378768,
+    186056.26539522349504029498971604569928220784236328,
+    8071.6720023658162106380029022722506138218516325024,
+    210.82427775157934587250973392071336271166969580291,
+    2.5066282746310002701649081771338373386264310793408
+]
+_lanczos_den_coeffs = [
+    0.0, 39916800.0, 120543840.0, 150917976.0, 105258076.0, 45995730.0,
+    13339535.0, 2637558.0, 357423.0, 32670.0, 1925.0, 66.0, 1.0]
+LANCZOS_N = len(_lanczos_den_coeffs)
+_lanczos_n_iter = unroll.unrolling_iterable(range(LANCZOS_N))
+_lanczos_n_iter_back = unroll.unrolling_iterable(range(LANCZOS_N - 1, -1, -1))
+_gamma_integrals = [
+    1.0, 1.0, 2.0, 6.0, 24.0, 120.0, 720.0, 5040.0, 40320.0, 362880.0,
+    3628800.0, 39916800.0, 479001600.0, 6227020800.0, 87178291200.0,
+    1307674368000.0, 20922789888000.0, 355687428096000.0,
+    6402373705728000.0, 121645100408832000.0, 2432902008176640000.0,
+    51090942171709440000.0, 1124000727777607680000.0]
+
+def _lanczos_sum(x):
+    num = 0.
+    den = 0.
+    assert x > 0.
+    if x < 5.:
+        for i in _lanczos_n_iter_back:
+            num = num * x + _lanczos_num_coeffs[i]
+            den = den * x + _lanczos_den_coeffs[i]
+    else:
+        for i in _lanczos_n_iter:
+            num = num / x + _lanczos_num_coeffs[i]
+            den = den / x + _lanczos_den_coeffs[i]
+    return num / den
+
+def gamma(x):
+    """Compute the gamma function for x."""
+    if isnan(x) or (isinf(x) and x > 0.):
+        return x
+    if isinf(x):
+        raise ValueError("math domain error")
+    if x == 0.:
+        raise ValueError("math domain error")
+    if x == math.floor(x):
+        if x < 0.:
+            raise ValueError("math domain error")
+        if x < len(_gamma_integrals):
+            return _gamma_integrals[int(x) - 1]
+    absx = abs(x)
+    if absx < 1e-20:
+        r = 1. / x
+        if isinf(r):
+            raise OverflowError("math range error")
+        return r
+    if absx > 200.:
+        if x < 0.:
+            return 0. / -_sinpi(x)
+        else:
+            raise OverflowError("math range error")
+    y = absx + _lanczos_g_minus_half
+    if absx > _lanczos_g_minus_half:
+        q = y - absx
+        z = q - _lanczos_g_minus_half
+    else:
+        q = y - _lanczos_g_minus_half
+        z = q - absx
+    z = z * _lanczos_g / y
+    if x < 0.:
+        r = -math.pi / _sinpi(absx) / absx * math.exp(y) / _lanczos_sum(absx)
+        r -= z * r
+        if absx < 140.:
+            r /= math.pow(y, absx - .5)
+        else:
+            sqrtpow = math.pow(y, absx / 2. - .25)
+            r /= sqrtpow
+            r /= sqrtpow
+    else:
+        r = _lanczos_sum(absx) / math.exp(y)
+        r += z * r
+        if absx < 140.:
+            r *= math.pow(y, absx - .5)
+        else:
+            sqrtpow = math.pow(y, absx / 2. - .25)
+            r *= sqrtpow
+            r *= sqrtpow
+    if isinf(r):
+        raise OverflowError("math range error")
+    return r
+
+def lgamma(x):
+    """Compute the natural logarithm of the gamma function for x."""
+    if isnan(x):
+        return x
+    if isinf(x):
+        return INFINITY
+    if x == math.floor(x) and x <= 2.:
+        if x <= 0.:
+            raise ValueError("math range error")
+        return 0.
+    absx = abs(x)
+    if absx < 1e-20:
+        return -math.log(absx)
+    if x > 0.:
+        r = (math.log(_lanczos_sum(x)) - _lanczos_g + (x - .5) *
+             (math.log(x + _lanczos_g - .5) - 1))
+    else:
+        r = (math.log(math.pi) - math.log(abs(_sinpi(absx))) - math.log(absx) -
+             (math.log(_lanczos_sum(absx)) - _lanczos_g +
+              (absx - .5) * (math.log(absx + _lanczos_g - .5) - 1)))
+    if isinf(r):
+        raise OverflowError("math domain error")
+    return r
+
+
+def to_ulps(x):
+    """Convert a non-NaN float x to an integer, in such a way that
+    adjacent floats are converted to adjacent integers.  Then
+    abs(ulps(x) - ulps(y)) gives the difference in ulps between two
+    floats.
+
+    The results from this function will only make sense on platforms
+    where C doubles are represented in IEEE 754 binary64 format.
+
+    """
+    n = struct.unpack('<q', struct.pack('<d', x))[0]
+    if n < 0:
+        n = ~(n+2**63)
+    return n
+
+def ulps_check(expected, got, ulps=20):
+    """Given non-NaN floats `expected` and `got`,
+    check that they're equal to within the given number of ulps.
+
+    Returns None on success and an error message on failure."""
+
+    ulps_error = to_ulps(got) - to_ulps(expected)
+    if abs(ulps_error) <= ulps:
+        return None
+    return "error = {} ulps; permitted error = {} ulps".format(ulps_error,
+                                                               ulps)
+
+def acc_check(expected, got, rel_err=2e-15, abs_err = 5e-323):
+    """Determine whether non-NaN floats a and b are equal to within a
+    (small) rounding error.  The default values for rel_err and
+    abs_err are chosen to be suitable for platforms where a float is
+    represented by an IEEE 754 double.  They allow an error of between
+    9 and 19 ulps."""
+
+    # need to special case infinities, since inf - inf gives nan
+    if math.isinf(expected) and got == expected:
+        return None
+
+    error = got - expected
+
+    permitted_error = max(abs_err, rel_err * abs(expected))
+    if abs(error) < permitted_error:
+        return None
+    return "error = {}; permitted error = {}".format(error,
+                                                     permitted_error)
diff --git a/lib-python/2.7/test/math_testcases.txt b/rpython/rlib/test/math_testcases.txt
copy from lib-python/2.7/test/math_testcases.txt
copy to rpython/rlib/test/math_testcases.txt
diff --git a/rpython/rlib/test/test_rfloat.py b/rpython/rlib/test/test_rfloat.py
--- a/rpython/rlib/test/test_rfloat.py
+++ b/rpython/rlib/test/test_rfloat.py
@@ -5,6 +5,8 @@
 from rpython.rlib.rfloat import copysign
 from rpython.rlib.rfloat import round_away
 from rpython.rlib.rfloat import round_double
+from rpython.rlib.rfloat import erf, erfc, gamma, lgamma, isnan
+from rpython.rlib.rfloat import ulps_check, acc_check
 from rpython.rlib.rbigint import rbigint
 
 def test_copysign():
@@ -129,3 +131,104 @@
         float_as_rbigint_ratio(float('-inf'))
     with py.test.raises(ValueError):
         float_as_rbigint_ratio(float('nan'))
+
+def test_mtestfile():
+    from rpython.rlib import rfloat
+    import zipfile
+    import os
+    def _parse_mtestfile(fname):
+        """Parse a file with test values
+
+        -- starts a comment
+        blank lines, or lines containing only a comment, are ignored
+        other lines are expected to have the form
+          id fn arg -> expected [flag]*
+
+        """
+        with open(fname) as fp:
+            for line in fp:
+                # strip comments, and skip blank lines
+                if '--' in line:
+                    line = line[:line.index('--')]
+                if not line.strip():
+                    continue
+
+                lhs, rhs = line.split('->')
+                id, fn, arg = lhs.split()
+                rhs_pieces = rhs.split()
+                exp = rhs_pieces[0]
+                flags = rhs_pieces[1:]
+
+                yield (id, fn, float(arg), float(exp), flags)
+
+    ALLOWED_ERROR = 20  # permitted error, in ulps
+    fail_fmt = "{}:{}({!r}): expected {!r}, got {!r}"
+
+    failures = []
+    math_testcases = os.path.join(os.path.dirname(__file__),
+                                  "math_testcases.txt")
+    for id, fn, arg, expected, flags in _parse_mtestfile(math_testcases):
+        func = getattr(rfloat, fn)
+
+        if 'invalid' in flags or 'divide-by-zero' in flags:
+            expected = 'ValueError'
+        elif 'overflow' in flags:
+            expected = 'OverflowError'
+
+        try:
+            got = func(arg)
+        except ValueError:
+            got = 'ValueError'
+        except OverflowError:
+            got = 'OverflowError'
+
+        accuracy_failure = None
+        if isinstance(got, float) and isinstance(expected, float):
+            if isnan(expected) and isnan(got):
+                continue
+            if not isnan(expected) and not isnan(got):
+                if fn == 'lgamma':
+                    # we use a weaker accuracy test for lgamma;
+                    # lgamma only achieves an absolute error of
+                    # a few multiples of the machine accuracy, in
+                    # general.
+                    accuracy_failure = acc_check(expected, got,
+                                              rel_err = 5e-15,
+                                              abs_err = 5e-15)
+                elif fn == 'erfc':
+                    # erfc has less-than-ideal accuracy for large
+                    # arguments (x ~ 25 or so), mainly due to the
+                    # error involved in computing exp(-x*x).
+                    #
+                    # XXX Would be better to weaken this test only
+                    # for large x, instead of for all x.
+                    accuracy_failure = ulps_check(expected, got, 2000)
+
+                else:
+                    accuracy_failure = ulps_check(expected, got, 20)
+                if accuracy_failure is None:
+                    continue
+
+        if isinstance(got, str) and isinstance(expected, str):
+            if got == expected:
+                continue
+
+        fail_msg = fail_fmt.format(id, fn, arg, expected, got)
+        if accuracy_failure is not None:
+            fail_msg += ' ({})'.format(accuracy_failure)
+        failures.append(fail_msg)
+    assert not failures
+
+
+def test_gamma_overflow_translated():
+    from rpython.translator.c.test.test_genc import compile
+    def wrapper(arg):
+        try:
+            return gamma(arg)
+        except OverflowError:
+            return -42
+
+    f = compile(wrapper, [float])
+    assert f(10.0) == 362880.0
+    assert f(1720.0) == -42
+    assert f(172.0) == -42
diff --git a/rpython/rtyper/lltypesystem/rstr.py b/rpython/rtyper/lltypesystem/rstr.py
--- a/rpython/rtyper/lltypesystem/rstr.py
+++ b/rpython/rtyper/lltypesystem/rstr.py
@@ -302,6 +302,7 @@
             b.chars[i] = str.chars[i]
         return b
 
+    @jit.look_inside_iff(lambda s: jit.isvirtual(s))
     @jit.elidable
     def ll_strhash(s):
         # unlike CPython, there is no reason to avoid to return -1
diff --git a/rpython/translator/backendopt/merge_if_blocks.py b/rpython/translator/backendopt/merge_if_blocks.py
--- a/rpython/translator/backendopt/merge_if_blocks.py
+++ b/rpython/translator/backendopt/merge_if_blocks.py
@@ -9,8 +9,10 @@
     if len(block.operations) > 1 and not first:
         return False
     op = block.operations[-1]
-    if (op.opname not in ('int_eq', 'uint_eq', 'llong_eq', 'ullong_eq',
-                          'char_eq', 'unichar_eq')
+    if (op.opname not in ('int_eq', 'uint_eq', 'char_eq', 'unichar_eq')
+        # note: 'llong_eq', 'ullong_eq' have been removed, as it's not
+        # strictly C-compliant to do a switch() on a long long.  It also
+        # crashes the JIT, and it's very very rare anyway.
         or op.result != block.exitswitch):
         return False
     if isinstance(op.args[0], Variable) and isinstance(op.args[1], Variable):
diff --git a/rpython/translator/backendopt/test/test_merge_if_blocks.py b/rpython/translator/backendopt/test/test_merge_if_blocks.py
--- a/rpython/translator/backendopt/test/test_merge_if_blocks.py
+++ b/rpython/translator/backendopt/test/test_merge_if_blocks.py
@@ -38,9 +38,10 @@
         return 4
     do_test_merge(merge_int, range(4))
     do_test_merge(merge_int, [r_uint(i) for i in range(4)])
-    if r_longlong is not r_int:
-        do_test_merge(merge_int, [r_longlong(i) for i in range(4)])
-    do_test_merge(merge_int, [r_ulonglong(i) for i in range(4)])
+    # this has been disabled:
+    #if r_longlong is not r_int:
+    #    do_test_merge(merge_int, [r_longlong(i) for i in range(4)])
+    #do_test_merge(merge_int, [r_ulonglong(i) for i in range(4)])
 
     def merge_chr(n):
         c = chr(n + 1)
diff --git a/rpython/translator/jvm/test/test_int.py b/rpython/translator/jvm/test/test_int.py
--- a/rpython/translator/jvm/test/test_int.py
+++ b/rpython/translator/jvm/test/test_int.py
@@ -16,5 +16,8 @@
 
     def test_rarithmetic(self):
         pass # does this make more sense in jvm
+
+    def test_str_of_uint(self):
+        py.test.skip("we don't care")
     
     div_mod_iteration_count = 20
diff --git a/rpython/translator/platform/netbsd.py b/rpython/translator/platform/netbsd.py
--- a/rpython/translator/platform/netbsd.py
+++ b/rpython/translator/platform/netbsd.py
@@ -18,7 +18,9 @@
 class Netbsd(posix.BasePosix):
     name = "netbsd"
 
-    link_flags = ['-pthread'] + get_env_vector('LDFLAGS', '')
+    link_flags = ['-pthread',
+                  '-Wl,-R' + get_env("LOCALBASE", "/usr/pkg") + '/lib'
+                 ] + get_env_vector('LDFLAGS', '')
     cflags = ['-O3', '-pthread', '-fomit-frame-pointer'
              ] + get_env_vector('CFLAGS', '')
     standalone_only = []
diff --git a/rpython/translator/sandbox/test/test_sandlib.py b/rpython/translator/sandbox/test/test_sandlib.py
--- a/rpython/translator/sandbox/test/test_sandlib.py
+++ b/rpython/translator/sandbox/test/test_sandlib.py
@@ -106,7 +106,7 @@
             pass
     
     def entry_point(argv):
-        fd = os.open("tcp://pypy.org:80", os.O_RDONLY, 0777)
+        fd = os.open("tcp://python.org:80", os.O_RDONLY, 0777)
         os.write(fd, 'GET /\n')
         print os.read(fd, 30)
         return 0
diff --git a/rpython/translator/tool/graphpage.py b/rpython/translator/tool/graphpage.py
--- a/rpython/translator/tool/graphpage.py
+++ b/rpython/translator/tool/graphpage.py
@@ -425,6 +425,8 @@
                     if block not in seen:
                         pending.append(block)
                         seen[block] = True
+                elif isinstance(y, dict):
+                    pending.append(y)   # go back from the dict to the real obj
         graph = IncompleteGraph(pending)
         SingleGraphPage(graph).display()
     else:


More information about the pypy-commit mailing list