o
    ?Hhg~                     @   s   d dl Z d dlmZ d dlZd dlmZmZmZ d dl	m
Z d dlmZmZmZ d dlmZmZmZmZmZmZ dd Zd	d
 ZG dd dZG dd dZG dd dZG dd dZdd Zdd ZdS )    N)product)assert_allcloseassert_equalassert_)raises)
csr_matrix
csc_matrix
lil_matrix)_adjust_scheme_to_boundsapprox_derivativecheck_derivativegroup_columns_eps_for_method_compute_absolute_stepc                  C   s   g dg dg dg dg dg dg dg} t jtttfD ]1}|| }t d}t g d	}t||}t|| g d
}t g d}t||}t|| qt|}t|}t|| d S )N)   r   r   r   r   r   )r   r   r   r   r   r   )r   r   r   r   r   r   )r   r   r   r   r   r   )r   r   r   r   r   r   )r   r   r   r   r   r   )r   r   r   r   r   r      )r   r      r   r   r   )r   r            r   )r   r   r   r   r   r   )	npasarrayr   r   r	   arangearrayr   r   )	structure	transformAordergroups_truegroupsgroups_1groups_2 r"   b/home/air/sanwanet/gpt-api/venv/lib/python3.10/site-packages/scipy/optimize/tests/test__numdiff.pytest_group_columns   s*   	



r$   c                  C   s   t t jj} | d | d | d d}dD ]}ttt jt j|||  ttt jt j|||  qt t jj} | d | d | d d}dD ])}ttt jt j|||  ttt jt j|||  ttt jt j|||  qGd S )N      ?UUUUUU?2-pointz3-pointcs)r   finfofloat64epsr   r   
complex128float32)EPSrelative_stepmethodr"   r"   r#   test_correct_fp_eps+   sB   r2   c                   @   s$   e Zd Zdd Zdd Zdd ZdS )TestAdjustSchemeToBoundsc                 C   s  t d}t dd}t |}t |}|t j  |t j t||dd||\}}t|| tt 	| t||dd||\}}t|| tt 	| t||dd||\}}t|| tt 	|  t||dd||\}}t|| tt 	|  d S )Nr   {Gz?r   1-sidedr   2-sided)
r   zerosfull
empty_likefillinfr
   r   r   all)selfx0h	inf_lower	inf_upper
h_adjusted	one_sidedr"   r"   r#   test_no_boundsP   s4   






z'TestAdjustSchemeToBounds.test_no_boundsc                 C   s   t g d}t d }t d}t g dd }t||dd||\}}t|| t||dd||\}}t|t g dd  t||dd	||\}}t|t | tt |  t||dd	||\}}t|t g dd  t|t g d
 d S )N)        g333333?g333333r   )r   r   皙?r   r5   r   )r   rF   r   r6   )FTT)	r   r   onesr
   r   absr   r<   r   )r=   r>   lbubr?   rB   _rC   r"   r"   r#   test_with_boundl   s$   

z(TestAdjustSchemeToBounds.test_with_boundc                 C   s  t ddg}t ddg}t ddg}t ddg}t||dd||\}}t|t ddg t||d	d||\}}t|t d
dg t||dd||\}}t|t ddg t|t ddg t||d	d||\}}t|t ddg t|t ddg d S )NgQg?rE   gQ?皙r   r5   gQr   g?r6   FTgQ?gQ)r   r   r
   r   r   )r=   rJ   rK   r>   r?   rB   rL   rC   r"   r"   r#   test_tight_bounds   s$   z*TestAdjustSchemeToBounds.test_tight_boundsN)__name__
__module____qualname__rD   rM   rO   r"   r"   r"   r#   r3   O   s    r3   c                   @   s(  e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd ZdJddZdKddZdd Zdd  Zd!d" Zd#d$ Zd%d& Zd'd( Zd)d* Zd+d, Zd-d. Zd/d0 Zd1d2 Zd3d4 Zd5d6 Zd7d8 Zd9d: Zd;d< Zd=d> Z d?d@ Z!dAdB Z"dCdD Z#dEdF Z$dGdH Z%dIS )LTestApproxDerivativesDensec                 C   
   t |S Nr   sinhr=   xr"   r"   r#   fun_scalar_scalar      
