~ubuntu-branches/ubuntu/wily/numexpr/wily-proposed

« back to all changes in this revision

Viewing changes to .pc/0002-skip-threading-tests-on-sparc.patch/numexpr/tests/test_numexpr.py

  • Committer: Package Import Robot
  • Author(s): Antonio Valentino
  • Date: 2013-12-09 18:54:24 UTC
  • mfrom: (7.1.9 sid)
  • Revision ID: package-import@ubuntu.com-20131209185424-65mkhb6tm6ts5lys
Tags: 2.2.2-3
* debian/rules:
  - run unittests in verbose mode
* debian/patches
  - dropped patch: 0002-relax-test-on-sparc.patch
    It does not actually fix the issue.
  - new patch 0002-skip-threading-tests-on-sparc.patch
    Skip all tests related to threading on sparc

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
###################################################################
 
2
#  Numexpr - Fast numerical array expression evaluator for NumPy.
 
3
#
 
4
#      License: MIT
 
5
#      Author:  See AUTHORS.txt
 
6
#
 
7
#  See LICENSE.txt and LICENSES/*.txt for details about copyright and
 
8
#  rights to use.
 
9
####################################################################
 
10
 
 
11
import os
 
12
import sys
 
13
import warnings
 
14
 
 
15
import numpy
 
16
from numpy import (
 
17
    array, arange, empty, zeros, int32, int64, uint16, complex_, float64, rec,
 
18
    copy, ones_like, where, alltrue, linspace,
 
19
    sum, prod, sqrt, fmod,
 
20
    sin, cos, tan, arcsin, arccos, arctan, arctan2,
 
21
    sinh, cosh, tanh, arcsinh, arccosh, arctanh,
 
22
    log, log1p, log10, exp, expm1)
 
23
from numpy.testing import (assert_equal, assert_array_equal,
 
24
    assert_array_almost_equal, assert_allclose)
 
25
from numpy import shape, allclose, array_equal, ravel, isnan, isinf
 
26
 
 
27
import numexpr
 
28
from numexpr import E, NumExpr, evaluate, disassemble, use_vml
 
29
 
 
30
import unittest
 
31
TestCase = unittest.TestCase
 
32
 
 
33
double = numpy.double
 
34
 
 
35
 
 
36
# Recommended minimum versions
 
37
minimum_numpy_version = "1.6"
 
38
 
 
39
class test_numexpr(TestCase):
 
40
    """Testing with 1 thread"""
 
41
    nthreads = 1
 
42
 
 
43
    def setUp(self):
 
44
        numexpr.set_num_threads(self.nthreads)
 
45
 
 
46
    def test_simple(self):
 
47
        ex = 2.0 * E.a + 3.0 * E.b * E.c
 
48
        sig = [('a', double), ('b', double), ('c', double)]
 
49
        func = NumExpr(ex, signature=sig)
 
50
        x = func(array([1., 2, 3]), array([4., 5, 6]), array([7., 8, 9]))
 
51
        assert_array_equal(x, array([  86.,  124.,  168.]))
 
52
 
 
53
    def test_simple_expr_small_array(self):
 
54
        func = NumExpr(E.a)
 
55
        x = arange(100.0)
 
56
        y = func(x)
 
57
        assert_array_equal(x, y)
 
58
 
 
59
    def test_simple_expr(self):
 
60
        func = NumExpr(E.a)
 
61
        x = arange(1e6)
 
62
        y = func(x)
 
63
        assert_array_equal(x, y)
 
64
 
 
65
    def test_rational_expr(self):
 
66
        func = NumExpr((E.a + 2.0*E.b) / (1 + E.a + 4*E.b*E.b))
 
67
        a = arange(1e6)
 
68
        b = arange(1e6) * 0.1
 
69
        x = (a + 2*b) / (1 + a + 4*b*b)
 
70
        y = func(a, b)
 
71
        assert_array_almost_equal(x, y)
 
72
 
 
73
    def test_reductions(self):
 
74
        # Check that they compile OK.
 
75
        assert_equal(disassemble(
 
76
            NumExpr("sum(x**2+2, axis=None)", [('x', double)])),
 
77
                     [(b'mul_ddd', b't3', b'r1[x]', b'r1[x]'),
 
78
                      (b'add_ddd', b't3', b't3', b'c2[2.0]'),
 
79
                      (b'sum_ddn', b'r0', b't3', None)])
 
80
        assert_equal(disassemble(
 
81
            NumExpr("sum(x**2+2, axis=1)", [('x', double)])),
 
82
                     [(b'mul_ddd', b't3', b'r1[x]', b'r1[x]'),
 
83
                      (b'add_ddd', b't3', b't3', b'c2[2.0]'),
 
84
                      (b'sum_ddn', b'r0', b't3', 1)])
 
85
        assert_equal(disassemble(
 
86
            NumExpr("prod(x**2+2, axis=2)", [('x', double)])),
 
87
                     [(b'mul_ddd', b't3', b'r1[x]', b'r1[x]'),
 
88
                      (b'add_ddd', b't3', b't3', b'c2[2.0]'),
 
89
                      (b'prod_ddn', b'r0', b't3', 2)])
 
