Ë
    ÃÓ^jE9  ã                  óà   — d Z ddlmZ ddlmZ ddlZddlmZm	Z
 erddlmZ g d¢Z G d„ d	«      Z	 	 	 	 	 	 	 	 dd
„Z	 	 	 	 	 	 	 	 dd„Z	 	 	 	 	 	 	 	 dd„Zdd„Zdd„Zdd„Zddœ	 	 	 	 	 	 	 dd„Zy)a´  Python access to ATen's TensorIterator build pipeline.

:class:`TensorIterator` builds an iterator from a set of operands and flags
that mirror ``at::TensorIteratorConfig``, then exposes the post-build
shape / dtype / device / stride information for inspection.

This is a build-pipeline-only surface: there is no ``for_each`` here. Use it
to debug shape and dtype inference, validate custom-op contracts, or inspect
how ATen would lay out a kernel's iteration.

Construction is canonical, *not* a faithful replay of arbitrary
``TensorIteratorConfig`` call sequences. Operands are always registered in
the order ``outputs -> inputs -> const_inputs`` and setters are applied in
one fixed order. Notably:

* The C++ builder distinguishes ``add_input(a); add_const_input(b)`` from
  ``add_const_input(b); add_input(a)`` -- ``input(0)`` refers to different
  operands. This Python surface cannot express that distinction: every
  ``inputs[i]`` precedes every ``const_inputs[j]``.
* Some C++ setters have order-dependent side effects (e.g.
  ``promote_inputs_to_common_dtype(true)`` also flips
  ``check_all_same_dtype`` to ``false``). The Python surface materializes
  the *final* boolean state of each knob, not the call order, so it can't
  reproduce a sequence where an intermediate setter observed a
  since-overwritten value.

Every in-tree caller of ``at::TensorIteratorConfig`` fits the canonical-
recipe shape; the lossiness is theoretical, not practical.
é    )Úannotations)ÚTYPE_CHECKINGN)Ú_TensorIteratorÚ_TensorIteratorSpec)ÚSequence)ÚTensorIteratorÚ	binary_opÚbinary_float_opÚcomparison_opÚunary_opÚunary_float_opÚ
nullary_opÚ	reduce_opc                  ót  — e Zd ZdZdddddddddddddddddddœ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd„Zedd„«       Zedd	„«       Zedd
„«       Zedd„«       Z	edd„«       Z
edd„«       Zedd„«       Zedd„«       Zedd„«       Zdd„Zddd„Zddd„Zdd d„Zdd!d„Zd"d„Zd#d„Zd$d„Zy)%r   a¤  A built TensorIterator. Read-only view of the build-pipeline result.

    Constructor kwargs mirror ``at::TensorIteratorConfig``; defaults match
    the C++ defaults. See module docstring for canonical-recipe caveats.

    Examples
    --------
    Build a TI for a binary op with type promotion and inspect the result::

        >>> import torch
        >>> from torch._tensor_iterator import TensorIterator
        >>> a = torch.zeros(3, 4, dtype=torch.float32)
        >>> b = torch.zeros(3, 4, dtype=torch.float64)
        >>> it = TensorIterator(
        ...     outputs=[None],
        ...     const_inputs=[a, b],
        ...     promote_inputs_to_common_dtype=True,
        ...     cast_common_dtype_to_outputs=True,
        ... )
        >>> it.common_dtype
        torch.float64
        >>> it.numel
        12
        >>> it.ndim       # contiguous (3, 4) collapses to a single dim
        1

    Declare a static shape (the iterator skips broadcast/coalesce)::

        >>> a = torch.zeros(2, 6)
        >>> out = torch.empty(2, 6)
        >>> it = TensorIterator(
        ...     outputs=[out],
        ...     const_inputs=[a],
        ...     resize_outputs=False,
        ...     static_shape=(2, 6),
        ... )

    Build a reduction TI (output must be pre-allocated to the reduced shape)::

        >>> a = torch.zeros(3, 4)
        >>> out = torch.empty(3, 1)
        >>> it = TensorIterator(
        ...     outputs=[out],
        ...     const_inputs=[a],
        ...     resize_outputs=False,
        ...     is_reduction=True,
        ... )

    Inspect post-coalesce strides (in bytes; use ``element_strides`` for
    element units)::

        >>> a = torch.zeros(3, 4)
        >>> b = torch.zeros(3, 4)
        >>> it = TensorIterator(outputs=[None], const_inputs=[a, b])
        >>> tuple(it.strides(0))           # output byte strides
        (4,)
        >>> it.element_strides(0)          # ... in elements
        (1,)
    NTF© )ÚoutputsÚinputsÚconst_inputsÚcheck_all_same_dtypeÚcheck_all_same_deviceÚpromote_inputs_to_common_dtypeÚpromote_integer_inputs_to_floatÚcast_common_dtype_to_outputsÚenforce_safe_casting_to_outputÚenforce_linear_iterationÚresize_outputsÚcheck_mem_overlapÚallow_cpu_scalarsÚis_reductionÚstatic_dtypeÚstatic_deviceÚstatic_shapeÚsquash_dimsc               ó¼  — t        «       }|�t        |«      ng |_        |�t        |«      ng |_        |�t        |«      ng |_        ||_        ||_        ||_        ||_        ||_	        |	|_
        |
