Ejemplo n.º 1
0
def setitem(ary, loc, value):
    """
    Set the 'value' into 'ary' at the location specified through 'loc'.
    'loc' can be a scalar or a slice object, or a tuple thereof
    """

    if not isinstance(loc, tuple):
        loc = (loc,)

    # Let's try to convert non-arrays and non-scalars to an array
    # e.g. converting a python list to an array
    if not (bhary.check(value) or np.isscalar(value)):
        value = array_create.array(value)

    # Lets make sure that not all dimensions are indexed by integers
    loc = list(loc)
    if len(loc) == ary.ndim and all((np.isscalar(s) for s in loc)):
        # 'slice' doesn't support negative start index
        if loc[0] < 0:
            loc[0] += ary.shape[0]
        loc[0] = slice(loc[0], loc[0]+1)

    # Copy the 'value' to 'ary' using the 'loc'
    if ary.ndim == 0:
        assign(value, ary)
    else:
        assign(value, ary[tuple(loc)])
Ejemplo n.º 2
0
def assign(ary, out):
    """Copy data from array 'ary' to 'out'"""

    if not np.isscalar(ary):
        (ary, out) = broadcast_arrays(ary, out)
        # We ignore self assignments
        if bhary.get_base(ary) is bhary.get_base(out) and \
                bhary.identical_views(ary, out):
            return

    # We use a tmp array if the in-/out-put has memory conflicts
    if overlap_conflict(out, ary):
        tmp = array_create.empty_like(out)
        assign(ary, tmp)
        return assign(tmp, out)

    if bhary.check(out):
        out = get_bhc(out)
        if not np.isscalar(ary):
            if not bhary.check(ary):
                # Convert the NumPy array to bohrium
                ary = array_create.array(ary)
            ary = get_bhc(ary)
        target.ufunc(identity, out, ary)
    else:
        if bhary.check(ary):
            if "BH_SYNC_WARN" in os.environ:
                import warnings
                warnings.warn("BH_SYNC_WARN: Copying the array to NumPy", RuntimeWarning, stacklevel=2)
            get_base(ary)._data_bhc2np()
        out[...] = ary
Ejemplo n.º 3
0
def broadcast_arrays(*args):
    """
    Broadcast any number of arrays against each other.

    .. note:: This function is very similar to NumPy's  `broadcast_arrays()`

    Parameters
    ----------
    `array_list` : array_likes
        The arrays to broadcast.

    Returns
    -------
    broadcasted : list of arrays
        These arrays are views on the original arrays or the untouched originals.
        They are typically not contiguous.  Furthermore, more than one element of a
        broadcasted array may refer to a single memory location.  If you
        need to write to the arrays, make copies first.
    shape : tuple
        The shape the arrays are broadcasted to
    """
    try:
        if len(args) == 0:
            return ([], [])

        # Common case where nothing needs to be broadcasted.
        bcast = numpy.broadcast(*args)
        if all(array.shape == bcast.shape for array in args
               if not numpy.isscalar(array)):
            return (args, bcast.shape)

        ret = []
        # We use NumPy's broadcast_arrays() to broadcast the views.
        # Notice that the 'subok' argument is first introduced in version 10 of NumPy
        try:
            bargs = numpy.broadcast_arrays(*args, subok=True)
        except TypeError as err:
            if "subok" in err.message:
                bargs = numpy.broadcast_arrays(*args)
            else:
                raise

        for a, b in zip(args, bargs):
            if numpy.isscalar(a) or not isinstance(a, numpy.ndarray):
                ret.append(b)
            elif bhary.identical_views(a, b):
                ret.append(a)
            else:
                ret.append(b)
    except ValueError as msg:
        if str(msg).find(
                "shape mismatch: objects cannot be broadcast to a single shape"
        ) != -1:
            shapes = [arg.shape for arg in args]
            raise ValueError(
                "shape mismatch: objects cannot be broadcasted to a single shape: %s"
                % shapes)
        raise
    return (ret, bcast.shape)
Ejemplo n.º 4
0
def broadcast_arrays(*args):
    """
    Broadcast any number of arrays against each other.

    .. note:: This function differ from NumPy in one way: it does not touch arrays that does not need broadcasting

    Parameters
    ----------
    `*args` : array_likes
        The arrays to broadcast.

    Returns
    -------
    broadcasted : list of arrays
        These arrays are views on the original arrays or the untouched originals.
        They are typically not contiguous.  Furthermore, more than one element of a
        broadcasted array may refer to a single memory location.  If you
        need to write to the arrays, make copies first.

    Examples
    --------
    >>> x = np.array([[1,2,3]])
    >>> y = np.array([[1],[2],[3]])
    >>> np.broadcast_arrays(x, y)
    [array([[1, 2, 3],
           [1, 2, 3],
           [1, 2, 3]]), array([[1, 1, 1],
           [2, 2, 2],
           [3, 3, 3]])]

    Here is a useful idiom for getting contiguous copies instead of
    non-contiguous views.

    >>> [np.array(a) for a in np.broadcast_arrays(x, y)]
    [array([[1, 2, 3],
           [1, 2, 3],
           [1, 2, 3]]), array([[1, 1, 1],
           [2, 2, 2],
           [3, 3, 3]])]

    """
    try:
        ret = []
        bargs = numpy.broadcast_arrays(*args)

        for a, b in zip(args, bargs):
            if numpy.isscalar(a) or not isinstance(a, numpy.ndarray):
                ret.append(b)
            elif bhary.identical_views(a, b):
                ret.append(a)
            else:
                ret.append(b)
    except ValueError as msg:
        if str(msg).find("shape mismatch: objects cannot be broadcast to a single shape") != -1:
            shapes = [arg.shape for arg in args]
            raise ValueError("shape mismatch: objects cannot be broadcast to a single shape: %s" % shapes)

    return ret