90
        # Check that full reductions work.
 
91
        x = zeros(1e5)+.01   # checks issue #41
 
92
        assert_allclose(evaluate("sum(x+2,axis=None)"), sum(x+2,axis=None))
 
93
        assert_allclose(evaluate("sum(x+2,axis=0)"), sum(x+2,axis=0))
 
94
        assert_allclose(evaluate("prod(x,axis=0)"), prod(x,axis=0))
 
95
 
 
96
        x = arange(10.0)
 
97
        assert_allclose(evaluate("sum(x**2+2,axis=0)"), sum(x**2+2,axis=0))
 
98
        assert_allclose(evaluate("prod(x**2+2,axis=0)"), prod(x**2+2,axis=0))
 
99
 
 
100
        x = arange(100.0)
 
101
        assert_allclose(evaluate("sum(x**2+2,axis=0)"), sum(x**2+2,axis=0))
 
102
        assert_allclose(evaluate("prod(x-1,axis=0)"), prod(x-1,axis=0))
 
103
        x = linspace(0.1,1.0,2000)
 
104
        assert_allclose(evaluate("sum(x**2+2,axis=0)"), sum(x**2+2,axis=0))
 
105
        assert_allclose(evaluate("prod(x-1,axis=0)"), prod(x-1,axis=0))
 
106
 
 
107
        # Check that reductions along an axis work
 
108
        y = arange(9.0).reshape(3,3)
 
109
        assert_allclose(evaluate("sum(y**2, axis=1)"), sum(y**2, axis=1))
 
110
        assert_allclose(evaluate("sum(y**2, axis=0)"), sum(y**2, axis=0))
 
111
        assert_allclose(evaluate("sum(y**2, axis=None)"), sum(y**2, axis=None))
 
112
        assert_allclose(evaluate("prod(y**2, axis=1)"), prod(y**2, axis=1))
 
113
        assert_allclose(evaluate("prod(y**2, axis=0)"), prod(y**2, axis=0))
 
114
        assert_allclose(evaluate("prod(y**2, axis=None)"), prod(y**2, axis=None))
 
115
        # Check integers
 
116
        x = arange(10.)
 
117
        x = x.astype(int)
 
118
        assert_allclose(evaluate("sum(x**2+2,axis=0)"), sum(x**2+2,axis=0))
 
119
        assert_allclose(evaluate("prod(x**2+2,axis=0)"), prod(x**2+2,axis=0))
 
120
        # Check longs
 
121
        x = x.astype(long)
 
122
        assert_allclose(evaluate("sum(x**2+2,axis=0)"), sum(x**2+2,axis=0))
 
123
        assert_allclose(evaluate("prod(x**2+2,axis=0)"), prod(x**2+2,axis=0))
 
124
        # Check complex
 
125
        x = x + .1j
 
126
        assert_allclose(evaluate("sum(x**2+2,axis=0)"), sum(x**2+2,axis=0))
 
127
        assert_allclose(evaluate("prod(x-1,axis=0)"), prod(x-1,axis=0))
 
128
 
 
129
    def test_in_place(self):
 
130
        x = arange(10000.).reshape(1000,10)
 
131
        evaluate("x + 3", out=x)
 
132
        assert_equal(x, arange(10000.).reshape(1000,10) + 3)
 
133
        y = arange(10)
 
134
        evaluate("(x - 3) * y + (x - 3)", out=x)
 
135
        assert_equal(x, arange(10000.).reshape(1000,10) * (arange(10) + 1))
 
136
 
 
137
    def test_axis(self):
 
138
        y = arange(9.0).reshape(3,3)
 
139
        try:
 
140
            evaluate("sum(y, axis=2)")
 
141
        except ValueError:
 
142
            pass
 
143
        else:
 
144
            raise ValueError("should raise exception!")
 
145
        try:
 
146
            evaluate("sum(y, axis=-3)")
 
147
        except ValueError:
 
148
            pass
 
149
        else:
 
150
            raise ValueError("should raise exception!")
 
151
        try:
 
152
            # Negative axis are not supported
 
153
            evaluate("sum(y, axis=-1)")
 
154
        except ValueError:
 
155
            pass
 
156
        else:
 
157
            raise ValueError("should raise exception!")
 
158
 
 
159
    def test_r0_reuse(self):
 
160
        assert_equal(disassemble(NumExpr("x * x + 2", [('x', double)])),
 
161
                    [(b'mul_ddd', b'r0', b'r1[x]', b'r1[x]'),
 
162
                     (b'add_ddd', b'r0', b'r0', b'c2[2.0]')])
 
163
 
 
164
 
 
165
class test_numexpr2(test_numexpr):
 
166
    """Testing with 2 threads"""
 
167
    nthreads = 2
 
168
 
 
169
 
 
170
class test_evaluate(TestCase):
 
171
    def test_simple(self):
 
172
        a = array([1., 2., 3.])
 
173
        b = array([4., 5., 6.])
 
174
        c = array([7., 8., 9.])
 
175
        x = evaluate("2*a + 3*b*c")
 
176
        assert_array_equal(x, array([  86.,  124.,  168.]))
 
177
 
 
178
    def test_simple_expr_small_array(self):
 
179
        x = arange(100.0)
 
180
        y = evaluate("x")
 
181
        assert_array_equal(x, y)
 
182
 
 
183
    def test_simple_expr(self):
 
184
        x = arange(1e6)
 
185
        y = evaluate("x")
 
186
        assert_array_equal(x, y)
 
187
 
 
188
    # Test for issue #37
 
189
    if sys.version_info[0] < 3:
 
190
        # In python 3 '/' perforns true division, not integer division.
 
191
        # Integer division '//' is still not suppoerted by numexpr
 
192
        def test_zero_div(self):
 
193
            x = arange(100, dtype='i4')
 
194
            y = evaluate("1/x")
 
195
            x2 = zeros(100, dtype='i4')
 
196
            x2[1] = 1
 
197
            assert_array_equal(x2, y)
 
198
 
 
199
    # Test for issue #22
 
200
    def test_true_div(self):
 
201
        x = arange(10, dtype='i4')
 
202
        assert_array_equal(evaluate("x/2"), x / 2)
 
203
        assert_array_equal(evaluate("x/2", truediv=False), x / 2)
 
204
        assert_array_equal(evaluate("x/2", truediv='auto'), x / 2)
 
205
        assert_array_equal(evaluate("x/2", truediv=True), x / 2.0)
 
206
 
 
207
    # PyTables uses __nonzero__ among ExpressionNode objects internally
 
208
    # so this should be commented out for the moment.  See #24.
 
209
    # def test_boolean_operator(self):
 
210
    #     x = arange(10, dtype='i4')
 
211
    #     try:
 
212
    #         evaluate("(x > 1) and (x < 9)")
 
213
    #     except TypeError:
 
214
    #         pass
 
215
    #     else:
 
216
    #         raise ValueError("should raise exception!")
 
217
 
 
218
    def test_rational_expr(self):
 
219
        a = arange(1e6)
 
220
        b = arange(1e6) * 0.1
 
221
        x = (a + 2*b) / (1 + a + 4*b*b)
 
222
        y = evaluate("(a + 2*b) / (1 + a + 4*b*b)")
 
223
        assert_array_almost_equal(x, y)
 
224
 
 
225
    def test_complex_expr(self):
 
226
        def complex(a, b):
 
227
            c = zeros(a.shape, dtype=complex_)
 
228
            c.real = a
 
229
            c.imag = b
 
230
            return c
 
231
        a = arange(1e4)
 
232
        b = arange(1e4)**1e-5
 
233
        z = a + 1j*b
 
234
        x = z.imag
 
235
        x = sin(complex(a, b)).real + z.imag
 
236
        y = evaluate("sin(complex(a, b)).real + z.imag")
 
237
        assert_array_almost_equal(x, y)
 
238
 
 
239
    def test_complex_strides(self):
 
240
        a = arange(100).reshape(10,10)[::2]
 
241
        b = arange(50).reshape(5,10)
 
242
        assert_array_equal(evaluate("a+b"), a+b)
 
243
        c = empty([10], dtype=[('c1', int32), ('c2', uint16)])
 
244
        c['c1'] = arange(10)
 
245
        c['c2'].fill(0xaaaa)
 
246
        c1 = c['c1']
 
247
        a0 = a[0]
 
248
        assert_array_equal(evaluate("c1"), c1)
 
249
        assert_array_equal(evaluate("a0+c1"), a0+c1)
 
250
 
 
251
    def test_broadcasting(self):
 
252
        a = arange(100).reshape(10,10)[::2]
 
253
        c = arange(10)
 
254
        d = arange(5).reshape(5,1)
 
255
        assert_array_equal(evaluate("a+c"), a+c)
 
256
        assert_array_equal(evaluate("a+d"), a+d)
 
257
        expr = NumExpr("2.0*a+3.0*c",[('a', double),('c', double)])
 
258
        assert_array_equal(expr(a,c), 2.0*a+3.0*c)
 
259
 
 
260
    def test_all_scalar(self):
 
261
        a = 3.
 
262
        b = 4.
 
263
        assert_allclose(evaluate("a+b"), a+b)
 
264
        expr = NumExpr("2*a+3*b",[('a', double),('b', double)])
 
265
        assert_equal(expr(a,b), 2*a+3*b)
 
266
 
 
267
    def test_run(self):
 
268
        a = arange(100).reshape(10,10)[::2]
 
269
        b = arange(10)
 
270
        expr = NumExpr("2*a+3*b",[('a', double),('b', double)])
 
271
        assert_array_equal(expr(a,b), expr.run(a,b))
 
272
 
 
273
    def test_illegal_value(self):
 
274
        a = arange(3)
 
