def _eval_expand_func(self, **hints): from sympy 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) / S(q)) * log(sin((pi * k) / S(q))), (k, 1, floor((q - 1) / S(2)))) t3 = (pi / 2) * cot((pi * p) / q) + log(2 * q) return t1 + t2 - t3 return self
def eval(cls, arg): if arg.is_Rational: return log(arg + S.One) elif not arg.is_Float: # not safe to add 1 to Float return log.eval(arg + S.One) elif arg.is_number: return log(Rational(arg) + S.One)
def test_power_rewrite_exp(): assert (I**I).rewrite(exp) == exp(-pi/2) expr = (2 + 3*I)**(4 + 5*I) assert expr.rewrite(exp) == exp((4 + 5*I)*(log(sqrt(13)) + I*atan(S(3)/2))) assert expr.rewrite(exp).expand() == \ 169*exp(5*I*log(13)/2)*exp(4*I*atan(S(3)/2))*exp(-5*atan(S(3)/2)) assert ((6 + 7*I)**5).rewrite(exp) == 7225*sqrt(85)*exp(5*I*atan(S(7)/6)) expr = 5**(6 + 7*I) assert expr.rewrite(exp) == exp((6 + 7*I)*log(5)) assert expr.rewrite(exp).expand() == 15625*exp(7*I*log(5)) assert Pow(123, 789, evaluate=False).rewrite(exp) == 123**789 assert (1**I).rewrite(exp) == 1**I assert (0**I).rewrite(exp) == 0**I expr = (-2)**(2 + 5*I) assert expr.rewrite(exp) == exp((2 + 5*I)*(log(2) + I*pi)) assert expr.rewrite(exp).expand() == 4*exp(-5*pi)*exp(5*I*log(2)) assert ((-2)**S(-5)).rewrite(exp) == (-2)**S(-5) x, y = symbols('x y') assert (x**y).rewrite(exp) == exp(y*log(x)) assert (7**x).rewrite(exp) == exp(x*log(7), evaluate=False) assert ((2 + 3*I)**x).rewrite(exp) == exp(x*(log(sqrt(13)) + I*atan(S(3)/2))) assert (y**(5 + 6*I)).rewrite(exp) == exp(log(y)*(5 + 6*I)) assert all((1/func(x)).rewrite(exp) == 1/(func(x).rewrite(exp)) for func in (sin, cos, tan, sec, csc, sinh, cosh, tanh))
def eval(cls, arg): from sympy import asin arg = sympify(arg) if arg.is_Number: if arg is S.NaN: return S.NaN elif arg is S.Infinity: return S.Infinity elif arg is S.NegativeInfinity: return S.NegativeInfinity elif arg is S.Zero: return S.Zero elif arg is S.One: return log(sqrt(2) + 1) elif arg is S.NegativeOne: return log(sqrt(2) - 1) elif arg.is_negative: return -cls(-arg) else: if arg is S.ComplexInfinity: return S.ComplexInfinity i_coeff = arg.as_coefficient(S.ImaginaryUnit) if i_coeff is not None: return S.ImaginaryUnit * asin(i_coeff) else: if _coeff_isneg(arg): return -cls(-arg)
def get_math_macros(): """ Returns a dictionary with math-related macros from math.h/cmath Note that these macros are not strictly required by the C/C++-standard. For MSVC they are enabled by defining "_USE_MATH_DEFINES" (preferably via a compilation flag). Returns ======= Dictionary mapping sympy expressions to strings (macro names) """ from sympy.codegen.cfunctions import log2, Sqrt from sympy.functions.elementary.exponential import log from sympy.functions.elementary.miscellaneous import sqrt return { S.Exp1: 'M_E', log2(S.Exp1): 'M_LOG2E', 1/log(2): 'M_LOG2E', log(2): 'M_LN2', log(10): 'M_LN10', S.Pi: 'M_PI', S.Pi/2: 'M_PI_2', S.Pi/4: 'M_PI_4', 1/S.Pi: 'M_1_PI', 2/S.Pi: 'M_2_PI', 2/sqrt(S.Pi): 'M_2_SQRTPI', 2/Sqrt(S.Pi): 'M_2_SQRTPI', sqrt(2): 'M_SQRT2', Sqrt(2): 'M_SQRT2', 1/sqrt(2): 'M_SQRT1_2', 1/Sqrt(2): 'M_SQRT1_2' }
def eval(cls, arg): from sympy import acos arg = sympify(arg) if arg.is_Number: if arg is S.NaN: return S.NaN elif arg is S.Infinity: return S.Infinity elif arg is S.NegativeInfinity: return S.Infinity elif arg is S.Zero: return S.Pi*S.ImaginaryUnit / 2 elif arg is S.One: return S.Zero elif arg is S.NegativeOne: return S.Pi*S.ImaginaryUnit if arg.is_number: cst_table = { S.ImaginaryUnit: log(S.ImaginaryUnit*(1 + sqrt(2))), -S.ImaginaryUnit: log(-S.ImaginaryUnit*(1 + sqrt(2))), S.Half: S.Pi/3, -S.Half: 2*S.Pi/3, sqrt(2)/2: S.Pi/4, -sqrt(2)/2: 3*S.Pi/4, 1/sqrt(2): S.Pi/4, -1/sqrt(2): 3*S.Pi/4, sqrt(3)/2: S.Pi/6, -sqrt(3)/2: 5*S.Pi/6, (sqrt(3) - 1)/sqrt(2**3): 5*S.Pi/12, -(sqrt(3) - 1)/sqrt(2**3): 7*S.Pi/12, sqrt(2 + sqrt(2))/2: S.Pi/8, -sqrt(2 + sqrt(2))/2: 7*S.Pi/8, sqrt(2 - sqrt(2))/2: 3*S.Pi/8, -sqrt(2 - sqrt(2))/2: 5*S.Pi/8, (1 + sqrt(3))/(2*sqrt(2)): S.Pi/12, -(1 + sqrt(3))/(2*sqrt(2)): 11*S.Pi/12, (sqrt(5) + 1)/4: S.Pi/5, -(sqrt(5) + 1)/4: 4*S.Pi/5 } if arg in cst_table: if arg.is_real: return cst_table[arg]*S.ImaginaryUnit return cst_table[arg] if arg is S.ComplexInfinity: return S.Infinity i_coeff = arg.as_coefficient(S.ImaginaryUnit) if i_coeff is not None: if _coeff_isneg(i_coeff): return S.ImaginaryUnit * acos(i_coeff) return S.ImaginaryUnit * acos(-i_coeff) else: if _coeff_isneg(arg): return -cls(-arg)
def eval(cls, n, z): n, z = list(map(sympify, (n, z))) from sympy import unpolarify if n.is_integer: if n.is_nonnegative: nz = unpolarify(z) if z != nz: return polygamma(n, nz) if n == -1: return loggamma(z) else: if z.is_Number: if z is S.NaN: return S.NaN elif z is S.Infinity: if n.is_Number: if n is S.Zero: return S.Infinity else: return S.Zero elif z.is_Integer: if z.is_nonpositive: return S.ComplexInfinity else: if n is S.Zero: return -S.EulerGamma + C.harmonic(z - 1, 1) elif n.is_odd: return (-1) ** (n + 1) * C.factorial(n) * zeta(n + 1, z) if n == 0: if z is S.NaN: return S.NaN elif z.is_Rational: # TODO actually *any* n/m can be done, but that is messy lookup = { S(1) / 2: -2 * log(2) - S.EulerGamma, S(1) / 3: -S.Pi / 2 / sqrt(3) - 3 * log(3) / 2 - S.EulerGamma, S(1) / 4: -S.Pi / 2 - 3 * log(2) - S.EulerGamma, S(3) / 4: -3 * log(2) - S.EulerGamma + S.Pi / 2, S(2) / 3: -3 * log(3) / 2 + S.Pi / 2 / sqrt(3) - S.EulerGamma, } if z > 0: n = floor(z) z0 = z - n if z0 in lookup: return lookup[z0] + Add(*[1 / (z0 + k) for k in range(n)]) elif z < 0: n = floor(1 - z) z0 = z + n if z0 in lookup: return lookup[z0] - Add(*[1 / (z0 - 1 - k) for k in range(n)]) elif z in (S.Infinity, S.NegativeInfinity): return S.Infinity else: t = z.extract_multiplicatively(S.ImaginaryUnit) if t in (S.Infinity, S.NegativeInfinity): return S.Infinity
def test_trigintegrate_mixed(): assert trigintegrate(sin(x)*sec(x), x) == -log(sin(x)**2 - 1)/2 assert trigintegrate(sin(x)*csc(x), x) == x assert trigintegrate(sin(x)*cot(x), x) == sin(x) assert trigintegrate(cos(x)*sec(x), x) == x assert trigintegrate(cos(x)*csc(x), x) == log(cos(x)**2 - 1)/2 assert trigintegrate(cos(x)*tan(x), x) == -cos(x) assert trigintegrate(cos(x)*cot(x), x) == log(cos(x) - 1)/2 \ - log(cos(x) + 1)/2 + cos(x)
def eval(cls, arg): arg = sympify(arg) if arg.is_Number: if arg is S.NaN: return S.NaN elif arg is S.Infinity: return S.Pi*S.ImaginaryUnit / 2 elif arg is S.NegativeInfinity: return S.Pi*S.ImaginaryUnit / 2 elif arg is S.Zero: return S.Infinity elif arg is S.One: return S.Zero elif arg is S.NegativeOne: return S.Pi*S.ImaginaryUnit if arg.is_number: cst_table = { S.ImaginaryUnit: - (S.Pi*S.ImaginaryUnit / 2) + log(1 + sqrt(2)), -S.ImaginaryUnit: (S.Pi*S.ImaginaryUnit / 2) + log(1 + sqrt(2)), (sqrt(6) - sqrt(2)): S.Pi / 12, (sqrt(2) - sqrt(6)): 11*S.Pi / 12, sqrt(2 - 2/sqrt(5)): S.Pi / 10, -sqrt(2 - 2/sqrt(5)): 9*S.Pi / 10, 2 / sqrt(2 + sqrt(2)): S.Pi / 8, -2 / sqrt(2 + sqrt(2)): 7*S.Pi / 8, 2 / sqrt(3): S.Pi / 6, -2 / sqrt(3): 5*S.Pi / 6, (sqrt(5) - 1): S.Pi / 5, (1 - sqrt(5)): 4*S.Pi / 5, sqrt(2): S.Pi / 4, -sqrt(2): 3*S.Pi / 4, sqrt(2 + 2/sqrt(5)): 3*S.Pi / 10, -sqrt(2 + 2/sqrt(5)): 7*S.Pi / 10, S(2): S.Pi / 3, -S(2): 2*S.Pi / 3, sqrt(2*(2 + sqrt(2))): 3*S.Pi / 8, -sqrt(2*(2 + sqrt(2))): 5*S.Pi / 8, (1 + sqrt(5)): 2*S.Pi / 5, (-1 - sqrt(5)): 3*S.Pi / 5, (sqrt(6) + sqrt(2)): 5*S.Pi / 12, (-sqrt(6) - sqrt(2)): 7*S.Pi / 12, } if arg in cst_table: if arg.is_real: return cst_table[arg]*S.ImaginaryUnit return cst_table[arg] if arg is S.ComplexInfinity: from sympy.calculus.util import AccumBounds return S.ImaginaryUnit*AccumBounds(-S.Pi/2, S.Pi/2)
def composite(nth): """ Return the nth composite number, with the composite numbers indexed as composite(1) = 4, composite(2) = 6, etc.... Examples ======== >>> from sympy import composite >>> composite(36) 52 >>> composite(1) 4 >>> composite(17737) 20000 See Also ======== sympy.ntheory.primetest.isprime : Test if n is prime primerange : Generate all primes in a given range primepi : Return the number of primes less than or equal to n prime : Return the nth prime compositepi : Return the number of positive composite numbers less than or equal to n """ n = as_int(nth) if n < 1: raise ValueError("nth must be a positive integer; composite(1) == 4") composite_arr = [4, 6, 8, 9, 10, 12, 14, 15, 16, 18] if n <= 10: return composite_arr[n - 1] from sympy.functions.special.error_functions import li from sympy.functions.elementary.exponential import log a = 4 # Lower bound for binary search b = int(n*(log(n) + log(log(n)))) # Upper bound for the search. while a < b: mid = (a + b) >> 1 if mid - li(mid) - 1 > n: b = mid else: a = mid + 1 n_composites = a - primepi(a) - 1 while n_composites > n: if not isprime(a): n_composites -= 1 a -= 1 if isprime(a): a -= 1 return a
def eval(cls, arg): arg = sympify(arg) if arg.is_Number: if arg is S.NaN: return S.NaN elif arg is S.Infinity: return S.Infinity elif arg is S.NegativeInfinity: return S.Infinity elif arg is S.Zero: return S.Pi*S.ImaginaryUnit / 2 elif arg is S.One: return S.Zero elif arg is S.NegativeOne: return S.Pi*S.ImaginaryUnit if arg.is_number: cst_table = { S.ImaginaryUnit: log(S.ImaginaryUnit*(1 + sqrt(2))), -S.ImaginaryUnit: log(-S.ImaginaryUnit*(1 + sqrt(2))), S.Half: S.Pi/3, -S.Half: 2*S.Pi/3, sqrt(2)/2: S.Pi/4, -sqrt(2)/2: 3*S.Pi/4, 1/sqrt(2): S.Pi/4, -1/sqrt(2): 3*S.Pi/4, sqrt(3)/2: S.Pi/6, -sqrt(3)/2: 5*S.Pi/6, (sqrt(3) - 1)/sqrt(2**3): 5*S.Pi/12, -(sqrt(3) - 1)/sqrt(2**3): 7*S.Pi/12, sqrt(2 + sqrt(2))/2: S.Pi/8, -sqrt(2 + sqrt(2))/2: 7*S.Pi/8, sqrt(2 - sqrt(2))/2: 3*S.Pi/8, -sqrt(2 - sqrt(2))/2: 5*S.Pi/8, (1 + sqrt(3))/(2*sqrt(2)): S.Pi/12, -(1 + sqrt(3))/(2*sqrt(2)): 11*S.Pi/12, (sqrt(5) + 1)/4: S.Pi/5, -(sqrt(5) + 1)/4: 4*S.Pi/5 } if arg in cst_table: if arg.is_real: return cst_table[arg]*S.ImaginaryUnit return cst_table[arg] if arg is S.ComplexInfinity: return S.ComplexInfinity if arg == S.ImaginaryUnit*S.Infinity: return S.Infinity + S.ImaginaryUnit*S.Pi/2 if arg == -S.ImaginaryUnit*S.Infinity: return S.Infinity - S.ImaginaryUnit*S.Pi/2
def _eval_aseries(self, n, args0, x, logx): if args0[0] != oo: return super(loggamma, self)._eval_aseries(n, args0, x, logx) z = self.args[0] m = min(n, C.ceiling((n + S(1)) / 2)) r = log(z) * (z - S(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 = C.Order(1, x) else: o = C.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
def test_issue_7638(): f = pi/log(sqrt(2)) assert ((1 + I)**(I*f/2))**0.3 == (1 + I)**(0.15*I*f) # if 1/3 -> 1.0/3 this should fail since it cannot be shown that the # sign will be +/-1; for the previous "small arg" case, it didn't matter # that this could not be proved assert (1 + I)**(4*I*f) == ((1 + I)**(12*I*f))**(S(1)/3) assert (((1 + I)**(I*(1 + 7*f)))**(S(1)/3)).exp == S(1)/3 r = symbols('r', real=True) assert sqrt(r**2) == abs(r) assert cbrt(r**3) != r assert sqrt(Pow(2*I, 5*S.Half)) != (2*I)**(5/S(4)) p = symbols('p', positive=True) assert cbrt(p**2) == p**(2/S(3)) assert NS(((0.2 + 0.7*I)**(0.7 + 1.0*I))**(0.5 - 0.1*I), 1) == '0.4 + 0.2*I' assert sqrt(1/(1 + I)) == sqrt(1 - I)/sqrt(2) # or 1/sqrt(1 + I) e = 1/(1 - sqrt(2)) assert sqrt(e) == I/sqrt(-1 + sqrt(2)) assert e**-S.Half == -I*sqrt(-1 + sqrt(2)) assert sqrt((cos(1)**2 + sin(1)**2 - 1)**(3 + I)).exp == S.Half assert sqrt(r**(4/S(3))) != r**(2/S(3)) assert sqrt((p + I)**(4/S(3))) == (p + I)**(2/S(3)) assert sqrt((p - p**2*I)**2) == p - p**2*I assert sqrt((p + r*I)**2) != p + r*I e = (1 + I/5) assert sqrt(e**5) == e**(5*S.Half) assert sqrt(e**6) == e**3 assert sqrt((1 + I*r)**6) != (1 + I*r)**3
def _eval_expand_func(self, deep=True, **hints): if deep: hints['func'] = False n = self.args[0].expand(deep, **hints) z = self.args[1].expand(deep, **hints) else: n, z = self.args[0], self.args[1].expand(deep, func=True) if n.is_Integer and n.is_nonnegative: if z.is_Add: coeff, factors = z.as_coeff_factors() if coeff.is_Integer: tail = Add(*[ z + i for i in xrange(0, int(coeff)) ]) return polygamma(n, z-coeff) + (-1)**n*C.Factorial(n)*tail elif z.is_Mul: coeff, terms = z.as_coeff_terms() if coeff.is_Integer and coeff.is_positive: tail = [ polygamma(n, z + i//coeff) for i in xrange(0, int(coeff)) ] if n is S.Zero: return log(coeff) + Add(*tail)/coeff**(n+1) else: return Add(*tail)/coeff**(n+1) return polygamma(n, z)
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(*[C.Pow(z - i, e) for i in xrange(1, int(coeff) + 1)]) else: tail = -Add(*[C.Pow(z + i, e) for i in xrange(0, int(-coeff))]) return polygamma(n, z - coeff) + (-1) ** n * C.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 + C.Rational(i, coeff)) for i in xrange(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)
def _eval_as_leading_term(self, x): n, z = [a.as_leading_term(x) for a in self.args] o = C.Order(z, x) if n == 0 and o.contains(1 / x): return o.getn() * log(x) else: return self.func(n, z)
def fdiff(self, argindex=1): """ Returns the first derivative of this function. """ if argindex == 1: return self*log(_Two) else: raise ArgumentIndexError(self, argindex)
def fdiff(self, argindex=1): """ Returns the first derivative of this function. """ if argindex == 1: return S.One/(log(_Ten)*self.args[0]) else: raise ArgumentIndexError(self, argindex)
def is_convergent(self): r""" See docs of Sum.is_convergent() for explanation of convergence in SymPy. The infinite product: .. math:: \prod_{1 \leq i < \infty} f(i) is defined by the sequence of partial products: .. math:: \prod_{i=1}^{n} f(i) = f(1) f(2) \cdots f(n) as n increases without bound. The product converges to a non-zero value if and only if the sum: .. math:: \sum_{1 \leq i < \infty} \log{f(n)} converges. References ========== .. [1] https://en.wikipedia.org/wiki/Infinite_product Examples ======== >>> from sympy import Interval, S, Product, Symbol, cos, pi, exp, oo >>> n = Symbol('n', integer=True) >>> Product(n/(n + 1), (n, 1, oo)).is_convergent() False >>> Product(1/n**2, (n, 1, oo)).is_convergent() False >>> Product(cos(pi/n), (n, 1, oo)).is_convergent() True >>> Product(exp(-n**2), (n, 1, oo)).is_convergent() False """ from sympy.concrete.summations import Sum sequence_term = self.function log_sum = log(sequence_term) lim = self.limits try: is_conv = Sum(log_sum, *lim).is_convergent() except NotImplementedError: if Sum(sequence_term - 1, *lim).is_absolutely_convergent() is S.true: return S.true raise NotImplementedError("The algorithm to find the product convergence of %s " "is not yet implemented" % (sequence_term)) return is_conv
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 if n == 0 and z.is_Rational: p, q = z.as_numer_denom() # Reference: # Values of the polygamma functions at rational arguments, J. Choi, 2007 part_1 = -S.EulerGamma - pi * cot(p * pi / q) / 2 - log(q) + Add( *[cos(2 * k * pi * p / q) * log(2 * sin(k * pi / q)) for k in range(1, q)]) if z > 0: n = floor(z) z0 = z - n return part_1 + Add(*[1 / (z0 + k) for k in range(n)]) elif z < 0: n = floor(1 - z) z0 = z + n return part_1 - Add(*[1 / (z0 - 1 - k) for k in range(n)]) return polygamma(n, z)
def _eval_expand_func(self, **hints): z = self.args[0] if z.is_Rational: p, q = z.as_numer_denom() # General rational arguments (u + p/q) # Split z as n + p/q with p < q n = p // q p = p - n * q if p.is_positive and q.is_positive and p < q: k = Dummy("k") if n.is_positive: return loggamma(p / q) - n * log(q) + C.Sum(log((k - 1) * q + p), (k, 1, n)) elif n.is_negative: return loggamma(p / q) - n * log(q) + S.Pi * S.ImaginaryUnit * n - C.Sum(log(k * q - p), (k, 1, -n)) elif n.is_zero: return loggamma(p / q) return self
def fdiff(self, argindex=2): from sympy import meijerg if argindex == 2: a, z = self.args return -C.exp(-z)*z**(a-1) elif argindex == 1: a, z = self.args return uppergamma(a, z)*log(z) + meijerg([], [1, 1], [0, 0, a], [], z) else: raise ArgumentIndexError(self, argindex)
def eval(cls, arg): arg = sympify(arg) if arg.is_Number: if arg is S.NaN: return S.NaN elif arg is S.Infinity: return S.Zero elif arg is S.NegativeInfinity: return S.Zero elif arg is S.Zero: return S.ComplexInfinity elif arg is S.One: return log(1 + sqrt(2)) elif arg is S.NegativeOne: return - log(1 + sqrt(2)) if arg.is_number: cst_table = { S.ImaginaryUnit: -S.Pi / 2, S.ImaginaryUnit*(sqrt(2) + sqrt(6)): -S.Pi / 12, S.ImaginaryUnit*(1 + sqrt(5)): -S.Pi / 10, S.ImaginaryUnit*2 / sqrt(2 - sqrt(2)): -S.Pi / 8, S.ImaginaryUnit*2: -S.Pi / 6, S.ImaginaryUnit*sqrt(2 + 2/sqrt(5)): -S.Pi / 5, S.ImaginaryUnit*sqrt(2): -S.Pi / 4, S.ImaginaryUnit*(sqrt(5)-1): -3*S.Pi / 10, S.ImaginaryUnit*2 / sqrt(3): -S.Pi / 3, S.ImaginaryUnit*2 / sqrt(2 + sqrt(2)): -3*S.Pi / 8, S.ImaginaryUnit*sqrt(2 - 2/sqrt(5)): -2*S.Pi / 5, S.ImaginaryUnit*(sqrt(6) - sqrt(2)): -5*S.Pi / 12, S(2): -S.ImaginaryUnit*log((1+sqrt(5))/2), } if arg in cst_table: return cst_table[arg]*S.ImaginaryUnit if arg is S.ComplexInfinity: return S.Zero if _coeff_isneg(arg): return -cls(-arg)
def eval(cls, z): z = sympify(z) if z.is_integer: if z.is_nonpositive: return S.Infinity elif z.is_positive: return log(gamma(z)) elif z.is_rational: p, q = z.as_numer_denom() # Half-integral values: if p.is_positive and q == 2: return log(sqrt(S.Pi) * 2 ** (1 - p) * gamma(p) / gamma((p + 1) * S.Half)) if z is S.Infinity: return S.Infinity elif abs(z) is S.Infinity: return S.ComplexInfinity if z is S.NaN: return S.NaN
def test_issue_11463(): numpy = import_module('numpy') if not numpy: skip("numpy not installed.") x = Symbol('x') f = lambdify(x, real_root((log(x/(x-2))), 3), 'numpy') # numpy.select evaluates all options before considering conditions, # so it raises a warning about root of negative number which does # not affect the outcome. This warning is suppressed here with ignore_warnings(RuntimeWarning): assert f(numpy.array(-1)) < -1
def fdiff(self, argindex=2): from sympy import meijerg, unpolarify if argindex == 2: a, z = self.args return C.exp(-unpolarify(z)) * z ** (a - 1) elif argindex == 1: a, z = self.args return gamma(a) * digamma(a) - log(z) * uppergamma(a, z) - meijerg([], [1, 1], [0, 0, a], [], z) else: raise ArgumentIndexError(self, argindex)
def _eval(self, n, k): # n.is_Number and k.is_Integer and k != 1 and n != k from sympy.functions.elementary.exponential import log from sympy.core import N if k.is_Integer: if n.is_Integer and n >= 0: n, k = int(n), int(k) if k > n: return S.Zero elif k > n // 2: k = n - k if HAS_GMPY: from sympy.core.compatibility import gmpy return Integer(gmpy.bincoef(n, k)) prime_count_estimate = N(n / log(n)) # if the number of primes less than n is less than k, use prime sieve method # otherwise it is more memory efficient to compute factorials explicitly if prime_count_estimate < k: M, result = int(_sqrt(n)), 1 for prime in sieve.primerange(2, n + 1): if prime > n - k: result *= prime elif prime > n // 2: continue elif prime > M: if n % prime < k % prime: result *= prime else: N, K = n, k exp = a = 0 while N > 0: a = int((N % prime) < (K % prime + a)) N, K = N // prime, K // prime exp = a + exp if exp > 0: result *= prime**exp else: result = ff(n, k) / factorial(k) return Integer(result) else: d = result = n - k + 1 for i in range(2, k + 1): d += 1 result *= d result /= i return result
def Pow(expr, assumptions): """ Real**Integer -> Real Positive**Real -> Real Real**(Integer/Even) -> Real if base is nonnegative Real**(Integer/Odd) -> Real Imaginary**(Integer/Even) -> Real Imaginary**(Integer/Odd) -> not Real Imaginary**Real -> ? since Real could be 0 (giving real) or 1 (giving imaginary) b**Imaginary -> Real if log(b) is imaginary and b != 0 and exponent != integer multiple of I*pi/log(b) Real**Real -> ? e.g. sqrt(-1) is imaginary and sqrt(2) is not """ if expr.is_number: return AskRealHandler._number(expr, assumptions) if expr.base.func == exp: if ask(Q.imaginary(expr.base.args[0]), assumptions): if ask(Q.imaginary(expr.exp), assumptions): return True # If the i = (exp's arg)/(I*pi) is an integer or half-integer # multiple of I*pi then 2*i will be an integer. In addition, # exp(i*I*pi) = (-1)**i so the overall realness of the expr # can be determined by replacing exp(i*I*pi) with (-1)**i. i = expr.base.args[0]/I/pi if ask(Q.integer(2*i), assumptions): return ask(Q.real(((-1)**i)**expr.exp), assumptions) return if ask(Q.imaginary(expr.base), assumptions): if ask(Q.integer(expr.exp), assumptions): odd = ask(Q.odd(expr.exp), assumptions) if odd is not None: return not odd return if ask(Q.imaginary(expr.exp), assumptions): imlog = ask(Q.imaginary(log(expr.base)), assumptions) if imlog is not None: # I**i -> real, log(I) is imag; # (2*I)**i -> complex, log(2*I) is not imag return imlog if ask(Q.real(expr.base), assumptions): if ask(Q.real(expr.exp), assumptions): if expr.exp.is_Rational and \ ask(Q.even(expr.exp.q), assumptions): return ask(Q.positive(expr.base), assumptions) elif ask(Q.integer(expr.exp), assumptions): return True elif ask(Q.positive(expr.base), assumptions): return True elif ask(Q.negative(expr.base), assumptions): return False
def _eval_expand_func(self, **hints): from sympy import log, expand_mul, Dummy, exp_polar, I s, z = self.args if s == 1: return -log(1 + exp_polar(-I*pi)*z) if s.is_Integer and s <= 0: u = Dummy('u') start = u/(1 - u) for _ in range(-s): start = u*start.diff(u) return expand_mul(start).subs(u, z) return polylog(s, z)
def eval(cls, s, z): s, z = sympify((s, z)) if z == 1: return zeta(s) elif z == -1: return -dirichlet_eta(s) elif z == 0: return S.Zero elif s == 2: if z == S.Half: return pi**2/12 - log(2)**2/2 elif z == 2: return pi**2/4 - I*pi*log(2) elif z == -(sqrt(5) - 1)/2: return -pi**2/15 + log((sqrt(5)-1)/2)**2/2 elif z == -(sqrt(5) + 1)/2: return -pi**2/10 - log((sqrt(5)+1)/2)**2 elif z == (3 - sqrt(5))/2: return pi**2/15 - log((sqrt(5)-1)/2)**2 elif z == (sqrt(5) - 1)/2: return pi**2/10 - log((sqrt(5)-1)/2)**2 # For s = 0 or -1 use explicit formulas to evaluate, but # automatically expanding polylog(1, z) to -log(1-z) seems undesirable # for summation methods based on hypergeometric functions elif s == 0: return z/(1 - z) elif s == -1: return z/(1 - z)**2 # polylog is branched, but not over the unit disk from sympy.functions.elementary.complexes import (Abs, unpolarify, polar_lift) if z.has(exp_polar, polar_lift) and (Abs(z) <= S.One) == True: return cls(s, unpolarify(z))
def test_issue_9536(): from sympy.functions.elementary.exponential import log a = Symbol('a', real=True) assert FiniteSet(log(a)).intersect(S.Reals) == Intersection( S.Reals, FiniteSet(log(a)))
def _eval_rewrite_as_intractable(self, z): return log(gamma(z))
def composite(nth): """ Return the nth composite number, with the composite numbers indexed as composite(1) = 4, composite(2) = 6, etc.... Examples ======== >>> from sympy import composite >>> composite(36) 52 >>> composite(1) 4 >>> composite(17737) 20000 See Also ======== sympy.ntheory.primetest.isprime : Test if n is prime primerange : Generate all primes in a given range primepi : Return the number of primes less than or equal to n prime : Return the nth prime compositepi : Return the number of positive composite numbers less than or equal to n """ n = as_int(nth) if n < 1: raise ValueError("nth must be a positive integer; composite(1) == 4") composite_arr = [4, 6, 8, 9, 10, 12, 14, 15, 16, 18] if n <= 10: return composite_arr[n - 1] a, b = 4, sieve._list[-1] if n <= b - primepi(b) - 1: while a < b - 1: mid = (a + b) >> 1 if mid - primepi(mid) - 1 > n: b = mid else: a = mid if isprime(a): a -= 1 return a from sympy.functions.special.error_functions import li from sympy.functions.elementary.exponential import log a = 4 # Lower bound for binary search b = int(n * (log(n) + log(log(n)))) # Upper bound for the search. while a < b: mid = (a + b) >> 1 if mid - li(mid) - 1 > n: b = mid else: a = mid + 1 n_composites = a - primepi(a) - 1 while n_composites > n: if not isprime(a): n_composites -= 1 a -= 1 if isprime(a): a -= 1 return a
def _solve_lambert(f, symbol, gens): """Return solution to ``f`` if it is a Lambert-type expression else raise NotImplementedError. The equality, ``f(x, a..f) = a*log(b*X + c) + d*X - f = 0`` has the solution, `X = -c/b + (a/d)*W(d/(a*b)*exp(c*d/a/b)*exp(f/a))`. There are a variety of forms for `f(X, a..f)` as enumerated below: 1a1) if B**B = R for R not [0, 1] then log(B) + log(log(B)) = log(log(R)) X = log(B), a = 1, b = 1, c = 0, d = 1, f = log(log(R)) 1a2) if B*(b*log(B) + c)**a = R then log(B) + a*log(b*log(B) + c) = log(R) X = log(B); d=1, f=log(R) 1b) if a*log(b*B + c) + d*B = R then X = B, f = R 2a) if (b*B + c)*exp(d*B + g) = R then log(b*B + c) + d*B + g = log(R) a = 1, f = log(R) - g, X = B 2b) if -b*B + g*exp(d*B + h) = c then log(g) + d*B + h - log(b*B + c) = 0 a = -1, f = -h - log(g), X = B 3) if d*p**(a*B + g) - b*B = c then log(d) + (a*B + g)*log(p) - log(c + b*B) = 0 a = -1, d = a*log(p), f = -log(d) - g*log(p) """ nrhs, lhs = f.as_independent(symbol, as_Add=True) rhs = -nrhs lamcheck = [ tmp for tmp in gens if (tmp.func in [exp, log] or ( tmp.is_Pow and symbol in tmp.exp.free_symbols)) ] if not lamcheck: raise NotImplementedError() if lhs.is_Mul: lhs = expand_log(log(lhs)) rhs = log(rhs) lhs = factor(lhs, deep=True) # make sure we are inverted as completely as possible r = Dummy() i, lhs = _invert(lhs - r, symbol) rhs = i.xreplace({r: rhs}) # For the first ones: # 1a1) B**B = R != 0 (when 0, there is only a solution if the base is 0, # but if it is, the exp is 0 and 0**0=1 # comes back as B*log(B) = log(R) # 1a2) B*(a + b*log(B))**p = R or with monomial expanded or with whole # thing expanded comes back unchanged # log(B) + p*log(a + b*log(B)) = log(R) # lhs is Mul: # expand log of both sides to give: # log(B) + log(log(B)) = log(log(R)) # 1b) d*log(a*B + b) + c*B = R # lhs is Add: # isolate c*B and expand log of both sides: # log(c) + log(B) = log(R - d*log(a*B + b)) soln = [] if not soln: mainlog = _mostfunc(lhs, log, symbol) if mainlog: if lhs.is_Mul and rhs != 0: soln = _lambert(log(lhs) - log(rhs), symbol) elif lhs.is_Add: other = lhs.subs(mainlog, 0) if other and not other.is_Add and [ tmp for tmp in other.atoms(Pow) if symbol in tmp.free_symbols ]: if not rhs: diff = log(other) - log(other - lhs) else: diff = log(lhs - other) - log(rhs - other) soln = _lambert(expand_log(diff), symbol) else: #it's ready to go soln = _lambert(lhs - rhs, symbol) # For the next two, # collect on main exp # 2a) (b*B + c)*exp(d*B + g) = R # lhs is mul: # log to give # log(b*B + c) + d*B = log(R) - g # 2b) -b*B + g*exp(d*B + h) = R # lhs is add: # add b*B # log and rearrange # log(R + b*B) - d*B = log(g) + h if not soln: mainexp = _mostfunc(lhs, exp, symbol) if mainexp: lhs = collect(lhs, mainexp) if lhs.is_Mul and rhs != 0: soln = _lambert(expand_log(log(lhs) - log(rhs)), symbol) elif lhs.is_Add: # move all but mainexp-containing term to rhs other = lhs.subs(mainexp, 0) mainterm = lhs - other rhs = rhs - other if (mainterm.could_extract_minus_sign() and rhs.could_extract_minus_sign()): mainterm *= -1 rhs *= -1 diff = log(mainterm) - log(rhs) soln = _lambert(expand_log(diff), symbol) # 3) d*p**(a*B + b) + c*B = R # collect on main pow # log(R - c*B) - a*B*log(p) = log(d) + b*log(p) if not soln: mainpow = _mostfunc(lhs, Pow, symbol) if mainpow and symbol in mainpow.exp.free_symbols: lhs = collect(lhs, mainpow) if lhs.is_Mul and rhs != 0: soln = _lambert(expand_log(log(lhs) - log(rhs)), symbol) elif lhs.is_Add: # move all but mainpow-containing term to rhs other = lhs.subs(mainpow, 0) mainterm = lhs - other rhs = rhs - other diff = log(mainterm) - log(rhs) soln = _lambert(expand_log(diff), symbol) if not soln: raise NotImplementedError('%s does not appear to have a solution in ' 'terms of LambertW' % f) return list(ordered(soln))
def eval(cls, s): if s == 1: return log(2) z = zeta(s) if not z.has(zeta): return (1 - 2**(1 - s)) * z
def _eval_rewrite_as_log(self, x, **kwargs): return log(x + sqrt(x + 1) * sqrt(x - 1))
def test_bessely_leading_term(): assert bessely(0, x).as_leading_term(x) == (2*log(x) - 2*log(2))/pi assert bessely(1, sin(x)).as_leading_term(x) == (x*log(x) - x*log(2))/pi assert bessely(1, 2*sqrt(x)).as_leading_term(x) == sqrt(x)*log(x)/pi
def _eval_rewrite_as_Sum(self, *args): from sympy.concrete.summations import Sum return exp(Sum(log(self.function), *self.limits))
def _eval_rewrite_as_log(self, arg, **kwargs): return log(1/arg + sqrt(1/arg**2 + 1))
def _eval_rewrite_as_log(self, x, **kwargs): return (log(1 + 1/x) - log(1 - 1/x)) / 2
def test_bessely_series(): const = 2*S.EulerGamma/pi - 2*log(2)/pi + 2*log(x)/pi assert bessely(0, x).series(x, n=4) == const + x**2*(-log(x)/(2*pi)\ + (2 - 2*S.EulerGamma)/(4*pi) + log(2)/(2*pi)) + O(x**4*log(x)) assert bessely(0, x**(1.1)).series(x, n=4) == 2*S.EulerGamma/pi\ - 2*log(2)/pi + 2.2*log(x)/pi + x**2.2*(-0.55*log(x)/pi\ + (2 - 2*S.EulerGamma)/(4*pi) + log(2)/(2*pi)) + O(x**4*log(x)) assert bessely(0, x**2 + x).series(x, n=4) == \ const - (2 - 2*S.EulerGamma)*(-x**3/(2*pi) - x**2/(4*pi)) + 2*x/pi\ + x**2*(-log(x)/(2*pi) - 1/pi + log(2)/(2*pi))\ + x**3*(-log(x)/pi + 1/(6*pi) + log(2)/pi) + O(x**4*log(x)) assert bessely(0, x/(1 - x)).series(x, n=3) == const\ + 2*x/pi + x**2*(-log(x)/(2*pi) + (2 - 2*S.EulerGamma)/(4*pi)\ + log(2)/(2*pi) + 1/pi) + O(x**3*log(x)) assert bessely(0, log(1 + x)).series(x, n=3) == const\ - x/pi + x**2*(-log(x)/(2*pi) + (2 - 2*S.EulerGamma)/(4*pi)\ + log(2)/(2*pi) + 5/(12*pi)) + O(x**3*log(x)) assert bessely(1, sin(x)).series(x, n=4) == -(1/pi)*(1 - 2*S.EulerGamma)\ * (-x**3/12 + x/2) + x*(log(x)/pi - log(2)/pi) + x**3*(-7*log(x)\ / (24*pi) - 1/(6*pi) + (Rational(5, 2) - 2*S.EulerGamma)/(16*pi)\ + 7*log(2)/(24*pi)) + O(x**4*log(x)) assert bessely(1, 2*sqrt(x)).series(x, n=3) == sqrt(x)*(log(x)/pi \ - (1 - 2*S.EulerGamma)/pi) + x**Rational(3, 2)*(-log(x)/(2*pi)\ + (Rational(5, 2) - 2*S.EulerGamma)/(2*pi))\ + x**Rational(5, 2)*(log(x)/(12*pi)\ - (Rational(10, 3) - 2*S.EulerGamma)/(12*pi)) + O(x**3*log(x)) assert bessely(-2, sin(x)).series(x, n=4) == bessely(2, sin(x)).series(x, n=4)
def eval(cls, arg): arg = sympify(arg) if arg.is_Number: if arg is S.NaN: return S.NaN elif arg is S.Infinity: return S.Infinity elif arg is S.NegativeInfinity: return S.Infinity elif arg.is_zero: return S.Pi*S.ImaginaryUnit / 2 elif arg is S.One: return S.Zero elif arg is S.NegativeOne: return S.Pi*S.ImaginaryUnit if arg.is_number: cst_table = { S.ImaginaryUnit: log(S.ImaginaryUnit*(1 + sqrt(2))), -S.ImaginaryUnit: log(-S.ImaginaryUnit*(1 + sqrt(2))), S.Half: S.Pi/3, Rational(-1, 2): S.Pi*Rational(2, 3), sqrt(2)/2: S.Pi/4, -sqrt(2)/2: S.Pi*Rational(3, 4), 1/sqrt(2): S.Pi/4, -1/sqrt(2): S.Pi*Rational(3, 4), sqrt(3)/2: S.Pi/6, -sqrt(3)/2: S.Pi*Rational(5, 6), (sqrt(3) - 1)/sqrt(2**3): S.Pi*Rational(5, 12), -(sqrt(3) - 1)/sqrt(2**3): S.Pi*Rational(7, 12), sqrt(2 + sqrt(2))/2: S.Pi/8, -sqrt(2 + sqrt(2))/2: S.Pi*Rational(7, 8), sqrt(2 - sqrt(2))/2: S.Pi*Rational(3, 8), -sqrt(2 - sqrt(2))/2: S.Pi*Rational(5, 8), (1 + sqrt(3))/(2*sqrt(2)): S.Pi/12, -(1 + sqrt(3))/(2*sqrt(2)): S.Pi*Rational(11, 12), (sqrt(5) + 1)/4: S.Pi/5, -(sqrt(5) + 1)/4: S.Pi*Rational(4, 5) } if arg in cst_table: if arg.is_extended_real: return cst_table[arg]*S.ImaginaryUnit return cst_table[arg] if arg is S.ComplexInfinity: return S.ComplexInfinity if arg == S.ImaginaryUnit*S.Infinity: return S.Infinity + S.ImaginaryUnit*S.Pi/2 if arg == -S.ImaginaryUnit*S.Infinity: return S.Infinity - S.ImaginaryUnit*S.Pi/2 if arg.is_zero: return S.Pi*S.ImaginaryUnit*S.Half if isinstance(arg, cosh) and arg.args[0].is_number: z = arg.args[0] if z.is_real: from sympy.functions.elementary.complexes import Abs return Abs(z) r, i = match_real_imag(z) if r is not None and i is not None: f = floor(i/pi) m = z - I*pi*f even = f.is_even if even is True: if r.is_nonnegative: return m elif r.is_negative: return -m elif even is False: m -= I*pi if r.is_nonpositive: return -m elif r.is_positive: return m
def test_issue_18842(): f = log(x/(1 - x)) assert f.series(x, 0.491, n=1).removeO().nsimplify() == \ -S(180019443780011)/5000000000000000
def _pi_coeff(arg, cycles=1): """ When arg is a Number times pi (e.g. 3*pi/2) then return the Number normalized to be in the range [0, 2], else None. When an even multiple of pi is encountered, if it is multiplying something with known parity then the multiple is returned as 0 otherwise as 2. Examples ======== >>> from sympy.functions.elementary.trigonometric import _pi_coeff as coeff >>> from sympy import pi >>> from sympy.abc import x, y >>> coeff(3*x*pi) 3*x >>> coeff(11*pi/7) 11/7 >>> coeff(-11*pi/7) 3/7 >>> coeff(4*pi) 0 >>> coeff(5*pi) 1 >>> coeff(5.0*pi) 1 >>> coeff(5.5*pi) 3/2 >>> coeff(2 + pi) """ arg = sympify(arg) if arg is S.Pi: return S.One elif not arg: return S.Zero elif arg.is_Mul: cx = arg.coeff(S.Pi) if cx: c, x = cx.as_coeff_Mul() # pi is not included as coeff if c.is_Float: # recast exact binary fractions to Rationals f = abs(c) % 1 if f != 0: p = -int(round(log(f, 2).evalf())) m = 2**p cm = c * m i = int(cm) if i == cm: c = C.Rational(i, m) cx = c * x else: c = C.Rational(int(c)) cx = c * x if x.is_integer: c2 = c % 2 if c2 == 1: return x elif not c2: if x.is_even is not None: # known parity return S.Zero return 2 * x else: return c2 * x return cx
def test_issue_5852(): assert series(1/cos(x/log(x)), x, 0) == 1 + x**2/(2*log(x)**2) + \ 5*x**4/(24*log(x)**4) + O(x**6)
def test_power_rewrite_exp(): assert (I**I).rewrite(exp) == exp(-pi / 2) expr = (2 + 3 * I)**(4 + 5 * I) assert expr.rewrite(exp) == exp( (4 + 5 * I) * (log(sqrt(13)) + I * atan(Rational(3, 2)))) assert expr.rewrite(exp).expand() == \ 169*exp(5*I*log(13)/2)*exp(4*I*atan(Rational(3, 2)))*exp(-5*atan(Rational(3, 2))) assert ((6 + 7 * I)**5).rewrite(exp) == 7225 * sqrt(85) * exp( 5 * I * atan(Rational(7, 6))) expr = 5**(6 + 7 * I) assert expr.rewrite(exp) == exp((6 + 7 * I) * log(5)) assert expr.rewrite(exp).expand() == 15625 * exp(7 * I * log(5)) assert Pow(123, 789, evaluate=False).rewrite(exp) == 123**789 assert (1**I).rewrite(exp) == 1**I assert (0**I).rewrite(exp) == 0**I expr = (-2)**(2 + 5 * I) assert expr.rewrite(exp) == exp((2 + 5 * I) * (log(2) + I * pi)) assert expr.rewrite(exp).expand() == 4 * exp(-5 * pi) * exp(5 * I * log(2)) assert ((-2)**S(-5)).rewrite(exp) == (-2)**S(-5) x, y = symbols('x y') assert (x**y).rewrite(exp) == exp(y * log(x)) if global_parameters.exp_is_pow: assert (7**x).rewrite(exp) == Pow(S.Exp1, x * log(7), evaluate=False) else: assert (7**x).rewrite(exp) == exp(x * log(7), evaluate=False) assert ((2 + 3 * I)**x).rewrite(exp) == exp( x * (log(sqrt(13)) + I * atan(Rational(3, 2)))) assert (y**(5 + 6 * I)).rewrite(exp) == exp(log(y) * (5 + 6 * I)) assert all((1 / func(x)).rewrite(exp) == 1 / (func(x).rewrite(exp)) for func in (sin, cos, tan, sec, csc, sinh, cosh, tanh))
def _eval_rewrite_as_log(self, x): return log(x + sqrt(x**2 + 1))
def test_issue_22165(): assert O(log(x)).contains(2)
def eval(cls, arg): from sympy.simplify.simplify import signsimp from sympy.core.function import expand_mul from sympy.core.power import Pow if hasattr(arg, '_eval_Abs'): obj = arg._eval_Abs() if obj is not None: return obj if not isinstance(arg, Expr): raise TypeError("Bad argument type for Abs(): %s" % type(arg)) # handle what we can arg = signsimp(arg, evaluate=False) n, d = arg.as_numer_denom() if d.free_symbols and not n.free_symbols: return cls(n)/cls(d) if arg.is_Mul: known = [] unk = [] for t in arg.args: if t.is_Pow and t.exp.is_integer and t.exp.is_negative: bnew = cls(t.base) if isinstance(bnew, cls): unk.append(t) else: known.append(Pow(bnew, t.exp)) else: tnew = cls(t) if isinstance(tnew, cls): unk.append(t) else: known.append(tnew) known = Mul(*known) unk = cls(Mul(*unk), evaluate=False) if unk else S.One return known*unk if arg is S.NaN: return S.NaN if arg is S.ComplexInfinity: return S.Infinity if arg.is_Pow: base, exponent = arg.as_base_exp() if base.is_extended_real: if exponent.is_integer: if exponent.is_even: return arg if base is S.NegativeOne: return S.One return Abs(base)**exponent if base.is_extended_nonnegative: return base**re(exponent) if base.is_extended_negative: return (-base)**re(exponent)*exp(-S.Pi*im(exponent)) return elif not base.has(Symbol): # complex base # express base**exponent as exp(exponent*log(base)) a, b = log(base).as_real_imag() z = a + I*b return exp(re(exponent*z)) if isinstance(arg, exp): return exp(re(arg.args[0])) if isinstance(arg, AppliedUndef): return if arg.is_Add and arg.has(S.Infinity, S.NegativeInfinity): if any(a.is_infinite for a in arg.as_real_imag()): return S.Infinity if arg.is_zero: return S.Zero if arg.is_extended_nonnegative: return arg if arg.is_extended_nonpositive: return -arg if arg.is_imaginary: arg2 = -S.ImaginaryUnit * arg if arg2.is_extended_nonnegative: return arg2 # reject result if all new conjugates are just wrappers around # an expression that was already in the arg conj = signsimp(arg.conjugate(), evaluate=False) new_conj = conj.atoms(conjugate) - arg.atoms(conjugate) if new_conj and all(arg.has(i.args[0]) for i in new_conj): return if arg != conj and arg != -conj: ignore = arg.atoms(Abs) abs_free_arg = arg.xreplace({i: Dummy(real=True) for i in ignore}) unk = [a for a in abs_free_arg.free_symbols if a.is_extended_real is None] if not unk or not all(conj.has(conjugate(u)) for u in unk): return sqrt(expand_mul(arg*conj))
def test_simple_2(): assert Order(2 * x) * x == Order(x**2) assert Order(2 * x) / x == Order(1, x) assert Order(2 * x) * x * exp(1 / x) == Order(x**2 * exp(1 / x)) assert (Order(2 * x) * x * exp(1 / x) / log(x)**3).expr == x**2 * exp(1 / x) * log(x)**-3
def test_ceiling(): assert ceiling(nan) is nan assert ceiling(oo) is oo assert ceiling(-oo) is -oo assert ceiling(zoo) is zoo assert ceiling(0) == 0 assert ceiling(1) == 1 assert ceiling(-1) == -1 assert ceiling(E) == 3 assert ceiling(-E) == -2 assert ceiling(2*E) == 6 assert ceiling(-2*E) == -5 assert ceiling(pi) == 4 assert ceiling(-pi) == -3 assert ceiling(S.Half) == 1 assert ceiling(Rational(-1, 2)) == 0 assert ceiling(Rational(7, 3)) == 3 assert ceiling(-Rational(7, 3)) == -2 assert ceiling(Float(17.0)) == 17 assert ceiling(-Float(17.0)) == -17 assert ceiling(Float(7.69)) == 8 assert ceiling(-Float(7.69)) == -7 assert ceiling(I) == I assert ceiling(-I) == -I e = ceiling(i) assert e.func is ceiling and e.args[0] == i assert ceiling(oo*I) == oo*I assert ceiling(-oo*I) == -oo*I assert ceiling(exp(I*pi/4)*oo) == exp(I*pi/4)*oo assert ceiling(2*I) == 2*I assert ceiling(-2*I) == -2*I assert ceiling(I/2) == I assert ceiling(-I/2) == 0 assert ceiling(E + 17) == 20 assert ceiling(pi + 2) == 6 assert ceiling(E + pi) == 6 assert ceiling(I + pi) == I + 4 assert ceiling(ceiling(pi)) == 4 assert ceiling(ceiling(y)) == ceiling(y) assert ceiling(ceiling(x)) == ceiling(x) assert unchanged(ceiling, x) assert unchanged(ceiling, 2*x) assert unchanged(ceiling, k*x) assert ceiling(k) == k assert ceiling(2*k) == 2*k assert ceiling(k*n) == k*n assert unchanged(ceiling, k/2) assert unchanged(ceiling, x + y) assert ceiling(x + 3) == ceiling(x) + 3 assert ceiling(x + k) == ceiling(x) + k assert ceiling(y + 3) == ceiling(y) + 3 assert ceiling(y + k) == ceiling(y) + k assert ceiling(3 + pi + y*I) == 7 + ceiling(y)*I assert ceiling(k + n) == k + n assert unchanged(ceiling, x*I) assert ceiling(k*I) == k*I assert ceiling(Rational(23, 10) - E*I) == 3 - 2*I assert ceiling(sin(1)) == 1 assert ceiling(sin(-1)) == 0 assert ceiling(exp(2)) == 8 assert ceiling(-log(8)/log(2)) != -2 assert int(ceiling(-log(8)/log(2)).evalf(chop=True)) == -3 assert ceiling(factorial(50)/exp(1)) == \ 11188719610782480504630258070757734324011354208865721592720336801 assert (ceiling(y) >= y) == True assert (ceiling(y) > y) == False assert (ceiling(y) < y) == False assert (ceiling(y) <= y) == False assert (ceiling(x) >= x).is_Relational # x could be non-real assert (ceiling(x) < x).is_Relational assert (ceiling(x) >= y).is_Relational # arg is not same as rhs assert (ceiling(x) < y).is_Relational assert (ceiling(y) >= -oo) == True assert (ceiling(y) > -oo) == True assert (ceiling(y) <= oo) == True assert (ceiling(y) < oo) == True assert ceiling(y).rewrite(floor) == -floor(-y) assert ceiling(y).rewrite(frac) == y + frac(-y) assert ceiling(y).rewrite(floor).subs(y, -pi) == -floor(pi) assert ceiling(y).rewrite(floor).subs(y, E) == -floor(-E) assert ceiling(y).rewrite(frac).subs(y, pi) == ceiling(pi) assert ceiling(y).rewrite(frac).subs(y, -E) == ceiling(-E) assert Eq(ceiling(y), y + frac(-y)) assert Eq(ceiling(y), -floor(-y)) neg = Symbol('neg', negative=True) nn = Symbol('nn', nonnegative=True) pos = Symbol('pos', positive=True) np = Symbol('np', nonpositive=True) assert (ceiling(neg) <= 0) == True assert (ceiling(neg) < 0) == (neg <= -1) assert (ceiling(neg) > 0) == False assert (ceiling(neg) >= 0) == (neg > -1) assert (ceiling(neg) > -3) == (neg > -3) assert (ceiling(neg) <= 10) == (neg <= 10) assert (ceiling(nn) < 0) == False assert (ceiling(nn) >= 0) == True assert (ceiling(pos) < 0) == False assert (ceiling(pos) <= 0) == False assert (ceiling(pos) > 0) == True assert (ceiling(pos) >= 0) == True assert (ceiling(pos) >= 1) == True assert (ceiling(pos) > 5) == (pos > 5) assert (ceiling(np) <= 0) == True assert (ceiling(np) > 0) == False assert ceiling(neg).is_positive == False assert ceiling(neg).is_nonpositive == True assert ceiling(nn).is_positive is None assert ceiling(nn).is_nonpositive is None assert ceiling(pos).is_positive == True assert ceiling(pos).is_nonpositive == False assert ceiling(np).is_positive == False assert ceiling(np).is_nonpositive == True assert (ceiling(7, evaluate=False) >= 7) == True assert (ceiling(7, evaluate=False) > 7) == False assert (ceiling(7, evaluate=False) <= 7) == True assert (ceiling(7, evaluate=False) < 7) == False assert (ceiling(7, evaluate=False) >= 6) == True assert (ceiling(7, evaluate=False) > 6) == True assert (ceiling(7, evaluate=False) <= 6) == False assert (ceiling(7, evaluate=False) < 6) == False assert (ceiling(7, evaluate=False) >= 8) == False assert (ceiling(7, evaluate=False) > 8) == False assert (ceiling(7, evaluate=False) <= 8) == True assert (ceiling(7, evaluate=False) < 8) == True assert (ceiling(x) <= 5.5) == Le(ceiling(x), 5.5, evaluate=False) assert (ceiling(x) >= -3.2) == Ge(ceiling(x), -3.2, evaluate=False) assert (ceiling(x) < 2.9) == Lt(ceiling(x), 2.9, evaluate=False) assert (ceiling(x) > -1.7) == Gt(ceiling(x), -1.7, evaluate=False) assert (ceiling(y) <= 5.5) == (y <= 5) assert (ceiling(y) >= -3.2) == (y > -4) assert (ceiling(y) < 2.9) == (y <= 2) assert (ceiling(y) > -1.7) == (y > -2) assert (ceiling(y) <= n) == (y <= n) assert (ceiling(y) >= n) == (y > n - 1) assert (ceiling(y) < n) == (y <= n - 1) assert (ceiling(y) > n) == (y > n)
def prime(nth): """ Return the nth prime, with the primes indexed as prime(1) = 2, prime(2) = 3, etc.... The nth prime is approximately n*log(n). Logarithmic integral of x is a pretty nice approximation for number of primes <= x, i.e. li(x) ~ pi(x) In fact, for the numbers we are concerned about( x<1e11 ), li(x) - pi(x) < 50000 Also, li(x) > pi(x) can be safely assumed for the numbers which can be evaluated by this function. Here, we find the least integer m such that li(m) > n using binary search. Now pi(m-1) < li(m-1) <= n, We find pi(m - 1) using primepi function. Starting from m, we have to find n - pi(m-1) more primes. For the inputs this implementation can handle, we will have to test primality for at max about 10**5 numbers, to get our answer. References ========== - https://en.wikipedia.org/wiki/Prime_number_theorem#Table_of_.CF.80.28x.29.2C_x_.2F_log_x.2C_and_li.28x.29 - https://en.wikipedia.org/wiki/Prime_number_theorem#Approximations_for_the_nth_prime_number - https://en.wikipedia.org/wiki/Skewes%27_number Examples ======== >>> from sympy import prime >>> prime(10) 29 >>> prime(1) 2 >>> prime(100000) 1299709 See Also ======== sympy.ntheory.primetest.isprime : Test if n is prime primerange : Generate all primes in a given range primepi : Return the number of primes less than or equal to n """ n = as_int(nth) if n < 1: raise ValueError("nth must be a positive integer; prime(1) == 2") prime_arr = [2, 3, 5, 7, 11, 13, 17] if n <= 7: return prime_arr[n - 1] from sympy.functions.special.error_functions import li from sympy.functions.elementary.exponential import log a = 2 # Lower bound for binary search b = int(n * (log(n) + log(log(n)))) # Upper bound for the search. while a < b: mid = (a + b) >> 1 if li(mid) > n: b = mid else: a = mid + 1 n_primes = primepi(a - 1) while n_primes < n: if isprime(a): n_primes += 1 a += 1 return a - 1
def test_floor(): assert floor(nan) is nan assert floor(oo) is oo assert floor(-oo) is -oo assert floor(zoo) is zoo assert floor(0) == 0 assert floor(1) == 1 assert floor(-1) == -1 assert floor(E) == 2 assert floor(-E) == -3 assert floor(2*E) == 5 assert floor(-2*E) == -6 assert floor(pi) == 3 assert floor(-pi) == -4 assert floor(S.Half) == 0 assert floor(Rational(-1, 2)) == -1 assert floor(Rational(7, 3)) == 2 assert floor(Rational(-7, 3)) == -3 assert floor(-Rational(7, 3)) == -3 assert floor(Float(17.0)) == 17 assert floor(-Float(17.0)) == -17 assert floor(Float(7.69)) == 7 assert floor(-Float(7.69)) == -8 assert floor(I) == I assert floor(-I) == -I e = floor(i) assert e.func is floor and e.args[0] == i assert floor(oo*I) == oo*I assert floor(-oo*I) == -oo*I assert floor(exp(I*pi/4)*oo) == exp(I*pi/4)*oo assert floor(2*I) == 2*I assert floor(-2*I) == -2*I assert floor(I/2) == 0 assert floor(-I/2) == -I assert floor(E + 17) == 19 assert floor(pi + 2) == 5 assert floor(E + pi) == 5 assert floor(I + pi) == 3 + I assert floor(floor(pi)) == 3 assert floor(floor(y)) == floor(y) assert floor(floor(x)) == floor(x) assert unchanged(floor, x) assert unchanged(floor, 2*x) assert unchanged(floor, k*x) assert floor(k) == k assert floor(2*k) == 2*k assert floor(k*n) == k*n assert unchanged(floor, k/2) assert unchanged(floor, x + y) assert floor(x + 3) == floor(x) + 3 assert floor(x + k) == floor(x) + k assert floor(y + 3) == floor(y) + 3 assert floor(y + k) == floor(y) + k assert floor(3 + I*y + pi) == 6 + floor(y)*I assert floor(k + n) == k + n assert unchanged(floor, x*I) assert floor(k*I) == k*I assert floor(Rational(23, 10) - E*I) == 2 - 3*I assert floor(sin(1)) == 0 assert floor(sin(-1)) == -1 assert floor(exp(2)) == 7 assert floor(log(8)/log(2)) != 2 assert int(floor(log(8)/log(2)).evalf(chop=True)) == 3 assert floor(factorial(50)/exp(1)) == \ 11188719610782480504630258070757734324011354208865721592720336800 assert (floor(y) < y) == False assert (floor(y) <= y) == True assert (floor(y) > y) == False assert (floor(y) >= y) == False assert (floor(x) <= x).is_Relational # x could be non-real assert (floor(x) > x).is_Relational assert (floor(x) <= y).is_Relational # arg is not same as rhs assert (floor(x) > y).is_Relational assert (floor(y) <= oo) == True assert (floor(y) < oo) == True assert (floor(y) >= -oo) == True assert (floor(y) > -oo) == True assert floor(y).rewrite(frac) == y - frac(y) assert floor(y).rewrite(ceiling) == -ceiling(-y) assert floor(y).rewrite(frac).subs(y, -pi) == floor(-pi) assert floor(y).rewrite(frac).subs(y, E) == floor(E) assert floor(y).rewrite(ceiling).subs(y, E) == -ceiling(-E) assert floor(y).rewrite(ceiling).subs(y, -pi) == -ceiling(pi) assert Eq(floor(y), y - frac(y)) assert Eq(floor(y), -ceiling(-y)) neg = Symbol('neg', negative=True) nn = Symbol('nn', nonnegative=True) pos = Symbol('pos', positive=True) np = Symbol('np', nonpositive=True) assert (floor(neg) < 0) == True assert (floor(neg) <= 0) == True assert (floor(neg) > 0) == False assert (floor(neg) >= 0) == False assert (floor(neg) <= -1) == True assert (floor(neg) >= -3) == (neg >= -3) assert (floor(neg) < 5) == (neg < 5) assert (floor(nn) < 0) == False assert (floor(nn) >= 0) == True assert (floor(pos) < 0) == False assert (floor(pos) <= 0) == (pos < 1) assert (floor(pos) > 0) == (pos >= 1) assert (floor(pos) >= 0) == True assert (floor(pos) >= 3) == (pos >= 3) assert (floor(np) <= 0) == True assert (floor(np) > 0) == False assert floor(neg).is_negative == True assert floor(neg).is_nonnegative == False assert floor(nn).is_negative == False assert floor(nn).is_nonnegative == True assert floor(pos).is_negative == False assert floor(pos).is_nonnegative == True assert floor(np).is_negative is None assert floor(np).is_nonnegative is None assert (floor(7, evaluate=False) >= 7) == True assert (floor(7, evaluate=False) > 7) == False assert (floor(7, evaluate=False) <= 7) == True assert (floor(7, evaluate=False) < 7) == False assert (floor(7, evaluate=False) >= 6) == True assert (floor(7, evaluate=False) > 6) == True assert (floor(7, evaluate=False) <= 6) == False assert (floor(7, evaluate=False) < 6) == False assert (floor(7, evaluate=False) >= 8) == False assert (floor(7, evaluate=False) > 8) == False assert (floor(7, evaluate=False) <= 8) == True assert (floor(7, evaluate=False) < 8) == True assert (floor(x) <= 5.5) == Le(floor(x), 5.5, evaluate=False) assert (floor(x) >= -3.2) == Ge(floor(x), -3.2, evaluate=False) assert (floor(x) < 2.9) == Lt(floor(x), 2.9, evaluate=False) assert (floor(x) > -1.7) == Gt(floor(x), -1.7, evaluate=False) assert (floor(y) <= 5.5) == (y < 6) assert (floor(y) >= -3.2) == (y >= -3) assert (floor(y) < 2.9) == (y < 3) assert (floor(y) > -1.7) == (y >= -1) assert (floor(y) <= n) == (y < n + 1) assert (floor(y) >= n) == (y >= n) assert (floor(y) < n) == (y < n) assert (floor(y) > n) == (y >= n + 1)
def _solve_lambert(f, symbol, gens, domain=S.Complexes): """Return solution to ``f`` if it is a Lambert-type expression else raise NotImplementedError. For ``f(X, a..f) = a*log(b*X + c) + d*X - f = 0`` the solution for ``X`` is ``X = -c/b + (a/d)*W(d/(a*b)*exp(c*d/a/b)*exp(f/a))``. There are a variety of forms for `f(X, a..f)` as enumerated below: 1a1) if B**B = R for R not in [0, 1] (since those cases would already be solved before getting here) then log of both sides gives log(B) + log(log(B)) = log(log(R)) and X = log(B), a = 1, b = 1, c = 0, d = 1, f = log(log(R)) 1a2) if B*(b*log(B) + c)**a = R then log of both sides gives log(B) + a*log(b*log(B) + c) = log(R) and X = log(B), d=1, f=log(R) 1b) if a*log(b*B + c) + d*B = R and X = B, f = R 2a) if (b*B + c)*exp(d*B + g) = R then log of both sides gives log(b*B + c) + d*B + g = log(R) and X = B, a = 1, f = log(R) - g 2b) if g*exp(d*B + h) - b*B = c then the log form is log(g) + d*B + h - log(b*B + c) = 0 and X = B, a = -1, f = -h - log(g) 3) if d*p**(a*B + g) - b*B = c then the log form is log(d) + (a*B + g)*log(p) - log(b*B + c) = 0 and X = B, a = -1, d = a*log(p), f = -log(d) - g*log(p) """ def _solve_even_degree_expr(expr, t, symbol, domain=S.Complexes): """Return the unique solutions of equations derived from ``expr`` by replacing ``t`` with ``+/- symbol``. Parameters ========== expr : Expr The expression which includes a dummy variable t to be replaced with +symbol and -symbol. symbol : Symbol The symbol for which a solution is being sought. Returns ======= List of unique solution of the two equations generated by replacing ``t`` with positive and negative ``symbol``. Notes ===== If ``expr = 2*log(t) + x/2` then solutions for ``2*log(x) + x/2 = 0`` and ``2*log(-x) + x/2 = 0`` are returned by this function. Though this may seem counter-intuitive, one must note that the ``expr`` being solved here has been derived from a different expression. For an expression like ``eq = x**2*g(x) = 1``, if we take the log of both sides we obtain ``log(x**2) + log(g(x)) = 0``. If x is positive then this simplifies to ``2*log(x) + log(g(x)) = 0``; the Lambert-solving routines will return solutions for this, but we must also consider the solutions for ``2*log(-x) + log(g(x))`` since those must also be a solution of ``eq`` which has the same value when the ``x`` in ``x**2`` is negated. If `g(x)` does not have even powers of symbol then we don't want to replace the ``x`` there with ``-x``. So the role of the ``t`` in the expression received by this function is to mark where ``+/-x`` should be inserted before obtaining the Lambert solutions. """ nlhs, plhs = [ expr.xreplace({t: sgn*symbol}) for sgn in (-1, 1)] sols = _solve_lambert(nlhs, symbol, gens, domain) if sols == S.EmptySet: return S.EmptySet if plhs != nlhs: sols.extend(_solve_lambert(plhs, symbol, gens, domain)) # uniq is needed for a case like # 2*log(t) - log(-z**2) + log(z + log(x) + log(z)) # where subtituting t with +/-x gives all the same solution; # uniq, rather than list(set()), is used to maintain canonical # order return list(uniq(sols)) nrhs, lhs = f.as_independent(symbol, as_Add=True) rhs = -nrhs lamcheck = [tmp for tmp in gens if (tmp.func in [exp, log] or (tmp.is_Pow and symbol in tmp.exp.free_symbols))] if not lamcheck: raise NotImplementedError() if lhs.is_Add or lhs.is_Mul: # replacing all even_degrees of symbol with dummy variable t # since these will need special handling; non-Add/Mul do not # need this handling t = Dummy('t', **symbol.assumptions0) lhs = lhs.replace( lambda i: # find symbol**even i.is_Pow and i.base == symbol and i.exp.is_even, lambda i: # replace t**even t**i.exp) if lhs.is_Add and lhs.has(t): t_indep = lhs.subs(t, 0) t_term = lhs - t_indep _rhs = rhs - t_indep if not t_term.is_Add and _rhs and not ( t_term.has(S.ComplexInfinity, S.NaN)): eq = expand_log(log(t_term) - log(_rhs)) return _solve_even_degree_expr(eq, t, symbol, domain) elif lhs.is_Mul and rhs: # this needs to happen whether t is present or not lhs = expand_log(log(lhs), force=True) rhs = log(rhs) if lhs.has(t) and lhs.is_Add: # it expanded from Mul to Add eq = lhs - rhs return _solve_even_degree_expr(eq, t, symbol, domain) # restore symbol in lhs lhs = lhs.xreplace({t: symbol}) lhs = powsimp(factor(lhs, deep=True)) # make sure we have inverted as completely as possible r = Dummy() i, lhs = _invert(lhs - r, symbol) rhs = i.xreplace({r: rhs}) # For the first forms: # # 1a1) B**B = R will arrive here as B*log(B) = log(R) # lhs is Mul so take log of both sides: # log(B) + log(log(B)) = log(log(R)) # 1a2) B*(b*log(B) + c)**a = R will arrive unchanged so # lhs is Mul, so take log of both sides: # log(B) + a*log(b*log(B) + c) = log(R) # 1b) d*log(a*B + b) + c*B = R will arrive unchanged so # lhs is Add, so isolate c*B and expand log of both sides: # log(c) + log(B) = log(R - d*log(a*B + b)) soln = [] if not soln: mainlog = _mostfunc(lhs, log, symbol) if mainlog: if lhs.is_Mul and rhs != 0: if domain.is_subset(S.Reals): soln = _lambert_real(log(lhs) - log(rhs), symbol) else: soln = _lambert(log(lhs) - log(rhs), symbol) elif lhs.is_Add: other = lhs.subs(mainlog, 0) if other and not other.is_Add and [ tmp for tmp in other.atoms(Pow) if symbol in tmp.free_symbols]: if not rhs: diff = log(other) - log(other - lhs) else: diff = log(lhs - other) - log(rhs - other) if domain.is_subset(S.Reals): soln = _lambert_real(expand_log(diff), symbol) else: soln = _lambert(expand_log(diff), symbol) else: #it's ready to go if domain.is_subset(S.Reals): soln = _lambert_real(lhs - rhs, symbol) else: soln = _lambert(lhs - rhs, symbol) if soln == S.EmptySet : return S.EmptySet # For the next forms, # # collect on main exp # 2a) (b*B + c)*exp(d*B + g) = R # lhs is mul, so take log of both sides: # log(b*B + c) + d*B = log(R) - g # 2b) g*exp(d*B + h) - b*B = R # lhs is add, so add b*B to both sides, # take the log of both sides and rearrange to give # log(R + b*B) - d*B = log(g) + h if not soln: mainexp = _mostfunc(lhs, exp, symbol) if mainexp: lhs = collect(lhs, mainexp) if lhs.is_Mul and rhs != 0: if domain.is_subset(S.Reals): soln = _lambert_real(expand_log(log(lhs) - log(rhs)), symbol) else: soln = _lambert(expand_log(log(lhs) - log(rhs)), symbol) elif lhs.is_Add: # move all but mainexp-containing term to rhs other = lhs.subs(mainexp, 0) mainterm = lhs - other rhs = rhs - other if (mainterm.could_extract_minus_sign() and rhs.could_extract_minus_sign()): mainterm *= -1 rhs *= -1 diff = log(mainterm) - log(rhs) if domain.is_subset(S.Reals): soln = _lambert_real(expand_log(diff), symbol) else: soln = _lambert(expand_log(diff), symbol) # For the last form: # # 3) d*p**(a*B + g) - b*B = c # collect on main pow, add b*B to both sides, # take log of both sides and rearrange to give # a*B*log(p) - log(b*B + c) = -log(d) - g*log(p) if not soln: mainpow = _mostfunc(lhs, Pow, symbol) if mainpow and symbol in mainpow.exp.free_symbols: lhs = collect(lhs, mainpow) if lhs.is_Mul and rhs != 0: # b*B = 0 if domain.is_subset(S.Reals): soln = _lambert_real(expand_log(log(lhs) - log(rhs)), symbol) else: soln = _lambert(expand_log(log(lhs) - log(rhs)), symbol) elif lhs.is_Add: # move all but mainpow-containing term to rhs other = lhs.subs(mainpow, 0) mainterm = lhs - other rhs = rhs - other diff = log(mainterm) - log(rhs) if domain.is_subset(S.Reals): soln = _lambert_real(expand_log(diff), symbol) else: soln = _lambert(expand_log(diff), symbol) if not soln: raise NotImplementedError('%s does not appear to have a solution in ' 'terms of LambertW' % f) return list(ordered(soln))
def test_ln_args(): assert O(log(x)) + O(log(2 * x)) == O(log(x)) assert O(log(x)) + O(log(x**3)) == O(log(x)) assert O(log(x * y)) + O(log(x) + log(y)) == O(log(x * y))
def eval(cls, n, z): n, z = list(map(sympify, (n, z))) from sympy import unpolarify if n.is_integer: if n.is_nonnegative: nz = unpolarify(z) if z != nz: return polygamma(n, nz) if n == -1: return loggamma(z) else: if z.is_Number: if z is S.NaN: return S.NaN elif z is S.Infinity: if n.is_Number: if n is S.Zero: return S.Infinity else: return S.Zero elif z.is_Integer: if z.is_nonpositive: return S.ComplexInfinity else: if n is S.Zero: return -S.EulerGamma + harmonic(z - 1, 1) elif n.is_odd: return (-1)**(n + 1) * factorial(n) * zeta( n + 1, z) if n == 0: if z is S.NaN: return S.NaN elif z.is_Rational: # TODO actually *any* n/m can be done, but that is messy lookup = { S(1) / 2: -2 * log(2) - S.EulerGamma, S(1) / 3: -S.Pi / 2 / sqrt(3) - 3 * log(3) / 2 - S.EulerGamma, S(1) / 4: -S.Pi / 2 - 3 * log(2) - S.EulerGamma, S(3) / 4: -3 * log(2) - S.EulerGamma + S.Pi / 2, S(2) / 3: -3 * log(3) / 2 + S.Pi / 2 / sqrt(3) - S.EulerGamma } if z > 0: n = floor(z) z0 = z - n if z0 in lookup: return lookup[z0] + Add( *[1 / (z0 + k) for k in range(n)]) elif z < 0: n = floor(1 - z) z0 = z + n if z0 in lookup: return lookup[z0] - Add( *[1 / (z0 - 1 - k) for k in range(n)]) elif z in (S.Infinity, S.NegativeInfinity): return S.Infinity else: t = z.extract_multiplicatively(S.ImaginaryUnit) if t in (S.Infinity, S.NegativeInfinity): return S.Infinity
def test_leading_term(): from sympy.functions.special.gamma_functions import digamma assert O(1 / digamma(1 / x)) == O(1 / log(x))
def test_issue_9910(): assert O(x * log(x) + sin(x), (x, oo)) == O(x * log(x), (x, oo))
def test_caching_bug(): #needs to be a first test, so that all caches are clean #cache it O(w) #and test that this won't raise an exception O(w**(-1 / x / log(3) * log(5)), w)
def _eval_nseries(self, x, n, logx): # NOTE! This function is an important part of the gruntz algorithm # for computing limits. It has to return a generalized power # series with coefficients in C(log, log(x)). In more detail: # It has to return an expression # c_0*x**e_0 + c_1*x**e_1 + ... (finitely many terms) # where e_i are numbers (not necessarily integers) and c_i are # expressions involving only numbers, the log function, and log(x). from sympy import powsimp, collect, exp, log, O, ceiling b, e = self.args if e.is_Integer: if e > 0: # positive integer powers are easy to expand, e.g.: # sin(x)**4 = (x-x**3/3+...)**4 = ... return expand_multinomial(Pow( b._eval_nseries(x, n=n, logx=logx), e), deep=False) elif e is S.NegativeOne: # this is also easy to expand using the formula: # 1/(1 + x) = 1 - x + x**2 - x**3 ... # so we need to rewrite base to the form "1+x" b = b._eval_nseries(x, n=n, logx=logx) prefactor = b.as_leading_term(x) # express "rest" as: rest = 1 + k*x**l + ... + O(x**n) rest = expand_mul((b - prefactor) / prefactor) if rest == 0: # if prefactor == w**4 + x**2*w**4 + 2*x*w**4, we need to # factor the w**4 out using collect: return 1 / collect(prefactor, x) if rest.is_Order: return 1 / prefactor + rest / prefactor n2 = rest.getn() if n2 is not None: n = n2 # remove the O - powering this is slow if logx is not None: rest = rest.removeO() k, l = rest.leadterm(x) if l.is_Rational and l > 0: pass elif l.is_number and l > 0: l = l.evalf() else: raise NotImplementedError() terms = [1 / prefactor] for m in xrange(1, ceiling(n / l)): new_term = terms[-1] * (-rest) if new_term.is_Pow: new_term = new_term._eval_expand_multinomial( deep=False) else: new_term = expand_mul(new_term, deep=False) terms.append(new_term) # Append O(...), we know the order. if n2 is None or logx is not None: terms.append(O(x**n)) return powsimp(Add(*terms), deep=True, combine='exp') else: # negative powers are rewritten to the cases above, for # example: # sin(x)**(-4) = 1/( sin(x)**4) = ... # and expand the denominator: denominator = (b**(-e))._eval_nseries(x, n=n, logx=logx) if 1 / denominator == self: return self # now we have a type 1/f(x), that we know how to expand return (1 / denominator)._eval_nseries(x, n=n, logx=logx) if e.has(Symbol): return exp(e * log(b))._eval_nseries(x, n=n, logx=logx) # see if the base is as simple as possible bx = b while bx.is_Pow and bx.exp.is_Rational: bx = bx.base if bx == x: return self # work for b(x)**e where e is not an Integer and does not contain x # and hopefully has no other symbols def e2int(e): """return the integer value (if possible) of e and a flag indicating whether it is bounded or not.""" n = e.limit(x, 0) unbounded = n.is_unbounded if not unbounded: # XXX was int or floor intended? int used to behave like floor # so int(-Rational(1, 2)) returned -1 rather than int's 0 try: n = int(n) except TypeError: #well, the n is something more complicated (like 1+log(2)) try: n = int(n.evalf()) + 1 # XXX why is 1 being added? except TypeError: pass # hope that base allows this to be resolved n = _sympify(n) return n, unbounded order = O(x**n, x) ei, unbounded = e2int(e) b0 = b.limit(x, 0) if unbounded and (b0 is S.One or b0.has(Symbol)): # XXX what order if b0 is S.One: resid = (b - 1) if resid.is_positive: return S.Infinity elif resid.is_negative: return S.Zero raise ValueError('cannot determine sign of %s' % resid) return b0**ei if (b0 is S.Zero or b0.is_unbounded): if unbounded is not False: return b0**e # XXX what order if not ei.is_number: # if not, how will we proceed? raise ValueError('expecting numerical exponent but got %s' % ei) nuse = n - ei bs = b._eval_nseries(x, n=nuse, logx=logx) terms = bs.removeO() if terms.is_Add: bs = terms lt = terms.as_leading_term(x) # bs -> lt + rest -> lt*(1 + (bs/lt - 1)) return ((Pow(lt, e) * Pow((bs / lt).expand(), e).nseries( x, n=nuse, logx=logx)).expand() + order) rv = bs**e if terms != bs: rv += order return rv # either b0 is bounded but neither 1 nor 0 or e is unbounded # b -> b0 + (b-b0) -> b0 * (1 + (b/b0-1)) o2 = order * (b0**-e) z = (b / b0 - 1) o = O(z, x) #r = self._compute_oseries3(z, o2, self.taylor_term) if o is S.Zero or o2 is S.Zero: unbounded = True else: if o.expr.is_number: e2 = log(o2.expr * x) / log(x) else: e2 = log(o2.expr) / log(o.expr) n, unbounded = e2int(e2) if unbounded: # requested accuracy gives infinite series, # order is probably non-polynomial e.g. O(exp(-1/x), x). r = 1 + z else: l = [] g = None for i in xrange(n + 2): g = self.taylor_term(i, z, g) g = g.nseries(x, n=n, logx=logx) l.append(g) r = Add(*l) return r * b0**e + order