Skip to content

Instantly share code, notes, and snippets.

@jart
Created July 22, 2023 15:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jart/d004a1a39940247e5398180c8484ebbd to your computer and use it in GitHub Desktop.
Save jart/d004a1a39940247e5398180c8484ebbd to your computer and use it in GitHub Desktop.
c23 stdckdint.h test vectors
#include <stdio.h>
#include <ckdint.h>
#include <stdint.h>
#include <inttypes.h>
typedef signed __int128 int128_t;
typedef unsigned __int128 uint128_t;
#define TBIT(T) (sizeof(T) * 8 - 1)
#define TMIN(T) (((T) ~(T)0) > 1 ? (T)0 : (T)((uint128_t)1 << TBIT(T)))
#define TMAX(T) (((T) ~(T)0) > 1 ? (T) ~(T)0 : (T)(((uint128_t)1 << TBIT(T)) - 1))
#define DECLARE_TEST_VECTORS(T) \
static const T k##T[] = { \
0, 1, 2, 3, 4, 5, 6, \
(T)-1, (T)-2, (T)-3, (T)-4, (T)-5, (T)-6, \
TMIN(T), \
(T)(TMIN(T) + 1), \
(T)(TMIN(T) + 2), \
(T)(TMIN(T) + 3), \
(T)(TMIN(T) + 4), \
TMAX(T), \
(T)(TMAX(T) - 1), \
(T)(TMAX(T) - 2), \
(T)(TMAX(T) - 3), \
(T)(TMAX(T) - 4), \
(T)(TMIN(T) / 2), \
(T)(TMIN(T) / 2 + 1), \
(T)(TMIN(T) / 2 + 2), \
(T)(TMIN(T) / 2 + 3), \
(T)(TMIN(T) / 2 + 4), \
(T)(TMAX(T) / 2), \
(T)(TMAX(T) / 2 - 1), \
(T)(TMAX(T) / 2 - 2), \
(T)(TMAX(T) / 2 - 3), \
(T)(TMAX(T) / 2 - 4), \
}
DECLARE_TEST_VECTORS(int8_t);
DECLARE_TEST_VECTORS(uint8_t);
DECLARE_TEST_VECTORS(int16_t);
DECLARE_TEST_VECTORS(uint16_t);
DECLARE_TEST_VECTORS(int32_t);
DECLARE_TEST_VECTORS(uint32_t);
DECLARE_TEST_VECTORS(int64_t);
DECLARE_TEST_VECTORS(uint64_t);
DECLARE_TEST_VECTORS(int128_t);
DECLARE_TEST_VECTORS(uint128_t);
unsigned total = 0;
unsigned noise = 0;
unsigned predicted = 0;
unsigned overflows = 0;
unsigned wewereright = 0;
static void OnTest(const char *name,
const char *T,
const char *U,
const char *V,
uint128_t x,
uint128_t y,
char predicted_overflow,
char correct_overflow) {
overflows += correct_overflow;
predicted += predicted_overflow;
wewereright += predicted_overflow == correct_overflow;
total += 1;
if (predicted_overflow != correct_overflow && ++noise < 20) {
printf("[%s, %s, %s]: we were wrong %s(%016" PRIx64 "%016"
PRIx64 ", %016" PRIx64 "%016" PRIx64 ")"
" predicted_overflow=%d correct_overflow=%d\n",
T, U, V, name,
(uint64_t)(x >> 64), (uint64_t)x,
(uint64_t)(y >> 64), (uint64_t)y,
predicted_overflow, correct_overflow);
}
}
signed long f(signed long *z, signed long x, signed long y) {
return ckd_mul(z, x, y);
}
#if 0
int main(int argc, char *argv[]) {
uint8_t z;
int8_t x = -2;
int128_t y = (uint128_t)1 << 127;
bool o = ckd_mul(&z, x, y);
printf("x=%016lx%016lx\n",(long)((uint128_t)x>>64), (long)(uint128_t)x);
printf("y=%016lx%016lx\n",(long)((uint128_t)y>>64), (long)(uint128_t)y);
printf("z=%016lx%016lx o=%d\n",(long)((uint128_t)z>>64), (long)(uint128_t)z, o);
o = __builtin_mul_overflow(x, y, &z);
printf("z=%016lx%016lx o=%d\n", (long)((uint128_t)z>>64), (long)(uint128_t)z, o);
}
#else
int main(int argc, char *argv[]) {
#define M(T,U,V) \
for (unsigned i = 0; i < sizeof(k##U) / sizeof(k##U[0]); ++i) { \
U x = k##U[i]; \
for (unsigned j = 0; j < sizeof(k##V) / sizeof(k##V[0]); ++j) { \
T z; \
V y = k##V[j]; \
OnTest("ckd_add", #T, #U, #V, x, y, \
ckd_add(&z, x, y), \
__builtin_add_overflow(x, y, &z)); \
OnTest("ckd_sub", #T, #U, #V, x, y, \
ckd_sub(&z, x, y), \
__builtin_sub_overflow(x, y, &z)); \
OnTest("ckd_mul", #T, #U, #V, x, y, \
ckd_mul(&z, x, y), \
__builtin_mul_overflow(x, y, &z)); \
} \
}
#define MM(T,U) \
M(T,U,uint8_t) \
M(T,U,uint16_t) \
M(T,U,uint32_t) \
M(T,U,uint64_t) \
M(T,U,uint128_t) \
M(T,U,int8_t) \
M(T,U,int16_t) \
M(T,U,int32_t) \
M(T,U,int64_t) \
M(T,U,int128_t)
#define MMM(T) \
MM(T,uint8_t) \
MM(T,uint16_t) \
MM(T,uint32_t) \
MM(T,uint64_t) \
MM(T,uint128_t) \
MM(T,int8_t) \
MM(T,int16_t) \
MM(T,int32_t) \
MM(T,int64_t) \
MM(T,int128_t)
MMM(uint8_t)
MMM(uint16_t)
MMM(uint32_t)
MMM(uint64_t)
MMM(uint128_t)
MMM(int8_t)
MMM(int16_t)
MMM(int32_t)
MMM(int64_t)
MMM(int128_t)
printf("%d%% overflows (%u / %u)\n", (int)((double)overflows / total * 100),
overflows, total);
printf("%d%% predicted (%u / %u)\n", (int)((double)predicted / total * 100),
predicted, total);
printf("%d%% wewereright (%u / %u)\n",
(int)((double)wewereright / total * 100), wewereright, total);
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment