jiahuimbzuai/CoQuIR huggingface dataset:
//  [python]
def _munp(self, n, c):
        def __munp(n, c):
            val = 0.0
            k = arange(0, n + 1)
            for ki, cnk in zip(k, s.comb(n, k)):
                val = val + cnk * (-1) ** ki / (1.0 - c * ki)
            return where(c * n < 1, val * (-1.0 / c) ** n, inf)
        return _lazywhere(c != 0, (c,),
                lambda c: __munp(n, c),
                gam(n + 1))
//  [python]
def _munp(self, n, c):
        def __munp(n, c):
            val = 0.0
            k = arange(0, n + 1)
            for ki, cnk in zip(k, comb(n, k)):
                val = val + cnk * (-1) ** ki / (1.0 - c * ki)
            return where(c * n < 1, val * (-1.0 / c) ** n, inf)
        return _lazywhere(c != 0, (c,),
                lambda c: __munp(n, c),
                gam(n + 1))
//  [python]
def _munp(self, n, c):
        k = np.arange(0, n+1)
        vals = 1.0/c**n * np.sum(
            s.comb(n, k) * (-1)**k * sc.gamma(c*k + 1),
            axis=0)
        return np.where(c*n > -1, vals, np.inf)
//  [python]
def _munp(self, n, c):
        k = np.arange(0, n+1)
        vals = 1.0/c**n * np.sum(
            sc.comb(n, k) * (-1)**k * sc.gamma(c*k + 1),
            axis=0)
        return np.where(c*n > -1, vals, np.inf)
//  [python]
def _munp(self, n, c):
        def __munp(n, c):
            val = 0.0
            k = np.arange(0, n + 1)
            for ki, cnk in zip(k, s.comb(n, k)):
                val = val + cnk * (-1) ** ki / (1.0 - c * ki)
            return np.where(c * n < 1, val * (-1.0 / c) ** n, np.inf)
        return _lazywhere(c != 0, (c,),
                          lambda c: __munp(n, c),
                          s.gamma(n + 1))
//  [python]
def _munp(self, n, c):
        def __munp(n, c):
            val = 0.0
            k = np.arange(0, n + 1)
            for ki, cnk in zip(k, sc.comb(n, k)):
                val = val + cnk * (-1) ** ki / (1.0 - c * ki)
            return np.where(c * n < 1, val * (-1.0 / c) ** n, np.inf)
        return _lazywhere(c != 0, (c,),
                          lambda c: __munp(n, c),
                          sc.gamma(n + 1))
//  [python]
def BuildGammaSet(gamma_best, biggest_normal, num_abnormal, numb_all_abn, exp_num_G, chrom1_line,prob_zero):
	gamma_set = []
	if gamma_best == 0:
		p = ((biggest_normal)/float(len(chrom1_line)))
		P_G = math.log(int(scipy.misc.comb(numb_all_abn,num_abnormal, exact=1)))+math.log(p)*num_abnormal+math.log(1-p)*(numb_all_abn-num_abnormal)
	else:
		P_G = scipy.stats.distributions.poisson.logpmf(num_abnormal,exp_num_G*int(gamma_best))
	gamma_set.append(gamma_best)
	gamma = gamma_best+1
	P_G_plus = scipy.stats.distributions.poisson.logpmf(num_abnormal,exp_num_G*int(gamma))
	count = 0
	while  P_G_plus > -80 and count<2:
	#while  P_G_plus > 10**(-3) and count<4:
		count+=1
		logger.debug('P_G_plus ='+str(P_G_plus))
		logger.debug('gamma = '+str(gamma))
		gamma_set.append(gamma)
		gamma = gamma +1
		P_G_plus = scipy.stats.distributions.poisson.logpmf(num_abnormal,exp_num_G*int(gamma))
	gamma = gamma_best - 1
	P_G_minus = scipy.stats.distributions.poisson.logpmf(num_abnormal,exp_num_G*int(gamma))
	count = 0
	while  P_G_minus > -80 and count<2:
	#while  P_G_minus > 10**(-3) and count<4:
		gamma_set.append(gamma)
		gamma = gamma - 1
		logger.debug('P_G_minus ='+str(P_G_minus))
		logger.debug('gamma = '+str(gamma))
		if gamma != 0:
			P_G_minus = scipy.stats.distributions.poisson.logpmf(num_abnormal,exp_num_G*int(gamma))
		elif gamma==0:

			p = biggest_normal / float(len(chrom1_line))
			P_G_minus = math.log(int(scipy.misc.comb(numb_all_abn,num_abnormal, exact=1)))*math.log(p)*num_abnormal*math.log(1-p)*numb_all_abn
			#P_G_minus = lg(int(scipy.misc.comb(numb_all_abn,num_abnormal, exact=1))*p**num_abnormal*(1-p)**numb_all_abn
	if 0 not in gamma_set:
		logger.debug('I added 0 to gamma illegaly')
		gamma_set.append(0)
	logger.debug('gamma_best = '+str(gamma_best)+' gamma_set = '+str(gamma_set))
	return gamma_set
//  [python]
def BuildGammaSet(gamma_best, biggest_normal, num_abnormal, numb_all_abn, exp_num_G, chrom1_line,prob_zero):
	gamma_set = []
	if gamma_best == 0:
		p = ((biggest_normal)/float(len(chrom1_line)))
		P_G = math.log(int(scipy.special.comb(numb_all_abn,num_abnormal, exact=1)))+math.log(p)*num_abnormal+math.log(1-p)*(numb_all_abn-num_abnormal)
	else:
		P_G = scipy.stats.distributions.poisson.logpmf(num_abnormal,exp_num_G*int(gamma_best))
	gamma_set.append(gamma_best)
	gamma = gamma_best+1
	P_G_plus = scipy.stats.distributions.poisson.logpmf(num_abnormal,exp_num_G*int(gamma))
	count = 0
	while  P_G_plus > -80 and count<2:
	#while  P_G_plus > 10**(-3) and count<4:
		count+=1
		logger.debug('P_G_plus ='+str(P_G_plus))
		logger.debug('gamma = '+str(gamma))
		gamma_set.append(gamma)
		gamma = gamma +1
		P_G_plus = scipy.stats.distributions.poisson.logpmf(num_abnormal,exp_num_G*int(gamma))
	gamma = gamma_best - 1
	P_G_minus = scipy.stats.distributions.poisson.logpmf(num_abnormal,exp_num_G*int(gamma))
	count = 0
	while  P_G_minus > -80 and count<2:
	#while  P_G_minus > 10**(-3) and count<4:
		gamma_set.append(gamma)
		gamma = gamma - 1
		logger.debug('P_G_minus ='+str(P_G_minus))
		logger.debug('gamma = '+str(gamma))
		if gamma != 0:
			P_G_minus = scipy.stats.distributions.poisson.logpmf(num_abnormal,exp_num_G*int(gamma))
		elif gamma==0:

			p = biggest_normal / float(len(chrom1_line))
			P_G_minus = math.log(int(scipy.special.comb(numb_all_abn,num_abnormal, exact=1)))*math.log(p)*num_abnormal*math.log(1-p)*numb_all_abn
			#P_G_minus = lg(int(scipy.misc.comb(numb_all_abn,num_abnormal, exact=1))*p**num_abnormal*(1-p)**numb_all_abn
	if 0 not in gamma_set:
		logger.debug('I added 0 to gamma illegaly')
		gamma_set.append(0)
	logger.debug('gamma_best = '+str(gamma_best)+' gamma_set = '+str(gamma_set))
	return gamma_set
