示例#1
0
 def _prep(self, order='C'):
     M, N, K = 2, 3, 4
     rng = nlcpy.random.default_rng(0)
     a = nlcpy.asarray(rng.random((M, K), dtype='f8'), order=order)
     b = nlcpy.asarray(rng.random((K, N), dtype='f8'), order=order)
     c = nlcpy.empty((M, N), dtype='f8', order=order)
     return M, N, K, a, b, c
示例#2
0
def test_fft_with_order(dtype, order, fft):
    # Check that FFT/IFFT produces identical results for C, Fortran and
    # non contiguous arrays
    rng = np.random.RandomState(42)
    # X = rng.rand(8, 7, 13).astype(dtype, copy=False)
    X = rng.rand((8, 7, 13)).astype(dtype, copy=False)
    # See discussion in pull/14178
    _tol = 8.0 * np.sqrt(np.log2(X.size)) * np.finfo(X.dtype).eps
    if order == 'F':
        # Y = np.asfortranarray(X)
        Y = np.asarray(X, order='F')
    else:
        # Make a non contiguous array
        # #Y = X[::-1]
        # #X = np.ascontiguousarray(X[::-1])
        Y = X[:-1]
        X = np.asarray(X[:-1], order='C')

    if fft.__name__.endswith('fft'):
        for axis in range(3):
            X_res = fft(X, axis=axis)
            Y_res = fft(Y, axis=axis)
            assert_allclose(X_res, Y_res, atol=_tol, rtol=_tol)
    elif fft.__name__.endswith(('fft2', 'fftn')):
        axes = [(0, 1), (1, 2), (0, 2)]
        if fft.__name__.endswith('fftn'):
            axes.extend([(0, ), (1, ), (2, ), None])
        for ax in axes:
            X_res = fft(X, axes=ax)
            Y_res = fft(Y, axes=ax)
            assert_allclose(X_res, Y_res, atol=_tol, rtol=_tol)
    else:
        raise ValueError()
示例#3
0
def _lange(x, norm, axis):
    order = 'F' if x.flags.f_contiguous and not x.flags.c_contiguous else 'C'
    dtype = 'f' if x.dtype.char in 'fF' else 'd'
    if x.size == 0:
        shape = [x.shape[i] for i in set(range(x.ndim)) - set(axis)]
        return nlcpy.zeros(shape, dtype=dtype)
    if norm in (None, 'fro', 'f'):
        if x.dtype.kind == 'c':
            x = abs(x)
        return nlcpy.sqrt(nlcpy.sum(x * x, axis=axis))
    if norm == nlcpy.inf:
        norm = 'I'
    else:
        norm = '1'
    lwork = x.shape[0] if norm == 'I' else 1
    x = nlcpy.asarray(nlcpy.moveaxis(x, (axis[0], axis[1]), (0, 1)), order='F')
    y = nlcpy.empty(x.shape[2:], dtype=dtype, order='F')
    work = nlcpy.empty(lwork, dtype=dtype)
    fpe = request._get_fpe_flag()
    args = (
        ord(norm),
        x._ve_array,
        y._ve_array,
        work._ve_array,
        veo.OnStack(fpe, inout=veo.INTENT_OUT),
    )

    request._push_and_flush_request(
        'nlcpy_norm',
        args,
    )

    return nlcpy.asarray(y, order=order)
示例#4
0
    def wrap_func(*args, **kwargs):
        is_out = False
        try:
            return func(*args, **kwargs)
        except NotImplementedError:
            f = getattr(numpy, func.__name__)
            # retrieve input ndarrays of NLCPy from VE
            largs = list(args)
            for i, _l in enumerate(largs):
                if isinstance(_l, nlcpy.ndarray):
                    largs[i] = _l.get()
            for k, v in kwargs.items():
                if isinstance(v, nlcpy.ndarray):
                    kwargs[k] = v.get()
                if k == 'out':
                    is_out = True
                    in_out = v

            # call NumPy function
            ret = f(*largs, **kwargs)
            # transfer the return values to VE
            if isinstance(ret, numpy.ndarray) or \
                    numpy.isscalar(ret) and numpy.dtype(type(ret)).char in '?iIlLfFdD':
                vp_ret = nlcpy.asarray(ret)
                if is_out:
                    in_out[...] = vp_ret
                return vp_ret
            elif isinstance(ret, numpy.lib.npyio.NpzFile):
                return nlcpy.NpzFile(ret)
            elif isinstance(ret, dict):
                for key, val in ret.items():
                    ret[key] = nlcpy.asarray(val)
                return ret
            elif isinstance(ret, (list, tuple)):
                vpp = []
                for x in ret:
                    if isinstance(x, numpy.ndarray) is False:
                        if numpy.any(isinstance(x, numpy.ndarray)) is True:
                            b_ret = [nlcpy.asarray(i) for i in x]
                        else:
                            b_ret = x
                    else:
                        b_ret = nlcpy.asarray(x)
                    vpp.append(b_ret)
                vp_ret = vpp
                if isinstance(ret, tuple):
                    vp_ret = tuple(vp_ret)
                return vp_ret
            else:
                return ret
示例#5
0
 def test_eigvals(self, dtype, order):
     a = nlcpy.asarray(testing.shaped_random(self.shape, nlcpy, dtype), order=order)
     args = dict()
     args["a"] = a
     w1 = nlcpy.linalg.eigvals(**args)
     w2, v = nlcpy.linalg.eig(**args)
     numpy.testing.assert_allclose(w1, w2, atol=1e-12, rtol=1e-12)
示例#6
0
文件: count.py 项目: SX-Aurora/nlcpy
def count_nonzero(a, axis=None, keepdims=False):
    """Counts the number of non-zero values in the array ``a``.

    The word "non-zero" is in reference to the Python 2.x built-in method
    ``__nonzero__()`` (renamed ``__bool__()`` in Python 3.x) of Python objects that
    tests an object's "truthfulness". For example, any number is considered truthful
    if it is nonzero, whereas any string is considered truthful if it is not the empty
    string. Thus, this function (recursively) counts how many elements in a (and in
    sub-arrays thereof) have their ``__nonzero__()`` or ``__bool__()`` method evaluated
    to ``True``.

    Parameters
    ----------
    a : array_like
        The array for which to count non-zeros.
    axis : int or tuple, optional
        Axis or tuple of axes along which to count non-zeros. Default is None, meaning
        that non-zeros will be counted along a flattened version of ``a``.
    keepdims : bool, optional
        If this is set to True, the axes that are counted are left in the result as
        dimensions with size one. With this option, the result will broadcast correctly
        against the input array.

    Returns
    -------
    count : int or array of int
        Number of non-zero values in the array along a given axis.
        Otherwise, the total number of non-zero values in the array is returned.

    See Also
    --------
    nonzero : Returns the indices of the elements that are non-zero.

    Examples
    --------
    >>> import nlcpy as vp
    >>> vp.count_nonzero(vp.eye(4))
    array(4)
    >>> a = vp.array([[0, 1, 7, 0], [3, 0, 2, 19]])
    >>> vp.count_nonzero(a)
    array(5)
    >>> vp.count_nonzero(a, axis=0)
    array([1, 1, 2, 1])
    >>> vp.count_nonzero(a, axis=1)
    array([2, 3])
    >>> vp.count_nonzero(a, axis=1, keepdims=True)
    array([[2],
           [3]])
    """
    a = nlcpy.asarray(a).astype('?', copy=False)
    return a.sum(axis=axis, dtype=nlcpy.intp, keepdims=keepdims)
示例#7
0
文件: ufunc.py 项目: SX-Aurora/nlcpy
def _precheck_func_for_ufunc(
        self,
        args,
        kw,
        impl,
        name,
        op,
        type_check,
        accept_error):
    kw[name] = nlcpy
    nlcpy_result, nlcpy_error, nlcpy_msg, nlcpy_tb = \
        helper._call_func(self, impl, args, kw)

    kw[name] = numpy
    numpy_result, numpy_error, numpy_msg, numpy_tb = \
        helper._call_func(self, impl, args, kw)

    if nlcpy_msg is not None:
        nlcpy_msg = re.sub(r'nlcpy', "numpy", nlcpy_msg)

    if nlcpy_error or numpy_error:
        helper._check_nlcpy_numpy_error(self, nlcpy_error, nlcpy_msg,
                                        nlcpy_tb, numpy_error, numpy_msg,
                                        numpy_tb, accept_error=accept_error)
        return None, None

    if not isinstance(nlcpy_result, (tuple, list)):
        nlcpy_result = nlcpy_result,
    if not isinstance(numpy_result, (tuple, list)):
        numpy_result = numpy_result,

    # shape check
    for numpy_r, nlcpy_r in zip(numpy_result, nlcpy_result):
        assert numpy.asarray(numpy_r).shape == nlcpy.asarray(nlcpy_r).shape

    # type check
    if type_check:
        for numpy_r, nlcpy_r in zip(numpy_result, nlcpy_result):
            if type(numpy_r) is not numpy.ndarray:
                numpy_r = numpy.array(numpy_r)
            if type(nlcpy_r) is not nlcpy.ndarray:
                nlcpy_r = nlcpy.array(numpy_r)
            if numpy_r.dtype != nlcpy_r.dtype:
                msg = ['\n']
                msg.append(' numpy.dtype: {}'.format(numpy_r.dtype))
                msg.append(' nlcpy.dtype: {}'.format(nlcpy_r.dtype))
                raise AssertionError('\n'.join(msg))

    return nlcpy_result, numpy_result
示例#8
0
    def test_reshape_contiguity(self):
        shape_init, shape_final = self.shape_in_out

        a_nlcpy = testing.shaped_arange(shape_init, xp=nlcpy)
        a_nlcpy = nlcpy.asarray(a_nlcpy, order=self.order_init)
        b_nlcpy = a_nlcpy.reshape(shape_final, order=self.order_reshape)

        a_numpy = testing.shaped_arange(shape_init, xp=numpy)
        a_numpy = numpy.asarray(a_numpy, order=self.order_init)
        b_numpy = a_numpy.reshape(shape_final, order=self.order_reshape)

        assert b_nlcpy.flags.f_contiguous == b_numpy.flags.f_contiguous
        assert b_nlcpy.flags.c_contiguous == b_numpy.flags.c_contiguous

        testing.assert_array_equal(b_nlcpy.strides, b_numpy.strides)
        testing.assert_array_equal(b_nlcpy, b_numpy)
示例#9
0
    def test_array_function(self):
        a = numpy.random.randn(100, 100)
        a_cpu = numpy.asarray(a)
        a_ve = nlcpy.asarray(a)

        # The numpy call for both CPU and ve arrays is intentional to test the
        # __array_function__ protocol
        qr_cpu = numpy.linalg.qr(a_cpu)
        qr_ve = numpy.linalg.qr(a_ve)

        if isinstance(qr_cpu, tuple):
            for b_cpu, b_ve in zip(qr_cpu, qr_ve):
                self.assertEqual(b_cpu.dtype, b_ve.dtype)
                nlcpy.testing.assert_allclose(b_cpu, b_ve, atol=1e-4)
        else:
            self.assertEqual(qr_cpu.dtype, qr_ve.dtype)
            nlcpy.testing.assert_allclose(qr_cpu, qr_ve, atol=1e-4)
示例#10
0
def full_like(a, fill_value, dtype=None, order='K', subok=False, shape=None):
    """Returns a full array with the same shape and type as a given array.

    Parameters
    ----------
    a : array_like
        The shape and dtype of *a* define these same attributes of the returned array.
    fill_value : scalar
        Fill value.
    dtype : dtype, optional
        Overrides the data type of the result.
    order : {'C', 'F', 'A', or 'K'}, optional
        Overrides the memory layout of the result. 'C' means C-order, 'F' means F-order,
        'A' means 'F' if *a* is Fortran contiguous, 'C' otherwise. 'K' means match the
        layout of *a* as closely as possible.
    subok : bool, optional
        Not implemented.
    shape : int or sequence of ints, optional
        Overrides the shape of the result. If order='K' and the number of dimensions is
        unchanged, will try to keep order, otherwise, order='C' is implied.

    Returns
    -------
    out : ndarray
        Array of *fill_value* with the same shape and type as *a*.

    See Also
    --------
    empty_like : Returns a new array with the same shape
        and type as a given array.
    ones_like : Returns an array of ones with the same shape
        and type as a given array.
    zeros_like : Returns an array of zeros with the same shape
        and type as a given array.
    full : Returns a new array of given shape and type,
        filled with fill_value.

    Examples
    --------
    >>> import nlcpy as vp
    >>> x = vp.arange(6, dtype=int)
    >>> vp.full_like(x, 1)
    array([1, 1, 1, 1, 1, 1])
    >>> vp.full_like(x, 0.1)
    array([0, 0, 0, 0, 0, 0])
    >>> vp.full_like(x, 0.1, dtype=vp.double)
    array([0.1, 0.1, 0.1, 0.1, 0.1, 0.1])
    >>> vp.full_like(x, vp.nan, dtype=vp.double)
    array([nan, nan, nan, nan, nan, nan])
    >>> y = vp.arange(6, dtype=vp.double)
    >>> vp.full_like(y, 0.1)
    array([0.1, 0.1, 0.1, 0.1, 0.1, 0.1])

    """
    if subok is not False:
        raise NotImplementedError('subok in full_like is not implemented yet.')

    a = nlcpy.asanyarray(a)
    if shape is None:
        shape = a.shape
    if dtype is None:
        dtype = a.dtype
    else:
        dtype = nlcpy.dtype(dtype)

    if numpy.dtype(dtype).kind == 'V':
        raise NotImplementedError(
            'void dtype in full_like is not implemented yet.')

    if order is None or order in 'kKaA':
        if a._f_contiguous and not a._c_contiguous:
            order = 'F'
        else:
            order = 'C'

    if numpy.isscalar(fill_value):
        if numpy.iscomplex(fill_value):
            if dtype in ('complex64', 'complex128'):
                pass
            else:
                fill_value = numpy.real(fill_value)
                warnings.warn(
                    'Casting complex values to real discards the imaginary part',
                    numpy.ComplexWarning,
                    stacklevel=2)
        out = nlcpy.ndarray(shape=shape, dtype=dtype, order=order)
        out.fill(fill_value)

    elif fill_value is None:
        raise NotImplementedError('fill_value in nlcpy.full_like is None')

    else:
        fill_value = nlcpy.asarray(fill_value)
        out = nlcpy.array(nlcpy.broadcast_to(fill_value, shape=shape),
                          dtype=dtype,
                          order=order)

    return out
示例#11
0
def full(shape, fill_value, dtype=None, order='C'):
    """Returns a new array of given shape and type, filled with *fill_value*.

    Parameters
    ----------
    shape : int or sequence of ints
        Shape of the new array, e.g., ``(2, 3)`` or ``2``.
    fill_value : scalar
        Fill value.
    dtype : dtype, optional
        The desired dtype for the array, e.g, ``nlcpy.int64``.
        Default is ``nlcpy.float64``.
    order : {'C', 'F'}, optional
        Whether to store multidimensional data in C- or Fortran-contiguous (row- or
        column-wise) order in memory.

    Returns
    -------
    out : ndarray
        Array of *fill_value* with the given shape, dtype, and order.

    See Also
    --------
    full_like : Returns a full array with the same shape
        and type as a given array.
    empty : Returns a new array of given shape and type,
        without initializing entries.
    ones : Returns a new array of given shape and type,
        filled with ones.
    zeros : Returns a new array of given shape and type,
        filled with zeros.

    Examples
    --------
    >>> import nlcpy as vp
    >>> vp.full((2, 2), vp.inf)
    array([[inf, inf],
           [inf, inf]])
    >>> vp.full((2, 2), 10)
    array([[10, 10],
           [10, 10]])

    """
    if numpy.dtype(dtype).kind == 'V':
        raise NotImplementedError('void dtype in full is not implemented yet.')

    if dtype is None:
        dtype = numpy.result_type(fill_value)
    else:
        dtype = nlcpy.dtype(dtype)

    if numpy.isscalar(fill_value):
        if numpy.iscomplex(fill_value):
            if dtype in ('complex64', 'complex128'):
                pass
            else:
                fill_value = numpy.real(fill_value)
                warnings.warn(
                    'Casting complex values to real discards the imaginary part',
                    numpy.ComplexWarning,
                    stacklevel=2)
        out = nlcpy.ndarray(shape=shape, dtype=dtype, order=order)
        out.fill(fill_value)

    elif fill_value is None:
        raise NotImplementedError('fill_value in nlcpy.full is None')

    else:
        fill_value = nlcpy.asarray(fill_value)
        out = nlcpy.array(nlcpy.broadcast_to(fill_value, shape=shape),
                          dtype=dtype,
                          order=order)

    return out
示例#12
0
def where(condition, x=None, y=None):
    """Returns elements chosen from *x* or *y* depending on *condition*.

    Note
    ----
    When only condition is provided, this function is a shorthand for
    ``nlcpy.asarray(condition).nonzero()``. Using nonzero directly should be preferred,
    as it behaves correctly for subclasses. The rest of this documentation covers only
    the case where all three arguments are provided.

    Parameters
    ----------
    condition : array_like, bool
        Where True, yield *x*, otherwise yield *y*.
    x, y : array_like
        Values from which to choose. *x*, *y* and *condition* need to be broadcastable to
        some shape.

    Returns
    -------
    out : ndarray
        An array with elements from *x* where *condition* is True, and elements from *y*
        elsewhere.

    Note
    ----
    If all the arrays are 1-D, :func:`where` is equivalent to::

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

    See Also
    --------
    nonzero : Returns the indices of the elements
        that are non-zero.

    Examples
    --------
    >>> import nlcpy as vp
    >>> a = vp.arange(10)
    >>> a
    array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    >>> vp.where(a < 5, a, 10*a)
    array([ 0,  1,  2,  3,  4, 50, 60, 70, 80, 90])

    This can be used on multidimensional arrays too:

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

    The shapes of x, y, and the condition are broadcast together:

    >>> x = vp.arange(3).reshape([3,1])
    >>> y = vp.arange(4).reshape([1,4])
    >>> vp.where(x < y, x, 10 + y)  # both x and 10+y are broadcast
    array([[10,  0,  0,  0],
           [10, 11,  1,  1],
           [10, 11, 12,  2]])
    >>> a = vp.array([[0, 1, 2],
    ...               [0, 2, 4],
    ...               [0, 3, 6]])
    >>> vp.where(a < 4, a, -1)  # -1 is broadcast
    array([[ 0,  1,  2],
           [ 0,  2, -1],
           [ 0,  3, -1]])

    """

    if condition is None:
        condition = False
    arr = nlcpy.asarray(condition)
    if x is None and y is None:
        return nlcpy.nonzero(arr)

    if x is None or y is None:
        raise ValueError("either both or neither of x and y should be given")

    if not isinstance(x, nlcpy.ndarray):
        x = numpy.asarray(x)
    if not isinstance(y, nlcpy.ndarray):
        y = numpy.asarray(y)
    ret_type = numpy.result_type(x, y)

    arr_x = nlcpy.asarray(x, dtype=ret_type)
    arr_y = nlcpy.asarray(y, dtype=ret_type)

    if arr.dtype != bool:
        arr = (arr != 0)

    values, shape = core._broadcast_core((arr, arr_x, arr_y))
    ret = nlcpy.ndarray(shape=shape, dtype=ret_type)
    request._push_request(
        "nlcpy_where",
        "indexing_op",
        (ret, values[0], values[1], values[2]),
    )

    return ret
示例#13
0
def insert(arr, obj, values, axis=None):
    """Inserts values along the given axis before the given indices.

    Parameters
    ----------
    arr : array_like
        Input array.
    obj : int, slice or sequence of ints
        Object that defines the index or indices before which values is inserted.
        Support for multiple insertions when obj is a single scalar or a sequence
        with one element (similar to calling insert multiple times).
    values : array_like
        Values to insert into arr. If the type of values is different from that of
        arr, values is converted to the type of arr. values should be shaped so that
        arr[...,obj,...] = values is legal.
    axis : int, optional
        Axis along which to insert values. If axis is None then arr is flattened
        first.

    Returns
    -------
    out : ndarray
        A copy of arr with values inserted. Note that insert does not occur in-place:
        a new array is returned. If axis is None, out is a flattened array.

    Note:
        Note that for higher dimensional inserts obj=0 behaves very different from
        obj=[0] just like arr[:,0,:] = values is different from arr[:,[0],:] = values.

    See Also
    --------
    append : Appends values to the end of an array.
    concatenate : Joins a sequence of arrays along an existing axis.
    delete : Returns a new array with sub-arrays along an axis deleted.

    Examples
    --------
    >>> import nlcpy as vp
    >>> from nlcpy import testing
    >>> a = vp.array([[1, 1], [2, 2], [3, 3]])
    >>> a
    array([[1, 1],
           [2, 2],
           [3, 3]])
    >>> vp.insert(a, 1, 5)
    array([1, 5, 1, 2, 2, 3, 3])
    >>> vp.insert(a, 1, 5, axis=1)
    array([[1, 5, 1],
           [2, 5, 2],
           [3, 5, 3]])

    Difference between sequence and scalars:

    >>> vp.insert(a, [1], [[1],[2],[3]], axis=1)
    array([[1, 1, 1],
           [2, 2, 2],
           [3, 3, 3]])
    >>> vp.testing.assert_array_equal(
    ...                vp.insert(a, 1, [1, 2, 3], axis=1),
    ...                vp.insert(a, [1], [[1],[2],[3]], axis=1))
    >>> b = a.flatten()
    >>> b
    array([1, 1, 2, 2, 3, 3])
    >>> vp.insert(b, [2, 2], [5, 6])
    array([1, 1, 5, 6, 2, 2, 3, 3])
    >>> vp.insert(b, slice(2, 4), [5, 6])
    array([1, 1, 5, 2, 6, 2, 3, 3])
    >>> vp.insert(b, [2, 2], [7.13, False]) # type casting
    array([1, 1, 7, 0, 2, 2, 3, 3])
    >>> x = vp.arange(8).reshape(2, 4)
    >>> idx = (1, 3)
    >>> vp.insert(x, idx, 999, axis=1)
    array([[  0, 999,   1,   2, 999,   3],
           [  4, 999,   5,   6, 999,   7]])

    """
    a = nlcpy.asarray(arr)
    if axis is None:
        if a.ndim != 1:
            a = a.ravel()
        axis = 0
    elif isinstance(axis, nlcpy.ndarray) or isinstance(axis, numpy.ndarray):
        axis = int(axis)
    elif not isinstance(axis, int):
        raise TypeError("an integer is required "
                        "(got type {0})".format(type(axis).__name__))

    if axis < -a.ndim or axis >= a.ndim:
        raise nlcpy.AxisError(
            "axis {0} is out of bounds for array of dimension {1}".format(axis, a.ndim))

    if axis < 0:
        axis += a.ndim

    if type(obj) is slice:
        start, stop, step = obj.indices(a.shape[axis])
        obj = nlcpy.arange(start, stop, step)
    else:
        obj = nlcpy.array(obj)
        if obj.dtype.char == '?':
            warnings.warn(
                "in the future insert will treat boolean arrays and "
                "array-likes as a boolean index instead of casting it to "
                "integer", FutureWarning, stacklevel=3)
        elif obj.dtype.char in 'fdFD':
            if obj.size == 1:
                raise TypeError(
                    "slice indices must be integers or "
                    "None or have an __index__ method")
            elif obj.size > 0:
                raise IndexError(
                    'arrays used as indices must be of integer (or boolean) type')
        elif obj.dtype.char in 'IL':
            if obj.size == 1:
                objval = obj[()] if obj.ndim == 0 else obj[0]
                if objval > a.shape[axis]:
                    raise IndexError(
                        "index {0} is out of bounds for axis {1} with size {2}".format(
                            objval, axis, a.shape[axis]))
            else:
                tmp = 'float64' if obj.dtype.char == 'L' else 'int64'
                raise UFuncTypeError(
                    "Cannot cast ufunc 'add' output from dtype('{0}') to "
                    "dtype('{1}') with casting rule 'same_kind'".format(tmp, obj.dtype))
        obj = obj.astype('l')
        if obj.ndim > 1:
            raise ValueError(
                "index array argument obj to insert must be one dimensional or scalar")

    if obj.ndim == 0:
        if obj > a.shape[axis] or obj < -a.shape[axis]:
            raise IndexError(
                "index {0} is out of bounds for axis {1} with size {2}".format(
                    obj[()] if obj > 0 else obj[()] + a.shape[axis],
                    axis, a.shape[axis]))

    newshape = list(a.shape)
    if obj.size == 1:
        values = nlcpy.array(values, copy=False, ndmin=a.ndim, dtype=a.dtype)
        if obj.ndim == 0:
            values = nlcpy.moveaxis(values, 0, axis)
        newshape[axis] += values.shape[axis]
        obj = nlcpy.array(nlcpy.broadcast_to(obj, values.shape[axis]))
        val_shape = list(a.shape)
        val_shape[axis] = values.shape[axis]
        values = nlcpy.broadcast_to(values, val_shape)
    else:
        newshape[axis] += obj.size
        values = nlcpy.array(values, copy=False, ndmin=a.ndim, dtype=a.dtype)
        val_shape = list(a.shape)
        val_shape[axis] = obj.size
        values = nlcpy.broadcast_to(values, val_shape)

    out = nlcpy.empty(newshape, dtype=a.dtype)
    work = nlcpy.zeros(obj.size + out.shape[axis] + 2, dtype='l')
    work[-1] = -1
    request._push_request(
        'nlcpy_insert',
        'manipulation_op',
        (a, obj, values, out, axis, work)
    )
    if work[-1] != -1:
        raise IndexError(
            "index {0} is out of bounds for axis {1} with size {2}"
            .format(obj[work[-1]], axis, out.shape[axis]))
    return out
示例#14
0
def qr(a, mode='reduced'):
    """Computes the qr factorization of a matrix.

    Factor the matrix *a* as *qr*, where *q* is orthonormal and *r* is upper-triangular.

    Parameters
    ----------
    a : (M, N) array_like
        Matrix to be factored.
    mode : {'reduced', 'complete', 'r', 'raw', 'full', 'economic'}, optional
        If K = min(M, N), then

        - 'reduced' : returns q, r with dimensions (M, K), (K, N) (default)
        - 'complete' : returns q, r with dimensions (M, M), (M, N)
        - 'r' : returns r only with dimensions (K, N)
        - 'raw' : returns h, tau with dimensions (N, M), (K,)
        - 'full' or 'f' : alias of 'reduced', deprecated
        - 'economic' or 'e' : returns h from 'raw', deprecated.

    Returns
    -------
    q : ndarray, optional
        A matrix with orthonormal columns. When mode = 'complete' the result is an
        orthogonal/unitary matrix depending on whether or not a is real/complex. The
        determinant may be either +/- 1 in that case.
    r : ndarray, optional
        The upper-triangular matrix.
    (h, tau) : ndarray, optional
        The array h contains the Householder reflectors that generate q along with r. The
        tau array contains scaling factors for the reflectors. In the deprecated
        'economic' mode only h is returned.

    Note
    ----
    This is an interface to the LAPACK routines ``dgeqrf``, ``zgeqrf``, ``dorgqr``,
    and ``zungqr``.

    For more information on the qr factorization, see for example:
    https://en.wikipedia.org/wiki/QR_factorization

    Note that when 'raw' option is specified the returned arrays are of type "float64" or
    "complex128" and the h array is transposed to be FORTRAN compatible.

    Examples
    --------
    >>> import numpy as np
    >>> import nlcpy as vp
    >>> from nlcpy import testing
    >>> a = vp.random.randn(9, 6)
    >>> q, r = vp.linalg.qr(a)
    >>> vp.testing.assert_allclose(a, vp.dot(q, r))  # a does equal qr
    >>> r2 = vp.linalg.qr(a, mode='r')
    >>> r3 = vp.linalg.qr(a, mode='economic')
    >>> # mode='r' returns the same r as mode='full'
    >>> vp.testing.assert_allclose(r, r2)
    >>> # But only triu parts are guaranteed equal when mode='economic'
    >>> vp.testing.assert_allclose(r, np.triu(r3[:6,:6], k=0))

    Example illustrating a common use of qr: solving of least squares problems

    What are the least-squares-best *m* and *y0* in ``y = y0 + mx`` for the following
    data: {(0,1), (1,0), (1,2), (2,1)}. (Graph the points and you’ll see that it should
    be y0 = 0, m = 1.) The answer is provided by solving the over-determined matrix
    equation ``Ax = b``, where::

        A = array([[0, 1], [1, 1], [1, 1], [2, 1]])
        x = array([[y0], [m]])
        b = array([[1], [0], [2], [1]])

    If A = qr such that q is orthonormal (which is always possible via Gram-Schmidt),
    then ``x = inv(r) * (q.T) * b``. (In practice, however, we simply use :func:`lstsq`.)

    >>> A = vp.array([[0, 1], [1, 1], [1, 1], [2, 1]])
    >>> A
    array([[0, 1],
           [1, 1],
           [1, 1],
           [2, 1]])
    >>> b = vp.array([1, 0, 2, 1])
    >>> q, r = vp.linalg.qr(A)
    >>> p = vp.dot(q.T, b)
    >>> vp.dot(vp.linalg.inv(r), p)
    array([1.1102230246251565e-16, 1.0000000000000002e+00])

    """
    if mode not in ('reduced', 'complete', 'r', 'raw'):
        if mode in ('f', 'full'):
            msg = "".join(
                ("The 'full' option is deprecated in favor of 'reduced'.\n",
                 "For backward compatibility let mode default."))
            warnings.warn(msg, DeprecationWarning, stacklevel=3)
            mode = 'reduced'
        elif mode in ('e', 'economic'):
            msg = "The 'economic' option is deprecated."
            warnings.warn(msg, DeprecationWarning, stacklevel=3)
            mode = 'economic'
        else:
            raise ValueError("Unrecognized mode '%s'" % mode)

    a = nlcpy.asarray(a)
    util._assertRank2(a)
    if a.dtype == 'F':
        dtype = 'D'
        a_dtype = 'F'
    elif a.dtype == 'D':
        dtype = 'D'
        a_dtype = 'D'
    elif a.dtype == 'f':
        dtype = 'd'
        a_dtype = 'f'
    else:
        dtype = 'd'
        a_dtype = 'd'

    m, n = a.shape
    if a.size == 0:
        if mode == 'reduced':
            return nlcpy.empty((m, 0), a_dtype), nlcpy.empty((0, n), a_dtype)
        elif mode == 'complete':
            return nlcpy.identity(m, a_dtype), nlcpy.empty((m, n), a_dtype)
        elif mode == 'r':
            return nlcpy.empty((0, n), a_dtype)
        elif mode == 'raw':
            return nlcpy.empty((n, m), dtype), nlcpy.empty((0, ), dtype)
        else:
            return nlcpy.empty((m, n), a_dtype), nlcpy.empty((0, ), a_dtype)

    a = nlcpy.asarray(a, dtype=dtype, order='F')
    k = min(m, n)
    if mode == 'complete':
        if m > n:
            x = nlcpy.empty((m, m), dtype=dtype, order='F')
            x[:m, :n] = a
            a = x
        r_shape = (m, n)
    elif mode in ('r', 'reduced', 'economic'):
        r_shape = (k, n)
    else:
        r_shape = 1
    jobq = 0 if mode in ('r', 'raw', 'economic') else 1
    tau = nlcpy.empty(k, dtype=dtype)
    r = nlcpy.zeros(r_shape, dtype=dtype)
    work = nlcpy.empty(n * 64, dtype=dtype)
    fpe = request._get_fpe_flag()
    args = (
        m,
        n,
        jobq,
        a._ve_array,
        tau._ve_array,
        r._ve_array,
        work._ve_array,
        veo.OnStack(fpe, inout=veo.INTENT_OUT),
    )

    request._push_and_flush_request(
        'nlcpy_qr',
        args,
    )

    if mode == 'raw':
        return a.T, tau

    if mode == 'r':
        return nlcpy.asarray(r, dtype=a_dtype)

    if mode == 'economic':
        return nlcpy.asarray(a, dtype=a_dtype)

    mc = m if mode == 'complete' else k
    q = nlcpy.asarray(a[:, :mc], dtype=a_dtype, order='C')
    r = nlcpy.asarray(r, dtype=a_dtype, order='C')
    return q, r
示例#15
0
文件: sort.py 项目: SX-Aurora/nlcpy
def sort(a, axis=-1, kind=None, order=None):
    """Returns a sorted copy of an array.

    Parameters
    ----------
    a : array_like
        Array to be sorted.
    axis : int or None, optional
        Axis along which to sort. If None, the array is flattened before sorting. The
        default is -1, which sorts along the last axis.
    kind : {'None','stable'}, optional
        Sorting algorithm. The default is 'stable', kind only supported 'stable'. ('None'
        is treated as 'stable'.)
    order : str or list of str, optional
        In the current NLCPy, This argument is not supported. The default is 'None'.

    Returns
    -------
    sorted_array : ndarray
        Array of the same type and shape as *a*.

    Restriction
    -----------
    *NotImplementedError*:

      - If *kind* is not None and ``kind != 'stable'``.
      - If *order* is not None.
      - If 'c' is contained in *a.dtype.kind*.

    Note
    ----

    'stable' uses the radix sort for all data types.

    See Also
    --------
    ndarray.sort : Method to sort an array in-place.
    argsort : Indirect sort.

    Examples
    --------
    >>> import nlcpy as vp
    >>> a = vp.array([[1,4],[3,1]])
    >>> vp.sort(a)                # sort along the last axis
    array([[1, 4],
           [1, 3]])
    >>> vp.sort(a, axis=None)     # sort the flattened array
    array([1, 1, 3, 4])
    >>> vp.sort(a, axis=0)        # sort along the first axis
    array([[1, 1],
           [3, 4]])

    """
    a = nlcpy.asarray(a)
    if kind is not None and kind not in 'stable':
        raise NotImplementedError('kind only supported \'stable\'.')
    if order is not None:
        raise NotImplementedError('order is not implemented.')
    if a.dtype.kind in ('c', ):
        raise NotImplementedError('Unsupported dtype %s' % a.dtype)
    if axis is None:
        ret = a.flatten()
        axis = -1
    else:
        ret = a.copy()
    ret.sort(axis=axis, kind=kind, order=order)
    return ret
示例#16
0
def _geev(a, jobvr):
    a = nlcpy.asarray(a)
    util._assertRankAtLeast2(a)
    util._assertNdSquareness(a)

    # used to match the contiguous of result to numpy.
    c_order = a.flags.c_contiguous or sum([i > 1 for i in a.shape[:-2]]) < 2

    a_complex = a.dtype.char in 'FD'
    if a.dtype.char == 'F':
        dtype = 'D'
        f_dtype = 'f'
        c_dtype = 'F'
    elif a.dtype.char == 'D':
        dtype = 'D'
        f_dtype = 'd'
        c_dtype = 'D'
    else:
        dtype = 'd'
        if a.dtype.char == 'f':
            f_dtype = 'f'
            c_dtype = 'F'
        else:
            f_dtype = 'd'
            c_dtype = 'D'

    if a.size == 0:
        dtype = c_dtype if a_complex else f_dtype
        w = nlcpy.empty(shape=a.shape[:-1], dtype=dtype)
        if jobvr:
            vr = nlcpy.empty(shape=a.shape, dtype=dtype)
            return w, vr
        else:
            return w

    a = nlcpy.array(nlcpy.moveaxis(a, (-1, -2), (1, 0)), dtype=dtype, order='F')
    wr = nlcpy.empty(a.shape[1:], dtype=dtype, order='F')
    wi = nlcpy.empty(a.shape[1:], dtype=dtype, order='F')
    vr = nlcpy.empty(a.shape if jobvr else 1, dtype=dtype, order='F')
    vc = nlcpy.empty(a.shape if jobvr else 1, dtype='D', order='F')

    n = a.shape[0]
    work = nlcpy.empty(
        65 * n if a_complex else 66 * n, dtype=dtype, order='F')
    rwork = nlcpy.empty(2 * n if a_complex else 1, dtype=f_dtype, order='F')
    info = numpy.empty(1, dtype='l')
    fpe = request._get_fpe_flag()
    args = (
        a._ve_array,
        wr._ve_array,
        wi._ve_array,
        vr._ve_array,
        vc._ve_array,
        work._ve_array,
        rwork._ve_array,
        ord('V') if jobvr else ord('N'),
        veo.OnStack(info, inout=veo.INTENT_OUT),
        veo.OnStack(fpe, inout=veo.INTENT_OUT),
    )

    request._push_and_flush_request(
        'nlcpy_eig',
        args,
    )

    if a_complex:
        w_complex = True
        w = wr
        vc = vr
    else:
        w_complex = nlcpy.any(wi)
        w = wr + wi * 1.0j
    if w_complex:
        if c_order:
            w = nlcpy.asarray(nlcpy.moveaxis(w, 0, -1), dtype=c_dtype, order='C')
        else:
            w = nlcpy.moveaxis(nlcpy.asarray(w, dtype=c_dtype), 0, -1)
    else:
        wr = w.real
        w = nlcpy.moveaxis(nlcpy.asarray(wr, dtype=f_dtype), 0, -1)

    if jobvr:
        if w_complex:
            if c_order:
                vr = nlcpy.asarray(
                    nlcpy.moveaxis(vc, (1, 0), (-1, -2)), dtype=c_dtype, order='C')
            else:
                vr = nlcpy.moveaxis(
                    nlcpy.asarray(vc, dtype=c_dtype), (1, 0), (-1, -2))
        else:
            if c_dtype == "F":
                vr = nlcpy.asarray(vc.real, dtype=f_dtype, order='C')
            else:
                vc = nlcpy.moveaxis(
                    nlcpy.asarray(vc, dtype=c_dtype), (1, 0), (-1, -2))
                vr = vc.real

    if jobvr:
        return w, vr
    else:
        return w
示例#17
0
def norm(x, ord=None, axis=None, keepdims=False):
    """Returns matrix or vector norm.

    This function is able to return one of eight different matrix norms, or one of an
    infinite number of vector norms (described below), depending on the value of the
    ``ord`` parameter.

    Parameters
    ----------
    x : array_like
        Input array. If *axis* is None, *x* must be 1-D or 2-D.
    ord : {non-zero int, inf, -inf, 'fro', 'nuc'}, optional
        Order of the norm (see table under ``Note``). inf means nlcpy's *inf* object.
    axis : {None, int, 2-tuple of ints}, optional
        If *axis* is an integer, it specifies the axis of *x* along which to compute the
        vector norms. If *axis* is a 2-tuple, it specifies the axes that hold 2-D
        matrices, and the matrix norms of these matrices are computed. If *axis* is None
        then either a vector norm (when *x* is 1-D) or a matrix norm (when *x* is 2-D) is
        returned.
    keepdims : bool, optional
        If this is set to True, the axes which are normed over are left in the result as
        dimensions with size one. With this option the result will broadcast correctly
        against the original x.

    Returns
    -------
    n : ndarray
        Norm of the matrix or vector(s).

    Note
    ----
    For values of ``ord < 1``, the result is, strictly speaking, not a mathematical
    'norm', but it may still be useful for various numerical purposes. The following
    norms can be calculated:

    .. csv-table::
        :header: ord, norm for matrices, norm for vectors

        None, Frobenius norm, 2-norm
        'fro', Frobenius norm, \-
        'nuc', nuclear norm, \-
        inf, "max(sum(abs(x), axis=1))", max(abs(x))
        -inf, "min(sum(abs(x), axis=1))", min(abs(x))
        0, \-, sum(x != 0)
        1, "max(sum(abs(x), axis=0))", as below
        -1, "min(sum(abs(x), axis=0))", as below
        2, 2-norm (largest sing. value), as below
        -2, smallest singular value, as below
        other, \-, sum(abs(x)**ord)**(1./ord)

    The Frobenius norm is given by :math:`|A|_F = [\\sum_{i,j}abs(a_{i,j})^2]^{1/2}`

    The nuclear norm is the sum of the singular values.

    Examples
    --------
    >>> import nlcpy as vp
    >>> a = vp.arange(9) - 4
    >>> a
    array([-4, -3, -2, -1,  0,  1,  2,  3,  4])
    >>> b = a.reshape((3, 3))
    >>> b
    array([[-4, -3, -2],
           [-1,  0,  1],
           [ 2,  3,  4]])
    >>> vp.linalg.norm(a)    # doctest: +SKIP
    array(7.74596669)
    >>> vp.linalg.norm(b)    # doctest: +SKIP
    array(7.74596669)
    >>> vp.linalg.norm(b, 'fro')   # doctest: +SKIP
    array(7.74596669)
    >>> vp.linalg.norm(a, vp.inf)  # doctest: +SKIP
    array(4.)
    >>> vp.linalg.norm(b, vp.inf)  # doctest: +SKIP
    array(9.)
    >>> vp.linalg.norm(a, -vp.inf)  # doctest: +SKIP
    array(0.)
    >>> vp.linalg.norm(b, -vp.inf)  # doctest: +SKIP
    array(2.)
    >>> vp.linalg.norm(a, 1)   # doctest: +SKIP
    array(20.)
    >>> vp.linalg.norm(b, 1)   # doctest: +SKIP
    array(7.)
    >>> vp.linalg.norm(a, -1)  # doctest: +SKIP
    array(0.)
    >>> vp.linalg.norm(b, -1)  # doctest: +SKIP
    array(6.)
    >>> vp.linalg.norm(a, 2)   # doctest: +SKIP
    array(7.74596669)
    >>> vp.linalg.norm(b, 2)  # doctest: +SKIP
    array(7.34846923)
    >>> vp.linalg.norm(a, -2) # doctest: +SKIP
    array(0.)
    >>> vp.linalg.norm(b, -2) # doctest: +SKIP
    array(3.75757704e-16)
    >>> vp.linalg.norm(a, 3)  # doctest: +SKIP
    array(5.84803548)
    >>> vp.linalg.norm(a, -3) # doctest: +SKIP
    array(0.)

    Using the *axis* argument to compute vector norms:

    >>> c = vp.array([[ 1, 2, 3],
    ...               [-1, 1, 4]])
    >>> vp.linalg.norm(c, axis=0)   # doctest: +SKIP
    array([1.41421356, 2.23606798, 5.        ])
    >>> vp.linalg.norm(c, axis=1)   # doctest: +SKIP
    array([3.74165739, 4.24264069])
    >>> vp.linalg.norm(c, ord=1, axis=1)  # doctest: +SKIP
    array([6., 6.])

    Using the axis argument to compute matrix norms:

    >>> m = vp.arange(8).reshape(2,2,2)
    >>> vp.linalg.norm(m, axis=(1,2))   # doctest: +SKIP
    array([ 3.74165739, 11.22497216])
    >>> vp.linalg.norm(m[0, :, :]), vp.linalg.norm(m[1, :, :])  # doctest: +SKIP
    (array(3.74165739), array(11.22497216))

    """
    x = nlcpy.asarray(x)
    if x.dtype.char in '?ilIL':
        x = nlcpy.array(x, dtype='d')
    # used to match the contiguous of result to numpy.
    order = 'F' if x.flags.f_contiguous and not x.flags.c_contiguous else 'C'

    # Immediately handle some default, simple, fast, and common cases.
    if axis is None:
        ret = None
        ndim = x.ndim
        axis = tuple(range(x.ndim))
        if ord is None and x.ndim == 2:
            ret = _lange(x, ord, axis)
        elif ord is None or ord == 2 and x.ndim == 1:
            x = x.ravel()
            if x.dtype.char in 'FD':
                sqnorm = nlcpy.dot(x.real, x.real) + nlcpy.dot(x.imag, x.imag)
            else:
                sqnorm = nlcpy.dot(x, x)
            ret = nlcpy.sqrt(sqnorm)
        if ret is not None:
            if keepdims:
                ret = ret.reshape(ndim * [1])
            return ret
    elif not isinstance(axis, tuple):
        try:
            axis = (int(axis), )
        except Exception:
            raise TypeError(
                "'axis' must be None, an integer or a tuple of integers")

    if len(axis) == 1:
        if ord == nlcpy.inf:
            return abs(x).max(axis=axis, keepdims=keepdims)
        elif ord == -nlcpy.inf:
            return abs(x).min(axis=axis, keepdims=keepdims)
        elif ord == 0:
            return nlcpy.sum((x != 0).astype(x.real.dtype),
                             axis=axis,
                             keepdims=keepdims)
        elif ord == 1:
            return nlcpy.add.reduce(abs(x), axis=axis, keepdims=keepdims)
        elif ord is None or ord == 2:
            s = (nlcpy.conj(x) * x).real
            ret = nlcpy.sqrt(nlcpy.add.reduce(s, axis=axis, keepdims=keepdims))
            return nlcpy.asarray(ret, order=order)
        else:
            try:
                ord + 1
            except TypeError:
                raise ValueError("Invalid norm order for vectors.")
            ret = abs(x)**ord
            ret = nlcpy.add.reduce(ret, axis=axis, keepdims=keepdims)
            ret **= (1 / ord)
            if (keepdims or x.ndim > 1) and x.dtype.char in 'fF':
                ret = nlcpy.asarray(ret, dtype='f')
            else:
                ret = nlcpy.asarray(ret, dtype='d')
            return ret
    elif len(axis) == 2:
        row_axis, col_axis = axis
        if row_axis < 0:
            row_axis += x.ndim
        if col_axis < 0:
            col_axis += x.ndim
        if row_axis == col_axis:
            raise ValueError('Duplicate axes given.')
        if ord == 2:
            y = nlcpy.moveaxis(x, (row_axis, col_axis), (-2, -1))
            ret = nlcpy.linalg.svd(y, compute_uv=0).max(axis=-1)
        elif ord == -2:
            y = nlcpy.moveaxis(x, (row_axis, col_axis), (-2, -1))
            ret = nlcpy.linalg.svd(y, compute_uv=0).min(axis=-1)
        elif ord == 1:
            if x.shape[col_axis] == 0:
                raise ValueError(
                    'zero-size array to '
                    'reduction operation maximum which has no identity')
            ret = _lange(x, ord, axis)
        elif ord == nlcpy.inf:
            if x.shape[row_axis] == 0:
                raise ValueError(
                    'zero-size array to '
                    'reduction operation maximum which has no identity')
            ret = _lange(x, ord, axis)
        elif ord in (None, 'fro', 'f'):
            ret = _lange(x, ord, axis)
        elif ord == -1:
            if col_axis > row_axis:
                col_axis -= 1
            ret = nlcpy.add.reduce(abs(x), axis=row_axis).min(axis=col_axis)
        elif ord == -nlcpy.inf:
            if row_axis > col_axis:
                row_axis -= 1
            ret = nlcpy.add.reduce(abs(x), axis=col_axis).min(axis=row_axis)
        elif ord == 'nuc':
            y = nlcpy.moveaxis(x, (row_axis, col_axis), (-2, -1))
            ret = nlcpy.sum(nlcpy.linalg.svd(y, compute_uv=0), axis=-1)
        else:
            raise ValueError("Invalid norm order for matrices.")
        if keepdims:
            ret_shape = list(x.shape)
            ret_shape[axis[0]] = 1
            ret_shape[axis[1]] = 1
            ret = ret.reshape(ret_shape)
        ret = nlcpy.asarray(ret, order=order)
        return ret
    else:
        raise ValueError("Improper number of dimensions to norm.")
