Exemplo n.º 1
0
def _dict_from_expr(expr, opt):
    """Transform an expression into a multinomial form. """
    if expr.is_commutative is False:
        raise PolynomialError('non-commutative expressions are not supported')

    def _is_expandable_pow(expr):
        return (expr.is_Pow and expr.exp.is_positive and expr.exp.is_Integer
                and expr.base.is_Add)

    if opt.expand is not False:
        expr = expr.expand()
        # TODO: Integrate this into expand() itself
        while any(
                _is_expandable_pow(i) or i.is_Mul and any(
                    _is_expandable_pow(j) for j in i.args)
                for i in Add.make_args(expr)):

            expr = expand_multinomial(expr)
        while any(i.is_Mul and any(j.is_Add for j in i.args)
                  for i in Add.make_args(expr)):
            expr = expand_mul(expr)

    if opt.gens:
        rep, gens = _dict_from_expr_if_gens(expr, opt)
    else:
        rep, gens = _dict_from_expr_no_gens(expr, opt)

    return rep, opt.clone({'gens': gens})
Exemplo n.º 2
0
    def _eval_expand_func(self, **hints):
        n, z = self.args

        if n.is_Integer and n.is_nonnegative:
            if z.is_Add:
                coeff = z.args[0]
                if coeff.is_Integer:
                    e = -(n + 1)
                    if coeff > 0:
                        tail = Add(
                            *[Pow(z - i, e) for i in range(1,
                                                           int(coeff) + 1)])
                    else:
                        tail = -Add(
                            *[Pow(z + i, e) for i in range(0, int(-coeff))])
                    return polygamma(n,
                                     z - coeff) + (-1)**n * factorial(n) * tail

            elif z.is_Mul:
                coeff, z = z.as_two_terms()
                if coeff.is_Integer and coeff.is_positive:
                    tail = [
                        polygamma(n, z + Rational(i, coeff))
                        for i in range(0, int(coeff))
                    ]
                    if n == 0:
                        return Add(*tail) / coeff + log(coeff)
                    else:
                        return Add(*tail) / coeff**(n + 1)
                z *= coeff

        return polygamma(n, z)
Exemplo n.º 3
0
    def _eval_expand_func(self, **hints):
        from diofant import Sum
        n = self.args[0]
        m = self.args[1] if len(self.args) == 2 else 1

        if m == S.One:
            if n.is_Add:
                off = n.args[0]
                nnew = n - off
                if off.is_Integer and off.is_positive:
                    result = [S.One / (nnew + i)
                              for i in range(off, 0, -1)] + [harmonic(nnew)]
                    return Add(*result)
                elif off.is_Integer and off.is_negative:
                    result = [-S.One / (nnew + i)
                              for i in range(0, off, -1)] + [harmonic(nnew)]
                    return Add(*result)

            if n.is_Rational:
                # Expansions for harmonic numbers at general rational arguments (u + p/q)
                # Split n as u + p/q with p < q
                p, q = n.as_numer_denom()
                u = p // q
                p = p - u * q
                if u.is_nonnegative and p.is_positive and q.is_positive and p < q:
                    k = Dummy("k")
                    t1 = q * Sum(1 / (q * k + p), (k, 0, u))
                    t2 = 2 * Sum(
                        cos((2 * pi * p * k) / q) * log(sin((pi * k) / q)),
                        (k, 1, floor((q - 1) / Integer(2))))
                    t3 = (pi / 2) * cot((pi * p) / q) + log(2 * q)
                    return t1 + t2 - t3

        return self
