<commit_before>"""
There are three types of functions implemented in SymPy:

    1) defined functions (in the sense that they can be evaluated) like
       exp or sin; they have a name and a body:
           f = exp
    2) undefined function which have a name but no body. Undefined
       functions can be defined using a Function class as follows:
           f = Function('f')
       (the result will be a Function instance)
    3) anonymous function (or lambda function) which have a body (defined
       with dummy variables) but have no name:
           f = Lambda(x, exp(x)*x)
           f = Lambda((x, y), exp(x)*y)
    The fourth type of functions are composites, like (sin + cos)(x); these work in
    SymPy core, but are not yet part of SymPy.

    Examples
    ========

    >>> import sympy
    >>> f = sympy.Function("f")
    >>> from sympy.abc import x
    >>> f(x)
    f(x)
    >>> print(sympy.srepr(f(x).func))
    Function('f')
    >>> f(x).args
    (x,)

"""
from __future__ import print_function, division

from .add import Add
from .assumptions import ManagedProperties
from .basic import Basic
from .cache import cacheit
from .compatibility import iterable, is_sequence, as_int, ordered
from .core import BasicMeta, C
from .decorators import _sympifyit
from .expr import Expr, AtomicExpr
from .numbers import Rational, Float
from .rules import Transform
from .singleton import S
from .sympify import sympify

from sympy.core.containers import Tuple, Dict
from sympy.core.logic import fuzzy_and
from sympy.core.compatibility import string_types, with_metaclass, xrange
from sympy.utilities import default_sort_key
from sympy.utilities.iterables import uniq

from sympy import mpmath
import sympy.mpmath.libmp as mlib


def _coeff_isneg(a):
    """Return True if the leading Number is negative.

    Examples
    ========

    >>> from sympy.core.function import _coeff_isneg
    >>> from sympy import S, Symbol, oo, pi
    >>> _coeff_isneg(-3*pi)
    True
    >>> _coeff_isneg(S(3))
    False
    >>> _coeff_isneg(-oo)
    True
    >>> _coeff_isneg(Symbol('n', negative=True)) # coeff is 1
    False

    """

    if a.is_Mul:
        a = a.args[0]
    return a.is_Number and a.is_negative


class PoleError(Exception):
    pass


class ArgumentIndexError(ValueError):
    def __str__(self):
        return ("Invalid operation with argument number %s for Function %s" %
               (self.args[1], self.args[0]))


class FunctionClass(with_metaclass(BasicMeta, ManagedProperties)):
    """
    Base class for function classes. FunctionClass is a subclass of type.

    Use Function('<function name>' [ , signature ]) to create
    undefined function classes.
    """
    _new = type.__new__

    def __init__(cls, *args, **kwargs):
        nargs = kwargs.pop('nargs', cls.__dict__.get('nargs', None))
        super(FunctionClass, cls).__init__(args, kwargs)

        # Canonicalize nargs here; change to set in nargs.
        if type(nargs) is not property:
            if is_sequence(nargs):
                nargs = tuple(ordered(set(nargs)))
            elif nargs is not None:
                nargs = (as_int(nargs),)
            cls._nargs = nargs  # convert to set in nargs
        else:
            pass  # Application and WildFunction pass this way

    @property
    def nargs(self):
        """Return a set of the allowed number of arguments for the function.

        Examples
        ========

        >>> from sympy.core.function import Function
        >>> from sympy.abc import x, y
        >>> f = Function('f')

        If the function can take any number of arguments, the set of whole
        numbers is returned:

        >>> f=Function('f')
        >>> f.nargs
        Naturals0()
        >>> f(1).nargs
        Naturals0()
        >>> f(1, 2).nargs
        Naturals0()

        If the function was initialized to accept one or more arguments, a
        corresponding set will be returned:

        >>> f = Function('f', nargs=1)
        >>> f.nargs
        {1}
        >>> f(1).nargs
        {1}
        >>> g = Function('g', nargs=(2, 1))
        >>> g.nargs
        {1, 2}

        """
        from sympy.sets.fancysets import Naturals0
        from sympy.core.sets import FiniteSet
        # XXX it would be nice to handle this in __init__ but there are import
        # problems with trying to import FiniteSet there
        return FiniteSet(self._nargs) if self._nargs else Naturals0()

    def __repr__(cls):
        return cls.__name__


