Source

pypy / pypy / rpython / test / test_rint.py

The branch 'remove-globals-in-jit' does not exist.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
import py
import sys, operator
from pypy.translator.translator import TranslationContext
from pypy.annotation import unaryop, binaryop
from pypy.rpython.test import snippet
from pypy.rlib.rarithmetic import r_int, r_uint, r_longlong, r_ulonglong
from pypy.rlib.rarithmetic import ovfcheck, r_int64, intmask, int_between
from pypy.rlib import objectmodel
from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin

from pypy.rpython.lltypesystem import lltype
from pypy.rpython.ootypesystem import ootype
from pypy.rpython.lltypesystem.lloperation import llop

class TestSnippet(object):

    def _test(self, func, types):
        t = TranslationContext()
        t.buildannotator().build_types(func, types)
        t.buildrtyper().specialize()
        t.checkgraphs()

    def test_not1(self):
        self._test(snippet.not1, [int])

    def test_not2(self):
        self._test(snippet.not2, [int])

    def test_int1(self):
        self._test(snippet.int1, [int])

    def test_int_cast1(self):
        self._test(snippet.int_cast1, [int])

    def DONTtest_unary_operations(self):
        # XXX TODO test if all unary operations are implemented
        for opname in unaryop.UNARY_OPERATIONS:
            print 'UNARY_OPERATIONS:', opname

    def DONTtest_binary_operations(self):
        # XXX TODO test if all binary operations are implemented
        for opname in binaryop.BINARY_OPERATIONS:
            print 'BINARY_OPERATIONS:', opname


