
    ^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    , $%(/(;tG}&,&8d6lb2>2JD.PR$8!%:".L+/N,,H).L+(@%,!2!2(# ,D$!.D# $\ 2D#K0D'+zz|
    c                .    | j                   j                  S r%   )r)   ndimr*   s    r,   r0   zTensorIterator.ndim   s    zz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     zzr.   c                .    | j                   j                  S r%   )r)   numelr1   s    r,   r5   zTensorIterator.numel   s    zzr.   c                .    | j                   j                  S r%   )r)   ntensorsr1   s    r,   r7   zTensorIterator.ntensors       zz"""r.   c                .    | j                   j                  S r%   )r)   ninputsr1   s    r,   r:   zTensorIterator.ninputs   s    zz!!!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       zz'''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     zz&&&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     zz  ''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     zz&&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     zz  ''r.   c                8    | j                   j                  |      S r%   )r)   dtyperF   s     r,   rM   zTensorIterator.dtype   s    zz&&r.   c                8    | j                   j                  |      S r%   )r)   devicerF   s     r,   rO   zTensorIterator.device   s    zz  ''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     zz!!%((r.   c                8    | j                   j                  |      S )zPer-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     zz))%00r.   c                ,    t        | j                        S r%   )reprr)   r1   s    r,   __repr__zTensorIterator.__repr__  s    DJJ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,026%)&*/405-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* 
+/4b           # # " " # # ( ( ( ( ' '('
(
'()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#))uzz*AO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%qc::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 )zEquivalent 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   ( zzQXX44::,gdkk]$qxxjJ  779
"F779+U488:,0  99

"cjjldkkm&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.   