//  [python]
def _cdf_without_replacement(i, n, N):
    return s.comb(i, n) / s.comb(N, n)
//  [python]
def _cdf_without_replacement(i, n, N):
    return scipy.special.comb(i, n) / scipy.special.comb(N, n)
//  [python]
def _ell(A, m):
    """
    A helper function for expm_2009.

    Parameters
    ----------
    A : linear operator
        A linear operator whose norm of power we care about.
    m : int
        The power of the linear operator

    Returns
    -------
    value : int
        A value related to a bound.

    """
    if len(A.shape) != 2 or A.shape[0] != A.shape[1]:
        raise ValueError('expected A to be like a square matrix')

    # The c_i are explained in (2.2) and (2.6) of the 2005 expm paper.
    # They are coefficients of terms of a generating function series expansion.
    choose_2m_m = s.comb(2*m, m, exact=True)
    abs_c_recip = float(choose_2m_m) * float_factorial(2*m + 1)

    # This is explained after Eq. (1.2) of the 2009 expm paper.
    # It is the "unit roundoff" of IEEE double precision arithmetic.
    u = 2**-53

    # Compute the one-norm of matrix power p of abs(A).
    A_abs_onenorm = _onenorm_matrix_power_nnm(abs(A), 2*m + 1)

    # Treat zero norm as a special case.
    if not A_abs_onenorm:
        return 0

    alpha = A_abs_onenorm / (_onenorm(A) * abs_c_recip)
    log2_alpha_div_u = np.log2(alpha/u)
    value = int(np.ceil(log2_alpha_div_u / (2 * m)))
    return max(value, 0)
//  [python]
def _ell(A, m):
    """
    A helper function for expm_2009.

    Parameters
    ----------
    A : linear operator
        A linear operator whose norm of power we care about.
    m : int
        The power of the linear operator

    Returns
    -------
    value : int
        A value related to a bound.

    """
    if len(A.shape) != 2 or A.shape[0] != A.shape[1]:
        raise ValueError('expected A to be like a square matrix')

    # The c_i are explained in (2.2) and (2.6) of the 2005 expm paper.
    # They are coefficients of terms of a generating function series expansion.
    choose_2m_m = scipy.special.comb(2*m, m, exact=True)
    abs_c_recip = float(choose_2m_m) * float_factorial(2*m + 1)

    # This is explained after Eq. (1.2) of the 2009 expm paper.
    # It is the "unit roundoff" of IEEE double precision arithmetic.
    u = 2**-53

    # Compute the one-norm of matrix power p of abs(A).
    A_abs_onenorm = _onenorm_matrix_power_nnm(abs(A), 2*m + 1)

    # Treat zero norm as a special case.
    if not A_abs_onenorm:
        return 0

    alpha = A_abs_onenorm / (_onenorm(A) * abs_c_recip)
    log2_alpha_div_u = np.log2(alpha/u)
    value = int(np.ceil(log2_alpha_div_u / (2 * m)))
    return max(value, 0)
//  [python]
def from_bernstein_basis(cls, bp, extrapolate=None):
        """
        Construct a piecewise polynomial in the power basis
        from a polynomial in Bernstein basis.

        Parameters
        ----------
        bp : BPoly
            A Bernstein basis polynomial, as created by BPoly
        extrapolate : bool or 'periodic', optional
            If bool, determines whether to extrapolate to out-of-bounds points
            based on first and last intervals, or to return NaNs.
            If 'periodic', periodic extrapolation is used. Default is True.
        """
        if not isinstance(bp, BPoly):
            raise TypeError(".from_bernstein_basis only accepts BPoly instances. "
                            "Got %s instead." % type(bp))

        dx = np.diff(bp.x)
        k = bp.c.shape[0] - 1  # polynomial order

        rest = (None,)*(bp.c.ndim-2)

        c = np.zeros_like(bp.c)
        for a in range(k+1):
            factor = (-1)**a * s.comb(k, a) * bp.c[a]
            for s in range(a, k+1):
                val = s.comb(k-a, s-a) * (-1)**s
                c[k-s] += factor * val / dx[(slice(None),)+rest]**s

        if extrapolate is None:
            extrapolate = bp.extrapolate

        return cls.construct_fast(c, bp.x, extrapolate, bp.axis)
//  [python]
def from_bernstein_basis(cls, bp, extrapolate=None):
        """
        Construct a piecewise polynomial in the power basis
        from a polynomial in Bernstein basis.

        Parameters
        ----------
        bp : BPoly
            A Bernstein basis polynomial, as created by BPoly
        extrapolate : bool or 'periodic', optional
            If bool, determines whether to extrapolate to out-of-bounds points
            based on first and last intervals, or to return NaNs.
            If 'periodic', periodic extrapolation is used. Default is True.
        """
        if not isinstance(bp, BPoly):
            raise TypeError(".from_bernstein_basis only accepts BPoly instances. "
                            "Got %s instead." % type(bp))

        dx = np.diff(bp.x)
        k = bp.c.shape[0] - 1  # polynomial order

        rest = (None,)*(bp.c.ndim-2)

        c = np.zeros_like(bp.c)
        for a in range(k+1):
            factor = (-1)**a * comb(k, a) * bp.c[a]
            for s in range(a, k+1):
                val = comb(k-a, s-a) * (-1)**s
                c[k-s] += factor * val / dx[(slice(None),)+rest]**s

        if extrapolate is None:
            extrapolate = bp.extrapolate

        return cls.construct_fast(c, bp.x, extrapolate, bp.axis)
