예제 #1
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()
예제 #2
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)
예제 #3
0
 def test_ifft2(self):
     x = random((30, 20)) + 1j * random((30, 20))
     assert_allclose(np.fft.ifft(np.fft.ifft(x, axis=1), axis=0),
                     np.fft.ifft2(x),
                     atol=1e-6)
     assert_allclose(np.fft.ifft2(x) * np.sqrt(30 * 20),
                     np.fft.ifft2(x, norm="ortho"),
                     atol=1e-6)
예제 #4
0
 def test_fftn(self):
     x = random((30, 20, 10)) + 1j * random((30, 20, 10))
     assert_allclose(np.fft.fft(np.fft.fft(np.fft.fft(x, axis=2), axis=1),
                                axis=0),
                     np.fft.fftn(x),
                     atol=1e-6)
     assert_allclose(np.fft.fftn(x) / np.sqrt(30 * 20 * 10),
                     np.fft.fftn(x, norm="ortho"),
                     atol=1e-6)
예제 #5
0
 def test_hfft(self):
     x = random(14) + 1j * random(14)
     x_herm = np.concatenate((random(1), x, random(1)))
     # x = np.concatenate((x_herm, x[::-1].conj()))
     x = np.concatenate((x_herm, np.conj(x[::-1])))
     assert_allclose(np.fft.fft(x), np.fft.hfft(x_herm), atol=1e-6)
     assert_allclose(np.fft.hfft(x_herm) / np.sqrt(30),
                     np.fft.hfft(x_herm, norm="ortho"),
                     atol=1e-6)
예제 #6
0
 def test_rfft(self):
     x = random(30)
     for n in [x.size, 2 * x.size]:
         for norm in [None, 'ortho']:
             assert_allclose(np.fft.fft(x, n=n, norm=norm)[:(n // 2 + 1)],
                             np.fft.rfft(x, n=n, norm=norm),
                             atol=1e-6)
         assert_allclose(np.fft.rfft(x, n=n) / np.sqrt(n),
                         np.fft.rfft(x, n=n, norm="ortho"),
                         atol=1e-6)
예제 #7
0
 def test_fft(self):
     x = random(30) + 1j * random(30)
     assert_allclose(fft1(x), np.fft.fft(x), atol=1e-6)
     assert_allclose(fft1(x) / np.sqrt(30),
                     np.fft.fft(x, norm="ortho"),
                     atol=1e-6)
예제 #8
0
 def test_rfftn(self):
     x = random((30, 20, 10))
     assert_allclose(np.fft.fftn(x)[:, :, :6], np.fft.rfftn(x), atol=1e-6)
     assert_allclose(np.fft.rfftn(x) / np.sqrt(30 * 20 * 10),
                     np.fft.rfftn(x, norm="ortho"),
                     atol=1e-6)
예제 #9
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.")