U
    hâËdß‚  ã                   @   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_valueséU   é   é   Ú
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!   úK/home/sam/Atlas/atlas_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€|}qFq‚qF||krŽ|}||7 }||7 }nf|| d }||k rèˆ |||  | ƒrÊqèq¬|}|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„|}qJq†qJ||kr’|}|| ||  }}n`|| }||k rêˆ | |||  ƒrÌqêq®|}|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�s„t ‚ˆ| |ƒ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 qÖq | 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 r€t||ƒ}ˆ ||||| || ƒ |}ˆ| t||ƒƒ} ˆ| ||ƒ} ||7 }||8 }q ˆ| ||ƒ} | jdksÈt‚| jd dt |ƒfksât‚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