|_        ||_        ||_        ||_        ||_        |�||_        |�||_        |� t        |«      |_        t        |«      |_        |j)                  «       | _        y ©N)Ú_CTensorIteratorSpecÚlistr   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   ÚbuildÚ_impl)Úselfr   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   Úspecs                       úa/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/torch/_tensor_iterator.pyÚ__init__zTensorIterator.__init__w   sæ   € ô, $Ó%ˆØ(/Ð(;”t˜G”}ÀˆŒØ&,Ð&8”d˜6”l¸bˆŒØ2>Ð2JœD Ô.ÐPRˆÔà$8ˆÔ!Ø%:ˆÔ"Ø.LˆÔ+Ø/NˆÔ,Ø,HˆÔ)Ø.LˆÔ+Ø(@ˆÔ%Ø,ˆÔØ!2ˆÔØ!2ˆÔØ(ˆÔàÐ#Ø ,ˆDÔØÐ$Ø!.ˆDÔØÐ#Ü $ \Ó 2ˆDÔÜ# KÓ0ˆDÔà'+§z¡z£|ˆ�
ó    c                ó.   — | j                   j                  S r%   )r)   Úndim©r*   s    r,   r0   zTensorIterator.ndim¨   s   € à�z‰z�‰Ðr.   c                ó.   — | j                   j                  S )a‘  Iterator shape (post coalesce/reorder), as a zero-copy
        ``memoryview`` of ``int64`` elements. The view holds a reference
        to this iterator and keeps it alive for as long as the view is
        reachable; copy via ``tuple(it.shape)`` if you need a snapshot
        you can outlive the iterator with. Hot-path readers (dispatch
        conditionals) get index access without an allocation.)r)   Úshaper1   s    r,   r3   zTensorIterator.shape¬   s   € ð �z‰z×ÑÐr.   c                ó.   — | j                   j                  S r%   )r)   Únumelr1   s    r,   r5   zTensorIterator.numel¶   s   € à�z‰z×ÑÐr.   c                ó.   — | j                   j                  S r%   )r)   Úntensorsr1   s    r,   r7   zTensorIterator.ntensorsº   ó   € à�z‰z×"Ñ"Ð"r.   c                ó.   — | j                   j                  S r%   )r)   Úninputsr1   s    r,   r:   zTensorIterator.ninputs¾   s   € à�z‰z×!Ñ!Ð!r.   c                ó.   — | j                   j                  S r%   )r)   Únoutputsr1   s    r,   r<   zTensorIterator.noutputsÂ   r8   r.   c                ó.   — | j                   j                  S r%   )r)   Úis_contiguousr1   s    r,   r>   zTensorIterator.is_contiguousÆ   ó   € à�z‰z×'Ñ'Ð'r.   c                ó.   — | j                   j                  S r%   )r)   Úis_trivial_1dr1   s    r,   rA   zTensorIterator.is_trivial_1dÊ   r?   r.   c                ó.   — | j                   j                  S )aL  The inferred computation dtype, or ``None`` if no single dtype
        was inferred. Populated whenever TensorIterator can resolve a
        common dtype -- under promotion flags, or when every input
        already shares a dtype. ``None`` does not mean "promotion was
        not requested"; it means inference produced no answer.)r)   Úcommon_dtyper1   s    r,   rC   zTensorIterator.common_dtypeÎ   s   € ð �z‰z×&Ñ&Ð&r.   c                ó8   — | j                   j                  |«      S )at  Return the iterator's current operand at ``index``.

        Note: under ``promote_inputs_to_common_dtype`` /
        ``cast_common_dtype_to_outputs`` (CPU paths), this may be a
        promoted/cast kernel temporary rather than the tensor that was
        registered with the config -- it's the iterator's view of the
        operand a kernel would actually iterate over.)r)   Útensor©r*   Úindexs     r,   rE   zTensorIterator.tensor×   s   € ð �z‰z× Ñ  Ó'Ð'r.   c                ó8   — | j                   j                  |«      S )zbReturn the iterator's current input. See :meth:`tensor` for the
        promoted-temporary caveat.)r)   ÚinputrF   s     r,   rI   zTensorIterator.inputá   s   € ð �z‰z×Ñ Ó&Ð&r.   c                ó8   — | j                   j                  |«      S )z_Return the iterator's current output. See :meth:`tensor` for the
        cast-temporary caveat.)r)   ÚoutputrF   s     r,   rK   zTensorIterator.outputæ   s   € ð �z‰z× Ñ  Ó'Ð'r.   c                ó8   — | j                   j                  |«      S r%   )r)   ÚdtyperF   s     r,   rM   zTensorIterator.dtypeë   s   € Ø�z‰z×Ñ Ó&Ð&r.   c                ó8   — | j                   j                  |«      S r%   )r)   ÚdevicerF   s     r,   rO   zTensorIterator.deviceî   s   € Ø�z‰z× Ñ  Ó'Ð'r.   c                ó8   — | j                   j                  |«      S )aK  Per-operand strides in bytes (post reorder/coalesce), as a
        zero-copy ``memoryview`` of ``int64`` elements. The view holds a
        reference to this iterator and keeps it alive for as long as the
        view is reachable; copy via ``tuple(it.strides(i))`` if you need
        a snapshot you can outlive the iterator with.)r)   ÚstridesrF   s     r,   rQ   zTensorIterator.stridesñ   s   € ð �z‰z×!Ñ! %Ó(Ð(r.   c                ó8   — | j                   j                  |«      S )zÿPer-operand strides in elements (byte stride / element size).

        Allocates a fresh tuple on every call. Don't use on a hot path:
        cache the result, or read :meth:`strides` once and divide by
        :meth:`element_size` of the operand inline.)r)   Úelement_stridesrF   s     r,   rS   zTensorIterator.element_stridesù   s   € ð �z‰z×)Ñ)¨%Ó0Ð0r.   c                ó,   — t        | j                  «      S r%   )Úreprr)   r1   s    r,   Ú__repr__zTensorIterator.__repr__  s   € Ü�D—J‘JÓÐr.   )&r   z list[torch.Tensor | None] | Noner   úlist[torch.Tensor] | Noner   rW   r   Úboolr   rX   r   rX   r   rX   r   rX   r   rX   r   rX   r   rX   r   rX   r   rX   r   rX   r    útorch.dtype | Noner!   ztorch.device | Noner"   zSequence[int] | Noner#   zSequence[int]ÚreturnÚNone)rZ   Úint)rZ   Ú
