summaryrefslogtreecommitdiff
path: root/source/fitz
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2018-01-03 15:11:33 +0100
committerTor Andersson <tor.andersson@artifex.com>2018-01-04 13:15:42 +0100
commit2d5b4683e912d6e6e1f1e2ca5aa0297beb3e6807 (patch)
treede2343f1280afd1ae32a1b8d7805a42f0fc5f8e7 /source/fitz
parenta292539cc9e5e91843d48e691038d9c1b529422c (diff)
downloadmupdf-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.c19
-rw-r--r--source/fitz/random.c80
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);
+}