{"action":"created","comment":{"url":"https://api.github.com/repos/SFTtech/openage/pulls/comments/22772910","id":22772910,"diff_hunk":"@@ -0,0 +1,171 @@\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 <cstdlib>\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, uint32_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\n+//seeds must be hashed since they may be poorly distributed\n+//and may have high zero content initially\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+static void hash_seed_from_blob(const void *dat, uint64_t *state, int64_t bytes) {\n+\tconst char *data = static_cast<const char *>(dat);\n+\tuint64_t uint64 = 0;\n+\tmemcpy(&uint64, data, bytes <= 8 ? bytes : 8);\n+\tstate[0] = hash64(uint64);\n+\tstate[1] = hash64(uint64 ^ state[0]);\n+\tfor(int64_t i = 1; i <= bytes - 8; i++) {\n+\t\tstate[0] = hash64(state[0] ^ *reinterpret_cast<const uint64_t *>(data + i));\n+\t\tstate[1] = hash64(state[0] ^ state[1]);\n+\t}\n+\t\n+\tif(!(state[0] || state[1])) {\n+\t\tstate[0] = 0x0123456789abcdef;\n+\t}\n+}\n+\n+void rng::seed(const void *data, uint32_t bytes) {\n+\tif(bytes == 0) {\n+\t\tthrow util::Error(\"0 bytes supplied as seed data\");\n+\t}\n+\thash_seed_from_blob(data, this->state, bytes);\n+\tthis->discard(discard_on_seed);\n+}\n+\n+//http://en.wikipedia.org/wiki/Xorshift\n+//!actually does the number crunching\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()) {\n+\t\treturn out;\n+\t}\n+\tthrow util::Error(\"Unable to write rng to output stream\");\n+}\n+\n+std::istream &rng::from_stream(std::istream &in) {\n+\tif((in >> this->state[0]).good() &&\n+\t   !(in >> this->state[1]).fail()) {\n+\t\treturn in;\n+\t}\n+\tthrow util::Error(\"Unable to serialize rng from input stream\");\n+}\n+\n+std::string rng::to_string() const {\n+\tstd::stringstream strstr;\n+\treturn (strstr << *this).str();\n+}\n+\n+void rng::from_string(const std::string &instr) {\n+\tstd::stringstream strstr(instr);\n+\tstrstr >> *this;\n+}\n+\n+using namespace std::chrono;\n+static uint64_t do_time_seed(bool do_rand) {\n+\tuint64_t rand1 = 0;\n+\tif(do_rand) {\n+\t\ttry {\n+\t\t\tstd::random_device rnd;\n+\t\t\tif(rnd.entropy() > 0){\n+\t\t\t\trand1 = rnd() + (uint64_t(rnd()) << 32);\n+\t\t\t}\n+\t\t}\n+\t\tcatch (...) {}","path":"cpp/rng/rng.cpp","position":154,"original_position":154,"commit_id":"4f22bb4098b9be09f76f52204f48a2dd7a76fd81","original_commit_id":"4f22bb4098b9be09f76f52204f48a2dd7a76fd81","user":{"login":"TheJJ","id":673543,"avatar_url":"https://avatars.githubusercontent.com/u/673543?v=3","gravatar_id":"","url":"https://api.github.com/users/TheJJ","html_url":"https://github.com/TheJJ","followers_url":"https://api.github.com/users/TheJJ/followers","following_url":"https://api.github.com/users/TheJJ/following{/other_user}","gists_url":"https://api.github.com/users/TheJJ/gists{/gist_id}","starred_url":"https://api.github.com/users/TheJJ/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TheJJ/subscriptions","organizations_url":"https://api.github.com/users/TheJJ/orgs","repos_url":"https://api.github.com/users/TheJJ/repos","events_url":"https://api.github.com/users/TheJJ/events{/privacy}","received_events_url":"https://api.github.com/users/TheJJ/received_events","type":"User","site_admin":false},"body":"what is catched here?","created_at":"2015-01-12T01:24:43Z","updated_at":"2015-01-12T01:24:43Z","html_url":"https://github.com/SFTtech/openage/pull/191#discussion_r22772910","pull_request_url":"https://api.github.com/repos/SFTtech/openage/pulls/191","_links":{"self":{"href":"https://api.github.com/repos/SFTtech/openage/pulls/comments/22772910"},"html":{"href":"https://github.com/SFTtech/openage/pull/191#discussion_r22772910"},"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-12T01:24:43Z","closed_at":null,"merged_at":null,"merge_commit_sha":"70ed3e139925d6fc893c3436ce194bd35a3836ed","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/4f22bb4098b9be09f76f52204f48a2dd7a76fd81","head":{"label":"schets:simple-rng","ref":"simple-rng","sha":"4f22bb4098b9be09f76f52204f48a2dd7a76fd81","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-10T23:04:58Z","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-11T19:14:17Z","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":2827,"watchers_count":2827,"language":"C++","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":233,"mirror_url":null,"open_issues_count":53,"forks":233,"open_issues":53,"watchers":2827,"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/4f22bb4098b9be09f76f52204f48a2dd7a76fd81"}}}}