U
    qhn                     @  s  d dl mZ d dlZd dlmZmZ d dlZd dlm	Z
 d dlmZmZmZmZmZmZ d dlmZmZ dddd	d
ZdZddddddZdddddddZejeddgdZd[ddddddddZddddddd ZejeddgdZd\ddddddd!d"Zd#d$ddd%d&d'Zd]d)d*dd+d,d-Zd^d)d*dd+d.d/Z d_dd0d)d1d2d3Z!d`dd0d)d4d5d6Z"d7d8d9d:d;Z#dad8d0d<d7d=d>d?Z$d@dAdBdCdDZ%dbdAd0d@dEdFdGZ&dHdIdJdKdLZ'dcdId0d<dHdMdNdOZ(d)dPdQdRdSZ)dddUdVdddWdXdYZ*dS )e    )annotationsN)AnySequence)MapProtoOptionalProtoSequenceProtoTensorProtohelpersubbyte)load_external_data_for_tensoruses_external_datazSequence[int]zlist[complex])fareturnc                   s    fddt t d D S )Nc                   s*   g | ]"}t  |d    |d  d  qS )      )complex).0ir    5/tmp/pip-unpacked-wheel-xnis5xre/onnx/numpy_helper.py
<listcomp>   s     z,combine_pairs_to_complex.<locals>.<listcomp>r   )rangelenr   r   r   r   combine_pairs_to_complex   s    r   z np.int16 | np.int32 | np.ndarrayzint | Sequence[int] | Nonez
np.ndarray)datadimsr   c                 C  sx   dd }|dkrZt | jdkrB|t| gtjtjd S || tjtjS || tj|tjS )a_  Converts ndarray of bf16 (as uint32) to f32 (as uint32).

    Args:
        data: A numpy array, empty dimensions are allowed if dims is
            None.
        dims: If specified, the function reshapes the results.

    Returns:
        A numpy array of float32 with the same dimension if dims is
        None, or reshaped to dims if specified
    c                 S  s   | d> S )N   r   xr   r   r   <lambda>#       z%bfloat16_to_float32.<locals>.<lambda>Nr   )	r   shapenparrayastypeint32viewfloat32reshape)r   r   shiftr   r   r   bfloat16_to_float32   s    $r+   intboolz
np.float32)ivalfnuzr   c           	      C  s\  |st d| dk s| dkr*t|  d|rBd}| dkrptjS n.d}| dkr\ttj S | dkrpttjS t| } | d	@ d
? }| d@ }| d@ }|d> }|dkr"|dkrFd| }|d@ dkr|d
M }|dK }|d8 }|d@ dkr|d
M }|dK }|d8 }||d
@ d> O }||d> O }n$||d> O }|d| 7 }||d> O }t|tj}|S )Nzfn=False is not implemented.r      z is not a float8.            x            r            )NotImplementedError
ValueErrorr#   nanr(   uint32r'   	r.   r/   r0   Zexponent_biasZexpoZmantsignresfr   r   r   _float8e4m3_to_float32_scalar+   sH    


rE   r/   r0   )ZexcludedTF)r   r   r/   r0   r   c                 C  s0   |st dt| ||d}|dkr&|S ||S )a  Converts ndarray of float8, e4m3 (as uint32) to f32 (as uint32).

    See :ref:`onnx-detail-float8` for technical details.

    Args:
        data: A numpy array, empty dimensions are allowed if dims is None.
        dims: If specified, the function reshapes the results.
        fn: No infinite values.
        uz: No negative zero.

    Returns:
        A numpy array of float32 with the same dimension if dims is None,
        or reshaped to dims if specified.
    z4float32_to_float8e4m3 not implemented with fn=False.r/   r0   N)r=   _float8e4m3_to_float32r)   r   r   r/   r0   rC   r   r   r   float8e4m3_to_float32Z   s    rI   c           	      C  sR  |r"|r"| dkrt t jS d}nj|s|s| dkr@t t j S | dkrTt t jS | dkrjt t j S | dkr~t t jS d}ntdt | } | d@ d	? }| d