示例#18
0
def solve(a, b):
    """Solves a linear matrix equation, or system of linear scalar equations.

    Computes the "exact" solution, *x*, of the well-determined, i.e., full rank, linear
    matrix equation :math:`ax = b`.

    Parameters
    ----------
    a : (..., M, M) array_like
        Coefficient matrix.
    b : {(..., M,), (..., M, K)} array_like
        Ordinate or "dependent variable" values.

    Returns
    -------
    x : {(..., M,), (..., M, K)} ndarray
        Solution to the system a x = b. Returned shape is identical to *b*.

    Note
    ----
    The solutions are computed using LAPACK routine ``_gesv``.

    `a` must be square and of full-rank, i.e., all rows (or, equivalently, columns) must
    be linearly independent; if either is not true, use :func:`lstsq` for the
    least-squares best "solution" of the system/equation.

    Examples
    --------
    Solve the system of equations ``3 * x0 + x1 = 9`` and ``x0 + 2 * x1 = 8``:

    >>> import nlcpy as vp
    >>> a = vp.array([[3,1], [1,2]])
    >>> b = vp.array([9,8])
    >>> x = vp.linalg.solve(a, b)
    >>> x
    array([2., 3.])

    """
    a = nlcpy.asarray(a)
    b = nlcpy.asarray(b)
    c_order = (a.flags.c_contiguous or a.ndim < 4 or
               a.ndim - b.ndim < 2 and b.flags.c_contiguous) and \
        not (a.ndim < b.ndim and not b.flags.c_contiguous)
    util._assertRankAtLeast2(a)
    util._assertNdSquareness(a)

    if a.ndim - 1 == b.ndim:
        if a.shape[-1] != b.shape[-1]:
            raise ValueError(
                'solve1: Input operand 1 has a mismatch in '
                'its core dimension 0, with gufunc signature (m,m),(m)->(m) '
                '(size {0} is different from {1})'.format(
                    b.shape[-1], a.shape[-1]))
    elif b.ndim == 1:
        raise ValueError(
            'solve: Input operand 1 does not have enough dimensions '
            '(has 1, gufunc core with signature (m,m),(m,n)->(m,n) requires 2)'
        )
    else:
        if a.shape[-1] != b.shape[-2]:
            raise ValueError(
                'solve: Input operand 1 has a mismatch in '
                'its core dimension 0, with gufunc signature (m,m),(m,n)->(m,n) '
                '(size {0} is different from {1})'.format(
                    b.shape[-2], a.shape[-1]))

    if b.ndim == 1 or a.ndim - 1 == b.ndim and a.shape[-1] == b.shape[-1]:
        tmp = 1
        _newaxis = (None, )
    else:
        tmp = 2
        _newaxis = (None, None)
    for i in range(1, min(a.ndim - 2, b.ndim - tmp) + 1):
        if a.shape[-2 - i] != b.shape[-tmp - i] and \
           1 not in (a.shape[-2 - i], b.shape[-tmp - i]):
            raise ValueError(
                'operands could not be broadcast together with '
                'remapped shapes [original->remapped]: {0}->({1}) '
                '{2}->({3}) and requested shape ({4})'.format(
                    str(a.shape).replace(' ', ''),
                    str(a.shape[:-2] + _newaxis).replace(' ', '').replace(
                        'None', 'newaxis').strip('(,)'),
                    str(b.shape).replace(' ', ''),
                    str(b.shape[:-tmp] + _newaxis).replace(' ', '').replace(
                        'None', 'newaxis').replace('None',
                                                   'newaxis').strip('(,)'),
                    str(b.shape[-tmp:]).replace(' ', '').strip('(,)')))

    if a.dtype.char in 'FD' or b.dtype.char in 'FD':
        dtype = 'complex128'
        if a.dtype.char in 'fF' and b.dtype.char in 'fF':
            x_dtype = 'complex64'
        else:
            x_dtype = 'complex128'
    else:
        dtype = 'float64'
        if a.dtype.char == 'f' and b.dtype.char == 'f':
            x_dtype = 'float32'
        else:
            x_dtype = 'float64'

    x_shape = b.shape
    if b.ndim == a.ndim - 1:
        b = b[..., nlcpy.newaxis]
    diff = abs(a.ndim - b.ndim)
    if a.ndim < b.ndim:
        bcast_shape = [
            b.shape[i] if b.shape[i] != 1 or i < diff else a.shape[i - diff]
            for i in range(b.ndim - 2)
        ]
    else:
        bcast_shape = [
            a.shape[i] if a.shape[i] != 1 or i < diff else b.shape[i - diff]
            for i in range(a.ndim - 2)
        ]
    bcast_shape_a = bcast_shape + list(a.shape[-2:])
    bcast_shape_b = bcast_shape + list(b.shape[-2:])
    a = nlcpy.broadcast_to(a, bcast_shape_a)
    if bcast_shape_b != list(b.shape):
        b = nlcpy.broadcast_to(b, bcast_shape_b)
        x_shape = b.shape
    if b.size == 0:
        return nlcpy.empty(x_shape, dtype=x_dtype)

    a = nlcpy.array(nlcpy.moveaxis(a, (-1, -2), (1, 0)),
                    dtype=dtype,
                    order='F')
    b = nlcpy.array(nlcpy.moveaxis(b, (-1, -2), (1, 0)),
                    dtype=dtype,
                    order='F')

    info = numpy.empty(1, dtype='l')
    fpe = request._get_fpe_flag()
    args = (
        a._ve_array,
        b._ve_array,
        veo.OnStack(info, inout=veo.INTENT_OUT),
        veo.OnStack(fpe, inout=veo.INTENT_OUT),
    )

    request._push_and_flush_request('nlcpy_solve',
                                    args,
                                    callback=util._assertNotSingular(info))

    if c_order:
        x = nlcpy.moveaxis(b, (1, 0), (-1, -2)).reshape(x_shape)
        return nlcpy.asarray(x, x_dtype, 'C')
    else:
        x = nlcpy.asarray(b, x_dtype)
        return nlcpy.moveaxis(x, (1, 0), (-1, -2)).reshape(x_shape)
示例#19
0
文件: ufunc.py 项目: SX-Aurora/nlcpy
def _check_ufunc_result(op, worst_dtype, v, n, in1=None, in2=None,
                        out=None, where=None, dtype=None, ufunc_name='', n_calc=1):

    # nan/inf care
    if numpy.isscalar(n):
        if numpy.isinf(n) and nlcpy.isinf(v) or numpy.isnan(n) and nlcpy.isnan(v):
            return
    else:
        v, n = _nan_inf_care(v, n)

    v_array = nlcpy.asarray(v)
    n_array = numpy.asarray(n)
    atol, rtol = _guess_tolerance(op, worst_dtype, ufunc_name)
    if ufunc_name in ('reduce', 'accumulate', 'reduceat'):
        atol *= n_calc
        rtol *= n_calc
        if numpy.asarray(n).dtype.char in '?ilIL' and \
           (numpy.asarray(in1).dtype.char not in '?ilIL' or
           numpy.dtype(dtype).char not in '?ilIL' or
           op in ('logaddexp', 'logaddexp2', 'arctan2', 'hypot')):
            atol = 1

    # prepare error message
    msg = "\n"
    msg += "***** parameters when pytest raised an error *****"
    msg += "\nout={}, where={}, dtype={}".format(
        True if out is not None else False,
        True if where is not None else False, dtype)
    msg += "\nop: {}".format(op)
    if in1 is not None:
        if isinstance(in1, numpy.ndarray):
            msg += "\nin1: dtype={}\n{}".format(in1.dtype, in1)
        else:
            msg += "\nin1: dtype={}\n{}".format(type(in1), in1)
    if in2 is not None:
        if isinstance(in2, numpy.ndarray):
            msg += "\nin2: dtype={}\n{}".format(in2.dtype, in2)
        else:
            msg += "\nin2: dtype={}\n{}".format(type(in2), in2)
    if out is not None:
        msg += "\nout: dtype={}\n{}".format(out.dtype, out)
    if where is not None:
        msg += "\nwhere: dtype={}\n{}".format(where.dtype, where)
    msg += "\n\nnlcpy_result: dtype={}\n{}".format(v_array.dtype, v_array)
    msg += "\nnumpy_result: dtype={}\n{}".format(n_array.dtype, n_array)
    msg += "\n"

    # compare results
    try:
        if v_array.dtype == DT_BOOL and n_array.dtype == DT_BOOL:
            array.assert_array_equal(v_array, n_array, verbose=True, err_msg=msg)
        elif atol == 0 and rtol == 0:
            array.assert_array_equal(v_array, n_array, verbose=True, err_msg=msg)
        else:
            array.assert_allclose(
                v_array, n_array, rtol, atol, verbose=True, err_msg=msg)
    except Exception:
        raise

    # if contiguous_check and isinstance(n, numpy.ndarray):
    if isinstance(n, numpy.ndarray):
        if n.flags.c_contiguous and not v.flags.c_contiguous:
            raise AssertionError(
                'The state of c_contiguous flag is false. \n\n'
                'nlcpy_flags:\n{} \n\nnumpy_flags:\n{})'.format(
                    v.flags, n.flags))
        if n.flags.f_contiguous and not v.flags.f_contiguous:
            raise AssertionError(
                'The state of f_contiguous flag is false. \n\n'
                'nlcpy_flags:\n{} \n\nnumpy_flags:\n{})'.format(
                    v.flags, n.flags))
示例#20
0
import pytest  # NOQA

import numpy
import numpy as np  # NOQA

import nlcpy
from nlcpy import testing


@testing.parameterize(*testing.product({
    'a': [[1, 2, 3, 4, 5], (1, 2, 3),
          range(10),
          bytearray(b'abc'),
          memoryview(b'abc'),
          numpy.asarray([1, 2]),
          nlcpy.asarray([1, 2]), [True, False], [1, 2, 3], [2.3, 4.5],
          [3. + 0.1j, 4. + 0.2j], [[1, 2, 3, 4, 5], [1, 2, 3, 4, 5]],
          [(1, 2, 3), (1, 2, 3)], [range(10), range(10)],
          [bytearray(b'abc'), bytearray(b'abc')],
          [memoryview(b'abc'), memoryview(b'abc')],
          [numpy.asarray([1, 2]), numpy.asarray([1, 2])],
          [nlcpy.asarray([1, 2]), nlcpy.asarray([1, 2])], (True, False),
          (1, 2, 3), (2.3, 4.5), (3. + 0.1j, 4. + 0.2j),
          ([1, 2, 3, 4, 5], [1, 2, 3, 4, 5]), ((1, 2, 3), (1, 2, 3)),
          (range(10), range(10)), (bytearray(b'abc'), bytearray(b'abc')),
          (memoryview(b'abc'), memoryview(b'abc')),
          (numpy.asarray([1, 2]), numpy.asarray([1, 2])),
          (nlcpy.asarray([1, 2]), nlcpy.asarray([1, 2]))],
}))
@testing.with_requires('numpy>=1.10.0')
class TestFftInput(unittest.TestCase):
示例#21
0
def linspace(start,
             stop,
             num=50,
             endpoint=True,
             retstep=False,
             dtype=None,
             axis=0):
    """Returns evenly spaced numbers over a specified interval.

    Returns *num* evenly spaced samples, calculated over the interval ``[start, stop]``.
    The endpoint of the interval can optionally be excluded.

    Parameters
    ----------
    start : array_like
        The starting value of the sequence.
    stop : array_like
        The end value of the sequence, unless *endpoint* is set to False. In that case,
        the sequence consists of all but the last of ``num + 1`` evenly spaced samples,
        so that *stop* is excluded. Note that the step size changes when *endpoint* is
        False.
    num : int, optional
        Number of samples to generate. Default is 50. Must be non-negative.
    endpoint : bool, optional
        If True, *stop* is the last sample. Otherwise, it is not included. Default is
        True.
    retstep : bool, optional
        If True, return (*samples*, *step*) where *step* is the spacing between samples.
    dtype : dtype, optional
        The type of the output array. If *dtype* is not given, infer the data type from
        the other input arguments.
    axis : int, optional
        The axis in the result to store the samples. Relevant only if start or stop are
        array-like. By default (0), the samples will be along a new axis inserted at the
        beginning. Use -1 to get an axis at the end.

    Returns
    -------
    samples : ndarray
        There are *num* equally spaced samples in the closed interval ``[start, stop]``
        or the half-open interval ``[start, stop)`` (depending on whether *endpoint* is
        True or False).
    step : float, optional
        Only returned if *retstep* is True
        Size of spacing between samples.

    See Also
    --------
    arange : Returns evenly spaced values within a given interval.

    Examples
    --------
    >>> import nlcpy as vp
    >>> vp.linspace(2.0, 3.0, num=5)
    array([2.  , 2.25, 2.5 , 2.75, 3.  ])
    >>> vp.linspace(2.0, 3.0, num=5, endpoint=False)
    array([2. , 2.2, 2.4, 2.6, 2.8])
    >>> vp.linspace(2.0, 3.0, num=5, retstep=True)
    (array([2.  , 2.25, 2.5 , 2.75, 3.  ]), array([0.25]))

    """
    num = operator.index(num)
    if num < 0:
        raise ValueError("Number of samples, %s, must be non-negative." % num)

    dtype_kind = numpy.dtype(dtype).kind
    if dtype_kind == 'V':
        raise NotImplementedError(
            'void dtype in linspace is not implemented yet.')

    start = nlcpy.asarray(start)
    stop = nlcpy.asarray(stop)
    dt = numpy.result_type(start, stop, float(num))
    if start.dtype.char in '?iIlL' or stop.dtype.char in '?iIlL':
        dt = 'D' if dt.char in 'FD' else 'd'

    if dtype is None:
        dtype = dt

    start = nlcpy.asarray(start, dtype=dt)
    stop = nlcpy.asarray(stop, dtype=dt)
    delta = stop - start
    div = (num - 1) if endpoint else num
    if num == 0:
        ret = nlcpy.empty((num, ) + delta.shape, dtype=dtype)
        if retstep:
            ret = (ret, nlcpy.NaN)
        return ret
    elif div == 0 or num == 1:
        ret = nlcpy.resize(start, (1, ) + delta.shape).astype(dtype)
        if retstep:
            ret = (ret, stop)
        return ret
    else:
        ret = nlcpy.empty((num, ) + delta.shape, dtype=dtype)
    retdata = ret

    delta = delta[nlcpy.newaxis]
    start = nlcpy.array(nlcpy.broadcast_to(start, delta.shape))
    stop = nlcpy.array(nlcpy.broadcast_to(stop, delta.shape))
    step = delta / div if div > 1 else delta
    if retdata._memloc in {on_VE, on_VE_VH}:
        denormal = nlcpy.zeros(1, dtype='l')
        request._push_request(
            "nlcpy_linspace", "creation_op",
            (ret, start, stop, delta, step, int(endpoint), denormal))
        if axis != 0:
            ret = nlcpy.moveaxis(ret, 0, axis)
        if retstep:
            ret = (ret, step)

    if retdata._memloc in {on_VH, on_VE_VH}:
        del retdata.vh_data
        del step.vh_data
        typ = numpy.dtype(dtype).type
        if retstep:
            (retdata.vh_data,
             step.vh_data) = numpy.linspace(typ(start),
                                            typ(stop), num, endpoint,
                                            typ(retstep), dtype, axis)
        else:
            retdata.vh_data = numpy.linspace(typ(start),
                                             typ(stop), num, endpoint,
                                             typ(retstep), dtype, axis)
    return ret
