o
    Xi,                     @  s   d Z ddlmZ ddgZddlZddlmZmZ ddlZ	ddl
Z
ddlmZmZmZmZmZmZ ejr=ddlmZ ddlZ			d1d2ddZ	d3dddddddddd	d4d&dZ		d5dddd'd6d/d0ZdS )7z(Convenience constructors for IR objects.    )annotationstensornodeN)MappingSequence)_convenience_core_enums
_protocolsserdetensor_adaptersvalueKnpt.ArrayLike | onnx.TensorProto | ir.DLPackCompatible | ir.ArrayCompatibledtypeir.DataType | Nonename
str | None
doc_stringreturn_protocols.TensorProtocolc                 C  s6  t | tjr|dur|| jkrtd| d| j d| S t | tjrMt| }|dur/||_	|dur6||_
|durK||jkrKtd| d|j d|S tt| dkr]tj| ||d	S t | tjtjfrotj| |||d
S |durt |tjstd| | }nTt | tr| stdt | trt | tsttj}n8t | trttj}n,t | tr| rtdd | D rttj}ntdd | D rttj}nd}nd}tj| |d}t | tst | tr| rtdd | D rtj j!|dd}tj"|t#|j$||dS tj||t#|j$||dS )ac  Create a tensor value from an ArrayLike object or a TensorProto.

    The dtype must match the value. Reinterpretation of the value is
    not supported, unless if the value is a plain Python object, in which case
    it is converted to a numpy array with the given dtype.

    ``value`` can be a numpy array, a plain Python object, or a TensorProto.

    .. warning::
        For 4bit dtypes, the value must be unpacked. Use :class:`~onnx_ir.PackedTensor`
        to create a tensor with packed data.

    Example::

        >>> import onnx_ir as ir
        >>> import numpy as np
        >>> import ml_dtypes
        >>> import onnx
        >>> ir.tensor(np.array([1, 2, 3], dtype=np.int16))
        Tensor<INT16,[3]>(array([1, 2, 3], dtype=int16), name=None)
        >>> ir.tensor([1, 2, 3], dtype=ir.DataType.BFLOAT16)
        Tensor<BFLOAT16,[3]>(array([1, 2, 3], dtype=bfloat16), name=None)
        >>> tp_tensor = ir.tensor(onnx.helper.make_tensor("tensor", onnx.TensorProto.FLOAT, dims=[], vals=[0.5]))
        >>> tp_tensor.numpy()
        array(0.5, dtype=float32)
        >>> import torch
        >>> ir.tensor(torch.tensor([1.0, 2.0]), name="torch_tensor")
        TorchTensor<FLOAT,[2]>(tensor([1., 2.]), name='torch_tensor')

    Args:
        value: The numpy array to create the tensor from.
        dtype: The data type of the tensor.
        name: The name of the tensor.
        doc_string: The documentation string of the tensor.

    Returns:
        A tensor value.

    Raises:
        ValueError: If the dtype does not match the value when value is not a plain Python
            object like ``list[int]``.
    Nz=The dtype must match the value when value is a Tensor. dtype=z, value.dtype=z>. You do not have to specify the dtype when value is a Tensor.zBThe dtype must match the value when value is a TensorProto. dtype=z, value.data_type=zAYou do not have to specify the dtype when value is a TensorProto.z<class 'torch.Tensor'>)r   r   )r   r   r   z-dtype must be an instance of DataType. dtype=z8dtype must be specified when value is an empty sequence.c                 s  s&    | ]}t |tot |t V  qd S N)
isinstanceintbool.0elem r   V/home/ubuntu/.local/lib/python3.10/site-packages/onnx_ir/_convenience/_constructors.py	<genexpr>r   s   $ ztensor.<locals>.<genexpr>c                 s      | ]}t |tV  qd S r   )r   floatr   r   r   r   r   t       )r   c                 s  r    r   )r   strr   r   r   r   r      r"   zutf-8)encoding)shaper   r   )r   r%   r   r   )%r   r
   TensorProtocolr   
ValueErroronnxTensorProtor   deserialize_tensorr   r   r#   typer   TorchTensorDLPackCompatibleArrayCompatibler   Tensorr	   DataType	TypeErrornumpyr   r   r   npint64r!   float32allarraystringsencodeStringTensorShaper%   )r   r   r   r   tensor_numpy_dtyper7   r   r   r   r      sx   0





 )	domainoverloadnum_outputsoutputsversiongraphr   r   metadata_propsop_typer#   inputsSequence[ir.Value | None]