275
        try:
 
276
            evaluate("a < [0, 0, 0]")
 
277
        except TypeError:
 
278
            pass
 
279
        else:
 
280
            self.fail()
 
281
 
 
282
    # Execution order set here so as to not use too many threads
 
283
    # during the rest of the execution.  See #33 for details.
 
284
    def test_changing_nthreads_00_inc(self):
 
285
        a = linspace(-1, 1, 1e6)
 
286
        b = ((.25*a + .75)*a - 1.5)*a - 2
 
287
        for nthreads in range(1,7):
 
288
            numexpr.set_num_threads(nthreads)
 
289
            c = evaluate("((.25*a + .75)*a - 1.5)*a - 2")
 
290
            assert_array_almost_equal(b, c)
 
291
 
 
292
    def test_changing_nthreads_01_dec(self):
 
293
        a = linspace(-1, 1, 1e6)
 
294
        b = ((.25*a + .75)*a - 1.5)*a - 2
 
295
        for nthreads in range(6, 1, -1):
 
296
            numexpr.set_num_threads(nthreads)
 
297
            c = evaluate("((.25*a + .75)*a - 1.5)*a - 2")
 
298
            assert_array_almost_equal(b, c)
 
299
 
 
300
 
 
301
tests = [
 
302
('MISC', ['b*c+d*e',
 
303
          '2*a+3*b',
 
304
          '-a',
 
305
          'sinh(a)',
 
306
          '2*a + (cos(3)+5)*sinh(cos(b))',
 
307
          '2*a + arctan2(a, b)',
 
308
          'arcsin(0.5)',
 
309
          'where(a != 0.0, 2, a)',
 
310
          'where(a > 10, b < a, b > a)',
 
311
          'where((a-10).real != 0.0, a, 2)',
 
312
          '0.25 * (a < 5) + 0.33 * (a >= 5)',
 
313
          'cos(1+1)',
 
314
          '1+1',
 
315
          '1',
 
316
          'cos(a2)',
 
317
          ])]
 
318
 
 
319
optests = []
 
320
for op in list('+-*/%') + ['**']:
 
321
    optests.append("(a+1) %s (b+3)" % op)
 
322
    optests.append("3 %s (b+3)" % op)
 
323
    optests.append("(a+1) %s 4" % op)
 
324
    optests.append("2 %s (b+3)" % op)
 
325
    optests.append("(a+1) %s 2" % op)
 
326
    optests.append("(a+1) %s -1" % op)
 
327
    optests.append("(a+1) %s 0.5" % op)
 
328
    # Check divisions and modulus by zero (see ticket #107)
 
329
    optests.append("(a+1) %s 0" % op)
 
330
tests.append(('OPERATIONS', optests))
 
331
 
 
332
cmptests = []
 
333
for op in ['<', '<=', '==', '>=', '>', '!=']:
 
334
    cmptests.append("a/2+5 %s b" % op)
 
335
    cmptests.append("a/2+5 %s 7" % op)
 
336
    cmptests.append("7 %s b" % op)
 
337
    cmptests.append("7.0 %s 5" % op)
 
338
tests.append(('COMPARISONS', cmptests))
 
339
 
 
340
func1tests = []
 
341
for func in ['copy', 'ones_like', 'sqrt',
 
342
             'sin', 'cos', 'tan', 'arcsin', 'arccos', 'arctan',
 
343
             'sinh', 'cosh', 'tanh', 'arcsinh', 'arccosh', 'arctanh',
 
344
             'log', 'log1p', 'log10', 'exp', 'expm1', 'abs']:
 
345
    func1tests.append("a + %s(b+c)" % func)
 
346
tests.append(('1_ARG_FUNCS', func1tests))
 
347
 
 
348
func2tests = []
 
349
for func in ['arctan2', 'fmod']:
 
350
    func2tests.append("a + %s(b+c, d+1)" % func)
 
351
    func2tests.append("a + %s(b+c, 1)" % func)
 
352
    func2tests.append("a + %s(1, d+1)" % func)
 
353
tests.append(('2_ARG_FUNCS', func2tests))
 
354
 
 
355
powtests = []
 
356
# n = -1, 0.5, 2, 4 already handled in section "OPERATIONS"
 
357
for n in (-7, -2.5, -1.5, -1.3, -.5, 0, 0.0, 1, 2.3, 2.5, 3):
 
358
    powtests.append("(a+1)**%s" % n)
 
359
tests.append(('POW_TESTS', powtests))
 
360
 
 
361
def equal(a, b, exact):
 
362
    if array_equal(a, b):
 
363
        return True
 
364
 
 
365
    if hasattr(a, 'dtype') and a.dtype in ['f4','f8']:
 
366
        nnans = isnan(a).sum()
 
367
        if nnans > 0:
 
368
            # For results containing NaNs, just check that the number
 
369
            # of NaNs is the same in both arrays.  This check could be
 
370
            # made more exhaustive, but checking element by element in
 
371
            # python space is very expensive in general.
 
372
            return nnans == isnan(b).sum()
 
