Ejemplo n.º 1
0
 def _eval_expand_mul(self, deep=True, **hints):
     hit = False
     sargs, terms = self.args, []
     for term in sargs:
         if term.is_Mul:
             old = term
             hints['mul'] = True
             targs = [t._eval_expand_mul(deep=deep, **hints) for t in term.args]
             hints['mul'] = False
             term = Mul(*targs)
             newterm = term._eval_expand_mul(deep=deep, **hints)
             hit = hit or newterm != old
         else:
             hints['mul'] = True
             newterm = term._eval_expand_mul(deep=deep, **hints)
         terms.append(newterm)
     hints['mul'] = True
     if not hit:
         return self
     return self.func(*terms)
Ejemplo n.º 2
0
    def as_numer_denom(self):

        # clear rational denominator
        content, expr = self.primitive()
        ncon, dcon = content.as_numer_denom()

        # collect numerators and denominators of the terms
        nd = defaultdict(list)
        for f in expr.args:
            ni, di = f.as_numer_denom()
            nd[di].append(ni)
        # put infinity in the numerator
        if S.Zero in nd:
            n = nd.pop(S.Zero)
            assert len(n) == 1
            n = n[0]
            nd[S.One].append(n / S.Zero)

        # check for quick exit
        if len(nd) == 1:
            d, n = nd.popitem()
            return Add(*[_keep_coeff(ncon, ni)
                         for ni in n]), _keep_coeff(dcon, d)

        # sum up the terms having a common denominator
        for d, n in nd.iteritems():
            if len(n) == 1:
                nd[d] = n[0]
            else:
                nd[d] = Add(*n)

        # assemble single numerator and denominator
        denoms, numers = [list(i) for i in zip(*nd.iteritems())]
        n, d = Add(*[
            Mul(*(denoms[:i] + [numers[i]] + denoms[i + 1:]))
            for i in xrange(len(numers))
        ]), Mul(*denoms)

        return _keep_coeff(ncon, n), _keep_coeff(dcon, d)
Ejemplo n.º 3
0
 def _eval_expand_mul(self, deep=True, **hints):
     hit = False
     sargs, terms = self.args, []
     for term in sargs:
         if term.is_Mul:
             old = term
             hints['mul'] = True
             targs = [
                 t._eval_expand_mul(deep=deep, **hints) for t in term.args
             ]
             hints['mul'] = False
             term = Mul(*targs)
             newterm = term._eval_expand_mul(deep=deep, **hints)
             hit = hit or newterm != old
         else:
             hints['mul'] = True
             newterm = term._eval_expand_mul(deep=deep, **hints)
         terms.append(newterm)
     hints['mul'] = True
     if not hit:
         return self
     return self.func(*terms)
Ejemplo n.º 4
0
 def _eval_expand_power_exp(self, deep=True, *args, **hints):
     """a**(n+m) -> a**n*a**m"""
     if deep:
         b = self.base.expand(deep=deep, **hints)
         e = self.exp.expand(deep=deep, **hints)
     else:
         b = self.base
         e = self.exp
     if e.is_Add and e.is_commutative:
         expr = []
         for x in e.args:
             if deep:
                 x = x.expand(deep=deep, **hints)
             expr.append(Pow(self.base, x))
         return Mul(*expr)
     return Pow(b, e)
Ejemplo n.º 5
0
    def _eval_power(b, e):
        if (e is S.NaN): return S.NaN
        if isinstance(e, Number):
            if isinstance(e, Real):
                return b._eval_evalf(e._prec)**e
            if e.is_negative:
                # (3/4)**-2 -> (4/3)**2
                ne = -e
                if (ne is S.One):
                    return Rational(b.q, b.p)
                if b < 0:
                    if e.q != 1:
                        return -(S.NegativeOne)**(
                            (e.p % e.q) / S(e.q)) * Rational(b.q, -b.p)**ne
                    else:
                        return S.NegativeOne**ne * Rational(b.q, -b.p)**ne
                else:
                    return Rational(b.q, b.p)**ne
            if (e is S.Infinity):
                if b.p > b.q:
                    # (3/2)**oo -> oo
                    return S.Infinity
                if b.p < -b.q:
                    # (-3/2)**oo -> oo + I*oo
                    return S.Infinity + S.Infinity * S.ImaginaryUnit
                return S.Zero
            if isinstance(e, Integer):
                # (4/3)**2 -> 4**2 / 3**2
                return Rational(b.p**e.p, b.q**e.p)
            if isinstance(e, Rational):
                if b.p != 1:
                    # (4/3)**(5/6) -> 4**(5/6) * 3**(-5/6)
                    return Integer(b.p)**e * Integer(b.q)**(-e)
                if b >= 0:
                    return Integer(b.q)**Rational(
                        e.p * (e.q - 1), e.q) / (Integer(b.q)**Integer(e.p))
                else:
                    return (-1)**e * (-b)**e

        c, t = b.as_coeff_terms()
        if e.is_even and isinstance(c, Number) and c < 0:
            return (-c * Mul(*t))**e

        return
