Ë
    ÝÍ:j×Ý  ã                   ó"  — d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlm	Z	 d dl
mZ d dlmZ d dlZd dlZd dlmZmZmZmZ d dlZddlmZmZmZ dej4                  d	ej4                  d
ej4                  fd„Z	 	 d6dej4                  d	ej4                  dedz  ded
ej4                  f
d„Z G d„ d«      Z G d„ d«      Z  G d„ de«      Z! G d„ de jD                  ¬«      Z# G d„ dejH                  «      Z%ddœddddde&d
dfd „Z'd7d!„Z( G d"„ d#«      Z) G d$„ d%e)«      Z* G d&„ d'e)«      Z+ G d(„ d)e+«      Z, G d*„ d+e+«      Z- G d,„ d-e+«      Z. G d.„ d/e jD                  ¬«      Z/ G d0„ d1e/«      Z0dd2e!jb                  ddi fd3e2ez  d4e	e2   dz  fd5„Z3y)8é    N)ÚSequence)ÚEnum)ÚPath)Ú
ModelProtoÚTensorProtoÚhelperÚnumpy_helperé   )Ú
apply_plotÚload_model_with_shape_inferÚsmooth_distributionÚpkÚqkÚreturnc                 ó  — t        j                  | j                  | j                  ¬«      }| dd t        j                  | dd |dd z  «      z  |dd | dk(  |dk\  z  }d||<   | dkD  |dkD  z  }t         j
                  || <   |S )z‘
    See https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.rel_entr.html#scipy.special.rel_entr.
    Python implementation.
    ©ÚdtypeNr   )ÚnpÚemptyÚshaper   ÚlogÚinf)r   r   ÚresÚc2Úc1s        úw/home/mcse/projects/srt_converter/srt-converter-venv/lib/python3.12/site-packages/onnxruntime/quantization/calibrate.pyÚrel_entrr      s„   € ô
 �(‰(�2—8‘8 2§8¡8Ô
,€CØ‘ˆU”R—V‘V˜B™q˜E B¡q E™MÓ*Ñ*€C‰€FØ
�‰'�b˜A‘gÑ	€BØ€Cˆ�GØ
ˆq‰&�R˜!‘VÑ	€BÜ�v‰v€Cˆˆ�HØ€Jó    ÚbaseÚaxisc                 óR  — |�|dkD  sJ d«       ‚|€J d«       ‚t        j                  | «      j                  t         j                  «      } d| z  t        j                  | |d¬«      z  } t        j                  |«      j                  t         j                  «      }t        j
                  | |«      \  } }d|z  t        j                  ||d¬«      z  }t        | |«      }t        j                  ||¬«      }|�|t        j                  |«      z  }|j                  | j                  «      S )zÉ
    Simplifeied version of entropy.
    Source: https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.entropy.html.
    This avoids taking a dependency on scipy just for this function.
    r   z0base={base} must be a positive number or `None`.z
qk is Noneç      ð?T)r    Úkeepdims©r    )	r   ÚasarrayÚastypeÚfloat32ÚsumÚbroadcast_arraysr   r   r   )r   r   r   r    ÚvecÚss         r   Úentropyr,   *   sõ   € ð ˆ<˜4 !š8ÐWÐ%WÓWÐ#Øˆ>Ð'˜<Ó'ˆ>ä	�‰�B‹×	Ñ	œrŸz™zÓ	*€BØ	ˆr‰”B—F‘F˜2 D°4Ô8Ñ	8€Bä	�‰�B‹×	Ñ	œrŸz™zÓ	*€BÜ× Ñ   RÓ(�F€BˆØ	ˆr‰”B—F‘F˜2 D°4Ô8Ñ	8€BÜ
�2�rÓ
€Cä
�‰ˆs˜Ô€AØÐØ	ŒR�V‰V�D‹\ÑˆØ�8‰8�B—H‘HÓÐr   c                   óz   — e Zd Z eg d¢«      Z eg d¢«      Zd„ Zed„ «       Zed„ «       Z	d„ Z
ededd fd	„«       Zy
)Ú
TensorData)ÚavgÚstdÚlowestÚhighestÚhistÚ
hist_edgesÚbins)r/   r0   r1   r2   r4   c                 óì  — t        |j                  «       «      | _        |j                  «       D ]Ã  \  }}|t        j
                  vr t        d|›dt        j
                  › d�«      ‚|t        j                  v rmt        |d«      st        dt        |«      › d|›�«      ‚|j                  t        j                  t        j                  fvrt        d|j                  › d|›�«      ‚t        | ||«       ŒÅ y )NzUnexpected value z not in ú.r   úUnexpected type z for k=zUnexpected dtype )ÚlistÚkeysÚ_attrsÚitemsr.   Ú_allowedÚ
ValueErrorÚ_floatsÚhasattrÚtyper   r   Úfloat16r'   Úsetattr)ÚselfÚkwargsÚkÚvs       r   Ú__init__zTensorData.__init__J   sÕ   € Ü˜6Ÿ;™;›=Ó)ˆŒØ—L‘L“Nò 	 ‰DˆAˆqØœ
×+Ñ+Ñ+Ü Ð#4°Q°E¸Ä*×BUÑBUÐAVÐVWÐ!XÓYÐYØ”J×&Ñ&Ñ&Ü˜q 'Ô*Ü$Ð'7¼¸Q»°yÀÈÀuÐ%MÓNÐNØ—7‘7¤2§:¡:¬r¯z©zÐ":Ñ:Ü$Ð'8¸¿¹¸	ÀÈÈÐ%NÓOÐOÜ�D˜!˜QÕñ	 r   c                 ó’   — t        | d«      rt        | d«      st        dt        | «      › d�«      ‚| j                  | j                  fS )Nr1   r2   z0Attributes 'lowest' and/or 'highest' missing in r7   )r@   ÚAttributeErrorÚdirr1   r2   ©rD   s    r   Úrange_valuezTensorData.range_valueV   sF   € ä�t˜XÔ&¬g°d¸IÔ.FÜ Ð#SÔTWÐX\ÓT]ÐS^Ð^_Ð!`ÓaÐaØ—‘˜TŸ\™\Ð*Ð*r   c                 ó’   — t        | d«      rt        | d«      st        dt        | «      › d�«      ‚| j                  | j                  fS )Nr/   r0   z)Attributes 'avg' and/or 'std' missing in r7   )r@   rJ   rK   r/   r0   rL   s    r   Úavg_stdzTensorData.avg_std\   sC   € ä�t˜UÔ#¬7°4¸Ô+?Ü Ð#LÌSÐQUËYÈKÐWXÐ!YÓZÐZØ—‘˜$Ÿ(™(Ð#Ð#r   c                 óŠ   — | j                   D �ci c]  }|t        | |«      “Œ }}| j                  j                  |d<   |S c c}w )NÚCLS)r;   ÚgetattrÚ	__class__Ú__name__)rD   rF   Údatas      r   Úto_dictzTensorData.to_dictb   sB   € à-1¯[©[Ö9¨�”7˜4 Ó#Ñ#Ð9ˆÐ9Ø—n‘n×-Ñ-ˆˆU‰Øˆùò :s   �A Údr   c                 óœ  — i }|j                  «       D ]°  \  }}|dk(  rŒ|}t        |t        «      rE|j                  d«      dk(  r1t	        j
                  |d   t	        j                  |d   «      ¬«      }nI|| j                  v r;t        |t        t        f«      r%t	        j
                  |t        j                  ¬«      }|||<   Œ²  | di |¤ŽS )z;Reconstruct a TensorData from a dict produced by to_dict().rQ   únumpy.arrayrU   r   r   © )r<   Ú
isinstanceÚdictÚgetr   Úarrayr   r?   ÚintÚfloatr'   )ÚclsrW   rE   rF   rG   Úvalues         r   Ú	from_dictzTensorData.from_dicth   s°   € ð ˆØ—G‘G“Iò 	‰DˆAˆqØ�EŠzØØˆEÜ˜%¤Ô&¨5¯9©9°UÓ+;¸}Ò+LÜŸ™  v¡´b·h±h¸uÀW¹~Ó6NÔO‘Ø�c—k‘kÑ!¤j°¼¼e¸Ô&EÜŸ™ ¬b¯j©jÔ9�ØˆF�1ŠIð	ñ ‰}�V‰}Ðr   N)rT   Ú
__module__Ú__qualname__Ú	frozensetr=   r?   rH   ÚpropertyrM   rO   rV   Úclassmethodr\   rc   rZ   r   r   r.   r.   F   sl   „ ÙÒZÓ[€HÙÒIÓJ€Gò
 ð ñ+ó ð+ð
 ñ$ó ð$ò
ð ð˜$ð  <ò ó ñr   r.   c                   ór   — e Zd Zdeeeez  f   fd„Zd„ Zd„ Z	d„ Z
d„ Zd„ Zd„ Zd	„ Zd
„ Zededd fd„«       Zy)ÚTensorsDatarU   c           
      ób  — || _         i | _        |j                  «       D �]  \  }}t        |t        «      st        dt        |«      › d�«      ‚t        |t        «      r˜|t        j                  k(  r/t        |«      dk(  r!t        |d   |d   ¬«      | j                  |<   Œ�t        |«      dk(  r)t        |d   |d   |d   |d   ¬	«      | j                  |<   Œ¸t        d
|d›dt        |«      › d|› d�«      ‚t        |t        «      st        dt        |«      › d�«      ‚|| j                  |<   �Œ y )NzKeys must be strings not r7   é   r   r
   ©r1   r2   é   é   )r1   r2   r3   r5   zUnexpected tuple for Úrz	, it has z elements: zValues must be TensorData not )Úcalibration_methodrU   r<   r[   ÚstrÚ	TypeErrorrA   ÚtupleÚCalibrationMethodÚMinMaxÚlenr.   )rD   rq   rU   rF   rG   s        r   rH   zTensorsData.__init__y   s$  € Ø"4ˆÔØˆŒ	Ø—J‘J“Ló 	‰DˆAˆqÜ˜a¤Ô%ÜÐ";¼DÀ»G¸9ÀAÐ FÓGÐGÜ˜!œUÔ#Ø%Ô):×)AÑ)AÒAÄcÈ!ÃfÐPQÂkÜ#-°Q°q±TÀ1ÀQÁ4Ô#H�D—I‘I˜a‘LØÜ�q“6˜Q’;Ü#-°Q°q±TÀ1ÀQÁ4ÈaÐPQÉdÐYZÐ[\ÑY]Ô#^�D—I‘I˜a‘LØÜÐ"7¸¸!°u¸IÄcÈ!ÃfÀXÈ[ÐYZÐX[Ð[\Ð ]Ó^Ð^Ü˜a¤Ô,ÜÐ"@ÄÀaÃÀ	ÈÐ KÓLÐLØˆD�I‰I�a‹Lñ	r   c              #   ó8   K  — | j                   E d {  –—†  y 7 Œ­w©N©rU   rL   s    r   Ú__iter__zTensorsData.__iter__‹   s   è ø€ Ø—9‘9×Òús   ‚’“c                 ó   — || j                   v S ry   rz   ©rD   Úkeys     r   Ú__contains__zTensorsData.__contains__Ž   s   € Ø�d—i‘iÐÐr   c                 ó    — | j                   |   S ry   rz   r}   s     r   Ú__getitem__zTensorsData.__getitem__‘   s   € Ø�y‰y˜‰~Ðr   c                 ó\   — || j                   vrt        d|›d�«      ‚|| j                   |<   y )Nz)Only an existing tensor can be modified, z is not.)rU   ÚRuntimeError)rD   r~   rb   s      r   Ú__setitem__zTensorsData.__setitem__”   s1   € Ø�d—i‘iÑÜÐ!JÈ3È'ÐQYÐZÓ[Ð[Øˆ�	‰	�#Šr   c                 ó6   — | j                   j                  «       S ry   )rU   r:   rL   s    r   r:   zTensorsData.keys™   s   € Ø�y‰y�~‰~ÓÐr   c                 ó6   — | j                   j                  «       S ry   )rU   ÚvaluesrL   s    r   r‡   zTensorsData.valuesœ   s   € Ø�y‰y×ÑÓ!Ð!r   c                 ó6   — | j                   j                  «       S ry   )rU   r<   rL   s    r   r<   zTensorsData.itemsŸ   s   € Ø�y‰y�‰Ó Ð r   c                 ób   — | j                   j                  | j                  | j                  dœ}|S )N)rQ   rU   rq   )rS   rT   rU   rq   )rD   rU   s     r   rV   zTensorsData.to_dict¢   s/   € ð —>‘>×*Ñ*Ø—I‘IØ"&×"9Ñ"9ñ