Exemplo n.º 4
0
def sum_simplify(s):
    """Main function for Sum simplification"""
    from diofant.concrete.summations import Sum

    terms = Add.make_args(s)
    s_t = []  # Sum Terms
    o_t = []  # Other Terms

    for term in terms:
        if isinstance(term, Mul):
            constant = 1
            other = 1
            s = 0
            n_sum_terms = 0
            for j in range(len(term.args)):
                if isinstance(term.args[j], Sum):
                    s = term.args[j]
                    n_sum_terms = n_sum_terms + 1
                elif term.args[j].is_number:
                    constant = constant * term.args[j]
                else:
                    other = other * term.args[j]
            if other == 1 and n_sum_terms == 1:
                # Insert the constant inside the Sum
                s_t.append(Sum(constant * s.function, *s.limits))
            elif other != 1 and n_sum_terms == 1:
                o_t.append(other * Sum(constant * s.function, *s.limits))
            else:
                o_t.append(term)
        elif isinstance(term, Sum):
            s_t.append(term)
        else:
            o_t.append(term)

    used = [False] * len(s_t)

    for method in range(2):
        for i, s_term1 in enumerate(s_t):
            if not used[i]:
                for j, s_term2 in enumerate(s_t):
                    if not used[j] and i != j:
                        temp = sum_add(s_term1, s_term2, method)
                        if isinstance(temp, Sum):
                            s_t[i] = temp
                            s_term1 = s_t[i]
                            used[j] = True

    result = Add(*o_t)

    for i, s_term in enumerate(s_t):
        if not used[i]:
            result = Add(result, s_term)

    return result
Exemplo n.º 5
0
def fateman_poly_F_1(n):
    """Fateman's GCD benchmark: trivial GCD """
    Y = [Symbol('y_' + str(i)) for i in range(0, n + 1)]

    y_0, y_1 = Y[0], Y[1]

    u = y_0 + Add(*[y for y in Y[1:]])
    v = y_0**2 + Add(*[y**2 for y in Y[1:]])

    F = ((u + 1) * (u + 2)).as_poly(*Y)
    G = ((v + 1) * (-3 * y_1 * y_0**2 + y_1**2 - 1)).as_poly(*Y)

    H = Poly(1, *Y)

    return F, G, H
Exemplo n.º 6
0
def swinnerton_dyer_poly(n, x=None, **args):
    """Generates n-th Swinnerton-Dyer polynomial in `x`.  """
    from .numberfields import minimal_polynomial
    if n <= 0:
        raise ValueError(
            "can't generate Swinnerton-Dyer polynomial of order %s" % n)

    if x is not None:
        sympify(x)
    else:
        x = Dummy('x')

    if n > 3:
        p = 2
        a = [sqrt(2)]
        for i in range(2, n + 1):
            p = nextprime(p)
            a.append(sqrt(p))
        return minimal_polynomial(Add(*a), x, polys=args.get('polys', False))

    if n == 1:
        ex = x**2 - 2
    elif n == 2:
        ex = x**4 - 10 * x**2 + 1
    elif n == 3:
        ex = x**8 - 40 * x**6 + 352 * x**4 - 960 * x**2 + 576
    if not args.get('polys', False):
        return ex
    else:
        return PurePoly(ex, x)
Exemplo n.º 7
0
def sum_add(self, other, method=0):
    """Helper function for Sum simplification"""
    from diofant.concrete.summations import Sum

    if type(self) == type(other):
        if method == 0:
            if self.limits == other.limits:
                return Sum(self.function + other.function, *self.limits)
        elif method == 1:
            if simplify(self.function - other.function) == 0:
                if len(self.limits) == len(other.limits) == 1:
                    i = self.limits[0][0]
                    x1 = self.limits[0][1]
                    y1 = self.limits[0][2]
                    j = other.limits[0][0]
                    x2 = other.limits[0][1]
                    y2 = other.limits[0][2]

                    if i == j:
                        if x2 == y1 + 1:
                            return Sum(self.function, (i, x1, y2))
                        elif x1 == y2 + 1:
                            return Sum(self.function, (i, x2, y1))

    return Add(self, other)