Ejemplo n.º 5
0
def masked_set(ary, bool_mask, value):
    """
    Set the 'value' into 'ary' at the location specified through 'bool_mask'.
    """

    if numpy.isscalar(value) and ufuncs.isfinite(value):
        ary *= ~bool_mask
        ary += bool_mask * value
    else:
        ary[reorganization.nonzero(bool_mask)] = value
Ejemplo n.º 6
0
def masked_set(ary, bool_mask, value):
    """
    Set the 'value' into 'ary' at the location specified through 'bool_mask'.
    """

    if numpy.isscalar(value):
        ary *= ~bool_mask
        ary += bool_mask * value
    else:
        ary[reorganization.nonzero(bool_mask)] = value
Ejemplo n.º 7
0
def broadcast_arrays(*args):
    """
    Broadcast any number of arrays against each other.

    .. note:: This function differ from NumPy in one way: it does not touch arrays that does not need broadcasting

    Parameters
    ----------
    `*args` : array_likes
        The arrays to broadcast.

    Returns
    -------
    broadcasted : list of arrays
        These arrays are views on the original arrays or the untouched originals.
        They are typically not contiguous.  Furthermore, more than one element of a
        broadcasted array may refer to a single memory location.  If you
        need to write to the arrays, make copies first.

    Examples
    --------
    >>> x = np.array([[1,2,3]])
    >>> y = np.array([[1],[2],[3]])
    >>> np.broadcast_arrays(x, y)
    [array([[1, 2, 3],
           [1, 2, 3],
           [1, 2, 3]]), array([[1, 1, 1],
           [2, 2, 2],
           [3, 3, 3]])]

    Here is a useful idiom for getting contiguous copies instead of
    non-contiguous views.

    >>> [np.array(a) for a in np.broadcast_arrays(x, y)]
    [array([[1, 2, 3],
           [1, 2, 3],
           [1, 2, 3]]), array([[1, 1, 1],
           [2, 2, 2],
           [3, 3, 3]])]

    """
    ret = []
    bargs = numpy.broadcast_arrays(*args)
    for a, b in itertools.izip(args, bargs):
        if numpy.isscalar(a):
            ret.append(b)
        elif ndarray.identical_views(a, b):
            ret.append(a)
        else:
            ret.append(b)
    return ret
Ejemplo n.º 8
0
def broadcast_arrays(*args):
    """
    Broadcast any number of arrays against each other.

    .. note:: This function differ from NumPy in one way: it does not touch arrays that does not need broadcasting

    Parameters
    ----------
    `*args` : array_likes
        The arrays to broadcast.

    Returns
    -------
    broadcasted : list of arrays
        These arrays are views on the original arrays or the untouched originals.
        They are typically not contiguous.  Furthermore, more than one element of a
        broadcasted array may refer to a single memory location.  If you
        need to write to the arrays, make copies first.

    Examples
    --------
    >>> x = np.array([[1,2,3]])
    >>> y = np.array([[1],[2],[3]])
    >>> np.broadcast_arrays(x, y)
    [array([[1, 2, 3],
           [1, 2, 3],
           [1, 2, 3]]), array([[1, 1, 1],
           [2, 2, 2],
           [3, 3, 3]])]

    Here is a useful idiom for getting contiguous copies instead of
    non-contiguous views.

    >>> [np.array(a) for a in np.broadcast_arrays(x, y)]
    [array([[1, 2, 3],
           [1, 2, 3],
           [1, 2, 3]]), array([[1, 1, 1],
           [2, 2, 2],
           [3, 3, 3]])]

    """
    ret = []
    bargs = numpy.broadcast_arrays(*args)
    for a, b in itertools.izip(args, bargs):
        if numpy.isscalar(a):
            ret.append(b)
        elif bhary.identical_views(a, b):
            ret.append(a)
        else:
            ret.append(b)
    return ret
Ejemplo n.º 9
0
def assign(ary, out):
    """Copy data from array 'a' to 'out'"""

    if not np.isscalar(ary):
        (ary, out) = broadcast_arrays(ary, out)

    #We use a tmp array if the in-/out-put has memory conflicts
    if overlap_conflict(out, ary):
        tmp = array_create.empty_like(out)
        assign(ary, tmp)
        return assign(tmp, out)

    if ndarray.check(out):
        out = get_bhc(out)
        if not np.isscalar(ary):
            if not ndarray.check(ary):
                ary = array_create.array(ary)#Convert the NumPy array to bohrium
            ary = get_bhc(ary)
        target.ufunc(identity, out, ary)
    else:
        if ndarray.check(ary):
            get_base(ary)._data_bhc2np()
        out[...] = ary
Ejemplo n.º 10
0
def setitem(ary, loc, value):
    """Set the 'value' into 'ary' at the location specified through 'loc'.
    'loc' can be a scalar or a slice object, or a tuple thereof"""

    if not isinstance(loc, tuple):
        loc = (loc,)

    #Lets make sure that not all dimensions are indexed by integers
    loc = list(loc)
    if len(loc) == ary.ndim and all((np.isscalar(s) for s in loc)):
        if loc[0] < 0:#'slice' doesn't support negative start index
            loc[0] += ary.shape[0]
        loc[0] = slice(loc[0], loc[0]+1)
    #Copy the 'value' to 'ary' using the 'loc'
    if ary.ndim == 0:
        assign(value, ary)
    else:
        assign(value, ary[tuple(loc)])
