2012-08-24 12:52:44 +04:00
/*
2017-10-12 16:15:58 +03:00
* Taken from https : //github.com/swenson/sort
* Revision : 05f d77bfec049ce8b7c408c4d3dd2d51ee061a15
* Removed all code unrelated to Timsort and made minor adjustments for
* cross - platform compatibility .
2012-08-24 12:52:44 +04:00
*/
/*
2017-10-12 16:15:58 +03:00
* The MIT License ( MIT )
*
* Copyright ( c ) 2010 - 2017 Christopher Swenson .
* Copyright ( c ) 2012 Vojtech Fried .
* Copyright ( c ) 2012 Google Inc . All Rights Reserved .
*
* Permission is hereby granted , free of charge , to any person obtaining a
* copy of this software and associated documentation files ( the " Software " ) ,
* to deal in the Software without restriction , including without limitation
* the rights to use , copy , modify , merge , publish , distribute , sublicense ,
* and / or sell copies of the Software , and to permit persons to whom the
* Software is furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING
* FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE .
*/
2012-08-24 12:52:44 +04:00
# include <stdlib.h>
# include <stdio.h>
# include <string.h>
2012-08-27 19:56:07 +04:00
# ifdef HAVE_STDINT_H
2012-08-24 12:52:44 +04:00
# include <stdint.h>
2017-10-09 01:20:01 +03:00
# elif defined(_WIN32)
2012-08-27 19:56:07 +04:00
typedef unsigned __int64 uint64_t ;
# endif
2017-10-12 16:15:58 +03:00
# ifndef SORT_NAME
# error "Must declare SORT_NAME"
2012-08-27 19:56:07 +04:00
# endif
2012-08-24 12:52:44 +04:00
2017-10-12 16:15:58 +03:00
# ifndef SORT_TYPE
# error "Must declare SORT_TYPE"
2012-09-18 07:15:06 +04:00
# endif
2017-10-12 16:15:58 +03:00
# ifndef SORT_CMP
# define SORT_CMP(x, y) ((x) < (y) ? -1 : ((x) == (y) ? 0 : 1))
2012-09-18 07:15:06 +04:00
# endif
2017-10-12 16:15:58 +03:00
# ifndef TIM_SORT_STACK_SIZE
# define TIM_SORT_STACK_SIZE 128
# endif
# define SORT_SWAP(x,y) {SORT_TYPE __SORT_SWAP_t = (x); (x) = (y); (y) = __SORT_SWAP_t;}
2019-09-30 18:04:54 +03:00
/* Common, type-agnostic functions and constants that we don't want to declare twice. */
2017-10-12 16:15:58 +03:00
# ifndef SORT_COMMON_H
# define SORT_COMMON_H
2012-08-24 12:52:44 +04:00
# ifndef MAX
# define MAX(x,y) (((x) > (y) ? (x) : (y)))
# endif
2017-10-12 16:15:58 +03:00
2012-08-24 12:52:44 +04:00
# ifndef MIN
# define MIN(x,y) (((x) < (y) ? (x) : (y)))
# endif
2017-10-12 16:15:58 +03:00
static int compute_minrun ( const uint64_t ) ;
2012-08-24 12:52:44 +04:00
# ifndef CLZ
2019-04-05 09:34:59 +03:00
# if defined(__GNUC__) && ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ > 3))
2012-08-24 12:52:44 +04:00
# define CLZ __builtin_clzll
# else
2017-10-12 16:15:58 +03:00
static int clzll ( uint64_t ) ;
2012-08-24 12:52:44 +04:00
/* adapted from Hacker's Delight */
2017-10-12 16:15:58 +03:00
static int clzll ( uint64_t x ) {
2012-08-24 12:52:44 +04:00
int n ;
2017-10-12 16:15:58 +03:00
if ( x = = 0 ) {
return 64 ;
}
2012-08-24 12:52:44 +04:00
n = 0 ;
2017-10-12 16:15:58 +03:00
if ( x < = 0x00000000FFFFFFFFL ) {
n = n + 32 ;
x = x < < 32 ;
}
if ( x < = 0x0000FFFFFFFFFFFFL ) {
n = n + 16 ;
x = x < < 16 ;
}
if ( x < = 0x00FFFFFFFFFFFFFFL ) {
n = n + 8 ;
x = x < < 8 ;
}
if ( x < = 0x0FFFFFFFFFFFFFFFL ) {
n = n + 4 ;
x = x < < 4 ;
}
if ( x < = 0x3FFFFFFFFFFFFFFFL ) {
n = n + 2 ;
x = x < < 2 ;
}
if ( x < = 0x7FFFFFFFFFFFFFFFL ) {
n = n + 1 ;
}
2012-08-24 12:52:44 +04:00
return n ;
}
# define CLZ clzll
# endif
# endif
2017-10-12 16:15:58 +03:00
static __inline int compute_minrun ( const uint64_t size ) {
2012-08-24 12:52:44 +04:00
const int top_bit = 64 - CLZ ( size ) ;
const int shift = MAX ( top_bit , 6 ) - 6 ;
const int minrun = size > > shift ;
2017-10-12 16:15:58 +03:00
const uint64_t mask = ( 1ULL < < shift ) - 1 ;
2012-08-24 12:52:44 +04:00
2017-10-12 16:15:58 +03:00
if ( mask & size ) {
return minrun + 1 ;
}
2012-08-24 12:52:44 +04:00
2017-10-12 16:15:58 +03:00
return minrun ;
}
2012-08-24 12:52:44 +04:00
2017-10-12 16:15:58 +03:00
# endif /* SORT_COMMON_H */
2012-08-24 12:52:44 +04:00
# define SORT_CONCAT(x, y) x ## _ ## y
# define SORT_MAKE_STR1(x, y) SORT_CONCAT(x,y)
# define SORT_MAKE_STR(x) SORT_MAKE_STR1(SORT_NAME,x)
2017-10-12 16:15:58 +03:00
# define BINARY_INSERTION_FIND SORT_MAKE_STR(binary_insertion_find)
# define BINARY_INSERTION_SORT_START SORT_MAKE_STR(binary_insertion_sort_start)
# define BINARY_INSERTION_SORT SORT_MAKE_STR(binary_insertion_sort)
# define REVERSE_ELEMENTS SORT_MAKE_STR(reverse_elements)
# define COUNT_RUN SORT_MAKE_STR(count_run)
# define CHECK_INVARIANT SORT_MAKE_STR(check_invariant)
# define TIM_SORT SORT_MAKE_STR(tim_sort)
# define TIM_SORT_RESIZE SORT_MAKE_STR(tim_sort_resize)
# define TIM_SORT_MERGE SORT_MAKE_STR(tim_sort_merge)
# define TIM_SORT_COLLAPSE SORT_MAKE_STR(tim_sort_collapse)
2012-08-24 12:52:44 +04:00
2017-10-12 16:15:58 +03:00
# ifndef MAX
# define MAX(x,y) (((x) > (y) ? (x) : (y)))
# endif
# ifndef MIN
# define MIN(x,y) (((x) < (y) ? (x) : (y)))
# endif
2012-08-24 12:52:44 +04:00
typedef struct {
2017-10-12 16:15:58 +03:00
size_t start ;
size_t length ;
2012-08-24 12:52:44 +04:00
} TIM_SORT_RUN_T ;
2017-10-12 16:15:58 +03:00
2012-08-24 12:52:44 +04:00
void BINARY_INSERTION_SORT ( SORT_TYPE * dst , const size_t size ) ;
void TIM_SORT ( SORT_TYPE * dst , const size_t size ) ;
2017-10-12 16:15:58 +03:00
2012-08-24 12:52:44 +04:00
/* Function used to do a binary search for binary insertion sort */
2017-10-12 16:15:58 +03:00
static __inline size_t BINARY_INSERTION_FIND ( SORT_TYPE * dst , const SORT_TYPE x ,
const size_t size ) {
size_t l , c , r ;
2012-08-24 12:52:44 +04:00
SORT_TYPE cx ;
l = 0 ;
r = size - 1 ;
c = r > > 1 ;
2017-10-12 16:15:58 +03:00
/* check for out of bounds at the beginning. */
if ( SORT_CMP ( x , dst [ 0 ] ) < 0 ) {
2012-08-24 12:52:44 +04:00
return 0 ;
2017-10-12 16:15:58 +03:00
} else if ( SORT_CMP ( x , dst [ r ] ) > 0 ) {
return r ;
2012-08-24 12:52:44 +04:00
}
cx = dst [ c ] ;
2017-10-12 16:15:58 +03:00
while ( 1 ) {
2012-08-24 12:52:44 +04:00
const int val = SORT_CMP ( x , cx ) ;
2017-10-12 16:15:58 +03:00
if ( val < 0 ) {
if ( c - l < = 1 ) {
return c ;
}
2012-08-24 12:52:44 +04:00
r = c ;
2017-10-12 16:15:58 +03:00
} else { /* allow = for stability. The binary search favors the right. */
if ( r - c < = 1 ) {
return c + 1 ;
}
2012-08-24 12:52:44 +04:00
l = c ;
}
2017-10-12 16:15:58 +03:00
2012-08-24 12:52:44 +04:00
c = l + ( ( r - l ) > > 1 ) ;
cx = dst [ c ] ;
}
}
/* Binary insertion sort, but knowing that the first "start" entries are sorted. Used in timsort. */
2017-10-12 16:15:58 +03:00
static void BINARY_INSERTION_SORT_START ( SORT_TYPE * dst , const size_t start , const size_t size ) {
size_t i ;
for ( i = start ; i < size ; i + + ) {
size_t j ;
2012-08-24 12:52:44 +04:00
SORT_TYPE x ;
2017-10-12 16:15:58 +03:00
size_t location ;
2012-08-24 12:52:44 +04:00
/* If this entry is already correct, just move along */
2017-10-12 16:15:58 +03:00
if ( SORT_CMP ( dst [ i - 1 ] , dst [ i ] ) < = 0 ) {
continue ;
}
2012-08-24 12:52:44 +04:00
/* Else we need to find the right place, shift everything over, and squeeze in */
x = dst [ i ] ;
location = BINARY_INSERTION_FIND ( dst , x , i ) ;
2017-10-12 16:15:58 +03:00
for ( j = i - 1 ; j > = location ; j - - ) {
2012-08-24 12:52:44 +04:00
dst [ j + 1 ] = dst [ j ] ;
2017-10-12 16:15:58 +03:00
if ( j = = 0 ) { /* check edge case because j is unsigned */
break ;
}
2012-08-24 12:52:44 +04:00
}
2017-10-12 16:15:58 +03:00
2012-08-24 12:52:44 +04:00
dst [ location ] = x ;
}
}
/* Binary insertion sort */
2017-10-12 16:15:58 +03:00
void BINARY_INSERTION_SORT ( SORT_TYPE * dst , const size_t size ) {
/* don't bother sorting an array of size <= 1 */
if ( size < = 1 ) {
return ;
}
2012-08-24 12:52:44 +04:00
BINARY_INSERTION_SORT_START ( dst , 1 , size ) ;
}
/* timsort implementation, based on timsort.txt */
2017-10-12 16:15:58 +03:00
static __inline void REVERSE_ELEMENTS ( SORT_TYPE * dst , size_t start , size_t end ) {
while ( 1 ) {
if ( start > = end ) {
return ;
}
2012-08-24 12:52:44 +04:00
SORT_SWAP ( dst [ start ] , dst [ end ] ) ;
start + + ;
end - - ;
}
}
2017-10-12 16:15:58 +03:00
static size_t COUNT_RUN ( SORT_TYPE * dst , const size_t start , const size_t size ) {
size_t curr ;
if ( size - start = = 1 ) {
return 1 ;
}
if ( start > = size - 2 ) {
if ( SORT_CMP ( dst [ size - 2 ] , dst [ size - 1 ] ) > 0 ) {
2012-08-24 12:52:44 +04:00
SORT_SWAP ( dst [ size - 2 ] , dst [ size - 1 ] ) ;
2017-10-12 16:15:58 +03:00
}
2012-08-24 12:52:44 +04:00
return 2 ;
}
curr = start + 2 ;
2017-10-12 16:15:58 +03:00
if ( SORT_CMP ( dst [ start ] , dst [ start + 1 ] ) < = 0 ) {
2012-08-24 12:52:44 +04:00
/* increasing run */
2017-10-12 16:15:58 +03:00
while ( 1 ) {
if ( curr = = size - 1 ) {
break ;
}
if ( SORT_CMP ( dst [ curr - 1 ] , dst [ curr ] ) > 0 ) {
break ;
}
2012-08-24 12:52:44 +04:00
curr + + ;
}
2017-10-12 16:15:58 +03:00
2012-08-24 12:52:44 +04:00
return curr - start ;
2017-10-12 16:15:58 +03:00
} else {
2012-08-24 12:52:44 +04:00
/* decreasing run */
2017-10-12 16:15:58 +03:00
while ( 1 ) {
if ( curr = = size - 1 ) {
break ;
}
if ( SORT_CMP ( dst [ curr - 1 ] , dst [ curr ] ) < = 0 ) {
break ;
}
2012-08-24 12:52:44 +04:00
curr + + ;
}
2017-10-12 16:15:58 +03:00
2012-08-24 12:52:44 +04:00
/* reverse in-place */
REVERSE_ELEMENTS ( dst , start , curr - 1 ) ;
return curr - start ;
}
}
2017-10-12 16:15:58 +03:00
static int CHECK_INVARIANT ( TIM_SORT_RUN_T * stack , const int stack_curr ) {
size_t A , B , C ;
if ( stack_curr < 2 ) {
2012-08-24 12:52:44 +04:00
return 1 ;
}
2017-10-12 16:15:58 +03:00
if ( stack_curr = = 2 ) {
const size_t A1 = stack [ stack_curr - 2 ] . length ;
const size_t B1 = stack [ stack_curr - 1 ] . length ;
if ( A1 < = B1 ) {
return 0 ;
}
return 1 ;
}
2012-08-24 12:52:44 +04:00
A = stack [ stack_curr - 3 ] . length ;
B = stack [ stack_curr - 2 ] . length ;
C = stack [ stack_curr - 1 ] . length ;
2017-10-12 16:15:58 +03:00
if ( ( A < = B + C ) | | ( B < = C ) ) {
return 0 ;
}
2012-08-24 12:52:44 +04:00
return 1 ;
}
typedef struct {
size_t alloc ;
SORT_TYPE * storage ;
} TEMP_STORAGE_T ;
2017-10-12 16:15:58 +03:00
static void TIM_SORT_RESIZE ( TEMP_STORAGE_T * store , const size_t new_size ) {
if ( store - > alloc < new_size ) {
2012-08-24 12:52:44 +04:00
SORT_TYPE * tempstore = ( SORT_TYPE * ) realloc ( store - > storage , new_size * sizeof ( SORT_TYPE ) ) ;
2017-10-12 16:15:58 +03:00
if ( tempstore = = NULL ) {
fprintf ( stderr , " Error allocating temporary storage for tim sort: need %lu bytes " ,
( unsigned long ) ( sizeof ( SORT_TYPE ) * new_size ) ) ;
2012-08-24 12:52:44 +04:00
exit ( 1 ) ;
}
2017-10-12 16:15:58 +03:00
2012-08-24 12:52:44 +04:00
store - > storage = tempstore ;
store - > alloc = new_size ;
}
}
2017-10-12 16:15:58 +03:00
static void TIM_SORT_MERGE ( SORT_TYPE * dst , const TIM_SORT_RUN_T * stack , const int stack_curr ,
TEMP_STORAGE_T * store ) {
const size_t A = stack [ stack_curr - 2 ] . length ;
const size_t B = stack [ stack_curr - 1 ] . length ;
const size_t curr = stack [ stack_curr - 2 ] . start ;
2012-08-24 12:52:44 +04:00
SORT_TYPE * storage ;
2017-10-12 16:15:58 +03:00
size_t i , j , k ;
2012-08-24 12:52:44 +04:00
TIM_SORT_RESIZE ( store , MIN ( A , B ) ) ;
storage = store - > storage ;
/* left merge */
2017-10-12 16:15:58 +03:00
if ( A < B ) {
2012-08-24 12:52:44 +04:00
memcpy ( storage , & dst [ curr ] , A * sizeof ( SORT_TYPE ) ) ;
i = 0 ;
j = curr + A ;
2017-10-12 16:15:58 +03:00
for ( k = curr ; k < curr + A + B ; k + + ) {
if ( ( i < A ) & & ( j < curr + A + B ) ) {
if ( SORT_CMP ( storage [ i ] , dst [ j ] ) < = 0 ) {
2012-08-24 12:52:44 +04:00
dst [ k ] = storage [ i + + ] ;
2017-10-12 16:15:58 +03:00
} else {
2012-08-24 12:52:44 +04:00
dst [ k ] = dst [ j + + ] ;
2017-10-12 16:15:58 +03:00
}
} else if ( i < A ) {
2012-08-24 12:52:44 +04:00
dst [ k ] = storage [ i + + ] ;
2017-10-12 16:15:58 +03:00
} else {
break ;
2012-08-24 12:52:44 +04:00
}
}
2017-10-12 16:15:58 +03:00
} else {
/* right merge */
2012-08-24 12:52:44 +04:00
memcpy ( storage , & dst [ curr + A ] , B * sizeof ( SORT_TYPE ) ) ;
2017-10-12 16:15:58 +03:00
i = B ;
j = curr + A ;
k = curr + A + B ;
2019-05-16 22:16:01 +03:00
while ( k > curr ) {
k - - ;
2017-10-12 16:15:58 +03:00
if ( ( i > 0 ) & & ( j > curr ) ) {
if ( SORT_CMP ( dst [ j - 1 ] , storage [ i - 1 ] ) > 0 ) {
dst [ k ] = dst [ - - j ] ;
} else {
dst [ k ] = storage [ - - i ] ;
}
} else if ( i > 0 ) {
dst [ k ] = storage [ - - i ] ;
} else {
break ;
2012-08-24 12:52:44 +04:00
}
}
}
}
2017-10-12 16:15:58 +03:00
static int TIM_SORT_COLLAPSE ( SORT_TYPE * dst , TIM_SORT_RUN_T * stack , int stack_curr ,
TEMP_STORAGE_T * store , const size_t size ) {
2015-02-27 09:55:49 +03:00
while ( 1 ) {
2017-10-12 16:15:58 +03:00
size_t A , B , C , D ;
2016-08-22 13:16:31 +03:00
int ABC , BCD , CD ;
2015-02-27 09:55:49 +03:00
2012-08-24 12:52:44 +04:00
/* if the stack only has one thing on it, we are done with the collapse */
2015-02-27 09:55:49 +03:00
if ( stack_curr < = 1 ) {
break ;
}
2012-08-24 12:52:44 +04:00
/* if this is the last merge, just do it */
2015-02-27 09:55:49 +03:00
if ( ( stack_curr = = 2 ) & & ( stack [ 0 ] . length + stack [ 1 ] . length = = size ) ) {
2012-08-24 12:52:44 +04:00
TIM_SORT_MERGE ( dst , stack , stack_curr , store ) ;
stack [ 0 ] . length + = stack [ 1 ] . length ;
stack_curr - - ;
break ;
}
/* check if the invariant is off for a stack of 2 elements */
2015-02-27 09:55:49 +03:00
else if ( ( stack_curr = = 2 ) & & ( stack [ 0 ] . length < = stack [ 1 ] . length ) ) {
2012-08-24 12:52:44 +04:00
TIM_SORT_MERGE ( dst , stack , stack_curr , store ) ;
stack [ 0 ] . length + = stack [ 1 ] . length ;
stack_curr - - ;
break ;
2015-02-27 09:55:49 +03:00
} else if ( stack_curr = = 2 ) {
2012-08-24 12:52:44 +04:00
break ;
2015-02-27 09:55:49 +03:00
}
2012-08-24 12:52:44 +04:00
2015-02-27 09:55:49 +03:00
B = stack [ stack_curr - 3 ] . length ;
C = stack [ stack_curr - 2 ] . length ;
D = stack [ stack_curr - 1 ] . length ;
2012-08-24 12:52:44 +04:00
2015-02-27 09:55:49 +03:00
if ( stack_curr > = 4 ) {
A = stack [ stack_curr - 4 ] . length ;
ABC = ( A < = B + C ) ;
} else {
ABC = 0 ;
2012-08-24 12:52:44 +04:00
}
2015-02-27 09:55:49 +03:00
BCD = ( B < = C + D ) | | ABC ;
CD = ( C < = D ) ;
/* Both invariants are good */
if ( ! BCD & & ! CD ) {
break ;
}
/* left merge */
if ( BCD & & ! CD ) {
TIM_SORT_MERGE ( dst , stack , stack_curr - 1 , store ) ;
stack [ stack_curr - 3 ] . length + = stack [ stack_curr - 2 ] . length ;
stack [ stack_curr - 2 ] = stack [ stack_curr - 1 ] ;
stack_curr - - ;
} else {
/* right merge */
2012-08-24 12:52:44 +04:00
TIM_SORT_MERGE ( dst , stack , stack_curr , store ) ;
stack [ stack_curr - 2 ] . length + = stack [ stack_curr - 1 ] . length ;
stack_curr - - ;
}
}
2015-02-27 09:55:49 +03:00
2012-08-24 12:52:44 +04:00
return stack_curr ;
}
2017-10-12 16:15:58 +03:00
static __inline int PUSH_NEXT ( SORT_TYPE * dst ,
const size_t size ,
TEMP_STORAGE_T * store ,
const size_t minrun ,
TIM_SORT_RUN_T * run_stack ,
size_t * stack_curr ,
size_t * curr ) {
size_t len = COUNT_RUN ( dst , * curr , size ) ;
size_t run = minrun ;
if ( run > size - * curr ) {
run = size - * curr ;
}
if ( run > len ) {
BINARY_INSERTION_SORT_START ( & dst [ * curr ] , len , run ) ;
len = run ;
}
run_stack [ * stack_curr ] . start = * curr ;
run_stack [ * stack_curr ] . length = len ;
( * stack_curr ) + + ;
* curr + = len ;
if ( * curr = = size ) {
/* finish up */
while ( * stack_curr > 1 ) {
TIM_SORT_MERGE ( dst , run_stack , * stack_curr , store ) ;
run_stack [ * stack_curr - 2 ] . length + = run_stack [ * stack_curr - 1 ] . length ;
( * stack_curr ) - - ;
}
if ( store - > storage ! = NULL ) {
free ( store - > storage ) ;
store - > storage = NULL ;
}
return 0 ;
}
return 1 ;
}
void TIM_SORT ( SORT_TYPE * dst , const size_t size ) {
size_t minrun ;
2012-08-24 12:52:44 +04:00
TEMP_STORAGE_T _store , * store ;
2017-10-12 16:15:58 +03:00
TIM_SORT_RUN_T run_stack [ TIM_SORT_STACK_SIZE ] ;
size_t stack_curr = 0 ;
size_t curr = 0 ;
2012-08-24 12:52:44 +04:00
2017-10-21 16:09:33 +03:00
/* don't bother sorting an array of size 1 */
if ( size < = 1 ) {
return ;
}
2017-10-12 16:15:58 +03:00
if ( size < 64 ) {
2012-08-24 12:52:44 +04:00
BINARY_INSERTION_SORT ( dst , size ) ;
return ;
}
/* compute the minimum run length */
minrun = compute_minrun ( size ) ;
/* temporary storage for merges */
store = & _store ;
store - > alloc = 0 ;
store - > storage = NULL ;
2017-10-12 16:15:58 +03:00
if ( ! PUSH_NEXT ( dst , size , store , minrun , run_stack , & stack_curr , & curr ) ) {
return ;
}
if ( ! PUSH_NEXT ( dst , size , store , minrun , run_stack , & stack_curr , & curr ) ) {
return ;
}
2012-08-24 12:52:44 +04:00
2017-10-12 16:15:58 +03:00
if ( ! PUSH_NEXT ( dst , size , store , minrun , run_stack , & stack_curr , & curr ) ) {
return ;
}
while ( 1 ) {
if ( ! CHECK_INVARIANT ( run_stack , stack_curr ) ) {
2012-08-24 12:52:44 +04:00
stack_curr = TIM_SORT_COLLAPSE ( dst , run_stack , stack_curr , store , size ) ;
continue ;
}
2017-10-12 16:15:58 +03:00
if ( ! PUSH_NEXT ( dst , size , store , minrun , run_stack , & stack_curr , & curr ) ) {
return ;
}
2012-08-24 12:52:44 +04:00
}
}
# undef SORT_CONCAT
# undef SORT_MAKE_STR1
# undef SORT_MAKE_STR
# undef SORT_NAME
# undef SORT_TYPE
# undef SORT_CMP
# undef TEMP_STORAGE_T
# undef TIM_SORT_RUN_T
# undef PUSH_NEXT
# undef SORT_SWAP
# undef SORT_CONCAT
# undef SORT_MAKE_STR1
# undef SORT_MAKE_STR
# undef BINARY_INSERTION_FIND
# undef BINARY_INSERTION_SORT_START
# undef BINARY_INSERTION_SORT
# undef REVERSE_ELEMENTS
# undef COUNT_RUN
# undef TIM_SORT
# undef TIM_SORT_RESIZE
# undef TIM_SORT_COLLAPSE
# undef TIM_SORT_RUN_T
# undef TEMP_STORAGE_T