U
    9%e߂                     @   sd   d Z ddlZddlmZ eddZdZdZdZed	d
Z	eddZ
dd Zdd Zdd ZdS )z
Timsort implementation.  Mostly adapted from CPython's listobject.c.

For more information, see listsort.txt in CPython's source tree.
    N)typesTimsortImplementation)compile	count_run
binarysortgallop_leftgallop_right
merge_initmerge_append	merge_popmerge_compute_minrunmerge_lomerge_himerge_atmerge_force_collapsemerge_collapserun_timsortrun_timsort_with_valuesU         
MergeState)
min_gallopkeysvaluespendingnMergeRun)startsizec                    s  | t jd| dd | fdd| fdd| dd	 
| d
d | fdd| fdd	| dd | fdd| fdd| fdd| fdd| dd | fdd| fddd  |  	fd!d"|  	f	d#d$| fd%d&| fd'd(| fd)d*| fd+d,| 
fd-d.| fd/d0}| fd1d2}t| 
||S )3Nr   c                 S   s   || k	S N r   r   r!   r!   Q/var/www/html/Darija-Ai-API/env/lib/python3.8/site-packages/numba/misc/timsort.py
has_values?   s    z%make_timsort_impl.<locals>.has_valuesc                    sH   t t| d d t}| |}|}tgt }t t|||S )z?
        Initialize a MergeState for a non-keyed sort.
              minlenMERGESTATE_TEMP_SIZEr   MAX_MERGE_PENDINGr   
MIN_GALLOP)r   	temp_size	temp_keystemp_valuesr   intpmake_temp_areazeror!   r#   r	   C   s
    
z%make_timsort_impl.<locals>.merge_initc                    sN   t t| d d t}| |}||}tgt }t t|||S )z;
        Initialize a MergeState for a keyed sort.
        r%   r&   r'   )r   r   r-   r.   r/   r   r0   r!   r#   merge_init_with_valuesN   s
    

z1make_timsort_impl.<locals>.merge_init_with_valuesc                 S   s8   | j }|tk st|| j|< t| j| j| j| j|d S )z2
        Append a run on the merge stack.
        r&   )r   r+   AssertionErrorr   r   r   r   r   )msrunr   r!   r!   r#   r
   Y   s    
z'make_timsort_impl.<locals>.merge_appendc                 S   s   t | j| j| j| j| jd S )z7
        Pop the top run from the merge stack.
        r&   )r   r   r   r   r   r   )r6   r!   r!   r#   r   c   s    z$make_timsort_impl.<locals>.merge_popc                    sj   t | j}||kr| S ||k r(|d> }q| j|} | j| jrP| j|}n|}t| j||| j| jS )zJ
        Ensure enough temp memory for 'need' items is available.
        r&   )r)   r   r   r   r   r   r   )r6   ZneedZallocedr.   r/   )r$   r2   r!   r#   merge_getmemj   s    

z'make_timsort_impl.<locals>.merge_getmemc                    s   t  || j| j| j| jS )z5
        Modify the MergeState's min_gallop.
        )r   r   r   r   r   )r6   Z
new_gallop)r1   r!   r#   merge_adjust_gallop~   s    z.make_timsort_impl.<locals>.merge_adjust_gallopc                 S   s   | |k S )z
        Trivial comparison function between two keys.  This is factored out to
        make it clear where comparisons occur.
        r!   )abr!   r!   r#   LT   s    zmake_timsort_impl.<locals>.LTc                    s   ||kr||kst | |}||kr.|d7 }||k r| | }|}|}||k r|||| d?  }	 || |	 rr|	}qF|	d }qFt||dD ]}	| |	d  | |	< q|| |< |r|| }
t||dD ]}	||	d  ||	< q|
||< |d7 }q.dS )a  
        binarysort is the best method for sorting small arrays: it does
        few compares, but can do data movement quadratic in the number of
        elements.
        [lo, hi) is a contiguous slice of a list, and is sorted via
        binary insertion.  This sort is stable.
        On entry, must have lo <= start <= hi, and that [lo, start) is already
        sorted (pass start == lo if you don't know!).
        r&   Nr5   range)r   r   lohir   _has_valuesZpivotlrpZ	pivot_val)r<   r$   r!   r#   r      s,    

