Skip to content
Snippets Groups Projects
Select Git revision
  • c8dbf8cb8e2ba440dfb64e7a27ba53a27ce6ee08
  • master default protected
  • v2.0-dev protected
  • zikeliml/Task-96-dotExporterForAST
  • zikeliml/124-rework-tutorials
  • fma
  • fhennig/v2.0-deprecations
  • holzer-master-patch-46757
  • 66-absolute-access-is-probably-not-copied-correctly-after-_eval_subs
  • gpu_bufferfield_fix
  • hyteg
  • vectorization_sqrt_fix
  • target_dh_refactoring
  • const_fix
  • improved_comm
  • gpu_liveness_opts
  • release/1.3.7 protected
  • release/1.3.6 protected
  • release/2.0.dev0 protected
  • release/1.3.5 protected
  • release/1.3.4 protected
  • release/1.3.3 protected
  • release/1.3.2 protected
  • release/1.3.1 protected
  • release/1.3 protected
  • release/1.2 protected
  • release/1.1.1 protected
  • release/1.1 protected
  • release/1.0.1 protected
  • release/1.0 protected
  • release/0.4.4 protected
  • last/Kerncraft
  • last/OpenCL
  • last/LLVM
  • release/0.4.3 protected
  • release/0.4.2 protected
36 results

test_types.py

