diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2018-01-03 15:11:33 +0100 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2018-01-04 13:15:42 +0100 |
commit | 2d5b4683e912d6e6e1f1e2ca5aa0297beb3e6807 (patch) | |
tree | de2343f1280afd1ae32a1b8d7805a42f0fc5f8e7 /source/fitz | |
parent | a292539cc9e5e91843d48e691038d9c1b529422c (diff) | |
download | mupdf-2d5b4683e912d6e6e1f1e2ca5aa0297beb3e6807.tar.xz |
Add portable pseudo-random number generator based on the lrand48 family.
Diffstat (limited to 'source/fitz')
-rw-r--r-- | source/fitz/context.c | 19 | ||||
-rw-r--r-- | source/fitz/random.c | 80 |
2 files changed, 99 insertions, 0 deletions
diff --git a/source/fitz/context.c b/source/fitz/context.c index f4ebdc98..67fef05b 100644 --- a/source/fitz/context.c +++ b/source/fitz/context.c @@ -3,6 +3,7 @@ #include <assert.h> #include <string.h> #include <stdio.h> +#include <time.h> struct fz_id_context_s { @@ -132,6 +133,22 @@ void fz_tune_image_scale(fz_context *ctx, fz_tune_image_scale_fn *image_scale, v ctx->tuning->image_scale_arg = arg; } +static void fz_init_random_context(fz_context *ctx) +{ + if (!ctx) + return; + + ctx->seed48[0] = 0; + ctx->seed48[1] = 0; + ctx->seed48[2] = 0; + ctx->seed48[3] = 0xe66d; + ctx->seed48[4] = 0xdeec; + ctx->seed48[5] = 0x5; + ctx->seed48[6] = 0xb; + + fz_srand48(ctx, (uint32_t)time(NULL)); +} + void fz_drop_context(fz_context *ctx) { @@ -250,6 +267,7 @@ fz_new_context_imp(const fz_alloc_context *alloc, const fz_locks_context *locks, fz_new_document_handler_context(ctx); fz_new_style_context(ctx); fz_new_tuning_context(ctx); + fz_init_random_context(ctx); } fz_catch(ctx) { @@ -304,6 +322,7 @@ fz_clone_context_internal(fz_context *ctx) new_ctx->id = fz_keep_id_context(new_ctx); new_ctx->tuning = ctx->tuning; new_ctx->tuning = fz_keep_tuning_context(new_ctx); + memcpy(new_ctx->seed48, ctx->seed48, sizeof ctx->seed48); new_ctx->handler = ctx->handler; new_ctx->handler = fz_keep_document_handler_context(new_ctx); diff --git a/source/fitz/random.c b/source/fitz/random.c new file mode 100644 index 00000000..95e1990c --- /dev/null +++ b/source/fitz/random.c @@ -0,0 +1,80 @@ +#include "mupdf/fitz.h" + +/* The pseudo-random number generator in this file is based on the MIT licensed + * implementation in musl libc. */ + +#include <string.h> + +/* The seed is initialized in context.c as follows: + * static uint16_t __seed48[7] = { 0, 0, 0, 0xe66d, 0xdeec, 0x5, 0xb }; + */ + +static uint64_t fz_rand48_step(uint16_t *xi, uint16_t *lc) +{ + uint64_t a, x; + x = xi[0] | (xi[1]+0U)<<16 | (xi[2]+0ULL)<<32; + a = lc[0] | (lc[1]+0U)<<16 | (lc[2]+0ULL)<<32; + x = a*x + lc[3]; + xi[0] = x; + xi[1] = x>>16; + xi[2] = x>>32; + return x & 0xffffffffffffull; +} + +double fz_erand48(fz_context *ctx, uint16_t s[3]) +{ + union { + uint64_t u; + double f; + } x = { 0x3ff0000000000000ULL | fz_rand48_step(s, ctx->seed48+3)<<4 }; + return x.f - 1.0; +} + +double fz_drand48(fz_context *ctx) +{ + return fz_erand48(ctx, ctx->seed48); +} + +int32_t fz_nrand48(fz_context *ctx, uint16_t s[3]) +{ + return fz_rand48_step(s, ctx->seed48+3) >> 17; +} + +int32_t fz_lrand48(fz_context *ctx) +{ + return fz_nrand48(ctx, ctx->seed48); +} + +int32_t fz_jrand48(fz_context *ctx, uint16_t s[3]) +{ + return (int32_t)(fz_rand48_step(s, ctx->seed48+3) >> 16); +} + +int32_t fz_mrand48(fz_context *ctx) +{ + return fz_jrand48(ctx, ctx->seed48); +} + +void fz_lcong48(fz_context *ctx, uint16_t p[7]) +{ + memcpy(ctx->seed48, p, sizeof ctx->seed48); +} + +uint16_t *fz_seed48(fz_context *ctx, uint16_t *s) +{ + static uint16_t p[3]; + memcpy(p, ctx->seed48, sizeof p); + memcpy(ctx->seed48, s, sizeof p); + return p; +} + +void fz_srand48(fz_context *ctx, int32_t seed) +{ + fz_seed48(ctx, (uint16_t [3]){ 0x330e, seed, seed>>16 }); +} + +void fz_memrnd(fz_context *ctx, unsigned char *data, int len) +{ + while (len-- > 0) + *data++ = (unsigned char)fz_lrand48(ctx); +} |