Ejemplo n.º 11
0
def overlap_conflict(out, *inputs):
    """
    Return True when there is a possible memory conflict between the output
    and the inputs.


    :param Mixed out: Array in the role of being written to.
    :param Mixed inputs: Arrays in the role being read from.
    :returns: True in case of conflict.
    :rtype: bool
    """

    for i in inputs:
        if not np.isscalar(i):
            if np.may_share_memory(out, i) and not (out.ndim == i.ndim and \
                     out.strides == i.strides and out.shape == i.shape and \
                     out.ctypes.data == i.ctypes.data):
                return True
    return False
Ejemplo n.º 12
0
def overlap_conflict(out, *inputs):
    """
    Return True when there is a possible memory conflict between the output
    and the inputs.


    :param Mixed out: Array in the role of being written to.
    :param Mixed inputs: Arrays in the role being read from.
    :returns: True in case of conflict.
    :rtype: bool
    """

    for i in inputs:
        if not np.isscalar(i):
            if np.may_share_memory(out, i) and not (out.ndim == i.ndim and \
                     out.strides == i.strides and out.shape == i.shape and \
                     out.ctypes.data == i.ctypes.data):
                return True
    return False
Ejemplo n.º 13
0
def broadcast_arrays(*args):
    """
    Broadcast any number of arrays against each other.

    .. note:: This function is very similar to NumPy's  `broadcast_arrays()`

    Parameters
    ----------
    `array_list` : array_likes
        The arrays to broadcast.

    Returns
    -------
    broadcasted : list of arrays
        These arrays are views on the original arrays or the untouched originals.
        They are typically not contiguous.  Furthermore, more than one element of a
        broadcasted array may refer to a single memory location.  If you
        need to write to the arrays, make copies first.
    shape : tuple
        The shape the arrays are broadcasted to
    """
    try:
        if len(args) == 0:
            return ([], [])

        if len(args) == 1:
            if numpy.isscalar(args[0]):  # It is possible that `args[0]` is a scalar
                shape = (1,)
            else:
                shape = args[0].shape
            return (args, shape)

        # Common case where nothing needs to be broadcasted.
        bcast = numpy.broadcast(*args)
        if all(array.shape == bcast.shape for array in args if not numpy.isscalar(array)):
            return (args, bcast.shape)

        ret = []
        # We use NumPy's broadcast_arrays() to broadcast the views.
        # Notice that the 'subok' argument is first introduced in version 10 of NumPy
        try:
            bargs = numpy.broadcast_arrays(*args, subok=True)
        except TypeError as err:
            if "subok" in err.message:
                bargs = numpy.broadcast_arrays(*args)
            else:
                raise

        # The broadcasted view inherits dynamic changes if there are any.
        # Used for broadcasting dynamic views within a do_while loop
        bcast_array = args[0]
        bcast_dvi = bcast_array.bhc_dynamic_view_info
        for a, b in zip(args, bargs):
            # If the broadcast view changes shape between iterations,
            # force the same change to the views being broadcasted.
            # Used in regard to iterators within do_while loops.
            a_dvi = a.bhc_dynamic_view_info

            # If array that is broadcasted has dynamic changes, the
            # broadcasted array must inherit these
            if a_dvi:
                b_dvi = deepcopy(a_dvi)
            else:
                b_dvi = loop.DynamicViewInfo({}, a.shape, a.strides)

            # If the array that is broadcasted from has changes in shape
            # must these changes also be inherited by the broadcasted array
            if bcast_dvi:
                # If the view contains a slide in a broadcasted dimension,
                # the slide must be inherited
                for dim in bcast_dvi.dims_with_changes():
                    # If the array, which is broadcasted from, does not have
                    # dynamic changes, there are no changes to add
                    if bcast_dvi.dim_shape_change(dim) == 0:
                        continue

                    # The array, which is broadcasted from, has dynamic changes
                    # while the broadcasted array does not. Add the changes to the
                    # broadcasted array
                    elif b_dvi.dim_shape_change(dim) == 0:
                        for (_, shape_change, step_delay, shape, stride) in bcast_dvi.changes_in_dim(dim):
                            # No reason to add a change of 0 in the dimension
                            if shape_change == 0:
                                continue
                            b_dvi.add_dynamic_change(dim, 0, shape_change, step_delay, shape, stride)

                    # Both array, which is broadcasted from, and the broadcasted array has
                    # dynamic changes. Make sure they are the same. If not the change cannot
                    # be guessed, which results in an error.
                    elif b_dvi.dim_shape_change(dim) != 0 and \
                            b_dvi.dim_shape_change(dim) != bcast_dvi.dim_shape_change(dim):
                        raise loop.IteratorIllegalBroadcast(
                            dim, a.shape, a_dvi.dim_shape_change(dim),
                            bcast_array.shape, bcast_dvi.dim_shape_change(dim))

            # Add the dynamic changes, if any
            if b_dvi.has_changes():
                b.bhc_dynamic_view_info = b_dvi

            # Append the broadcasted array
            ret.append(b)

    except ValueError as msg:
        if str(msg).find("shape mismatch: objects cannot be broadcast to a single shape") != -1:
            shapes = [arg.shape for arg in args]
            raise ValueError("shape mismatch: objects cannot be broadcasted to a single shape: %s" % shapes)
        raise
    return (ret, bcast.shape)
