
    ^Mhs9              	          d Z ddlZddlZ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 Zd Zd	 Zd*dZd Zd Z	 	 	 	 	 	 d+dZedk    r ej        d          Ze                    ded           e                    ded
d           e                    dedd           e                    dedd           e                    ded dd!"           e                    d#ed dd$"           e                    d%d&d'(           e                                Zej         Z e ej!                    eej"        ej#        ej$        ej%        ej!        ej&        e)           dS dS ),aJ  This script evaluates scipy's implementation of hyp2f1 against mpmath's.

Author: Albert Steppi

This script is long running and generates a large output file. With default
arguments, the generated file is roughly 700MB in size and it takes around
40 minutes using an Intel(R) Core(TM) i5-8250U CPU with n_jobs set to 8
(full utilization). There are optional arguments which can be used to restrict
(or enlarge) the computations performed. These are described below.
The output of this script can be analyzed to identify suitable test cases and
to find parameter and argument regions where hyp2f1 needs to be improved.

The script has one mandatory positional argument for specifying the path to
the location where the output file is to be placed, and 4 optional arguments
--n_jobs, --grid_size, --regions, and --parameter_groups. --n_jobs specifies
the number of processes to use if running in parallel. The default value is 1.
The other optional arguments are explained below.

Produces a tab separated values file with 11 columns. The first four columns
contain the parameters a, b, c and the argument z. The next two contain |z| and
a region code for which region of the complex plane belongs to. The regions are

    0) z == 1
    1) |z| < 0.9 and real(z) >= 0
    2) |z| <= 1 and real(z) < 0
    3) 0.9 <= |z| <= 1 and |1 - z| < 0.9:
    4) 0.9 <= |z| <= 1 and |1 - z| >= 0.9 and real(z) >= 0:
    5) 1 < |z| < 1.1 and |1 - z| >= 0.9 and real(z) >= 0
    6) |z| > 1 and not in 5)

The --regions optional argument allows the user to specify a list of regions
to which computation will be restricted.

Parameters a, b, c are taken from a 10 * 10 * 10 grid with values at

    -16, -8, -4, -2, -1, 1, 2, 4, 8, 16

with random perturbations applied.

There are 9 parameter groups handling the following cases.

    1) A, B, C, B - A, C - A, C - B, C - A - B all non-integral.
    2) B - A integral
    3) C - A integral
    4) C - B integral
    5) C - A - B integral
    6) A integral
    7) B integral
    8) C integral
    9) Wider range with c - a - b > 0.

The seventh column of the output file is an integer between 1 and 8 specifying
the parameter group as above.

The --parameter_groups optional argument allows the user to specify a list of
parameter groups to which computation will be restricted.

The argument z is taken from a grid in the box
    -box_size <= real(z) <= box_size, -box_size <= imag(z) <= box_size.
with grid size specified using the optional command line argument --grid_size,
and box_size specified with the command line argument --box_size.
The default value of grid_size is 20 and the default value of box_size is 2.0,
yielding a 20 * 20 grid in the box with corners -2-2j, -2+2j, 2-2j, 2+2j.

The final four columns have the expected value of hyp2f1 for the given
parameters and argument as calculated with mpmath, the observed value
calculated with scipy's hyp2f1, the relative error, and the absolute error.

As special cases of hyp2f1 are moved from the original Fortran implementation
into Cython, this script can be used to ensure that no regressions occur and
to point out where improvements are needed.
    N)product)Pool)hyp2f1	mp_hyp2f1c                    | dk    rdS t          |           dk     r| j        dk    rdS t          |           dk    r| j        dk     rdS dt          |           cxk    rdk    rn nt          d| z
            dk     rdS dt          |           cxk    rdk    rn nt          d| z
            dk    rdS dt          |           cxk     rdk     r&n n#t          d| z
            dk    r| j        dk    rd	S d
