66
77#include <stddef.h>
88#include <stdint.h>
9+ #include <stdlib.h>
910#include <sys/types.h>
1011#include <sys/util.h>
1112
12- typedef int (* comp3_t )(const void * , const void * , void * );
13-
1413/*
1514 * Normally parent is defined parent(k) = floor((k-1) / 2) but we can avoid a
1615 * divide by noticing that floor((k-1) / 2) = ((k - 1) >> 1).
@@ -32,7 +31,25 @@ typedef int (*comp3_t)(const void *, const void *, void *);
3231
3332#define A (k ) ((uint8_t *)base + size * (k))
3433
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 )
3653{
3754 int root ;
3855 int child ;
@@ -42,12 +59,12 @@ static void sift_down(void *base, int start, int end, size_t size, comp3_t comp,
4259 child = left (root );
4360
4461 /* if root < left */
45- if (comp ( A (swap ), A (child ), comp_arg ) < 0 ) {
62+ if (compare ( cmp , A (swap ), A (child )) < 0 ) {
4663 swap = child ;
4764 }
4865
4966 /* 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 ) {
5168 swap = right (root );
5269 }
5370
@@ -59,28 +76,51 @@ static void sift_down(void *base, int start, int end, size_t size, comp3_t comp,
5976 }
6077}
6178
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 )
6380{
6481 int start ;
6582
6683 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 );
6885 }
6986}
7087
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 )
7289{
7390 int end ;
7491
75- heapify (base , nmemb , size , comp , comp_arg );
92+ heapify (base , nmemb , size , cmp );
7693
7794 for (end = nmemb - 1 ; end > 0 ; -- end ) {
7895 byteswp (A (end ), A (0 ), size );
79- sift_down (base , 0 , end , size , comp , comp_arg );
96+ sift_down (base , 0 , end , size , cmp );
8097 }
8198}
8299
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 )
84102{
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 );
86126}
0 commit comments