Repository: scipy/scipy
File: scipy/special/_basic.py (Python)

Code before:
    -----
    - Array arguments accepted only for exact=False case.
    - If N < 0, or k < 0, then 0 is returned.
    - If k > N and repetition=False, then 0 is returned.

    Examples
    --------
    >>> import numpy as np
    >>> from scipy.special import comb
    >>> k = np.array([3, 4])
    >>> n = np.array([10, 10])
    >>> comb(n, k, exact=False)
    array([ 120.,  210.])
    >>> comb(10, 3, exact=True)
    120
    >>> comb(10, 3, exact=True, repetition=True)
    220

    """
    if repetition:
        # Special case: C(n, 0) with repetition = 1 for n >= 0
        # Without this check, comb(0, 0, repetition=True) would compute
        # comb(-1, 0) which incorrectly returns 0
        if exact:
            if int(k) == k and k == 0 and int(N) == N and N >= 0:
                return 1
        else:
            if np.isscalar(k) and k == 0 and np.isscalar(N) and N >= 0:
                return np.float64(1.0)
        return comb(N + k - 1, k, exact=exact)
    if exact:
        if int(N) == N and int(k) == k:
            # _comb_int casts inputs to integers, which is safe & intended here
            return _comb_int(N, k)
        else:
            raise ValueError("Non-integer `N` and `k` with `exact=True` is not "
                             "supported.")
    else:
        k, N = asarray(k), asarray(N)
        cond = (k <= N) & (N >= 0) & (k >= 0)
        vals = binom(N, k)
        if isinstance(vals, np.ndarray):
            vals[~cond] = 0
        elif not cond:
            vals = np.float64(0)
        return vals


def perm(N, k, exact=False):
    """Permutations of N things taken k at a time, i.e., k-permutations of N.


Review comment (suggestion):
The `int(k) == k` check is redundant

```suggestion
            if k == 0 and int(N) == N and N >= 0:
                return 1
```

Code after:
    -----
    - Array arguments accepted only for exact=False case.
    - If N < 0, or k < 0, then 0 is returned.
    - If k > N and repetition=False, then 0 is returned.

    Examples
    --------
    >>> import numpy as np
    >>> from scipy.special import comb
    >>> k = np.array([3, 4])
    >>> n = np.array([10, 10])
    >>> comb(n, k, exact=False)
    array([ 120.,  210.])
    >>> comb(10, 3, exact=True)
    120
    >>> comb(10, 3, exact=True, repetition=True)
    220

    """
    if repetition:
        # Special case: C(n, 0) with repetition = 1 for n >= 0
        # Without this check, comb(0, 0, repetition=True) would compute
        # comb(-1, 0) which incorrectly returns 0
        if exact:
            if k == 0 and int(N) == N and N >= 0:
                return 1
        else:
            k, N = asarray(k), asarray(N)
            cond = (k == 0) & (N >= 0)
            vals = binom(N + k - 1, k)
            if isinstance(vals, np.ndarray):
                vals[cond] = 1.0
            elif cond:
                vals = np.float64(1.0)
            return vals
        return comb(N + k - 1, k, exact=exact)
    if exact:
        if int(N) == N and int(k) == k:
            # _comb_int casts inputs to integers, which is safe & intended here
            return _comb_int(N, k)
        else:
            raise ValueError("Non-integer `N` and `k` with `exact=True` is not "
                             "supported.")
    else:
        k, N = asarray(k), asarray(N)
        cond = (k <= N) & (N >= 0) & (k >= 0)
        vals = binom(N, k)
        if isinstance(vals, np.ndarray):
            vals[~cond] = 0
        elif not cond:
            vals = np.float64(0)