class Application(with_metaclass(FunctionClass, Basic)):
    """
    Base class for applied functions.

    Instances of Application represent the result of applying an application of
    any type to any object.
    """

    is_Function = True

    @cacheit
    def __new__(cls, *args, **options):
        from sympy.sets.fancysets import Naturals0
        from sympy.core.sets import FiniteSet
        args = list(map(sympify, args))
        evaluate = options.pop('evaluate', True)
        nargs = options.pop('nargs', None)
        if options:
            raise ValueError("Unknown options: %s" % options)

        if evaluate:
            evaluated = cls.eval(*args)
            if evaluated is not None:
                return evaluated

        obj = super(Application, cls).__new__(cls, *args, **options)
        try:
            obj.nargs = FiniteSet(obj.nargs) if obj.nargs else Naturals0()
        except AttributeError:
            obj._nargs = FiniteSet(obj._nargs) if obj._nargs else Naturals0()
        return obj

    @property
    def nargs(obj):
        from sympy.core.sets import FiniteSet, Set
        if isinstance(obj._nargs, Set):
            return obj._nargs
        return FiniteSet(obj._nargs)

    @classmethod
    def eval(cls, *args):
        """
        Returns a canonical form of cls applied to arguments args.

        The eval() method is called when the class cls is about to be
        instantiated and it should return either some simplified instance
        (possible of some other class), or if the class cls should be
        unmodified, return None.

        Examples of eval() for the function "sign"
        ---------------------------------------------

        @classmethod<commit_msg>handle Application.nargs at instantiation<commit_after>"""
There are three types of functions implemented in SymPy:

    1) defined functions (in the sense that they can be evaluated) like
       exp or sin; they have a name and a body:
           f = exp
    2) undefined function which have a name but no body. Undefined
       functions can be defined using a Function class as follows:
           f = Function('f')
       (the result will be a Function instance)
    3) anonymous function (or lambda function) which have a body (defined
       with dummy variables) but have no name:
           f = Lambda(x, exp(x)*x)
           f = Lambda((x, y), exp(x)*y)
    The fourth type of functions are composites, like (sin + cos)(x); these work in
    SymPy core, but are not yet part of SymPy.

    Examples
    ========

    >>> import sympy
    >>> f = sympy.Function("f")
    >>> from sympy.abc import x
    >>> f(x)
    f(x)
    >>> print(sympy.srepr(f(x).func))
    Function('f')
    >>> f(x).args
    (x,)