373
        ninfs = isinf(a).sum()
 
374
        if ninfs > 0:
 
375
            # Ditto for Inf's
 
376
            return ninfs == isinf(b).sum()
 
377
    if exact:
 
378
        return (shape(a) == shape(b)) and alltrue(ravel(a) == ravel(b), axis=0)
 
379
    else:
 
380
        if hasattr(a, 'dtype') and a.dtype == 'f4':
 
381
            atol = 1e-5   # Relax precission for special opcodes, like fmod
 
382
        else:
 
383
            atol = 1e-8
 
384
        return (shape(a) == shape(b) and
 
385
                allclose(ravel(a), ravel(b), atol=atol))
 
386
 
 
387
class Skip(Exception): pass
 
388
 
 
389
def test_expressions():
 
390
    test_no = [0]
 
391
    def make_test_method(a, a2, b, c, d, e, x, expr,
 
392
                         test_scalar, dtype, optimization, exact, section):
 
393
        this_locals = locals()
 
394
        def method():
 
395
            # We don't want to listen at RuntimeWarnings like
 
396
            # "overflows" or "divide by zero" in plain eval().
 
397
            warnings.simplefilter("ignore")
 
398
            npval = eval(expr, globals(), this_locals)
 
399
            warnings.simplefilter("always")
 
400
            npval = eval(expr, globals(), this_locals)
 
401
            try:
 
402
                neval = evaluate(expr, local_dict=this_locals,
 
403
                                 optimization=optimization)
 
404
                assert equal(npval, neval, exact), """%r
 
405
(test_scalar=%r, dtype=%r, optimization=%r, exact=%r,
 
406
 npval=%r (%r - %r)\n neval=%r (%r - %r))""" % (expr, test_scalar, dtype.__name__,
 
407
                                     optimization, exact,
 
408
                                     npval, type(npval), shape(npval),
 
409
                                     neval, type(neval), shape(neval))
 
410
            except AssertionError:
 
411
                raise
 
412
            except NotImplementedError:
 
413
                print('%r not implemented for %s (scalar=%d, opt=%s)'
 
414
                      % (expr, dtype.__name__, test_scalar, optimization))
 
415
            except:
 
416
                print('numexpr error for expression %r' % (expr,))
 
417
                raise
 
418
        method.description = ('test_expressions(%s, test_scalar=%r, '
 
419
                              'dtype=%r, optimization=%r, exact=%r)') \
 
420
                    % (expr, test_scalar, dtype.__name__, optimization, exact)
 
421
        test_no[0] += 1
 
422
        method.__name__ = 'test_scalar%d_%s_%s_%s_%04d' % (test_scalar,
 
423
                                                           dtype.__name__,
 
424
                                                           optimization.encode('ascii'),
 
425
                                                           section.encode('ascii'),
 
426
                                                           test_no[0])
 
427
        return method
 
428
    x = None
 
429
    for test_scalar in (0, 1, 2):
 
430
        for dtype in (int, long, numpy.float32, double, complex):
 
431
            array_size = 100
 
432
            a = arange(2*array_size, dtype=dtype)[::2]
 
433
            a2 = zeros([array_size, array_size], dtype=dtype)
 
434
            b = arange(array_size, dtype=dtype) / array_size
 
435
            c = arange(array_size, dtype=dtype)
 
436
            d = arange(array_size, dtype=dtype)
 
437
            e = arange(array_size, dtype=dtype)
 
438
            if dtype == complex:
 
439
                a = a.real
 
440
                for x in [a2, b, c, d, e]:
 
441
                    x += 1j
 
442
                    x *= 1+1j
 
443
            if test_scalar == 1:
 
