o
    .iB                     @   s>  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mZ d dl	Z	d dl	m
Z
 d dlmZ d dlmZmZmZmZmZ d dlmZmZmZmZmZ eeef Zeeeedf f Zd	d
 Zdeee  dedefddZdee
ee
df f defddZ dededeg e!f defddZ"dedededeeee ee ef fddZ#dee dee dedefddZ$d d! Z%dee
ee
df f d"eded#ededefd$d%Z&d&d' Z'd"ededdfd(d)Z(defd*d+Z)d,d- Z*d.d/ Z+d0d1 Z,d2d3 Z-d4d5 Z.d6d7 Z/d8d9 Z0e j1d:d; Z2d<d= Z3d>d? Z4d@dA Z5dBdC Z6dS )D    N)partial)AnyCallableOptionalUnion)Tensor)is_batchedtensor)_add_batch_dim_remove_batch_dim_vmap_decrement_nesting_vmap_increment_nestinglazy_load_decompositions)_broadcast_to_and_flattentree_flatten	tree_map_tree_unflattenTreeSpec.c                    s    dt   fdd}|S )Nzvtorch.func.{grad, vjp, jacrev, hessian} don't yet support saved tensor hooks. Please open an issue with your use case.c                     s@   t jj  | i |W  d    S 1 sw   Y  d S N)torchautogradgraphdisable_saved_tensors_hooks)argskwargsfmessage N/home/ubuntu/LTX-2/.venv/lib/python3.10/site-packages/torch/_functorch/vmap.pyfn,   s   $z.doesnt_support_saved_tensors_hooks.<locals>.fn)	functoolswraps)r   r   r   r   r   "doesnt_support_saved_tensors_hooks&   s
   r"   flat_in_dims	flat_argsreturnc                    sZ   dd t | |D  t dkrtd r)t fdd D r)td  d d S )	Nc                 S   s"   g | ]\}}|d ur| |qS r   )size.0in_dimargr   r   r   
<listcomp>8   s
    z0_validate_and_get_batch_size.<locals>.<listcomp>r   z/vmap: Expected at least one Tensor to vmap overc                 3   s    | ]	}| d  kV  qdS )r   Nr   )r(   r&   batch_sizesr   r   	<genexpr>?   s    z/_validate_and_get_batch_size.<locals>.<genexpr>zTvmap: Expected all tensors to have the same size in the mapped dimension, got sizes z for the mapped dimension)ziplen
ValueErrorany)r#   r$   r   r,   r   _validate_and_get_batch_size5   s   r3   batched_outputsc                 C   s   t | tr	t| S dS )N   )
isinstancetupler0   )r4   r   r   r   _num_outputsG   s   
r8   valuenum_elementserror_message_lambdac                 C   s.   t | ts
| f| S t| |krt| | S r   )r6   r7   r0   r1   )r9   r:   r;   r   r   r   	_as_tupleQ   s
   


r<   in_dimsr   funcc           	      C   s  t | tst | tstdt| d|  dt|  dt|dkr,tdt| dt|\}}t| |}|d u rRtdt| d|  dt| d  d	| d	t	t
||D ]~\}\}}t |tsx|d urxtdt| d|  d
| dt |trt |tstdt| d|  d
| dt| d	|d ur||  k s|| krtdt| d|  d
| d|  d|  d|  d|d ur|dk r||  ||< qYt|||||fS )Nvmap(z
, in_dims=zv, ...)(<inputs>): expected `in_dims` to be int or a (potentially nested) tuple matching the structure of inputs, got: .r   z)(<inputs>): got no inputs. Maybe you forgot to add inputs, or you are trying to vmap over a function with no inputs. The latter is unsupported.zb, ...)(<inputs>): in_dims is not compatible with the structure of `inputs`. in_dims has structure r5   z but inputs has structure z, ...)(<inputs>): Got in_dim=zE for an input but in_dim must be either an integer dimension or None.z' for an input but the input is of type zT. We cannot vmap over non-Tensor arguments, please use None as the respective in_dimz> for some input, but that input is a Tensor of dimensionality z  so expected in_dim to satisfy -z <= in_dim < )r6   intr7   r1   	_get_nametyper0   r   r   	enumerater/   r   dimr3   )	r=   r   r>   r$   	args_specr#   ir*   r)   r   r   r   _process_batched_inputs[   sn   

"rH   
vmap_levelc                    s"    fddt | |D }t||S )Nc                    s(   g | ]\}}|d u r|nt || qS r   )r	   r'   rI   r   r   r+      s    z*_create_batched_inputs.<locals>.<listcomp>)r/   r   )r#   r$   rI   rF   batched_inputsr   rJ   r   _create_batched_inputs   s   

rL   c                 C   sp   |d u rt |tjrt|rtd|  d|  d|S t |tjs1td|  d|  dt| dt||||S )Nr?   z	, ...): `z5` can not return a BatchedTensor when out_dim is Nonez%` must only return Tensors, got type z3. Did you mean to set out_dims= to None for output?)r6   r   r   r   r1   rC   r
   )namebatched_outputrI   
batch_sizeout_dimr   r   r   _maybe_remove_batch_dim   s   rQ   out_dimsrO   c           	         s   t | \}fdd}t| tjr7ttrg}n&ttr+tdkr+}nd u r3g}n|  nt}|d u rC|   fddt||D }t	|S )Nc                
      s.   t dt  d dtd  d d	)Nr?   , ..., out_dims=z`)(<inputs>): out_dims is not compatible with the structure of `outputs`. out_dims has structure r5   z but outputs has structure r@   )r1   rB   r   r   )r>   rR   output_specr   r   incompatible_error   s   