//  [python]
def from_power_basis(cls, pp, extrapolate=None):
        """
        Construct a piecewise polynomial in Bernstein basis
        from a power basis polynomial.

        Parameters
        ----------
        pp : PPoly
            A piecewise polynomial in the power basis
        extrapolate : bool or 'periodic', optional
            If bool, determines whether to extrapolate to out-of-bounds points
            based on first and last intervals, or to return NaNs.
            If 'periodic', periodic extrapolation is used. Default is True.
        """
        if not isinstance(pp, PPoly):
            raise TypeError(".from_power_basis only accepts PPoly instances. "
                            "Got %s instead." % type(pp))

        dx = np.diff(pp.x)
        k = pp.c.shape[0] - 1   # polynomial order

        rest = (None,)*(pp.c.ndim-2)

        c = np.zeros_like(pp.c)
        for a in range(k+1):
            factor = pp.c[a] / s.comb(k, k-a) * dx[(slice(None),)+rest]**(k-a)
            for j in range(k-a, k+1):
                c[j] += factor * s.comb(j, k-a)

        if extrapolate is None:
            extrapolate = pp.extrapolate

        return cls.construct_fast(c, pp.x, extrapolate, pp.axis)
//  [python]
def from_power_basis(cls, pp, extrapolate=None):
        """
        Construct a piecewise polynomial in Bernstein basis
        from a power basis polynomial.

        Parameters
        ----------
        pp : PPoly
            A piecewise polynomial in the power basis
        extrapolate : bool or 'periodic', optional
            If bool, determines whether to extrapolate to out-of-bounds points
            based on first and last intervals, or to return NaNs.
            If 'periodic', periodic extrapolation is used. Default is True.
        """
        if not isinstance(pp, PPoly):
            raise TypeError(".from_power_basis only accepts PPoly instances. "
                            "Got %s instead." % type(pp))

        dx = np.diff(pp.x)
        k = pp.c.shape[0] - 1   # polynomial order

        rest = (None,)*(pp.c.ndim-2)

        c = np.zeros_like(pp.c)
        for a in range(k+1):
            factor = pp.c[a] / comb(k, k-a) * dx[(slice(None),)+rest]**(k-a)
            for j in range(k-a, k+1):
                c[j] += factor * comb(j, k-a)

        if extrapolate is None:
            extrapolate = pp.extrapolate

        return cls.construct_fast(c, pp.x, extrapolate, pp.axis)
//  [python]
def _raise_degree(c, d):
        r"""Raise a degree of a polynomial in the Bernstein basis.

        Given the coefficients of a polynomial degree `k`, return (the
        coefficients of) the equivalent polynomial of degree `k+d`.

        Parameters
        ----------
        c : array_like
            coefficient array, 1-D
        d : integer

        Returns
        -------
        array
            coefficient array, 1-D array of length `c.shape[0] + d`

        Notes
        -----
        This uses the fact that a Bernstein polynomial `b_{a, k}` can be
        identically represented as a linear combination of polynomials of
        a higher degree `k+d`:

            .. math:: b_{a, k} = comb(k, a) \sum_{j=0}^{d} b_{a+j, k+d} \
                                 comb(d, j) / comb(k+d, a+j)

        """
        if d == 0:
            return c

        k = c.shape[0] - 1
        out = np.zeros((c.shape[0] + d,) + c.shape[1:], dtype=c.dtype)

        for a in range(c.shape[0]):
            f = c[a] * s.comb(k, a)
            for j in range(d+1):
                out[a+j] += f * s.comb(d, j) / s.comb(k+d, a+j)
        return out
//  [python]
def _raise_degree(c, d):
        r"""Raise a degree of a polynomial in the Bernstein basis.

        Given the coefficients of a polynomial degree `k`, return (the
        coefficients of) the equivalent polynomial of degree `k+d`.

        Parameters
        ----------
        c : array_like
            coefficient array, 1-D
        d : integer

        Returns
        -------
        array
            coefficient array, 1-D array of length `c.shape[0] + d`

        Notes
        -----
        This uses the fact that a Bernstein polynomial `b_{a, k}` can be
        identically represented as a linear combination of polynomials of
        a higher degree `k+d`:

            .. math:: b_{a, k} = comb(k, a) \sum_{j=0}^{d} b_{a+j, k+d} \
                                 comb(d, j) / comb(k+d, a+j)

        """
        if d == 0:
            return c

        k = c.shape[0] - 1
        out = np.zeros((c.shape[0] + d,) + c.shape[1:], dtype=c.dtype)

        for a in range(c.shape[0]):
            f = c[a] * comb(k, a)
            for j in range(d+1):
                out[a+j] += f * comb(d, j) / comb(k+d, a+j)
        return out
//  [python]
def test_comb(self):
        assert_array_almost_equal(s.comb([10, 10], [3, 4]), [120., 210.])
        assert_almost_equal(s.comb(10, 3), 120.)
        assert_equal(s.comb(10, 3, exact=True), 120)
        assert_equal(s.comb(10, 3, exact=True, repetition=True), 220)
//  [python]
def test_comb(self):
        assert_array_almost_equal(special.comb([10, 10], [3, 4]), [120., 210.])
        assert_almost_equal(special.comb(10, 3), 120.)
        assert_equal(special.comb(10, 3, exact=True), 120)
        assert_equal(special.comb(10, 3, exact=True, repetition=True), 220)
//  [python]
def test_comb_with_np_int64(self):
        n = 70
        k = 30
        np_n = np.int64(n)
        np_k = np.int64(k)
        assert_equal(s.comb(np_n, np_k, exact=True),
                     s.comb(n, k, exact=True))
//  [python]
def test_comb_with_np_int64(self):
        n = 70
        k = 30
        np_n = np.int64(n)
        np_k = np.int64(k)
        assert_equal(special.comb(np_n, np_k, exact=True),
                     special.comb(n, k, exact=True))
//  [python]
cb = scipy.special.cbrt([27, 64])
assert((cb == numpy.array([3., 4.])).all())

