def _promote_dtype(x): if x.dtype.kind in 'bui': # use float64 instead of promote_types to match SciPy's behavior float_dtype = cupy.float64 else: float_dtype = cupy.promote_types(x.dtype, cupy.float32) return x.astype(float_dtype, copy=False)
def _convolve( in1, in2, use_convolve, swapped_inputs, mode, cp_stream, autosync, ): val = _valfrommode(mode) # Promote inputs promType = cp.promote_types(in1.dtype, in2.dtype) in1 = in1.astype(promType) in2 = in2.astype(promType) # Create empty array to hold number of aout dimensions out_dimens = np.empty(in1.ndim, np.int) if val == VALID: for i in range(in1.ndim): out_dimens[i] = (max(in1.shape[i], in2.shape[i]) - min(in1.shape[i], in2.shape[i]) + 1) if out_dimens[i] < 0: raise Exception( "no part of the output is valid, use option 1 (same) or 2 \ (full) for third argument") elif val == SAME: for i in range(in1.ndim): if not swapped_inputs: out_dimens[i] = in1.shape[i] # Per scipy docs else: out_dimens[i] = min(in1.shape[i], in2.shape[i]) elif val == FULL: for i in range(in1.ndim): out_dimens[i] = in1.shape[i] + in2.shape[i] - 1 else: raise Exception("mode must be 0 (valid), 1 (same), or 2 (full)") # Create empty array out on GPU out = cp.empty(out_dimens.tolist(), in1.dtype) out = _convolve_gpu( in1, out, in2, val, use_convolve, swapped_inputs, cp_stream, ) if autosync is True: cp_stream.synchronize() return out
def _get_spline_output(input, output): """Create workspace array, temp, and the final dtype for the output. Differs from SciPy by not always forcing the internal floating point dtype to be double precision. """ complex_data = input.dtype.kind == 'c' if complex_data: min_float_dtype = cupy.complex64 else: min_float_dtype = cupy.float32 if isinstance(output, cupy.ndarray): if complex_data and output.dtype.kind != 'c': raise ValueError( 'output must have complex dtype for complex inputs' ) float_dtype = cupy.promote_types(output.dtype, min_float_dtype) output_dtype = output.dtype else: if output is None: output = output_dtype = input.dtype else: output_dtype = cupy.dtype(output) float_dtype = cupy.promote_types(output, min_float_dtype) if (isinstance(output, cupy.ndarray) and output.dtype == float_dtype == output_dtype and output.flags.c_contiguous): if output is not input: output[...] = input[...] temp = output else: temp = input.astype(float_dtype, copy=False) temp = cupy.ascontiguousarray(temp) if cupy.shares_memory(temp, input, 'MAY_SHARE_BOUNDS'): temp = temp.copy() return temp, float_dtype, output_dtype
def channelize_poly(x, h, n_chans): """ Polyphase channelize signal into n channels Parameters ---------- x : array_like The input data to be channelized h : array_like The 1-D input filter; will be split into n channels of int number of taps n_chans : int Number of channels for channelizer Returns ---------- yy : channelized output matrix Notes ---------- Currently only supports simple channelizer where channel spacing is equivalent to the number of channels used (zero overlap). Number of filter taps (len of filter / n_chans) must be <=32. """ dtype = cp.promote_types(x.dtype, h.dtype) x = asarray(x, dtype=dtype) h = asarray(h, dtype=dtype) # number of taps in each h_n filter n_taps = int(len(h) / n_chans) if n_taps > 32: raise NotImplementedError( "The number of calculated taps ({}) in \ each filter is currently capped at 32. Please reduce filter \ length or number of channels".format( n_taps ) ) if n_taps > 32: raise NotImplementedError( "Number of taps ({}) must be less than (32).".format(n_taps) ) # number of outputs n_pts = int(len(x) / n_chans) if x.dtype == cp.float32 or x.dtype == cp.complex64: y = cp.empty((n_pts, n_chans), dtype=cp.complex64) elif x.dtype == cp.float64 or x.dtype == cp.complex128: y = cp.empty((n_pts, n_chans), dtype=cp.complex128) _channelizer(x, h, y, n_chans, n_taps, n_pts) # Remove with CuPy v8 if (x.dtype, n_pts, n_taps, n_chans) in _cupy_fft_cache: plan = _cupy_fft_cache[(x.dtype, n_pts, n_taps, n_chans)] else: plan = _cupy_fft_cache[ (x.dtype, n_pts, n_taps, n_chans) ] = fftpack.get_fft_plan(y, axes=-1) return cp.conj(fftpack.fft(y, overwrite_x=True, plan=plan)).T
def _dct_or_dst_type3(x, n=None, axis=-1, norm=None, forward=True, dst=False, overwrite_x=False): """Forward DCT/DST-III (or inverse DCT/DST-II) along a single axis. Parameters ---------- x : cupy.ndarray The data to transform. n : int The size of the transform. If None, ``x.shape[axis]`` is used. axis : int Axis along which the transform is applied. forward : bool Set true to indicate that this is a forward DCT-II as opposed to an inverse DCT-III (The difference between the two is only in the normalization factor). norm : {None, 'ortho', 'forward', 'backward'} The normalization convention to use. dst : bool If True, a discrete sine transform is computed rather than the discrete cosine transform. overwrite_x : bool Indicates that it is okay to overwrite x. In practice, the current implementation never performs the transform in-place. Returns ------- y: cupy.ndarray The transformed array. """ if axis < -x.ndim or axis >= x.ndim: raise numpy.AxisError('axis out of range') if axis < 0: axis += x.ndim if n is not None and n < 1: raise ValueError(f'invalid number of data points ({n}) specified') x = _cook_shape(x, (n, ), (axis, ), 'R2R') n = x.shape[axis] # determine normalization factor if norm == 'ortho': sl0_scale = 0.5 * math.sqrt(2) inorm = 'sqrt' elif norm == 'forward': sl0_scale = 0.5 inorm = 'full' if forward else 'none' elif norm == 'backward' or norm is None: sl0_scale = 0.5 inorm = 'none' if forward else 'full' else: raise ValueError(f'Invalid norm value "{norm}", should be "backward", ' '"ortho" or "forward"') norm_factor = _get_dct_norm_factor(n, inorm=inorm, dct_type=3) dtype = cupy.promote_types(x, cupy.complex64) sl0 = [slice(None)] * x.ndim sl0[axis] = slice(1) if dst: if norm == 'ortho': float_dtype = cupy.promote_types(x.dtype, cupy.float32) if x.dtype != float_dtype: x = x.astype(float_dtype) elif not overwrite_x: x = x.copy() x[tuple(sl0)] *= math.sqrt(2) sl0_scale = 0.5 slrev = [slice(None)] * x.ndim slrev[axis] = slice(None, None, -1) x = x[tuple(slrev)] # scale by exponentials and normalization factor tmp = _exp_factor_dct3(x, n, axis, dtype, norm_factor) x = x * tmp # broadcasting x[tuple(sl0)] *= sl0_scale # inverse fft x = _fft.ifft(x, n=n, axis=axis, overwrite_x=True) x = cupy.real(x) # reorder entries return _reshuffle_dct3(x, n, axis, dst)