<commit_before>import weakref
import abc

import numpy as np
import sympy
from sympy import Function, IndexedBase, as_finite_diff
from sympy.abc import s

from devito.dimension import t, x, y, z, time, Dimension
from devito.finite_difference import (centered, cross_derivative,
                                      first_derivative, left, right,
                                      second_derivative)
from devito.logger import debug, error, warning
from devito.memory import CMemory, first_touch
from devito.arguments import (ConstantDataArgProvider, TensorDataArgProvider,
                              ScalarFunctionArgProvider, TensorFunctionArgProvider,
                              ObjectArgProvider)
from devito.parameters import configuration

__all__ = ['Symbol', 'Indexed',
           'ConstantData', 'DenseData', 'TimeData',
           'Forward', 'Backward']

configuration.add('first_touch', 0, [0, 1], lambda i: bool(i))

# This cache stores a reference to each created data object
# so that we may re-create equivalent symbols during symbolic
# manipulation with the correct shapes, pointers, etc.
_SymbolCache = {}


class TimeAxis(object):
    """Direction in which to advance the time index on
    :class:`TimeData` objects.

    :param axis: Either 'Forward' or 'Backward'
    """

    def __init__(self, axis):
        assert axis in ['Forward', 'Backward']
        self._axis = {'Forward': 1, 'Backward': -1}[axis]

    def __eq__(self, other):
        return self._axis == other._axis

    def __repr__(self):
        return {-1: 'Backward', 1: 'Forward'}[self._axis]


Forward = TimeAxis('Forward')
Backward = TimeAxis('Backward')


class Basic(object):
    """
    Base class for API objects, used to build and run :class:`Operator`s.

    There are two main types of objects: symbolic and generic. Symbolic objects
    may carry data, and are used to build equations. Generic objects may be
    used to represent or pass arbitrary data structures. The following diagram
    outlines the top of this hierarchy.

                                 Basic
                                   |
                    ----------------------------------
                    |                                |
              CachedSymbol                         Object
                    |                       <see Object.__doc__>
             AbstractSymbol
    <see diagram in AbstractSymbol.__doc__>

    All derived :class:`Basic` objects may be emitted through code generation
    to create a just-in-time compilable kernel.
    """

    # Top hierarchy
    is_AbstractSymbol = False
    is_Object = False

    # Symbolic objects created internally by Devito
    is_SymbolicFunction = False
    is_ScalarFunction = False
    is_TensorFunction = False

    # Symbolic objects created by user
    is_SymbolicData = False
    is_ConstantData = False
    is_TensorData = False
    is_DenseData = False
    is_TimeData = False
    is_CompositeData = False
    is_PointData = False

    # Basic symbolic object properties
    is_Scalar = False
    is_Tensor = False

    @abc.abstractmethod
    def __init__(self, *args, **kwargs):
        return


class CachedSymbol(Basic):
    """Base class for symbolic objects that caches on the class type."""

    @classmethod
    def _cached(cls):
        """Test if current class is already in the symbol cache."""
        return cls in _SymbolCache

    @classmethod
    def _cache_put(cls, obj):
        """Store given object instance in symbol cache.

        :param obj: Object to be cached.
        """
        _SymbolCache[cls] = weakref.ref(obj)

    @classmethod
    def _symbol_type(cls, name):
        """Create new type instance from cls and inject symbol name"""
        return type(name, (cls, ), dict(cls.__dict__))

    def _cached_init(self):
        """Initialise symbolic object with a cached object state"""
        original = _SymbolCache[self.__class__]
        self.__dict__ = original().__dict__


class AbstractSymbol(Function, CachedSymbol):
    """Base class for data classes that provides symbolic behaviour.

    :param name: Symbolic name to give to the resulting function. Must
                 be given as keyword argument.
    :param shape: Shape of the underlying object. Must be given as
                  keyword argument.

    This class implements the behaviour of Devito's symbolic
    objects by inheriting from and mimicking the behaviour of :class
    sympy.Function:. In order to maintain meta information across the
    numerous re-instantiation SymPy performs during symbolic
    manipulation, we inject the symbol name as the class name and
    cache all created objects on that name. This entails that a symbolic
    object should implement `__init__` in the following format:

    def __init__(self, \*args, \*\*kwargs):
        if not self._cached():
            ... # Initialise object properties from kwargs

    Note: The parameters :param name: and :param shape: must always be
    present and given as keyword arguments, since SymPy uses `*args`
    to (re-)create the dimension arguments of the symbolic function.

    This class is the root of the Devito data objects hierarchy, which
    is structured as follows.

                             AbstractSymbol
                                   |
                 -------------------------------------
                 |                                   |
          SymbolicFunction                      SymbolicData
                 |                                   |
          ------------------                 ------------------
          |                |                 |                |
    ScalarFunction  TensorFunction     ConstantData           |
                                                              |
                                                ----------------------------
                                                |             |            |
                                            DenseData      TimeData  CompositeData
                                                                           |
                                                                       PointData

    The key difference between a :class:`SymbolicData` and a :class:`SymbolicFunction`
    is that the former is created directly by the user and employed in some
    computation, while the latter is created and managed internally by Devito.
    """

    is_AbstractSymbol = True

    def __new__(cls, *args, **kwargs):
        if cls in _SymbolCache:
            newobj = Function.__new__(cls, *args)
            newobj._cached_init()
        else:<commit_msg>options for new<commit_after>import weakref
import abc

import numpy as np
import sympy
from sympy import Function, IndexedBase, as_finite_diff
from sympy.abc import s

