From 08a417bfea444c148d756a2415ed016a0985643c Mon Sep 17 00:00:00 2001 From: suigin Date: Fri, 17 Feb 2017 03:15:49 -0800 Subject: [PATCH] Fixed issue with psetstr. Also added unit test for low-level string conversion functions. --- .gitignore | 1 + Makefile | 3 ++- TODO | 2 ++ check/p/strings.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++ src/p/psetstr.c | 39 +++++++++++++++++++----------------- 5 files changed, 77 insertions(+), 19 deletions(-) create mode 100644 check/p/strings.c diff --git a/.gitignore b/.gitignore index 112cb64..52d6dc7 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ check/alloc/query check/alloc/valid check/libcheck.a check/p/negnot +check/p/strings check/p/pcmp check/p/pcopy check/p/pmove diff --git a/Makefile b/Makefile index b8bd354..73f1718 100644 --- a/Makefile +++ b/Makefile @@ -273,7 +273,8 @@ CHECK_P := \ pmove \ pnorm \ pzero \ - negnot + negnot \ + strings CHECK_Z := \ getset \ diff --git a/TODO b/TODO index 5f87cb7..af28b9e 100644 --- a/TODO +++ b/TODO @@ -8,6 +8,8 @@ Low-level Functions: * create addua/subua to add in carry for larger ops? * port remainder of division implementation to x86-64 assembly * optimize pclz, almost always called on normalized input +* add ptrunc and reimplement ztrunc in terms of it +* get rid of bit-level truncation in prand_kiss, truncation only in zrand*** Integer Functions: diff --git a/check/p/strings.c b/check/p/strings.c new file mode 100644 index 0000000..295072d --- /dev/null +++ b/check/p/strings.c @@ -0,0 +1,51 @@ +#include "../check.h" +#include +#include + +static struct hebi_kiss kiss = HEBI_KISS_INIT; + +/* packet buffers for stress test */ +enum { MAX_PACKETS = 16 }; +static hebi_packet x[MAX_PACKETS + 1]; +static hebi_packet y[MAX_PACKETS + 1]; +static hebi_packet z[MAX_PACKETS + 1]; + +/* room for all base 2 digits, optional radix prefix and null terminator */ +enum { MAX_LENGTH = MAX_PACKETS * HEBI_PACKET_BIT + 2 + 1 }; +static char str[MAX_LENGTH]; + +static void +stresstest(unsigned int flags) +{ + size_t i, m, n, bits, len; + unsigned int base; + + for (i = 0; i < MAX_PACKETS * HEBI_PACKET_BIT; i++) { + /* get next random value */ + bits = i; + n = (bits + HEBI_PACKET_BIT - 1) / HEBI_PACKET_BIT; + if (n > 0) { + hebi_prand_kiss(x, n, bits, &kiss); + n = hebi_pnorm(x, n); /* TODO: fix prand */ + } + + /* test converting to string and back for each base */ + for (base = 2; base <= 62 /* TODO: 63 & 64 */; base++) { + hebi_pcopy(z, x, n); + len = hebi_pgetstr(str, sizeof(str), z, n, base, flags); + assert(len > 0 && len < sizeof(str)); + + hebi_pzero(y, MAX_PACKETS + 1); + m = hebi_psetstr(y, MAX_PACKETS + 1, str, len, base, flags); + assert(m == n && hebi_pcmp(x, y, m) == 0); + } + } +} + +int +main(int argc, char *argv[]) +{ + checkinit(argc, argv); + stresstest(HEBI_STR_CLASSIC_ALPHABET); + return 0; +} diff --git a/src/p/psetstr.c b/src/p/psetstr.c index ae8a7e2..306eccb 100644 --- a/src/p/psetstr.c +++ b/src/p/psetstr.c @@ -275,14 +275,14 @@ static const unsigned char classic36digitlut[256] = { ['K'] = 21, ['L'] = 22, ['M'] = 23, ['N'] = 24, ['O'] = 25, ['P'] = 26, ['Q'] = 27, ['R'] = 28, ['S'] = 29, ['T'] = 30, ['U'] = 31, ['V'] = 32, - ['W'] = 33, ['Y'] = 34, ['X'] = 35, ['Z'] = 36, + ['W'] = 33, ['X'] = 34, ['Y'] = 35, ['Z'] = 36, ['a'] = 11, ['b'] = 12, ['c'] = 13, ['d'] = 14, ['e'] = 15, ['f'] = 16, ['g'] = 17, ['h'] = 18, ['i'] = 19, ['j'] = 20, ['k'] = 21, ['l'] = 22, ['m'] = 23, ['n'] = 24, ['o'] = 25, ['p'] = 26, ['q'] = 27, ['r'] = 28, ['s'] = 29, ['t'] = 30, - ['u'] = 31, ['v'] = 32, ['w'] = 33, ['y'] = 34, - ['x'] = 35, ['z'] = 36 + ['u'] = 31, ['v'] = 32, ['w'] = 33, ['x'] = 34, + ['y'] = 35, ['z'] = 36 }; static const unsigned char classic64digitlut[256] = { @@ -294,14 +294,14 @@ static const unsigned char classic64digitlut[256] = { ['K'] = 21, ['L'] = 22, ['M'] = 23, ['N'] = 24, ['O'] = 25, ['P'] = 26, ['Q'] = 27, ['R'] = 28, ['S'] = 29, ['T'] = 30, ['U'] = 31, ['V'] = 32, - ['W'] = 33, ['Y'] = 34, ['X'] = 35, ['Z'] = 36, + ['W'] = 33, ['X'] = 34, ['Y'] = 35, ['Z'] = 36, ['a'] = 37, ['b'] = 38, ['c'] = 39, ['d'] = 40, ['e'] = 41, ['f'] = 42, ['g'] = 43, ['h'] = 44, ['i'] = 45, ['j'] = 46, ['k'] = 47, ['l'] = 48, ['m'] = 49, ['n'] = 50, ['o'] = 51, ['p'] = 52, ['q'] = 53, ['r'] = 54, ['s'] = 55, ['t'] = 56, - ['u'] = 57, ['v'] = 58, ['w'] = 59, ['y'] = 60, - ['x'] = 61, ['z'] = 62, ['$'] = 63, ['@'] = 64 + ['u'] = 57, ['v'] = 58, ['w'] = 59, ['x'] = 60, + ['y'] = 61, ['z'] = 62, ['$'] = 63, ['@'] = 64 }; static inline unsigned int @@ -382,8 +382,17 @@ outofspace( } #define ENSURE_SPACE_AVAILABLE(SIZE) \ -if (UNLIKELY((SIZE) > n)) \ - return outofspace((SIZE), str, cur, len, radix) + if (UNLIKELY((SIZE) > n)) \ + return outofspace((SIZE), str, cur, len, radix) + +#define PUSH_LIMB(VAL) \ + MULTILINEBEGIN \ + if (VAL) { \ + size++; \ + ENSURE_SPACE_AVAILABLE(size); \ + hebi_psetu(r + size - 1, (VAL)); \ + } \ + MULTILINEEND static size_t readshift( @@ -445,6 +454,7 @@ readmultiply( const unsigned char *restrict digitlut ) { uint64_t limb; + uint64_t overflow; uint64_t scale; uint64_t maxscale; unsigned int digit; @@ -471,21 +481,14 @@ readmultiply( numdigits++; } if (size > 0) { - size++; - ENSURE_SPACE_AVAILABLE(size); scale = maxscale; if (numdigits != maxdigits) scale = hebi_powu64__(radix, numdigits); - hebi_pmulu(r, r, scale, size - 1); + overflow = hebi_pmulu(r, r, scale, size); + PUSH_LIMB(overflow); limb = hebi_paddu(r, r, limb, size); } - if (limb) { - size++; - ENSURE_SPACE_AVAILABLE(size); - hebi_psetu(r + size - 1, limb); - } else { - size = hebi_pnorm(r, size); - } + PUSH_LIMB(limb); } while (cur < len); return size;