444
                a = a[array_size // 2]
 
445
            if test_scalar == 2:
 
446
                b = b[array_size // 2]
 
447
            for optimization, exact in [
 
448
                ('none', False), ('moderate', False), ('aggressive', False)]:
 
449
                for section_name, section_tests in tests:
 
450
                    for expr in section_tests:
 
451
                        if dtype == complex and (
 
452
                               '<' in expr or '>' in expr or '%' in expr
 
453
                               or "arctan2" in expr or "fmod" in expr):
 
454
                            # skip complex comparisons or functions not
 
455
                            # defined in complex domain.
 
456
                            continue
 
457
                        if (dtype in (int, long) and test_scalar and
 
458
                            expr == '(a+1) ** -1'):
 
459
                            continue
 
460
 
 
461
                        m = make_test_method(a, a2, b, c, d, e, x,
 
462
                                             expr, test_scalar, dtype,
 
463
                                             optimization, exact,
 
464
                                             section_name)
 
465
                        yield m
 
466
 
 
467
class test_int64(TestCase):
 
468
    def test_neg(self):
 
469
        a = array([2**31-1, 2**31, 2**32, 2**63-1], dtype=int64)
 
470
        res = evaluate('-a')
 
471
        assert_array_equal(res, [1-2**31, -(2**31), -(2**32), 1-2**63])
 
472
        self.assertEqual(res.dtype.name, 'int64')
 
473
 
 
474
class test_int32_int64(TestCase):
 
475
    if sys.version_info[0] < 2:
 
476
        # no long literals in python 3
 
477
        def test_small_long(self):
 
478
            # Small longs should not be downgraded to ints.
 
479
            res = evaluate('42L')
 
480
            assert_array_equal(res, 42)
 
481
            self.assertEqual(res.dtype.name, 'int64')
 
482
 
 
483
    def test_small_int(self):
 
484
        # Small ints (32-bit ones) should not be promoted to longs.
 
485
        res = evaluate('2')
 
486
        assert_array_equal(res, 2)
 
487
        self.assertEqual(res.dtype.name, 'int32')
 
488
 
 
489
    def test_big_int(self):
 
490
        # Big ints should be promoted to longs.
 
491
        res = evaluate('2**40')
 
492
        assert_array_equal(res, 2**40)
 
493
        self.assertEqual(res.dtype.name, 'int64')
 
494
 
 
495
    def test_long_constant_promotion(self):
 
496
        int32array = arange(100, dtype='int32')
 
497
        itwo = numpy.int32(2)
 
498
        ltwo = numpy.int64(2)
 
499
        res = int32array * 2
 
500
        res32 = evaluate('int32array * itwo')
 
501
        res64 = evaluate('int32array * ltwo')
 
502
        assert_array_equal(res, res32)
 
503
        assert_array_equal(res, res64)
 
504
        self.assertEqual(res32.dtype.name, 'int32')
 
505
        self.assertEqual(res64.dtype.name, 'int64')
 
506
 
 
507
    def test_int64_array_promotion(self):
 
508
        int32array = arange(100, dtype='int32')
 
509
        int64array = arange(100, dtype='int64')
 
510
        respy = int32array * int64array
 
511
        resnx = evaluate('int32array * int64array')
 
512
        assert_array_equal(respy, resnx)
 
513
        self.assertEqual(resnx.dtype.name, 'int64')
 
514
 
 
515
 
 
516
class test_uint32_int64(TestCase):
 
517
    def test_small_uint32(self):
 
518
        # Small uint32 should not be downgraded to ints.
 
519
        a = numpy.uint32(42)
 
520
        res = evaluate('a')
 
521
        assert_array_equal(res, 42)
 
522
        self.assertEqual(res.dtype.name, 'int64')
 
523
 
 
524
    def test_uint32_constant_promotion(self):
 
525
        int32array = arange(100, dtype='int32')
 
526
        stwo = numpy.int32(2)
 
527
        utwo = numpy.uint32(2)
 
528
        res = int32array * utwo
 
529
        res32 = evaluate('int32array * stwo')
 
530
        res64 = evaluate('int32array * utwo')
 
531
        assert_array_equal(res, res32)
 
532
        assert_array_equal(res, res64)
 
533
        self.assertEqual(res32.dtype.name, 'int32')
 
534
        self.assertEqual(res64.dtype.name, 'int64')
 
535
 
 
536
    def test_int64_array_promotion(self):
 
537
        uint32array = arange(100, dtype='uint32')
 
538
        int64array = arange(100, dtype='int64')
 
539
        respy = uint32array * int64array
 
540
        resnx = evaluate('uint32array * int64array')
 
541
        assert_array_equal(respy, resnx)
 
542
        self.assertEqual(resnx.dtype.name, 'int64')
 
543
 
 
544
 
 
545
class test_strings(TestCase):
 
546
    BLOCK_SIZE1 = 128
 
547
    BLOCK_SIZE2 = 8
 
548
    str_list1 = [b'foo', b'bar', b'', b'  ']
 
549
    str_list2 = [b'foo', b'', b'x', b' ']
 
550
    str_nloops = len(str_list1) * (BLOCK_SIZE1 + BLOCK_SIZE2 + 1)
 
551
    str_array1 = array(str_list1 * str_nloops)
 
552
    str_array2 = array(str_list2 * str_nloops)
 
553
    str_constant = b'doodoo'
 
554
 
 
555
    def test_null_chars(self):
 
556
        str_list = [
 
557
            b'\0\0\0', b'\0\0foo\0', b'\0\0foo\0b', b'\0\0foo\0b\0',
 
558
            b'foo\0', b'foo\0b', b'foo\0b\0', b'foo\0bar\0baz\0\0' ]
 
559
        for s in str_list:
 
560
            r = evaluate('s')
 
561
            self.assertEqual(s, r.tostring())  # check *all* stored data
 
562
 
 
563
    def test_compare_copy(self):
 
564
        sarr = self.str_array1
 
565
        expr = 'sarr'
 
566
        res1 = eval(expr)
 
567
        res2 = evaluate(expr)
 
568
        assert_array_equal(res1, res2)
 
569
 
 
570
    def test_compare_array(self):
 
571
        sarr1 = self.str_array1
 
572
        sarr2 = self.str_array2
 
573
        expr = 'sarr1 >= sarr2'
 
574
        res1 = eval(expr)
 
575
        res2 = evaluate(expr)
 
576
        assert_array_equal(res1, res2)
 
577
 
 
578
    def test_compare_variable(self):
 
579
        sarr = self.str_array1
 
580
        svar = self.str_constant
 
581
        expr = 'sarr >= svar'
 
582
        res1 = eval(expr)
 
583
        res2 = evaluate(expr)
 
584
        assert_array_equal(res1, res2)
 
585
 
 
586
    def test_compare_constant(self):
 
587
        sarr = self.str_array1
 
588
        expr = 'sarr >= %r' % self.str_constant
 
589
        res1 = eval(expr)
 
590
        res2 = evaluate(expr)
 
591
        assert_array_equal(res1, res2)
 
592
 
 
593
    def test_add_string_array(self):
 
594
        sarr1 = self.str_array1
 
595
        sarr2 = self.str_array2
 
596
        expr = 'sarr1 + sarr2'
 
597
        self.assert_missing_op('add_sss', expr, locals())
 
598
 
 
599
    def test_add_numeric_array(self):
 
600
        sarr = self.str_array1
 
601
        narr = arange(len(sarr), dtype='int32')
 
602
        expr = 'sarr >= narr'
 
603
        self.assert_missing_op('ge_bsi', expr, locals())
 
604
 
 
605
    def assert_missing_op(self, op, expr, local_dict):
 
606
        msg = "expected NotImplementedError regarding '%s'" % op
 
607
        try:
 
608
            evaluate(expr, local_dict)
 
609
        except NotImplementedError, nie:
 
610
            if "'%s'" % op not in nie.args[0]:
 
611
                self.fail(msg)
 
612
        else:
 
613
            self.fail(msg)
 
614
 
 
615
    def test_compare_prefix(self):
 
616
        # Check comparing two strings where one is a prefix of the
 
617
        # other.
 
618
        for s1, s2 in [ (b'foo', b'foobar'), (b'foo', b'foo\0bar'),
 
619
                        (b'foo\0a', b'foo\0bar') ]:
 
620
            self.assertTrue(evaluate('s1 < s2'))
 
621
            self.assertTrue(evaluate('s1 <= s2'))
 
622
            self.assertTrue(evaluate('~(s1 == s2)'))
 
623
            self.assertTrue(evaluate('~(s1 >= s2)'))
 
624
            self.assertTrue(evaluate('~(s1 > s2)'))
 
625
 
 
626
        # Check for NumPy array-style semantics in string equality.
 
627
        s1, s2 = b'foo', b'foo\0\0'
 
628
        self.assertTrue(evaluate('s1 == s2'))
 
629
 
 
630
# Case for testing selections in fields which are aligned but whose
 
631
# data length is not an exact multiple of the length of the record.
 
632
# The following test exposes the problem only in 32-bit machines,
 
633
# because in 64-bit machines 'c2' is unaligned.  However, this should
 
634
# check most platforms where, while not unaligned, 'len(datatype) >
 
635
# boundary_alignment' is fullfilled.
 
636
class test_irregular_stride(TestCase):
 
637
    def test_select(self):
 
638
        f0 = arange(10, dtype=int32)
 
639
        f1 = arange(10, dtype=float64)
 
640
 
 
641
        irregular = rec.fromarrays([f0, f1])
 
642
 
 
643
        f0 = irregular['f0']
 
644
        f1 = irregular['f1']
 
645
 
 
646
        i0 = evaluate('f0 < 5')
 
647
        i1 = evaluate('f1 < 5')
 
648
 
 
649
        assert_array_equal(f0[i0], arange(5, dtype=int32))
 
650
        assert_array_equal(f1[i1], arange(5, dtype=float64))
 
651
 
 
652
# Cases for testing arrays with dimensions that can be zero.
 
653
class test_zerodim(TestCase):
 
654
 
 
655
    def test_zerodim1d(self):
 
656
        a0 = array([], dtype=int32)
 
657
        a1 = array([], dtype=float64)
 
658
 
 
659
        r0 = evaluate('a0 + a1')
 
660
        r1 = evaluate('a0 * a1')
 
661
 
 
662
        assert_array_equal(r0, a1)
 
663
        assert_array_equal(r1, a1)
 
664
 
 
665
    def test_zerodim3d(self):
 
666
        a0 = array([], dtype=int32).reshape(0,2,4)
 
667
        a1 = array([], dtype=float64).reshape(0,2,4)
 
668
 
 
669
        r0 = evaluate('a0 + a1')
 
670
        r1 = evaluate('a0 * a1')
 
671
 
 
672
        assert_array_equal(r0, a1)
 
673
        assert_array_equal(r1, a1)
 
674
 
 
675
# Case test for threads
 
676
class test_threading(TestCase):
 
677
    def test_thread(self):
 
678
        import threading
 
679
        class ThreadTest(threading.Thread):
 
680
            def run(self):
 
681
                a = arange(3)
 
682
                assert_array_equal(evaluate('a**3'), array([0, 1, 8]))
 
683
        test = ThreadTest()
 
684
        test.start()
 
685
 
 
686
# The worker function for the subprocess (needs to be here because Windows
 
687
# has problems pickling nested functions with the multiprocess module :-/)
 
688
def _worker(qout = None):
 
689
    ra = numpy.arange(1e3)
 
690
    rows = evaluate('ra > 0')
 
691
    #print "Succeeded in evaluation!\n"
 
692
    if qout is not None:
 
693
        qout.put("Done")
 
694
 
 
695
# Case test for subprocesses (via multiprocessing module)
 
696
class test_subprocess(TestCase):
 
697
    def test_multiprocess(self):
 
698
        try:
 
699
            import multiprocessing as mp
 
700
        except ImportError:
 
701
            return
 
702
        # Check for two threads at least
 
703
        numexpr.set_num_threads(2)
 
704
        #print "**** Running from main process:"
 
705
        _worker()
 
706
        #print "**** Running from subprocess:"
 
707
        qout = mp.Queue()
 
708
        ps = mp.Process(target=_worker, args=(qout,))
 
709
        ps.daemon = True
 
710
        ps.start()
 
711
 
 
712
        result = qout.get()
 
713
        #print result
 
714
 
 
715
 
 
716
 
 
717
 
 
718
def print_versions():
 
719
    """Print the versions of software that numexpr relies on."""
 
720
    if numpy.__version__ < minimum_numpy_version:
 
721
        print "*Warning*: NumPy version is lower than recommended: %s < %s" % \
 
722
              (numpy.__version__, minimum_numpy_version)
 
723
    print '-=' * 38
 
724
    print "Numexpr version:   %s" % numexpr.__version__
 
725
    print "NumPy version:     %s" % numpy.__version__
 
726
    print 'Python version:    %s' % sys.version
 
727
    if os.name == 'posix':
 
728
        (sysname, nodename, release, version, machine) = os.uname()
 
729
        print 'Platform:          %s-%s' % (sys.platform, machine)
 
730
    print "AMD/Intel CPU?     %s" % numexpr.is_cpu_amd_intel
 
731
    print "VML available?     %s" % use_vml
 
732
    if use_vml:
 
733
        print "VML/MKL version:   %s" % numexpr.get_vml_version()
 
734
    print ("Number of threads used by default: %d "
 
735
           "(out of %d detected cores)" % (numexpr.nthreads, numexpr.ncores))
 
736
    print '-=' * 38
 
737
 
 
738
 
 
739
def test():
 
740
    """
 
741
    Run all the tests in the test suite.
 
742
    """
 
743
 
 
744
    print_versions()
 
745
    return unittest.TextTestRunner().run(suite())
 
746
test.__test__ = False
 
747
 
 
748
 
 
749
def suite():
 
750
    import unittest
 
751
    import platform as pl
 
752
 
 
753
    theSuite = unittest.TestSuite()
 
754
    niter = 1
 
755
 
 
756
    class TestExpressions(TestCase):
 
757
        pass
 
758
 
 
759
    def add_method(func):
 
760
        def method(self):
 
761
            return func()
 
762
        setattr(TestExpressions, func.__name__,
 
763
                method.__get__(None, TestExpressions))
 
764
 
 
765
    for func in test_expressions():
 
766
        add_method(func)
 
767
 
 
768
    for n in range(niter):
 
769
        theSuite.addTest(unittest.makeSuite(test_numexpr))
 
770
        theSuite.addTest(unittest.makeSuite(test_numexpr2))
 
771
        theSuite.addTest(unittest.makeSuite(test_evaluate))
 
772
        theSuite.addTest(unittest.makeSuite(TestExpressions))
 
773
        theSuite.addTest(unittest.makeSuite(test_int32_int64))
 
774
        theSuite.addTest(unittest.makeSuite(test_uint32_int64))
 
775
        theSuite.addTest(unittest.makeSuite(test_strings))
 
776
        theSuite.addTest(
 
777
            unittest.makeSuite(test_irregular_stride) )
 
778
        theSuite.addTest(unittest.makeSuite(test_zerodim))
 
779
 
 
780
        # multiprocessing module is not supported on Hurd/kFreeBSD
 
781
        if (pl.system().lower() not in ('gnu', 'gnu/kfreebsd')):
 
782
            theSuite.addTest(unittest.makeSuite(test_subprocess))
 
783
 
 
784
        # I need to put this test after test_subprocess because
 
785
        # if not, the test suite locks immediately before test_subproces.
 
786
        # This only happens with Windows, so I suspect of a subtle bad
 
787
        # interaction with threads and subprocess :-/
 
788
        theSuite.addTest(unittest.makeSuite(test_threading))
 
789
 
 
790
    return theSuite
 
791
 
 
792
if __name__ == '__main__':
 
793
    print_versions()
 
794
    unittest.main(defaultTest = 'suite')
 
795
#    suite = suite()
 
796
#    unittest.TextTestRunner(verbosity=2).run(suite)