Ë
    ÃÓ^jd  ã                  ó\   — d dl mZ d dlmZmZ d dlZddlmZ erddlm	Z	m
Z
  G d„ d«      Zy)	é    )Úannotations)ÚAnyÚTYPE_CHECKINGNé   )ÚDimEntry)ÚDimÚTensorc                  óZ   — e Zd ZU dZded<   ded<   dd„Zdd„Zdd„Zdd	„Z	 	 	 	 	 	 dd
„Z	y)ÚEnableAllLayersa`  
    RAII-style context manager for enabling functorch vmap layers.
    It manages the creation and cleanup of functorch dynamic layers.

    This is probably one of the more algorithmically important parts of first
    class dims. Intuitively, FCD can be thought of as another way of using
    vmap, where you don't actually have to vmap at the top level, instead the
    vmaps are implicitly determined by inspecting the bound dimensions on the
    FCD tensors involved in a compute (this is similar to our concept of
    non-lexical modes that we spent a long time talking about years ago). But
    under the hood you still need to actually enable the vmap mode. So once
    FCD has determined all of the dims we are batching over, it needs to
    enable all those layers so functorch can actually apply the batching
    rules. Therefore enable all layers!
    ÚintÚlevels_startz	list[Dim]Úlevels_to_dimc                ó2  — ddl m} d| _        g | _        |D ]a  }|j	                  «       rŒ|j                  «       }t        ||«      st        dt        |«      › �«      ‚| j                  j                  |«       Œc | j                  j                  d„ ¬«       y)z¦
        Initialize and push dynamic layers for all first-class dimensions.

        Args:
            levels: List of dimension entries to create layers for
        r   )r   r   zExpected Dim, got c                ó   — | j                   S ©N)Ú_level)Úds    úk/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/functorch/dim/_enable_all_layers.pyú<lambda>z*EnableAllLayers.__init__.<locals>.<lambda>7   s
   € ¨a¯h©h€ ó    )ÚkeyN)Ú r   r   r   Úis_positionalÚdimÚ
isinstanceÚAssertionErrorÚtypeÚappendÚsort)ÚselfÚlevelsr   Úlr   s        r   Ú__init__zEnableAllLayers.__init__"   sŠ   € õ 	àˆÔØˆÔàò 	-ˆAØ—?‘?Õ$Ø—E‘E“G�Ü! ! SÔ)Ü(Ð+=¼dÀ1»g¸YÐ)GÓHÐHØ×"Ñ"×)Ñ)¨!Õ,ð	-ð 	×Ñ×ÑÑ$6ÐÕ7r   c                óÆ   — t        | j                  «      D ]H  \  }}|j                  }t        j                  j
                  j                  |d«      }|dk(  sŒB|| _        ŒJ | S )NÚ	differentr   )Ú	enumerater   ÚsizeÚtorchÚ_CÚ
_functorchÚ_vmap_increment_nestingr   )r    Úir   Ú
batch_sizeÚlevels        r   Ú	__enter__zEnableAllLayers.__enter__9   s[   € ä × 2Ñ 2Ó3ò 	*‰FˆAˆsØŸ™ˆJÜ—H‘H×'Ñ'×?Ñ?À
ÈKÓXˆEØ�A‹vØ$)�Õ!ð		*ð
 ˆr   c                ó  — | j                   t        | j                  «      z   dz
  }t        t        | j                  «      «      D ]F  }t        j
                  j                  j                  «       }|||z
  k7  sŒ4t        d||z
  › d|› �«      ‚ y)z)Clean up dynamic layers in reverse order.r   zExpected layer z, got N)	r   Úlenr   Úranger(   r)   r*   Ú_vmap_decrement_nestingr   )r    Úexc_typeÚexc_valÚexc_tbÚ	to_remover,   Úpoppeds          r   Ú__exit__zEnableAllLayers.__exit__B   sƒ   € à×%Ñ%¬¨D×,>Ñ,>Ó(?Ñ?À!ÑCˆ	Ü”s˜4×-Ñ-Ó.Ó/ò 	VˆAÜ—X‘X×(Ñ(×@Ñ@ÓBˆFØ˜ Q™Ó&Ü$ °yÀ1±}°oÀVÈFÈ8Ð%TÓUÐUñ	Vr   c                óœ  — g }t        |j                  «        d«      D ]  }|j                  t        |«      «       Œ |}t        j
                  j                  j                  |«      �r:t        j
                  j                  j                  |«      }|€t        d«      ‚|| j                  k\  r%|| j                  t        | j                  «      z   k  st        d|› d�«      ‚t        | j                  || j                  z
     «      }t        j
                  j                  j                  |«      }|€t        d«      ‚|j                  ||«       t        j
                  j                  j                  |«      }t        j
                  j                  j                  |«      r�Œ:ddlm}	  |	«       }
||
_        ||
_        ||
_        ||
_        |
S )a  
        Create a Tensor from a batched tensor by unwrapping functorch layers.

        Args:
            batchedtensor: Batched tensor from functorch operation
            has_device: Whether tensor has device info

        Returns:
            Tensor with appropriate levels
        r   zExpected level to be non-NonezLevel z out of rangezExpected bdim to be non-Noner   )r	   )r2   r   r   r   r(   r)   r*   Úis_batchedtensorÚmaybe_get_levelr   r   r1   r   Úmaybe_get_bdimÚinsertÚget_unwrappedr   r	   Ú_tensorÚ_batchtensorÚ_has_deviceÚ_levels)r    ÚbatchedtensorÚ
has_devicer!   r,   Útensorr.   r   Úbdimr	   Úresults              r   Úfrom_batchedzEnableAllLayers.from_batchedJ   s�  € ð "$ˆÜ˜×)Ñ)Ó+Ð+¨QÓ/ò 	'ˆAØ�M‰Mœ( 1›+Õ&ð	'ð ˆä�h‰h×!Ñ!×2Ñ2°6Õ:Ü—H‘H×'Ñ'×7Ñ7¸Ó?ˆEØˆ}Ü$Ð%DÓEÐEà˜×*Ñ*Ò*Ø˜D×-Ñ-´°D×4FÑ4FÓ0GÑGÒGä$ v¨e¨W°MÐ%BÓCÐCÜ˜4×-Ñ-¨e°d×6GÑ6GÑ.GÑHÓIˆCÜ—8‘8×&Ñ&×5Ñ5°fÓ=ˆDØˆ|Ü$Ð%CÓDÐDØ�M‰M˜$ Ô$Ü—X‘X×(Ñ(×6Ñ6°vÓ>ˆFô �h‰h×!Ñ!×2Ñ2°6Ö:õ  	á“ˆØˆŒØ+ˆÔØ'ˆÔØˆŒØˆr   c                ó¬  ‡ ‡— t         j                  j                  j                  |«      sy|}t	        t        t        ‰ j                  «      «      «      D ]|  Š|€ yt        ˆˆ fd„|D «       «      sŒt         j                  j                  j                  |‰ j                  ‰z   «       t         j                  j                  j                  |«      }Œ~ y)a   
        Update the levels of a batched tensor in place.

        This requires the _maybe_unsafe_set_level binding that we'll add to functorch.

        Args:
            batchtensor: Batched tensor to update
            levels: New levels to set
        Nc              3  óT   •K  — | ]  }|t        ‰j                  ‰   «      k(  –— Œ! y ­wr   )r   r   )Ú.0r"   r,   r    s     €€r   ú	<genexpr>z8EnableAllLayers.inplace_update_layers.<locals>.<genexpr>‹   s&   øè ø€ ÒH¸A�1œ ×!3Ñ!3°AÑ!6Ó7Õ7ÑHùs   ƒ%()r(   r)   r*   r;   Úreversedr2   r1   r   ÚanyÚ_maybe_unsafe_set_levelr   r?   )r    Úbatchtensorr!   Úimplr,   s   `   @r   Úinplace_update_layersz%EnableAllLayers.inplace_update_layersu   s¡   ù€ ô �x‰x×"Ñ"×3Ñ3°KÔ@Øàˆäœ%¤ D×$6Ñ$6Ó 7Ó8Ó9ò 	?ˆAØˆ|ÙäÔHÀÔHÕHô —‘×#Ñ#×;Ñ;¸DÀ$×BSÑBSÐVWÑBWÔXÜ—x‘x×*Ñ*×8Ñ8¸Ó>‘ñ	?r   N)r!   úlist[DimEntry])Úreturnr   )r4   r   r5   r   r6   r   rU   ÚNone)rD   útorch.TensorrE   ÚboolrU   r	   )rQ   rW   r!   rT   rU   rV   )
Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú__annotations__r#   r/   r9   rI   rS   © r   r   r   r      sH   … ñð  ÓØÓó8ó.óVó)ðV?Ø'ð?Ø1?ð?à	ô?r   r   )Ú
__future__r   Útypingr   r   r(   Ú
_dim_entryr   r   r   r	   r   r^   r   r   ú<module>rb      s%   ðÝ "ç %ã å  ñ ß÷A?ò A?r   