Ejemplo n.º 6
0
    def as_content_primitive(self, radical=False):
        """Return the tuple (R, self/R) where R is the positive Rational
        extracted from self. If radical is True (default is False) then
        common radicals will be removed and included as a factor of the
        primitive expression.

        **Examples**

        >>> from sympy import sqrt
        >>> (3 + 3*sqrt(2)).as_content_primitive()
        (3, 1 + sqrt(2))

        Radical content can also be factored out of the primitive:

        >>> (2*sqrt(2) + 4*sqrt(10)).as_content_primitive(radical=True)
        (2, sqrt(2)*(1 + 2*sqrt(5)))

        See docstring of Expr.as_content_primitive for more examples.
        """
        con, prim = Add(*[_keep_coeff(*a.as_content_primitive(radical=radical)) for a in self.args]).primitive()
        if radical and prim.is_Add:
            # look for common radicals that can be removed
            args = prim.args
            rads = []
            common_q = None
            for m in args:
                term_rads = defaultdict(list)
                for ai in Mul.make_args(m):
                    if ai.is_Pow:
                        b, e = ai.as_base_exp()
                        if e.is_Rational and b.is_Integer and b > 0:
                            term_rads[e.q].append(int(b)**e.p)
                if not term_rads:
                    break
                if common_q is None:
                    common_q = set(term_rads.keys())
                else:
                    common_q = common_q & set(term_rads.keys())
                    if not common_q:
                        break
                rads.append(term_rads)
            else:
                # process rads
                # keep only those in common_q
                for r in rads:
                    for q in r.keys():
                        if q not in common_q:
                            r.pop(q)
                    for q in r:
                        r[q] = prod(r[q])
                # find the gcd of bases for each q
                G = []
                for q in common_q:
                    g = reduce(igcd, [r[q] for r in rads], 0)
                    if g != 1:
                        G.append(Pow(g, Rational(1, q)))
                if G:
                    G = Mul(*G)
                    args = [ai/G for ai in args]
                    prim = G*Add(*args)

        return con, prim
Ejemplo n.º 7
0
    def flatten(cls, seq):
        """
        Takes the sequence "seq" of nested Adds and returns a flatten list.

        Returns: (commutative_part, noncommutative_part, order_symbols)

        Applies associativity, all terms are commutable with respect to
        addition.

        ** Developer Notes **
            See Mul.flatten

        """
        rv = None
        if len(seq) == 2:
            a, b = seq
            if b.is_Rational:
                a, b = b, a
            assert a
            if a.is_Rational:
                if b.is_Mul:
                    # if it's an unevaluated 2-arg, expand it
                    c, t = b.as_coeff_Mul()
                    if t.is_Add:
                        h, t = t.as_coeff_Add()
                        bargs = [c*ti for ti in Add.make_args(t)]
                        bargs.sort(key=hash)
                        ch = c*h
                        if ch:
                            bargs.insert(0, ch)
                        b = Add._from_args(bargs)
                if b.is_Add:
                    bargs = list(b.args)
                    if bargs[0].is_Number:
                        bargs[0] += a
                        if not bargs[0]:
                            bargs.pop(0)
                    else:
                        bargs.insert(0, a)
                    rv = bargs, [], None
                elif b.is_Mul:
                    rv = [a, b], [], None
            if rv:
                if all(s.is_commutative for s in rv[0]):
                    return rv
                return [], rv[0], None

        terms = {}      # term -> coeff
                        # e.g. x**2 -> 5   for ... + 5*x**2 + ...

        coeff = S.Zero  # standalone term (Number or zoo will always be in slot 0)
                        # e.g. 3 + ...
        order_factors = []

        for o in seq:

            # O(x)
            if o.is_Order:
                for o1 in order_factors:
                    if o1.contains(o):
                        o = None
                        break
                if o is None:
                    continue
                order_factors = [o]+[o1 for o1 in order_factors if not o.contains(o1)]
                continue

            # 3 or NaN
            elif o.is_Number:
                if o is S.NaN or coeff is S.ComplexInfinity and o.is_bounded is False:
                    # we know for sure the result will be nan
                    return [S.NaN], [], None
                if coeff.is_Number:
                    coeff += o
                    if coeff is S.NaN:
                        # we know for sure the result will be nan
                        return [S.NaN], [], None
                continue

            elif o is S.ComplexInfinity:
                if coeff.is_bounded is False:
                    # we know for sure the result will be nan
                    return [S.NaN], [], None
                coeff = S.ComplexInfinity
                continue

            # Add([...])
            elif o.is_Add:
                # NB: here we assume Add is always commutative
                seq.extend(o.args)  # TODO zerocopy?
                continue

            # Mul([...])
            elif o.is_Mul:
                c, s = o.as_coeff_Mul()

                # 3*...
                # unevaluated 2-arg Mul, but we always unfold it so
                # it can combine with other terms (just like is done
                # with the Pow below)
                if c.is_Number and s.is_Add:
                    seq.extend([c*a for a in s.args])
                    continue

            # check for unevaluated Pow, e.g. 2**3 or 2**(-1/2)
            elif o.is_Pow:
                b, e = o.as_base_exp()
                if b.is_Number and (e.is_Integer or (e.is_Rational and e.is_negative)):
                    seq.append(Pow(b, e))
                    continue
                c, s = S.One, o

            else:
                # everything else
                c = S.One
                s = o


            # now we have:
            # o = c*s, where
            #
            # c is a Number
            # s is an expression with number factor extracted

            # let's collect terms with the same s, so e.g.
            # 2*x**2 + 3*x**2  ->  5*x**2
            if s in terms:
                terms[s] += c
            else:
                terms[s] = c


        # now let's construct new args:
        # [2*x**2, x**3, 7*x**4, pi, ...]
        newseq = []
        noncommutative = False
        for s,c in terms.items():
            # 0*s
            if c is S.Zero:
                continue
            # 1*s
            elif c is S.One:
                newseq.append(s)
            # c*s
            else:
                if s.is_Mul:
                    # Mul, already keeps its arguments in perfect order.
                    # so we can simply put c in slot0 and go the fast way.
                    cs = s._new_rawargs(*((c,) + s.args))
                    newseq.append(cs)

                else:
                    # alternatively we have to call all Mul's machinery (slow)
                    newseq.append(Mul(c,s))

            noncommutative = noncommutative or not s.is_commutative

        # oo, -oo
        if coeff is S.Infinity:
            newseq = [f for f in newseq if not (f.is_nonnegative or f.is_real and
                                                (f.is_bounded or
                                                 f.is_finite or
                                                 f.is_infinitesimal))]
        elif coeff is S.NegativeInfinity:
            newseq = [f for f in newseq if not (f.is_nonpositive or f.is_real and
                                                (f.is_bounded or
                                                 f.is_finite or
                                                 f.is_infinitesimal))]
        if coeff is S.ComplexInfinity:
            # zoo might be
            #   unbounded_real + bounded_im
            #   bounded_real + unbounded_im
            #   unbounded_real + unbounded_im
            # addition of a bounded real or imaginary number won't be able to
            # change the zoo nature; if unbounded a NaN condition could result if
            # the unbounded symbol had sign opposite of the unbounded portion of zoo,
            # e.g. unbounded_real - unbounded_real
            newseq = [c for c in newseq if not (c.is_bounded and
                                                c.is_real is not None)]

        # process O(x)
        if order_factors:
            newseq2 = []
            for t in newseq:
                for o in order_factors:
                    # x + O(x) -> O(x)
                    if o.contains(t):
                        t = None
                        break
                # x + O(x**2) -> x + O(x**2)
                if t is not None:
                    newseq2.append(t)
            newseq = newseq2 + order_factors
            # 1 + O(1) -> O(1)
            for o in order_factors:
                if o.contains(coeff):
                    coeff = S.Zero
                    break


        # order args canonically
        # Currently we sort things using hashes, as it is quite fast. A better
        # solution is not to sort things at all - but this needs some more
        # fixing. NOTE: this is used in primitive, too, so if it changes
        # here it should be changed there.
        newseq.sort(key=hash)

        # current code expects coeff to be always in slot-0
        if coeff is not S.Zero:
            newseq.insert(0, coeff)

        # we are done
        if noncommutative:
            return [], newseq, None
        else:
            return newseq, [], None