@ }| d@ }|d> }|dkr|dkr<d| }|d	@ dkr|dM }|dK }|d8 }||d@ d> O }||d> O }n$||d> O }|d| 7 }||d> O }t |t j}|S )Nr3   r   >         r1   >   }   ~   r5      |      z%fn and uz must be both False or True.r   r7   r8   r   r5   r      r;   r:   )r#   r(   r?   infr=   r@   r'   rA   r   r   r   _float8e5m2_to_float32_scalarx   sD    


rS   c                 C  s$   t | ||d}|dkr|S ||S )a  Converts ndarray of float8, e5m2 (as uint32) to f32 (as uint32).

    See :ref:`onnx-detail-float8` for technical details.

    Args:
        data: A numpy array, empty dimensions are allowed if dims is None.
        dims: If specified, the function reshapes the results.
        fn: No infinite values.
        uz: No negative zero.

    Returns:
        A numpy array of float32 with the same dimension if dims is None,
        or reshaped to dims if specified
    rF   N)_float8e5m2_to_float32r)   rH   r   r   r   float8e5m2_to_float32   s    rU   znp.int32 | np.ndarrayzint | Sequence[int])r   r   signedr   c                   s    fdd}t |dd}||  \}}t j|j|j ft jd}||ddd< ||ddd< |jt |d kr| dd }||}|S )	a  Converts ndarray of int4 (as packed uint8) to f32
    See :ref:`onnx-detail-int4` for technical details.

    Args:
        data: A numpy array, empty dimensions are allowed if dims is
            None.
        dims: The dimensions are used to reshape the unpacked buffer
        signed: Whether the 4 bit integer is signed or unsigned

    Returns:
        A numpy array of float32 reshaped to dims.
    c                   s   t |  S N)r
   Zunpack_single_4bitx2r   rV   r   r   r       r!   zunpack_int4.<locals>.<lambda>r   r   dtyper   N)r#   Z
frompyfuncravelemptysizer(   prodr)   )r   r   rV   Zsingle_funcfuncZres_highZres_lowrC   r   rX   r   unpack_int4   s    
ra    r   str)tensorbase_dirr   c                 C  s  |  drtd| jtjkr&td| j}t|}tt|}t	|}| j
}| jtjkrt| |}dd |D }t|||S t| rt| | |  dr| j}	tjdkrtj|	|d  }	|tjkrtj|	tjd}
t|
|S |tjkrtj|	tjd}
t|
|S |tjkrHtj|	tjd}
t|
|d	d
S |tj krntj|	tjd}
t!|
|S |tj"krtj|	tjd}
t!|
|d	d	dS |tj#krtj|	tj$d}
t%|
|ddS |tj&krtj|	tjd}
t%|
|d	dS tj|	|d|S |tj'kr.tj| j(tj)d|*tj+S |tjkrVtj| j(tj,d}
t|
|S |tjkr~tj| j(tj,d}
t|
|S |tjkrtj| j(tj,d}
t|
|d	d
S |tj krtj| j(tj,d}
t!|
|S |tj"kr tj| j(tj,d}
t!|
|d	d	dS |tj#kr*tj| j(|d}
t%|
|ddS |tj&krTtj| j(|d}
t%|
|d	dS t| |}
|tj-tj.fkrxt/|
}
tj|
|d||S )zConverts a tensor def object to a numpy array.

    Args:
        tensor: a TensorProto object.
        base_dir: if external tensor exists, base_dir can help to find the path to it

    Returns:
        arr: the converted array.
    segmentz*Currently not supporting loading segments.z4The element type in the input tensor is not defined.c                 S  s   g | ]}| d qS )utf-8)decode)r   sr   r   r   r      s     z_to_array.<locals>.<listcomp>raw_databigrY   T)r0   rF   FrX   )0HasFieldr>   	data_typer   	UNDEFINED	TypeErrorr	   tensor_dtype_to_np_dtypeZ$tensor_dtype_to_storage_tensor_dtypeZtensor_dtype_to_fieldr   STRINGgetattrr#   Zasarrayr%   r)   r   r   rj   sys	byteorder
