Пример #1
0
def compute_intervals(expr):
    """Return an iterable of :class:`Interval`s representing the data items
    accessed by the :class:`sympy.Eq` ``expr``."""
    # Detect the indexeds' offsets along each dimension
    stencil = Stencil()
    for e in retrieve_indexed(expr, mode='all', deep=True):
        for a in e.indices:
            if isinstance(a, Dimension):
                stencil[a].update([0])
            d = None
            off = [0]
            for i in a.args:
                if isinstance(i, Dimension):
                    d = i
                elif i.is_integer:
                    off += [int(i)]
            if d is not None:
                stencil[d].update(off)

    # Determine intervals and their iterators
    iterators = OrderedDict()
    for i in stencil.dimensions:
        if i.is_NonlinearDerived:
            iterators.setdefault(i.parent, []).append(stencil.entry(i))
        else:
            iterators.setdefault(i, [])
    intervals = []
    for k, v in iterators.items():
        offs = set.union(set(stencil.get(k)), *[i.ofs for i in v])
        intervals.append(Interval(k, min(offs), max(offs)))

    return intervals, iterators
Пример #2
0
def detect_accesses(expr):
    """
    Return a mapper ``M : F -> S``, where F are Functions appearing
    in ``expr`` and S are Stencils. ``M[f]`` represents all data accesses
    to ``f`` within ``expr``. Also map ``M[None]`` to all Dimensions used in
    ``expr`` as plain symbols, rather than as array indices.
    """
    # Compute M : F -> S
    mapper = defaultdict(Stencil)
    for e in retrieve_indexed(expr, deep=True):
        f = e.function
        for a in e.indices:
            if isinstance(a, Dimension):
                mapper[f][a].update([0])
            d = None
            off = []
            for i in a.args:
                if isinstance(i, Dimension):
                    d = i
                elif i.is_integer:
                    off += [int(i)]
            if d is not None:
                mapper[f][d].update(off or [0])

    # Compute M[None]
    other_dims = [i for i in retrieve_terminals(expr) if isinstance(i, Dimension)]
    other_dims.extend(list(expr.implicit_dims))
    mapper[None] = Stencil([(i, 0) for i in other_dims])

    return mapper
Пример #3
0
def detect_free_dimensions(expr):
    """
    Return a degenerate :class:`Stencil` for the :class:`Dimension`s used
    as plain symbols, rather than as array indices, in ``expr``.
    """
    return Stencil([(i, 0) for i in retrieve_terminals(expr)
                    if isinstance(i, Dimension)])
def build_intervals(mapper):
    """
    Given M as produced by :func:`detect_accesses`, return: ::

        * An iterable of :class:`Interval`s, representing the data items
          accessed in each :class:`Dimension` in M;
        * A dictionary of ``iterators``, suitable to build an
          :class:`IterationSpace`.
    """
    iterators = OrderedDict()
    stencil = Stencil.union(*mapper.values())
    for i in stencil.dimensions:
        if i.is_NonlinearDerived:
            iterators.setdefault(i.parent, []).append(stencil.entry(i))
        else:
            iterators.setdefault(i, [])

    intervals = []
    for k, v in iterators.items():
        offs = set.union(set(stencil.get(k)), *[i.ofs for i in v])
        intervals.append(Interval(k, min(offs), max(offs)))

    return intervals, iterators