class Ikra::Symbolic::ArrayStencilCommand

Attributes

offsets[R]
out_of_range_value[R]
use_parameter_array[R]

Public Class Methods

new( target, offsets, out_of_range_value, block, ast: nil, block_size: DEFAULT_BLOCK_SIZE, keep: false, use_parameter_array: true, generator_node: nil, with_index: false, command_binding: nil) click to toggle source
Calls superclass method Ikra::Symbolic::ArrayCommand::new
# File lib/symbolic/symbolic.rb, line 627
def initialize(
    target, 
    offsets, 
    out_of_range_value, 
    block, 
    ast: nil,
    block_size: DEFAULT_BLOCK_SIZE, 
    keep: false, 
    use_parameter_array: true,
    generator_node: nil,
    with_index: false,
    command_binding: nil)

    super(block: block, block_ast: ast, block_size: block_size, keep: keep, generator_node: generator_node, command_binding: command_binding)

    if offsets.first == "G"
        # A stencil will be generated
        dims = target.to_command.dimensions.size

        directions = offsets[1]
        # Directions says how many of the dimensions can be used in the stencil. E.g.: in 2D directions = 1 would relate in a stencil that only has up, down, left, right offsets, but no diagonals
        distance = offsets[2]
        # Distance says how many steps can be made into the directions distance = 2 in the example before would mean 1 or 2 up/down/left/right

        if directions > dims
            raise ArgumentError.new(
                "Directions should not be higher than the number of dimensions")
        end

        singles = [0]
        # Building the numbers that can be part of an offset
        for i in 1..distance
            singles = singles + [i] + [-i]
        end

        offsets = []

        # Iterate all possibilities
        for i in 0..singles.size**dims-1
            # Transform current permutation to according string / base representation
            base = i.to_s(singles.size)

            # Fill up zeroes
            sizedif = (singles.size**dims-1).to_s(singles.size).size - base.size
            base = "0" * sizedif + base

            # Check whether offset is allowed (concerning directions)
            if base.gsub(/[^0]/, "").size >= dims - directions
                new_offset = []
                for j in 0..dims-1
                    new_offset.push(singles[base[j].to_i])
                end
                offsets.push(new_offset)
            end
        end
    end

    if not offsets.first.is_a?(Array)
        offsets = offsets.map do |offset|
            [offset]
        end
    end

    # Read more than just one element, fall back to `:entire` for now

    @out_of_range_value = out_of_range_value
    @use_parameter_array = use_parameter_array

    if use_parameter_array
        @input = [StencilArrayInput.new(
            command: target.to_command,
            pattern: :entire,
            offsets: offsets,
            out_of_bounds_value: out_of_range_value)]
    else
        @input = [StencilSingleInput.new(
            command: target.to_command,
            pattern: :entire,
            offsets: offsets,
            out_of_bounds_value: out_of_range_value)]
    end

    if with_index
        @input.push(SingleInput.new(
            command: ArrayIndexCommand.new(dimensions: dimensions),
            pattern: :tid))
    end
    
    # Offsets should be arrays
    for offset in offsets
        if !offset.is_a?(Array)
            raise ArgumentError.new("Array expected but #{offset.class} found")
        end

        if offset.size != dimensions.size
            raise ArgumentError.new("#{dimensions.size} indices expected")
        end
    end
    
    @offsets = offsets

    # Translate relative indices to 1D-indicies starting by 0
    if block_def_node != nil
        if use_parameter_array
            offsets_mapped = Hash.new
            for i in 0..offsets.size-1
                offsets_mapped[offsets[i]] = i
            end

            # Do not modify the original AST
            @ast = block_def_node.clone
            @ast.accept(FlattenIndexNodeVisitor.new(
                block_parameter_names.first, offsets_mapped, self))
        end
    end
end

Public Instance Methods

==(other) click to toggle source
Calls superclass method Ikra::Symbolic::ArrayCommand#==
# File lib/symbolic/symbolic.rb, line 744
def ==(other)
    return super(other) && offsets == other.offsets && 
        out_of_range_value == other.out_of_range_value &&
        use_parameter_array == other.use_parameter_array
end
accept(visitor) click to toggle source
# File lib/symbolic/visitor.rb, line 22
def accept(visitor)
    visitor.visit_array_stencil_command(self)
end
max_offset() click to toggle source
# File lib/symbolic/symbolic.rb, line 758
def max_offset
    return offsets.max
end
min_offset() click to toggle source
# File lib/symbolic/symbolic.rb, line 754
def min_offset
    return offsets.min
end
size() click to toggle source
# File lib/symbolic/symbolic.rb, line 750
def size
    return input.first.command.size
end

Protected Instance Methods

block=(block) click to toggle source
Calls superclass method
# File lib/symbolic/symbolic.rb, line 764
def block=(block)
    super

    if use_parameter_array
        offsets_mapped = Hash.new
        for i in 0..offsets.size-1
            offsets_mapped[offsets[i]] = i
        end

        # Do not modify the original AST
        @ast = block_def_node.clone
        @ast.accept(FlattenIndexNodeVisitor.new(
            block_parameter_names.first, offsets_mapped, self))
    end
end