Ejemplo n.º 14
0
def where(condition, x=None, y=None):
    """
    where(condition, [x, y])

    Return elements, either from `x` or `y`, depending on `condition`.

    If only `condition` is given, return ``condition.nonzero()``.

    Parameters
    ----------
    condition : array_like, bool
        When True, yield `x`, otherwise yield `y`.
    x, y : array_like, optional
        Values from which to choose. `x` and `y` need to have the same
        shape as `condition`.

    Returns
    -------
    out : ndarray or tuple of ndarrays
        If both `x` and `y` are specified, the output array contains
        elements of `x` where `condition` is True, and elements from
        `y` elsewhere.

        If only `condition` is given, return the tuple
        ``condition.nonzero()``, the indices where `condition` is True.

    See Also
    --------
    nonzero, choose

    Notes
    -----
    If `x` and `y` are given and input arrays are 1-D, `where` is
    equivalent to::

        [xv if c else yv for (c,xv,yv) in zip(condition,x,y)]

    Examples
    --------
    >>> np.where([[True, False], [True, True]],
    ...          [[1, 2], [3, 4]],
    ...          [[9, 8], [7, 6]])
    array([[1, 8],
           [3, 4]])

    >>> np.where([[0, 1], [1, 0]])
    (array([0, 1]), array([1, 0]))

    >>> x = np.arange(9.).reshape(3, 3)
    >>> np.where( x > 5 )
    (array([2, 2, 2]), array([0, 1, 2]))
    >>> x[np.where( x > 3.0 )]               # Note: result is 1D.
    array([ 4.,  5.,  6.,  7.,  8.])
    >>> np.where(x < 5, x, -1)               # Note: broadcasting.
    array([[ 0.,  1.,  2.],
           [ 3.,  4., -1.],
           [-1., -1., -1.]])

    Find the indices of elements of `x` that are in `goodvalues`.

    >>> goodvalues = [3, 4, 7]
    >>> ix = np.in1d(x.ravel(), goodvalues).reshape(x.shape)
    >>> ix
    array([[False, False, False],
           [ True,  True, False],
           [False,  True, False]], dtype=bool)
    >>> np.where(ix)
    (array([1, 1, 2]), array([0, 1, 1]))

    """

    if not (bhary.check(condition) or bhary.check(x) or bhary.check(y)):
        return numpy.where(condition, x, y)

    if x is None or y is None:
        warnings.warn("Bohrium only supports where() when 'x' and 'y' are specified", stacklevel=2)
        return numpy.where(condition)

    # Let's find a non-scalar and make sure that non-scalars are Bohrium arrays
    t = None
    if not numpy.isscalar(condition):
        condition = array_create.array(condition)
        t = condition

    if not numpy.isscalar(x):
        x = array_create.array(x)
        t = x

    if not numpy.isscalar(y):
        y = array_create.array(y)
        t = y

    # All arguments are scalars
    if t is None:
        if condition:
            return x
        else:
            return y

    ret = array_create.zeros_like(t)
    ret += condition * x
    ret += ~condition * y
    return ret
Ejemplo n.º 15
0
def where(condition, x=None, y=None):
    """
    where(condition, [x, y])

    Return elements, either from `x` or `y`, depending on `condition`.

    If only `condition` is given, return ``condition.nonzero()``.

    Parameters
    ----------
    condition : array_like, bool
        When True, yield `x`, otherwise yield `y`.
    x, y : array_like, optional
        Values from which to choose. `x` and `y` need to have the same
        shape as `condition`.

    Returns
    -------
    out : ndarray or tuple of ndarrays
        If both `x` and `y` are specified, the output array contains
        elements of `x` where `condition` is True, and elements from
        `y` elsewhere.

        If only `condition` is given, return the tuple
        ``condition.nonzero()``, the indices where `condition` is True.

    See Also
    --------
    nonzero, choose

    Notes
    -----
    If `x` and `y` are given and input arrays are 1-D, `where` is
    equivalent to::

        [xv if c else yv for (c,xv,yv) in zip(condition,x,y)]

    Examples
    --------
    >>> np.where([[True, False], [True, True]],
    ...          [[1, 2], [3, 4]],
    ...          [[9, 8], [7, 6]])
    array([[1, 8],
           [3, 4]])

    >>> np.where([[0, 1], [1, 0]])
    (array([0, 1]), array([1, 0]))

    >>> x = np.arange(9.).reshape(3, 3)
    >>> np.where( x > 5 )
    (array([2, 2, 2]), array([0, 1, 2]))
    >>> x[np.where( x > 3.0 )]               # Note: result is 1D.
    array([ 4.,  5.,  6.,  7.,  8.])
    >>> np.where(x < 5, x, -1)               # Note: broadcasting.
    array([[ 0.,  1.,  2.],
           [ 3.,  4., -1.],
           [-1., -1., -1.]])

    Find the indices of elements of `x` that are in `goodvalues`.

    >>> goodvalues = [3, 4, 7]
    >>> ix = np.in1d(x.ravel(), goodvalues).reshape(x.shape)
    >>> ix
    array([[False, False, False],
           [ True,  True, False],
           [False,  True, False]], dtype=bool)
    >>> np.where(ix)
    (array([1, 1, 2]), array([0, 1, 1]))

    """
    if x is None or y is None:
        warnings.warn(
            "Bohrium only supports where() when 'x' and 'y' are specified",
            stacklevel=2)
        return numpy.where(condition)

    if not (bhary.check(condition) or bhary.check(x) or bhary.check(y)):
        return numpy.where(condition, x, y)

    # Make sure that non-scalars are Bohrium arrays
    if numpy.isscalar(condition):
        condition = bool(condition)
    else:
        condition = array_create.array(condition).astype("bool")

    if not numpy.isscalar(x):
        x = array_create.array(x)

    if not numpy.isscalar(y):
        y = array_create.array(y)

    # Shortcut if all arguments are scalars
    if all(numpy.isscalar(k) or k.size == 1 for k in (x, y, condition)):
        return x if condition else y

    # Find appropriate output type
    array_types = []
    scalar_types = []
    for v in (x, y):
        if numpy.isscalar(v):
            scalar_types.append(type(v))
        else:
            array_types.append(v.dtype)
    out_type = numpy.find_common_type(array_types, scalar_types)

    # Shortcut if input arrays are finite
    if ufuncs.isfinite(x).all() and ufuncs.isfinite(y).all():
        if numpy.isscalar(condition):
            res = condition * x + (not condition) * y
        else:
            res = condition * x + ufuncs.logical_not(condition) * y
        if numpy.isscalar(res):
            return out_type(res)
        else:
            return res.astype(out_type)

    # General case: use fancy indexing
    (condition, x,
     y), newshape = array_manipulation.broadcast_arrays(condition, x, y)
    ret = array_create.zeros(newshape, dtype=out_type)
    ret[condition] = x if numpy.isscalar(x) else x[condition]
    ret[~condition] = y if numpy.isscalar(y) else y[~condition]
    return ret