ˆð
 ˆr   rW   r   c                 ó*  — |d   }t        |t        «      r5|j                  d«      dk(  r!|d   j                  d«      d   }t        |   }n|}|d   j                  «       D ��ci c]  \  }}|t        j                  |«      “Œ }}} | ||«      S c c}}w )z<Reconstruct a TensorsData from a dict produced by to_dict().rq   rQ   ru   rb   r7   éÿÿÿÿrU   )r[   r\   r]   Úsplitru   r<   r.   rc   )ra   rW   Ú
method_valÚnameÚmethodrF   rG   Úreconstructeds           r   rc   zTensorsData.from_dict«   s˜   € ð Ð+Ñ,ˆ
Ü�j¤$Ô'¨J¯N©N¸5Ó,AÐEXÒ,XØ˜gÑ&×,Ñ,¨SÓ1°"Ñ5ˆDÜ& tÑ,‰FàˆFØ@AÀ&Á	ÇÁÓ@Q×R¹¸¸1˜œJ×0Ñ0°Ó3Ñ3ÐRˆÑRÙ�6˜=Ó)Ð)ùó Ss   Á# BN)rT   rd   re   r\   rr   r.   rt   rH   r{   r   r�   r„   r:   r‡   r<   rV   rh   rc   rZ   r   r   rj   rj   x   sg   „ ð°°c¸:ÈÑ;MÐ6MÑ1Nó ò$ò òòò
 ò"ò!òð ð	*˜$ð 	* =ò 	*ó ñ	*r   rj   c                   ó   — e Zd ZdZdZdZdZy)ru   r   r
   rl   ro   N)rT   rd   re   rv   ÚEntropyÚ
PercentileÚDistributionrZ   r   r   ru   ru   ¸   s   „ Ø€FØ€GØ€JØ�Lr   ru   c                   óh   — e Zd Zed„ «       Zej                  defd„«       Zd„ Z	d„ Z
d„ Zdedefd	„Zy
)ÚCalibrationDataReaderc                 óX   — t        |d«      xr t        |j                  «      xs t        S )NÚget_next)r@   Úcallabler˜   ÚNotImplemented)ra   Úsubclasss     r   Ú__subclasshook__z&CalibrationDataReader.__subclasshook__À   s%   € ä˜ *Ó-ÒM´(¸8×;LÑ;LÓ2MÒ`ÔR`Ð`r   r   c                 ó   — t         ‚)z9generate the input data dict for ONNXinferenceSession run©ÚNotImplementedErrorrL   s    r   r˜   zCalibrationDataReader.get_nextÄ   s
   € ô "Ð!r   c                 ó   — | S ry   rZ   rL   s    r   r{   zCalibrationDataReader.__iter__É   s   € Øˆr   c                 ó6   — | j                  «       }|€t        ‚|S ry   )r˜   ÚStopIteration)rD   Úresults     r   Ú__next__zCalibrationDataReader.__next__Ì   s   € Ø—‘“ˆØˆ>ÜÐØˆr   c                 ó   — t         ‚ry   rž   rL   s    r   Ú__len__zCalibrationDataReader.__len__Ò   ó   € Ü!Ð!r   Ústart_indexÚ	end_indexc                 ó   — t         ‚ry   rž   )rD   r¨   r©   s      r   Ú	set_rangezCalibrationDataReader.set_rangeÕ   r§   r   N)rT   rd   re   rh   rœ   ÚabcÚabstractmethodr\   r˜   r{   r¤   r¦   r_   r«   rZ   r   r   r–   r–   ¿   sY   „ Øñaó ðað 	×Ñð"˜$ò "ó ð"òòò"ð" Sð "°Sô "r   r–   )Ú	metaclassc                   ó   — e Zd ZdZd„ Zy)ÚCalibrationCacheEncoderzñShared JSON encoder for calibration caches.

    Handles numpy ndarrays and numpy scalar types (integer/floating) so
    calibration JSON output is consistent across ``save_tensors_data`` and
    ``quant_utils.write_calibration_table``.
    c                 ó  — t        |t        t        f«      r|j                  «       S t        |t        j
                  «      r'|j                  «       t        |j                  «      ddœS t        |t        «      r"|j                  j                  t        |«      dœS t        |t        j                  «      rt        |«      S t        |t        j                  «      rt        |«      S t         j"                  j%                  | |«      S )NrY   )rU   r   rQ   )rQ   rb   )r[   r.   rj   rV   r   ÚndarrayÚtolistrr   r   ru   rS   rT   Úintegerr_   Úfloatingr`   ÚjsonÚJSONEncoderÚdefault)rD   Úobjs     r   r¸   zCalibrationCacheEncoder.defaultá   s²   € Ü�cœJ¬Ð4Ô5Ø—;‘;“=Ð Ü�cœ2Ÿ:™:Ô&ØŸJ™J›L´3°s·y±y³>È-ÑXÐXÜ�cÔ,Ô-ØŸ=™=×1Ñ1¼CÀ»HÑEÐEÜ�cœ2Ÿ:™:Ô&Ü�s“8ˆOÜ�cœ2Ÿ;™;Ô'Ü˜“:ÐÜ×Ñ×'Ñ'¨¨cÓ2Ð2r   N)rT   rd   re   Ú__doc__r¸   rZ   r   r   r°   r°   Ù   s   „ ñó3r   r°   F)Úsmooth_quantÚtensors_dataÚpathú
str | Pathr»   c                óF  — t        |«      }|j                  j                  dd¬«       t        j                  |j                  dd¬«      \  }}	 t        j                  |d«      5 }| j                  «       }||d<   t        j                  ||t        ¬«       |j                  «        d	d	d	«       t        j                  ||«       y	# 1 sw Y   Œ xY w# t        $ rE t        j                  t         «      5  t        j"                  |«       d	d	d	«       ‚ # 1 sw Y   ‚ xY ww xY w)
zÚSerialize calibration tensor ranges to a JSON file at *path*.

    :param smooth_quant: whether the producing run used SmoothQuant.  Stored in
        the cache so a later load can detect a mismatch and recompute.
    T)ÚparentsÚexist_okz.calibcache_z.tmp)rK   ÚprefixÚsuffixÚwr»   )ra   N)r   ÚparentÚmkdirÚtempfileÚmkstempÚosÚfdopenrV   r¶   Údumpr°   ÚflushÚreplaceÚBaseExceptionÚ
contextlibÚsuppressÚFileNotFoundErrorÚunlink)r¼   r½   r»   ÚfdÚtmp_nameÚfÚpayloads          r   Úsave_tensors_datar×   ï   sî   € ô �‹:€DØ‡K�K×Ñ˜d¨TÐÔ2Ü×#Ñ#¨¯©¸NÐSYÔZ�L€Bˆð
Ü�Y‰Y�r˜3Óð 	 1Ø"×*Ñ*Ó,ˆGØ&2ˆG�NÑ#Ü�I‰I�g˜qÔ&=Õ>Ø�G‰GŒI÷		ô
 	�
‰
�8˜TÕ"÷	ð 	ûô ò Ü× Ñ Ô!2Ó3ñ 	 Ü�I‰I�hÔ÷	 à÷	 àúðús=   ÁC Á%ACÂ'C ÃCÃC Ã"D Ã4DÄ
	D ÄD	ÄD c                 ó0  — t        | «      } | j                  «       st        d| › �«      ‚| j                  «       st	        d| › �«      ‚| j                  d«      5 }t        j                  |«      }ddd«       t        j                  «      S # 1 sw Y   ŒxY w)zOLoad calibration tensor ranges from a JSON file written by save_tensors_data().zCalibration cache not found: z&Calibration cache path is not a file: rp   N)
r   ÚexistsrÑ   Úis_filer>   Úopenr¶   Úloadrj   rc   )r½   rÕ   rW   s      r   Úload_tensors_datarÝ     sƒ   € ä�‹:€DØ�;‰;Œ=ÜÐ"?À¸vÐ FÓGÐGØ�<‰<Œ>ÜÐAÀ$ÀÐHÓIÐIØ	�‰�3‹ð ˜1Ü�I‰I�a‹Lˆ÷ä× Ñ  Ó#Ð#÷ð ús   ÁBÂBc                   ó|   — e Zd Z	 	 	 	 	 ddeez  dee   dz  fd„Zdgfd„Zd„ Zde	fd	„Z
d
„ Zd„ Zdefd„Zdefd„Zy)ÚCalibraterBaseNÚ
model_pathÚop_types_to_calibratec                 ó"  — t        |t        «      rt        t        |«      «      | _        n,t        |t        «      rt        |«      | _        nt        d«      ‚|| _        || _        || _        || _	        || _
        d| _        d| _        dg| _        y)a  
        :param model_path: ONNX model to calibrate. It should be a model file path
        :param op_types_to_calibrate: operator types to calibrate. By default, calibrate all the float32/float16 tensors.
        :param augmented_model_path: save augmented model to this path.
        :param symmetric: make range of tensor symmetric (central point is 0).
        :param use_external_data_format: use external data format to store model which size is >= 2Gb.
        :param per_channel: whether to compute ranges per each channel.
        z model_path should be model path.NÚCPUExecutionProvider)r[   rr   r   r   Úmodelr>   rá   Úaugmented_model_pathÚ	symmetricÚuse_external_data_formatÚper_channelÚaugment_modelÚinfer_sessionÚexecution_providers)rD   rà   rá   rå   ræ   rç   rè   s          r   rH   zCalibraterBase.__init__  sƒ   € ô" �j¤#Ô&Ü4´T¸*Ó5EÓFˆD�JÜ˜