Ejemplo n.º 8
0
 def __rdiv__(self, other):
     return Mul(other, Pow(self, S.NegativeOne))
Ejemplo n.º 9
0
 def __div__(self, other):
     return Mul(self, Pow(other, S.NegativeOne))
Ejemplo n.º 10
0
 def __rmul__(self, other):
     return Mul(other, self)
Ejemplo n.º 11
0
Archivo: numbers.py Proyecto: NO2/sympy
    def _eval_power(b, e):
        """
        Tries to do some simplifications on b ** e, where b is
        an instance of Integer

        Returns None if no further simplifications can be done

        When exponent is a fraction (so we have for example a square root),
        we try to find a simpler representation by factoring the argument
        up to factors of 2**15, e.g.

          - 4**Rational(1,2) becomes 2
          - (-4)**Rational(1,2) becomes 2*I
          - (2**(3+7)*3**(6+7))**Rational(1,7) becomes 6*18**(3/7)

        Further simplification would require a special call to factorint on
        the argument which is not done here for sake of speed.

        """
        from sympy import perfect_power

        if e is S.NaN:
            return S.NaN
        if b is S.One:
            return S.One
        if b is S.NegativeOne:
            return
        if e is S.Infinity:
            if b > S.One:
                return S.Infinity
            if b is S.NegativeOne:
                return S.NaN
            # cases for 0 and 1 are done in their respective classes
            return S.Infinity + S.ImaginaryUnit * S.Infinity
        if not isinstance(e, Number):
            # simplify when exp is even
            # (-2) ** k --> 2 ** k
            c, t = b.as_coeff_mul()
            if e.is_even and isinstance(c, Number) and c < 0:
                return (-c*Mul(*t))**e
        if not isinstance(e, Rational):
            return
        if e is S.Half and b < 0:
            # we extract I for this special case since everyone is doing so
            return S.ImaginaryUnit*Pow(-b, e)
        if e < 0:
            # invert base and change sign on exponent
            ne = -e
            if b < 0:
                if e.q != 1:
                    return -(S.NegativeOne)**((e.p % e.q) /
                                             S(e.q)) * Rational(1, -b)**ne
                else:
                    return (S.NegativeOne)**ne*Rational(1, -b)**ne
            else:
                return Rational(1, b)**ne
        # see if base is a perfect root, sqrt(4) --> 2
        b_pos = int(abs(b))
        x, xexact = integer_nthroot(b_pos, e.q)
        if xexact:
            # if it's a perfect root we've finished
            result = Integer(x ** abs(e.p))
            if b < 0:
                result *= (-1)**e
            return result

        # The following is an algorithm where we collect perfect roots
        # from the factors of base.

        # if it's not an nth root, it still might be a perfect power
        p = perfect_power(b_pos)
        if p:
            dict = {p[0]: p[1]}
        else:
            dict = Integer(b_pos).factors(limit=2**15)

        # now process the dict of factors
        if b.is_negative:
            dict[-1] = 1
        out_int = 1
        sqr_int = 1
        sqr_gcd = 0
        sqr_dict = {}
        for prime, exponent in dict.iteritems():
            exponent *= e.p
            div_e, div_m = divmod(exponent, e.q)
            if div_e > 0:
                out_int *= prime**div_e
            if div_m > 0:
                sqr_dict[prime] = div_m
        for p, ex in sqr_dict.iteritems():
            if sqr_gcd == 0:
                sqr_gcd = ex
            else:
                sqr_gcd = igcd(sqr_gcd, ex)
        for k, v in sqr_dict.iteritems():
            sqr_int *= k**(v//sqr_gcd)
        if sqr_int == b and out_int == 1:
            result = None
        else:
            result = out_int*Pow(sqr_int , Rational(sqr_gcd, e.q))
        return result
Ejemplo n.º 12
0
    def flatten(cls, seq):
        """
        Takes the sequence "seq" of nested Adds and returns a flatten list.

        Returns: (commutative_part, noncommutative_part, order_symbols)

        Applies associativity, all terms are commutable with respect to
        addition.
        """
        terms = {}  # term -> coeff
        # e.g. x**2 -> 5   for ... + 5*x**2 + ...

        coeff = S.Zero  # standalone term
        # e.g. 3 + ...
        order_factors = []

        for o in seq:

            # O(x)
            if o.is_Order:
                for o1 in order_factors:
                    if o1.contains(o):
                        o = None
                        break
                if o is None:
                    continue
                order_factors = [o] + [
                    o1 for o1 in order_factors if not o.contains(o1)
                ]
                continue

            # 3 or NaN
            elif o.is_Number:
                if o is S.NaN or coeff is S.ComplexInfinity and o.is_bounded is False:
                    # we know for sure the result will be nan
                    return [S.NaN], [], None
                if coeff.is_Number:
                    coeff += o
                    if coeff is S.NaN:
                        # we know for sure the result will be nan
                        return [S.NaN], [], None
                continue

            elif o is S.ComplexInfinity:
                if coeff.is_bounded is False:
                    # we know for sure the result will be nan
                    return [S.NaN], [], None
                coeff = S.ComplexInfinity
                continue

            # Add([...])
            elif o.is_Add:
                # NB: here we assume Add is always commutative
                seq.extend(o.args)  # TODO zerocopy?
                continue

            # Mul([...])
            elif o.is_Mul:
                c, s = o.as_coeff_Mul()

                # 3*...
                if c.is_Number:
                    # unevaluated 2-arg Mul
                    if s.is_Add and s.is_commutative:
                        seq.extend([c * a for a in s.args])
                        continue

            # everything else
            else:
                c = S.One
                s = o

            # now we have:
            # o = c*s, where
            #
            # c is a Number
            # s is an expression with number factor extracted

            # let's collect terms with the same s, so e.g.
            # 2*x**2 + 3*x**2  ->  5*x**2
            if s in terms:
                terms[s] += c
            else:
                terms[s] = c

        # now let's construct new args:
        # [2*x**2, x**3, 7*x**4, pi, ...]
        newseq = []
        noncommutative = False
        for s, c in terms.items():
            # 0*s
            if c is S.Zero:
                continue
            # 1*s
            elif c is S.One:
                newseq.append(s)
            # c*s
            else:
                if s.is_Mul:
                    # Mul, already keeps its arguments in perfect order.
                    # so we can simply put c in slot0 and go the fast way.
                    cs = s._new_rawargs(*((c, ) + s.args))
                    newseq.append(cs)

                else:
                    # alternatively we have to call all Mul's machinery (slow)
                    newseq.append(Mul(c, s))

            noncommutative = noncommutative or not s.is_commutative

        # oo, -oo
        if coeff is S.Infinity:
            newseq = [
                f for f in newseq
                if not (f.is_nonnegative or f.is_real and
                        (f.is_bounded or f.is_finite or f.is_infinitesimal))
            ]
        elif coeff is S.NegativeInfinity:
            newseq = [
                f for f in newseq
                if not (f.is_nonpositive or f.is_real and
                        (f.is_bounded or f.is_finite or f.is_infinitesimal))
            ]
        if coeff is S.ComplexInfinity:
            # zoo might be
            #   unbounded_real + bounded_im
            #   bounded_real + unbounded_im
            #   unbounded_real + unbounded_im
            # addition of a bounded real or imaginary number won't be able to
            # change the zoo nature; if unbounded a NaN condition could result if
            # the unbounded symbol had sign opposite of the unbounded portion of zoo,
            # e.g. unbounded_real - unbounded_real
            newseq = [
                c for c in newseq
                if not (c.is_bounded and c.is_real is not None)
            ]

        # process O(x)
        if order_factors:
            newseq2 = []
            for t in newseq:
                for o in order_factors:
                    # x + O(x) -> O(x)
                    if o.contains(t):
                        t = None
                        break
                # x + O(x**2) -> x + O(x**2)
                if t is not None:
                    newseq2.append(t)
            newseq = newseq2 + order_factors
            # 1 + O(1) -> O(1)
            for o in order_factors:
                if o.contains(coeff):
                    coeff = S.Zero
                    break

        # order args canonically
        # Currently we sort things using hashes, as it is quite fast. A better
        # solution is not to sort things at all - but this needs some more
        # fixing.
        newseq.sort(key=hash)

        # current code expects coeff to be always in slot-0
        if coeff is not S.Zero:
            newseq.insert(0, coeff)

        # we are done
        if noncommutative:
            return [], newseq, None
        else:
            return newseq, [], None
Ejemplo n.º 13
0
    def flatten(cls, seq):
        """
        Takes the sequence "seq" of nested Adds and returns a flatten list.

        Returns: (commutative_part, noncommutative_part, order_symbols)

        Applies associativity, all terms are commutable with respect to
        addition.
        """
        terms = {}      # term -> coeff
                        # e.g. x**2 -> 5   for ... + 5*x**2 + ...

        coeff = S.Zero  # standalone term
                        # e.g. 3 + ...
        order_factors = []

        for o in seq:

            # O(x)
            if o.is_Order:
                for o1 in order_factors:
                    if o1.contains(o):
                        o = None
                        break
                if o is None:
                    continue
                order_factors = [o]+[o1 for o1 in order_factors if not o.contains(o1)]
                continue

            # 3
            elif o.is_Number:
                coeff += o
                continue

            # Add([...])
            elif o.is_Add:
                # NB: here we assume Add is always commutative
                seq.extend(o.args)  # TODO zerocopy?
                continue

            # Mul([...])
            elif o.is_Mul:
                c = o.args[0]

                # 3*...
                if c.is_Number:
                    if c is S.One:
                        s = o
                    else:
                        s = o.as_two_terms()[1]

                else:
                    c = S.One
                    s = o

            # everything else
            else:
                c = S.One
                s = o


            # now we have:
            # o = c*s, where
            #
            # c is a Number
            # s is an expression with number factor extracted

            # let's collect terms with the same s, so e.g.
            # 2*x**2 + 3*x**2  ->  5*x**2
            if s in terms:
                terms[s] += c
            else:
                terms[s] = c


        # now let's construct new args:
        # [2*x**2, x**3, 7*x**4, pi, ...]
        newseq = []
        noncommutative = False
        for s,c in terms.items():
            # 0*s
            if c is S.Zero:
                continue
            # 1*s
            elif c is S.One:
                newseq.append(s)
            # c*s
            else:
                if s.is_Mul:
                    # Mul, already keeps it's arguments in perfect order.
                    # so we can simply put c in slot0 and go the fast way.
                    cs = s._new_rawargs(*((c,) + s.args))
                    newseq.append(cs)

                else:
                    # alternatively we have to call all Mul's machinery (slow)
                    newseq.append(Mul(c,s))

            noncommutative = noncommutative or not s.is_commutative

        # nan
        if coeff is S.NaN:
            # we know for sure the result will be nan
            return [S.NaN], [], None

        # oo, -oo
        elif (coeff is S.Infinity) or (coeff is S.NegativeInfinity):
            newseq = [f for f in newseq if not f.is_real]


        # process O(x)
        if order_factors:
            newseq2 = []
            for t in newseq:
                for o in order_factors:
                    # x + O(x) -> O(x)
                    if o.contains(t):
                        t = None
                        break
                # x + O(x**2) -> x + O(x**2)
                if t is not None:
                    newseq2.append(t)
            newseq = newseq2 + order_factors
            # 1 + O(1) -> O(1)
            for o in order_factors:
                if o.contains(coeff):
                    coeff = S.Zero
                    break


        # order args canonically
        # Currently we sort things using hashes, as it is quite fast. A better
        # solution is not to sort things at all - but this needs some more
        # fixing.
        newseq.sort(key=hash)

        # current code expects coeff to be always in slot-0
        if coeff is not S.Zero:
            newseq.insert(0, coeff)

        # we are done
        if noncommutative:
            return [], newseq, None
        else:
            return newseq, [], None
Ejemplo n.º 14
0
    def flatten(cls, seq):
        """
        Takes the sequence "seq" of nested Adds and returns a flatten list.

        Returns: (commutative_part, noncommutative_part, order_symbols)

        Applies associativity, all terms are commutable with respect to
        addition.

        NB: the removal of 0 is already handled by AssocOp.__new__

        See also
        ========

        sympy.core.mul.Mul.flatten

        """
        rv = None
        if len(seq) == 2:
            a, b = seq
            if b.is_Rational:
                a, b = b, a
            if a.is_Rational:
                if b.is_Mul:
                    rv = [a, b], [], None
            if rv:
                if all(s.is_commutative for s in rv[0]):
                    return rv
                return [], rv[0], None

        terms = {}  # term -> coeff
        # e.g. x**2 -> 5   for ... + 5*x**2 + ...

        coeff = S.Zero  # coefficient (Number or zoo) to always be in slot 0
        # e.g. 3 + ...
        order_factors = []

        for o in seq:

            # O(x)
            if o.is_Order:
                for o1 in order_factors:
                    if o1.contains(o):
                        o = None
                        break
                if o is None:
                    continue
                order_factors = [o] + [
                    o1 for o1 in order_factors if not o.contains(o1)
                ]
                continue

            # 3 or NaN
            elif o.is_Number:
                if (o is S.NaN or coeff is S.ComplexInfinity
                        and o.is_bounded is False):
                    # we know for sure the result will be nan
                    return [S.NaN], [], None
                if coeff.is_Number:
                    coeff += o
                    if coeff is S.NaN:
                        # we know for sure the result will be nan
                        return [S.NaN], [], None
                continue

            elif o is S.ComplexInfinity:
                if coeff.is_bounded is False:
                    # we know for sure the result will be nan
                    return [S.NaN], [], None
                coeff = S.ComplexInfinity
                continue

            # Add([...])
            elif o.is_Add:
                # NB: here we assume Add is always commutative
                seq.extend(o.args)  # TODO zerocopy?
                continue

            # Mul([...])
            elif o.is_Mul:
                c, s = o.as_coeff_Mul()

            # check for unevaluated Pow, e.g. 2**3 or 2**(-1/2)
            elif o.is_Pow:
                b, e = o.as_base_exp()
                if b.is_Number and (e.is_Integer or
                                    (e.is_Rational and e.is_negative)):
                    seq.append(b**e)
                    continue
                c, s = S.One, o

            else:
                # everything else
                c = S.One
                s = o

            # now we have:
            # o = c*s, where
            #
            # c is a Number
            # s is an expression with number factor extracted
            # let's collect terms with the same s, so e.g.
            # 2*x**2 + 3*x**2  ->  5*x**2
            if s in terms:
                terms[s] += c
            else:
                terms[s] = c

        # now let's construct new args:
        # [2*x**2, x**3, 7*x**4, pi, ...]
        newseq = []
        noncommutative = False
        for s, c in terms.items():
            # 0*s
            if c is S.Zero:
                continue
            # 1*s
            elif c is S.One:
                newseq.append(s)
            # c*s
            else:
                if s.is_Mul:
                    # Mul, already keeps its arguments in perfect order.
                    # so we can simply put c in slot0 and go the fast way.
                    cs = s._new_rawargs(*((c, ) + s.args))
                    newseq.append(cs)
                elif s.is_Add:
                    # we just re-create the unevaluated Mul
                    newseq.append(Mul(c, s, evaluate=False))
                else:
                    # alternatively we have to call all Mul's machinery (slow)
                    newseq.append(Mul(c, s))

            noncommutative = noncommutative or not s.is_commutative

        # oo, -oo
        if coeff is S.Infinity:
            newseq = [
                f for f in newseq if not (f.is_nonnegative or f.is_real and
                                          (f.is_bounded or f.is_infinitesimal))
            ]

        elif coeff is S.NegativeInfinity:
            newseq = [
                f for f in newseq if not (f.is_nonpositive or f.is_real and
                                          (f.is_bounded or f.is_infinitesimal))
            ]

        if coeff is S.ComplexInfinity:
            # zoo might be
            #   unbounded_real + bounded_im
            #   bounded_real + unbounded_im
            #   unbounded_real + unbounded_im
            # addition of a bounded real or imaginary number won't be able to
            # change the zoo nature; if unbounded a NaN condition could result
            # if the unbounded symbol had sign opposite of the unbounded
            # portion of zoo, e.g., unbounded_real - unbounded_real.
            newseq = [
                c for c in newseq
                if not (c.is_bounded and c.is_real is not None)
            ]

        # process O(x)
        if order_factors:
            newseq2 = []
            for t in newseq:
                for o in order_factors:
                    # x + O(x) -> O(x)
                    if o.contains(t):
                        t = None
                        break
                # x + O(x**2) -> x + O(x**2)
                if t is not None:
                    newseq2.append(t)
            newseq = newseq2 + order_factors
            # 1 + O(1) -> O(1)
            for o in order_factors:
                if o.contains(coeff):
                    coeff = S.Zero
                    break

        # order args canonically
        _addsort(newseq)

        # current code expects coeff to be first
        if coeff is not S.Zero:
            newseq.insert(0, coeff)

        # we are done
        if noncommutative:
            return [], newseq, None
        else:
            return newseq, [], None
Ejemplo n.º 15
0
    def _eval_power(base, exp):
        """
        Tries to do some simplifications on base ** exp, where base is
        an instance of Integer

        Returns None if no further simplifications can be done

        When exponent is a fraction (so we have for example a square root),
        we try to find the simplest possible representation, so that
          - 4**Rational(1,2) becomes 2
          - (-4)**Rational(1,2) becomes 2*I
        We will
        """
        if exp is S.NaN: return S.NaN
        if base is S.One: return S.One
        if base is S.NegativeOne: return
        if exp is S.Infinity:
            if base.p > S.One: return S.Infinity
            if base.p == -1: return S.NaN
            # cases 0, 1 are done in their respective classes
            return S.Infinity + S.ImaginaryUnit * S.Infinity
        if not isinstance(exp, Number):
            # simplify when exp is even
            # (-2) ** k --> 2 ** k
            c,t = base.as_coeff_terms()
            if exp.is_even and isinstance(c, Number) and c < 0:
                return (-c * Mul(*t)) ** exp
        if not isinstance(exp, Rational): return
        if exp is S.Half and base < 0:
            # we extract I for this special case since everyone is doing so
            return S.ImaginaryUnit * Pow(-base, exp)
        if exp < 0:
            # invert base and change sign on exponent
            if base < 0:
                return -(S.NegativeOne) ** ((exp.p % exp.q) / S(exp.q)) * Rational(1, -base) ** (-exp)
            else:
                return Rational(1, base.p) ** (-exp)
        # see if base is a perfect root, sqrt(4) --> 2
        x, xexact = integer_nthroot(abs(base.p), exp.q)
        if xexact:
            # if it's a perfect root we've finished
            result = Integer(x ** abs(exp.p))
            if exp < 0: result = 1/result
            if base < 0: result *= (-1)**exp
            return result
        # The following is an algorithm where we collect perfect roots
        # from the factors of base
        if base > 4294967296:
            # Prevent from factorizing too big integers
            return None
        dict = base.factors()
        out_int = 1
        sqr_int = 1
        sqr_gcd = 0
        sqr_dict = {}
        for prime,exponent in dict.iteritems():
            exponent *= exp.p
            div_e = exponent // exp.q
            div_m = exponent % exp.q
            if div_e > 0:
                out_int *= prime**div_e
            if div_m > 0:
                sqr_dict[prime] = div_m
        for p,ex in sqr_dict.iteritems():
            if sqr_gcd == 0:
                sqr_gcd = ex
            else:
                sqr_gcd = igcd(sqr_gcd, ex)
        for k,v in sqr_dict.iteritems():
            sqr_int *= k**(v // sqr_gcd)
        if sqr_int == base.p and out_int == 1:
            result = None
        else:
            result = out_int * Pow(sqr_int , Rational(sqr_gcd, exp.q))
        return result
Ejemplo n.º 16
0
 def __neg__(self):
     return Mul(S.NegativeOne, self)
Ejemplo n.º 17
0
    def _eval_expand_power_base(self, **hints):
        """(a*b)**n -> a**n * b**n"""
        force = hints.get('force', False)

        b = self.base
        e = self.exp
        if not b.is_Mul:
            return self

        cargs, nc = b.args_cnc(split_1=False)

        # expand each term - this is top-level-only
        # expansion but we have to watch out for things
        # that don't have an _eval_expand method
        if nc:
            nc = [i._eval_expand_power_base(**hints)
                if hasattr(i, '_eval_expand_power_base') else i
                for i in nc]

            if e.is_Integer:
                if e.is_positive:
                    rv = Mul(*nc*e)
                else:
                    rv = 1/Mul(*nc*-e)
                if cargs:
                    rv *= Mul(*cargs)**e
                return rv

            if not cargs:
                return Pow(Mul(*nc), e, evaluate=False)

            nc = [Mul(*nc)]

        # sift the commutative bases
        def pred(x):
            if x is S.ImaginaryUnit:
                return S.ImaginaryUnit
            polar = x.is_polar
            if polar:
                return True
            if polar is None:
                return fuzzy_bool(x.is_nonnegative)
        sifted = sift(cargs, pred)
        nonneg = sifted[True]
        other = sifted[None]
        neg = sifted[False]
        imag = sifted[S.ImaginaryUnit]
        if imag:
            I = S.ImaginaryUnit
            i = len(imag) % 4
            if i == 0:
                pass
            elif i == 1:
                other.append(I)
            elif i == 2:
                if neg:
                    nonn = -neg.pop()
                    if nonn is not S.One:
                        nonneg.append(nonn)
                else:
                    neg.append(S.NegativeOne)
            else:
                if neg:
                    nonn = -neg.pop()
                    if nonn is not S.One:
                        nonneg.append(nonn)
                else:
                    neg.append(S.NegativeOne)
                other.append(I)
            del imag

        # bring out the bases that can be separated from the base

        if force or e.is_integer:
            # treat all commutatives the same and put nc in other
            cargs = nonneg + neg + other
            other = nc
        else:
            # this is just like what is happening automatically, except
            # that now we are doing it for an arbitrary exponent for which
            # no automatic expansion is done

            assert not e.is_Integer

            # handle negatives by making them all positive and putting
            # the residual -1 in other
            if len(neg) > 1:
                o = S.One
                if not other and neg[0].is_Number:
                    o *= neg.pop(0)
                if len(neg) % 2:
                    o = -o
                for n in neg:
                    nonneg.append(-n)
                if o is not S.One:
                    other.append(o)
            elif neg and other:
                if neg[0].is_Number and neg[0] is not S.NegativeOne:
                    other.append(S.NegativeOne)
                    nonneg.append(-neg[0])
                else:
                    other.extend(neg)
            else:
                other.extend(neg)
            del neg

            cargs = nonneg
            other += nc

        rv = S.One
        if cargs:
            rv *= Mul(*[Pow(b, e, evaluate=False) for b in cargs])
        if other:
            rv *= Pow(Mul(*other), e, evaluate=False)
        return rv
Ejemplo n.º 18
0
 def __mul__(self, other):
     return Mul(self, other)
Ejemplo n.º 19
0
    def _eval_expand_power_base(self, deep=True, **hints):
        """(a*b)**n -> a**n * b**n"""
        force = hints.get('force', False)
        b, ewas = self.args
        if deep:
            e = self.exp.expand(deep=deep, **hints)
        else:
            e = self.exp
        if b.is_Mul:
            bargs = b.args
            if force or e.is_integer:
                nonneg = bargs
                other = []
            elif ewas.is_Rational or len(
                    bargs) == 2 and bargs[0] is S.NegativeOne:
                # the Rational exponent was already expanded automatically
                # if there is a negative Number * foo, foo must be unknown
                #    or else it, too, would have automatically expanded;
                #    sqrt(-Number*foo) -> sqrt(Number)*sqrt(-foo); then
                #    sqrt(-foo) -> unchanged if foo is not positive else
                #               -> I*sqrt(foo)
                #    So...if we have a 2 arg Mul and the first is a Number
                #    that number is -1 and there is nothing more than can
                #    be done without the force=True hint
                nonneg = []
            else:
                # this is just like what is happening automatically, except
                # that now we are doing it for an arbitrary exponent for which
                # no automatic expansion is done
                def pred(x):
                    if x.is_polar is None:
                        return x.is_nonnegative
                    return x.is_polar

                sifted = sift(b.args, pred)
                nonneg = sifted[True]
                other = sifted[None]
                neg = sifted[False]

                # make sure the Number gets pulled out
                if neg and neg[0].is_Number and neg[0] is not S.NegativeOne:
                    nonneg.append(-neg[0])
                    neg[0] = S.NegativeOne

                # leave behind a negative sign
                oddneg = len(neg) % 2
                if oddneg:
                    other.append(S.NegativeOne)

                # negate all negatives and append to nonneg
                nonneg += [-n for n in neg]

            if nonneg:  # then there's a new expression to return
                d = sift(nonneg, lambda x: x.is_commutative is True)
                c = d[True]
                nc = d[False]
                if not e.is_Integer:
                    other.extend(nc)
                    nc = []
                elif len(nc) == 1:
                    c.extend(nc)
                    nc = []
                else:
                    nc = [Mul._from_args(nc)] * e
                other = [Pow(Mul(*other), e)] + nc
                if deep:
                    return Mul(*([Pow(b.expand(deep=deep, **hints), e)\
                    for b in c] + other))
                else:
                    return Mul(*([Pow(b, e) for b in c] + other))
        return Pow(b, e)
Ejemplo n.º 20
0
    def _eval_expand_multinomial(self, deep=True, **hints):
        """(a+b+..) ** n -> a**n + n*a**(n-1)*b + .., n is positive integer"""
        if deep:
            b = self.base.expand(deep=deep, **hints)
            e = self.exp.expand(deep=deep, **hints)
        else:
            b = self.base
            e = self.exp

        if b is None:
            base = self.base
        else:
            base = b

        if e is None:
            exp = self.exp
        else:
            exp = e

        if e is not None or b is not None:
            result = base**exp

            if result.is_Pow:
                base, exp = result.base, result.exp
            else:
                return result
        else:
            result = None

        if exp.is_Integer and exp.p > 0 and base.is_Add:
            n = int(exp)

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

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

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

                    return (f*g).expand() + n*g*Add(*order_terms)

                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 = (a.q * b.q) ** n
                                a, b = a.p*b.q, a.q*b.p
                            else:
                                k = a.q ** n
                                a, b = a.p, a.q*b
                        elif not b.is_Integer:
                            k = 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
                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.

                # An elegant way would be to use Poly, but unfortunately it is
                # slower than the direct method below, so it is commented out:
                #b = {}
                #for k in expansion_dict:
                #    b[k] = Integer(expansion_dict[k])
                #return Poly(b, *p).as_basic()

                from sympy.polys.polynomial import multinomial_as_basic
                result = multinomial_as_basic(expansion_dict, *p)
                return result
            else:
                if n == 2:
                    return Add(*[f*g for f in base.args for g in base.args])
                else:
                    return Mul(base, Pow(base, n-1).expand()).expand()
        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 *= base**term
                else:
                    tail += term

            return coeff * base**tail
        else:
            return result