{"id":20248620,"url":"https://github.com/cslarsen/mersenne-twister","last_synced_at":"2025-04-10T22:22:40.712Z","repository":{"id":2207614,"uuid":"3156571","full_name":"cslarsen/mersenne-twister","owner":"cslarsen","description":"This Mersenne Twister is a fast pseudo-random number generator (PRNG) in C++","archived":false,"fork":false,"pushed_at":"2017-12-07T11:02:29.000Z","size":135,"stargazers_count":87,"open_issues_count":2,"forks_count":23,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-24T19:21:46.636Z","etag":null,"topics":["mersenne-twister","monte-carlo","prng","pseudo-random"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cslarsen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-01-11T19:25:44.000Z","updated_at":"2025-03-15T13:09:43.000Z","dependencies_parsed_at":"2022-09-08T07:10:34.229Z","dependency_job_id":null,"html_url":"https://github.com/cslarsen/mersenne-twister","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cslarsen%2Fmersenne-twister","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cslarsen%2Fmersenne-twister/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cslarsen%2Fmersenne-twister/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cslarsen%2Fmersenne-twister/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cslarsen","download_url":"https://codeload.github.com/cslarsen/mersenne-twister/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248306867,"owners_count":21081747,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["mersenne-twister","monte-carlo","prng","pseudo-random"],"created_at":"2024-11-14T09:48:53.500Z","updated_at":"2025-04-10T22:22:40.684Z","avatar_url":"https://github.com/cslarsen.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"A fast Mersenne Twister in C++\n==============================\n\nThis is an implementation of the fast pseudo-random number generator (PRNG)\n**MT19937**, colloquially called the _Mersenne Twister_.  It was given this\nname because it has a period of 2^19937 - 1, which is a Mersenne prime.\n\nThe code here is actually ~1.6 times *faster* (on Intel CPUs) than the\nreference implementation mt19937ar.c (see below).\n\nThe Mersenne Twister is highly regarded for its performance and high quality\npseudo-random numbers. In spite of this, it is *not* suited for cryptographic\ncode, because one only needs to observe 624 iterates to predict all future\nones.  It was designed with statistical simulations in mind, and should\ntherefore be quite good for Monte Carlo simulations, probabilistic algorithms\nand so on.\n\nYou can read more about the [Mersenne Twister on\nWikipedia](https://secure.wikimedia.org/wikipedia/en/wiki/Mersenne_twister).\n\n**UPDATE**\n\nI removed the `srand` and `rand` C standard library drop-in functions, because\nI believe they contained errors.\n\n**OLDER UPDATE**\n\nAll prior versions with loop unrolling had a bug that caused numbers to differ\nsignificantly from the reference implementation. This has now been fixed, and\nthe tests have been expanded to test 2000 consecutive numbers and numbers at\ndoubling index positions up to over four billion.  Thanks to Mikael Leetmaa for\nletting me know about this!\n\nI've also fixed an out-of-bounds read in the MT array. Thanks to Nyall Dawson\nfor finding this bug!\n\nPerformance\n-----------\n\nThis implementation is _very fast_.  It runs faster than the reference,\nnon-SIMD, implementation in the original paper (*and* the more recent code in\nmt19937ar.c) on the computers I've checked with (all Intel CPUs of different\ngenerations). To be sure, please run the test program by typing `make check`.\nSee below for numbers.\n\nThe original optimization trick I did was to unroll the loop in\n`generate_number()` three times to avoid the relatively expensive modulus\noperations.  The mod instructions were used to have the array index wrap\naround, but was alleviated with the loops and some simple arithmetic.  This is\na well known trick.\n\nHowever, I tried unrolling each loop even more, since the loop counters can be\nfactorized.  The idea was to fill the CPU's [instruction\npipeline](http://en.wikipedia.org/wiki/Instruction_pipeline) and avoid flushing\nit.  It worked fine on my Intel Core i7 computer, and increased performance\nfrom around 186M numbers/sec to 204M numbers/sec. It may not work as well on\nother architectures, though.\n\nI was tipped by Michel Valin of another neat trick to choose which value in the\nmatrix to use. The previous code checked if `y` was odd with a bitwise AND, and\nused that to index into an array to choose between zero and a magic value.\nHowever, there's a really cool trick that can be used instead: Just put the `y`\nvalue in a _signed_ variable, shift left 31 then shift right 31 again. What\nhappens then is that, because the variable is signed, it will use the `SARL`\nx86 instruction so that the LSB is effectively copied to all other bit\npositions. The final step is then to bitwise AND the result with the magic\nvalue. In other words, previous code:\n\n    static int MATRIX[] = {0, 0x12345678};\n    // ...\n    uint32_t foo = MATRIX[y \u0026 1] // 0 if y is even, 0x12345678 if it's odd\n\nchanges to\n\n    uint32_t foo = ((int32_t(y) \u003c\u003c 31) \u003e\u003e 31) \u0026 0x12345678\n\nWith `-ftree-vectorize`, it seems that this trick does wonders and speeds up\nthe code even more.\n\nFinally, note that people have done SIMD and CUDA implementations.  If\nyou are looking for even more speed, I suggest you check them out.\n\nCompilation and usage\n---------------------\n\nTo build the example, just type\n\n    $ make clean check\n\nYou'll see if this implementation runs faster than the reference non-SIMD\nMersenne Twister.\n\nOn an older Intel Core i7 (my machine), using clang 4 (I think) the output\nlooks like this:\n\n    $ ./test-mt 20\n    Testing Mersenne Twister with reference implementation\n      * Pass 1/2  OK\n      * Pass 2/2  OK\n\n    Timing our implementation (best times over 20 passes) ... \n      1.0321990s \n      0.9729490s ..................\n      min=0.972949s max=1.0322s mean=1.00114s stddev=0.0143048s\n      193.8 million — 205.6 million numbers/second\n\n    Timing reference mt19937ar.c (best times over 20 passes) ... \n      1.1132160s .\n      1.1116460s ..\n      1.0994660s .\n      1.0944240s ............\n      min=1.09442s max=1.14412s mean=1.12278s stddev=0.0126344s\n      174.8 million — 182.7 million numbers/second\n\n    1.12485 times faster than the reference (ratio of best runs)\n\nOn an Intel Xeon with gcc 6.3:\n\n    Testing Mersenne Twister with reference implementation\n      * Pass 1/2  OK\n      * Pass 2/2  OK\n\n    Timing our implementation (best times over 20 passes) ...\n      0.5661380s\n      0.5654360s\n      0.5652670s .\n      0.5649580s ...\n      0.5641450s ...........\n      min=0.564145s max=0.569173s mean=0.565719s stddev=0.00129429s\n      351.4 million — 354.5 million numbers/second\n\n    Timing reference mt19937ar.c (best times over 20 passes) ...\n      0.9026930s\n      0.9001340s\n      0.8963510s .\n      0.8963100s .\n      0.8959060s ..\n      0.8956320s .\n      0.8955830s ......\n      0.8953400s .\n      min=0.89534s max=0.902693s mean=0.896933s stddev=0.00172019s\n      221.6 million — 223.4 million numbers/second\n\n    1.58707 times faster than the reference (ratio of best runs)\n\nYou can pass the number of iterations to perform on the command line, e.g.\n\n    $ ./test-mt 100\n\nThis is quite important to let the CPU throttle up to get the best numbers. For\neach iteration, the time is printed if it's better than seen before. If it\nisn't better, a dot is printed.\n\nTo actually use the code, include the header and cpp file into your project.\nThen\n\n    namespace mt {\n      #include \"mersenne-twister.h\"\n    }\n\n    // ...\n\n    mt::seed(1234);\n    printf(\"a pseudo-random number: %d\\n\", mt::rand_u32());\n\nAlso look at the `Makefile` here as well, it contains a few optimization flags\nthat you may want to use.\n\nPortability\n-----------\n\nThe code should be portable, although I have only tried on Intel CPUs. I don't\nknow if the speed holds up on other CPUs (and I doubt it). If you're not on\nUNIX, you can pretty easily port the code.\n\nThe MT19937 algorithm is inherently 32-bit, so you only get 32-bit values.\n\n\nBugs\n----\n\nPlease report any bugs to the author.\n\nAuthor and license\n------------------\n\nWritten by [Christian Stigen Larsen](https://csl.name)\n\nDistributed under the modified BSD license.\n\n2015-02-17, 2017-12-06\n\nReferences\n----------\n\n* This code was originally a translation of the [MT19937 pseudo-code on\n  Wikipedia](https://secure.wikimedia.org/wikipedia/en/wiki/Mersenne_twister)\n* The [original Mersenne Twister paper](http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/ARTICLES/mt.pdf)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcslarsen%2Fmersenne-twister","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcslarsen%2Fmersenne-twister","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcslarsen%2Fmersenne-twister/lists"}