"""
from __future__ import print_function, division

from .add import Add
from .assumptions import ManagedProperties
from .basic import Basic
from .cache import cacheit
from .compatibility import iterable, is_sequence, as_int, ordered
from .core import BasicMeta, C
from .decorators import _sympifyit
from .expr import Expr, AtomicExpr
from .numbers import Rational, Float
from .rules import Transform
from .singleton import S
from .sympify import sympify

from sympy.core.containers import Tuple, Dict
from sympy.core.logic import fuzzy_and
from sympy.core.compatibility import string_types, with_metaclass, xrange
from sympy.utilities import default_sort_key
from sympy.utilities.iterables import uniq

from sympy import mpmath
import sympy.mpmath.libmp as mlib


def _coeff_isneg(a):
    """Return True if the leading Number is negative.

    Examples
    ========

    >>> from sympy.core.function import _coeff_isneg
    >>> from sympy import S, Symbol, oo, pi
    >>> _coeff_isneg(-3*pi)
    True
    >>> _coeff_isneg(S(3))
    False
    >>> _coeff_isneg(-oo)
    True
    >>> _coeff_isneg(Symbol('n', negative=True)) # coeff is 1
    False

    """

    if a.is_Mul:
        a = a.args[0]
    return a.is_Number and a.is_negative


class PoleError(Exception):
    pass


class ArgumentIndexError(ValueError):
    def __str__(self):
        return ("Invalid operation with argument number %s for Function %s" %
               (self.args[1], self.args[0]))


class FunctionClass(with_metaclass(BasicMeta, ManagedProperties)):
    """
    Base class for function classes. FunctionClass is a subclass of type.

    Use Function('<function name>' [ , signature ]) to create
    undefined function classes.
    """
    _new = type.__new__

    def __init__(cls, *args, **kwargs):
        nargs = kwargs.pop('nargs', cls.__dict__.get('nargs', None))
        super(FunctionClass, cls).__init__(args, kwargs)

        # Canonicalize nargs here; change to set in nargs.
        if type(nargs) is not property:
            if is_sequence(nargs):
                nargs = tuple(ordered(set(nargs)))
            elif nargs is not None:
                nargs = (as_int(nargs),)
            cls._nargs = nargs  # convert to set in nargs
        else:
            pass  # Application and WildFunction pass this way

    @property
    def nargs(self):
        """Return a set of the allowed number of arguments for the function.

        Examples
        ========

        >>> from sympy.core.function import Function
        >>> from sympy.abc import x, y
        >>> f = Function('f')

        If the function can take any number of arguments, the set of whole
        numbers is returned:

        >>> f=Function('f')
        >>> f.nargs
        Naturals0()
        >>> f(1).nargs
        Naturals0()
        >>> f(1, 2).nargs
        Naturals0()

        If the function was initialized to accept one or more arguments, a
        corresponding set will be returned:

        >>> f = Function('f', nargs=1)
        >>> f.nargs
        {1}
        >>> f(1).nargs
        {1}
        >>> g = Function('g', nargs=(2, 1))
        >>> g.nargs
        {1, 2}

        """
        from sympy.sets.fancysets import Naturals0
        from sympy.core.sets import FiniteSet
        # XXX it would be nice to handle this in __init__ but there are import
        # problems with trying to import FiniteSet there
        return FiniteSet(self._nargs) if self._nargs else Naturals0()

    def __repr__(cls):
        return cls.__name__


class Application(with_metaclass(FunctionClass, Basic)):
    """
    Base class for applied functions.

    Instances of Application represent the result of applying an application of
    any type to any object.
    """

    is_Function = True

    @cacheit
    def __new__(cls, *args, **options):
        from sympy.sets.fancysets import Naturals0
        from sympy.core.sets import FiniteSet

        args = list(map(sympify, args))
        evaluate = options.pop('evaluate', True)
        nargs = options.pop('nargs', None)

        if options:
            raise ValueError("Unknown options: %s" % options)

        if evaluate:
            evaluated = cls.eval(*args)
            if evaluated is not None:
                return evaluated

        obj = super(Application, cls).__new__(cls, *args, **options)

        # handle nargs
        try:
            obj.nargs = FiniteSet(obj.nargs) if obj.nargs else Naturals0()
        except AttributeError:
            try:
                obj._nargs = FiniteSet(obj._nargs) if obj._nargs else Naturals0()
            except AttributeError:
                obj._nargs = FiniteSet(nargs) if nargs else Naturals0()

        return obj

    @property
    def nargs(obj):
        from sympy.core.sets import FiniteSet, Set
        if isinstance(obj._nargs, Set):
            return obj._nargs
        return FiniteSet(obj._nargs)

    @classmethod
    def eval(cls, *args):
        """
        Returns a canonical form of cls applied to arguments args.

        The eval() method is called when the class cls is about to be
        instantiated and it should return either some simplified instance
        (possible of some other class), or if the class cls should be
        unmodified, return None.

        Examples of eval() for the function "sign"
        ---------------------------------------------

        @classmethod
{'fraction_non_alphanumeric': 0.10078440694081293, 'fraction_numerical': 0.004516282386498692, 'mean_word_length': 2.325955204216074, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 149, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3706213', 'n_tokens_mistral': 3670, 'n_tokens_neox': 3588, 'n_words': 1283}