U
    <ºcè!  ã                   @   s4  d Z ddl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 ejjjZe d¡ dekrzee
eee	eegƒrze d¡ d-dd„Zddejfd	d
„Zdd„ Zddejfdd„Zdejfdd„Zdd„ Zdd„ Zedd„ ƒZedd„ ƒZdd„ Zdd„ Zdd „ Z d!d"„ Z!d#d$„ Z"d%d&„ Z#d'd(„ Z$d)d*„ Z%d+d,„ Z&dS ).z`Importing this file includes common utility methods for checking quantized
tensors and modules.
é    N)Úcontextmanager)ÚTEST_WITH_ASANÚTEST_WITH_TSANÚTEST_WITH_UBSANÚIS_PPCÚIS_MACOSÚ
IS_WINDOWSÚnoneÚqnnpackc                 C   s6   t  | d|  | |d |d   | ¡d|  d S )z7Computes the output shape given convolution parameters.é   é   )ÚnpÚfloor)Z
input_sizeZkernel_sizeÚpaddingZstrideZdilationZoutput_padding© r   úL/tmp/pip-unpacked-wheel-gikjz4vx/torch/testing/_internal/common_quantized.pyÚ_conv_output_shape   s    ÿÿÿÿr   c                 C   s^   |dkrt  |¡j}|dkr(t  |¡j}t  | | | ¡ t j¡}t  |||¡}| |¡}|S )zQuantizes a numpy array.N)r   ÚiinfoÚminÚmaxÚroundÚastypeÚint64Úclip)ÚxÚscaleÚ
zero_pointÚqminÚqmaxÚdtypeÚqxr   r   r   Ú	_quantize   s    
r!   c                 C   s   |   t¡| | }|S )zDequantizes a numpy array.)r   Úfloat)r    r   r   r   r   r   r   Ú_dequantize$   s    r#   éÿ   c                 C   s(   | |   ¡ | }t |||¡ |¡}|S )zhRequantizes a numpy array, i.e., intermediate int32 or int16 values are
    converted back to given type)r   r   r   r   )r   Z
multiplierr   r   r   Zqtyper    r   r   r   Ú_requantize*   s    r%   Fc                 C   sP  |t jt jfkst‚|t jkr,|t jks,t‚t| t jƒr@|  ¡ } |t jkrb|rXd\}}qxd\}}n|rpd\}}nd\}}|  ¡ }|  	¡ }|t jk}||kr¤d}	d}
nœ|rät	|| ƒ}| }|| ||  }	t	|	t
 t
j¡jƒ}	d}
n\t	|dƒ}t|dƒ}|| ||  }	t	|	t
 t
j¡jƒ}	|t||	 ƒ }
t	||
ƒ}
t||
ƒ}
t|	ƒt|
ƒgS )úxCalculate the dynamic quantization parameters (scale, zero_point)
    according to the min and max element of the tensor)iÀÿÿÿé?   )i€ÿÿÿé   )r   r(   )r   r$   ç      ð?r   ç        )ÚtorchÚper_tensor_affineZper_tensor_symmetricÚAssertionErrorZqint8Ú
isinstanceÚTensorÚnumpyr   r   r   ÚfinfoÚfloat32Úepsr   r"   Úint)ÚXr   Zreduce_rangeZqschemer   r   Úmin_valÚmax_valZis_symmetricr   r   r   r   r   Ú_calculate_dynamic_qparams1   s@    









r8   c           
      C   s$  t | tjƒr|  ¡ } t |¡jt |¡j }}|| }tj| j	d tj
d}tj| j	d tjd}t|j	d ƒD ]ª}|  ¡ }|  ¡ }	||	kržd||< d||< qpt|	dƒ}	t|dƒ}|	| | ||< t|| t tj¡jƒ||< |t|||  ƒ ||< t||| ƒ||< t||| ƒ||< qp||fS )r&   r   )r   r)   r*   )r.   r+   r/   r0   r   r   r   r   ÚzerosÚshapeZfloat64r   Úranger1   r2   r3   r   )
r5   r   r   r   Zn_levelsr   r   Úir6   r7   r   r   r   Ú&_calculate_dynamic_per_channel_qparamsZ   s(    


r=   c                 C   s¼   t | ttfƒrTt| ƒt|ƒks"t‚g }tt| ƒƒD ]}| t| | || ƒ¡ q2|S |jrb| 	¡ }| jrp|  	¡ } | |  
¡ }|dkr–dtdƒtdƒfS |  
¡ }|| }d| ¡  }|||fS )a°  Calculates the signal to noise ratio and returns the signal and noise
    power, as well as the SNR in dB.
    If the input is a list/tuple this function is called recursively on each
    element. The result will have the same nested structure as the inputs.

    Args:
        x, x_hat: Either a tensor or a nested list/tuple of tensors.
    Returns:
        signal, noise, SNR(in dB): Either floats or a nested list of floats
    r   r*   Úinfé   )r.   ÚlistÚtupleÚlenr-   r;   ÚappendÚ_snrZis_quantizedZ
