o
    i                    @   s  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 dlmZ d dlmZ d dlmZ d dlZG d	d
 d
eZdd Zdd Zdd Zi dddddddddddddddddddddd dfd!d"dd dfd#dd$dd%d&d'd&d(d&d)d&d&ddd*d*d&d&d&d+d&d,d,d-d.d/Zi dd0dej dfdd0dd0dd0dd0dd0dd0dd0dd1d!d1d#d0d$d0d%d0d'd0d(d0d)d0d0d0d0ej dfej dfd0d0d0d0d0d1d1ej dfd2d/Z!d3d4 Z"e# d5d6 Z$d7e%fd8d9Z&dd<dZ'dd=d>Z(dd@dZ)ddAdZ*ddDdZ+ddEdZ,ddFdZ-ddGdZ.ddHdZ/ddId#Z0ddJd$Z1dKd% Z2dLd' Z3ddNd(Z4dOd) Z5dPdQ Z6dRdS Z7dTdU Z8dVdW Z9dXdY Z:dZd[ Z;d\d] Z<d^d_ Z=d`da Z>dbdc Z?ddde Z@G dfdg dgeZAG dhdi dieAZBG djdk dkeAZCG dldm dmeAZDG dndo doeAZEddpdZFddqd!ZG	;	;ddrdsZHddtduZIddwdxZJddydzZKdd{d|ZLdd}d~ZMdS )    N)driver)runtime)cusparse)_dtype)device)stream)_utilc                   @   sV   e Zd Zdd Zedd Zdd ZejfddZ	d	d
 Z
dd Zdd Zdd ZdS )MatDescriptorc                 C   s
   || _ d S N)
descriptor)selfr    r   K/home/ubuntu/veenaModal/venv/lib/python3.10/site-packages/cupyx/cusparse.py__init__      
zMatDescriptor.__init__c                 C   s   t  }t|S r
   )	_cusparsecreateMatDescrr	   )clsdescrr   r   r   create   s   zMatDescriptor.createc                 C   s
   | j dfS )Nr   )r   )r   r   r   r   
__reduce__   r   zMatDescriptor.__reduce__c                 C   s*   | rd S | j rt| j  d | _ d S d S r
   )r   r   destroyMatDescrr   is_shutting_downr   r   r   __del__   s   
zMatDescriptor.__del__c                 C      t | j| d S r
   )r   
setMatTyper   )r   typr   r   r   set_mat_type%      zMatDescriptor.set_mat_typec                 C   r   r
   )r   setMatIndexBaser   )r   baser   r   r   set_mat_index_base(   r   z MatDescriptor.set_mat_index_basec                 C   r   r
   )r   setMatFillModer   )r   	fill_moder   r   r   set_mat_fill_mode+   r   zMatDescriptor.set_mat_fill_modec                 C   r   r
   )r   setMatDiagTyper   )r   	diag_typer   r   r   set_mat_diag_type.   r   zMatDescriptor.set_mat_diag_typeN)__name__
__module____qualname__r   classmethodr   r   r   r   r   r   r"   r%   r(   r   r   r   r   r	      s    
r	   c                     s.   dd | D }t tj|  fdd| D S )Nc                 S   s   g | ]	}|d ur|j qS r
   dtype.0xr   r   r   
<listcomp>3   s    z%_cast_common_type.<locals>.<listcomp>c                    s,   g | ]}|d ur|j  kr| n|qS r
   )r.   astyper/   r-   r   r   r2   5   s    $)
_functoolsreduce_numpypromote_types)xsdtypesr   r-   r   _cast_common_type2   s
   
r:   c                 C   s   | rt jS t jS r
   )r   CUSPARSE_OPERATION_TRANSPOSE CUSPARSE_OPERATION_NON_TRANSPOSE)transr   r   r   _transpose_flag9   s   r>   c                 G   sR   |dkrd}n|dkrd}n|dkrd}n	|dkrd}nt tt||  }|| S )NfsdFcDz)	TypeErrorgetattrr   )namer.   argsprefixr?   r   r   r   _call_cusparse@   s   rK   csrmv)@  *  csrmvExcsrmmcsrmm2csrgeamcsrgeam2)<#  Ncsrgemmcsrgemm2)rM   .  gthrspmv'  rN   )LinuxWindowsspmmi=(  	csr2dense	csc2densecsrsort)rM   Ncscsortcoosortcoo2csr)rZ   N)rT   rW   )i$,  N)i\+  N)iP-  N)csr2coocsr2csccsc2csr
csr2cscEx2
csc2csrEx2	dense2csc	dense2csrcsr2csr_compresscsrsm2csrilu02denseToSparsesparseToDensespgemmspsm)i1  N)  N)iNc                 C   s8   t | trt }|| vrd|}t|| | S | S )Nz/No version information specified for the OS: {})
isinstancedict	_platformsystemformat
ValueError)r1   os_namemsgr   r   r   _get_avail_version_from_spec   s   
r{   c                 C   s   t js
t}t }nt}t }| |vrd| }t|||  \}}t	|}t	|}|d ur5||k r5dS |d ur?||kr?dS dS )Nz1No available version information specified for {}FT)
_runtimeis_hip_available_cusparse_versionr   get_build_version_available_hipsparse_version_driverrw   rx   r{   )rH   available_versionversionrz   version_addedversion_removedr   r   r   check_availability   s    

r   returnc                   C   s   t t S r
   )r   