frombufferbyteswaptobytesBFLOAT16int16r+   FLOAT8E4M3FNint8rI   FLOAT8E4M3FNUZ
FLOAT8E5M2rU   FLOAT8E5M2FNUZUINT4uint8ra   INT4ZFLOAT16
int32_datauint16r'   Zfloat16r&   Z	COMPLEX64Z
COMPLEX128r   )rd   re   tensor_dtypenp_dtypeZstorage_np_dtypeZstorage_fieldr   Zutf8_stringsssrj   r   r   r   r   	_to_array   s    














r   c                 C  s  | j }|tjkrjt| r"t| | | j}t| j}tj	|t
jd }t|D ]\}}|||< qN||S |tjtjtjtjfkrtjt
jtjt
jtjt
jtjt
ji}t| rt| | | dr| j}n| j}t| j}tj	||| d }t|D ]\}}|||< q||S |tjtjfkrt| r<t| | | drP| j}n| j}t| j}tjt
jtjt
ji}|| }	|tjk}
tj	t|tjd }t|D ]\}}|||< qt|||
d}| |	S t!| |dS )a+  Converts a tensor def object to a numpy array.
    Supports types defined in :mod:`onnx._custom_element_types`.

    Args:
        tensor: a TensorProto object.
        base_dir: if external tensor exists, base_dir can help to find the path to it

    Returns:
        arr: the converted array.
    rY   rj   )r   rV   )re   )"rm   r   rx   r   r   r   tupler   r#   r]   custom_np_typesbfloat16r\   	enumerater)   rz   r|   r}   r~   float8e4m3fnfloat8e4m3fnuz
float8e5m2float8e5m2fnuzrl   rj   r   r   int4uint4r   r   ra   r%   r   )rd   re   	elem_typer   r"   yr   dmrZ   rV   Zunpacked_datar   r   r   to_arrayR  sn    




    







  

r   z
str | None)arrnamer   c              
   C  s  t | tjtjfs$tdt|  t }|j| j	 |rB||_
| jtks^t| jtjrt| j|_|  }|D ]}t |tr|j|d qxt |tjr|D ]8}t |tr|j|d qt |tr|j| qqxt |tr|j| qxtdtt|qx|S zt| j}W n6 tk
r\ } ztd| j|W 5 d}~X Y nX ||_|  |_tjdkrt| |S )zConverts a numpy array to a tensor def.

    Args:
        arr: a numpy array.
        name: (optional) the name of the tensor.

    Returns:
        TensorProto: the converted tensor def.
    z2arr must be of type np.generic or np.ndarray, got rg   zMUnrecognized object in the object array, expect a string, or array of bytes: z$Numpy data type not understood yet: Nrk   ) 
isinstancer#   ndarrayZgenericro   typer   r   extendr"   r   rZ   objectZ
issubdtypeZstr_r	   np_dtype_to_tensor_dtyperm   flattenrc   Zstring_dataappendencodebytesr=   KeyErrorRuntimeErrorrw   rj   rs   rt   convert_endian)r   r   rd   Z
flat_arrayeri   rZ   r   r   r   _from_array  sH    






