o
    ٷi4                     @   sv  d dl Z d dlZd dlmZ d dlmZ d dlZd dlZd dl	Z	d dl
Z	d dlmZ d dlmZmZmZ d dlmZmZ dZej Zdd	 Zd
d Zdd ZedddZeg dZdd Zdd Zdd Z dd Z!dd Z"dd Z#dd Z$dd  Z%g ed!dded!d!dZ&d"d# e&D Z&ej'(d$e&d%d& Z)ej'(d$e&d'd( Z*d)d* Z+d+d, Z,d-d. Z-d/Z.d0d1 Z/dS )2    N)testmod)Path)AbstractBackend)_optimize_transformationparse_shape	rearrange)collect_test_backendsis_backend_testedzAlex Rogozhnikovc                   C   s0   t tjdttdd t tjdttdd d S )NT)np)raise_on_error
extraglobs)r   einopslayersdictr
    r   r   K/home/ubuntu/.local/lib/python3.10/site-packages/einops/tests/test_other.pytest_doctests_examples   s   r   c                  C   s   ddl m}  t|  }g }g }t }|r&| }|| 7 }|| |s|D ]-}|j|vr0q(z|  ||j W q( t	yU } z||j|f W Y d}~q(d}~ww t
|dks`J |t
|dksnJ d|ddS )z
    This test will fail if some of backends are not installed or can't be imported
    Other tests will just work and only test installed backends.
       )parse_backends_to_testNr   z%did not instantiate backends_to_test=z, they won't be tested) r   setr   __subclasses__popappendframework_nameremove	Exceptionlen)r   backends_to_testerrorsbackend_subclassesbackendsbackendbackend_typeer   r   r   test_backends_installed   s,   


 r%   c                  C   s~  t d dd tdD } | dd tdD 7 } | g dg7 } | g dg7 } | D ]}td	D ]}t|}tjd
d|ddg}|d d  }td
|d }tt|d | }t|| }tjd
ddd}	t||||	 \}
}}}}t	
|	|s}J ||j|d|dg}||
j|d|dg}t	
||sJ t| }t||D ]\}}t	
||sJ qq.q(d S )NzTesting optimizationsc                 S      g | ]}d g| qS )   r   .0n_dimensionsr   r   r   
<listcomp>:       z7test_optimize_transformations_numpy.<locals>.<listcomp>   c                 S   r&   )   r   r(   r   r   r   r+   ;   r,      )r'   r.         )r'   r.   r0   r1         r0   r   i   )sizer   i   iM  )axis)printranger   rngintegersreshapetuplepermutationr   r
   array_equalsum	transposezip)shapesshape_attemptr*   x
init_shape	n_reducedreduced_axesaxes_reorderingfinal_shapeinit_shape2reduced_axes2axes_reordering2final_shape2combination2result1result2combination3abr   r   r   #test_optimize_transformations_numpy8   s6     rU   Fsymbolicr   
         (   c                  C   s   t D ]=} td| j ttd}t| td}||  kr(tdddddks+J  J |tddddd  kr<|ks?J  J qd S )	NzShape parsing for a b c drY   rZ   r[   r\   )rS   rT   cdr   )_IMPERATIVE_BACKENDSr7   r   r   x_np
from_numpyr   r"   parsed1parsed2r   r   r   test_parse_shape_imperative]   s   
(*rf   c                  C   sF   t D ]} ttd}t| td}||  krt ks J  J qd S )Nz_ _ _ _r`   r   ra   rb   r   rc   r   r   r   test_underscoref   s
   
 rh   c                  C   sJ   t D ] } ttd}t| td}||  krtddks"J  J qd S )Nz_ _ _ hellor\   )hellorg   rc   r   r   r   test_underscore_onem   s
   
$rj   c                  C   sL   t D ]!} ttd}t| td}||  kr tdddks#J  J qd S )Nz_ _ a1 a1a111ar[   r\   )a1a1a111arg   rc   r   r   r   test_underscore_severalt   s
   
