1+ #pragma once
2+ #include " kf/stl/new"
13/*
24 * Taken from https://github.com/swenson/sort
35 * Revision: 05fd77bfec049ce8b7c408c4d3dd2d51ee061a15
@@ -51,14 +53,12 @@ namespace timsort
5153 /* adapted from Hacker's Delight */
5254 inline int clzll (uint64_t x)
5355 {
54- int n;
55-
5656 if (x == 0 )
5757 {
5858 return 64 ;
5959 }
6060
61- n = 0 ;
61+ int n = 0 ;
6262
6363 if (x <= 0x00000000FFFFFFFFL )
6464 {
@@ -137,14 +137,19 @@ namespace timsort
137137 size_t r = size - 1 ;
138138 size_t c = r >> 1 ;
139139
140+ if (dst == nullptr || size == 0 )
141+ {
142+ return 0 ;
143+ }
144+
140145 /* check for out of bounds at the beginning. */
141146 if (cmp (x, dst[0 ]) < 0 )
142147 {
143148 return 0 ;
144149 }
145- else if (cmp (x, dst[r]) > 0 )
150+ else if (cmp (x, dst[r]) >= 0 )
146151 {
147- return r ;
152+ return size ;
148153 }
149154
150155 T* cx = &dst[c];
@@ -181,6 +186,11 @@ namespace timsort
181186 template <class T >
182187 inline void binary_insertion_sort_start (T* dst, const size_t start, const size_t size)
183188 {
189+ if (dst == nullptr || size == 0 )
190+ {
191+ return ;
192+ }
193+
184194 for (size_t i = start; i < size; i++)
185195 {
186196 /* If this entry is already correct, just move along */
@@ -211,6 +221,11 @@ namespace timsort
211221 template <class T >
212222 inline void reverse_elements (T* dst, size_t start, size_t end)
213223 {
224+ if (dst == nullptr )
225+ {
226+ return ;
227+ }
228+
214229 while (true )
215230 {
216231 if (start >= end)
@@ -227,6 +242,11 @@ namespace timsort
227242 template <class T >
228243 inline size_t count_run (T* dst, const size_t start, const size_t size)
229244 {
245+ if (dst == nullptr || size == 0 )
246+ {
247+ return 0 ;
248+ }
249+
230250 size_t curr;
231251
232252 if (size - start == 1 )
@@ -251,7 +271,7 @@ namespace timsort
251271 /* increasing run */
252272 while (true )
253273 {
254- if (curr == size - 1 )
274+ if (curr == size)
255275 {
256276 break ;
257277 }
@@ -271,7 +291,7 @@ namespace timsort
271291 /* decreasing run */
272292 while (true )
273293 {
274- if (curr == size - 1 )
294+ if (curr == size)
275295 {
276296 break ;
277297 }
@@ -292,6 +312,11 @@ namespace timsort
292312
293313 inline int check_invariant (TIM_SORT_RUN_T* stack, const int stack_curr)
294314 {
315+ if (stack == nullptr )
316+ {
317+ return -1 ;
318+ }
319+
295320 if (stack_curr < 2 )
296321 {
297322 return 1 ;
@@ -332,11 +357,24 @@ namespace timsort
332357 template <class T >
333358 inline void tim_sort_resize (TEMP_STORAGE_T<T>* store, const size_t new_size)
334359 {
360+ if (store == nullptr )
361+ {
362+ return ;
363+ }
364+
335365 if (store->alloc < new_size)
336366 {
337367 T* tempstore = (T*)malloc (new_size * sizeof (T));
338- memcpy (tempstore, store->storage , store->alloc );
339- detail::free (store->storage );
368+ if (tempstore == nullptr )
369+ {
370+ return ;
371+ }
372+
373+ if (store->storage != nullptr )
374+ {
375+ memcpy (tempstore, store->storage , store->alloc * sizeof (T));
376+ detail::free (store->storage );
377+ }
340378
341379 store->storage = tempstore;
342380 store->alloc = new_size;
@@ -418,47 +456,49 @@ namespace timsort
418456 }
419457
420458 template <class T >
421- inline int tim_sort_collapse (T* dst, TIM_SORT_RUN_T* stack, int stack_curr , TEMP_STORAGE_T<T>* store, const size_t size)
459+ inline int tim_sort_collapse (T* dst, TIM_SORT_RUN_T* stack, int stack_size , TEMP_STORAGE_T<T>* store, const size_t size)
422460 {
423461 while (true )
424462 {
425463 /* if the stack only has one thing on it, we are done with the collapse */
426- if (stack_curr <= 1 )
464+ if (stack_size <= 1 )
427465 {
428466 break ;
429467 }
430468
431469 /* if this is the last merge, just do it */
432- if ((stack_curr == 2 ) && (stack[0 ].length + stack[1 ].length == size))
470+ if ((stack_size == 2 ) && (stack[0 ].length + stack[1 ].length == size))
433471 {
434- tim_sort_merge (dst, stack, stack_curr , store);
472+ tim_sort_merge (dst, stack, stack_size , store);
435473 stack[0 ].length += stack[1 ].length ;
436- stack_curr--;
474+ stack[1 ] = { 0 , 0 };
475+ stack_size--;
437476 break ;
438477 }
439478 /* check if the invariant is off for a stack of 2 elements */
440- else if ((stack_curr == 2 ) && (stack[0 ].length <= stack[1 ].length ))
479+ else if ((stack_size == 2 ) && (stack[0 ].length <= stack[1 ].length ))
441480 {
442- tim_sort_merge (dst, stack, stack_curr , store);
481+ tim_sort_merge (dst, stack, stack_size , store);
443482 stack[0 ].length += stack[1 ].length ;
444- stack_curr--;
483+ stack[1 ] = { 0 , 0 };
484+ stack_size--;
445485 break ;
446486 }
447- else if (stack_curr == 2 )
487+ else if (stack_size == 2 )
448488 {
449489 break ;
450490 }
451491
452492 size_t A;
453- size_t B = stack[stack_curr - 3 ].length ;
454- size_t C = stack[stack_curr - 2 ].length ;
455- size_t D = stack[stack_curr - 1 ].length ;
493+ size_t B = stack[stack_size - 3 ].length ;
494+ size_t C = stack[stack_size - 2 ].length ;
495+ size_t D = stack[stack_size - 1 ].length ;
456496
457497 int ABC, BCD, CD;
458498
459- if (stack_curr >= 4 )
499+ if (stack_size >= 4 )
460500 {
461- A = stack[stack_curr - 4 ].length ;
501+ A = stack[stack_size - 4 ].length ;
462502 ABC = (A <= B + C);
463503 }
464504 else
@@ -478,21 +518,23 @@ namespace timsort
478518 /* left merge */
479519 if (BCD && !CD)
480520 {
481- tim_sort_merge (dst, stack, stack_curr - 1 , store);
482- stack[stack_curr - 3 ].length += stack[stack_curr - 2 ].length ;
483- stack[stack_curr - 2 ] = stack[stack_curr - 1 ];
484- stack_curr--;
521+ tim_sort_merge (dst, stack, stack_size - 1 , store);
522+ stack[stack_size - 3 ].length += stack[stack_size - 2 ].length ;
523+ stack[stack_size - 2 ] = stack[stack_size - 1 ];
524+ stack[stack_size - 1 ] = { 0 , 0 };
525+ stack_size--;
485526 }
486527 else
487528 {
488529 /* right merge */
489- tim_sort_merge (dst, stack, stack_curr, store);
490- stack[stack_curr - 2 ].length += stack[stack_curr - 1 ].length ;
491- stack_curr--;
530+ tim_sort_merge (dst, stack, stack_size, store);
531+ stack[stack_size - 2 ].length += stack[stack_size - 1 ].length ;
532+ stack[stack_size - 1 ] = { 0 , 0 };
533+ stack_size--;
492534 }
493535 }
494536
495- return stack_curr ;
537+ return stack_size ;
496538 }
497539
498540 template <class T >
@@ -501,36 +543,49 @@ namespace timsort
501543 TEMP_STORAGE_T<T>* store,
502544 const size_t minrun,
503545 TIM_SORT_RUN_T* run_stack,
504- size_t * stack_curr ,
546+ size_t * stack_size ,
505547 size_t * curr)
506548 {
549+
550+ if (dst == nullptr ||
551+ store == nullptr ||
552+ run_stack == nullptr ||
553+ stack_size == nullptr ||
554+ curr == nullptr )
555+ {
556+ return 0 ;
557+ }
558+
507559 size_t len = count_run (dst, *curr, size);
508560 size_t run = minrun;
509561
562+ /* If there is less than minrun left until the end of the array */
510563 if (run > size - *curr)
511564 {
512565 run = size - *curr;
513566 }
514567
568+ /* If the found sorted run is smaller than minrun,
569+ * we need to extend this segment by sorting the rest of the elements to match the run size */
515570 if (run > len)
516571 {
517572 binary_insertion_sort_start (&dst[*curr], len, run);
518573 len = run;
519574 }
520575
521- run_stack[*stack_curr ].start = *curr;
522- run_stack[*stack_curr ].length = len;
523- (*stack_curr )++;
576+ run_stack[*stack_size ].start = *curr;
577+ run_stack[*stack_size ].length = len;
578+ (*stack_size )++;
524579 *curr += len;
525580
526581 if (*curr == size)
527582 {
528583 /* finish up */
529- while (*stack_curr > 1 )
584+ while (*stack_size > 1 )
530585 {
531- tim_sort_merge (dst, run_stack, static_cast <int >(*stack_curr ), store);
532- run_stack[*stack_curr - 2 ].length += run_stack[*stack_curr - 1 ].length ;
533- (*stack_curr )--;
586+ tim_sort_merge (dst, run_stack, static_cast <int >(*stack_size ), store);
587+ run_stack[*stack_size - 2 ].length += run_stack[*stack_size - 1 ].length ;
588+ (*stack_size )--;
534589 }
535590
536591 if (store->storage )
@@ -550,6 +605,11 @@ namespace timsort
550605 template <class T >
551606 inline void binary_insertion_sort (T* dst, const size_t size)
552607 {
608+ if (dst == nullptr )
609+ {
610+ return ;
611+ }
612+
553613 /* don't bother sorting an array of size <= 1 */
554614 if (size <= 1 )
555615 {
@@ -562,6 +622,11 @@ namespace timsort
562622 template <class T >
563623 inline void tim_sort (T* dst, const size_t size)
564624 {
625+ if (dst == nullptr )
626+ {
627+ return ;
628+ }
629+
565630 /* don't bother sorting an array of size 1 */
566631 if (size <= 1 )
567632 {
0 commit comments