{"id":40178673,"url":"https://github.com/zephyrtronium/crazy","last_synced_at":"2026-01-19T18:03:29.177Z","repository":{"id":19254055,"uuid":"22489721","full_name":"zephyrtronium/crazy","owner":"zephyrtronium","description":"Interfaces and implementations for sources of randomness and pseudo-randomness","archived":false,"fork":false,"pushed_at":"2019-12-12T03:10:30.000Z","size":136,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-18T15:49:34.469Z","etag":null,"topics":["go","lfg","mersenne-twister","prng","rand","xoroshiro","xoshiro"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"zlib","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zephyrtronium.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-08-01T00:10:40.000Z","updated_at":"2023-01-20T04:58:56.000Z","dependencies_parsed_at":"2022-08-01T04:37:58.932Z","dependency_job_id":null,"html_url":"https://github.com/zephyrtronium/crazy","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/zephyrtronium/crazy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zephyrtronium%2Fcrazy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zephyrtronium%2Fcrazy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zephyrtronium%2Fcrazy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zephyrtronium%2Fcrazy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zephyrtronium","download_url":"https://codeload.github.com/zephyrtronium/crazy/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zephyrtronium%2Fcrazy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28578952,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-19T17:42:58.221Z","status":"ssl_error","status_checked_at":"2026-01-19T17:40:54.158Z","response_time":67,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["go","lfg","mersenne-twister","prng","rand","xoroshiro","xoshiro"],"created_at":"2026-01-19T18:03:28.412Z","updated_at":"2026-01-19T18:03:29.163Z","avatar_url":"https://github.com/zephyrtronium.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# crazy\n\nPackage crazy provides interfaces and implementations for sources of randomness\nand pseudo-randomness.\n\nCrazy rejects certain basic assumptions taken by math/rand, including:\n\n- Randomness does not necessarily produce numbers. Rather than returning\n  (u)int64s, crazy's Source is identical to io.Reader. (Crazy's sources\n  also implement rand.Source64, though.)\n- Not all randomness sources can be seeded. In particular, crypto/rand is a\n  Source but not a Seeder.\n- Sometimes people want to save and restore exact PRNG states. A Saver has\n  this capability.\n\nCurrently implemented PRNGs are LFG(273, 607), MT64-19937, xoroshiro128+\na modification of xoroshiro128+ that rearranges the output bytes, and\nxoshiro256*​*. crypto/rand.Reader naturally implements Source.\n\nThe only currently implemented distributions are normal and exponential, but\nthe ziggurat directory contains a Python script to calculate the necessary\nparameters for any monotonically decreasing distribution.\n\n## Which PRNG?\n\nAs mentioned above, crazy includes a variety of different generators. For most\napplications, xoshiro256** is the best generator because it is very fast, very\nsmall, and has excellent output stream properties. However, there are some\nsituations where the others may be better:\n\n- MT64-19937 has the property of 623-equidistribution, meaning that every tuple\n\tof 623 values appears in the output sequence, except the all-zero tuple.\n\tThis property makes it well-suited to applications requiring uniformity in\n\tmany dimensions, like random walks over a highly connected graph. It is,\n\thowever, the slowest generator implemented in crazy.\n- LFG(273, 607) is fast with reasonable quality. It is the same generator as\n\tthe one used in the standard library, but it travels in the opposite\n\tdirection and uses a different seeding algorithm. LFG may be suitable for\n\tmoderately dimensional MCMC, where MT64's slow speed doesn't outweigh its\n\tsuperior distribution and huge period, but xoshiro's 4-dimensional\n\tequidistribution is still insufficient.\n- xoroshiro128+ has the lowest dimension of PRNGs in crazy, but it is also the\n\tfastest. For tasks where speed is the only significant factor, and the low\n\tlinear complexity in the low bits of its output stream is acceptable,\n\txoroshiro is a good fit.\n\n## Benchmarks\n\nCrazy includes benchmarks for each generator to fill blocks of various sizes.\nThese benchmarks are named following the convention of BenchmarkGenerator/S,\nwhere Generator is LFG, MT64, Xoroshiro, or Rexoroshiro; and S is 8, K, M, or G\nto benchmark filling blocks of size 8 B, 1 kB, 32 MB, or 1 GB, respectively.\nGenerally, the G tests give the best indication of average performance, M tests\nare for consideration of those who don't want to lose a gigabyte of memory, and\nK tests give an indication of performance when paging is mitigated. (The state\nsize of LFG(273, 607) is itself larger than the typical page size for x86/64,\nso it may appear slower than usual relative to the others in K tests.) 8 tests\nindicate the speed of generating individual values at a time, but this is not\nrecommended if avoidable.\n\nAn example of running benchmarks might look like:\n\n```\n\u003e go test -short -bench /[KG] -benchtime 10s -timeout 1h\ngoos: windows\ngoarch: amd64\npkg: github.com/zephyrtronium/crazy\nBenchmarkLFG/K-8                50000000               242 ns/op        4228.04 MB/s\nBenchmarkLFG/G-8                      50         247917030 ns/op        4331.05 MB/s\nBenchmarkMT64/K-8               30000000               586 ns/op        1745.66 MB/s\nBenchmarkMT64/G-8                     20         603785375 ns/op        1778.35 MB/s\nBenchmarkXoroshiro/K-8          100000000              199 ns/op        5128.92 MB/s\nBenchmarkXoroshiro/G-8               100         203835315 ns/op        5267.69 MB/s\nBenchmarkRexoroshiro/K-8        100000000              216 ns/op        4736.30 MB/s\nBenchmarkRexoroshiro/G-8             100         219902115 ns/op        4882.82 MB/s\nBenchmarkXoshiro/K-8            50000000               256 ns/op        3997.27 MB/s\nBenchmarkXoshiro/G-8                  50         282325022 ns/op        3803.21 MB/s\nPASS\nok      github.com/zephyrtronium/crazy  176.454s\n```\n\nIn these results, the ns/op measures the time spent to fill an entire 1K or 1G\nblock, not just to generate a single value). The MB/s throughput is generally a\nbetter indicator of performance. When benchmarking for yourself, use the\n`-benchtime` argument to `go test` in order to measure generation of more values.\n\nNote that `-short` is passed to `go test` as well. Some tests concerned with\nallowed ranges of Distributions and RNGs generate several hundred million MT64\nvalues. The `-short` flag tells them to generate closer to one million values\ninstead.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzephyrtronium%2Fcrazy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzephyrtronium%2Fcrazy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzephyrtronium%2Fcrazy/lists"}