o
    0 is                     @   s  d dl mZ d dl mZ d dlmZ dd ZG dd dejZdefd	d
Z	deddfddZ
dededdfddZdededdfddZdededdfddZede Zede Zede ZedgdddZedgdd Zed gd!d" Zed#gd$d% Zed&gdd'd(Zedgdd)d*Zed+g	dd,d-Zed+g	dd.d/Zed0gd1d2 Zed3gd4d5 Zed6gd7d8 Zed+g	dd9d:Zed+g	dd;d<Zed=g	dd>d?Zed@gddAdBZed@gddCdDZ edgdEdF Z!G dGdH dHej"Z#edIgddJdKZ$G dLdM dMej"Z%edNgddOdPZ&edQgddRdSZ'edTgddUdVZ(edTg	ddWdXZ)edYgdZd[ Z*edYgd\d] Z+ed^gd_d` Z,ed^gdadb Z-edcgddde Z.edcgdfdg Z/edhgdidj Z0edkgddldmZ1edng	ddodpZ2edng	ddqdrZ3edng	ddsdtZ4edng	ddudvZ5edng	ddwdxZ6edng	ddydzZ7edng	dd{d|Z8edng	dd}d~Z9ed@gdddZ:ed@g	dddZ;ed@gdddZ<ed@g	dddZ=edgdd Z>edgdddZ?edg	dddZ@edgdd ZAdS )    )_internal_types)_cuda_types)Datac                    s    fdd}|S )Nc                    s   G  fdddt j}| S )Nc                       s   e Zd Z fddZdS )z7_wrap_thrust_func.<locals>.wrapper.<locals>.FuncWrapperc                    sz   D ]} j d| d q j d  j d d j _ fdd|D } fdd	D } g|R i |S )
Nz
#include <>z$#include <thrust/execution_policy.h>z#include <thrust/functional.h>Znvccc                    s   g | ]}t | qS  _Datainit.0a)envr   \/home/app/PaddleOCR-VL-test/.venv_paddleocr/lib/python3.10/site-packages/cupyx/jit/thrust.py
<listcomp>   s    zP_wrap_thrust_func.<locals>.wrapper.<locals>.FuncWrapper.call.<locals>.<listcomp>c                    s   i | ]}|t |  qS r   r   )r   kr   kwargsr   r   
<dictcomp>   s    zP_wrap_thrust_func.<locals>.wrapper.<locals>.FuncWrapper.call.<locals>.<dictcomp>)	generatedZadd_codebackend)selfr   argsr   headerZ	data_argsZdata_kwargsfuncheadersr   r   call	   s   z<_wrap_thrust_func.<locals>.wrapper.<locals>.FuncWrapper.callN)__name__
__module____qualname__r   r   r   r   r   FuncWrapper   s    r    )r   ZBuiltinFunc)r   r    r   )r   r   wrapper   s   
z"_wrap_thrust_func.<locals>.wrapperr   )r   r"   r   r!   r   _wrap_thrust_func   s   r#   c                   @   s   e Zd ZdS )_ExecPolicyTypeN)r   r   r   r   r   r   r   r$      s    r$   exec_policyc                 C   s    t | jtst| j dd S )Nz must be execution policy type)
isinstancectyper$   	TypeErrorcode)r%   r   r   r   _assert_exec_policy_type   s   r*   r   returnNc                 C   s,   t | jtjstd| j d| j dd S )N`z` must be of pointer type: `)r&   r'   r   PointerBaser(   r)   )r   r   r   r   _assert_pointer_type   s   r.   bc              
   C   s:   | j |j krtd| j d|j d| j  d|j  d	d S )Nr,   ` and `` must be of the same type: `` != `)r'   r(   r)   r   r/   r   r   r   _assert_same_type%   s   r4   c              
   C   sR   t |  t | | jj|jjkr'td| j d|j d| jj d|jj d	d S )Nr,   r0   z%` must be of the same pointer type: `r2   )r.   r'   
child_typer(   r)   typer3   r   r   r   _assert_same_pointer_type,   s   r7   c              
   C   sF   t |  | jj|jkr!td| j d|j d| jj d|j d	d S )Nz`*r0   r1   r2   r,   )r.   r'   r5   r(   r)   r3   r   r   r   _assert_pointer_of6   s   r8   zthrust::hostzthrust::devicezthrust::seqzthrust/adjacent_difference.hc                 C   `   t | t|| t|| |durtd||||g}ddd |D }td| d|jS )z3Computes the differences of adjacent elements.
    N!binary_op option is not supported, c                 S      g | ]}|j qS r   r)   r
   r   r   r   r   M       z'adjacent_difference.<locals>.<listcomp>zthrust::adjacent_difference()r*   r4   r7   NotImplementedErrorjoinr   r'   r   r%   firstlastresult	binary_opr   paramsr   r   r   adjacent_differenceC      