z%make_timsort_impl.<locals>.binarysortc                    s   ||k st |d |krdS  | |d  | | rxt|d |D ]*} | | | |d  s@|| df  S q@|| dfS t|d |D ]*} | | | |d  r|| df  S q|| dfS dS )a  
        Return the length of the run beginning at lo, in the slice [lo, hi).
        lo < hi is required on entry.  "A run" is the longest ascending sequence, with

            lo[0] <= lo[1] <= lo[2] <= ...

        or the longest descending sequence, with

            lo[0] > lo[1] > lo[2] > ...

        A tuple (length, descending) is returned, where boolean *descending*
        is set to 0 in the former case, or to 1 in the latter.
        For its intended use in a stable mergesort, the strictness of the defn of
        "descending" is needed so that the caller can safely reverse a descending
        sequence without violating stability (strict > ensures there are no equal
        elements to get out of order).
        r&   )r&   Fr%   TFNr>   )r   r@   rA   kr<   r!   r#   r      s    z$make_timsort_impl.<locals>.count_runc           
         st  ||kst ||kr||k s t || }d}d} || | r|| }||k r |||  | r|}|d> d }|dkr|}qFqqF||kr|}||7 }||7 }nf|| d }||k r |||  | rqq|}|d> d }|dkr|}q||kr|}|| ||  }}|d |kr(||k r(||ks,t |d7 }||k rp||| d?  }	 ||	 | rh|	d }n|	}q4|S )a  
        Locate the proper position of key in a sorted vector; if the vector contains
        an element equal to key, return the position immediately to the left of
        the leftmost equal element.  [gallop_right() does the same except returns
        the position to the right of the rightmost equal element (if any).]

        "a" is a sorted vector with stop elements, starting at a[start].
        stop must be > start.

        "hint" is an index at which to begin the search, start <= hint < stop.
        The closer hint is to the final result, the faster this runs.

        The return value is the int k in start..stop such that

            a[k-1] < key <= a[k]

        pretending that a[start-1] is minus infinity and a[stop] is plus infinity.
        IOW, key belongs at index k; or, IOW, the first k elements of a should
        precede key, and the last stop-start-k should follow key.

        See listsort.txt for info on the method.
        r   r&   r5   
keyr:   r   stophintr   ZlastofsZofsZmaxofsmrG   r!   r#   r      sJ    
&