z,TestApproxDerivativesDense.fun_scalar_scalarc                 C   rT   rU   r   coshrX   r"   r"   r#   jac_scalar_scalar   r[   z,TestApproxDerivativesDense.jac_scalar_scalarc                 C   ,   t |d d t |d t |d gS Nr   r   r   r   tanexprX   r"   r"   r#   fun_scalar_vector      ,z,TestApproxDerivativesDense.fun_scalar_vectorc                 C   8   t d|d  t |d d t |d gddS Nr   r   rF   r   r   r   cosrc   reshaperX   r"   r"   r#   jac_scalar_vector   
   (z,TestApproxDerivativesDense.jac_scalar_vectorc                 C   $   t |d |d  t |d  S Nr   r   r   sinlogrX   r"   r"   r#   fun_vector_scalar      $z,TestApproxDerivativesDense.fun_vector_scalarc                 C   s    t |d t |t |gS Nr   ra   rX   r"   r"   r#   wrong_dimensions_fun   s    z/TestApproxDerivativesDense.wrong_dimensions_func              	   C   |   t |d t |d |d   t |d  t |d |d  |d   |d t |d |d   t |d  gS Nr   r   r   r   rj   rr   rq   rX   r"   r"   r#   jac_vector_scalar      **z,TestApproxDerivativesDense.jac_vector_scalarc                 C   H   t |d t |d  |d t |d  |d d |d d  gS Nr   r   r         ࿩r   r   rq   rj   rX   r"   r"   r#   fun_vector_vector   
   z,TestApproxDerivativesDense.fun_vector_vectorc                 C   sT   |dksJ t |d t |d  |d t |d  |d d |d d  gS )=Used to test passing custom arguments with check_derivative()*   r   r   r   r~   r   r=   rY   argr"   r"   r#   fun_vector_vector_with_arg   s   z5TestApproxDerivativesDense.fun_vector_vector_with_argc                 C      t t |d |d t |d  g|d  t |d  t |d gd|d d  |d d  d|d d  |d d  ggS Nr   r   r   r   r~         r   rX   r"   r"   r#   jac_vector_vector   
   "$6z,TestApproxDerivativesDense.jac_vector_vectorc                 C   s   |dksJ t t |d |d t |d  g|d  t |d  t |d gd|d d  |d d  d|d d  |d d  ggS )r   r   r   r   r   r   r~   r   r   r   r"   r"   r#   jac_vector_vector_with_arg   s   "$6z5TestApproxDerivativesDense.jac_vector_vector_with_arg      ?c                 C   s*   t t ||d  t ||d  gS ro   r   r   rc   r=   rY   c0c1r"   r"   r#   fun_parametrized   s   *z+TestApproxDerivativesDense.fun_parametrizedrG   c              
   C   s:   t |t ||d   dgd|t ||d   ggS ro   r   r   r"   r"   r#   jac_parametrized   s   z+TestApproxDerivativesDense.jac_parametrizedc                 C   s   t |dkr	|S t jS )N:0yE>r   rI   nanrX   r"   r"   r#   fun_with_nan      z'TestApproxDerivativesDense.fun_with_nanc                 C   s   t |dkr	dS t jS )Nr   r   r   rX   r"   r"   r#   jac_with_nan   r   z'TestApproxDerivativesDense.jac_with_nanc                 C   s,   t |d |d  t |d |d  gS ro   )r   r   rj   rX   r"   r"   r#   fun_zero_jacobian   re   z,TestApproxDerivativesDense.fun_zero_jacobianc              
   C   sV   t |d |d g|d  t |d |d   |d  t |d |d   ggS rx   )r   r   rq   rX   r"   r"   r#   jac_zero_jacobian   s   >z,TestApproxDerivativesDense.jac_zero_jacobianc                 C   s   t | }t|S rU   )r   r   itemmathrc   )r=   rY   xpr"   r"   r#   jac_non_numpy   s   
