def __new__(cls, expr, x, xlim, direction='<', **assumptions): expr = Basic.sympify(expr) x = Basic.sympify(x) xlim = Basic.sympify(xlim) if not isinstance(x, Basic.Symbol): raise ValueError("Limit 2nd argument must be Symbol instance (got %s)" % (x)) assert isinstance(x, Basic.Symbol),`x` if not expr.has(x): return expr if isinstance(xlim, Basic.NegativeInfinity): xoo = InfLimit.limit_process_symbol() if expr.has(xoo): xoo = Basic.Symbol(x.name + '_oo',dummy=True,positive=True,unbounded=True) return InfLimit(expr.subs(x,-xoo), xoo) if isinstance(xlim, Basic.Infinity): return InfLimit(expr, x) else: xoo = InfLimit.limit_process_symbol() if expr.has(xoo): xoo = Basic.Symbol(x.name + '_oo',dummy=True,positive=True,unbounded=True) if direction=='<': return InfLimit(expr.subs(x, xlim+1/xoo), xoo) elif direction=='>': return InfLimit(expr.subs(x, xlim-1/xoo), xoo) else: raise ValueError("Limit direction must be < or > (got %s)" % (direction)) # XXX This code is currently unreachable obj = Basic.__new__(cls, expr, x, xlim, **assumptions) obj.direction = direction return obj
def subs(self, old, new): old = Basic.sympify(old) if old==self.func: arg = self[0] new = Basic.sympify(new) return new(arg.subs(old, new)) return self
def _eval_apply(cls, x, k): x = Basic.sympify(x) k = Basic.sympify(k) if isinstance(x, Basic.NaN): return S.NaN elif isinstance(k, Basic.Integer): if isinstance(k, Basic.NaN): return S.NaN elif isinstance(k, Basic.Zero): return S.One else: result = S.One if k.is_positive: if isinstance(x, Basic.Infinity): return S.Infinity elif isinstance(x, Basic.NegativeInfinity): if k.is_odd: return S.NegativeInfinity else: return S.Infinity else: return reduce(lambda r, i: r*(x-i), xrange(0, int(k)), 1) else: if isinstance(x, Basic.Infinity): return S.Infinity elif isinstance(x, Basic.NegativeInfinity): return S.Infinity else: return 1/reduce(lambda r, i: r*(x+i), xrange(1, abs(int(k))+1), 1)
def __new__(cls, center, hradius, vradius, **kwargs): hradius = Basic.sympify(hradius) vradius = Basic.sympify(vradius) if not isinstance(center, Point): raise TypeError("center must be be a Point") if hradius == vradius: return Circle(center, hradius, **kwargs) return GeometryEntity.__new__(cls, center, hradius, vradius, **kwargs)
def __new__(cls, *args, **kwargs): if isinstance(args[0], (tuple, list, set)): coords = tuple([Basic.sympify(x) for x in args[0]]) else: coords = tuple([Basic.sympify(x) for x in args]) if len(coords) != 2: raise NotImplementedError("Only two dimensional points currently supported") return GeometryEntity.__new__(cls, *coords)
def __new__(cls, expr, x): expr = orig_expr = Basic.sympify(expr) orig_x = Basic.sympify(x) assert isinstance(orig_x,Basic.Symbol),`orig_x` # handle trivial results if orig_expr==orig_x: return S.Infinity elif not orig_expr.has(orig_x): return orig_expr x = InfLimit.limit_process_symbol() if not orig_expr.has(x): expr = orig_expr.subs(orig_x, x) elif orig_x==x: expr = orig_expr else: x = Basic.Symbol(orig_x.name + '_oo', dummy=True, unbounded=True, positive=True) expr = orig_expr.subs(orig_x, x) result = None if hasattr(expr,'_eval_inflimit'): # support for callbacks result = getattr(expr,'_eval_inflimit')(x) elif isinstance(expr, Basic.Add): result, factors = expr.as_coeff_factors(x) for f in factors: result += f.inflimit(x) if isinstance(result, Basic.NaN): result = None break elif isinstance(expr, Basic.Mul): result, terms = expr.as_coeff_terms(x) for t in terms: result *= t.inflimit(x) if isinstance(result, Basic.NaN): result = None break elif isinstance(expr, Basic.Pow): if not expr.exp.has(x): result = expr.base.inflimit(x) ** expr.exp elif not expr.base.has(x): result = expr.base ** expr.exp.inflimit(x) else: result = Basic.exp(expr.exp * Basic.log(expr.base)).inflimit(x) elif isinstance(expr, Basic.Function): # warning: assume that # lim_x f(g1(x),g2(x),..) = f(lim_x g1(x), lim_x g2(x)) # if this is incorrect, one must define f._eval_inflimit(x) method result = expr.func(*[a.inflimit(x) for a in expr]) if result is None: result = mrv_inflimit(expr, x) return result
def taylor_term(self, n, x, *previous_terms): if n == 0: return 1 / Basic.sympify(x) elif n < 0 or n % 2 == 0: return S.Zero else: x = Basic.sympify(x) B = S.Bernoulli(n+1) F = Basic.Factorial(n+1) return 2**(n+1) * B/F * x**n
def _eval_apply(self, arg, base=None, **fixme): if base is not None: base = Basic.sympify(base) if not isinstance(base, Basic.Exp1): return self(arg)/self(base) arg = Basic.sympify(arg) if isinstance(arg, Basic.Number): if isinstance(arg, Basic.Zero): return S.NegativeInfinity elif isinstance(arg, Basic.One): return S.Zero elif isinstance(arg, Basic.Infinity): return S.Infinity elif isinstance(arg, Basic.NegativeInfinity): return S.Infinity elif isinstance(arg, Basic.NaN): return S.NaN elif arg.is_negative: return S.Pi * S.ImaginaryUnit + self(-arg) elif isinstance(arg, Basic.Exp1): return S.One #this doesn't work due to caching: :( #elif isinstance(arg, exp) and arg[0].is_real: #using this one instead: elif isinstance(arg, exp): return arg[0] #this shouldn't happen automatically (see the issue 252): #elif isinstance(arg, Basic.Pow): # if isinstance(arg.exp, Basic.Number) or \ # isinstance(arg.exp, Basic.NumberSymbol) or arg.exp.is_number: # return arg.exp * self(arg.base) #elif isinstance(arg, Basic.Mul) and arg.is_real: # return Basic.Add(*[self(a) for a in arg]) elif not isinstance(arg, Basic.Add): coeff = arg.as_coefficient(S.ImaginaryUnit) if coeff is not None: if isinstance(coeff, Basic.Infinity): return S.Infinity elif isinstance(coeff, Basic.NegativeInfinity): return S.Infinity elif isinstance(coeff, Basic.Rational): if coeff.is_nonnegative: return S.Pi * S.ImaginaryUnit * S.Half + self(coeff) else: return -S.Pi * S.ImaginaryUnit * S.Half + self(-coeff)
def _eval_apply(self, arg): arg = Basic.sympify(arg) if isinstance(arg, Basic.NaN): return S.NaN elif arg.is_real: return arg else: if not isinstance(arg, Basic.Add): arg = [arg] included, reverted, excluded = [], [], [] for term in arg: coeff = term.as_coefficient(S.ImaginaryUnit) if coeff is not None: if not coeff.is_real: reverted.append(coeff) elif not term.has(S.ImaginaryUnit) and term.is_real: excluded.append(term) else: included.append(term) if len(arg[:]) != len(included): a, b, c = map(lambda xs: Basic.Add(*xs), [included, reverted, excluded]) return self(a) - im(b) + c
def _eval_apply(self, arg): #XXX this doesn't work, but it should (see #390): #return arg**S.Half arg = Basic.sympify(arg) if isinstance(arg, Basic.Number): if isinstance(arg, Basic.NaN): return S.NaN if isinstance(arg, Basic.Infinity): return S.Infinity if isinstance(arg, Basic.NegativeInfinity): return S.ImaginaryUnit * S.Infinity if isinstance(arg, Basic.Rational): factors = arg.factors() sqrt_factors = {} eval_factors = {} n = Basic.Integer(1) for k,v in factors.items(): n *= Basic.Integer(k) ** (v//2) if v % 2: n *= Basic.Integer(k) ** S.Half return n return arg ** S.Half if arg.is_nonnegative: coeff, terms = arg.as_coeff_terms() if not isinstance(coeff, Basic.One): return self(coeff) * self(Basic.Mul(*terms)) base, exp = arg.as_base_exp() if isinstance(exp, Basic.Number): if exp == 2: return Basic.abs(base) return base ** (exp/2)
def _eval_apply(cls, n): n = Basic.sympify(n) if isinstance(n, Basic.Number): if isinstance(n, Basic.Zero): return S.One elif isinstance(n, Basic.Integer): if n.is_negative: return S.Zero else: n, result = n.p, 1 if n < 20: for i in range(2, n+1): result *= i else: N, bits = n, 0 while N != 0: if N & 1 == 1: bits += 1 N = N >> 1 result = cls._recursive(n)*2**(n-bits) return Basic.Integer(result) if n.is_integer: if n.is_negative: return S.Zero else: return Basic.gamma(n+1)
def __div__(self, divisor): """ Create a new point where each coordinate in this point is divided by factor. """ divisor = Basic.sympify(divisor) return Point( [x/divisor for x in self] )
def _eval_apply(self, arg): arg = Basic.sympify(arg) if isinstance(arg, Basic.Number): if isinstance(arg, Basic.NaN): return S.NaN elif isinstance(arg, Basic.Infinity): return S.Infinity * S.ImaginaryUnit elif isinstance(arg, Basic.NegativeInfinity): return S.NegativeInfinity * S.ImaginaryUnit elif isinstance(arg, Basic.Zero): return S.Pi*S.ImaginaryUnit / 2 elif isinstance(arg, Basic.One): return S.Zero elif isinstance(arg, Basic.NegativeOne): return S.Pi*S.ImaginaryUnit else: cst_table = { S.Half : S.Pi/3, -S.Half : 2*S.Pi/3, S.Sqrt(2)/2 : S.Pi/4, -S.Sqrt(2)/2 : 3*S.Pi/4, 1/S.Sqrt(2) : S.Pi/4, -1/S.Sqrt(2) : 3*S.Pi/4, S.Sqrt(3)/2 : S.Pi/6, -S.Sqrt(3)/2 : 5*S.Pi/6, } if arg in cst_table: return cst_table[arg]*S.ImaginaryUnit
def __mul__(self, factor): """ Create a new point where each coordinate in this point is multiplied by factor. """ factor = Basic.sympify(factor) return Point( [x*factor for x in self] )
def _eval_apply(self, arg): arg = Basic.sympify(arg) if isinstance(arg, Basic.Number): if isinstance(arg, Basic.NaN): return S.NaN elif isinstance(arg, Basic.Infinity): return S.Zero elif isinstance(arg, Basic.NegativeInfinity): return S.Zero elif isinstance(arg, Basic.Zero): return S.Pi*S.ImaginaryUnit / 2 elif isinstance(arg, Basic.One): return S.Infinity elif isinstance(arg, Basic.NegativeOne): return S.NegativeInfinity elif arg.is_negative: return -self(-arg) else: i_coeff = arg.as_coefficient(S.ImaginaryUnit) if i_coeff is not None: return -S.ImaginaryUnit * S.ACot(i_coeff) else: coeff, terms = arg.as_coeff_terms() if coeff.is_negative: return -self(-arg)
def taylor_term(self, n, x, *previous_terms): if n == 0: return S.Pi*S.ImaginaryUnit / 2 elif n < 0 or n % 2 == 0: return S.Zero else: x = Basic.sympify(x) return x**n / n
def taylor_term(self, n, x, *previous_terms): if n == 0: return S.Pi / 2 # FIX THIS elif n < 0 or n % 2 == 0: return S.Zero else: x = Basic.sympify(x) return (-1)**((n+1)//2) * x**n / n
def taylor_term(self, n, x, *previous_terms): if n<0: return S.Zero if n==0: return S.One x = Basic.sympify(x) if previous_terms: p = previous_terms[-1] if p is not None: return p * x / n return x**n/Basic.Factorial()(n)
def taylor_term(self, n, x, *previous_terms): # of log(1+x) if n<0: return S.Zero x = Basic.sympify(x) if n==0: return x if previous_terms: p = previous_terms[-1] if p is not None: return (-n) * p * x / (n+1) return (1-2*(n%2)) * x**(n+1)/(n+1)
def __new__(self, c, r, n, **kwargs): r = Basic.sympify(r) if not isinstance(c, Point): raise GeometryError("RegularPolygon.__new__ requires c to be a Point instance") if not isinstance(r, Basic): raise GeometryError("RegularPolygon.__new__ requires r to be a number or Basic instance") if n < 3: raise GeometryError("RegularPolygon.__new__ requires n >= 3") obj = GeometryEntity.__new__(self, c, r, n, **kwargs) return obj
def taylor_term(self, n, x, *previous_terms): if n < 0 or n % 2 == 0: return S.Zero else: x = Basic.sympify(x) if len(previous_terms) > 2: p = previous_terms[-2] return p * x**2 / (n*(n-1)) else: return x**(n) / Basic.Factorial(n)
def taylor_term(self, n, x, *previous_terms): if n < 0 or n % 2 == 0: return S.Zero else: x = Basic.sympify(x) k = (n - 1)/2 if len(previous_terms) > 2: return -previous_terms[-2] * x**2 * (n-2)/(n*k) else: return 2*(-1)**k * x**n/(n*Basic.Factorial(k)*Basic.sqrt(S.Pi))
def taylor_term(self, n, x, *previous_terms): if n < 0 or n % 2 == 0: return S.Zero else: x = Basic.sympify(x) a, b = ((n-1)//2), 2**(n+1) B = Basic.bernoulli(n+1) F = Basic.Factorial(n+1) return (-1)**a * b*(b-1) * B/F * x**n
def __add__(self, other): """ Create a new point where each coordinate in this point is increased by the corresponding coordinate in other. """ if isinstance(other, Point): if len(other) == len(self): return Point( [simplify(a+b) for a,b in zip(self, other)] ) else: raise Exception("Points must have the same number of dimensions") else: other = Basic.sympify(other) return Point( [simplify(a+other) for a in self] )
def _eval_apply(cls, arg): arg = Basic.sympify(arg) if arg.is_integer: return arg elif isinstance(arg, Basic.Number): if isinstance(arg, Basic.Infinity): return S.Infinity elif isinstance(arg, Basic.NegativeInfinity): return S.NegativeInfinity elif isinstance(arg, Basic.NaN): return S.NaN elif isinstance(arg, Basic.Integer): return arg elif isinstance(arg, Basic.Rational): return Basic.Integer(arg.p // arg.q) elif isinstance(arg, Basic.Real): return Basic.Integer(int(arg.floor())) elif isinstance(arg, Basic.NumberSymbol): return arg.approximation_interval(Basic.Integer)[0] elif isinstance(arg, Basic.ImaginaryUnit): return S.ImaginaryUnit elif isinstance(arg, Basic.Add): included, excluded = [], [] for term in arg: coeff = term.as_coefficient(S.ImaginaryUnit) if coeff is not None and coeff.is_real: excluded.append(cls(coeff)*S.ImaginaryUnit) elif term.is_real: if term.is_integer: excluded.append(term) else: included.append(term) else: return if excluded: return cls(Basic.Add(*included)) + Basic.Add(*excluded) else: coeff, terms = arg.as_coeff_terms(S.ImaginaryUnit) if not terms and not arg.atoms(type=Basic.Symbol): if arg.is_negative: return -ceiling(-arg) else: return cls(arg.evalf()) elif terms == [ S.ImaginaryUnit ] and coeff.is_real: return cls(coeff)*S.ImaginaryUnit
def taylor_term(self, n, x, *previous_terms): if n < 0 or n % 2 == 0: return S.Zero else: x = Basic.sympify(x) if len(previous_terms) > 2: p = previous_terms[-2] return -p * (n-2)**2/(k*(k-1)) * x**2 else: k = (n - 1) // 2 R = Basic.RisingFactorial(S.Half, k) F = Basic.Factorial(k) return (-1)**k * R / F * x**n / n
def __new__(cls, *args, **kwargs): c, r = None, None if len(args) == 3 and isinstance(args[0], Point): from polygon import Triangle t = Triangle(args[0], args[1], args[2]) if t.area == 0: raise GeometryError("Cannot construct a circle from three collinear points") c = t.circumcenter r = t.circumradius elif len(args) == 2: # Assume (center, radius) pair c = args[0] r = Basic.sympify(args[1]) if not (c is None or r is None): return GeometryEntity.__new__(cls, c, r, **kwargs) raise GeometryError("Circle.__new__ received unknown arguments")
def _eval_apply(self, arg): arg = Basic.sympify(arg) if isinstance(arg, Basic.Number): if isinstance(arg, Basic.NaN): return S.NaN elif isinstance(arg, Basic.Infinity): return S.One elif isinstance(arg, Basic.NegativeInfinity): return S.NegativeOne elif isinstance(arg, Basic.Zero): return S.Zero elif arg.is_negative: return -self(-arg) elif isinstance(arg, Basic.Mul): coeff, terms = arg.as_coeff_terms() if coeff.is_negative: return -self(-arg)
def _eval_apply(self, arg): arg = Basic.sympify(arg) if isinstance(arg, Basic.Number): if isinstance(arg, Basic.NaN): return S.NaN elif isinstance(arg, Basic.Zero): return S.Zero elif arg.is_negative: return -self(-arg) else: i_coeff = arg.as_coefficient(S.ImaginaryUnit) if i_coeff is not None: return S.ImaginaryUnit * Basic.sinh(i_coeff) else: pi_coeff = arg.as_coefficient(S.Pi) if pi_coeff is not None: if pi_coeff.is_integer: return S.Zero elif isinstance(pi_coeff, Basic.Rational): cst_table = { 2 : S.One, 3 : S.Half*Basic.sqrt(3), 4 : S.Half*Basic.sqrt(2), 6 : S.Half, } try: result = cst_table[pi_coeff.q] if (pi_coeff.p // pi_coeff.q) % 2 == 1: return -result else: return result except KeyError: pass coeff, terms = arg.as_coeff_terms() if coeff.is_negative: return -self(-arg)
def _eval_apply(self, arg): arg = Basic.sympify(arg) if isinstance(arg, Basic.Number): if isinstance(arg, Basic.NaN): return S.NaN #elif isinstance(arg, Basic.Zero): # return S.ComplexInfinity elif arg.is_negative: return -self(-arg) else: i_coeff = arg.as_coefficient(S.ImaginaryUnit) if i_coeff is not None: return -S.ImaginaryUnit * Basic.coth(i_coeff) else: pi_coeff = arg.as_coefficient(S.Pi) if pi_coeff is not None: #if pi_coeff.is_integer: # return S.ComplexInfinity if isinstance(pi_coeff, Basic.Rational): cst_table = { 2 : S.Zero, 3 : 1 / Basic.sqrt(3), 4 : S.One, 6 : Basic.sqrt(3) } try: result = cst_table[pi_coeff.q] if (2*pi_coeff.p // pi_coeff.q) % 4 in (1, 3): return -result else: return result except KeyError: pass coeff, terms = arg.as_coeff_terms() if coeff.is_negative: return -self(-arg)