o
    1&i                     @   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   || uS N r   r   r!   r!   =C:\wamp64\www\opt\env\Lib\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	J || j|< t| j| j| j| j|d S )z2
        Append a run on the merge stack.
        r&   )r   r+   r   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   )r5   r!   r!   r#   r   c   s   z$make_timsort_impl.<locals>.merge_popc                    sp   t | j}||kr| S ||k r|d> }||k s| j|} | j| jr+| 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   )r5   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   )r5   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
J | |}||kr|d7 }||k r{| | }|}|}||k rA||| d?  }	 || |	 r9|	}n|	d }||k s't ||dD ]
}	| |	d  | |	< qG|| |< |rq|| }
t ||dD ]
}	||	d  ||	< qb|
||< |d7 }||k sdS 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range)r   r   lohir   _has_valuesZpivotlrpZ	pivot_val)r;   r$   r!   r#   r      s0   
z%make_timsort_impl.<locals>.binarysortc                    s   ||k sJ |d |krdS  | |d  | | r<t |d |D ]} | | | |d  s5|| df  S q || dfS t |d |D ]} | | | |d  rX|| df  S qC|| df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%   TFr=   )r   r?   r@   kr;   r!   r#   r      s   z$make_timsort_impl.<locals>.count_runc           
         sx  ||ksJ ||kr||k sJ || }d}d} || | rS|| }||k rD |||  | r?|}|d> d }|dkr>|}nn||k s'||krJ|}||7 }||7 }n5|| d }||k ry |||  | rgn|}|d> d }|dkru|}||k s]||kr|}|| || }}|d |kr||k r||ksJ |d7 }||k r||| d?  }	 ||	 | r|	d }n|	}||k s|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&   r!   
keyr9   r   stophintr   ZlastofsZofsZmaxofsmrF   r!   r#   r      sR   


 
	z&make_timsort_impl.<locals>.gallop_leftc           
         sx  ||ksJ ||kr||k sJ || }d}d} | || rV|| d }||k rF | |||  rA|}|d> d }|dkr@|}nn||k s)||krL|}|| || }}n2|| }||k rz | |||  rhn|}|d> d }|dkrv|}||k s^||kr|}||7 }||7 }|d |kr||k r||ksJ |d7 }||k r||| d?  }	 | ||	 r|	}n|	d }||k s|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&   r!   rG   rF   r!   r#   r   ;  sR   

 	z'make_timsort_impl.<locals>.gallop_rightc                 S   s<   d}| dksJ | dkr|| d@ O }| dL } | dks| | 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&   r!   )r   rC   r!   r!   r#   r     s   z/make_timsort_impl.<locals>.merge_compute_minrunc                    sn   |dksJ |dksJ t |D ]}|||  | || < q ||r3t |D ]}|||  ||| < q&dS d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     
z)make_timsort_impl.<locals>.sortslice_copyc                    sn   |dksJ |dksJ t |D ]}|||  | || < q ||r3t |D ]}|||  ||| < q&dS dS )z%
        Downwards memcpy().
        r   Nr=   rM   rO   r!   r#   sortslice_copy_down  rQ   z.make_timsort_impl.<locals>.sortslice_copy_downr&   c                    sR  |dkr|dkr||ksJ ||| ksJ | |} | j | jd|||| | j }| j}|}	|}
|}d}||}| j}|dkr|dkrd}d}	 |	| || r|	| ||< |rc|
| ||< |d7 }|d7 }|d8 }|dkrtn7|d7 }d}||krn,n*|| ||< |r|| ||< |d7 }|d7 }|d8 }|dkrn|d7 }d}||krnqL r}|dkr}|dkr}|d7 }|tks|tkry||dk8 }|	| |||| |}||8 }|}|dkr||||||| ||7 }||7 }||8 }|dkrn}|	| ||< |r|
| ||< |d7 }|d7 }|d8 }|dkrn\|| |	||| |}||8 }|}|dkrP||||	|
|| ||7 }||7 }||8 }|dkrPn)|| ||< |r_|| ||< |d7 }|d7 }|d8 }|dkrqn|tks|tks|d7 }|dkr|dksG|dkr||||||| n|dksJ ||ksJ | |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   Tr&   r   r   r   r,   r5   r   r   ssanassbnbZa_keysZa_valuesZb_keysZb_valuesdestrA   r   ZacountZbcountrE   )	DO_GALLOPr;   r   r   r$   r8   r7   rP   r!   r#   r     s   