$
r   )rd   r   r   c           	      C  s
  t | tjst| |S | j}|tjkrH|jd d dkrHtj	}tj
}n|tjkrr|jd d dkrrtj}tj
}n|tjkr|jd d dkrtj}tj
}n|tjkr|jd d dkrtj}tj
}n|tjkr|jd d dkrtj}tj}nf|tjkr|jd d dkrtj}tj}n8|tjkrL|jd d dkrLtj}tj
}n
t| |S |tjtjfkr| | }|jd	 d
krtd| j d|ddd	 d@ |d
dd	 d>  }t }|j| j |r||_ |! |_"||_#|S t| ||}||_#|S )a  Converts an array into a TensorProto including
    supported type defined in :mod:`onnx._custom_element_types`.

    Args:
        tensor: a numpy array.
        name: (optional) the name of the tensor.

    Returns:
        TensorProto: the converted tensor def.
    r   Ze4m3fnZe4m3fnuzZe5m2Ze5m2fnuzr   r   r   r   r   zIThe conversion of a tensor of INT4 or UINT4 requires an even size (shape=z+). Every byte stores two INT4 or two UINT4.NrP   r9   )$r   r#   r   r   rZ   r   r   descrr   rz   r   r   r|   r   r}   r   r~   r   rx   r   r   r   r{   r   r   r%   r\   r^   r>   r"   r   r   r   rw   rj   rm   )	rd   r   dttoZdt_tovaluebufferZpbtr   r   r   
from_array  sT    

  
$
r   r   z	list[Any])sequencer   c                 C  sz   | j }|tjkr dd | jD S |tjkr:dd | jD S |tjkrTdd | jD S |tjkrndd | j	D S t
ddS )zConverts a sequence def to a Python list.

    Args:
        sequence: a SequenceProto object.

    Returns:
        list: the converted list.
    c                 S  s   g | ]}t |qS r   r   r   vr   r   r   r   #  s     zto_list.<locals>.<listcomp>c                 S  s   g | ]}t |qS r   r   r   r   r   r   r   %  s     c                 S  s   g | ]}t |qS r   )to_listr   r   r   r   r   '  s     c                 S  s   g | ]}t |qS r   )to_dictr   r   r   r   r   )  s     z8The element type in the input sequence is not supported.N)r   r   TENSORtensor_valuesSPARSE_TENSORZsparse_tensor_valuesSEQUENCEsequence_valuesMAP
map_valuesro   )r   r   r   r   r   r     s    	



r   z
int | None)lstr   rZ   r   c           	        s  t  }|r||_|r|}nFt dkrZ d }t|tr@t j}q`t|trRt j}q`t j}nt j}||_	t dkrt
 fdd D std|t jkr D ]}|jt|g qnZ|t jkr D ]}|jt|g qn2|t jkr
 D ]}|jt|g qntd|S )a]  Converts a list into a sequence def.

    Args:
        lst: a Python list
        name: (optional) the name of the sequence.
        dtype: (optional) type of element in the input list, used for specifying
                          sequence values when converting an empty list.

    Returns:
        SequenceProto: the converted sequence def.
    r   c                 3  s    | ]}t |t d  V  qdS )r   N)r   r   )r   elemr   r   r   	<genexpr>O  s     zfrom_list.<locals>.<genexpr>zqThe element type in the input list is not the same for all elements and therefore is not supported as a sequence.zZThe element type in the input list is not a tensor, sequence, or map and is not supported.)r   r   r   r   dictr   listr   r   r   allro   r   r   r   r   	from_listr   	from_dict)	r   r   rZ   r   r   Z
first_elemrd   seqmappingr   r   r   r   -  s>    

"

