Skip to content

Commit 773a46d

Browse files
committed
misc + docs + random macro finalization
1 parent 468abc7 commit 773a46d

File tree

6 files changed

+1495
-186
lines changed

6 files changed

+1495
-186
lines changed

fio-stl.h

Lines changed: 156 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -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) {
4113841143
RESP 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. */
4114641233
FIO_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). */
4280442887
SFUNC 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
/* *****************************************************************************
5317853262
Playhouse 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) {
5336653454
FIO_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

5337353458
FIO_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

5361753704
FIO_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

Comments
 (0)