o
    "ÂeD  ã                   @   s  d Z ddlZddlZddlmZ ddlmZ ddlmZ ddlm	Z
 ddlmZ dd	lmZ g d
¢ZdddddddœZd#dd„ZejejejejejejdœZd$dd„Zi Zdd„ Zi Zdd„ Ze
jejejejejdœZe
jejejejejdœZdd„ Zdd „ Zd!d"„ Z dS )%z¦
Handles dispatching array operations to the correct backend library, as well
as converting arrays to backend formats and then potentially storing them as
constants.
é    Né   )Úobject_arrays)Úcupy)Újax)Ú
tensorflow)Útheano)Útorch)Úget_funcÚ
has_einsumÚhas_tensordotÚbuild_expressionÚevaluate_constantsÚhas_backendz
dask.arrayztheano.tensorzopt_einsum.backends.torchz	jax.numpyzautograd.numpyzmars.tensor)Zdaskr   r   r   ZautogradZmarsc                 C   sX   zt  t ||¡¡}|du rt|| ƒW S t|| |ƒW S  ty+   d}t| || ¡ƒ‚w )z½Try and import ``{backend}.{func}``.
    If library is installed and func is found, return the func;
    otherwise if default is provided, return default;
    otherwise raise an error.
    Nz´{} doesn't seem to provide the function {} - see https://optimized-einsum.readthedocs.io/en/latest/backends.html for details on which functions are required for which contractions.)Ú	importlibÚimport_moduleÚ_aliasesÚgetÚgetattrÚAttributeErrorÚformat)ÚfuncÚbackendÚdefaultÚlibZ	error_msg© r   ú<lib/python3.10/site-packages/opt_einsum/backends/dispatch.pyÚ_import_func   s   "ür   ))Ú	tensordotÚnumpy)Ú	transposer   )Úeinsumr   )r   Úobject)r   r!   )r    r!   r   c                 C   s>   zt | |f W S  ty   t| ||ƒ}|t | |f< | Y S w )ziReturn ``{backend}.{func}``, e.g. ``numpy.einsum``,
    or a default func if provided. Cache result.
    )Ú_cached_funcsÚKeyErrorr   )r   r   r   Úfnr   r   r   r	   <   s   ýr	   c                 C   óX   zt |  W S  ty+   ztd| ƒ dt | < W n ty$   dt | < Y nw t |   Y S w )zHCheck if ``{backend}.einsum`` exists, cache result for performance.
    r    TF)Ú_has_einsumr#   r	   r   ©r   r   r   r   r
   L   ó   

ÿùr
   c                 C   r%   )zKCheck if ``{backend}.tensordot`` exists, cache result for performance.
    r   TF)Ú_has_tensordotr#   r	   r   r'   r   r   r   r   ^   r(   r   )r   r   r   r   r   c                 C   ó   t |  ||ƒS )zxBuild an expression, based on ``expr`` and initial arrays ``arrays``,
    that evaluates using backend ``backend``.
    )ÚCONVERT_BACKENDS©r   ZarraysÚexprr   r   r   r   €   ó   r   c                 C   r*   )zƒConvert constant arrays to the correct backend, and perform as much of
    the contraction of ``expr`` with these as possible.
    )ÚEVAL_CONSTS_BACKENDSr,   r   r   r   r   ‡   r.   r   c                 C   s   |   ¡ tv S )z$Checks if the backend is known.
    )Úlowerr+   r'   r   r   r   r   Ž   s   r   )N)r   N)!Ú__doc__r   r   Ú r   r   Z_cupyr   Z_jaxr   Z_tensorflowr   Z_theanor   Z_torchÚ__all__r   r   r   r   r    Zobject_einsumr"   r	   r&   r
   r)   r   r   r+   r   r/   r   r   r   r   r   Ú<module>   sZ    ú

ù
û	û	