z(TestApproxDerivativesDense.jac_non_numpyc                 C   sh   d}t | j|dd}t | j|}t | j|dd}| |}t||dd t||dd t||dd d S )	Nr   r(   r1   r)   ư>rtol&.>-q=r   rZ   r^   r   r=   r>   
jac_diff_2
jac_diff_3
jac_diff_4jac_truer"   r"   r#   test_scalar_scalar   s   
z-TestApproxDerivativesDense.test_scalar_scalarc                 C   sp   d}t | j|ddd}t | j|dd}t | j|ddd}| |}t||dd t||d	d t||d
d d S )Nr   r(   "\O>r1   abs_step)r   r)   r   r   r   r   r   r   r"   r"   r#   test_scalar_scalar_abs_step   s   
z6TestApproxDerivativesDense.test_scalar_scalar_abs_stepc                 C   sn   d}t | j|dd}t | j|}t | j|dd}| t|}t||dd t||dd t||dd d S )	Nr%   r(   r   r)   r   r   r   r   )r   rd   rl   r   
atleast_1dr   r   r"   r"   r#   test_scalar_vector  s   z-TestApproxDerivativesDense.test_scalar_vectorc                 C   r   t ddg}t| j|dd}t| j|}t| j|dd}| |}t||dd t||dd t||d	d d S )
N      Y@r~   r(   r   r)   r   r   Hz>r   )r   r   r   rs   rz   r   r   r"   r"   r#   test_vector_scalar     
z-TestApproxDerivativesDense.test_vector_scalarc                 C   s~   t ddg}t| j|ddd}t| j|dt jd}t| j|ddd}| |}t||dd	 t||d
d	 t||dd	 d S )Nr   r~   r(   r   r   )r   rel_stepr)   r   r   A:)>r   )r   r   r   rs   r;   rz   r   r   r"   r"   r#   test_vector_scalar_abs_step$  s   
z6TestApproxDerivativesDense.test_vector_scalar_abs_stepc                 C   r   )
N      Y皙?r(   r   r)   h㈵>r   r   r   r   r   r   r   r   r   r   r"   r"   r#   test_vector_vector2  r   z-TestApproxDerivativesDense.test_vector_vectorc                 C   s<   d}t tt| j| | t|}t tt| j||d d S )Nr   )f0)assert_raisesRuntimeErrorr   rv   r   r   
ValueError)r=   r>   r   r"   r"   r#   test_wrong_dimensions>  s   
z0TestApproxDerivativesDense.test_wrong_dimensionsc                 C   sZ   t ddg}t| j|ddd}t| j|dd}| |}t||dd t||dd d S )	NrN   rG   r(   g-C6?)r1   r   )r   r4   r   r   )r=   r>   r   r   r   r"   r"   r#   test_custom_rel_stepF  s   
z/TestApproxDerivativesDense.test_custom_rel_stepc              
   C   s   t ddg}d}d}d}d}| j|||d}t ddg}| |||}t| j|d|||ft|d||fd	}	t| j||||ft|d||fd
}
t|	|dd t|
|dd d S )Nr         rE          @)r   gưr   r(   )r1   r   r   argskwargsbounds)r   r   r   r   r   r   r   r   )r   r   r   r   r   dictr   )r=   r>   r   r   rJ   rK   r   r   r   r   r   r"   r"   r#   test_optionsP  s$   
z'TestApproxDerivativesDense.test_optionsc                 C   s|   t d }t d}t ddg}ttt| j|||fd t ddg}t| j|d||fd}| |}t||d	d
 d S )Nr   g       r   r   r   r   r(   r1   r   r   r   )	r   rH   r   r   r   r   r   r   r   )r=   rJ   rK   r>   jac_diffr   r"   r"   r#   test_with_bounds_2_pointb  s   

z3TestApproxDerivativesDense.test_with_bounds_2_pointc                 C   s   t ddg}t ddg}t ddg}| |}t| j|}t||dd t| j||t jfd}t||dd t| j|t j |fd}t||dd t| j|||fd}t||dd d S )Nr   r   r   r   r   )r   r   r   r   r   r   r;   )r=   rJ   rK   r>   r   r   r"   r"   r#   test_with_bounds_3_pointp  s$   

z3TestApproxDerivativesDense.test_with_bounds_3_pointc                 C   s   t ddg}|d }|d }| |}t| j|d||fd}t||dd t| j|dd||fd}t||dd t| j|||fd	}t||dd t| j|d||fd
}t||dd d S )Ng      $@r   g&.!>r(   r   r   r   r1   r   r   r   r   r   )r   r   r   r   r   r   )r=   r>   rJ   rK   r   r   r"   r"   r#   rO     s*   
z,TestApproxDerivativesDense.test_tight_boundsc                 C   s   d}d}d}|  |}t| j|dd||fd}t| j|d||fd}t||dd t||d	d d}|  |}t| j|dd||fd}t| j|d||fd}t||dd t||d	d d S )
N:0yEr   rE   r(   r   r   r   r   r   )r   r   r   r   )r=   rJ   rK   r>   r   r   r   r"   r"   r#   test_bound_switches  s0   



z.TestApproxDerivativesDense.test_bound_switchesc                 C   sh   d}|  |}t| j |dd}t| j |}t||dd t||dd ttt| j |fi tdd d S )Nr   r(   r   r   r   r   r)   )r   r   r   r   	TypeErrorr   )r=   r>   r   r   r   r"   r"   r#   test_non_numpy  s   

z)TestApproxDerivativesDense.test_non_numpyc                    s  t jd dd fdd t jdddt jdt jdt jt d	d	g}t |d
fd}t |t jd
fd} |j	t jksOJ t
||dd  fdd}t||t jd
d}t
||dd dd }dd }dd }dd }t jt jt jfD ]5}	t |	j}
t d|	}td |||d
}||||||
}t||d
|d||  t |k sJ qd S )Nr   c                 S   s   | d | d |  S ro   r"   )prY   r"   r"   r#   func  s   z0TestApproxDerivativesDense.test_fp.<locals>.funcc                    s    | || S rU   r"   )r   rY   y)r   r"   r#   err     z/TestApproxDerivativesDense.test_fp.<locals>.errr   d   dtyper   r(   )r1   r   gMbP?)atolc                    s$   | j tjksJ  | tjS rU   )r   r   r.   astype)r   )r   rY   r   r"   r#   err_fp32  s   z4TestApproxDerivativesDense.test_fp.<locals>.err_fp32r   c                 S   
   t | S rU   r   rq   rY   r"   r"   r#   f  r[   z-TestApproxDerivativesDense.test_fp.<locals>.fc                 S   r   rU   )r   rj   r   r"   r"   r#   g  r[   z-TestApproxDerivativesDense.test_fp.<locals>.gc                 S   s   t |  S rU   r   r   r"   r"   r#   hess  s   z0TestApproxDerivativesDense.test_fp.<locals>.hessc                 S   s\   | d t t||t|||   }||  t t||t|||   }|| S ru   )maxr   rI   )r?   r>   r   r   r/   t0t1r"   r"   r#   	calc_atol  s   **z5TestApproxDerivativesDense.test_fp.<locals>.calc_atolr   r   )r   randomseedlinspacer+   r   r   r   r.   r   r   float16r*   r,   r   rI   )r=   p0jac_fp64jac_fpr   r   r   r   r   r   r/   r>   r?   r   r"   )r   r   rY   r   r#   test_fp  sB   	z"TestApproxDerivativesDense.test_fpc                 C   s   t ddg}t| j| j|}t|dk  t| j| j|}t|dk  t ddg}t| j| j|}t|dk t| j| j|}t|dk d S )N      $
   r   r   rE   r   )r   r   r   r   r   r   r   r   r=   r>   accuracyr"   r"   r#   test_check_derivative  s$   z0TestApproxDerivativesDense.test_check_derivativec                 C   s6   t ddg}t| j| j|ddid}t|dk  d S )Nr   r   r   r   )r   r   )r   r   r   r   r   r   r   r"   r"   r#   !test_check_derivative_with_kwargs	  s   z<TestApproxDerivativesDense.test_check_derivative_with_kwargsN)r   )rG   )&rP   rQ   rR   rZ   r^   rd   rl   rs   rv   rz   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rO   r   r   r   r   r   r"   r"   r"   r#   rS      sH    	
	