rI   zthrust/binary_search.hc                 G   s"  t | t| t|| dt|  krdkr4n n|d }t|dkr)|d nd}t|| tj}n;dt|  kr@dkrkn t	d|d }|d }	|d }
t|dkr[|d nd}t|| t||	 |
j}nt	d|durwt
d|||g|}d	d
d |D }td| d|S );Attempts to find the element value with binary search.
          r   N      z0Invalid number of inputs of thrust.binary_searchcomp option is not supportedr;   c                 S   r<   r   r=   r
   r   r   r   r   p   r>   z!binary_search.<locals>.<listcomp>zthrust::binary_search(r?   )r*   r.   r4   lenr8   r   bool_r7   r'   r(   rA   rB   r   r   r%   rD   rE   r   valuecompZresult_ctypeZvalue_firstZ
value_lastrF   rH   r   r   r   binary_searchU   .   

	

rV   zthrust/copy.hc                 C   sP   t | t|| t|| ||||g}ddd |D }td| d|jS )zCopies the elements.
    r;   c                 S   r<   r   r=   r
   r   r   r   r   }   r>   zcopy.<locals>.<listcomp>zthrust::copy(r?   )r*   r4   r7   rB   r   r'   r   r%   rD   rE   rF   r   rH   r   r   r   copyt   s   

rY   zthrust/count.hc                 C   sf   t | t|jtjstd|j|jkrtd||||g}ddd |D }td| dtjS )zMCounts the number of elements in [first, last) that equals to ``value``.
    z`first` must be of pointer typez+`first` and `last` must be of the same typer;   c                 S   r<   r   r=   r
   r   r   r   r      r>   zcount.<locals>.<listcomp>zthrust::count(r?   )	r*   r&   r'   r   r-   r(   rB   r   Zint32r   r%   rD   rE   rT   r   rH   r   r   r   count   s   r[   zthrust/equal.hc                 C   s`   t | t|| t|| |durtd||||g}ddd |D }td| dtjS )z2Returns true if the two ranges are identical.
    N#binary_pred option is not supportedr;   c                 S   r<   r   r=   r
   r   r   r   r      r>   zequal.<locals>.<listcomp>zthrust::equal(r?   )r*   r4   r7   rA   rB   r   r   rR   )r   r%   first1last1first2binary_predr   rH   r   r   r   equal   rJ   ra   c                 C   sj   t | t| t|| |durtd||||g}ddd |D }td| dt|j|jgS )z<Attempts to find the element value in an ordered range.
    NrP   r;   c                 S   r<   r   r=   r
   r   r   r   r      r>   zequal_range.<locals>.<listcomp>zthrust::equal_range(r?   	r*   r.   r4   rA   rB   r   r   Tupler'   )r   r%   rD   rE   rT   rU   r   rH   r   r   r   equal_range   s   

rd   zthrust/scan.hc           	      C   sr   t | t|| t|| |durtd||||g}|dur%|| ddd |D }td| d|jS )z0Computes an exclusive prefix sum operation.
    Nr:   r;   c                 S   r<   r   r=   r
   r   r   r   r      r>   z"exclusive_scan.<locals>.<listcomp>zthrust::exclusive_scan(r?   )r*   r4   r7   rA   appendrB   r   r'   )	r   r%   rD   rE   rF   r	   rG   r   rH   r   r   r   exclusive_scan   s   


