예제 #1
0
def prepare_coefficient(coefficient, num, name, interior_facet=False):
    """Bridges the kernel interface and the GEM abstraction for
    Coefficients.

    :arg coefficient: UFL Coefficient
    :arg num: coefficient index in the original form
    :arg name: unique name to refer to the Coefficient in the kernel
    :arg interior_facet: interior facet integral?
    :returns: GEM expression referring to the Coefficient value
    """
    varexp = gem.Variable(name, (None, None))

    if coefficient.ufl_element().family() == 'Real':
        size = numpy.prod(coefficient.ufl_shape, dtype=int)
        data = gem.view(varexp, slice(num, num + 1), slice(size))
        return gem.reshape(data, (), coefficient.ufl_shape)

    element = create_element(coefficient.ufl_element())
    size = numpy.prod(element.index_shape, dtype=int)

    def expression(data):
        result, = prune(
            [gem.reshape(gem.view(data, slice(size)), element.index_shape)])
        return result

    if not interior_facet:
        data = gem.view(varexp, slice(num, num + 1), slice(size))
        return expression(gem.reshape(data, (), (size, )))
    else:
        data_p = gem.view(varexp, slice(num, num + 1), slice(size))
        data_m = gem.view(varexp, slice(num, num + 1), slice(size, 2 * size))
        return (expression(gem.reshape(data_p, (), (size, ))),
                expression(gem.reshape(data_m, (), (size, ))))
예제 #2
0
파일: ufc.py 프로젝트: inducer/tsfc
def prepare_coefficient(coefficient, num, name, interior_facet=False):
    """Bridges the kernel interface and the GEM abstraction for
    Coefficients.

    :arg coefficient: UFL Coefficient
    :arg num: coefficient index in the original form
    :arg name: unique name to refer to the Coefficient in the kernel
    :arg interior_facet: interior facet integral?
    :returns: GEM expression referring to the Coefficient value
    """
    varexp = gem.Variable(name, (None, None))

    if coefficient.ufl_element().family() == 'Real':
        size = numpy.prod(coefficient.ufl_shape, dtype=int)
        data = gem.view(varexp, slice(num, num + 1), slice(size))
        return gem.reshape(data, (), coefficient.ufl_shape)

    element = create_element(coefficient.ufl_element())
    size = numpy.prod(element.index_shape, dtype=int)

    def expression(data):
        result, = prune([gem.reshape(gem.view(data, slice(size)), element.index_shape)])
        return result

    if not interior_facet:
        data = gem.view(varexp, slice(num, num + 1), slice(size))
        return expression(gem.reshape(data, (), (size,)))
    else:
        data_p = gem.view(varexp, slice(num, num + 1), slice(size))
        data_m = gem.view(varexp, slice(num, num + 1), slice(size, 2 * size))
        return (expression(gem.reshape(data_p, (), (size,))),
                expression(gem.reshape(data_m, (), (size,))))
예제 #3
0
def test_view_view(matrix):
    expression = gem.view(gem.view(matrix, slice(3, 8), slice(5, 12)),
                          slice(4), slice(3, 6))
    assert expression.shape == (4, 3)

    actual = [convert(expression, multiindex)
              for multiindex in numpy.ndindex(expression.shape)]

    assert list(product(range(3, 7), range(8, 11))) == actual
예제 #4
0
def test_view_view(matrix):
    expression = gem.view(gem.view(matrix, slice(3, 8), slice(5, 12)),
                          slice(4), slice(3, 6))
    assert expression.shape == (4, 3)

    actual = [convert(expression, multiindex)
              for multiindex in numpy.ndindex(expression.shape)]

    assert list(product(range(3, 7), range(8, 11))) == actual