:rS   c                   @   sL   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dS )TestApproxDerivativeSparsec                 C   s   t jd d| _ddt | j  | _ddt | j  | _t | j| _d| jd d d  | jd d d< d| jdd d  | jdd d< | 	| j| _
d S )Nr   2   rN   r   rG   gP?r   )r   r   r   nr   rJ   rK   emptyr>   jacJ_truer=   r"   r"   r#   setup_method  s     z'TestApproxDerivativeSparse.setup_methodc                 C   sD   |dd  d |d d d  }t dd| ft d| df S )Nr   r   rF   r   r   )r   hstack)r=   rY   er"   r"   r#   fun  s    $zTestApproxDerivativeSparse.func                 C   s   |j }t||f}d|d  |d< d|d d  |d< td|d D ]2}d||d   |||d f< d	|| d  d
||   |||f< d||d  d  |||d f< q#d	|d d  |d< d|d  |d< |S )Nr   r   r   r   r   r   r   r   i	   r   rF   rF   rF   rh   rF   rh   )sizer   r7   range)r=   rY   r   Jir"   r"   r#   r   #  s   $"zTestApproxDerivativeSparse.jacc                 C   sb   t j||ftd}d|d< d|d< td|d D ]}d|||d |d f< qd|d< d|d< |S )Nr   r   r  r  r   r
  r  )r   r7   intr  )r=   r   r   r  r"   r"   r#   r   1  s   z$TestApproxDerivativeSparse.structurec                 C   s  |  | j}t| j}t||}tj| t||}tg d||gtj | j	gtj| j
gD ]O\}}}}t| j| j|||f||fd}	tt|	t t|	 | jdd t| jd}
|
d d d  d9  < t| j| j||
||fd}	t|	 | jd	d q0d S )
Nr'   )r1   r   sparsityr   r   r   r   rF   )r1   r   r  r   )r   r   r   r   r   r   shuffler   r;   rJ   rK   r   r  r>   r   
isinstancer   r   toarrayr   	full_like)r=   r   r   r    r!   r1   r   lur  r   r"   r"   r#   test_all<  s*   

z#TestApproxDerivativeSparse.test_allc                 C   s6   |  | j}t| j| j|d}t| | jdd d S )N)r  r   r   )r   r   r   r  r>   r   r  r   )r=   r   r  r"   r"   r#   test_no_precomputed_groupsQ  s   z5TestApproxDerivativeSparse.test_no_precomputed_groupsc                 C   sn   t j| j| jftd}t | j}dD ]!}t| j| j|d}t| j| j||f|d}t||	 ddd qd S )Nr   r'   r   )r  r1   gV瞯<gVs<)r   r   )
r   rH   r   r  r   r   r  r>   r   r  )r=   r   r   r1   J_denseJ_sparser"   r"   r#   test_equivalenceV  s   
z+TestApproxDerivativeSparse.test_equivalencec                    s`    fdd}t  j| j j jfd}t|dk  t  j| j j jfd}t|dk  d S )Nc                    s   t  | S rU   )r   r   r   r  r"   r#   r   a  r   z=TestApproxDerivativeSparse.test_check_derivative.<locals>.jacr   r   )r   r  r>   rJ   rK   r   )r=   r   r   r"   r  r#   r   `  s   