getVersion_deviceget_cusparse_handler   r   r   r   r      s   r      Fc                 C   s
  t dstd|du s|jjsJ |s| jn| jddd }|d t|kr+tdt }|\}}	t	| ||\} }}| j
}
|du rIt||
}t||
j}t||
j}td|
|t|| jd | jd | j|j| jj| jjj| jjj| jjj|jj|j|jj |S )a\  Matrix-vector product for a CSR-matrix and a dense vector.

    .. math::

       y = \alpha * o_a(A) x + \beta y,

    where :math:`o_a` is a transpose function when ``transa`` is ``True`` and
    is an identity function otherwise.

    Args:
        a (cupyx.cusparse.csr_matrix): Matrix A.
        x (cupy.ndarray): Vector x.
        y (cupy.ndarray or None): Vector y. It must be F-contiguous.
        alpha (float): Coefficient for x.
        beta (float): Coefficient for y.
        transa (bool): If ``True``, transpose of ``A`` is used.

    Returns:
        cupy.ndarray: Calculated ``y``.

    rL   zcsrmv is not available.Nr   dimension mismatchr   )r   RuntimeErrorflagsf_contiguousshapelenrx   r   r   r:   r.   _cupyzerosr6   arrayctypesrK   r>   nnzdata_descrr   ptrindptrindices)ar1   yalphabetatransaa_shapehandlemnr.   r   r   r   rL      s,   c                 C   sv   | j j jd dkrdS | jj jd dkrdS | jj jd dkr!dS |j jd dkr+dS |dur9|j jd dkr9dS dS )a  Check if the pointers of arguments for csrmvEx are aligned or not

    Args:
        a (cupyx.cusparse.csr_matrix): Matrix A.
        x (cupy.ndarray): Vector x.
        y (cupy.ndarray or None): Vector y.

        Check if a, x, y pointers are aligned by 128 bytes as
        required by csrmvEx.

    Returns:
        bool:
        ``True`` if all pointers are aligned.
        ``False`` if otherwise.

       r   FNT)r   r   r   r   )r   r1   r   r   r   r   csrmvExIsAligned   s   r   Tc                 C   s  t dstd|du s|jjsJ | jd t|krtdt }| j\}}t	| ||\} }}| j
}	|du r>t||	}t|	}
|rHtjntj}tj}t||	j}t||	j}t| ||sdJ t|||| jd | jd | j|j|
| jj| jjj|
| jjj| jjj|jj|
|j|
|jj|
|
}t|d}|jjd dksJ t |||| jd | jd | j|j|
| jj| jjj|
| jjj| jjj|jj|
|j|
|jj|
|
|jj |S )	a  Matrix-vector product for a CSR-matrix and a dense vector.

    .. math::

       y = \alpha * A x + \beta y,

    Args:
        a (cupyx.cusparse.csr_matrix): Matrix A.
        x (cupy.ndarray): Vector x.
        y (cupy.ndarray or None): Vector y. It must be F-contiguous.
        alpha (float): Coefficient for x.
        beta (float): Coefficient for y.
        merge_path (bool): If ``True``, merge path algorithm is used.

        All pointers must be aligned with 128 bytes.

    Returns:
        cupy.ndarray: Calculated ``y``.

    rO   zcsrmvEx is not available.Nr   r   r   br   )!r   r   r   r   r   r   rx   r   r   r:   r.   r   r   r   to_cuda_dtyper   CUSPARSE_ALG_MERGE_PATHCUSPARSE_ALG_NAIVEr<   r6   r   r   r   csrmvEx_bufferSizer   r   r   r   r   r   r   emptyrO   )r   r1   r   r   r   
merge_pathr   r   r   r.   datatypealgmodetransa_flag
bufferSizebufr   r   r   rO     sN   


c                 C   sX  t dstd| j|j  krdksJ  J |jjsJ |du s(|jjs(J |s-| jn| jddd }|d |jd krBtdt }|\}}	|jd }
t	| ||\} }}|du rft
||
f| jd	}|	}|}t|| jj}t|| jj}td| j|t|| jd |
| jd | j|j| jj| jjj| jjj| jjj|jj||j|jj| |S )
a|  Matrix-matrix product for a CSR-matrix and a dense matrix.

    .. math::

       C = \alpha o_a(A) B + \beta C,

    where :math:`o_a` is a transpose function when ``transa`` is ``True`` and
    is an identity function otherwise.

    Args:
        a (cupyx.scipy.sparse.csr): Sparse matrix A.
        b (cupy.ndarray): Dense matrix B. It must be F-contiguous.
        c (cupy.ndarray or None): Dense matrix C. It must be F-contiguous.
        alpha (float): Coefficient for AB.
        beta (float): Coefficient for C.
        transa (bool): If ``True``, transpose of A is used.

    Returns:
        cupy.ndarray: Calculated C.

    rP   zcsrmm is not available.   Nr   r   r   r   rB   )r   r   ndimr   r   r   rx   r   r   r:   r   r   r.   r6   r   r   rK   r>   r   r   r   r   r   r   r   )r   r   rC   r   r   r   r   r   r   kr   ldbldcr   r   r   rP   T  s6    
      ?        c                 C   s  t dstd| j|j  krdksJ  J | jsJ |jjs#J |du s-|jjs-J |r3|r3J |s8| jn| jddd }|sE|jn|jddd }|d |d krYtdt	 }	|\}
}|d }t
| ||\} }}|du r|t|
|f| jd	}|jd }|jd }t|}t|}t|| jj}t|| jj}td| j|	||| jd || jd | j|j| jj| jjj| jjj| jjj|jj||j|jj| |S )
aV  Matrix-matrix product for a CSR-matrix and a dense matrix.

    .. math::

       C = \alpha o_a(A) o_b(B) + \beta C,

    where :math:`o_a` and :math:`o_b` are transpose functions when ``transa``
    and ``tranb`` are ``True`` respectively. And they are identity functions
    otherwise.
    It is forbidden that both ``transa`` and ``transb`` are ``True`` in
    cuSPARSE specification.

    Args:
        a (cupyx.scipy.sparse.csr): Sparse matrix A.
        b (cupy.ndarray): Dense matrix B. It must be F-contiguous.
        c (cupy.ndarray or None): Dense matrix C. It must be F-contiguous.
        alpha (float): Coefficient for AB.
        beta (float): Coefficient for C.
        transa (bool): If ``True``, transpose of A is used.
        transb (bool): If ``True``, transpose of B is used.

    Returns:
        cupy.ndarray: Calculated C.

    rQ   zcsrmm2 is not available.r   Nr   r   r   r   rB   )r   r   r   has_canonical_formatr   r   r   rx   r   r   r:   r   r   r.   r>   r6   r   r   rK   r   r   r   r   r   r   r   )r   r   rC   r   r   r   transbr   b_shaper   r   r   r   r   r   op_aop_br   r   r   rQ     s>    