Ejemplo n.º 16
0
    def reduce(self, ary, axis=0, out=None):
        """
        A Bohrium Reduction
    Reduces `ary`'s dimension by len('axis'), by applying ufunc along the
    axes in 'axis'.

    Let :math:`ary.shape = (N_0, ..., N_i, ..., N_{M-1})`.  Then
    :math:`ufunc.reduce(ary, axis=i)[k_0, ..,k_{i-1}, k_{i+1}, .., k_{M-1}]` =
    the result of iterating `j` over :math:`range(N_i)`, cumulatively applying
    ufunc to each :math:`ary[k_0, ..,k_{i-1}, j, k_{i+1}, .., k_{M-1}]`.
    For a one-dimensional array, reduce produces results equivalent to:
    ::

     r = op.identity # op = ufunc
     for i in range(len(A)):
       r = op(r, A[i])
     return r

    For example, add.reduce() is equivalent to sum().

    Parameters
    ----------
    ary : array_like
        The array to act on.
    axis : None or int or tuple of ints, optional
        Axis or axes along which a reduction is performed.
        The default (`axis` = 0) is perform a reduction over the first
        dimension of the input array. `axis` may be negative, in
        which case it counts from the last to the first axis.

        .. versionadded:: 1.7.0

        If this is `None`, a reduction is performed over all the axes.
        If this is a tuple of ints, a reduction is performed on multiple
        axes, instead of a single axis or all the axes as before.

        For operations which are either not commutative or not associative,
        doing a reduction over multiple axes is not well-defined. The
        ufuncs do not currently raise an exception in this case, but will
        likely do so in the future.
    out : ndarray, optional
        A location into which the result is stored. If not provided, a
        freshly-allocated array is returned.

    Returns
    -------
    r : ndarraout      The reduced array. If `out` was supplied, `r` is a reference to it.

    Examples
    --------
    >>> np.multiply.reduce([2,3,5])
    30

    A multi-dimensional array example:

    >>> X = np.arange(8).reshape((2,2,2))
    >>> X
    array([[[0, 1],
            [2, 3]],
           [[4, 5],
            [6, 7]]])
    >>> np.add.reduce(X, 0)
    array([[ 4,  6],
           [ 8, 10]])
    >>> np.add.reduce(X) # confirm: default axis value is 0
    array([[ 4,  6],
           [ 8, 10]])
    >>> np.add.reduce(X, 1)
    array([[ 2,  4],
           [10, 12]])
    >>> np.add.reduce(X, 2)
    array([[ 1,  5],
           [ 9, 13]])
        """

        if out is not None:
            if ndarray.check(out):
                if not ndarray.check(ary):
                    ary = array_create.array(ary)
            else:
                if ndarray.check(ary):
                    ary = a.copy2numpy()
        #Let NumPy handle NumPy array reductions
        if not ndarray.check(ary):
            func = eval("np.%s.reduce" % self.info['name'])
            return func(ary, axis=axis, out=out)

        #Make sure that 'axis' is a list of dimensions to reduce
        if axis is None:
            axis = range(ary.ndim)#We reduce all dimensions
        elif np.isscalar(axis):
            axis = [axis]#We reduce one dimension
        else:
            axis = list(axis)#We reduce multiple dimensions

        #When reducting booleans numerically, we count the number of True values
        if (not self.info['name'].startswith("logical")) and dtype_equal(ary, np.bool):
            ary = array_create.array(ary, dtype=np.uint64)

        #Check for out of bounds and convert negative axis values
        if len(axis) > ary.ndim:
            raise ValueError("number of 'axises' to reduce is out of bounds")
        for i in xrange(len(axis)):
            if axis[i] < 0:
                axis[i] = ary.ndim+axis[i]
            if axis[i] >= ary.ndim:
                raise ValueError("'axis' is out of bounds")

        if len(axis) == 1:#One axis reduction we can handle directly
            axis = axis[0]

            #Find the output shape
            if ary.ndim == 1:
                shape = []
            else:
                shape = tuple(s for i, s in enumerate(ary.shape) if i != axis)
                if out is not None and out.shape != shape:
                    raise ValueError("output dimension mismatch expect "\
                                     "shape '%s' got '%s'"%(shape, out.shape))

            tmp = array_create.empty(shape, dtype=ary.dtype)
            target.reduce(self, get_bhc(tmp), get_bhc(ary), axis)

            if out is not None:
                out[...] = tmp
            else:
                out = tmp
            return out
        else:
            tmp1 = self.reduce(ary, axis[0])
            axis = [i-1 for i in axis[1:]]
            tmp2 = self.reduce(tmp1, axis)
            if out is not None:
                out[...] = tmp2
            else:
                out = tmp2
            return out