예제 #5
0
파일: firedrake.py 프로젝트: wei-pan/tsfc
def prepare_coefficient(coefficient, name, interior_facet=False):
    """Bridges the kernel interface and the GEM abstraction for
    Coefficients.

    :arg coefficient: UFL Coefficient
    :arg name: unique name to refer to the Coefficient in the kernel
    :arg interior_facet: interior facet integral?
    :returns: (funarg, expression)
         funarg     - :class:`coffee.Decl` function argument
         expression - GEM expression referring to the Coefficient
                      values
    """
    assert isinstance(interior_facet, bool)

    if coefficient.ufl_element().family() == 'Real':
        # Constant
        funarg = coffee.Decl(SCALAR_TYPE,
                             coffee.Symbol(name),
                             pointers=[("restrict", )],
                             qualifiers=["const"])

        expression = gem.reshape(gem.Variable(name, (None, )),
                                 coefficient.ufl_shape)

        return funarg, expression

    finat_element = create_element(coefficient.ufl_element())

    if isinstance(finat_element, TensorFiniteElement):
        scalar_shape = finat_element.base_element.index_shape
        tensor_shape = finat_element.index_shape[len(scalar_shape):]
    else:
        scalar_shape = finat_element.index_shape
        tensor_shape = ()
    scalar_size = numpy.prod(scalar_shape, dtype=int)
    tensor_size = numpy.prod(tensor_shape, dtype=int)

    funarg = coffee.Decl(SCALAR_TYPE,
                         coffee.Symbol(name),
                         pointers=[("const", "restrict"), ("restrict", )],
                         qualifiers=["const"])

    if not interior_facet:
        expression = gem.reshape(
            gem.Variable(name, (scalar_size, tensor_size)), scalar_shape,
            tensor_shape)
    else:
        varexp = gem.Variable(name, (2 * scalar_size, tensor_size))
        plus = gem.view(varexp, slice(scalar_size), slice(tensor_size))
        minus = gem.view(varexp, slice(scalar_size, 2 * scalar_size),
                         slice(tensor_size))
        expression = (gem.reshape(plus, scalar_shape, tensor_shape),
                      gem.reshape(minus, scalar_shape, tensor_shape))
    return funarg, expression
예제 #6
0
def test_view_reshape(vector):
    expression = gem.view(gem.reshape(vector, (3, 4)), slice(2), slice(1, 3))
    assert expression.shape == (2, 2)

    actual = [convert(expression, multiindex)
              for multiindex in numpy.ndindex(expression.shape)]

    assert [(1,), (2,), (5,), (6,)] == actual
예제 #7
0
def test_reshape_shape(vector):
    expression = gem.reshape(gem.view(vector, slice(5, 11)), (3, 2))
    assert expression.shape == (3, 2)

    actual = [convert(expression, multiindex)
              for multiindex in numpy.ndindex(expression.shape)]

    assert [(i,) for i in range(5, 11)] == actual
예제 #8
0
def test_view_reshape(vector):
    expression = gem.view(gem.reshape(vector, (3, 4)), slice(2), slice(1, 3))
    assert expression.shape == (2, 2)

    actual = [convert(expression, multiindex)
              for multiindex in numpy.ndindex(expression.shape)]

    assert [(1,), (2,), (5,), (6,)] == actual
예제 #9
0
def test_reshape_shape(vector):
    expression = gem.reshape(gem.view(vector, slice(5, 11)), (3, 2))
    assert expression.shape == (3, 2)

    actual = [convert(expression, multiindex)
              for multiindex in numpy.ndindex(expression.shape)]

    assert [(i,) for i in range(5, 11)] == actual
예제 #10
0
def prepare_arguments(arguments, multiindices, scalar_type, interior_facet=False, diagonal=False):
    """Bridges the kernel interface and the GEM abstraction for
    Arguments.  Vector Arguments are rearranged here for interior
    facet integrals.

    :arg arguments: UFL Arguments
    :arg multiindices: Argument multiindices
    :arg interior_facet: interior facet integral?
    :arg diagonal: Are we assembling the diagonal of a rank-2 element tensor?
    :returns: (funarg, expression)
         funarg      - :class:`loopy.GlobalArg` function argument
         expressions - GEM expressions referring to the argument
                       tensor
    """

    assert isinstance(interior_facet, bool)

    if len(arguments) == 0:
        # No arguments
        funarg = lp.GlobalArg("A", dtype=scalar_type, shape=(1,))
        expression = gem.Indexed(gem.Variable("A", (1,)), (0,))

        return funarg, [expression]

    elements = tuple(create_element(arg.ufl_element()) for arg in arguments)
    shapes = tuple(element.index_shape for element in elements)

    if diagonal:
        if len(arguments) != 2:
            raise ValueError("Diagonal only for 2-forms")
        try:
            element, = set(elements)
        except ValueError:
            raise ValueError("Diagonal only for diagonal blocks (test and trial spaces the same)")

        elements = (element, )
        shapes = tuple(element.index_shape for element in elements)
        multiindices = multiindices[:1]

    def expression(restricted):
        return gem.Indexed(gem.reshape(restricted, *shapes),
                           tuple(chain(*multiindices)))

    u_shape = numpy.array([numpy.prod(shape, dtype=int) for shape in shapes])
    if interior_facet:
        c_shape = tuple(2 * u_shape)
        slicez = [[slice(r * s, (r + 1) * s)
                   for r, s in zip(restrictions, u_shape)]
                  for restrictions in product((0, 1), repeat=len(arguments))]
    else:
        c_shape = tuple(u_shape)
        slicez = [[slice(s) for s in u_shape]]

    funarg = lp.GlobalArg("A", dtype=scalar_type, shape=c_shape)
    varexp = gem.Variable("A", c_shape)
    expressions = [expression(gem.view(varexp, *slices)) for slices in slicez]
    return funarg, prune(expressions)