¤DÔ)Ü4°ZÓ@ˆD�JäÐ?Ó@Ð@à%:ˆÔ"Ø$8ˆÔ!Ø"ˆŒØ(@ˆÔ%Ø&ˆÔà!ˆÔØ!ˆÔØ$:Ð#;ˆÕ r   rã   c                 ó2   — || _         | j                  «        y)zz
        reset the execution providers to execute the collect_data. It triggers to re-creating inference session.
        N)rë   Úcreate_inference_session)rD   rë   s     r   Úset_execution_providersz&CalibraterBase.set_execution_providers4  s   € ð $7ˆÔ Ø×%Ñ%Õ'r   c                 óÌ   — t        j                  «       }t         j                  j                  |_        t        j
                  | j                  || j                  ¬«      | _        y)z9
        create an OnnxRuntime InferenceSession.
        )Úsess_optionsÚ	providersN)	ÚonnxruntimeÚSessionOptionsÚGraphOptimizationLevelÚORT_DISABLE_ALLÚgraph_optimization_levelÚInferenceSessionrå   rë   rê   )rD   rð   s     r   rí   z'CalibraterBase.create_inference_session;  sN   € ô #×1Ñ1Ó3ˆÜ0;×0RÑ0R×0bÑ0bˆÔ-Ü(×9Ñ9Ø×%Ñ%Ø%Ø×.Ñ.ô
ˆÕr   rä   c                 óÐ  — |j                   j                  D �ci c]  }|j                  |“Œ }}|j                  |j                   j                  D �ci c]  }|j                  |“Œ c}«       |j                  |j                   j
                  D �ci c]  }|j                  |“Œ c}«       |j                   j                  D �ch c]  }|j                  ’Œ }}t        «       }t        j                  t        j                  h}	|j                   j                  D ]µ  }
| j                  r|
j                  | j                  v sŒ(t        j                  |
j
                  |
j                  «      D ]a  }||v sŒ||   }|j                   j#                  d«      sŒ)|j                   j$                  j&                  |	v sŒL||vsŒQ|j)                  |«       Œc Œ· ||fS c c}w c c}w c c}w c c}w )zÉ
        select input/output tensors of candidate nodes to calibrate.
        returns:
            tensors (set): set of tensor name.
            value_infos (dict): tensor name to value info.
        Útensor_type)ÚgraphÚ
value_inforŽ   ÚupdateÚoutputÚinputÚinitializerÚsetr   ÚFLOATÚFLOAT16Únoderá   Úop_typeÚ	itertoolsÚchainrA   ÚHasFieldrù   Ú	elem_typeÚadd)rD   rä   ÚviÚvalue_infosÚotÚitÚinitrÿ   Útensors_to_calibrateÚtensor_type_to_calibrater  Útensor_names               r   Úselect_tensors_to_calibratez*CalibraterBase.select_tensors_to_calibrateG  s‡  € ð .3¯[©[×-CÑ-CÖD r�r—w‘w ‘{ÐDˆÐDØ×Ñ°%·+±+×2DÑ2DÖE¨B˜BŸG™G R™KÒEÔFØ×Ñ°%·+±+×2CÑ2CÖD¨B˜BŸG™G R™KÒDÔEØ-2¯[©[×-DÑ-DÖE T�t—y“yÐEˆÐEä"›uÐÜ$/×$5Ñ$5´{×7JÑ7JÐ#KÐ à—K‘K×$Ñ$ò 
	BˆDØ×-Ò-°·±À×A[ÑA[Ò1[Ü#,§?¡?°4·:±:¸t¿{¹{Ó#Kò B�KØ" kÒ1Ø(¨Ñ5˜àŸG™G×,Ñ,¨]Õ;Ø!#§¡×!4Ñ!4×!>Ñ!>ÐBZÒ!ZØ!,°KÒ!?à0×4Ñ4°[ÕAñBð
	Bð $ [Ð0Ð0ùò) EùÚEùÚDùÚEs   ™GÁGÂGÃG#c                 ó   — | j                   S )zP
        return: augmented onnx model. Call after calling augment_graph
        )rä   rL   s    r   Úget_augment_modelz CalibraterBase.get_augment_modeld  s   € ð �z‰zÐr   c                 ó   — t         ‚)zï
        abstract method: augment the input model to prepare for collecting data. It will:
            1. augment the model to be able to collect desired statistics data
            2. save augmented model to augmented_model_paths
        rž   rL   s    r   Úaugment_graphzCalibraterBase.augment_graphj  s
   € ô "Ð!r   Údata_readerc                 ó   — t         ‚)z€
        abstract method: collect the tensors that will be used for range computation. It can be called multiple times.
        rž   )rD   r  s     r   Úcollect_datazCalibraterBase.collect_datar  ó
   € ô "Ð!r   r   c                 ó   — t         ‚)ze
        abstract method: compute data based on the calibration method stored in TensorsData
        rž   rL   s    r   Úcompute_datazCalibraterBase.compute_datax  r  r   )Núaugmented_model.onnxFFF)rT   rd   re   rr   r   r   rH   rî   rí   r   r  r  r  r–   r  rj   r  rZ   r   r   rß   rß     sz   „ ð 7;Ø3ØØ!&Øñ <à˜$‘Jð <ð  (¨™}¨tÑ3ó <ðD <RÐ:Ró (ò

ð1°ó 1ò:ò"ð"Ð(=ó "ð"˜kô "r   rß   c                   óv   ‡ — e Zd Z	 	 	 	 	 	 	 	 ddeez  dee   dz  fˆ fd„Zd„ Zd„ Zde	fd„Z
d	„ Zd
efd„Zˆ xZS )ÚMinMaxCalibraterNrà   rá   c
                 ó„  •— t         ‰| �  ||||||	¬«       g | _        d| _        t	        | j
                  j                  j                  «      | _        | j
                  j                  j                  D �
ch c]  }
|
j                  ’Œ c}
| _
        || _        |r|dk  s|dkD  rt        d«      ‚|| _        || _        yc c}
w )aw  
        :param model_path: ONNX model to calibrate. It is a model path
        :param op_types_to_calibrate: operator types to calibrate. By default, calibrate all the float32/float16 tensors.
        :param augmented_model_path: save augmented model to this path.
        :param symmetric: make range of tensor symmetric (central point is 0).
        :param use_external_data_format: use external data format to store model which size is >= 2Gb
        :param moving_average: compute the moving average of the minimum and maximum values instead of the global minimum and maximum.
        :param averaging_constant: constant smoothing factor to use when computing the moving average.
        :param max_intermediate_outputs: maximum number of intermediate outputs before an intermediate range is computed.
        :param per_channel: whether to compute ranges per each channel.
        )rá   rå   ræ   rç   rè   Nr   r
   z;Invalid averaging constant, which should not be < 0 or > 1.)ÚsuperrH   Úintermediate_outputsÚcalibrate_tensors_rangerw   rä   rú   rý   Únum_model_outputsrŽ   Úmodel_original_outputsÚmoving_averager>   Úaveraging_constantÚmax_intermediate_outputs)rD   rà   rá   rå   ræ   rç   r&  r'  r(  rè   rý   rS   s              €r   rH   zMinMaxCalibrater.__init__€  s¼   ø€ ô. 	‰ÑØØ"7Ø!5ØØ%=Ø#ð 	ô 	
ð %'ˆÔ!Ø'+ˆÔ$Ü!$ T§Z¡Z×%5Ñ%5×%<Ñ%<Ó!=ˆÔØAEÇÁ×AQÑAQ×AXÑAXÖ&Y°v v§{£{Ò&YˆÔ#Ø,ˆÔÙÐ1°AÒ5Ð9KÈaÒ9OÜÐZÓ[Ð[Ø"4ˆÔØ(@ˆÕ%ùò 'Zs   Á5B=c                 ó  ‡ ‡‡‡— ‰ j                  ‰ j                  «      \  }}t        t        j                  «       «      Št        j                  t        j                  dgt        j                  ¬«      ‰«      }‰ j                  j                  j                  j                  |«       d„ Šˆ fd„Šˆˆˆˆ fd„}|D ]  } ||d«        ||d«       Œ t        j                  ‰ j                  ‰ j                  ‰ j                   ¬«       y	)
zÙ
        Adds ReduceMin and ReduceMax nodes to all quantization_candidates op type nodes in
        model and ensures their outputs are stored as part of the graph output
        :return: augmented ONNX model
        r‹   r   c                 ó²   — |j                   D ]:  }t        j                  j                  | |j                  «      sŒ.|j
                  c S  t        d| › d�«      ‚)Nz&Model does not contain a version for 'z'.)Úopset_importÚonnxÚdefsÚhasÚdomainÚversionrƒ   )r  rä   r+  s      r   Úget_op_versionz6MinMaxCalibrater.augment_graph.<locals>.get_op_version´  sS   € Ø %× 2Ñ 2ò 0�Ü—9‘9—=‘= ¨,×*=Ñ*=Õ>Ø'×/Ñ/Ò/ð0ô Ð!GÈÀyÐPRÐSÓTÐTr   c                 óF  •‡ — t        ˆ fd„t        ‰j                  j                  j                  «      D «       t        ‰j                  j                  j                  «      «      }|D ]7  }‰j                  j                  j                  j                  ||«       |dz  }Œ9 y )Nc              3   óF   •K  — | ]  \  }}‰|j                   v sŒ|–— Œ y ­wry   )rþ   )Ú.0ÚiÚxr  s      €r   ú	<genexpr>zGMinMaxCalibrater.augment_graph.<locals>.insert_nodes.<locals>.<genexpr>¼  s#   øè ø€ ÒZ‘t�q˜!À;ÐRS×RYÑRYÒCY”ÑZùs   ƒ!š!r
   )ÚnextÚ	enumeraterä   rú   r  rw   Úinsert)r  Ú	new_nodesÚindexr  rD   s   `   €r   Úinsert_nodesz4MinMaxCalibrater.augment_graph.<locals>.insert_nodesº  s   ù€ ÜÛZœy¨¯©×)9Ñ)9×)>Ñ)>Ó?ÔZÔ\_Ð`d×`jÑ`j×`pÑ`p×`uÑ`uÓ\vóˆEð "ò �Ø—
‘
× Ñ ×%Ñ%×,Ñ,¨U°DÔ9Ø˜‘
‘ñr   c                 óè  •— d}| dz   |z   }|dz   }t         j                  j                  || g|g||¬«      }t         j                  j                  d|‰g|g|¬«      }‰j                  j                  j
                  D �ci c]  }|j                  |“Œ }}|j                  ‰j                  j                  j                  D �	ci c]  }	|	j                  |	“Œ c}	«       |j                  ‰j                  j                  j                  D �
ci c]  }
|
j                  |
“Œ c}
«       | |v r$||    j                  j                  j                  }nt        d| ›d�«      ‚‰j                  �r+t        ||    j                  j                  j                   j"                  «      }d	gt%        d
|«      ¢} ‰|‰j                  «      dk  r0|j&                  j)                  t        j*                  d|«      «       n t-        t/        j0                  «       «      }t3        j4                  t7        j8                  |t6        j:                  ¬«      |«      }|j                  j)                  |«       ‰j                  j                  j<                  j)                  |«        ‰| ||g«       ‰j                  j                  j                  j)                  t        j>                  ||d g«      «       y c c}w c c}	w c c}
w )Nr
   Ú_Ú_Reshape)r#   rŽ   ÚReshape)ÚinputsÚoutputsrŽ   z'Unable to guess tensor type for tensor zE, running shape inference before quantization may resolve this issue.r   rl   é   Úaxesr   ) r,  r   Ú	make_noderä   rú   rû   rŽ   rü   rý   rþ   rA   rù   r  r>   rè   rw   r   ÚdimÚrangeÚ	attributeÚappendÚmake_attributerr   ÚuuidÚuuid4r	   Ú