示例#22
0
def svd(a, full_matrices=True, compute_uv=True, hermitian=False):
    """Singular Value Decomposition.

    When *a* is a 2D array, it is factorized as
    ``u @ nlcpy.diag(s) @ vh = (u * s) @ vh``,
    where *u* and *vh* are 2D unitary arrays and *s* is a 1D array of *a*'s singular
    values.
    When *a* is higher-dimensional, SVD is applied in stacked mode as explained below.

    Parameters
    ----------
    a : (..., M, N) array_like
        A real or complex array with a.ndim >= 2.
    full_matrices : bool, optional
        If True (default), *u* and *vh* have the shapes ``(..., M, M)`` and ``(..., N,
        N)``, respectively. Otherwise, the shapes are ``(..., M, K)`` and ``(..., K,
        N)``, respectively, where ``K = min(M, N)``.
    compute_uv : bool, optional
        Whether or not to compute *u* and *vh* in addition to *s*. True by default.
    hermitian : bool, optional
        If True, *a* is assumed to be Hermitian (symmetric if real-valued), enabling a
        more efficient method for finding singular values. Defaults to False.

    Returns
    -------
    u : {(..., M, M), (..., M, K)} ndarray
        Unitary array(s). The first ``a.ndim - 2`` dimensions have the same size as those
        of the input *a*. The size of the last two dimensions depends on the value of
        *full_matrices*. Only returned when *compute_uv* is True.
    s : (..., K) ndarray
        Vector(s) with the singular values, within each vector sorted in descending
        order. The first ``a.ndim - 2`` dimensions have the same size as those of the
        input *a*.
    vh : {(..., N, N), (..., K, N)} ndarray
        Unitary array(s). The first ``a.ndim - 2`` dimensions have the same size as those
        of the input *a*. The size of the last two dimensions depends on the value of
        *full_matrices*. Only returned when *compute_uv* is True.

    Note
    ----
    The decomposition is performed using LAPACK routine ``_gesdd``.

    SVD is usually described for the factorization of a 2D matrix :math:`A`.
    The higher-dimensional case will be discussed below. In the 2D case, SVD is written
    as
    :math:`A=USV^{H}`, where :math:`A = a`, :math:`U = u`, :math:`S = nlcpy.diag(s)`
    and :math:`V^{H} = vh`. The 1D array `s` contains the singular values of `a` and
    `u` and `vh` are unitary. The rows of `vh` are the eigenvectors of :math:`A^{H}A`
    and the columns of `u` are the eigenvectors of :math:`AA^{H}`. In both cases the
    corresponding (possibly non-zero) eigenvalues are given by ``s**2``.

    If `a` has more than two dimensions, then broadcasting rules apply, as explained in
    :ref:`Linear algebra on several matrices at once <linalg_several_matrices_at_once>`.
    This means that SVD is working in "stacked" mode: it iterates over all indices
    of the first ``a.ndim - 2`` dimensions and for each combination SVD is applied to the
    last two indices.

    Examples
    --------
    >>> import nlcpy as vp
    >>> from nlcpy import testing
    >>> a = vp.random.randn(9, 6) + 1j*vp.random.randn(9, 6)

    Reconstruction based on full SVD, 2D case:

    >>> u, s, vh = vp.linalg.svd(a, full_matrices=True)
    >>> u.shape, s.shape, vh.shape
    ((9, 9), (6,), (6, 6))
    >>> vp.testing.assert_allclose(a, vp.dot(u[:, :6] * s, vh))
    >>> smat = vp.zeros((9, 6), dtype=complex)
    >>> smat[:6, :6] = vp.diag(s)
    >>> vp.testing.assert_allclose(a, vp.dot(u, vp.dot(smat, vh)))

    Reconstruction based on reduced SVD, 2D case:

    >>> u, s, vh = vp.linalg.svd(a, full_matrices=False)
    >>> u.shape, s.shape, vh.shape
    ((9, 6), (6,), (6, 6))
    >>> vp.testing.assert_allclose(a, vp.dot(u * s, vh))
    >>> smat = vp.diag(s)
    >>> vp.testing.assert_allclose(a, vp.dot(u, vp.dot(smat, vh)))

    """
    a = nlcpy.asarray(a)
    util._assertRankAtLeast2(a)
    if hermitian:
        util._assertNdSquareness(a)

    # used to match the contiguous of result to numpy.
    c_order = a.flags.c_contiguous or sum([i > 1 for i in a.shape[:-2]]) < 2

    a_complex = a.dtype.char in 'FD'
    if a.dtype == 'F':
        dtype = 'F'
        f_dtype = 'f'
    elif a.dtype == 'D':
        dtype = 'D'
        f_dtype = 'd'
    elif a.dtype == 'f':
        dtype = 'f'
        f_dtype = 'f'
    else:
        dtype = 'd'
        f_dtype = 'd'

    if hermitian:
        if compute_uv:
            # lapack returns eigenvalues in reverse order, so to reconsist.
            s, u = nlcpy.linalg.eigh(a)
            signs = nlcpy.sign(s)
            s = abs(s)
            sidx = nlcpy.argsort(s)[..., ::-1]
            signs = _take_along_axis(signs, sidx, signs.ndim - 1)
            s = _take_along_axis(s, sidx, s.ndim - 1)
            u = _take_along_axis(u, sidx[..., None, :], u.ndim - 1)
            # singular values are unsigned, move the sign into v
            vt = nlcpy.conjugate(u * signs[..., None, :])
            vt = nlcpy.moveaxis(vt, -2, -1)
            return u, s, vt
        else:
            s = nlcpy.linalg.eigvalsh(a)
            s = nlcpy.sort(abs(s))[..., ::-1]
            return s

    m = a.shape[-2]
    n = a.shape[-1]
    min_mn = min(m, n)
    max_mn = max(m, n)
    if a.size == 0:
        s = nlcpy.empty(a.shape[:-2] + (min_mn, ), f_dtype)
        if compute_uv:
            if full_matrices:
                u_shape = a.shape[:-1] + (m, )
                vt_shape = a.shape[:-2] + (n, n)
            else:
                u_shape = a.shape[:-1] + (min_mn, )
                vt_shape = a.shape[:-2] + (min_mn, n)
            u = nlcpy.empty(u_shape, dtype=dtype)
            vt = nlcpy.empty(vt_shape, dtype=dtype)
            return u, s, vt
        else:
            return s

    a = nlcpy.array(nlcpy.moveaxis(a, (-1, -2), (1, 0)),
                    dtype=dtype,
                    order='F')
    if compute_uv:
        if full_matrices:
            u = nlcpy.empty((m, m) + a.shape[2:], dtype=dtype, order='F')
            vt = nlcpy.empty((n, n) + a.shape[2:], dtype=dtype, order='F')
            job = 'A'
        else:
            u = nlcpy.empty((m, m) + a.shape[2:], dtype=dtype, order='F')
            vt = nlcpy.empty((min_mn, n) + a.shape[2:], dtype=dtype, order='F')
            job = 'S'
    else:
        u = nlcpy.empty(1)
        vt = nlcpy.empty(1)
        job = 'N'

    if a_complex:
        mnthr1 = int(min_mn * 17.0 / 9.0)
        if max_mn >= mnthr1:
            if job == 'N':
                lwork = 130 * min_mn
            elif job == 'S':
                lwork = (min_mn + 130) * min_mn
            else:
                lwork = max(
                    (min_mn + 130) * min_mn,
                    (min_mn + 1) * min_mn + 32 * max_mn,
                )
        else:
            lwork = 64 * (min_mn + max_mn) + 2 * min_mn
    else:
        mnthr = int(min_mn * 11.0 / 6.0)
        if m >= n:
            if m >= mnthr:
                if job == 'N':
                    lwork = 131 * n
                elif job == 'S':
                    lwork = max((131 + n) * n, (4 * n + 7) * n)
                else:
                    lwork = max((n + 131) * n, (n + 1) * n + 32 * m,
                                (4 * n + 6) * n + m)
            else:
                if job == 'N':
                    lwork = 64 * m + 67 * n
                elif job == 'S':
                    lwork = max(64 * m + 67 * n, (3 * n + 7) * n)
                else:
                    lwork = (3 * n + 7) * n
        else:
            if n >= mnthr:
                if job == 'N':
                    lwork = 131 * m
                elif job == 'S':
                    lwork = max((m + 131) * m, (4 * m + 7) * m)
                else:
                    lwork = max((m + 131) * m, (m + 1) * m + 32 * n,
                                (4 * m + 7) * m)
            else:
                if job == 'N':
                    lwork = 67 * m + 64 * n
                else:
                    lwork = max(67 * m + 64 * n, (3 * m + 7) * m)

    s = nlcpy.empty((min_mn, ) + a.shape[2:], dtype=f_dtype, order='F')
    work = nlcpy.empty(lwork, dtype=dtype)
    if a_complex:
        if job == 'N':
            lrwork = 5 * min_mn
        else:
            lrwork = min_mn * max(5 * min_mn + 7,
                                  2 * max(m, n) + 2 * min_mn + 1)
    else:
        lrwork = 1
    rwork = nlcpy.empty(lrwork, dtype=f_dtype)
    iwork = nlcpy.empty(8 * min_mn, dtype=f_dtype)
    info = numpy.empty(1, dtype='l')
    fpe = request._get_fpe_flag()
    args = (
        ord(job),
        a._ve_array,
        s._ve_array,
        u._ve_array,
        vt._ve_array,
        work._ve_array,
        rwork._ve_array,
        iwork._ve_array,
        veo.OnStack(info, inout=veo.INTENT_OUT),
        veo.OnStack(fpe, inout=veo.INTENT_OUT),
    )

    request._push_and_flush_request(
        'nlcpy_svd',
        args,
    )

    if c_order:
        s = nlcpy.asarray(nlcpy.moveaxis(s, 0, -1), order='C')
    else:
        s = nlcpy.moveaxis(s, 0, -1)
    if compute_uv:
        u = nlcpy.moveaxis(u, (1, 0), (-1, -2))
        if not full_matrices:
            u = u[..., :m, :min_mn]
        if c_order:
            u = nlcpy.asarray(u, dtype=dtype, order='C')
            vt = nlcpy.asarray(nlcpy.moveaxis(vt, (1, 0), (-1, -2)),
                               dtype,
                               order='C')
        else:
            vt = nlcpy.moveaxis(nlcpy.asarray(vt, dtype), (1, 0), (-1, -2))
        return u, s, vt
    else:
        return s
 def test_astype_type_f_contiguous_no_copy(self, dtype, order):
     a = testing.shaped_arange((2, 3, 4), nlcpy, dtype)
     a = nlcpy.asarray(a, order='F')
     b = a.astype(dtype, order=order, copy=False)
     self.assertTrue(b is a)