com = scipy.special.comb(5, 2, exact = False, repetition=True)
//  [python]
def _ell(A, m):
    """
    A helper function for expm_2009.

    Parameters
    ----------
    A : linear operator
        A linear operator whose norm of power we care about.
    m : int
        The power of the linear operator

    Returns
    -------
    value : int
        A value related to a bound.

    """
    if len(A.shape) != 2 or A.shape[0] != A.shape[1]:
        raise ValueError('expected A to be like a square matrix')

    p = 2*m + 1

    # The c_i are explained in (2.2) and (2.6) of the 2005 expm paper.
    # They are coefficients of terms of a generating function series expansion.
    choose_2p_p = s.comb(2*p, p, exact=True)
    abs_c_recip = float(choose_2p_p * math.factorial(2*p + 1))

    # This is explained after Eq. (1.2) of the 2009 expm paper.
    # It is the "unit roundoff" of IEEE double precision arithmetic.
    u = 2**-53

    # Compute the one-norm of matrix power p of abs(A).
    A_abs_onenorm = _onenorm_matrix_power_nnm(abs(A), p)

    # Treat zero norm as a special case.
    if not A_abs_onenorm:
        return 0

    alpha = A_abs_onenorm / (_onenorm(A) * abs_c_recip)
    log2_alpha_div_u = np.log2(alpha/u)
    value = int(np.ceil(log2_alpha_div_u / (2 * m)))
    return max(value, 0)
//  [python]
def test_comb_zeros(self):
        assert_equal(s.comb(2, 3, exact=True), 0)
        assert_equal(s.comb(-1, 3, exact=True), 0)
        assert_equal(s.comb(2, -1, exact=True), 0)
        assert_equal(s.comb(2, -1, exact=False), 0)
        assert_array_almost_equal(s.comb([2, -1, 2, 10], [3, 3, -1, 3]),
                [0., 0., 0., 120.])
//  [python]
def test_comb_zeros(self):
        assert_equal(special.comb(2, 3, exact=True), 0)
        assert_equal(special.comb(-1, 3, exact=True), 0)
        assert_equal(special.comb(2, -1, exact=True), 0)
        assert_equal(special.comb(2, -1, exact=False), 0)
        assert_array_almost_equal(special.comb([2, -1, 2, 10], [3, 3, -1, 3]),
                [0., 0., 0., 120.])
//  [python]
def calcHistArray(self, pc, norm, indNeigh, used_idx):
        """override this function with custom Histogram"""
        N = len(pc)
        histArray = np.zeros((N, self._div**3))
        for i in range(N):
            u = np.asarray(norm[i].T).squeeze()
            k = self._nneighbors
            n = k + 1
            N_features = s.comb(n, 2)
            features = []
            p_list = [i] + indNeigh[i]
            p_list_copy = [i] + indNeigh[i]
            for z in p_list:
                p_list_copy.pop(0)
                for p in p_list_copy:
                    pi = pc[p]
                    pj = pc[z]
                    if np.arccos(np.dot(norm[p], pj - pi)) <= np.arccos(np.dot(norm[z], pi - pj)):
                        ps = pi
                        pt = pj
                        ns = np.asarray(norm[p]).squeeze()
                        nt = np.asarray(norm[z]).squeeze()
                    else:
                        ps = pj
                        pt = pi
                        ns = np.asarray(norm[z]).squeeze()
                        nt = np.asarray(norm[p]).squeeze()

                    u = ns
                    difV = pt - ps
                    dist = np.linalg.norm(difV)
                    difV = difV/dist
                    difV = np.asarray(difV).squeeze()
                    v = np.cross(difV, u)
                    w = np.cross(u, v)

                    alpha = np.dot(v, nt)
                    phi = np.dot(u, difV)
                    theta = np.arctan(np.dot(w, nt) / np.dot(u, nt))

                    features.append(np.array([alpha, phi, theta]))
                
            features = np.asarray(features)
            pfh_hist, bin_edges = self.calc_pfh_hist(features)
            histArray[i, :] = pfh_hist / (N_features)
        return histArray
//  [python]
def calcHistArray(self, pc, norm, indNeigh, used_idx):
        """override this function with custom Histogram"""
        N = len(pc)
        histArray = np.zeros((N, self._div**3))
        for i in range(N):
            u = np.asarray(norm[i].T).squeeze()
            k = self._nneighbors
            n = k + 1
            N_features = sp.comb(n, 2)
            features = []
            p_list = [i] + indNeigh[i]
            p_list_copy = [i] + indNeigh[i]
            for z in p_list:
                p_list_copy.pop(0)
                for p in p_list_copy:
                    pi = pc[p]
                    pj = pc[z]
                    if np.arccos(np.dot(norm[p], pj - pi)) <= np.arccos(np.dot(norm[z], pi - pj)):
                        ps = pi
                        pt = pj
                        ns = np.asarray(norm[p]).squeeze()
                        nt = np.asarray(norm[z]).squeeze()
                    else:
                        ps = pj
                        pt = pi
                        ns = np.asarray(norm[z]).squeeze()
                        nt = np.asarray(norm[p]).squeeze()

                    u = ns
                    difV = pt - ps
                    dist = np.linalg.norm(difV)
                    difV = difV/dist
                    difV = np.asarray(difV).squeeze()
                    v = np.cross(difV, u)
                    w = np.cross(u, v)

                    alpha = np.dot(v, nt)
                    phi = np.dot(u, difV)
                    theta = np.arctan(np.dot(w, nt) / np.dot(u, nt))

                    features.append(np.array([alpha, phi, theta]))
                
            features = np.asarray(features)
            pfh_hist, bin_edges = self.calc_pfh_hist(features)
            histArray[i, :] = pfh_hist / (N_features)
        return histArray
//  [python]
def from_bernstein_basis(cls, bp, extrapolate=None):
        """
        Construct a piecewise polynomial in the power basis
        from a polynomial in Bernstein basis.

        Parameters
        ----------
        bp : BPoly
            A Bernstein basis polynomial, as created by BPoly
        extrapolate : bool or 'periodic', optional
            If bool, determines whether to extrapolate to out-of-bounds points
            based on first and last intervals, or to return NaNs.
            If 'periodic', periodic extrapolation is used. Default is True.
        """
        dx = np.diff(bp.x)
        k = bp.c.shape[0] - 1  # polynomial order

        rest = (None,)*(bp.c.ndim-2)

        c = np.zeros_like(bp.c)
        for a in range(k+1):
            factor = (-1)**a * s.comb(k, a) * bp.c[a]
            for s in range(a, k+1):
                val = s.comb(k-a, s-a) * (-1)**s
                c[k-s] += factor * val / dx[(slice(None),)+rest]**s

        if extrapolate is None:
            extrapolate = bp.extrapolate

        return cls.construct_fast(c, bp.x, extrapolate, bp.axis)
