Skip to content
Merged

Dev #18

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 31 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,33 +1,54 @@
name: CI
name: PipeSort CI

on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
workflow_dispatch: {}

jobs:
build-and-test:
runs-on: ubuntu-latest

steps:
- name: Checkout
- name: Checkout repository
uses: actions/checkout@v4

- name: Install deps
- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y cmake ninja-build gcc clang
sudo apt-get install -y cmake ninja-build gcc

- name: Configure
run: cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
run: |
cmake -S . -B build \
-G Ninja \
-DCMAKE_BUILD_TYPE=Release

- name: Build
run: cmake --build build
run: |
cmake --build build

- name: Verify sorted output (correct list)
run: |
./build/test_all 200000 123 | tee result.txt

echo "Checking correctness..."
if grep -q "sorted: NO" result.txt; then
echo "❌ Sorting error detected"
exit 1
fi

if ! grep -q "sorted: YES" result.txt; then
echo "❌ No successful sort detected"
exit 1
fi

echo "✅ All lists sorted correctly"

- name: Run correctness (test_all)
- name: 5M benchmark vs qsort
if: github.event_name == 'workflow_dispatch'
run: |
./build/test_all 200000 123 | tee out.txt
# Fail if any sorter reports "sorted: NO"
! grep -q "sorted: NO" out.txt
./build/bench_u128_qsort 5000000 123

3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ add_library(pipesort_obj OBJECT
internal/pipe_sort_u256_idx_radix8.c
internal/pipe_sort_u512_idx_radix8.c
)
add_executable(bench_u128_qsort tests/bench_u128_qsort.c)
target_link_libraries(bench_u128_qsort PRIVATE pipesort)

target_include_directories(pipesort_obj PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
Expand All @@ -36,3 +38,4 @@ install(TARGETS pipesort
)

install(DIRECTORY include/pipesort/ DESTINATION include/pipesort FILES_MATCHING PATTERN "*.h")

90 changes: 90 additions & 0 deletions tests/bench_u128_qsort.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <time.h>

#include "../include/pipesort/pipesort.h" // psort_u128_t, psort_u128, psort_u128_is_sorted

static inline uint64_t xorshift64(uint64_t *s) {
uint64_t x = *s;
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
*s = x;
return x;
}

static int cmp_u128(const void *a, const void *b) {
const psort_u128_t *x = (const psort_u128_t *)a;
const psort_u128_t *y = (const psort_u128_t *)b;
if (x->hi < y->hi) return -1;
if (x->hi > y->hi) return 1;
if (x->lo < y->lo) return -1;
if (x->lo > y->lo) return 1;
return 0;
}

static double now_sec(void) {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (double)ts.tv_sec + (double)ts.tv_nsec * 1e-9;
}

int main(int argc, char **argv) {
int n = (argc > 1) ? atoi(argv[1]) : 5000000;
uint64_t seed = (argc > 2) ? (uint64_t)strtoull(argv[2], NULL, 10) : 123;

if (n <= 0) {
fprintf(stderr, "n must be > 0\n");
return 2;
}

printf("bench_u128_qsort: n=%d seed=%llu\n", n, (unsigned long long)seed);

psort_u128_t *a = (psort_u128_t *)malloc((size_t)n * sizeof(psort_u128_t));
psort_u128_t *b = (psort_u128_t *)malloc((size_t)n * sizeof(psort_u128_t));
if (!a || !b) {
fprintf(stderr, "malloc failed (n=%d)\n", n);
free(a); free(b);
return 2;
}

// Generate data
uint64_t s = seed ? seed : 1;
for (int i = 0; i < n; i++) {
a[i].hi = xorshift64(&s);
a[i].lo = xorshift64(&s);
}
memcpy(b, a, (size_t)n * sizeof(psort_u128_t));

// qsort
double t0 = now_sec();
qsort(a, (size_t)n, sizeof(psort_u128_t), cmp_u128);
double t1 = now_sec();

// psort_u128
double t2 = now_sec();
psort_u128(b, n);
double t3 = now_sec();

int ok_q = psort_u128_is_sorted(a, n);
int ok_p = psort_u128_is_sorted(b, n);

printf("qsort time: %.6f s sorted: %s\n", (t1 - t0), ok_q ? "YES" : "NO");
printf("psort_u128 time: %.6f s sorted: %s\n", (t3 - t2), ok_p ? "YES" : "NO");

if (!ok_q || !ok_p) {
fprintf(stderr, "ERROR: sort failed\n");
free(a); free(b);
return 1;
}

double speedup = (t1 - t0) / (t3 - t2);
printf("speedup (qsort/psort): %.3fx\n", speedup);

free(a);
free(b);
return 0;
}

Loading