少年修仙传客户端基础资源
hch
2024-04-01 d01413b00ef631ac20347716b23818b0b811f65f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/**
 * \file
 * Quicksort.
 *
 * Copyright (C) 2013 Xamarin Inc
 *
 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
 */
 
#include "config.h"
 
#ifdef HAVE_SGEN_GC
 
#include "sgen/sgen-gc.h"
 
#define ELEM(i) \
    (((unsigned char*)array) + ((i) * element_size))
#define SET(i,j) \
    do memmove ((i), (j), element_size); while (0)
#define SWAP(i,j) \
    do { \
        size_t __i = (i), __j = (j); \
        if (__i != __j) { \
            SET (swap_tmp, ELEM (__i)); \
            SET (ELEM (__i), ELEM (__j)); \
            SET (ELEM (__j), swap_tmp); \
        } \
    } while (0)
 
static void
sgen_qsort_rec (
    void *const array,
    const size_t element_size,
    int (*compare) (const void *, const void *),
    ssize_t begin,
    ssize_t end,
    unsigned char *const pivot_tmp,
    unsigned char *const swap_tmp)
{
    ssize_t left, right, mid, pivot;
    while (begin < end) {
        left = begin;
        right = end;
        mid = begin + (end - begin) / 2;
 
        /* Choose median of 3 as pivot and pre-sort to avoid O(n^2) case.
         *
         * L --o--o----->
         *     |  |
         * M --o--|--o-->
         *        |  |
         * R -----o--o-->
         */
        if (compare (ELEM (mid), ELEM (left)) < 0)
            SWAP (mid, left);
        if (compare (ELEM (right), ELEM (left)) < 0)
            SWAP (right, left);
        if (compare (ELEM (right), ELEM (mid)) < 0)
            SWAP (right, mid);
        pivot = mid;
        SET (pivot_tmp, ELEM (pivot));
 
        /* Partition. */
        for (;;) {
            while (left <= right && compare (ELEM (left), pivot_tmp) <= 0)
                ++left;
            while (left <= right && compare (ELEM (right), pivot_tmp) > 0)
                --right;
            if (left > right)
                break;
            SWAP (left, right);
            if (pivot == right)
                pivot = left;
            ++left;
            --right;
        }
        SET (ELEM (pivot), ELEM (right));
        SET (ELEM (right), pivot_tmp);
        --right;
 
        /* Recursively sort shorter partition, loop on longer partition. */
        if (right - begin < end - left) {
            sgen_qsort_rec (
                array,
                element_size,
                compare,
                begin,
                right,
                pivot_tmp,
                swap_tmp);
            begin = left;
        } else {
            sgen_qsort_rec (
                array,
                element_size,
                compare,
                left,
                end,
                pivot_tmp,
                swap_tmp);
            end = right;
        }
    }
}
 
void sgen_qsort (
    void *const array,
    const size_t count,
    const size_t element_size,
    int (*compare) (const void *, const void *))
{
#ifndef _MSC_VER
    unsigned char pivot_tmp [element_size];
    unsigned char swap_tmp [element_size];
#else
    unsigned char *pivot_tmp = (unsigned char *)alloca (element_size);
    unsigned char *swap_tmp = (unsigned char *)alloca (element_size);
#endif
    sgen_qsort_rec (
        array,
        element_size,
        compare,
        0,
        (ssize_t)count - 1,
        pivot_tmp,
        swap_tmp);
}
 
#endif