from_arrayr   r^   Úint64rÿ   Úmake_tensor_value_info)r  Úreduce_op_namer#   Úreduce_outputÚintermediate_outputÚreduce_nodeÚreshape_noder
  r  Úor5  Ú	onnx_typeÚtensor_rankÚreduced_axesÚreduce_axes_nameÚreduce_axesr1  r=  Úreshape_shape_namerD   s                   €€€€r   Úadd_reduce_min_maxz:MinMaxCalibrater.augment_graph.<locals>.add_reduce_min_maxÂ  s„  ø€ ð ˆHð (¨#Ñ-°Ñ>ˆMØ"/°*Ñ"<ÐÜŸ+™+×/Ñ/Ø  Ð0CÐ/DÈxÐ^kð 0ó ˆKô  Ÿ;™;×0Ñ0ØØ+Ð-?Ð@Ø&˜Ø(ð	 1ó ˆLð 26·±×1AÑ1A×1LÑ1LÖM¨2˜2Ÿ7™7 B™;ÐMˆKÐMØ×Ñ°4·:±:×3CÑ3C×3JÑ3JÖK¨a §¡¨¡	ÒKÔLØ×Ñ°4·:±:×3CÑ3C×3IÑ3IÖJ¨a §¡¨¡	ÒJÔKØ˜kÑ)Ø'¨Ñ4×9Ñ9×EÑE×OÑO‘	ä Ø=¸k¸_ð MZð Zóð ð ×ÓÜ! +¨kÑ":×"?Ñ"?×"KÑ"K×"QÑ"Q×"UÑ"UÓV�Ø !Ð:¤E¨!¨[Ó$9Ð:�á! .°$·*±*Ó=ÀÒBØ×)Ñ)×0Ñ0´×1FÑ1FÀvÈ|Ó1\Õ]ä'*¬4¯:©:«<Ó'8Ð$Ü".×"9Ñ"9¼"¿(¹(À<ÔWY×W_ÑW_Ô:`ÐbrÓ"s�KØ×%Ñ%×,Ñ,Ð-=Ô>Ø—J‘J×$Ñ$×0Ñ0×7Ñ7¸ÔDá˜ {°LÐ&AÔBØ�J‰J×Ñ×#Ñ#×*Ñ*¬6×+HÑ+HÈÐXaÐdhÐciÓ+jÕkùò3 NùÚKùÚJs   Á?K%ÃK*Ä
K/Ú	ReduceMinÚ	ReduceMax©Úsave_as_external_dataN)r  rä   rr   rL  rM  r	   rN  r   r^   rO  rú   rÿ   rJ  r,  Úsaverå   rç   )	rD   Útensorsr?  Úreshape_shaper]  Útensorr1  r=  r\  s	   `     @@@r   r  zMinMaxCalibrater.augment_graph©  sÎ   û€ ð ×5Ñ5°d·j±jÓA‰
ˆ�Ü ¤§¡£Ó.ÐÜ$×/Ñ/´·±¸"¸ÄRÇXÁXÔ0NÐPbÓcˆØ�
‰
×Ñ×$Ñ$×+Ñ+¨MÔ:ò	Uô	÷,	lð\ ò 	4ˆFÙ˜v {Ô3Ù˜v {Õ3ð	4ô 	�	‰	Ø�J‰JØ×%Ñ%Ø"&×"?Ñ"?ö	
r   c                 ó   — g | _         y ry   ©r"  rL   s    r   Úclear_collected_dataz%MinMaxCalibrater.clear_collected_dataú  ó
   € Ø$&ˆÕ!r   r  c           	      ó°  — 	 |j                  «       }|snÅ| j                  j                  t        | j                  j                  «       | j                  j                  d |«      d¬«      D ��cg c]!  \  }}|j                  | j                  vr|nd ‘Œ# c}}«       | j                  �2t        | j                  «      | j                  k(  r| j                  «        ŒØt        | j                  «      dk(  r| j                  €t        d«      ‚| j                  «       }t        |t         «      st#        dt%        |«      › d�«      ‚| j                  «        y c c}}w )NF©Ústrictr   úNo data is collected.z+compute_data must return a TensorsData not r7   )r˜   r"  rJ  Úziprê   Úget_outputsÚrunrŽ   r%  r(  rw   rh  r#  r>   r  r[   rj   rs   rA   )rD   r  rB  Úsess_orb   Úts         r   r  zMinMaxCalibrater.collect_dataý  s8  € ØØ ×)Ñ)Ó+ˆFÙØØ×%Ñ%×,Ñ,ô *-Ø×*Ñ*×6Ñ6Ó8¸$×:LÑ:L×:PÑ:PÐQUÐW]Ó:^Ðglô*÷á%˜ ð $Ÿ[™[°×0KÑ0KÑK‘EÐQUÑUóôð ×-Ñ-Ð9Ü˜×1Ñ1Ó2°d×6SÑ6SÒSà×)Ñ)Ô+ð! ô$ ˆt×(Ñ(Ó)¨QÒ.°4×3OÑ3OÐ3WÜÐ4Ó5Ð5à×ÑÓˆÜ˜!œ[Ô)ÜÐIÌ$ÈqË'ÈÐRSÐTÓUÐUØ×!Ñ!Õ#ùó's   Á-&E
c                 ó>  — |s|S |j                  «       D �]  \  }}t        |t        «      r|j                  d   }|j                  d   }n|\  }}t        ||   t        «      r%||   j                  d   }||   j                  d   }n||   \  }}| j                  r+|| j
                  ||z
  z  z   }	|| j
                  ||z
  z  z   }
nt        ||«      }	t        ||«      }
t        |t        «      st        ||   t        «      rt        |	|
¬«      ||<   Œþ|	|
f||<   �Œ |S )Nr   r
   rm   )r<   r[   r.   rM   r&  r'  ÚminÚmax)rD   Ú	old_rangeÚ	new_ranger~   rb   Úold_minÚold_maxÚnew_minÚnew_maxÚ	min_valueÚ	max_values              r   Úmerge_rangezMinMaxCalibrater.merge_range  s1  € ÙØÐà#Ÿ/™/Ó+ó 	8‰JˆC�ä˜%¤Ô,Ø×+Ñ+¨AÑ.�Ø×+Ñ+¨AÑ.‘à#(Ñ �˜ä˜) C™.¬*Ô5Ø# C™.×4Ñ4°QÑ7�Ø# C™.×4Ñ4°QÑ7‘à#,¨S¡>Ñ �˜à×"Ò"Ø# d×&=Ñ&=ÀÈ7ÑARÑ&SÑS�	Ø# d×&=Ñ&=ÀÈ7ÑARÑ&SÑS‘	ä ¨Ó1�	Ü ¨Ó1�	ô ˜%¤Ô,´
¸9ÀS¹>Ì:Ô0VÜ!+°9ÀiÔ!P�	˜#’à"+¨YÐ!7�	˜#“ð3	8ð6 Ðr   r   c           
      óî  — t        | j                  «      dk(  r| j                  S t        t        | j                  d   «      «      D �cg c])  }| j                  j                  «       |   j                  ‘Œ+ }}| j                  D �cg c]  }t        t        ||d¬«      «      ‘Œ }}i }|D ];  }|j                  «       D ]&  \  }}|j                  |g «      j                  |«       Œ( Œ= || j                  d }	t        dt        |	«      d«      D �cg c]  }|	|   j                  d«      d   ‘Œ }
}|D �ci c]  }|| j                  vsŒ|||   “Œ }}g }t        dt        |	«      d«      D ]ü  }| j                  r>t!        j"                  ||	|      d¬«      }t!        j"                  ||	|dz         d¬«      }n=t!        j$                  ||	|      d¬«      }t!        j&                  ||	|dz         d¬«      }| j(                  rTt!        j&                  t!        j*                  |«      t!        j*                  |«      gd¬«      }|j                  | |f«       Œê|j                  ||f«       Œþ t-        t.        j0                  t        t        |
|d¬«      «      «      }| j                  r-| j3                  | j                  |«      | _        | j                  S || _        | j                  S c c}w c c}w c c}w c c}w )	zŒ
        Compute the min-max range of tensor
        :return: dictionary mapping: {added node names: (ReduceMin, ReduceMax) pairs }
        r   Frk  Nrl   r?  r$   r
   )rw   r"  r#  rH  rê   ro  rŽ   r\   rn  r<   Ú
setdefaultrJ  r$  Ú
rpartitionr%  r&  r   ÚnanmeanÚnanminÚnanmaxræ   Úabsrj   ru   rv   r~  )rD   r5  Úoutput_namesrS  Úoutput_dicts_listÚmerged_output_dictrW   rF   rG   Úadded_output_namesÚcalibrate_tensor_namesÚmerged_added_output_dictÚpairsÚmin_value_arrayÚmax_value_arrayÚmax_absolute_valueÚnew_calibrate_tensors_ranges                    r   r  zMinMaxCalibrater.compute_data9  s  € ô ˆt×(Ñ(Ó)¨QÒ.Ø×/Ñ/Ð/äJOÔPSÐTX×TmÑTmÐnoÑTpÓPqÓJrÖsÀQ˜×*Ñ*×6Ñ6Ó8¸Ñ;×@Ó@ÐsˆÐsð (,×'@Ñ'@ö
à#ô ”�\Ð#6¸uÔEÕFð
Ðð 
ð
  ÐØ"ò 	?ˆAØŸ™›	ò ?‘��1Ø"×-Ñ-¨a°Ó4×;Ñ;¸AÕ>ñ?ð	?ð *¨$×*@Ñ*@Ð*BÐCÐä>CÀAÄsÐK]ÓG^Ð`aÓ>bö"
Ø9:Ð˜qÑ!×,Ñ,¨SÓ1°!Ó4ð"
Ðð "
ð
 /Aö$
Ø)*ÀAÈT×MhÑMhÒDhˆAÐ! !Ñ$Ñ$ð$
Ð ð $
ð ˆÜ�qœ#Ð0Ó1°1Ó5ò 	AˆAØ×"Ò"Ü"$§*¡*Ð-EÐFXÐYZÑF[Ñ-\ÐcdÔ"e�Ü"$§*¡*Ð-EÐFXÐYZÐ]^ÑY^ÑF_Ñ-`ÐghÔ"i‘ä"$§)¡)Ð,DÐEWÐXYÑEZÑ,[ÐbcÔ"d�Ü"$§)¡)Ð,DÐEWÐXYÐ\]ÑX]ÑE^Ñ,_ÐfgÔ"h�à�~Š~Ü%'§Y¡Y´·±°Ó0GÌÏÉÐP_ÓI`Ð/aÐhiÔ%jÐ"Ø—‘Ð1Ð1Ð3EÐFÕGà—‘˜o¨Ð?Õ@ð	Aô '2Ü×$Ñ$¤d¬3Ð/EÀuÐUZÔ+[Ó&\ó'
Ð#ð ×'Ò'Ø+/×+;Ñ+;¸D×<XÑ<XÐZuÓ+vˆDÔ(ð ×+Ñ+Ð+ð ,GˆDÔ(à×+Ñ+Ð+ùòU tùò
ùò"
ùò$
s   Á.K#ÂK(ÄK-Ä3K2ÅK2)Nr  FFFç{®Gáz„?NF)rT   rd   re   rr   r   r   rH   r  rh  r–   r  r~  rj   r  Ú__classcell__©rS   s   @r   r  r    sp   ø„ ð 7;Ø3ØØ!&ØØØ!%Øñ'Aà˜$‘Jð'Að  (¨™}¨tÑ3õ'AòRO
òb'ð$Ð(=ó $ò6ðB3,˜k÷ 3,r   r  c                   ór   ‡ — e Zd Z	 	 	 	 	 	 	 	 	 ddeez  dee   dz  fˆ fd„Zd„ Zd„ Zde	fd„Z
d	efd
„Zˆ xZS )ÚHistogramCalibraterNrà   rá   c                 óŒ  •— t         ‰| �  |||||¬«       g | _        d| _        t	        | j
                  j                  j                  «      | _        | j
                  j                  j                  D �ch c]  }|j                  ’Œ c}| _
        d| _        || _        || _        || _        |	| _        d| _        |
| _        yc c}w )a=  
        :param model_path: ONNX model to calibrate. It is a model path.
        :param op_types_to_calibrate: operator types to calibrate. By default, calibrate all the float32/float16 tensors.
        :param augmented_model_path: save augmented model to this path.
        :param use_external_data_format: use external data format to store model which size is >= 2Gb
        :param method: A string. One of ['entropy', 'percentile'].
        :param symmetric: make range of tensor symmetric (central point is 0).
        :param num_bins: number of bins to create a new histogram for collecting tensor values.
        :param num_quantized_bins: number of quantized bins. Default 128.
        :param percentile: A float number between [0, 100]. Default 99.99.
        :param scenario: see :class:`DistributionCalibrater`
        )rá   rå   ræ   rç   N)r!  rH   r"  r#  rw   rä   rú   rý   r$  rŽ   r%  Ú	collectorr�   Únum_binsÚnum_quantized_binsÚ
percentiler  Úscenario)rD   rà   rá   rå   rç   r�   ræ   r˜  r™  rš  r›  rý   rS   s               €r   rH   zHistogramCalibrater.__init__p  sµ   ø€ ô2 	‰ÑØØ"7Ø!5ØØ%=ð 	ô 	
ð %'ˆÔ!Ø'+ˆÔ$Ü!$ T§Z¡Z×%5Ñ%5×%<Ñ%<Ó!=ˆÔØAEÇÁ×AQÑAQ×AXÑAXÖ&Y°v v§{£{Ò&YˆÔ#ØˆŒØˆŒØ ˆŒØ"4ˆÔØ$ˆŒØ$(ˆÔ!Ø ˆ�ùò 'Zs   Á4Cc                 óZ  — | j                  | j                  «      \  | _        }| j                  D ]C  }|| j                  vsŒ| j                  j                  j
                  j                  ||   «       ŒE t        j                  | j                  | j                  | j                  ¬«       y)zƒ
        make all quantization_candidates op type nodes as part of the graph output.
        :return: augmented ONNX model
        r`  N)r  rä   r  r%  rú   rý   rJ  r,  rb  rå   rç   )rD   r  re  s      r   r  z!HistogramCalibrater.augment_graphœ  s’   € ð
 26×1QÑ1QÐRV×R\ÑR\Ó1]Ñ.ˆÔ! ;Ø×/Ñ/ò 	DˆFØ˜T×8Ñ8Ò8Ø—
‘
× Ñ ×'Ñ'×.Ñ.¨{¸6Ñ/BÕCð	Dô 	�	‰	Ø�J‰JØ×%Ñ%Ø"&×"?Ñ"?ö	
r   c                 ó   — g | _         y ry   rg  rL   s    r   rh  z(HistogramCalibrater.clear_collected_data¬  ri  r   r  c           
      ó¨  — | j                   j                  «       D �ch c]  }|j                  ’Œ }}| j                   j                  «       D �cg c]  }|j                  ‘Œ }}	 |j	                  «       }|snŠ| j                   j                  d|«      }g }t        |«      D ]B  \  }}	||   |v r%|j                  t        j                  |	«      «       Œ2|j                  |	«       ŒD | j                  j                  |«       Œ�t        | j                  «      dk(  rt        d«      ‚| j                  D �
cg c]  }
t        t        ||
d¬«      «      ‘Œ }}
i }|D ];  }|j                  «       D ]&  \  }}|j                  |g «      j                  |«       Œ( Œ= |D �ci c]  }|| j                   v sŒ|||   “Œ }}| j"                  sRt%        | j&                  | j(                  | j*                  | j,                  | j.                  | j0                  ¬«      | _        | j"                  j3                  |«       | j5                  «        yc c}w c c}w c c}
w c c}w )zy
        Entropy Calibrator collects operators' tensors as well as generates tensor histogram for each operator.
        Nr   rm  Frk  )r�   ræ   r˜  r™  rš  r›  )rê   Ú
get_inputsrŽ   ro  r˜   rp  r9  rJ  Úcopyr"  rw   r>   r\   rn  r<   r€  r  r—  ÚHistogramCollectorr�   ræ   r˜  r™  rš  r›  Úcollectrh  )rD   r  Únode_argÚinput_names_setr†  rB  rC  Úfixed_outputsÚoutput_indexrý   rS  r‡  Úmerged_dictrW   rF   rG   r5  Úclean_merged_dicts                     r   r  z HistogramCalibrater.collect_data¯  s.  € ð :>×9KÑ9K×9VÑ9VÓ9XÖY¨X˜8Ÿ=›=ÐYˆÐYØ6:×6HÑ6H×6TÑ6TÓ6VÖW¨(˜Ÿ›ÐWˆÐWàØ ×)Ñ)Ó+ˆFÙØØ×(Ñ(×,Ñ,¨T°6Ó:ˆGð ˆMÜ(1°'Ó(:ò 1Ñ$�˜fØ Ñ-°Ñ@Ø!×(Ñ(¬¯©°6Ó):Õ;à!×(Ñ(¨Õ0ð	1ð ×%Ñ%×,Ñ,¨]Ô;ð ô" ˆt×(Ñ(Ó)¨QÒ.ÜÐ4Ó5Ð5ð (,×'@Ñ'@ö
à#ô ”�\Ð#6¸uÔEÕFð
Ðð 
ð
 ˆØ"ò 	8ˆAØŸ™›	ò 8‘��1Ø×&Ñ& q¨"Ó-×4Ñ4°QÕ7ñ8ð	8ð 9DÖf°1ÀqÈD×LeÑLeÒGe˜Q ¨A¡Ñ.ÐfÐÐfà�~Š~Ü/Ø—{‘{ØŸ.™.ØŸ™Ø#'×#:Ñ#:ØŸ?™?ØŸ™ôˆDŒNð 	�‰×ÑÐ0Ô1à×!Ñ!Õ#ùò] ZùÚWùò,
ùò gs   �I ÁIÄ2I
ÆIÆ,Ir   c                 ón  — | j                   st        d«      ‚t        | t        «      rt        j
                  }nZt        | t        «      rt        j                  }n9t        | t        «      rt        j                  }nt        dt        | «      › d�«      ‚t        || j                   j                  «       «      S )z€
        Compute the min-max range of tensor
        :return: dictionary mapping: {tensor name: (min value, max value)}
        z9No collector created and can't generate calibration data.zUnknown calibrater z". This method must be overwritten.)r—  r>   r[   ÚEntropyCalibraterru   r’   ÚPercentileCalibraterr“   ÚDistributionCalibraterr”   rs   rA   rj   Úcompute_collection_result)rD   Úcals     r   r  z HistogramCalibrater.compute_dataã  s�   € ð
 �~Š~ÜÐXÓYÐYä�dÔ-Ô.Ü#×+Ñ+‰CÜ˜Ô2Ô3Ü#×.Ñ.‰CÜ˜Ô4Ô5Ü#×0Ñ0‰CäÐ1´$°t³*°Ð=_Ð`ÓaÐaÜ˜3 §¡× HÑ HÓ JÓKÐKr   )	Nr  Frš  Fé€   é   ç-²�ïÿX@Úsame)rT   rd   re   rr   r   r   rH   r  rh  r–   r  rj   r  r’  r“  s   @r   r•  r•  o  sk   ø„ ð 7;Ø3Ø!&ØØØØØØñ*!à˜$‘Jð*!ð  (¨™}¨tÑ3õ*!òX
ò 'ð2$Ð(=ó 2$ðhL˜k÷ Lr   r•  c                   óJ   ‡ — e Zd Z	 	 	 	 	 	 	 ddeez  dee   dz  fˆ fd„Zˆ xZS )rª  Nrà   rá   c	           
      ó4   •— t         ‰	| �  ||||||||¬«       y)aÄ  
        :param model_path: ONNX model to calibrate. It is a model path
        :param op_types_to_calibrate: operator types to calibrate. By default, calibrate all the float32/float16 tensors.
        :param augmented_model_path: save augmented model to this path.
        :param use_external_data_format: use external data format to store model which size is >= 2Gb
        :param method: A string. One of ['entropy', 'percentile', 'distribution'].
        :param symmetric: make range of tensor symmetric (central point is 0).
        :param num_bins: number of bins to create a new histogram for collecting tensor values.
        :param num_quantized_bins: number of quantized bins. Default 128.
        )r�   ræ   r˜  r™  N©r!  rH   )
rD   rà   rá   rå   rç   r�   ræ   r˜  r™  rS   s
            €r   rH   zEntropyCalibrater.__init__÷  s/   ø€ ô* 	‰ÑØØ!Ø Ø$ØØØØ1ð 	õ 		
r   )Nr  Fr,   Fr¯  r¯  ©rT   rd   re   rr   r   r   rH   r’  r“  s   @r   rª  rª  ö  sC   ø„ ð 7;Ø3Ø!&ØØØØñ
à˜$‘Jð
ð  (¨™}¨tÑ3÷
ñ 
r   rª  c                   óJ   ‡ — e Zd Z	 	 	 	 	 	 	 ddeez  dee   dz  fˆ fd„Zˆ xZS )r«  Nrà   rá   c	           
      ó4   •— t         ‰	| �  ||||||||¬«       y)a¯  
        :param model_path: ONNX model to calibrate. It is a model path
        :param op_types_to_calibrate: operator types to calibrate. By default, calibrate all the float32/float16 tensors.
        :param augmented_model_path: save augmented model to this path.
        :param use_external_data_format: use external data format to store model which size is >= 2Gb
        :param method: A string. One of ['entropy', 'percentile', 'distribution'].
        :param symmetric: make range of tensor symmetric (central point is 0).
        :param num_quantized_bins: number of quantized bins. Default 128.
        :param percentile: A float number between [0, 100]. Default 99.99.
        )r�   ræ   r˜  rš  Nrµ  )
rD   rà   rá   rå   rç   r�   ræ   r˜  rš  rS   s
            €r   rH   zPercentileCalibrater.__init__  s/   ø€ ô* 	‰ÑØØ!Ø Ø$ØØØØ!ð 	õ 		