Exemplo n.º 8
0
 def _eval_evalf(self, prec):
     try:
         _roots = self.poly.nroots(n=prec_to_dps(prec))
     except (DomainError, PolynomialError):
         return self
     else:
         return Add(*[self.fun(r) for r in _roots])
Exemplo n.º 9
0
def interpolating_poly(n, x, X='x', Y='y'):
    """Construct Lagrange interpolating polynomial for ``n`` data points. """
    if isinstance(X, str):
        X = symbols("%s:%s" % (X, n))

    if isinstance(Y, str):
        Y = symbols("%s:%s" % (Y, n))

    coeffs = []

    for i in range(0, n):
        numer = []
        denom = []

        for j in range(0, n):
            if i == j:
                continue

            numer.append(x - X[j])
            denom.append(X[i] - X[j])

        numer = Mul(*numer)
        denom = Mul(*denom)

        coeffs.append(numer / denom)

    return Add(*[coeff * y for coeff, y in zip(coeffs, Y)])
Exemplo n.º 10
0
def test_glom():
    def key(x):
        return x.as_coeff_Mul()[1]

    def count(x):
        return x.as_coeff_Mul()[0]

    def newargs(cnt, arg):
        return cnt * arg

    rl = glom(key, count, newargs)

    result = rl(Add(x, -x, 3 * x, 2, 3, evaluate=False))
    expected = Add(3 * x, 5)
    assert set(result.args) == set(expected.args)

    result = rl(Add(*expected.args, evaluate=False))
    assert set(result.args) == set(expected.args)
Exemplo n.º 11
0
    def doit(self, **hints):
        if not hints.get('roots', True):
            return self

        _roots = roots(self.poly, multiple=True)

        if len(_roots) < self.poly.degree():
            return self
        else:
            return Add(*[self.fun(r) for r in _roots])
Exemplo n.º 12
0
def _separatevars(expr, force):
    if len(expr.free_symbols) == 1:
        return expr
    # don't destroy a Mul since much of the work may already be done
    if expr.is_Mul:
        args = list(expr.args)
        changed = False
        for i, a in enumerate(args):
            args[i] = separatevars(a, force)
            changed = changed or args[i] != a
        if changed:
            expr = expr.func(*args)
        return expr

    # get a Pow ready for expansion
    if expr.is_Pow:
        expr = Pow(separatevars(expr.base, force=force), expr.exp)

    # First try other expansion methods
    expr = expr.expand(mul=False, multinomial=False, force=force)

    _expr, reps = posify(expr) if force else (expr, {})
    expr = factor(_expr).subs(reps)

    if not expr.is_Add:
        return expr

    # Find any common coefficients to pull out
    args = list(expr.args)
    commonc = args[0].args_cnc(cset=True, warn=False)[0]
    for i in args[1:]:
        commonc &= i.args_cnc(cset=True, warn=False)[0]
    commonc = Mul(*commonc)
    commonc = commonc.as_coeff_Mul()[1]  # ignore constants
    commonc_set = commonc.args_cnc(cset=True, warn=False)[0]

    # remove them
    for i, a in enumerate(args):
        c, nc = a.args_cnc(cset=True, warn=False)
        c = c - commonc_set
        args[i] = Mul(*c) * Mul(*nc)
    nonsepar = Add(*args)

    if len(nonsepar.free_symbols) > 1:
        _expr = nonsepar
        _expr, reps = posify(_expr) if force else (_expr, {})
        _expr = (factor(_expr)).subs(reps)

        if not _expr.is_Add:
            nonsepar = _expr

    return commonc * nonsepar
Exemplo n.º 13
0
def split_surds(expr):
    """
    split an expression with terms whose squares are rationals
    into a sum of terms whose surds squared have gcd equal to g
    and a sum of terms with surds squared prime with g

    Examples
    ========

    >>> from diofant import sqrt
    >>> from diofant.simplify.radsimp import split_surds
    >>> split_surds(3*sqrt(3) + sqrt(5)/7 + sqrt(6) + sqrt(10) + sqrt(15))
    (3, sqrt(2) + sqrt(5) + 3, sqrt(5)/7 + sqrt(10))
    """
    args = sorted(expr.args, key=default_sort_key)
    coeff_muls = [x.as_coeff_Mul() for x in args]
    surds = [x[1]**2 for x in coeff_muls if x[1].is_Pow]
    surds.sort(key=default_sort_key)
    g, b1, b2 = _split_gcd(*surds)
    g2 = g
    if not b2 and len(b1) >= 2:
        b1n = [x / g for x in b1]
        b1n = [x for x in b1n if x != 1]
        # only a common factor has been factored; split again
        g1, b1n, b2 = _split_gcd(*b1n)
        g2 = g * g1
    a1v, a2v = [], []
    for c, s in coeff_muls:
        if s.is_Pow and s.exp == S.Half:
            s1 = s.base
            if s1 in b1:
                a1v.append(c * sqrt(s1 / g2))
            else:
                a2v.append(c * s)
        else:
            a2v.append(c * s)
    a = Add(*a1v)
    b = Add(*a2v)
    return g2, a, b
Exemplo n.º 14
0
def expr_from_dict(rep, *gens):
    """Convert a multinomial form into an expression. """
    result = []

    for monom, coeff in rep.items():
        term = [coeff]
        for g, m in zip(gens, monom):
            if m:
                term.append(Pow(g, m))

        result.append(Mul(*term))

    return Add(*result)
Exemplo n.º 15
0
    def _print_Add(self, expr):
        # purpose: print complex numbers nicely in Fortran.
        # collect the purely real and purely imaginary parts:
        pure_real = []
        pure_imaginary = []
        mixed = []
        for arg in expr.args:
            if arg.is_number and arg.is_extended_real:
                pure_real.append(arg)
            elif arg.is_number and arg.is_imaginary:
                pure_imaginary.append(arg)
            else:
                mixed.append(arg)
        if len(pure_imaginary) > 0:
            if len(mixed) > 0:
                PREC = precedence(expr)
                term = Add(*mixed)
                t = self._print(term)
                if t.startswith('-'):
                    sign = "-"
                    t = t[1:]
                else:
                    sign = "+"
                if precedence(term) < PREC:
                    t = "(%s)" % t

                return "cmplx(%s,%s) %s %s" % (
                    self._print(Add(*pure_real)),
                    self._print(-S.ImaginaryUnit * Add(*pure_imaginary)),
                    sign,
                    t,
                )
            else:
                return "cmplx(%s,%s)" % (
                    self._print(Add(*pure_real)),
                    self._print(-S.ImaginaryUnit * Add(*pure_imaginary)),
                )
        else:
            return CodePrinter._print_Add(self, expr)
Exemplo n.º 16
0
def fateman_poly_F_2(n):
    """Fateman's GCD benchmark: linearly dense quartic inputs """
    Y = [Symbol('y_' + str(i)) for i in range(0, n + 1)]

    y_0 = Y[0]

    u = Add(*[y for y in Y[1:]])

    H = Poly((y_0 + u + 1)**2, *Y)

    F = Poly((y_0 - u - 2)**2, *Y)
    G = Poly((y_0 + u + 2)**2, *Y)

    return H * F, H * G, H
Exemplo n.º 17
0
def fateman_poly_F_3(n):
    """Fateman's GCD benchmark: sparse inputs (deg f ~ vars f) """
    Y = [Symbol('y_' + str(i)) for i in range(0, n + 1)]

    y_0 = Y[0]

    u = Add(*[y**(n + 1) for y in Y[1:]])

    H = Poly((y_0**(n + 1) + u + 1)**2, *Y)

    F = Poly((y_0**(n + 1) - u - 2)**2, *Y)
    G = Poly((y_0**(n + 1) + u + 2)**2, *Y)

    return H * F, H * G, H
