
    fTh|u                        S SK r S SKrS SKrS SKJr  S SKJr  SSKJr  \R                  " \
5      r " S S\R                  5      r " S S	\R                  5      r " S
 S\R                  5      r " S S\R                  5      r " S S\R                  5      r " S S\R                  5      rSS jrSS jrSS jr " S S\5      r " S S\5      r " S S\5      rSS jr " S S\5      rg)     N)nn)Function   )loggingc                   L   ^  \ rS rSrSr         SU 4S jjrSS jrSrU =r$ )QuantEmbedding   a  
Quantized version of `torch.nn.Embedding`. Adds quantization-specific arguments on top of `torch.nn.Embedding`.

Args:
    weight_bit (`int`, *optional*, defaults to `8`):
        Bitwidth for the quantized weight.
    momentum (`float`, *optional*, defaults to `0.95`):
        Momentum for updating the activation quantization range.
    quant_mode (`bool`, *optional*, defaults to `False`):
        Whether or not the layer is quantized.
c                   > [         TU ]  5         Xl        X l        X0l        X@l        XPl        X`l        Xpl        [        R                  " [        R                  " X/5      5      U l        U R                  S[        R                  " S5      5        U R                  S[        R                  " U R                  5      5        Xl        Xl        Xl        SU l        [(        R*                  U l        g )Nweight_scaling_factor   weight_integerF)super__init__num_dimpadding_idxmax_norm	norm_typescale_grad_by_freqsparser   	Parametertorchzerosweightregister_buffer
zeros_like
weight_bitmomentum
quant_modepercentile_modeSymmetricQuantFunctionapplyweight_function)selfnum_embeddingsembedding_dimr   r   r   r   r   _weightr   r   r   	__class__s               _/var/www/auris/envauris/lib/python3.13/site-packages/transformers/models/ibert/quant_modules.pyr   QuantEmbedding.__init__,   s     	"	 & ""4ll5;;/N#OP4ekk!nE-u/?/?/LM$ $$5;;    c           	      b   U R                   (       dc  [        R                  R                  UU R                  U R
                  U R                  U R                  U R                  U R                  5      S 4$ U R                  nUR                  R                  5       nUR                  5       R                  S5      nUR                  5       R                  S5      n[        U R                   XgS5      U l        U R%                  U R                  U R                   U R&                  U R"                  5      U l        [        R                  R                  UU R(                  U R
                  U R                  U R                  U R                  U R                  5      nXR"                  -  U R"                  4$ )Nr   F)r   r   
functional	embeddingr   r   r   r   r   r   datadetachminexpandmax$symmetric_linear_quantization_paramsr   r   r#   r    r   )	r$   x	positionsincremental_stateww_transformw_minw_maxemb_ints	            r)   forwardQuantEmbedding.forwardM   sO   ''KK$$MMNN++KK   KKffmmo!((+!((+%I$//[`in%o""22KK$*>*>@Z@Z
 --))MMNN##KK
 333T5O5OOOr+   )r   r   r   r   r   r   r    r   r   r   r   r   r#   r   r   )	NN       @FFN   ffffff?FNN)	__name__
__module____qualname____firstlineno____doc__r   r=   __static_attributes____classcell__r(   s   @r)   r   r      s7    
   <B"P "Pr+   r   c                   J   ^  \ rS rSrSrSU 4S jjrS r     SS jrSrU =r	$ )	QuantActr   a<  
Quantizes the given activation.

Args:
    activation_bit (`int`):
        Bitwidth for the quantized activation.
    act_range_momentum (`float`, *optional*, defaults to `0.95`):
        Momentum for updating the activation quantization range.
    per_channel (`bool`, *optional*, defaults to `False`):
        Whether to or not use channel-wise quantization.
    channel_len (`int`, *optional*):
        Specify the channel length when set the *per_channel* True.
    quant_mode (`bool`, *optional*, defaults to `False`):
        Whether or not the layer is quantized.