&rm   c               	   C   s   t tj ttd W d    n1 sw   Y  tD ] } t tj t| td W d    n1 s8w   Y  qd S )Nza a b b)pytestraisesr   EinopsErrorr   ra   r`   rb   )r"   r   r   r   test_repeating{   s   rq   c                  C   s   t D ]} ddgdt fdgdtddfddgdtddfg ddtddfg ddtd	dfdgd
tddfddgd
tddfg dd
tddfg dd
tddfg ddtdd	dfdd	gdtdd	dffD ]%\}}}t|}t||}t| ||}||  kr|ksJ  J qgqd S )NrY   rZ   ...... arS   rY   rZ   r[   r[   rX   r\   a ... a ... brS   rT   r`   r   r
   onesr   rb   r"   rC   patternexpectedrE   rd   re   r   r   r   test_ellipsis   s&   

r~   c                  C   s   t D ]E} g ddtddfg ddtddfg ddtddffD ]%\}}}t|}t||}t| ||}||  krC|ksFJ  J q!qd S )	Nr   r'   r.      z1 2 3 ar   rt   )rY   r   r'   za 1 2rY   za () 2ry   r{   r   r   r   test_parse_with_anonymous_axes   s   

r   c               
   C   s   t D ]I} g ddfg ddfg ddfg ddfg ddfg ddffD ]&\}}tt t|}t| || W d    n1 sEw   Y  q$qd S )Nr   za b cz2 a b cza b c ()z	a b c d eza b c d e ...)r`   rn   ro   RuntimeErrorr
   rz   r   rb   )r"   rC   r|   rE   r   r   r   test_failures   s   






r   Tc                 C   s   g | ]	}|j d kr|qS )ztensorflow.keras)r   )r)   r"   r   r   r   r+      s    r+   r"   c           	   
   C   s   g dg dg dfD ]o}t d| jd| | |}t|d}i }| D ]\}}t|tr3|n| ||t	g dfg||< q(t | t
|dfi t|dd	d
i}| ||t	g dfg}t |j |jdksrJ t|dszJ qd S )NrX   )rY   rZ   NNNNNNz-special shape parsing backend.framework_name=z input_shape=r]   z*a b (c1 c2) (d1 d2) -> (a b d1) c1 (c2 d2)za b c1 _d2r'   )i  r[   r'   r   )r7   r   create_symbolr   items
isinstanceinteval_symbolr
   zerosr   rC   allclose)	r"   input_shapeinput_symbolshape_placeholder	out_shapenamesymbolresult_placeholderresultr   r   r   test_parse_shape_symbolic   s4   


r   c           
      C   s|  ddgd d gdt  fdgd gdt ddfddgd d gdt ddfg dg ddt ddfg d	g d
dt ddfdgd gdt ddfddgd d gdt ddfg dg ddt ddfg d	g d
dt ddfg d	g d
dt dddfddgd d gdt dddffD ]9\}}}}| |}t||}i }| D ]\}}	t|	tr|	||< q| |	|t|fg||< q||ksJ qd S )NrY   rZ   rr   rs   rt   ru   )NNNr[   rX   r   r\   rv   rw   rx   z	 a ... b )	r   r   r   r   r   r   r   r
   r   )
r"   static_shaperC   r|   r}   r   r   r   r   r   r   r   r   "test_parse_shape_symbolic_ellipsis   s*   



r   c                  C   sv   t ddd} | t ddd7 } | D ](}dD ]#}d|v }tjg d|d}||}|||ks7J |||jfqqd S )NFrV   T)int32int64float32float64float)r.   r   r0   )dtype)r   r
   r   rb   is_float_typer   )r!   r"   r   is_floatinputr   r   r   test_is_float_type   s   
 r   c                     s   t dst  ddl} ddlm} ddlm mmm	m
 ddlm} |  G  fddd|j}| }| j|d	d
}dD ]+}| ||d |d g}dD ]}|||}	|| | }
| jj|	|
ddd qTqDdS )a7  
    Test ensures that allow_ops_in_compiled_graph allows compiling in a single graph
    Additionally we ensure that after compilation cache works properly
     (by changing shapes and patterns)
    We additionally check that pack/unpack still can be handled
     despite variable number of inputs/outputs
    torchr   Nnneinsumpackreducerepeatunpack)allow_ops_in_compiled_graphc                       s4   e Zd Zd fddZd	fdd	Z  ZS )
zCtest_torch_compile_for_functions.<locals>.TorchModuleWithOperationsreturnNc                    s   t    d S )N)super__init__)self	__class__r   r   r     s   zLtest_torch_compile_for_functions.<locals>.TorchModuleWithOperations.__init__r   c                    s   |j \}}} fdd}||d}||dd}|gdt   |d\}}	t||d|	d	}
|
d
 t|
 }t||d|d}|||dd
 }|| S )Nc                    s    |   }d fdd|D S )N c                    s$   g | ]}|d  dvr|n|  qS )r5   acdr   )r)   psuffixr   r   r+     s   $ zltest_torch_compile_for_functions.<locals>.TorchModuleWithOperations.forward.<locals>.suf.<locals>.<listcomp>)splitjoin)r|   partsr   r   r   suf  s   zXtest_torch_compile_for_functions.<locals>.TorchModuleWithOperations.forward.<locals>.sufza b c -> a b c 4za b c d -> a b cminr'   za b * cza b d c -> (a b ) 1 c dzab one1 c *r   z(a b ) 1 c -> a b c)rT   za b c , a b c d -> d)rC   r   r   )r   x_abcr   rS   rT   r^   r   x_abcdx_abdcpsx_arrayx1additionr   r   r   forward  s    zKtest_torch_compile_for_functions.<locals>.TorchModuleWithOperations.forward)r   N)r   )__name__
__module____qualname__r   r   __classcell__r   r   r   r   TorchModuleWithOperations  s    r   T	fullgraph)rY   rZ   r\   r   r'   )r   suf1other_suffixgh㈵>)atolrtol)r	   rn   skipr   r   r   r   r   r   r   r   einops._torch_specificr   Modulecompileranddoubler   testingassert_close)r   r   r   r   originalcompiledr4   rE   r   rP   rQ   r   r   r    test_torch_compile_for_functions  s$   
r   c                  C   s   t dst  ddl} ddlm} ddlm}m}m} |	|ddd|d	d
ddddd|dddd}| j
|dd}dD ]}| ||g}||}	||}
| |	|
sVJ q=dS )z
    Einops layers are in general very friendly towards tracing/compiling,
    but we still want to make sure we can compile them.
    r   r   Nr   )EinMix	RearrangeReducezb (t c) -> b t c   )r^   zb t c -> qkv b t coutz
qkv c coutzqkv coutr.      )weight_shape
bias_shapeqkvr^   coutzqkv b t cout -> b t qkvr   )r   Tr   )r       @   )r	   rn   r   r   r   einops.layers.torchr   r   r   
Sequentialr   r   r   )r   r   r   r   r   r   r   r4   rE   rP   rQ   r   r   r   test_torch_compile_for_layers4  s"   
r   aS  
import einops
import numpy as np
from concurrent.futures import ThreadPoolExecutor
import torch

def f():
    return einops.rearrange(np.ndarray((20, 150, 150)), "... i j -> ... j i")
with ThreadPoolExecutor(max_workers=2) as ex:
    fs = []
    for i in range(20):
        fs.append(ex.submit(f))
    for fut in fs:
        fut.result()
c                  C   s   t dst  t dst  t "} t| d}|t t	j
d|  gdd W d    d S 1 s9w   Y  d S )Nr   numpyztest.pypythonT)check)r	   rn   r   tempfileTemporaryDirectoryr   joinpath
write_textsrc
subprocessrunabsoluteas_posix)r_   testfiler   r   r   test_einops_threadinga  s   

"r   )0r   r   doctestr   pathlibr   r   r
   rn   r   einops.layerseinops._backendsr   einops.einopsr   r   r   einops.testsr   r	   
__author__randomdefault_rngr9   r   r%   rU   r`   r   ra   rf   rh   rj   rm   rq   r~   r   r   _SYMBOLIC_BACKENDSmarkparametrizer   r   r   r   r   r   r   r   r   r   r   <module>   sR    
 		



3