Exemplo n.º 18
0
def _parallel_dict_from_expr_if_gens(exprs, opt):
    """Transform expressions into a multinomial form given generators. """
    k, indices = len(opt.gens), {}

    for i, g in enumerate(opt.gens):
        indices[g] = i

    polys = []

    for expr in exprs:
        poly = {}

        if expr.is_Equality:
            expr = expr.lhs - expr.rhs

        for term in Add.make_args(expr):
            coeff, monom = [], [0] * k

            for factor in Mul.make_args(term):
                if not _not_a_coeff(factor) and factor.is_Number:
                    coeff.append(factor)
                else:
                    try:
                        base, exp = decompose_power(factor)

                        if exp < 0:
                            exp, base = -exp, Pow(base, -S.One)

                        monom[indices[base]] += exp
                    except KeyError:
                        if not factor.free_symbols.intersection(opt.gens):
                            coeff.append(factor)
                        else:
                            raise PolynomialError(
                                "%s contains an element of the generators set"
                                % factor)

            monom = tuple(monom)

            if monom in poly:
                poly[monom] += Mul(*coeff)
            else:
                poly[monom] = Mul(*coeff)

        polys.append(poly)

    return polys, opt.gens
Exemplo n.º 19
0
def symmetric_poly(n, *gens, **args):
    """Generates symmetric polynomial of order `n`. """
    gens = _analyze_gens(gens)

    if n < 0 or n > len(gens) or not gens:
        raise ValueError(
            "can't generate symmetric polynomial of order %s for %s" %
            (n, gens))
    elif not n:
        poly = S.One
    else:
        poly = Add(*[Mul(*s) for s in subsets(gens, int(n))])

    if not args.get('polys', False):
        return poly
    else:
        return Poly(poly, *gens)
Exemplo n.º 20
0
 def _eval_aseries(self, n, args0, x, logx):
     from diofant import Order
     if args0[0] != oo:
         return super(loggamma, self)._eval_aseries(n, args0, x, logx)
     z = self.args[0]
     m = min(n, ceiling((n + Integer(1)) / 2))
     r = log(z) * (z - Rational(1, 2)) - z + log(2 * pi) / 2
     l = [
         bernoulli(2 * k) / (2 * k * (2 * k - 1) * z**(2 * k - 1))
         for k in range(1, m)
     ]
     o = None
     if m == 0:
         o = Order(1, x)
     else:
         o = Order(1 / z**(2 * m - 1), x)
     # It is very inefficient to first add the order and then do the nseries
     return (r + Add(*l))._eval_nseries(x, n, logx) + o
Exemplo n.º 21
0
    def eval(cls, n, sym=None):
        if n.is_Number:
            if n.is_Integer and n.is_nonnegative:
                if n is S.Zero:
                    return S.One
                elif n is S.One:
                    if sym is None:
                        return -S.Half
                    else:
                        return sym - S.Half
                # Bernoulli numbers
                elif sym is None:
                    if n.is_odd:
                        return S.Zero
                    n = int(n)
                    # Use mpmath for enormous Bernoulli numbers
                    if n > 500:
                        p, q = bernfrac(n)
                        return Rational(int(p), int(q))
                    case = n % 6
                    highest_cached = cls._highest[case]
                    if n <= highest_cached:
                        return cls._cache[n]
                    # To avoid excessive recursion when, say, bernoulli(1000) is
                    # requested, calculate and cache the entire sequence ... B_988,
                    # B_994, B_1000 in increasing order
                    for i in range(highest_cached + 6, n + 6, 6):
                        b = cls._calc_bernoulli(i)
                        cls._cache[i] = b
                        cls._highest[case] = i
                    return b
                # Bernoulli polynomials
                else:
                    n, result = int(n), []
                    for k in range(n + 1):
                        result.append(binomial(n, k) * cls(k) * sym**(n - k))
                    return Add(*result)
            else:
                raise ValueError("Bernoulli numbers are defined only"
                                 " for nonnegative integer indices.")

        if sym is None:
            if n.is_odd and (n - 1).is_positive:
                return S.Zero
