Last active
February 7, 2021 16:46
-
-
Save maciejczyzewski/5b704c9b8f0f13b660d7 to your computer and use it in GitHub Desktop.
Reference Implementation in JavaScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* NCG written in 2015 by Maciej A. Czyzewski | |
To the extent possible under law, the author has dedicated all copyright | |
and related and neighboring rights to this software to the public domain | |
worldwide. This software is distributed without any warranty. | |
See <http://creativecommons.org/publicdomain/zero/1.0/>. */ | |
// Simulating a 16-bit & 32-bit value | |
function U16(i) { return i & 0xFFFF; } function U32(i) { return i & 0xFFFFFFFF; } | |
// S - seed, I - increment, t - mask, i - temporary | |
var S, I, t, i; | |
// The length of the initial states | |
var SIZE = 16; | |
// The number of rounds in algorithm | |
var ROUNDS = 1; | |
// Abbreviation for getting values from the tape | |
function M(i) { return (((i % SIZE) + SIZE) % SIZE); } | |
// Bits rotation formula | |
function R(x, y) { return (((x) << (y)) | ((x) >> (16 - (y)))) } | |
// Variebles in the algorithm | |
var a, b, c = 0, d = 0, e; | |
// Initial state vector (pi digits) | |
var G, Q = new Array(1, 4, 1, 5, 9, 2, 6, 5, | |
3, 5, 8, 9, 7, 9, 3, 2); | |
function push(seed) { | |
// Preparation | |
I = U32(seed * 0x3C6EF35F); | |
for (S = U32(seed), i = 0; i < SIZE; i++) { | |
// Reinforcement | |
G[M(i)] = U16(G[M(i)] ^ (((I * (S + 1)) ^ S) >> 16)); | |
G[M(i)] = U16(G[M(i)] ^ (((I * (S - 1)) ^ S) >> 00)); | |
// Finalization | |
I = U32(I ^ ((G[M(I - 1)] + G[M(i)]) << 16) | |
^ ((G[M(I + 1)] - G[M(i)]) << 00)); | |
} | |
} | |
function pull() { | |
// Variebles | |
a = G[M(I + 0)]; b = G[M(I + 1)]; | |
// Initialization | |
t = U32((a + I) * (b - S)); | |
// Chaos | |
e = U16((G[M(t - b)] << ((a >>> 0) % 9)) ^ (G[M(t + a)] >> ((b >>> 0) % 9))); | |
// Rounds | |
for (i = 0; i < ROUNDS * 2; i += 2) { | |
// Absorption | |
c = U16(c ^ G[M(I + i - 2)]); d = U16(d ^ G[M(I + i + 2)]); | |
// Mixing & Modification | |
c = U16(c ^ (d = U16(d ^ R(e, (c >>> 0) % 17)))); | |
G[M(I + i - 2)] = U16(G[M(I + i - 2)] - (d = U16(d + (t & c)))); | |
d = U16(d + (c = U16(c + R(t, (d >>> 0) % 17)))); | |
G[M(I + i + 2)] = U16(G[M(I + i + 2)] + (c = U16(c + (e & d)))); | |
} | |
// Transformation | |
G[M(I + 0)] = U16(R(c, (t >>> 0) % 17) ^ R(d, (t >>> 0) % 17) ^ (t & a) ^ (e & b)); | |
G[M(I + 1)] = U16((b >> 1) ^ (-(b & 1) & 0xB400)); // LFSR | |
// Finalization | |
t = U32(t + (c ^ (b << 8) ^ (d << 16) ^ (a & 0xFF) ^ ((a >> 8) << 24))); | |
// Cleaning | |
c = d = 0xFFFF; | |
// Increment | |
I = U32(I + 2); | |
return t; | |
} | |
function reset() { | |
// Copying defaults | |
G = Q; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment