about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGenevieve Alfirevic <gen@nyble.dev>2025-02-08 04:51:06 -0600
committerGenevieve Alfirevic <gen@nyble.dev>2025-02-08 04:51:06 -0600
commit25f4bb271f3d7d4b92c4ca86ddc8220c7ab13cfe (patch)
tree622f6130b42dd6024dc3978e8163ce64fc0f4ef0
downloadmermaid-25f4bb271f3d7d4b92c4ca86ddc8220c7ab13cfe.tar.gz
mermaid-25f4bb271f3d7d4b92c4ca86ddc8220c7ab13cfe.zip
Ripped MT out of other codebase
-rw-r--r--.gitignore1
-rw-r--r--.rustfmt.toml1
-rw-r--r--Cargo.lock7
-rw-r--r--Cargo.toml6
-rw-r--r--LICENSE121
-rw-r--r--README.md37
-rw-r--r--src/lib.rs288
-rw-r--r--test/MTwikipedia-array_state624
-rw-r--r--test/MTwikipedia-state624
-rw-r--r--test/MTwikipedia.c145
-rw-r--r--test/mt19937ar-cok200
-rw-r--r--test/mt19937ar-cok-real200
12 files changed, 2254 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/.rustfmt.toml b/.rustfmt.toml
new file mode 100644
index 0000000..218e203
--- /dev/null
+++ b/.rustfmt.toml
@@ -0,0 +1 @@
+hard_tabs = true
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..9d54999
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "mermaid"
+version = "0.1.0"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..642b5da
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "mermaid"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..0e259d4
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,121 @@
+Creative Commons Legal Code
+
+CC0 1.0 Universal
+
+    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+    LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
+    ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+    INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+    REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
+    PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
+    THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
+    HEREUNDER.
+
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer
+exclusive Copyright and Related Rights (defined below) upon the creator
+and subsequent owner(s) (each and all, an "owner") of an original work of
+authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for
+the purpose of contributing to a commons of creative, cultural and
+scientific works ("Commons") that the public can reliably and without fear
+of later claims of infringement build upon, modify, incorporate in other
+works, reuse and redistribute as freely as possible in any form whatsoever
+and for any purposes, including without limitation commercial purposes.
+These owners may contribute to the Commons to promote the ideal of a free
+culture and the further production of creative, cultural and scientific
+works, or to gain reputation or greater distribution for their Work in
+part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any
+expectation of additional consideration or compensation, the person
+associating CC0 with a Work (the "Affirmer"), to the extent that he or she
+is an owner of Copyright and Related Rights in the Work, voluntarily
+elects to apply CC0 to the Work and publicly distribute the Work under its
+terms, with knowledge of his or her Copyright and Related Rights in the
+Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be
+protected by copyright and related or neighboring rights ("Copyright and
+Related Rights"). Copyright and Related Rights include, but are not
+limited to, the following:
+
+  i. the right to reproduce, adapt, distribute, perform, display,
+     communicate, and translate a Work;
+ ii. moral rights retained by the original author(s) and/or performer(s);
+iii. publicity and privacy rights pertaining to a person's image or
+     likeness depicted in a Work;
+ iv. rights protecting against unfair competition in regards to a Work,
+     subject to the limitations in paragraph 4(a), below;
+  v. rights protecting the extraction, dissemination, use and reuse of data
+     in a Work;
+ vi. database rights (such as those arising under Directive 96/9/EC of the
+     European Parliament and of the Council of 11 March 1996 on the legal
+     protection of databases, and under any national implementation
+     thereof, including any amended or successor version of such
+     directive); and
+vii. other similar, equivalent or corresponding rights throughout the
+     world based on applicable law or treaty, and any national
+     implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention
+of, applicable law, Affirmer hereby overtly, fully, permanently,
+irrevocably and unconditionally waives, abandons, and surrenders all of
+Affirmer's Copyright and Related Rights and associated claims and causes
+of action, whether now known or unknown (including existing as well as
+future claims and causes of action), in the Work (i) in all territories
+worldwide, (ii) for the maximum duration provided by applicable law or
+treaty (including future time extensions), (iii) in any current or future
+medium and for any number of copies, and (iv) for any purpose whatsoever,
+including without limitation commercial, advertising or promotional
+purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
+member of the public at large and to the detriment of Affirmer's heirs and
+successors, fully intending that such Waiver shall not be subject to
+revocation, rescission, cancellation, termination, or any other legal or
+equitable action to disrupt the quiet enjoyment of the Work by the public
+as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason
+be judged legally invalid or ineffective under applicable law, then the
+Waiver shall be preserved to the maximum extent permitted taking into
+account Affirmer's express Statement of Purpose. In addition, to the
+extent the Waiver is so judged Affirmer hereby grants to each affected
+person a royalty-free, non transferable, non sublicensable, non exclusive,
+irrevocable and unconditional license to exercise Affirmer's Copyright and
+Related Rights in the Work (i) in all territories worldwide, (ii) for the
+maximum duration provided by applicable law or treaty (including future
+time extensions), (iii) in any current or future medium and for any number
+of copies, and (iv) for any purpose whatsoever, including without
+limitation commercial, advertising or promotional purposes (the
+"License"). The License shall be deemed effective as of the date CC0 was
+applied by Affirmer to the Work. Should any part of the License for any
+reason be judged legally invalid or ineffective under applicable law, such
+partial invalidity or ineffectiveness shall not invalidate the remainder
+of the License, and in such case Affirmer hereby affirms that he or she
+will not (i) exercise any of his or her remaining Copyright and Related
+Rights in the Work or (ii) assert any associated claims and causes of
+action with respect to the Work, in either case contrary to Affirmer's
+express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
+    surrendered, licensed or otherwise affected by this document.
+ b. Affirmer offers the Work as-is and makes no representations or
+    warranties of any kind concerning the Work, express, implied,
+    statutory or otherwise, including without limitation warranties of
+    title, merchantability, fitness for a particular purpose, non
+    infringement, or the absence of latent or other defects, accuracy, or
+    the present or absence of errors, whether or not discoverable, all to
+    the greatest extent permissible under applicable law.
+ c. Affirmer disclaims responsibility for clearing rights of other persons
+    that may apply to the Work or any use thereof, including without
+    limitation any person's Copyright and Related Rights in the Work.
+    Further, Affirmer disclaims responsibility for obtaining any necessary
+    consents, permissions or other rights required for any use of the
+    Work.
+ d. Affirmer understands and acknowledges that Creative Commons is not a
+    party to this document and has no duty or obligation with respect to
+    this CC0 or use of the Work.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..fd5f353
--- /dev/null
+++ b/README.md
@@ -0,0 +1,37 @@
+# Mersenne Twister
+
+*(readme mostly ripped straight from another projects notes about*
+*it's implementation of mt19937. That's also where I ripped the lib.rs*
+*file from. i just wanted to use it in another project so i thought*
+*i was extract it. this is a port and not using a crate from crates.io*
+*because i thought it would be fun and thrilling. i was right)*
+
+https://en.wikipedia.org/wiki/Mersenne_Twister
+
+I've been doing research on Mersenne Twister. Apparently if you seed
+it poorly, a "bad seed", with a run of lots of 1s of 0s, you can get
+into a bad state that can take a long time to recover (citation needed).
+
+This S.O. answer about seeding Mersenne mentions there are other PRNGs
+that are easier to implement. https://stackoverflow.com/a/8473025
+
+Checked against the (original?) Mersenne Twister website.
+	https://www.math.sci.hiroshima-u.ac.jp/m-mat/MT/emt.html
+It has the latest version of the algorithm up at
+	https://www.math.sci.hiroshima-u.ac.jp/m-mat/MT/MT2002/emt19937ar.html
+which has output that we can test against here
+	https://www.math.sci.hiroshima-u.ac.jp/m-mat/MT/MT2002/CODES/mt19937ar.out
+and it all matches! both the u32 generator and the double "real" (f64)
+generator.
+
+License:  
+From the [license page for MT](https://www.math.sci.hiroshima-u.ac.jp/m-mat/MT/MT2002/elicense.html).  
+> Until 2001/4/6, MT had been distributed under GNU Public License, but after
+> 2001/4/6, we decided to let MT be used for any purpose, including commercial
+> use. 2002-versions mt19937ar.c, mt19937ar-cok.c are considered to be usable freely.
+
+Given that seeming dedication to the public domain, this is in turn rightly
+licensed as such. If that does not work for you, there is a LICENSE file
+with Creative Commons Zero, too, that I stuck in the repo. Can I do that?
+Iunno, I'm not a lawyer. I think probably, yes, since it seems to be
+dedicated to the public domain, anyway.
\ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..d2e4b2b
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,288 @@
+use std::ops::Range;
+
+/// Mersenne Twister implementation based on the C code from wikipedia
+/// https://en.wikipedia.org/wiki/Mersenne_Twister#C_code
+pub struct MersenneTwister {
+    state: [u32; Self::N],
+    state_index: usize,
+}
+
+impl MersenneTwister {
+    // "number of recurrence"
+    const N: usize = 624;
+    // " middle word, an offset used in the recurrence relation"
+    const M: usize = 397;
+    // ?
+    const F: u32 = 1812433253;
+    // "word size (in number of bits)"
+    const W: u32 = 32;
+    // "separation point of one word, or the number of bits of the lower bitmask"
+    const R: u32 = 31;
+    const UMASK: u32 = 0xffffffff << Self::R;
+    const LMASK: u32 = 0xffffffff >> (Self::W - Self::R);
+    // "coefficients of the rational normal form twist matrix"
+    const A: u32 = 0x9908b0df;
+
+    // TGFSR(R) Tempering bitmasks
+    const B: u32 = 0x9d2c5680;
+    const C: u32 = 0xefc60000;
+
+    // TGFSR(R) Tempering bit shifts
+    const S: u32 = 7;
+    const T: u32 = 15;
+
+    // Mersenne Twister bit shifts
+    const U: u32 = 11;
+    const L: u32 = 18;
+
+    fn initialize_state(state: &mut [u32], seed: u32) {
+        state[0] = seed;
+
+        let mut current_seed = seed;
+        for idx in 1..Self::N {
+            current_seed =
+                Self::F.wrapping_mul(current_seed ^ (current_seed >> (Self::W - 2))) + idx as u32;
+            state[idx] = current_seed;
+        }
+    }
+
+    fn initialize_by_array(state: &mut [u32], key: &[u32]) {
+        Self::initialize_state(state, 19650218);
+        let mut i = 1;
+        let mut j = 0;
+
+        let k = if Self::N > key.len() {
+            Self::N
+        } else {
+            key.len()
+        };
+
+        for _ in 0..k {
+            state[i] = (state[i] ^ (state[i - 1] ^ (state[i - 1] >> 30)).wrapping_mul(1664525))
+                + key[j]
+                + j as u32;
+
+            i += 1;
+            j += 1;
+
+            if i >= Self::N {
+                state[0] = state[Self::N - 1];
+                i = 1;
+            }
+
+            if j >= key.len() {
+                j = 0;
+            }
+        }
+
+        for _ in 0..Self::N - 1 {
+            state[i] = (state[i] ^ (state[i - 1] ^ (state[i - 1] >> 30)).wrapping_mul(1566083941))
+                - i as u32;
+
+            i += 1;
+
+            if i >= Self::N {
+                state[0] = state[Self::N - 1];
+                i = 1;
+            }
+        }
+
+        state[0] = 0x80000000;
+    }
+
+    #[allow(dead_code)]
+    pub fn new(seed: u32) -> Self {
+        let mut state = [032; Self::N];
+        Self::initialize_state(&mut state, seed);
+
+        Self {
+            state,
+            state_index: 0,
+        }
+    }
+
+    pub fn new_seed_array(key: &[u32]) -> Self {
+        let mut state = [032; Self::N];
+        Self::initialize_by_array(&mut state, key);
+
+        Self {
+            state,
+            state_index: 0,
+        }
+    }
+
+    #[allow(non_snake_case)]
+    pub fn random_u32(&mut self) -> u32 {
+        let mut j = if self.state_index < Self::N - 1 {
+            self.state_index + 1
+        } else {
+            self.state_index - (Self::N - 1)
+        };
+
+        let mut x = (self.state[self.state_index] & Self::UMASK) | (self.state[j] & Self::LMASK);
+        let mut xA = x >> 1;
+
+        if x & 0x00000001 > 0 {
+            xA ^= Self::A;
+        }
+
+        j = if self.state_index < (Self::N - Self::M) {
+            self.state_index + Self::M
+        } else {
+            self.state_index - (Self::N - Self::M)
+        };
+
+        x = self.state[j] ^ xA;
+        self.state[self.state_index] = x;
+        self.state_index += 1;
+
+        if self.state_index >= Self::N {
+            self.state_index = 0;
+        };
+
+        let mut y = x ^ (x >> Self::U); // tempering
+        y = y ^ ((y << Self::S) & Self::B);
+        y = y ^ ((y << Self::T) & Self::C);
+
+        y ^ (y >> Self::L)
+    }
+
+    pub fn random_f64(&mut self) -> f64 {
+        let rand = self.random_u32();
+
+        // [0,1)
+        rand as f64 * (1.0 / (u32::MAX as u64 + 1) as f64)
+    }
+
+    pub fn random_range(&mut self, range: Range<u32>) -> u32 {
+        (self.random_f64() * (range.end as f64 - range.start as f64) + range.start as f64) as u32
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::borrow::BorrowMut;
+
+    use super::MersenneTwister;
+
+    #[test]
+    fn mersenne_state_simple_seed_matches() {
+        let mt = MersenneTwister::new(19650218);
+        let numbers = load_MTwikipedia_state();
+
+        for (idx, number) in numbers.into_iter().enumerate() {
+            let ours = mt.state[idx];
+            if ours != number {
+                panic!("reference simple state was {number}, we got {ours}")
+            }
+        }
+    }
+
+    #[test]
+    fn mersenne_state_array_matches() {
+        let key: [u32; 4] = [0x123, 0x234, 0x345, 0x456];
+        let mt = MersenneTwister::new_seed_array(&key);
+        let numbers = load_MTwikipedia_array_state();
+
+        for (idx, number) in numbers.into_iter().enumerate() {
+            let ours = mt.state[idx];
+            if ours != number {
+                panic!("reference array state was {number}, we got {ours}")
+            }
+        }
+    }
+
+    #[test]
+    fn mersenne_matches() {
+        // Initial array
+        let key: [u32; 4] = [0x123, 0x234, 0x345, 0x456];
+        let mut mt = MersenneTwister::new_seed_array(&key);
+        let numbers = load_mt19937ar_cok();
+
+        for number in numbers {
+            let ours = mt.random_u32();
+            if ours != number {
+                panic!("reference was {number}, we got {ours}")
+            }
+        }
+    }
+
+    #[test]
+    fn mersenne_matches_real() {
+        // Initial array
+        let key: [u32; 4] = [0x123, 0x234, 0x345, 0x456];
+        let mut mt = MersenneTwister::new_seed_array(&key);
+        let numbers = load_mt19937ar_cok_real();
+
+        // The C program first generated 1000 random u32, so we do it too.
+        for _ in 0..1000 {
+            let _ = mt.random_u32();
+        }
+
+        for number in numbers {
+            let ours = mt.random_f64();
+            let string = format!("{ours:.8}");
+            if !string.eq(&number) {
+                panic!("reference was '{number}', we got '{string}'")
+            }
+        }
+    }
+
+    fn load_mt19937ar_cok() -> Vec<u32> {
+        let string = std::fs::read_to_string("test/mt19937ar-cok").unwrap();
+        let mut numbers = vec![];
+
+        for line in string.lines() {
+            let mut chars = line.chars();
+            for _ in 0..5 {
+                let number: String = chars.borrow_mut().take(10).collect();
+                let _ = chars.next(); // throwout the space
+
+                let ulong: u32 = number.trim().parse().unwrap();
+                numbers.push(ulong);
+            }
+        }
+
+        numbers
+    }
+
+    fn load_mt19937ar_cok_real() -> Vec<String> {
+        let string = std::fs::read_to_string("test/mt19937ar-cok-real").unwrap();
+        let mut numbers = vec![];
+
+        for line in string.lines() {
+            let mut chars = line.chars();
+            for _ in 0..5 {
+                let number: String = chars.borrow_mut().take(10).collect();
+                let _ = chars.next(); // throwout the space
+                numbers.push(number);
+            }
+        }
+
+        numbers
+    }
+
+    #[allow(non_snake_case)]
+    fn load_MTwikipedia_array_state() -> Vec<u32> {
+        let string = std::fs::read_to_string("test/MTwikipedia-array_state").unwrap();
+        let mut numbers = vec![];
+
+        for line in string.lines() {
+            numbers.push(line.trim().parse().unwrap());
+        }
+
+        numbers
+    }
+
+    #[allow(non_snake_case)]
+    fn load_MTwikipedia_state() -> Vec<u32> {
+        let string = std::fs::read_to_string("test/MTwikipedia-state").unwrap();
+        let mut numbers = vec![];
+
+        for line in string.lines() {
+            numbers.push(line.trim().parse().unwrap());
+        }
+
+        numbers
+    }
+}
diff --git a/test/MTwikipedia-array_state b/test/MTwikipedia-array_state
new file mode 100644
index 0000000..64df1eb
--- /dev/null
+++ b/test/MTwikipedia-array_state
@@ -0,0 +1,624 @@
+2147483648
+1827812183
+1371430253
+3559376401
+4152304030
+3484546413
+ 904688886
+2640105624
+3033298696
+3386595201
+ 369478181
+2269089429
+ 618892536
+1404079710
+2891471128
+2871169702
+1020385029
+3311824836
+ 923090660
+1921041923
+1544466474
+ 685797265
+2465597578
+2346973074
+ 630894856
+ 665182002
+ 769175936
+3017123521
+3508859727
+1803296144
+2059566241
+4053644259
+3993140148
+ 741891261
+  54278865
+  20043431
+2445648452
+1044381999
+1773042707
+2768959228
+1818875112
+2035786986
+3458871676
+4190322778
+1552412821
+3743407409
+ 921020090
+3028219647
+1811282874
+ 458436201
+2261805142
+3540504881
+  55523394
+3406035835
+3643554219
+ 160478601
+3131812209
+1750246847
+ 310524801
+ 538838761
+4097216171
+1424467795
+1736964303
+3924877158
+4050066274
+1284818847
+ 997608279
+1743645731
+3861638089
+1979190831
+ 331968179
+  67771207
+ 937697508
+3340056593
+ 752755706
+1581536688
+2292813118
+ 822270257
+3518209714
+3540339067
+1356302093
+ 564364160
+3439306709
+4156257291
+2902329296
+2676847202
+ 199377087
+2700614214
+4256495779
+1042379751
+1902843850
+ 541663347
+1105719791
+2055488122
+1772382387
+1590461887
+1096731286
+4039442187
+1175370089
+1659062698
+  53134572
+2821322629
+3865246561
+1928684207
+2238726924
+3291877865
+2486983120
+2591476417
+2633030347
+4263927136
+3370274455
+3018969306
+3342536519
+1048809092
+3887576647
+1798999130
+1882276042
+2314104910
+3303817434
+2251178951
+1354109516
+2944211425
+ 542518603
+3545156308
+ 292048272
+1667455762
+1824881537
+2291719689
+2601744913
+1475382386
+2151236187
+3551355316
+ 207179492
+4025262836
+4201541508
+4185568575
+1371095840
+2533214650
+ 750598898
+3336127010
+1112746635
+2168833184
+1866663264
+1008882524
+ 705705152
+ 434584641
+3720585473
+1359539617
+1186019465
+2997504282
+3279906530
+4174236237
+1111392757
+1874728325
+3994133610
+ 855552173
+1490712571
+ 770322226
+3509743848
+3097776221
+1669989606
+2981948555
+3420675648
+ 763522569
+1854726402
+1446282084
+4210797998
+3497860296
+1500567652
+4170419592
+ 375681337
+1685467682
+3252917671
+ 204735328
+ 725724149
+  86204629
+3407749819
+1497038849
+1240663743
+1497563373
+ 330463645
+ 678281313
+ 555587055
+3420977290
+3864978040
+2598258963
+  88433849
+ 706471606
+2204253466
+1207243547
+ 479433004
+2525229949
+3011716495
+3622461821
+2931310287
+ 994916916
+3209595751
+3887340275
+1441571561
+2496624432
+3592967859
+2170622192
+3964102663
+1750936864
+4286251765
+2410873793
+4056435468
+3778832465
+3568403537
+3195560039
+2447945345
+2289664522
+3125246309
+3254932065
+3412281324
+1070323682
+1454196965
+1242606593
+2025763526
+2480282382
+1785523412
+1678120983
+3466302448
+ 913688339
+2335682621
+2870884017
+3943203012
+3376940353
+ 821708821
+   5329814
+2050965739
+4012960695
+4026282590
+ 848005093
+2090115245
+1732838459
+1701934203
+2618985574
+2392637351
+3610308264
+1162509741
+3772926898
+4026399774
+2801305136
+2182020938
+2540720293
+4177612013
+3758227323
+2141839466
+3457019126
+ 690868322
+ 598123635
+4220136616
+2063722767
+ 534543515
+3995640444
+3697772838
+ 605496025
+ 194542699
+4283492525
+3414550867
+2944993929
+3138370086
+2273260021
+1368435547
+ 328762456
+2810028600
+3571321502
+1782649452
+4008389438
+3374096016
+2070297302
+3548106024
+ 406229528
+ 420474145
+1345435476
+1454548380
+2158312864
+1379619651
+1353546123
+3811653577
+ 882683258
+2752377205
+3614226931
+1500298293
+2610950419
+1253921430
+2107280447
+2276719522
+1296486334
+3787958895
+3076802280
+1113584194
+1511963190
+4162049235
+3993023547
+3616161164
+1305747926
+3972166487
+1967370814
+ 920085398
+3066264196
+3270634177
+ 116308049
+3500602755
+2095466291
+ 374997835
+4013819058
+ 294797265
+2531304952
+1915167960
+ 667114423
+  33740368
+2659595205
+1992038463
+1788663246
+1032288339
+2725176344
+ 965149701
+2340916620
+2880875099
+  90563045
+ 550093497
+2205859613
+4113574329
+2611773242
+   6224964
+2216769577
+2724275975
+1825208654
+1095989352
+1353654145
+4130469231
+2872700633
+3968090132
+3983530071
+3891778552
+ 253511543
+3451123488
+1858275584
+2348219340
+4164791526
+1546492002
+2318605776
+1965910834
+4016688232
+1661025458
+2551621891
+2559017942
+2999442539
+2626132036
+3855956683
+ 889284004
+4228792998
+2508936804
+2464411834
+3126525029
+1845662917
+1099875911
+ 230942152
+1316977638
+4287590380
+3960960001
+2035696777
+2084606597
+4185117397
+ 272555796
+1438814277
+3792058704
+2373818687
+ 328461098
+1933025545
+ 478993165
+2186693443
+2504363491
+2844647904
+4178236473
+ 174820621
+3894751753
+3928736686
+ 691843130
+3709350628
+2757608178
+1391782179
+1043240547
+2220523142
+2016183159
+2906513762
+3465827756
+3911890461
+2425950392
+ 948237040
+3362307558
+ 826526964
+1022776727
+1602110624
+ 495555482
+3374275041
+1251359676
+1255187341
+2187964004
+2260892791
+2998084135
+1359605011
+1974780261
+ 150018524
+ 729982456
+ 538716187
+2451949310
+1404163987
+ 323166556
+3575751708
+ 912151627
+1062492739
+ 136196234
+1525463811
+3934317698
+4059639798
+1714397141
+3799270074
+3933323871
+1950899325
+2202877835
+ 512028145
+ 121304123
+1747320652
+4025527049
+3203512622
+ 370863179
+1383153679
+ 338573713
+ 843668046
+3786076594
+3761568863
+1943691400
+4239756727
+2866888284
+ 927687523
+2835168303
+3639022486
+4177667412
+2454774443
+3330293413
+1073705099
+ 489962519
+2122918676
+3091912613
+2087072392
+2474785306
+4196422017
+1950304138
+1417647053
+3170449575
+2871308877
+2834888397
+2515213887
+ 706488188
+2765291661
+3342253292
+ 946613144
+2657539519
+1870033541
+2568978334
+2381242604
+2390291123
+1426830313
+1033183417
+1865206616
+3909956281
+3229647106
+ 567876042
+2632601739
+1787091399
+1136358267
+1707922556
+3600383805
+  83493536
+3720481151
+1860566046
+1457764290
+1087693608
+2574737982
+3472233887
+1946429651
+ 657205714
+1561347349
+3458704973
+ 658970395
+2666292445
+4010435611
+2923502084
+2919668932
+1447403386
+ 272213229
+2379902797
+ 856095986
+ 390957008
+ 316624381
+  37938916
+1312588871
+3443811924
+3563720170
+ 681138701
+3713652810
+1229426900
+  45899309
+3319920329
+3184643346
+1733808374
+3218014532
+4131837143
+2708745467
+1925606777
+1070300412
+1857066639
+ 231709688
+  89357594
+2807557743
+4246955725
+2648639203
+4014481964
+3609309784
+3413370774
+3362710738
+4117303240
+2975382313
+4244728709
+ 676814731
+1401643182
+4193290992
+1880982784
+3412352641
+ 432923266
+3204217730
+3640767186
+2748687591
+3238328348
+1816348975
+3454683239
+1788280760
+2390076397
+ 583783115
+ 749971462
+2070386333
+3684914363
+2505473379
+3781484919
+3251603932
+1061410633
+2657465574
+1047386942
+ 598203491
+3802852895
+3892183081
+ 650367471
+1888164348
+3790664944
+3285152048
+1772040010
+2779620173
+ 262034140
+4011996451
+ 172805695
+3112617504
+3698026131
+2749738982
+1338645063
+2883589338
+1171912066
+1463032348
+2303251030
+1690714656
+  87045526
+3931593098
+1973669665
+2196833368
+3131780013
+2099423072
+3143196216
+2732157577
+3060002362
+3279855788
+2424755944
+3186596011
+ 892164315
+1948474334
+1752877034
+3954052922
+2895910728
+2605843797
+  41504255
+2282306723
+2818684947
+2301112141
+ 125160123
+  16831279
+2001639563
+2988100720
+2804013521
+1917204704
+2217119131
+ 747297802
+  57526359
+1150692435
+1127421285
+1638007393
+2357393576
+1363062508
+ 112227006
+1305326547
+2699963315
+3027707384
+2567899981
+ 539524824
+1322391149
+4115045373
+2610809222
+1511354791
+1747171732
+2430429081
+2427698197
+ 668479568
+1616806017
+  77518867
diff --git a/test/MTwikipedia-state b/test/MTwikipedia-state
new file mode 100644
index 0000000..4fc4b09
--- /dev/null
+++ b/test/MTwikipedia-state
@@ -0,0 +1,624 @@
+  19650218
+2194844435
+ 874550967
+1417962806
+ 719805879
+2188372024
+ 721660136
+1814940559
+2833403150
+3889680837
+1003665704
+1330738387
+2892331238
+3489052161
+3855278296
+3311200630
+1422571577
+2585306665
+2882769417
+2783805802
+4207719964
+2400416080
+2341377904
+2590753297
+3924081815
+1211472509
+3057012486
+3436335279
+ 551149560
+1318655221
+1900533858
+3537525294
+2107812065
+3148644481
+ 594136785
+1814262168
+1224061569
+ 653651109
+ 254650943
+2832785922
+3699583528
+2088609312
+3529585711
+  41492871
+2876012911
+4240588078
+1402615791
+1934126869
+3096545044
+2890863071
+  80499043
+ 970921794
+3007610686
+ 750866145
+ 799115259
+3629971774
+2864380489
+3888374480
+2087741561
+3146346387
+3269762417
+2727485495
+2488668711
+2964190680
+2116659522
+4141458096
+3537107937
+3667677805
+2429248426
+2452306317
+3015982257
+ 499957222
+2360410630
+4194693085
+ 147288288
+3359074475
+1635136148
+4073107990
+3628367767
+3898116531
+ 275612352
+2842514961
+3115851985
+3103448722
+ 302309156
+  22171017
+2075519075
+3671007489
+3949991970
+1963601502
+4167967445
+ 804406473
+1055110313
+3894654986
+2278780139
+  34711884
+4121261916
+3468881884
+2287991389
+ 393453278
+ 548699130
+1499706375
+ 332872900
+1556864443
+1043137738
+4174970395
+1614747618
+ 669116410
+1897615374
+3255278936
+1370736725
+1550777747
+1685794058
+1862314184
+2400528575
+2672900100
+1647333586
+3524644532
+1765506473
+2857335743
+3636393737
+2932986219
+1203228647
+1628511289
+3647085204
+2987412752
+2905279128
+2631768385
+4014428911
+1727529885
+1124854030
+2262104686
+2499713312
+2421398767
+4134715143
+2358935835
+1002066021
+ 340444514
+3268366900
+1112268606
+1897974631
+3331577291
+2922602614
+3423543891
+1267030560
+2344564886
+1942259446
+3179572998
+1573187880
+1205933762
+3025229445
+4246102746
+ 346693941
+2002220930
+1829519945
+3309743875
+1904872348
+ 955816590
+2796353700
+ 668528669
+2648785169
+2704726048
+ 893089804
+ 738773343
+2832484895
+2050343702
+ 104744889
+3439545764
+ 980222603
+ 422274176
+3865519914
+2026267864
+ 539814729
+4137805178
+1140607595
+2537690753
+3971218783
+1931293181
+3089667358
+1133695167
+ 399772074
+3682192071
+4293649418
+1029228868
+3902327948
+1974090788
+3344730195
+2795804747
+3396216457
+ 366677807
+ 416687433
+ 930072460
+ 901228284
+1521860141
+3484259358
+ 478803252
+3138556488
+4137898487
+3807832586
+3773310804
+3221624091
+3076008769
+4156878137
+ 406561453
+3897607181
+ 623564883
+2247148685
+1696011322
+2911604503
+3979653402
+ 742342831
+3881512158
+2282092805
+2681274264
+3681829528
+  46152446
+3126539534
+3635632789
+1012335624
+3686064131
+2587648220
+2008745587
+2556071384
+1788453345
+ 861781568
+2727104545
+ 758340017
+1880693944
+2136364769
+1370367813
+ 798286522
+ 506003017
+2520802485
+2991500316
+3489134272
+3275208410
+1640252809
+3797759893
+4271912220
+3111882026
+ 140581304
+2568658569
+2686841033
+3059852298
+ 293994524
+1890650113
+1797269750
+3428669802
+1401714789
+2643788909
+3727894469
+2833360921
+1622853283
+3832221927
+ 277065458
+3711010937
+4192871202
+3356722694
+ 680496635
+2574997514
+1476265004
+3232676806
+3318710975
+4210635059
+4159903992
+2116300560
+2532158399
+ 718792604
+2539969944
+3164133583
+2649636591
+2200349072
+2851998122
+ 670873689
+2613796143
+3562264788
+1174445287
+1149173203
+2225964784
+4266377361
+3119455410
+1518371465
+1816545474
+2516586762
+ 240910660
+2681595121
+1301176317
+3127753611
+ 862342957
+ 771183330
+ 438085196
+1046497567
+ 922186079
+1222939296
+  51184555
+1757804190
+ 426665187
+2730510776
+2573705612
+1312406577
+ 667742236
+3239950393
+2582034960
+3759737929
+1601926242
+2947737408
+ 975540284
+1285948639
+3761027786
+1226457986
+  34782949
+2916146832
+ 142734034
+ 569716755
+4042990521
+3947471773
+1575951506
+3517313596
+3100986137
+2199197158
+3376719924
+4087139828
+3705107125
+1482533137
+1541227668
+1678953742
+2056318769
+3045003063
+1622629937
+ 487578169
+4137196231
+3764647071
+2241527512
+2558474063
+1038354351
+2094837850
+2481932343
+3229539130
+3756851151
+1006180559
+4181103103
+3565909441
+2371373280
+1493415041
+ 160348120
+1285104017
+3595587370
+4264242568
+1161124915
+2042766103
+ 737713932
+3481808155
+ 478389208
+1300643225
+1007986266
+1168231653
+3652705112
+2909421388
+3924670764
+1731016690
+4084014919
+4205099837
+1373900512
+2937538864
+2730075174
+ 957417377
+3258199283
+  87174175
+ 792789163
+2527971304
+2716998340
+3091367825
+  97659251
+1782441684
+ 919015551
+ 735476370
+  87326482
+ 926205331
+1888657273
+3715638227
+1715499660
+1922410526
+4175228089
+1525608673
+3578587616
+2042086160
+3730509879
+3607443975
+3879209240
+3652717612
+2372597521
+3471943430
+2765853569
+3643232056
+3297105617
+2692883557
+1805942063
+1394934451
+3337180104
+1181922214
+2331394419
+ 306465830
+3736887952
+1729663122
+3390355091
+2379159653
+3851731257
+4021176185
+1079541434
+ 433656928
+1831627642
+2892512290
+4063025724
+ 406246264
+1293199350
+1120564498
+3926678815
+1350089133
+4273098366
+3385122292
+ 993379095
+ 725502136
+  25504318
+ 752278045
+3729298457
+2392480235
+2657233815
+ 320925812
+2950230896
+ 989728679
+ 506301841
+1404204260
+1413065993
+ 865242585
+ 866785615
+1859142878
+ 589268143
+ 775553472
+1410495094
+1607063978
+3888932143
+ 704411669
+3513884419
+3370826939
+2896358996
+ 439226283
+2352722741
+1626809714
+ 246502175
+ 189424636
+1337937966
+3719088974
+4178799653
+2794717891
+1831166187
+1862432793
+2263235392
+3847861459
+ 802662362
+3621709005
+2634319122
+3245216029
+1466421412
+1528864744
+ 349292989
+3152395874
+3374677426
+2279952808
+1238578150
+ 107682552
+ 913857966
+3747681661
+3560958606
+3617063034
+1988620951
+1854864649
+1862999556
+2962654934
+1498851202
+2003448718
+2942754891
+ 798789550
+3882536840
+3338815162
+3066948065
+2057094004
+4171611151
+4284063395
+2325690120
+2659914459
+ 165909127
+2783186990
+2161504072
+ 343671839
+2751150377
+3621950182
+ 222528329
+3219381950
+ 238911006
+2710753737
+2982111755
+1115859074
+ 156211365
+ 228231184
+2302165064
+ 933165355
+4181545713
+2201173365
+ 291303663
+  19134280
+3581811046
+  68817880
+1037069880
+2445243929
+2507869609
+1468655994
+2646143627
+2709652242
+ 559859542
+2657856757
+ 248278651
+ 656698256
+2682159578
+3542996035
+2775252812
+1761180115
+3646714856
+2330951878
+ 834843492
+3951905925
+ 744286448
+3621804227
+2822882772
+1168938371
+3349647456
+ 672527398
+1163635478
+3445281068
+ 722448549
+3543924788
+2823456463
+1931863550
+2483173049
+4148604134
+3081487737
+2916138664
+ 940193076
+4142650279
+2563327448
+3737140007
+2407111514
+ 243557343
+1657192483
+3995730323
+1012445178
+2365602253
+2830079959
+2287658550
+2893719730
+2373631903
+4215513121
+ 189686171
+2003138393
+3410898923
+1020530876
+1103312993
+1976606742
+ 899447370
+1949555562
+3167671920
+ 595304244
+1919198655
+2929333298
+ 619161901
+ 623498751
+2063591130
+ 763251111
+4291719204
+3951567013
+2998385089
+ 758818611
+1375945828
+2510752543
+4188334520
+ 121785359
+3225750324
+1354685949
+1643999927
+ 911976986
+ 518523023
+3993561529
+2326708913
+ 336174575
+ 853096604
+2873283550
+4022490143
+3010604384
+2080594943
+1702902668
+3360749048
+4184957279
+2421794725
+4155016765
+3104188113
+1576615579
+ 604774175
+2739462297
+4096823942
+1932918233
+1779286169
+2544260698
+1430072091
+2196303270
+4237199385
+2613550760
+1481676153
+2920297152
+2463881971
+1098865791
+2939219489
+2494804283
+3108728554
+1635052534
+2905164258
diff --git a/test/MTwikipedia.c b/test/MTwikipedia.c
new file mode 100644
index 0000000..83eda43
--- /dev/null
+++ b/test/MTwikipedia.c
@@ -0,0 +1,145 @@
+// This file is the C Code from the Mersenne Twister wikipedia article
+//		https://en.wikipedia.org/wiki/Mersenne_Twister#C_code
+// bodged together with the init_by_array and main functions from
+//		https://www.math.sci.hiroshima-u.ac.jp/m-mat/MT/MT2002/CODES/mt19937ar.c
+// so I can test if the C Code on wikipedia generates the correct random numbers
+// as seen in
+//		https://www.math.sci.hiroshima-u.ac.jp/m-mat/MT/MT2002/CODES/mt19937ar.out
+// 
+// I did not check them all, but a few at random. They match, which makes me think
+// they operate the same. Now I need to look for the bug in my Rust,,,
+#include <stdint.h>
+#include <stdio.h>
+
+#define n 624
+#define m 397
+#define w 32
+#define r 31
+#define UMASK (0xffffffffUL << r)
+#define LMASK (0xffffffffUL >> (w-r))
+#define a 0x9908b0dfUL
+#define u 11
+#define s 7
+#define t 15
+#define l 18
+#define b 0x9d2c5680UL
+#define c 0xefc60000UL
+#define f 1812433253UL
+
+typedef struct
+{
+    uint32_t state_array[n];         // the array for the state vector 
+    int state_index;                 // index into state vector array, 0 <= state_index <= n-1   always
+} mt_state;
+
+
+void initialize_state(mt_state* state, uint32_t seed) 
+{
+    uint32_t* state_array = &(state->state_array[0]);
+    
+    state_array[0] = seed;                          // suggested initial seed = 19650218UL
+    
+    for (int i=1; i<n; i++)
+    {
+        seed = f * (seed ^ (seed >> (w-2))) + i;    // Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier.
+        state_array[i] = seed; 
+    }
+    
+    state->state_index = 0;
+}
+
+/* initialize by an array with array-length */
+/* init_key is the array for initializing keys */
+/* key_length is its length */
+/* slight change for C++, 2004/2/26 */
+void init_by_array(mt_state* state, unsigned long init_key[], int key_length)
+{
+    int i, j, k;
+    initialize_state(state, 19650218UL);
+    i=1; j=0;
+
+    k = (n>key_length ? n : key_length);
+
+	uint32_t* mt = &(state->state_array[0]);
+
+    for (; k; k--) {
+        mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
+          + init_key[j] + j; /* non linear */
+        mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
+        i++; j++;
+        if (i>=n) { mt[0] = mt[n-1]; i=1; }
+        if (j>=key_length) j=0;
+    }
+    for (k=n-1; k; k--) {
+        mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
+          - i; /* non linear */
+        mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
+        i++;
+        if (i>=n) { mt[0] = mt[n-1]; i=1; }
+    }
+
+    mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ 
+}
+
+
+uint32_t random_uint32(mt_state* state)
+{
+    uint32_t* state_array = &(state->state_array[0]);
+    
+    int k = state->state_index;      // point to current state location
+                                     // 0 <= state_index <= n-1   always
+    
+//  int k = k - n;                   // point to state n iterations before
+//  if (k < 0) k += n;               // modulo n circular indexing
+                                     // the previous 2 lines actually do nothing
+                                     //  for illustration only
+    
+    int j = k - (n-1);               // point to state n-1 iterations before
+    if (j < 0) j += n;               // modulo n circular indexing
+
+    uint32_t x = (state_array[k] & UMASK) | (state_array[j] & LMASK);
+    
+    uint32_t xA = x >> 1;
+    if (x & 0x00000001UL) xA ^= a;
+    
+    j = k - (n-m);                   // point to state n-m iterations before
+    if (j < 0) j += n;               // modulo n circular indexing
+    
+    x = state_array[j] ^ xA;         // compute next value in the state
+    state_array[k++] = x;            // update new state value
+    
+    if (k >= n) k = 0;               // modulo n circular indexing
+    state->state_index = k;
+    
+    uint32_t y = x ^ (x >> u);       // tempering 
+             y = y ^ ((y << s) & b);
+             y = y ^ ((y << t) & c);
+    uint32_t z = y ^ (y >> l);
+    
+    return z; 
+}
+
+int main(void)
+{
+    int i;
+    unsigned long init[4]={0x123, 0x234, 0x345, 0x456}, length=4;
+
+	mt_state state;
+	state.state_index = 0;
+
+    initialize_state(&state, 19650218UL);
+    //init_by_array(&state, init, length);
+
+    /*printf("1000 outputs of genrand_int32()\n");
+    for (i=0; i<1000; i++) {
+      printf("%10lu ", random_uint32(&state));
+      if (i%5==4) printf("\n");
+    }*/
+
+    // Print the internal state so we can check it against the Rust
+    for (i = 0; i < n; ++i) {
+        printf("%10lu\n", state.state_array[i]);
+    }
+
+    return 0;
+}
\ No newline at end of file
diff --git a/test/mt19937ar-cok b/test/mt19937ar-cok
new file mode 100644
index 0000000..c225da2
--- /dev/null
+++ b/test/mt19937ar-cok
@@ -0,0 +1,200 @@
+1067595299  955945823  477289528 4107218783 4228976476 
+3344332714 3355579695  227628506  810200273 2591290167 
+2560260675 3242736208  646746669 1479517882 4245472273 
+1143372638 3863670494 3221021970 1773610557 1138697238 
+1421897700 1269916527 2859934041 1764463362 3874892047 
+3965319921   72549643 2383988930 2600218693 3237492380 
+2792901476  725331109  605841842  271258942  715137098 
+3297999536 1322965544 4229579109 1395091102 3735697720 
+2101727825 3730287744 2950434330 1661921839 2895579582 
+2370511479 1004092106 2247096681 2111242379 3237345263 
+4082424759  219785033 2454039889 3709582971  835606218 
+2411949883 2735205030  756421180 2175209704 1873865952 
+2762534237 4161807854 3351099340  181129879 3269891896 
+ 776029799 2218161979 3001745796 1866825872 2133627728 
+  34862734 1191934573 3102311354 2916517763 1012402762 
+2184831317 4257399449 2899497138 3818095062 3030756734 
+1282161629  420003642 2326421477 2741455717 1278020671 
+3744179621  271777016 2626330018 2560563991 3055977700 
+4233527566 1228397661 3595579322 1077915006 2395931898 
+1851927286 3013683506 1999971931 3006888962 1049781534 
+1488758959 3491776230  104418065 2448267297 3075614115 
+3872332600  891912190 3936547759 2269180963 2633455084 
+1047636807 2604612377 2709305729 1952216715  207593580 
+2849898034  670771757 2210471108  467711165  263046873 
+3569667915 1042291111 3863517079 1464270005 2758321352 
+3790799816 2301278724 3106281430    7974801 2792461636 
+ 555991332  621766759 1322453093  853629228  686962251 
+1455120532  957753161 1802033300 1021534190 3486047311 
+1902128914 3701138056 4176424663 1795608698  560858864 
+3737752754 3141170998 1553553385 3367807274  711546358 
+2475125503  262969859  251416325 2980076994 1806565895 
+ 969527843 3529327173 2736343040 2987196734 1649016367 
+2206175811 3048174801 3662503553 3138851612 2660143804 
+1663017612 1816683231  411916003 3887461314 2347044079 
+1015311755 1203592432 2170947766 2569420716  813872093 
+1105387678 1431142475  220570551 4243632715 4179591855 
+2607469131 3090613241  282341803 1734241730 1391822177 
+1001254810  827927915 1886687171 3935097347 2631788714 
+3905163266  110554195 2447955646 3717202975 3304793075 
+3739614479 3059127468  953919171 2590123714 1132511021 
+3795593679 2788030429  982155079 3472349556  859942552 
+2681007391 2299624053  647443547  233600422  608168955 
+3689327453 1849778220 1608438222 3968158357 2692977776 
+2851872572  246750393 3582818628 3329652309 4036366910 
+1012970930  950780808 3959768744 2538550045  191422718 
+2658142375 3276369011 2927737484 1234200027 1920815603 
+3536074689 1535612501 2184142071 3276955054  428488088 
+2378411984 4059769550 3913744741 2732139246   64369859 
+3755670074  842839565 2819894466 2414718973 1010060670 
+1839715346 2410311136  152774329 3485009480 4102101512 
+2852724304  879944024 1785007662 2748284463 1354768064 
+3267784736 2269127717 3001240761 3179796763  895723219 
+ 865924942 4291570937   89355264 1471026971 4114180745 
+3201939751 2867476999 2460866060 3603874571 2238880432 
+3308416168 2072246611 2755653839 3773737248 1709066580 
+4282731467 2746170170 2832568330  433439009 3175778732 
+  26248366 2551382801  183214346 3893339516 1928168445 
+1337157619 3429096554 3275170900 1782047316 4264403756 
+1876594403 4289659572 3223834894 1728705513 4068244734 
+2867840287 1147798696  302879820 1730407747 1923824407 
+1180597908 1569786639  198796327  560793173 2107345620 
+2705990316 3448772106 3678374155  758635715  884524671 
+ 486356516 1774865603 3881226226 2635213607 1181121587 
+1508809820 3178988241 1594193633 1235154121  326117244 
+2304031425  937054774 2687415945 3192389340 2003740439 
+1823766188 2759543402   10067710 1533252662 4132494984 
+  82378136  420615890 3467563163  541562091 3535949864 
+2277319197 3330822853 3215654174 4113831979 4204996991 
+2162248333 3255093522 2219088909 2978279037  255818579 
+2859348628 3097280311 2569721123 1861951120 2907080079 
+2719467166  998319094 2521935127 2404125338  259456032 
+2086860995 1839848496 1893547357 2527997525 1489393124 
+2860855349   76448234 2264934035  744914583 2586791259 
+1385380501   66529922 1819103258 1899300332 2098173828 
+1793831094  276463159  360132945 4178212058  595015228 
+ 177071838 2800080290 1573557746 1548998935  378454223 
+1460534296 1116274283 3112385063 3709761796  827999348 
+3580042847 1913901014  614021289 4278528023 1905177404 
+  45407939 3298183234 1184848810 3644926330 3923635459 
+1627046213 3677876759  969772772 1160524753 1522441192 
+ 452369933 1527502551  832490847 1003299676 1071381111 
+2891255476  973747308 4086897108 1847554542 3895651598 
+2227820339 1621250941 2881344691 3583565821 3510404498 
+ 849362119  862871471  797858058 2867774932 2821282612 
+3272403146 3997979905  209178708 1805135652    6783381 
+2823361423  792580494 4263749770  776439581 3798193823 
+2853444094 2729507474 1071873341 1329010206 1289336450 
+3327680758 2011491779   80157208  922428856 1158943220 
+1667230961 2461022820 2608845159  387516115 3345351910 
+1495629111 4098154157 3156649613 3525698599 4134908037 
+ 446713264 2137537399 3617403512  813966752 1157943946 
+3734692965 1680301658 3180398473 3509854711 2228114612 
+1008102291  486805123  863791847 3189125290 1050308116 
+3777341526 4291726501  844061465 1347461791 2826481581 
+ 745465012 2055805750 4260209475 2386693097 2980646741 
+ 447229436 2077782664 1232942813 4023002732 1399011509 
+3140569849 2579909222 3794857471  900758066 2887199683 
+1720257997 3367494931 2668921229  955539029 3818726432 
+1105704962 3889207255 2277369307 2746484505 1761846513 
+2413916784 2685127085 4240257943 1166726899 4215215715 
+3082092067 3960461946 1663304043 2087473241 4162589986 
+2507310778 1579665506  767234210  970676017  492207530 
+1441679602 1314785090 3262202570 3417091742 1561989210 
+3011406780 1146609202 3262321040 1374872171 1634688712 
+1280458888 2230023982  419323804 3262899800   39783310 
+1641619040 1700368658 2207946628 2571300939 2424079766 
+ 780290914 2715195096 3390957695  163151474 2309534542 
+1860018424  555755123  280320104 1604831083 2713022383 
+1728987441 3639955502  623065489 3828630947 4275479050 
+3516347383 2343951195 2430677756  635534992 3868699749 
+ 808442435 3070644069 4282166003 2093181383 2023555632 
+1568662086 3422372620 4134522350 3016979543 3259320234 
+2888030729 3185253876 4258779643 1267304371 1022517473 
+ 815943045  929020012 2995251018 3371283296 3608029049 
+2018485115  122123397 2810669150 1411365618 1238391329 
+1186786476 3155969091 2242941310 1765554882  279121160 
+4279838515 1641578514 3796324015   13351065  103516986 
+1609694427  551411743 2493771609 1316337047 3932650856 
+4189700203  463397996 2937735066 1855616529 2626847990 
+  55091862 3823351211  753448970 4045045500 1274127772 
+1124182256   92039808 2126345552  425973257  386287896 
+2589870191 1987762798 4084826973 2172456685 3366583455 
+3602966653 2378803535 2901764433 3716929006 3710159000 
+2653449155 3469742630 3096444476 3932564653 2595257433 
+ 318974657 3146202484  853571438  144400272 3768408841 
+ 782634401 2161109003  570039522 1886241521   14249488 
+2230804228 1604941699 3928713335 3921942509 2155806892 
+ 134366254  430507376 1924011722  276713377  196481886 
+3614810992 1610021185 1785757066  851346168 3761148643 
+2918835642 3364422385 3012284466 3735958851 2643153892 
+3778608231 1164289832  205853021 2876112231 3503398282 
+3078397001 3472037921 1748894853 2740861475  316056182 
+1660426908  168885906  956005527 3984354789  566521563 
+1001109523 1216710575 2952284757 3834433081 3842608301 
+2467352408 3974441264 3256601745 1409353924 1329904859 
+2307560293 3125217879 3622920184 3832785684 3882365951 
+2308537115 2659155028 1450441945 3532257603 3186324194 
+1225603425 1124246549  175808705 3009142319 2796710159 
+3651990107  160762750 1902254979 1698648476 1134980669 
+ 497144426 3302689335 4057485630 3603530763 4087252587 
+ 427812652  286876201  823134128 1627554964 3745564327 
+2589226092 4202024494   62878473 3275585894 3987124064 
+2791777159 1916869511 2585861905 1375038919 1403421920 
+  60249114 3811870450 3021498009 2612993202  528933105 
+2757361321 3341402964 2621861700  273128190 4015252178 
+3094781002 1621621288 2337611177 1796718448 1258965619 
+4241913140 2138560392 3022190223 4174180924  450094611 
+3274724580  617150026 2704660665 1469700689 1341616587 
+ 356715071 1188789960 2278869135 1766569160 2795896635 
+  57824704 2893496380 1235723989 1630694347 3927960522 
+ 428891364 1814070806 2287999787 4125941184 3968103889 
+3548724050 1025597707 1404281500 2002212197   92429143 
+2313943944 2403086080 3006180634 3561981764 1671860914 
+1768520622 1803542985  844848113 3006139921 1410888995 
+1157749833 2125704913 1789979528 1799263423  741157179 
+2405862309  767040434 2655241390 3663420179 2172009096 
+2511931187 1680542666  231857466 1154981000  157168255 
+1454112128 3505872099 1929775046 2309422350 2143329496 
+2960716902  407610648 2938108129 2581749599  538837155 
+2342628867  430543915  740188568 1937713272 3315215132 
+2085587024 4030765687  766054429 3517641839  689721775 
+1294158986 1753287754 4202601348 1974852792   33459103 
+3568087535 3144677435 1686130825 4134943013 3005738435 
+3599293386  426570142  754104406 3660892564 1964545167 
+ 829466833  821587464 1746693036 1006492428 1595312919 
+1256599985 1024482560 1897312280 2902903201  691790057 
+1037515867 3176831208 1968401055 2173506824 1089055278 
+1748401123 2941380082  968412354 1818753861 2973200866 
+3875951774 1119354008 3988604139 1647155589 2232450826 
+3486058011 3655784043 3759258462  847163678 1082052057 
+ 989516446 2871541755 3196311070 3929963078  658187585 
+3664944641 2175149170 2203709147 2756014689 2456473919 
+3890267390 1293787864 2830347984 3059280931 4158802520 
+1561677400 2586570938  783570352 1355506163   31495586 
+3789437343 3340549429 2092501630  896419368  671715824 
+3530450081 3603554138 1055991716 3442308219 1499434728 
+3130288473 3639507000   17769680 2259741420  487032199 
+4227143402 3693771256 1880482820 3924810796  381462353 
+4017855991 2452034943 2736680833 2209866385 2128986379 
+ 437874044  595759426  641721026 1636065708 3899136933 
+ 629879088 3591174506  351984326 2638783544 2348444281 
+2341604660 2123933692  143443325 1525942256  364660499 
+ 599149312  939093251 1523003209  106601097  376589484 
+1346282236 1297387043  764598052 3741218111  933457002 
+1886424424 3219631016  525405256 3014235619  323149677 
+2038881721 4100129043 2851715101 2984028078 1888574695 
+2014194741 3515193880 4180573530 3461824363 2641995497 
+3179230245 2902294983 2217320456 4040852155 1784656905 
+3311906931   87498458 2752971818 2635474297 2831215366 
+3682231106 2920043893 3772929704 2816374944  309949752 
+2383758854  154870719  385111597 1191604312 1840700563 
+ 872191186 2925548701 1310412747 2102066999 1504727249 
+3574298750 1191230036 3330575266 3180292097 3539347721 
+ 681369118 3305125752 3648233597  950049240 4173257693 
+1760124957  512151405  681175196  580563018 1169662867 
+4015033554 2687781101  699691603 2673494188 1137221356 
+ 123599888  472658308 1053598179 1012713758 3481064843 
+3759461013 3981457956 3830587662 1877191791 3650996736 
+ 988064871 3515461600 4089077232 2225147448 1249609188 
+2643151863 3896204135 2416995901 1397735321 3460025646 
\ No newline at end of file
diff --git a/test/mt19937ar-cok-real b/test/mt19937ar-cok-real
new file mode 100644
index 0000000..de4e7fb
--- /dev/null
+++ b/test/mt19937ar-cok-real
@@ -0,0 +1,200 @@
+0.76275443 0.99000644 0.98670464 0.10143112 0.27933125 
+0.69867227 0.94218740 0.03427201 0.78842173 0.28180608 
+0.92179002 0.20785655 0.54534773 0.69644020 0.38107718 
+0.23978165 0.65286910 0.07514568 0.22765211 0.94872929 
+0.74557914 0.62664415 0.54708246 0.90959343 0.42043116 
+0.86334511 0.19189126 0.14718544 0.70259889 0.63426346 
+0.77408121 0.04531601 0.04605807 0.88595519 0.69398270 
+0.05377184 0.61711170 0.05565708 0.10133577 0.41500776 
+0.91810699 0.22320679 0.23353705 0.92871862 0.98897234 
+0.19786706 0.80558809 0.06961067 0.55840445 0.90479405 
+0.63288060 0.95009721 0.54948447 0.20645042 0.45000959 
+0.87050869 0.70806991 0.19406895 0.79286390 0.49332866 
+0.78483914 0.75145146 0.12341941 0.42030252 0.16728160 
+0.59906494 0.37575460 0.97815160 0.39815952 0.43595080 
+0.04952478 0.33917805 0.76509902 0.61034321 0.90654701 
+0.92915732 0.85365931 0.18812377 0.65913428 0.28814566 
+0.59476081 0.27835931 0.60722542 0.68310435 0.69387186 
+0.03699800 0.65897714 0.17527003 0.02889304 0.86777366 
+0.12352068 0.91439461 0.32022990 0.44445731 0.34903686 
+0.74639273 0.65918367 0.92492794 0.31872642 0.77749724 
+0.85413832 0.76385624 0.32744211 0.91326300 0.27458185 
+0.22190155 0.19865383 0.31227402 0.85321225 0.84243342 
+0.78544200 0.71854080 0.92503892 0.82703064 0.88306297 
+0.47284073 0.70059042 0.48003761 0.38671694 0.60465770 
+0.41747204 0.47163243 0.72750808 0.65830223 0.10955369 
+0.64215401 0.23456345 0.95944940 0.72822249 0.40888451 
+0.69980355 0.26677428 0.57333635 0.39791582 0.85377858 
+0.76962816 0.72004885 0.90903087 0.51376506 0.37732665 
+0.12691640 0.71249738 0.81217908 0.37037313 0.32772374 
+0.14238259 0.05614811 0.74363008 0.39773267 0.94859135 
+0.31452454 0.11730313 0.62962618 0.33334237 0.45547255 
+0.10089665 0.56550662 0.60539371 0.16027624 0.13245301 
+0.60959939 0.04671662 0.99356286 0.57660859 0.40269560 
+0.45274629 0.06699735 0.85064246 0.87742744 0.54508392 
+0.87242982 0.29321385 0.67660627 0.68230715 0.79052073 
+0.48592054 0.25186266 0.93769755 0.28565487 0.47219067 
+0.99054882 0.13155240 0.47110470 0.98556600 0.84397623 
+0.12875246 0.90953202 0.49129015 0.23792727 0.79481194 
+0.44337770 0.96564297 0.67749118 0.55684872 0.27286897 
+0.79538393 0.61965356 0.22487929 0.02226018 0.49248200 
+0.42247006 0.91797788 0.99250134 0.23449967 0.52531508 
+0.10246337 0.78685622 0.34310922 0.89892996 0.40454552 
+0.68608407 0.30752487 0.83601319 0.54956031 0.63777550 
+0.82199797 0.24890696 0.48801123 0.48661910 0.51223987 
+0.32969635 0.31075073 0.21393155 0.73453207 0.15565705 
+0.58584522 0.28976728 0.97621478 0.61498701 0.23891470 
+0.28518540 0.46809591 0.18371914 0.37597910 0.13492176 
+0.66849449 0.82811466 0.56240330 0.37548956 0.27562998 
+0.27521910 0.74096121 0.77176757 0.13748143 0.99747138 
+0.92504502 0.09175241 0.21389176 0.21766512 0.31183245 
+0.23271221 0.21207367 0.57903312 0.77523344 0.13242613 
+0.31037988 0.01204835 0.71652949 0.84487594 0.14982178 
+0.57423142 0.45677888 0.48420169 0.53465428 0.52667473 
+0.46880526 0.49849733 0.05670710 0.79022476 0.03872047 
+0.21697212 0.20443086 0.28949326 0.81678186 0.87629474 
+0.92297064 0.27373097 0.84625273 0.51505586 0.00582792 
+0.33295971 0.91848412 0.92537226 0.91760033 0.07541125 
+0.71745848 0.61158698 0.00941650 0.03135554 0.71527471 
+0.24821915 0.63636652 0.86159918 0.26450229 0.60160194 
+0.35557725 0.24477500 0.07186456 0.51757096 0.62120362 
+0.97981062 0.69954667 0.21065616 0.13382753 0.27693186 
+0.59644095 0.71500764 0.04110751 0.95730081 0.91600724 
+0.47704678 0.26183479 0.34706971 0.07545431 0.29398385 
+0.93236070 0.60486023 0.48015011 0.08870451 0.45548581 
+0.91872718 0.38142712 0.10668643 0.01397541 0.04520355 
+0.93822273 0.18011940 0.57577277 0.91427606 0.30911399 
+0.95853475 0.23611214 0.69619891 0.69601980 0.76765372 
+0.58515930 0.49479057 0.11288752 0.97187699 0.32095365 
+0.57563608 0.40760618 0.78703383 0.43261152 0.90877651 
+0.84686346 0.10599030 0.72872803 0.19315490 0.66152912 
+0.10210518 0.06257876 0.47950688 0.47062066 0.72701157 
+0.48915116 0.66110261 0.60170685 0.24516994 0.12726050 
+0.03451185 0.90864994 0.83494878 0.94800035 0.91035206 
+0.14480751 0.88458997 0.53498312 0.15963215 0.55378627 
+0.35171349 0.28719791 0.09097957 0.00667896 0.32309622 
+0.87561479 0.42534520 0.91748977 0.73908457 0.41793223 
+0.99279792 0.87908370 0.28458072 0.59132853 0.98672190 
+0.28547393 0.09452165 0.89910674 0.53681109 0.37931425 
+0.62683489 0.56609740 0.24801549 0.52948179 0.98328855 
+0.66403523 0.55523786 0.75886666 0.84784685 0.86829981 
+0.71448906 0.84670080 0.43922919 0.20771016 0.64157936 
+0.25664246 0.73055695 0.86395782 0.65852932 0.99061803 
+0.40280575 0.39146298 0.07291005 0.97200603 0.20555729 
+0.59616495 0.08138254 0.45796388 0.33681125 0.33989127 
+0.18717090 0.53545811 0.60550838 0.86520709 0.34290701 
+0.72743276 0.73023855 0.34195926 0.65019733 0.02765254 
+0.72575740 0.32709576 0.03420866 0.26061893 0.56997511 
+0.28439072 0.84422744 0.77637570 0.55982168 0.06720327 
+0.58449067 0.71657369 0.15819609 0.58042821 0.07947911 
+0.40193792 0.11376012 0.88762938 0.67532159 0.71223735 
+0.27829114 0.04806073 0.21144026 0.58830274 0.04140071 
+0.43215628 0.12952729 0.94668759 0.87391019 0.98382450 
+0.27750768 0.90849647 0.90962737 0.59269720 0.96102026 
+0.49544979 0.32007095 0.62585546 0.03119821 0.85953001 
+0.22017528 0.05834068 0.80731217 0.53799961 0.74166948 
+0.77426600 0.43938444 0.54862081 0.58575513 0.15886492 
+0.73214332 0.11649057 0.77463977 0.85788827 0.17061997 
+0.66838056 0.96076133 0.07949296 0.68521946 0.89986254 
+0.05667410 0.12741385 0.83470977 0.63969104 0.46612929 
+0.10200126 0.01194925 0.10476340 0.90285217 0.31221221 
+0.32980614 0.46041971 0.52024973 0.05425470 0.28330912 
+0.60426543 0.00598243 0.97244013 0.21135841 0.78561597 
+0.78428734 0.63422849 0.32909934 0.44771136 0.27380750 
+0.14966697 0.18156268 0.65686758 0.28726350 0.97074787 
+0.63676171 0.96649494 0.24526295 0.08297372 0.54257548 
+0.03166785 0.33735355 0.15946671 0.02102971 0.46228045 
+0.11892296 0.33408336 0.29875681 0.29847692 0.73767569 
+0.02080745 0.62980060 0.08082293 0.22993106 0.25031439 
+0.87787525 0.45150053 0.13673441 0.63407612 0.97907688 
+0.52241942 0.50580158 0.06273902 0.05270283 0.77031811 
+0.05113352 0.24393329 0.75036441 0.37436336 0.22877652 
+0.59975358 0.85707591 0.88691457 0.85547165 0.36641027 
+0.58720133 0.45462835 0.09243817 0.32981586 0.07820411 
+0.25421519 0.36004706 0.60092307 0.46192412 0.36758683 
+0.98424170 0.08019934 0.68594024 0.45826386 0.29962317 
+0.79365413 0.89231296 0.49478547 0.87645944 0.23590734 
+0.28106737 0.75026285 0.08136314 0.79582424 0.76010628 
+0.82792971 0.27947652 0.72482861 0.82191216 0.46171689 
+0.79189752 0.96043686 0.51609668 0.88995725 0.28998963 
+0.55191845 0.03934737 0.83033700 0.49553013 0.98009549 
+0.19017594 0.98347750 0.33452066 0.87144372 0.72106301 
+0.71272114 0.71465963 0.88361677 0.85571283 0.73782329 
+0.20920458 0.34855153 0.46766817 0.02780062 0.74898344 
+0.03680650 0.44866557 0.77426312 0.91025891 0.25195236 
+0.87319953 0.63265037 0.25552148 0.27422476 0.95217406 
+0.39281839 0.66441573 0.09158900 0.94515992 0.07800798 
+0.02507888 0.39901462 0.17382573 0.12141278 0.85502334 
+0.19902911 0.02160210 0.44460522 0.14688742 0.68020336 
+0.71323733 0.60922473 0.95400380 0.99611159 0.90897777 
+0.41073520 0.66206647 0.32064685 0.62805003 0.50677209 
+0.52690101 0.87473387 0.73918362 0.39826974 0.43683919 
+0.80459118 0.32422684 0.01958019 0.95319576 0.98326137 
+0.83931735 0.69060863 0.33671416 0.68062550 0.65152380 
+0.33392969 0.03451730 0.95227244 0.68200635 0.85074171 
+0.64721009 0.51234433 0.73402047 0.00969637 0.93835057 
+0.80803854 0.31485260 0.20089527 0.01323282 0.59933780 
+0.31584602 0.20209563 0.33754800 0.68604181 0.24443049 
+0.19952227 0.78162632 0.10336988 0.11360736 0.23536740 
+0.23262256 0.67803776 0.48749791 0.74658435 0.92156640 
+0.56706407 0.36683221 0.99157136 0.23421374 0.45183767 
+0.91609720 0.85573315 0.37706276 0.77042618 0.30891908 
+0.40709595 0.06944866 0.61342849 0.88817388 0.58734506 
+0.98711323 0.14744128 0.63242656 0.87704136 0.68347125 
+0.84446569 0.43265239 0.25146321 0.04130111 0.34259839 
+0.92697368 0.40878778 0.56990338 0.76204273 0.19820348 
+0.66314909 0.02482844 0.06669207 0.50205581 0.26084093 
+0.65139159 0.41650223 0.09733904 0.56344203 0.62651696 
+0.67332139 0.58037374 0.47258086 0.21010758 0.05713135 
+0.89390629 0.10781246 0.32037450 0.07628388 0.34227964 
+0.42190597 0.58201860 0.77363549 0.49595133 0.86031236 
+0.83906769 0.81098161 0.26694195 0.14215941 0.88210306 
+0.53634237 0.12090720 0.82480459 0.75930318 0.31847147 
+0.92768077 0.01037616 0.56201727 0.88107122 0.35925856 
+0.85860762 0.61109408 0.70408301 0.58434977 0.92192494 
+0.62667915 0.75988365 0.06858761 0.36156496 0.58057195 
+0.13636150 0.57719713 0.59340255 0.63530602 0.22976282 
+0.71915530 0.41162531 0.63979565 0.09931342 0.79344045 
+0.10893790 0.84450224 0.23122236 0.99485593 0.73637397 
+0.17276368 0.13357764 0.74965804 0.64991737 0.61990341 
+0.41523170 0.05878239 0.05687301 0.05497131 0.42868366 
+0.42571090 0.25810502 0.89642955 0.30439758 0.39310223 
+0.11357431 0.04288255 0.23397550 0.11200634 0.85621396 
+0.89733974 0.37508865 0.42077265 0.68597384 0.72781399 
+0.19296476 0.61699087 0.31667128 0.67756410 0.00177323 
+0.05725176 0.79474693 0.18885238 0.06724856 0.68193156 
+0.42202167 0.22082041 0.28554673 0.64995708 0.87851940 
+0.29124547 0.61009521 0.87374537 0.05743712 0.69902994 
+0.81925115 0.45653873 0.37236821 0.31118709 0.52734307 
+0.39672836 0.38185294 0.30163915 0.17374510 0.04913278 
+0.90404879 0.25742801 0.58266467 0.97663209 0.79823377 
+0.36437958 0.15206043 0.26529938 0.22690047 0.05839021 
+0.84721160 0.18622435 0.37809403 0.55706977 0.49828704 
+0.47659049 0.24289680 0.88477595 0.07807463 0.56245739 
+0.73490635 0.21099431 0.13164942 0.75840044 0.66877037 
+0.28988183 0.44046090 0.24967434 0.80048356 0.26029740 
+0.30416821 0.64151867 0.52067892 0.12880774 0.85465381 
+0.02690525 0.19149288 0.49630295 0.79682619 0.43566145 
+0.00288078 0.81484193 0.03763639 0.68529083 0.01339574 
+0.38405386 0.30537067 0.22994703 0.44000045 0.27217985 
+0.53831243 0.02870435 0.86282045 0.61831306 0.09164956 
+0.25609707 0.07445781 0.72185784 0.90058883 0.30070608 
+0.94476583 0.56822213 0.21933909 0.96772793 0.80063440 
+0.26307906 0.31183306 0.16501252 0.55436179 0.68562285 
+0.23829083 0.86511559 0.57868991 0.81888344 0.20126869 
+0.93172350 0.66028129 0.21786948 0.78515828 0.10262106 
+0.35390326 0.79303876 0.63427924 0.90479631 0.31024934 
+0.60635447 0.56198079 0.63573813 0.91854197 0.99701497 
+0.83085849 0.31692291 0.01925964 0.97446405 0.98751283 
+0.60944293 0.13751018 0.69519957 0.68956636 0.56969015 
+0.46440193 0.88341765 0.36754434 0.89223647 0.39786427 
+0.85055280 0.12749961 0.79452122 0.89449784 0.14567830 
+0.45716830 0.74822309 0.28200437 0.42546044 0.17464886 
+0.68308746 0.65496587 0.52935411 0.12736159 0.61523955 
+0.81590528 0.63107864 0.39786553 0.20102294 0.53292914 
+0.75485590 0.59847044 0.32861691 0.12125866 0.58917183 
+0.07638293 0.86845380 0.29192617 0.03989733 0.52180460 
+0.32503407 0.64071852 0.69516575 0.74254998 0.54587026 
+0.48713246 0.32920155 0.08719954 0.63497059 0.54328459 
+0.64178757 0.45583809 0.70694291 0.85212760 0.86074305 
+0.33163422 0.85739792 0.59908488 0.74566046 0.72157152
\ No newline at end of file