alright, 5hrs of refactoring and remaking it because I was tired of the AI code breaking

This commit is contained in:
2026-07-18 18:04:56 -05:00
parent 5f1a2b2cea
commit d14fb980bb
13 changed files with 1509 additions and 1828 deletions
+1037
View File
File diff suppressed because it is too large Load Diff
+6
View File
@@ -0,0 +1,6 @@
#ifndef FOSSBENCH_BENCHMARK_H
#define FOSSBENCH_BENCHMARK_H
int fossbench_run(int verbose, int upload_mode, int system_check);
#endif
+316
View File
@@ -0,0 +1,316 @@
/* Upload results if the user wants to. */
static void json_escape(const char *src, char *dst, size_t cap)
{
size_t used = 0;
while (*src && used + 1 < cap) {
unsigned char c = (unsigned char)*src++;
const char *esc = NULL;
if (c == '\"') esc = "\\\"";
else if (c == '\\') esc = "\\\\";
else if (c == '\n') esc = "\\n";
else if (c == '\r') esc = "\\r";
else if (c == '\t') esc = "\\t";
if (esc) {
size_t n = strlen(esc); if (used + n >= cap) break;
memcpy(dst + used, esc, n); used += n;
} else if (c >= 0x20) dst[used++] = (char)c;
}
dst[used] = '\0';
}
#if !defined(_WIN32)
/* Load the certificates included with the program. */
static int load_embedded_ca_bundle(SSL_CTX *ctx)
{
X509_STORE *store = SSL_CTX_get_cert_store(ctx);
BIO *bio = BIO_new_mem_buf(fb_ca_bundle_pem, -1);
X509 *cert;
int loaded = 0;
if (!bio) return 0;
while ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) {
if (X509_STORE_add_cert(store, cert)) loaded++;
X509_free(cert);
}
BIO_free(bio);
ERR_clear_error(); /* Reaching the end sets an error, which is fine. */
return loaded > 0;
}
#endif
#if defined(_WIN32)
/* Check if WinHTTP found a certificate problem. */
static int is_winhttp_secure_error(DWORD err)
{
switch (err) {
case ERROR_WINHTTP_SECURE_CERT_DATE_INVALID:
case ERROR_WINHTTP_SECURE_CERT_CN_INVALID:
case ERROR_WINHTTP_SECURE_INVALID_CA:
case ERROR_WINHTTP_SECURE_CERT_REV_FAILED:
case ERROR_WINHTTP_SECURE_CHANNEL_ERROR:
case ERROR_WINHTTP_SECURE_INVALID_CERT:
case ERROR_WINHTTP_SECURE_CERT_REVOKED:
case ERROR_WINHTTP_SECURE_FAILURE:
case ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE:
case ERROR_WINHTTP_SECURE_FAILURE_PROXY:
return 1;
default:
return 0;
}
}
/* Send the request with Windows networking. */
static int winhttp_post(const char *host, const char *port, const char *path,
int use_tls, const char *payload, int payload_len,
const char *auth_header, int *out_status)
{
wchar_t whost[256], wpath[512], wheaders[700];
char header_buf[700];
HINTERNET hsession = NULL, hconnect = NULL, hrequest = NULL;
INTERNET_PORT wport = (INTERNET_PORT)atoi(port);
DWORD status = 0, status_size = sizeof(status);
int ok = 0;
if (MultiByteToWideChar(CP_UTF8, 0, host, -1, whost, sizeof whost / sizeof whost[0]) == 0 ||
MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, sizeof wpath / sizeof wpath[0]) == 0)
return 0;
snprintf(header_buf, sizeof(header_buf), "Content-Type: application/json\r\n%s", auth_header);
if (MultiByteToWideChar(CP_UTF8, 0, header_buf, -1, wheaders, sizeof wheaders / sizeof wheaders[0]) == 0)
return 0;
hsession = WinHttpOpen(L"fossbench", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
if (!hsession) {
fprintf(stderr, " upload error: cannot initialize WinHTTP\n");
return 0;
}
hconnect = WinHttpConnect(hsession, whost, wport, 0);
if (!hconnect) {
fprintf(stderr, " upload error: cannot connect to %s:%s\n", host, port);
goto done;
}
hrequest = WinHttpOpenRequest(hconnect, L"POST", wpath, NULL, WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
use_tls ? WINHTTP_FLAG_SECURE : 0);
if (!hrequest) {
fprintf(stderr, " upload error: cannot create HTTP request\n");
goto done;
}
if (!WinHttpSendRequest(hrequest, wheaders, (DWORD)-1L, (LPVOID)payload,
(DWORD)payload_len, (DWORD)payload_len, 0)) {
if (is_winhttp_secure_error(GetLastError()))
fprintf(stderr, " upload error: TLS connection or certificate verification failed\n");
else
fprintf(stderr, " upload error: send failed\n");
goto done;
}
if (!WinHttpReceiveResponse(hrequest, NULL)) {
if (is_winhttp_secure_error(GetLastError()))
fprintf(stderr, " upload error: TLS connection or certificate verification failed\n");
else
fprintf(stderr, " upload error: no server response\n");
goto done;
}
if (!WinHttpQueryHeaders(hrequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
WINHTTP_HEADER_NAME_BY_INDEX, &status, &status_size,
WINHTTP_NO_HEADER_INDEX)) {
fprintf(stderr, " upload error: no server response\n");
goto done;
}
*out_status = (int)status;
ok = 1;
done:
if (hrequest) WinHttpCloseHandle(hrequest);
if (hconnect) WinHttpCloseHandle(hconnect);
WinHttpCloseHandle(hsession);
return ok;
}
#endif
static int upload_results(const struct system_info *info, double score,
double singlecore_score, const struct result *multi,
const struct result *single, uint64_t duration_ms,
const struct background_metrics *background, const char *token)
{
char host[256], port[16], path[512], payload[16384];
char auth_header[600];
char cpu[512], model[512], os[512], compiler[256], kernel[256];
const char *base = FB_API_BASE_URL, *p, *slash, *colon;
int use_tls, status = 0, payload_len;
#if !defined(_WIN32)
char request[20000], response[512];
struct addrinfo hints, *addresses = NULL, *a;
SSL_CTX *tls_ctx = NULL;
SSL *tls = NULL;
int fd = -1, request_len;
#endif
if (!strncmp(base, "https://", 8)) {
use_tls = 1; p = base + 8; strcpy(port, "443");
} else if (!strncmp(base, "http://", 7)) {
use_tls = 0; p = base + 7; strcpy(port, "80");
} else {
fprintf(stderr, " upload error: unsupported URL scheme\n");
return 0;
}
slash = strchr(p, '/');
if (!slash) slash = p + strlen(p);
colon = memchr(p, ':', (size_t)(slash - p));
if (colon) {
size_t hn = (size_t)(colon - p), pn = (size_t)(slash - colon - 1);
if (hn >= sizeof(host) || pn == 0 || pn >= sizeof(port)) return 0;
memcpy(host, p, hn); host[hn] = '\0'; memcpy(port, colon + 1, pn); port[pn] = '\0';
} else {
size_t hn = (size_t)(slash - p); if (hn >= sizeof(host)) return 0;
memcpy(host, p, hn); host[hn] = '\0';
}
{
int base_path_len = (int)strlen(slash);
while (base_path_len > 0 && slash[base_path_len - 1] == '/') base_path_len--;
snprintf(path, sizeof(path), "%.*s/api/v1/submissions", base_path_len, slash);
}
json_escape(info->cpu, cpu, sizeof(cpu));
json_escape(info->model, model, sizeof(model));
json_escape(info->operating_system, os, sizeof(os));
json_escape(info->compiler, compiler, sizeof(compiler));
json_escape(info->kernel, kernel, sizeof(kernel));
/* The server still calls this field fossmark_version. */
payload_len = snprintf(payload, sizeof(payload),
"{\"cpu\":\"%s\",\"model\":\"%s\",\"cpu_cores\":%ld,\"cpu_threads\":%ld,"
"\"memory_mb\":%ld,\"operating_system\":\"%s\",\"compiler\":\"%s\","
"\"fossmark_version\":\"%s\",\"score\":%.17g,\"duration_ms\":%llu,"
"\"score_details\":{\"scoring_method\":\"weighted_geometric_mean\","
"\"target_score\":%.17g,\"multicore_score\":%.17g,\"singlecore_score\":%.17g,"
"\"minimum_test_seconds\":%.17g,\"repeats\":%d,"
"\"system_environment\":{\"kernel\":\"%s\",\"sample_seconds\":%d,"
"\"background_cpu_average_percent\":%.17g,\"background_cpu_peak_percent\":%.17g,"
"\"available_memory_mb\":%ld,\"process_count\":%ld},\"tests\":[",
cpu, model, info->cpu_cores, info->cpu_threads, info->memory_mb, os, compiler,
FB_VERSION, score, (unsigned long long)duration_ms, FB_TARGET_SCORE, score,
singlecore_score, MIN_SECONDS, REPEATS, kernel, background->samples,
background->average_cpu_percent, background->peak_cpu_percent,
background->available_memory_mb, background->process_count);
if (payload_len < 0 || (size_t)payload_len >= sizeof(payload)) return 0;
{
size_t used = (size_t)payload_len;
size_t i;
for (i = 0; i < NTESTS; i++) {
int n = snprintf(payload + used, sizeof(payload) - used,
"%s{\"name\":\"%s\",\"detail\":\"%s\",\"unit\":\"%s\","
"\"start_iterations\":%llu,\"work_per_iteration\":%.17g,"
"\"reference_rate\":%.17g,\"weight\":%.17g,"
"\"multicore\":{\"display_metric\":%.17g,\"rate\":%.17g,\"score\":%.17g,"
"\"seconds\":%.17g,\"iterations\":%llu,\"threads\":%d,\"checksum\":\"%llu\"},"
"\"singlecore\":{\"display_metric\":%.17g,\"rate\":%.17g,\"score\":%.17g,"
"\"seconds\":%.17g,\"iterations\":%llu,\"threads\":%d,\"checksum\":\"%llu\"}}",
i ? "," : "", tests[i].name, tests[i].detail, tests[i].unit,
(unsigned long long)tests[i].start_n, tests[i].work_per_n,
tests[i].ref_rate, tests[i].weight,
display_metric(&tests[i], &multi[i]), multi[i].rate, multi[i].score,
multi[i].seconds, (unsigned long long)multi[i].iters, multi[i].threads,
(unsigned long long)multi[i].checksum,
display_metric(&tests[i], &single[i]), single[i].rate, single[i].score,
single[i].seconds, (unsigned long long)single[i].iters, single[i].threads,
(unsigned long long)single[i].checksum);
if (n < 0 || (size_t)n >= sizeof(payload) - used) return 0;
used += (size_t)n;
}
if (used + 3 >= sizeof(payload)) return 0;
memcpy(payload + used, "]}}", 4);
payload_len = (int)(used + 3);
}
auth_header[0] = '\0';
if (token && token[0]) {
int n = snprintf(auth_header, sizeof(auth_header),
"Authorization: Bearer %s\r\n", token);
if (n < 0 || (size_t)n >= sizeof(auth_header)) {
fprintf(stderr, " upload error: API token too long\n");
return 0;
}
}
#if !defined(_WIN32)
request_len = snprintf(request, sizeof(request),
"POST %s HTTP/1.1\r\nHost: %s:%s\r\nContent-Type: application/json\r\n"
"Content-Length: %d\r\nConnection: close\r\n%s\r\n%s",
path, host, port, payload_len, auth_header, payload);
if (request_len < 0 || (size_t)request_len >= sizeof(request)) return 0;
memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; hints.ai_family = AF_UNSPEC;
if (getaddrinfo(host, port, &hints, &addresses) != 0) { fprintf(stderr, " upload error: cannot resolve %s\n", host); return 0; }
for (a = addresses; a; a = a->ai_next) {
fd = socket(a->ai_family, a->ai_socktype, a->ai_protocol);
if (fd >= 0 && connect(fd, a->ai_addr, a->ai_addrlen) == 0) break;
if (fd >= 0) close(fd);
fd = -1;
}
freeaddrinfo(addresses);
if (fd < 0) { fprintf(stderr, " upload error: cannot connect to %s:%s\n", host, port); return 0; }
if (use_tls) {
tls_ctx = SSL_CTX_new(TLS_client_method());
if (!tls_ctx) {
fprintf(stderr, " upload error: cannot initialize TLS trust store\n");
goto upload_failed;
}
SSL_CTX_set_default_verify_paths(tls_ctx); /* Try system certificates too. */
if (!load_embedded_ca_bundle(tls_ctx)) {
fprintf(stderr, " upload error: cannot initialize TLS trust store\n");
goto upload_failed;
}
SSL_CTX_set_verify(tls_ctx, SSL_VERIFY_PEER, NULL);
tls = SSL_new(tls_ctx);
if (!tls || !SSL_set_tlsext_host_name(tls, host) ||
!SSL_set1_host(tls, host) || !SSL_set_fd(tls, fd) ||
SSL_connect(tls) != 1) {
fprintf(stderr, " upload error: TLS connection or certificate verification failed\n");
goto upload_failed;
}
}
{
size_t sent = 0;
while (sent < (size_t)request_len) {
int n = use_tls ? SSL_write(tls, request + sent, (int)((size_t)request_len - sent)) :
(int)send(fd, request + sent, (size_t)request_len - sent, 0);
if (n <= 0) { fprintf(stderr, " upload error: send failed\n"); goto upload_failed; }
sent += (size_t)n;
}
}
{
int n = use_tls ? SSL_read(tls, response, sizeof(response) - 1) :
(int)recv(fd, response, sizeof(response) - 1, 0);
if (n <= 0) { fprintf(stderr, " upload error: no server response\n"); goto upload_failed; }
response[n] = '\0';
if (sscanf(response, "HTTP/%*s %d", &status) != 1) status = 0;
}
if (tls) { SSL_shutdown(tls); SSL_free(tls); }
if (tls_ctx) SSL_CTX_free(tls_ctx);
close(fd);
#else
if (!winhttp_post(host, port, path, use_tls, payload, payload_len, auth_header, &status))
return 0;
#endif
if (status == 401) {
fprintf(stderr, " upload failed: API token was rejected (HTTP 401)\n");
return 0;
}
if (status == 422) {
fprintf(stderr, " upload failed: server rejected the submission as invalid (HTTP 422)\n");
return 0;
}
if (status < 200 || status >= 300) { fprintf(stderr, " upload failed: server returned HTTP %d\n", status); return 0; }
if (token)
printf(" Results uploaded and published to your profile (HTTP %d).\n", status);
else
printf(" Results uploaded, pending administrator review (HTTP %d).\n", status);
return 1;
#if !defined(_WIN32)
upload_failed:
if (tls) SSL_free(tls);
if (tls_ctx) SSL_CTX_free(tls_ctx);
if (fd >= 0) close(fd);
return 0;
#endif
}
+2 -23
View File
@@ -1,26 +1,5 @@
/*
* Embedded CA trust bundle (fallback for upload_results() TLS).
*
* Statically linking against a machine's OpenSSL is not enough to verify
* TLS certificates on an arbitrary target machine: SSL_CTX_set_default_verify_paths()
* only works if OpenSSL's compiled-in default CA directory/file happens to exist on
* the machine running the binary - a path baked in wherever OpenSSL itself was built,
* not the release binary. That almost never matches the end user's machine (macOS has
* no such path at all outside Homebrew; Linux distros disagree on the location), so
* uploads failed with a TLS/certificate error on nearly every machine except the one
* that built the release binaries.
*
* This bundle is carried as a fallback trust source so upload_results() can verify
* fossbench.net's certificate chain unconditionally, without relying on the host having
* a usable system trust store. It is tried in addition to (not instead of) the system's
* own default verify paths, so locally-trusted/corporate CAs still work where present.
*
* Contents: the Mozilla CA root program's included/trusted certificate set, as shipped
* by the ca-certificates-mozilla distro package (/etc/ssl/certs/ca-certificates.crt),
* the same root program curl/Go/Python(certifi) bundle for the identical reason.
* Regenerate by re-running the script that produced this file against a current
* ca-certificates package; do this roughly yearly as roots rotate.
*/
/* Backup certificates for uploads.
* These come from Mozilla's CA list. */
#ifndef FB_CA_BUNDLE_H
#define FB_CA_BUNDLE_H
@@ -1,7 +1,7 @@
/*
* fossbench_x86_64.S - x86-64 (AMD64) CPU benchmark kernels
* fossbench-amd64.S - x86-64 (AMD64) CPU benchmark kernels
*
* The AMD64 counterpart to fossbench.S. Same nine routines, same contract: each
* The AMD64 counterpart to the ARM64 backend. Same nine routines and contract: each
* is a pure function of its arguments under the System V AMD64 ABI, contains no
* syscalls, no libc calls and no external data relocations, so it assembles and
* runs on Linux (ELF), macOS (Mach-O) and the BSDs. The portable C driver in
@@ -1,5 +1,5 @@
/*
* fossbench.S - AArch64 CPU benchmark kernels
* fossbench-arm64.S - AArch64 CPU benchmark kernels
*
* OS-independent: contains no syscalls, no libc calls, no relocations against
* external data. Every routine is a pure function of its arguments under the
@@ -1,7 +1,7 @@
/*
* fossbench_i386.S - x86 32-bit (i386) CPU benchmark kernels
* fossbench-i386.S - x86 32-bit (i386) CPU benchmark kernels
*
* The i386 counterpart to fossbench_x86_64.S. Same nine routines, same
* The i386 counterpart to the AMD64 backend. Same nine routines, same
* contract: each is a pure function of its arguments, contains no syscalls,
* no libc calls and no external data relocations, so it assembles and runs
* unmodified under the plain i386 SysV (cdecl) ABI on Linux.
@@ -1,10 +1,4 @@
/*
* Portable kernel backend for big-endian PowerPC.
*
* Keeping this backend in C lets the compiler implement 64-bit arguments and
* returns according to the platform ABI. All byte-oriented formats
* are decoded explicitly, so the code is correct on big-endian systems.
*/
/* PowerPC kernel code. */
#include <math.h>
#include <stddef.h>
#include <stdint.h>
@@ -80,9 +74,7 @@ static uint64_t fb_simd_scalar(uint64_t iters, void *memory)
#endif
#if defined(__powerpc64__)
/* The PowerPC 970 in every iMac G5 implements AltiVec. Using GCC's vector
* type here lets the compiler handle whichever PPC64 ELF ABI the system uses;
* both PPC64 ABIs differ from the PPC32 assembly convention below. */
/* The iMac G5 has AltiVec. */
typedef uint32_t fb_vec_u32 __attribute__((vector_size(16)));
uint64_t fb_simd(uint64_t iters, void *memory)
@@ -110,8 +102,7 @@ uint64_t fb_simd(uint64_t iters, void *memory)
return sum;
}
#else
/* These are kept in fossbench_ppc32_ext.S so this translation unit, and thus
* the executable's default code path, only requires baseline PPC32. */
/* The optional PowerPC code is in the assembly file. */
extern void fb_simd_ps_kernel(uint64_t iters, void *memory);
extern void fb_simd_vsx_kernel(uint64_t iters, void *memory);
extern void fb_simd_altivec_kernel(uint64_t iters, void *memory);
@@ -147,8 +138,7 @@ static int device_is_nintendo(void)
static fb_simd_kernel detect_simd_kernel(void)
{
/* Linux exposes these in AT_HWCAP on both 32- and 64-bit PowerPC.
* Spell out the ABI values instead of depending on kernel-only headers. */
/* Linux tells us which PowerPC features are available. */
#if defined(__linux__) && defined(AT_HWCAP)
const unsigned long hwcap = getauxval(AT_HWCAP);
const unsigned long has_altivec = 0x10000000UL;
@@ -1,5 +1,5 @@
/* Optional PPC32 extended-instruction kernels. No instruction in this file
* is reached until fossbench_ppc32.c has checked the device tree or AT_HWCAP.
* is reached until fossbench-powerpc.c has checked the device tree or AT_HWCAP.
* Arguments use the PPC32 ABI: iters in r3:r4 and memory in r5. */
.text
+8 -1460
View File
File diff suppressed because it is too large Load Diff
+28 -65
View File
@@ -1,21 +1,4 @@
/*
* test_kernels.c - correctness checks for the fossbench assembly kernels
*
* The benchmark's own best-of-N run guards against non-determinism, but a
* kernel can be perfectly deterministic and still wrong. This file is the
* "single C file to poke at and test with": it validates each kernel against
* an independent reference or an invariant, so a mistake in the assembly is
* caught here rather than silently skewing a score.
*
* Every check (except the single-threaded pointer-chase) is run concurrently
* on all available cores. The kernels take their buffers as arguments and hold
* no shared state, so a correct kernel must give identical, correct results no
* matter how many copies run at once; a hidden global or a reentrancy bug would
* survive a single-threaded run but fail here.
*
* Build: cc -O2 -pthread test_kernels.c fossbench.S -o test_kernels -lm
* Exit status is 0 iff every check passes.
*/
/* The actual tests. */
#include <stdio.h>
#include <stdlib.h>
@@ -40,14 +23,7 @@ extern uint64_t fb_chase(void **ptrs, uint64_t steps);
static int failures = 0;
static int checks = 0;
/*
* Concurrency plumbing. Each check runs on every core at once; the counters and
* stdout are shared, so ok()/note() serialise on this lock. `fb_primary` is set
* on exactly one thread per check (the one running on the main thread): it owns
* the human-readable output so the "[ ok ]" lines and diagnostics appear once,
* not once per core. Every thread still evaluates every assertion, so a failure
* on any core - even a silent secondary - is reported and counted.
*/
/* Concurrency plumbing. */
static pthread_mutex_t io_lock = PTHREAD_MUTEX_INITIALIZER;
static __thread int fb_primary = 1;
static long fb_ncores = 1;
@@ -64,14 +40,14 @@ static void ok(const char *what, int cond)
failures++;
}
} else if (!cond) {
/* a secondary core disagrees: surface it explicitly */
/* Show if another thread failed. */
printf(" [FAIL] %s (concurrent core)\n", what);
failures++;
}
pthread_mutex_unlock(&io_lock);
}
/* Diagnostic output that should appear once per check, not once per core. */
/* Only print this once. */
static void note(const char *fmt, ...)
{
va_list ap;
@@ -85,8 +61,7 @@ static void note(const char *fmt, ...)
pthread_mutex_unlock(&io_lock);
}
/* Run `check` on every core simultaneously. The main thread is the primary;
* fb_ncores-1 workers run the same check as silent secondaries. */
/* Run the same check on every core. */
static void *fb_worker(void *arg)
{
void (*check)(void) = *(void (**)(void))arg;
@@ -112,14 +87,14 @@ static void parallel(void (*check)(void))
}
}
check(); /* primary runs on this thread */
check(); /* Run the first check here. */
for (i = 0; i < spawned; i++)
pthread_join(th[i], NULL);
free(th);
}
/* ---------- reference implementations ---------- */
/* Small C versions used for comparison. */
static uint64_t ref_prime_count(uint64_t limit)
{
@@ -137,9 +112,7 @@ static uint64_t ref_prime_count(uint64_t limit)
return count;
}
/* A textbook scalar ChaCha20 block function, used both to anchor against the
* RFC 8439 known-answer vector and to validate the NEON kernel block-for-block.
* `out` receives 64 keystream bytes for the given counter and 12-byte nonce. */
/* Basic ChaCha20 used to check the kernel. */
#define ROTL32(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
static void ref_chacha_block(uint32_t out_words[16], const uint8_t key[32],
@@ -180,12 +153,11 @@ static void ref_chacha_block(uint32_t out_words[16], const uint8_t key[32],
out_words[i] = x[i] + s[i];
}
/* ---------- checks ---------- */
/* The actual tests. */
static void check_int(void)
{
/* determinism and non-triviality: the checksum must be stable and
* must actually change with the iteration count */
/* The actual tests. */
uint64_t a = fb_int_math(1000);
uint64_t b = fb_int_math(1000);
uint64_t c = fb_int_math(2000);
@@ -217,7 +189,7 @@ static void check_primes(void)
note(" primes < %d: got %llu, expected %llu\n",
LIM, (unsigned long long)got, (unsigned long long)ref);
ok("primes matches reference sieve", got == ref);
ok("primes < 10 == 4", fb_primes(10, sieve) == 4); /* 2,3,5,7 */
ok("primes < 10 == 4", fb_primes(10, sieve) == 4); /* The primes are 2, 3, 5, and 7. */
ok("primes < 2 == 0", fb_primes(2, sieve) == 0);
free(sieve);
}
@@ -244,8 +216,7 @@ static void check_compress(void)
uint64_t incompressible, compressible;
size_t i;
/* genuinely incompressible data (splitmix64 output): with no matches
* to exploit, an LZ coder's output must be at least the input size */
/* Random data should not compress much. */
{
uint64_t st = 0x1234567890abcdefULL;
for (i = 0; i < N; i++) {
@@ -257,7 +228,7 @@ static void check_compress(void)
}
incompressible = fb_compress(src, N, ht);
/* all-zero data is maximally compressible: it must shrink hugely */
/* Zeros should compress a lot. */
memset(src, 0, N);
compressible = fb_compress(src, N, ht);
@@ -276,9 +247,7 @@ static void check_crypto(void)
uint8_t key[32];
size_t i;
/* (1) anchor the scalar reference to the RFC 8439 s.2.3.2 vector:
* key = 00,01,...,1f; counter = 1; nonce = 00,00,00,09,...,4a,...
* serialised keystream begins 10 f1 e7 e4. */
/* Check the C version with the RFC example. */
{
uint32_t w[16];
uint8_t rnonce[12] = {0,0,0,9, 0,0,0,0x4a, 0,0,0,0};
@@ -296,9 +265,7 @@ static void check_crypto(void)
ks0[2] == 0xe7 && ks0[3] == 0xe4);
}
/* (2) validate the NEON kernel against that reference. The kernel
* hardwires nonce = 0 and starts the block counter at 0, so we
* compare its keystream to the reference block-for-block. */
/* Compare the kernel with the C version. */
{
uint8_t buf[128];
uint8_t zero_nonce[12] = {0};
@@ -307,7 +274,7 @@ static void check_crypto(void)
for (i = 0; i < 32; i++)
key[i] = (uint8_t)(i * 5 + 1);
memset(buf, 0, sizeof buf); /* zeros -> raw keystream */
memset(buf, 0, sizeof buf); /* Zeros give the keystream. */
fb_chacha20(buf, sizeof buf, key, 1);
ref_chacha_block(ref0, key, 0, zero_nonce);
@@ -327,7 +294,7 @@ static void check_crypto(void)
ok("NEON ChaCha20 matches scalar reference (2 blocks)", match);
}
/* (3) the cipher is a real XOR stream: applying it twice is identity */
/* Running it twice should restore the data. */
{
uint8_t plain[128], work[128], k2[32];
for (i = 0; i < 128; i++)
@@ -345,18 +312,17 @@ static void check_crypto(void)
static void check_physics(void)
{
/* two equal masses released from rest must accelerate toward each
* other: symmetric, momentum-conserving, and bounded. */
/* The two bodies should move toward each other. */
double bodies[2 * 8] = {0};
double total_p;
bodies[0] = -1.0; bodies[3] = 1.0; /* body 0 at x=-1, mass 1 */
bodies[8] = 1.0; bodies[11] = 1.0; /* body 1 at x=+1, mass 1 */
bodies[0] = -1.0; bodies[3] = 1.0; /* First body. */
bodies[8] = 1.0; bodies[11] = 1.0; /* Second body. */
fb_physics(bodies, 2, 200);
/* velocities must be equal and opposite (Newton's third law) */
total_p = bodies[4] + bodies[12]; /* vx0 + vx1 */
/* The velocities should cancel out. */
total_p = bodies[4] + bodies[12]; /* Add both x velocities. */
note(" 2-body: vx0=%.6f vx1=%.6f (sum should be ~0)\n",
bodies[4], bodies[12]);
ok("physics conserves momentum", fabs(total_p) < 1e-9);
@@ -396,13 +362,12 @@ static void check_sort(void)
s = fb_sort(a, N);
ok("sort produces sorted output", is_sorted(a, N));
/* multiset is preserved: sort the reference with the C library and
* compare element by element */
/* Compare it with the C library sort. */
qsort(b, N, sizeof(uint32_t), cmp_u32);
ok("sort is a permutation of the input",
memcmp(a, b, N * sizeof(uint32_t)) == 0);
/* already-sorted input stays sorted and gives the same checksum */
/* The actual tests. */
{
uint64_t s2 = fb_sort(a, N);
ok("sort is idempotent on sorted data",
@@ -416,8 +381,7 @@ static void check_sort(void)
static void check_chase(void)
{
/* build a tiny 4-node cycle by hand and confirm the walk returns to
* the start after exactly `n` steps (offset 0 relative to entry) */
/* Make a small pointer loop. */
void *nodes[4];
nodes[0] = &nodes[1];
@@ -425,11 +389,10 @@ static void check_chase(void)
nodes[2] = &nodes[3];
nodes[3] = &nodes[0];
/* 4 hops from &nodes[0] returns to &nodes[0]; fb_chase returns the
* final pointer minus the starting pointer, so a full loop gives 0 */
/* Four hops should return to the start. */
ok("chase completes a full cycle", fb_chase(nodes, 4) == 0);
ok("chase(0) is zero", fb_chase(nodes, 0) == 0);
/* one hop lands on &nodes[1], i.e. one pointer-width past the start */
/* One hop should move to the next pointer. */
ok("chase single hop offset",
fb_chase(nodes, 1) == (uint64_t)((char *)&nodes[1] - (char *)&nodes[0]));
}
@@ -453,7 +416,7 @@ int main(void)
printf("Encryption:\n"); parallel(check_crypto);
printf("Physics:\n"); parallel(check_physics);
printf("Sorting:\n"); parallel(check_sort);
/* the pointer chase is the single-threaded test: run it on one core */
/* Run the pointer test on one core. */
printf("Single-Threaded (chase):\n"); check_chase();
printf("\n=================================\n");