S )zDAssign numbers for regions where hyp2f1 must be handled differently.      ?        r   g?            g?      )absreal)zs    e/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/scipy/special/_precompute/hyp2f1_data.py
get_regionr   W   s   F{{q	Q#!&A++q	Q1!q	A				!					AE

S 0 0q	A				!					AE

c 1 1q	
SVV				c					c!a%jjC//AFaKKqq    c                    t          | |||          t          | |||          }}t          j        |          rt          j        |          s||k    rd}d}nWt          j        |          rt	          d          }t	          d          }n$t          ||z
            }|t          |          z  }| |||t          |          t          |          |||||fS )6Get results for given parameter and value combination.g        inf)r   r   npisnanfloatr   r   	abcr   groupexpectedobservedrelative_errorabsolute_errors	            r   
get_resultr%   i   s    "1aA..q!Q0B0BhHHX8#%8H#5#58  	(		 8 uuX011'#h--7 	
			A1 r   c                     t          d          t          | |||          }}t          d          t          d          }}| |||t          |          t	          |          |||||fS )r   nan)complexr   r   r   r   r   s	            r   get_result_no_mpr)      sk     1a););hH%*5\\5<<NN				A1 r   r
   Tc                     d t          | |          D             }t          |          5 }|                    |rt          nt          |          }ddd           n# 1 swxY w Y   |S )a  Batch compute results for multiple parameter and argument values.

    Parameters
    ----------
    params : iterable
        iterable of tuples of floats (a, b, c) specifying parameter values
        a, b, c for hyp2f1
    Z : iterable of complex
        Arguments at which to evaluate hyp2f1
    n_jobs : Optional[int]
        Number of jobs for parallel execution.

    Returns
    -------
    list
        List of tuples of results values. See return value in source code
        of `get_result`.
    c              3   4   K   | ]\  \  }}}}}|||||fV  d S N ).0r   r   r   r    r   s         r   	<genexpr>zget_results.<locals>.<genexpr>   sK         3 0Aq%!Aq!U     r   N)r   r   starmapr%   r)   )paramsZn_jobs
compute_mpinput_poolrowss          r   get_resultsr8      s    & 7>vq7I7I  F 
f 
||$:JJ*:
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 

 Ks   %AA"Ac                 P    t          | |||          }d|  d| d| d| d| d| dS )z?Generate string for single test case as used in test_hyp2f1.py.z8    pytest.param(
        Hyp2f1TestCase(
            a=z,
            b=z,
            c=z,
            z=z,
            expected=z,
            rtol=z,
        ),
    ),r   )r   r   r   r   rtolr!   s         r   _make_hyp2f1_test_caser;      s|    Aq!$$H				 		 		 		 			 		
 		 		 !)		 		 !		 		 		r   c                 X    d}|d                     d | D                       z  }|dz  }|S )a1  Generate string for a list of test cases for test_hyp2f1.py.

    Parameters
    ----------
    rows : list
        List of lists of the form [a, b, c, z, rtol] where a, b, c, z are
        parameters and the argument for hyp2f1 and rtol is an expected
        relative error for the associated test case.

    Returns
    -------
    str
        String for a list of test cases. The output string can be printed
        or saved to a file and then copied into an argument for
        `pytest.mark.parameterize` within `scipy.special.tests.test_hyp2f1.py`.
    z[

c              3   H   K   | ]\  }}}}}t          |||||          V  d S r,   )r;   )r.   r   r   r   r   r:   s         r   r/   z)make_hyp2f1_test_cases.<locals>.<genexpr>   sP        Aq!Q 	q!Q400     r   z
])join)r7   results     r   make_hyp2f1_test_casesrA      sO    " F
dii   $     F eOFMr          @   c           
      T
   t           j                            t           j                            |                     } t          j                            d          }t	          j        g d          }d|                    dt          |          f          z  }	g }