z&make_timsort_impl.<locals>.gallop_leftc           
         st  ||kst ||kr||k s t || }d}d} | || r|| d }||k r | |||  r|}|d> d }|dkr|}qJqqJ||kr|}|| ||  }}n`|| }||k r | |||  rqq|}|d> d }|dkr|}q||kr|}||7 }||7 }|d |kr(||k r(||ks,t |d7 }||k rp||| d?  }	 | ||	 rd|	}n|	d }q4|S )a  
        Exactly like gallop_left(), except that if key already exists in a[start:stop],
        finds the position immediately to the right of the rightmost equal value.

        The return value is the int k in start..stop such that

            a[k-1] <= key < a[k]

        The code duplication is massive, but this is enough different given that
        we're sticking to "<" comparisons that it's much harder to follow if
        written as one routine with yet another "left or right?" flag.
        r   r&   rH   rI   rG   r!   r#   r   ;  sJ    &
z'make_timsort_impl.<locals>.gallop_rightc                 S   s6   d}| dkst | dkr.|| d@ O }| dL } q| | S )a  
        Compute a good value for the minimum run length; natural runs shorter
        than this are boosted artificially via binary insertion.

        If n < 64, return n (it's too small to bother with fancy stuff).
        Else if n is an exact power of 2, return 32.
        Else return an int k, 32 <= k <= 64, such that n/k is close to, but
        strictly less than, an exact power of 2.

        See listsort.txt for more info.
        r   @   r&   rH   )r   rD   r!   r!   r#   r     s    
z/make_timsort_impl.<locals>.merge_compute_minrunc                    sj   |dkst |dkst t|D ]}|||  | || < q  ||rft|D ]}|||  ||| < qLdS )z#
        Upwards memcpy().
        r   Nr>   Z	dest_keysZdest_valuesZ
dest_startZsrc_keysZ
src_valuesZ	src_startZnitemsir$   r!   r#   sortslice_copy  s    
z)make_timsort_impl.<locals>.sortslice_copyc                    sj   |dkst |dkst t|D ]}|||  | || < q  ||rft|D ]}|||  ||| < qLdS )z%
        Downwards memcpy().
        r   Nr>   rO   rQ   r!   r#   sortslice_copy_down  s    
z.make_timsort_impl.<locals>.sortslice_copy_downr&   c                    sL  |dkr|dkr||kst ||| ks,t | |} | j| jd|||| | j}| j}|}	|}
|}d}||}| j}|dkr|dkrd}d}|	| || r|	| ||< |r|
| ||< |d7 }|d7 }|d8 }|dkrqd|d7 }d}||krbqdq|| ||< |r$|| ||< |d7 }|d7 }|d8 }|dkrJqd|d7 }d}||krqdq rz|dkrz|dkrz|d7 }|tks|tkr||dk8 }|	| |||| |}||8 }|}|dkr||||||| ||7 }||7 }||8 }|dkrq|	| ||< |r&|
| ||< |d7 }|d7 }|d8 }|dkrLq|| |	||| |}||8 }|}|dkr||||	|
|| ||7 }||7 }||8 }|dkrq|| ||< |r|| ||< |d7 }|d7 }|d8 }|dkrqq|d7 }qz|dkr&||||||| n|dks4t ||ksBt | |S )a@  
        Merge the na elements starting at ssa with the nb elements starting at
        ssb = ssa + na in a stable way, in-place.  na and nb must be > 0,
        and should have na <= nb. See listsort.txt for more info.

        An updated MergeState is returned (with possibly a different min_gallop
        or larger temp arrays).

        NOTE: compared to CPython's timsort, the requirement that
            "Must also have that keys[ssa + na - 1] belongs at the end of the merge"

        is removed. This makes the code a bit simpler and easier to reason about.
        r   r&   r5   r   r   r   r,   r6   r   r   ssanassbnbZa_keysZa_valuesZb_keysZb_valuesdestrB   r   ZacountZbcountrF   )	DO_GALLOPr<   r   r   r$   r9   r8   rR   r!   r#   r     s    
  



  


  



  z#make_timsort_impl.<locals>.merge_loc                    s  |dkr|dkr||kst ||| ks,t | |} | j| jd|||| |}|}| j}	| j}
|| d }|d }|| d }|	|
}| j}|dkr8|dkr8d}d}|	| || r || ||< |r|| ||< |d8 }|d8 }|d8 }|dkrq~|d7 }d}||kr|q~q|	| ||< |r>|
| ||< |d8 }|d8 }|d8 }|dkrdq~|d7 }d}||krq~q r|dkr|dkr|d7 }|tks|tkr.||dk8 }|	| ||| d |d |}|d | }|}|dkr.||||||| ||8 }||8 }||8 }|dkr.q.|	| ||< |rL|
| ||< |d8 }|d8 }|d8 }|dkrrq.|| |	|| d |d |}|d | }|}|dkr||||	|
|| ||8 }||8 }||8 }|dkrq.|| ||< |r|| ||< |d8 }|d8 }|d8 }|dkrq.q|d7 }q|dkrh|||| d |	|
|| d | n|dksvt ||kst | |S )aA  
        Merge the na elements starting at ssa with the nb elements starting at
        ssb = ssa + na in a stable way, in-place.  na and nb must be > 0,
        and should have na >= nb.  See listsort.txt for more info.

        An updated MergeState is returned (with possibly a different min_gallop
        or larger temp arrays).

        NOTE: compared to CPython's timsort, the requirement that
            "Must also have that keys[ssa + na - 1] belongs at the end of the merge"

        is removed. This makes the code a bit simpler and easier to reason about.
        r   r&   rT   rU   )	r[   r<   r   r   r$   r9   r8   rR   rS   r!   r#   r   Y  s    
  



 
  

 
  



  
z#make_timsort_impl.<locals>.merge_hic           
         sX  | j }|dkst|dkst||d ks:||d ks:t| j| \}}| j|d  \}}|dkrj|dksnt|| |ks~tt||| | j|< ||d kr| j|d  | j|d < | } || |||| |}	||	| 8 }|	}|dkr| S  ||| d  |||| || d }	|	| }||kr@| ||||||S | ||||||S dS )zl
        Merge the two runs at stack indices i and i+1.

        An updated MergeState is returned.
        r%   r      r&   N)r   r5   r   r   )
r6   r   r   rP   r   rV   rW   rX   rY   rF   )r   r   r   r   r   r!   r#   r     s,    (
z#make_timsort_impl.<locals>.merge_atc                    s   | j dkr| j}| j d }|dkrH||d  j|| j||d  j ksv|dkr||d  j||d  j|| j kr||d  j||d  jk r|d8 } | |||} q || j||d  jk rֈ | |||} q qq | S )a(  
        Examine the stack of runs waiting to be merged, merging adjacent runs
        until the stack invariants are re-established:

        1. len[-3] > len[-2] + len[-1]
        2. len[-2] > len[-1]

        An updated MergeState is returned.

        See listsort.txt for more info.
        r&   r%   r   r   r   r   r6   r   r   r   r   r   r!   r#   r   '  s    

.$z)make_timsort_impl.<locals>.merge_collapsec                    sZ   | j dkrV| j}| j d }|dkrF||d  j||d  jk rF|d8 } | |||} q | S )z
        Regardless of invariants, merge all runs on the stack until only one
        remains.  This is used at the end of the mergesort.

        An updated MergeState is returned.
        r&   r%   r   r]   r^   r_   r!   r#   r   C  s    

z/make_timsort_impl.<locals>.merge_force_collapsec                    s   |}|d }||k r@| | | |  | |< | |< |d7 }|d8 }q | |r|}|d }||k r|| ||  ||< ||< |d7 }|d8 }qVdS )z,
        Reverse a slice, in-place.
        r&   Nr!   )r   r   r   rK   rP   jrQ   r!   r#   reverse_sliceV  s    

z(make_timsort_impl.<locals>.reverse_slicec           	         s   t |}|dk rdS |}}|dkr|||| \}}|rR|||||  ||k rt||} ||||| ||  |}| t||} | ||} ||7 }||8 }q | ||} | jdkst| jd dt |fkstdS )z2
        Run timsort with the mergestate.
        r%   Nr   r&   )r)   r(   r   r   r5   r   )	r6   r   r   Z
nremainingZminrunr@   r   descforce)r   r   r
   r   r   r   ra   r3   r!   r#   run_timsort_with_mergestatej  s(    

z6make_timsort_impl.<locals>.run_timsort_with_mergestatec                    s   | } | | | dS )z2
        Run timsort over the given keys.
        Nr!   r"   )r	   rd   r!   r#   r     s    z&make_timsort_impl.<locals>.run_timsortc                    s    | || | dS )z=
        Run timsort over the given keys and values.
        Nr!   r"   )r4   rd   r!   r#   r     s    
 z2make_timsort_impl.<locals>.run_timsort_with_values)r   r1   r   )wrapr2   r   r   r!   )r[   r<   r   r   r   r   r$   r1   r2   r9   r
   r   r   r   r   r8   r   r	   r4   r   r   ra   rd   rR   rS   r3   r#   make_timsort_impl9   s    



	

1$UK
  /$          rf   c                  G   s   t dd f|  S )Nc                 S   s   | S r    r!   fr!   r!   r#   <lambda>      z!make_py_timsort.<locals>.<lambda>)rf   argsr!   r!   r#   make_py_timsort  s    rm   c                     s"   ddl m  t fddf|  S )Nr   jitc                    s    dd| S )NT)Znopythonr!   rg   rn   r!   r#   ri     rj   z"make_jit_timsort.<locals>.<lambda>)Znumbaro   rf   rk   r!   rn   r#   make_jit_timsort  s    rp   )__doc__collectionsZ
numba.corer   
namedtupler   r+   r,   r*   r   r   rf   rm   rp   r!   r!   r!   r#   <module>   s.   	       v