//  [python]
def from_bernstein_basis(cls, bp, extrapolate=None):
        """
        Construct a piecewise polynomial in the power basis
        from a polynomial in Bernstein basis.

        Parameters
        ----------
        bp : BPoly
            A Bernstein basis polynomial, as created by BPoly
        extrapolate : bool or 'periodic', optional
            If bool, determines whether to extrapolate to out-of-bounds points
            based on first and last intervals, or to return NaNs.
            If 'periodic', periodic extrapolation is used. Default is True.
        """
        dx = np.diff(bp.x)
        k = bp.c.shape[0] - 1  # polynomial order

        rest = (None,)*(bp.c.ndim-2)

        c = np.zeros_like(bp.c)
        for a in range(k+1):
            factor = (-1)**a * comb(k, a) * bp.c[a]
            for s in range(a, k+1):
                val = comb(k-a, s-a) * (-1)**s
                c[k-s] += factor * val / dx[(slice(None),)+rest]**s

        if extrapolate is None:
            extrapolate = bp.extrapolate

        return cls.construct_fast(c, bp.x, extrapolate, bp.axis)
//  [python]
def from_power_basis(cls, pp, extrapolate=None):
        """
        Construct a piecewise polynomial in Bernstein basis
        from a power basis polynomial.

        Parameters
        ----------
        pp : PPoly
            A piecewise polynomial in the power basis
        extrapolate : bool or 'periodic', optional
            If bool, determines whether to extrapolate to out-of-bounds points
            based on first and last intervals, or to return NaNs.
            If 'periodic', periodic extrapolation is used. Default is True.
        """
        dx = np.diff(pp.x)
        k = pp.c.shape[0] - 1   # polynomial order

        rest = (None,)*(pp.c.ndim-2)

        c = np.zeros_like(pp.c)
        for a in range(k+1):
            factor = pp.c[a] / s.comb(k, k-a) * dx[(slice(None),)+rest]**(k-a)
            for j in range(k-a, k+1):
                c[j] += factor * s.comb(j, k-a)

        if extrapolate is None:
            extrapolate = pp.extrapolate

        return cls.construct_fast(c, pp.x, extrapolate, pp.axis)
//  [python]
def from_power_basis(cls, pp, extrapolate=None):
        """
        Construct a piecewise polynomial in Bernstein basis
        from a power basis polynomial.

        Parameters
        ----------
        pp : PPoly
            A piecewise polynomial in the power basis
        extrapolate : bool or 'periodic', optional
            If bool, determines whether to extrapolate to out-of-bounds points
            based on first and last intervals, or to return NaNs.
            If 'periodic', periodic extrapolation is used. Default is True.
        """
        dx = np.diff(pp.x)
        k = pp.c.shape[0] - 1   # polynomial order

        rest = (None,)*(pp.c.ndim-2)

        c = np.zeros_like(pp.c)
        for a in range(k+1):
            factor = pp.c[a] / comb(k, k-a) * dx[(slice(None),)+rest]**(k-a)
            for j in range(k-a, k+1):
                c[j] += factor * comb(j, k-a)

        if extrapolate is None:
            extrapolate = pp.extrapolate

        return cls.construct_fast(c, pp.x, extrapolate, pp.axis)
//  [python]
def _permutation_distribution_t(data, permutations, size_a, equal_var,
                                random_state=None):
    """Generation permutation distribution of t statistic"""

    random_state = check_random_state(random_state)

    # prepare permutation indices
    size = data.shape[-1]
    # number of distinct combinations
    n_max = s.comb(size, size_a)

    if permutations < n_max:
        perm_generator = (random_state.permutation(size)
                          for i in range(permutations))
    else:
        permutations = n_max
        perm_generator = (np.concatenate(z)
                          for z in _all_partitions(size_a, size-size_a))

    t_stat = []
    for indices in _batch_generator(perm_generator, batch=50):
        # get one batch from perm_generator at a time as a list
        indices = np.array(indices)
        # generate permutations
        data_perm = data[..., indices]
        # move axis indexing permutations to position 0 to broadcast
        # nicely with t_stat_observed, which doesn't have this dimension
        data_perm = np.moveaxis(data_perm, -2, 0)

        a = data_perm[..., :size_a]
        b = data_perm[..., size_a:]
        t_stat.append(_calc_t_stat(a, b, equal_var))

    t_stat = np.concatenate(t_stat, axis=0)

    return t_stat, permutations, n_max
//  [python]
def _permutation_distribution_t(data, permutations, size_a, equal_var,
                                random_state=None):
    """Generation permutation distribution of t statistic"""

    random_state = check_random_state(random_state)

    # prepare permutation indices
    size = data.shape[-1]
    # number of distinct combinations
    n_max = special.comb(size, size_a)

    if permutations < n_max:
        perm_generator = (random_state.permutation(size)
                          for i in range(permutations))
    else:
        permutations = n_max
        perm_generator = (np.concatenate(z)
                          for z in _all_partitions(size_a, size-size_a))

    t_stat = []
    for indices in _batch_generator(perm_generator, batch=50):
        # get one batch from perm_generator at a time as a list
        indices = np.array(indices)
        # generate permutations
        data_perm = data[..., indices]
        # move axis indexing permutations to position 0 to broadcast
        # nicely with t_stat_observed, which doesn't have this dimension
        data_perm = np.moveaxis(data_perm, -2, 0)

        a = data_perm[..., :size_a]
        b = data_perm[..., size_a:]
        t_stat.append(_calc_t_stat(a, b, equal_var))

    t_stat = np.concatenate(t_stat, axis=0)

    return t_stat, permutations, n_max
//  [python]
def get_rho(self, u, D=None):
        # !!! PAGE 137 of the book
        # and "Application of Random Fields in Human Brain Mapping,
        # J. Cao and K. J. Worsley
        u = u.reshape(-1, 1)
        k = self.df
        if D is None:
            D = self.dim + 1
        rho = []

        # j = 0
        rho.append(1 - scipy.stats.chi2.cdf(u, k))

        # j >= 1
        for j in range(1, D):
            # first_coef = u**((k - j)/2) * np.exp(-u / 2) /\
            #     ((2 * np.pi)**(j / 2) * math.gamma(k / 2) * 2**((k - 2) / 2))
            first_coef = u**((k - j)/2) * np.exp(-u / 2) /\
                ((2 * np.pi)**(j / 2) * math.gamma(k / 2) * 2**((k - j) / 2))

            second_coef = 0
            for l in range(0, int((j - 1) / 2) + 1):
                for m in range(0, j - 1 - 2 * l + 1):
                    if k >= j - m - 2 * l:
                        #old version is scipy.misc.comb
                        second_coef += scipy.misc.comb(k - 1, j - 1 - m - 2 * l) *\
                        (-1)**(j-1+m+l)*math.factorial(j-1)/\
                        (math.factorial(m)*math.factorial(l)*2**l)*\
                        u**(m+l)

            rho.append(first_coef * second_coef)

        rho = np.hstack(rho)
        return rho
//  [python]
def get_rho(self, u, D=None):
        # !!! PAGE 137 of the book
        # and "Application of Random Fields in Human Brain Mapping,
        # J. Cao and K. J. Worsley
        u = u.reshape(-1, 1)
        k = self.df
        if D is None:
            D = self.dim + 1
        rho = []

        # j = 0
        rho.append(1 - scipy.stats.chi2.cdf(u, k))

        # j >= 1
        for j in range(1, D):
            # first_coef = u**((k - j)/2) * np.exp(-u / 2) /\
            #     ((2 * np.pi)**(j / 2) * math.gamma(k / 2) * 2**((k - 2) / 2))
            first_coef = u**((k - j)/2) * np.exp(-u / 2) /\
                ((2 * np.pi)**(j / 2) * math.gamma(k / 2) * 2**((k - j) / 2))

            second_coef = 0
            for l in range(0, int((j - 1) / 2) + 1):
                for m in range(0, j - 1 - 2 * l + 1):
                    if k >= j - m - 2 * l:
                        #old version is scipy.misc.comb
                        second_coef += scipy.special.comb(k - 1, j - 1 - m - 2 * l) *\
                        (-1)**(j-1+m+l)*math.factorial(j-1)/\
                        (math.factorial(m)*math.factorial(l)*2**l)*\
                        u**(m+l)

            rho.append(first_coef * second_coef)

        rho = np.hstack(rho)
        return rho
//  [python]
def _raise_degree(c, d):
        r"""Raise a degree of a polynomial in the Bernstein basis.

        Given the coefficients of a polynomial degree `k`, return (the
        coefficients of) the equivalent polynomial of degree `k+d`.

        Parameters
        ----------
        c : array_like
            coefficient array, 1D
        d : integer

        Returns
        -------
        array
            coefficient array, 1D array of length `c.shape[0] + d`

        Notes
        -----
        This uses the fact that a Bernstein polynomial `b_{a, k}` can be
        identically represented as a linear combination of polynomials of
        a higher degree `k+d`:

            .. math:: b_{a, k} = comb(k, a) \sum_{j=0}^{d} b_{a+j, k+d} \
                                 comb(d, j) / comb(k+d, a+j)

        """
        if d == 0:
            return c

        k = c.shape[0] - 1
        out = np.zeros((c.shape[0] + d,) + c.shape[1:], dtype=c.dtype)

        for a in range(c.shape[0]):
            f = c[a] * s.comb(k, a)
            for j in range(d+1):
                out[a+j] += f * s.comb(d, j) / s.comb(k+d, a+j)
        return out
//  [python]
def _raise_degree(c, d):
        r"""Raise a degree of a polynomial in the Bernstein basis.

        Given the coefficients of a polynomial degree `k`, return (the
        coefficients of) the equivalent polynomial of degree `k+d`.

        Parameters
        ----------
        c : array_like
            coefficient array, 1D
        d : integer

        Returns
        -------
        array
            coefficient array, 1D array of length `c.shape[0] + d`

        Notes
        -----
        This uses the fact that a Bernstein polynomial `b_{a, k}` can be
        identically represented as a linear combination of polynomials of
        a higher degree `k+d`:

            .. math:: b_{a, k} = comb(k, a) \sum_{j=0}^{d} b_{a+j, k+d} \
                                 comb(d, j) / comb(k+d, a+j)

        """
        if d == 0:
            return c

        k = c.shape[0] - 1
        out = np.zeros((c.shape[0] + d,) + c.shape[1:], dtype=c.dtype)

        for a in range(c.shape[0]):
            f = c[a] * comb(k, a)
            for j in range(d+1):
                out[a+j] += f * comb(d, j) / comb(k+d, a+j)
        return out
//  [python]
def from_bernstein_basis(cls, bp, extrapolate=None):
        """
        Construct a piecewise polynomial in the power basis
        from a polynomial in Bernstein basis.

        Parameters
        ----------
        bp : BPoly
            A Bernstein basis polynomial, as created by BPoly
        extrapolate : bool, optional
            Whether to extrapolate to ouf-of-bounds points based on first
            and last intervals, or to return NaNs. Default: True.

        """
        dx = np.diff(bp.x)
        k = bp.c.shape[0] - 1  # polynomial order

        rest = (None,)*(bp.c.ndim-2)

        c = np.zeros_like(bp.c)
        for a in range(k+1):
            factor = (-1)**(a) * s.comb(k, a) * bp.c[a]
            for s in range(a, k+1):
                val = s.comb(k-a, s-a) * (-1)**s
                c[k-s] += factor * val / dx[(slice(None),)+rest]**s

        if extrapolate is None:
            extrapolate = bp.extrapolate

        return cls.construct_fast(c, bp.x, extrapolate, bp.axis)
//  [python]
def from_bernstein_basis(cls, bp, extrapolate=None):
        """
        Construct a piecewise polynomial in the power basis
        from a polynomial in Bernstein basis.

        Parameters
        ----------
        bp : BPoly
            A Bernstein basis polynomial, as created by BPoly
        extrapolate : bool, optional
            Whether to extrapolate to ouf-of-bounds points based on first
            and last intervals, or to return NaNs. Default: True.

        """
        dx = np.diff(bp.x)
        k = bp.c.shape[0] - 1  # polynomial order

        rest = (None,)*(bp.c.ndim-2)

        c = np.zeros_like(bp.c)
        for a in range(k+1):
            factor = (-1)**(a) * comb(k, a) * bp.c[a]
            for s in range(a, k+1):
                val = comb(k-a, s-a) * (-1)**s
                c[k-s] += factor * val / dx[(slice(None),)+rest]**s

        if extrapolate is None:
            extrapolate = bp.extrapolate

        return cls.construct_fast(c, bp.x, extrapolate, bp.axis)