c                   > [         TU ]  5         Xl        X l        XPl        X0l        SU l        [        R                  U l	        U R
                  (       d  U R                  S[        R                  " S5      5        U R                  S[        R                  " S5      5        U R                  S[        R                  " S5      5        U =R                  S-  sl        U =R                  S-  sl        g [        S5      e)NFx_minr   x_maxact_scaling_factorgh㈵>;per-channel mode is not currently supported for activation.)r   r   activation_bitact_range_momentumr   per_channel
percentiler!   r"   act_functionr   r   r   rO   rP   NotImplementedError)r$   rS   rT   rU   channel_lenr   r(   s         r)   r   QuantAct.__init__   s    ,"4$&288  %++a.9  %++a.9  !5u{{1~FJJ$JJJ$J%&cddr+   c           
          U R                   R                   SU R                   SU R                   SU R                  R                  5       S SU R                  R                  5       S S3
$ )Nz(activation_bit=z, quant_mode: z, Act_min: z.2fz, Act_max: ))r(   rC   rS   r   rO   itemrP   )r$   s    r)   __repr__QuantAct.__repr__   si    ~~&&''78K8K7L M??+;tzz7H6M N

)#.a1	
r+   c                    Uc  UOX1-   nU R                   (       Ga  U R                  (       a   S5       eU R                  (       a   S5       eUR                  R	                  5       nUR                  R                  5       n	U	R                  5       R                  5       S:X  a"  UR                  5       R                  5       S:X  d   S5       eU R                  R	                  5       S:  aG  U R                  R                  5       S:  a)  U R                  U-   U l        U R                  U	-   U l	        OU R                  S:X  aM  [        R                  " U R                  U5      U l        [        R
                  " U R                  U	5      U l	        ObU R                  U R                  -  USU R                  -
  -  -   U l        U R                  U R                  -  U	SU R                  -
  -  -   U l	        U R                  (       d  US 4$ Uc  U R                  OUnUc  U R                  OUn	[        U R                  XU R                  S	9U l        Uc2  U R!                  XR                  U R                  U R                  5      n
O.["        R%                  UUU R                  U R                  UU5      n
U R                  R'                  S5      nX-  U R                  4$ )
Nz:percentile mode is not currently supported for activation.rR   r   z5NaN detected when computing min/max of the activationg&|g&|>r   )rU   )trainingrV   rU   r/   r1   r3   isnansumrO   rP   rT   r   r   r4   rS   rQ   rW   FixedPointMulr"   view)r$   r5   pre_act_scaling_factoridentityidentity_scaling_factorspecified_minspecified_maxx_actrO   rP   quant_act_intcorrect_output_scales               r)   r=   QuantAct.forward   sT    %8<===d(dd&''f)ff'JJNN$EJJNN$E;;=$$&!+0A0A0Cq0H GH
 zz~~')djjnn.>.G!ZZ%/
!ZZ%/
 ((B."YYtzz59
"YYtzz59
!ZZ$*A*AAEQQUQhQhMhDii
!ZZ$*A*AAEQQUQhQhMhDii
$;+3

+3

"F4;K;K#
 ") --a1D1DdooW[WnWnoM)//&##'''M  $66;;B?3T5L5LLLr+   )	rW   rT   rQ   rS   rU   rV   r   rP   rO   )rA   FNF)NNNNN
rC   rD   rE   rF   rG   r   r^   r=   rH   rI   rJ   s   @r)   rL   rL   r   s0     e&
  $ $<M <Mr+   rL   c                   H   ^  \ rS rSrSr SU 4S jjrU 4S jrSS jrSrU =r	$ )	QuantLinear   a  
Quantized version of `torch.nn.Linear`. Adds quantization-specific arguments on top of `torch.nn.Linear`.

Args:
    weight_bit (`int`, *optional*, defaults to `8`):
        Bitwidth for the quantized weight.
    bias_bit (`int`, *optional*, defaults to `32`):
        Bitwidth for the quantized bias.
    per_channel (`bool`, *optional*, defaults to `False`):
        Whether or not to use channel-wise quantization.
    quant_mode (`bool`, *optional*, defaults to `False`):
        Whether or not the layer is quantized.
c                   > [         TU ]  5         Xl        X l        [        R
                  " [        R                  " X!/5      5      U l        U R                  S[        R                  " U R                  5      5        U R                  S[        R                  " U R                  5      5        U(       a_  [        R
                  " [        R                  " U5      5      U l        U R                  S[        R                  " U R                  5      5        X@l        Xpl        X`l        XPl        Xpl        SU l        ["        R$                  U l        g )Nr   fc_scaling_factorbias_integerF)r   r   in_featuresout_featuresr   r   r   r   r   r   r   biasr   r   rU   bias_bitr    r!   r"   r#   )	r$   rw   rx   ry   r   rz   rU   r   r(   s	           r)   r   QuantLinear.__init__   s     	&(ll5;;/J#KL-u/?/?/LM0%++d>O>O2PQU[[%>?DI  1A1A$))1LM$$& $$5;;r+   c                 d   > [         TU ]  5       nSU SU R                   SU R                   S3nU$ )N(z weight_bit=z, quant_mode=r\   )r   r^   r   r   )r$   sr(   s     r)   r^   QuantLinear.__repr__  s9    Gs,t/}T__<MQOr+   c                    U R                   (       d4  [        R                  R                  XR                  U R
                  S9S 4$ Ub  UR                  S:X  d   S5       eU R                  nUR                  R                  5       nU R                  (       a1  [        R                  " USS S9u  pV[        R                  " USS S9u  pvO>UR                  5       R                  S5      nUR                  5       R                  S5      n[        U R                  XWU R                  5      U l        U R#                  U R                  U R                  U R$                  U R                   5      U l        U R                   U-  nU R
                  b-  U R#                  U R
                  U R(                  SU5      U l        UR-                  SS5      nX-  n	[        R                  R                  XR&                  U R*                  S9U-  U4$ )N)r   ry   )r   zInput activation to the QuantLinear layer should be globally (non-channel-wise) quantized. Please add a QuantAct layer with `per_channel = True` before this QuantAct layerr   )r   outFra   )r   r   r-   linearr   ry   shaper/   r0   rU   r   r1   r3   r2   r4   r   ru   r#   r    r   rz   rv   rf   )
r$   r5   prev_act_scaling_factorr8   r9   r:   _r;   bias_scaling_factorx_ints
             r)   r=   QuantLinear.forward  s   ==''++DII'NPTTT '27N7T7TX\7\ 	
_	
\
 KKffmmoyy!>HEyy!>HE1OO%,,Q/EOO%,,Q/E!EdooW\eieueu!v"22KK$*>*>@V@V
 #447NN99  $ 4 4TYYuVi jD"9">">q""E+ MM  /B/BIZIZ [^qq
 	
r+   )ry   rz   rv   ru   rw   rx   rU   r    r   r   r   r#   r   )Tr@       FFNrp   rJ   s   @r)   rr   rr      s#     ns<,
#
 #
r+   rr   c                   @   ^  \ rS rSrSrSU 4S jjrS rSS jrSrU =r	$ )	IntGELUi,  aa  
Quantized version of `torch.nn.GELU`. Adds quantization-specific arguments on top of `torch.nn.GELU`.

Args:
    quant_mode (`bool`, *optional*, defaults to `False`):
        Whether or not the layer is quantized.
    force_dequant (`str`, *optional*, defaults to `"none"`):
        Force dequantize the layer if either "gelu" or "nonlinear" is given.
c                 >  > [         TU ]  5         Xl        US;   a  [        R	                  S5        SU l        U R                  (       d  [
        R                  " 5       U l        SU l        SU l	        / SQU l
        U R                  S==   U R                  S   -  ss'   g )	N)	nonlineargeluzForce dequantize geluFg-?   )g]m{ҿgMr      r   )r   r   r   loggerinfor   GELUactivation_fnkconstcoeff)r$   r   force_dequantr(   s      r)   r   IntGELU.__init__7  st    $11KK/0#DO!#D
)


1A&r+   c                    [         R                  " U R                  S   U-  5      n[         R                  " U R                  S   US-  -  5      n[         R                  " U5      n[         R                  " [         R
                  " U5      U* 5      nXVU-   S-  U-   -  nUS-  U R                  S   -  n[        R                  USU R                  -  -  5      nUSU R                  -  -  nXr4$ Nr   r   r   )	r   floorr   signr1   abs	floor_ster"   r   )r$   r   scaling_factorb_intc_intr   abs_inty_ints           r)   int_erfIntGELU.int_erfG  s    DJJqMN:;DJJqMNA,==>zz% ))EIIe,uf55Q.67'*TZZ]: 4:: 56'!TZZ-7$$r+   c                     U R                   (       d  U R                  U5      S 4$ X-  nU R                  X2U R                  -  5      u  pESU-  nX4U-   -  nX%-  S-  nX2-  U4$ )N      ?r   )r   r   r   r   )r$   r5   r   r   sigmoid_intsigmoid_scaling_factor	shift_ints          r)   r=   IntGELU.forwardV  sw    %%a($..".2ll5SWSYSYBY.Z+11	y01'@1D%~55r+   )r   r   r   r   r   )Tnoner   )
rC   rD   rE   rF   rG   r   r   r=   rH   rI   rJ   s   @r)   r   r   ,  s    ' %6 6r+   r   c                   B   ^  \ rS rSrSrSU 4S jjrS rS rS rSr	U =r
$ )	
IntSoftmaxie  a  
Quantized version of `torch.nn.Softmax`. Adds quantization-specific arguments on top of `torch.nn.Softmax`.

Args:
    output_bit (`int`):
        Bitwidth for the layer output activation.
    quant_mode (`bool`, *optional*, defaults to `False`):
        Whether or not the layer is quantized.
    force_dequant (`str`, *optional*, defaults to `"none"`):
        Force dequantize the layer if either "softmax" or "nonlinear" is given.
c                 |  > [         TU ]  5         Xl        SU l        X l        US;   a  [
        R                  S5        SU l        [        SU R                  S9U l        SU l	        SU l
        / S	QU l        U R                  S
==   U R                  S   -  ss'   U R                  S==   U R                  S   -  ss'   g )Nr   )r   softmaxzForce dequantize softmaxF   r   gvq-   )gN$?g'|:?r   r   r   r   )r   r   
output_bitmax_bitr   r   r   rL   actx0r   coef)r$   r   r   r   r(   s       r)   r   IntSoftmax.__init__r  s    $$44KK23#DOB4??;
1			!		!$		!		!$r+   c                 D   [         R                  " 5          [         R                  " U R                  S   U-  5      n[         R                  " U R                  S   US-  -  5      nS S S 5        UW-   U-  W-   nU R                  S   US-  -  nXR4$ ! , (       d  f       N1= fr   )r   no_gradr   r   )r$   r   r   r   r   zs         r)   int_polynomialIntSoftmax.int_polynomial  s    ]]_KK		!~ =>EKK		!~q/@ @AE  U]e#e+1(99   _s   AB
Bc                    [         R                  " 5          [         R                  " U R                  U-  5      nS S S 5        [         R                  " XR
                  W-  5      n[        R                  X-  5      nXU-  -
  nU R                  XR5      u  pg[         R                  " [        R                  USU R
                  U-
  -  -  5      SS9nUSU R
                  -  -  nXb4$ ! , (       d  f       N= f)Nr   r   r1   )
r   r   r   r   r3   r   r   r"   r   clamp)r$   r   r   x0_intqrexp_intexp_scaling_factors           r)   int_expIntSoftmax.int_exp  s    ]]_[[>!9:F 		%f!45OOEN+QJ&*&9&9!&L#++ioogdjj1n8M.MNTUV+am;&& _s   $C&&
C4c                    U R                   (       d   [        R                  R                  USS9S 4$ X-  nUR	                  SSS9u  pEX4-
  nU R                  X25      u  pgU R                  Xg5      u  pX-  nUR                  SSS9n	[        R                  SU R                  -  U	-  5      n
[        R                  Xj-  SU R                  U R                  -
  -  -  5      nSSU R                  -  -  nXb-  U4$ )Nra   r   T)r   keepdimr   r   )r   r   r-   r   r3   r   r   rd   r   r"   r   r   )r$   r5   r   r   	x_int_maxr   r   r   expexp_int_sumfactors              r)   r=   IntSoftmax.forward  s    ==(((3T99"yyRy6	!&*ll5&I# #'((7"G*kkb$k7DLL;!>?//'"2Q4<<$//;Y5Z"Z[Q//'77r+   )r   r   r   r   r   r   r   )Fr   )rC   rD   rE   rF   rG   r   r   r   r=   rH   rI   rJ   s   @r)   r   r   e  s!    
%"!
'8 8r+   r   c                   F   ^  \ rS rSrSrSU 4S jjrS rS rS	S jrSr	U =r
$ )
IntLayerNormi  a  
Quantized version of `torch.nn.LayerNorm`. Adds quantization-specific arguments on top of `torch.nn.LayerNorm`.

Args:
    output_bit (`int`, *optional*, defaults to `8`):
        Bitwidth for the layer output activation.
    quant_mode (`bool`, *optional*, defaults to `False`):
        Whether or not the layer is quantized.
    force_dequant (`str`, *optional*, defaults to `"none"`):
        Force dequantize the layer if either "layernorm" or "nonlinear" is given.
c                    > [         TU ]  5         Xl        X l        [        R
                  " [        R                  " U5      5      U l        [        R
                  " [        R                  " U5      5      U l	        X@l
        US;   a  [        R                  S5        SU l
        U R                  S[        R                  " S5      5        X0l        SU l        S U l        [#        U R                  U R                  S9U l        g )N)r   	layernormzForce dequantize layernormFshiftr   r   r   )r   r   normalized_shapeepsr   r   r   r   r   ry   r   r   r   r   r   r   dim_sqrtrL   
activation)r$   r   r   r   r   r   r(   s         r)   r   IntLayerNorm.__init__  s     0ll5;;/?#@ALL-=!>?	$66KK45#DOWekk!n5$"4??tOr+   c           	         [         R                  " 5          US-  n[         R                  " USSS9n[         R                  " [         R                  " USU R
                  -  -  5      5      R                  5       R                  5       nU R                  n[         R                  " U R                  U5      U l        [        R                  S[        U5       S[        U R                  5       35        S S S 5        g ! , (       d  f       g = f)Nr   Taxisr   zDynamic shift adjustment: z -> )r   r   rd   log2sqrtr   ceilr3   r   r   r   int)r$   r   y_sq_intvar_intr   	shift_olds         r)   	set_shiftIntLayerNorm.set_shift  s    ]]_axHiiq$?GZZ

7Q_+D EFKKMRRTE

I4::u5DJKK4S^4DDTZZHYZ[ __s   CC::
Dc                     U R                  U5        [        R                  USU R                  -  -  5      nUS-  n[        R
                  " USSS9nU$ )z
This fallback function is called when overflow is detected during training time, and adjusts the `self.shift`
to avoid overflow in the subsequent runs.
r   Tr   )r   r   r"   r   r   rd   )r$   r   y_int_shiftedr   r   s        r)   overflow_fallbackIntLayerNorm.overflow_fallback  sL    
 	u!4::(=> !#))H1d;r+   c                    U R                   (       dr  UR                  SSS9nX-
  n[        R                  " US-  SSS9nU[        R                  " U R                  U-   5      -  nXR
                  -  U R                  -   nUS 4$ U R                  cd  [        R                  " UR                  S   [        R                  S9n[        R                  " U5      R                  UR                  5      U l        X-  n[        R                  UR                  SSS95      nXx-
  n	[        R                  U	SU R                   -  -  5      n
U
S-  n[        R"                  " USSS9nU R$                  (       a]  UR'                  5       SU R(                  -  :  a<  U R+                  U	5      nUR'                  5       SU R(                  -  S-   :  d   S5       e[        R                  [        R                  " U5      5      SU R                   -  -  n[        R                  SU-  5      n[        R                  X-  S-  5      n	U R                  S-  nU R                  R,                  R/                  5       U R
                  R,                  R/                  5       -  n[        R                  X-  5      nU	U-   n	X R
                  -  nX-  nX4$ )	Nr   Tr   )dtypeg?zfError detected in overflow handling: `var_int` exceeds `self.max_bit` (the maximum possible bit width)l        i   @)r   meanr   r   r   r   ry   r   tensorr   floattodevice	round_ster"   r   r   rd   rb   r3   r   r   r/   r0   )r$   r5   r   r   yvarnr   mean_intr   r   r   r   std_intr   ry   bias_ints                    r)   r=   IntLayerNorm.forward  s:   66q$6/DA**QT48CEJJtxx#~..AKK$))+Ad7N == QWWQZu{{;A!JJqM,,QXX6DM "??5::1d:#CD !4::(=> !#))H1d; =={{}4<</007{{}q$,,'<< X< //%**W"56DJJF1 23. yy~~$$&$++*:*:*A*A*CD??4#89 '++5"  r+   )
r   ry   r   r   r   r   r   r   r   r   )r@   Fr   r   )rC   rD   rE   rF   rG   r   r   r   r=   rH   rI   rJ   s   @r)   r   r     s#    
P&\	.! .!r+   r   c                 R   U R                   S   n[        USUS-  -
  -  5      n[        XB-  S-  5      n[        R                  " XS9R                  nUS:X  a  US-  nO![        R                  " U * US9R                  * nU(       d   UR                  5       nUR                  5       nX4$ )a  
Calculate the percentile max and min values in a given tensor

Args:
    input (`torch.Tensor`):
        The target tensor to calculate percentile max and min.
    lower_percentile (`float`):
        If 0.1, means we return the value of the smallest 0.1% value in the tensor as percentile min.
    upper_percentile (`float`):
        If 99.9, means we return the value of the largest 0.1% value in the tensor as percentile max.
    output_tensor (`bool`, *optional*, defaults to `False`):
        If True, this function returns tensors, otherwise it returns values.

Returns:
    `Tuple(torch.Tensor, torch.Tensor)`: Percentile min and max value of *input*
r   r   g{Gz?)r   )r   roundr   kthvaluevaluesr]   )	inputlower_percentileupper_percentileoutput_tensorinput_lengthlower_indexupper_indexupper_boundlower_bounds	            r)   get_percentile_min_maxr	    s    " ;;q>L,<t,C(CDEK7$>?K..6==K1!Ao ~~uf<CCC!&&(!&&(##r+   c                    [        U R                  5      S:X  a)  UR                  SSSS5      nUR                  SSSS5      nO`[        U R                  5      S:X  a%  UR                  SS5      nUR                  SS5      nO"UR                  S5      nUR                  S5      nU(       a3  U R                  SU-  5      R	                  U5      R                  5         U $ [        R                  " SU-  U -  U-   5      $ )a  
Quantize single-precision input tensor to integers with the given scaling factor and zeropoint.

Args:
    input (`torch.Tensor`):
        Single-precision input tensor to be quantized.
    scale (`torch.Tensor`):
        Scaling factor for quantization.
    zero_pint (`torch.Tensor`):
        Shift for quantization.
    inplace (`bool`, *optional*, defaults to `False`):
        Whether to compute inplace or not.

Returns:
    `torch.Tensor`: Linearly quantized value of *input* according to *scale* and *zero_point*.
   ra   r   r   r   )lenr   rf   mul_add_round_r   r   )r   scale
zero_pointinplaces       r)   linear_quantizer  5  s    $ 5;;1

2q!Q'__RAq1
	U[[	Q	

2q!__R+


2__R(


3;$$Z0779;;sU{U*Z788r+   c                    [         R                  " 5          SU S-
  -  S-
  nU(       aa  [         R                  " [         R                  " UR	                  5       UR	                  5       /SS9SS9u  pV[         R
                  " USS9U-  nO@[        UR	                  5       UR	                  5       5      n[         R
                  " USS9U-  nSSS5        U$ ! , (       d  f       W$ = f)a  
Compute the scaling factor with the given quantization range for symmetric quantization.

Args:
    saturation_min (`torch.Tensor`):
        Lower bound for quantization range.
    saturation_max (`torch.Tensor`):
        Upper bound for quantization range.
    per_channel (`bool`, *optional*, defaults to `False`):
        Whether to or not use channel-wise quantization.

Returns:
    `torch.Tensor`: Scaling factor that linearly quantizes the given range between *saturation_min* and
    *saturation_max*.
r   r   r   g:0yE>r   N)r   r   r3   stackr   r   )num_bitssaturation_minsaturation_maxrU   r   r  r   s          r)   r4   r4   X  s    $ 
(Q,!#yyn.@.@.BNDVDVDX-Y_`!aghiHEKK4014E **,n.@.@.BCEKK4014E 
 L 
 Ls   B4C
C#c                   8    \ rS rSrSr\S 5       r\S 5       rSrg)r!   ix  zo
Class to quantize the given floating-point values using symmetric quantization with given range and bitwidth.
c                     [         R                  " SUR                  S9nSUS-
  -  S-
  n[        XUSS9n[         R                  " Xv* US-
  5      nX@l        U$ )a  
Args:
    x (`torch.Tensor`):
        Floating point tensor to be quantized.
    k (`int`):
        Quantization bitwidth.
    percentile_mode (`bool`):
        Whether or not to use percentile calibration.
    scale (`torch.Tensor`):
        Pre-calculated scaling factor for *x*. Note that the current implementation of SymmetricQuantFunction
        requires pre-calculated scaling factor.

Returns:
    `torch.Tensor`: Symmetric-quantized value of *input*.
g        )r   r   r   F)r  )r   r   r   r  r   r  )ctxr5   r   r    r  r  r   new_quant_xs           r)   r=   SymmetricQuantFunction.forward}  sY    " \\#ell;
!a%L1%a
EJkk+r1q59	r+   c                     U R                   n[        UR                  5      S:X  a  UR                  SSSS5      nO=[        UR                  5      S:X  a  UR                  SS5      nOUR                  S5      nUR	                  5       U-  S S S S 4$ )Nr  ra   r   r   )r  r  r   rf   clone)r  grad_outputr  s      r)   backwardSymmetricQuantFunction.backward  s    		{  !Q&JJr1a+E""#q(JJr1%EJJrNE  "U*D$dBBr+    N	rC   rD   rE   rF   rG   staticmethodr=   r!  rH   r#  r+   r)   r!   r!   x  s1      2 
C 
Cr+   r!   c                   8    \ rS rSrSr\S 5       r\S 5       rSrg)r   i  z3
Straight-through Estimator(STE) for torch.floor()
c                 .    [         R                  " U5      $ r   )r   r   r  r5   s     r)   r=   floor_ste.forward      {{1~r+   c                 "    UR                  5       $ r   r  r  r   s     r)   r!  floor_ste.backward        ""r+   r#  Nr$  r#  r+   r)   r   r     /       # #r+   r   c                   8    \ rS rSrSr\S 5       r\S 5       rSrg)r   i  z3
Straight-through Estimator(STE) for torch.round()
c                 .    [         R                  " U5      $ r   )r   r   r(  s     r)   r=   round_ste.forward  r*  r+   c                 "    UR                  5       $ r   r,  r-  s     r)   r!  round_ste.backward  r/  r+   r#  Nr$  r#  r+   r)   r   r     r0  r+   r   c                    U R                  5       nU R                  S5      n [        R                  " U R	                  5       R                  5       5      u  p4/ nU Hi  n[        [        R                  " USU-  -  5      R                  [        R                  " S5      [        R                  S95      nUR                  U5        Mk     [        R                  " U5      n[        U5      U-
  n[        R                  " U5      R!                  U R"                  5      R                  U5      [        R                  " U5      R!                  U R"                  5      R                  U5      4$ )z
Decompose the scaling factor into mantissa and twos exponent.

Args:
    scaling_factor (`torch.Tensor`):
        Target scaling factor to decompose.

Returns:
    ``Tuple(torch.Tensor, torch.Tensor)`: mantisa and exponent
ra   r   1)rounding)sizerf   npfrexpcpunumpyr   decimalDecimalquantizeROUND_HALF_UPappendarrayr   r   
from_numpyr   r   )inputsr   shape_of_inputoutput_moutput_etmp_mmint_m_shifteds           r)   batch_frexprL    s    [[]N [[_F&**,"4"4"67HEOOAG,-66ws7KV]VkVk6l
 	]#	 
 xxHW~(H 	"%%fmm499.I"%%fmm499.I r+   c                   @    \ rS rSrSr\  SS j5       r\S 5       rSrg)re   i  a	  
Function to perform fixed-point arithmetic that can match integer arithmetic on hardware.

Args:
    pre_act (`torch.Tensor`):
        Input tensor.
    pre_act_scaling_factor (`torch.Tensor`):
        Scaling factor of the input tensor *pre_act*.
    bit_num (`int`):
        Quantization bitwidth.
    z_scaling_factor (`torch.Tensor`):
        Scaling factor of the output tensor.
    identity (`torch.Tensor`, *optional*):
        Identity tensor, if exists.
    identity_scaling_factor (`torch.Tensor`, *optional*):
        Scaling factor of the identity tensor *identity*, if exists.

Returns:
    `torch.Tensor`: Output tensor(*pre_act* if *identity* is not given, otherwise the addition of *pre_act* and
    *identity*), whose scale is rescaled to *z_scaling_factor*.
Nc                    [        UR                  5      S:X  a  S nOS nXPl        SUS-
  -  S-
  n[        R                  " 5          U" U5      nUb  U" U5      nX@l        [        R                  " X-  5      n	UR                  [        R                  5      n
UR                  [        R                  5      R                  [        R                  5      nX-  nU" U5      n[        U5      u  pU	R                  [        R                  5      UR                  [        R                  5      -  n[        R                  " USU-  -  5      nUb  [        R                  " XV-  5      nUR                  [        R                  5      n
UR                  [        R                  5      R                  [        R                  5      nX-  nU" U5      n[        U5      u  nnUR                  [        R                  5      UR                  [        R                  5      -  n[        R                  " USU-  -  5      nUU-   n[        R                  " UR                  [        R                  5      U* S-
  U5      sS S S 5        $ ! , (       d  f       g = f)Nr   c                     U $ r   r#  r5   s    r)   <lambda>'FixedPointMul.forward.<locals>.<lambda>  s    r+   c                 (    U R                  SSS5      $ )Nr   ra   )rf   rP  s    r)   rQ  rR    s    q!R 0r+   r   r   r?   )r  r   rh   r   r   z_scaling_factorr   typedoubler   rL  r   )r  pre_actrg   bit_numrT  rh   ri   reshaper   z_int_A_B	new_scalerJ  eoutputwx_intm1e1output1s                       r)   r=   FixedPointMul.forward  s    %++,1!G0G'A+"]]_%,-C%D"#*12I*J'#3 KK @AE',,U\\:B"''4::5<<HBI	*Iy)DAZZ-u||0DDF[[36!23F#X%GH,11%,,?&++EKK8>>u||LG	#I.	$Y/B ++ell3bggell6KK++gb&9: 6);;v{{5;;7!aCC __s   H)I::
Jc                     S nU R                   b  UR                  5       U R                  -  nUR                  5       U R                  -  S S S S US 4$ r   )rh   r  rT  )r  r   identity_grads      r)   r!  FixedPointMul.backward/  sU    <<#'--/#2F2FFM  "S%9%994tTS`bfffr+   r#  rB   r$  r#  r+   r)   re   re     s<    ,   $2D 2Dh g gr+   re   )F)r	   )r>  r=  r:  r   r   torch.autogradr   utilsr   
get_loggerrC   r   Moduler   rL   rr   r   r   r   r	  r  r4   r!   r   r   rL  re   r#  r+   r)   <module>rl     s   $     #  
		H	%PPRYY PPfgMryy gMTM
")) M
`66bii 66rD8 D8Nb!299 b!J!$H 9F@*CX *CZ# ## #DQgH Qgr+   