c                 C   s  t dstdt| tjjjstdt	| t|tjjjs*tdt	|| j
s/J |j
s4J | j|jkr>tdt }| j\}}t| |\} }tdd}t|tj t }t|d d}	t|||| jj| j| jjj| jjj|jj|j|jjj|jjj|j|	jj|j j tt!|d}
tt!|| j"}t#|| j"j }t#|| j"j }t$d| j"||||j| jj| j| jjj| jjj| jjj|j|jj|j|jjj|jjj|jjj|j|jj|	jj|
jj tjjj||
|	f| jd}d	|_%|S )
e  Matrix-matrix addition.

    .. math::
        C = \alpha A + \beta B

    Args:
        a (cupyx.scipy.sparse.csr_matrix): Sparse matrix A.
        b (cupyx.scipy.sparse.csr_matrix): Sparse matrix B.
        alpha (float): Coefficient for A.
        beta (float): Coefficient for B.

    Returns:
        cupyx.scipy.sparse.csr_matrix: Result matrix.

    rR   zcsrgeam is not available.unsupported type (actual: {})inconsistent shapesr   ir   r   T)&r   r   rs   cupyxscipysparse
csr_matrixrF   rw   typer   r   rx   r   r   r:   r6   r   r   setPointerModeCUSPARSE_POINTER_MODE_HOSTr	   r   r   xcsrgeamNnzr   r   r   r   r   r   r   r   intr.   r   rK   _has_canonical_format)r   r   r   r   r   r   r   r   c_descrc_indptr	c_indicesc_datarC   r   r   r   rR     sX   




c                 C   s  t dstdt| tjjjstdt	| t|tjjjs*tdt	|| j
s/J |j
s4J | j|jkr>tdt }| j\}}t| |\} }tdd}t|tj t|| jj}t|| jj}t }t|d d}	d}
td	| j||||j| jj| j| jjj | j!jj | j"jj |j|jj|j|jjj |j!jj |j"jj |j|
|	jj |
}t|tj#}t$|||| jj| j| j!jj | j"jj |jj|j|j!jj |j"jj |j|	jj |jj|jj  tt%|d}tt%|| j}td| j||||j| jj| j| jjj | j!jj | j"jj |j|jj|j|jjj |j!jj |j"jj |j|jj |	jj |jj |jj  tjjj|||	f| jd
}d|_&|S )r   rS   zcsrgeam2 is not available.r   r   r   r   r   r   csrgeam2_bufferSizeExtr   T)'r   r   rs   r   r   r   r   rF   rw   r   r   r   rx   r   r   r:   r6   r   r   r   r   r   r.   r   r	   r   r   rK   r   r   r   r   r   r   r   int8xcsrgeam2Nnzr   r   )r   r   r   r   r   r   r   r   r   r   null_ptr	buff_sizebuffr   r   rC   r   r   r   rS     sf   


c                 C   s6  t dstd| j|j  krdksJ  J | jsJ |js"J |s'| jn| jddd }|s4|jn|jddd }|d |d krHtdt }|\}}|d }	t| |\} }| j	dkse|j	dkrqt
jjj||	f| jd	S t|}
t|}td
d}t|tj t }t|d d}t||
|||	|| jj| j	| jjj| jjj|jj|j	|jjj|jjj|j|jj|jj tt |d}tt || j}t!d| j||
|||	|| jj| j	| jjj| jjj| jjj|jj|j	|jjj|jjj|jjj|j|jj|jj|jj t
jjj|||f||	fd}d|_"|S )a  Matrix-matrix product for CSR-matrix.

    math::
       C = op(A) op(B),

    Args:
        a (cupyx.scipy.sparse.csr_matrix): Sparse matrix A.
        b (cupyx.scipy.sparse.csr_matrix): Sparse matrix B.
        transa (bool): If ``True``, transpose of A is used.
        transb (bool): If ``True``, transpose of B is used.

    Returns:
        cupyx.scipy.sparse.csr_matrix: Calculated C.

    rU   zcsrgemm is not available.r   Nr   r   r   r   r-   r   r   r   T)#r   r   r   r   r   rx   r   r   r:   r   r   r   r   r   r.   r>   r6   r   r   r   r   r	   r   r   xcsrgemmNnzr   r   r   r   r   r   r   r   rK   r   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rC   r   r   r   rU   P  sZ    

	c                 C   s  t dstd| j|j  krdksJ  J t| tjjjs)td	t
| t|tjjjs:td	t
|| js?J |jsDJ | jd |jd krRtd|dur|jdks]J t|tjjjsntd	t
||jssJ | jd |jd ks|jd |jd krtdtjrt d	k rtd
t }| j\}}|j\}}	|du rt| |\} }n	t| ||\} }}t }
t|| jj}d}|du r|}t }d}|}|}|}n t|| jj}|j}|j}|j}|jjj }|j!jj }|j"jj }t#d| j|||	||j| jj$| j| j!jj | j"jj |jj$|j|j!jj |j"jj ||j$||||
}t%&|tj'}t&dd}t(|tj) t }t%&|d d}t*|||	|| jj$| j| j!jj | j"jj |jj$|j|j!jj |j"jj |j$||||j$|jj |jj|
|jj  t%&t+|d}t%&t+|| j}t#d| j|||	||j| jj$| j| jjj | j!jj | j"jj |jj$|j|jjj |j!jj |j"jj ||j$|||||j$|jj |jj |jj |
|jj  tjjj|||f||	fd}d|_,t-|
 |S )a  Matrix-matrix product for CSR-matrix.

    math::
       C = alpha * A * B + beta * D

    Args:
        a (cupyx.scipy.sparse.csr_matrix): Sparse matrix A.
        b (cupyx.scipy.sparse.csr_matrix): Sparse matrix B.
        d (cupyx.scipy.sparse.csr_matrix or None): Sparse matrix D.
        alpha (scalar): Coefficient
        beta (scalar): Coefficient

    Returns:
        cupyx.scipy.sparse.csr_matrix

    rV   zcsrgemm2 is not available.r   r   r   r   mismatched shapeNrr   z'd != None is supported since ROCm 4.2.0csrgemm2_bufferSizeExtr   r   r   T).r   r   r   rs   r   r   r   r   rF   rw   r   r   r   rx   r|   r}   r   r   r   r   r:   r   createCsrgemm2Infor6   r   r.   r   r	   r   r   r   r   r   r   r   rK   r   r   r   r   r   r   xcsrgemm2Nnzr   r   destroyCsrgemm2Info)r   r   rA   r   r   r   r   r   _r   infor   	beta_datad_descrd_nnzd_datad_indptr	d_indicesr   r   c_nnzr   r   r   r   rC   r   r   r   rV     s    