r   )Nr  Frš  Fr°  r±  r¶  r“  s   @r   r«  r«    sC   ø„ ð 7;Ø3Ø!&ØØØØñ
à˜$‘Jð
ð  (¨™}¨tÑ3÷
ñ 
r   r«  c                   óH   ‡ — e Zd Z	 	 	 	 	 	 ddeez  dee   dz  fˆ fd„Zˆ xZS )r¬  Nrà   rá   c           	      ó2   •— t         ‰| �  |||||||¬«       y)aŒ  
        :param model_path: ONNX model to calibrate. It is a model path
        :param op_types_to_calibrate: operator types to calibrate. By default, calibrate all the float32/float16 tensors.
        :param augmented_model_path: save augmented model to this path.
        :param use_external_data_format: use external data format to store model which size is >= 2Gb
        :param method: A string. One of ['entropy', 'percentile', 'distribution'].
        :param symmetric: make range of tensor symmetric (central point is 0).
        :param num_bins: number of bins to create a new histogram for collecting tensor values.
        :param scenario: for float 8 only, if `scenario="same"`,
            the algorithm weights and float 8 follow the same distribution,
            if `scenario="p3"`, it assumes the weights follow
            a gaussian law and float 8 ~ X^3 where X is a gaussian law
        )r�   r˜  r›  Nrµ  )	rD   rà   rá   rå   rç   r�   r˜  r›  rS   s	           €r   rH   zDistributionCalibrater.__init__;  s,   ø€ ô. 	‰ÑØØ!Ø Ø$ØØØð 	õ 	
r   )Nr  FÚdistributionr¯  r²  r¶  r“  s   @r   r¬  r¬  :  s@   ø„ ð 7;Ø3Ø!&ØØØñ
à˜$‘Jð
ð  (¨™}¨tÑ3÷
ñ 
r   r¬  c                   óX   — e Zd ZdZej
                  d„ «       Zej
                  d„ «       Zy)ÚCalibrationDataCollectorzL
    Base class for collecting data for calibration-based quantization.
    c                 ó   — t         ‚)z‹
        Generate informative data based on given data.
            name_to_arr : dict
                tensor name to NDArray data
        rž   ©rD   Úname_to_arrs     r   r¢  z CalibrationDataCollector.collectb  s
   € ô "Ð!r   c                 ó   — t         ‚)z?
        Get the optimal result among collection data.
        rž   rL   s    r   r­  z2CalibrationDataCollector.compute_collection_resultk  s
   € ô
 "Ð!r   N)rT   rd   re   rº   r¬   r­   r¢  r­  rZ   r   r   r½  r½  ]  s;   „ ñð 	×Ññ"ó ð"ð 	×Ññ"ó ñ"r   r½  c                   ód   — e Zd ZdZd„ Zd„ Zd„ Zd„ Zd„ Zd„ Z	d„ Z
d	„ Zd
„ Zedd„«       Zd„ Zd„ Zy)r¡  a`  
    Collecting histogram for each tensor. Percentile and Entropy method are supported.

    ref: https://github.com//apache/incubator-mxnet/blob/master/python/mxnet/contrib/quantization.py
    ref: https://docs.nvidia.com/deeplearning/tensorrt/pytorch-quantization-toolkit/docs/_modules/
                 pytorch_quantization/calib/histogram.html
    c                 óf   — i | _         || _        || _        || _        || _        || _        || _        y ry   )Úhistogram_dictr�   ræ   r˜  r™  rš  r›  )rD   r�   ræ   r˜  r™  rš  r›  s          r   rH   zHistogramCollector.__init__|  s5   € Ø ˆÔØˆŒØ"ˆŒØ ˆŒØ"4ˆÔØ$ˆŒØ ˆ�r   c                 ó   — | j                   S ry   )rÄ  rL   s    r   Úget_histogram_dictz%HistogramCollector.get_histogram_dict…  s   € Ø×"Ñ"Ð"r   c                 óæ   — t        d«       | j                  dv r| j                  |«      S | j                  dk(  r.| j                  r| j	                  |«      S | j                  |«      S t        d«      ‚)Nz/Collecting tensor data and making histogram ...>   r,   r»  rš  úDOnly 'entropy', 'percentile' or 'distribution' methods are supported)Úprintr�   Úcollect_valueræ   Úcollect_absolute_valuer>   r¿  s     r   r¢  zHistogramCollector.collectˆ  sl   € ÜÐ?Ô@ð �;‰;Ð5Ñ5Ø×%Ñ% kÓ2Ð2Ø�[‰[˜LÒ(Ø�~Š~Ø×2Ñ2°;Ó?Ð?à×)Ñ)¨+Ó6Ð6äÐcÓdÐdr   c                 óÌ  — |j                  «       D �]K  \  }}t        |t        «      r�|D ]2  }t        |t        j                  «      rŒJ dt        |«      › d|›�«       ‚ |D �ch c]  }|j                  ’Œ }}t        |«      dk(  sJ d|› d|›�«       ‚t        j                  |«      }n6t        |t        j                  «      st        dt        |«      › d|›�«      ‚|}|j                  «       }|j                  dkD  r+t        j                  |«      }t        j                  |«      }	nBt        j                  d|j                  ¬«      }t        j                  d|j                  ¬«      }	t        j                  |«      }|| j                   vrxt        j"                  || j$                  ¬«      \  }
}|j'                  |j                  «      }|j                  t        j(                  k7  sJ d«       ‚|
|||	f| j                   |<   �Œõ| j                   |   }|d	   }|d
   }t+        |d«      sJ dt        |«      › �«       ‚t+        |d«      sJ dt        |«      › �«       ‚|d   }|d   }t        j                  |«      }||d   kD  rB|d   |d   z
  }t        j,                  |d   |z   ||z   |«      }t        j.                  ||f«      }t        j"                  ||¬«      \  }
}|j'                  |j                  «      }|
dt        |«      xxx |z  ccc |j                  t        j(                  k7  sJ d«       ‚|
|t1        ||«      t3        ||	«      f| j                   |<   �ŒN yc c}w )z5
        Collect histogram on absolute value
        r8   z for tensor=r
   z6The calibration expects only one element type but got r   r   )r5   zMonly float32 or float16 is supported, every constant must be explicitly typedrl   ro   r   z'old_min should be a numpy array but is r‹   N)r<   r[   r9   r   r²   rA   r   rw   r%   r>   ÚflattenÚsizerƒ  r„  r^   ÚabsoluterÄ  Ú	histogramr˜  r&   Úfloat64r@   ÚarangeÚhstackrt  ru  )rD   rÀ  re  Údata_arrÚarrÚaÚdtypesÚdata_arr_npr|  r}  r3   r4   Úold_histogramrx  ry  Úold_histÚold_hist_edgesÚ	temp_amaxÚwidthÚnew_bin_edgess                       r   rË  z)HistogramCollector.collect_absolute_value—  sZ  € ð !,× 1Ñ 1Ó 3ó 4	sÑˆF�HÜ˜(¤DÔ)Ø#ò m�CÜ% c¬2¯:©:Õ6ÐlÐ:JÌ4ÐPSË9È+ÐUaÐbhÐakÐ8lÓlÐ6ðmà+3Ö4 a˜!Ÿ'›'Ð4�Ð4Ü˜6“{ aÒ'ð ØLÈVÈHÐT`ÐagÐ`jÐkóÐ'ô !Ÿj™j¨Ó2‘Ü ¬"¯*©*Ô5Ü Ð#3´D¸³NÐ3CÀ<ÐPVÈzÐ!ZÓ[Ð[à&�Ø%×-Ñ-Ó/ˆKØ×Ñ !Ò#ÜŸI™I kÓ2�	ÜŸI™I kÓ2‘	äŸH™H Q¨k×.?Ñ.?Ô@�	ÜŸH™H Q¨k×.?Ñ.?Ô@�	äŸ+™+ kÓ2ˆKà˜T×0Ñ0Ñ0ä#%§<¡<°À$Ç-Á-Ô#PÑ ��jØ'×.Ñ.¨{×/@Ñ/@ÓA�
Ø"×(Ñ(¬B¯J©JÒ6ð ØcóÐ6ð 04°ZÀÈIÐ.V�×#Ñ# FÓ+à $× 3Ñ 3°FÑ ;�Ø'¨Ñ*�Ø'¨Ñ*�Ü˜w¨Ô0ÐkÐ4[Ô\`ÐahÓ\iÐ[jÐ2kÓkÐ0Ü˜w¨Ô0ÐkÐ4[Ô\`ÐahÓ\iÐ[jÐ2kÓkÐ0Ø(¨Ñ+�Ø!.¨qÑ!1�ÜŸI™I kÓ2�	Ø˜~¨bÑ1Ò1à*¨1Ñ-°¸qÑ0AÑA�Eä$&§I¡I¨n¸RÑ.@À5Ñ.HÈ)ÐV[ÑJ[Ð]bÓ$c�MÜ%'§Y¡Y°ÀÐ/NÓ%O�NÜ#%§<¡<°À.Ô#QÑ ��jØ'×.Ñ.¨{×/@Ñ/@ÓA�
Ø�_”s˜8“}Ó%¨Ñ1Ó%Ø"×(Ñ(¬B¯J©JÒ6ð ØcóÐ6ð 04°ZÄÀWÈiÓAXÔZ]Ð^eÐgpÓZqÐ.r�×#Ñ# FÓ+ñi4	sùò 5s   Á#M!c           	      óî  — |j                  «       D �]a  \  }}t        j                  |«      }|j                  «       }|j                  dkD  r+t        j
                  |«      }t        j                  |«      }nBt        j                  d|j                  ¬«      }t        j                  d|j                  ¬«      }t        j                  t        t        |«      t        |«      «      |j                  ¬«      }|| j                  v r3| j                  |   }| j                  |||||«      | j                  |<   �Œ&t        j                  || j                  | |f¬«      \  }}	||	|||f| j                  |<   �Œd y)z1
        Collect histogram on real value
        r   r   ©rH  N)r<   r   r%   rÍ  rÎ  rƒ  r„  r^   r   ru  r…  rÄ  Úmerge_histogramrÐ  r˜  )
rD   rÀ  re  rÔ  r|  r}  Ú	thresholdrÙ  r3   r4   s
             r   rÊ  z HistogramCollector.collect_valueÑ  s<  € ð !,× 1Ñ 1Ó 3ó 	ÑˆF�HÜ—z‘z (Ó+ˆHØ×'Ñ'Ó)ˆHà�}‰}˜qÒ ÜŸI™I hÓ/�	ÜŸI™I hÓ/‘	äŸH™H Q¨h¯n©nÔ=�	ÜŸH™H Q¨h¯n©nÔ=�	äŸ™¤¤S¨£^´S¸³^Ó!DÈHÏNÉNÔ[ˆIà˜×,Ñ,Ñ,Ø $× 3Ñ 3°FÑ ;�Ø.2×.BÑ.BØ! 8¨Y¸	À9ó/�×#Ñ# FÓ+ô $&§<¡<°¸$¿-¹-ÐQZÐPZÐ\eÐOfÔ#gÑ ��jàØØØØð/�×#Ñ# FÓ+ñ)	r   c                 ó  — |\  }}}}	}
||
k  rEt        j                  |t        |«      |
 |
f¬«      \  }}||z   |t        ||«      t	        |	|«      |
fS |
dk(  r-t        j                  |t        |«      | |f¬«      \  }}||z  }nft        |«      }d|
z  |z  }t        ||
z
  |z  dz   «      }|d|z  z   }||z  |
z   }t        j                  ||| |f¬«      \  }}||||z
  xxx |z  ccc ||t        ||«      t	        |	|«      |fS )Nrà  r   rl   r
   )r   rÐ  rw   rt  ru  r_   )rD   rÙ  rÔ  rz  r{  Únew_thresholdrÚ  rÛ  rx  ry  Úold_thresholdÚnew_histr?  r3   r4   Úold_num_binsÚ
old_strideÚhalf_increased_binsÚnew_num_binss                      r   rá  z"HistogramCollector.merge_histogramñ  sT  € ØFSÑCˆ�> 7¨G°]à˜MÒ)ÜŸ,™, x´°X³ÈÀ~ÐWdÐFeÔf‰KˆH�aà˜8Ñ#ØÜ�G˜WÓ%Ü�G˜WÓ%Øðð ð  Ò!Ü#%§<¡<°¼#¸h»-ÐQ^ÐP^Ð`mÐOnÔ#oÑ ��jØ˜Ñ ‘ä" 8›}�Ø Ñ.°Ñ=�
Ü&)¨=¸=Ñ+HÈZÑ*WÐZ[Ñ*[Ó&\Ð#Ø+¨aÐ2EÑ.EÑE�Ø 3°jÑ @À=Ñ P�Ü#%§<¡<°¸,ÐP]È~Ð_lÐNmÔ#nÑ ��jØÐ(¨<Ð:MÑ+MÓNÐRZÑZÓNàØÜ�G˜WÓ%Ü�G˜WÓ%Øðð r   c                 ób  — | j                   rt        | j                   «      dk(  rt        d«      ‚t        d| j                  ›d�«       | j                  dk(  r| j                  «       S | j                  dk(  r| j                  «       S | j                  dk(  r| j                  «       S t        d«      ‚)	Nr   z=Histogram has not been collected. Please run collect() first.z0Finding optimal threshold for each tensor using z algorithm ...r,   rš  r»  rÈ  )rÄ  rw   r>   rÉ  r�   Úcompute_entropyÚcompute_percentileÚcompute_distributionrL   s    r   r­  z,HistogramCollector.compute_collection_result  sœ   € Ø×"Ò"¤c¨$×*=Ñ*=Ó&>À!Ò&CÜÐ\Ó]Ð]ÜÐ@ÀÇÁÀÈ~Ð^Ô_à�;‰;˜)Ò#Ø×'Ñ'Ó)Ð)Ø�[‰[˜LÒ(Ø×*Ñ*Ó,Ð,Ø�[‰[˜NÒ*Ø×,Ñ,Ó.Ð.äÐcÓdÐdr   c                 óˆ  — | j                   dk  s| j                   dkD  rt        d«      ‚| j                  }| j                   }i }t        dt	        |«      › �«       t        d| j
                  › �«       t        dd|z
  › d|› d	�«       |j                  «       D �]¦  \  }}|d   }|d
   }|j                  «       }t        j                  ||z  «      }	| j                  rft        j                  |	|dz  «      }
