o
    EbA1                     @   s   d Z ddlZddlZddlmZ dZdZdZdZdefd	efd
efdefgZ	ddgZ
g dZdZdZdZdd Zdd Zdd Zdd ZedkrMe  dS dS )a  
python generate_sparsetools.py

Generate manual wrappers for C++ sparsetools code.

Type codes used:

    'i':  integer scalar
    'I':  integer array
    'T':  data array
    'B':  boolean array
    'V':  std::vector<integer>*
    'W':  std::vector<data>*
    '*':  indicates that the next argument is an output argument
    'v':  void
    'l':  64-bit integer scalar

See sparsetools.cxx for more details.

    N)newera  
bsr_diagonal        v iiiiiIIT*T
bsr_tocsr           v iiiiIIT*I*I*T
bsr_scale_rows      v iiiiII*TT
bsr_scale_columns   v iiiiII*TT
bsr_sort_indices    v iiii*I*I*T
bsr_transpose       v iiiiIIT*I*I*T
bsr_matmat          v iiiiiiIITIIT*I*I*T
bsr_matvec          v iiiiIITT*T
bsr_matvecs         v iiiiiIITT*T
bsr_elmul_bsr       v iiiiIITIIT*I*I*T
bsr_eldiv_bsr       v iiiiIITIIT*I*I*T
bsr_plus_bsr        v iiiiIITIIT*I*I*T
bsr_minus_bsr       v iiiiIITIIT*I*I*T
bsr_maximum_bsr     v iiiiIITIIT*I*I*T
bsr_minimum_bsr     v iiiiIITIIT*I*I*T
bsr_ne_bsr          v iiiiIITIIT*I*I*B
bsr_lt_bsr          v iiiiIITIIT*I*I*B
bsr_gt_bsr          v iiiiIITIIT*I*I*B
bsr_le_bsr          v iiiiIITIIT*I*I*B
bsr_ge_bsr          v iiiiIITIIT*I*I*B
aZ  
csc_diagonal        v iiiIIT*T
csc_tocsr           v iiIIT*I*I*T
csc_matmat_maxnnz   l iiIIII
csc_matmat          v iiIITIIT*I*I*T
csc_matvec          v iiIITT*T
csc_matvecs         v iiiIITT*T
csc_elmul_csc       v iiIITIIT*I*I*T
csc_eldiv_csc       v iiIITIIT*I*I*T
csc_plus_csc        v iiIITIIT*I*I*T
csc_minus_csc       v iiIITIIT*I*I*T
csc_maximum_csc     v iiIITIIT*I*I*T
csc_minimum_csc     v iiIITIIT*I*I*T
csc_ne_csc          v iiIITIIT*I*I*B
csc_lt_csc          v iiIITIIT*I*I*B
csc_gt_csc          v iiIITIIT*I*I*B
csc_le_csc          v iiIITIIT*I*I*B
csc_ge_csc          v iiIITIIT*I*I*B
a  
csr_matmat_maxnnz   l iiIIII
csr_matmat          v iiIITIIT*I*I*T
csr_diagonal        v iiiIIT*T
csr_tocsc           v iiIIT*I*I*T
csr_tobsr           v iiiiIIT*I*I*T
csr_todense         v iiIIT*T
csr_matvec          v iiIITT*T
csr_matvecs         v iiiIITT*T
csr_elmul_csr       v iiIITIIT*I*I*T
csr_eldiv_csr       v iiIITIIT*I*I*T
csr_plus_csr        v iiIITIIT*I*I*T
csr_minus_csr       v iiIITIIT*I*I*T
csr_maximum_csr     v iiIITIIT*I*I*T
csr_minimum_csr     v iiIITIIT*I*I*T
csr_ne_csr          v iiIITIIT*I*I*B
csr_lt_csr          v iiIITIIT*I*I*B
csr_gt_csr          v iiIITIIT*I*I*B
csr_le_csr          v iiIITIIT*I*I*B
csr_ge_csr          v iiIITIIT*I*I*B
csr_scale_rows      v iiII*TT
csr_scale_columns   v iiII*TT
csr_sort_indices    v iI*I*T
csr_eliminate_zeros v ii*I*I*T
csr_sum_duplicates  v ii*I*I*T
get_csr_submatrix   v iiIITiiii*V*V*W
csr_row_index       v iIIIT*I*T
csr_row_slice       v iiiIIT*I*T
csr_column_index1   v iIiiII*I*I
csr_column_index2   v IIiIT*I*T
csr_sample_values   v iiIITiII*T
csr_count_blocks    i iiiiII
csr_sample_offsets  i iiIIiII*I
csr_hstack          v iiIIIT*I*I*T
expandptr           v iI*I
test_throw_error    i
csr_has_sorted_indices    i iII
csr_has_canonical_format  i iII
z
coo_tocsr           v iiiIIT*I*I*T
coo_todense         v iilIIT*Ti
coo_matvec          v lIITT*T
dia_matvec          v iiiiITT*T
cs_graph_components i iII*I
ZbsrZcsrZcscother)Z	NPY_INT32Z	npy_int32)Z	NPY_INT64Z	npy_int64))ZNPY_BOOLZnpy_bool_wrapper)ZNPY_BYTEZnpy_byte)Z	NPY_UBYTEZ	npy_ubyte)Z	NPY_SHORTZ	npy_short)Z
NPY_USHORTZ
npy_ushort)ZNPY_INTZnpy_int)ZNPY_UINTZnpy_uint)ZNPY_LONGZnpy_long)Z	NPY_ULONGZ	npy_ulong)ZNPY_LONGLONGZnpy_longlong)ZNPY_ULONGLONGZnpy_ulonglong)Z	NPY_FLOATZ	npy_float)Z
NPY_DOUBLEZ
npy_double)ZNPY_LONGDOUBLEZnpy_longdouble)Z
NPY_CFLOATZnpy_cfloat_wrapper)ZNPY_CDOUBLEZnpy_cdouble_wrapper)ZNPY_CLONGDOUBLEZnpy_clongdouble_wrapperzf
static PY_LONG_LONG %(name)s_thunk(int I_typenum, int T_typenum, void **a)
{
    %(thunk_content)s
}
z
NPY_VISIBILITY_HIDDEN PyObject *
%(name)s_method(PyObject *self, PyObject *args)
{
    return call_thunk('%(ret_spec)s', "%(arg_spec)s", %(name)s_thunk, args);
}
z]
static int get_thunk_case(int I_typenum, int T_typenum)
{
    %(content)s;
    return -1;
}
c            	   	   C   s   g } g }d}d}t D ]C\}}d}||t||d 7 }|||d|df |d7 }tD ]\}}d}||t||d 7 }| |||||f |d7 }q*|d	7 }q
|| tt|d
 fS )a  
    Get a list containing cartesian product of data types, plus a getter routine.

    Returns
    -------
    i_types : list [(j, I_typenum, None, I_type, None), ...]
         Pairing of index type numbers and the corresponding C++ types,
         and an unique index `j`. This is for routines that are parameterized
         only by I but not by T.
    it_types : list [(j, I_typenum, T_typenum, I_type, T_type), ...]
         Same as `i_types`, but for routines parameterized both by T and I.
    getter_code : str
         C++ code for a function that takes I_typenum, T_typenum and returns
         the unique index corresponding to the lists, or -1 if no match was
         found.

    r   z    if (0) {}zb
        else if (I_typenum == %(I_typenum)s) {
            if (T_typenum == -1) { return %(j)s; })	I_typenumjN   zC
            else if (T_typenum == %(T_typenum)s) { return %(j)s; })	T_typenumr   z

        })Zcontent)I_TYPESdictappendT_TYPESGET_THUNK_CASE_TEMPLATE)	it_typesi_typesr   getter_coder   I_typepiecer   T_type r   D/usr/lib/python3/dist-packages/scipy/sparse/_generate_sparsetools.pyget_thunk_type_set   s    