(




	
c                 C      t dstd| j}|jdv sJ |du r tj| j|dd}n|jjs&J t	
 }td| j|| jd | jd | jj| jjj| jjj| jjj|jj| jd  |S )	a!  Converts CSR-matrix to a dense matrix.

    Args:
        x (cupyx.scipy.sparse.csr_matrix): A sparse matrix to convert.
        out (cupy.ndarray or None): A dense metrix to store the result.
            It must be F-contiguous.

    Returns:
        cupy.ndarray: Converted result.

    r^   zcsr2dense is not available.fdFDNrB   r.   orderr   r   )r   r   r.   charr   r   r   r   r   r   r   rK   r   r   r   r   r   r   r1   outr.   r   r   r   r   r^        c                 C   r   )	a!  Converts CSC-matrix to a dense matrix.

    Args:
        x (cupyx.scipy.sparse.csc_matrix): A sparse matrix to convert.
        out (cupy.ndarray or None): A dense metrix to store the result.
            It must be F-contiguous.

    Returns:
        cupy.ndarray: Converted result.

    r_   zcsc2dense is not available.r   NrB   r   r   r   )r   r   r.   r   r   r   r   r   r   r   r   rK   r   r   r   r   r   r   r   r   r   r   r_     r   c                 C     t dstd| j}|dkrdS t }| j\}}t||||| jj	j
| jj	j
}t|d}t|d}| j	 }t|||j	j
 t||||| jj| jj	j
| jj	j
|j	j
|j	j
	 t drwtd| j|||j	j
| j	j	j
|j	j
tj dS t|| j	}	t|}
t||
j|	j dS )zzSorts indices of CSR-matrix in place.

    Args:
        x (cupyx.scipy.sparse.csr_matrix): A sparse matrix to sort.

    r`   zcsrsort is not available.r   Nr   r   rX   )r   r   r   r   r   r   r   xcsrsort_bufferSizeExtr   r   r   r   r   r   copycreateIdentityPermutationxcsrsortr   r   rK   r.   CUSPARSE_INDEX_BASE_ZEROSpVecDescriptorr   DnVecDescriptorgatherdescr1   r   r   r   r   buffer_sizer   P	data_origdesc_xdesc_yr   r   r   r`   >  8   



c                 C   r   )zzSorts indices of CSC-matrix in place.

    Args:
        x (cupyx.scipy.sparse.csc_matrix): A sparse matrix to sort.

    ra   zcscsort is not available.r   Nr   r   rX   )r   r   r   r   r   r   r   xcscsort_bufferSizeExtr   r   r   r   r   r   r   r   xcscsortr   r   rK   r.   r   r   r   r   r   r   r   r   r   r   ra   d  r   rc              
   C   sz  t dstd| j}|dkrdS t }| j\}}t||||| jj	j
| jj	j
}t|d}t|d}| j	 }	t|||j	j
 |dkr_t||||| jj	j
| jj	j
|j	j
|j	j
 n|dkrzt||||| jj	j
| jj	j
|j	j
|j	j
 ntd	| jjd
krt drtd| j|||	j	j
| j	j	j
|j	j
tj nt|| j	}
t|	}t||j|
j |dkrd| _dS dS )zSorts indices of COO-matrix in place.

    Args:
        x (cupyx.scipy.sparse.coo_matrix): A sparse matrix to sort.
        sort_by (str): Sort the indices by row ('r', default) or column ('c').

    rb   zcoosort is not available.r   Nr   r   r  rC   z!sort_by must be either 'r' or 'c'?rX   F)r   r   r   r   r   r   r   xcoosort_bufferSizeExtrowr   r   colr   r   r   r   xcoosortByRowxcoosortByColumnrx   r.   r   rK   r   r   r   r   r   r   r   )r1   sort_byr   r   r   r   r   r   r   r   r   r   r   r   r   rb     sL   




c                 C   s   t  }| jd }| j}|dkrt|d d}nt|d d}t|| j	j
j|||j
jtj tjjj| j
| j|f| jdS )Nr   r   r   r   )r   r   r   r   r   r   r   r   xcoo2csrr  r   r   r   r   r   r   r   r  )r1   r   r   r   r   r   r   r   rc        

c                 C   s   t  }| jd }| j}|dkrt|d d}nt|d d}t|| j	j
j|||j
jtj tjjj| j
| j|f| jdS )Nr   r   r   r   )r   r   r   r   r   r   r   r   r  r  r   r   r   r   r   r   
csc_matrixr  )r1   r   r   r   r   r   r   r   coo2csc  r  r  c                 C   sp   t dstdt }| jd }| j}t|d}t	|| j
jj|||jjtj tjjj|||ff| jdS )aD  Converts a CSR-matrix to COO format.

    Args:
        x (cupyx.scipy.sparse.csr_matrix): A matrix to be converted.
        data (cupy.ndarray): A data array for converted data.
        indices (cupy.ndarray): An index array for converted data.

    Returns:
        cupyx.scipy.sparse.coo_matrix: A converted matrix.

    rd   zcsr2coo is not available.r   r   r   )r   r   r   r   r   r   r   r   r   xcsr2coor   r   r   r   r   r   r   
