
    2Vhg4                        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m	Z	 d dlm
Z
 d dlmZ d dlmZ d d	lmZ 	  ed
dg       G d d             Z ed      dd ej"                         dfd       Z ed       G d de             Zd Z G d de      Z ed      	 	 	 d!d       Z	  ed      d"d       Z ed      d        Z ed      d         Zy)#    N)backend)ops)keras_export)KerasTensor)any_symbolic_tensors)canonicalize_axis)standardize_axis_for_numpy)	Operationzkeras.Quantizerzkeras.quantizers.Quantizerc                   0    e Zd ZddZd Zed        Zd Zy)	Quantizerc                     || _         y Noutput_dtype)selfr   s     O/home/dcms/DCMS/lib/python3.12/site-packages/keras/src/quantizers/quantizers.py__init__zQuantizer.__init__   s
    (    c                     |S )z0Compute a quantized output from an input tensor. )r   xs     r   __call__zQuantizer.__call__   s    r   c                      | di |S )a  Creates a quantizer from its config.

        This method is the reverse of `get_config`,
        capable of instantiating the same quantizer from the config
        dictionary.

        This method is used by Keras `model_to_estimator`, saving and
        loading models to HDF5 formats, Keras model cloning, some visualization
        utilities, and exporting models to and from JSON.

        Args:
            config: A Python dictionary, typically the output of get_config.

        Returns:
            A quantizer instance.
        r   r   )clsconfigs     r   from_configzQuantizer.from_config   s    $ }V}r   c                     t        |  d      )a  Returns the config of the quantizer.

        A quantizer config is a Python dictionary (serializable)
        containing all configuration parameters of the quantizer.
        The same quantizer can be reinstantiated later
        (without any saved state) from this configuration.

        This method is optional if you are just training and executing models,
        exporting to and from SavedModels, or using weight checkpoints.

        This method is required for Keras `model_to_estimator`, saving and
        loading models to HDF5 formats, Keras model cloning, some visualization
        utilities, and exporting models to and from JSON.

        Returns:
            Python dictionary.
        z  does not implement get_config())NotImplementedErrorr   s    r   
get_configzQuantizer.get_config-   s    $ "TF*J"KLLr   N)int8)__name__
__module____qualname__r   r   classmethodr   r    r   r   r   r   r      s&    )  &Mr   r   z!keras.quantizers.abs_max_quantizei   r!   Fc           
      4   |rt        j                  | j                        }t        j                  |       } t        |      }t        j                  |d   t        j                  t        j                  t        j                  |       |d      |            }t        j                  | |      }t        j                  t        j                  |      |d   |d         }|j                  |      }t        j                  |      t        j                  ||      fS t        j                  |       } t        j                  |d   t        j                  t        j                  t        j                  |       |d      |            }t        j                   |t        j                  | j                              }t        j                  | |      }t        j                  t        j                  |      |d   |d         }t        j                   ||      }||fS )N   T)axiskeepdimsr   dtype)r   standardize_dtyper-   r   convert_to_numpyr	   npdivideaddmaxabsmultiplycliproundastypeconvert_to_tensorcast)	inputsr*   value_ranger-   epsilonto_numpyoriginal_dtypescaleoutputss	            r   abs_max_quantizerB   B   s     226<<@%%f-)$/		NFF266"&&.tdCWM
 ++fe,''"((7+[^[^L..'$$W-s/D/D0
 
 	
 ""6*FJJAdTBGLE HHUG55fllCDEll65)Ghhsyy);q>;q>JGhhw&GE>r   z keras.quantizers.AbsMaxQuantizerc                   D    e Zd Zd ej                         dfdZd Zd Zy)AbsMaxQuantizerr&   r!   c                     t         j                  | |       t        |t              r|f}t	        |      | _        || _        || _        y )Nr   )r   r   
