Persevering with within the path of earlier two posts, the package deal under helps all the xoshiro/xoroshiro algorithms returning 64-bit values.
- xoroshiro128+
- xoroshiro128++
- xoroshiro128**
- xoshiro256+
- xoshiro256++
- xoshiro256**
- xoshiro512+
- xoshiro512++
- xoshiro512**
- xoroshiro1024*
- xoroshiro1024++
- xoroshiro1024**
The numbers within the names seek advice from the dimensions of the state array that every methodology operates on.
Utilizing every of them follows the identical sample:
- Select the algorithm mode (the package deal defaults to xoshiro256++)
- Seed the state array
- Retrieve the subsequent quantity from the chosen algorithm as many instances as wanted
For instance…
SQL> BEGIN 2 xoshiro.set_mode('xoroshiro128++'); 3 xoshiro.set_state(xoshiro.seed_tab(12345, 67890)); 4 5 FOR i IN 0 .. 9 6 LOOP 7 DBMS_OUTPUT.put_line(i || ' ' || LPAD(xoshiro.get_next, 10)); 8 END LOOP; 9 END; 10 / 0 1051657426 1 9791286188 2 9989489894 3 6590593871 4 6705930516 5 1618779258 6 8800234758 7 2334047907 8 8330851765 9 3477959413
Optionally, you may name the bounce or long_jump features to bounce forward within the state by simulating many (from 2^64 to 2^768 relying on the mode and bounce measurement) calls of the get_next operate. As famous by Blackman and Vigna, these are sometimes used to generate non-overlapping sequences for parallel processing. In single threaded use there can be no want for them.
Along with these I additionally included the splitmix64 operate which is, itself, a pseudo-random quantity generator and can be utilized in an identical method. Set the seed, after which name the splitmix64_next to retrieve the subsequent quantity.
SQL> BEGIN 2 xoshiro.splitmix64_set_state(12345); 3 4 FOR i IN 0 .. 9 5 LOOP 6 DBMS_OUTPUT.put_line(i || ' ' || LPAD(xoshiro.splitmix64_next, 10)); 7 END LOOP; 8 END; 9 / 0 2454886589 1 3778200017 2 2205171434 3 3248800117 4 9350289611 5 6217189988 6 2262534019 7 7959005890 8 8850488307 9 1600295491
This isn’t the everyday utilization although. Moderately, splitmix64 is usually recommended as a way of seeding the state arrays of the opposite algorithms. Under, I set the splitmix64 state, after which create a seed of 4 values for the xoshiro256** generator.
SQL> DECLARE 2 v_seed xoshiro.seed_tab := xoshiro.seed_tab(); 3 BEGIN 4 xoshiro.splitmix64_set_state(12345); 5 v_seed.EXTEND(4); 6 7 FOR i IN 1 .. 4 8 LOOP 9 v_seed(i) := xoshiro.splitmix64_next; 10 END LOOP; 11 12 xoshiro.set_mode('xoshiro256**'); 13 xoshiro.set_state(v_seed); 14 15 FOR i IN 0 .. 9 16 LOOP 17 DBMS_OUTPUT.put_line(i || ' ' || LPAD(xoshiro.get_next, 10)); 18 END LOOP; 19 END; 20 / 0 1372083882 1 2398916695 2 1777038484 3 8917177268 4 1024131604 5 1969754298 6 2947371003 7 5456629693 8 7119811276 9 1679784635
Following is the whole package deal for all the 64-bit algorithms.
CREATE OR REPLACE PACKAGE xoshiro IS -- Based mostly on xoshiro/xoroshiro household of pseudorandom quantity turbines -- by by David Blackman and Sebastiano Vigna -- unique https://prng.di.unimi.it -- .///. -- (0 o) ---------------0000--(_)--0000--------------- -- -- Sean D. Stuber -- sean.stuber@gmail.com -- -- oooO Oooo --------------( )-----( )--------------- -- ( ) / -- _) (_/ -- It will be good to outline an express RANGE 0..18446744073709551615 for the subtype -- however as of 23ai, solely subtypes of PLS_INTEGER could have a variety. SUBTYPE uint64_t IS NUMBER(20, 0); TYPE seed_tab IS TABLE OF uint64_t; SUBTYPE bits_t IS SIMPLE_INTEGER RANGE 0 .. 63; SUBTYPE mode_t IS SIMPLE_INTEGER RANGE 1 .. 12; c_128plus CONSTANT mode_t := 1; -- xoroshiro128+ c_128plusplus CONSTANT mode_t := 2; -- xoroshiro128++ c_128starstar CONSTANT mode_t := 3; -- xoroshiro128** c_256plus CONSTANT mode_t := 4; -- xoshiro256+ c_256plusplus CONSTANT mode_t := 5; -- xoshiro256++ c_256starstar CONSTANT mode_t := 6; -- xoshiro256** c_512plus CONSTANT mode_t := 7; -- xoshiro512+ c_512plusplus CONSTANT mode_t := 8; -- xoshiro512++ c_512starstar CONSTANT mode_t := 9; -- xoshiro512** c_1024star CONSTANT mode_t := 10; -- xoroshiro1024* c_1024plusplus CONSTANT mode_t := 11; -- xoroshiro1024++ c_1024starstar CONSTANT mode_t := 12; -- xoroshiro1024** --Exceptions invalid_mode EXCEPTION; -- Choose a mode by numeric worth or by identify PROCEDURE set_mode(p_mode IN mode_t); PROCEDURE set_mode(p_mode IN VARCHAR2); -- Return the present mode quantity or identify FUNCTION get_mode RETURN mode_t; FUNCTION get_mode_name RETURN VARCHAR2; -- Given a set of seed values, initialize the state array for the present mode measurement -- Totally different modes for a selected measurement can share the identical state array. PROCEDURE set_state(p_seed IN seed_tab); -- Return the subsequent pseudorandom generator worth for the present mode FUNCTION get_next RETURN uint64_t; -- Simulate many calls to "get_next". Sometimes used to create non-overlapping sequences from the identical preliminary state. PROCEDURE bounce; -- Simulate much more calls to "get_next". Additionally used to create non-overlapping sequences from the identical preliminary state. PROCEDURE long_jump; -- SplitMix64 is not a part of the xoshiro/xoroshiro household -- Nonetheless utilizing it to fill the state arrays as an alternative of a easy integer -- is really useful by the unique authors. PROCEDURE splitmix64_set_state(p_seed uint64_t); FUNCTION splitmix64_next RETURN uint64_t; END;
As a comparability reference for myself and readers, I included snippets of the unique c code throughout the feedback of the package deal physique for the varied procedures and features of every mode.
CREATE OR REPLACE PACKAGE BODY xoshiro IS c_64bitmask CONSTANT uint64_t := POWER(2, 64) - 1; SUBTYPE array_128index_t IS PLS_INTEGER RANGE 0 .. 1; SUBTYPE array_256index_t IS PLS_INTEGER RANGE 0 .. 3; SUBTYPE array_512index_t IS PLS_INTEGER RANGE 0 .. 7; SUBTYPE array_1024index_t IS PLS_INTEGER RANGE 0 .. 15; TYPE state128_array_t IS TABLE OF uint64_t INDEX BY array_128index_t; TYPE state256_array_t IS TABLE OF uint64_t INDEX BY array_256index_t; TYPE state512_array_t IS TABLE OF uint64_t INDEX BY array_512index_t; TYPE state1024_array_t IS TABLE OF uint64_t INDEX BY array_1024index_t; g_mode mode_t := c_256plusplus; g_splitmix64_state uint64_t; g_128_state state128_array_t; -- xoroshiro128+, xoroshiro128++, xoroshiro128** g_256_state state256_array_t; -- xoshiro256+, xoshiro256++, xoshiro256** g_512_state state512_array_t; -- xoshiro512+, xoshiro512++, xoshiro512** g_1024_state state1024_array_t; -- xoroshiro1024*, xoroshiro1024++, xoroshiro1024** -- Used to index into the state array for the 1024bit modes g_1024_p array_1024index_t := 0; FUNCTION bitor(p_a IN uint64_t, p_b IN uint64_t) RETURN uint64_t IS BEGIN RETURN BITAND(p_a + p_b - BITAND(p_a, p_b), c_64bitmask); END bitor; FUNCTION bitxor(p_a IN uint64_t, p_b IN uint64_t) RETURN uint64_t IS BEGIN RETURN BITAND((p_a + p_b) - (BITAND(p_a, p_b) * 2), c_64bitmask); END bitxor; FUNCTION big_bitand(p_a IN NUMBER, p_b IN NUMBER) RETURN NUMBER IS v_result NUMBER; v_temp NUMBER; v_a_shift NUMBER; v_b_shift NUMBER; v_a_first_bit NUMBER; v_b_first_bit NUMBER; BEGIN -- Oracle's native BITAND operate has an higher restrict of energy(2,127)-1 CASE WHEN p_a > (64 - ok)); -- } BEGIN RETURN CASE WHEN p_k = 0 THEN p_x ELSE bitor(shl64(p_x, p_k), shr64(p_x, 64 - p_k)) END; END rotl; ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- FUNCTION next128plus RETURN uint64_t IS -- uint64_t subsequent(void) { -- const uint64_t s0 = s[0]; -- uint64_t s1 = s[1]; -- const uint64_t outcome = s0 + s1; -- -- s1 ^= s0; -- s[0] = rotl(s0, 24) ^ s1 ^ (s1 TO_NUMBER('df900294d8f554a5', 'xxxxxxxxxxxxxxxx'), 1 => TO_NUMBER('170865df4b3201fc', 'xxxxxxxxxxxxxxxx')) WHEN g_mode = c_128plusplus THEN state128_array_t(0 => TO_NUMBER('2bd7a6a6e99c2ddc', 'xxxxxxxxxxxxxxxx'), 1 => TO_NUMBER('0992ccaf6a6fca05', 'xxxxxxxxxxxxxxxx')) END; v_s0 uint64_t := 0; v_s1 uint64_t := 0; v_dummy uint64_t; BEGIN FOR i IN 0 .. 1 LOOP FOR b IN 0 .. 63 LOOP IF BITAND(v_jump(i), shl64(1, b)) != 0 THEN v_s0 := bitxor(v_s0, g_128_state(0)); v_s1 := bitxor(v_s1, g_128_state(1)); END IF; v_dummy := next128; END LOOP; END LOOP; g_128_state(0) := v_s0; g_128_state(1) := v_s1; END jump128; PROCEDURE long_jump128 IS -- xoroshiro128+ and xoroshiro128** use the identical lengthy bounce array -- /* That is the long-jump operate for the generator. It's equal to -- 2^96 calls to subsequent(); it may be used to generate 2^32 beginning factors, -- from every of which bounce() will generate 2^32 non-overlapping -- subsequences for parallel distributed computations. */ -- -- void long_jump(void) { -- static const uint64_t LONG_JUMP[] = { 0xd2a98b26625eee7b, 0xdddf9b1090aa7ac1 }; -- -- uint64_t s0 = 0; -- uint64_t s1 = 0; -- for(int i = 0; i TO_NUMBER('d2a98b26625eee7b', 'xxxxxxxxxxxxxxxx'), 1 => TO_NUMBER('dddf9b1090aa7ac1', 'xxxxxxxxxxxxxxxx')) WHEN g_mode = c_128plusplus THEN state128_array_t(0 => TO_NUMBER('360fd5f2cf8d5d99', 'xxxxxxxxxxxxxxxx'), 1 => TO_NUMBER('9c6e6877736c46e3', 'xxxxxxxxxxxxxxxx')) END; v_s0 uint64_t := 0; v_s1 uint64_t := 0; v_dummy uint64_t; BEGIN FOR i IN 0 .. 1 LOOP FOR b IN 0 .. 63 LOOP IF BITAND(v_longjump(i), shl64(1, b)) != 0 THEN v_s0 := bitxor(v_s0, g_128_state(0)); v_s1 := bitxor(v_s1, g_128_state(1)); END IF; v_dummy := next128; END LOOP; END LOOP; g_128_state(0) := v_s0; g_128_state(1) := v_s1; END long_jump128; ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- FUNCTION next256 RETURN uint64_t IS -- The outcome for the present state is calculated in another way for every mode -- however the steps to increment the state for the subsequent worth are the identical -- const uint64_t outcome = s[0] + s[3]; -- xoshiro256+ -- const uint64_t outcome = rotl(s[0] + s[3], 23) + s[0]; -- xoshiro256++ -- const uint64_t outcome = rotl(s[1] * 5, 7) * 9; -- xoshiro256** -- uint64_t subsequent(void) { -- const uint64_t outcome = s[0] + s[3]; -- -- const uint64_t t = s[1] TO_NUMBER('180ec6d33cfd0aba', 'xxxxxxxxxxxxxxxx'), 1 => TO_NUMBER('d5a61266f0c9392c', 'xxxxxxxxxxxxxxxx'), 2 => TO_NUMBER('a9582618e03fc9aa', 'xxxxxxxxxxxxxxxx'), 3 => TO_NUMBER('39abdc4529b1661c', 'xxxxxxxxxxxxxxxx')) ; v_s0 uint64_t := 0; v_s1 uint64_t := 0; v_s2 uint64_t := 0; v_s3 uint64_t := 0; v_dummy uint64_t; BEGIN FOR i IN 0 .. 3 LOOP FOR b IN 0 .. 63 LOOP IF BITAND(v_jump(i), shl64(1, b)) != 0 THEN v_s0 := bitxor(v_s0, g_256_state(0)); v_s1 := bitxor(v_s1, g_256_state(1)); v_s2 := bitxor(v_s2, g_256_state(2)); v_s3 := bitxor(v_s3, g_256_state(3)); END IF; v_dummy := next256; END LOOP; END LOOP; g_256_state(0) := v_s0; g_256_state(1) := v_s1; g_256_state(2) := v_s2; g_256_state(3) := v_s3; END jump256; PROCEDURE long_jump256 IS -- /* That is the long-jump operate for the generator. It's equal to -- 2^192 calls to subsequent(); it may be used to generate 2^64 beginning factors, -- from every of which bounce() will generate 2^64 non-overlapping -- subsequences for parallel distributed computations. */ -- -- void long_jump(void) { -- static const uint64_t LONG_JUMP[] = { 0x76e15d3efefdcbbf, 0xc5004e441c522fb3, 0x77710069854ee241, 0x39109bb02acbe635 }; -- -- uint64_t s0 = 0; -- uint64_t s1 = 0; -- uint64_t s2 = 0; -- uint64_t s3 = 0; -- for(int i = 0; i TO_NUMBER('76e15d3efefdcbbf', 'xxxxxxxxxxxxxxxx'), 1 => TO_NUMBER('c5004e441c522fb3', 'xxxxxxxxxxxxxxxx'), 2 => TO_NUMBER('77710069854ee241', 'xxxxxxxxxxxxxxxx'), 3 => TO_NUMBER('39109bb02acbe635', 'xxxxxxxxxxxxxxxx')) ; v_s0 uint64_t := 0; v_s1 uint64_t := 0; v_s2 uint64_t := 0; v_s3 uint64_t := 0; v_dummy uint64_t; BEGIN FOR i IN 0 .. 3 LOOP FOR b IN 0 .. 63 LOOP IF BITAND(v_longjump(i), shl64(1, b)) != 0 THEN v_s0 := bitxor(v_s0, g_256_state(0)); v_s1 := bitxor(v_s1, g_256_state(1)); v_s2 := bitxor(v_s2, g_256_state(2)); v_s3 := bitxor(v_s3, g_256_state(3)); END IF; v_dummy := next256; END LOOP; END LOOP; g_256_state(0) := v_s0; g_256_state(1) := v_s1; g_256_state(2) := v_s2; g_256_state(3) := v_s3; END long_jump256; ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- FUNCTION next512 RETURN uint64_t IS -- The outcome for the present state is calculated in another way for every mode -- however the steps to increment the state for the subsequent worth are the identical -- const uint64_t outcome = s[0] + s[2]; -- xoshiro512+ -- const uint64_t outcome = rotl(s[0] + s[2], 17) + s[2]; -- xoshiro512++ -- const uint64_t outcome = rotl(s[1] * 5, 7) * 9; -- xoshiro512** -- uint64_t subsequent(void) { -- const uint64_t outcome = s[0] + s[2]; -- -- const uint64_t t = s[1] TO_NUMBER('33ed89b6e7a353f9', 'xxxxxxxxxxxxxxxx'), 1 => TO_NUMBER('760083d7955323be', 'xxxxxxxxxxxxxxxx'), 2 => TO_NUMBER('2837f2fbb5f22fae', 'xxxxxxxxxxxxxxxx'), 3 => TO_NUMBER('4b8c5674d309511c', 'xxxxxxxxxxxxxxxx'), 4 => TO_NUMBER('b11ac47a7ba28c25', 'xxxxxxxxxxxxxxxx'), 5 => TO_NUMBER('f1be7667092bcc1c', 'xxxxxxxxxxxxxxxx'), 6 => TO_NUMBER('53851efdb6df0aaf', 'xxxxxxxxxxxxxxxx'), 7 => TO_NUMBER('1ebbc8b23eaf25db', 'xxxxxxxxxxxxxxxx')) ; v_t state512_array_t := state512_array_t(0 => 0, 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0, 7 => 0); v_dummy uint64_t; BEGIN FOR i IN 0 .. 7 LOOP FOR b IN 0 .. 63 LOOP IF BITAND(v_jump(i), shl64(1, b)) != 0 THEN FOR w IN 0 .. 7 LOOP v_t(w) := bitxor(v_t(w), g_512_state(w)); END LOOP; END IF; v_dummy := next512; END LOOP; END LOOP; FOR i IN 0 .. 7 LOOP g_512_state(i) := v_t(i); END LOOP; END jump512; PROCEDURE long_jump512 IS -- /* That is the long-jump operate for the generator. It's equal to -- 2^384 calls to subsequent(); it may be used to generate 2^128 beginning factors, -- from every of which bounce() will generate 2^128 non-overlapping -- subsequences for parallel distributed computations. */ -- -- void long_jump(void) { -- static const uint64_t LONG_JUMP[] = { 0x11467fef8f921d28, 0xa2a819f2e79c8ea8, 0xa8299fc284b3959a, 0xb4d347340ca63ee1, 0x1cb0940bedbff6ce, 0xd956c5c4fa1f8e17, 0x915e38fd4eda93bc, 0x5b3ccdfa5d7daca5 }; -- -- uint64_t t[sizeof s / sizeof *s]; -- memset(t, 0, sizeof t); -- for(int i = 0; i TO_NUMBER('11467fef8f921d28', 'xxxxxxxxxxxxxxxx'), 1 => TO_NUMBER('a2a819f2e79c8ea8', 'xxxxxxxxxxxxxxxx'), 2 => TO_NUMBER('a8299fc284b3959a', 'xxxxxxxxxxxxxxxx'), 3 => TO_NUMBER('b4d347340ca63ee1', 'xxxxxxxxxxxxxxxx'), 4 => TO_NUMBER('1cb0940bedbff6ce', 'xxxxxxxxxxxxxxxx'), 5 => TO_NUMBER('d956c5c4fa1f8e17', 'xxxxxxxxxxxxxxxx'), 6 => TO_NUMBER('915e38fd4eda93bc', 'xxxxxxxxxxxxxxxx'), 7 => TO_NUMBER('5b3ccdfa5d7daca5', 'xxxxxxxxxxxxxxxx')) ; v_t state512_array_t := state512_array_t(0 => 0, 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0, 7 => 0); v_dummy uint64_t; BEGIN FOR i IN 0 .. 7 LOOP FOR b IN 0 .. 63 LOOP IF BITAND(v_longjump(i), shl64(1, b)) != 0 THEN FOR w IN 0 .. 7 LOOP v_t(w) := bitxor(v_t(w), g_512_state(w)); END LOOP; END IF; v_dummy := next512; END LOOP; END LOOP; FOR i IN 0 .. 7 LOOP g_512_state(i) := v_t(i); END LOOP; END long_jump512; ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- FUNCTION next1024 RETURN uint64_t IS -- The outcome for the present state is calculated in another way for every mode -- however the steps to increment the state for the subsequent worth are the identical -- const uint64_t outcome = s0 * 0x9e3779b97f4a7c13; -- xoshiro1024* -- const uint64_t outcome = rotl(s0 + s15, 23) + s15; -- xoshiro1024++ -- cconst uint64_t outcome = rotl(s0 * 5, 7) * 9; -- xoshiro1024** -- uint64_t subsequent(void) { -- const int q = p; -- const uint64_t s0 = s[p = (p + 1) & 15]; -- uint64_t s15 = s[q]; -- const uint64_t outcome = s0 * 0x9e3779b97f4a7c13; -- -- s15 ^= s0; -- s[q] = rotl(s0, 25) ^ s15 ^ (s15 TO_NUMBER('931197d8e3177f17', 'xxxxxxxxxxxxxxxx'), 1 => TO_NUMBER('b59422e0b9138c5f', 'xxxxxxxxxxxxxxxx'), 2 => TO_NUMBER('f06a6afb49d668bb', 'xxxxxxxxxxxxxxxx'), 3 => TO_NUMBER('acb8a6412c8a1401', 'xxxxxxxxxxxxxxxx'), 4 => TO_NUMBER('12304ec85f0b3468', 'xxxxxxxxxxxxxxxx'), 5 => TO_NUMBER('b7dfe7079209891e', 'xxxxxxxxxxxxxxxx'), 6 => TO_NUMBER('405b7eec77d9eb14', 'xxxxxxxxxxxxxxxx'), 7 => TO_NUMBER('34ead68280c44e4a', 'xxxxxxxxxxxxxxxx'), 8 => TO_NUMBER('e0e4ba3e0ac9e366', 'xxxxxxxxxxxxxxxx'), 9 => TO_NUMBER('8f46eda8348905b7', 'xxxxxxxxxxxxxxxx'), 10 => TO_NUMBER('328bf4dbad90d6ff', 'xxxxxxxxxxxxxxxx'), 11 => TO_NUMBER('c8fd6fb31c9effc3', 'xxxxxxxxxxxxxxxx'), 12 => TO_NUMBER('e899d452d4b67652', 'xxxxxxxxxxxxxxxx'), 13 => TO_NUMBER('45f387286ade3205', 'xxxxxxxxxxxxxxxx'), 14 => TO_NUMBER('03864f454a8920bd', 'xxxxxxxxxxxxxxxx'), 15 => TO_NUMBER('a68fa28725b1b384', 'xxxxxxxxxxxxxxxx')) ; v_t state1024_array_t := state1024_array_t(0 => 0, 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0, 7 => 0, 8 => 0, 9 => 0, 10 => 0, 11 => 0, 12 => 0, 13 => 0, 14 => 0, 15 => 0); v_dummy uint64_t; BEGIN FOR i IN 0 .. 15 LOOP FOR b IN 0 .. 63 LOOP IF BITAND(v_jump(i), shl64(1, b)) != 0 THEN FOR j IN 0 .. 15 LOOP v_t(j) := bitxor(v_t(j), g_1024_state(BITAND(j + g_1024_p, 15))); END LOOP; END IF; v_dummy := next1024; END LOOP; END LOOP; FOR i IN 0 .. 15 LOOP g_1024_state(BITAND(i + g_1024_p, 15)) := v_t(i); END LOOP; END jump1024; PROCEDURE long_jump1024 IS -- /* That is the long-jump operate for the generator. It's equal to -- 2^768 calls to subsequent(); it may be used to generate 2^256 beginning factors, -- from every of which bounce() will generate 2^256 non-overlapping -- subsequences for parallel distributed computations. */ -- -- void long_jump(void) { -- static const uint64_t LONG_JUMP[] = { 0x7374156360bbf00f, -- 0x4630c2efa3b3c1f6, 0x6654183a892786b1, 0x94f7bfcbfb0f1661, -- 0x27d8243d3d13eb2d, 0x9701730f3dfb300f, 0x2f293baae6f604ad, -- 0xa661831cb60cd8b6, 0x68280c77d9fe008c, 0x50554160f5ba9459, -- 0x2fc20b17ec7b2a9a, 0x49189bbdc8ec9f8f, 0x92a65bca41852cc1, -- 0xf46820dd0509c12a, 0x52b00c35fbf92185, 0x1e5b3b7f589e03c1 }; -- -- uint64_t t[sizeof s / sizeof *s]; -- memset(t, 0, sizeof t); -- for(int i = 0; i TO_NUMBER('7374156360bbf00f', 'xxxxxxxxxxxxxxxx'), 1 => TO_NUMBER('4630c2efa3b3c1f6', 'xxxxxxxxxxxxxxxx'), 2 => TO_NUMBER('6654183a892786b1', 'xxxxxxxxxxxxxxxx'), 3 => TO_NUMBER('94f7bfcbfb0f1661', 'xxxxxxxxxxxxxxxx'), 4 => TO_NUMBER('27d8243d3d13eb2d', 'xxxxxxxxxxxxxxxx'), 5 => TO_NUMBER('9701730f3dfb300f', 'xxxxxxxxxxxxxxxx'), 6 => TO_NUMBER('2f293baae6f604ad', 'xxxxxxxxxxxxxxxx'), 7 => TO_NUMBER('a661831cb60cd8b6', 'xxxxxxxxxxxxxxxx'), 8 => TO_NUMBER('68280c77d9fe008c', 'xxxxxxxxxxxxxxxx'), 9 => TO_NUMBER('50554160f5ba9459', 'xxxxxxxxxxxxxxxx'), 10 => TO_NUMBER('2fc20b17ec7b2a9a', 'xxxxxxxxxxxxxxxx'), 11 => TO_NUMBER('49189bbdc8ec9f8f', 'xxxxxxxxxxxxxxxx'), 12 => TO_NUMBER('92a65bca41852cc1', 'xxxxxxxxxxxxxxxx'), 13 => TO_NUMBER('f46820dd0509c12a', 'xxxxxxxxxxxxxxxx'), 14 => TO_NUMBER('52b00c35fbf92185', 'xxxxxxxxxxxxxxxx'), 15 => TO_NUMBER('1e5b3b7f589e03c1', 'xxxxxxxxxxxxxxxx')) ; v_t state1024_array_t := state1024_array_t(0 => 0, 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0, 7 => 0, 8 => 0, 9 => 0, 10 => 0, 11 => 0, 12 => 0, 13 => 0, 14 => 0, 15 => 0); v_dummy uint64_t; BEGIN FOR i IN 0 .. 15 LOOP FOR b IN 0 .. 63 LOOP IF BITAND(v_longjump(i), shl64(1, b)) != 0 THEN FOR j IN 0 .. 15 LOOP v_t(j) := bitxor(v_t(j), g_1024_state(BITAND(j + g_1024_p, 15))); END LOOP; END IF; v_dummy := next1024; END LOOP; END LOOP; FOR i IN 0 .. 15 LOOP g_1024_state(BITAND(i + g_1024_p, 15)) := v_t(i); END LOOP; END long_jump1024; ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- PROCEDURE set_mode(p_mode IN mode_t) IS BEGIN g_mode := p_mode; END set_mode; PROCEDURE set_mode(p_mode IN VARCHAR2) IS BEGIN set_mode( CASE LOWER(p_mode) WHEN 'xoroshiro128+' THEN c_128plus WHEN 'xoroshiro128++' THEN c_128plusplus WHEN 'xoroshiro128**' THEN c_128starstar WHEN 'xoshiro256+' THEN c_256plus WHEN 'xoshiro256++' THEN c_256plusplus WHEN 'xoshiro256**' THEN c_256starstar WHEN 'xoshiro512+' THEN c_512plus WHEN 'xoshiro512++' THEN c_512plusplus WHEN 'xoshiro512**' THEN c_512starstar WHEN 'xoroshiro1024*' THEN c_1024star WHEN 'xoroshiro1024++' THEN c_1024plusplus WHEN 'xoroshiro1024**' THEN c_1024starstar END); END set_mode; FUNCTION get_mode RETURN mode_t IS BEGIN RETURN g_mode; END get_mode; FUNCTION get_mode_name RETURN VARCHAR2 IS BEGIN RETURN CASE g_mode WHEN c_128plus THEN 'xoroshiro128+' WHEN c_128plusplus THEN 'xoroshiro128++' WHEN c_128starstar THEN 'xoroshiro128**' WHEN c_256plus THEN 'xoshiro256+' WHEN c_256plusplus THEN 'xoshiro256++' WHEN c_256starstar THEN 'xoshiro256**' WHEN c_512plus THEN 'xoshiro512+' WHEN c_512plusplus THEN 'xoshiro512++' WHEN c_512starstar THEN 'xoshiro512**' WHEN c_1024star THEN 'xoroshiro1024*' WHEN c_1024plusplus THEN 'xoroshiro1024++' WHEN c_1024starstar THEN 'xoroshiro1024**' END; END get_mode_name; FUNCTION get_next RETURN uint64_t IS BEGIN RETURN CASE WHEN g_mode IN (c_128plus, c_128plusplus, c_128starstar) THEN next128 WHEN g_mode IN (c_256plus, c_256plusplus, c_256starstar) THEN next256 WHEN g_mode IN (c_512plus, c_512plusplus, c_512starstar) THEN next512 WHEN g_mode IN (c_1024star, c_1024plusplus, c_1024starstar) THEN next1024 END; END get_next; PROCEDURE bounce IS BEGIN CASE WHEN g_mode IN (c_128plus, c_128plusplus, c_128starstar) THEN jump128; WHEN g_mode IN (c_256plus, c_256plusplus, c_256starstar) THEN jump256; WHEN g_mode IN (c_512plus, c_512plusplus, c_512starstar) THEN jump512; WHEN g_mode IN (c_1024star, c_1024plusplus, c_1024starstar) THEN jump1024; ELSE RAISE invalid_mode; END CASE; END bounce; PROCEDURE long_jump IS BEGIN CASE WHEN g_mode IN (c_128plus, c_128plusplus, c_128starstar) THEN long_jump128; WHEN g_mode IN (c_256plus, c_256plusplus, c_256starstar) THEN long_jump256; WHEN g_mode IN (c_512plus, c_512plusplus, c_512starstar) THEN long_jump512; WHEN g_mode IN (c_1024star, c_1024plusplus, c_1024starstar) THEN long_jump1024; ELSE RAISE invalid_mode; END CASE; END long_jump; PROCEDURE set_state(p_seed IN seed_tab) IS BEGIN CASE WHEN g_mode IN (c_128plus, c_128plusplus, c_128starstar) THEN g_128_state := state128_array_t(); FOR i IN 0 .. 1 LOOP g_128_state(i) := p_seed(i + 1); END LOOP; WHEN g_mode IN (c_256plus, c_256plusplus, c_256starstar) THEN g_256_state := state256_array_t(); FOR i IN 0 .. 3 LOOP g_256_state(i) := p_seed(i + 1); END LOOP; WHEN g_mode IN (c_512plus, c_512plusplus, c_512starstar) THEN g_512_state := state512_array_t(); FOR i IN 0 .. 7 LOOP g_512_state(i) := p_seed(i + 1); END LOOP; WHEN g_mode IN (c_1024star, c_1024plusplus, c_1024starstar) THEN g_1024_p := 0; g_1024_state := state1024_array_t(); FOR i IN 0 .. 15 LOOP g_1024_state(i) := p_seed(i + 1); END LOOP; ELSE RAISE invalid_mode; END CASE; END set_state; PROCEDURE splitmix64_set_state(p_seed uint64_t) IS BEGIN g_splitmix64_state := p_seed; END splitmix64_set_state; FUNCTION splitmix64_next RETURN uint64_t IS /* Based mostly on the splitmix64.c code by Sebastiano Vigna https://xorshift.di.unimi.it/splitmix64.c static uint64_t x; uint64_t subsequent() { uint64_t z = (x += 0x9e3779b97f4a7c15); z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; z = (z ^ (z >> 27)) * 0x94d049bb133111eb; return z ^ (z >> 31); } This won't be almost as quick as the unique because it makes use of division as an alternative of bit shifting. Nonetheless, the performance of it must be constant */ v_z NUMBER; BEGIN g_splitmix64_state := BITAND(g_splitmix64_state + TO_NUMBER('9e3779b97f4a7c15', 'xxxxxxxxxxxxxxxx'), c_64bitmask); v_z := g_splitmix64_state; v_z := bitxor(v_z, shr64(v_z, 30)); v_z := v_z * TO_NUMBER('bf58476d1ce4e5b9', 'xxxxxxxxxxxxxxxx'); v_z := big_bitand(v_z, c_64bitmask); v_z := bitxor(v_z, shr64(v_z, 27)); v_z := v_z * TO_NUMBER('94d049bb133111eb', 'xxxxxxxxxxxxxxxx'); v_z := big_bitand(v_z, c_64bitmask); RETURN BITAND(bitxor(v_z, shr64(v_z, 31)), c_64bitmask); END splitmix64_next; END;
The BIG_BITAND operate I described intimately beforehand is used throughout the shl64, next1024, and splitmix64_next features to make sure giant (128-bit) values are dealt with accurately.
I hope you discover the code attention-grabbing and helpful. I’ve yet another article deliberate on this collection – protecting the the 32-bit variations inside this generator household. Whereas they may have been mixed right into a single package deal; I felt it was a greater answer to maintain them separate as they’re unlikely for use collectively in sensible utility. Usually I count on customers will need outcomes of a single single bit-size, 64 or 32. Combining them wouldn’t serve a lot objective.
Questions and feedback, as at all times, are welcome.