@@ -3267,29 +3267,35 @@ Defining a Pseudo-Random Number Generator Function (deterministic / not)
32673267**************************************************************************** */
32683268
32693269/**
3270- * Defines a deterministic Pseudo-Random Number Generator function.
3270+ * Defines a semi- deterministic Pseudo-Random 128 bit Number Generator function.
32713271 *
32723272 * The following functions will be defined:
32733273 *
3274- * - static fio_u128 name##128(void); // returns 128 bits - for internal use
3275- * - extern uint64_t name##64(void); // returns 64 bits
3276- * - extern void name##_bytes(void *buffer, size_t len); // fills buffer
3274+ * - extern fio_u128 name##128(void); // returns 128 bits
3275+ * - extern uint64_t name##64(void); // returns 64 bits (simply half the result)
3276+ * - extern void name##_bytes(void *buffer, size_t len); // fills a buffer
3277+ * - extern void name##_reset(void); // resets the state of the PRNG
32773278 *
32783279 * If `reseed_log` is non-zero and less than 32, the PNGR is no longer
32793280 * deterministic, as it will automatically re-seeds itself every 2^reseed_log
32803281 * iterations.
32813282 *
3282- * The PRNG follows the design for SHISHUA, without using intrinsic functions.
3283- *
32843283 * If `extern` is `static` or `FIO_SFUNC`, static function will be defined.
3285- *
3286- * https://espadrine.github.io/blog/posts/shishua-the-fastest-prng-in-the-world.html
32873284 */
3288- #define FIO_DEFINE_RANDOM_FUNCTION(extern, name, reseed_log, seed_offset) \
3289- static uint64_t name##___state[4] = {0x9c65875be1fce7b9ULL, \
3290- 0x7cc568e838f6a40dULL, \
3291- 0x4bb8d885a0fe47d5ULL, \
3292- 0x95561f0927ad7ecdULL}; \
3285+ #define FIO_DEFINE_RANDOM128_FN(extern, name, reseed_log, seed_offset) \
3286+ static uint64_t name##___state[8] FIO_ALIGN(64) = { \
3287+ 0x9c65875be1fce7b9ULL + seed_offset, \
3288+ 0x7cc568e838f6a40dULL, \
3289+ 0x4bb8d885a0fe47d5ULL + seed_offset, \
3290+ 0x95561f0927ad7ecdULL, \
3291+ 0}; \
3292+ extern void name##_reset(void) { \
3293+ name##___state[0] = 0x9c65875be1fce7b9ULL + seed_offset; \
3294+ name##___state[1] = 0x7cc568e838f6a40dULL; \
3295+ name##___state[2] = 0x4bb8d885a0fe47d5ULL + seed_offset; \
3296+ name##___state[3] = 0x95561f0927ad7ecdULL; \
3297+ name##___state[4] = 0; \
3298+ } \
32933299 FIO_SFUNC void name##___state_reseed(uint64_t *state) { \
32943300 const size_t jitter_samples = 8 | (state[0] & 15); \
32953301 for (size_t i = 0; i < jitter_samples; ++i) { \
@@ -3310,13 +3316,11 @@ Defining a Pseudo-Random Number Generator Function (deterministic / not)
33103316 } \
33113317 } \
33123318 /** Returns a 128 bit pseudo-random number. */ \
3313- FIO_IFUNC fio_u128 name##___rand (void) { \
3319+ extern fio_u128 name##128 (void) { \
33143320 fio_u256 r; \
3315- if (reseed_log && reseed_log < 32) { \
3316- static size_t counter; \
3317- if (!((counter++) & ((1ULL << reseed_log) - 1))) \
3318- name##___state_reseed(name##___state); \
3319- } \
3321+ if (!((name##___state[4]++) & ((1ULL << reseed_log) - 1)) && \
3322+ ((size_t)(reseed_log - 1) < 63)) \
3323+ name##___state_reseed(name##___state); \
33203324 uint64_t s1[4]; \
33213325 { /* load state to registers and roll, mul, add */ \
33223326 const uint64_t s0[] = {name##___state[0], \
@@ -3327,10 +3331,7 @@ Defining a Pseudo-Random Number Generator Function (deterministic / not)
33273331 0x764DBBB75F3B3E0DULL, \
33283332 ~(0x37701261ED6C16C7ULL), \
33293333 ~(0x764DBBB75F3B3E0DULL)}; \
3330- const uint64_t addc[] = {FIO_U64_HASH_PRIME0, \
3331- FIO_U64_HASH_PRIME1, \
3332- FIO_U64_HASH_PRIME2, \
3333- FIO_U64_HASH_PRIME3}; \
3334+ const uint64_t addc[] = {name##___state[4], 0, name##___state[4], 0}; \
33343335 for (size_t i = 0; i < 4; ++i) { \
33353336 s1[i] = fio_lrot64(s0[i], 33); \
33363337 s1[i] += addc[i]; \
@@ -3351,21 +3352,24 @@ Defining a Pseudo-Random Number Generator Function (deterministic / not)
33513352 } \
33523353 /** Returns a 64 bit pseudo-random number. */ \
33533354 extern uint64_t name##64(void) { \
3354- fio_u128 r = name##___rand(); \
3355- return r.u64[0]; \
3355+ static size_t counter; \
3356+ static fio_u128 r; \
3357+ if (!((counter++) & 1)) \
3358+ r = name##128(); \
3359+ return r.u64[counter & 1]; \
33563360 } \
33573361 /** Fills the `dest` buffer with pseudo-random noise. */ \
33583362 extern void name##_bytes(void *dest, size_t len) { \
33593363 if (!dest || !len) \
33603364 return; \
33613365 uint8_t *d = (uint8_t *)dest; \
33623366 for (unsigned i = 15; i < len; i += 16) { \
3363- fio_u128 r = name##___rand (); \
3367+ fio_u128 r = name##128 (); \
33643368 fio_memcpy16(d, r.u8); \
33653369 d += 16; \
33663370 } \
33673371 if (len & 15) { \
3368- fio_u128 r = name##___rand (); \
3372+ fio_u128 r = name##128 (); \
33693373 fio_memcpy15x(d, r.u8, len); \
33703374 } \
33713375 }
@@ -20392,10 +20396,10 @@ fio___string_write_unescape_write(uint8_t *restrict dest,
2039220396 *ps = s;
2039320397 return r;
2039420398}
20395- FIO_IFUNC int fio_string_write_unescape(fio_str_info_s *restrict dest,
20396- fio_string_realloc_fn alloc,
20397- const void *src,
20398- size_t len) {
20399+ SFUNC int fio_string_write_unescape(fio_str_info_s *restrict dest,
20400+ fio_string_realloc_fn alloc,
20401+ const void *src,
20402+ size_t len) {
2039920403 return fio___string_altering_cycle((fio___string_altering_args_s){
2040020404 .dest = dest,
2040120405 .reallocate = alloc,
@@ -40786,6 +40790,7 @@ Pub/Sub Cleanup
4078640790#if !defined(FIO_INCLUDE_FILE) /* Dev test - ignore line */
4078740791#define FIO___DEV___ /* Development inclusion - ignore line */
4078840792#define FIO_RESP3 /* Development inclusion - ignore line */
40793+ #define FIO_ATOL /* Development inclusion - ignore line */
4078940794#include "./include.h" /* Development inclusion - ignore line */
4079040795#endif /* Development inclusion - ignore line */
4079140796/* *****************************************************************************
@@ -41138,9 +41143,91 @@ static int fio___resp3_stack_pop(fio_resp3_s *p) {
4113841143RESP Implementation - inline functions.
4113941144***************************************************************************** */
4114041145
41141- static size_t fio___resp3_parse_start(fio_resp3_s *parser,
41142- uint8_t *buf,
41143- size_t len);
41146+ FIO_SFUNC size_t fio___resp3_parse_line(fio_resp3_s *p,
41147+ uint8_t *buf,
41148+ size_t len) {
41149+ uint8_t *const start = buf;
41150+ uint8_t *eol = (uint8_t *)FIO_MEMCHR(buf, '\n', len);
41151+ if (!eol)
41152+ return 0;
41153+ uint8_t *end = eol - (eol[0 - (eol > buf)] == '\r');
41154+ ++eol;
41155+ if (end == buf)
41156+ goto finished;
41157+ p->stack[p->depth].otype = buf[0];
41158+ switch (*buf) {
41159+ /** The general form is `+<string>\r\n` */
41160+ case FIO___RESP3_U8_SIMPLE: /* ((unsigned char)'+') */
41161+ /** The general form is `-<string>\r\n` */
41162+ case FIO___RESP3_U8_ERROR: /* ((unsigned char)'-') */
41163+ /** Big number `(<big number>\r\n` */
41164+ case FIO___RESP3_U8_BIGNUM: /* ((unsigned char)'(') */
41165+ ++buf;
41166+ p->stack[p->depth].obj = p->settings.get_string((char *)buf, end - buf);
41167+ goto finished;
41168+ /** The general form is `:<number>\r\n` */
41169+ case FIO___RESP3_U8_NUMBER: /* ((unsigned char)':') */
41170+ ++buf;
41171+ p->stack[p->depth].obj = p->settings.get_number(fio_atol((char **)&buf));
41172+ if (buf[0] != '\r' && buf[0] != '\n')
41173+ goto error;
41174+ goto finished;
41175+ /** Null: `_\r\n` */
41176+ case FIO___RESP3_U8_NULL: /* ((unsigned char)'_') */
41177+ p->stack[p->depth].obj = p->settings.set_null;
41178+ if (buf[1] != '\r' && buf[1] != '\n')
41179+ goto error;
41180+ goto finished;
41181+
41182+ /** Double: ,<floating-point-number>\r\n (inf, inf, nan, -nan) */
41183+ case FIO___RESP3_U8_FLOAT: /* ((unsigned char)',') */
41184+ ++buf;
41185+ goto finished;
41186+ if (buf[1] != '\r' && buf[1] != '\n')
41187+ goto error;
41188+ goto finished;
41189+ /** Boolean: `#t\r\n` and `#f\r\n` */
41190+ case FIO___RESP3_U8_BOOL: /* ((unsigned char)'#') */
41191+ ++buf;
41192+ switch (buf[0]) {
41193+ case 't': p->stack[p->depth].obj = p->settings.set_true; break;
41194+ case 'f': p->stack[p->depth].obj = p->settings.set_false; break;
41195+ default: goto error;
41196+ }
41197+ if (buf[1] != '\r' && buf[1] != '\n')
41198+ goto error;
41199+ goto finished;
41200+
41201+ /* Blob Types */
41202+
41203+ /** The general form is `$<length>\r\n<bytes>\r\n` */
41204+ case FIO___RESP3_U8_BLOB: /* ((unsigned char)'$') */ break;
41205+ /** Blob error: `!<length>\r\n<bytes>\r\n`.*/
41206+ case FIO___RESP3_U8_ERROR_BLOB: /* ((unsigned char)'!') */ break;
41207+ /** Verbatim string: first 3 bytes are the type `XXX:`,i.e., `txt:` */
41208+ case FIO___RESP3_U8_VBLOB: /* ((unsigned char)'=') */ break;
41209+
41210+ /* <aggregate-type-char><numelements><CR><LF> */
41211+ case FIO___RESP3_U8_ARRAY: /* ((unsigned char)'*') */ break;
41212+ case FIO___RESP3_U8_PUSH: /* ((unsigned char)'>') */ break;
41213+ case FIO___RESP3_U8_MAP: /* ((unsigned char)'%') */ break;
41214+ case FIO___RESP3_U8_ATTR: /* ((unsigned char)'|') */ break;
41215+ case FIO___RESP3_U8_SET: /* ((unsigned char)'~') */ break;
41216+ }
41217+
41218+ finished:
41219+ if (fio___resp3_stack_consume(p))
41220+ goto error;
41221+ return eol - start;
41222+ push_finished:
41223+ return eol - start;
41224+ error:
41225+ return eol - start;
41226+ }
41227+
41228+ FIO_SFUNC size_t fio___resp3_parse_router(fio_resp3_s *parser,
41229+ uint8_t *buf,
41230+ size_t len) {}
4114441231
4114541232/** Parse `data`, returning the abount of bytes consumed. */
4114641233FIO_IFUNC size_t fio_resp3_parse(fio_resp3_s *parser,
@@ -41149,11 +41236,7 @@ FIO_IFUNC size_t fio_resp3_parse(fio_resp3_s *parser,
4114941236 size_t r = 0, tmp = 0;
4115041237 if (!buf)
4115141238 return r;
41152- while (len && (tmp = parser->private_data.parse(parser, buf, len)) + 1 > 1) {
41153- r += tmp;
41154- buf += tmp;
41155- len -= tmp;
41156- }
41239+
4115741240 return r;
4115841241}
4115941242
@@ -42778,13 +42861,13 @@ Simple Property Set / Get
4277842861***************************************************************************** */
4277942862
4278042863#define HTTP___MAKE_GET_SET(property) \
42781- FIO_IFUNC fio_str_info_s fio_http_##property(fio_http_s *h) { \
42864+ SFUNC fio_str_info_s fio_http_##property(fio_http_s *h) { \
4278242865 FIO_ASSERT_DEBUG(h, "NULL HTTP handler!"); \
4278342866 return fio_keystr_info(&h->property); \
4278442867 } \
4278542868 \
42786- FIO_IFUNC fio_str_info_s fio_http_##property##_set(fio_http_s *h, \
42787- fio_str_info_s value) { \
42869+ SFUNC fio_str_info_s fio_http_##property##_set(fio_http_s *h, \
42870+ fio_str_info_s value) { \
4278842871 FIO_ASSERT_DEBUG(h, "NULL HTTP handler!"); \
4278942872 fio_keystr_destroy(&h->property, fio___http_keystr_free); \
4279042873 h->property = fio_keystr_init(value, fio___http_keystr_alloc); \
@@ -42798,7 +42881,7 @@ HTTP___MAKE_GET_SET(version)
4279842881
4279942882#undef HTTP___MAKE_GET_SET
4280042883
42801- FIO_IFUNC_DEF_GET( fio_http, fio_http_s, size_t, status)
42884+ FIO_DEF_GET_FUNC(SFUNC, fio_http, fio_http_s, size_t, status)
4280242885
4280342886/** Sets the status associated with the HTTP handle (response). */
4280442887SFUNC size_t fio_http_status_set(fio_http_s *h, size_t status) {
@@ -53174,6 +53257,7 @@ Copyright and License: see header file (000 copyright.h) or top of file
5317453257#undef FIO___TEST_REINCLUDE
5317553258#endif
5317653259
53260+ FIO_DEFINE_RANDOM128_FN(FIO_SFUNC, fio___prng, 0, 0)
5317753261/* *****************************************************************************
5317853262Playhouse hashing (next risky version)
5317953263***************************************************************************** */
@@ -53285,6 +53369,10 @@ FIO_SFUNC void fio_risky2_hash128(void *restrict dest,
5328553369 fio_memcpy16(dest, r);
5328653370}
5328753371
53372+ FIO_SFUNC uintptr_t FIO_NAME_TEST(stl, risky2_wrapper)(char *buf, size_t len) {
53373+ return fio_risky2_hash(buf, len, 1);
53374+ }
53375+
5328853376#undef FIO___R2_HASH_MUL_PRIME
5328953377#undef FIO___R2_HASH_ROUND_FULL
5329053378
@@ -53366,9 +53454,6 @@ FIO_SFUNC uintptr_t FIO_NAME_TEST(stl, risky_wrapper)(char *buf, size_t len) {
5336653454FIO_SFUNC uintptr_t FIO_NAME_TEST(stl, stable_wrapper)(char *buf, size_t len) {
5336753455 return fio_stable_hash(buf, len, 1);
5336853456}
53369- FIO_SFUNC uintptr_t FIO_NAME_TEST(stl, risky2_wrapper)(char *buf, size_t len) {
53370- return fio_risky2_hash(buf, len, 1);
53371- }
5337253457
5337353458FIO_SFUNC uintptr_t FIO_NAME_TEST(stl, risky_ptr_wrapper)(char *buf,
5337453459 size_t len) {
@@ -53580,8 +53665,10 @@ FIO_SFUNC void FIO_NAME_TEST(stl, random_buffer)(uint64_t *stream,
5358053665 fprintf(stderr, "\t- \x1B[1m%s\x1B[0m (%zu CPU cycles):\n", name, clk);
5358153666#endif
5358253667 fprintf(stderr,
53583- "\t zeros / ones (bit frequency)\t%.05f\n",
53584- ((float)1.0 * totals[0]) / totals[1]);
53668+ "\t zeros / ones (frequency bias)\t%.05f%% (should be near zero)\n",
53669+ ((((float)100.0 * totals[0]) / totals[1]) > (float)100.0
53670+ ? ((((float)100.0 * totals[0]) / totals[1]) - 100)
53671+ : ((float)100 - (((float)100.0 * totals[0]) / totals[1]))));
5358553672 if (!(totals[0] < totals[1] + (total_bits / 20) &&
5358653673 totals[1] < totals[0] + (total_bits / 20)))
5358753674 FIO_LOG_ERROR("randomness isn't random?");
@@ -53615,12 +53702,14 @@ FIO_SFUNC void FIO_NAME_TEST(stl, random_buffer)(uint64_t *stream,
5361553702}
5361653703
5361753704FIO_SFUNC void FIO_NAME_TEST(stl, random)(void) {
53618- fprintf(stderr,
53619- "* Testing randomness "
53620- "- bit frequency / hemming distance / chi-square.\n");
5362153705 const size_t test_len = (1UL << 21);
5362253706 uint64_t *rs =
5362353707 (uint64_t *)FIO_MEM_REALLOC(NULL, 0, sizeof(*rs) * test_len, 0);
53708+ fprintf(
53709+ stderr,
53710+ "* Testing randomness "
53711+ "- bit frequency / hemming distance / chi-square (%zu random bytes).\n",
53712+ (size_t)(sizeof(*rs) * test_len));
5362453713 clock_t start, end;
5362553714 FIO_ASSERT_ALLOC(rs);
5362653715
@@ -53710,7 +53799,22 @@ FIO_SFUNC void FIO_NAME_TEST(stl, random)(void) {
5371053799 FIO_NAME_TEST(stl, random_buffer)
5371153800 (rs, test_len, "fio_rand_bytes", end - start);
5371253801
53713- fio_rand_feed2seed(rs, sizeof(*rs) * test_len);
53802+ FIO_MEMSET(rs, 0, sizeof(*rs) * test_len);
53803+ fio___prng64(); /* warmup */
53804+ start = clock();
53805+ for (size_t i = 0; i < test_len; ++i) {
53806+ rs[i] = fio___prng64();
53807+ }
53808+ end = clock();
53809+ FIO_NAME_TEST(stl, random_buffer)
53810+ (rs, test_len, "PNGR128/64bits", end - start);
53811+ FIO_MEMSET(rs, 0, sizeof(*rs) * test_len);
53812+ start = clock();
53813+ fio___prng_bytes(rs, test_len * sizeof(*rs));
53814+ end = clock();
53815+ FIO_NAME_TEST(stl, random_buffer)
53816+ (rs, test_len, "PNGR128_bytes", end - start);
53817+
5371453818 FIO_MEM_FREE(rs, sizeof(*rs) * test_len);
5371553819 fprintf(stderr, "\n");
5371653820 {
0 commit comments