r   r   zdict[Any, Any])	map_protor   c                 C  s`   g }| j tjkrt| j}n
t| j}t| j}t|t|krNt	d| j
dtt||}|S )zConverts a map def to a Python dictionary.

    Args:
        map_proto: a MapProto object.

    Returns:
        The converted dictionary.
    z2Length of keys and values for MapProto (map name: z) are not the same.)key_typer   rq   r   string_keyskeysr   valuesr   
IndexErrorr   r   zip)r   Zkey_listZ
value_list
dictionaryr   r   r   r   f  s    	

r   )dict_r   r   c                   s   t  }|r||_t| }t|d  t }tjtj	tj
tjtjtjtjtjg}t fdd|D srtdt|  }t|d tfdd|D stdt|}||_|tjkr|j| n||kr|j| |j| |S )zConverts a Python dictionary into a map def.

    Args:
        dict_: Python dictionary
        name: (optional) the name of the map.

    Returns:
        MapProto: the converted map def.
    r   c                 3  s   | ]}t | kV  qd S rW   r#   result_type)r   key)raw_key_typer   r   r     s   zfrom_dict.<locals>.<genexpr>zfThe key type in the input dictionary is not the same for all keys and therefore is not valid as a map.c                 3  s   | ]}t | kV  qd S rW   r   )r   val)raw_value_typer   r   r     s     zjThe value type in the input dictionary is not the same for all values and therefore is not valid as a map.)r   r   r   r#   r   r	   r   r   ZINT8ZINT16ZINT32ZINT64ZUINT8ZUINT16ZUINT32ZUINT64r   ro   r   r   r   rq   r   r   r   CopyFrom)r   r   r   r   r   Zvalid_key_int_typesr   Z	value_seqr   )r   r   r   r     sH    


r   r   z
Any | None)optionalr   c                 C  s   | j }|tjkrdS |tjkr(t| jS |tjkr<t| jS |tjkrPt	| j
S |tjkrdt| jS |tjkrxt| jS tddS )zConverts an optional def to a Python optional.

    Args:
        optional: an OptionalProto object.

    Returns:
        opt: the converted optional.
    Nz8The element type in the input optional is not supported.)r   r   rn   r   r   tensor_valuer   Zsparse_tensor_valuer   r   sequence_valuer   r   	map_valueOPTIONALto_optionalZoptional_valuero   )r   r   r   r   r   r     s    	










r   )optr   rZ   r   c                 C  s   t  }|r||_|r>tt j }||kr8t| d|}n:t| trPt j}n(t| trbt j	}n| dkrrt j
}nt j}||_| dk	r|t jkr|jt|  n@|t j	kr|jt|  n$|t jkr|jt|  ntd|S )a  Converts an optional value into a Optional def.

    Args:
        opt: a Python optional
        name: (optional) the name of the optional.
        dtype: (optional) type of element in the input, used for specifying
                          optional values when converting empty none. dtype must
                          be a valid OptionalProto.DataType value

    Returns:
        optional: the converted optional def.
    z( must be a valid OptionalProto.DataType.NzUThe element type in the input is not a tensor, sequence, or map and is not supported.)r   r   r   ZDataTyper   ro   r   r   r   r   rn   r   r   r   r   r   r   r   r   r   )r   r   rZ   r   Zvalid_dtypesr   r   r   r   from_optional  s6    




r   None)rd   r   c                 C  s.   | j }t|}tj| j|d  | _dS )znCall to convert endianness of raw data in tensor.

    Args:
        tensor: TensorProto to be converted.
    rY   N)rm   r	   rp   r#   ru   rj   rv   rw   )rd   r   r   r   r   r   r     s    
r   r   z
tuple[int]znp.dtype)input_shaperZ   seedr   c              	   C  s   t j| |t jt jt jt jt jt jt j	t j
fkrtt |jt t j	j}tt |jt t j	j}t jj||| d|S t| ddS )a'  Create random integer array for backend/test/case/node.

    Args:
        input_shape: The shape for the returned integer array.
        dtype: The NumPy data type for the returned integer array.
        seed: The seed for np.random.

    Returns:
        np.ndarray: Random integer array.
    )r^   z' is not supported by create_random_int.N)r#   randomr   r   r   r@   Zuint64r{   ry   r&   Zint64minZiinfomaxrandintr%   ro   )r   rZ   r   endstartr   r   r   create_random_int  s    r   )N)NTF)NFF)rb   )rb   )N)N)NN)N)NN)r   )+
__future__r   rs   typingr   r   Znumpyr#   Zonnx._custom_element_typesZ_custom_element_typesr   Zonnxr   r   r   r   r	   r
   Zonnx.external_data_helperr   r   r   r+   rE   Z	vectorizerG   rI   rS   rT   rU   ra   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sZ     *    (    !rHA=   9:   4 