t        j                  ||
   |j                  ¬«       t        j                  ||
   |j                  ¬«      f||<   n‚d|z
  dz  }t        j                  |	d|z
  «      }
t        j                  |	|«      }t        j                  ||   |j                  ¬«      t        j                  ||
   |j                  ¬«      f||<   |d   }|d   }||   d   |k  r|||   d
   f||<   ||   d
   |kD  r||   d   |f||<   g ||   ¢|d d ¢­||<   t        j                  j!                  dd«      dv s�Œ›t#        ||«       �Œ© |S )Nr   éd   z<Invalid percentile. Must be in range 0 <= percentile <= 100.úNumber of tensors : úNumber of histogram bins : zPercentile : (g      Y@ú,ú)r
   r   g      i@r"   rl   ro   ÚQUANTIZATION_DEBUGÚ0©r
   Ú1)rš  r>   rÄ  rÉ  rw   r˜  r<   r(   r   Úcumsumræ   Úsearchsortedr^   r   rÉ   Úenvironr]   r   )rD   rÄ  rš  Úthresholds_dictre  rÐ  r3   r4   ÚtotalÚcdfÚ	idx_rightÚpercent_to_cut_one_sideÚidx_leftr|  r}  s                  r   rí  z%HistogramCollector.compute_percentile  sZ  € Ø�?‰?˜QÒ $§/¡/°CÒ"7ÜÐ[Ó\Ð\à×,Ñ,ˆØ—_‘_ˆ