z+_unwrap_batched.<locals>.incompatible_errorr5   c                    s$   g | ]\}}t t| |qS r   )rQ   rB   )r(   rN   rP   )rO   r>   rI   r   r   r+      s    z#_unwrap_batched.<locals>.<listcomp>)
r   r6   r   r   rA   r7   r0   r   r/   r   )	r4   rR   rI   rO   r>   flat_batched_outputsrU   flat_out_dimsflat_outputsr   )rO   r>   rR   rT   rI   r   _unwrap_batched   s"   


rY   c                 C   s4   t | trd S | d u rd S tdt| d| d)Nr?   rS   z): `out_dims` must be an int, None or a python collection of ints representing where in the outputs the vmapped dimension should appear.)r6   rA   r1   rB   )xr>   rR   r   r   r   _check_int_or_none   s   
r[   c                 C   s&   t | trd S ttt|| d|  d S )N)r>   rR   )r6   rA   r   r   r[   )rR   r>   r   r   r   $_check_out_dims_is_int_or_int_pytree   s   
r\   c                 C   s6   t | dr| jS t| tjrdt| j dS t| S )N__name__zfunctools.partial(z, ...))hasattrr]   r6   r    r   rB   r>   repr)r>   r   r   r   rB      s
   
rB   c                 O   sp   t   t||  t||| \}}}	}
|d ur*t|	|||}t| |||
||fi |S t| |||	|
||fi |S r   )r   r\   rH   _get_chunked_inputs_chunked_vmap
_flat_vmap)r>   r=   rR   
randomness
chunk_sizer   r   rO   r#   r$   rF   chunks_flat_argsr   r   r   	vmap_impl  s<   
rf   c                 C   s4   | |  }}|g| }| | }|dkr| | |S )Nr   )append)total_elemsrd   n_chunkschunk_sizes	remainderr   r   r   get_chunk_sizes&  s   

rl   c                    sN   |f |d urt ||}tt| t fddt| |D }t| }|S )Nc                 3   s8    | ]\}}|d ur|j  |dn|gt  V  qd S N)rE   )tensor_splitr0   )r(   tr)   
split_idxsr   r   r.   6  s    	
z&_get_chunked_inputs.<locals>.<genexpr>)rl   r7   	itertools
accumulater/   )r$   r#   rO   rd   rj   flat_args_chunksre   r   rp   r   r`   0  s   
	r`   c                 C   sH   g }d }| D ]}t |\}}|| |d u r|}qtt| }||fS r   )r   rg   listr/   )chunks_output_flat_chunks_outputarg_specoutputflat_output	arg_specsflat_output_chunksr   r   r   _flatten_chunks_outputH  s   
r}   c                 C   sX   t | |}t|t|ksJ g }t|D ]\}}|tj|| |d d ||< q|S rm   )r   r0   rD   rg   r   cat)rR   rx   r|   rW   rz   idxrP   r   r   r   _concat_chunked_outputsY  s   

r   c                 K   s   g }|dkr
t  nd }|D ]&}	t||	}
|
dkrq|d ur#t | |t| |
||	|||fi | qt|\}}~t|||}t||S )Nsamer   )	r   get_rng_stater3   set_rng_staterg   rb   r}   r   r   )r>   r#   re   rF   rR   rc   r   chunks_outputrsr$   rO   r|   rx   rz   r   r   r   ra   g  s2   


ra   c                 C   s   | dvrt d|  d S )N)error	differentr   zLOnly allowed values for randomness are 'error', 'different', or 'same'. Got )RuntimeError)rc   r   r   r   _check_randomness_arg  s
   r   c                 c   s(    zt | |}|V  W t  d S t  w r   )r   r   )rO   rc   rI   r   r   r   vmap_increment_nesting  s
   
r   c                 K   sZ   t ||}t||||}	| |	i |}
t|
|||| W  d    S 1 s&w   Y  d S r   )r   rL   rY   )r>   rO   r#   r$   rF   rR   rc   r   rI   rK   r4   r   r   r   rb     s   $rb   c                    s    fdd}|S )Nc                     sR   t  }t| |}|i |}t||W  d    S 1 s"w   Y  d S r   )r   wrap_batchedunwrap_batched)r   r   rI   rK   r4   rO   r>   r=   rc   r   r   inner  s
   $zrestore_vmap.<locals>.innerr   )r>   r=   rO   rc   r   r   r   r   restore_vmap  s   r   c                 C   s4   t | \}}t||}|d usJ t||||}|S r   )r   r   rL   )r   bdimslevelr$   spec
flat_bdimsresultr   r   r   r     s
   
r   c                    sR   t | \}}t|dkr| dfS  fdd|D }t| \}}t||t||fS )Nr   r   c                    s0   g | ]}t |tjrtjj| n|d fqS r   )r6   r   r   _C
_functorchrY   )r(   r*   r   r   r   r+     s    
z"unwrap_batched.<locals>.<listcomp>)r   r0   r/   r   )r   r   r$   r   r   ry   r   r   r   r   r     s   
r   )7
contextlibr    rr   r   typingr   r   r   r   r   r   torch._C._functorchr   torch._functorch.predispatchr	   r
   r   r   r   torch.utils._pytreer   r   r   r   r   rA   r7   	in_dims_t
out_dims_tr"   ru   r3   r8   strr<   rH   rL   rQ   rY   r[   r\   rB   rf   rl   r`   r}   r   ra   r   contextmanagerr   rb   r   r   r   r   r   r   r   <module>   s   	

"




>

*"
2

