 42c456ff81
			
		
	
	42c456ff81
	
	
	
		
			
			Use size_t to match n when building the bitmask for checking whether a rank is occupied, instead of the default signed int. Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
		
			
				
	
	
		
			85 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			85 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "cache.h"
 | |
| #include "mergesort.h"
 | |
| 
 | |
| /* Combine two sorted lists.  Take from `list` on equality. */
 | |
| static void *llist_merge(void *list, void *other,
 | |
| 			 void *(*get_next_fn)(const void *),
 | |
| 			 void (*set_next_fn)(void *, void *),
 | |
| 			 int (*compare_fn)(const void *, const void *))
 | |
| {
 | |
| 	void *result = list, *tail;
 | |
| 
 | |
| 	if (compare_fn(list, other) > 0) {
 | |
| 		result = other;
 | |
| 		goto other;
 | |
| 	}
 | |
| 	for (;;) {
 | |
| 		do {
 | |
| 			tail = list;
 | |
| 			list = get_next_fn(list);
 | |
| 			if (!list) {
 | |
| 				set_next_fn(tail, other);
 | |
| 				return result;
 | |
| 			}
 | |
| 		} while (compare_fn(list, other) <= 0);
 | |
| 		set_next_fn(tail, other);
 | |
| 	other:
 | |
| 		do {
 | |
| 			tail = other;
 | |
| 			other = get_next_fn(other);
 | |
| 			if (!other) {
 | |
| 				set_next_fn(tail, list);
 | |
| 				return result;
 | |
| 			}
 | |
| 		} while (compare_fn(list, other) > 0);
 | |
| 		set_next_fn(tail, list);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Perform an iterative mergesort using an array of sublists.
 | |
|  *
 | |
|  * n is the number of items.
 | |
|  * ranks[i] is undefined if n & 2^i == 0, and assumed empty.
 | |
|  * ranks[i] contains a sublist of length 2^i otherwise.
 | |
|  *
 | |
|  * The number of bits in a void pointer limits the number of objects
 | |
|  * that can be created, and thus the number of array elements necessary
 | |
|  * to be able to sort any valid list.
 | |
|  *
 | |
|  * Adding an item to this array is like incrementing a binary number;
 | |
|  * positional values for set bits correspond to sublist lengths.
 | |
|  */
 | |
| void *llist_mergesort(void *list,
 | |
| 		      void *(*get_next_fn)(const void *),
 | |
| 		      void (*set_next_fn)(void *, void *),
 | |
| 		      int (*compare_fn)(const void *, const void *))
 | |
| {
 | |
| 	void *ranks[bitsizeof(void *)];
 | |
| 	size_t n = 0;
 | |
| 	int i;
 | |
| 
 | |
| 	while (list) {
 | |
| 		void *next = get_next_fn(list);
 | |
| 		if (next)
 | |
| 			set_next_fn(list, NULL);
 | |
| 		for (i = 0; n & ((size_t)1 << i); i++)
 | |
| 			list = llist_merge(ranks[i], list, get_next_fn,
 | |
| 					   set_next_fn, compare_fn);
 | |
| 		n++;
 | |
| 		ranks[i] = list;
 | |
| 		list = next;
 | |
| 	}
 | |
| 
 | |
| 	for (i = 0; n; i++, n >>= 1) {
 | |
| 		if (!(n & 1))
 | |
| 			continue;
 | |
| 		if (list)
 | |
| 			list = llist_merge(ranks[i], list, get_next_fn,
 | |
| 					   set_next_fn, compare_fn);
 | |
| 		else
 | |
| 			list = ranks[i];
 | |
| 	}
 | |
| 	return list;
 | |
| }
 |