
    6biK!                         S r SSKJs  Jr  SSKJr  SSKJr  SS jr	S r
 " S S\R                  5      r " S	 S
\5      r " S S\5      r " S S\R                  5      r " S S\R                  5      rg)z6Contains testing utilities related to mixed precision.    N)regularizers)
base_layerc                 L   ^ ^^ [         R                  UU 4S j5       mU4S jnU$ )ad  Returns a function that asserts it's gradient has a certain value.

This serves as a hook to assert intermediate gradients have a certain value.
This returns an identity function. The identity's gradient function is also
the identity function, except it asserts that the gradient equals
`expected_gradient` and has dtype `expected_dtype`.

Args:
  expected_gradient: The gradient function asserts that the gradient is this
    value.
  expected_dtype: The gradient function asserts the gradient has this dtype.

Returns:
  An identity function whose gradient function asserts the gradient has a
  certain value.
c                 J   >^  [         R                  " T 5      m UUU 4S jnT U4$ )z8Function that asserts it's gradient has a certain value.c                   > T(       a'  U R                   T:X  d   ST SU R                    35       e[        R                  " TU R                   SS9n[        R                  " T/5         [        R                  R
                  R                  X5      nSSS5        [        R                  " W/5         [        R                  " U 5      n SSS5        U $ ! , (       d  f       NF= f! , (       d  f       U $ = f)z@Gradient function that asserts the gradient has a certain
value.zdx.dtype should be z	 but is: expected_gradient)dtypenameN)r	   tfconvert_to_tensorcontrol_dependenciescompatv1assert_equalidentity)dxexpected_tensor	assert_opexpected_dtyper   xs      `/home/james-whalen/.local/lib/python3.13/site-packages/tf_keras/src/mixed_precision/test_util.pygradScreate_identity_with_grad_check_fn.<locals>._identity_with_grad_check.<locals>.grad.   s     HH.M((8	"((LM. 22!8KO ((!-IILL55bJ	 .(()5[[_ 6I	 .-55Is   '*C0C"
C"
C1r   r   )r   r   r   r   s   ` r   _identity_with_grad_checkEcreate_identity_with_grad_check_fn.<locals>._identity_with_grad_check)   s"     KKN	& $w    c                    > T" U 5      $ N )r   r   s    r   identity_with_grad_checkDcreate_identity_with_grad_check_fn.<locals>.identity_with_grad_checkE   s    (++r   r   custom_gradient)r   r   r!   r   s   `` @r   "create_identity_with_grad_check_fnr%      s*    $  6, $#r   c                 H   ^ ^ [         R                  U 4S j5       mU4S jnU$ )aO  Returns a function that optionally has NaN gradients.

This serves as a hook to introduce NaN gradients to a model. This returns an
identity function. The identity's gradient function will check if the
boolean tensor `have_nan_gradients` is True. If so, the gradient will be
NaN.  Otherwise, the gradient will also be the identity.

Args:
  have_nan_gradients: A scalar boolean tensor. If True, gradients will be
    NaN. Otherwise, the gradient function is the identity function.

Returns:
  An identity function whose gradient function will return NaNs, if
  `have_nan_gradients` is True.
c                 B   > [         R                  " U 5      n U4S jnX4$ )z@Function whose gradient is NaN iff `have_nan_gradients` is True.c                 F   >^  [         R                  " TU 4S jU 4S j5      $ )Nc                      > T [        S5      -  $ )NNaN)floatr   s   r   <lambda>kcreate_identity_with_nan_gradients_fn.<locals>._identity_with_nan_gradients.<locals>.grad.<locals>.<lambda>c   s    Bu,=r   c                     > T $ r   r    r,   s   r   r-   r.   c   s    rr   )r   cond)r   have_nan_gradientss   `r   r   Ycreate_identity_with_nan_gradients_fn.<locals>._identity_with_nan_gradients.<locals>.grada   s    77"$=z r   r   )r   r   r1   s     r   _identity_with_nan_gradientsKcreate_identity_with_nan_gradients_fn.<locals>._identity_with_nan_gradients\   s      KKN	
 wr   c                    > T" U 5      $ r   r    )r   r3   s    r   identity_with_nan_gradientsJcreate_identity_with_nan_gradients_fn.<locals>.identity_with_nan_gradientsj   s    +A..r   r#   )r1   r6   r3   s   ` @r   %create_identity_with_nan_gradients_fnr8   K   s*    " 	 	/ '&r   c                   6   ^  \ rS rSrSrSU 4S jjrS rSrU =r$ )AssertTypeLayerp   z5A layer which asserts it's inputs are a certain type.c                    > U(       a   [         R                  " U5      R                  OS U l        [        TU ]  " S0 UD6  g )Nr    )r   as_dtyper
   _assert_typesuper__init__)selfassert_typekwargs	__class__s      r   r@   AssertTypeLayer.__init__s   s3    -8BKK$))d 	 	"6"r   c                    U R                   (       az  [        R                  R                  U5      nU HT  nUR                  R
                  U R                   :X  a  M)   SUR                  R                  < SU R                   < 35       e   gg)zEAsserts `inputs` are of the correct type. Should be called in