r   c                    s   |d }|dd   fdd}d}|D ]*\}}}}	}
||	|
}d}|dkr+|d	7 }n|d
7 }||t ||	|
|||| d 7 }q|d7 }tt | |d }tt | | d }||fS )a3  
    Generate thunk and method code for a given routine.

    Parameters
    ----------
    name : str
        Name of the C++ routine
    args : str
        Argument list specification (in format explained above)
    types : list
        List of types to instantiate, as returned `get_thunk_type_set`

    r   r   Nc                    s:  g }d}d} D ]}|rdnd}d}|dkrd}q|dkr)| d||  |f  nj|d	kr9| d
||  |f  nZ|dkrI| d
|| |f  nJ|dkrV| d|f  n=|dkrj|r`td| d| |f  n)|dkr~|rttd| d||f  n|dkr| d||f  ntd|f |d7 }qd|S )zE
        Generate argument list for calling the C++ function
        Fr    zconst *Tiz*(%s*)a[%d]Iz
(%s*)a[%d]TBz(npy_bool_wrapper*)a[%d]Vz"'V' argument must be an output argz(std::vector<%s>*)a[%d]Wz"'W' argument must be an output arglz*(%snpy_int64*)a[%d]zInvalid spec character %rr   z, )r
   
ValueErrorjoin)r   r   argsZnext_is_writeabler   tconstarg_specr   r   get_arglist  s<   

z"parse_routine.<locals>.get_arglistz>int j = get_thunk_case(I_typenum, T_typenum);
    switch (j) {z
        case %(j)s:vz?
            (void)%(name)s(%(arglist)s);
            return 0;z*
            return %(name)s(%(arglist)s);)r   r   r   r   r   arglistnamezb
    default:
        throw std::runtime_error("internal error: invalid argument typenums");
    })r)   thunk_content)r)   ret_specr%   )r	   THUNK_TEMPLATEMETHOD_TEMPLATE)r)   r!   typesr+   r&   r*   r   r   r   r   r   r(   r   Z
thunk_codeZmethod_coder   r$   r   parse_routine   s.   &

r/   c                  C   s  t jtpd d} | jddddd |  \}}g }t \}}}tD ]\}}g }	g }
| D ]g}| }|r<|	dr=q/z
|
d d	\}}W n ty[ } ztd
|f |d }~ww d|
 }d|v skd|v rtt|||\}}nt|||\}}||v rtd|f || |	| |
| q/tjtjtd|d }tt|s|jrtd|f  t|d%}t| || |	D ]}|| q|
D ]}|| qW d    n1 sw   Y  q#td|f  q#d}|D ]	}|d|f 7 }qd}|D ]}|dt|d 7 }q|d7 }tjtjtdd}tt|s(|jrVtd|f  t|d}t| || || W d    d S 1 sOw   Y  d S td|f  d S )Nr   )usagez
--no-forcestore_falseforceT)actiondestdefault#r   zMalformed line: %rr"   r   zDuplicate routine %rZsparsetoolsz_impl.hz$[generate_sparsetools] generating %rwz,[generate_sparsetools] %r already up-to-datezCNPY_VISIBILITY_HIDDEN PyObject *%s_method(PyObject *, PyObject *);
z4
static struct PyMethodDef sparsetools_methods[] = {zH
        {"%(name)s", (PyCFunction)%(name)s_method, METH_VARARGS, NULL},)r)   z%
        {NULL, NULL, 0, NULL}
    };zsparsetools_impl.h)optparseZOptionParser__doc__stripZ
add_option
parse_argsr   COMPILATION_UNITS
splitlines
startswithsplitr   r    r/   r
   ospathdirname__file__r   r2   printopenwrite_autogen_blurbwriter	   )poptionsr!   namesr   r   r   Z	unit_nameZroutinesZthunksmethodsliner)   eZthunkmethoddstfZmethod_defsZmethod_structr   r   r   mainO  s   




$rQ   c                 C   s   |  d d S )Nzh/* This file is autogenerated by generate_sparsetools.py
 * Do not edit manually or check into VCS.
 */
)rG   )streamr   r   r   rF     s   rF   __main__)r9   r8   r@   Zdistutils.dep_utilr   ZBSR_ROUTINESZCSC_ROUTINESZCSR_ROUTINESZOTHER_ROUTINESr<   r   r   r,   r-   r   r   r/   rQ   rF   __name__r   r   r   r   <module>   s6    	)
0ZS