memoryview)rZ   rX   )rZ   rY   )rG   r\   rZ   útorch.Tensor)r   )rG   r\   rZ   ztorch.dtype)rG   r\   rZ   ztorch.device)rG   r\   rZ   r]   )rG   r\   rZ   ztuple[int, ...])rZ   Ústr)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r-   Úpropertyr0   r3   r5   r7   r:   r<   r>   rA   rC   rE   rI   rK   rM   rO   rQ   rS   rV   r   r.   r,   r   r   :   sà  „ ñ:ð~ 59Ø,0Ø26Ø%)Ø&*Ø/4Ø05Ø-2Ø/4Ø).Ø#Ø"&Ø"'Ø"Ø+/Ø-1Ø-1Ø%'ñ)/4ð 2ð/4ð *ð	/4ð
 0ð/4ð #ð/4ð  $ð/4ð )-ð/4ð *.ð/4ð '+ð/4ð )-ð/4ð #'ð/4ð ð/4ð  ð/4ð  ð/4ð  ð!/4ð" )ð#/4ð$ +ð%/4ð& +ð'/4ð( #ð)/4ð* 
ó+/4ðb òó ðð ò ó ð ð ò ó ð ð ò#ó ð#ð ò"ó ð"ð ò#ó ð#ð ò(ó ð(ð ò(ó ð(ð ò'ó ð'ó(ô'ô
(ô
'ô(ó)ó1ô r.   r   c                ó*   — t        | g||gdddd¬«      S )z0Equivalent of ``at::TensorIterator::binary_op``.T)r   r   r   r   r   r   ©r   ©ÚoutÚaÚbs      r,   r	   r	   
  s)   € ô Ø�Ø˜�VØØ'+Ø%)Ø'+ôð r.   c           	     ó,   — t        | g||gddddd¬«      S )z6Equivalent of ``at::TensorIterator::binary_float_op``.T)r   r   r   r   r   r   r   rf   rg   s      r,   r
   r
     s,   € ô Ø�Ø˜�VØØ'+Ø%)Ø'+Ø(,ôð r.   c                ó˜   — | €t         j                  nd}| duxr | j                  t         j                  k7  }t        | g||gdd||¬«      S )aH  Equivalent of ``at::TensorIterator::comparison_op``.

    When ``out`` is ``None``, the output dtype is forced to bool. When ``out``
    is a defined non-bool tensor, the common dtype is cast back to its dtype
    via ``cast_common_dtype_to_outputs``. The bool-output case skips that cast
    as a performance optimization.
    NT)r   r   r   r   r   r    )ÚtorchrX   rM   r   )rh   ri   rj   r    Úcast_to_outputss        r,   r   r   '  sS   € ð "% ”5—:’:°$€LØ �oÒA¨#¯)©)´u·z±zÑ*A€OÜØ�Ø˜�VØØ'+Ø%4Ø!ôð r.   c                ó    — t        | g|g¬«      S )z/Equivalent of ``at::TensorIterator::unary_op``.)r   r   rf   ©rh   ri   s     r,   r   r   =  s   € ä 3 %°q°cÔ:Ð:r.   c                ó(   — t        | g|gdddd¬«      S )z5Equivalent of ``at::TensorIterator::unary_float_op``.T)r   r   r   r   r   r   rf   rp   s     r,   r   r   B  s%   € äØ�Ø�SØ'+Ø%)Ø'+Ø(,ôð r.   c                ó:   — | €t        d«      ‚t        | gdd¬«      S )z¼Equivalent of ``at::TensorIterator::nullary_op``.

    Unlike the binary/unary factories, ``out`` must be a defined tensor;
    the C++ named constructor takes a non-undefined output.
    zAnullary_op requires a defined output tensor; None is not allowed.F)r   r   r   )Ú	TypeErrorr   )rh   s    r,   r   r   N  s3   € ð €{ÜØOó
ð 	
ô Ø�Ø"Øôð r.   )Úout2c               ó6  — |��| j                   |j                   cxk(  r|j                   k(  s4n t        d| j                   › d|j                   › d|j                   › �«      ‚| j                  «       |j                  «       k7  r-t        d| j                  «       › d|j                  «       › �«      ‚| j                  |j                  k7  s!| j	                  «       |j	                  «       k7  rt        d«      ‚t        | |g|gdddd¬	«      S t        | g|gdddd¬
«      S )a½  Equivalent of ``at::TensorIterator::reduce_op``.

    Pass ``out2`` for the two-output reduction overload (e.g. ``min`` returning
    values + indices). The output tensor(s) must be pre-allocated and shaped
    correctly: this factory does not allocate or resize. With ``out2``, both
    outputs must live on ``a``'s device and share its sizes/strides -- the
    C++ named constructor asserts this and the same checks are mirrored
    here.
    zAreduce_op: out, out2, and the input must share a device, got out=z, out2=z, a=z4reduce_op: out and out2 must have the same dim, got z and z=reduce_op: out and out2 must have identical sizes and stridesFT)r   r   r   r   r   r   )r   r   r   r   r   r   )rO   ÚRuntimeErrorÚdimr3   Ústrider   )rh   ri   rt   s      r,   r   r   _  s  € ð( ÑØ�z‰z˜QŸX™XÔ4¨¯©Ô4ÜðØŸ:™:˜, g¨d¯k©k¨]¸$¸q¿x¹x¸jðJóð ð �7‰7‹9˜Ÿ™›
Ò"ÜØFØ—7‘7“9�+˜U 4§8¡8£: ,ð0óð ð �9‰9˜Ÿ
™
Ò" c§j¡j£l°d·k±k³mÒ&CÜØOóð ô Ø˜$�KØ˜Ø!&Ø Ø#Øô
ð 	
ô Ø�Ø�SØ'+ØØØôð r.   )rh   útorch.Tensor | Noneri   r^   rj   r^   rZ   r   )rh   ry   ri   r^   rZ   r   )rh   r^   rZ   r   )rh   r^   ri   r^   rt   ry   rZ   r   )rc   Ú
__future__r   Útypingr   rm   Útorch._Cr   Ú_CTensorIteratorr   r&   Úcollections.abcr   Ú__all__r   r	   r
   r   r   r   r   r   r   r.   r,   ú<module>r€      sâ   ðñõ< #å  ã ÷ñ Ý(ò	€÷H ñ H ð`Ø	ðØ!-ðØ2>ðàóðØ	ðØ!-ðØ2>ðàóðØ	ðØ!-ðØ2>ðàóó,;ó
	óð* !%ñ	2Ø	ð2àð2ð ð	2ð
 ô2r.   