from typing import Any, Literal, Mapping, Optional, Sequence, Tuple, Union

import mpmath.libmp as libmp
from mpmath import inf as mpmath_inf
from mpmath.ctx_mp_python import mpnumeric
from sympy.core import Expr
from sympy.core.symbol import Symbol

from .compatibility import SYMPY_INTS

def bitcount(n: int) -> int: ...

INF: float = ...
MINUS_INF: float = ...
DEFAULT_MAXPREC: float = ...

class PrecisionExhausted(ArithmeticError): ...

_MPF = Tuple[int, int, int, int]
_RESULT = Tuple[Optional[_MPF], Optional[_MPF], Optional[int], Optional[int]]

def _create_evalf_table() -> None: ...

def fastlog(x: _MPF) -> int: ...
def pure_complex(v: Expr, or_real: bool = ...) -> Tuple[Expr, Expr]: ...
def scaled_zero(
    mag: Union[int, Tuple[Union[int, Sequence[int]], int, int, int], SYMPY_INTS],
    sign: Literal[1, -1] = ...,
) -> _MPF: ...
def complex_accuracy(result: _RESULT) -> int: ...
def get_integer_part(
    expr: Expr, no: Literal[1, -1], options: Mapping[str, Any], return_ints: bool = ...
) -> _RESULT: ...
def add_terms(terms: Expr, prec: int, target_prec: int) -> Any: ...
def evalf_trig(v: Expr, prec: int, options: Mapping[str, Any]) -> _RESULT: ...
def evalf_log(expr: Expr, prec: int, options: Mapping[str, Any]) -> _RESULT: ...
def evalf_atan(v: Expr, prec: int, options: Mapping[str, Any]) -> _RESULT: ...
def evalf_piecewise(expr: Expr, prec: int, options: Mapping[str, Any]) -> _RESULT: ...
def evalf_bernoulli(expr: Expr, prec: int, options: Mapping[str, Any]) -> _RESULT: ...
def as_mpmath(x: Expr, prec: int, options: Mapping[str, Any]) -> mpnumeric: ...
def do_integral(expr: Expr, prec: int, options: Mapping[str, Any]) -> _RESULT: ...
def evalf_integral(expr: Expr, prec: int, options: Mapping[str, Any]) -> _RESULT: ...
def check_convergence(
    numer: Expr, denom: Expr, n: Expr
) -> Tuple[int, Optional[Expr], Optional[Expr]]: ...
def hypsum(expr: Expr, n: Expr, start: Expr, prec: int) -> _MPF: ...
def evalf_prod(expr: Expr, prec: int, options: Mapping[str, Any]) -> _RESULT: ...
def evalf_sum(expr: Expr, prec: int, options: Mapping[str, Any]) -> _RESULT: ...
def evalf_symbol(x: Expr, prec: int, options: Mapping[str, Any]) -> _RESULT: ...
def evalf(x: Basic, prec: int, options: Mapping[str, Any]) -> _RESULT: ...

class EvalfMixin:
    def evalf(
        self,
        n: int = ...,
        subs: Optional[Mapping[Symbol, Expr]] = ...,
        maxn: Optional[int] = ...,
        chop: Optional[Union[int, bool]] = ...,
        strict: Optional[bool] = ...,
        quad: Optional[str] = ...,
        verbose: Optional[bool] = ...,
    ) -> Optional[_MPF]: ...

def N(x: Expr, n: int = ..., **options: Any): ...