示例#24
0
def _syevd(a, jobz, UPLO):
    a = nlcpy.asarray(a)
    util._assertRankAtLeast2(a)
    util._assertNdSquareness(a)
    UPLO = UPLO.upper()
    if UPLO not in 'UL':
        raise ValueError("UPLO argument must be 'L' or 'U'")

    # used to match the contiguous of result to numpy.
    c_order = a.flags.c_contiguous or sum([i > 1 for i in a.shape[:-2]]) < 2

    a_complex = a.dtype.char in 'FD'
    if a.dtype.char == 'F':
        dtype = 'F'
        f_dtype = 'f'
    elif a.dtype.char == 'D':
        dtype = 'D'
        f_dtype = 'd'
    else:
        if a.dtype.char == 'f':
            dtype = 'f'
            f_dtype = 'f'
        else:
            dtype = 'd'
            f_dtype = 'd'

    if a.size == 0:
        w = nlcpy.empty(shape=a.shape[:-1], dtype=f_dtype)
        if jobz:
            vr = nlcpy.empty(shape=a.shape, dtype=dtype)
            return w, vr
        else:
            return w

    a = nlcpy.array(nlcpy.moveaxis(a, (-1, -2), (1, 0)), dtype=dtype, order='F')
    w = nlcpy.empty(a.shape[1:], dtype=f_dtype, order='F')
    n = a.shape[0]
    if a.size > 1:
        if a_complex:
            lwork = max(2 * n + n * n, n + 48)
            lrwork = 1 + 5 * n + 2 * n * n if jobz else n
        else:
            lwork = max(2 * n + 32, 1 + 6 * n + 2 * n * n) if jobz else 2 * n + 32
            lrwork = 1
        liwork = 3 + 5 * n if jobz else 1
    else:
        lwork = 1
        lrwork = 1
        liwork = 1

    work = nlcpy.empty(lwork, dtype=dtype)
    rwork = nlcpy.empty(lrwork, dtype=f_dtype)
    iwork = nlcpy.empty(liwork, dtype='l')
    info = numpy.empty(1, dtype='l')
    fpe = request._get_fpe_flag()
    args = (
        a._ve_array,
        w._ve_array,
        work._ve_array,
        rwork._ve_array,
        iwork._ve_array,
        ord('V') if jobz else ord('N'),
        ord(UPLO),
        veo.OnStack(info, inout=veo.INTENT_OUT),
        veo.OnStack(fpe, inout=veo.INTENT_OUT),
    )

    request._push_and_flush_request(
        'nlcpy_eigh',
        args,
    )

    if c_order:
        w = nlcpy.asarray(nlcpy.moveaxis(w, 0, -1), order='C')
    else:
        w = nlcpy.moveaxis(w, 0, -1)
    if jobz:
        if c_order:
            a = nlcpy.asarray(nlcpy.moveaxis(a, (1, 0), (-1, -2)), order='C')
        else:
            a = nlcpy.moveaxis(a, (1, 0), (-1, -2))
        return w, a
    else:
        return w
示例#25
0
def inv(a):
    """Computes the (multiplicative) inverse of a matrix.

    Given a square matrix *a*, return the matrix *ainv* satisfying

    ::

        dot(a, ainv) = dot(ainv, a) = eye(a.shape[0]).

    Parameters
    ----------
    a : (..., M, M) array_like
        Matrix to be inverted.

    Returns
    -------
    ainv : (..., M, M) ndarray
        (Multiplicative) inverse of the matrix *a*.

    Note
    ----
    Broadcasting rules apply, see the :ref:`nlcpy.linalg <nlcpy_linalg>`
    documentation for details.

    Examples
    --------
    >>> import nlcpy as vp
    >>> from nlcpy import testing
    >>> a = vp.array([[1., 2.], [3., 4.]])
    >>> ainv = vp.linalg.inv(a)
    >>> vp.testing.assert_allclose(vp.dot(a, ainv), vp.eye(2), atol=1e-8, rtol=1e-5)
    >>> vp.testing.assert_allclose(vp.dot(ainv, a), vp.eye(2), atol=1e-8, rtol=1e-5)

    Inverses of several matrices can be computed at once:

    >>> a = vp.array([[[1., 2.], [3., 4.]], [[1, 3], [3, 5]]])
    >>> vp.linalg.inv(a)   # doctest: +SKIP
    array([[[-2.  ,  1.  ],
            [ 1.5 , -0.5 ]],
    <BLANKLINE>
           [[-1.25,  0.75],
            [ 0.75, -0.25]]])

    """
    a = nlcpy.asarray(a)
    # used to match the contiguous of result to numpy.
    c_order = a.flags.c_contiguous or sum([i > 1 for i in a.shape[:-2]]) < 2
    util._assertRankAtLeast2(a)
    util._assertNdSquareness(a)
    if a.dtype.char in 'FD':
        dtype = 'D'
        if a.dtype.char in 'fF':
            ainv_dtype = 'F'
        else:
            ainv_dtype = 'D'
    else:
        dtype = 'd'
        if a.dtype.char == 'f':
            ainv_dtype = 'f'
        else:
            ainv_dtype = 'd'
    if a.size == 0:
        return nlcpy.asarray(a, dtype=ainv_dtype)
    a = nlcpy.array(nlcpy.moveaxis(a, (-1, -2), (1, 0)),
                    dtype=dtype,
                    order='F')
    ipiv = nlcpy.empty(a.shape[-1])
    work = nlcpy.empty(a.shape[-1] * 256)
    info = numpy.empty(1, dtype='l')
    fpe = request._get_fpe_flag()
    args = (
        a._ve_array,
        ipiv._ve_array,
        work._ve_array,
        veo.OnStack(info, inout=veo.INTENT_OUT),
        veo.OnStack(fpe, inout=veo.INTENT_OUT),
    )

    request._push_and_flush_request('nlcpy_inv',
                                    args,
                                    callback=util._assertNotSingular(info))

    if c_order:
        a = nlcpy.moveaxis(a, (1, 0), (-1, -2))
        return nlcpy.asarray(a, dtype=ainv_dtype, order='C')
    else:
        a = nlcpy.asarray(a, dtype=ainv_dtype)
        return nlcpy.moveaxis(a, (1, 0), (-1, -2))
示例#26
0
文件: sort.py 项目: SX-Aurora/nlcpy
def argsort(a, axis=-1, kind=None, order=None):
    """Returns the indices that would sort an array.

    Perform an indirect sort along the given axis using the radix sort. It returns an
    array of indices of the same shape as *a* that index data along the given axis in
    sorted order.

    Parameters
    ----------
    a : array_like
        Array to sort.
    axis : int or None, optional
        Axis along which to sort. The default is -1 (the last axis). If None, the
        flattened array is used.
    kind : {'None','stable'}, optional
        Sorting algorithm. The default is 'stable', kind only supported 'stable'. ('None'
        is treated as 'stable'.)
    order : str or list of str, optional
        This argument is not supported. The default is 'None'.

    Returns
    -------
    index_array : ndarray
        Array of indices that sort *a* along the specified *axis*. If a is
        one-dimensional, ``a[index_array]`` yields a sorted *a*. More generally,

    Restriction
    -----------
    *NotImplementedError*:

      - If *kind* is not None and ``kind != 'stable'``.
      - If *order* is not None.
      - If 'c' is contained in *a.dtype.kind*.

    See Also
    --------
    sort : Describes sorting algorithms used.
    ndarray.sort : Method to sort an array in-place.

    Examples
    --------

    One dimensional array:

    >>> import nlcpy as vp
    >>> x = vp.array([3, 1, 2])
    >>> vp.argsort(x)
    array([1, 2, 0])

    Two-dimensional array:

    >>> x = vp.array([[0, 3], [2, 2]])
    >>> x
    array([[0, 3],
           [2, 2]])
    >>> ind = vp.argsort(x, axis=0)  # sorts along first axis (down)
    >>> ind
    array([[0, 1],
           [1, 0]])
    >>> ind = vp.argsort(x, axis=1)  # sorts along last axis (across)
    >>> ind
    array([[0, 1],
           [0, 1]])

    """
    a = nlcpy.asarray(a)
    if kind is not None and kind not in 'stable':
        raise NotImplementedError('kind only supported \'stable\'.')
    if order is not None:
        raise NotImplementedError('order is not implemented.')
    if a.dtype.kind in ('c', ):
        raise NotImplementedError('Unsupported dtype %s' % a.dtype)
    ret = a.argsort(axis=axis, kind=kind, order=order)
    return ret
示例#27
0
def delete(arr, obj, axis=None):
    """Returns a new array with sub-arrays along an axis deleted.

    For a one dimensional array, this returns those entries not returned by arr[obj].

    Parameters
    ----------
    arr : array_like
        Input array.
    obj : slice, int or array of ints
        Indicate indices of sub-arrays to remove along the specified axis.
    axis : int, optional
        The axis along which to delete the subarray defined by obj.
        If axis is None, obj is applied to the flattened array.

    Returns
    -------
    out : ndarray
        A copy of arr with the elements specified by obj removed.
        Note that delete does not occur in-place. If axis is None, out is a flattened
        array.

    Note
    ----
    Often it is preferable to use a boolean mask. For example:

    >>> import nlcpy as vp
    >>> arr = vp.arange(12) + 1
    >>> mask = vp.ones(len(arr), dtype=bool)
    >>> mask[[0,2,4]] = False
    >>> result = arr[mask,...]

    Is equivalent to vp.delete(arr, [0,2,4], axis=0), but allows further use of mask.

    See Also
    --------
    insert : Inserts values along the given axis before the given indices.
    append : Appends values to the end of an array.

    Examples
    --------
    >>> import nlcpy as vp
    >>> arr = vp.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
    >>> arr
    array([[ 1,  2,  3,  4],
           [ 5,  6,  7,  8],
           [ 9, 10, 11, 12]])
    >>> vp.delete(arr, 1, 0)
    array([[ 1,  2,  3,  4],
           [ 9, 10, 11, 12]])
    >>> vp.delete(arr, slice(None, None, 2), 1)
    array([[ 2,  4],
           [ 6,  8],
           [10, 12]])
    >>> vp.delete(arr, [1,3,5], None)
    array([ 1,  3,  5,  7,  8,  9, 10, 11, 12])

    """

    input_arr = nlcpy.asarray(arr)
    ndim = input_arr.ndim

    if input_arr._f_contiguous and not input_arr._c_contiguous:
        order_out = 'F'
    else:
        order_out = 'C'

    if axis is None:
        if ndim != 1:
            input_arr = input_arr.ravel()
        ndim = input_arr.ndim
        axis = ndim - 1

    if isinstance(axis, numpy.ndarray) or isinstance(axis, nlcpy.ndarray):
        axis = int(axis)
    elif not isinstance(axis, int):
        raise TypeError("an integer is required (got type "
                        + str(type(axis).__name__) + ")")

    if axis < -ndim or axis > ndim - 1:
        raise AxisError(
            "axis {} is out of bounds for array of dimension {}".format(axis, ndim))
    if axis < 0:
        axis += ndim

    N = input_arr.shape[axis]
    if isinstance(obj, slice):
        start, stop, step = obj.indices(N)
        xr = range(start, stop, step)
        if len(xr) == 0:
            return input_arr.copy(order=order_out)
        else:
            del_obj = nlcpy.arange(start, stop, step)
    else:
        del_obj = nlcpy.asarray(obj)
        if del_obj.ndim != 1:
            del_obj = del_obj.ravel()

        if del_obj.dtype == bool:
            if del_obj.ndim != 1 or del_obj.size != input_arr.shape[axis]:
                raise ValueError(
                    'boolean array argument obj to delete must be one dimensional and '
                    'match the axis length of {}'.format(input_arr.shape[axis]))
            del_obj = del_obj.astype(nlcpy.intp)

        if isinstance(obj, (int, nlcpy.integer)):
            if (obj < -N or obj >= N):
                raise IndexError(
                    "index %i is out of bounds for axis %i with "
                    "size %i" % (obj, axis, N))
            if (obj < 0):
                del_obj += N
        elif del_obj.size > 0 and del_obj.dtype != int:
            raise IndexError(
                'arrays used as indices must be of integer (or boolean) type')

    if del_obj.size == 0:
        new = nlcpy.array(input_arr)
        return new
    else:
        new = nlcpy.empty(input_arr.shape, input_arr.dtype, order_out)
        idx = nlcpy.ones(input_arr.shape[axis], dtype=del_obj.dtype)
        obj_count = nlcpy.zeros([3], dtype='l')
        request._push_request(
            'nlcpy_delete',
            'manipulation_op',
            (input_arr, del_obj, axis, idx, new, obj_count)
        )
        count = obj_count.get()
        if count[1] != 0:
            raise IndexError(
                "index out of bounds for axis {}".format(axis))
        if count[2] != 0:
            warnings.warn(
                "in the future negative indices will not be ignored by "
                "`numpy.delete`.", FutureWarning, stacklevel=3)
        sl = [slice(N - count[0]) if i == axis
              else slice(None) for i in range(new.ndim)]
        return new[sl].copy()
