6
6
7
7
#include <stddef.h>
8
8
#include <stdint.h>
9
+ #include <stdlib.h>
9
10
#include <sys/types.h>
10
11
#include <sys/util.h>
11
12
12
- typedef int (* comp3_t )(const void * , const void * , void * );
13
-
14
13
/*
15
14
* Normally parent is defined parent(k) = floor((k-1) / 2) but we can avoid a
16
15
* divide by noticing that floor((k-1) / 2) = ((k - 1) >> 1).
@@ -32,7 +31,25 @@ typedef int (*comp3_t)(const void *, const void *, void *);
32
31
33
32
#define A (k ) ((uint8_t *)base + size * (k))
34
33
35
- static void sift_down (void * base , int start , int end , size_t size , comp3_t comp , void * comp_arg )
34
+ struct qsort_comp {
35
+ bool has3 ;
36
+ void * arg ;
37
+ union {
38
+ int (* comp2 )(const void * a , const void * b );
39
+ int (* comp3 )(const void * a , const void * b , void * arg );
40
+ };
41
+ };
42
+
43
+ static inline int compare (struct qsort_comp * cmp , void * a , void * b )
44
+ {
45
+ if (cmp -> has3 ) {
46
+ return cmp -> comp3 (a , b , cmp -> arg );
47
+ }
48
+
49
+ return cmp -> comp2 (a , b );
50
+ }
51
+
52
+ static void sift_down (void * base , int start , int end , size_t size , struct qsort_comp * cmp )
36
53
{
37
54
int root ;
38
55
int child ;
@@ -42,12 +59,12 @@ static void sift_down(void *base, int start, int end, size_t size, comp3_t comp,
42
59
child = left (root );
43
60
44
61
/* if root < left */
45
- if (comp ( A (swap ), A (child ), comp_arg ) < 0 ) {
62
+ if (compare ( cmp , A (swap ), A (child )) < 0 ) {
46
63
swap = child ;
47
64
}
48
65
49
66
/* right exists and min(A(root),A(left)) < A(right) */
50
- if (right (root ) < end && comp ( A (swap ), A (right (root )), comp_arg ) < 0 ) {
67
+ if (right (root ) < end && compare ( cmp , A (swap ), A (right (root ))) < 0 ) {
51
68
swap = right (root );
52
69
}
53
70
@@ -59,28 +76,51 @@ static void sift_down(void *base, int start, int end, size_t size, comp3_t comp,
59
76
}
60
77
}
61
78
62
- static void heapify (void * base , int nmemb , size_t size , comp3_t comp , void * comp_arg )
79
+ static void heapify (void * base , int nmemb , size_t size , struct qsort_comp * cmp )
63
80
{
64
81
int start ;
65
82
66
83
for (start = parent (nmemb - 1 ); start >= 0 ; -- start ) {
67
- sift_down (base , start , nmemb , size , comp , comp_arg );
84
+ sift_down (base , start , nmemb , size , cmp );
68
85
}
69
86
}
70
87
71
- static void heap_sort (void * base , int nmemb , size_t size , comp3_t comp , void * comp_arg )
88
+ static void heap_sort (void * base , int nmemb , size_t size , struct qsort_comp * cmp )
72
89
{
73
90
int end ;
74
91
75
- heapify (base , nmemb , size , comp , comp_arg );
92
+ heapify (base , nmemb , size , cmp );
76
93
77
94
for (end = nmemb - 1 ; end > 0 ; -- end ) {
78
95
byteswp (A (end ), A (0 ), size );
79
- sift_down (base , 0 , end , size , comp , comp_arg );
96
+ sift_down (base , 0 , end , size , cmp );
80
97
}
81
98
}
82
99
83
- void qsort_r (void * base , size_t nmemb , size_t size , comp3_t comp , void * arg )
100
+ void qsort_r (void * base , size_t nmemb , size_t size ,
101
+ int (* comp3 )(const void * a , const void * b , void * arg ), void * arg )
84
102
{
85
- heap_sort (base , nmemb , size , comp , arg );
103
+ struct qsort_comp cmp = {
104
+ .has3 = true,
105
+ .arg = arg ,
106
+ {
107
+ .comp3 = comp3
108
+ }
109
+ };
110
+
111
+ heap_sort (base , nmemb , size , & cmp );
112
+ }
113
+
114
+ void qsort (void * base , size_t nmemb , size_t size ,
115
+ int (* comp2 )(const void * a , const void * b ))
116
+ {
117
+ struct qsort_comp cmp = {
118
+ .has3 = false,
119
+ .arg = NULL ,
120
+ {
121
+ .comp2 = comp2
122
+ }
123
+ };
124
+
125
+ heap_sort (base , nmemb , size , & cmp );
86
126
}
0 commit comments