{"action":"created","comment":{"url":"https://api.github.com/repos/SFTtech/openage/pulls/comments/22865982","id":22865982,"diff_hunk":"@@ -0,0 +1,203 @@\n+// Copyright 2015-2015 the openage authors. See copying.md for legal info.\n+#include \"rng.h\"\n+#include \"../util/error.h\"\n+#include \"../log.h\"\n+\n+#include <chrono>\n+#include <random>\n+#include <sstream>\n+#include <string.h>\n+\n+namespace openage {\n+namespace rng {\n+\n+rng::rng(uint64_t v1) {\n+\tthis->seed(v1);\n+}\n+\n+rng::rng(const void *data, size_t len) {\n+\tthis->seed(data, len);\n+}\n+\n+rng::rng(const std::string &instr) {\n+\tthis->from_string(instr);\n+}\n+\n+rng::rng(std::istream &instream) {\n+\tthis->from_stream(instream);\n+}\n+\n+void rng::seed(uint64_t val) {\n+\tthis->seed(&val, sizeof(val));\n+}\n+\n+//murmurhash3 bit avalancher - output is uniformly distributed\n+//and changing one bit of input results in ~1/2 of output bits changed\n+//This function is a good way of mixing up an input,\n+//or mixing together two results with hash64(val1 ^ val2)\n+static uint64_t hash64(uint64_t val) {\n+\tval ^= val >> 33;\n+\tval *= 0xff51afd7ed558ccd;\n+\tval ^= val >> 33;\n+\tval *= 0xc4ceb9fe1a85ec53;\n+\treturn val ^ (val >> 33);\n+}\n+\n+//translates a char* into a uint64_t\n+static inline uint64_t from_cptr(const char* data) {\n+\treturn *reinterpret_cast<const uint64_t *>(data);\n+}\n+\n+//!hashes an initial seed into the base state\n+static void init_hash(uint64_t *state, uint64_t seed) {\n+\t//Mix the initial seed into data for each state value\n+\tstate[0] = hash64(seed);\n+\tstate[1] = hash64(seed ^ state[0]);\n+}\n+\n+//For each 8-byte block after the initial seed,\n+//mix it with state[0] and set state[0] equal to the result.\n+//Then, set state[1] to the mixture of state[1] and state[0]\n+//This lets each bit from the input play a role in the output\n+//w/o requiring that the size be a multiple of 8 or having extra\n+//code for the non multiple-of-8 sections\n+static void hash_bytes(uint64_t *state, const char *data, size_t count) {\n+\tfor(size_t i = 1; i <= count; i++) {\n+\t\tstate[0] = hash64(state[0] ^ from_cptr(data+i));\n+\t\tstate[1] = hash64(state[0] ^ state[1]);\n+\t}\n+}\n+\n+void rng::seed(const void *dat, size_t count) {\n+\tif(count == 0) {\n+\t\tthrow util::Error(\"0 bytes supplied as seed data\");\n+\t}\n+\n+\tconstexpr uint64_t default_seed = 0x0123456789abcdef;\n+\tconstexpr size_t uint64_s = sizeof(uint64_t);\n+\tconst char *data = static_cast<const char *>(dat);\n+\n+\tif(count > uint64_s) {\n+\t\tinit_hash(state, from_cptr(data));\n+\t\thash_bytes(state, data, count - uint64_s);\n+\t}\n+\telse {\n+\t\tuint64_t init_seed = 0;\n+\t\tmemcpy(&init_seed, data, count);\n+\t\tinit_hash(state, init_seed);\n+\t}\n+\n+\tif(!(state[0] || state[1])) {\n+\t\tstate[0] = default_seed;\n+\t}\n+\n+\t//This helps prevent low-zero states caused by a bad seed\n+\tthis->discard(discard_on_seed);\n+}\n+\n+//http://en.wikipedia.org/wiki/Xorshift\n+//!actually does the number crunching and state updates\n+static inline uint64_t do_rng(uint64_t &s0, uint64_t &s1) {\n+\ts1 ^= s1 << 23;\n+\ts1 = (s1 ^ s0 ^ (s1 >> 17) ^ (s0 >> 26));\n+\treturn s1 + s0;\n+}\n+\n+uint64_t rng::random() {\n+\tstd::swap(this->state[0], this->state[1]);\n+\treturn do_rng(this->state[0], this->state[1]);\n+}\n+\n+//This provides serious optimizations over the standard generator by\n+//eliminating memory writes and data dependencies\n+template<class T, class Lambda>\n+static inline void act_fill(T *dat, uint64_t *state, size_t len, const Lambda &op){\n+\n+\tuint64_t s0 = state[0];\n+\tuint64_t s1 = state[1];\n+\tsize_t ev_len = len - (len & 1);\n+\t\n+\tfor(size_t i = 0; i < ev_len; i += 2) {\n+\t\top(do_rng(s1, s0), dat, i);\n+\t\top(do_rng(s0, s1), dat, i + 1);\n+\t}\n+\tif(len & 1) {\n+\t\top(do_rng(s1, s0), dat, len-1);\n+\t\tstd::swap(s1, s0);\n+\t}\n+\tstate[0] = s0;\n+\tstate[1] = s1;\n+}\n+\n+void rng::fill(uint64_t *dat, size_t len) {\n+\tact_fill(dat, this->state, len, [](uint64_t v, uint64_t *d, size_t i) {d[i] = v;});\n+}\n+\n+void rng::discard(size_t len) {\n+\tact_fill<uint64_t>(nullptr, this->state, len, [](uint64_t, uint64_t *, size_t) {});\n+}\n+\n+void rng::fill_real(double *dat, size_t len) {\n+\tact_fill(dat, this->state, len, [](double v, double *d, size_t i) {\n+\t\t\td[i] = v / rng::max();\n+\t\t});\n+}\n+\n+std::ostream &rng::to_stream(std::ostream &out) const {\n+\tif((out << this->state[0] << \" \").good() &&\n+\t   !(out << this->state[1]).fail()) {","path":"cpp/rng/rng.cpp","position":148,"original_position":148,"commit_id":"e589b4e850d462f649ee925d45156633178beb0c","original_commit_id":"e589b4e850d462f649ee925d45156633178beb0c","user":{"login":"fr3akout","id":556394,"avatar_url":"https://avatars.githubusercontent.com/u/556394?v=3","gravatar_id":"","url":"https://api.github.com/users/fr3akout","html_url":"https://github.com/fr3akout","followers_url":"https://api.github.com/users/fr3akout/followers","following_url":"https://api.github.com/users/fr3akout/following{/other_user}","gists_url":"https://api.github.com/users/fr3akout/gists{/gist_id}","starred_url":"https://api.github.com/users/fr3akout/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fr3akout/subscriptions","organizations_url":"https://api.github.com/users/fr3akout/orgs","repos_url":"https://api.github.com/users/fr3akout/repos","events_url":"https://api.github.com/users/fr3akout/events{/privacy}","received_events_url":"https://api.github.com/users/fr3akout/received_events","type":"User","site_admin":false},"body":"Why are you using !(...).fail() instead of good()?","created_at":"2015-01-13T14:51:26Z","updated_at":"2015-01-13T14:51:26Z","html_url":"https://github.com/SFTtech/openage/pull/191#discussion_r22865982","pull_request_url":"https://api.github.com/repos/SFTtech/openage/pulls/191","_links":{"self":{"href":"https://api.github.com/repos/SFTtech/openage/pulls/comments/22865982"},"html":{"href":"https://github.com/SFTtech/openage/pull/191#discussion_r22865982"},"pull_request":{"href":"https://api.github.com/repos/SFTtech/openage/pulls/191"}}},"pull_request":{"url":"https://api.github.com/repos/SFTtech/openage/pulls/191","id":27155826,"html_url":"https://github.com/SFTtech/openage/pull/191","diff_url":"https://github.com/SFTtech/openage/pull/191.diff","patch_url":"https://github.com/SFTtech/openage/pull/191.patch","issue_url":"https://api.github.com/repos/SFTtech/openage/issues/191","number":191,"state":"open","locked":false,"title":"This is a simple to use and efficient rng.","user":{"login":"schets","id":3722633,"avatar_url":"https://avatars.githubusercontent.com/u/3722633?v=3","gravatar_id":"","url":"https://api.github.com/users/schets","html_url":"https://github.com/schets","followers_url":"https://api.github.com/users/schets/followers","following_url":"https://api.github.com/users/schets/following{/other_user}","gists_url":"https://api.github.com/users/schets/gists{/gist_id}","starred_url":"https://api.github.com/users/schets/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/schets/subscriptions","organizations_url":"https://api.github.com/users/schets/orgs","repos_url":"https://api.github.com/users/schets/repos","events_url":"https://api.github.com/users/schets/events{/privacy}","received_events_url":"https://api.github.com/users/schets/received_events","type":"User","site_admin":false},"body":"It provides an easy and reliable way of reproducible random numbers,\r\nalong with platform-independent serialization. There is also a thread-safe global rng, although it makes no promises about the order in which requests will be processed.","created_at":"2015-01-10T22:52:11Z","updated_at":"2015-01-13T14:51:26Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2d583e9daa1087462900fc7f62ce4876efb2235a","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/SFTtech/openage/pulls/191/commits","review_comments_url":"https://api.github.com/repos/SFTtech/openage/pulls/191/comments","review_comment_url":"https://api.github.com/repos/SFTtech/openage/pulls/comments/{number}","comments_url":"https://api.github.com/repos/SFTtech/openage/issues/191/comments","statuses_url":"https://api.github.com/repos/SFTtech/openage/statuses/e589b4e850d462f649ee925d45156633178beb0c","head":{"label":"schets:simple-rng","ref":"simple-rng","sha":"e589b4e850d462f649ee925d45156633178beb0c","user":{"login":"schets","id":3722633,"avatar_url":"https://avatars.githubusercontent.com/u/3722633?v=3","gravatar_id":"","url":"https://api.github.com/users/schets","html_url":"https://github.com/schets","followers_url":"https://api.github.com/users/schets/followers","following_url":"https://api.github.com/users/schets/following{/other_user}","gists_url":"https://api.github.com/users/schets/gists{/gist_id}","starred_url":"https://api.github.com/users/schets/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/schets/subscriptions","organizations_url":"https://api.github.com/users/schets/orgs","repos_url":"https://api.github.com/users/schets/repos","events_url":"https://api.github.com/users/schets/events{/privacy}","received_events_url":"https://api.github.com/users/schets/received_events","type":"User","site_admin":false},"repo":{"id":26276665,"name":"openage","full_name":"schets/openage","owner":{"login":"schets","id":3722633,"avatar_url":"https://avatars.githubusercontent.com/u/3722633?v=3","gravatar_id":"","url":"https://api.github.com/users/schets","html_url":"https://github.com/schets","followers_url":"https://api.github.com/users/schets/followers","following_url":"https://api.github.com/users/schets/following{/other_user}","gists_url":"https://api.github.com/users/schets/gists{/gist_id}","starred_url":"https://api.github.com/users/schets/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/schets/subscriptions","organizations_url":"https://api.github.com/users/schets/orgs","repos_url":"https://api.github.com/users/schets/repos","events_url":"https://api.github.com/users/schets/events{/privacy}","received_events_url":"https://api.github.com/users/schets/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/schets/openage","description":"Free (as in freedom) open source clone of the Age of Empires II engine.","fork":true,"url":"https://api.github.com/repos/schets/openage","forks_url":"https://api.github.com/repos/schets/openage/forks","keys_url":"https://api.github.com/repos/schets/openage/keys{/key_id}","collaborators_url":"https://api.github.com/repos/schets/openage/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/schets/openage/teams","hooks_url":"https://api.github.com/repos/schets/openage/hooks","issue_events_url":"https://api.github.com/repos/schets/openage/issues/events{/number}","events_url":"https://api.github.com/repos/schets/openage/events","assignees_url":"https://api.github.com/repos/schets/openage/assignees{/user}","branches_url":"https://api.github.com/repos/schets/openage/branches{/branch}","tags_url":"https://api.github.com/repos/schets/openage/tags","blobs_url":"https://api.github.com/repos/schets/openage/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/schets/openage/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/schets/openage/git/refs{/sha}","trees_url":"https://api.github.com/repos/schets/openage/git/trees{/sha}","statuses_url":"https://api.github.com/repos/schets/openage/statuses/{sha}","languages_url":"https://api.github.com/repos/schets/openage/languages","stargazers_url":"https://api.github.com/repos/schets/openage/stargazers","contributors_url":"https://api.github.com/repos/schets/openage/contributors","subscribers_url":"https://api.github.com/repos/schets/openage/subscribers","subscription_url":"https://api.github.com/repos/schets/openage/subscription","commits_url":"https://api.github.com/repos/schets/openage/commits{/sha}","git_commits_url":"https://api.github.com/repos/schets/openage/git/commits{/sha}","comments_url":"https://api.github.com/repos/schets/openage/comments{/number}","issue_comment_url":"https://api.github.com/repos/schets/openage/issues/comments/{number}","contents_url":"https://api.github.com/repos/schets/openage/contents/{+path}","compare_url":"https://api.github.com/repos/schets/openage/compare/{base}...{head}","merges_url":"https://api.github.com/repos/schets/openage/merges","archive_url":"https://api.github.com/repos/schets/openage/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/schets/openage/downloads","issues_url":"https://api.github.com/repos/schets/openage/issues{/number}","pulls_url":"https://api.github.com/repos/schets/openage/pulls{/number}","milestones_url":"https://api.github.com/repos/schets/openage/milestones{/number}","notifications_url":"https://api.github.com/repos/schets/openage/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/schets/openage/labels{/name}","releases_url":"https://api.github.com/repos/schets/openage/releases{/id}","created_at":"2014-11-06T15:39:05Z","updated_at":"2015-01-03T05:55:06Z","pushed_at":"2015-01-12T17:28:44Z","git_url":"git://github.com/schets/openage.git","ssh_url":"git@github.com:schets/openage.git","clone_url":"https://github.com/schets/openage.git","svn_url":"https://github.com/schets/openage","homepage":"http://openage.sft.mx","size":4727,"stargazers_count":1,"watchers_count":1,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":1,"default_branch":"master"}},"base":{"label":"SFTtech:master","ref":"master","sha":"79ee27a8cce40e513c437bbabc8a7f71b010cfe5","user":{"login":"SFTtech","id":1783325,"avatar_url":"https://avatars.githubusercontent.com/u/1783325?v=3","gravatar_id":"","url":"https://api.github.com/users/SFTtech","html_url":"https://github.com/SFTtech","followers_url":"https://api.github.com/users/SFTtech/followers","following_url":"https://api.github.com/users/SFTtech/following{/other_user}","gists_url":"https://api.github.com/users/SFTtech/gists{/gist_id}","starred_url":"https://api.github.com/users/SFTtech/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SFTtech/subscriptions","organizations_url":"https://api.github.com/users/SFTtech/orgs","repos_url":"https://api.github.com/users/SFTtech/repos","events_url":"https://api.github.com/users/SFTtech/events{/privacy}","received_events_url":"https://api.github.com/users/SFTtech/received_events","type":"Organization","site_admin":false},"repo":{"id":14095175,"name":"openage","full_name":"SFTtech/openage","owner":{"login":"SFTtech","id":1783325,"avatar_url":"https://avatars.githubusercontent.com/u/1783325?v=3","gravatar_id":"","url":"https://api.github.com/users/SFTtech","html_url":"https://github.com/SFTtech","followers_url":"https://api.github.com/users/SFTtech/followers","following_url":"https://api.github.com/users/SFTtech/following{/other_user}","gists_url":"https://api.github.com/users/SFTtech/gists{/gist_id}","starred_url":"https://api.github.com/users/SFTtech/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SFTtech/subscriptions","organizations_url":"https://api.github.com/users/SFTtech/orgs","repos_url":"https://api.github.com/users/SFTtech/repos","events_url":"https://api.github.com/users/SFTtech/events{/privacy}","received_events_url":"https://api.github.com/users/SFTtech/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/SFTtech/openage","description":"Free (as in freedom) open source clone of the Age of Empires II engine.","fork":false,"url":"https://api.github.com/repos/SFTtech/openage","forks_url":"https://api.github.com/repos/SFTtech/openage/forks","keys_url":"https://api.github.com/repos/SFTtech/openage/keys{/key_id}","collaborators_url":"https://api.github.com/repos/SFTtech/openage/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/SFTtech/openage/teams","hooks_url":"https://api.github.com/repos/SFTtech/openage/hooks","issue_events_url":"https://api.github.com/repos/SFTtech/openage/issues/events{/number}","events_url":"https://api.github.com/repos/SFTtech/openage/events","assignees_url":"https://api.github.com/repos/SFTtech/openage/assignees{/user}","branches_url":"https://api.github.com/repos/SFTtech/openage/branches{/branch}","tags_url":"https://api.github.com/repos/SFTtech/openage/tags","blobs_url":"https://api.github.com/repos/SFTtech/openage/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/SFTtech/openage/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/SFTtech/openage/git/refs{/sha}","trees_url":"https://api.github.com/repos/SFTtech/openage/git/trees{/sha}","statuses_url":"https://api.github.com/repos/SFTtech/openage/statuses/{sha}","languages_url":"https://api.github.com/repos/SFTtech/openage/languages","stargazers_url":"https://api.github.com/repos/SFTtech/openage/stargazers","contributors_url":"https://api.github.com/repos/SFTtech/openage/contributors","subscribers_url":"https://api.github.com/repos/SFTtech/openage/subscribers","subscription_url":"https://api.github.com/repos/SFTtech/openage/subscription","commits_url":"https://api.github.com/repos/SFTtech/openage/commits{/sha}","git_commits_url":"https://api.github.com/repos/SFTtech/openage/git/commits{/sha}","comments_url":"https://api.github.com/repos/SFTtech/openage/comments{/number}","issue_comment_url":"https://api.github.com/repos/SFTtech/openage/issues/comments/{number}","contents_url":"https://api.github.com/repos/SFTtech/openage/contents/{+path}","compare_url":"https://api.github.com/repos/SFTtech/openage/compare/{base}...{head}","merges_url":"https://api.github.com/repos/SFTtech/openage/merges","archive_url":"https://api.github.com/repos/SFTtech/openage/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/SFTtech/openage/downloads","issues_url":"https://api.github.com/repos/SFTtech/openage/issues{/number}","pulls_url":"https://api.github.com/repos/SFTtech/openage/pulls{/number}","milestones_url":"https://api.github.com/repos/SFTtech/openage/milestones{/number}","notifications_url":"https://api.github.com/repos/SFTtech/openage/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/SFTtech/openage/labels{/name}","releases_url":"https://api.github.com/repos/SFTtech/openage/releases{/id}","created_at":"2013-11-03T22:35:23Z","updated_at":"2015-01-12T02:27:36Z","pushed_at":"2015-01-04T21:55:36Z","git_url":"git://github.com/SFTtech/openage.git","ssh_url":"git@github.com:SFTtech/openage.git","clone_url":"https://github.com/SFTtech/openage.git","svn_url":"https://github.com/SFTtech/openage","homepage":"http://openage.sft.mx","size":6595,"stargazers_count":2826,"watchers_count":2826,"language":"C++","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":232,"mirror_url":null,"open_issues_count":53,"forks":232,"open_issues":53,"watchers":2826,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/SFTtech/openage/pulls/191"},"html":{"href":"https://github.com/SFTtech/openage/pull/191"},"issue":{"href":"https://api.github.com/repos/SFTtech/openage/issues/191"},"comments":{"href":"https://api.github.com/repos/SFTtech/openage/issues/191/comments"},"review_comments":{"href":"https://api.github.com/repos/SFTtech/openage/pulls/191/comments"},"review_comment":{"href":"https://api.github.com/repos/SFTtech/openage/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/SFTtech/openage/pulls/191/commits"},"statuses":{"href":"https://api.github.com/repos/SFTtech/openage/statuses/e589b4e850d462f649ee925d45156633178beb0c"}}}}