rf   c	                 C   s   t | t|| t|| |durtd|durtd|||||g}	|dur.|	| ddd |	D }
td|
 d|jS )	zaComputes an exclusive prefix sum operation by key.
    _assert_exec_policy_type(exec_policy)
    Nr\   r:   r;   c                 S   r<   r   r=   r
   r   r   r   r      r>   z)exclusive_scan_by_key.<locals>.<listcomp>zthrust::exclusive_scan_by_key(r?   )r.   r4   r7   rA   re   rB   r   r'   )r   r%   r]   r^   r_   rF   r	   r`   rG   r   rH   r   r   r   exclusive_scan_by_key   s   


rg   zthrust/fill.hc                 C   sF   t | t|| ||||g}ddd |D }td| dtjS )z5Assigns the value to every element in the range.
    r;   c                 S   r<   r   r=   r
   r   r   r   r      r>   zfill.<locals>.<listcomp>zthrust::fill(r?   )r*   r4   rB   r   r   voidrZ   r   r   r   fill   s
   
ri   zthrust/find.hc                 C   N   t | t| t|| ||||g}ddd |D }td| d|jS )z>Finds the first iterator whose value equals to ``value``.
    r;   c                 S   r<   r   r=   r
   r   r   r   r      r>   zfind.<locals>.<listcomp>zthrust::find(r?   r*   r.   r4   rB   r   r'   rZ   r   r   r   find   s   
rl   zthrust/gather.hc                 C   sZ   t | t| t|| t|| |||||g}ddd |D }td| d|jS )zFCopies elements from source into destination  according to a map.
    r;   c                 S   r<   r   r=   r
   r   r   r   r     r>   zgather.<locals>.<listcomp>zthrust::gather(r?   )r*   r.   r4   r7   rB   r   r'   )r   r%   Z	map_firstZmap_lastZinput_firstrF   r   rH   r   r   r   gather      

rm   c                 C   r9   )z0Computes an inclusive prefix sum operation.
    Nr:   r;   c                 S   r<   r   r=   r
   r   r   r   r     r>   z"inclusive_scan.<locals>.<listcomp>zthrust::inclusive_scan(r?   r@   rC   r   r   r   inclusive_scan  s   

ro   c           
      C   sz   t | t| t|| t|| |durtd|dur"td|||||g}ddd |D }	td|	 d|jS )	z7Computes an inclusive prefix sum operation by key.
    Nr\   r:   r;   c                 S   r<   r   r=   r
   r   r   r   r   ,  r>   z)inclusive_scan_by_key.<locals>.<listcomp>zthrust::inclusive_scan_by_key(r?   )r*   r.   r4   r7   rA   rB   r   r'   )
