diff options
Diffstat (limited to 'zbar/qrcode/isaac.c')
-rw-r--r-- | zbar/qrcode/isaac.c | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/zbar/qrcode/isaac.c b/zbar/qrcode/isaac.c new file mode 100644 index 0000000..88889f3 --- /dev/null +++ b/zbar/qrcode/isaac.c @@ -0,0 +1,145 @@ +/*Written by Timothy B. Terriberry (tterribe@xiph.org) 1999-2009 public domain. + Based on the public domain implementation by Robert J. Jenkins Jr.*/ +#include "isaac.h" +#include <float.h> +#include <math.h> +#include <string.h> + +#define ISAAC_MASK (0xFFFFFFFFU) + +static void isaac_update(isaac_ctx *_ctx) +{ + unsigned *m; + unsigned *r; + unsigned a; + unsigned b; + unsigned x; + unsigned y; + int i; + m = _ctx->m; + r = _ctx->r; + a = _ctx->a; + b = _ctx->b + (++_ctx->c) & ISAAC_MASK; + for (i = 0; i < ISAAC_SZ / 2; i++) { + x = m[i]; + a = (a ^ a << 13) + m[i + ISAAC_SZ / 2] & ISAAC_MASK; + m[i] = y = m[(x & ISAAC_SZ - 1 << 2) >> 2] + a + b & ISAAC_MASK; + r[i] = b = m[y >> ISAAC_SZ_LOG + 2 & ISAAC_SZ - 1] + x & ISAAC_MASK; + x = m[++i]; + a = (a ^ a >> 6) + m[i + ISAAC_SZ / 2] & ISAAC_MASK; + m[i] = y = m[(x & ISAAC_SZ - 1 << 2) >> 2] + a + b & ISAAC_MASK; + r[i] = b = m[y >> ISAAC_SZ_LOG + 2 & ISAAC_SZ - 1] + x & ISAAC_MASK; + x = m[++i]; + a = (a ^ a << 2) + m[i + ISAAC_SZ / 2] & ISAAC_MASK; + m[i] = y = m[(x & ISAAC_SZ - 1 << 2) >> 2] + a + b & ISAAC_MASK; + r[i] = b = m[y >> ISAAC_SZ_LOG + 2 & ISAAC_SZ - 1] + x & ISAAC_MASK; + x = m[++i]; + a = (a ^ a >> 16) + m[i + ISAAC_SZ / 2] & ISAAC_MASK; + m[i] = y = m[(x & ISAAC_SZ - 1 << 2) >> 2] + a + b & ISAAC_MASK; + r[i] = b = m[y >> ISAAC_SZ_LOG + 2 & ISAAC_SZ - 1] + x & ISAAC_MASK; + } + for (i = ISAAC_SZ / 2; i < ISAAC_SZ; i++) { + x = m[i]; + a = (a ^ a << 13) + m[i - ISAAC_SZ / 2] & ISAAC_MASK; + m[i] = y = m[(x & ISAAC_SZ - 1 << 2) >> 2] + a + b & ISAAC_MASK; + r[i] = b = m[y >> ISAAC_SZ_LOG + 2 & ISAAC_SZ - 1] + x & ISAAC_MASK; + x = m[++i]; + a = (a ^ a >> 6) + m[i - ISAAC_SZ / 2] & ISAAC_MASK; + m[i] = y = m[(x & ISAAC_SZ - 1 << 2) >> 2] + a + b & ISAAC_MASK; + r[i] = b = m[y >> ISAAC_SZ_LOG + 2 & ISAAC_SZ - 1] + x & ISAAC_MASK; + x = m[++i]; + a = (a ^ a << 2) + m[i - ISAAC_SZ / 2] & ISAAC_MASK; + m[i] = y = m[(x & ISAAC_SZ - 1 << 2) >> 2] + a + b & ISAAC_MASK; + r[i] = b = m[y >> ISAAC_SZ_LOG + 2 & ISAAC_SZ - 1] + x & ISAAC_MASK; + x = m[++i]; + a = (a ^ a >> 16) + m[i - ISAAC_SZ / 2] & ISAAC_MASK; + m[i] = y = m[(x & ISAAC_SZ - 1 << 2) >> 2] + a + b & ISAAC_MASK; + r[i] = b = m[y >> ISAAC_SZ_LOG + 2 & ISAAC_SZ - 1] + x & ISAAC_MASK; + } + _ctx->b = b; + _ctx->a = a; + _ctx->n = ISAAC_SZ; +} + +static void isaac_mix(unsigned _x[8]) +{ + static const unsigned char SHIFT[8] = { 11, 2, 8, 16, 10, 4, 8, 9 }; + int i; + for (i = 0; i < 8; i++) { + _x[i] ^= _x[i + 1 & 7] << SHIFT[i]; + _x[i + 3 & 7] += _x[i]; + _x[i + 1 & 7] += _x[i + 2 & 7]; + i++; + _x[i] ^= _x[i + 1 & 7] >> SHIFT[i]; + _x[i + 3 & 7] += _x[i]; + _x[i + 1 & 7] += _x[i + 2 & 7]; + } +} + +void isaac_init(isaac_ctx *_ctx, const void *_seed, int _nseed) +{ + const unsigned char *seed; + unsigned *m; + unsigned *r; + unsigned x[8]; + int i; + int j; + _ctx->a = _ctx->b = _ctx->c = 0; + m = _ctx->m; + r = _ctx->r; + x[0] = x[1] = x[2] = x[3] = x[4] = x[5] = x[6] = x[7] = 0x9E3779B9; + for (i = 0; i < 4; i++) + isaac_mix(x); + if (_nseed > ISAAC_SEED_SZ_MAX) + _nseed = ISAAC_SEED_SZ_MAX; + seed = (const unsigned char *)_seed; + for (i = 0; i < (_nseed >> 2); i++) { + r[i] = seed[i << 2 | 3] << 24 | seed[i << 2 | 2] << 16 | + seed[i << 2 | 1] << 8 | seed[i << 2]; + } + if (_nseed & 3) { + r[i] = seed[i << 2]; + for (j = 1; j < (_nseed & 3); j++) + r[i] += seed[i << 2 | j] << (j << 3); + i++; + } + memset(r + i, 0, (ISAAC_SZ - i) * sizeof(*r)); + for (i = 0; i < ISAAC_SZ; i += 8) { + for (j = 0; j < 8; j++) + x[j] += r[i + j]; + isaac_mix(x); + memcpy(m + i, x, sizeof(x)); + } + for (i = 0; i < ISAAC_SZ; i += 8) { + for (j = 0; j < 8; j++) + x[j] += m[i + j]; + isaac_mix(x); + memcpy(m + i, x, sizeof(x)); + } + isaac_update(_ctx); +} + +unsigned isaac_next_uint32(isaac_ctx *_ctx) +{ + if (!_ctx->n) + isaac_update(_ctx); + return _ctx->r[--_ctx->n]; +} + +/*Returns a uniform random integer less than the given maximum value. + _n: The upper bound on the range of numbers returned (not inclusive). + This must be strictly less than 2**32. + Return: An integer uniformly distributed between 0 (inclusive) and _n + (exclusive).*/ +unsigned isaac_next_uint(isaac_ctx *_ctx, unsigned _n) +{ + unsigned r; + unsigned v; + unsigned d; + do { + r = isaac_next_uint32(_ctx); + v = r % _n; + d = r - v; + } while ((d + _n - 1 & ISAAC_MASK) < d); + return v; +} |