(self, **hints)
(a+b+..) ** n -> a**n + n*a**(n-1)*b + .., n is nonzero integer
(a+b+..) ** n -> a**n + n*a**(n-1)*b + .., n is nonzero integer
( a + b + .. ) ** n - > a ** n + n * a ** ( n - 1 ) * b + .. n is nonzero integer
def _eval_expand_multinomial(self, **hints):
        """(a+b+..) ** n -> a**n + n*a**(n-1)*b + .., n is nonzero integer"""

        base, exp = self.args
        result = self

        if exp.is_Rational and exp.p > 0 and base.is_Add:
            if not exp.is_Integer:
                n = Integer(exp.p // exp.q)

                if not n:
                    return result
                else:
                    radical, result = self.func(base, exp - n), []

                    expanded_base_n = self.func(base, n)
                    if expanded_base_n.is_Pow:
                        expanded_base_n = \
                            expanded_base_n._eval_expand_multinomial()
                    for term in Add.make_args(expanded_base_n):
                        result.append(term*radical)

                    return Add(*result)

            n = int(exp)

            if base.is_commutative:
                order_terms, other_terms = [], []

                for b in base.args:
                    if b.is_Order:
                        order_terms.append(b)
                    else:
                        other_terms.append(b)

                if order_terms:
                    # (f(x) + O(x^n))^m -> f(x)^m + m*f(x)^{m-1} *O(x^n)
                    f = Add(*other_terms)
                    o = Add(*order_terms)

                    if n == 2:
                        return expand_multinomial(f**n, deep=False) + n*f*o
                    else:
                        g = expand_multinomial(f**(n - 1), deep=False)
                        return expand_mul(f*g, deep=False) + n*g*o

                if base.is_number:
                    # Efficiently expand expressions of the form (a + b*I)**n
                    # where 'a' and 'b' are real numbers and 'n' is integer.
                    a, b = base.as_real_imag()

                    if a.is_Rational and b.is_Rational:
                        if not a.is_Integer:
                            if not b.is_Integer:
                                k = self.func(a.q * b.q, n)
                                a, b = a.p*b.q, a.q*b.p
                            else:
                                k = self.func(a.q, n)
                                a, b = a.p, a.q*b
                        elif not b.is_Integer:
                            k = self.func(b.q, n)
                            a, b = a*b.q, b.p
                        else:
                            k = 1

                        a, b, c, d = int(a), int(b), 1, 0

                        while n:
                            if n & 1:
                                c, d = a*c - b*d, b*c + a*d
                                n -= 1
                            a, b = a*a - b*b, 2*a*b
                            n //= 2

                        I = S.ImaginaryUnit

                        if k == 1:
                            return c + I*d
                        else:
                            return Integer(c)/k + I*d/k

                p = other_terms
                # (x+y)**3 -> x**3 + 3*x**2*y + 3*x*y**2 + y**3
                # in this particular example:
                # p = [x,y]; n = 3
                # so now it's easy to get the correct result -- we get the
                # coefficients first:
                from sympy import multinomial_coefficients
                from sympy.polys.polyutils import basic_from_dict
                expansion_dict = multinomial_coefficients(len(p), n)
                # in our example: {(3, 0): 1, (1, 2): 3, (0, 3): 1, (2, 1): 3}
                # and now construct the expression.
                return basic_from_dict(expansion_dict, *p)
            else:
                if n == 2:
                    return Add(*[f*g for f in base.args for g in base.args])
                else:
                    multi = (base**(n - 1))._eval_expand_multinomial()
                    if multi.is_Add:
                        return Add(*[f*g for f in base.args
                            for g in multi.args])
                    else:
                        # XXX can this ever happen if base was an Add?
                        return Add(*[f*multi for f in base.args])
        elif (exp.is_Rational and exp.p < 0 and base.is_Add and
                abs(exp.p) > exp.q):
            return 1 / self.func(base, -exp)._eval_expand_multinomial()
        elif exp.is_Add and base.is_Number:
            #  a + b      a  b
            # n      --> n  n  , where n, a, b are Numbers

            coeff, tail = S.One, S.Zero
            for term in exp.args:
                if term.is_Number:
                    coeff *= self.func(base, term)
                else:
                    tail += term

            return coeff * self.func(base, tail)
        else:
            return result
def _eval_expand_multinomial ( self , * * hints ) : base , exp = self . args result = self if exp . is_Rational and exp . p > 0 and base . is_Add : if not exp . is_Integer : n = Integer ( exp . p // exp . q ) if not n : return result else : radical , result = self . func ( base , exp - n ) , [ ] expanded_base_n = self . func ( base , n ) if expanded_base_n . is_Pow : expanded_base_n = expanded_base_n . _eval_expand_multinomial ( ) for term in Add . make_args ( expanded_base_n ) : result . append ( term * radical ) return Add ( * result ) n = int ( exp ) if base . is_commutative : order_terms , other_terms = [ ] , [ ] for b in base . args : if b . is_Order : order_terms . append ( b ) else : other_terms . append ( b ) if order_terms : # (f(x) + O(x^n))^m -> f(x)^m + m*f(x)^{m-1} *O(x^n) f = Add ( * other_terms ) o = Add ( * order_terms ) if n == 2 : return expand_multinomial ( f ** n , deep = False ) + n * f * o else : g = expand_multinomial ( f ** ( n - 1 ) , deep = False ) return expand_mul ( f * g , deep = False ) + n * g * o if base . is_number : # Efficiently expand expressions of the form (a + b*I)**n # where 'a' and 'b' are real numbers and 'n' is integer. a , b = base . as_real_imag ( ) if a . is_Rational and b . is_Rational : if not a . is_Integer : if not b . is_Integer : k = self . func ( a . q * b . q , n ) a , b = a . p * b . q , a . q * b . p else : k = self . func ( a . q , n ) a , b = a . p , a . q * b elif not b . is_Integer : k = self . func ( b . q , n ) a , b = a * b . q , b . p else : k = 1 a , b , c , d = int ( a ) , int ( b ) , 1 , 0 while n : if n & 1 : c , d = a * c - b * d , b * c + a * d n -= 1 a , b = a * a - b * b , 2 * a * b n //= 2 I = S . ImaginaryUnit if k == 1 : return c + I * d else : return Integer ( c ) / k + I * d / k p = other_terms # (x+y)**3 -> x**3 + 3*x**2*y + 3*x*y**2 + y**3 # in this particular example: # p = [x,y]; n = 3 # so now it's easy to get the correct result -- we get the # coefficients first: from sympy import multinomial_coefficients from sympy . polys . polyutils import basic_from_dict expansion_dict = multinomial_coefficients ( len ( p ) , n ) # in our example: {(3, 0): 1, (1, 2): 3, (0, 3): 1, (2, 1): 3} # and now construct the expression. return basic_from_dict ( expansion_dict , * p ) else : if n == 2 : return Add ( * [ f * g for f in base . args for g in base . args ] ) else : multi = ( base ** ( n - 1 ) ) . _eval_expand_multinomial ( ) if multi . is_Add : return Add ( * [ f * g for f in base . args for g in multi . args ] ) else : # XXX can this ever happen if base was an Add? return Add ( * [ f * multi for f in base . args ] ) elif ( exp . is_Rational and exp . p < 0 and base . is_Add and abs ( exp . p ) > exp . q ) : return 1 / self . func ( base , - exp ) . _eval_expand_multinomial ( ) elif exp . is_Add and base . is_Number : #  a + b      a  b # n      --> n  n  , where n, a, b are Numbers coeff , tail = S . One , S . Zero for term in exp . args : if term . is_Number : coeff *= self . func ( base , term ) else : tail += term return coeff * self . func ( base , tail ) else : return result