r   r%   r]   r^   r_   rF   r`   rG   r   rH   r   r   r   inclusive_scan_by_key  s   

rp   zthrust/inner_product.hc           
      C   sr   t | t|| t|| |durtd|durtd|||||g}ddd |D }	td|	 d|jS )	z/Calculates an inner product of the ranges.
    Nz"binary_op1 option is not supportedz"binary_op2 option is not supportedr;   c                 S   r<   r   r=   r
   r   r   r   r   >  r>   z!inner_product.<locals>.<listcomp>zthrust::inner_product(r?   r@   )
r   r%   r]   r^   r_   r	   Z
binary_op1Z
binary_op2r   rH   r   r   r   inner_product0  s   

rq   zthrust/sort.hc                 C   \   t | t| t|| |durtd|||g}ddd |D }td| dtjS )z<Returns true if the range is sorted in ascending order.
    NrP   r;   c                 S   r<   r   r=   r
   r   r   r   r   O  r>   zis_sorted.<locals>.<listcomp>zthrust::is_sorted(r?   )r*   r.   r4   rA   rB   r   r   rR   r   r%   rD   rE   rU   r   rH   r   r   r   	is_sortedE     

rt   c                 C   \   t | t| t|| |durtd|||g}ddd |D }td| d|jS )z=Returns the last iterator for which the range is sorted.
    NrP   r;   c                 S   r<   r   r=   r
   r   r   r   r   ]  r>   z#is_sorted_until.<locals>.<listcomp>zthrust::is_sorted_until(r?   r*   r.   r4   rA   rB   r   r'   rs   r   r   r   is_sorted_untilS  ru   rx   c                 G   "  t | t| t|| dt|  krdkr4n n|d }t|dkr)|d nd}t|| |j}n;dt|  kr@dkrkn td|d }|d }	|d }
t|dkr[|d nd}t|| t||	 |
j}ntd|durwtd|||g|}d		d
d |D }t
d| d|S )rK   rL   rM   r   NrN   rO   z.Invalid number of inputs of thrust.lower_boundrP   r;   c                 S   r<   r   r=   r
   r   r   r   r   |  r>   zlower_bound.<locals>.<listcomp>zthrust::lower_bound(r?   r*   r.   r4   rQ   r8   r'   r7   r(   rA   rB   r   rS   r   r   r   lower_bounda  rW   r{   c                   @      e Zd ZdefddZdS )_ConstantIteratorr+   c                 C      | j }d| dS )Nzthrust::constant_iterator<r   r5   r   
value_typer   r   r   __str__     z_ConstantIterator.__str__Nr   r   r   strr   r   r   r   r   r}         r}   z#thrust/iterator/constant_iterator.hc                 C   B   |durt d|g}ddd |D }td| dt|jS )3Finds the first positions whose values differ.
    Nindex_type is not supportedr;   c                 S   r<   r   r=   r
   r   r   r   r     r>   z*make_constant_iterator.<locals>.<listcomp>zthrust::make_constant_iterator(r?   )rA   rB   r   r}   r'   r   xir   rH   r   r   r   make_constant_iterator     
r   c                   @   r|   )_CountingIteratorr+   c                 C   r~   )Nzthrust::counting_iterator<r   r   r   r   r   r   r     r   z_CountingIterator.__str__Nr   r   r   r   r   r     r   r   z#thrust/iterator/counting_iterator.hc                 C   r   )r   Nr   r;   c                 S   r<   r   r=   r
   r   r   r   r     r>   z*make_counting_iterator.<locals>.<listcomp>zthrust::make_counting_iterator(r?   )rA   rB   r   r   r'   r   r   r   r   make_counting_iterator  r   r   zthrust/mismatch.hc                 C   sl   t | t|| t|| |durtd||||g}ddd |D }td| dt|j|jgS )r   Nzpred option is not supportedr;   c                 S   r<   r   r=   r
   r   r   r   r     r>   zmismatch.<locals>.<listcomp>zthrust::mismatch(r?   )	r*   r4   r7   rA   rB   r   r   rc   r'   )r   r%   r]   r^   r_   predr   rH   r   r   r   mismatch  s   


r   zthrust/reduce.hc           	      C   s|   t | t| t|| |||g}|dur|| |j}n|jj}|dur+tdddd |D }td| d|S )z!Generalization of summation.
    Nr:   r;   c                 S   r<   r   r=   r
   r   r   r   r     r>   zreduce.<locals>.<listcomp>zthrust::reduce(r?   )	r*   r.   r4   re   r'   r5   rA   rB   r   )	r   r%   rD   rE   r	   rG   r   return_typerH   r   r   r   reduce  s   


r   c	                 C   s   t | t| t|| t| t| t| ||||||g}	|dur)td|dur1tdddd |	D }
td|
 dt|j|jgS )	z1Generalization of reduce to key-value pairs.
    Nr\   r:   r;   c                 S   r<   r   r=   r
   r   r   r   r     r>   z!reduce_by_key.<locals>.<listcomp>zthrust::reduce_by_key(r?   rb   )r   r%   
keys_first	keys_lastvalues_firstZkeys_outputZvalues_outputr`   rG   r   rH   r   r   r   reduce_by_key  s$   

r   zthrust/remove.hc                 C   rj   )ARemoves from the range all elements that are equal to value.
    r;   c                 S   r<   r   r=   r
   r   r   r   r     r>   zremove.<locals>.<listcomp>zthrust::remove(r?   rk   rZ   r   r   r   remove  s   
r   c                 C   sX   t | t| t|| t| |||||g}ddd |D }td| d|jS )r   r;   c                 S   r<   r   r=   r
   r   r   r   r   
  r>   zremove_copy.<locals>.<listcomp>zthrust::remove_copy(r?   rk   )r   r%   rD   rE   rF   rT   r   rH   r   r   r   remove_copy  s   