attributes4Mapping[str, _convenience.SupportedAttrTypes] | Noner?   r@   rA   
int | NonerB   Sequence[ir.Value] | NonerC   rD   ir.Graph | NonerE   dict[str, str] | Noneir.Nodec       	         C  s:   |du rd}nt |}tj|| ||||||||	|
|dS )a  Create a :class:`~onnx_ir.Node`.

    This is a convenience constructor for creating a Node that supports Python
    objects as attributes.

    Example::

        >>> import onnx_ir as ir
        >>> input_a = ir.val("A", shape=[1, 2], type=ir.TensorType(ir.DataType.INT32))
        >>> input_b = ir.val("B", shape=[1, 2], type=ir.TensorType(ir.DataType.INT32))
        >>> node = ir.node(
        ...     "SomeOp",
        ...     inputs=[input_a, input_b],
        ...     attributes={"alpha": 1.0, "some_list": [1, 2, 3]},
        ...     domain="some.domain",
        ...     name="node_name"
        ... )
        >>> node.op_type
        'SomeOp'

    Args:
        op_type: The name of the operator.
        inputs: The input values. When an input is None, it is an empty input.
        attributes: The attributes. RefAttr can be used only when the node is defined in a Function.
        overload: The overload name when the node is invoking a function.
        domain: The domain of the operator. For onnx operators, this is an empty string.
        num_outputs: The number of outputs of the node. If not specified, the number is 1.
        outputs: The output values. If None, the outputs are created during initialization.
        version: The version of the operator. If None, the version is unspecified and will follow that of the graph.
        graph: The graph that the node belongs to. If None, the node is not added to any graph.
            A `Node` must belong to zero or one graph.
        name: The name of the node. If None, the node is anonymous.
        doc_string: The documentation string.
        metadata_props: The metadata properties.

    Returns:
        A node with the given op_type and inputs.
    Nr   )r?   rF   rG   rI   r@   rA   rB   rC   rD   r   r   rE   )r   convert_attributesr   Node)rF   rG   rI   r?   r@   rA   rB   rC   rD   r   r   rE   attrsr   r   r   r      s"   5
)r+   const_valuerE   r%   ,ir.Shape | Sequence[int | str | None] | Noner+   ir.TypeProtocol | NonerS   ir.TensorProtocol | Noneir.Valuec                C  s   |durXt |j}|dur||krtd| d| d|dur2||jkr2td| d|j d|durJt ||jkrJtd| d	|j d
t j| |t |j||dS |du re|duret |}|durtt|t jstt |}t j| |||dS )a8  Create a :class:`~onnx_ir.Value` with the given name and type.

    This is a convenience constructor for creating a Value that allows you to specify
    dtype and shape in a more relaxed manner. Whereas to create a Value directly, you
    need to create a :class:`~onnx_ir.TypeProtocol` and :class:`~onnx_ir.Shape` object
    first, this function allows you to specify dtype as a :class:`~onnx_ir.DataType`
    and shape as a sequence of integers or symbolic dimensions.

    Example::

        >>> import onnx_ir as ir
        >>> t = ir.val("x", ir.DataType.FLOAT, ["N", 42, 3])
        >>> t.name
        'x'
        >>> t.type
        Tensor(FLOAT)
        >>> t.shape
        Shape([SymbolicDim(N), 42, 3])

    .. versionadded:: 0.1.9

    Args:
        name: The name of the value.
        dtype: The data type of the TensorType of the value. This is used only when type is None.
        shape: The shape of the value.
        type: The type of the value. Only one of dtype and type can be specified.
        const_value: The constant tensor that initializes the value. Supply this argument
            when you want to create an initializer. The type and shape can be obtained from the tensor.
        metadata_props: The metadata properties that will be serialized to the ONNX proto.

    Returns:
        A Value object.
    Nz.The type does not match the const_value. type=z but const_value has type zC. You do not have to specify the type when const_value is provided.z0The dtype does not match the const_value. dtype=z but const_value has dtype zD. You do not have to specify the dtype when const_value is provided.z0The shape does not match the const_value. shape=z but const_value has shape zD. You do not have to specify the shape when const_value is provided.)r   r+   r%   rS   rE   )r   r+   r%   rE   )r   
TensorTyper   r'   r;   r%   Valuer   )r   r   r%   r+   rS   rE   const_tensor_typer   r   r   val   s4   *


r[   )NNN)
r   r   r   r   r   r   r   r   r   r   r   )rF   r#   rG   rH   rI   rJ   r?   r#   r@   r#   rA   rK   rB   rL   rC   rK   rD   rM   r   r   r   r   rE   rN   r   rO   )NN)r   r   r   r   r%   rT   r+   rU   rS   rV   rE   rN   r   rW   )__doc__
__future__r   __all__typingcollections.abcr   r   r2   r3   r(   onnx_irr   r   r	   r
   r   r   TYPE_CHECKINGnumpy.typingnptirr   r   r[   r   r   r   r   <module>   sH    |K