module c import v.ast // Note: @@@ here serve as placeholders. // They will be replaced with correct strings // for each constant, during C code generation. // V_COMMIT_HASH is generated by cmd/tools/gen_vc.v . const c_commit_hash_default = ' #ifndef V_COMMIT_HASH #define V_COMMIT_HASH "@@@" #endif ' const c_concurrency_helpers = ' typedef struct __shared_map __shared_map; struct __shared_map { sync__RwMutex mtx; map val; }; static inline voidptr __dup_shared_map(voidptr src, ${ast.int_type_name} sz) { __shared_map* dest = builtin__memdup(src, sz); sync__RwMutex_init(&dest->mtx); return dest; } typedef struct __shared_array __shared_array; struct __shared_array { sync__RwMutex mtx; array val; }; static inline voidptr __dup_shared_array(voidptr src, ${ast.int_type_name} sz) { __shared_array* dest = builtin__memdup(src, sz); sync__RwMutex_init(&dest->mtx); return dest; } static inline void __sort_ptr(uintptr_t a[], bool b[], ${ast.int_type_name} l) { for (${ast.int_type_name} i=1; i0 && a[j-1] > ins) { a[j] = a[j-1]; b[j] = b[j-1]; j--; } a[j] = ins; b[j] = insb; } } ' const c_common_macros = ' #define E_STRUCT_DECL #define E_STRUCT #define __NOINLINE __attribute__((noinline)) #define __IRQHANDLER __attribute__((interrupt)) #define __V_architecture 0 #if defined(__x86_64__) || defined(_M_AMD64) #define __V_amd64 1 #undef __V_architecture #define __V_architecture 1 #endif #if defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) #define __V_arm64 1 #undef __V_architecture #define __V_architecture 2 #endif #if defined(__arm__) || defined(_M_ARM) #define __V_arm32 1 #undef __V_architecture #define __V_architecture 3 #endif #if defined(__riscv) && __riscv_xlen == 64 #define __V_rv64 1 #undef __V_architecture #define __V_architecture 4 #endif #if defined(__riscv) && __riscv_xlen == 32 #define __V_rv32 1 #undef __V_architecture #define __V_architecture 5 #endif #if defined(__i386__) || defined(_M_IX86) #define __V_x86 1 #undef __V_architecture #define __V_architecture 6 #endif #if defined(__s390x__) #define __V_s390x 1 #undef __V_architecture #define __V_architecture 7 #endif #if defined(__powerpc64__) && defined(__LITTLE_ENDIAN__) #define __V_ppc64le 1 #undef __V_architecture #define __V_architecture 8 #endif #if defined(__loongarch64) #define __V_loongarch64 1 #undef __V_architecture #define __V_architecture 9 #endif #if defined(__sparc__) #define __V_sparc64 1 #undef __V_architecture #define __V_architecture 10 #endif #if defined(__powerpc64__) && defined(__BIG_ENDIAN__) #define __V_ppc64 1 #undef __V_architecture #define __V_architecture 11 #endif #if (defined(__powerpc__) || defined(__powerpc) || defined(__POWERPC__) || defined(__ppc__) || defined(__ppc) || defined(__PPC__)) && !defined(__powerpc64__) && !defined(__ppc64__) && !defined(__PPC64__) #define __V_ppc 1 #undef __V_architecture #define __V_architecture 12 #endif // Using just __GNUC__ for detecting gcc, is not reliable because other compilers define it too: #ifdef __GNUC__ #define __V_GCC__ #endif #ifdef __TINYC__ #undef __V_GCC__ #endif #ifdef __cplusplus #undef __V_GCC__ #endif #ifdef __clang__ #undef __V_GCC__ #endif #ifdef _MSC_VER #undef __V_GCC__ #undef E_STRUCT_DECL #undef E_STRUCT #define E_STRUCT_DECL unsigned char _dummy_pad #define E_STRUCT 0 #endif #if defined(__has_include) && !defined(__TINYC__) #if __has_include() && !defined(_WIN32) #define __V_HAVE_EXECINFO_H 1 #include #else // On linux: int backtrace(void **__array, int __size); // On BSD: size_t backtrace(void **, size_t); #endif #elif (defined(__linux__) && (defined(__GLIBC__) || defined(__GNU_LIBRARY__))) || defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) #define __V_HAVE_EXECINFO_H 1 #include #else // On linux: int backtrace(void **__array, int __size); // On BSD: size_t backtrace(void **, size_t); #endif #ifndef __V_HAVE_EXECINFO_H #ifdef __cplusplus extern "C" { #endif int backtrace(void **__array, int __size); char **backtrace_symbols(void *const *__array, int __size); void backtrace_symbols_fd(void *const *__array, int __size, int __fd); #ifdef __cplusplus } #endif #endif #ifdef __TINYC__ #define _Atomic volatile #undef E_STRUCT_DECL #undef E_STRUCT #define E_STRUCT_DECL unsigned char _dummy_pad #define E_STRUCT 0 #undef __NOINLINE #undef __IRQHANDLER // tcc does not support inlining at all #define __NOINLINE #define __IRQHANDLER // #include int tcc_backtrace(const char *fmt, ...); #endif // Use __offsetof_ptr instead of __offset_of, when you *do* have a valid pointer, to avoid UB: #ifndef __offsetof_ptr #define __offsetof_ptr(ptr,PTYPE,FIELDNAME) ((size_t)((byte *)&((PTYPE *)ptr)->FIELDNAME - (byte *)ptr)) #endif // for __offset_of #ifndef __offsetof #if defined(__TINYC__) || defined(_MSC_VER) #define __offsetof(PTYPE,FIELDNAME) ((size_t)(&((PTYPE *)0)->FIELDNAME)) #else #define __offsetof(st, m) __builtin_offsetof(st, m) #endif #endif #if defined(_WIN32) || defined(__CYGWIN__) #define VV_EXP extern __declspec(dllexport) #ifdef _VPARALLELCC #define VV_LOC #else #define VV_LOC static #endif #else // 4 < gcc < 5 is used by some older Ubuntu LTS and Centos versions, // and does not support __has_attribute(visibility) ... #ifndef __has_attribute #define __has_attribute(x) 0 // Compatibility with non-clang compilers. #endif #if (defined(__GNUC__) && (__GNUC__ >= 4)) || (defined(__clang__) && __has_attribute(visibility)) #ifdef ARM #define VV_EXP extern __attribute__((externally_visible,visibility("default"))) #else #define VV_EXP extern __attribute__((visibility("default"))) #endif #if defined(_VOBJECTFILE) || (defined(__clang__) && (defined(_VUSECACHE) || defined(_VBUILDMODULE))) #define VV_LOC static #else #define VV_LOC __attribute__ ((visibility ("hidden"))) #endif #else #define VV_EXP extern #ifdef _VPARALLELCC #define VV_LOC #else #define VV_LOC static #endif #endif #endif #ifdef __cplusplus #include #define _MOV std::move #else #define _MOV #endif #if defined(__TINYC__) && defined(__has_include) // tcc does not support has_include properly yet, turn it off completely #undef __has_include #endif //likely and unlikely macros #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) #define _likely_(x) __builtin_expect(x,1) #define _unlikely_(x) __builtin_expect(x,0) #else #define _likely_(x) (x) #define _unlikely_(x) (x) #endif ' const c_common_weak_attr = ' #if !defined(VWEAK) #define VWEAK __attribute__((weak)) #ifdef _MSC_VER #undef VWEAK #define VWEAK #endif #if defined(__MINGW32__) || defined(__MINGW64__) #undef VWEAK #define VWEAK #endif #endif ' const c_common_hidden_attr = ' #if !defined(VHIDDEN) #define VHIDDEN __attribute__((visibility("hidden"))) #ifdef _MSC_VER #undef VHIDDEN #define VHIDDEN #endif #if defined(__MINGW32__) || defined(__MINGW64__) #undef VHIDDEN #define VHIDDEN #endif #endif ' const c_common_callconv_attr = ' #if !defined(VCALLCONV) #ifdef _MSC_VER #define VCALLCONV(name) __##name #else #define VCALLCONV(name) __attribute__((name)) #endif #endif ' const c_common_noreturn_attr = ' #if !defined(VNORETURN) #if defined(__TINYC__) #define VNORETURN __attribute__((noreturn)) # elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L # define VNORETURN _Noreturn # elif !defined(VNORETURN) && defined(__GNUC__) && __GNUC__ >= 2 # define VNORETURN __attribute__((noreturn)) # endif #ifndef VNORETURN #define VNORETURN #endif #endif ' const c_common_unreachable_attr = ' #if !defined(VUNREACHABLE) #if defined(__GNUC__) && !defined(__clang__) #define V_GCC_VERSION (__GNUC__ * 10000L + __GNUC_MINOR__ * 100L + __GNUC_PATCHLEVEL__) #if (V_GCC_VERSION >= 40500L) && !defined(__TINYC__) #define VUNREACHABLE() do { __builtin_unreachable(); } while (0) #endif #endif #if defined(__clang__) && defined(__has_builtin) && !defined(__TINYC__) #if __has_builtin(__builtin_unreachable) #define VUNREACHABLE() do { __builtin_unreachable(); } while (0) #endif #endif #ifndef VUNREACHABLE #define VUNREACHABLE() do { } while (0) #endif #endif ' const c_unsigned_comparison_functions = ' // unsigned/signed comparisons static inline bool _us32_gt(uint32_t a, int32_t b) { return a > INT32_MAX || (int32_t)a > b; } static inline bool _us32_ge(uint32_t a, int32_t b) { return a >= INT32_MAX || (int32_t)a >= b; } static inline bool _us32_eq(uint32_t a, int32_t b) { return a <= INT32_MAX && (int32_t)a == b; } static inline bool _us32_ne(uint32_t a, int32_t b) { return a > INT32_MAX || (int32_t)a != b; } static inline bool _us32_le(uint32_t a, int32_t b) { return a <= INT32_MAX && (int32_t)a <= b; } static inline bool _us32_lt(uint32_t a, int32_t b) { return a < INT32_MAX && (int32_t)a < b; } static inline bool _us64_gt(uint64_t a, int64_t b) { return a > INT64_MAX || (int64_t)a > b; } static inline bool _us64_ge(uint64_t a, int64_t b) { return a >= INT64_MAX || (int64_t)a >= b; } static inline bool _us64_eq(uint64_t a, int64_t b) { return a <= INT64_MAX && (int64_t)a == b; } static inline bool _us64_ne(uint64_t a, int64_t b) { return a > INT64_MAX || (int64_t)a != b; } static inline bool _us64_le(uint64_t a, int64_t b) { return a <= INT64_MAX && (int64_t)a <= b; } static inline bool _us64_lt(uint64_t a, int64_t b) { return a < INT64_MAX && (int64_t)a < b; } ' const c_float_to_unsigned_conversion_functions = ' // deterministic float -> u64 conversions for explicit V casts // direct C casts are undefined for out-of-range values static inline uint64_t _v_f64_to_u64(double x) { if (!(x >= 0.0)) { return 0; } if (x >= 18446744073709551616.0) { return UINT64_MAX; } return (uint64_t)x; } ' const c_helper_macros = '//============================== HELPER C MACROS =============================*/ // _SLIT0 is used as NULL string for literal arguments // `"" s` is used to enforce a string literal argument #define _SLIT0 (string){.str=(byteptr)(""), .len=0, .is_lit=1} #define _S(s) ((string){.str=(byteptr)("" s), .len=(sizeof(s)-1), .is_lit=1}) #define _SLEN(s, n) ((string){.str=(byteptr)("" s), .len=n, .is_lit=1}) // optimized way to compare literal strings #define _SLIT_EQ(sptr, slen, lit) (slen == sizeof("" lit)-1 && !builtin__vmemcmp(sptr, "" lit, slen)) #define _SLIT_NE(sptr, slen, lit) (slen != sizeof("" lit)-1 || builtin__vmemcmp(sptr, "" lit, slen)) // take the address of an rvalue #define ADDR(type, expr) (&((type[]){expr}[0])) // copy something to the heap #define HEAP(type, expr) ((type*)builtin__memdup((void*)&((type[]){expr}[0]), sizeof(type))) #define HEAP_noscan(type, expr) ((type*)builtin__memdup_noscan((void*)&((type[]){expr}[0]), sizeof(type))) #define HEAP_align(type, expr, align) ((type*)builtin__memdup_align((void*)&((type[]){expr}[0]), sizeof(type), align)) #define HEAP_vgc(type, expr, ptrmap, nptrs) ((type*)builtin__vgc_memdup_typed((void*)&((type[]){expr}[0]), sizeof(type), (ptrmap), (nptrs))) #define _PUSH_MANY(arr, val, tmp, tmp_typ) {tmp_typ tmp = (val); builtin__array_push_many(arr, tmp.data, tmp.len);} #define _PUSH_MANY_noscan(arr, val, tmp, tmp_typ) {tmp_typ tmp = (val); builtin__array_push_many_noscan(arr, tmp.data, tmp.len);} ' const c_windows_msvc_intsizeof_macro = '#ifndef _INTSIZEOF\n\t#define _INTSIZEOF(n) \\\n\t\t((sizeof(n) + \\\n\t\tsizeof(int) - 1) & \\\n\t\t~(sizeof(int) - 1))\n#endif\n' const c_windows_msvc_va_arg_macro = '#ifndef va_arg\n\t#define va_arg(ap, t) \\\n\t\t(*(t*)((ap += \\\n\t\t_INTSIZEOF(t)) - \\\n\t\t_INTSIZEOF(t)))\n#endif\n' const c_headers = c_helper_macros + c_common_macros + c_common_callconv_attr + r' // c_headers typedef int (*qsort_callback_func)(const void*, const void*); #if defined(_MSC_VER) && !defined(__clang__) #define V_CRT_LINKAGE __declspec(dllimport) #define V_CRT_CALL VCALLCONV(cdecl) #else #define V_CRT_LINKAGE #define V_CRT_CALL #endif #if (defined(_MSC_VER) && !defined(__clang__)) || defined(__cplusplus) // Under C++ (g++/clang++), let libc declare FILE/stdio/string/stdlib to keep // noexcept specifiers consistent — the manual extern "C" prototypes below // would otherwise conflict with system headers under -std=c++NN. #include #include #include #include #ifndef va_copy #define va_copy(dest, src) ((dest) = (src)) #endif #ifndef _TRUNCATE #define _TRUNCATE ((size_t)-1) #endif #elif defined(__MINGW32__) || defined(__MINGW64__) || (defined(__clang__) && (defined(_WIN32) || defined(_WIN64))) typedef struct _iobuf FILE; FILE* __cdecl __acrt_iob_func(unsigned index); #define stdin (__acrt_iob_func(0)) #define stdout (__acrt_iob_func(1)) #define stderr (__acrt_iob_func(2)) #elif defined(__TINYC__) && (defined(_WIN32) || defined(_WIN64)) #ifndef _FILE_DEFINED struct _iobuf { char *_ptr; int _cnt; char *_base; int _flag; int _file; int _charbuf; int _bufsiz; char *_tmpfname; }; typedef struct _iobuf FILE; #define _FILE_DEFINED #endif #if defined(_WIN64) FILE* __cdecl __iob_func(void); #else #ifdef _MSVCRT_ extern FILE _iob[]; #define __iob_func() (_iob) #else extern FILE (*_imp___iob)[]; #define __iob_func() (*_imp___iob) #define _iob __iob_func() #endif #endif #define stdin (&__iob_func()[0]) #define stdout (&__iob_func()[1]) #define stderr (&__iob_func()[2]) #elif defined(__vinix__) typedef struct __file FILE; extern FILE* stdin; extern FILE* stdout; extern FILE* stderr; struct __thread_data; struct __threadattr; // pthread_t handling for vinix builds: // - Vinix kernel (freestanding, __STDC_HOSTED__=0): no libc, define // pthread_t ourselves so V code that references it compiles. // - util-vinix cross-compiled on a libc-providing host (hosted, e.g. // glibc on Linux or macOS with -D__vinix__): pull pthread_t from // libc to avoid colliding with the libc typedef. #if defined(__STDC_HOSTED__) && __STDC_HOSTED__ && defined(__has_include) && __has_include() #include #else typedef struct __thread_data *pthread_t; #endif typedef __builtin_va_list va_list; #ifndef va_start #define va_start(ap, v) __builtin_va_start(ap, v) #endif #ifndef va_arg #define va_arg(ap, t) __builtin_va_arg(ap, t) #endif #ifndef va_end #define va_end(ap) __builtin_va_end(ap) #endif #ifndef va_copy #define va_copy(dest, src) __builtin_va_copy(dest, src) #endif #else #if defined(__APPLE__) || defined(__FreeBSD__) typedef struct __sFILE FILE; extern FILE* __stdinp; extern FILE* __stdoutp; extern FILE* __stderrp; #define stdin __stdinp #define stdout __stdoutp #define stderr __stderrp #elif defined(__NetBSD__) || defined(__DragonFly__) typedef struct __sFILE FILE; extern FILE* __stdinp; extern FILE* __stdoutp; extern FILE* __stderrp; #define stdin __stdinp #define stdout __stdoutp #define stderr __stderrp #elif defined(__OpenBSD__) typedef struct __sFILE FILE; #ifndef _STDFILES_DECLARED #define _STDFILES_DECLARED struct __sFstub { long _stub; }; extern struct __sFstub __stdin[]; extern struct __sFstub __stdout[]; extern struct __sFstub __stderr[]; #endif #define stdin ((struct __sFILE *)__stdin) #define stdout ((struct __sFILE *)__stdout) #define stderr ((struct __sFILE *)__stderr) #elif defined(__BIONIC__) struct __sFILE; typedef struct __sFILE FILE; extern FILE* stdin; extern FILE* stdout; extern FILE* stderr; #elif defined(__linux__) && !defined(__GLIBC__) && !defined(__GNU_LIBRARY__) && !defined(__BIONIC__) && !defined(__UCLIBC__) typedef struct _IO_FILE FILE; // musl exposes the stdio streams as `FILE *const`, so match that to stay // compatible with later includes from headers like miniz.h. extern FILE* const stdin; extern FILE* const stdout; extern FILE* const stderr; #else typedef struct _IO_FILE FILE; extern FILE* stdin; extern FILE* stdout; extern FILE* stderr; #endif typedef __builtin_va_list va_list; #ifndef va_start #define va_start(ap, v) __builtin_va_start(ap, v) #endif #ifndef va_arg #define va_arg(ap, t) __builtin_va_arg(ap, t) #endif #ifndef va_end #define va_end(ap) __builtin_va_end(ap) #endif #ifndef va_copy #define va_copy(dest, src) __builtin_va_copy(dest, src) #endif #endif #if (!defined(_MSC_VER) || defined(__clang__)) && !defined(__cplusplus) // mingw-w64 stdio.h declares these as static __mingw_ovr inline overrides // when __USE_MINGW_ANSI_STDIO is on. Skip them under gcc+mingw to avoid // static-after-extern conflicts; clang+mingw needs them because it builds // with -Werror=implicit-function-declaration and does not hit the conflict. #if !((defined(__MINGW32__) || defined(__MINGW64__)) && !defined(__clang__)) V_CRT_LINKAGE int V_CRT_CALL vfprintf(FILE *stream, const char *format, va_list ap); V_CRT_LINKAGE int V_CRT_CALL vsnprintf(char *str, size_t size, const char *format, va_list ap); V_CRT_LINKAGE int V_CRT_CALL fprintf(FILE *stream, const char *format, ...); V_CRT_LINKAGE int V_CRT_CALL printf(const char *format, ...); V_CRT_LINKAGE int V_CRT_CALL snprintf(char *str, size_t size, const char *format, ...); V_CRT_LINKAGE int V_CRT_CALL sprintf(char *str, const char *format, ...); V_CRT_LINKAGE int V_CRT_CALL sscanf(const char *str, const char *format, ...); V_CRT_LINKAGE int V_CRT_CALL scanf(const char *format, ...); #endif V_CRT_LINKAGE int V_CRT_CALL puts(const char *str); V_CRT_LINKAGE void V_CRT_CALL perror(const char *str); V_CRT_LINKAGE int V_CRT_CALL fputs(const char *str, FILE *stream); V_CRT_LINKAGE int V_CRT_CALL getchar(void); V_CRT_LINKAGE int V_CRT_CALL putchar(int ch); V_CRT_LINKAGE int V_CRT_CALL getc(FILE *stream); V_CRT_LINKAGE int V_CRT_CALL fgetc(FILE *stream); V_CRT_LINKAGE int V_CRT_CALL ungetc(int ch, FILE *stream); V_CRT_LINKAGE int V_CRT_CALL fflush(FILE *stream); V_CRT_LINKAGE int V_CRT_CALL feof(FILE *stream); V_CRT_LINKAGE int V_CRT_CALL ferror(FILE *stream); V_CRT_LINKAGE void V_CRT_CALL clearerr(FILE *stream); V_CRT_LINKAGE int V_CRT_CALL setvbuf(FILE *stream, char *buf, int mode, size_t size); V_CRT_LINKAGE long V_CRT_CALL ftell(FILE *stream); V_CRT_LINKAGE void V_CRT_CALL rewind(FILE *stream); V_CRT_LINKAGE FILE * V_CRT_CALL fopen(const char *filename, const char *mode); V_CRT_LINKAGE FILE * V_CRT_CALL fdopen(int fd, const char *mode); V_CRT_LINKAGE FILE * V_CRT_CALL freopen(const char *filename, const char *mode, FILE *stream); V_CRT_LINKAGE int V_CRT_CALL fileno(FILE *stream); V_CRT_LINKAGE size_t V_CRT_CALL fread(void *ptr, size_t size, size_t items, FILE *stream); V_CRT_LINKAGE size_t V_CRT_CALL fwrite(const void *ptr, size_t size, size_t items, FILE *stream); #if defined(__vinix__) V_CRT_LINKAGE char * V_CRT_CALL fgets(char *str, size_t size, FILE *stream); #else V_CRT_LINKAGE char * V_CRT_CALL fgets(char *str, int size, FILE *stream); #endif V_CRT_LINKAGE int V_CRT_CALL fclose(FILE *stream); #if defined(__vinix__) V_CRT_LINKAGE FILE * V_CRT_CALL popen(char *command, char *mode); #else V_CRT_LINKAGE FILE * V_CRT_CALL popen(const char *command, const char *mode); #endif V_CRT_LINKAGE int V_CRT_CALL pclose(FILE *stream); V_CRT_LINKAGE void * V_CRT_CALL malloc(size_t size); V_CRT_LINKAGE void * V_CRT_CALL calloc(size_t nitems, size_t size); V_CRT_LINKAGE void * V_CRT_CALL realloc(void *ptr, size_t size); V_CRT_LINKAGE void * V_CRT_CALL aligned_alloc(size_t alignment, size_t size); V_CRT_LINKAGE void V_CRT_CALL free(void *ptr); V_CRT_LINKAGE int V_CRT_CALL rand(void); V_CRT_LINKAGE void V_CRT_CALL srand(unsigned int seed); V_CRT_LINKAGE int V_CRT_CALL atexit(void (*cb)(void)); V_CRT_LINKAGE void V_CRT_CALL exit(int status); V_CRT_LINKAGE int V_CRT_CALL abs(int n); V_CRT_LINKAGE int V_CRT_CALL atoi(const char *str); V_CRT_LINKAGE double V_CRT_CALL atof(const char *str); V_CRT_LINKAGE char * V_CRT_CALL getenv(const char *name); V_CRT_LINKAGE int V_CRT_CALL setenv(const char *name, const char *value, int overwrite); V_CRT_LINKAGE int V_CRT_CALL unsetenv(const char *name); V_CRT_LINKAGE int V_CRT_CALL system(const char *command); V_CRT_LINKAGE int V_CRT_CALL remove(const char *path); V_CRT_LINKAGE int V_CRT_CALL rename(const char *old_path, const char *new_path); V_CRT_LINKAGE char * V_CRT_CALL realpath(const char *path, char *resolved_path); V_CRT_LINKAGE int V_CRT_CALL mkstemp(char *stemplate); V_CRT_LINKAGE void V_CRT_CALL qsort(void *base, size_t items, size_t item_size, qsort_callback_func cb); #if defined(__vinix__) V_CRT_LINKAGE int V_CRT_CALL strcmp(char *left, char *right); V_CRT_LINKAGE int V_CRT_CALL strncmp(char *left, char *right, size_t n); #else V_CRT_LINKAGE int V_CRT_CALL strcmp(const char *left, const char *right); V_CRT_LINKAGE int V_CRT_CALL strncmp(const char *left, const char *right, size_t n); #endif #if !defined(_WIN32) && !defined(_WIN64) && !defined(__BIONIC__) V_CRT_LINKAGE char * V_CRT_CALL strdup(const char *str); #endif #if !defined(_WIN32) && !defined(_WIN64) V_CRT_LINKAGE int V_CRT_CALL strcasecmp(const char *left, const char *right); V_CRT_LINKAGE int V_CRT_CALL strncasecmp(const char *left, const char *right, size_t n); #endif #if defined(__vinix__) V_CRT_LINKAGE size_t V_CRT_CALL strlen(char *str); #else V_CRT_LINKAGE size_t V_CRT_CALL strlen(const char *str); #endif V_CRT_LINKAGE char * V_CRT_CALL strerror(int errnum); V_CRT_LINKAGE void * V_CRT_CALL memcpy(void *dest, const void *src, size_t n); V_CRT_LINKAGE void * V_CRT_CALL memmove(void *dest, const void *src, size_t n); V_CRT_LINKAGE void * V_CRT_CALL memset(void *dest, int ch, size_t n); V_CRT_LINKAGE int V_CRT_CALL memcmp(const void *left, const void *right, size_t n); V_CRT_LINKAGE void * V_CRT_CALL memchr(const void *str, int c, size_t n); V_CRT_LINKAGE char * V_CRT_CALL strchr(const char *str, int c); V_CRT_LINKAGE char * V_CRT_CALL strrchr(const char *str, int c); V_CRT_LINKAGE char * V_CRT_CALL strstr(const char *haystack, const char *needle); V_CRT_LINKAGE int V_CRT_CALL fseek(FILE *stream, long offset, int whence); V_CRT_LINKAGE isize V_CRT_CALL getline(char **lineptr, size_t *n, FILE *stream); #if defined(_WIN32) || defined(_WIN64) V_CRT_LINKAGE int V_CRT_CALL _fileno(FILE *stream); V_CRT_LINKAGE FILE * V_CRT_CALL _wfopen(const unsigned short *filename, const unsigned short *mode); V_CRT_LINKAGE int V_CRT_CALL _wremove(const unsigned short *path); V_CRT_LINKAGE void * V_CRT_CALL _aligned_malloc(size_t size, size_t alignment); V_CRT_LINKAGE void * V_CRT_CALL _aligned_realloc(void *memory, size_t size, size_t alignment); V_CRT_LINKAGE void V_CRT_CALL _aligned_free(void *memory); V_CRT_LINKAGE unsigned short * V_CRT_CALL _wgetenv(const unsigned short *varname); V_CRT_LINKAGE int V_CRT_CALL _wputenv(const unsigned short *envstring); #endif #if defined(_MSC_VER) && !defined(__clang__) #ifndef _TRUNCATE #define _TRUNCATE ((size_t)-1) #endif V_CRT_LINKAGE int V_CRT_CALL _vscprintf(const char *format, va_list ap); V_CRT_LINKAGE int V_CRT_CALL _vsnprintf_s(char *buffer, size_t size, size_t count, const char *format, va_list ap); #endif #endif #ifndef _IOFBF #define _IOFBF 0 #endif #ifndef _IOLBF #define _IOLBF 1 #endif #ifndef _IONBF #define _IONBF 2 #endif #ifndef EOF #define EOF (-1) #endif #ifndef SEEK_SET #define SEEK_SET 0 #endif #ifndef SEEK_CUR #define SEEK_CUR 1 #endif #ifndef SEEK_END #define SEEK_END 2 #endif #ifndef RAND_MAX enum { #if defined(_MSC_VER) RAND_MAX = 0x7fff #else RAND_MAX = 2147483647 #endif }; #endif #undef V_CRT_LINKAGE #undef V_CRT_CALL static void v_stable_sort(void *base, size_t items, size_t item_size, qsort_callback_func cb) { if (items < 2 || item_size == 0) { return; } if (items > ((size_t)-1) / item_size) { qsort(base, items, item_size, cb); return; } const size_t bytes = items * item_size; char *base_bytes = (char*)base; char *tmp = (char*)malloc(bytes); if (tmp == 0) { qsort(base, items, item_size, cb); return; } char *src = base_bytes; char *dst = tmp; for (size_t width = 1; width < items;) { for (size_t left = 0; left < items;) { size_t mid = left; mid += width; if (mid > items) { mid = items; } size_t right = mid; right += width; if (right > items || right < mid) { right = items; } size_t i = left; size_t j = mid; size_t k = left; while (i < mid && j < right) { char *leftp = src; leftp += i * item_size; char *rightp = src; rightp += j * item_size; char *dstp = dst; dstp += k * item_size; if (cb(leftp, rightp) <= 0) { memcpy(dstp, leftp, item_size); i++; } else { memcpy(dstp, rightp, item_size); j++; } k++; } while (i < mid) { char *dstp = dst; dstp += k * item_size; char *srcp = src; srcp += i * item_size; memcpy(dstp, srcp, item_size); i++; k++; } while (j < right) { char *dstp = dst; dstp += k * item_size; char *srcp = src; srcp += j * item_size; memcpy(dstp, srcp, item_size); j++; k++; } left = right; } char *next_src = dst; dst = src; src = next_src; if (width > items / 2) { width = items; } else { width *= 2; } } if (src != base_bytes) { memcpy(base_bytes, src, bytes); } free(tmp); } #if defined(__TINYC__) // https://lists.nongnu.org/archive/html/tinycc-devel/2025-10/msg00007.html // gnu headers use to #define __attribute__ to empty for non-gcc compilers #undef __attribute__ #endif #if defined(_MSC_VER) && !defined(__clang__) // Ensure C99-like return semantics and NUL-termination for MSVC snprintf/vsnprintf. static int v__vsnprintf(char *s, size_t n, const char *fmt, va_list ap) { va_list ap_copy; va_copy(ap_copy, ap); const int needed = _vscprintf(fmt, ap_copy); va_end(ap_copy); if (n > 0) { const int written = _vsnprintf_s(s, n, _TRUNCATE, fmt, ap); if (written < 0) { s[n - 1] = 0; } } return needed; } static int v__snprintf(char *s, size_t n, const char *fmt, ...) { va_list ap; va_start(ap, fmt); const int needed = v__vsnprintf(s, n, fmt, ap); va_end(ap); return needed; } #define vsnprintf v__vsnprintf #define snprintf v__snprintf #endif //================================== GLOBALS =================================*/ #ifdef _VOBJECTFILE static void _vinit(int ___argc, voidptr ___argv); static void _vcleanup(void); #else void _vinit(int ___argc, voidptr ___argv); void _vcleanup(void); #endif #ifdef _WIN32 // Export helpers so the autogenerated DllMain, or a user-defined one, // can reuse the default V shared-library init/cleanup path. #ifdef _VOBJECTFILE static void _vinit_caller(); static void _vcleanup_caller(); #else VV_EXP void _vinit_caller(); VV_EXP void _vcleanup_caller(); #endif #endif #if !defined(_WIN32) #define sigaction_size sizeof(sigaction); #endif #define _ARR_LEN(a) ( (sizeof(a)) / (sizeof(a[0])) ) #if INTPTR_MAX == INT32_MAX #define TARGET_IS_32BIT 1 #elif INTPTR_MAX == INT64_MAX #define TARGET_IS_64BIT 1 #else #error "The environment is not 32 or 64-bit." #endif #if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ || defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || defined(__BIG_ENDIAN__) || defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || defined(_MIBSEB) || defined(__MIBSEB) || defined(__MIBSEB__) #define TARGET_ORDER_IS_BIG 1 #elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) || defined(_M_AMD64) || defined(_M_ARM64) || defined(_M_X64) || defined(_M_IX86) #define TARGET_ORDER_IS_LITTLE 1 #else #error "Unknown architecture endianness" #endif #if !defined(_WIN32) && !defined(__vinix__) #include #include // tolower #include #include // sleep extern char **environ; #include #ifndef PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP // musl does not have that #define pthread_rwlockattr_setkind_np(a, b) #endif #endif #if (defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__serenity__) || defined(__sun) || defined(__plan9__) || defined(__OpenBSD__)) && !defined(__vinix__) #include #include // for os__wait #endif #ifdef __OpenBSD__ #include #endif #ifdef __FreeBSD__ #include #include #endif #ifdef __NetBSD__ #include // for os__wait #endif #ifdef __TERMUX__ #if !defined(__BIONIC_AVAILABILITY_GUARD) #define __BIONIC_AVAILABILITY_GUARD(api_level) 0 #endif #if __BIONIC_AVAILABILITY_GUARD(28) #else void * aligned_alloc(size_t alignment, size_t size) { return malloc(size); } #endif #endif #ifdef __APPLE__ // macOS only exports aligned_alloc starting with 10.15. #if !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101500 static void *v__aligned_alloc_fallback(size_t alignment, size_t size) { void *res = 0; if (alignment < sizeof(void *)) { alignment = sizeof(void *); } if (posix_memalign(&res, alignment, size) != 0) { return 0; } return res; } #define aligned_alloc v__aligned_alloc_fallback #endif #endif #ifdef _WIN32 #ifdef WINVER #undef WINVER #endif #define WINVER 0x0600 #ifdef _WIN32_WINNT #undef _WIN32_WINNT #endif #define _WIN32_WINNT 0x0600 #ifndef WIN32_FULL #define WIN32_LEAN_AND_MEAN #endif #ifndef _UNICODE #define _UNICODE #endif #ifndef UNICODE #define UNICODE #endif #include #include // _waccess #include // _wgetcwd #ifdef V_USE_SIGNAL_H #include // signal and SIGSEGV for segmentation fault handler #endif #ifdef _MSC_VER // On MSVC these are the same (as long as /volatile:ms is passed) #define _Atomic volatile // MSVC cannot parse some things properly #undef __NOINLINE #undef __IRQHANDLER #define __NOINLINE __declspec(noinline) #define __IRQHANDLER __declspec(naked) #include #pragma comment(lib, "Dbghelp") #endif #endif #if defined(__CYGWIN__) && !defined(_WIN32) #error Cygwin is not supported, please use MinGW or Visual Studio. #endif #if defined(__MINGW32__) || defined(__MINGW64__) || (defined(_WIN32) && defined(__TINYC__)) || defined(_MSC_VER) #undef PRId64 #undef PRIi64 #undef PRIo64 #undef PRIu64 #undef PRIx64 #undef PRIX64 #define PRId64 "lld" #define PRIi64 "lli" #define PRIo64 "llo" #define PRIu64 "llu" #define PRIx64 "llx" #define PRIX64 "llX" #endif #ifdef _VFREESTANDING #undef _VFREESTANDING #endif ' const c_builtin_types = ' //================================== builtin types ================================*/ #if defined(__x86_64__) || defined(_M_AMD64) || defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) || (defined(__riscv_xlen) && __riscv_xlen == 64) || defined(__s390x__) || (defined(__powerpc64__) && defined(__LITTLE_ENDIAN__)) || defined(__loongarch64) || defined(__sparc__) || (defined(__powerpc64__) && defined(__BIG_ENDIAN__)) typedef int64_t vint_t; #else typedef int32_t vint_t; #endif typedef int64_t i64; typedef int16_t i16; typedef int8_t i8; typedef uint64_t u64; typedef uint32_t u32; typedef uint8_t u8; typedef uint16_t u16; typedef u8 byte; typedef int32_t i32; typedef uint32_t rune; typedef size_t usize; typedef ptrdiff_t isize; #ifndef VNOFLOAT typedef float f32; typedef double f64; #else typedef int32_t f32; typedef int64_t f64; #endif typedef int64_t int_literal; #ifndef VNOFLOAT typedef double float_literal; #else typedef int64_t float_literal; #endif typedef unsigned char* byteptr; typedef void* voidptr; typedef char* charptr; typedef u8 array_fixed_byte_300 [300]; typedef struct sync__Channel* chan; #ifndef CUSTOM_DEFINE_no_bool #ifndef __cplusplus #if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 202311L #ifndef bool #ifdef CUSTOM_DEFINE_4bytebool typedef int bool; #else typedef u8 bool; #endif #define true 1 #define false 0 #endif #endif #endif #endif ' const c_shift_helpers = ' #define V_SAFE_SHIFT_BITS(type) ((u64)(sizeof(type) * 8)) #define V_SAFE_LSHIFT_UNSIGNED(name, type) static inline type name(type x, u64 y) { return y >= V_SAFE_SHIFT_BITS(type) ? (type)0 : (type)(x << y); } #define V_SAFE_LSHIFT_SIGNED(name, type, unsigned_type) static inline type name(type x, u64 y) { return y >= V_SAFE_SHIFT_BITS(type) ? (type)0 : (type)(((unsigned_type)x) << y); } #define V_SAFE_RSHIFT_UNSIGNED(name, type) static inline type name(type x, u64 y) { return y >= V_SAFE_SHIFT_BITS(type) ? (type)0 : (type)(x >> y); } #define V_SAFE_RSHIFT_SIGNED(name, type) static inline type name(type x, u64 y) { return y >= V_SAFE_SHIFT_BITS(type) ? (type)(x < 0 ? -1 : 0) : (type)(x >> y); } V_SAFE_LSHIFT_SIGNED(v__lshift_char, char, u8) V_SAFE_RSHIFT_SIGNED(v__rshift_char, char) V_SAFE_LSHIFT_SIGNED(v__lshift_i8, i8, u8) V_SAFE_RSHIFT_SIGNED(v__rshift_i8, i8) V_SAFE_LSHIFT_SIGNED(v__lshift_i16, i16, u16) V_SAFE_RSHIFT_SIGNED(v__rshift_i16, i16) V_SAFE_LSHIFT_SIGNED(v__lshift_i32, i32, u32) V_SAFE_RSHIFT_SIGNED(v__rshift_i32, i32) V_SAFE_LSHIFT_SIGNED(v__lshift_int, int, unsigned int) V_SAFE_RSHIFT_SIGNED(v__rshift_int, int) V_SAFE_LSHIFT_SIGNED(v__lshift_vint_t, vint_t, u64) V_SAFE_RSHIFT_SIGNED(v__rshift_vint_t, vint_t) V_SAFE_LSHIFT_SIGNED(v__lshift_i64, i64, u64) V_SAFE_RSHIFT_SIGNED(v__rshift_i64, i64) V_SAFE_LSHIFT_SIGNED(v__lshift_isize, isize, usize) V_SAFE_RSHIFT_SIGNED(v__rshift_isize, isize) V_SAFE_LSHIFT_UNSIGNED(v__lshift_u8, u8) V_SAFE_RSHIFT_UNSIGNED(v__rshift_u8, u8) V_SAFE_LSHIFT_UNSIGNED(v__lshift_u16, u16) V_SAFE_RSHIFT_UNSIGNED(v__rshift_u16, u16) V_SAFE_LSHIFT_UNSIGNED(v__lshift_u32, u32) V_SAFE_RSHIFT_UNSIGNED(v__rshift_u32, u32) V_SAFE_LSHIFT_UNSIGNED(v__lshift_u64, u64) V_SAFE_RSHIFT_UNSIGNED(v__rshift_u64, u64) V_SAFE_LSHIFT_UNSIGNED(v__lshift_usize, usize) V_SAFE_RSHIFT_UNSIGNED(v__rshift_usize, usize) V_SAFE_LSHIFT_UNSIGNED(v__lshift_rune, rune) V_SAFE_RSHIFT_UNSIGNED(v__rshift_rune, rune) V_SAFE_LSHIFT_SIGNED(v__lshift_int_literal, int_literal, u64) V_SAFE_RSHIFT_SIGNED(v__rshift_int_literal, int_literal) #undef V_SAFE_RSHIFT_SIGNED #undef V_SAFE_RSHIFT_UNSIGNED #undef V_SAFE_LSHIFT_SIGNED #undef V_SAFE_LSHIFT_UNSIGNED #undef V_SAFE_SHIFT_BITS ' const c_mapfn_callback_types = ' typedef u64 (*MapHashFn)(voidptr); typedef bool (*MapEqFn)(voidptr, voidptr); typedef void (*MapCloneFn)(voidptr, voidptr); typedef void (*MapFreeFn)(voidptr); ' const c_bare_headers = c_helper_macros + c_common_macros + c_common_callconv_attr + ' #define _VFREESTANDING // Memory allocation related headers void *malloc(size_t size); void *calloc(size_t nitems, size_t size); void *realloc(void *ptr, size_t size); void *memcpy(void *dest, const void *src, size_t n); void *memset(void *s, int c, size_t n); void *memmove(void *dest, const void *src, size_t n); // varargs implementation, TODO: works on tcc and gcc, but is very unportable and hacky typedef __builtin_va_list va_list; #define va_start(a, b) __builtin_va_start(a, b) #define va_end(a) __builtin_va_end(a) #define va_arg(a, b) __builtin_va_arg(a, b) #define va_copy(a, b) __builtin_va_copy(a, b) //================================== GLOBALS =================================*/ #ifdef _VOBJECTFILE static void _vinit(int ___argc, voidptr ___argv); static void _vcleanup(void); #else void _vinit(int ___argc, voidptr ___argv); void _vcleanup(); #endif #if !defined(_WIN32) #define sigaction_size sizeof(sigaction); #endif #define _ARR_LEN(a) ( (sizeof(a)) / (sizeof(a[0])) ) VV_LOC voidptr builtin__memdup(voidptr src, isize size); ' const c_wyhash_headers = ' #ifndef wyhash_final_version_4_2 #define wyhash_final_version_4_2 #ifndef WYHASH_CONDOM // protections that produce different results: // 1: normal valid behavior // 2: extra protection against entropy loss (probability=2^-63), aka. "blind multiplication" #define WYHASH_CONDOM 1 #endif #ifndef WYHASH_32BIT_MUM // 0: normal version, slow on 32 bit systems // 1: faster on 32 bit systems but produces different results, incompatible with wy2u0k function #define WYHASH_32BIT_MUM 0 #endif // includes #include #if defined(_MSC_VER) && defined(_M_X64) #include #pragma intrinsic(_umul128) #endif // 128bit multiply function static inline uint64_t _wyrot(uint64_t x) { return (x>>32)|(x<<32); } static inline void _wymum(uint64_t *A, uint64_t *B){ #if(WYHASH_32BIT_MUM) uint64_t hh=(*A>>32)*(*B>>32), hl=(*A>>32)*(uint32_t)*B, lh=(uint32_t)*A*(*B>>32), ll=(uint64_t)(uint32_t)*A*(uint32_t)*B; #if(WYHASH_CONDOM>1) *A^=_wyrot(hl)^hh; *B^=_wyrot(lh)^ll; #else *A=_wyrot(hl)^hh; *B=_wyrot(lh)^ll; #endif #elif defined(__SIZEOF_INT128__) && !defined(VWASM) __uint128_t r=*A; r*=*B; #if(WYHASH_CONDOM>1) *A^=(uint64_t)r; *B^=(uint64_t)(r>>64); #else *A=(uint64_t)r; *B=(uint64_t)(r>>64); #endif #elif defined(_MSC_VER) && defined(_M_X64) #if(WYHASH_CONDOM>1) uint64_t a, b; a=_umul128(*A,*B,&b); *A^=a; *B^=b; #else *A=_umul128(*A,*B,B); #endif #else uint64_t ha=*A>>32, hb=*B>>32, la=(uint32_t)*A, lb=(uint32_t)*B, hi, lo; uint64_t rh=ha*hb, rm0=ha*lb, rm1=hb*la, rl=la*lb, t=rl+(rm0<<32), c=t>32)+(rm1>>32)+c; #if(WYHASH_CONDOM>1) *A^=lo; *B^=hi; #else *A=lo; *B=hi; #endif #endif } // multiply and xor mix function, aka MUM static inline uint64_t _wymix(uint64_t A, uint64_t B){ _wymum(&A,&B); return A^B; } // endian macros #ifndef WYHASH_LITTLE_ENDIAN #ifdef TARGET_ORDER_IS_LITTLE #define WYHASH_LITTLE_ENDIAN 1 #else #define WYHASH_LITTLE_ENDIAN 0 #endif #endif // read functions #if (WYHASH_LITTLE_ENDIAN) static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return v;} static inline uint64_t _wyr4(const uint8_t *p) { uint32_t v; memcpy(&v, p, 4); return v;} #elif !defined(__TINYC__) && (defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)) static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return __builtin_bswap64(v);} static inline uint64_t _wyr4(const uint8_t *p) { uint32_t v; memcpy(&v, p, 4); return __builtin_bswap32(v);} #elif defined(_MSC_VER) static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return _byteswap_uint64(v);} static inline uint64_t _wyr4(const uint8_t *p) { uint32_t v; memcpy(&v, p, 4); return _byteswap_ulong(v);} #else static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return (((v >> 56) & 0xff)| ((v >> 40) & 0xff00)| ((v >> 24) & 0xff0000)| ((v >> 8) & 0xff000000)| ((v << 8) & 0xff00000000)| ((v << 24) & 0xff0000000000)| ((v << 40) & 0xff000000000000)| ((v << 56) & 0xff00000000000000)); } static inline uint64_t _wyr4(const uint8_t *p) { uint32_t v; memcpy(&v, p, 4); return (((v >> 24) & 0xff)| ((v >> 8) & 0xff00)| ((v << 8) & 0xff0000)| ((v << 24) & 0xff000000)); } #endif static inline uint64_t _wyr3(const uint8_t *p, size_t k) { return (((uint64_t)p[0])<<16)|(((uint64_t)p[k>>1])<<8)|p[k-1];} // wyhash main function static inline uint64_t wyhash(const void *key, size_t len, uint64_t seed, const uint64_t *secret){ const uint8_t *p=(const uint8_t *)key; seed^=_wymix(seed^secret[0]^len,secret[1]); uint64_t a, b; if (_likely_(len<=16)) { if (_likely_(len>=4)) { a=(_wyr4(p)<<32)|_wyr4(p+((len>>3)<<2)); b=(_wyr4(p+len-4)<<32)|_wyr4(p+len-4-((len>>3)<<2)); } else if (_likely_(len>0)) { a=_wyr3(p,len); b=0; } else a=b=0; } else { size_t i=len; if (_unlikely_(i>=48)) { uint64_t see1=seed, see2=seed; do { seed=_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed); see1=_wymix(_wyr8(p+16)^secret[2],_wyr8(p+24)^see1); see2=_wymix(_wyr8(p+32)^secret[3],_wyr8(p+40)^see2); p+=48; i-=48; } while(_likely_(i>=48)); seed^=see1^see2; } while(_unlikely_(i>16)) { seed=_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed); i-=16; p+=16; } a=_wyr8(p+i-16); b=_wyr8(p+i-8); } a^=secret[1]; b^=seed; _wymum(&a,&b); return _wymix(a^secret[0]^len,b^secret[1]); } // the default secret parameters static const uint64_t _wyp[4] = {0x2d358dccaa6c78a5ull, 0x8bb84b93962eacc9ull, 0x4b33a62ed433d4a3ull, 0x4d5a2da51de1aa47ull}; // a useful 64bit-64bit mix function to produce deterministic pseudo random numbers that can pass BigCrush and PractRand static inline uint64_t wyhash64(uint64_t A, uint64_t B){ A^=0x2d358dccaa6c78a5ull; B^=0x8bb84b93962eacc9ull; _wymum(&A,&B); return _wymix(A^0x2d358dccaa6c78a5ull,B^0x8bb84b93962eacc9ull);} // the wyrand PRNG that pass BigCrush and PractRand static inline uint64_t wyrand(uint64_t *seed){ *seed+=0x2d358dccaa6c78a5ull; return _wymix(*seed,*seed^0x8bb84b93962eacc9ull);} #ifndef __vinix__ // convert any 64 bit pseudo random numbers to uniform distribution [0,1). It can be combined with wyrand, wyhash64 or wyhash. static inline double wy2u01(uint64_t r){ const double _wynorm=1.0/(1ull<<52); return (r>>12)*_wynorm;} // convert any 64 bit pseudo random numbers to APPROXIMATE Gaussian distribution. It can be combined with wyrand, wyhash64 or wyhash. static inline double wy2gau(uint64_t r){ const double _wynorm=1.0/(1ull<<20); return ((r&0x1fffff)+((r>>21)&0x1fffff)+((r>>42)&0x1fffff))*_wynorm-3.0;} #endif #if(!WYHASH_32BIT_MUM) // fast range integer random number generation on [0,k) credit to Daniel Lemire. May not work when WYHASH_32BIT_MUM=1. It can be combined with wyrand, wyhash64 or wyhash. static inline uint64_t wy2u0k(uint64_t r, uint64_t k){ _wymum(&r,&k); return k; } #endif #endif #define _IN_MAP(val, m) builtin__map_exists(m, val) '