ó
    EñiŸs  ã                   óÆ  • S r SSKrSSKrSSKJr  SSKJr  SSKJrJ	r	  SSK
Jr  SSKJr  SSKrSSKJr  SS	KJr  SS
KJr  \" S\\\4   \\\\\4   4   -  \-  5      r\r\" S\\\\4   -  \\\\\4   4   -  \-  5      r " S S5      r\R4                  R6                  \R4                  R8                  \R4                  R:                  \R4                  R<                  \R4                  R>                  \R4                  R@                  \R4                  RB                  \R4                  RD                  \R4                  RF                  \R4                  RH                  \R4                  RJ                  \R4                  RL                  \R4                  RN                  \R4                  RP                  \R4                  RR                  1r*\R4                  RV                  RX                  \R4                  RV                  RZ                  \R4                  RV                  R\                  \R4                  RV                  R^                  \R4                  RV                  R`                  \R4                  RV                  Rb                  \R4                  RV                  Rd                  \R4                  RV                  Rf                  \R4                  RV                  Rh                  \R4                  RV                  Rj                  \R4                  RV                  Rl                  \R4                  RV                  Rn                  \R4                  RV                  Rp                  \R4                  RV                  Rr                  \R4                  RV                  Rt                  \R4                  RV                  Rv                  \R4                  RV                  Rx                  \R4                  RV                  Rz                  \R4                  RV                  R|                  \R~                  \R€                  \R|                  \R‚                  \R„                  \R†                  \Rˆ                  \RŠ                  \RŒ                  1rG\R�                  SSSSSSSSSSSSSSSSSS S!S"S#S$S%S&1rIS' rJS( rKS) rLS* rMS+\S,\NS-\4S. jrOS/ rPS0 rQS1 rRS2 rSS3 rTS4 rUS5 rVS6 rWS7 rXS8 rYS9 rZS-\[4S: jr\S; r]S< r^S=\R¾                  S>\R¾                  S-\[4S? jr`S@\aSA\aSB\[SC\RÄ                  SD\[S-\\a\a4   4SE jrcSF rdSG reSH\R4                  RÌ                  SI\R4                  RÌ                  S-\NS-  4SJ jrgSK\SL\h\N\4   S-\h\N\4   4SM jriSK\S-SN4SO jrjSP\SL\h\N\4   S-SN4SQ jrkS@\aSA\aS-S4SR jrl\RÚ                  4S=\R¾                  S>\R¾                  S@\aSA\aSC\RÄ                  SS\R¾                  SB\[ST\RÜ                  S-\\R¾                  \R¾                  4   4SU jjroSK\S-\a4SV jrpSW\R4                  RÌ                  SX\\SY4   S-\h\N\\SY4   4   4SZ jrqS[\R4                  RÌ                  S-\4S\ jrrS]rs/ S^Qrtg)_z?
Utils shared by different modes of quantization (eager/graph)
é    N)ÚOrderedDict)ÚCallable)ÚgetfullargspecÚ	signature)ÚAny)ÚTypeAliasType)Ú	QuantType)ÚNode)Úis_parametrizedÚNodePatternÚPatternc                   ó   • \ rS rSrSrSrg)ÚMatchAllNodeé/   zfA node pattern that matches all nodes, used in defining
fusion patterns in FX Graph Mode Quantization
© N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú__static_attributes__r   ó    ÚX/home/mande/repo/quber/.venv/lib/python3.13/site-packages/torch/ao/quantization/utils.pyr   r   /   s   † ôr   r   ÚreluÚrelu_Ú
contiguousÚdetachÚdetach_ÚhardsigmoidÚhardsigmoid_ÚpermuteÚrepeatÚrepeat_interleaveÚreshapeÚresize_ÚshapeÚsigmoidÚsigmoid_ÚsizeÚsqueezeÚsqueeze_ÚtanhÚtanh_Ú	transposeÚ	unsqueezeÚ
unsqueeze_Úviewc                 ó*  • U R                   S:H  =(       a    U R                  [        ;   nU R                   S:H  =(       a    U R                  [        ;   nU R                   S:H  =(       a(    [	        U[        U R                  5         5      [        ;   nX#U4$ )NÚcall_functionÚcall_methodÚcall_module)ÚopÚtargetÚ	func_listÚmethod_listÚtypeÚstrÚmodule_type_list)ÚnodeÚmodulesÚis_call_functionÚis_call_methodÚis_call_modules        r   Ú
check_noderB   ‚   sw   € à—w‘w /Ñ1×N°d·k±kÄYÑ6NÐØ—W‘W Ñ-×L°$·+±+ÄÑ2L€Nà�‰�=Ñ ×X¤T¨'´#°d·k±kÓ2BÑ*CÓ%DÔHXÑ%Xð ð ¨^Ð;Ð;r   c                 óH   • U R                  5       nUR                  U5        U$ )a{  
Combines two dictionaries.

This function takes two dictionaries as input and returns a new dictionary
that contains all the key-value pairs from both input dictionaries.
If there are any duplicate keys in the `additional_dict`, the values
from the `additional_dict` will overwrite those in the `default_dict`.
Args:
    default_dict (dict): The main dictionary that will be used as the base
    additional_dict (dict): The dictionary used to update `default_dict`

Returns:
    dict: The resulting dictionary
Example:
    >>> x = dict(a=1, b=1)
    >>> y = dict(b=2, c=3)
    >>> get_combined_dict(x, y)
    {'a': 1, 'b': 2, 'c': 3}
)ÚcopyÚupdate)Údefault_dictÚadditional_dictÚds      r   Úget_combined_dictrI   Œ   s#   € ð( 	×ÑÓ€AØ‡H�Hˆ_ÔØ€Hr   c                 ó\   • U [         R                  :H  =(       d    U [         R                  :H  $ ©N)ÚtorchÚper_tensor_affineÚper_tensor_symmetric©Úqschemes    r   Úis_per_tensorrQ   ¥   s#   € Ø”e×-Ñ-Ñ-×V°¼E×<VÑ<VÑ1VÐVr   c                 óf   • U [         R                  [         R                  [         R                  4;   $ rK   )rL   Úper_channel_affineÚ per_channel_affine_float_qparamsÚper_channel_symmetricrO   s    r   Úis_per_channelrV   ©   s/   € ØÜ× Ñ Ü×.Ñ.Ü×#Ñ#ðñ ð r   ÚobjÚfqnÚreturnc                 óX   • [         R                  " [        UR                  S5      U 5      $ )zG
Given an obj and a fqn such as "foo.bar.baz", returns gm.foo.bar.baz.
Ú.)Ú	functoolsÚreduceÚgetattrÚsplit)rW   rX   s     r   Úgetattr_from_fqnr`   ±   s!   € ô ×ÒœG S§Y¡Y¨s£^°SÓ9Ð9r   c                 ó  • [         R                  [         R                  [         R                  [         R                  [         R
                  [         R                  [         R                  [         R                  [         R                  [         R                  [         R                  [         R                  [         R                  [         R                  [         R                  [         R                  [         R                  [         R                  [         R                  [         R                  [         R                  [         R                  [         R                  [         R                  0nX;  a  [        S[        U 5      -   5      eX   $ )NzUnsupported dtype: )rL   Úquint8Úuint8Úqint8Úint8Úqint32Úint32Úquint4x2Úquint2x4Úuint16Úint16Úfloat8_e5m2Úfloat8_e4m3fnÚAssertionErrorr;   )ÚqdtypeÚDTYPE_MAPPINGs     r   Úto_underlying_dtyperq   ¸   sÓ   € ä�‰”e—k‘kÜ�‰”U—Z‘ZÜ�‰”e—k‘kÜ�‰œŸ™Ü�‰œŸ™Ü�‰”U—[‘[Ü�
‰
”E—J‘JÜ�‰”e—l‘lÜ�‰”U—[‘[Ü�‰”U—[‘[Ü×Ñœ5×,Ñ,Ü×ÑœU×0Ñ0ð€Mð Ó"ÜÐ2´S¸³[Ñ@ÓAÐAØÑ Ð r   c                 ó&  • SSK Jn  [        U SS 5      nU R                  nX#S.nU(       a  [	        X5      (       a  S US.$ [        U5      (       a  [        R                  nOR[        U5      (       a4  U[        R                  :X  a  [        R                  nU R                  US'   O[        SU 35      eX$S'   U R                  5       u  pVXTS'   XdS'   [        U S	5      (       a  U R                  US	'   [        U S
5      (       a  U R                   US
'   U$ )Nr   )ÚPlaceholderObserverrP   )rP   ÚdtypeÚaxiszUnrecognized qscheme: ÚscaleÚ
zero_pointÚ	quant_minÚ	quant_max)Útorch.ao.quantization.observerrs   r^   rt   Ú
isinstancerQ   rL   rM   rV   rU   rS   Úch_axisÚRuntimeErrorÚcalculate_qparamsÚhasattrrx   ry   )Úobserver_or_fake_quantrs   rP   rt   Úqparamsrv   rw   s          r   Úget_qparam_dictr‚   Ì   s
  € ÝBäÐ,¨i¸Ó>€GØ"×(Ñ(€EØ!Ñ2€Gæ”jÐ!7×MÑMØ¨%Ñ0Ð0ä�W×ÑÜ×)Ñ)‰Ü	˜×	 Ñ	 ð ”e×1Ñ1Ó1Ü×.Ñ.ˆGØ0×8Ñ8ˆ�ŠäÐ3°G°9Ð=Ó>Ð>ð !ˆIÑà.×@Ñ@ÓBÑ€EØˆGÑØ&ˆLÑäÐ% {×3Ñ3Ø5×?Ñ?ˆ�ÑÜÐ% {×3Ñ3Ø5×?Ñ?ˆ�Ñà€Nr   c                 óª   • [        U5      nUR                  U0 5      n[        U 5      U;  a  [        S[        U 5       SU 35      eU[        U 5         $ )a¼  Get the observed/quantized custom module class that we need
to swap `custom_module` to
Input:
    custom_module: input, can be an instance of either a float or observed custom module
    custom_module_class_mapping: the float to observed or observed to quantized custom module class mapping
    qconfig: qconfig configured for the custom module

Output:
    corresponding observed/quantized custom module class for input custom module instance
z5did not find corresponding observed module class for z in mapping: )Úget_quant_typeÚgetr:   rn   )Úcustom_moduleÚcustom_module_class_mappingÚqconfigÚ
quant_typeÚclass_mappings        r   Úget_swapped_custom_module_classr‹   ð   sh   € ô   Ó(€JØ/×3Ñ3°JÀÓC€MÜˆMÓ -Ó/Üð Ü $ ]Ó 3Ð4°MÀ-ÀðRó
ð 	
ð œ˜mÓ,Ñ-Ð-r   c                 óV   • U c  [        S5      eU R                  5       nUR                  $ )Nz6qconfig must be provided to determine activation dtype)rn   Ú
activationrt   )rˆ   r�   s     r   Úactivation_dtyperŽ     s-   € Ø�ÜÐUÓVÐVØ×#Ñ#Ó%€JØ×ÑÐr   c                 óV   • U c  [        S5      eU R                  5       nUR                  $ )Nz2qconfig must be provided to determine weight dtype)rn   Úweightrt   )rˆ   r�   s     r   Úweight_dtyper‘     s)   € Ø�ÜÐQÓRÐRØ�^‰^Ó€FØ�<‰<Ðr   c                 óx  • [        U 5      [        R                  [        R                  [        R                  [        R
                  [        R                  [        R                  [        R                  [        R                  [        R                  [        R                  4
;   =(       a    [        U 5      (       + $ )z‰Given a qconfig, decide if the activation needs to be
quantized or not, this includes quantizing to quint8, qint8 and qint32 and float16
)rŽ   rL   rb   rd   rf   Úfloat16rc   re   rk   rg   rl   rm   Ú#activation_is_dynamically_quantized©rˆ   s    r   Ú"activation_is_statically_quantizedr–     sw   € ô ˜GÓ$Ü�‰Ü�‰Ü�‰Ü�‰Ü�‰Ü�
‰
Ü�‰Ü�‰Ü×ÑÜ×Ñð)ñ ÷ =ô 3°7Ó;Ô;ð=r   c                 ó"   • [        U 5      u  pnU$ )z–Given a qconfig, decide if the activation needs to be
dynamically quantized or not, this includes dynamically quantizing to
quint8, qint8 and float16
)Úget_qconfig_dtypes)rˆ   Ú_activation_dtypeÚ_Úactivation_is_dynamics       r   r”   r”   '  s   € ô
 3EÀWÓ2MÑ/ÐÐ/Ø Ð r   c                 ó–   • [        U 5      [        R                  [        R                  [        R                  [        R
                  4;   $ )zzGiven a qconfig, decide if the activation needs to be
quantized to int8 or not, this includes quantizing to quint8, qint8
)rŽ   rL   rb   rd   rc   re   r•   s    r   Úactivation_is_int8_quantizedr�   0  s7   € ô ˜GÓ$Ü�‰Ü�‰Ü�‰Ü�
‰
ð	)ñ ð r   c                 óZ   • [        U 5      [        R                  [        R                  4;   $ )zPGiven a qconfig, decide if the activation needs to be
quantized to int32 or not
)rŽ   rL   rf   rg   r•   s    r   Úactivation_is_int32_quantizedrŸ   <  s!   € ô ˜GÓ$¬¯©´u·{±{Ð(CÑCÐCr   c                 óJ  • [        U 5      [        R                  [        R                  [        R                  [        R
                  [        R                  [        R                  [        R                  [        R                  [        R                  [        R                  4
;   $ )zCGiven a qconfig, decide if the weight needs to be
quantized or not
)r‘   rL   rb   rd   r“   rh   rc   re   rk   rg   rl   rm   r•   s    r   Úweight_is_quantizedr¡   C  se   € ô ˜Ó Ü�‰Ü�‰Ü�‰Ü�‰Ü�‰Ü�
‰
Ü�‰Ü�‰Ü×ÑÜ×Ñð%ñ ð r   c                 ó–   • [        U 5      [        R                  [        R                  [        R                  [        R
                  4;   $ )zNGiven a qconfig, decide if the weight needs to be statically
quantized or not
)r‘   rL   rb   rd   rc   re   r•   s    r   Úweight_is_statically_quantizedr£   U  s-   € ô ˜Ó ¤U§\¡\´5·;±;ÄÇÁÌUÏZÉZÐ$XÑXÐXr   c                 óÊ   • [        U 5      u  pnU[        R                  [        R                  4;   =(       a,    U[        R                  [        R
                  4;   =(       a    U$ )zLGiven a qconfig, returns True if this op is using int8 dynamic
quantization
)r˜   rL   rb   rc   rd   re   )rˆ   rŽ   r‘   r›   s       r   Ú op_is_int8_dynamically_quantizedr¥   \  sV   € ô =OÈwÓ<WÑ9ÐÐ$9àœUŸ\™\¬5¯;©;Ð7Ñ7÷ 	"ð 	œŸ™¤e§j¡jÐ1Ñ1÷	"ð "ðr   c                 óª   • U c  [        S5      eU R                  5       nU R                  5       n[        USS5      nUR                  UR                  U4$ )z_returns the qconfig tuple for qconfig:
(activation_dtype, weight_dtype, activation_is_dynamic)
z*qconfig must be provided to extract dtypesÚ
is_dynamicF)rn   r�   r�   r^   rt   )rˆ   r�   r�   Úact_is_dynamics       r   r˜   r˜   j  sT   € ð �ÜÐIÓJÐJØ×#Ñ#Ó%€JØ�^‰^Ó€FÜ˜Z¨°uÓ=€NØ×Ñ˜fŸl™l¨NÐ;Ð;r   c           
      óº  • U c  [        S5      eU R                  5       nU R                  5       n[        R                  [        R
                  [        R                  [        R                  [        R                  [        R                  [        R                  [        R                  [        R                  [        R                  /
nUR                  U;   ab  [        US5      (       a!  UR                   (       a  ["        R$                  $ UR                  U;   a  ["        R&                  $ ["        R(                  $ UR                  [        R*                  :X  a`  [        US5      (       a!  UR                   (       a  ["        R$                  $ UR                  [        R*                  :X  a  ["        R&                  $ [-        SUR                   SUR                   S35      e)Nz0qconfig must be provided to determine quant typer§   z=Unrecognized dtype combination in get_quant_type: activation(z	),weight(Ú))rn   r�   r�   rL   rb   rd   rh   rf   rc   re   rk   rg   rl   rm   rt   r   r§   r	   ÚDYNAMICÚSTATICÚWEIGHT_ONLYr“   Ú	Exception)rˆ   r�   r�   Ústatic_dtypess       r   r„   r„   v  sS  € Ø�ÜÐOÓPÐPØ×#Ñ#Ó%€JØ�^‰^Ó€Fä�‰Ü�‰Ü�‰Ü�‰Ü�‰Ü�
‰
Ü�‰Ü�‰Ü×ÑÜ×Ñð€Mð ‡|�|�}Ó$Ü�:˜|×,Ñ,°×1F×1FÜ×$Ñ$Ð$Ø×Ñ Ó.Ü×#Ñ#Ð#ä×(Ñ(Ð(à‡|�|”u—}‘}Ó$Ü�:˜|×,Ñ,°×1F×1FÜ×$Ñ$Ð$Ø×Ñ¤§¡Ó.Ü×#Ñ#Ð#ä
Ø
GÈ
×HXÑHXÐGYð ZØ—,‘,�˜qð	"óð r   Úmin_valÚmax_valc                 óÄ  • U R                  5       S:X  d  UR                  5       S:X  a  [        R                  " SSS9  gU R                  5       S:X  d  UR                  5       S:X  aL  U [	        S5      :X  a%  U[	        S5      :X  a  [        R                  " SSS9  gX:”  a  [        SU  S	U 35      e g
[        R                  " X:„  5      (       a  [        SU  S	U 35      eg
)z€Checks if the given minimum and maximum values are valid, meaning that
they exist and the min value is less than the max value.
r   zMmust run observer before calling calculate_qparams. Returning default values.é   ©Ú
stacklevelFÚinfz-infzmin z should be less than max T)ÚnumelÚwarningsÚwarnÚdimÚfloatrn   rL   Úany)r°   r±   s     r   Úcheck_min_max_validr½   ›  sÜ   € ð ‡}�}ƒ˜!Ó˜wŸ}™}›°!Ó3Ü�Šð*àò	
ð
 à‡{�{ƒ}˜Ó˜WŸ[™[›]¨aÓ/Ø”e˜E“lÓ" w´%¸³-Ó'?Ü�MŠMð.àòð àÓÜ  4¨ yÐ0IÈ'ÈÐ!SÓTÐTð ð ô �9Š9�WÑ&×'Ñ'Ü  4¨ yÐ0IÈ'ÈÐ!SÓTÐTàr   rx   ry   Úhas_customized_qrangert   Úreduce_rangec                 óf  • U(       aÏ  U[         R                  [         R                  4;   a  Su  pVOSu  pVXp‡Ub  Ub  UUpeXe-
  S-   n	U[         R                  [         R                  4;   a  SU	s=:  a  S::  d  O  [        S5      eO>U[         R                  [         R                  4;   a  SU	s=:  a  S::  d  O  [        S5      eU(       a	  U S	-  US	-  pX4$ U[         R                  [         R                  4;   a  U(       a  S
u  pX4$ Su  p X4$ U[         R                  [         R                  4;   a  U(       a  Su  pX4$ Su  p X4$ U[         R                  [         R                  4;   a  Su  pX4$ U[         R                  :X  a  Su  pX4$ U[         R                  :X  a  Su  pX4$ Su  pX4$ )zlCalculates actual qmin and qmax based on the quantization range,
observer datatype and if range is reduced.
)r   l   ÿÿ )r   éÿ   é   r   é   zRquantization range should be positive and not exceed the maximum bit range (=256).l        zYquantization range should be positive and not exceed the maximum bit range (=4294967296).r³   )iÀÿÿÿé?   )i€ÿÿÿé   )r   rÅ   )i   €iÿÿÿ)r   iÿÿ  )i €ÿÿiÿ  )r   é   )
rL   rf   rg   rd   re   rn   rb   rc   rj   rk   )
rx   ry   r¾   rt   r¿   Úinitial_quant_minÚinitial_quant_maxÚcustom_quant_minÚcustom_quant_maxÚ
qrange_lens
             r   Úcalculate_qmin_qmaxrÌ   º  sò  € ö ð ”U—\‘\¤5§;¡;Ð/Ó/Ø3?Ñ0ÐÐ0à39Ñ0Ðð .7Ð*ØÑ'Ð,<Ñ,Hà Ø ð  1ð
 'Ñ:¸QÑ>ˆ
Ø”U—[‘[¤%§*¡*Ð-Ó-Ø˜
Õ) cÕ)Ü$Øhóð ð *ð ”u—|‘|¤U§[¡[Ð1Ó1Ø˜
Õ+ eÕ+Ü$Øoóð ö Ø#,°¡>°9À±>�yð* ÐÐð% ”U—[‘[¤%§*¡*Ð-Ó-ÞØ'.Ñ$�	ð  ÐÐð (1Ñ$�	˜9ð ÐÐð ”u—|‘|¤U§[¡[Ð1Ó1ÞØ'-Ñ$�	ð ÐÐð (.Ñ$�	˜9ð ÐÐð ”u—|‘|¤U§[¡[Ð1Ó1Ø#<Ñ ˆIð ÐÐð ”e—l‘lÓ"Ø#/Ñ ˆIð
 ÐÐð	 ”e—k‘kÓ!Ø#6Ñ ˆIð ÐÐð $)Ñ ˆIØÐÐr   c                 óf   • U R                  SS5      n[        U5      S:X  a  SUS   4$ US   US   4$ )z$
Turn 'foo.bar' into ['foo', 'bar']
r[   rÂ   Ú r   )ÚrsplitÚlen)r7   Úrs     r   Ú_parent_namerÒ   ú  s>   € ð 	�‰�c˜1Ó€AÜ
ˆ1ƒv�ƒ{Ø�1�Q‘4ˆxˆà�‰t�Q�q‘TˆzÐr   c                 ó´   • [        U R                  5      S:X  a  g[        U 5      (       a.  [        U R                  5      S:H  =(       a    SU R                  ;   $ g)zŠ
Checks if module._modules is empty or
if module is a parametrization, checks that module._modules only has
the 'parametrizations' module
r   TrÂ   ÚparametrizationsF)rÐ   Ú_modulesr   )Úmodules    r   Ú)has_no_children_ignoring_parametrizationsr×     sI   € ô ˆ6�?‰?Ó˜qÓ ØÜ	˜×	 Ñ	 Ü�6—?‘?Ó# qÑ(×RÐ-?À6Ç?Á?Ñ-RÐRàr   ÚrootÚ	submodulec                 óF   • U R                  5        H  u  p#XL d  M  Us  $    g)a.  Get the path (fully qualified name) of a submodule

Example::

>> class M(torch.nn.Module):
       def __init__(self) -> None:
           self.linear = torch.nn.Linear(5, 5)
       def forward(self, x):
           return self.linear(x)

>> m = M()
>> l = m.linear
>> _get_path_of_module(m, l)
"linear"
N)Únamed_modules)rØ   rÙ   ÚnÚps       r   Ú_get_path_of_modulerÞ     s(   € ð$ ×"Ñ"Ö$‰ˆØŒ>ØŠHñ %ð r   ÚfÚlocc                 óŽ   • UR                  5        VVs0 s H"  u  p#U[        U 5      R                  ;   d  M   X#_M$     snn$ s  snnf )z�Get local keyword arguments

Example::

>> def f(self, a, b=9):
       pass
>> loc = {"a": 6, "c": 7}
>> _get_signature_locals(f, loc)
{"a": 6}
)Úitemsr   Ú
parameters)rß   rà   ÚkÚvs       r   Ú_get_signature_localsræ   +  s9   € ð !ŸY™Yœ[ÔIš[‘T�Q¨A´¸1³×1HÑ1HÑ,H‹DˆAŠD™[ÒIÐIùÓIs
   ”A·AzOrderedDict[str, Any]c                 óB  • 0 n[        U 5      R                  R                  5        Hl  u  p#UR                  UR                  La  UR                  X'   M.  UR
                  UR                  L a  SX'   MM  UR
                  UR                  L d  Mh  0 X'   Mn     [        U5      $ )z�Get all default keyword arguments from function signature

Example::

>> def f(self, a, b=9):
       pass
>> _get_default_kwargs(f)
{"b": 9}
r   )	r   rã   râ   ÚdefaultÚemptyÚkindÚVAR_POSITIONALÚVAR_KEYWORDr   )rß   ÚkwargsÚnameÚparams       r   Ú_get_default_kwargsrð   9  s‚   € ð €FÜ  “|×.Ñ.×4Ñ4Ö6‰ˆØ�=‰= §¡Ò+Ø Ÿ=™=ˆF‹LØ�Z‰Z˜5×/Ñ/Ò/ØˆF‹LØ�Z‰Z˜5×,Ñ,Ô,ØˆF‹Lñ 7ô �vÓÐr   Úfuncc                 óš   • [        U 5      n[        X5      nUR                  5       nUR                  5        H  u  pVXT;   d  M  XdU'   M     U$ )a  Given a function and local function arguments, normalize the keyword
arguments by filling in default arguments from function signature

Example::

>> def f(self, key1=3, key2=3):
       pass
>> loc = {"key2": 6}
>> _normalize_kwargs(f, loc)
{"key1": 3, "key2": 6}
)rð   ræ   rD   râ   )rñ   rà   Údefault_kwargsÚlocal_kwargsÚnormalized_kwargsÚattrÚvals          r   Ú_normalize_kwargsrø   N  sR   € ô )¨Ó.€NÜ(¨Ó3€LØ&×+Ñ+Ó-ÐØ!×'Ñ'Ö)‰	ˆØÕ$à&)˜dÓ#ñ *ð Ðr   c                 óX   • U Ss=::  a  U::  d  O  [        S5      eX:¼  a  [        S5      eg)a=  Validates that the user-specified quantization range is properly initialized
and within the given bound supported by the observer dtype.

To accommodate lower-bit quantization with respect to the existing torch.qint8 and
torch.quint8 datatypes, the user can choose to use dynamic quantization range by passing
in a tuple of initial qmin and qmax values. One use case is these customized qmin and qmax
values are used to calculate static estimates of the scale and zero point for aggressive lower-bit
fake quantization. These estimates are compared against parameters learned through backpropagation.
The related literatures for scale and zero point via backpropagation are as follows:

Learned Step Size Quantization: https://openreview.net/pdf?id=rkgO66VKDS
Trained Quantization Thresholds: https://arxiv.org/pdf/1903.08066.pdf
r   z1Used-specified quantization range must include 0.zKqmin must be strictly less than qmax for user-specified quantization range.N)rn   )rx   ry   s     r   Úvalidate_qmin_qmaxrú   d  s8   € ð  ˜Õ'˜iÕ'ÜÐPÓQÐQØÓÜØYó
ð 	
ð r   ÚepsrP   c                 óÚ  • [        X5      (       dT  [        R                  " S/U R                  R                  S9[        R                  " S/U R                  R                  S94$ [        R
                  " U [        R                  " U 5      5      n[        R                  " U[        R                  " U5      5      n	UR                  n
[        R                  " UR                  5       [        R                  U
S9n[        R                  " UR                  5       [        R                  U
S9nUR                  U
5      nU[        R                  :X  d  U[        R                  :X  a³  [        R                  " U* U	5      n	U	[!        X2-
  5      S-  -  n[        R                  " Xµ5      nU[        R"                  [        R$                  4;   aM  U(       a&  UR'                  UR                  5       X#-   S-  5      nOõUR'                  UR                  5       S5      nOÔU[        R(                  :X  aI  X-
  [!        X2-
  5      -  n[        R*                  " Xµ:„  U[        R,                  " U5      5      nSU -  U-  nOwX˜-
  [!        X2-
  5      -  n[        R                  " Xµ5      nU[        R.                  " X‹-  5      R                  [        R0                  5      -
  n[        R2                  " XÂU5      n[5        UR6                  5      S:X  a*  [        R                  " [!        U5      /UR8                  U
S9n[5        UR6                  5      S:X  ah  [        R                  " [1        U5      /UR8                  U
S9nU[        R(                  :X  a*  [        R                  " [!        U5      /UR8                  U
S9nUR                  [        R                  5      UR                  [        R                  5      4$ )aD  Calculates the quantization parameters, given min and max
value tensors. Works for both per tensor and per channel cases

Args:
    min_val: Minimum values per channel
    max_val: Maximum values per channel

Returns:
    scales: Scales tensor of shape (#channels,)
    zero_points: Zero points tensor of shape (#channels,)
g      ð?)Údevicer   )rt   rý   r³   é€   éÿÿÿÿ)r½   rL   Útensorrý   r:   ÚminÚ
zeros_likeÚmaxÚonesr)   ÚdoubleÚzerosÚint64ÚtorN   rU   r»   rc   rb   Únew_fullrT   ÚwhereÚ	ones_likeÚroundÚintÚclamprÐ   r&   rt   )r°   r±   rx   ry   rt   rû   r¾   rP   Úmin_val_negÚmax_val_posrý   rv   rw   s                r   Údetermine_qparamsr  €  sî  € ô* ˜w×0Ñ0Ü�|Š|˜S˜E¨'¯.©.×*=Ñ*=Ñ>ÄÇÂØˆC˜Ÿ™×+Ñ+ñA
ð 
ð 	
ô —)’)˜G¤U×%5Ò%5°gÓ%>Ó?€KÜ—)’)˜G¤U×%5Ò%5°gÓ%>Ó?€Kà×Ñ€FÜ�JŠJ�{×'Ñ'Ó)´·±ÀfÑM€EÜ—’˜[×-Ñ-Ó/´u·{±{È6ÑR€JØ
�&‰&�‹.€Cà”%×,Ñ,Ó,°¼5×;VÑ;VÓ0VÜ—i’i  ¨kÓ:ˆØœu YÑ%:Ó;¸aÑ?Ñ@ˆÜ—	’	˜%Ó%ˆØ”U—[‘[¤%§,¡,Ð/Ó/Þ$à'×0Ñ0Ø—O‘OÓ%¨	Ñ(=À!Ñ'Có‘
ð (×0Ñ0°·±Ó1BÀCÓH�
øØ	”E×:Ñ:Ó	:ØÑ"¤e¨IÑ,AÓ&BÑBˆÜ—’˜E™K¨´·²ÀÓ0FÓGˆð
 ˜'‘\ EÑ)‰
àÑ*¬e°IÑ4IÓ.JÑJˆÜ—	’	˜%Ó%ˆØ¤§¢¨[Ñ-@Ó!A×!DÑ!DÄUÇYÁYÓ!OÑOˆ
Ü—[’[ ¸	ÓBˆ
ô ˆ5�;‰;Ó˜1Óä—’œe E›l˜^°5·;±;ÀvÑNˆÜ
ˆ:×ÑÓ Ó!ä—\’\Ü�‹_Ð Z×%5Ñ%5¸fñ
ˆ
ð ”e×<Ñ<Ó<ÜŸšÜ�zÓ"Ð#¨:×+;Ñ+;ÀFñˆJð �8‰8”E—L‘LÓ! :§=¡=´·±Ó#=Ð=Ð=r   c                 ó>   • [        [        U 5      R                  5      $ )zGet number of positional args for a function

Example::

>> def f(self, key1=3, key2=3):
       pass
>> _get_num_pos_args(f)
3
)rÐ   r   Úargs)rß   s    r   Ú_get_num_pos_argsr  Î  s   € ô Œ~˜aÓ ×%Ñ%Ó&Ð&r   ÚmodelÚexample_inputs.c                 ó<  ^^^• U m0 mUUU4S jn[         R                  R                  R                  mU[         R                  R                  l         U " U6   T[         R                  R                  l        T$ ! T[         R                  R                  l        f = f)aÑ  Given a model and its example inputs, return a dictionary from
fully qualified name of submodules to example_inputs for that submodule,
e.g. {"linear1": (tensor1,), "linear2": (tensor2,), "sub": (tensor3,),
      "sub.linear1": (tensor4,), ...}

Used to make quantizing submodules easier now that FX Graph Mode Quantization requires
example inputs.

Also works for keyword arguments with default values, we would flatten keyword
arguments as positional arguments and fill in the missing keyword args with default
values, e.g. if we have a forward function:
def forward(self, x, key1=3, key2=3):
    ...

and we call it with self.submodule(x, key2=6)
we'll get example_inputs: (x, 3, 6)

user can also override `key1` with positional arguments as well:
for self.submodule(x, 5, key2=6)
we'll get: (x, 5, 6)

variable positional arguments and variable positional keyword arguments in forward
function are not supported currently, so please make sure no submodules is using
them.
c                 ó¦  >• [        U5      R                  5       n[        U R                  U5      n[	        U R                  5      S-
  nU[        U5      -
  nU(       a+  U(       a$  UR                  SS9  US-  nU(       a	  U(       a  M$  UR                  UR                  5       5        [        U5      n[        TU 5      nUb  UT	U'   T
" U /UQ70 UD6$ )NrÂ   F)Úlast)ÚlistrD   rø   Úforwardr  rÐ   ÚpopitemÚextendÚvaluesÚtuplerÞ   )Úselfr  rí   Úsubmodule_example_inputsrõ   Únum_argsÚ
num_to_popÚsubmodule_example_inputs_tuplerX   Úfqn_to_example_inputsÚorig_module_callrØ   s            €€€r   Ú_patched_module_callÚ7get_fqn_to_example_inputs.<locals>._patched_module_callú  sÊ   ø€ Ü#'¨£:§?¡?Ó#4Ð Ü-¨d¯l©l¸FÓCÐä$ T§\¡\Ó2°QÑ6ˆØ¤Ð$<Ó =Ñ=ˆ
ÞÖ.Ø×%Ñ%¨5Ð%Ñ1Ø˜!‰OˆJö ×.Ð.ð 	!×'Ñ'Ð(9×(@Ñ(@Ó(BÔCÜ).Ð/GÓ)HÐ&Ü! $¨Ó-ˆØ‰?Ø)GÐ! #Ñ&Ù Ð6 tÒ6¨vÑ6Ð6r   )rL   ÚnnÚModuleÚ__call__)r  r  r'  r%  r&  rØ   s      @@@r   Úget_fqn_to_example_inputsr,  Û  st   ú€ ð8 €DØÐ÷7ô  —x‘x—‘×/Ñ/ÐØ3„E‡H�H‡O�OÔð4Ùˆ~Ñð $4Œ�‰�‰Ô Ø Ð øð $4Œ�‰�‰Õ ús   ÁA: Á:!BrÖ   c                 ó  • U R                  5        Vs1 s H  oR                  iM     snU R                  5        Vs1 s H  oR                  iM     sn-  n [        R                  " S5      [        R                  " S5      1U:X  a,  [        R
                  " SSS9  [        R                  " S5      1n [        U5      S:”  a  [        SU 35      e[        U5      S:”  a  [        [        U5      5      nU$ S	nU$ s  snf s  snf )
zz
Returns the unique device for a module, or None if no device is found.
Throws an error if multiple devices are detected.
ÚcpuÚmetazfBoth 'meta' and 'cpu' are present in the list of devices. Module can have one device. We Select 'cpu'.r³   r´   rÂ   zKprepare only works with cpu or single-device CUDA modules, but got devices r   N)
rã   rý   ÚbuffersrL   r¸   r¹   rÐ   rn   ÚnextÚiter)rÖ   rÝ   Údevicesrý   s       r   Ú_assert_and_get_unique_devicer4    s÷   € ð
 "(×!2Ñ!2Ô!4Ó5Ò!4˜A�xŒxÑ!4Ñ5Ø Ÿ.™.Ô*ó9Ú*�Q�ŒÑ*ñ9ñ €Gðô 	�Š�UÓœUŸ\š\¨&Ó1Ð2°gÓ=Ü�ŠØtØò	
ô —<’< Ó&Ð'ˆØÜ
ˆ7ƒ|�aÓÜðØ&˜ið)ó
ð 	
ô %(¨£L°1Ó$4ŒT”$�w“-Ó €FØ€Mð ;?€FØ€Mùò' 6ùò 9s
   “C:¼C?aŠ  torch.ao.quantization is deprecated and will be removed in 2.10. 
For migrations of users: 
1. Eager mode quantization (torch.ao.quantization.quantize, torch.ao.quantization.quantize_dynamic), please migrate to use torchao eager mode quantize_ API instead 
2. FX graph mode quantization (torch.ao.quantization.quantize_fx.prepare_fx,torch.ao.quantization.quantize_fx.convert_fx, please migrate to use torchao pt2e quantization API instead (prepare_pt2e, convert_pt2e) 
3. pt2e quantization has been migrated to torchao (https://github.com/pytorch/ao/tree/main/torchao/quantization/pt2e) 
see https://github.com/pytorch/ao/issues/2259 for more details)r   r   r   rB   rI   rQ   rV   r`   r‚   r‹   rŽ   r‘   r–   r”   r�   rŸ   r¡   r£   r¥   r˜   r„   r½   rÌ   r×   r,  rq   r  rú   ÚDEPRECATION_WARNING)ur   r\   r¸   Úcollectionsr   Úcollections.abcr   Úinspectr   r   Útypingr   Útyping_extensionsr   rL   Ú torch.ao.quantization.quant_typer	   Útorch.fxr
   Útorch.nn.utils.parametrizer   r  r   ÚQuantizerClsr   r   r)  ÚReLUÚReLU6ÚAdaptiveAvgPool1dÚAdaptiveAvgPool2dÚAdaptiveAvgPool3dÚ	AvgPool1dÚ	AvgPool2dÚ	AvgPool3dÚ	MaxPool1dÚ	MaxPool2dÚ	MaxPool3dÚIdentityÚHardsigmoidÚSigmoidÚTanhr<   Ú
functionalÚadaptive_avg_pool1dÚadaptive_avg_pool2dÚadaptive_avg_pool3dÚeluÚ	hardswishÚinstance_normÚ
layer_normÚ
leaky_reluÚsiluÚmishÚdropoutÚ
max_pool1dÚ
max_pool2dÚ
max_pool3dr   ÚhardtanhÚ	hardtanh_r   r'   r.   r#   r*   ÚstackÚsumr,   r/   Úcatr8   Úmeanr9   rB   rI   rQ   rV   r;   r`   rq   r‚   r‹   rŽ   r‘   r–   r”   r�   rŸ   r¡   r£   Úboolr¥   r˜   r„   ÚTensorr½   r  rt   rÌ   rÒ   r×   r*  rÞ   Údictræ   rð   rø   rú   rM   rP   r  r  r,  r4  r5  Ú__all__r   r   r   Ú<module>rg     sO  ðñó Û Ý #Ý $ß -Ý Ý +ã Ý 6Ý Ý 6ñ Ø�5˜˜t˜Ñ$ u¨T°5¸¸t¸Ñ3DÐ-DÑ'EÑEÈÑKó€ð €ñ ØØØˆH�hÐÑñ àˆH�e˜H hÐ.Ñ/Ð/Ñ0ñ1ð 
ñ
ó€÷ñ ð 
‡H�H‡M�MØ	‡H�H‡N�NØ	‡H�H×ÑØ	‡H�H×ÑØ	‡H�H×ÑØ	‡H�H×ÑØ	‡H�H×ÑØ	‡H�H×ÑØ	‡H�H×ÑØ	‡H�H×ÑØ	‡H�H×ÑØ	‡H�H×ÑØ	‡H�H×ÑØ	‡H�H×ÑØ	‡H�H‡M�MðÐ ð$ 
‡H�H×Ñ×+Ñ+Ø	‡H�H×Ñ×+Ñ+Ø	‡H�H×Ñ×+Ñ+Ø	‡H�H×Ñ×ÑØ	‡H�H×Ñ×!Ñ!Ø	‡H�H×Ñ×%Ñ%Ø	‡H�H×Ñ×"Ñ"Ø	‡H�H×Ñ×"Ñ"Ø	‡H�H×Ñ×ÑØ	‡H�H×Ñ×ÑØ	‡H�H×Ñ×ÑØ	‡H�H×Ñ×"Ñ"Ø	‡H�H×Ñ×"Ñ"Ø	‡H�H×Ñ×"Ñ"Ø	‡H�H×Ñ×ÑØ	‡H�H×Ñ× Ñ Ø	‡H�H×Ñ×!Ñ!Ø	‡H�H×Ñ×#Ñ#Ø	‡H�H×Ñ×ÑØ	‡O�OØ	×ÑØ	‡M�MØ	‡M�MØ	‡K�KØ	‡I�IØ	‡J�JØ	‡O�OØ	‡I�Ið9€	ð> 
‡J�JØ
ØØØØØØØØØØØØØØØ
ØØØ
ØØØØØ
ð3€ò<<òò2Wòð:˜#ð : Cð :¨Cô :ò!ò(!òH.ò.òò=ò$!ò	òDòò$Yð°ô ò	<ò"ðJ §¡ð ¸¿¹ð Èô ð>= Øð= àð= ð  ð= ð �;‰;ð	= ð
 ð= ð ˆ3�ˆ8�_ô= ò@òðØ
�(‰(�/‰/ðØ&+§h¡h§o¡oðàˆ4�Zôð0J˜Xð J¨D°°c°©Nð J¸tÀCÈÀH¹~ô Jð˜8ð Ð(?ô ð*˜Hð ¨4°°S°©>ð Ð>Uô ð,
 #ð 
°#ð 
¸$ô 
ðH #×4Ñ4ñK>Ø�\‰\ðK>à�\‰\ðK>ð ðK>ð ð	K>ð
 �;‰;ðK>ð 
�‰ðK>ð  ðK>ð �]‰]ðK>ð ˆ5�<‰<˜Ÿ™Ð%Ñ&õK>ð\
'˜ð 
' cô 
'ð6!Ø�8‰8�?‰?ð6!Ø,1°#°s°(©Oð6!à	ˆ#ˆu�S˜#�X‰Ð
Ñô6!ðr¨%¯(©(¯/©/ð ¸cô ð8	Eð ò�r   