coo_matrix)r1   r   r   r   r   r   r  r   r   r   rd     s   
rd   c                 C   s   t dstdt }| j\}}| j}t|| j}t|d}|dkr.t	|d d}n+t|d d}t
d| j||||| jjj| jjj| jjj|jj|jj|jjtjtj tjjj|||f| jdS )Nre   csr2csc is not available.r   r   r   r   )r   r   r   r   r   r   r   r   r.   r   rK   r   r   r   r   r   CUSPARSE_ACTION_NUMERICr   r   r   r   r  r1   r   r   r   r   r   r   r   r   r   r   re     *   
re   c                 C   s<  t dstdt }| j\}}| j}t|| j}t|d}|dkr.t	|d d}nct|d d}t
| j}tj}	tj}
tj}t||||| jjj| jjj| jjj|jj|jj|jj||	|
|}t|tj}t||||| jjj| jjj| jjj|jj|jj|jj||	|
||jj tjjj|||f| jdS )Nrg   zcsr2cscEx2 is not available.r   r   r   r   )r   r   r   r   r   r   r   r   r.   r   r   r   r   r  r   CUSPARSE_CSR2CSC_ALG1csr2cscEx2_bufferSizer   r   r   r   r6   r   rg   r   r   r   r  r1   r   r   r   r   r   r   r   x_dtypeactionibasealgor   bufferr   r   r   rg     8   
rg   c                 C   s`   t  }| jd }| j}t|d}t|| jj	j
|||j	j
tj tjjj|||ff| jdS )aD  Converts a CSC-matrix to COO format.

    Args:
        x (cupyx.scipy.sparse.csc_matrix): A matrix to be converted.
        data (cupy.ndarray): A data array for converted data.
        indices (cupy.ndarray): An index array for converted data.

    Returns:
        cupyx.scipy.sparse.coo_matrix: A converted matrix.

    r   r   r   )r   r   r   r   r   r   r   r  r   r   r   r   r   r   r   r  )r1   r   r   r   r   r   r  r   r   r   csc2coo*  s   
r  c                 C   s   t dstdt }| j\}}| j}t|| j}t|d}|dkr.t	|d d}n+t|d d}t
d| j||||| jjj| jjj| jjj|jj|jj|jjtjtj tjjj|||f| jdS )Nrf   r  r   r   r   re   r   )r   r   r   r   r   r   r   r   r.   r   rK   r   r   r   r   r   r  r   r   r   r   r   r  r   r   r   rf   B  r  rf   c                 C   s<  t dstdt }| j\}}| j}t|| j}t|d}|dkr.t	|d d}nct|d d}t
| j}tj}	tj}
tj}t||||| jjj| jjj| jjj|jj|jj|jj||	|
|}t|tj}t||||| jjj| jjj| jjj|jj|jj|jj||	|
||jj tjjj|||f| jdS )Nrh   zcsc2csrEx2 is not available.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   r6   r   rg   r   r   r   r   r  r   r   r   rh   Z  r  rh   c                 C   s  t dstd| jdksJ t| } tjddd}t }| j	\}}t
 }t|d}td| j|tj|||j| jj||jj|jj t|}t|| j}t|d d}t|d}	td| j||||j| jj||jj|jj|	jj|jj tjjj||	|f| j	d	}
d
|
_|
S )zConverts a dense matrix in CSC format.

    Args:
        x (cupy.ndarray): A matrix to be converted.

    Returns:
        cupyx.scipy.sparse.csc_matrix: A converted matrix.

    ri   zdense2csc is not available.r   r   r   r-   r   r   r   T)r   r   r   r   asfortranarrayr6   r   r   r   r   r	   r   rK   r.   r   CUSPARSE_DIRECTION_COLUMNr   r   r   r   r   r   r   r   r  r   )r1   r   r   r   r   r   nnz_per_colr   r   r   cscr   r   r   ri   x  s6   



ri   c                 C   s,  t dstd| jdksJ t| } tjddd}t }| j	\}}t
 }t|d}td| j|tj|||j| jj||jj|jj t|}tjrT|dkrTtd	t|| j}t|d
 d}t|d}	td| j||||j| jj||jj|jj|jj|	jj tjjj||	|f| j	d}
d|
_|
S )zConverts a dense matrix in CSR format.

    Args:
        x (cupy.ndarray): A matrix to be converted.

    Returns:
        cupyx.scipy.sparse.csr_matrix: A converted matrix.

    rj   zdense2csr is not available.r   r   r   r-   r   r   @hipSPARSE currently cannot handle sparse matrices with null ptrsr   r   T)r   r   r   r   r  r6   r   r   r   r   r	   r   rK   r.   r   CUSPARSE_DIRECTION_ROWr   r   r   r   r   r|   r}   rx   r   r   r   r   r   )r1   r   r   r   r   r   nnz_per_rowr   r   r   csrr   r   r   rj     s<   



rj   c           
      C   s   t dstd| jjdv sJ t }| j\}}t|d}t	d| j||| j
j| jjj| jjj|jj|	}t|| j}t|d d}t|d}	t	d| j|||| j
j| jjj| jjj| jjj| j|jj|jj|	jj|jj| tjjj||	|f| jdS )Nrk   z"csr2csr_compress is not available.r   r   nnz_compressr   r   )r   r   r.   r   r   r   r   r   r   rK   r   r   r   r   r   r   r   r   r   r   r   r   )
r1   tolr   r   r   r%  r   r   r   r   r   r   r   rk     s0   

rk   c                 C   s.   | dkrt jS | dkrt jS | dkrt jS t)Nuint16int32int64)r   CUSPARSE_INDEX_16UCUSPARSE_INDEX_32ICUSPARSE_INDEX_64IrF   r-   r   r   r   _dtype_to_IndexType  s   r/  c                   @   s,   e Zd ZdddZejfddZdd ZdS )	BaseDescriptorNc                 C   s   || _ || _|| _d S r
   )r   getdestroy)r   r   r1  	destroyerr   r   r   r     s   
zBaseDescriptor.__init__c                 C   sB   | rd S | j d u rd | _d S | jd ur|  | j d | _d S d S r
   )r2  r   r   r   r   r   r     s   



zBaseDescriptor.__del__c                 C   s    | j d urt|  | j|S tr
   )r1  rG   r   AttributeError)r   rH   r   r   r   __getattr__  s   
zBaseDescriptor.__getattr__)NN)r)   r*   r+   r   r   r   r   r5  r   r   r   r   r0    s    
	r0  c                   @   s    e Zd Zedd Zdd ZdS )SpMatDescriptorc           	      C   s:  t jj|s	J |j\}}tj}t|j	}|j
dkr@t|||j|jjj|jjj|jjjt|jj	t|jj	||
}tj}nT|j
dkrdt|||j|jjj|jjj|jjjt|jj	||	}tj}n0|j
dkrt|||j|jjj|jjj|jjjt|jj	t|jj	||
}d }ntd
|j
tj}t|||S )Nr&  coor"  z3csr, csc and coo format are supported (actual: {}).)r   r   r   issparser   r   r   r   r   r.   rw   	createCsrr   r   r   r   r   r/  csrGet	createCoor  r  cooGet	createCscrx   destroySpMatr6  )	r   r   rowscolsidx_base
cuda_dtyper   r1  r2  r   r   r   r     s<   



zSpMatDescriptor.createc                 C   s   t | j|| d S r
   )r   spMatSetAttributer   )r   	attributer   r   r   r   set_attribute-  s   zSpMatDescriptor.set_attributeN)r)   r*   r+   r,   r   rE  r   r   r   r   r6    s    
r6  c                   @      e Zd Zedd ZdS )r   c              	   C   sP   |j }t|j}t|||jj|jjt|jtj	|}tj
}tj}t|||S r
   )sizer   r   r.   r   createSpVecr   r   r/  r   spVecGetdestroySpVecr   )r   idxr1   r   rB  r   r1  r2  r   r   r   r   3  s   zSpVecDescriptor.createNr)   r*   r+   r,   r   r   r   r   r   r   1      r   c                   @   rF  )r   c                 C   s8   t |j}t|j|jj|}tj}tj	}t
|||S r
   )r   r   r.   r   createDnVecrG  r   r   dnVecGetdestroyDnVecr   )r   r1   rB  r   r1  r2  r   r   r   r   B  s
   zDnVecDescriptor.createNrL  r   r   r   r   r   @  rM  r   c                   @   rF  )DnMatDescriptorc           	      C   sf   |j dksJ |jjsJ |j\}}|}t|j}t||||j	j
|tj}tj}tj}t|||S )Nr   )r   r   r   r   r   r   r.   r   createDnMatr   r   CUSPARSE_ORDER_COLdnMatGetdestroyDnMatrQ  )	r   r   r?  r@  ldrB  r   r1  r2  r   r   r   r   M  s   
zDnMatDescriptor.createNrL  r   r   r   r   rQ  K  rM  rQ  c                 C   s  t dstdt| tjjjr+| j}t|tjjjs&d	t
|}t||} | }t| tjjjtjjjfsAtd	t
| |sF| jn| jddd }|d t|krZtd| js_J |\}	}
t| ||\} }}|du rxt|	| j}n
t||	krtd| jd	kr|d	 |S t| }t|}t|}t }t|}t|| jj}t|| jj}t !| j}t"j#}t"$|||j%|j&|j&|j%|j&||	}t'|tj(}t")|||j%|j&|j&|j%|j&|||j%j*
 |S )
a  Multiplication of sparse matrix and dense vector.

    .. math::

        y = \alpha * op(A) x + \beta * y

    Args:
        a (cupyx.scipy.sparse.csr_matrix, csc_matrix or coo_matrix):
            Sparse matrix A
        x (cupy.ndarray): Dense vector x
        y (cupy.ndarray or None): Dense vector y
        alpha (scalar): Coefficient
        beta (scalar): Coefficient
        transa (bool): If ``True``, op(A) = transpose of A.

    Returns:
        cupy.ndarray
    rY   zspmv is not available."aT must be csr_matrix (actual: {})r   Nr   r   r   r   )+r   r   rs   r   r   r   r  Tr   rw   r   rF   r  r   r   rx   r   r:   r   r   r.   r   fillr6  r   r   r   r   r>   r6   r   r   r   r   r   CUSPARSE_MV_ALG_DEFAULTspMV_bufferSizer   r   r   r   spMVr   )r   r1   r   r   r   r   aTrz   r   r   r   desc_ar   r   r   r   rB  algr   r   r   r   r   rY   [  sX   





c                 C   s`  t dstd| j|j  krdksJ  J |jjsJ |du s(|jjs(J t| tjjj	rK| j
}t|tjjjsFdt|}t||} | }t| tjjjtjjjfsatdt| |sf| jn| jddd }	|ss|jn|jddd }
|	d |
d	 krtd
| jsJ |	\}}|
\}}t| ||\} }}|du rt||f| jd}n|jd	 |ks|jd |krtd
| jd	kr|d	 |S t| }t|}t|}t }t|}t|}t || jj!}t || jj!}t"#| j}t$j%}t$&||||j'|j(|j(|j'|j(||
}t)|tj*}t$+||||j'|j(|j(|j'|j(|||j'j,}|S )a  Multiplication of sparse matrix and dense matrix.

    .. math::

        C = \alpha * op(A) op(B) + \beta * C

    Args:
        a (cupyx.scipy.sparse.csr_matrix, csc_matrix or coo_matrix):
            Sparse matrix A
        b (cupy.ndarray): Dense matrix B
        c (cupy.ndarray or None): Dense matrix C
        alpha (scalar): Coefficient
        beta (scalar): Coefficient
        transa (bool): If ``True``, op(A) = transpose of A.
        transb (bool): If ``True``, op(B) = transpose of B.

    Returns:
        cupy.ndarray
    r]   zspmm is not available.r   NrW  r   r   r   r   r   rB   )-r   r   r   r   r   rs   r   r   r   r  rX  r   rw   r   rF   r  r   rx   r   r:   r   r   r.   r   rY  r6  r   rQ  r   r   r>   r6   r   r   r   r   r   CUSPARSE_MM_ALG_DEFAULTspMM_bufferSizer   r   r   r   spMMr   )r   r   rC   r   r   r   r   r]  rz   r   r   r   r   r   r   r^  desc_bdesc_cr   r   r   rB  r_  r   r   r   r   r   r]     sf    






