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
845 changes: 632 additions & 213 deletions internal/native/avx/native_amd64.s

Large diffs are not rendered by default.

859 changes: 639 additions & 220 deletions internal/native/avx2/native_amd64.s

Large diffs are not rendered by default.

881 changes: 668 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"
75 changes: 75 additions & 0 deletions native/sort.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#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 int _strcmp(const char *p,const char *q){
while(*p && *q && *p == *q) {
Copy link
Collaborator

@liuq19 liuq19 Jun 26, 2023

Choose a reason for hiding this comment

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

这里仍然可能有越界访问,例如 p 和 q 是完全相等的key,同时不以 '\0' 结尾,那么就会访问到越界的内存。可以先判断是否超过 key.len, 避免越界访问

Copy link
Author

Choose a reason for hiding this comment

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

thanks, i will fix that.

Copy link
Collaborator

Choose a reason for hiding this comment

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

ok, thanks

p++, q++;
}

return *p - *q;
}

static always_inline bool less(MapPair lhs, MapPair rhs) {
return _strcmp(lhs.key.buf, rhs.key.buf) < 0;
}

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;
}

}
89 changes: 89 additions & 0 deletions native/unittest/test_sort.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#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];

mpr[0].key.buf = "abcd";
mpr[0].key.len = 4;

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

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

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

mpr[4].key.buf = "abcd";
mpr[4].key.len = 4;

MapPair expect[5];
expect[0].key.buf = "测试字段";
expect[0].key.len = 0;

expect[1].key.buf = "";
expect[1].key.len = 4;

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

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

expect[4].key.buf = "abcdf";
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 = 5;

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

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

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);
}