예제 #11
0
def _slate2gem_block(expr, self):
    child, = map(self, expr.children)
    child_shapes = expr.children[0].shapes
    offsets = tuple(
        sum(shape[:idx])
        for shape, (idx, *_) in zip(child_shapes.values(), expr._indices))
    return view(
        child,
        *(slice(idx, idx + extent)
          for idx, extent in zip(offsets, expr.shape)))
예제 #12
0
def test_pickle_gem(protocol):
    f = gem.VariableIndex(gem.Indexed(gem.Variable('facet', (2,)), (1,)))
    q = gem.Index()
    r = gem.Index()
    _1 = gem.Indexed(gem.Literal(numpy.random.rand(3, 6, 8)), (f, q, r))
    _2 = gem.Indexed(gem.view(gem.Variable('w', (None, None)), slice(8), slice(1)), (r, 0))
    expr = gem.ComponentTensor(gem.IndexSum(gem.Product(_1, _2), (r,)), (q,))

    unpickled = pickle.loads(pickle.dumps(expr, protocol))
    assert repr(expr) == repr(unpickled)
예제 #13
0
def prepare_arguments(arguments,
                      multiindices,
                      scalar_type,
                      interior_facet=False):
    """Bridges the kernel interface and the GEM abstraction for
    Arguments.  Vector Arguments are rearranged here for interior
    facet integrals.

    :arg arguments: UFL Arguments
    :arg multiindices: Argument multiindices
    :arg interior_facet: interior facet integral?
    :returns: (funarg, prepare, expressions)
         funarg      - :class:`coffee.Decl` function argument
         prepare     - list of COFFEE nodes to be prepended to the
                       kernel body
         expressions - GEM expressions referring to the argument
                       tensor
    """
    funarg = coffee.Decl(scalar_type, coffee.Symbol("A"), pointers=[()])
    varexp = gem.Variable("A", (None, ))

    if len(arguments) == 0:
        # No arguments
        zero = coffee.FlatBlock("memset({name}, 0, sizeof(*{name}));\n".format(
            name=funarg.sym.gencode()))
        return funarg, [zero], [gem.reshape(varexp, ())]

    elements = tuple(create_element(arg.ufl_element()) for arg in arguments)
    shapes = [element.index_shape for element in elements]
    indices = tuple(chain(*multiindices))

    def expression(restricted):
        return gem.Indexed(gem.reshape(restricted, *shapes), indices)

    u_shape = numpy.array(
        [numpy.prod(element.index_shape, dtype=int) for element in elements])
    if interior_facet:
        c_shape = tuple(2 * u_shape)
        slicez = [[
            slice(r * s, (r + 1) * s) for r, s in zip(restrictions, u_shape)
        ] for restrictions in product((0, 1), repeat=len(arguments))]
    else:
        c_shape = tuple(u_shape)
        slicez = [[slice(s) for s in u_shape]]

    expressions = [
        expression(gem.view(gem.reshape(varexp, c_shape), *slices))
        for slices in slicez
    ]

    zero = coffee.FlatBlock(
        str.format("memset({name}, 0, {size} * sizeof(*{name}));\n",
                   name=funarg.sym.gencode(),
                   size=numpy.product(c_shape, dtype=int)))
    return funarg, [zero], prune(expressions)