c                 C   s6  t dstdtjj| stjj| stdt|t	j
s$td|jdvr-td| jd | jd   krC|jd ksHtd	 td	| j|jkrRtd
|du rZtj}n|du rbtj}ntd||du rqtj}	n|du rytj}	ntd||du rd}
n|du rd}
ntd||du rtj}n|du rtj}ntd|| j}|jdkrd}n|jdkrd}n|jdkrd}n|jdkrd}ntd|tt|d }tt|d }tt|d }|du s|dkrtj}n(|du s|dkrtj}n|dkr|jdv rtj}ntj}ntd |tjj| rF|tjkr1td!| j} tjj| s>J d| }d| }| jd }|jdkrSdn|jd }|jrbtj}|}n|jrltj}|}ntd"t  }t!j"||d#}t#$ }|%tj& |'tj( |)| |*|	 t+ }|||
||||| j,|j-j.|j/| j.j.j0| j1j.j0| j2j.j0|j.j0|||}t	j3|ft!j4d#}|||
||||| j,|j-j.|j/| j.j.j0| j1j.j0| j2j.j0|j.j0||||j.j0 |||
||||| j,|j-j.|j/| j.j.j0| j1j.j0| j2j.j0|j.j0||||j.j0 t56 7  t8| d$S )%aV  Solves a sparse triangular linear system op(a) * x = alpha * b.

    Args:
        a (cupyx.scipy.sparse.csr_matrix or cupyx.scipy.sparse.csc_matrix):
            Sparse matrix with dimension ``(M, M)``.
        b (cupy.ndarray): Dense vector or matrix with dimension ``(M)`` or
            ``(M, K)``.
        alpha (float or complex): Coefficient.
        lower (bool):
            True: ``a`` is lower triangle matrix.
            False: ``a`` is upper triangle matrix.
        unit_diag (bool):
            True: diagonal part of ``a`` has unit elements.
            False: diagonal part of ``a`` has non-unit elements.
        transa (bool or str): True, False, 'N', 'T' or 'H'.
            'N' or False: op(a) == ``a``.
            'T' or True: op(a) == ``a.T``.
            'H': op(a) == ``a.conj().T``.
        blocking (bool):
            True: blocking algorithm is used.
            False: non-blocking algorithm is used.
        level_info (bool):
            True: solves it with level information.
            False: solves it without level information.

    Note: ``b`` will be overwritten.
    rl   zcsrsm2 is not available.z"a must be CSR or CSC sparse matrixzb must be cupy.ndarray)r   r   b.ndim must be 1 or 2r   r   zinvalid shapedtype mismatchTFUnknown lower (actual: {})Unknown unit_diag (actual: {})zUnknown blocking (actual: {})Unknown level_info (actual: {})r?   r@   rA   rB   rC   rD   rE   Invalid dtype (actual: {})csrsm2_bufferSizeExtcsrsm2_analysiscsrsm2_solveNrX  HfdzUnknown transa (actual: {})z@If matrix is CSC format and complex dtype,transa must not be 'H''b must be F-contiguous or C-contiguous.r-   N)9r   r   r   r   r   isspmatrix_csrisspmatrix_cscrx   rs   r   ndarrayr   r   r.   rF   r   CUSPARSE_FILL_MODE_LOWERCUSPARSE_FILL_MODE_UPPERrw   CUSPARSE_DIAG_TYPE_NON_UNITCUSPARSE_DIAG_TYPE_UNITCUSPARSE_SOLVE_POLICY_NO_LEVELCUSPARSE_SOLVE_POLICY_USE_LEVELr   rG   r<   r;   &CUSPARSE_OPERATION_CONJUGATE_TRANSPOSErX  _f_contiguous_c_contiguousr   r   r6   r   r	   r   r   CUSPARSE_MATRIX_TYPE_GENERALr"   r   r%   r(   createCsrsm2Infor   r   r   r   r   r   r   r   r   _streamget_current_streamsynchronizedestroyCsrsm2Info)r   r   r   lower	unit_diagr   blocking