//  [python]
def from_power_basis(cls, pp, extrapolate=None):
        """
        Construct a piecewise polynomial in Bernstein basis
        from a power basis polynomial.

        Parameters
        ----------
        pp : PPoly
            A piecewise polynomial in the power basis
        extrapolate : bool, optional
            Whether to extrapolate to ouf-of-bounds points based on first
            and last intervals, or to return NaNs. Default: True.

        """
        dx = np.diff(pp.x)
        k = pp.c.shape[0] - 1   # polynomial order

        rest = (None,)*(pp.c.ndim-2)

        c = np.zeros_like(pp.c)
        for a in range(k+1):
            factor = pp.c[a] / s.comb(k, k-a) * dx[(slice(None),)+rest]**(k-a)
            for j in range(k-a, k+1):
                c[j] += factor * s.comb(j, k-a)

        if extrapolate is None:
            extrapolate = pp.extrapolate

        return cls.construct_fast(c, pp.x, extrapolate, pp.axis)
//  [python]
def from_power_basis(cls, pp, extrapolate=None):
        """
        Construct a piecewise polynomial in Bernstein basis
        from a power basis polynomial.

        Parameters
        ----------
        pp : PPoly
            A piecewise polynomial in the power basis
        extrapolate : bool, optional
            Whether to extrapolate to ouf-of-bounds points based on first
            and last intervals, or to return NaNs. Default: True.

        """
        dx = np.diff(pp.x)
        k = pp.c.shape[0] - 1   # polynomial order

        rest = (None,)*(pp.c.ndim-2)

        c = np.zeros_like(pp.c)
        for a in range(k+1):
            factor = pp.c[a] / comb(k, k-a) * dx[(slice(None),)+rest]**(k-a)
            for j in range(k-a, k+1):
                c[j] += factor * comb(j, k-a)

        if extrapolate is None:
            extrapolate = pp.extrapolate

        return cls.construct_fast(c, pp.x, extrapolate, pp.axis)
//  [python]
def _raise_degree(c, d):
        """Raise a degree of a polynomial in the Bernstein basis.

        Given the coefficients of a polynomial degree `k`, return (the
        coefficients of) the equivalent polynomial of degree `k+d`.

        Parameters
        ----------
        c : array_like
            coefficient array, 1D
        d : integer

        Returns
        -------
        array
            coefficient array, 1D array of length `c.shape[0] + d`

        Notes
        -----
        This uses the fact that a Bernstein polynomial `b_{a, k}` can be
        identically represented as a linear combination of polynomials of
        a higher degree `k+d`:

            .. math:: b_{a, k} = comb(k, a) \sum_{j=0}^{d} b_{a+j, k+d} \
                                comb(d, j) / comb(k+d, a+j)

        """
        if d == 0:
            return c

        k = c.shape[0] - 1
        out = np.zeros((c.shape[0] + d,) + c.shape[1:], dtype=c.dtype)

        for a in range(c.shape[0]):
            f = c[a] * s.comb(k, a)
            for j in range(d+1):
                out[a+j] += f * s.comb(d, j) / s.comb(k+d, a+j)
        return out
//  [python]
def _raise_degree(c, d):
        """Raise a degree of a polynomial in the Bernstein basis.

        Given the coefficients of a polynomial degree `k`, return (the
        coefficients of) the equivalent polynomial of degree `k+d`.

        Parameters
        ----------
        c : array_like
            coefficient array, 1D
        d : integer

        Returns
        -------
        array
            coefficient array, 1D array of length `c.shape[0] + d`

        Notes
        -----
        This uses the fact that a Bernstein polynomial `b_{a, k}` can be
        identically represented as a linear combination of polynomials of
        a higher degree `k+d`:

            .. math:: b_{a, k} = comb(k, a) \sum_{j=0}^{d} b_{a+j, k+d} \
                                comb(d, j) / comb(k+d, a+j)

        """
        if d == 0:
            return c

        k = c.shape[0] - 1
        out = np.zeros((c.shape[0] + d,) + c.shape[1:], dtype=c.dtype)

        for a in range(c.shape[0]):
            f = c[a] * comb(k, a)
            for j in range(d+1):
                out[a+j] += f * comb(d, j) / comb(k+d, a+j)
        return out
//  [python]
def test_neg_binomial_prior(self):
        """changepoint.bayes_offline.NegBinomialPrior"""
        t = 4
        k = 100
        p = 0.1
        inst = offline.NegBinomialPrior(k, p)
        self.assertAlmostEqual(inst.prior(t),
                               (scipy.misc.comb(t - k, k - 1) * p**k *
                                (1 - p)**(t - k)))
//  [python]
def test_neg_binomial_prior(self):
        """changepoint.bayes_offline.NegBinomialPrior"""
        t = 4
        k = 100
        p = 0.1
        inst = offline.NegBinomialPrior(k, p)
        self.assertAlmostEqual(inst.prior(t),
                               (scipy.special.comb(t - k, k - 1) * p**k *
                                (1 - p)**(t - k)))
//  [python]
def combins(n, k, m):
    s = []
    for i in range(1, n + 1):
        c = s.comb(n - i, k)
        if m >= c:
            s.append(1)
            m -= c
            k = k - 1
        else:
            s.append(0)
    return tuple(s)
//  [python]
def combins(n, k, m):
    s = []
    for i in range(1, n + 1):
        c = scipy.special.comb(n - i, k)
        if m >= c:
            s.append(1)
            m -= c
            k = k - 1
        else:
            s.append(0)
    return tuple(s)
//  [python]
def combins_table(n, k, map_max=None):
    table = []
    rev_table = {}
    table_top = s.comb(n, k)
    for m in range(int(table_top)):
        # forward mapping
        c = combins(n, k, m)
        if map_max is None or m < map_max:
            table.append(c)
            rev_table[c] = m
        else:
            rev_table[c] = m % map_max
    return table, rev_table
//  [python]
def combins_table(n, k, map_max=None):
    table = []
    rev_table = {}
    table_top = scipy.special.comb(n, k)
    for m in range(int(table_top)):
        # forward mapping
        c = combins(n, k, m)
        if map_max is None or m < map_max:
            table.append(c)
            rev_table[c] = m
        else:
            rev_table[c] = m % map_max
    return table, rev_table