예제 #14
0
파일: firedrake.py 프로젝트: inducer/tsfc
def prepare_coefficient(coefficient, name, interior_facet=False):
    """Bridges the kernel interface and the GEM abstraction for
    Coefficients.

    :arg coefficient: UFL Coefficient
    :arg name: unique name to refer to the Coefficient in the kernel
    :arg interior_facet: interior facet integral?
    :returns: (funarg, expression)
         funarg     - :class:`coffee.Decl` function argument
         expression - GEM expression referring to the Coefficient
                      values
    """
    assert isinstance(interior_facet, bool)

    if coefficient.ufl_element().family() == 'Real':
        # Constant
        funarg = coffee.Decl(SCALAR_TYPE, coffee.Symbol(name),
                             pointers=[("restrict",)],
                             qualifiers=["const"])

        expression = gem.reshape(gem.Variable(name, (None,)),
                                 coefficient.ufl_shape)

        return funarg, expression

    finat_element = create_element(coefficient.ufl_element())
    shape = finat_element.index_shape
    size = numpy.prod(shape, dtype=int)

    funarg = coffee.Decl(SCALAR_TYPE, coffee.Symbol(name),
                         pointers=[("restrict",)],
                         qualifiers=["const"])

    if not interior_facet:
        expression = gem.reshape(gem.Variable(name, (size,)), shape)
    else:
        varexp = gem.Variable(name, (2 * size,))
        plus = gem.view(varexp, slice(size))
        minus = gem.view(varexp, slice(size, 2 * size))
        expression = (gem.reshape(plus, shape),
                      gem.reshape(minus, shape))
    return funarg, expression
예제 #15
0
def test_pickle_gem(protocol):
    f = gem.VariableIndex(gem.Indexed(gem.Variable('facet', (2, )), (1, )))
    q = gem.Index()
    r = gem.Index()
    _1 = gem.Indexed(gem.Literal(numpy.random.rand(3, 6, 8)), (f, q, r))
    _2 = gem.Indexed(
        gem.view(gem.Variable('w', (None, None)), slice(8), slice(1)), (r, 0))
    expr = gem.ComponentTensor(gem.IndexSum(gem.Product(_1, _2), (r, )), (q, ))

    unpickled = pickle.loads(pickle.dumps(expr, protocol))
    assert repr(expr) == repr(unpickled)
예제 #16
0
def prepare_coefficient(coefficient, name, scalar_type, interior_facet=False):
    """Bridges the kernel interface and the GEM abstraction for
    Coefficients.

    :arg coefficient: UFL Coefficient
    :arg name: unique name to refer to the Coefficient in the kernel
    :arg interior_facet: interior facet integral?
    :returns: (funarg, expression)
         funarg     - :class:`loopy.GlobalArg` function argument
         expression - GEM expression referring to the Coefficient
                      values
    """
    assert isinstance(interior_facet, bool)

    if coefficient.ufl_element().family() == 'Real':
        # Constant
        funarg = lp.GlobalArg(name,
                              dtype=scalar_type,
                              shape=(coefficient.ufl_element().value_size(), ))
        expression = gem.reshape(gem.Variable(name, (None, )),
                                 coefficient.ufl_shape)

        return funarg, expression

    finat_element = create_element(coefficient.ufl_element())

    shape = finat_element.index_shape
    size = numpy.prod(shape, dtype=int)

    if not interior_facet:
        expression = gem.reshape(gem.Variable(name, (size, )), shape)
    else:
        varexp = gem.Variable(name, (2 * size, ))
        plus = gem.view(varexp, slice(size))
        minus = gem.view(varexp, slice(size, 2 * size))
        expression = (gem.reshape(plus, shape), gem.reshape(minus, shape))
        size = size * 2
    funarg = lp.GlobalArg(name, dtype=scalar_type, shape=(size, ))
    return funarg, expression