示例#28
0
def lstsq(a, b, rcond='warn'):
    """Returns the least-squares solution to a linear matrix equation.

    Solves the equation :math:`ax = b` by computing a vector *x* that minimizes the
    squared Euclidean 2-norm :math:`|b-ax|^2_2`. The equation may be under-, well-, or
    over-determined (i.e., the number of linearly independent rows of *a* can be less
    than, equal to, or greater than its number of linearly independent columns). If *a*
    is square and of full rank, then *x* (but for round-off error) is the "exact"
    solution of the equation.

    Parameters
    ----------
    a : (M,N) array_like
        "Coefficient" matrix.
    b : {(M,), (M, K)} array_like
        Ordinate or "dependent variable" values. If *b* is two-dimensional, the
        least-squares solution is calculated for each of the *K* columns of *b*.
    rcond : float, optional
        Cut-off ratio for small singular values of *a*. For the purposes of rank
        determination, singular values are treated as zero if they are smaller than
        *rcond* times the largest singular value of *a*.

    Returns
    -------
    x : {(N,), (N, K)} ndarray
        Least-squares solution. If *b* is two-dimensional, the solutions are in the *K*
        columns of *x*.
    residuals : {(1,), (K,), (0,)} ndarray
        Sums of residuals; squared Euclidean 2-norm for each column in ``b - a@x``. If
        the rank of *a* is < N or M <= N, this is an empty array. If *b* is
        1-dimensional, this is a (1,) shape array. Otherwise the shape is (K,).
    rank : *int*
        Rank of matrix *a*.
    s : (min(M, N),) ndarray
        Singular values of *a*.

    Note
    ----
    If `b` is a matrix, then all array results are returned as matrices.

    Examples
    --------
    .. plot::
        :align: center

        Fit a line, ``y = mx + c``, through some noisy data-points:

        >>> import nlcpy as vp
        >>> x = vp.array([0, 1, 2, 3])
        >>> y = vp.array([-1, 0.2, 0.9, 2.1])

        By examining the coefficients, we see that the line should have a gradient of
        roughly 1 and cut the y-axis at, more or less, -1.
        We can rewrite the line equation as ``y = Ap``, where ``A = [[x 1]]`` and
        ``p = [[m], [c]]``. Now use lstsq to solve for *p*:

        >>> A = vp.array((x, vp.ones(len(x)))).T
        >>> A
        array([[0., 1.],
               [1., 1.],
               [2., 1.],
               [3., 1.]])
        >>> m, c = vp.linalg.lstsq(A, y, rcond=None)[0]
        >>> m, c  # doctest: +SKIP
        (array(1.), array(-0.95)) # may vary

        Plot the data along with the fitted line:

        >>> import matplotlib.pyplot as plt
        >>> _ = plt.plot(x, y, 'o', label='Original data', markersize=15)
        >>> _ = plt.plot(x, m*x + c, 'r', label='Fitted line')
        >>> _ = plt.legend()
        >>> plt.show()

    """
    a = nlcpy.asarray(a)
    b = nlcpy.asarray(b)
    b_ndim = b.ndim
    if b_ndim == 1:
        b = b[:, nlcpy.newaxis]
    util._assertRank2(a, b)

    if a.shape[-2] != b.shape[-2]:
        raise util.LinAlgError('Incompatible dimensions')

    a_complex = a.dtype.char in 'FD'
    b_complex = b.dtype.char in 'FD'
    if a_complex or b_complex:
        if a.dtype.char in 'fF' and b.dtype.char in 'fF':
            x_dtype = 'F'
            f_dtype = 'f'
        else:
            x_dtype = 'D'
            f_dtype = 'd'
    else:
        if a.dtype.char == 'f' and b.dtype.char == 'f':
            x_dtype = 'f'
            f_dtype = 'f'
        else:
            x_dtype = 'd'
            f_dtype = 'd'

    m = a.shape[-2]
    n = a.shape[-1]
    k = b.shape[-1]
    minmn = min(m, n)
    maxmn = max(m, n)
    k_extend = (k == 0)
    if k_extend:
        b = nlcpy.zeros([m, 1], dtype=b.dtype)
        k = 1
    if minmn == 0:
        if n > 0:
            x = nlcpy.zeros([n, k], dtype=x_dtype)
            residuals = nlcpy.array([], dtype=f_dtype)
        else:
            x = nlcpy.array([], dtype=x_dtype)
            if b_complex:
                br = nlcpy.asarray(b.real, dtype='d')
                bi = nlcpy.asarray(b.imag, dtype='d')
                square_b = nlcpy.power(br, 2) + nlcpy.power(bi, 2)
            else:
                square_b = nlcpy.power(b, 2, dtype='d')
            residuals = nlcpy.add.reduce(square_b, dtype=f_dtype)
        return (x, residuals, 0, nlcpy.array([], dtype=f_dtype))

    if rcond == 'warn':
        rcond = -1.0
    if rcond is None:
        rcond = nlcpy.finfo(x_dtype).eps * max(m, n)
    rcond = nlcpy.asarray(rcond, dtype=f_dtype)

    a = nlcpy.array(a, dtype=x_dtype, order='F')
    if m < n:
        _b = nlcpy.empty([n, k], dtype=x_dtype, order='F')
        _b[:m, :] = b
        b = _b
    else:
        b = nlcpy.array(b, dtype=x_dtype, order='F')
    s = nlcpy.empty(min(m, n), dtype=f_dtype)
    rank = numpy.empty(1, dtype='l')

    nlvl = max(0, int(nlcpy.log(minmn / 26.0) / nlcpy.log(2)) + 1)
    mnthr = int(minmn * 1.6)
    mm = m
    lwork = 1
    if a_complex:
        _tmp = 2
        wlalsd = minmn * k
        lrwork = 10 * maxmn + 2 * maxmn * 25 + 8 * maxmn * nlvl + 3 * 25 * k \
                            + max(26 ** 2, n * (1 + k) + 2 * k)
    else:
        _tmp = 3
        wlalsd = 9 * minmn + 2 * minmn * 25 + 8 * minmn * nlvl + minmn * k + 26**2
        lrwork = 1

    if m >= n:
        if m >= mnthr:
            mm = n
            lwork = max(65 * n, n + 32 * k)
        lwork = max(lwork, _tmp * n + (mm + n) * 64, _tmp * n + 32 * k,
                    _tmp * n + 32 * n - 32, _tmp * n + wlalsd)
    else:
        if n >= mnthr:
            lwork = max(lwork, m * m + 4 * m + wlalsd, m * m + 132 * m,
                        m * m + 4 * m + 32 * k, m * m + (k + 1) * m,
                        m * m + n + m)
        else:
            lwork = max(lwork, 3 * m + wlalsd, 3 * m + 64 * (n + m),
                        3 * m + 32 * k)

    liwork = minmn * (11 + 3 * nlvl)
    work = nlcpy.empty(lwork)
    iwork = nlcpy.empty(liwork, dtype='l')
    rwork = nlcpy.empty(lrwork, dtype=f_dtype)
    info = numpy.empty(1, dtype='l')
    fpe = request._get_fpe_flag()
    args = (
        a._ve_array,
        b._ve_array,
        s._ve_array,
        work._ve_array,
        iwork._ve_array,
        rwork._ve_array,
        rcond._ve_array,
        veo.OnStack(rank, inout=veo.INTENT_OUT),
        veo.OnStack(info, inout=veo.INTENT_OUT),
        veo.OnStack(fpe, inout=veo.INTENT_OUT),
    )

    request._push_and_flush_request('nlcpy_lstsq',
                                    args,
                                    callback=_lstsq_errchk(info),
                                    sync=True)

    if rank < n or m <= n:
        residuals = nlcpy.array([], dtype=f_dtype)
    else:
        _b = b[n:]
        square_b = nlcpy.power(_b.real, 2) + nlcpy.power(_b.imag, 2)
        residuals = nlcpy.add.reduce(square_b, dtype=f_dtype)
    if k_extend:
        x = b[..., :0]
        residuals = residuals[..., :0]
    elif b_ndim == 1:
        x = nlcpy.asarray(b[:n, 0], dtype=x_dtype, order='C')
    else:
        x = nlcpy.asarray(b[:n, :], dtype=x_dtype, order='C')

    return (x, residuals, rank[0], s)
示例#29
0
def cholesky(a):
    """Cholesky decomposition.

    Return the Cholesky decomposition, *L* * *L.H*, of the square matrix *a*, where *L*
    is lower-triangular and *.H* is the conjugate transpose operator (which is the
    ordinary transpose if *a* is real-valued). *a* must be Hermitian (symmetric if
    real-valued) and positive-definite. Only *L* is actually returned.

    Parameters
    ----------
    a : (..., M, M) array_like
        Hermitian (symmetric if all elements are real), positive-definite input matrix.

    Returns
    -------
    L : (..., M, M) ndarray
        Upper or lower-triangular Cholesky factor of *a*.

    Note
    ----
    The Cholesky decomposition is often used as a fast way of solving :math:`Ax = b`

    (when *A* is both Hermitian/symmetric and positive-definite).

    First, we solve for y in :math:`Ly = b`, and then for x in :math:`L.Hx = y`.

    Examples
    --------
    >>> import nlcpy as vp
    >>> A = vp.array([[1,-2j],[2j,5]])
    >>> A
    array([[ 1.+0.j, -0.-2.j],
           [ 0.+2.j,  5.+0.j]])
    >>> L = vp.linalg.cholesky(A)
    >>> L
    array([[1.+0.j, 0.+0.j],
           [0.+2.j, 1.+0.j]])
    >>> vp.dot(L, vp.conjugate(L.T)) # verify that L * L.H = A
    array([[1.+0.j, 0.-2.j],
           [0.+2.j, 5.+0.j]])

    """
    a = nlcpy.asarray(a)
    util._assertRankAtLeast2(a)
    util._assertNdSquareness(a)

    if a.dtype == 'F':
        dtype = 'D'
        L_dtype = 'F'
    elif a.dtype == 'D':
        dtype = 'D'
        L_dtype = 'D'
    elif a.dtype == 'f':
        dtype = 'd'
        L_dtype = 'f'
    else:
        dtype = 'd'
        L_dtype = 'd'

    if a.size == 0:
        return nlcpy.empty(a.shape, dtype=L_dtype)

    # used to match the contiguous of result to numpy.
    c_order = a.flags.c_contiguous or sum([i > 1 for i in a.shape[:-2]]) < 2

    a = nlcpy.array(nlcpy.moveaxis(a, (-1, -2), (1, 0)),
                    dtype=dtype,
                    order='F')
    info = numpy.empty(1, dtype='l')
    fpe = request._get_fpe_flag()
    args = (
        a._ve_array,
        veo.OnStack(info, inout=veo.INTENT_OUT),
        veo.OnStack(fpe, inout=veo.INTENT_OUT),
    )

    request._push_and_flush_request(
        'nlcpy_cholesky', args, callback=util._assertPositiveDefinite(info))

    if c_order:
        L = nlcpy.asarray(nlcpy.moveaxis(a, (1, 0), (-1, -2)),
                          dtype=L_dtype,
                          order='C')
    else:
        L = nlcpy.moveaxis(nlcpy.asarray(a, dtype=L_dtype), (1, 0), (-1, -2))
    return L