àˆäÐ$¤S¨Ó%8Ð$9Ð:Ô;ÜÐ+¨D¯M©M¨?Ð;Ô<Ü�˜u zÑ1Ð2°!°J°<¸qÐAÔBà!/×!5Ñ!5Ó!7ó 	-ÑˆF�IØ˜Q‘<ˆDØ" 1™ˆJØ—H‘H“JˆEÜ—)‘)˜D 5™LÓ)ˆCØ�~Š~ÜŸO™O¨C°¸eÑ1CÓD�	ô —X‘X˜j¨Ñ3¸:×;KÑ;KÔLÐLÜ—H‘H˜Z¨	Ñ2¸*×:JÑ:JÔKð+� Ò'ð
 ,1°:Ñ+=ÀÑ*FÐ'ÜŸO™O¨C°Ð7NÑ1NÓO�	ÜŸ?™?¨3Ð0GÓH�ä—H‘H˜Z¨Ñ1¸×9IÑ9IÔJÜ—H‘H˜Z¨	Ñ2¸*×:JÑ:JÔKð+� Ñ'ð " !™ˆIØ! !™ˆIØ˜vÑ& qÑ)¨IÒ5Ø+4°oÀfÑ6MÈaÑ6PÐ*Q� Ñ'Ø˜vÑ& qÑ)¨IÒ5Ø+:¸6Ñ+BÀ1Ñ+EÀyÐ*Q� Ñ'Ø&K¨¸Ñ(?Ð&KÀ$ÀrÈÀ(Ñ&KˆO˜FÑ#ä�z‰z�~‰~Ð2°CÓ8¸HÓDÜ˜4 Ö,ð;	-ð> Ðr   c                 ó¬  — | j                   }| j                  }i }t        dt        |«      › �«       t        d| j                  › d�«       t        d| j                  › �«       |j                  «       D ]^  \  }}| j                  ||«      }|||<   g |¢|d d ¢­||<   t        j                  j                  dd«      dv sŒMt        |d	   |d
   «       Œ` |S )Nrñ  rò  z: (The number may increase depends on the data it collects)zNumber of quantized bins : rl   rõ  rö  r÷  r   r
   )rÄ  r™  rÉ  rw   r˜  r<   Úget_entropy_thresholdrÉ   rû  r]   r   )rD   rÄ  r™  rü  re  rÐ  Úoptimal_thresholds          r   rì  z"HistogramCollector.compute_entropyM  sì   € Ø×,Ñ,ˆØ!×4Ñ4ÐàˆäÐ$¤S¨Ó%8Ð$9Ð:Ô;ÜÐ+¨D¯M©M¨?Ð:tÐuÔvÜÐ+¨D×,CÑ,CÐ+DÐEÔFà!/×!5Ñ!5Ó!7ò 	7ÑˆF�IØ $× :Ñ :¸9ÐFXÓ YÐØ&7ˆO˜FÑ#Ø&JÐ(9Ð&J¸IÀbÀq¸MÑ&JˆO˜FÑ#ô �z‰z�~‰~Ð2°CÓ8¸HÒDÜ˜9 Q™<¨°1©Õ6ð	7ð Ðr   c                 óÞ  — |dk  rt        d|› d�«      ‚|d d |dd  z   dz  }|dk(  r–| |z  j                  «       | j                  «       z  }| |dz  z  j                  «       | j                  «       z  |dz  z
  dz  }t        j                  ||j                  ¬«      t        j                  ||j                  ¬«      fS t        |«      |k(  rªt        |«      dz  dk(  r™| ||z  z  j                  «       | j                  «       z  }| ||z  |z
  dz  z  j                  «       | j                  «       z  dz  }t        j                  ||j                  ¬«      t        j                  ||j                  ¬«      fS t        j                  |«      |z  }d|t        j                  |«      <   d|t        j                  |«      <   t        j                  |«      |z  |z  }| |z  j                  «       | j                  «       z  }| |dz  z  j                  «       | j                  «       z  |dz  z
  dz  }t        j                  ||j                  ¬«      t        j                  ||j                  ¬«      fS )	Nr   zpower=z <= 0 is invalid.r‹   r
   g      à?rl   r   )	r>   r(   r   r^   r   r_   r…  ÚisnanÚisinf)r3   r4   Úpowerr‡   r/   r0   Úfacts          r   Ú_avg_stdzHistogramCollector._avg_stdb  s  € à�AŠ:Ü˜v e WÐ,=Ð>Ó?Ð?Ø˜S˜b�/ J¨q¨r NÑ2°cÑ9ˆØ�AŠ:Ø˜&‘=×%Ñ%Ó'¨$¯(©(«*Ñ4ˆCØ˜6 1™9Ñ$×)Ñ)Ó+¨d¯h©h«jÑ8¸3À¹6ÑAÀcÑIˆCÜ—8‘8˜C z×'7Ñ'7Ô8¼"¿(¹(À3Èj×N^ÑN^Ô:_Ð_Ð_Üˆu‹:˜Ò¤3 u£:°¡>°QÒ#6Ø˜& %™-Ñ'×,Ñ,Ó.°·±³Ñ;ˆCØ˜F E™M¨CÑ/°AÑ5Ñ5×:Ñ:Ó<¸t¿x¹x»zÑIÈcÑQˆCÜ—8‘8˜C z×'7Ñ'7Ô8¼"¿(¹(À3Èj×N^ÑN^Ô:_Ð_Ð_ä�v‰v�f‹~ Ñ&ˆØ ˆŒR�X‰X�d‹^ÑØ ˆŒR�X‰X�d‹^ÑÜ—‘˜“ 5Ñ(¨4Ñ/ˆØ�f‰}×!Ñ!Ó# d§h¡h£jÑ0ˆØ�v˜q‘yÑ ×%Ñ%Ó'¨$¯(©(«*Ñ4°s¸A±vÑ=À#ÑEˆÜ�x‰x˜ :×#3Ñ#3Ô4´b·h±h¸sÈ*×JZÑJZÔ6[Ð[Ð[r   c           
      ó˜  — | j                   dk  rt        d«      ‚| j                  }i }t        dt	        |«      › �«       t        d| j                   › �«       t        d| j
                  ›d�«       |j                  «       D �]E  \  }}|d   }|d   }|j                  t        j                  k7  sJ ‚| j
                  d	k(  r| j                  ||d¬
«      \  }}n2| j
                  dk(  r| j                  ||d¬
«      \  }}nt        d«      ‚|j                  t        j                  k7  sJ ‚|j                  t        j                  k7  sJ ‚|j                  t        j                  k7  sJ ‚t        |||||j                  «       |j                  «       ¬«      ||<   t        j                  j!                  dd«      dv s�Œ:t#        ||«       �ŒH |S )Ni   z3Invalid num_bins. Must be in range 512 <= num_bins.rñ  rò  zScenario : rô  r   r
   r²  )r  Úp3gUUUUUUÕ?z,Invalid scenario. Must be in {'same', 'p3'}.)r/   r0   r3   r4   r1   r2   rõ  rö  r÷  )r˜  r>   rÄ  rÉ  rw   r›  r<   r   r   rÑ  r
  r.   rt  ru  rÉ   rû  r]   r   )	rD   rÄ  rü  re  rÐ  r3   r4   Úavg_coefÚstd_coefs	            r   rî  z'HistogramCollector.compute_distributionx  s¦  € Ø�=‰=˜3ÒÜÐRÓSÐSà×,Ñ,ˆØˆäÐ$¤S¨Ó%8Ð$9Ð:Ô;ÜÐ+¨D¯M©M¨?Ð;Ô<Ü�˜DŸM™MÐ,¨AÐ.Ô/à!/×!5Ñ!5Ó!7ó 	-ÑˆF�IØ˜Q‘<ˆDØ" 1™ˆJà×#Ñ#¤r§z¡zÒ1Ð1Ð1Ø�}‰} Ò&Ø%)§]¡]°4¸È1 ]Ó%MÑ"�™(Ø—‘ $Ò&Ø%)§]¡]°4¸È9 ]Ó%UÑ"�™(ä Ð!OÓPÐPØ—>‘>¤R§Z¡ZÒ/Ð/Ð/Ø—>‘>¤R§Z¡ZÒ/Ð/Ð/Ø×#Ñ#¤r§z¡zÒ1Ð1Ð1Ü&0ØØØØ%Ø!—~‘~Ó'Ø"Ÿ™Ó(ô'ˆO˜FÑ#ô �z‰z�~‰~Ð2°CÓ8¸HÓDÜ˜4 Ö,ð3	-ð6 Ðr   c           	      ó  — |d   }|d   }|j                   }|dz  }|dz  }|d   j                  }t        j                  ||z
  dz   «      }	t	        |	j                   «      D �
cg c]0  }
t        j
                  d|¬«      t        j
                  d|¬«      f‘Œ2 }}
t	        ||dz   d«      D �]ö  }
||
z
  }t        ||
z   dz   |«      }||   ||   f||
|z
  <   t        j                  ||| «      }|j                  «       }t        |d| «      }t        ||d «      }|dxx   |z  cc<   |dxx   |z  cc<   |dk7  j                  t        j                  «      }t        j                  |t        j                  ¬«      }|j                   |z  }t	        |«      D ]  }||z  }||z   }t        ||| «      ||<   Œ |dxx   t        |||z  d «      z  cc<   t        j                  |j                   t        j                  ¬«      }t	        |«      D ]+  }||z  }||z   }t        ||| «      }|dk7  sŒ!||   |z  ||| Œ- t        |«      }t        |«      }|�|€&t        j
                  t        j                  |¬«      }n!t        j
                  t        ||«      |¬«      }||	|
|z
  <   �Œù t        j                  |	«      }||   }|d   }|d   }|d   |k  r||d   f}|d   |kD  r|d   |f}t!        |d   d«      sJ ‚t!        |d   d«      sJ ‚|S c c}
w )	aF  Given a dataset, find the optimal threshold for quantizing it.
        The reference distribution is `q`, and the candidate distribution is `p`.
        `q` is a truncated version of the original distribution.
        Ref: http://on-demand.gputechconf.com/gtc/2017/presentation/s7310-8-bit-inference-with-tensorrt.pdf
        r   r
   rl   r   Nr‹   ro   r   )rÎ  r   r   ÚzerosrH  r^   rt  r   Údeepcopyr(   r&   rO  r   r   r,   Úargminr@   )rD   rÐ  r™  r3   r4   r˜  Úzero_bin_indexÚnum_half_quantized_binr   Úkl_divergencer5  Ú
thresholdsr¨   r©   Úsliced_distributionÚpÚleft_outliers_countÚright_outliers_countÚnonzerosÚquantized_binsÚnum_merged_binsr<  ÚstartÚendÚqÚnormÚdivÚmin_kl_divergence_idxr  r|  r}  s                                  r   r  z(HistogramCollector.get_entropy_threshold   sw  € ð ˜‰|ˆØ˜q‘\ˆ
Ø—9‘9ˆØ! Q™ˆØ!3°qÑ!8Ðà˜!‘×"Ñ"ˆÜŸ™ Ð2HÑ!HÈ1Ñ!LÓMˆÜTYÐZg×ZlÑZlÓTmÖnÈq”r—x‘x ¨Ô/´·±¸!À5Ô1IÒJÐnˆ
Ðnô  Ð-¨~ÀÑ/AÀ1ÓEó .	<ˆAØ(¨1Ñ,ˆKÜ˜N¨QÑ.°Ñ2°HÓ=ˆIà6@ÀÑ6MÈzÐZcÑOdÐ5eˆJ�qÐ1Ñ1Ñ2ä"&§-¡-°°[ÀÐ0KÓ"LÐð $×(Ñ(Ó*ˆAÜ"% d¨<¨KÐ&8Ó"9ÐÜ#& t¨I¨JÐ'7Ó#8Ð Øˆa‹DÐ'Ñ'‹DØˆb‹EÐ)Ñ)‹Eð ˜Q™—‘¤r§x¡xÓ0ˆHô  ŸX™XÐ&8ÄÇÁÔIˆNØ1×6Ñ6Ð:LÑLˆOô Ð1Ó2ò L�Ø Ñ/�Ø˜oÑ-�Ü(+Ð,?ÀÀcÐ,JÓ(K�˜uÒ%ðLð ˜2Ó¤#Ð&9Ð:LÈÑ:^Ð:`Ð&aÓ"bÑbÓô —‘˜Ÿ™¤r§x¡xÔ0ˆAÜÐ1Ó2ò @�Ø Ñ/�Ø˜oÑ-�ä˜8 E¨#Ð.Ó/�Ø˜1“9Ø#1°%Ñ#8¸4Ñ#?�A�e˜C‘Lð@ô $ AÓ&ˆAÜ# AÓ&ˆAØˆy˜A˜IÜ—h‘hœrŸv™v¨UÔ3‘ä—h‘hœw q¨!›}°EÔ:�Ø8;ˆM˜!Ð4Ñ4Ó5ð].	<ô` !#§	¡	¨-Ó 8ÐØ&Ð'<Ñ=ÐØ˜a‘Lˆ	Ø˜a‘Lˆ	Ø˜QÑ )Ò+Ø!*Ð,=¸aÑ,@Ð AÐØ˜QÑ )Ò+Ø!2°1Ñ!5°yÐ AÐÜÐ(¨Ñ+¨WÔ5Ð5Ð5ÜÐ(¨Ñ+¨WÔ5Ð5Ð5Ø Ð ùòU os   Á"5L	N)r
   )rT   rd   re   rº   rH   rÆ  r¢  rË  rÊ  rá  r­  rí  rì  Ústaticmethodr
  rî  r  rZ   r   r   r¡  r¡  s  s]   „ ñò!ò#òeò8sòtò@ò@eò,ò\ð* ò\ó ð\ò*&óPX!r   r¡  r  rä   rá   c                 ó‚  — d }|t         j                  k(  rp|j                  dd«      }|j                  dd«      }	|j                  dd«      }
|j                  dd «      }|j                  dd«      }t        | |||||	|
||¬«	      }�n |t         j                  k(  rI|j                  d	d
«      }|j                  dd
«      }|j                  dd«      }t        | ||||||¬«      }n¤|t         j                  k(  rI|j                  d	d«      }|j                  dd«      }|j                  dd«      }t        | ||||||¬«      }nH|t         j                  k(  r5|j                  d	d«      }|j                  dd«      }t        | |||||¬«      }|r+|j                  «        |r||_        |j                  «        |S t        d|› �«      ‚)Nræ   Fr&  r'  r‘  r(  rè   )rç   ræ   r&  r'  r(  rè   r˜  r¯  r™  )rç   ræ   r˜  r™  r°  rš  r±  T)rç   ræ   r˜  rš  r›  r²  )rç   r˜  r›  zUnsupported calibration method )ru   rv   r]   r  r’   rª  r“   r«  r”   r¬  r  rë   rí   r>   )rä   rá   rå   Úcalibrate_methodrç   rñ   Úextra_optionsÚ
calibratorræ   r&  r'  r(  rè   r˜  r™  rš  r›  s                    r   Úcreate_calibratorr)  û  sÿ  € ð €JØÔ,×3Ñ3Ò3à!×%Ñ% k°5Ó9ˆ	Ø&×*Ñ*Ð+;¸UÓCˆØ*×.Ñ.Ð/CÀTÓJÐØ#0×#4Ñ#4Ð5OÐQUÓ#VÐ Ø#×'Ñ'¨°uÓ=ˆÜ%ØØ!Ø Ø%=ØØ)Ø1Ø%=Ø#ô

Š
ð 
Ô.×6Ñ6Ò	6à ×$Ñ$ Z°Ó5ˆØ*×.Ñ.Ð/CÀSÓIÐØ!×%Ñ% k°5Ó9ˆ	Ü&ØØ!Ø Ø%=ØØØ1ô
‰
ð 
Ô.×9Ñ9Ò	9à ×$Ñ$ Z°Ó6ˆØ"×&Ñ& |°VÓ<ˆ
Ø!×%Ñ% k°4Ó8ˆ	Ü)ØØ!Ø Ø%=ØØØ!ô
‰
ð 
Ô.×;Ñ;Ò	;à ×$Ñ$ Z°Ó6ˆØ ×$Ñ$ Z°Ó8ˆä+ØØ!Ø Ø%=ØØô
ˆ
ñ Ø× Ñ Ô"ÙØ-6ˆJÔ*Ø×+Ñ+Ô-ØÐä
Ð6Ð7GÐ6HÐIÓ
JÐJr   )Nr   )r½   r¾   r   rj   )4r¬   rÏ   r   r  r¶   rÉ   rÇ   rL  Úcollections.abcr   Úenumr   Úpathlibr   Únumpyr   r,  r   r   r   r	   rò   Úquant_utilsr   r   r   r²   r   r`   r_   r,   r.   rj   ru   ÚABCMetar–   r·   r°   Úboolr×   rÝ   rß   r  r•  rª  r«  r¬  r½  r¡  rv   rr   r)  rZ   r   r   ú<module>r1     sÚ  ðó Û Û Û Û Û 	Û Û Ý $Ý Ý ã Û ß >Ó >ã ç UÑ Uð�—‘ð  §¡ð °·
±
ó ð" Øñ	Ø
�
‰
ðà
�
‰
ðð �$‰,ðð ð	ð
 ‡Z�Zó÷8/ñ /÷d=*ñ =*ô@˜ô ô" c§k¡kõ "ô43˜d×.Ñ.ô 3ð, `eò  Mð ¸ð ÐX\ð Ðimó ó,	$÷k"ñ k"ô\m,�~ô m,ô`DL˜.ô DLôN
Ð+ô 
ôD
Ð.ô 
ôD 
Ð0ô  
ôF"¨¯©õ "ô,E!Ð1ô E!ðT 37Ø/Ø&×-Ñ-Ø"ØØñNKØ�‰:ðNKà# C™=¨4Ñ/ôNKr   