예제 #17
0
파일: ufc.py 프로젝트: inducer/tsfc
def prepare_arguments(arguments, multiindices, interior_facet=False):
    """Bridges the kernel interface and the GEM abstraction for
    Arguments.  Vector Arguments are rearranged here for interior
    facet integrals.

    :arg arguments: UFL Arguments
    :arg multiindices: Argument multiindices
    :arg interior_facet: interior facet integral?
    :returns: (funarg, prepare, expressions)
         funarg      - :class:`coffee.Decl` function argument
         prepare     - list of COFFEE nodes to be prepended to the
                       kernel body
         expressions - GEM expressions referring to the argument
                       tensor
    """
    funarg = coffee.Decl(SCALAR_TYPE, coffee.Symbol("A"), pointers=[()])
    varexp = gem.Variable("A", (None,))

    if len(arguments) == 0:
        # No arguments
        zero = coffee.FlatBlock(
            "memset({name}, 0, sizeof(*{name}));\n".format(name=funarg.sym.gencode())
        )
        return funarg, [zero], [gem.reshape(varexp, ())]

    elements = tuple(create_element(arg.ufl_element()) for arg in arguments)
    shapes = [element.index_shape for element in elements]
    indices = tuple(chain(*multiindices))

    def expression(restricted):
        return gem.Indexed(gem.reshape(restricted, *shapes), indices)

    u_shape = numpy.array([numpy.prod(element.index_shape, dtype=int)
                           for element in elements])
    if interior_facet:
        c_shape = tuple(2 * u_shape)
        slicez = [[slice(r * s, (r + 1) * s)
                   for r, s in zip(restrictions, u_shape)]
                  for restrictions in product((0, 1), repeat=len(arguments))]
    else:
        c_shape = tuple(u_shape)
        slicez = [[slice(s) for s in u_shape]]

    expressions = [expression(gem.view(gem.reshape(varexp, c_shape), *slices))
                   for slices in slicez]

    zero = coffee.FlatBlock(
        str.format("memset({name}, 0, {size} * sizeof(*{name}));\n",
                   name=funarg.sym.gencode(), size=numpy.product(c_shape, dtype=int))
    )
    return funarg, [zero], prune(expressions)
예제 #18
0
def prepare_arguments(arguments,
                      multiindices,
                      scalar_type,
                      interior_facet=False):
    """Bridges the kernel interface and the GEM abstraction for
    Arguments.  Vector Arguments are rearranged here for interior
    facet integrals.

    :arg arguments: UFL Arguments
    :arg multiindices: Argument multiindices
    :arg interior_facet: interior facet integral?
    :returns: (funarg, expression)
         funarg      - :class:`coffee.Decl` function argument
         expressions - GEM expressions referring to the argument
                       tensor
    """
    assert isinstance(interior_facet, bool)

    if len(arguments) == 0:
        # No arguments
        funarg = coffee.Decl(scalar_type, coffee.Symbol("A", rank=(1, )))
        expression = gem.Indexed(gem.Variable("A", (1, )), (0, ))

        return funarg, [expression]

    elements = tuple(create_element(arg.ufl_element()) for arg in arguments)
    shapes = tuple(element.index_shape for element in elements)

    def expression(restricted):
        return gem.Indexed(gem.reshape(restricted, *shapes),
                           tuple(chain(*multiindices)))

    u_shape = numpy.array([numpy.prod(shape, dtype=int) for shape in shapes])
    if interior_facet:
        c_shape = tuple(2 * u_shape)
        slicez = [[
            slice(r * s, (r + 1) * s) for r, s in zip(restrictions, u_shape)
        ] for restrictions in product((0, 1), repeat=len(arguments))]
    else:
        c_shape = tuple(u_shape)
        slicez = [[slice(s) for s in u_shape]]

    funarg = coffee.Decl(scalar_type, coffee.Symbol("A", rank=c_shape))
    varexp = gem.Variable("A", c_shape)
    expressions = [expression(gem.view(varexp, *slices)) for slices in slicez]
    return funarg, prune(expressions)