call().zInput tensor has type z" which does not match assert type N)r>   r   nestflattenr	   
base_dtyper
   )rA   inputsinputs_flattenedinps       r   assert_input_types"AssertTypeLayer.assert_input_typesy   sn     !wwv6'yy++t/@/@@  yy~~t'8'8:@ ( r   )r>   r   )	__name__
__module____qualname____firstlineno____doc__r@   rM   __static_attributes____classcell__rD   s   @r   r:   r:   p   s    ?#
 
r   r:   c                   V   ^  \ rS rSrSr    S	U 4S jjrS rS rS rU 4S jr	Sr
U =r$ )
MultiplyLayer   z8A layer which multiplies its input by a scalar variable.c                 J  > Xl         [        U[        5      (       a"  [        R                  " U[        5       S9U l         X l        [        U[        5      (       a"  [        R                  " U[        5       S9U l        X0l        X@l        [        TU ](  " SSU R                  0UD6  g)a  Initializes the MultiplyLayer.

Args:
  regularizer: The weight regularizer on the scalar variable.
  activity_regularizer: The activity regularizer.
  use_operator: If True, add using the * operator. If False, add using
    tf.multiply.
  var_name: The name of the variable. It can be useful to pass a name
    other than 'v', to test having the attribute name (self.v) being
    different from the variable name.
  **kwargs: Passed to AssertTypeLayer constructor.
)custom_objectsactivity_regularizerNr    )_regularizer
isinstancedictr   deserializeglobals_activity_regularizer_use_operator	_var_namer?   r@   )rA   regularizerr\   use_operatorvar_namerC   rD   s         r   r@   MultiplyLayer.__init__   s    ( (k4(( , 8 8GI!D &:"*D11)5)A)A$WY*D& *! 	
!%!;!;	
?E	
r   c                 h    U R                  U R                  SSU R                  S9U l        SU l        g )Nr    ones)initializerre   T)
add_weightrd   r]   vbuilt)rA   _s     r   buildMultiplyLayer.build   s6    NN))	 ! 
 
r   c                 Z    U R                  U5        U R                  XR                  5      $ r   )rM   	_multiplyrm   rA   rJ   s     r   callMultiplyLayer.call   s#    '~~fff--r   c                 X    U R                   (       a  X-  $ [        R                  " X5      $ r   )rc   r   multiply)rA   r   ys      r   rs   MultiplyLayer._multiply   s!    5L;;q$$r   c                 
  > [         TU ]  5       n[        R                  " U R                  5      US'   [        R                  " U R
                  5      US'   U R                  US'   U R                  US'   U R                  US'   U$ )Nre   r\   rf   rg   rB   )	r?   
get_configr   	serializer]   rb   rc   rd   r>   )rA   configrD   s     r   r|   MultiplyLayer.get_config   s    #% , 6 6t7H7H I})5)?)?&&*
%& "&!3!3~!^^z $ 1 1}r   )rb   r]   rc   rd   rn   rm   )NNFrm   )rO   rP   rQ   rR   rS   r@   rp   ru   rs   r|   rT   rU   rV   s   @r   rX   rX      s3    B !#
J.%	 	r   rX   c                   $    \ rS rSrSrS rS rSrg)MultiplyLayerWithoutAutoCast   z:Same as MultiplyLayer, but does not use AutoCastVariables.c           	          U R                   nUS;   a  SnU R                  SSSUSU R                  S9U l        SU l        g )	N)float16bfloat16float32rm   r    rj   F)rk   r	   experimental_autocastre   T)r	   rl   r]   rm   rn   )rA   ro   r	   s      r   rp   "MultiplyLayerWithoutAutoCast.build   sO    

++E"')) ! 
 
r   c                    U R                  U5        U R                  R                  [        R                  [        R
                  4;   d   eU R                  U[        R                  " U R                  UR                  5      5      $ r   )rM   rm   r	   r   r   float64rs   castrt   s     r   ru   !MultiplyLayerWithoutAutoCast.call   sW    'vv||

BJJ7777~~fbggdfffll&CDDr   )rn   rm   N)rO   rP   rQ   rR   rS   rp   ru   rT   r    r   r   r   r      s    DEr   r   c                        \ rS rSrS rS rSrg)IdentityRegularizer   c                 n    UR                   [        R                  :X  d   e[        R                  " U5      $ r   )r	   r   r   r   rA   r   s     r   __call__IdentityRegularizer.__call__   s&    ww"**$$${{1~r   c                     0 $ r   r    rA   s    r   r|   IdentityRegularizer.get_config       	r   r    NrO   rP   rQ   rR   r   r|   rT   r    r   r   r   r      s    r   r   c                        \ rS rSrS rS rSrg)ReduceSumRegularizer   c                 .    [         R                  " U5      $ r   )r   
reduce_sumr   s     r   r   ReduceSumRegularizer.__call__   s    }}Qr   c                     0 $ r   r    r   s    r   r|   ReduceSumRegularizer.get_config   r   r   r    Nr   r    r   r   r   r      s     r   r   r   )rS   tensorflow.compat.v2r   v2r   tf_keras.srcr   tf_keras.src.enginer   r%   r8   Layerr:   rX   r   Regularizerr   r   r    r   r   <module>r      su    = ! ! % *1$h"'Jj&& ,DO DNE= E.,22 <33 r   