
    Opf                     4    d Z ddlZddlmZ ddgZd	dZd ZdS )
z1
Determines if a contraction can use BLAS or not
    N   )helperscan_blastensor_blasc                    t          |           dk    rdS | \  }}t          ||z             D ]b}|                    |          |                    |          }}|dk    s|dk    s	||z   dk    r dS ||z   dz
  t          ||v           k    r dS c|L|D ]I}|d         |                    |                   |d         |                    |                   k    r dS Jt          |          dk    rdS d | D             }	|	d         |z
  }
|	d         |z
  }t          |          }| d         | d         k    rdS |	d         |	d         k    rd	S || d         |d|         k    rd
S |d|         || d         k    rd
S || d         || d         k    rd
S |d|         |d|         k    rd
S t          |
          dk    st          |          dk    rdS dS )a  
    Checks if we can use a BLAS call.

    Parameters
    ----------
    inputs : list of str
        Specifies the subscripts for summation.
    result : str
        Resulting summation.
    idx_removed : set
        Indices that are removed in the summation
    shapes : sequence of tuple[int], optional
        If given, check also that none of the indices are broadcast dimensions.

    Returns
    -------
    type : str or bool
        The type of BLAS call to be used or False if none.

    Notes
    -----
    We assume several operations are not efficient such as a transposed
    DDOT, therefore 'ijk,jki->' should prefer einsum. These return the blas
    type appended with "/EINSUM" to differentiate when they can still be done
    with tensordot if required, e.g. when a backend has no einsum.

    Examples
    --------
    >>> can_blas(['ij', 'jk'], 'ik', set('j'))
    'GEMM'

    >>> can_blas(['ijj', 'jk'], 'ik', set('j'))
    False

    >>> can_blas(['ab', 'cd'], 'abcd', set())
    'OUTER/EINSUM'

    >>> # looks like GEMM but actually 'j' is broadcast:
    >>> can_blas(['ij', 'jk'], 'ik', set('j'), shapes=[(4, 1), (5, 6)])
    False
       Fr   Nr   zOUTER/EINSUMc                 ,    g | ]}t          |          S  )set).0xs     O/var/www/html/nettyfy-visnx/env/lib/python3.11/site-packages/opt_einsum/blas.py
<listcomp>zcan_blas.<locals>.<listcomp>U   s    ###qCFF###    DOTz
DOT/EINSUMGEMMzGEMV/EINSUMTDOT)lenr   countintfind)inputsresultidx_removedshapes
input_leftinput_rightcnlnrsets	keep_left
keep_rightrss                r   r   r      sc   V 6{{au$Jk)** 
 
!!!$$k&7&7&:&:BFFQBGaKK55
 7Q;#a6k****55 +
  	 	Aay++,q	+:J:J1:M:M0NNNuu O
 ;1~ $#F###DQ+%Ia;&J	[		B ayF1Iu 
aDG		| 2#$$;ss+++v 
CRCK-	-	-v 
RCDD	[".	.	.v 
CRCK,	,	,v i..A

3z??a#7#7} vr   c                    t          |          }t          |          |z
  }t          |          |z
  }i t          || j                  D ]
\  }}	|	|<   t          ||j                  D ]
\  }}	|	|<   t          |          }
t	          j        |          }t	          j        |          }t	          j        |          }||z   }|D ]}	|                    |	d          }||k    r;t          j        | 	                                |	                                          }n||
 d         |d|
         k    r?t          j        | 
                    ||          |
                    ||                    }ni|d|
         ||
 d         k    rIt          j        | 
                    ||          j        |
                    ||          j                  }n	||
 d         ||
 d         k    rCt          j        | 
                    ||          |
                    ||          j                  }n|d|
         |d|
         k    rCt          j        | 
                    ||          j        |
                    ||                    }nUd\  }}|D ]4}	||                    |	          fz  }||                    |	          fz  }5t          j        | |||f          }t          fd|D                       }|j        |k    r/t          |          dk    r||_        nt          j        |          }||k    rt          j        |dz   |z   |          }|S )a  
    Computes the dot product between two tensors, attempts to use np.dot and
    then tensordot if that fails.

    Parameters
    ----------
    view_left : array_like
        The left hand view
    input_left : str
        Indices of the left view
    view_right : array_like
        The right hand view
    input_right : str
        Indices of the right view
    index_result : str
        The resulting indices
    idx_removed : set
        Indices removed in the contraction

    Returns
    -------
    type : array
        The resulting BLAS operation.

    Notes
    -----
    Interior function for tensor BLAS.

    This function will attempt to use `np.dot` by the iterating through the
    four possible transpose cases. If this fails all inner and matrix-vector
    operations will be handed off to einsum while all matrix-matrix operations will
    first copy the data, perform the DGEMM, and then copy the data to the required
    order.

    Examples
    --------

    >>> a = np.random.rand(4, 4)
    >>> b = np.random.rand(4, 4)
    >>> tmp = tensor_blas(a, 'ij', b, 'jk', 'ik', set('j'))
    >>> np.allclose(tmp, np.dot(a, b))

     N)r
   r
   )axesc              3   (   K   | ]}|         V  d S Nr
   )r   r   dimension_dicts     r   	<genexpr>ztensor_blas.<locals>.<genexpr>   s(      BBq*BBBBBBr   r   z->)r   zipshaper   r   compute_size_by_dictreplacenpdotravelreshapeTr   	tensordottuplesqueezeeinsum)	view_leftr   
view_rightr   index_resultr   r"   r#   isr$   dim_left	dim_rightdim_removedtensor_resultnew_viewleft_pos	right_postensor_shaper*   s                      @r   r   r   {   s   Z k""KJ+-I[!!K/J NJ	00  1qK!122  1q  
[		B+I~FFH,ZHHI.{NKKK,M 5 5%--a44 [  6)//++Z-=-=-?-?@@ 
RCDD	["-	-	-6)++HkBBJDVDVWbdmDnDnoo 
CRCK-	-	-6)++KBBDjFXFXYbdoFpFpFrss 
RCDD	[".	.	.6)++HkBBJDVDVW`bmDnDnDpqq 
CRCK,	,	,6)++KBBDjFXFXYdfoFpFpqq
 %) 	1 	1A++..H+**1--00II<	:Xy<QRRR BBBBMBBBBBL~%%}!!)HNNz(++H$$9]T1L@(KKOr   r)   )__doc__numpyr0   r&   r   __all__r   r   r
   r   r   <module>rI      sp              }
%l l l l^x x x x xr   