//  [python]
def bezier_interpolation(control_points, tau):
  """Bezier Interpolation to determine desired motor position at time t.

  tau range must be in the range [0, 1].
  degree of the bezier curve is len(control_points) - 1

  Args:
    control_points: Bezier curve generations parameters.
    tau: normalized time value.

  Returns:
    The interpolated position and velocity at normalized time tau.

  """

  degree = len(control_points) - 1

  final_val = 0
  for idx in range(degree + 1):
    num_of_combs = s.comb(degree, idx)
    final_val = final_val + (
        num_of_combs * ((1 - tau)**(degree - idx)) *
        (tau**idx) * control_points[idx])

  final_velval = 0
  k = degree - 1
  for idx in range(k + 1):
    num_of_combs = s.comb(k, idx)
    final_velval = final_velval + (
        degree * num_of_combs * ((1 - tau)**(k - idx)) * (tau**idx) *
        (control_points[idx + 1] - control_points[idx]))

  return final_val, final_velval
//  [python]
def bezier_interpolation(control_points, tau):
  """Bezier Interpolation to determine desired motor position at time t.

  tau range must be in the range [0, 1].
  degree of the bezier curve is len(control_points) - 1

  Args:
    control_points: Bezier curve generations parameters.
    tau: normalized time value.

  Returns:
    The interpolated position and velocity at normalized time tau.

  """

  degree = len(control_points) - 1

  final_val = 0
  for idx in range(degree + 1):
    num_of_combs = scipy.special.comb(degree, idx)
    final_val = final_val + (
        num_of_combs * ((1 - tau)**(degree - idx)) *
        (tau**idx) * control_points[idx])

  final_velval = 0
  k = degree - 1
  for idx in range(k + 1):
    num_of_combs = scipy.special.comb(k, idx)
    final_velval = final_velval + (
        degree * num_of_combs * ((1 - tau)**(k - idx)) * (tau**idx) *
        (control_points[idx + 1] - control_points[idx]))

  return final_val, final_velval
//  [python]
def pmf(self, x) -> float:
        """Computes the probability mass function for selected value :obj:`x`.

        :formula: The probability mass function (pmf) is computed by

            .. math:: \\mathbb{P}(X = x | r, p) = \\dfrac{(x + r - 1)!}{(r - 1)! x!} (1 - p)^{k} p^{r}

        :param x: Value to be evaluated
        :type x: :obj:`int`

        :return: Probability :math:`\\mathbb{P}(X = x | r, p)`
        :rtype: :obj:`float`
        """
        x = [x] if type(x) in [float, int] else x

        _comb = np.array([s.comb(_x + self.r_ - 1, _x, exact=True) for _x in x])

        # _comb = np.array([_a / _b for _a, _b in zip(_num, _denom)])
        _m1 = np.array([pow(1 - self.p_, _x) for _x in x])
        _m2 = pow(self.p_, self.r_)
        return _comb * _m1 * _m2
//  [python]
def pmf(self, x) -> float:
        """Computes the probability mass function for selected value :obj:`x`.

        :formula: The probability mass function (pmf) is computed by

            .. math:: \\mathbb{P}(X = x | r, p) = \\dfrac{(x + r - 1)!}{(r - 1)! x!} (1 - p)^{k} p^{r}

        :param x: Value to be evaluated
        :type x: :obj:`int`

        :return: Probability :math:`\\mathbb{P}(X = x | r, p)`
        :rtype: :obj:`float`
        """
        x = [x] if type(x) in [float, int] else x

        _comb = np.array([scipy.special.comb(_x + self.r_ - 1, _x, exact=True) for _x in x])

        # _comb = np.array([_a / _b for _a, _b in zip(_num, _denom)])
        _m1 = np.array([pow(1 - self.p_, _x) for _x in x])
        _m2 = pow(self.p_, self.r_)
        return _comb * _m1 * _m2
//  [python]
def _munp(self, n, a, b):
        """Returns the n-th moment(s) where all the following hold:

        - n >= 0
        - a > n / 2
        - b > n / 2

        The result is np.nan in all other cases.
        """
        def nth_moment(n_k, a_k, b_k):
            """Computes E[T^(n_k)] where T is skew-t distributed with
            parameters a_k and b_k.
            """
            num = (a_k + b_k) ** (0.5 * n_k)
            denom = 2 ** n_k * sc.beta(a_k, b_k)

            indices = np.arange(n_k + 1)
            sgn = np.where(indices % 2 > 0, -1, 1)
            d = sc.beta(a_k + 0.5 * n_k - indices, b_k - 0.5 * n_k + indices)
            sum_terms = s.comb(n_k, indices) * sgn * d

            return num / denom * sum_terms.sum()

        nth_moment_valid = (a > 0.5 * n) & (b > 0.5 * n) & (n >= 0)
        return _lazywhere(
            nth_moment_valid,
            (n, a, b),
            np.vectorize(nth_moment, otypes=[np.float64]),
            np.nan,
        )
//  [python]
def _munp(self, n, a, b):
        """Returns the n-th moment(s) where all the following hold:

        - n >= 0
        - a > n / 2
        - b > n / 2

        The result is np.nan in all other cases.
        """
        def nth_moment(n_k, a_k, b_k):
            """Computes E[T^(n_k)] where T is skew-t distributed with
            parameters a_k and b_k.
            """
            num = (a_k + b_k) ** (0.5 * n_k)
            denom = 2 ** n_k * sc.beta(a_k, b_k)

            indices = np.arange(n_k + 1)
            sgn = np.where(indices % 2 > 0, -1, 1)
            d = sc.beta(a_k + 0.5 * n_k - indices, b_k - 0.5 * n_k + indices)
            sum_terms = sc.comb(n_k, indices) * sgn * d

            return num / denom * sum_terms.sum()

        nth_moment_valid = (a > 0.5 * n) & (b > 0.5 * n) & (n >= 0)
        return _lazywhere(
            nth_moment_valid,
            (n, a, b),
            np.vectorize(nth_moment, otypes=[np.float64]),
            np.nan,
        )
//  [python]
def _combinations(
        n_features, min_degree, max_degree, interaction_only, include_bias
    ):
        comb = s.comb if interaction_only else s.comb_w_r
        start = max(1, min_degree)
        iter = chain.from_iterable(
            comb(range(n_features), i) for i in range(start, max_degree + 1)
        )
        if include_bias:
            iter = chain(comb(range(n_features), 0), iter)
        return iter