예제 #19
0
파일: firedrake.py 프로젝트: inducer/tsfc
def prepare_arguments(arguments, multiindices, interior_facet=False):
    """Bridges the kernel interface and the GEM abstraction for
    Arguments.  Vector Arguments are rearranged here for interior
    facet integrals.

    :arg arguments: UFL Arguments
    :arg multiindices: Argument multiindices
    :arg interior_facet: interior facet integral?
    :returns: (funarg, expression)
         funarg      - :class:`coffee.Decl` function argument
         expressions - GEM expressions referring to the argument
                       tensor
    """
    assert isinstance(interior_facet, bool)

    if len(arguments) == 0:
        # No arguments
        funarg = coffee.Decl(SCALAR_TYPE, coffee.Symbol("A", rank=(1,)))
        expression = gem.Indexed(gem.Variable("A", (1,)), (0,))

        return funarg, [expression]

    elements = tuple(create_element(arg.ufl_element()) for arg in arguments)
    shapes = tuple(element.index_shape for element in elements)

    def expression(restricted):
        return gem.Indexed(gem.reshape(restricted, *shapes),
                           tuple(chain(*multiindices)))

    u_shape = numpy.array([numpy.prod(shape, dtype=int) for shape in shapes])
    if interior_facet:
        c_shape = tuple(2 * u_shape)
        slicez = [[slice(r * s, (r + 1) * s)
                   for r, s in zip(restrictions, u_shape)]
                  for restrictions in product((0, 1), repeat=len(arguments))]
    else:
        c_shape = tuple(u_shape)
        slicez = [[slice(s) for s in u_shape]]

    funarg = coffee.Decl(SCALAR_TYPE, coffee.Symbol("A", rank=c_shape))
    varexp = gem.Variable("A", c_shape)
    expressions = [expression(gem.view(varexp, *slices)) for slices in slicez]
    return funarg, prune(expressions)
예제 #20
0
파일: ufc.py 프로젝트: inducer/tsfc
 def expression(data):
     result, = prune([gem.reshape(gem.view(data, slice(size)), element.index_shape)])
     return result
예제 #21
0
 def expression(data):
     result, = prune(
         [gem.reshape(gem.view(data, slice(size)), element.index_shape)])
     return result
예제 #22
0
 def expressions(data):
     return prune([transpose(gem.reshape(gem.view(data, slice_), shape), rank)
                   for slice_, shape, rank in zip(slices, transposed_shapes, tensor_ranks)])
예제 #23
0
def prepare_coefficients(coefficients, num, name, interior_facet=False):
    """Bridges the kernel interface and the GEM abstraction for
    Coefficients.

    :arg coefficients: split UFL Coefficients
    :arg num: coefficient index in the original form
    :arg name: unique name to refer to the Coefficient in the kernel
    :arg interior_facet: interior facet integral?
    :returns: GEM expression referring to the Coefficient value
    """
    varexp = gem.Variable(name, (None, None))

    if len(coefficients) == 1 and coefficients[0].ufl_element().family() == 'Real':
        coefficient, = coefficients
        size = numpy.prod(coefficient.ufl_shape, dtype=int)
        data = gem.view(varexp, slice(num, num + 1), slice(size))
        expression = gem.reshape(data, (), coefficient.ufl_shape)
        return [expression]

    elements = [create_element(coeff.ufl_element()) for coeff in coefficients]
    space_dimensions = [numpy.prod(element.index_shape, dtype=int)
                        for element in elements]
    ends = list(numpy.cumsum(space_dimensions))
    starts = [0] + ends[:-1]
    slices = [slice(start, end) for start, end in zip(starts, ends)]

    transposed_shapes = []
    tensor_ranks = []
    for element in elements:
        if isinstance(element, TensorFiniteElement):
            scalar_shape = element.base_element.index_shape
            tensor_shape = element.index_shape[len(scalar_shape):]
        else:
            scalar_shape = element.index_shape
            tensor_shape = ()

        transposed_shapes.append(tensor_shape + scalar_shape)
        tensor_ranks.append(len(tensor_shape))

    def transpose(expr, rank):
        assert not expr.free_indices
        assert 0 <= rank < len(expr.shape)
        if rank == 0:
            return expr
        else:
            indices = tuple(gem.Index(extent=extent) for extent in expr.shape)
            transposed_indices = indices[rank:] + indices[:rank]
            return gem.ComponentTensor(gem.Indexed(expr, indices),
                                       transposed_indices)

    def expressions(data):
        return prune([transpose(gem.reshape(gem.view(data, slice_), shape), rank)
                      for slice_, shape, rank in zip(slices, transposed_shapes, tensor_ranks)])

    size = sum(space_dimensions)
    if not interior_facet:
        data = gem.view(varexp, slice(num, num + 1), slice(size))
        return expressions(gem.reshape(data, (), (size,)))
    else:
        data_p = gem.view(varexp, slice(num, num + 1), slice(size))
        data_m = gem.view(varexp, slice(num, num + 1), slice(size, 2 * size))
        return list(zip(expressions(gem.reshape(data_p, (), (size,))),
                        expressions(gem.reshape(data_m, (), (size,)))))