feat: taken qsort from PDCLIB, Sorting drivers. Generic driver
structure. Driver ranking
This commit is contained in:
@@ -30,8 +30,8 @@ int abs(int val) {
|
||||
}
|
||||
|
||||
// next stolen form https://www.techiedelight.com/implement-itoa-function-in-c/
|
||||
// inline function to swap two numbers
|
||||
void swap(char *x, char *y) {
|
||||
// inline function to swapc two numbers
|
||||
void swapc(char *x, char *y) {
|
||||
char t = *x;
|
||||
*x = *y;
|
||||
*y = t;
|
||||
@@ -40,7 +40,7 @@ void swap(char *x, char *y) {
|
||||
// function to reverse buffer[i..j]
|
||||
char *reverse(char *buffer, int i, int j) {
|
||||
while (i < j)
|
||||
swap(&buffer[i++], &buffer[j--]);
|
||||
swapc(&buffer[i++], &buffer[j--]);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
129
kernel/libc/sort.c
Normal file
129
kernel/libc/sort.c
Normal file
@@ -0,0 +1,129 @@
|
||||
//
|
||||
// Created by rick on 06-03-21.
|
||||
//
|
||||
|
||||
#include "sort.h"
|
||||
#include "libc.h"
|
||||
#include <types.h>
|
||||
|
||||
// taken from https://github.com/DevSolar/pdclib/blob/master/functions/stdlib/qsort.c
|
||||
|
||||
/* This implementation is taken from Paul Edward's PDPCLIB.
|
||||
Original code is credited to Raymond Gardner, Englewood CO.
|
||||
Minor mods are credited to Paul Edwards.
|
||||
Some reformatting and simplification done by Martin Baute.
|
||||
All code is still Public Domain.
|
||||
*/
|
||||
|
||||
static inline void memswp(uint8_t *i, uint8_t *j, size_t size) {
|
||||
uint8_t tmp[size];
|
||||
memcpy(tmp, j, size);
|
||||
memcpy(j, i, size);
|
||||
memcpy(i, tmp, size);
|
||||
}
|
||||
|
||||
/* For small sets, insertion sort is faster than quicksort.
|
||||
T is the threshold below which insertion sort will be used.
|
||||
Must be 3 or larger.
|
||||
*/
|
||||
#define T 7
|
||||
|
||||
/* Macros for handling the QSort stack */
|
||||
#define PREPARE_STACK void * stack[STACKSIZE]; void ** stackptr = stack
|
||||
#define PUSH(base, limit) stackptr[0] = base; stackptr[1] = limit; stackptr += 2
|
||||
#define POP(base, limit) stackptr -= 2; (base) = stackptr[0]; (limit) = stackptr[1]
|
||||
/* TODO: Stack usage is log2( nmemb ) (minus what T shaves off the worst case).
|
||||
Worst-case nmemb is platform dependent and should probably be
|
||||
configured through _PDCLIB_config.h.
|
||||
*/
|
||||
#define STACKSIZE 64
|
||||
|
||||
void qsort(void *base, size_t nmemb, size_t size, int ( *compar )(const void *, const void *)) {
|
||||
void *i;
|
||||
void *j;
|
||||
size_t thresh = T * size;
|
||||
void *base_ = base;
|
||||
void *limit = base_ + nmemb * size;
|
||||
PREPARE_STACK;
|
||||
|
||||
for (;;) {
|
||||
if ((size_t) (limit - base_) > thresh) /* QSort for more than T elements. */
|
||||
{
|
||||
/* We work from second to last - first will be pivot element. */
|
||||
i = base_ + size;
|
||||
j = limit - size;
|
||||
/* We swap first with middle element, then sort that with second
|
||||
and last element so that eventually first element is the median
|
||||
of the three - avoiding pathological pivots.
|
||||
TODO: Instead of middle element, chose one randomly.
|
||||
*/
|
||||
memswp(((((size_t) (limit - base_)) / size) / 2) * size + base_, base_, size);
|
||||
|
||||
if (compar(i, j) > 0) {
|
||||
memswp(i, j, size);
|
||||
}
|
||||
|
||||
if (compar(base_, j) > 0) {
|
||||
memswp(base_, j, size);
|
||||
}
|
||||
|
||||
if (compar(i, base_) > 0) {
|
||||
memswp(i, base_, size);
|
||||
}
|
||||
|
||||
/* Now we have the median for pivot element, entering main Quicksort. */
|
||||
for (;;) {
|
||||
do {
|
||||
/* move i right until *i >= pivot */
|
||||
i += size;
|
||||
} while (compar(i, base_) < 0);
|
||||
|
||||
do {
|
||||
/* move j left until *j <= pivot */
|
||||
j -= size;
|
||||
} while (compar(j, base_) > 0);
|
||||
|
||||
if (i > j) {
|
||||
/* break loop if pointers crossed */
|
||||
break;
|
||||
}
|
||||
|
||||
/* else swap elements, keep scanning */
|
||||
memswp(i, j, size);
|
||||
}
|
||||
|
||||
/* move pivot into correct place */
|
||||
memswp(base_, j, size);
|
||||
|
||||
/* larger subfile base / limit to stack, sort smaller */
|
||||
if (j - base_ > limit - i) {
|
||||
/* left is larger */
|
||||
PUSH(base_, j);
|
||||
base_ = i;
|
||||
} else {
|
||||
/* right is larger */
|
||||
PUSH(i, limit);
|
||||
limit = j;
|
||||
}
|
||||
} else /* insertion sort for less than T elements */
|
||||
{
|
||||
for (j = base_, i = j + size; i < limit; j = i, i += size) {
|
||||
for (; compar(j, j + size) > 0; j -= size) {
|
||||
memswp(j, j + size, size);
|
||||
|
||||
if (j == base_) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stackptr != stack) /* if any entries on stack */
|
||||
{
|
||||
POP(base_, limit);
|
||||
} else /* else stack empty, done */
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
kernel/libc/sort.h
Normal file
11
kernel/libc/sort.h
Normal file
@@ -0,0 +1,11 @@
|
||||
//
|
||||
// Created by rick on 06-03-21.
|
||||
//
|
||||
|
||||
#ifndef NEW_KERNEL_SORT_H
|
||||
#define NEW_KERNEL_SORT_H
|
||||
#include <types.h>
|
||||
|
||||
void qsort(void *base, size_t num, size_t size, int (*compar)(const void *, const void *));
|
||||
|
||||
#endif //NEW_KERNEL_SORT_H
|
||||
Reference in New Issue
Block a user