Blame
  • Frederik Hennig's avatar
    Frederik Hennig authored and Markus Holzer committed
    bcc8d818
    History
    test_types.py 7.57 KiB
    import pytest
    
    import pystencils.config
    import sympy as sp
    import numpy as np
    
    import pystencils as ps
    from pystencils.typing import TypedSymbol, get_type_of_expression, VectorType, collate_types, \
        typed_symbols, CastFunc, PointerArithmeticFunc, PointerType, result_type, BasicType
    
    
    def test_result_type():
        i = np.dtype('int32')
        l = np.dtype('int64')
        ui = np.dtype('uint32')
        ul = np.dtype('uint64')
        f = np.dtype('float32')
        d = np.dtype('float64')
        b = np.dtype('bool')
    
        assert result_type(i, l) == l
        assert result_type(l, i) == l
        assert result_type(ui, i) == i
        assert result_type(ui, l) == l
        assert result_type(ul, i) == i
        assert result_type(ul, l) == l
        assert result_type(d, f) == d
        assert result_type(f, d) == d
        assert result_type(i, f) == f
        assert result_type(l, f) == f
        assert result_type(ui, f) == f
        assert result_type(ul, f) == f
        assert result_type(i, d) == d
        assert result_type(l, d) == d
        assert result_type(ui, d) == d
        assert result_type(ul, d) == d
        assert result_type(b, i) == i
        assert result_type(b, l) == l
        assert result_type(b, ui) == ui
        assert result_type(b, ul) == ul
        assert result_type(b, f) == f
        assert result_type(b, d) == d
    
    
    @pytest.mark.parametrize('dtype', ('float64', 'float32', 'int64', 'int32', 'uint32', 'uint64'))
    def test_simple_add(dtype):
        constant = 1.0
        if dtype[0] in 'ui':
            constant = 1
        f = ps.fields(f"f: {dtype}[1D]")
        d = TypedSymbol("d", dtype)
    
        test_arr = np.array([constant], dtype=dtype)
    
        ur = ps.Assignment(f[0], f[0] + d)
    
        ast = ps.create_kernel(ur)
        code = ps.get_code_str(ast)
        kernel = ast.compile()
        kernel(f=test_arr, d=constant)
    
        assert test_arr[0] == constant+constant
    
    
    @pytest.mark.parametrize('dtype1', ('float64', 'float32', 'int64', 'int32', 'uint32', 'uint64'))
    @pytest.mark.parametrize('dtype2', ('float64', 'float32', 'int64', 'int32', 'uint32', 'uint64'))
    def test_mixed_add(dtype1, dtype2):
    
        constant = 1
        f = ps.fields(f"f: {dtype1}[1D]")
        g = ps.fields(f"g: {dtype2}[1D]")
    
        test_f = np.array([constant], dtype=dtype1)
        test_g = np.array([constant], dtype=dtype2)
    
        ur = ps.Assignment(f[0], f[0] + g[0])
    
        # TODO Markus: check for the logging if colate_types(dtype1, dtype2) != dtype1
        ast = ps.create_kernel(ur)
        code = ps.get_code_str(ast)
        kernel = ast.compile()
        kernel(f=test_f, g=test_g)
    
        assert test_f[0] == constant+constant
    
    
    def test_collation():
        double_type = BasicType('float64')
        float_type = BasicType('float32')
        double4_type = VectorType(double_type, 4)
        float4_type = VectorType(float_type, 4)
        assert collate_types([double_type, float_type]) == double_type
        assert collate_types([double4_type, float_type]) == double4_type
        assert collate_types([double4_type, float4_type]) == double4_type
    
    
    def test_vector_type():
        double_type = BasicType('float64')
        float_type = BasicType('float32')
        double4_type = VectorType(double_type, 4)
        float4_type = VectorType(float_type, 4)
    
        assert double4_type.item_size == 4
        assert float4_type.item_size == 4
    
        double4_type2 = VectorType(double_type, 4)
        assert double4_type == double4_type2
        assert double4_type != 4
        assert double4_type != float4_type
    
    
    def test_pointer_type():
        double_type = BasicType('float64')
        float_type = BasicType('float32')
        double4_type = PointerType(double_type, restrict=True)
        float4_type = PointerType(float_type, restrict=False)
    
        assert double4_type.item_size == 1
        assert float4_type.item_size == 1
    
        assert not double4_type == 4
    
        assert not double4_type.alias
        assert float4_type.alias
    
    
    def test_dtype_of_constants():
        # Some come constants are neither of type Integer,Float,Rational and don't have args
        # >>> isinstance(pi, Integer)
        # False
        # >>> isinstance(pi, Float)
        # False
        # >>> isinstance(pi, Rational)
        # False
        # >>> pi.args
        # ()
        get_type_of_expression(sp.pi)
    
    
    def test_assumptions():
        x = ps.fields('x:  float32[3d]')
    
        assert x.shape[0].is_nonnegative
        assert (2 * x.shape[0]).is_nonnegative
        assert (2 * x.shape[0]).is_integer
        assert (TypedSymbol('a', BasicType('uint64'))).is_nonnegative
        assert (TypedSymbol('a', BasicType('uint64'))).is_positive is None
        assert (TypedSymbol('a', BasicType('uint64')) + 1).is_positive
        assert (x.shape[0] + 1).is_real
    
    
    @pytest.mark.parametrize('dtype', ('float64', 'float32'))
    def test_sqrt_of_integer(dtype):
        """Regression test for bug where sqrt(3) was classified as integer"""
        f = ps.fields(f'f: {dtype}[1D]')
        tmp = sp.symbols('tmp')
    
        assignments = [ps.Assignment(tmp, sp.sqrt(3)),
                       ps.Assignment(f[0], tmp)]
        arr = np.array([1], dtype=dtype)
        config = pystencils.config.CreateKernelConfig(data_type=dtype, default_number_float=dtype)
    
        ast = ps.create_kernel(assignments, config=config)
        kernel = ast.compile()
        kernel(f=arr)
        assert 1.7 < arr[0] < 1.8
    
        code = ps.get_code_str(ast)
        constant = '1.7320508075688772f'
        if dtype == 'float32':
            assert constant in code
        else:
            assert constant not in code
    
    
    @pytest.mark.parametrize('dtype', ('float64', 'float32'))
    def test_integer_comparision(dtype):
        f = ps.fields(f"f: {dtype}[2D]")
        d = TypedSymbol("dir", "int64")
    
        ur = ps.Assignment(f[0, 0], sp.Piecewise((0, sp.Equality(d, 1)), (f[0, 0], True)))
    
        ast = ps.create_kernel(ur)
        code = ps.get_code_str(ast)
    
        # There should be an explicit cast for the integer zero to the type of the field on the rhs
        if dtype == 'float64':
            t = "_data_f[_stride_f_0*ctr_0 + _stride_f_1*ctr_1] = " \
                "((((dir) == (1))) ? (0.0): (_data_f[_stride_f_0*ctr_0 + _stride_f_1*ctr_1]));"
        else:
            t = "_data_f[_stride_f_0*ctr_0 + _stride_f_1*ctr_1] = " \
                "((((dir) == (1))) ? (0.0f): (_data_f[_stride_f_0*ctr_0 + _stride_f_1*ctr_1]));"
        assert t in code
    
    
    def test_typed_symbols_dtype():
        assert typed_symbols(("s", "f"), np.uint) == typed_symbols("s, f", np.uint)
        t_symbols = typed_symbols(("s", "f"), np.uint)
        s = t_symbols[0]
    
        assert t_symbols[0] == TypedSymbol("s", np.uint)
        assert s.dtype.is_uint()
    
        assert typed_symbols("s", np.float64).dtype.c_name == 'double'
        assert typed_symbols("s", np.float32).dtype.c_name == 'float'
    
        assert TypedSymbol("s", np.uint).canonical == TypedSymbol("s", np.uint)
        assert TypedSymbol("s", np.uint).reversed == TypedSymbol("s", np.uint)
    
    
    def test_cast_func():
        assert CastFunc(TypedSymbol("s", np.uint), np.int64).canonical == TypedSymbol("s", np.uint).canonical
    
        a = CastFunc(5, np.uint)
        assert a.is_negative is False
        assert a.is_nonnegative
    
    
    def test_pointer_arithmetic_func():
        assert PointerArithmeticFunc(TypedSymbol("s", np.uint), 1).canonical == TypedSymbol("s", np.uint).canonical
    
    
    def test_division():
        f = ps.fields('f(10): float32[2D]')
        m, tau = sp.symbols("m, tau")
    
        up = [ps.Assignment(tau, 1 / (0.5 + (3.0 * m))),
              ps.Assignment(f.center, tau)]
        config = pystencils.config.CreateKernelConfig(data_type='float32', default_number_float='float32')
        ast = ps.create_kernel(up, config=config)
        code = ps.get_code_str(ast)
    
        assert "((1.0f) / (m*3.0f + 0.5f))" in code
    
    
    def test_pow():
        f = ps.fields('f(10): float32[2D]')
        m, tau = sp.symbols("m, tau")
    
        up = [ps.Assignment(tau, m ** 1.5),
              ps.Assignment(f.center, tau)]
    
        config = pystencils.config.CreateKernelConfig(data_type="float32", default_number_float='float32')
        ast = ps.create_kernel(up, config=config)
        code = ps.get_code_str(ast)
    
        assert "1.5f" in code