Ejemplo n.º 17
0
    def __call__(self, *args, **kwargs):
        args = list(args)

        #Check number of array arguments
        if len(args) != self.info['nop'] and len(args) != self.info['nop']-1:
            raise ValueError("invalid number of array arguments")

        #Lets make sure that 'out' is always a positional argument
        try:
            out = kwargs['out']
            del kwargs['out']
            if len(args) == self.info['nop']:
                raise ValueError("cannot specify 'out' as both a positional and keyword argument")
            args.append(out)
        except KeyError:
            pass

        #We do not support NumPy's exotic arguments
        for k, val in kwargs.iteritems():
            if val is not None:
                raise ValueError(
                    "Bohrium funcs doesn't support the '%s' argument" % str(k)
                )

        #Broadcast the args
        bargs = broadcast_arrays(*args)

        #Pop the output from the 'bargs' list
        out = None
        if len(args) == self.info['nop']:#output given
            out = args.pop()
            if bargs[-1].shape != out.shape:
                raise ValueError("non-broadcastable output operand with shape %s "
                                 "doesn't match the broadcast shape %s"%
                                 (str(args[-1].shape), str(out.shape)))
        out_shape = bargs[-1].shape

        #We use a tmp array if the in-/out-put has memory conflicts
        if out is not None:
            if overlap_conflict(out, *args):
                tmp = self.__call__(*args, **kwargs)
                assign(tmp, out)
                return out

        #Copy broadcasted array back to 'args' excluding scalars
        for i in xrange(len(args)):
            if not np.isscalar(args[i]):
                args[i] = bargs[i]

        if any([ndarray.check(a) for a in args]):
            if out is not None and not ndarray.check(out):
                raise NotImplementedError("For now, the output must be a Bohrium "\
                                          "array when the input arrays are")
        elif not ndarray.check(out):#All operands are regular NumPy arrays
            func = eval("np.%s"%self.info['name'])
            if out is not None:
                args.append(out)
            return func(*args)

        if len(args) > 2:
            raise ValueError("Bohrium do not support ufunc with more than two inputs")

        #Find the type signature
        (out_dtype, in_dtype) = _util.type_sig(self.info['name'], args)

        #Convert dtype of all inputs
        for i in xrange(len(args)):
            if not np.isscalar(args[i]) and not dtype_equal(args[i], in_dtype):
                tmp = array_create.empty_like(args[i], dtype=in_dtype)
                tmp[...] = args[i]
                args[i] = tmp

        #Insert the output array
        if out is None or not dtype_equal(out_dtype, out.dtype):
            args.insert(0, array_create.empty(out_shape, out_dtype))
        else:
            args.insert(0, out)

        #Convert 'args' to Bohrium-C arrays
        bhcs = []
        for arg in args:
            if np.isscalar(arg):
                bhcs.append(arg)
            elif ndarray.check(arg):
                bhcs.append(get_bhc(arg))
            else:
                arg = array_create.array(arg)
                bhcs.append(get_bhc(arg))

        #Some simple optimizations
        if self.info['name'] == "power" and np.isscalar(bhcs[2]) and bhcs[2] == 2:
            #Replace power of 2 with a multiplication
            target.ufunc(multiply, bhcs[0], bhcs[1], bhcs[1])
        else:
            target.ufunc(self, *bhcs)

        if out is None or dtype_equal(out_dtype, out.dtype):
            return args[0]
        else:#We need to convert the output type before returning
            assign(args[0], out)
            return out
        return out