from devito.dimension import t, x, y, z, time, Dimension
from devito.finite_difference import (centered, cross_derivative,
                                      first_derivative, left, right,
                                      second_derivative)
from devito.logger import debug, error, warning
from devito.memory import CMemory, first_touch
from devito.arguments import (ConstantDataArgProvider, TensorDataArgProvider,
                              ScalarFunctionArgProvider, TensorFunctionArgProvider,
                              ObjectArgProvider)
from devito.parameters import configuration

__all__ = ['Symbol', 'Indexed',
           'ConstantData', 'DenseData', 'TimeData',
           'Forward', 'Backward']

configuration.add('first_touch', 0, [0, 1], lambda i: bool(i))

# This cache stores a reference to each created data object
# so that we may re-create equivalent symbols during symbolic
# manipulation with the correct shapes, pointers, etc.
_SymbolCache = {}


class TimeAxis(object):
    """Direction in which to advance the time index on
    :class:`TimeData` objects.

    :param axis: Either 'Forward' or 'Backward'
    """

    def __init__(self, axis):
        assert axis in ['Forward', 'Backward']
        self._axis = {'Forward': 1, 'Backward': -1}[axis]

    def __eq__(self, other):
        return self._axis == other._axis

    def __repr__(self):
        return {-1: 'Backward', 1: 'Forward'}[self._axis]


Forward = TimeAxis('Forward')
Backward = TimeAxis('Backward')


class Basic(object):
    """
    Base class for API objects, used to build and run :class:`Operator`s.

    There are two main types of objects: symbolic and generic. Symbolic objects
    may carry data, and are used to build equations. Generic objects may be
    used to represent or pass arbitrary data structures. The following diagram
    outlines the top of this hierarchy.

                                 Basic
                                   |
                    ----------------------------------
                    |                                |
              CachedSymbol                         Object
                    |                       <see Object.__doc__>
             AbstractSymbol
    <see diagram in AbstractSymbol.__doc__>

    All derived :class:`Basic` objects may be emitted through code generation
    to create a just-in-time compilable kernel.
    """

    # Top hierarchy
    is_AbstractSymbol = False
    is_Object = False

    # Symbolic objects created internally by Devito
    is_SymbolicFunction = False
    is_ScalarFunction = False
    is_TensorFunction = False

    # Symbolic objects created by user
    is_SymbolicData = False
    is_ConstantData = False
    is_TensorData = False
    is_DenseData = False
    is_TimeData = False
    is_CompositeData = False
    is_PointData = False

    # Basic symbolic object properties
    is_Scalar = False
    is_Tensor = False

    @abc.abstractmethod
    def __init__(self, *args, **kwargs):
        return


class CachedSymbol(Basic):
    """Base class for symbolic objects that caches on the class type."""

    @classmethod
    def _cached(cls):
        """Test if current class is already in the symbol cache."""
        return cls in _SymbolCache

    @classmethod
    def _cache_put(cls, obj):
        """Store given object instance in symbol cache.

        :param obj: Object to be cached.
        """
        _SymbolCache[cls] = weakref.ref(obj)

    @classmethod
    def _symbol_type(cls, name):
        """Create new type instance from cls and inject symbol name"""
        return type(name, (cls, ), dict(cls.__dict__))

    def _cached_init(self):
        """Initialise symbolic object with a cached object state"""
        original = _SymbolCache[self.__class__]
        self.__dict__ = original().__dict__


class AbstractSymbol(Function, CachedSymbol):
    """Base class for data classes that provides symbolic behaviour.

    :param name: Symbolic name to give to the resulting function. Must
                 be given as keyword argument.
    :param shape: Shape of the underlying object. Must be given as
                  keyword argument.

    This class implements the behaviour of Devito's symbolic
    objects by inheriting from and mimicking the behaviour of :class
    sympy.Function:. In order to maintain meta information across the
    numerous re-instantiation SymPy performs during symbolic
    manipulation, we inject the symbol name as the class name and
    cache all created objects on that name. This entails that a symbolic
    object should implement `__init__` in the following format:

    def __init__(self, \*args, \*\*kwargs):
        if not self._cached():
            ... # Initialise object properties from kwargs

    Note: The parameters :param name: and :param shape: must always be
    present and given as keyword arguments, since SymPy uses `*args`
    to (re-)create the dimension arguments of the symbolic function.

    This class is the root of the Devito data objects hierarchy, which
    is structured as follows.

                             AbstractSymbol
                                   |
                 -------------------------------------
                 |                                   |
          SymbolicFunction                      SymbolicData
                 |                                   |
          ------------------                 ------------------
          |                |                 |                |
    ScalarFunction  TensorFunction     ConstantData           |
                                                              |
                                                ----------------------------
                                                |             |            |
                                            DenseData      TimeData  CompositeData
                                                                           |
                                                                       PointData

    The key difference between a :class:`SymbolicData` and a :class:`SymbolicFunction`
    is that the former is created directly by the user and employed in some
    computation, while the latter is created and managed internally by Devito.
    """

    is_AbstractSymbol = True

    def __new__(cls, *args, **kwargs):
        if cls in _SymbolCache:
            options = kwargs.get('options', {})
            newobj = Function.__new__(cls, *args, **options)
            newobj._cached_init()
        else:
{'fraction_non_alphanumeric': 0.08325222729654863, 'fraction_numerical': 0.001048139552294677, 'mean_word_length': 1.7045960720793683, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 60, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1959955', 'n_tokens_mistral': 3127, 'n_tokens_neox': 2998, 'n_words': 1178}