示例#1
0
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)
示例#2
0
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
示例#3
0
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
示例#4
0
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
示例#5
0
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)