r   zthrust/replace.hc                 C   sZ   t | t| t|| t|| |||||g}ddd |D }td| dtjS )KReplaces every element in the range equal to old_value with new_value.
    r;   c                 S   r<   r   r=   r
   r   r   r   r     r>   zreplace.<locals>.<listcomp>zthrust::replace(r?   r*   r.   r4   rB   r   r   rh   )r   r%   rD   rE   	old_value	new_valuer   rH   r   r   r   replace  rn   r   c           	      C   sd   t | t| t|| t| t|| ||||||g}ddd |D }td| d|jS )r   r;   c                 S   r<   r   r=   r
   r   r   r   r   )  r>   z replace_copy.<locals>.<listcomp>zthrust::replace_copy(r?   rk   )	r   r%   rD   rE   rF   r   r   r   rH   r   r   r   replace_copy  s   

r   zthrust/reverse.hc                 C   sL   t | t| t|| |||g}ddd |D }td| dtjS )Reverses a range.
    r;   c                 S   r<   r   r=   r
   r   r   r   r   9  r>   zreverse.<locals>.<listcomp>zthrust::reverse(r?   r   )r   r%   rD   rE   r   rH   r   r   r   reverse1  s   

r   c                 C   V   t | t| t|| t| ||||g}ddd |D }td| d|jS )r   r;   c                 S   r<   r   r=   r
   r   r   r   r   F  r>   z reverse_copy.<locals>.<listcomp>zthrust::reverse_copy(r?   rk   rX   r   r   r   reverse_copy=  s   
r   zthrust/scatter.hc                 C   s`   t | t| t|| t| t| |||||g}ddd |D }td| dtjS )zMCopies elements from source range into an output range according to map.
    r;   c                 S   r<   r   r=   r
   r   r   r   r   T  r>   zscatter.<locals>.<listcomp>zthrust::scatter(r?   r   )r   r%   rD   rE   maprF   r   rH   r   r   r   scatterJ  s   
r   zthrust/sequence.hc                 C   sz   t | t| t|| |||g}|dur|| |dur)t|| || ddd |D }td| dtjS )z0Fills the range with a sequence of numbers.
    Nr;   c                 S   r<   r   r=   r
   r   r   r   r   h  r>   zsequence.<locals>.<listcomp>zthrust::sequence(r?   )r*   r.   r4   re   rB   r   r   rh   )r   r%   rD   rE   r	   stepr   rH   r   r   r   sequence[  s   




r   zthrust/set_operations.hc           
      C   l   t | t|| t|| t| ||||||g}|dur"tdddd |D }	td|	 d|jS )zKConstructs a sorted range that is the set difference of sorted inputs.
    NrP   r;   c                 S   r<   r   r=   r
   r   r   r   r   y  r>   z"set_difference.<locals>.<listcomp>zthrust::set_difference(r?   r*   r4   r.   rA   rB   r   r'   
r   r%   r]   r^   r_   Zlast2rF   rU   r   rH   r   r   r   set_differencel     

r   c              	   C      t | t|| t|| t| t| t| t|	 |||||||||	g	}|
dur1tdddd |D }td| dt|j|	jgS )z>Constructs the key-value set difference of sorted inputs.
    NrP   r;   c                 S   r<   r   r=   r
   r   r   r   r     r>   z)set_difference_by_key.<locals>.<listcomp>zthrust::set_difference_by_key(r?   	r*   r4   r.   rA   rB   r   r   rc   r'   r   r%   keys_first1
keys_last1keys_first2
keys_last2values_first1Zvalues_first2keys_resultvalues_resultrU   r   rH   r   r   r   set_difference_by_key}  "   



r   c           
      C   r   )zMConstructs a sorted range that is the set intersection of sorted inputs.
    NrP   r;   c                 S   r<   r   r=   r
   r   r   r   r     r>   z$set_intersection.<locals>.<listcomp>zthrust::set_intersection(r?   r   r   r   r   r   set_intersection  r   r   c
                 C   s   t | t|| t|| t| t| t| ||||||||g}
|	dur,tdddd |
D }td| dt|j|jgS )z@Constructs the key-value set intersection of sorted inputs.
    NrP   r;   c                 S   r<   r   r=   r
   r   r   r   r     r>   z+set_intersection_by_key.<locals>.<listcomp>z thrust::set_intersection_by_key(r?   r   )r   r%   r   r   r   r   r   r   r   rU   r   rH   r   r   r   set_intersection_by_key  s    



r   c           
      C   r   )z@Constructs a sorted range that is the symmetric difference.
    NrP   r;   c                 S   r<   r   r=   r
   r   r   r   r     r>   z,set_symmetric_difference.<locals>.<listcomp>z!thrust::set_symmetric_difference(r?   r   r   r   r   r   set_symmetric_difference  r   r   c              	   C   r   )zDConstructs the key-value symmetric difference of sorted inputs.
    NrP   r;   c                 S   r<   r   r=   r
   r   r   r   r     r>   z3set_symmetric_difference_by_key.<locals>.<listcomp>z(thrust::set_symmetric_difference_by_key(r?   r   r   r   r   r   set_symmetric_difference_by_key  r   r   c           
      C   r   )zFConstructs a sorted range that is the set union of sorted inputs.
    NrP   r;   c                 S   r<   r   r=   r
   r   r   r   r     r>   zset_union.<locals>.<listcomp>zthrust::set_union(r?   r   r   r   r   r   	set_union  r   r   c              	   C   r   )z5Constructs the key-value union of sorted inputs.
    NrP   r;   c                 S   r<   r   r=   r
   r   r   r   r     r>   z$set_union_by_key.<locals>.<listcomp>zthrust::set_union_by_key(r?   r   r   r   r   r   set_union_by_key  r   r   c                 C   rr   )>Sorts the elements in [first, last) into ascending order.
    NrP   r;   c                 S   r<   r   r=   r
   r   r   r   r   "  r>   zsort.<locals>.<listcomp>zthrust::sort(r?   r*   r.   r4   rA   rB   r   r   rh   rs   r   r   r   sort     

r   c                 C   f   t | t| t|| t| |durtd||||g}ddd |D }td| dtjS )Performs key-value sort.
    NrP   r;   c                 S   r<   r   r=   r
   r   r   r   r   3  r>   zsort_by_key.<locals>.<listcomp>zthrust::sort_by_key(r?   r   r   r%   r   r   r   rU   r   rH   r   r   r   sort_by_key&     
r   c                 C   rr   )r   NrP   r;   c                 S   r<   r   r=   r
   r   r   r   r   F  r>   zstable_sort.<locals>.<listcomp>zthrust::stable_sort(r?   r   rs   r   r   r   stable_sort;  r   r   c                 C   r   )r   NrP   r;   c                 S   r<   r   r=   r
   r   r   r   r   W  r>   z&stable_sort_by_key.<locals>.<listcomp>zthrust::stable_sort_by_key(r?   r   r   r   r   r   stable_sort_by_keyJ  r   r   zthrust/swap.hc                 C   r   )z-Swaps each of the elements in the range.
    r;   c                 S   r<   r   r=   r
   r   r   r   r   e  r>   zswap_ranges.<locals>.<listcomp>zthrust::swap_ranges(r?   rk   )r   r%   r]   r^   r_   r   rH   r   r   r   swap_ranges[  s   
r   zthrust/unique.hc                 C   rv   )z4Removes all but the first element of the group.
    Nr\   r;   c                 S   r<   r   r=   r
   r   r   r   r     r>   zunique.<locals>.<listcomp>zthrust::unique(r?   rw   )r   r%   rD   rE   r`   r   rH   r   r   r   uniqueu  ru   r   c                 C   sr   t | t| t|| t| ||||g}|durtdddd |D }td| dt|j|jgS )zUniques key-value pairs.
    Nr\   r;   c                 S   r<   r   r=   r
   r   r   r   r     r>   z!unique_by_key.<locals>.<listcomp>zthrust::unique_by_key(r?   rb   )r   r%   r   r   r   r`   r   rH   r   r   r   unique_by_key  s   

r   c                 G   ry   )rK   rL   rM   r   NrN   rO   z.Invalid number of inputs of thrust.upper_boundrP   r;   c                 S   r<   r   r=   r
   r   r   r   r     r>   zupper_bound.<locals>.<listcomp>zthrust::upper_bound(r?   rz   rS   r   r   r   upper_bound  rW   r   )N)NN)NNN)BZ	cupyx.jitr   r   Zcupyx.jit._internal_typesr   r   r#   ZTypeBaser$   r*   r.   r4   r7   r8   hostZdeviceseqrI   rV   rY   r[   ra   rd   rf   rg   ri   rl   rm   ro   rp   rq   rt   rx   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   <module>   s    