isinstanceinttupler*   r<   r=   )r   r*   r<   r=   r   s        r   r   zAbsMaxQuantizer.__init__i   sB     	4l;dC 7D$K	&r   c                 ~    t        || j                  | j                  | j                  | j                        \  }}||fS r   )rB   r*   r<   r   r=   )r   r   quantized_xr@   s       r   r   zAbsMaxQuantizer.__call__w   s=    -tyy$**D,=,=t||
U E!!r   c                 `    | j                   | j                  | j                  | j                  dS )Nr*   r<   r=   r   rL   r   s    r   r    zAbsMaxQuantizer.get_config}   s,    II++|| --	
 	
r   N)r"   r#   r$   r   r=   r   r   r    r   r   r   rD   rD   g   s%    
  !"
r   rD   c                    t        j                  | j                  d      }t        j                  | |      } t        j                  ||      }d|z  dz
  }|sdnd}t        j
                  ||       }t        j                  |||z
        }t        j                  ||z
  |      }	|t        j                  | |      z
  }
t        j                  |
||      }t        j                  |      }t        j                  t        j
                  ||      |      }t        j                  t        j
                  ||      |      }||||	fS )z>Adjusts and nudges the quantization range for better accuracy.float32r)   r   )
r   result_typer-   r   r:   subtractr1   r6   r7   r5   )	min_range	max_rangenum_bitsnarrow_rangecompute_dtype	quant_max	quant_min
diff_ranger@   	inv_scalezero_point_from_min
zero_pointnudged_zero_point
nudged_min
nudged_maxs                  r   adjust_and_nudger_      s    ''	CMM2IM2Ih!#I%1Ii3J JJz9y#89E 

9y0*=I $cjjE&BB -y)DJ 		*- cll96GH%PJcll96GH%PJz5)33r   c                   ,     e Zd Zd fd	Zd Zd Z xZS )FakeQuantWithMinMaxVarsc                 L    t         |           || _        || _        || _        y r   )superr   rS   rT   r*   )r   rS   rT   r*   	__class__s       r   r   z FakeQuantWithMinMaxVars.__init__   s$     (	r   c                 `    t        |||| j                  | j                  | j                        S )N)rS   rT   r*   )fake_quant_with_min_max_varsrS   rT   r*   r   r;   min_valsmax_valss       r   callzFakeQuantWithMinMaxVars.call   s/    +]]**
 	
r   c                 D    t        |j                  |j                        S )Nr,   )r   shaper-   rg   s       r   compute_output_specz+FakeQuantWithMinMaxVars.compute_output_spec   s    6<<v||<<r      FN)r"   r#   r$   r   rj   rm   __classcell__)rd   s   @r   ra   ra      s    
=r   ra   z-keras.quantizers.fake_quant_with_min_max_varsc           
      r   t        | f      rt               j                  | ||      S t        j                  |       } t        j                  |      }t        j                  |      }t              t        | j                        t        j                         dk(  rpddl	}t        j                  | j                        }|j                  j                  t        j                  | d      t        j                  t        j                  |d      d      t        j                  t        j                  |d      d            }t        j                  ||      S | j                  dz
  }	t        j                   | |	      } |j                  j#                  t        j                  | d      t        j                  |d      t        j                  |d            }t        j                  ||      }t        j                   ||	      S t        j$                  fd	       }
 |
| ||      S )
au  Perform per-tensor or per-channel fake quantization.

    `[min_vals, max_vals]` define the clamping range for the `inputs`.

    The `inputs` are quantized into the quantization range:
    - `[0, 2^num_bits - 1]` when `narrow_range=False`
    - `[1, 2^num_bits - 1]` when `narrow_range=True`

    After quantization, the values are dequantized and output as floats within
    the `[min_vals, max_vals]` interval.

    This operation supports gradient computation, allowing `min_vals` and
    `max_vals` to be trained.

    Args:
        inputs: Input Keras tensor of float dtype.
        min_vals: A global minimum scalar or a per-channel minimum tensor.
        max_vals: A global maximum scalar or a per-channel maximum tensor.
        num_bits: Quantization bit width (e.g., `8` for int8). Defaults to `8`.
        narrow_range: Whether to use narrow quantization range. Defaults to
            `False`.
        axis: Axis along which to perform per-channel quantization. If `None`,
              per-tensor quantization is performed. Defaults to `None`.


    Returns:
        Tensor: A Keras tensor with fake quantization applied.
    N
