Source code for sympy.functions.elementary.integers

from __future__ import print_function, division

from sympy.core.singleton import S
from sympy.core.function import Function
from sympy.core import Add
from sympy.core.evalf import get_integer_part, PrecisionExhausted
from sympy.core.numbers import Integer
from sympy.core.relational import Gt, Lt, Ge, Le
from sympy.core.symbol import Symbol


###############################################################################
######################### FLOOR and CEILING FUNCTIONS #########################
###############################################################################


[docs]class RoundFunction(Function): """The base class for rounding functions.""" @classmethod def eval(cls, arg): from sympy import im if arg.is_integer: return arg if arg.is_imaginary or (S.ImaginaryUnit*arg).is_real: i = im(arg) if not i.has(S.ImaginaryUnit): return cls(i)*S.ImaginaryUnit return cls(arg, evaluate=False) v = cls._eval_number(arg) if v is not None: return v # Integral, numerical, symbolic part ipart = npart = spart = S.Zero # Extract integral (or complex integral) terms terms = Add.make_args(arg) for t in terms: if t.is_integer or (t.is_imaginary and im(t).is_integer): ipart += t elif t.has(Symbol): spart += t else: npart += t if not (npart or spart): return ipart # Evaluate npart numerically if independent of spart if npart and ( not spart or npart.is_real and (spart.is_imaginary or (S.ImaginaryUnit*spart).is_real) or npart.is_imaginary and spart.is_real): try: r, i = get_integer_part( npart, cls._dir, {}, return_ints=True) ipart += Integer(r) + Integer(i)*S.ImaginaryUnit npart = S.Zero except (PrecisionExhausted, NotImplementedError): pass spart += npart if not spart: return ipart elif spart.is_imaginary or (S.ImaginaryUnit*spart).is_real: return ipart + cls(im(spart), evaluate=False)*S.ImaginaryUnit else: return ipart + cls(spart, evaluate=False) def _eval_is_finite(self): return self.args[0].is_finite def _eval_is_real(self): return self.args[0].is_real def _eval_is_integer(self): return self.args[0].is_real
[docs]class floor(RoundFunction): """ Floor is a univariate function which returns the largest integer value not greater than its argument. However this implementation generalizes floor to complex numbers. Examples ======== >>> from sympy import floor, E, I, Float, Rational >>> floor(17) 17 >>> floor(Rational(23, 10)) 2 >>> floor(2*E) 5 >>> floor(-Float(0.567)) -1 >>> floor(-I/2) -I See Also ======== sympy.functions.elementary.integers.ceiling References ========== .. [1] "Concrete mathematics" by Graham, pp. 87 .. [2] http://mathworld.wolfram.com/FloorFunction.html """ _dir = -1 @classmethod def _eval_number(cls, arg): if arg.is_Number: if arg.is_Rational: return Integer(arg.p // arg.q) elif arg.is_Float: return Integer(int(arg.floor())) else: return arg if arg.is_NumberSymbol: return arg.approximation_interval(Integer)[0] def _eval_nseries(self, x, n, logx): r = self.subs(x, 0) args = self.args[0] args0 = args.subs(x, 0) if args0 == r: direction = (args - args0).leadterm(x)[0] if direction.is_positive: return r else: return r - 1 else: return r def __le__(self, other): if self.args[0] == other and other.is_real: return S.true return Le(self, other, evaluate=False) def __gt__(self, other): if self.args[0] == other and other.is_real: return S.false return Gt(self, other, evaluate=False)
[docs]class ceiling(RoundFunction): """ Ceiling is a univariate function which returns the smallest integer value not less than its argument. Ceiling function is generalized in this implementation to complex numbers. Examples ======== >>> from sympy import ceiling, E, I, Float, Rational >>> ceiling(17) 17 >>> ceiling(Rational(23, 10)) 3 >>> ceiling(2*E) 6 >>> ceiling(-Float(0.567)) 0 >>> ceiling(I/2) I See Also ======== sympy.functions.elementary.integers.floor References ========== .. [1] "Concrete mathematics" by Graham, pp. 87 .. [2] http://mathworld.wolfram.com/CeilingFunction.html """ _dir = 1 @classmethod def _eval_number(cls, arg): if arg.is_Number: if arg.is_Rational: return -Integer(-arg.p // arg.q) elif arg.is_Float: return Integer(int(arg.ceiling())) else: return arg if arg.is_NumberSymbol: return arg.approximation_interval(Integer)[1] def _eval_nseries(self, x, n, logx): r = self.subs(x, 0) args = self.args[0] args0 = args.subs(x, 0) if args0 == r: direction = (args - args0).leadterm(x)[0] if direction.is_positive: return r + 1 else: return r else: return r def __lt__(self, other): if self.args[0] == other and other.is_real: return S.false return Lt(self, other, evaluate=False) def __ge__(self, other): if self.args[0] == other and other.is_real: return S.true return Ge(self, other, evaluate=False)
[docs]class frac(Function): r"""Represents the fractional part of x For real numbers it is defined [1]_ as .. math:: x - \lfloor{x}\rfloor Examples ======== >>> from sympy import Symbol, frac, Rational, floor, ceiling, I >>> frac(Rational(4, 3)) 1/3 >>> frac(-Rational(4, 3)) 2/3 returns zero for integer arguments >>> n = Symbol('n', integer=True) >>> frac(n) 0 rewrite as floor >>> x = Symbol('x') >>> frac(x).rewrite(floor) x - floor(x) for complex arguments >>> r = Symbol('r', real=True) >>> t = Symbol('t', real=True) >>> frac(t + I*r) I*frac(r) + frac(t) See Also ======== sympy.functions.elementary.integers.floor sympy.functions.elementary.integers.ceiling References =========== .. [1] http://en.wikipedia.org/wiki/Fractional_part .. [2] http://mathworld.wolfram.com/FractionalPart.html """ @classmethod def eval(cls, arg): from sympy import AccumBounds, im def _eval(arg): if arg is S.Infinity or arg is S.NegativeInfinity: return AccumBounds(0, 1) if arg.is_integer: return S.Zero if arg.is_number: if arg is S.NaN: return S.NaN elif arg is S.ComplexInfinity: return None else: return arg - floor(arg) return cls(arg, evaluate=False) terms = Add.make_args(arg) real, imag = S.Zero, S.Zero for t in terms: # Two checks are needed for complex arguments # see issue-7649 for details if t.is_imaginary or (S.ImaginaryUnit*t).is_real: i = im(t) if not i.has(S.ImaginaryUnit): imag += i else: real += t else: real += t real = _eval(real) imag = _eval(imag) return real + S.ImaginaryUnit*imag def _eval_rewrite_as_floor(self, arg): return arg - floor(arg)