z0TestApproxDerivativeSparse.test_check_derivativeN)rP   rQ   rR   r  r  r   r   r  r  r  r   r"   r"   r"   r#   r     s    
r   c                   @   st   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd ZdS )"TestApproxDerivativeLinearOperatorc                 C   rT   rU   rV   rX   r"   r"   r#   rZ   o  r[   z4TestApproxDerivativeLinearOperator.fun_scalar_scalarc                 C   rT   rU   r\   rX   r"   r"   r#   r^   r  r[   z4TestApproxDerivativeLinearOperator.jac_scalar_scalarc                 C   r_   r`   ra   rX   r"   r"   r#   rd   u  re   z4TestApproxDerivativeLinearOperator.fun_scalar_vectorc                 C   rf   rg   ri   rX   r"   r"   r#   rl   x  rm   z4TestApproxDerivativeLinearOperator.jac_scalar_vectorc                 C   rn   ro   rp   rX   r"   r"   r#   rs   |  rt   z4TestApproxDerivativeLinearOperator.fun_vector_scalarc              	   C   rw   rx   ry   rX   r"   r"   r#   rz     r{   z4TestApproxDerivativeLinearOperator.jac_vector_scalarc                 C   r|   r}   r   rX   r"   r"   r#   r     r   z4TestApproxDerivativeLinearOperator.fun_vector_vectorc                 C   r   r   r   rX   r"   r"   r#   r     r   z4TestApproxDerivativeLinearOperator.jac_vector_vectorc                 C   s   d}t | j|ddd}t | j|dd}t | j|ddd}| |}tjd tdD ]/}tjjd	dd
d}t|	||| dd t|	||| dd t|	||| dd q+d S )Nr   r(   Tr1   as_linear_operatorr  r)   r   r   r   r  r   r   h㈵>)
r   rZ   r^   r   r   r   r  uniformr   dotr=   r>   r   r   r   r   r  r   r"   r"   r#   r     s4   
z5TestApproxDerivativeLinearOperator.test_scalar_scalarc                 C   s   d}t | j|ddd}t | j|dd}t | j|ddd}| t|}tjd tdD ]2}tjjd	dd
d}t	|
||
|dd t	|
||
|dd t	|
||
|dd q.d S )Nr%   r(   Tr  r   r)   r   r   r!  r"  r#  r   r   r$  )r   rd   rl   r   r   r   r   r  r%  r   r&  r'  r"   r"   r#   r     s4   z5TestApproxDerivativeLinearOperator.test_scalar_vectorc                 C   s   t ddg}t| j|ddd}t| j|dd}t| j|ddd}| |}t jd td	D ]<}t jjd
d	|j	d}t
||t ||dd t
||t ||dd t
||t ||dd q0d S )Nr   r~   r(   Tr  r   r)   r   r   r!  r#  r   r   r$  r   )r   r   r   rs   rz   r   r   r  r%  shaper   r&  r   r'  r"   r"   r#   r     s4   
z5TestApproxDerivativeLinearOperator.test_vector_scalarc                 C   s   t ddg}t| j|ddd}t| j|dd}t| j|ddd}| |}t jd td	D ]3}t jjd
d	|j	d}t
||||dd t
||||dd t
||||dd q0d S )Nr   r   r(   Tr  r   r)   r   r   r!  r#  r   r   r   r   )r   r   r   r   r   r   r   r  r%  r(  r   r&  r'  r"   r"   r#   r     s(   
z5TestApproxDerivativeLinearOperator.test_vector_vectorc                 C   s.   t ddg}ttt| j|ddt jfd d S )Nr   r   r(   r   r   )r   r   r   r   r   r   r;   )r=   r>   r"   r"   r#   test_exception  s
   

z1TestApproxDerivativeLinearOperator.test_exceptionN)rP   rQ   rR   rZ   r^   rd   rl   rs   rz   r   r   r   r   r   r   r)  r"   r"   r"   r#   r  m  s    r  c                  C   s  dd } t | ddgddd}t|ddg t | ddgdd	d}t|ddg t | ddgdddgd}t|ddg t | ddgddd	gd}t|ddg t | ddgdd	dgd}t|ddg t | ddgddtj dfd
}t|ddg t | ddgdd	dtjfd
}t|ddg d S )Nc                 S   s&   t | d d  t | d d  S ro   )r   rI   r   r"   r"   r#   r     s   &z"test_absolute_step_sign.<locals>.frF   r(   r   r   r   r   r   )r1   r   r   )r   r   r   r;   )r   gradr"   r"   r#   test_absolute_step_sign  s4   	
r+  c            
      C   sj  g d} t g d}t t jj}|d |d |d d}t d}| D ]A}|| }t ||d |d |t |d  g}td |||}t|| | dkt	d d	 }	td | ||}t||	|  q%t g d
}t |d |d  |d |d d |d t |d  g}t|||d}t|| | dkt	d d	 }	t|| |d}t||	|  d S )Nr'   )r   r   r   g     j@r%   r&   r   r   r   r   r   )rG   r   r   r   r(   )
r   r   r*   r+   r,   rI   r   r   r   float)
methodsr>   r/   r0   r   r1   r   correct_stepr   sign_x0r"   r"   r#   test__compute_absolute_step!  s>   



r0  )r   	itertoolsr   numpyr   numpy.testingr   r   r   pytestr   r   scipy.sparser   r   r	   scipy.optimize._numdiffr
   r   r   r   r   r   r$   r2   r3   rS   r   r  r+  r0  r"   r"   r"   r#   <module>   s"     $J  {[5