Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: insert sort and heap sort in sort.c #467

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
741 changes: 528 additions & 213 deletions internal/native/avx/native_amd64.s

Large diffs are not rendered by default.

735 changes: 525 additions & 210 deletions internal/native/avx2/native_amd64.s

Large diffs are not rendered by default.

761 changes: 548 additions & 213 deletions internal/native/sse/native_amd64.s

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion native/native.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@
#include "atof_eisel_lemire.c"
#include "atof_native.c"
#include "scanning.c"
#include "f32toa.c"
#include "f32toa.c"
#include "sort.c"
78 changes: 78 additions & 0 deletions native/sort.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#include <stdio.h>

#include "native.h"

typedef struct MapPair{
GoString key;
void* value;
} MapPair;

// swap elems in MapPair
void swap(MapPair* lhs, MapPair* rhs) {
MapPair temp;
temp = *lhs;
*lhs = *rhs;
*rhs = temp;
}

static always_inline size_t min(size_t x, size_t y) {
return x > y ? y : x;
}

static always_inline bool less(MapPair lhs, MapPair rhs) {
size_t index = 0;
size_t size = min(lhs.key.len, rhs.key.len);
while(index < size && *lhs.key.buf && *rhs.key.buf && *lhs.key.buf == *rhs.key.buf) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里比较长度之后,应该不用确认 *lhs.key.buf && *rhs.key.buf了,另外这里可以使用局部变量表示两个lhs.key.buf 和 rhs.key.buf。

lhs.key.buf++, rhs.key.buf++;
index++;
}

return *(unsigned char *)lhs.key.buf - *(unsigned char *)rhs.key.buf < 0;
liuq19 marked this conversation as resolved.
Show resolved Hide resolved
}

void heap_adjust(MapPair* kvs, size_t root, size_t end) {
for(size_t child=2*root + 1; child<=end; child = child*2 + 1) {
if(child < end && less(kvs[child], kvs[child+1])) {
child++;
}

if(!less(kvs[root], kvs[child])) {
break;
} else {
swap(&kvs[root], &kvs[child]);
root = child;
}
}
}

void heap_sort(MapPair* kvs, size_t n) {
if(n <= 1) {
return;
}

for(int i=(n-1)/2; i>=0; i--) {
heap_adjust(kvs, i, n-1);
}

for(int i=n-1; i>0; i--) {
swap(&kvs[i], &kvs[0]);
heap_adjust(kvs, 0, i-1);
}
}

void insert_sort(MapPair* kvs, size_t n) {
if(n <= 1) {
return;
}

for(size_t i=1; i<n; i++) {
MapPair temp = kvs[i];
int j=i-1;
while(j>=0 && less(temp, kvs[j])) {
kvs[j + 1] = kvs[j];
j--;
}
kvs[j+1] = temp;
}

}
104 changes: 104 additions & 0 deletions native/unittest/test_sort.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#include <assert.h>
#include <string.h>
#include "../sort.c"

void test_heap_sort(MapPair* input, MapPair* expect, int n) {
heap_sort(input, n);
for(int i=0; i<n; i++) {
assert(strcmp(input[i].key.buf, expect[i].key.buf) == 0);
}
}

void test_insert_sort(MapPair* input, MapPair* expect, int n) {
insert_sort(input, n);
for(int i=0; i<n; i++) {
assert(strcmp(input[i].key.buf, expect[i].key.buf) == 0);
}
}

int main() {
MapPair mpr[5];
char temp[6] = "abcdf";
mpr[0].key.buf = "abcd";
mpr[0].key.len = 5;

mpr[1].key.buf = "abcdf";
mpr[1].key.len = 6;

mpr[2].key.buf = "测试字段";
mpr[2].key.len = 13;

mpr[3].key.buf = "";
mpr[3].key.len = 1;

mpr[4].key.buf = temp;
mpr[4].key.len = 5;

MapPair expect[5];

expect[0].key.buf = "";
expect[0].key.len = 0;

expect[1].key.buf = "abcd";
expect[1].key.len = 5;

expect[2].key.buf = temp;
expect[2].key.len = 5;

expect[3].key.buf = "abcdf";
expect[3].key.len = 6;

expect[4].key.buf = "测试字段";
expect[4].key.len = 13;

MapPair mpr_2[5];
memcpy(mpr_2, mpr, 5 * sizeof(MapPair));

test_heap_sort(mpr, expect, 5);
test_insert_sort(mpr_2, expect, 5);

// test when n is a large number
MapPair mpr_n_heap[4096];
MapPair mpr_n_insert[4096];
MapPair expect_n[4096];
for(int i=0; i<4096; i++) {
mpr_n_heap[i].key.buf = "abcda";
mpr_n_heap[i].key.len = 6;

expect_n[i].key.buf = "abcda";
expect_n[i].key.len = 6;
}
mpr_n_heap[2000].key.buf = "";
mpr_n_heap[2000].key.len = 1;
mpr_n_heap[1000].key.buf = "aabb";
mpr_n_heap[1000].key.len = 5;
mpr_n_heap[3000].key.buf = "ss";
mpr_n_heap[3000].key.len = 3;
mpr_n_heap[4000].key.buf = "中文字符";
mpr_n_heap[4000].key.len = 13;
mpr_n_heap[4095].key.buf = "";
mpr_n_heap[4095].key.len = 1;

expect_n[0].key.buf = "";
expect_n[0].key.len = 1;
expect_n[1].key.buf = "";
expect_n[1].key.len = 1;
expect_n[2].key.buf = "aabb";
expect_n[2].key.len = 5;
expect_n[2000].key.buf = "abcda";
expect_n[2000].key.len = 6;
expect_n[1000].key.buf = "abcda";
expect_n[1000].key.len = 6;
expect_n[3000].key.buf = "abcda";
expect_n[3000].key.len = 6;
expect_n[4000].key.buf = "abcda";
expect_n[4000].key.len = 6;
expect_n[4094].key.buf = "ss";
expect_n[4094].key.len = 3;
expect_n[4095].key.buf = "中文字符";
expect_n[4095].key.len = 13;

memcpy(mpr_n_insert, mpr_n_heap, 4096 * sizeof(MapPair));
test_heap_sort(mpr_n_heap, expect_n, 4096);
test_insert_sort(mpr_n_insert, expect_n, 4096);
}