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()
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)
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)
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)
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)
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)
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)
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)
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.")