dequantizeZnormr"   Úlog10)r   Zx_hatÚresÚidxZnoiseÚsignalZsnrZsnr_dbr   r   r   rD   t   s"    rD   c                 c   s0   t jjj}| t jj_z
d V  W 5 |t jj_X d S ©N©r+   ÚbackendsÚ	quantizedZengine)ÚqengineÚpreviousr   r   r   Úoverride_quantized_engine‘   s
    


rO   c                 c   s.   z| rt j ¡  d V  W 5 | r(t j ¡  X d S rI   )r+   Z_CZ#_unset_default_mobile_cpu_allocatorZ!_set_default_mobile_cpu_allocator)Úqengine_is_qnnpackr   r   r   Ú"override_cpu_allocator_for_qnnpackš   s    

rQ   c                    s   ‡ fdd„}|S )Nc               
      s,   t D ]"}t|ƒ ˆ | |Ž W 5 Q R X qd S rI   )Úsupported_qenginesrO   )ÚargsÚkwargsrM   ©Ú	qfunctionr   r   Útest_fn¨   s    
z"override_qengines.<locals>.test_fnr   )rV   rW   r   rU   r   Úoverride_qengines§   s    rX   c                   C   s   t jjjdkS )NZfbgemmrJ   r   r   r   r   Úqengine_is_fbgemm¯   s    rY   c                   C   s   t jjjdkS )Nr
   rJ   r   r   r   r   rP   ±   s    rP   c                   C   s   t jjjdkS )NZonednnrJ   r   r   r   r   Úqengine_is_onednn³   s    rZ   c                   C   s   t jjjdkS )NÚx86rJ   r   r   r   r   Úqengine_is_x86µ   s    r\   c                 C   s6   t t|  ¡ ƒƒ}d||< ||d< |  t|ƒ¡}||fS )Nr   )r@   r;   ZdimÚpermuterA   )r5   ÚaxisZnew_axis_listÚyr   r   r   Ú_permute_to_axis_zero¹   s
    r`   c              	   C   s”   | j }t|  tj¡|ƒ\} }t | ¡}t|  ¡ d ƒD ]D}	t t 	| |	 d||	   ||	  ¡||¡||	  ||	  ||	< q6| 
t|ƒ¡}
|
 |¡S ©Nr   r)   )r   r`   Útor+   r2   Ú
zeros_liker;   ÚsizeÚclampr   r]   rA   )r5   Úper_channel_scaleÚper_channel_zero_pointr^   Ú	quant_minÚ	quant_maxr   Úpermute_axis_listrF   r<   Úoutr   r   r   Ú+_fake_quantize_per_channel_affine_referenceÂ   s     
ÿ ÿÿÿ
rl   c                 C   s    |j }t| tj¡|ƒ\}}t |¡}	t| ¡ d ƒD ]*}
t ||
 d||
   ||
  ¡|	|
< q6|	 	t
|ƒ¡}	|	|k|	|k }t | ¡}| | ||< | |¡S ra   )r   r`   rb   r+   r2   rc   r;   rd   r   r]   rA   )ZdYr5   rf   rg   r^   rh   ri   r   rj   ZXqr<   ÚmaskrF   r   r   r   Ú0_fake_quantize_per_channel_affine_grad_referenceÐ   s    
(
rn   c                 C   s:   t | tjƒst | ¡} n|  ¡  ¡ } | jt |¡tjdS )N)Údevicer   )	r.   r+   r/   ZtensorÚcloneÚdetachrb   ro   r2   )r5   ro   r   r   r   Ú	to_tensorÜ   s    rr   )r   )'Ú__doc__r0   r   r+   Ú
contextlibr   Z$torch.testing._internal.common_utilsr   r   r   r   r   r   rK   rL   Zsupported_enginesrR   ÚremoveÚanyr   Zuint8r!   r#   r%   r,   r8   r=   rD   rO   rQ   rX   rY   rP   rZ   r\   r`   rl   rn   rr   r   r   r   r   Ú<module>   s:    


 ÿ
)

	