||	dd d f         z   }||	dd d f         z   }||	dd d f         z   }|

                    t          d	 t          |||          D             d
                      |dz   }|dz   }||	dd d f         z   }|

                    t          d t          |||          D             d                      |dz   }||	dd d f         z   }|dz   }|

                    t          d t          |||          D             d                      ||	dd d f         z   }|dz   }|dz   }|

                    t          d t          |||          D             d                      |dz   }|dz   }|dz   }|

                    t          d t          |||          D             d                      |}||	dd d f         z   }||	dd d f         z   }|

                    t          d t          |||          D             d                      ||	dd d f         z   }|}||	dd d f         z   }|

                    t          d t          |||          D             d                      ||	dd d f         z   }||	dd d f         z   }|}|

                    t          d t          |||          D             d                      dt	          j        d          z   dz  }|t	          j        d          z  }t	          j        | |g          }t          d t          |||          D             d           }#|

                    |           fd |
D             }
t	          j        t	          j        | ||          t	          j        | ||                    \  }}||d!z  z   }|                                                                }|                    d"           fd#|D             }t+          |
|||$          }t-          | d%d&'          5 }t/          j        |d()          }|                    g d*           |D ]}|                    |           	 d d d            d S # 1 swxY w Y   d S )+Ni  )
iir
   r   r         g?r   )sizer   r
   r   c              3   *   K   | ]\  }}}|||d fV  dS )r
   Nr-   r.   r   r   r   s       r   r/   zmain.<locals>.<genexpr>  0      ::gaAaAq\::::::r   c                 n    t          t          | d                   t          | d                             S Nr   r
   maxr   xs    r   <lambda>zmain.<locals>.<lambda>  $    #c!A$iiQqT33 r   )keyg      ?c              3   *   K   | ]\  }}}|||d fV  dS )r   Nr-   rL   s       r   r/   zmain.<locals>.<genexpr>  rM   r   c                 n    t          t          | d                   t          | d                             S rO   rP   rR   s    r   rT   zmain.<locals>.<lambda>  rU   r   c              3   *   K   | ]\  }}}|||d fV  dS )r   Nr-   rL   s       r   r/   zmain.<locals>.<genexpr>  rM   r   c                 n    t          t          | d                   t          | d                             S rO   rP   rR   s    r   rT   zmain.<locals>.<lambda>   rU   r   c              3   *   K   | ]\  }}}|||d fV  dS )r   Nr-   rL   s       r   r/   zmain.<locals>.<genexpr>,  rM   r   c                 n    t          t          | d                   t          | d                             S rO   rP   rR   s    r   rT   zmain.<locals>.<lambda>-  rU   r   g      ?c              3   *   K   | ]\  }}}|||d fV  dS )r   Nr-   rL   s       r   r/   zmain.<locals>.<genexpr>9  rM   r   c                 n    t          t          | d                   t          | d                             S rO   rP   rR   s    r   rT   zmain.<locals>.<lambda>:  rU   r   c              3   *   K   | ]\  }}}|||d fV  dS )r   Nr-   rL   s       r   r/   zmain.<locals>.<genexpr>F  rM   r   c                 n    t          t          | d                   t          | d                             S rO   rP   rR   s    r   rT   zmain.<locals>.<lambda>G  rU   r   c              3   *   K   | ]\  }}}|||d fV  dS )   Nr-   rL   s       r   r/   zmain.<locals>.<genexpr>S  rM   r   c                 n    t          t          | d                   t          | d                             S rO   rP   rR   s    r   rT   zmain.<locals>.<lambda>T  rU   r   c              3   *   K   | ]\  }}}|||d fV  dS )rH   Nr-   rL   s       r   r/   zmain.<locals>.<genexpr>`  rM   r   c                 n    t          t          | d                   t          | d                             S rO   rP   rR   s    r   rT   zmain.<locals>.<lambda>a  rU   r   r   rI   c              3   B   K   | ]\  }}}||z
  |z
  d k    |||dfV  dS )r   	   Nr-   rL   s       r   r/   zmain.<locals>.<genexpr>l  sE       	
 	
$Q1AEAIMMQ1aLMMMM	
 	