level_infor$   r'   r  policyr.   thelperanalysissolver   nrhsr   r   r   a_descr   ws_sizewsr   r   r   rl     s   
$







rl   c                 C   s`  t dstdtjj| std| jd | jd kr%td	| j|du r-t
j}n|du r5t
j}ntd		|| j}|jd
krGd}n|jdkrOd}n|jdkrWd}n|jdkr_d}ntd	|tt
|d }tt
|d }tt
|d }tt
d}t }	| jd }
| j}t }|t
j |t
j t
 }||	|
||j| jjj| jjj| jjj|}tj |ft!j"d}t!j dt!j#d}||	|
||j| jjj| jjj| jjj|||jj
 z
||	||j$j W n t%y   td	|d w ||	|
||j| jjj| jjj| jjj|||jj
 z||	||j$j W dS  t%y/   td	|d w )a  Computes incomplete LU decomposition for a sparse square matrix.

    Args:
        a (cupyx.scipy.sparse.csr_matrix):
            Sparse matrix with dimension ``(M, M)``.
        level_info (bool):
            True: solves it with level information.
            False: solves it without level information.

    Note: ``a`` will be overwritten. This function does not support fill-in
        (only ILU(0) is supported) nor pivoting.
    rm   zcsrilu02 is not available.za must be CSR sparse matrixr   r   zinvalid shape (a.shape: {})FTri  r?   r@   rA   rB   rC   rD   rE   rj  csrilu02_bufferSizecsrilu02_analysisxcsrilu02_zeroPivotr-   r   za({0},{0}) is missingzu({0},{0}) is zeroN)&r   r   r   r   r   rr  rF   r   rx   rw   r   ry  rz  r.   r   rG   r   r   r   r	   r   r   r~  r"   r   createCsrilu02Infor   r   r   r   r   r   r   r6   r   r*  r   	Exception)r   r  r  r.   r  r  r  r  checkr   r   r   r   r   r  r  positionr   r   r   rm   |  sj   





rm   r&  c                 C   sl  t dstd| jdksJ | jjdv sJ t| } t| }|dkr1t	j
jj| j| jd}n'|dkrAt	j
jj| j| jd}n|dkrQt	j
jj| j| jd}ntd	|t|}tj}t }t||j|j|}t|tj}t||j|j||jj tjd
dd}	tjd
dd}
tjd
dd}t |j|	j!j|
j!j|j!j t"|}t#j$r|d
krt%d|dkr|j&}t|d}t|| j}t	j
jj|||f| jd}nH|dkr|j&}t|d}t|| j}t	j
jj|||f| jd}n&|dkrt'|d}t'|d}t|| j}t	j
jj|||ff| jd}t|}t(||j|j||jj d|_)|S )a0  Converts a dense matrix into a CSR, CSC or COO format.

    Args:
        x (cupy.ndarray): A matrix to be converted.
        format (str): Format of converted matrix. It must be either 'csr',
            'csc' or 'coo'.

    Returns:
        cupyx.scipy.sparse.spmatrix: A converted sparse matrix.

    rn   zdenseToSparse is not available.r   r   r&  r-   r"  r7  zunsupported format (actual: {})r   r+  r#  r   r   T)*r   r   r   r.   r   r   r  rQ  r   r   r   r   r   r   r  r  rF   rw   r6  r   "CUSPARSE_DENSETOSPARSE_ALG_DEFAULTr   r   denseToSparse_bufferSizer   r   r   denseToSparse_analysisr   r   r6   r   spMatGetSizer   r   r|   r}   rx   r   r   denseToSparse_convertr   )r1   rw   r   r   r   r  r   r   r   num_rows_tmpnum_cols_tmpr   r   r   r   r  r  r   r   r   rn     st   







rn   c           	      C   s   t dstd| j}|jdv sJ |du r tj| j|dd}n|jjs&J |j|ks-J t	
| }t
|}tj}t }t||j|j|}t|tj}tjr[| jdkr[tdt||j|j||jj |S )	a*  Converts sparse matrix to a dense matrix.

    Args:
        x (cupyx.scipy.sparse.spmatrix): A sparse matrix to convert.
        out (cupy.ndarray or None): A dense metrix to store the result.
            It must be F-contiguous.

    Returns:
        cupy.ndarray: A converted dense matrix.

    ro   zsparseToDense is not available.r   NrB   r   r   r#  )r   r   r.   r   r   r   r   r   r   r6  r   rQ  r   "CUSPARSE_SPARSETODENSE_ALG_DEFAULTr   r   sparseToDense_bufferSizer   r   r   r|   r}   r   rx   ro   r   r   )	r1   r   r.   r   desc_outr  r   r   r   r   r   r   ro     s.   




ro   c                 C   s  t dstd|du rd}n|du rd}n|dvr"td| d	tjj| r*n6tjj| rT|dkr;| j} d}n|dkrE| j} d}n|d
krP| 	 j} d}| }ntjj
| r\ntd| jseJ |jdkrsd}|dd}n|jdkr{d}ntd| jd | jd   kr|jd kstd td| j}|jdvrtd|||jkrtd|du rtj}n|du rtj}ntd||du rtj}	n|du rtj}	ntd||dkrtj}
n|dkrtj}
n|jdv rtj}
ntj}
|jrtj}n|jrt dk rtd|j}tj}ntd| j\}}|tjkr/|j\}}n|j\}}||f}tj|| jdd}t ! }t"#| }t$#|}t$#|}t% }t&j'||jdj(}t)*|j}tj+}zb|,tj-| |,tj.|	 t/||
||j0|j1|j1|j1|||
}tj2|tj3d}t4||
||j0|j1|j1|j1||||j0j5 t6||
||j0|j1|j1|j1||||j0j5 |r|d}|W t7| S t7| w )a  Solves a sparse triangular linear system op(a) * x = alpha * op(b).

    Args:
        a (cupyx.scipy.sparse.csr_matrix or cupyx.scipy.sparse.coo_matrix):
            Sparse matrix with dimension ``(M, M)``.
        b (cupy.ndarray): Dense matrix with dimension ``(M, K)``.
        alpha (float or complex): Coefficient.
        lower (bool):
            True: ``a`` is lower triangle matrix.
            False: ``a`` is upper triangle matrix.
        unit_diag (bool):
            True: diagonal part of ``a`` has unit elements.
            False: diagonal part of ``a`` has non-unit elements.
        transa (bool or str): True, False, 'N', 'T' or 'H'.
            'N' or False: op(a) == ``a``.
            'T' or True: op(a) == ``a.T``.
            'H': op(a) == ``a.conj().T``.
    rq   zspsm is not available.Frn  TrX  NTHzUnknown transa (actual: )ro  z'a must be CSR, CSC or COO sparse matrixr   r   r   re  r   r   r   rj  rf  rg  rh  rp  i-  zb must be F-contiguous.rq  r?   r   r-   )8r   r   rx   r   r   r   rr  rs  rX  conjisspmatrix_coor   r   reshaper   r.   r   rF   rw   r   ru  rv  rw  rx  r<   r;   r{  r|  r}  r   r   r   r   r   r6  r   rQ  spSM_createDescrr6   r   r   r   r   CUSPARSE_SPSM_ALG_DEFAULTrE  CUSPARSE_SPMAT_FILL_MODECUSPARSE_SPMAT_DIAG_TYPEspSM_bufferSizer   r   r   r   spSM_analysisr   
spSM_solvespSM_destroyDescr)r   r   r   r  r  r   is_b_vectorr.   r$   r'   r   r   r   r   r   c_shaperC   r   mat_amat_bmat_c
spsm_descrrB  r  r   r   r   r   r   rq   3  s   



$









rq   c                 C   s2  t dstd| j|j  krdksJ  J t| tjjjs)td	t
| t|tjjjs:td	t
|| js?J |jsDJ | jd |jd krRtd| j\}}|j\}}t| |\} }||f}tjjj|| jd}t }	t| }
t|}t|}t }tj}tj}tj||jdj}tjd|jdj}t|j}tj}d}t|	|||j|
j|j|j|j|||d|}t !|t j"}t|	|||j|
j|j|j|j|||||jj# t$|	|||j|
j|j|j|j|||d|}t !|t j"}t$|	|||j|
j|j|j|j|||||jj# tjdd	d}tjdd	d}tjdd	d}t%|j|jj|jj|jj |d t&|ksDJ |d t&|ksOJ t&|}|j'}t !|d
}t !||j}t(|j|jj#|jj#|jj# t)|	|||j|
j|j|j|j||| tjjj|||f|d}t*| |S )a+  Matrix-matrix product for CSR-matrix.

    math::
       C = alpha * A * B

    Args:
        a (cupyx.scipy.sparse.csr_matrix): Sparse matrix A.
        b (cupyx.scipy.sparse.csr_matrix): Sparse matrix B.
        alpha (scalar): Coefficient

    Returns:
        cupyx.scipy.sparse.csr_matrix

    rp   zspgemm is not available.r   r   r   r   r   r-   r+  r   r   )+r   r   r   rs   r   r   r   r   rF   rw   r   r   r   rx   r:   r.   r   r   r6  r   r   spGEMM_createDescrr<   r6   r   r   r   r   CUSPARSE_SPGEMM_DEFAULTspGEMM_workEstimationr   r   r   r   r   r   spGEMM_computer  r   r   csrSetPointersspGEMM_copyspGEMM_destroyDescr)r   r   r   r   r   r   r   r  rC   r   r  r  r  spgemm_descrr   r   r   rB  r  r   
buff1_sizebuff1
buff2_sizebuff2
c_num_rows
c_num_colsr   r   r   r   r   r   r   rp     s    








rp   )Nr   r   Fr
   )Nr   r   T)Nr   r   FF)r   r   )FF)Nr   r   )r  )Nr   r   FF)r   TFFTF)F)r&  )r   TFFr  )N	functoolsr4   numpyr6   platformru   cupyr   cupy_backends.cuda.apir   r   r   r|   cupy_backends.cuda.libsr   r   
cupy._corer   	cupy.cudar   r   r   r  r   cupyx.scipy.sparser   objectr	   r:   r>   rK   r~   infr   r{   memoizer   r   r   rL   r   rO   rP   rQ   rR   rS   rU   rV   r^   r_   r`   ra   rb   rc   r  rd   re   rg   r  rf   rh   ri   rj   rk   r/  r0  r6  r   r   rQ  rY   r]   rl   rm   rn   ro   rq   rp   r   r   r   r   <module>   sF   !	'
	
%


2

D
8
?
@
E
E
i
  &
&1*.$

CL
 

G
H
( #