o
    i1                     @   s   d dl m  m  mZ d dlZd dlZd dlm  mZ d dl	m  m
  mZ d dlmZ d dlmZ d(ddZd(ddZd	d
 Zdd Zdd Zd)ddZdd Zdd Zdd Zdd Zd*ddZdd Zdd Zd d! Zd"d# Zd$d% Zd+d&d'Z dS ),    N)use_name_ofOperationNotSupportedErroraxisc                 C   sh   t | ttjB r
| S t | ttB tjB r(t| dkr$td| d|  | d S td| dt	|  )N   	Expected zC to be a single integer or a list/tuple/array of length 1, but got r   1 to be an integer or a list/tuple/array, but got )

isinstanceintnpintegerlisttuplendarraylen
ValueErrortyper   name r   K/home/ubuntu/.local/lib/python3.10/site-packages/einx/_src/adapter/_util.py_axis_to_axisint
   s   r   c                 C   sJ   t | ttjB r| fS t | ttB tjB rt| S td| dt|  )Nr   r   )	r	   r
   r   r   r   r   r   r   r   r   r   r   r   _axis_to_axistuple   s
   r   c                    s    fdd}|S )Nc                     s(   | d }| dd  D ]} ||}q
|S Nr   r   r   )argsxy	binary_opr   r   nary_op   s   z,_associative_binary_to_nary.<locals>.nary_opr   )r   r   r   r   r   _associative_binary_to_nary   s   r    c                 C   sb   |dk r||j d 7 }|dk s||j kr td| d|j  dt|j}||d | ||S )Nr   r   Axis z" is out of bounds for tensor with  dimensions.)ndimr   r   shapeinsertreshape)	classicaltensorr   	new_shaper   r   r   
_unsqueeze(   s   
r*   c                    sz    dk r t |d jd 7   dk s t |d jkr,td  dt |d j d fdd|D }j| dS )	Nr   r   r!   z# is out of bounds for tensors with r"   c                    s   g | ]}t | qS r   )r*   ).0r(   r   r'   r   r   
<listcomp>9       z_stack.<locals>.<listcomp>r   )r   r$   r   concatenate)r'   tensorsr   r   r,   r   _stack3   s    r2   Fc                    s  dd |  D }dd |  D }t|t| tdkr3tj|fdddd}| ||j}d	d
 }|| ||} fdd|D }t|t krt t| }	dd |	D }	t|	dkrnd|	  d}	n	dd|	 d}	t	d|	 d fdd|D }