class BaseTestRint(BaseRtypingTest):

    def test_char_constant(self):
        def dummyfn(i):
            return chr(i)
        res = self.interpret(dummyfn, [ord(' ')])
        assert res == ' '
        res = self.interpret(dummyfn, [0])
        assert res == '\0'
        res = self.interpret(dummyfn, [ord('a')])
        assert res == 'a'

    def test_str_of_int(self):
        def dummy(i):
            return str(i)

        res = self.interpret(dummy, [0])
        assert self.ll_to_string(res) == '0'

        res = self.interpret(dummy, [1034])
        assert self.ll_to_string(res) == '1034'

        res = self.interpret(dummy, [-123])
        assert self.ll_to_string(res) == '-123'

        res = self.interpret(dummy, [-sys.maxint-1])
        assert self.ll_to_string(res) == str(-sys.maxint-1)

    def test_hex_of_int(self):
        def dummy(i):
            return hex(i)

        res = self.interpret(dummy, [0])
        assert self.ll_to_string(res) == '0x0'

        res = self.interpret(dummy, [1034])
        assert self.ll_to_string(res) == '0x40a'

        res = self.interpret(dummy, [-123])
        assert self.ll_to_string(res) == '-0x7b'

        res = self.interpret(dummy, [-sys.maxint-1])
        res = self.ll_to_string(res)
        assert res == '-0x8' + '0' * (len(res)-4)

    def test_oct_of_int(self):
        def dummy(i):
            return oct(i)

        res = self.interpret(dummy, [0])
        assert self.ll_to_string(res) == '0'

        res = self.interpret(dummy, [1034])
        assert self.ll_to_string(res) == '02012'

        res = self.interpret(dummy, [-123])
        assert self.ll_to_string(res) == '-0173'

        res = self.interpret(dummy, [-sys.maxint-1])
        res = self.ll_to_string(res)
        assert res == '-' + oct(sys.maxint+1).replace('L', '').replace('l', '')

    def test_str_of_longlong(self):
        def f(i):
            return str(i)

        res = self.interpret(f, [r_int64(0)])
        assert self.ll_to_string(res) == '0'

        res = self.interpret(f, [r_int64(413974738222117)])
        assert self.ll_to_string(res) == '413974738222117'

    def test_unsigned(self):
        bigvalue = r_uint(sys.maxint + 17)
        def dummy(i):
            i = r_uint(i)
            j = bigvalue
            return i < j

        res = self.interpret(dummy,[0])
        assert res is True

        res = self.interpret(dummy, [-1])
        assert res is False    # -1 ==> 0xffffffff

    def test_specializing_int_functions(self):
        def f(i):
            return i + 1
        f._annspecialcase_ = "specialize:argtype(0)"
        def g(n):
            if n > 0:
                return f(r_int64(0))
            else:
                return f(0)
        res = self.interpret(g, [0])
        assert res == 1

        res = self.interpret(g, [1])
        assert res == 1

    def test_downcast_int(self):
        def f(i):
            return int(i)
        res = self.interpret(f, [r_int64(0)])
        assert res == 0

    def test_isinstance_vs_int_types(self):
        class FakeSpace(object):
            def wrap(self, x):
                if x is None:
                    return [None]
                if isinstance(x, str):
                    return x
                if isinstance(x, r_int64):
                    return int(x)
                return "XXX"
            wrap._annspecialcase_ = 'specialize:argtype(0)'

        space = FakeSpace()
        def wrap(x):
            return space.wrap(x)
        res = self.interpret(wrap, [r_int64(0)])
        assert res == 0

    def test_truediv(self):
        def f(n, m):
            return operator.truediv(n, m)
        res = self.interpret(f, [20, 4])
        assert type(res) is float
        assert res == 5.0

    def test_float_conversion(self):
        def f(ii):
            return float(ii)
        res = self.interpret(f, [r_int64(100000000)])
        assert type(res) is float
        assert res == 100000000.
        res = self.interpret(f, [r_int64(1234567890123456789)])
        assert type(res) is float
        assert self.float_eq(res, 1.2345678901234568e+18)

    def test_float_conversion_implicit(self):
        def f(ii):
            return 1.0 + ii
        res = self.interpret(f, [r_int64(100000000)])
        assert type(res) is float
        assert res == 100000001.
        res = self.interpret(f, [r_int64(1234567890123456789)])
        assert type(res) is float
        assert self.float_eq(res, 1.2345678901234568e+18)

    def test_rarithmetic(self):
        inttypes = [int, r_uint, r_int64, r_ulonglong]
        for inttype in inttypes:
            c = inttype()
            def f():
                return c
            res = self.interpret(f, [])
            assert res == f()
            assert type(res) == inttype

        for inttype in inttypes:
            def f():
                return inttype(0)
            res = self.interpret(f, [])
            assert res == f()
            assert type(res) == inttype

        for inttype in inttypes:
            def f(x):
                return x
            res = self.interpret(f, [inttype(0)])
            assert res == f(inttype(0))
            assert type(res) == inttype

    def test_and_or(self):
        inttypes = [int, r_uint, r_int64, r_ulonglong]
        for inttype in inttypes:
            def f(a, b, c):
                return a&b|c
            res = self.interpret(f, [inttype(0x1234), inttype(0x00FF), inttype(0x5600)])
            assert res == f(0x1234, 0x00FF, 0x5600)

    def test_neg_abs_ovf(self):
        for op in (operator.neg, abs):
            def f(x):
                try:
                    return ovfcheck(op(x))
                except OverflowError:
                    return 0
            res = self.interpret(f, [-1])
            assert res == 1
            res = self.interpret(f, [int(-1<<(r_int.BITS-1))])
            assert res == 0

    def test_lshift_rshift(self):
        for name, f in [('_lshift', lambda x, y: x << y),
                        ('_rshift', lambda x, y: x >> y)]:
            for inttype in (int, r_uint, r_int64, r_ulonglong):
                res = self.interpret(f, [inttype(2147483647), 12])
                if inttype is int:
                    assert res == intmask(f(2147483647, 12))
                else:
                    assert res == inttype(f(2147483647, 12))
                #
                # check that '*_[lr]shift' take an inttype and an
                # int as arguments, without the need for a
                # 'cast_int_to_{uint,longlong,...}'
                _, _, graph = self.gengraph(f, [inttype, int])
                block = graph.startblock
                assert len(block.operations) == 1
                assert block.operations[0].opname.endswith(name)

    def test_cast_uint_to_longlong(self):
        if r_uint.BITS == r_longlong.BITS:
            py.test.skip("only on 32-bits")
        def f(x):
            return r_longlong(r_uint(x))
        res = self.interpret(f, [-42])
        assert res == (sys.maxint+1) * 2 - 42

    div_mod_iteration_count = 1000
    def test_div_mod(self):
        import random

        for inttype in (int, r_int64):

            def d(x, y):
                return x/y

            for i in range(self.div_mod_iteration_count):
                x = inttype(random.randint(-100000, 100000))
                y = inttype(random.randint(-100000, 100000))
                if not y: continue
                if (i & 31) == 0:
                    x = (x//y) * y      # case where x is exactly divisible by y
                res = self.interpret(d, [x, y])
                assert res == d(x, y)

            def m(x, y):
                return x%y

            for i in range(self.div_mod_iteration_count):
                x = inttype(random.randint(-100000, 100000))
                y = inttype(random.randint(-100000, 100000))
                if not y: continue
                if (i & 31) == 0:
                    x = (x//y) * y      # case where x is exactly divisible by y
                res = self.interpret(m, [x, y])
                assert res == m(x, y)

    def test_protected_div_mod(self):
        def div_unpro(x, y):
            return x//y
        def div_ovf(x, y):
            try:
                return ovfcheck(x//y)
            except OverflowError:
                return 42
        def div_zer(x, y):
            try:
                return x//y
            except ZeroDivisionError:
                return 84
        def div_ovf_zer(x, y):
            try:
                return ovfcheck(x//y)
            except OverflowError:
                return 42
            except ZeroDivisionError:
                return 84

        def mod_unpro(x, y):
            return x%y
        def mod_ovf(x, y):
            try:
                return ovfcheck(x%y)
            except OverflowError:
                return 42
        def mod_zer(x, y):
            try:
                return x%y
            except ZeroDivisionError:
                return 84
        def mod_ovf_zer(x, y):
            try:
                return ovfcheck(x%y)
            except OverflowError:
                return 42
            except ZeroDivisionError:
                return 84

        for inttype in (int, r_int64):

            args = [( 5, 2), (-5, 2), ( 5,-2), (-5,-2),
                    ( 6, 2), (-6, 2), ( 6,-2), (-6,-2),
                    (-sys.maxint, -1), (4, 0)]

            funcs = [div_unpro, div_ovf, div_zer, div_ovf_zer,
                     mod_unpro, mod_ovf, mod_zer, mod_ovf_zer]

            for func in funcs:
                print func
                if 'ovf' in func.func_name and inttype is r_longlong:
                    continue # don't have many llong_*_ovf operations...
                for x, y in args:
                    x, y = inttype(x), inttype(y)
                    try:
                        res1 = func(x, y)
                        if isinstance(res1, int):
                            res1 = ovfcheck(res1)
                    except (OverflowError, ZeroDivisionError):
                        continue
                    res2 = self.interpret(func, [x, y])
                    assert res1 == res2

    def test_int_add_nonneg_ovf(self):
        def f(x):
            try:
                a = ovfcheck(x + 50)
            except OverflowError:
                return 0
            try:
                a += ovfcheck(100 + x)
            except OverflowError:
                return 1
            return a
        res = self.interpret(f, [-3])
        assert res == 144
        res = self.interpret(f, [sys.maxint-50])
        assert res == 1
        res = self.interpret(f, [sys.maxint])
        assert res == 0

    def test_cast_to_float_exc_check(self):
        def f(x):
            try:
                return float(x)
            except ValueError:
                return 3.0

        res = self.interpret(f, [3])
        assert res == 3

    def test_hash(self):
        def f(x):
            return objectmodel.compute_hash(x)
        res = self.interpret(f, [123456789])
        assert res == 123456789
        res = self.interpret(f, [r_int64(123456789012345678)])
        if sys.maxint == 2147483647:
            # check the way we compute such a hash so far
            assert res == -1506741426 + 9 * 28744523
        else:
            assert res == 123456789012345678

    def test_int_between(self):
        def fn(a, b, c):
            return int_between(a, b, c)
        assert self.interpret(fn, [1, 1, 3])
        assert self.interpret(fn, [1, 2, 3])
        assert not self.interpret(fn, [1, 0, 2])
        assert not self.interpret(fn, [1, 5, 2])
        assert not self.interpret(fn, [1, 2, 2])
        assert not self.interpret(fn, [1, 1, 1])



class TestLLtype(BaseTestRint, LLRtypeMixin):
    pass

class TestOOtype(BaseTestRint, OORtypeMixin):
    def test_oobox_int(self):
        def f():
            x = llop.oobox_int(ootype.Object, 42)
            return llop.oounbox_int(lltype.Signed, x)
        assert self.interpret(f, []) == 42