tensorflowr   rN   r   )rS   rT   r,   r)   c                 R    t        j                   j                        }t        ||      \  }}t	        j
                  t	        j                  t	        j                   |      d            }t	        j                   t	        j                   j                        t	        j                   j                              }t	        j                  |      }t	        j                  t	        j
                  t	        j                  t	        j                  t	        j                  ||      |      d            |      }	t	        j                  |	|      }	t	        j                  t	        j                         t	        j                               d d fd
}
|	|
fS )Ng      ?r,   )upstreamc                 $   | |\  } t        j                  
| d      }t        t        |j                              D cg c]
  }|	k7  s	| }}t        j
                        }t        j                  || d      }	t        j                  ||      }nt        j                  |      }t        j                        }t        j                  || d      }	t        j                  ||      }nt        j                  |      }|||fS c c}w )N        )r*   )r   whererangelenrl   
less_equalsumgreater_equal)rt   argsdxiaxesmin_maskgrad_minmax_maskgrad_maxr*   masksr^   r]   r   s            r   gradz]fake_quant_with_min_max_vars.<locals>._fake_quant_with_min_max_vars_per_channel.<locals>.grad0  s    " 5(C0B$S]3A!qDyAADA ~~a4Hyy8S9H778$7778, ((J7Hyy8S9H778$7778,x))) Bs   
D
D)r   r.   r-   r_   r   floorr2   r5   r6   r:   rP   logical_andr|   rz   )r   min_valmax_valr-   r@   rY   
quant_zero	x_clampedx_clamped_shiftedresultr   r   r^   r]   r*   rT   rS   s   `          @@@r   )_fake_quant_with_min_max_vars_per_channelzOfake_quant_with_min_max_vars.<locals>._fake_quant_with_min_max_vars_per_channel  sP   ))!''2 4DWh4
0
Jy YYGGCLL*i8#>

 HHsxx
AGG,chhz177.K
	  LLJ?IILL%6	BJ 	 

 &. a,cnnQ
.K
 "& 	* 	*8 t|r   )r   ra   symbolic_callr   r9   rG   r   ndimr   rr   r.   r-   quantizationrf   r:   reshapeswapaxes(fake_quant_with_min_max_vars_per_channelcustom_gradient)r;   rh   ri   rS   rT   r*   tfr-   rA   	last_axisr   s      ```     r   rf   rf      s   J VI&&(66Hh
 	
 ""6*F$$X.H$$X.H8}H v{{3 L( ))&,,7<ooBB+Xr2I>Xr2I>!) C G 88G511
 aI\\&$	:FooNN+9-9-!) O G hhwe4G<<D99= =~ 5VXxPPr   z%keras.quantizers.compute_float8_scalec                 8   t        j                  |      }t        j                  t        j                  ||       d|z        }t        j                  | dkD  ||      }t        j                  t        j                  |       ||      }t        j                  |      S )N   rv   )r   
reciprocalr1   rw   isfinite)amaxr@   	dtype_maxmarginsfs        r   compute_float8_scaler   T  sq     NN5!E	CJJy$/F	;B	4#:r5	)B	3<<%r5	1B>>"r   z,keras.quantizers.compute_float8_amax_historyc                    t        j                  t        j                  t        j                  |             |j                        }t        j
                  t        j                  |d      dggt        j                  |dg            }|S )N)shiftr   r)   )r   r:   r3   r4   r-   scatter_updaterollr   )r   amax_historyamax_updatenew_amax_historys       r   compute_float8_amax_historyr   a  sg    ((3773771:.0B0BCK))R(
K!%
 r   z(keras.quantizers.quantize_and_dequantizec                    t        j                  t        t        j                  |      j
                        |      }t        j                  | t        j                  ||            }t        j                  || |      }t        j                  ||      }t        j                  t        j                  ||      t        j                  ||            }|S r   )	r   r:   float	ml_dtypesfinfor3   r1   r6   r5   )r;   r@   quantized_dtyperU   quantized_dtype_maxr   s         r   quantize_and_dequantizer   l  s     ((iooo.223] 	

6388E=9:A((*=>AO$A 	SXXa/%1OPAHr   rn   )r   )r   numpyr0   	keras.srcr   r   keras.src.api_exportr   keras.src.backendr   r   &keras.src.backend.common.backend_utilsr   r	   keras.src.ops.operationr
   r   r=   rB   rD   r_   ra   rf   r   r   r   r   r   r   <module>r      s2       - ) 2 D M - &  ">?@.M .M A.Mb 12 
GOO! 3!H 01
i 
 2
<4B=i =* =>
 	QQ ?QQh  56	 7	 <= > 89 :r   