Exemplo n.º 22
0
    def _eval_aseries(self, n, args0, x, logx):
        from diofant import Order
        if args0[1] != oo or not \
                (self.args[0].is_Integer and self.args[0].is_nonnegative):
            return super(polygamma, self)._eval_aseries(n, args0, x, logx)
        z = self.args[1]
        N = self.args[0]

        if N == 0:
            # digamma function series
            # Abramowitz & Stegun, p. 259, 6.3.18
            r = log(z) - 1 / (2 * z)
            o = None
            if n < 2:
                o = Order(1 / z, x)
            else:
                m = ceiling((n + 1) // 2)
                l = [
                    bernoulli(2 * k) / (2 * k * z**(2 * k))
                    for k in range(1, m)
                ]
                r -= Add(*l)
                o = Order(1 / z**(2 * m), x)
            return r._eval_nseries(x, n, logx) + o
        else:
            # proper polygamma function
            # Abramowitz & Stegun, p. 260, 6.4.10
            # We return terms to order higher than O(x**n) on purpose
            # -- otherwise we would not be able to return any terms for
            #    quite a long time!
            fac = gamma(N)
            e0 = fac + N * fac / (2 * z)
            m = ceiling((n + 1) // 2)
            for k in range(1, m):
                fac = fac * (2 * k + N - 1) * (2 * k + N - 2) / ((2 * k) *
                                                                 (2 * k - 1))
                e0 += bernoulli(2 * k) * fac / z**(2 * k)
            o = Order(1 / z**(2 * m), x)
            if n == 0:
                o = Order(1 / z, x)
            elif n == 1:
                o = Order(1 / z**2, x)
            r = e0 + o
            return (-1 * (-1 / z)**N * r)._eval_nseries(x, n, logx)
Exemplo n.º 23
0
def mrv_leadterm(e, x):
    """
    Compute the leading term of the series.

    Returns
    =======

    tuple
        The leading term `c_0 w^{e_0}` of the series of `e` in terms
        of the most rapidly varying subexpression `w` in form of
        the pair ``(c0, e0)`` of Expr.

    Examples
    ========

    >>> from diofant import Symbol, exp

    >>> x = Symbol('x', real=True, positive=True)

    >>> mrv_leadterm(1/exp(-x + exp(-x)) - exp(x), x)
    (-1, 0)
    """
    if not e.has(x):
        return e, S.Zero

    e = e.replace(lambda f: f.is_Pow and f.base != S.Exp1 and f.exp.has(x),
                  lambda f: exp(log(f.base) * f.exp))
    e = e.replace(
        lambda f: f.is_Mul and sum(a.is_Pow for a in f.args) > 1,
        lambda f: Mul(
            exp(Add(*[a.exp for a in f.args
                      if a.is_Pow and a.base is S.Exp1])), *
            [a for a in f.args if not a.is_Pow or a.base is not S.Exp1]))

    # The positive dummy, w, is used here so log(w*2) etc. will expand.
    # TODO: For limits of complex functions, the algorithm would have to
    # be improved, or just find limits of Re and Im components separately.
    w = Dummy("w", real=True, positive=True)
    e, logw = rewrite(e, x, w)

    lt = e.compute_leading_term(w, logx=logw)
    return lt.as_coeff_exponent(w)
Exemplo n.º 24
0
 def parse_hints(hints):
     """Split hints into (n, funcs, iterables, gens)."""
     n = 1
     funcs, iterables, gens = [], [], []
     for e in hints:
         if isinstance(e, (int, Integer)):
             n = e
         elif isinstance(e, FunctionClass):
             funcs.append(e)
         elif iterable(e):
             iterables.append((e[0], e[1:]))
             # XXX sin(x+2y)?
             # Note: we go through polys so e.g.
             # sin(-x) -> -sin(x) -> sin(x)
             gens.extend(
                 parallel_poly_from_expr([e[0](x) for x in e[1:]] +
                                         [e[0](Add(*e[1:]))])[1].gens)
         else:
             gens.append(e)
     return n, funcs, iterables, gens
Exemplo n.º 25
0
    def _entry(self, i, j, expand=True):
        coeff, matrices = self.as_coeff_matrices()

        if len(matrices) == 1:  # situation like 2*X, matmul is just X
            return coeff * matrices[0][i, j]

        head, tail = matrices[0], matrices[1:]
        if len(tail) == 0:
            raise ValueError("lenth of tail cannot be 0")
        X = head
        Y = MatMul(*tail)

        from diofant.core.symbol import Dummy
        from diofant.concrete.summations import Sum
        from diofant.matrices import ImmutableMatrix
        k = Dummy('k', integer=True)
        if X.has(ImmutableMatrix) or Y.has(ImmutableMatrix):
            return coeff * Add(*[X[i, k] * Y[k, j] for k in range(X.cols)])
        result = Sum(coeff * X[i, k] * Y[k, j], (k, 0, X.cols - 1))
        return result.doit() if expand else result
Exemplo n.º 26
0
def ratsimp(expr):
    """
    Put an expression over a common denominator, cancel and reduce.

    Examples
    ========

    >>> from diofant import ratsimp
    >>> from diofant.abc import x, y
    >>> ratsimp(1/x + 1/y)
    (x + y)/(x*y)
    """

    f, g = cancel(expr).as_numer_denom()
    try:
        Q, r = reduced(f, [g], field=True, expand=False)
    except ComputationFailed:
        return f / g

    return Add(*Q) + cancel(r / g)
Exemplo n.º 27
0
    def _together(expr):
        if isinstance(expr, Basic):
            if expr.is_Atom or (expr.is_Function and not deep):
                return expr
            elif expr.is_Add:
                return gcd_terms(list(map(_together, Add.make_args(expr))))
            elif expr.is_Pow:
                base = _together(expr.base)

                if deep:
                    exp = _together(expr.exp)
                else:
                    exp = expr.exp

                return expr.__class__(base, exp)
            else:
                return expr.__class__(*[_together(arg) for arg in expr.args])
        elif iterable(expr):
            return expr.__class__([_together(ex) for ex in expr])

        return expr
Exemplo n.º 28
0
def _sqrtdenest0(expr):
    """Returns expr after denesting its arguments."""

    if is_sqrt(expr):
        n, d = expr.as_numer_denom()
        if d is S.One:  # n is a square root
            if n.base.is_Add:
                args = sorted(n.base.args, key=default_sort_key)
                if len(args) > 2 and all((x**2).is_Integer for x in args):
                    try:
                        return _sqrtdenest_rec(n)
                    except SqrtdenestStopIteration:
                        pass
                expr = sqrt(_mexpand(Add(*[_sqrtdenest0(x) for x in args])))
            return _sqrtdenest1(expr)
        else:
            n, d = [_sqrtdenest0(i) for i in (n, d)]
            return n / d
    if isinstance(expr, Expr):
        args = expr.args
        if args:
            return expr.func(*[_sqrtdenest0(a) for a in args])
    return expr
Exemplo n.º 29
0
def test_Identity_doit():
    Inn = Identity(Add(n, n, evaluate=False))
    assert isinstance(Inn.rows, Add)
    assert Inn.doit() == Identity(2 * n)
    assert isinstance(Inn.doit().rows, Mul)
Exemplo n.º 30
0
def test_ZeroMatrix_doit():
    Znn = ZeroMatrix(Add(n, n, evaluate=False), n)
    assert isinstance(Znn.rows, Add)
    assert Znn.doit() == ZeroMatrix(2 * n, n)
    assert isinstance(Znn.doit().rows, Mul)