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