Ejemplo n.º 18
0
def where(condition, x=None, y=None):
    """
    where(condition, [x, y])

    Return elements, either from `x` or `y`, depending on `condition`.

    If only `condition` is given, return ``condition.nonzero()``.

    Parameters
    ----------
    condition : array_like, bool
        When True, yield `x`, otherwise yield `y`.
    x, y : array_like, optional
        Values from which to choose. `x` and `y` need to have the same
        shape as `condition`.

    Returns
    -------
    out : ndarray or tuple of ndarrays
        If both `x` and `y` are specified, the output array contains
        elements of `x` where `condition` is True, and elements from
        `y` elsewhere.

        If only `condition` is given, return the tuple
        ``condition.nonzero()``, the indices where `condition` is True.

    See Also
    --------
    nonzero, choose

    Notes
    -----
    If `x` and `y` are given and input arrays are 1-D, `where` is
    equivalent to::

        [xv if c else yv for (c,xv,yv) in zip(condition,x,y)]

    Examples
    --------
    >>> np.where([[True, False], [True, True]],
    ...          [[1, 2], [3, 4]],
    ...          [[9, 8], [7, 6]])
    array([[1, 8],
           [3, 4]])

    >>> np.where([[0, 1], [1, 0]])
    (array([0, 1]), array([1, 0]))

    >>> x = np.arange(9.).reshape(3, 3)
    >>> np.where( x > 5 )
    (array([2, 2, 2]), array([0, 1, 2]))
    >>> x[np.where( x > 3.0 )]               # Note: result is 1D.
    array([ 4.,  5.,  6.,  7.,  8.])
    >>> np.where(x < 5, x, -1)               # Note: broadcasting.
    array([[ 0.,  1.,  2.],
           [ 3.,  4., -1.],
           [-1., -1., -1.]])

    Find the indices of elements of `x` that are in `goodvalues`.

    >>> goodvalues = [3, 4, 7]
    >>> ix = np.in1d(x.ravel(), goodvalues).reshape(x.shape)
    >>> ix
    array([[False, False, False],
           [ True,  True, False],
           [False,  True, False]], dtype=bool)
    >>> np.where(ix)
    (array([1, 1, 2]), array([0, 1, 1]))

    """
    if x is None or y is None:
        warnings.warn("Bohrium only supports where() when 'x' and 'y' are specified", stacklevel=2)
        return numpy.where(condition)

    if not (bhary.check(condition) or bhary.check(x) or bhary.check(y)):
        return numpy.where(condition, x, y)

    # Make sure that non-scalars are Bohrium arrays
    if numpy.isscalar(condition):
        condition = bool(condition)
    else:
        condition = array_create.array(condition).astype("bool")

    if not numpy.isscalar(x):
        x = array_create.array(x)

    if not numpy.isscalar(y):
        y = array_create.array(y)

    # Shortcut if all arguments are scalars
    if all(numpy.isscalar(k) or k.size == 1 for k in (x, y, condition)):
        return x if condition else y

    # Find appropriate output type
    array_types = []
    scalar_types = []
    for v in (x, y):
        if numpy.isscalar(v):
            scalar_types.append(type(v))
        else:
            array_types.append(v.dtype)
    out_type = numpy.find_common_type(array_types, scalar_types)

    # Shortcut if input arrays are finite
    if ufuncs.isfinite(x).all() and ufuncs.isfinite(y).all():
        if numpy.isscalar(condition):
            res = condition * x + (not condition) * y
        else:
            res = condition * x + ufuncs.logical_not(condition) * y
        if numpy.isscalar(res):
            return out_type(res)
        else:
            return res.astype(out_type)

    # General case: use fancy indexing
    (condition, x, y), newshape = array_manipulation.broadcast_arrays(condition, x, y)
    ret = array_create.zeros(newshape, dtype=out_type)
    ret[condition] = x if numpy.isscalar(x) else x[condition]
    ret[~condition] = y if numpy.isscalar(y) else y[~condition]
    return ret
Ejemplo n.º 19
0
    def __call__(self, *args, **kwargs):
        args = list(args)

        # Check number of array arguments
        if len(args) != self.info['nop'] and len(args) != self.info['nop']-1:
            raise ValueError("invalid number of array arguments")

        # Lets make sure that 'out' is always a positional argument
        try:
            out = kwargs['out']
            del kwargs['out']
            if len(args) == self.info['nop']:
                raise ValueError("cannot specify 'out' as both a positional and keyword argument")
            args.append(out)
        except KeyError:
            pass

        # We do not support NumPy's exotic arguments
        for k, val in kwargs.items():
            if val is not None:
                raise ValueError("Bohrium ufuncs doesn't support the '%s' argument" % str(k))

        # Broadcast the args
        bargs = broadcast_arrays(*args)

        # Pop the output from the 'bargs' list
        out = None
        if len(args) == self.info['nop']:
            out = args.pop()
            if bargs[-1].shape != out.shape:
                raise ValueError("non-broadcastable output operand with shape %s "
                                 "doesn't match the broadcast shape %s" %
                                 (str(args[-1].shape), str(out.shape)))
        out_shape = bargs[-1].shape

        # We use a tmp array if the in-/out-put has memory conflicts
        if out is not None:
            if overlap_conflict(out, *args):
                tmp = self.__call__(*args, **kwargs)
                assign(tmp, out)
                return out

        # Copy broadcasted array back to 'args' excluding scalars
        for i in range(len(args)):
            if not np.isscalar(args[i]):
                args[i] = bargs[i]

        if any([bhary.check(a) for a in args]):
            if out is not None and not bhary.check(out):
                raise NotImplementedError("For now, the output must be a Bohrium "\
                                          "array when the input arrays are")
        elif not bhary.check(out):
            # All operands are regular NumPy arrays
            func = eval("np.%s"%self.info['name'])
            if out is not None:
                args.append(out)
            return func(*args)

        if len(args) > 2:
            raise ValueError("Bohrium do not support ufunc with more than two inputs")

        # Find the type signature
        (out_dtype, in_dtype) = _util.type_sig(self.info['name'], args)

        # Convert dtype of all inputs
        for i in range(len(args)):
            if not np.isscalar(args[i]) and not dtype_equal(args[i], in_dtype):
                tmp = array_create.empty_like(args[i], dtype=in_dtype)
                tmp[...] = args[i]
                args[i] = tmp

        # Insert the output array
        if out is None or not dtype_equal(out_dtype, out.dtype):
            args.insert(0, array_create.empty(out_shape, out_dtype))
        else:
            args.insert(0, out)

        # Convert 'args' to Bohrium-C arrays
        bhcs = []
        for arg in args:
            if np.isscalar(arg):
                bhcs.append(arg)
            elif bhary.check(arg):
                bhcs.append(get_bhc(arg))
            else:
                arg = array_create.array(arg)
                bhcs.append(get_bhc(arg))

        # Some simple optimizations
        if self.info['name'] == "power" and np.isscalar(bhcs[2]) and bhcs[2] == 2:
            # Replace power of 2 with a multiplication
            target.ufunc(multiply, bhcs[0], bhcs[1], bhcs[1])
        else:
            target.ufunc(self, *bhcs)

        if out is None or dtype_equal(out_dtype, out.dtype):
            return args[0]
        else:
            # We need to convert the output type before returning
            assign(args[0], out)
            return out
        return out
