def test_validate7(): '''Check that the Matmul2Code validate method raises the expected exception when the supplied node is a MATMUL binary operation but its first (matrix) argument has fewer than 2 dimensions. ''' trans = Matmul2CodeTrans() array_type = ArrayType(REAL_TYPE, [10]) array = Reference(DataSymbol("x", array_type)) matmul = BinaryOperation.create(BinaryOperation.Operator.MATMUL, array.copy(), array.copy()) _ = Assignment.create(array, matmul) with pytest.raises(TransformationError) as excinfo: trans.validate(matmul) assert ("Transformation Error: Expected 1st child of a MATMUL " "BinaryOperation to be a matrix with at least 2 dimensions, " "but found '1'." in str(excinfo.value))
def test_validate6(): '''Check that the Matmul2Code validate method raises the expected exception when the supplied node is a MATMUL binary operation but either or both of its arguments are references to datasymbols that are not arrays. ''' trans = Matmul2CodeTrans() scalar = Reference(DataSymbol("x", REAL_TYPE)) matmul = BinaryOperation.create(BinaryOperation.Operator.MATMUL, scalar, scalar.copy()) _ = Assignment.create(scalar.copy(), matmul) with pytest.raises(TransformationError) as excinfo: trans.validate(matmul) assert ("Transformation Error: Expected children of a MATMUL " "BinaryOperation to be references to arrays, but found " "'DataSymbol', 'DataSymbol'." in str(excinfo.value))
def test_validate4(): '''Check that the Matmul2Code validate method raises the expected exception when the supplied node is a MATMUL binary operation but it is not the only operation on the RHS of an assignment. ''' trans = Matmul2CodeTrans() vector_type = ArrayType(REAL_TYPE, [10]) array_type = ArrayType(REAL_TYPE, [10, 10]) vector = Reference(DataSymbol("x", vector_type)) array = Reference(DataSymbol("y", array_type)) matmul = BinaryOperation.create(BinaryOperation.Operator.MATMUL, array, vector) rhs = BinaryOperation.create(BinaryOperation.Operator.MUL, matmul, vector.copy()) _ = Assignment.create(array.copy(), rhs) with pytest.raises(TransformationError) as excinfo: trans.validate(matmul) assert ("Transformation Error: Matmul2CodeTrans only supports the " "transformation of a MATMUL operation when it is the sole " "operation on the rhs of an assignment." in str(excinfo.value))
def test_reference_can_be_copied(): ''' Test that a reference can be copied. ''' array_symbol = DataSymbol("symbol", ArrayType(REAL_TYPE, [10])) scalar_symbol = DataSymbol("other", REAL_TYPE) ref = Reference(array_symbol) ref1 = ref.copy() assert isinstance(ref1, Reference) assert ref1 is not ref assert ref1.symbol is array_symbol # Modifying the new reference does not affect the original ref1._symbol = scalar_symbol assert ref.symbol is array_symbol
def test_validate9(): '''Check that the Matmul2Code validate method raises the expected exception when the supplied node is a MATMUL binary operation but its second (vector) argument is a reference to a vector with greater than 1 dimension. ''' trans = Matmul2CodeTrans() array_type = ArrayType(REAL_TYPE, [10, 10]) array = Reference(DataSymbol("x", array_type)) vector_type = ArrayType(REAL_TYPE, [10, 10, 10]) vector = Reference(DataSymbol("y", vector_type)) matmul = BinaryOperation.create(BinaryOperation.Operator.MATMUL, array, vector) _ = Assignment.create(array.copy(), matmul) with pytest.raises(TransformationError) as excinfo: trans.validate(matmul) assert ("Transformation Error: Expected 2nd child of a MATMUL " "BinaryOperation to have 1 dimension, but found '3'." in str(excinfo.value))
def test_array_is_full_range(): '''Test that the is_full_range method in the Array Node works as expected. ''' # pylint: disable=too-many-statements zero = Literal("0", INTEGER_SINGLE_TYPE) one = Literal("1", INTEGER_SINGLE_TYPE) array_type = ArrayType(REAL_SINGLE_TYPE, [10]) symbol = DataSymbol("my_array", array_type) reference = Reference(symbol) lbound = BinaryOperation.create(BinaryOperation.Operator.LBOUND, reference, one) ubound = BinaryOperation.create(BinaryOperation.Operator.UBOUND, reference.copy(), one.copy()) symbol_error = DataSymbol("another_array", array_type) reference_error = Reference(symbol_error) # Index out of bounds array_reference = ArrayReference.create(symbol, [one.copy()]) with pytest.raises(ValueError) as excinfo: array_reference.is_full_range(1) assert ("In ArrayReference 'my_array' the specified index '1' must be " "less than the number of dimensions '1'." in str(excinfo.value)) # Array dimension is not a Range assert not array_reference.is_full_range(0) # Check LBOUND # Array dimension range lower bound is not a binary operation my_range = Range.create(one.copy(), one.copy(), one.copy()) array_reference = ArrayReference.create(symbol, [my_range]) assert not array_reference.is_full_range(0) # Array dimension range lower bound is not an LBOUND binary operation my_range = Range.create(ubound, one.copy(), one.copy()) array_reference = ArrayReference.create(symbol, [my_range]) assert not array_reference.is_full_range(0) # Array dimension range lower bound is an LBOUND binary operation # with the first value not being a reference lbound_error = BinaryOperation.create(BinaryOperation.Operator.LBOUND, zero.copy(), zero.copy()) my_range = Range.create(lbound_error, one.copy(), one.copy()) array_reference = ArrayReference.create(symbol, [my_range]) assert not array_reference.is_full_range(0) # Array dimension range lower bound is an LBOUND binary operation # with the first value being a reference to a different symbol lbound_error = BinaryOperation.create(BinaryOperation.Operator.LBOUND, reference_error, zero.copy()) my_range = Range.create(lbound_error, one.copy(), one.copy()) array_reference = ArrayReference.create(symbol, [my_range]) assert not array_reference.is_full_range(0) # Array dimension range lower bound is an LBOUND binary operation # with the second value not being a literal. lbound_error = BinaryOperation.create(BinaryOperation.Operator.LBOUND, reference.copy(), reference.copy()) my_range = Range.create(lbound_error, one.copy(), one.copy()) array_reference = ArrayReference.create(symbol, [my_range]) assert not array_reference.is_full_range(0) # Array dimension range lower bound is an LBOUND binary operation # with the second value not being an integer literal. lbound_error = BinaryOperation.create(BinaryOperation.Operator.LBOUND, reference.copy(), Literal("1.0", REAL_SINGLE_TYPE)) my_range = Range.create(lbound_error, one.copy(), one.copy()) array_reference = ArrayReference.create(symbol, [my_range]) assert not array_reference.is_full_range(0) # Array dimension range lower bound is an LBOUND binary operation # with the second value being an integer literal with the wrong # value (should be 0 as this dimension index is 0). lbound_error = BinaryOperation.create(BinaryOperation.Operator.LBOUND, reference.copy(), one.copy()) my_range = Range.create(lbound_error, one.copy(), one.copy()) array_reference = ArrayReference.create(symbol, [my_range]) assert not array_reference.is_full_range(0) # Check UBOUND # Array dimension range upper bound is not a binary operation my_range = Range.create(lbound, one.copy(), one.copy()) array_reference = ArrayReference.create(symbol, [my_range]) assert not array_reference.is_full_range(0) # Array dimension range upper bound is not a UBOUND binary operation my_range = Range.create(lbound.copy(), lbound.copy(), one.copy()) array_reference = ArrayReference.create(symbol, [my_range]) assert not array_reference.is_full_range(0) # Array dimension range upper bound is a UBOUND binary operation # with the first value not being a reference ubound_error = BinaryOperation.create(BinaryOperation.Operator.UBOUND, zero.copy(), zero.copy()) my_range = Range.create(lbound.copy(), ubound_error, one.copy()) array_reference = ArrayReference.create(symbol, [my_range]) assert not array_reference.is_full_range(0) # Array dimension range upper bound is a UBOUND binary operation # with the first value being a reference to a different symbol ubound_error = BinaryOperation.create(BinaryOperation.Operator.UBOUND, reference_error.copy(), zero.copy()) my_range = Range.create(lbound.copy(), ubound_error, one.copy()) array_reference = ArrayReference.create(symbol, [my_range]) assert not array_reference.is_full_range(0) # Array dimension range upper bound is a UBOUND binary operation # with the second value not being a literal. ubound_error = BinaryOperation.create(BinaryOperation.Operator.UBOUND, reference.copy(), reference.copy()) my_range = Range.create(lbound.copy(), ubound_error, one.copy()) array_reference = ArrayReference.create(symbol, [my_range]) assert not array_reference.is_full_range(0) # Array dimension range upper bound is a UBOUND binary operation # with the second value not being an integer literal. ubound_error = BinaryOperation.create(BinaryOperation.Operator.UBOUND, reference.copy(), Literal("1.0", REAL_SINGLE_TYPE)) my_range = Range.create(lbound.copy(), ubound_error, one.copy()) array_reference = ArrayReference.create(symbol, [my_range]) assert not array_reference.is_full_range(0) # Array dimension range upper bound is a UBOUND binary operation # with the second value being an integer literal with the wrong # value (should be 1 as this dimension is 1). ubound_error = BinaryOperation.create(BinaryOperation.Operator.UBOUND, reference.copy(), zero.copy()) my_range = Range.create(lbound.copy(), ubound_error, one.copy()) array_reference = ArrayReference.create(symbol, [my_range]) assert not array_reference.is_full_range(0) # Check Step # Array dimension range step is not a literal. my_range = Range.create(lbound.copy(), ubound.copy(), lbound.copy()) array_reference = ArrayReference.create(symbol, [my_range]) assert not array_reference.is_full_range(0) # Array dimension range step is not an integer literal. my_range = Range.create(lbound.copy(), ubound.copy(), one.copy()) # We have to change this to a non-integer manually as the create # function only accepts integer literals for the step argument. my_range.children[2] = Literal("1.0", REAL_SINGLE_TYPE) array_reference = ArrayReference.create(symbol, [my_range]) assert not array_reference.is_full_range(0) # Array dimension range step is is an integer literal with the # wrong value (not 1). my_range = Range.create(lbound.copy(), ubound.copy(), zero.copy()) array_reference = ArrayReference.create(symbol, [my_range]) assert not array_reference.is_full_range(0) # All is as it should be. # The full range is covered so return true. my_range = Range.create(lbound.copy(), ubound.copy(), one.copy()) array_reference = ArrayReference.create(symbol, [my_range]) assert array_reference.is_full_range(0)