| # mypy: allow-untyped-defs |
| import mpmath.libmp as mlib # type: ignore[import-untyped] |
| import sympy |
| from sympy import Expr |
| from sympy.core.decorators import _sympifyit |
| from sympy.core.expr import AtomicExpr |
| from sympy.core.numbers import Number |
| from sympy.core.parameters import global_parameters |
| from sympy.core.singleton import S, Singleton |
| |
| |
| class IntInfinity(Number, metaclass=Singleton): |
| r"""Positive integer infinite quantity. |
| |
| Integer infinity is a value in an extended integers which |
| is greater than all other integers. We distinguish it from |
| sympy's existing notion of infinity in that it reports that |
| it is_integer. |
| |
| Infinity is a singleton, and can be accessed by ``S.IntInfinity``, |
| or can be imported as ``int_oo``. |
| """ |
| |
| # NB: We can't actually mark this as infinite, as integer and infinite are |
| # inconsistent assumptions in sympy. We also report that we are complex, |
| # different from sympy.oo |
| |
| is_integer = True |
| is_commutative = True |
| is_number = True |
| is_extended_real = True |
| is_comparable = True |
| is_extended_positive = True |
| is_prime = False |
| |
| # Ensure we get dispatched to before plain numbers |
| _op_priority = 100.0 |
| |
| __slots__ = () |
| |
| def __new__(cls): |
| return AtomicExpr.__new__(cls) |
| |
| def _sympystr(self, printer): |
| return "int_oo" |
| |
| def _eval_subs(self, old, new): |
| if self == old: |
| return new |
| |
| # We could do these, not sure about it |
| """ |
| def _eval_evalf(self, prec=None): |
| return Float('inf') |
| |
| def evalf(self, prec=None, **options): |
| return self._eval_evalf(prec) |
| """ |
| |
| @_sympifyit("other", NotImplemented) |
| def __add__(self, other): |
| if isinstance(other, Number) and global_parameters.evaluate: |
| if other in (S.Infinity, S.NegativeInfinity): |
| return other |
| if other in (S.NegativeIntInfinity, S.NaN): |
| return S.NaN |
| return self |
| return Number.__add__(self, other) |
| |
| __radd__ = __add__ |
| |
| @_sympifyit("other", NotImplemented) |
| def __sub__(self, other): |
| if isinstance(other, Number) and global_parameters.evaluate: |
| if other is S.Infinity: |
| return S.NegativeInfinity |
| if other is S.NegativeInfinity: |
| return S.Infinity |
| if other in (S.IntInfinity, S.NaN): |
| return S.NaN |
| return self |
| return Number.__sub__(self, other) |
| |
| @_sympifyit("other", NotImplemented) |
| def __rsub__(self, other): |
| return (-self).__add__(other) |
| |
| @_sympifyit("other", NotImplemented) |
| def __mul__(self, other): |
| if isinstance(other, Number) and global_parameters.evaluate: |
| if other.is_zero or other is S.NaN: |
| return S.NaN |
| if other.is_extended_positive: |
| return self |
| return S.NegativeIntInfinity |
| return Number.__mul__(self, other) |
| |
| __rmul__ = __mul__ |
| |
| @_sympifyit("other", NotImplemented) |
| def __truediv__(self, other): |
| if isinstance(other, Number) and global_parameters.evaluate: |
| if other in ( |
| S.Infinity, |
| S.IntInfinity, |
| S.NegativeInfinity, |
| S.NegativeIntInfinity, |
| S.NaN, |
| ): |
| return S.NaN |
| if other.is_extended_nonnegative: |
| return S.Infinity # truediv produces float |
| return S.NegativeInfinity # truediv produces float |
| return Number.__truediv__(self, other) |
| |
| def __abs__(self): |
| return S.IntInfinity |
| |
| def __neg__(self): |
| return S.NegativeIntInfinity |
| |
| def _eval_power(self, expt): |
| if expt.is_extended_positive: |
| return S.IntInfinity |
| if expt.is_extended_negative: |
| return S.Zero |
| if expt is S.NaN: |
| return S.NaN |
| if expt is S.ComplexInfinity: |
| return S.NaN |
| if expt.is_extended_real is False and expt.is_number: |
| from sympy.functions.elementary.complexes import re |
| |
| expt_real = re(expt) |
| if expt_real.is_positive: |
| return S.ComplexInfinity |
| if expt_real.is_negative: |
| return S.Zero |
| if expt_real.is_zero: |
| return S.NaN |
| |
| return self ** expt.evalf() |
| |
| def _as_mpf_val(self, prec): |
| return mlib.finf |
| |
| def __hash__(self): |
| return super().__hash__() |
| |
| def __eq__(self, other): |
| return other is S.IntInfinity |
| |
| def __ne__(self, other): |
| return other is not S.IntInfinity |
| |
| def __gt__(self, other): |
| if other is S.Infinity: |
| return sympy.false # sympy.oo > int_oo |
| elif other is S.IntInfinity: |
| return sympy.false # consistency with sympy.oo |
| else: |
| return sympy.true |
| |
| def __ge__(self, other): |
| if other is S.Infinity: |
| return sympy.false # sympy.oo > int_oo |
| elif other is S.IntInfinity: |
| return sympy.true # consistency with sympy.oo |
| else: |
| return sympy.true |
| |
| def __lt__(self, other): |
| if other is S.Infinity: |
| return sympy.true # sympy.oo > int_oo |
| elif other is S.IntInfinity: |
| return sympy.false # consistency with sympy.oo |
| else: |
| return sympy.false |
| |
| def __le__(self, other): |
| if other is S.Infinity: |
| return sympy.true # sympy.oo > int_oo |
| elif other is S.IntInfinity: |
| return sympy.true # consistency with sympy.oo |
| else: |
| return sympy.false |
| |
| @_sympifyit("other", NotImplemented) |
| def __mod__(self, other): |
| if not isinstance(other, Expr): |
| return NotImplemented |
| return S.NaN |
| |
| __rmod__ = __mod__ |
| |
| def floor(self): |
| return self |
| |
| def ceiling(self): |
| return self |
| |
| |
| int_oo = S.IntInfinity |
| |
| |
| class NegativeIntInfinity(Number, metaclass=Singleton): |
| """Negative integer infinite quantity. |
| |
| NegativeInfinity is a singleton, and can be accessed |
| by ``S.NegativeInfinity``. |
| |
| See Also |
| ======== |
| |
| IntInfinity |
| """ |
| |
| # Ensure we get dispatched to before plain numbers |
| _op_priority = 100.0 |
| |
| is_integer = True |
| is_extended_real = True |
| is_commutative = True |
| is_comparable = True |
| is_extended_negative = True |
| is_number = True |
| is_prime = False |
| |
| __slots__ = () |
| |
| def __new__(cls): |
| return AtomicExpr.__new__(cls) |
| |
| def _eval_subs(self, old, new): |
| if self == old: |
| return new |
| |
| def _sympystr(self, printer): |
| return "-int_oo" |
| |
| """ |
| def _eval_evalf(self, prec=None): |
| return Float('-inf') |
| |
| def evalf(self, prec=None, **options): |
| return self._eval_evalf(prec) |
| """ |
| |
| @_sympifyit("other", NotImplemented) |
| def __add__(self, other): |
| if isinstance(other, Number) and global_parameters.evaluate: |
| if other is S.Infinity: |
| return S.Infinity |
| if other in (S.IntInfinity, S.NaN): |
| return S.NaN |
| return self |
| return Number.__add__(self, other) |
| |
| __radd__ = __add__ |
| |
| @_sympifyit("other", NotImplemented) |
| def __sub__(self, other): |
| if isinstance(other, Number) and global_parameters.evaluate: |
| if other is S.NegativeInfinity: |
| return S.Infinity |
| if other in (S.NegativeIntInfinity, S.NaN): |
| return S.NaN |
| return self |
| return Number.__sub__(self, other) |
| |
| @_sympifyit("other", NotImplemented) |
| def __rsub__(self, other): |
| return (-self).__add__(other) |
| |
| @_sympifyit("other", NotImplemented) |
| def __mul__(self, other): |
| if isinstance(other, Number) and global_parameters.evaluate: |
| if other.is_zero or other is S.NaN: |
| return S.NaN |
| if other.is_extended_positive: |
| return self |
| return S.IntInfinity |
| return Number.__mul__(self, other) |
| |
| __rmul__ = __mul__ |
| |
| @_sympifyit("other", NotImplemented) |
| def __truediv__(self, other): |
| if isinstance(other, Number) and global_parameters.evaluate: |
| if other in ( |
| S.Infinity, |
| S.IntInfinity, |
| S.NegativeInfinity, |
| S.NegativeIntInfinity, |
| S.NaN, |
| ): |
| return S.NaN |
| if other.is_extended_nonnegative: |
| return self |
| return S.Infinity # truediv returns float |
| return Number.__truediv__(self, other) |
| |
| def __abs__(self): |
| return S.IntInfinity |
| |
| def __neg__(self): |
| return S.IntInfinity |
| |
| def _eval_power(self, expt): |
| if expt.is_number: |
| if expt in ( |
| S.NaN, |
| S.Infinity, |
| S.NegativeInfinity, |
| S.IntInfinity, |
| S.NegativeIntInfinity, |
| ): |
| return S.NaN |
| |
| if isinstance(expt, sympy.Integer) and expt.is_extended_positive: |
| if expt.is_odd: |
| return S.NegativeIntInfinity |
| else: |
| return S.IntInfinity |
| |
| inf_part = S.IntInfinity**expt |
| s_part = S.NegativeOne**expt |
| if inf_part == 0 and s_part.is_finite: |
| return inf_part |
| if ( |
| inf_part is S.ComplexInfinity |
| and s_part.is_finite |
| and not s_part.is_zero |
| ): |
| return S.ComplexInfinity |
| return s_part * inf_part |
| |
| def _as_mpf_val(self, prec): |
| return mlib.fninf |
| |
| def __hash__(self): |
| return super().__hash__() |
| |
| def __eq__(self, other): |
| return other is S.NegativeIntInfinity |
| |
| def __ne__(self, other): |
| return other is not S.NegativeIntInfinity |
| |
| def __gt__(self, other): |
| if other is S.NegativeInfinity: |
| return sympy.true # -sympy.oo < -int_oo |
| elif other is S.NegativeIntInfinity: |
| return sympy.false # consistency with sympy.oo |
| else: |
| return sympy.false |
| |
| def __ge__(self, other): |
| if other is S.NegativeInfinity: |
| return sympy.true # -sympy.oo < -int_oo |
| elif other is S.NegativeIntInfinity: |
| return sympy.true # consistency with sympy.oo |
| else: |
| return sympy.false |
| |
| def __lt__(self, other): |
| if other is S.NegativeInfinity: |
| return sympy.false # -sympy.oo < -int_oo |
| elif other is S.NegativeIntInfinity: |
| return sympy.false # consistency with sympy.oo |
| else: |
| return sympy.true |
| |
| def __le__(self, other): |
| if other is S.NegativeInfinity: |
| return sympy.false # -sympy.oo < -int_oo |
| elif other is S.NegativeIntInfinity: |
| return sympy.true # consistency with sympy.oo |
| else: |
| return sympy.true |
| |
| @_sympifyit("other", NotImplemented) |
| def __mod__(self, other): |
| if not isinstance(other, Expr): |
| return NotImplemented |
| return S.NaN |
| |
| __rmod__ = __mod__ |
| |
| def floor(self): |
| return self |
| |
| def ceiling(self): |
| return self |
| |
| def as_powers_dict(self): |
| return {S.NegativeOne: 1, S.IntInfinity: 1} |