Ejemplo n.º 20
0
    def reduce(self, ary, axis=0, out=None):
        """
        A Bohrium Reduction
        Reduces `ary`'s dimension by len('axis'), by applying ufunc along the
        axes in 'axis'.

        Let :math:`ary.shape = (N_0, ..., N_i, ..., N_{M-1})`.  Then
        :math:`ufunc.reduce(ary, axis=i)[k_0, ..,k_{i-1}, k_{i+1}, .., k_{M-1}]` =
        the result of iterating `j` over :math:`range(N_i)`, cumulatively applying
        ufunc to each :math:`ary[k_0, ..,k_{i-1}, j, k_{i+1}, .., k_{M-1}]`.
        For a one-dimensional array, reduce produces results equivalent to:

          r = op.identity # op = ufunc
          for i in range(len(A)):
              r = op(r, A[i])
          return r

        For example, add.reduce() is equivalent to sum().

        Parameters
        ----------
        ary : array_like
            The array to act on.
        axis : None or int or tuple of ints, optional
            Axis or axes along which a reduction is performed.
            The default (`axis` = 0) is perform a reduction over the first
            dimension of the input array. `axis` may be negative, in
            which case it counts from the last to the first axis.

            .. versionadded:: 1.7.0

            If this is `None`, a reduction is performed over all the axes.
            If this is a tuple of ints, a reduction is performed on multiple
            axes, instead of a single axis or all the axes as before.

            For operations which are either not commutative or not associative,
            doing a reduction over multiple axes is not well-defined. The
            ufuncs do not currently raise an exception in this case, but will
            likely do so in the future.
        out : ndarray, optional
            A location into which the result is stored. If not provided, a
            freshly-allocated array is returned.

        Returns
        -------
        r : ndarraout      The reduced array. If `out` was supplied, `r` is a reference to it.

        Examples
        --------
        >>> np.multiply.reduce([2,3,5])
        30

        A multi-dimensional array example:

        >>> X = np.arange(8).reshape((2,2,2))
        >>> X
        array([[[0, 1],
                [2, 3]],
               [[4, 5],
                [6, 7]]])
        >>> np.add.reduce(X, 0)
        array([[ 4,  6],
               [ 8, 10]])
        >>> np.add.reduce(X) # confirm: default axis value is 0
        array([[ 4,  6],
               [ 8, 10]])
        >>> np.add.reduce(X, 1)
        array([[ 2,  4],
               [10, 12]])
        >>> np.add.reduce(X, 2)
        array([[ 1,  5],
               [ 9, 13]])
        """

        if out is not None:
            if bhary.check(out):
                if not bhary.check(ary):
                    ary = array_create.array(ary)
            else:
                if bhary.check(ary):
                    ary = ary.copy2numpy()

        # Let NumPy handle NumPy array reductions
        if not bhary.check(ary):
            func = eval("np.%s.reduce" % self.info['name'])
            return func(ary, axis=axis, out=out)

        # Make sure that 'axis' is a sorted list of dimensions to reduce
        if axis is None:
            # We reduce all dimensions
            axis = range(ary.ndim)
        elif np.isscalar(axis):
            # We reduce one dimension
            axis = [axis]
        else:
            # We reduce multiple dimensions
            axis = list(axis)

        if len(axis) != len(set(axis)):
            raise ValueError("duplicate value in 'axis'")
        axis = sorted(axis, reverse=True)

        # When reducing booleans numerically, we count the number of True values
        if (not self.info['name'].startswith("logical")) and dtype_equal(ary, np.bool):
            ary = array_create.array(ary, dtype=np.uint64)

        # Check for out of bounds and convert negative axis values
        if len(axis) > ary.ndim:
            raise ValueError("number of 'axes' to reduce is out of bounds")
        for i in range(len(axis)):
            if axis[i] < 0:
                axis[i] = ary.ndim + axis[i]
            if axis[i] >= ary.ndim:
                raise ValueError("'axis' is out of bounds")

        if len(axis) == 1:
            # One axis reduction we can handle directly
            axis = axis[0]

            # Find the output shape
            if ary.ndim == 1:
                shape = []
            else:
                shape = tuple(s for i, s in enumerate(ary.shape) if i != axis)
                if out is not None and out.shape != shape:
                    raise ValueError("output dimension mismatch expect "\
                                     "shape '%s' got '%s'" % (shape, out.shape))

            tmp = array_create.empty(shape, dtype=ary.dtype)

            # NumPy compatibility: when the axis dimension size is zero NumPy just returns the neutral value
            if ary.shape[axis] == 0:
                tmp[...] = getattr(getattr(np, self.info['name']), "identity")
            else:
                target.reduce(self, get_bhc(tmp), get_bhc(ary), axis)

            if out is not None:
                out[...] = tmp
            else:
                out = tmp

            return out
        else:
            # Let's reduce the first axis
            ary = self.reduce(ary, axis[0])
            # Then we reduce the rest of the axes
            axis = axis[1:]
            ary = self.reduce(ary, axis)
            # Finally, we may have to copy the result to 'out'
            if out is not None:
                out[...] = ary
            else:
                out = ary
            return out