def _expr_big_minus(cls, a, z, n): if n.is_even: return (1 + z)**a * exp(2 * pi * I * n * a) * cos( 2 * a * atan(sqrt(z))) else: return (1 + z)**a * exp( 2 * pi * I * n * a) * cos(2 * a * atan(sqrt(z)) - 2 * pi * a)
def test_contraction_structure_Mul_and_Pow(): x = IndexedBase('x') y = IndexedBase('y') i, j, k = Idx('i'), Idx('j'), Idx('k') i_ji = x[i]**(y[j]*x[i]) assert get_contraction_structure(i_ji) == {None: {i_ji}} ij_i = (x[i]*y[j])**(y[i]) assert get_contraction_structure(ij_i) == {None: {ij_i}} j_ij_i = x[j]*(x[i]*y[j])**(y[i]) assert get_contraction_structure(j_ij_i) == {(j,): {j_ij_i}} j_i_ji = x[j]*x[i]**(y[j]*x[i]) assert get_contraction_structure(j_i_ji) == {(j,): {j_i_ji}} ij_exp_kki = x[i]*y[j]*exp(y[i]*y[k, k]) result = get_contraction_structure(ij_exp_kki) expected = { (i,): {ij_exp_kki}, ij_exp_kki: [{ None: {exp(y[i]*y[k, k])}, exp(y[i]*y[k, k]): [{ None: {y[i]*y[k, k]}, y[i]*y[k, k]: [{(k,): {y[k, k]}}] }]} ] } assert result == expected
def _expr_big_minus(self, a, z, n): if n.is_even: return (1 + z)**a * exp(2 * pi * I * n * a) * sqrt(z) * sin( 2 * a * atan(sqrt(z))) else: return (1 + z)**a*exp(2*pi*I*n*a)*sqrt(z) \ * sin(2*a*atan(sqrt(z)) - 2*pi*a)
def test_contraction_structure_Mul_and_Pow(): x = IndexedBase('x') y = IndexedBase('y') i, j, k = Idx('i'), Idx('j'), Idx('k') i_ji = x[i]**(y[j] * x[i]) assert get_contraction_structure(i_ji) == {None: {i_ji}} ij_i = (x[i] * y[j])**(y[i]) assert get_contraction_structure(ij_i) == {None: {ij_i}} j_ij_i = x[j] * (x[i] * y[j])**(y[i]) assert get_contraction_structure(j_ij_i) == {(j, ): {j_ij_i}} j_i_ji = x[j] * x[i]**(y[j] * x[i]) assert get_contraction_structure(j_i_ji) == {(j, ): {j_i_ji}} ij_exp_kki = x[i] * y[j] * exp(y[i] * y[k, k]) result = get_contraction_structure(ij_exp_kki) expected = { (i, ): {ij_exp_kki}, ij_exp_kki: [{ None: {exp(y[i] * y[k, k])}, exp(y[i] * y[k, k]): [{ None: {y[i] * y[k, k]}, y[i] * y[k, k]: [{ (k, ): {y[k, k]} }] }] }] } assert result == expected
def _expr_big(cls, a, z, n): if n.is_even: return ((sqrt(z) + 1)**(2 * a) * exp(2 * pi * I * n * a) + (sqrt(z) - 1)**(2 * a) * exp(2 * pi * I * (n - 1) * a)) / 2 else: n -= 1 return ((sqrt(z) - 1)**(2 * a) * exp(2 * pi * I * a * (n + 1)) + (sqrt(z) + 1)**(2 * a) * exp(2 * pi * I * a * n)) / 2
def _expr_big(cls, a, z, n): if n.is_even: return sqrt(z) / 2 * ( (sqrt(z) - 1)**(2 * a) * exp(2 * pi * I * a * (n - 1)) - (sqrt(z) + 1)**(2 * a) * exp(2 * pi * I * a * n)) else: n -= 1 return sqrt(z) / 2 * ( (sqrt(z) - 1)**(2 * a) * exp(2 * pi * I * a * (n + 1)) - (sqrt(z) + 1)**(2 * a) * exp(2 * pi * I * a * n))
def test_functional_exponent(): t = standard_transformations + (convert_xor, function_exponentiation) x = Symbol('x') y = Symbol('y') a = Symbol('a') yfcn = Function('y') assert parse_expr("sin^2(x)", transformations=t) == (sin(x))**2 assert parse_expr("sin^y(x)", transformations=t) == (sin(x))**y assert parse_expr("exp^y(x)", transformations=t) == (exp(x))**y assert parse_expr("E^y(x)", transformations=t) == exp(yfcn(x)) assert parse_expr("a^y(x)", transformations=t) == a**(yfcn(x))
def roots_cyclotomic(f, factor=False): """Compute roots of cyclotomic polynomials. """ L, U = _inv_totient_estimate(f.degree()) for n in range(L, U + 1): g = cyclotomic_poly(n, f.gen, polys=True) if f == g: break else: # pragma: no cover raise RuntimeError("failed to find index of a cyclotomic polynomial") roots = [] if not factor: # get the indices in the right order so the computed # roots will be sorted h = n//2 ks = [i for i in range(1, n + 1) if igcd(i, n) == 1] ks.sort(key=lambda x: (x, -1) if x <= h else (abs(x - n), 1)) d = 2*I*pi/n for k in reversed(ks): roots.append(exp(k*d).expand(complex=True)) else: g = Poly(f, extension=root(-1, n)) for h, _ in ordered(g.factor_list()[1]): roots.append(-h.TC()) return roots
def test_Sum(): assert mcode(Sum(sin(x), (x, 0, 10))) == "Hold[Sum[Sin[x], {x, 0, 10}]]" assert mcode(Sum(exp(-x**2 - y**2), (x, -oo, oo), (y, -oo, oo))) == \ "Hold[Sum[E^(-x^2 - y^2), {x, -Infinity, Infinity}, " \ "{y, -Infinity, Infinity}]]"
def test_maximize(): # issue sympy/sympy#4173 assert maximize([x**(1/x), x > 0], x) == (exp(1/E), {x: E}) # https://groups.google.com/forum/#!topic/sympy/tB2Sly4Gh_4 assert maximize([12*x + 40*y, x + y <= 16, x + 3*y <= 36, x <= 10, x >= 0, y >= 0], x, y) == (480, {x: 0, y: 12})
def test_diofant_parser(): x = Symbol('x') inputs = { '2*x': 2 * x, '3.00': Float(3), '22/7': Rational(22, 7), '2+3j': 2 + 3 * I, 'exp(x)': exp(x), '-(2)': -Integer(2), '[-1, -2, 3]': [Integer(-1), Integer(-2), Integer(3)], 'Symbol("x").free_symbols': x.free_symbols, 'Float(Integer(3).evalf(3))': 3.00, 'factorint(12, visual=True)': Mul(Pow(2, 2, evaluate=False), Pow(3, 1, evaluate=False), evaluate=False), 'Limit(sin(x), x, 0, dir="-")': Limit(sin(x), x, 0, dir='-'), } for text, result in inputs.items(): assert parse_expr(text) == result
def test_Integral(): assert mcode(Integral(sin(sin(x)), x)) == "Hold[Integrate[Sin[Sin[x]], x]]" assert mcode(Integral(exp(-x**2 - y**2), (x, -oo, oo), (y, -oo, oo))) == \ "Hold[Integrate[E^(-x^2 - y^2), {x, -Infinity, Infinity}, " \ "{y, -Infinity, Infinity}]]"
def _expr_big(cls, a, x, n): sgn = -1 if n.is_odd: sgn = 1 n -= 1 return 2**(2*a - 1)*(1 + sgn*I*sqrt(x - 1))**(1 - 2*a) \ * exp(-2*n*pi*I*a)
def test_schwarzschild(): m = Manifold('Schwarzschild', 4) p = Patch('origin', m) cs = CoordSystem('spherical', p, ['t', 'r', 'theta', 'phi']) t, r, theta, phi = cs.coord_functions() dt, dr, dtheta, dphi = cs.base_oneforms() f, g = symbols('f g', cls=Function) metric = (exp(2*f(r))*TP(dt, dt) - exp(2*g(r))*TP(dr, dr) - r**2*TP(dtheta, dtheta) - r**2*sin(theta)**2*TP(dphi, dphi)) ricci = metric_to_Ricci_components(metric) assert all(ricci[i, j] == 0 for i in range(4) for j in range(4) if i != j) R = Symbol('R') eq1 = simplify((ricci[0, 0]/exp(2*f(r) - 2*g(r)) + ricci[1, 1])*r/2).subs(r, R).doit() assert eq1 == f(R).diff(R) + g(R).diff(R) eq2 = simplify(ricci[1, 1].replace(g, lambda x: -f(x)).replace(r, R).doit()) assert eq2 == -2*f(R).diff(R)**2 - f(R).diff(R, 2) - 2*f(R).diff(R)/R
def test_schwarzschild(): m = Manifold('Schwarzschild', 4) p = Patch('origin', m) cs = CoordSystem('spherical', p, ['t', 'r', 'theta', 'phi']) t, r, theta, phi = cs.coord_functions() dt, dr, dtheta, dphi = cs.base_oneforms() f, g = symbols('f g', cls=Function) metric = (exp(2*f(r))*TP(dt, dt) - exp(2*g(r))*TP(dr, dr) - r**2*TP(dtheta, dtheta) - r**2*sin(theta)**2*TP(dphi, dphi)) ricci = metric_to_Ricci_components(metric) assert all(ricci[i, j] == 0 for i in range(4) for j in range(4) if i != j) R = Symbol('R') eq1 = simplify((ricci[0, 0]/exp(2*f(r) - 2*g(r)) + ricci[1, 1])*r/2).subs({r: R}).doit() assert eq1 == f(R).diff(R) + g(R).diff(R) eq2 = simplify(ricci[1, 1].replace(g, lambda x: -f(x)).replace(r, R).doit()) assert eq2 == -2*f(R).diff(R)**2 - f(R).diff(R, 2) - 2*f(R).diff(R)/R
def test_pickling_polys_rootoftools(): f = x**3 + x + 3 for c in (RootOf, RootOf(f, 0)): check(c) for c in (RootSum, RootSum(f, Lambda(x, exp(x)))): check(c)
def test_constants(): assert mcode(pi) == "pi" assert mcode(oo) == "inf" assert mcode(-oo) == "-inf" assert mcode(S.NegativeInfinity) == "-inf" assert mcode(S.NaN) == "NaN" assert mcode(S.Exp1) == "exp(1)" assert mcode(exp(1)) == "exp(1)"
def test_deltasummation_basic_symbolic(): assert ds(Kd(exp(i), 0), (i, 1, 3)) == 0 assert ds(Kd(exp(i), 0), (i, -1, 3)) == 0 assert ds(Kd(exp(i), 1), (i, 0, 3)) == 1 assert ds(Kd(exp(i), 1), (i, 1, 3)) == 0 assert ds(Kd(exp(i), 1), (i, -10, 3)) == 1 assert ds(Kd(i, j), (j, 1, 3)) == \ Piecewise((1, And(Integer(1) <= i, i <= 3)), (0, True)) assert ds(Kd(i, j), (j, 1, 1)) == Piecewise((1, Eq(i, 1)), (0, True)) assert ds(Kd(i, j), (j, 2, 2)) == Piecewise((1, Eq(i, 2)), (0, True)) assert ds(Kd(i, j), (j, 3, 3)) == Piecewise((1, Eq(i, 3)), (0, True)) assert ds(Kd(i, j), (j, 1, k)) == \ Piecewise((1, And(Integer(1) <= i, i <= k)), (0, True)) assert ds(Kd(i, j), (j, k, 3)) == \ Piecewise((1, And(k <= i, i <= 3)), (0, True)) assert ds(Kd(i, j), (j, k, l)) == \ Piecewise((1, And(k <= i, i <= l)), (0, True))
def test_deltasummation_basic_symbolic(): assert ds(KD(exp(i), 0), (i, 1, 3)) == 0 assert ds(KD(exp(i), 0), (i, -1, 3)) == 0 assert ds(KD(exp(i), 1), (i, 0, 3)) == 1 assert ds(KD(exp(i), 1), (i, 1, 3)) == 0 assert ds(KD(exp(i), 1), (i, -10, 3)) == 1 assert ds(KD(i, j), (j, 1, 3)) == \ Piecewise((1, And(Integer(1) <= i, i <= 3)), (0, True)) assert ds(KD(i, j), (j, 1, 1)) == Piecewise((1, Eq(i, 1)), (0, True)) assert ds(KD(i, j), (j, 2, 2)) == Piecewise((1, Eq(i, 2)), (0, True)) assert ds(KD(i, j), (j, 3, 3)) == Piecewise((1, Eq(i, 3)), (0, True)) assert ds(KD(i, j), (j, 1, k)) == \ Piecewise((1, And(Integer(1) <= i, i <= k)), (0, True)) assert ds(KD(i, j), (j, k, 3)) == \ Piecewise((1, And(k <= i, i <= 3)), (0, True)) assert ds(KD(i, j), (j, k, l)) == \ Piecewise((1, And(k <= i, i <= l)), (0, True))
def test_constants(): assert mcode(pi) == "pi" assert mcode(oo) == "inf" assert mcode(-oo) == "-inf" assert mcode(nan) == "NaN" assert mcode(E) == "exp(1)" assert mcode(exp(1)) == "exp(1)" assert mcode(true) == "true" assert mcode(false) == "false"
def roots_binomial(f): """Returns a list of roots of a binomial polynomial. If the domain is ZZ then the roots will be sorted with negatives coming before positives. The ordering will be the same for any numerical coefficients as long as the assumptions tested are correct, otherwise the ordering will not be sorted (but will be canonical). """ n = f.degree() a, b = f.nth(n), f.nth(0) base = -cancel(b/a) alpha = root(base, n) if alpha.is_number: alpha = alpha.expand(complex=True) # define some parameters that will allow us to order the roots. # If the domain is ZZ this is guaranteed to return roots sorted # with reals before non-real roots and non-real sorted according # to real part and imaginary part, e.g. -1, 1, -1 + I, 2 - I neg = base.is_negative even = n % 2 == 0 if neg: if even and (base + 1).is_positive: big = True else: big = False # get the indices in the right order so the computed # roots will be sorted when the domain is ZZ ks = [] imax = n//2 if even: ks.append(imax) imax -= 1 if not neg: ks.append(0) for i in range(imax, 0, -1): if neg: ks.extend([i, -i]) else: ks.extend([-i, i]) if neg: ks.append(0) if big: for i in range(0, len(ks), 2): pair = ks[i: i + 2] pair = list(reversed(pair)) # compute the roots roots, d = [], 2*I*pi/n for k in ks: zeta = exp(k*d).expand(complex=True) roots.append((alpha*zeta).expand(power_base=False)) return roots
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)
def test_maximize(): # issue sympy/sympy#4173 assert maximize([x**(1 / x), x > 0], x) == (exp(1 / E), {x: E}) # https://groups.google.com/forum/#!topic/sympy/tB2Sly4Gh_4 assert maximize([ 12 * x + 40 * y, x + y <= 16, x + 3 * y <= 36, x <= 10, x >= 0, y >= 0 ], x, y) == (480, { x: 0, y: 12 })
def test_get_indices_Pow(): x = IndexedBase('x') y = IndexedBase('y') A = IndexedBase('A') i, j, k = Idx('i'), Idx('j'), Idx('k') assert get_indices(Pow(x[i], y[j])) == ({i, j}, {}) assert get_indices(Pow(x[i, k], y[j, k])) == ({i, j, k}, {}) assert get_indices(Pow(A[i, k], y[k] + A[k, j]*x[j])) == ({i, k}, {}) assert get_indices(Pow(2, x[i])) == get_indices(exp(x[i])) # test of a design decision, this may change: assert get_indices(Pow(x[i], 2)) == ({i, }, {})
def test_get_indices_Pow(): x = IndexedBase('x') y = IndexedBase('y') A = IndexedBase('A') i, j, k = Idx('i'), Idx('j'), Idx('k') assert get_indices(Pow(x[i], y[j])) == ({i, j}, {}) assert get_indices(Pow(x[i, k], y[j, k])) == ({i, j, k}, {}) assert get_indices(Pow(A[i, k], y[k] + A[k, j] * x[j])) == ({i, k}, {}) assert get_indices(Pow(2, x[i])) == get_indices(exp(x[i])) # test of a design decision, this may change: assert get_indices(Pow(x[i], 2)) == ({ i, }, {})
def test_Matrices(): assert mcode(Matrix(1, 1, [10])) == "10" A = Matrix([[1, sin(x / 2), abs(x)], [0, 1, pi], [0, exp(1), ceiling(x)]]) expected = ("[1 sin(x/2) abs(x);\n" "0 1 pi;\n" "0 exp(1) ceil(x)]") assert mcode(A) == expected # row and columns assert mcode(A[:, 0]) == "[1; 0; 0]" assert mcode(A[0, :]) == "[1 sin(x/2) abs(x)]" # empty matrices assert mcode(Matrix(0, 0, [])) == '[]' assert mcode(Matrix(0, 3, [])) == 'zeros(0, 3)' # annoying to read but correct assert mcode(Matrix([[x, x - y, -y]])) == "[x x - y -y]"
def test_Matrices(): assert mcode(Matrix(1, 1, [10])) == "10" A = Matrix([[1, sin(x/2), abs(x)], [0, 1, pi], [0, exp(1), ceiling(x)]]) expected = ("[1 sin(x/2) abs(x);\n" "0 1 pi;\n" "0 exp(1) ceil(x)]") assert mcode(A) == expected # row and columns assert mcode(A[:, 0]) == "[1; 0; 0]" assert mcode(A[0, :]) == "[1 sin(x/2) abs(x)]" # empty matrices assert mcode(Matrix(0, 0, [])) == '[]' assert mcode(Matrix(0, 3, [])) == 'zeros(0, 3)' # annoying to read but correct assert mcode(Matrix([[x, x - y, -y]])) == "[x x - y -y]"
def test_nocache(clear_imports, monkeypatch): """Regression tests with DIOFANT_USE_CACHE=False. """ monkeypatch.setenv('DIOFANT_USE_CACHE', 'False') from diofant.core.cache import CACHE from diofant.core.symbol import Symbol from diofant.functions import sin, sqrt, exp, sinh # test that we don't use cache assert CACHE == [] x = Symbol('x') assert CACHE == [] # issue sympy/sympy#8840 (1 + x)*x # not raises # issue sympy/sympy#9413 (2*x).is_complex # not raises # see commit c459d18 sin(x + x) # not raises # see commit 53dd1eb mx = -Symbol('x', negative=False) assert mx.is_positive is not True px = 2*Symbol('x', positive=False) assert px.is_positive is not True # see commit 2eaaba2 s = 1/sqrt(x**2) y = Symbol('y') result = s.subs(sqrt(x**2), y) assert result == 1/y # problem from https://groups.google.com/forum/#!topic/sympy/LkTMQKC_BOw # see commit c459d18 a = Symbol('a', positive=True) f = exp(x*(-a - 1)) g = sinh(x) f*g # not raises
def test_nocache(clear_imports, monkeypatch): """Regression tests with DIOFANT_USE_CACHE=False. """ monkeypatch.setenv('DIOFANT_USE_CACHE', 'False') from diofant.core.cache import CACHE from diofant.core.symbol import Symbol from diofant.functions import sin, sqrt, exp, sinh # test that we don't use cache assert CACHE == [] x = Symbol('x') assert CACHE == [] # issue sympy/sympy#8840 (1 + x)*x # not raises # issue sympy/sympy#9413 (2*x).is_complex # not raises # see commit c459d18 sin(x + x) # not raises # see commit 53dd1eb mx = -Symbol('x', negative=False) assert mx.is_positive is not True px = 2*Symbol('x', positive=False) assert px.is_positive is not True # see commit 2eaaba2 s = 1/sqrt(x**2) y = Symbol('y') result = s.subs({sqrt(x**2): y}) assert result == 1/y # problem from https://groups.google.com/forum/#!topic/sympy/LkTMQKC_BOw # see commit c459d18 a = Symbol('a', positive=True) f = exp(x*(-a - 1)) g = sinh(x) f*g # not raises
def test_diofant_parser(): x = Symbol('x') inputs = { '2*x': 2 * x, '3.00': Float(3), '22/7': Rational(22, 7), '2+3j': 2 + 3*I, 'exp(x)': exp(x), '-(2)': -Integer(2), '[-1, -2, 3]': [Integer(-1), Integer(-2), Integer(3)], 'Symbol("x").free_symbols': x.free_symbols, "Float(Integer(3).evalf(3))": 3.00, 'factorint(12, visual=True)': Mul( Pow(2, 2, evaluate=False), Pow(3, 1, evaluate=False), evaluate=False), 'Limit(sin(x), x, 0, dir="-")': Limit(sin(x), x, 0, dir='-'), } for text, result in inputs.items(): assert parse_expr(text) == result
def _eval_evalf(self, prec): # The default code is insufficient for polar arguments. # mpmath provides an optional argument "r", which evaluates # G(z**(1/r)). I am not sure what its intended use is, but we hijack it # here in the following way: to evaluate at a number z of |argument| # less than (say) n*pi, we put r=1/n, compute z' = root(z, n) # (carefully so as not to loose the branch information), and evaluate # G(z'**(1/r)) = G(z'**n) = G(z). from diofant.functions import exp_polar, ceiling from diofant import Expr import mpmath z = self.argument znum = self.argument._eval_evalf(prec) if znum.has(exp_polar): znum, branch = znum.as_coeff_mul(exp_polar) if len(branch) != 1: return branch = branch[0].args[0] / I else: branch = Integer(0) n = ceiling(abs(branch / S.Pi)) + 1 znum = znum**(Integer(1) / n) * exp(I * branch / n) # Convert all args to mpf or mpc try: [z, r, ap, bq] = [ arg._to_mpmath(prec) for arg in [znum, 1 / n, self.args[0], self.args[1]] ] except ValueError: return with mpmath.workprec(prec): v = mpmath.meijerg(ap, bq, z, r) return Expr._from_mpmath(v, prec)
def test_jscode_constants_mathh(): assert jscode(exp(1)) == "Math.E" assert jscode(pi) == "Math.PI" assert jscode(oo) == "Number.POSITIVE_INFINITY" assert jscode(-oo) == "Number.NEGATIVE_INFINITY"
def test_minimize_analytic(): assert minimize(exp(x**2 + y**2), x, y) == (1, {x: 0, y: 0})
def tofunc(nu, z): return exp(I * pi * nu) * fro(nu, exp_polar(-I * pi) * z)
def test_ccode_constants_mathh(): assert ccode(exp(1)) == "M_E" assert ccode(pi) == "M_PI" assert ccode(oo) == "HUGE_VAL" assert ccode(-oo) == "-HUGE_VAL"
def _denest_pow(eq): """ Denest powers. This is a helper function for powdenest that performs the actual transformation. """ from diofant.simplify.simplify import logcombine b, e = eq.as_base_exp() if b.is_Pow and e != 1: new = b._eval_power(e) if new is not None: eq = new b, e = new.as_base_exp() # denest exp with log terms in exponent if b is S.Exp1 and e.is_Mul: logs = [] other = [] for ei in e.args: if any(ai.func is log for ai in Add.make_args(ei)): logs.append(ei) else: other.append(ei) logs = logcombine(Mul(*logs)) return Pow(exp(logs), Mul(*other)) _, be = b.as_base_exp() if be is S.One and not (b.is_Mul or b.is_Rational and b.q != 1 or b.is_positive): return eq # denest eq which is either pos**e or Pow**e or Mul**e or # Mul(b1**e1, b2**e2) # handle polar numbers specially polars, nonpolars = [], [] for bb in Mul.make_args(b): if bb.is_polar: polars.append(bb.as_base_exp()) else: nonpolars.append(bb) if len(polars) == 1 and not polars[0][0].is_Mul: return Pow(polars[0][0], polars[0][1] * e) * powdenest( Mul(*nonpolars)**e) elif polars: return Mul(*[powdenest(bb**(ee*e)) for (bb, ee) in polars]) \ * powdenest(Mul(*nonpolars)**e) if b.is_Integer: # use log to see if there is a power here logb = expand_log(log(b)) if logb.is_Mul: c, logb = logb.args e *= c base = logb.args[0] return Pow(base, e) # if b is not a Mul or any factor is an atom then there is nothing to do if not b.is_Mul or any(s.is_Atom for s in Mul.make_args(b)): return eq # let log handle the case of the base of the argument being a Mul, e.g. # sqrt(x**(2*i)*y**(6*i)) -> x**i*y**(3**i) if x and y are positive; we # will take the log, expand it, and then factor out the common powers that # now appear as coefficient. We do this manually since terms_gcd pulls out # fractions, terms_gcd(x+x*y/2) -> x*(y + 2)/2 and we don't want the 1/2; # gcd won't pull out numerators from a fraction: gcd(3*x, 9*x/2) -> x but # we want 3*x. Neither work with noncommutatives. def nc_gcd(aa, bb): a, b = [i.as_coeff_Mul() for i in [aa, bb]] c = gcd(a[0], b[0]).as_numer_denom()[0] g = Mul(*(a[1].args_cnc(cset=True)[0] & b[1].args_cnc(cset=True)[0])) return _keep_coeff(c, g) glogb = expand_log(log(b)) if glogb.is_Add: args = glogb.args g = reduce(nc_gcd, args) if g != 1: cg, rg = g.as_coeff_Mul() glogb = _keep_coeff(cg, rg * Add(*[a / g for a in args])) # now put the log back together again if glogb.func is log or not glogb.is_Mul: if glogb.args[0].is_Pow: glogb = _denest_pow(glogb.args[0]) if (abs(glogb.exp) < 1) is S.true: return Pow(glogb.base, glogb.exp * e) return eq # the log(b) was a Mul so join any adds with logcombine add = [] other = [] for a in glogb.args: if a.is_Add: add.append(a) else: other.append(a) return Pow(exp(logcombine(Mul(*add))), e * Mul(*other))
def _expr_big_minus(cls, a, x, n): sgn = 1 if n.is_odd: sgn = -1 return sgn * 2**(2 * a - 1) * (sqrt(1 + x) + sgn)**(1 - 2 * a) * exp( -2 * pi * I * a * n)
def _expr_big_minus(cls, a, x, n): if a.is_integer: return cls._expr_small_minus(a, x) return (1 + x)**a * exp(2 * n * pi * I * a)