"



>
l
z#make_timsort_impl.<locals>.merge_loc                    s  |dkr|dkr||ksJ ||| ksJ | |} | j | jd|||| |}|}| j }	| j}
|| d }|d }|| d }|	|
}| j}|dkr|dkrd}d}	 |	| || r|| ||< |ro|| ||< |d8 }|d8 }|d8 }|dkrn7|d7 }d}||krn,n*|	| ||< |r|
| ||< |d8 }|d8 }|d8 }|dkrn|d7 }d}||krnqX 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n|	| ||< |r|
| ||< |d8 }|d8 }|d8 }|dkr1nb|| |	|| d |d |}|d | }|}|dkrj||||	|
|| ||8 }||8 }||8 }|dkrjn)|| ||< |ry|| ||< |d8 }|d8 }|d8 }|dkrn|tks|tks|d7 }|dkr|dksS|dkr|||| d |	|
|| d | n|dksJ ||ksJ | |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&   rS   rT   )	rZ   r;   r   r   r$   r8   r7   rP   rR   r!   r#   r   Y  s   

# 


 


>
m
z#make_timsort_impl.<locals>.merge_hic           
         sR  | j }|dks	J |dksJ ||d ks||d ksJ | j| \}}| j|d  \}}|dkr5|dks7J || |ks?J t||| | j|< ||d kr[| j|d  | j|d < | } || |||| |}	||	| 8 }|	}|dkry| S  ||| d  |||| || d }	|	| }||kr| ||||||S | ||||||S )zl
        Merge the two runs at stack indices i and i+1.

        An updated MergeState is returned.
        r%   r      r&   )r   r   r   )
r5   r   r   rN   r   rU   rV   rW   rX   rE   )r   r   r   r   r   r!   r#   r     s,   (z#make_timsort_impl.<locals>.merge_atc                    s   | j dkrq| j}| j d }|dkr$||d  j|| j||d  j ks;|dkrU||d  j||d  j|| j krU||d  j||d  jk rM|d8 } | |||} n|| j||d  jk ri | |||} n	 | S | j dks| 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   r5   r   r   r   r   r   r!   r#   r   '  s   

..
z)make_timsort_impl.<locals>.merge_collapsec                    sb   | j dkr/| j}| j d }|dkr#||d  j||d  jk r#|d8 } | |||} | j dks| 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 }||k s
 | |rM|}|d }||k rO|| || ||< ||< |d7 }|d8 }||k s2dS dS dS )z,
        Reverse a slice, in-place.
        r&   Nr!   )r   r   r   rI   rN   jrO   r!   r#   reverse_sliceV  s"   
z(make_timsort_impl.<locals>.reverse_slicec           	         s   t |}|dk r
dS |}}|dkrZ|||| \}}|r)|||||  ||k r@t||} ||||| ||  |}| t||} | ||} ||7 }||8 }|dks| ||} | jdksgJ | jd dt |fkstJ dS )z2
        Run timsort with the mergestate.
        r%   Nr   r&   )r)   r(   r   r   r   )	r5   r   r   Z
nremainingZminrunr?   r   descforce)r   r   r
   r   r   r   r`   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	   rc   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   rc   r!   r#   r     s   
z2make_timsort_impl.<locals>.run_timsort_with_values)r   r1   r   )wrapr2   r   r   r!   )rZ   r;   r   r   r   r   r$   r1   r2   r8   r
   r   r   r   r   r7   r   r	   r4   r   r   r`   rc   rP   rR   r3   r#   make_timsort_impl9   s|   



	

1$UK
  /$re   c                  G   s   t dd g| R  S )Nc                 S   s   | S r    r!   fr!   r!   r#   <lambda>  s    z!make_py_timsort.<locals>.<lambda>)re   argsr!   r!   r#   make_py_timsort  s   rk   c                     s$   ddl m  t fddg| R  S )Nr   jitc                    s    dd| S )NT)Znopythonr!   rf   rl   r!   r#   rh     s    z"make_jit_timsort.<locals>.<lambda>)Znumbarm   re   ri   r!   rl   r#   make_jit_timsort  s   rn   )__doc__collectionsZ
numba.corer   
namedtupler   r+   r,   r*   r   r   re   rk   rn   r!   r!   r!   r#   <module>   s.    	      v