def test_getO(): assert (x).getO() is None assert (x).removeO() == x assert (O(x)).getO() == O(x) assert (O(x)).removeO() == 0 assert (z + O(x) + O(y)).getO() == O(x) + O(y) assert (z + O(x) + O(y)).removeO() == z raises(NotImplementedError, lambda: (O(x) + O(y)).getn())
def test_seriesbug2b(): w = Symbol("w") #test sin e = sin(2*w)/w assert e.nseries(w, 0, 3) == 2 + O(w**2, w)
def test_logbug4(): assert log(2 + O(x)).nseries(x, 0, 2) == log(2) + O(x, x)
def test_genexp_x(): e = 1/(1 + sqrt(x)) assert e.nseries(x, 0, 2) == \ 1 + x - sqrt(x) - sqrt(x)**3 + O(x**2, x)
def test_seriesbug2(): w = Symbol("w") #simple case (1): e = ((2*w)/w)**(1 + w) assert e.nseries(w, 0, 1) == 2 + O(w, w) assert e.nseries(w, 0, 1).subs(w, 0) == 2
def test_ignore_order_terms(): eq = exp(x).series(x, 0, 3) + sin(y + x**3) - 1 assert cse(eq) == ([], [sin(x**3 + y) + x + x**2 / 2 + O(x**3)])
def test_exp(): e = (1 + x)**(1/x) assert e.nseries(x, n=3) == exp(1) - x*exp(1)/2 + O(x**2, x)
def test_issue_9192(): assert O(1) * O(1) == O(1) assert O(1)**O(1) == O(1)
def test_performance_of_adding_order(): l = list(x**i for i in range(1000)) l.append(O(x**1001)) assert Add(*l).subs(x, 1) == O(1)
def test_issue_6753(): assert (1 + x**2)**10000 * O(x) == O(x)
def test_order_at_some_point(): assert Order(x, (x, 1)) == Order(1, (x, 1)) assert Order(2 * x - 2, (x, 1)) == Order(x - 1, (x, 1)) assert Order(-x + 1, (x, 1)) == Order(x - 1, (x, 1)) assert Order(x - 1, (x, 1))**2 == Order((x - 1)**2, (x, 1)) assert Order(x - 2, (x, 2)) - O(x - 2, (x, 2)) == Order(x - 2, (x, 2))
def test_issue_4279(): a, b = symbols('a b') assert O(a, a, b) + O(1, a, b) == O(1, a, b) assert O(b, a, b) + O(1, a, b) == O(1, a, b) assert O(a + b, a, b) + O(1, a, b) == O(1, a, b) assert O(1, a, b) + O(a, a, b) == O(1, a, b) assert O(1, a, b) + O(b, a, b) == O(1, a, b) assert O(1, a, b) + O(a + b, a, b) == O(1, a, b)
def test_eval(): assert Order(x).subs(Order(x), 1) == 1 assert Order(x).subs(x, y) == Order(y) assert Order(x).subs(y, x) == Order(x) assert Order(x).subs(x, x + y) == Order(x + y, (x, -y)) assert (O(1)**x).is_Pow
def test_leading_term(): from sympy import digamma assert O(1 / digamma(1 / x)) == O(1 / log(x))
def test_expand_arit(): a = Symbol("a") b = Symbol("b", positive=True) c = Symbol("c") p = R(5) e = (a + b) * c assert e == c * (a + b) assert (e.expand() - a * c - b * c) == R(0) e = (a + b) * (a + b) assert e == (a + b)**2 assert e.expand() == 2 * a * b + a**2 + b**2 e = (a + b) * (a + b)**R(2) assert e == (a + b)**3 assert e.expand() == 3 * b * a**2 + 3 * a * b**2 + a**3 + b**3 assert e.expand() == 3 * b * a**2 + 3 * a * b**2 + a**3 + b**3 e = (a + b) * (a + c) * (b + c) assert e == (a + c) * (a + b) * (b + c) assert e.expand( ) == 2 * a * b * c + b * a**2 + c * a**2 + b * c**2 + a * c**2 + c * b**2 + a * b**2 e = (a + R(1))**p assert e == (1 + a)**5 assert e.expand() == 1 + 5 * a + 10 * a**2 + 10 * a**3 + 5 * a**4 + a**5 e = (a + b + c) * (a + c + p) assert e == (5 + a + c) * (a + b + c) assert e.expand( ) == 5 * a + 5 * b + 5 * c + 2 * a * c + b * c + a * b + a**2 + c**2 x = Symbol("x") s = exp(x * x) - 1 e = s.nseries(x, 0, 6) / x**2 assert e.expand() == 1 + x**2 / 2 + O(x**4) e = (x * (y + z))**(x * (y + z)) * (x + y) assert e.expand(power_exp=False, power_base=False) == x * ( x * y + x * z)**(x * y + x * z) + y * (x * y + x * z)**(x * y + x * z) assert e.expand(power_exp=False, power_base=False, deep=False) == x* \ (x*(y + z))**(x*(y + z)) + y*(x*(y + z))**(x*(y + z)) e = x * (x + (y + 1)**2) assert e.expand(deep=False) == x**2 + x * (y + 1)**2 e = (x * (y + z))**z assert e.expand(power_base=True, mul=True, deep=True) in [x**z * (y + z)**z, (x * y + x * z)**z] assert ((2 * y)**z).expand() == 2**z * y**z p = Symbol('p', positive=True) assert sqrt(-x).expand().is_Pow assert sqrt(-x).expand(force=True) == I * sqrt(x) assert ((2 * y * p)**z).expand() == 2**z * p**z * y**z assert ((2 * y * p * x)**z).expand() == 2**z * p**z * (x * y)**z assert ((2 * y * p * x)**z).expand(force=True) == 2**z * p**z * x**z * y**z assert ((2 * y * p * -pi)**z).expand() == 2**z * pi**z * p**z * (-y)**z assert ((2 * y * p * -pi * x)**z).expand() == 2**z * pi**z * p**z * (-x * y)**z n = Symbol('n', negative=True) m = Symbol('m', negative=True) assert ((-2 * x * y * n)**z).expand() == 2**z * (-n)**z * (x * y)**z assert ((-2 * x * y * n * m)**z).expand() == 2**z * (-m)**z * (-n)**z * (-x * y)**z # issue 5482 assert sqrt(-2 * x * n) == sqrt(2) * sqrt(-n) * sqrt(x) # issue 5605 (2) assert (cos(x + y)**2).expand(trig=True) in [ (-sin(x) * sin(y) + cos(x) * cos(y))**2, sin(x)**2 * sin(y)**2 - 2 * sin(x) * sin(y) * cos(x) * cos(y) + cos(x)**2 * cos(y)**2 ] # Check that this isn't too slow x = Symbol('x') W = 1 for i in range(1, 21): W = W * (x - i) W = W.expand() assert W.has(-1672280820 * x**15)
def test_issue_15539(): assert O(1 / x**2 + 1 / x**4, (x, -oo)) == O(1 / x**2, (x, -oo)) assert O(1 / x**4 + exp(x), (x, -oo)) == O(1 / x**4, (x, -oo)) assert O(1 / x**4 + exp(-x), (x, -oo)) == O(exp(-x), (x, -oo)) assert O(1 / x, (x, oo)).subs(x, -x) == O(-1 / x, (x, -oo))
def test_piecewise_series(): from sympy import sin, cos, O p1 = Piecewise((sin(x), x < 0), (cos(x), x > 0)) p2 = Piecewise((x + O(x**2), x < 0), (1 + O(x**2), x > 0)) assert p1.nseries(x, n=2) == p2
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 test_series1_failing(): assert x.nseries(x, 0, 0) == O(1, x) assert x.nseries(x, 0, 1) == O(x, x)
def test_simple_7(): assert 1 + O(1) == O(1) assert 2 + O(1) == O(1) assert x + O(1) == O(1) assert 1 / x + O(1) == 1 / x + O(1)
def test_bug3(): e = (2/x + 3/x**2)/(1/x + 1/x**2) assert e.nseries(x, n=3) == 3 + O(x)
def test_simple_8(): assert O(sqrt(-x)) == O(sqrt(x)) assert O(x**2 * sqrt(x)) == O(x**Rational(5, 2)) assert O(x**3 * sqrt(-(-x)**3)) == O(x**Rational(9, 2)) assert O(x**Rational(3, 2) * sqrt((-x)**3)) == O(x**3) assert O(x * (-2 * x)**(I / 2)) == O(x * (-x)**(I / 2))
def test_genexp_x2(): p = Rational(3, 2) e = (2/x + 3/x**p)/(1/x + 1/x**p) assert e.nseries(x, 0, 3) == 3 - sqrt(x) + x + O(sqrt(x)**3)
def test_1484(): assert cos(1+x+x**2).series(x,0,5) == cos(1) - x*sin(1) + x**2*(-sin(1) - \ cos(1)/2) + x**3*(-cos(1) + sin(1)/6) + \ x**4*(-11*cos(1)/24 + sin(1)/2) + O(x**5)
def test_mul_1(): assert (x*ln(2 + x)).nseries(x, n=5) == x*log(2) + x**2/2 - x**3/8 + \ x**4/24 + O(x**5) assert (x*ln(1 + x)).nseries( x, n=5) == x**2 - x**3/2 + x**4/3 + O(x**5)
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(self.func( 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" nuse = n cf = 1 try: ord = b.as_leading_term(x) cf = C.Order(ord, x).getn() if cf and cf.is_Number: nuse = n + 2 * ceiling(cf) else: cf = 1 except NotImplementedError: pass b_orig, prefactor = b, O(1, x) while prefactor.is_Order: nuse += 1 b = b_orig._eval_nseries(x, n=nuse, 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.is_Order: return 1 / prefactor + rest / prefactor + O(x**n, x) k, l = rest.leadterm(x) if l.is_Rational and l > 0: pass elif l.is_number and l > 0: l = l.evalf() elif l == 0: k = k.simplify() if k == 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) else: raise NotImplementedError() else: raise NotImplementedError() if cf < 0: cf = S.One / abs(cf) try: dn = C.Order(1 / prefactor, x).getn() if dn and dn < 0: pass else: dn = 0 except NotImplementedError: dn = 0 terms = [1 / prefactor] for m in xrange(1, ceiling((n - dn) / l * cf)): 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) terms.append(O(x**n, x)) 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: nuse, denominator = n, O(1, x) while denominator.is_Order: denominator = (b**(-e))._eval_nseries(x, n=nuse, logx=logx) nuse += 1 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 if e.is_real and e.is_positive: lt = b.as_leading_term(x) # Try to correct nuse (= m) guess from: # (lt + rest + O(x**m))**e = # lt**e*(1 + rest/lt + O(x**m)/lt)**e = # lt**e + ... + O(x**m)*lt**(e - 1) = ... + O(x**n) try: cf = C.Order(lt, x).getn() nuse = ceiling(n - cf * (e - 1)) except NotImplementedError: pass 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 ((self.func(lt, e) * self.func( (bs / lt).expand(), e).nseries( x, n=nuse, logx=logx)).expand() + order) if bs.is_Add: from sympy import O # So, bs + O() == terms c = Dummy('c') res = [] for arg in bs.args: if arg.is_Order: arg = c * arg.expr res.append(arg) bs = Add(*res) rv = (bs**e).series(x).subs(c, O(1, x)) rv += order return rv 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 expand_mul(r * b0**e) + order
def test_seriesbug2d(): w = Symbol("w", real=True) e = log(sin(2*w)/w) assert e.series(w, n=5) == log(2) - 2*w**2/3 - 4*w**4/45 + O(w**5)
def test_loggamma(): raises(TypeError, lambda: loggamma(2, 3)) raises(ArgumentIndexError, lambda: loggamma(x).fdiff(2)) assert loggamma(-1) is oo assert loggamma(-2) is oo assert loggamma(0) is oo assert loggamma(1) == 0 assert loggamma(2) == 0 assert loggamma(3) == log(2) assert loggamma(4) == log(6) n = Symbol("n", integer=True, positive=True) assert loggamma(n) == log(gamma(n)) assert loggamma(-n) is oo assert loggamma(n / 2) == log(2**(-n + 1) * sqrt(pi) * gamma(n) / gamma(n / 2 + S.Half)) from sympy import I assert loggamma(oo) is oo assert loggamma(-oo) is zoo assert loggamma(I * oo) is zoo assert loggamma(-I * oo) is zoo assert loggamma(zoo) is zoo assert loggamma(nan) is nan L = loggamma(Rational(16, 3)) E = -5 * log(3) + loggamma(Rational( 1, 3)) + log(4) + log(7) + log(10) + log(13) assert expand_func(L).doit() == E assert L.n() == E.n() L = loggamma(Rational(19, 4)) E = -4 * log(4) + loggamma(Rational( 3, 4)) + log(3) + log(7) + log(11) + log(15) assert expand_func(L).doit() == E assert L.n() == E.n() L = loggamma(Rational(23, 7)) E = -3 * log(7) + log(2) + loggamma(Rational(2, 7)) + log(9) + log(16) assert expand_func(L).doit() == E assert L.n() == E.n() L = loggamma(Rational(19, 4) - 7) E = -log(9) - log(5) + loggamma(Rational(3, 4)) + 3 * log(4) - 3 * I * pi assert expand_func(L).doit() == E assert L.n() == E.n() L = loggamma(Rational(23, 7) - 6) E = -log(19) - log(12) - log(5) + loggamma(Rational( 2, 7)) + 3 * log(7) - 3 * I * pi assert expand_func(L).doit() == E assert L.n() == E.n() assert loggamma(x).diff(x) == polygamma(0, x) s1 = loggamma(1 / (x + sin(x)) + cos(x)).nseries(x, n=4) s2 = (-log(2*x) - 1)/(2*x) - log(x/pi)/2 + (4 - log(2*x))*x/24 + O(x**2) + \ log(x)*x**2/2 assert (s1 - s2).expand(force=True).removeO() == 0 s1 = loggamma(1 / x).series(x) s2 = (1/x - S.Half)*log(1/x) - 1/x + log(2*pi)/2 + \ x/12 - x**3/360 + x**5/1260 + O(x**7) assert ((s1 - s2).expand(force=True)).removeO() == 0 assert loggamma(x).rewrite('intractable') == log(gamma(x)) s1 = loggamma(x).series(x) assert s1 == -log(x) - EulerGamma*x + pi**2*x**2/12 + x**3*polygamma(2, 1)/6 + \ pi**4*x**4/360 + x**5*polygamma(4, 1)/120 + O(x**6) assert s1 == loggamma(x).rewrite('intractable').series(x) assert conjugate(loggamma(x)) == loggamma(conjugate(x)) assert conjugate(loggamma(0)) is oo assert conjugate(loggamma(1)) == loggamma(conjugate(1)) assert conjugate(loggamma(-oo)) == conjugate(zoo) assert loggamma(Symbol('v', positive=True)).is_real is True assert loggamma(Symbol('v', zero=True)).is_real is False assert loggamma(Symbol('v', negative=True)).is_real is False assert loggamma(Symbol('v', nonpositive=True)).is_real is False assert loggamma(Symbol('v', nonnegative=True)).is_real is None assert loggamma(Symbol('v', imaginary=True)).is_real is None assert loggamma(Symbol('v', real=True)).is_real is None assert loggamma(Symbol('v')).is_real is None assert loggamma(S.Half).is_real is True assert loggamma(0).is_real is False assert loggamma(Rational(-1, 2)).is_real is False assert loggamma(I).is_real is None assert loggamma(2 + 3 * I).is_real is None def tN(N, M): assert loggamma(1 / x)._eval_nseries(x, n=N).getn() == M tN(0, 0) tN(1, 1) tN(2, 3) tN(3, 3) tN(4, 5) tN(5, 5)
def test_expbug5(): assert exp(log(1 + x)/x).nseries(x, n=3) == exp(1) + -exp(1)*x/2 + O(x**2) assert exp(O(x)).nseries(x, 0, 2) == 1 + O(x)
def test_diff(): assert O(x**2).diff(x) == O(x)