src/core/sort_func.hpp
author rubidium
Wed, 09 Jul 2008 13:32:13 +0000
branchnoai
changeset 11126 72d4c9314c72
parent 11044 097ea3e7ec56
permissions -rw-r--r--
(svn r13684) [NoAI] -Sync: with trunk r13599:13683.
11044
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
     1
/* $Id$ */
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
     2
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
     3
/** @file sort_func.hpp Functions related to sorting operations. */
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
     4
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
     5
#ifndef SORT_FUNC_HPP
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
     6
#define SORT_FUNC_HPP
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
     7
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
     8
#include <stdlib.h>
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
     9
#include "math_func.hpp"
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    10
#include "mem_func.hpp"
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    11
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    12
/**
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    13
 * Type safe qsort()
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    14
 *
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    15
 * @todo replace the normal qsort with this one
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    16
 * @note Use this sort for irregular sorted data.
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    17
 *
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    18
 * @param base Pointer to the first element of the array to be sorted.
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    19
 * @param num Number of elements in the array pointed by base.
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    20
 * @param comparator Function that compares two elements.
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    21
 * @param desc Sort descending.
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    22
 */
11126
72d4c9314c72 (svn r13684) [NoAI] -Sync: with trunk r13599:13683.
rubidium
parents: 11044
diff changeset
    23
template <typename T>
72d4c9314c72 (svn r13684) [NoAI] -Sync: with trunk r13599:13683.
rubidium
parents: 11044
diff changeset
    24
static FORCEINLINE void QSortT(T *base, uint num, int (CDECL *comparator)(const T*, const T*), bool desc = false)
11044
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    25
{
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    26
	if (num < 2) return;
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    27
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    28
	qsort(base, num, sizeof(T), (int (CDECL *)(const void *, const void *))comparator);
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    29
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    30
	if (desc) MemReverseT(base, num);
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    31
}
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    32
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    33
/**
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    34
 * Type safe Gnome Sort.
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    35
 *
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    36
 * This is a slightly modifyied Gnome search. The basic
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    37
 * Gnome search trys to sort already sorted list parts.
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    38
 * The modification skips these.
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    39
 *
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    40
 * @note Use this sort for presorted / regular sorted data.
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    41
 *
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    42
 * @param base Pointer to the first element of the array to be sorted.
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    43
 * @param num Number of elements in the array pointed by base.
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    44
 * @param comparator Function that compares two elements.
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    45
 * @param desc Sort descending.
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    46
 */
11126
72d4c9314c72 (svn r13684) [NoAI] -Sync: with trunk r13599:13683.
rubidium
parents: 11044
diff changeset
    47
template <typename T>
72d4c9314c72 (svn r13684) [NoAI] -Sync: with trunk r13599:13683.
rubidium
parents: 11044
diff changeset
    48
static inline void GSortT(T *base, uint num, int (CDECL *comparator)(const T*, const T*), bool desc = false)
11044
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    49
{
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    50
	if (num < 2) return;
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    51
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    52
	assert(base != NULL);
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    53
	assert(comparator != NULL);
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    54
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    55
	T *a = base;
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    56
	T *b = base + 1;
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    57
	uint offset = 0;
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    58
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    59
	while (num > 1) {
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    60
		const int diff = comparator(a, b);
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    61
		if ((!desc && diff <= 0) || (desc && diff >= 0)) {
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    62
			if (offset != 0) {
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    63
				/* Jump back to the last direction switch point */
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    64
				a += offset;
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    65
				b += offset;
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    66
				offset = 0;
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    67
				continue;
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    68
			}
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    69
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    70
			a++;
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    71
			b++;
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    72
			num--;
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    73
		} else {
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    74
			Swap(*a, *b);
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    75
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    76
			if (a == base) continue;
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    77
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    78
			a--;
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    79
			b--;
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    80
			offset++;
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    81
		}
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    82
	}
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    83
}
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    84
097ea3e7ec56 (svn r13600) [NoAI] -Sync: with trunk r13508:13599.
rubidium
parents:
diff changeset
    85
#endif /* SORT_FUNC_HPP */