-rw-r--r-- 50333 djbsort-20260127/command/djbsort-test.c raw
/* WARNING: auto-generated (by autogen/test); do not edit */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <assert.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/resource.h>
#include "crypto_uint8.h"
#include "crypto_uint32.h"
#include "crypto_uint64.h"
#include "crypto_declassify.h"
#include <djbsort.h> /* -ldjbsort */
static const char *targeto = 0;
static const char *targetp = 0;
static const char *targeti = 0;
static const char *targetn = 0;
static const char *targetoffset = 0;
static int ok = 1;
#define fail ((ok = 0),printf)
/* ----- valgrind support */
static int valgrind = 0;
static unsigned char valgrind_undefined_byte = 0;
static char *volatile valgrind_pointer = 0;
static char *valgrind_malloc_1(void)
{
char *x = (char *) malloc(1);
if (!x) abort();
*(char **volatile) &valgrind_pointer = x;
return valgrind_pointer;
}
static void valgrind_init(void)
{
char *e = getenv("valgrind_multiplier");
char *x;
if (!e) return;
x = valgrind_malloc_1();
valgrind_undefined_byte = x[0]+1;
valgrind_undefined_byte *= atoi(e);
valgrind_undefined_byte ^= x[0]+1;
free(x);
valgrind = 1;
}
static void secret(void *xvoid,long long xlen)
{
unsigned char *x = (unsigned char *) xvoid;
while (xlen > 0) {
*x ^= valgrind_undefined_byte;
++x;
--xlen;
}
}
static void declassify(void *x,long long xlen)
{
crypto_declassify(x,xlen);
}
/* ----- rng and hash, from supercop/try-anything.c */
typedef crypto_uint8 u8;
typedef crypto_uint32 u32;
typedef crypto_uint64 u64;
#define FOR(i,n) for (i = 0;i < n;++i)
static u32 L32(u32 x,int c) { return (x << c) | ((x&0xffffffff) >> (32 - c)); }
static u32 ld32(const u8 *x)
{
u32 u = x[3];
u = (u<<8)|x[2];
u = (u<<8)|x[1];
return (u<<8)|x[0];
}
static void st32(u8 *x,u32 u)
{
int i;
FOR(i,4) { x[i] = u; u >>= 8; }
}
static const u8 sigma[17] = "expand 32-byte k";
static void core_salsa(u8 *out,const u8 *in,const u8 *k)
{
u32 w[16],x[16],y[16],t[4];
int i,j,m;
FOR(i,4) {
x[5*i] = ld32(sigma+4*i);
x[1+i] = ld32(k+4*i);
x[6+i] = ld32(in+4*i);
x[11+i] = ld32(k+16+4*i);
}
FOR(i,16) y[i] = x[i];
FOR(i,20) {
FOR(j,4) {
FOR(m,4) t[m] = x[(5*j+4*m)%16];
t[1] ^= L32(t[0]+t[3], 7);
t[2] ^= L32(t[1]+t[0], 9);
t[3] ^= L32(t[2]+t[1],13);
t[0] ^= L32(t[3]+t[2],18);
FOR(m,4) w[4*j+(j+m)%4] = t[m];
}
FOR(m,16) x[m] = w[m];
}
FOR(i,16) st32(out + 4 * i,x[i] + y[i]);
}
static void salsa20(u8 *c,u64 b,const u8 *n,const u8 *k)
{
u8 z[16],x[64];
u32 u,i;
if (!b) return;
FOR(i,16) z[i] = 0;
FOR(i,8) z[i] = n[i];
while (b >= 64) {
core_salsa(x,z,k);
FOR(i,64) c[i] = x[i];
u = 1;
for (i = 8;i < 16;++i) {
u += (u32) z[i];
z[i] = u;
u >>= 8;
}
b -= 64;
c += 64;
}
if (b) {
core_salsa(x,z,k);
FOR(i,b) c[i] = x[i];
}
}
static void increment(u8 *n)
{
if (!++n[0])
if (!++n[1])
if (!++n[2])
if (!++n[3])
if (!++n[4])
if (!++n[5])
if (!++n[6])
if (!++n[7])
;
}
static unsigned char testvector_n[8];
static void testvector_mutate(unsigned long long seed)
{
const static unsigned char reseed[33] = "inject new seed for test vectors";
unsigned char tmp[32];
long long i;
salsa20(tmp,sizeof tmp,testvector_n,reseed);
for (i = 0;i < 8;++i) {
tmp[i] ^= seed;
seed >>= 8;
}
salsa20(testvector_n,sizeof testvector_n,testvector_n,tmp);
}
static void testvector(unsigned char *x,unsigned long long xlen)
{
const static unsigned char testvector_k[33] = "generate inputs for test vectors";
salsa20(x,xlen,testvector_n,testvector_k);
increment(testvector_n);
}
static unsigned long long myrandom(void)
{
unsigned char x[8];
unsigned long long result;
testvector(x,8);
result = x[7];
result = (result<<8)|x[6];
result = (result<<8)|x[5];
result = (result<<8)|x[4];
result = (result<<8)|x[3];
result = (result<<8)|x[2];
result = (result<<8)|x[1];
result = (result<<8)|x[0];
return result;
}
static unsigned char canary_n[8];
static void canary(unsigned char *x,unsigned long long xlen)
{
const static unsigned char canary_k[33] = "generate pad to catch overwrites";
salsa20(x,xlen,canary_n,canary_k);
increment(canary_n);
}
static void double_canary(unsigned char *x2,unsigned char *x,unsigned long long xlen)
{
if (valgrind) return;
canary(x - 16,16);
canary(x + xlen,16);
memcpy(x2 - 16,x - 16,16);
memcpy(x2 + xlen,x + xlen,16);
}
static void input_prepare(unsigned char *x2,unsigned char *x,unsigned long long xlen)
{
testvector(x,xlen);
if (valgrind) {
memcpy(x2,x,xlen);
return;
}
canary(x - 16,16);
canary(x + xlen,16);
memcpy(x2 - 16,x - 16,xlen + 32);
}
static void output_compare(const unsigned char *x2,const unsigned char *x,unsigned long long xlen,const char *fun)
{
if (valgrind) return;
if (memcmp(x2 - 16,x - 16,16)) {
fail("failure: %s writes before output\n",fun);
}
if (memcmp(x2 + xlen,x + xlen,16)) {
fail("failure: %s writes after output\n",fun);
}
}
/* ----- knownrandombytes */
static const int knownrandombytes_is_only_for_testing_not_for_cryptographic_use = 1;
extern void knownrandombytes(void *,long long);
#define QUARTERROUND(a,b,c,d) \
a += b; d = L32(d^a,16); \
c += d; b = L32(b^c,12); \
a += b; d = L32(d^a, 8); \
c += d; b = L32(b^c, 7);
static void core_chacha(u8 *out,const u8 *in,const u8 *k)
{
u32 x[16],y[16];
int i,j;
FOR(i,4) {
x[i] = ld32(sigma+4*i);
x[12+i] = ld32(in+4*i);
}
FOR(i,8) x[4+i] = ld32(k+4*i);
FOR(i,16) y[i] = x[i];
FOR(i,10) {
FOR(j,4) { QUARTERROUND(x[j],x[j+4],x[j+8],x[j+12]) }
FOR(j,4) { QUARTERROUND(x[j],x[((j+1)&3)+4],x[((j+2)&3)+8],x[((j+3)&3)+12]) }
}
FOR(i,16) st32(out+4*i,x[i]+y[i]);
}
static void chacha20(u8 *c,u64 b,const u8 *n,const u8 *k)
{
u8 z[16],x[64];
u32 u,i;
if (!b) return;
FOR(i,16) z[i] = 0;
FOR(i,8) z[i+8] = n[i];
while (b >= 64) {
core_chacha(x,z,k);
FOR(i,64) c[i] = x[i];
u = 1;
FOR(i,8) {
u += (u32) z[i];
z[i] = u;
u >>= 8;
}
b -= 64;
c += 64;
}
if (b) {
core_chacha(x,z,k);
FOR(i,b) c[i] = x[i];
}
}
#define crypto_rng_OUTPUTBYTES 736
static int crypto_rng(
unsigned char *r, /* random output */
unsigned char *n, /* new key */
const unsigned char *g /* old key */
)
{
static const unsigned char nonce[8] = {0};
unsigned char x[32+crypto_rng_OUTPUTBYTES];
chacha20(x,sizeof x,nonce,g);
memcpy(n,x,32);
memcpy(r,x+32,crypto_rng_OUTPUTBYTES);
return 0;
}
static unsigned char knownrandombytes_g[32];
static unsigned char knownrandombytes_r[crypto_rng_OUTPUTBYTES];
static unsigned long long knownrandombytes_pos = crypto_rng_OUTPUTBYTES;
void knownrandombytes_main(void *xvoid,long long xlen)
{
unsigned char *x = (unsigned char *) xvoid;
assert(knownrandombytes_is_only_for_testing_not_for_cryptographic_use);
while (xlen > 0) {
if (knownrandombytes_pos == crypto_rng_OUTPUTBYTES) {
crypto_rng(knownrandombytes_r,knownrandombytes_g,knownrandombytes_g);
knownrandombytes_pos = 0;
}
*x++ = knownrandombytes_r[knownrandombytes_pos];
xlen -= 1;
knownrandombytes_r[knownrandombytes_pos++] = 0;
}
}
void knownrandombytes(void *xvoid,long long xlen)
{
knownrandombytes_main(xvoid,xlen);
secret(xvoid,xlen);
}
/* ----- memory handling */
static void *callocplus(long long len)
{
if (valgrind) {
unsigned char *x = (unsigned char *) malloc(len);
if (!x) abort();
return x;
} else {
unsigned char *x = (unsigned char *) calloc(1,len + 256);
long long i;
if (!x) abort();
for (i = 0;i < len + 256;++i) x[i] = random();
return x;
}
}
static void *aligned(void *x,long long len)
{
if (valgrind)
return x;
else {
long long i;
unsigned char *y = (unsigned char *) x;
y += 64;
y += 63 & (-(unsigned long) y);
for (i = 0;i < len;++i) y[i] = 0;
return y;
}
}
/* ----- catching SIGILL, SIGBUS, SIGSEGV, etc. */
#include "limits.inc"
static void forked(void (*test)(long long),long long impl)
{
if (valgrind) {
test(impl);
return;
}
fflush(stdout);
pid_t child = fork();
int childstatus = -1;
if (child == -1) {
fprintf(stderr,"fatal: fork failed: %s",strerror(errno));
exit(111);
}
if (child == 0) {
ok = 1;
limits();
test(impl);
if (!ok) exit(100);
exit(0);
}
if (waitpid(child,&childstatus,0) != child) {
fprintf(stderr,"fatal: wait failed: %s",strerror(errno));
exit(111);
}
if (childstatus)
fail("failure: process failed, status %d\n",childstatus);
fflush(stdout);
}
/* ----- sorting */
static void *storage_sort_int32_x;
static unsigned char *test_sort_int32_x;
static void *storage_sort_int32_x2;
static unsigned char *test_sort_int32_x2;
static long long test_sort_int32_offset;
static int int32_cmp(const void *x,const void *y)
{
const int32_t a = *(int32_t *) x;
const int32_t b = *(int32_t *) y;
if (a < b) return -1;
if (a > b) return 1;
return 0;
}
static void test_sort_int32_impl(long long impl)
{
unsigned char *x = test_sort_int32_x;
unsigned char *x2 = test_sort_int32_x2;
long long xlen;
long long xwords;
void (*crypto_sort)(int32_t *,long long);
testvector_mutate(valgrind);
testvector_mutate(1);
testvector_mutate(impl);
testvector_mutate(test_sort_int32_offset);
if (targeti && strcmp(targeti,".") && strcmp(targeti,djbsort_dispatch_int32_implementation(impl))) return;
if (targetn && atol(targetn) != impl) return;
if (impl >= 0) {
crypto_sort = djbsort_dispatch_int32(impl);
printf("sort_int32 %lld implementation %s compiler %s\n",impl,djbsort_dispatch_int32_implementation(impl),djbsort_dispatch_int32_compiler(impl));
} else {
crypto_sort = djbsort_int32;
printf("sort_int32 selected implementation %s compiler %s\n",djbsort_int32_implementation(),djbsort_int32_compiler());
}
for (long long stage = 0;stage < 4;++stage) {
long long loops,maxtest;
switch(stage) {
case 0: loops = 1024; maxtest = 128; break;
case 1: loops = 4096; maxtest = 4096; break;
case 2: loops = 128; maxtest = 65536; break;
default: loops = 4; maxtest = 1048576; break;
}
for (long long loop = 0;loop < loops;++loop) {
int32_t *xs = (int32_t *) x;
xwords = myrandom() % (maxtest + 1);
xlen = 4*xwords;
input_prepare(x2,x,xlen);
secret(x,xlen);
crypto_sort(xs,xwords);
declassify(x,xlen);
output_compare(x2,x,xlen,"crypto_sort");
for (long long i = 1;i < xwords;++i)
if (int32_cmp(&xs[i-1],&xs[i]) > 0) {
fail("failure: crypto_sort output is not in order\n");
break;
}
double_canary(x2,x,xlen);
qsort(x2,xwords,4,int32_cmp);
output_compare(x2,x,xlen,"crypto_sort");
if (memcmp(x2,x,xlen) != 0) fail("failure: crypto_sort does not match qsort\n");
}
}
}
static void test_sort_int32(void)
{
if (targeto && strcmp(targeto,"sort")) return;
if (targetp && strcmp(targetp,"int32")) return;
storage_sort_int32_x = callocplus(4*1048576);
test_sort_int32_x = (unsigned char *) aligned(storage_sort_int32_x,4*1048576);
storage_sort_int32_x2 = callocplus(4*1048576);
test_sort_int32_x2 = (unsigned char *) aligned(storage_sort_int32_x2,4*1048576);
for (long long offset = 0;offset < 2;++offset) {
if (targetoffset && atol(targetoffset) != offset) continue;
if (offset && valgrind) break;
printf("sort_int32 offset %lld\n",offset);
test_sort_int32_offset = offset;
for (long long impl = -1;impl < djbsort_numimpl_int32();++impl)
forked(test_sort_int32_impl,impl);
test_sort_int32_x += 4;
test_sort_int32_x2 += 4;
}
free(storage_sort_int32_x2);
free(storage_sort_int32_x);
}
static void *storage_sort_int32down_x;
static unsigned char *test_sort_int32down_x;
static void *storage_sort_int32down_x2;
static unsigned char *test_sort_int32down_x2;
static long long test_sort_int32down_offset;
static int int32down_cmp(const void *x,const void *y)
{
const int32_t a = *(int32_t *) x;
const int32_t b = *(int32_t *) y;
if (a < b) return 1;
if (a > b) return -1;
return 0;
}
static void test_sort_int32down_impl(long long impl)
{
unsigned char *x = test_sort_int32down_x;
unsigned char *x2 = test_sort_int32down_x2;
long long xlen;
long long xwords;
void (*crypto_sort)(int32_t *,long long);
testvector_mutate(valgrind);
testvector_mutate(2);
testvector_mutate(impl);
testvector_mutate(test_sort_int32down_offset);
if (targeti && strcmp(targeti,".") && strcmp(targeti,djbsort_dispatch_int32down_implementation(impl))) return;
if (targetn && atol(targetn) != impl) return;
if (impl >= 0) {
crypto_sort = djbsort_dispatch_int32down(impl);
printf("sort_int32down %lld implementation %s compiler %s\n",impl,djbsort_dispatch_int32down_implementation(impl),djbsort_dispatch_int32down_compiler(impl));
} else {
crypto_sort = djbsort_int32down;
printf("sort_int32down selected implementation %s compiler %s\n",djbsort_int32down_implementation(),djbsort_int32down_compiler());
}
for (long long stage = 0;stage < 4;++stage) {
long long loops,maxtest;
switch(stage) {
case 0: loops = 1024; maxtest = 128; break;
case 1: loops = 4096; maxtest = 4096; break;
case 2: loops = 128; maxtest = 65536; break;
default: loops = 4; maxtest = 1048576; break;
}
for (long long loop = 0;loop < loops;++loop) {
int32_t *xs = (int32_t *) x;
xwords = myrandom() % (maxtest + 1);
xlen = 4*xwords;
input_prepare(x2,x,xlen);
secret(x,xlen);
crypto_sort(xs,xwords);
declassify(x,xlen);
output_compare(x2,x,xlen,"crypto_sort");
for (long long i = 1;i < xwords;++i)
if (int32down_cmp(&xs[i-1],&xs[i]) > 0) {
fail("failure: crypto_sort output is not in order\n");
break;
}
double_canary(x2,x,xlen);
qsort(x2,xwords,4,int32down_cmp);
output_compare(x2,x,xlen,"crypto_sort");
if (memcmp(x2,x,xlen) != 0) fail("failure: crypto_sort does not match qsort\n");
}
}
}
static void test_sort_int32down(void)
{
if (targeto && strcmp(targeto,"sort")) return;
if (targetp && strcmp(targetp,"int32down")) return;
storage_sort_int32down_x = callocplus(4*1048576);
test_sort_int32down_x = (unsigned char *) aligned(storage_sort_int32down_x,4*1048576);
storage_sort_int32down_x2 = callocplus(4*1048576);
test_sort_int32down_x2 = (unsigned char *) aligned(storage_sort_int32down_x2,4*1048576);
for (long long offset = 0;offset < 2;++offset) {
if (targetoffset && atol(targetoffset) != offset) continue;
if (offset && valgrind) break;
printf("sort_int32down offset %lld\n",offset);
test_sort_int32down_offset = offset;
for (long long impl = -1;impl < djbsort_numimpl_int32down();++impl)
forked(test_sort_int32down_impl,impl);
test_sort_int32down_x += 4;
test_sort_int32down_x2 += 4;
}
free(storage_sort_int32down_x2);
free(storage_sort_int32down_x);
}
static void *storage_sort_uint32_x;
static unsigned char *test_sort_uint32_x;
static void *storage_sort_uint32_x2;
static unsigned char *test_sort_uint32_x2;
static long long test_sort_uint32_offset;
static int uint32_cmp(const void *x,const void *y)
{
const uint32_t a = *(uint32_t *) x;
const uint32_t b = *(uint32_t *) y;
if (a < b) return -1;
if (a > b) return 1;
return 0;
}
static void test_sort_uint32_impl(long long impl)
{
unsigned char *x = test_sort_uint32_x;
unsigned char *x2 = test_sort_uint32_x2;
long long xlen;
long long xwords;
void (*crypto_sort)(uint32_t *,long long);
testvector_mutate(valgrind);
testvector_mutate(3);
testvector_mutate(impl);
testvector_mutate(test_sort_uint32_offset);
if (targeti && strcmp(targeti,".") && strcmp(targeti,djbsort_dispatch_uint32_implementation(impl))) return;
if (targetn && atol(targetn) != impl) return;
if (impl >= 0) {
crypto_sort = djbsort_dispatch_uint32(impl);
printf("sort_uint32 %lld implementation %s compiler %s\n",impl,djbsort_dispatch_uint32_implementation(impl),djbsort_dispatch_uint32_compiler(impl));
} else {
crypto_sort = djbsort_uint32;
printf("sort_uint32 selected implementation %s compiler %s\n",djbsort_uint32_implementation(),djbsort_uint32_compiler());
}
for (long long stage = 0;stage < 4;++stage) {
long long loops,maxtest;
switch(stage) {
case 0: loops = 1024; maxtest = 128; break;
case 1: loops = 4096; maxtest = 4096; break;
case 2: loops = 128; maxtest = 65536; break;
default: loops = 4; maxtest = 1048576; break;
}
for (long long loop = 0;loop < loops;++loop) {
uint32_t *xs = (uint32_t *) x;
xwords = myrandom() % (maxtest + 1);
xlen = 4*xwords;
input_prepare(x2,x,xlen);
secret(x,xlen);
crypto_sort(xs,xwords);
declassify(x,xlen);
output_compare(x2,x,xlen,"crypto_sort");
for (long long i = 1;i < xwords;++i)
if (uint32_cmp(&xs[i-1],&xs[i]) > 0) {
fail("failure: crypto_sort output is not in order\n");
break;
}
double_canary(x2,x,xlen);
qsort(x2,xwords,4,uint32_cmp);
output_compare(x2,x,xlen,"crypto_sort");
if (memcmp(x2,x,xlen) != 0) fail("failure: crypto_sort does not match qsort\n");
}
}
}
static void test_sort_uint32(void)
{
if (targeto && strcmp(targeto,"sort")) return;
if (targetp && strcmp(targetp,"uint32")) return;
storage_sort_uint32_x = callocplus(4*1048576);
test_sort_uint32_x = (unsigned char *) aligned(storage_sort_uint32_x,4*1048576);
storage_sort_uint32_x2 = callocplus(4*1048576);
test_sort_uint32_x2 = (unsigned char *) aligned(storage_sort_uint32_x2,4*1048576);
for (long long offset = 0;offset < 2;++offset) {
if (targetoffset && atol(targetoffset) != offset) continue;
if (offset && valgrind) break;
printf("sort_uint32 offset %lld\n",offset);
test_sort_uint32_offset = offset;
for (long long impl = -1;impl < djbsort_numimpl_uint32();++impl)
forked(test_sort_uint32_impl,impl);
test_sort_uint32_x += 4;
test_sort_uint32_x2 += 4;
}
free(storage_sort_uint32_x2);
free(storage_sort_uint32_x);
}
static void *storage_sort_uint32down_x;
static unsigned char *test_sort_uint32down_x;
static void *storage_sort_uint32down_x2;
static unsigned char *test_sort_uint32down_x2;
static long long test_sort_uint32down_offset;
static int uint32down_cmp(const void *x,const void *y)
{
const uint32_t a = *(uint32_t *) x;
const uint32_t b = *(uint32_t *) y;
if (a < b) return 1;
if (a > b) return -1;
return 0;
}
static void test_sort_uint32down_impl(long long impl)
{
unsigned char *x = test_sort_uint32down_x;
unsigned char *x2 = test_sort_uint32down_x2;
long long xlen;
long long xwords;
void (*crypto_sort)(uint32_t *,long long);
testvector_mutate(valgrind);
testvector_mutate(4);
testvector_mutate(impl);
testvector_mutate(test_sort_uint32down_offset);
if (targeti && strcmp(targeti,".") && strcmp(targeti,djbsort_dispatch_uint32down_implementation(impl))) return;
if (targetn && atol(targetn) != impl) return;
if (impl >= 0) {
crypto_sort = djbsort_dispatch_uint32down(impl);
printf("sort_uint32down %lld implementation %s compiler %s\n",impl,djbsort_dispatch_uint32down_implementation(impl),djbsort_dispatch_uint32down_compiler(impl));
} else {
crypto_sort = djbsort_uint32down;
printf("sort_uint32down selected implementation %s compiler %s\n",djbsort_uint32down_implementation(),djbsort_uint32down_compiler());
}
for (long long stage = 0;stage < 4;++stage) {
long long loops,maxtest;
switch(stage) {
case 0: loops = 1024; maxtest = 128; break;
case 1: loops = 4096; maxtest = 4096; break;
case 2: loops = 128; maxtest = 65536; break;
default: loops = 4; maxtest = 1048576; break;
}
for (long long loop = 0;loop < loops;++loop) {
uint32_t *xs = (uint32_t *) x;
xwords = myrandom() % (maxtest + 1);
xlen = 4*xwords;
input_prepare(x2,x,xlen);
secret(x,xlen);
crypto_sort(xs,xwords);
declassify(x,xlen);
output_compare(x2,x,xlen,"crypto_sort");
for (long long i = 1;i < xwords;++i)
if (uint32down_cmp(&xs[i-1],&xs[i]) > 0) {
fail("failure: crypto_sort output is not in order\n");
break;
}
double_canary(x2,x,xlen);
qsort(x2,xwords,4,uint32down_cmp);
output_compare(x2,x,xlen,"crypto_sort");
if (memcmp(x2,x,xlen) != 0) fail("failure: crypto_sort does not match qsort\n");
}
}
}
static void test_sort_uint32down(void)
{
if (targeto && strcmp(targeto,"sort")) return;
if (targetp && strcmp(targetp,"uint32down")) return;
storage_sort_uint32down_x = callocplus(4*1048576);
test_sort_uint32down_x = (unsigned char *) aligned(storage_sort_uint32down_x,4*1048576);
storage_sort_uint32down_x2 = callocplus(4*1048576);
test_sort_uint32down_x2 = (unsigned char *) aligned(storage_sort_uint32down_x2,4*1048576);
for (long long offset = 0;offset < 2;++offset) {
if (targetoffset && atol(targetoffset) != offset) continue;
if (offset && valgrind) break;
printf("sort_uint32down offset %lld\n",offset);
test_sort_uint32down_offset = offset;
for (long long impl = -1;impl < djbsort_numimpl_uint32down();++impl)
forked(test_sort_uint32down_impl,impl);
test_sort_uint32down_x += 4;
test_sort_uint32down_x2 += 4;
}
free(storage_sort_uint32down_x2);
free(storage_sort_uint32down_x);
}
static void *storage_sort_float32_x;
static unsigned char *test_sort_float32_x;
static void *storage_sort_float32_x2;
static unsigned char *test_sort_float32_x2;
static long long test_sort_float32_offset;
static int float32_cmp(const void *x,const void *y)
{
const float a = *(float *) x;
const float b = *(float *) y;
if (a != a || b != b) { /* NaN handling */
int32_t ai = *(int32_t *) x;
int32_t bi = *(int32_t *) y;
ai ^= ((uint32_t) (ai >> 31)) >> 1;
bi ^= ((uint32_t) (bi >> 31)) >> 1;
if (ai < bi) return -1;
if (ai > bi) return 1;
return 0;
}
if (a < b) return -1;
if (a > b) return 1;
return 0;
}
static void test_sort_float32_impl(long long impl)
{
unsigned char *x = test_sort_float32_x;
unsigned char *x2 = test_sort_float32_x2;
long long xlen;
long long xwords;
void (*crypto_sort)(float *,long long);
testvector_mutate(valgrind);
testvector_mutate(5);
testvector_mutate(impl);
testvector_mutate(test_sort_float32_offset);
if (targeti && strcmp(targeti,".") && strcmp(targeti,djbsort_dispatch_float32_implementation(impl))) return;
if (targetn && atol(targetn) != impl) return;
if (impl >= 0) {
crypto_sort = djbsort_dispatch_float32(impl);
printf("sort_float32 %lld implementation %s compiler %s\n",impl,djbsort_dispatch_float32_implementation(impl),djbsort_dispatch_float32_compiler(impl));
} else {
crypto_sort = djbsort_float32;
printf("sort_float32 selected implementation %s compiler %s\n",djbsort_float32_implementation(),djbsort_float32_compiler());
}
for (long long stage = 0;stage < 4;++stage) {
long long loops,maxtest;
switch(stage) {
case 0: loops = 1024; maxtest = 128; break;
case 1: loops = 4096; maxtest = 4096; break;
case 2: loops = 128; maxtest = 65536; break;
default: loops = 4; maxtest = 1048576; break;
}
for (long long loop = 0;loop < loops;++loop) {
float *xs = (float *) x;
xwords = myrandom() % (maxtest + 1);
xlen = 4*xwords;
input_prepare(x2,x,xlen);
secret(x,xlen);
crypto_sort(xs,xwords);
declassify(x,xlen);
output_compare(x2,x,xlen,"crypto_sort");
for (long long i = 1;i < xwords;++i)
if (float32_cmp(&xs[i-1],&xs[i]) > 0) {
fail("failure: crypto_sort output is not in order\n");
break;
}
double_canary(x2,x,xlen);
qsort(x2,xwords,4,float32_cmp);
output_compare(x2,x,xlen,"crypto_sort");
if (memcmp(x2,x,xlen) != 0) fail("failure: crypto_sort does not match qsort\n");
}
}
}
static void test_sort_float32(void)
{
if (targeto && strcmp(targeto,"sort")) return;
if (targetp && strcmp(targetp,"float32")) return;
storage_sort_float32_x = callocplus(4*1048576);
test_sort_float32_x = (unsigned char *) aligned(storage_sort_float32_x,4*1048576);
storage_sort_float32_x2 = callocplus(4*1048576);
test_sort_float32_x2 = (unsigned char *) aligned(storage_sort_float32_x2,4*1048576);
for (long long offset = 0;offset < 2;++offset) {
if (targetoffset && atol(targetoffset) != offset) continue;
if (offset && valgrind) break;
printf("sort_float32 offset %lld\n",offset);
test_sort_float32_offset = offset;
for (long long impl = -1;impl < djbsort_numimpl_float32();++impl)
forked(test_sort_float32_impl,impl);
test_sort_float32_x += 4;
test_sort_float32_x2 += 4;
}
free(storage_sort_float32_x2);
free(storage_sort_float32_x);
}
static void *storage_sort_float32down_x;
static unsigned char *test_sort_float32down_x;
static void *storage_sort_float32down_x2;
static unsigned char *test_sort_float32down_x2;
static long long test_sort_float32down_offset;
static int float32down_cmp(const void *x,const void *y)
{
const float a = *(float *) x;
const float b = *(float *) y;
if (a != a || b != b) { /* NaN handling */
int32_t ai = *(int32_t *) x;
int32_t bi = *(int32_t *) y;
ai ^= ((uint32_t) (ai >> 31)) >> 1;
bi ^= ((uint32_t) (bi >> 31)) >> 1;
if (ai < bi) return 1;
if (ai > bi) return -1;
return 0;
}
if (a < b) return 1;
if (a > b) return -1;
return 0;
}
static void test_sort_float32down_impl(long long impl)
{
unsigned char *x = test_sort_float32down_x;
unsigned char *x2 = test_sort_float32down_x2;
long long xlen;
long long xwords;
void (*crypto_sort)(float *,long long);
testvector_mutate(valgrind);
testvector_mutate(6);
testvector_mutate(impl);
testvector_mutate(test_sort_float32down_offset);
if (targeti && strcmp(targeti,".") && strcmp(targeti,djbsort_dispatch_float32down_implementation(impl))) return;
if (targetn && atol(targetn) != impl) return;
if (impl >= 0) {
crypto_sort = djbsort_dispatch_float32down(impl);
printf("sort_float32down %lld implementation %s compiler %s\n",impl,djbsort_dispatch_float32down_implementation(impl),djbsort_dispatch_float32down_compiler(impl));
} else {
crypto_sort = djbsort_float32down;
printf("sort_float32down selected implementation %s compiler %s\n",djbsort_float32down_implementation(),djbsort_float32down_compiler());
}
for (long long stage = 0;stage < 4;++stage) {
long long loops,maxtest;
switch(stage) {
case 0: loops = 1024; maxtest = 128; break;
case 1: loops = 4096; maxtest = 4096; break;
case 2: loops = 128; maxtest = 65536; break;
default: loops = 4; maxtest = 1048576; break;
}
for (long long loop = 0;loop < loops;++loop) {
float *xs = (float *) x;
xwords = myrandom() % (maxtest + 1);
xlen = 4*xwords;
input_prepare(x2,x,xlen);
secret(x,xlen);
crypto_sort(xs,xwords);
declassify(x,xlen);
output_compare(x2,x,xlen,"crypto_sort");
for (long long i = 1;i < xwords;++i)
if (float32down_cmp(&xs[i-1],&xs[i]) > 0) {
fail("failure: crypto_sort output is not in order\n");
break;
}
double_canary(x2,x,xlen);
qsort(x2,xwords,4,float32down_cmp);
output_compare(x2,x,xlen,"crypto_sort");
if (memcmp(x2,x,xlen) != 0) fail("failure: crypto_sort does not match qsort\n");
}
}
}
static void test_sort_float32down(void)
{
if (targeto && strcmp(targeto,"sort")) return;
if (targetp && strcmp(targetp,"float32down")) return;
storage_sort_float32down_x = callocplus(4*1048576);
test_sort_float32down_x = (unsigned char *) aligned(storage_sort_float32down_x,4*1048576);
storage_sort_float32down_x2 = callocplus(4*1048576);
test_sort_float32down_x2 = (unsigned char *) aligned(storage_sort_float32down_x2,4*1048576);
for (long long offset = 0;offset < 2;++offset) {
if (targetoffset && atol(targetoffset) != offset) continue;
if (offset && valgrind) break;
printf("sort_float32down offset %lld\n",offset);
test_sort_float32down_offset = offset;
for (long long impl = -1;impl < djbsort_numimpl_float32down();++impl)
forked(test_sort_float32down_impl,impl);
test_sort_float32down_x += 4;
test_sort_float32down_x2 += 4;
}
free(storage_sort_float32down_x2);
free(storage_sort_float32down_x);
}
static void *storage_sort_int64_x;
static unsigned char *test_sort_int64_x;
static void *storage_sort_int64_x2;
static unsigned char *test_sort_int64_x2;
static long long test_sort_int64_offset;
static int int64_cmp(const void *x,const void *y)
{
const int64_t a = *(int64_t *) x;
const int64_t b = *(int64_t *) y;
if (a < b) return -1;
if (a > b) return 1;
return 0;
}
static void test_sort_int64_impl(long long impl)
{
unsigned char *x = test_sort_int64_x;
unsigned char *x2 = test_sort_int64_x2;
long long xlen;
long long xwords;
void (*crypto_sort)(int64_t *,long long);
testvector_mutate(valgrind);
testvector_mutate(7);
testvector_mutate(impl);
testvector_mutate(test_sort_int64_offset);
if (targeti && strcmp(targeti,".") && strcmp(targeti,djbsort_dispatch_int64_implementation(impl))) return;
if (targetn && atol(targetn) != impl) return;
if (impl >= 0) {
crypto_sort = djbsort_dispatch_int64(impl);
printf("sort_int64 %lld implementation %s compiler %s\n",impl,djbsort_dispatch_int64_implementation(impl),djbsort_dispatch_int64_compiler(impl));
} else {
crypto_sort = djbsort_int64;
printf("sort_int64 selected implementation %s compiler %s\n",djbsort_int64_implementation(),djbsort_int64_compiler());
}
for (long long stage = 0;stage < 4;++stage) {
long long loops,maxtest;
switch(stage) {
case 0: loops = 1024; maxtest = 128; break;
case 1: loops = 4096; maxtest = 4096; break;
case 2: loops = 128; maxtest = 65536; break;
default: loops = 4; maxtest = 1048576; break;
}
for (long long loop = 0;loop < loops;++loop) {
int64_t *xs = (int64_t *) x;
xwords = myrandom() % (maxtest + 1);
xlen = 8*xwords;
input_prepare(x2,x,xlen);
secret(x,xlen);
crypto_sort(xs,xwords);
declassify(x,xlen);
output_compare(x2,x,xlen,"crypto_sort");
for (long long i = 1;i < xwords;++i)
if (int64_cmp(&xs[i-1],&xs[i]) > 0) {
fail("failure: crypto_sort output is not in order\n");
break;
}
double_canary(x2,x,xlen);
qsort(x2,xwords,8,int64_cmp);
output_compare(x2,x,xlen,"crypto_sort");
if (memcmp(x2,x,xlen) != 0) fail("failure: crypto_sort does not match qsort\n");
}
}
}
static void test_sort_int64(void)
{
if (targeto && strcmp(targeto,"sort")) return;
if (targetp && strcmp(targetp,"int64")) return;
storage_sort_int64_x = callocplus(8*1048576);
test_sort_int64_x = (unsigned char *) aligned(storage_sort_int64_x,8*1048576);
storage_sort_int64_x2 = callocplus(8*1048576);
test_sort_int64_x2 = (unsigned char *) aligned(storage_sort_int64_x2,8*1048576);
for (long long offset = 0;offset < 2;++offset) {
if (targetoffset && atol(targetoffset) != offset) continue;
if (offset && valgrind) break;
printf("sort_int64 offset %lld\n",offset);
test_sort_int64_offset = offset;
for (long long impl = -1;impl < djbsort_numimpl_int64();++impl)
forked(test_sort_int64_impl,impl);
test_sort_int64_x += 8;
test_sort_int64_x2 += 8;
}
free(storage_sort_int64_x2);
free(storage_sort_int64_x);
}
static void *storage_sort_int64down_x;
static unsigned char *test_sort_int64down_x;
static void *storage_sort_int64down_x2;
static unsigned char *test_sort_int64down_x2;
static long long test_sort_int64down_offset;
static int int64down_cmp(const void *x,const void *y)
{
const int64_t a = *(int64_t *) x;
const int64_t b = *(int64_t *) y;
if (a < b) return 1;
if (a > b) return -1;
return 0;
}
static void test_sort_int64down_impl(long long impl)
{
unsigned char *x = test_sort_int64down_x;
unsigned char *x2 = test_sort_int64down_x2;
long long xlen;
long long xwords;
void (*crypto_sort)(int64_t *,long long);
testvector_mutate(valgrind);
testvector_mutate(8);
testvector_mutate(impl);
testvector_mutate(test_sort_int64down_offset);
if (targeti && strcmp(targeti,".") && strcmp(targeti,djbsort_dispatch_int64down_implementation(impl))) return;
if (targetn && atol(targetn) != impl) return;
if (impl >= 0) {
crypto_sort = djbsort_dispatch_int64down(impl);
printf("sort_int64down %lld implementation %s compiler %s\n",impl,djbsort_dispatch_int64down_implementation(impl),djbsort_dispatch_int64down_compiler(impl));
} else {
crypto_sort = djbsort_int64down;
printf("sort_int64down selected implementation %s compiler %s\n",djbsort_int64down_implementation(),djbsort_int64down_compiler());
}
for (long long stage = 0;stage < 4;++stage) {
long long loops,maxtest;
switch(stage) {
case 0: loops = 1024; maxtest = 128; break;
case 1: loops = 4096; maxtest = 4096; break;
case 2: loops = 128; maxtest = 65536; break;
default: loops = 4; maxtest = 1048576; break;
}
for (long long loop = 0;loop < loops;++loop) {
int64_t *xs = (int64_t *) x;
xwords = myrandom() % (maxtest + 1);
xlen = 8*xwords;
input_prepare(x2,x,xlen);
secret(x,xlen);
crypto_sort(xs,xwords);
declassify(x,xlen);
output_compare(x2,x,xlen,"crypto_sort");
for (long long i = 1;i < xwords;++i)
if (int64down_cmp(&xs[i-1],&xs[i]) > 0) {
fail("failure: crypto_sort output is not in order\n");
break;
}
double_canary(x2,x,xlen);
qsort(x2,xwords,8,int64down_cmp);
output_compare(x2,x,xlen,"crypto_sort");
if (memcmp(x2,x,xlen) != 0) fail("failure: crypto_sort does not match qsort\n");
}
}
}
static void test_sort_int64down(void)
{
if (targeto && strcmp(targeto,"sort")) return;
if (targetp && strcmp(targetp,"int64down")) return;
storage_sort_int64down_x = callocplus(8*1048576);
test_sort_int64down_x = (unsigned char *) aligned(storage_sort_int64down_x,8*1048576);
storage_sort_int64down_x2 = callocplus(8*1048576);
test_sort_int64down_x2 = (unsigned char *) aligned(storage_sort_int64down_x2,8*1048576);
for (long long offset = 0;offset < 2;++offset) {
if (targetoffset && atol(targetoffset) != offset) continue;
if (offset && valgrind) break;
printf("sort_int64down offset %lld\n",offset);
test_sort_int64down_offset = offset;
for (long long impl = -1;impl < djbsort_numimpl_int64down();++impl)
forked(test_sort_int64down_impl,impl);
test_sort_int64down_x += 8;
test_sort_int64down_x2 += 8;
}
free(storage_sort_int64down_x2);
free(storage_sort_int64down_x);
}
static void *storage_sort_uint64_x;
static unsigned char *test_sort_uint64_x;
static void *storage_sort_uint64_x2;
static unsigned char *test_sort_uint64_x2;
static long long test_sort_uint64_offset;
static int uint64_cmp(const void *x,const void *y)
{
const uint64_t a = *(uint64_t *) x;
const uint64_t b = *(uint64_t *) y;
if (a < b) return -1;
if (a > b) return 1;
return 0;
}
static void test_sort_uint64_impl(long long impl)
{
unsigned char *x = test_sort_uint64_x;
unsigned char *x2 = test_sort_uint64_x2;
long long xlen;
long long xwords;
void (*crypto_sort)(uint64_t *,long long);
testvector_mutate(valgrind);
testvector_mutate(9);
testvector_mutate(impl);
testvector_mutate(test_sort_uint64_offset);
if (targeti && strcmp(targeti,".") && strcmp(targeti,djbsort_dispatch_uint64_implementation(impl))) return;
if (targetn && atol(targetn) != impl) return;
if (impl >= 0) {
crypto_sort = djbsort_dispatch_uint64(impl);
printf("sort_uint64 %lld implementation %s compiler %s\n",impl,djbsort_dispatch_uint64_implementation(impl),djbsort_dispatch_uint64_compiler(impl));
} else {
crypto_sort = djbsort_uint64;
printf("sort_uint64 selected implementation %s compiler %s\n",djbsort_uint64_implementation(),djbsort_uint64_compiler());
}
for (long long stage = 0;stage < 4;++stage) {
long long loops,maxtest;
switch(stage) {
case 0: loops = 1024; maxtest = 128; break;
case 1: loops = 4096; maxtest = 4096; break;
case 2: loops = 128; maxtest = 65536; break;
default: loops = 4; maxtest = 1048576; break;
}
for (long long loop = 0;loop < loops;++loop) {
uint64_t *xs = (uint64_t *) x;
xwords = myrandom() % (maxtest + 1);
xlen = 8*xwords;
input_prepare(x2,x,xlen);
secret(x,xlen);
crypto_sort(xs,xwords);
declassify(x,xlen);
output_compare(x2,x,xlen,"crypto_sort");
for (long long i = 1;i < xwords;++i)
if (uint64_cmp(&xs[i-1],&xs[i]) > 0) {
fail("failure: crypto_sort output is not in order\n");
break;
}
double_canary(x2,x,xlen);
qsort(x2,xwords,8,uint64_cmp);
output_compare(x2,x,xlen,"crypto_sort");
if (memcmp(x2,x,xlen) != 0) fail("failure: crypto_sort does not match qsort\n");
}
}
}
static void test_sort_uint64(void)
{
if (targeto && strcmp(targeto,"sort")) return;
if (targetp && strcmp(targetp,"uint64")) return;
storage_sort_uint64_x = callocplus(8*1048576);
test_sort_uint64_x = (unsigned char *) aligned(storage_sort_uint64_x,8*1048576);
storage_sort_uint64_x2 = callocplus(8*1048576);
test_sort_uint64_x2 = (unsigned char *) aligned(storage_sort_uint64_x2,8*1048576);
for (long long offset = 0;offset < 2;++offset) {
if (targetoffset && atol(targetoffset) != offset) continue;
if (offset && valgrind) break;
printf("sort_uint64 offset %lld\n",offset);
test_sort_uint64_offset = offset;
for (long long impl = -1;impl < djbsort_numimpl_uint64();++impl)
forked(test_sort_uint64_impl,impl);
test_sort_uint64_x += 8;
test_sort_uint64_x2 += 8;
}
free(storage_sort_uint64_x2);
free(storage_sort_uint64_x);
}
static void *storage_sort_uint64down_x;
static unsigned char *test_sort_uint64down_x;
static void *storage_sort_uint64down_x2;
static unsigned char *test_sort_uint64down_x2;
static long long test_sort_uint64down_offset;
static int uint64down_cmp(const void *x,const void *y)
{
const uint64_t a = *(uint64_t *) x;
const uint64_t b = *(uint64_t *) y;
if (a < b) return 1;
if (a > b) return -1;
return 0;
}
static void test_sort_uint64down_impl(long long impl)
{
unsigned char *x = test_sort_uint64down_x;
unsigned char *x2 = test_sort_uint64down_x2;
long long xlen;
long long xwords;
void (*crypto_sort)(uint64_t *,long long);
testvector_mutate(valgrind);
testvector_mutate(10);
testvector_mutate(impl);
testvector_mutate(test_sort_uint64down_offset);
if (targeti && strcmp(targeti,".") && strcmp(targeti,djbsort_dispatch_uint64down_implementation(impl))) return;
if (targetn && atol(targetn) != impl) return;
if (impl >= 0) {
crypto_sort = djbsort_dispatch_uint64down(impl);
printf("sort_uint64down %lld implementation %s compiler %s\n",impl,djbsort_dispatch_uint64down_implementation(impl),djbsort_dispatch_uint64down_compiler(impl));
} else {
crypto_sort = djbsort_uint64down;
printf("sort_uint64down selected implementation %s compiler %s\n",djbsort_uint64down_implementation(),djbsort_uint64down_compiler());
}
for (long long stage = 0;stage < 4;++stage) {
long long loops,maxtest;
switch(stage) {
case 0: loops = 1024; maxtest = 128; break;
case 1: loops = 4096; maxtest = 4096; break;
case 2: loops = 128; maxtest = 65536; break;
default: loops = 4; maxtest = 1048576; break;
}
for (long long loop = 0;loop < loops;++loop) {
uint64_t *xs = (uint64_t *) x;
xwords = myrandom() % (maxtest + 1);
xlen = 8*xwords;
input_prepare(x2,x,xlen);
secret(x,xlen);
crypto_sort(xs,xwords);
declassify(x,xlen);
output_compare(x2,x,xlen,"crypto_sort");
for (long long i = 1;i < xwords;++i)
if (uint64down_cmp(&xs[i-1],&xs[i]) > 0) {
fail("failure: crypto_sort output is not in order\n");
break;
}
double_canary(x2,x,xlen);
qsort(x2,xwords,8,uint64down_cmp);
output_compare(x2,x,xlen,"crypto_sort");
if (memcmp(x2,x,xlen) != 0) fail("failure: crypto_sort does not match qsort\n");
}
}
}
static void test_sort_uint64down(void)
{
if (targeto && strcmp(targeto,"sort")) return;
if (targetp && strcmp(targetp,"uint64down")) return;
storage_sort_uint64down_x = callocplus(8*1048576);
test_sort_uint64down_x = (unsigned char *) aligned(storage_sort_uint64down_x,8*1048576);
storage_sort_uint64down_x2 = callocplus(8*1048576);
test_sort_uint64down_x2 = (unsigned char *) aligned(storage_sort_uint64down_x2,8*1048576);
for (long long offset = 0;offset < 2;++offset) {
if (targetoffset && atol(targetoffset) != offset) continue;
if (offset && valgrind) break;
printf("sort_uint64down offset %lld\n",offset);
test_sort_uint64down_offset = offset;
for (long long impl = -1;impl < djbsort_numimpl_uint64down();++impl)
forked(test_sort_uint64down_impl,impl);
test_sort_uint64down_x += 8;
test_sort_uint64down_x2 += 8;
}
free(storage_sort_uint64down_x2);
free(storage_sort_uint64down_x);
}
static void *storage_sort_float64_x;
static unsigned char *test_sort_float64_x;
static void *storage_sort_float64_x2;
static unsigned char *test_sort_float64_x2;
static long long test_sort_float64_offset;
static int float64_cmp(const void *x,const void *y)
{
const double a = *(double *) x;
const double b = *(double *) y;
if (a != a || b != b) { /* NaN handling */
int64_t ai = *(int64_t *) x;
int64_t bi = *(int64_t *) y;
ai ^= ((uint64_t) (ai >> 63)) >> 1;
bi ^= ((uint64_t) (bi >> 63)) >> 1;
if (ai < bi) return -1;
if (ai > bi) return 1;
return 0;
}
if (a < b) return -1;
if (a > b) return 1;
return 0;
}
static void test_sort_float64_impl(long long impl)
{
unsigned char *x = test_sort_float64_x;
unsigned char *x2 = test_sort_float64_x2;
long long xlen;
long long xwords;
void (*crypto_sort)(double *,long long);
testvector_mutate(valgrind);
testvector_mutate(11);
testvector_mutate(impl);
testvector_mutate(test_sort_float64_offset);
if (targeti && strcmp(targeti,".") && strcmp(targeti,djbsort_dispatch_float64_implementation(impl))) return;
if (targetn && atol(targetn) != impl) return;
if (impl >= 0) {
crypto_sort = djbsort_dispatch_float64(impl);
printf("sort_float64 %lld implementation %s compiler %s\n",impl,djbsort_dispatch_float64_implementation(impl),djbsort_dispatch_float64_compiler(impl));
} else {
crypto_sort = djbsort_float64;
printf("sort_float64 selected implementation %s compiler %s\n",djbsort_float64_implementation(),djbsort_float64_compiler());
}
for (long long stage = 0;stage < 4;++stage) {
long long loops,maxtest;
switch(stage) {
case 0: loops = 1024; maxtest = 128; break;
case 1: loops = 4096; maxtest = 4096; break;
case 2: loops = 128; maxtest = 65536; break;
default: loops = 4; maxtest = 1048576; break;
}
for (long long loop = 0;loop < loops;++loop) {
double *xs = (double *) x;
xwords = myrandom() % (maxtest + 1);
xlen = 8*xwords;
input_prepare(x2,x,xlen);
secret(x,xlen);
crypto_sort(xs,xwords);
declassify(x,xlen);
output_compare(x2,x,xlen,"crypto_sort");
for (long long i = 1;i < xwords;++i)
if (float64_cmp(&xs[i-1],&xs[i]) > 0) {
fail("failure: crypto_sort output is not in order\n");
break;
}
double_canary(x2,x,xlen);
qsort(x2,xwords,8,float64_cmp);
output_compare(x2,x,xlen,"crypto_sort");
if (memcmp(x2,x,xlen) != 0) fail("failure: crypto_sort does not match qsort\n");
}
}
}
static void test_sort_float64(void)
{
if (targeto && strcmp(targeto,"sort")) return;
if (targetp && strcmp(targetp,"float64")) return;
storage_sort_float64_x = callocplus(8*1048576);
test_sort_float64_x = (unsigned char *) aligned(storage_sort_float64_x,8*1048576);
storage_sort_float64_x2 = callocplus(8*1048576);
test_sort_float64_x2 = (unsigned char *) aligned(storage_sort_float64_x2,8*1048576);
for (long long offset = 0;offset < 2;++offset) {
if (targetoffset && atol(targetoffset) != offset) continue;
if (offset && valgrind) break;
printf("sort_float64 offset %lld\n",offset);
test_sort_float64_offset = offset;
for (long long impl = -1;impl < djbsort_numimpl_float64();++impl)
forked(test_sort_float64_impl,impl);
test_sort_float64_x += 8;
test_sort_float64_x2 += 8;
}
free(storage_sort_float64_x2);
free(storage_sort_float64_x);
}
static void *storage_sort_float64down_x;
static unsigned char *test_sort_float64down_x;
static void *storage_sort_float64down_x2;
static unsigned char *test_sort_float64down_x2;
static long long test_sort_float64down_offset;
static int float64down_cmp(const void *x,const void *y)
{
const double a = *(double *) x;
const double b = *(double *) y;
if (a != a || b != b) { /* NaN handling */
int64_t ai = *(int64_t *) x;
int64_t bi = *(int64_t *) y;
ai ^= ((uint64_t) (ai >> 63)) >> 1;
bi ^= ((uint64_t) (bi >> 63)) >> 1;
if (ai < bi) return 1;
if (ai > bi) return -1;
return 0;
}
if (a < b) return 1;
if (a > b) return -1;
return 0;
}
static void test_sort_float64down_impl(long long impl)
{
unsigned char *x = test_sort_float64down_x;
unsigned char *x2 = test_sort_float64down_x2;
long long xlen;
long long xwords;
void (*crypto_sort)(double *,long long);
testvector_mutate(valgrind);
testvector_mutate(12);
testvector_mutate(impl);
testvector_mutate(test_sort_float64down_offset);
if (targeti && strcmp(targeti,".") && strcmp(targeti,djbsort_dispatch_float64down_implementation(impl))) return;
if (targetn && atol(targetn) != impl) return;
if (impl >= 0) {
crypto_sort = djbsort_dispatch_float64down(impl);
printf("sort_float64down %lld implementation %s compiler %s\n",impl,djbsort_dispatch_float64down_implementation(impl),djbsort_dispatch_float64down_compiler(impl));
} else {
crypto_sort = djbsort_float64down;
printf("sort_float64down selected implementation %s compiler %s\n",djbsort_float64down_implementation(),djbsort_float64down_compiler());
}
for (long long stage = 0;stage < 4;++stage) {
long long loops,maxtest;
switch(stage) {
case 0: loops = 1024; maxtest = 128; break;
case 1: loops = 4096; maxtest = 4096; break;
case 2: loops = 128; maxtest = 65536; break;
default: loops = 4; maxtest = 1048576; break;
}
for (long long loop = 0;loop < loops;++loop) {
double *xs = (double *) x;
xwords = myrandom() % (maxtest + 1);
xlen = 8*xwords;
input_prepare(x2,x,xlen);
secret(x,xlen);
crypto_sort(xs,xwords);
declassify(x,xlen);
output_compare(x2,x,xlen,"crypto_sort");
for (long long i = 1;i < xwords;++i)
if (float64down_cmp(&xs[i-1],&xs[i]) > 0) {
fail("failure: crypto_sort output is not in order\n");
break;
}
double_canary(x2,x,xlen);
qsort(x2,xwords,8,float64down_cmp);
output_compare(x2,x,xlen,"crypto_sort");
if (memcmp(x2,x,xlen) != 0) fail("failure: crypto_sort does not match qsort\n");
}
}
}
static void test_sort_float64down(void)
{
if (targeto && strcmp(targeto,"sort")) return;
if (targetp && strcmp(targetp,"float64down")) return;
storage_sort_float64down_x = callocplus(8*1048576);
test_sort_float64down_x = (unsigned char *) aligned(storage_sort_float64down_x,8*1048576);
storage_sort_float64down_x2 = callocplus(8*1048576);
test_sort_float64down_x2 = (unsigned char *) aligned(storage_sort_float64down_x2,8*1048576);
for (long long offset = 0;offset < 2;++offset) {
if (targetoffset && atol(targetoffset) != offset) continue;
if (offset && valgrind) break;
printf("sort_float64down offset %lld\n",offset);
test_sort_float64down_offset = offset;
for (long long impl = -1;impl < djbsort_numimpl_float64down();++impl)
forked(test_sort_float64down_impl,impl);
test_sort_float64down_x += 8;
test_sort_float64down_x2 += 8;
}
free(storage_sort_float64down_x2);
free(storage_sort_float64down_x);
}
/* ----- top level */
#include "print_cpuid.inc"
int main(int argc,char **argv)
{
valgrind_init();
if (valgrind) limits();
setvbuf(stdout,0,_IOLBF,0);
printf("djbsort version %s\n",djbsort_version());
printf("djbsort arch %s\n",djbsort_arch());
print_cpuid();
if (valgrind) {
printf("valgrind %d",(int) valgrind);
printf(" declassify %d",(int) crypto_declassify_uses_valgrind);
if (!crypto_declassify_uses_valgrind)
printf(" (expect false positives)");
printf("\n");
}
if (*argv) ++argv;
if (*argv) {
targeto = *argv++;
if (*argv) {
targetp = *argv++;
if (*argv) {
targeti = *argv++;
if (*argv) {
targetn = *argv++;
if (*argv) {
targetoffset = *argv++;
}
}
}
}
}
test_sort_int32();
test_sort_int32down();
test_sort_uint32();
test_sort_uint32down();
test_sort_float32();
test_sort_float32down();
test_sort_int64();
test_sort_int64down();
test_sort_uint64();
test_sort_uint64down();
test_sort_float64();
test_sort_float64down();
if (!ok) {
printf("some tests failed\n");
return 100;
}
printf("all tests succeeded\n");
return 0;
}