| 
|t|
}dd |  D  dd |  D } fdd|D tdkrtfdd|  D }| ||}|s| ||j}|rtj fdd|D }||fS )Nc                 S   s(   g | ]}t |tjr|jd kr|jqS r   )r	   stage3Axisvaluer   r+   ar   r   r   r-   ?   s   ( z0_squeeze_transpose_broadcast.<locals>.<listcomp>c                 S      g | ]}t |tjr|jqS r   r	   r4   r5   r   r7   r   r   r   r-   @       r   c                    s   t | tjo
| j v S Nr:   )r8   )squeeze_axesr   r   <lambda>C       z._squeeze_transpose_broadcast.<locals>.<lambda>F)keep_childrenc                 S   sR   i }g }|   D ]}t|tjr&||jd}||j|f |d ||j< q|S r   )nodesr	   r4   r5   getr   append)exprcountsaxesr8   cr   r   r   _to_axis_idsG   s   z2_squeeze_transpose_broadcast.<locals>._to_axis_idsc                    s   g | ]}| v r|qS r   r   r7   in_axesr   r   r-   S   r.   c                 S   s   h | ]\}}|qS r   r   )r+   r   countr   r   r   	<setcomp>V   s    z/_squeeze_transpose_broadcast.<locals>.<setcomp>r   zaxis z doeszaxes z, z doz
The input z3 not appear in the corresponding output expression.c                    s   g | ]}  |qS r   )index)r+   out_axisrI   r   r   r-   ]   r?   c                 S   r9   r   r:   r7   r   r   r   r-   a   r;   c                 S   r9   r   r:   r7   r   r   r   r-   b   r;   c                    s   g | ]}| vr|qS r   r   r7   rI   r   r   r-   c   r.   c                 3   s0    | ]}t |tjr|j v rd n|jV  qdS r   N)r	   r4   r5   r   r6   r7   )out_axes_broadcastr   r   	<genexpr>e   s   . z/_squeeze_transpose_broadcast.<locals>.<genexpr>c                    s&   g | ]}|j  v r|ntjd qS r3   )r   r4   r5   new_unnamed)r+   r   rI   r   r   r-   k   s   & )rA   setr   r4   remover&   r$   popjoinr   	transposer   broadcast_toListcreate)r'   expr_inr(   expr_outbroadcast_to_unitarysqueezable_in_axesout_axesrH   out_axes_intersectinvalid_axespermpre_broadcast_shaper   )rJ   rP   r=   r   _squeeze_transpose_broadcast=   s<   
rd   c                 C   s   t dd | D S )Nc                 s   s    | ]	}|d kr|V  qdS rO   r   )r+   sr   r   r   rQ   p       z!_squeeze_shape.<locals>.<genexpr>)r   r$   r   r   r   _squeeze_shapeo   s   rh   c                 C   s4   t |jt |krtd|j d| | ||S )NzExpected tensor with shape z$ to have the same squeezed shape as )rh   r$   r   r&   )r'   r(   r$   r   r   r   _squeeze_unsqueezes   s   ri   c                 C   sr   t |dkr|d u r|S t| ||S d gt | }ttt|D ]\}}| ||\}||< q!t| ||d}|S )Nr   r/   )r   r*   reversedr   	enumeratedivmodr2   )r'   r(   ravel_shaper   out_indicesire   r   r   r   _unravely   s   rp   c                 C   s2   | dkrdS | dkrdS | dkrdS | d  dS )Nr   1str   2nd   3rdthr   )ro   r   r   r   _to_ord_str   s   rv   c                    s8    r
d u r
t d|t fdd}|S )Nz:classical must be provided if allow_squeeze_unsqueeze=Truec               	      s  }t |rt|tst|tjs| }| i |}t|tjrktdkr+|g}nptjj|tjjj	|tjjj	j
dt }tjj|tjjtjjj	|tdt }t|fdd}n0t|t
rtdd |D rt|tkrtdt dt| ntdtt| g }tt|d	d
D ]\}\} t|tjjjtjjjB rrtnt
}||j| krtdt| d  d|j rt| }nI|d urtjj|tjjj	||dt| d}rtdtjj|tjjtjjj	
|j dt| d  }t| fdd}|| q|}t|dkr=|d S t
|S )Nr   z:Expected the adapted function to return a tuple of length c                    s    fddt tD S )Nc                    s   g | ]	}t jj qS r   )tracer	signaturepythonValue)r+   _originr   r   r-          zC_ensure_output.<locals>.inner.<locals>.<lambda>.<locals>.<listcomp>)ranger   r|   )expected_out_shapesr|   r   r>      r~   z/_ensure_output.<locals>.inner.<locals>.<lambda>c                 s   s    | ]	}t |tjV  qd S r<   )r	   rw   Tracer)r+   tr   r   r   rQ      rf   z0_ensure_output.<locals>.inner.<locals>.<genexpr>z, but got length zPExpected the adapted function to return a tracer or a tuple of tracers, but got F)strictr   z@ return value of the adapted function to be a tensor with shape z, but got shape z4 return value of the adapted function to be a tensorzallow_squeeze_unsqueeze=True cannot currently be used if return type of the adapted function is a general tracer object, not a tensor.c                       t jjj|  dS Nrg   rw   rx   r'   Tensorr|   expected_out_shaper   r   r>          r   )callabler	   r   rw   r   r   rx   ry   assert_builtinsr   equalcastallr   pytreemaprk   zipr'   r   ConvertibleTensorrh   r$   rv   ri   rC   )r   kwargsexpected_typetensors_outtensors_out2ro   r(   r   allow_squeeze_unsqueezer'   r   expected_type2opr   r   inner   sr   z_ensure_output.<locals>.inner)r   r   )r   r   r   r   r'   r   r   r   r   _ensure_output   s   Dr   c              	   C   s   g }| D ]?}t |tr0|dkr|ttttjtjtj	g q|dkr)|
tj qtd| t |tjr7qt |ts>J |
| qt|S )NscalarnumpyzUnknown concrete type string: )r	   strextendr
   floatboolr   r   floatingbool_rC   r   r   rw   r   r   r   )concrete_typesconcrete_types2r   r   r   r   _make_concrete_types   s   
r   c                 C   s0   t |}t| |pt| tjjjot| jj|S r<   )	r   r	   rw   rx   r'   r   
issubclassconcreter   )r   typesr   r   r   	_has_type   s   (r   c                 C   s$   t | ttB tB tjB tjB tjB S r<   )r	   r
   r   r   r   r   r   r   r   r   r   r   
_is_scalar   s   $r   c                 C   sR   t | rdS t| tjr| jS t| tjjjtjjj	B r| jS t
dt|  d)Nr   z+Cannot determine shape of object with type .)r   r	   r   r   r$   rw   rx   r'   r   r   r   r   r   r   r   r   
_get_shape   s   r   c                    s(   |  t t  fdd} | S )Nc                    s   t | g tjjjR r| S t | tjjjrDt| jjr | S t| jjr:| j	 | } t
|  fdd} | S td| jj dt | g R r`t|  | } t
|  fdd} | S tdt|  )Nc                    r   r   r   r|   rg   r   r   r>     r   z/_to_tensor.<locals>.to_tensor.<locals>.<lambda>zAn object of type z cannot be used as a tensorc                    r   r   r   r|   rg   r   r   r>     r   zExpected a tensor, but got )r	   rw   rx   r'   r   r   r   r   r   r$   r   r   r   r   
_to_tensorconvertforwardrg   r   	to_tensor  s"   z_to_tensor.<locals>.to_tensor)r   )r   r   r   r   r   r   r   	  s
   r   c                    s    fdd}|_ |S )Nc                     s,    d  d}d ur|d 7 }t |)Nz# operation is not supported by the z	 backend. r   )r   r   message2backendmessager   r   r   r   '  s   z_unsupported_op.<locals>.op)__name__)r   r   r   r   r   r   r   _unsupported_op&  s   r   r/   )F)NFNr<   )!einx._src.namedtensor.stage3_srcnamedtensorr4   r   r   	functoolseinx._src.tracerrw   einx._src.util.pytreeutilr   einx._src.util.functoolsr   einx._src.frontend.errorsr   r   r   r    r*   r2   rd   rh   ri   rp   rv   r   r   r   r   r   r   r   r   r   r   r   <module>   s0    

	


2
N