def METHOD_NAME(apad, w_np_fc):
    """2d convolution operator in HW layout.
    This is intended to be used as a subroutine from
    _conv2d_nchw_python.  Using scipy.signal.convolve2d directly does
    not work for all dtypes (e.g. float16).  Where possible, this
    function uses scipy.signal.convolve2d to take advantage of
    compiled scipy routines, falling back to an explicit loop only
    where needed
    Parameters
    ----------
    a_np : numpy.ndarray
        2-D with shape [in_height, in_width]
    w_np : numpy.ndarray
        2-D with shape [filter_height, filter_width].
    Returns
    -------
    b_np : np.ndarray
        2-D with shape [out_height, out_width]
    """
    try:
        return scipy.signal.convolve2d(apad, np.rot90(np.rot90(w_np_fc)), mode="valid")
    except ValueError:
        pass
    assert len(apad.shape) == len(w_np_fc.shape) == 2
    dtype = apad.dtype
    in_height, in_width = apad.shape
    kernel_h, kernel_w = w_np_fc.shape
    output_shape = [a_dim - w_dim + 1 for a_dim, w_dim in zip(apad.shape, w_np_fc.shape)]
    output = np.zeros(output_shape, dtype=apad.dtype)
    for y in range(output_shape[0]):
        for x in range(output_shape[1]):
            output[y][x] = np.sum(apad[y : y + kernel_h, x : x + kernel_w] * w_np_fc)
    return output