r   c                 n    t          t          | d                   t          | d                             S rO   rP   rR   s    r   rT   zmain.<locals>.<lambda>o  s$    c#ad))S1YY// r   c                 .    g | ]\  }}}}|v ||||fS r-   r-   )r.   r   r   r   r    parameter_groupss        r   
<listcomp>zmain.<locals>.<listcomp>u  s@     
 
 
!/Aq%((( 1e(((r   y              ?r	   c                 6    g | ]}t          |          v |S r-   )r   )r.   r   regionss     r   rk   zmain.<locals>.<listcomp>  s)    6661Z]]g55Q555r   )r3   r4   w )newline	)	delimiter)r   r   r   r   z|z|regionparameter_groupr!   r"   r#   r$   )ospathrealpath
expanduserr   randomRandomStatearrayrandom_samplelenextendsortedr   sqrtarangehstackmeshgridlinspaceflattentolistappendr8   opencsvwriterwriterow)outpathr3   box_size	grid_sizerm   rj   r4   random_stateroot_paramsperturbationsr1   ABCphiPgroup_9_paramsXYr2   r7   fr   rows       ``                  r   mainr      s    grw11'::;;G9((..L(--- K ,44[!!" 5   M F 	mAqqqD))AmAqqqD))AmAqqqD))A
MM::Aq)9)9:::33	
 	
 	
   	cAcAmAqqqD))A
MM::Aq)9)9:::33	
 	
 	
   	cAmAqqqD))AcA
MM::Aq)9)9:::33	
 	
 	
   	mAqqqD))AcAcA
MM::Aq)9)9:::33	
 	
 	
   	dAdAcA
MM::Aq)9)9:::33	
 	
 	
   	AmAqqqD))AmAqqqD))A
MM::Aq)9)9:::33	
 	
 	
   	mAqqqD))AAmAqqqD))A
MM::Aq)9)9:::33	
 	
 	
   	mAqqqD))AmAqqqD))AA
MM::Aq)9)9:::33	
 	
 	
   rwqzz>1
CRYr]]A
	A2q'A	
 	
(/1a(8(8	
 	
 	
 0/	  N #n%%%
 
 
 
39
 
 
 ;
XIx33
XIx33 DAq 	
AF
A			AHHV6666666 vqJGGGD	gsB	'	'	' !1A...  	
 	
 	
  	! 	!COOC    	!#! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !s   ATT!$T!__main__a=  Test scipy's hyp2f1 against mpmath's on a grid in the complex plane over a grid of parameter values. Saves output to file specified in positional argument "outpath". Caution: With default arguments, the generated output file is roughly 700MB in size. Script may take several hours to finish if "--n_jobs" is set to 1.)descriptionr   zPath to output tsv file.)typehelpz--n_jobsz#Number of jobs for multiprocessing.)r   defaultr   z
--box_sizezLhyp2f1 is evaluated in box of side_length 2*box_size centered at the origin.z--grid_sizezjhyp2f1 is evaluated on grid_size * grid_size grid in box of side length 2*box_size centered at the origin.z--parameter_groups+zRestrict to supplied parameter groups. See the Docstring for this module for more info on parameter groups. Calculate for all parameter groups by default.)r   nargsr   r   z	--regionszRestrict to argument z only within the supplied regions. See the Docstring for this module for more info on regions. Calculate for all regions by default.z--no_mp
store_truezIf this flag is set, do not compute results with mpmath. Saves time if results have already been computed elsewhere. Fills in "expected" column with None values.)actionr   )r3   r   r   rj   rm   r4   )r
   T)r
   rB   rC   NNT)'__doc__ru   r   argparsenumpyr   	itertoolsr   multiprocessingr   scipy.specialr   scipy.special.tests.test_hyp2f1r   r   r%   r)   r8   r;   rA   r   __name__ArgumentParserparseradd_argumentstrintr   
parse_argsargsno_mpr4   printrj   r   r3   r   r   rm   r-   r   r   <module>r      s  G GT 
			 



                        !           5 5 5 5 5 5  $  B  &   >  "  8 v! v! v! v!r z$X$%  F "<     2	     	     5	     (     '     1     DZJ	E$
   D{..     y r   