{"id":20785878,"url":"https://github.com/boostibot/game_of_life","last_synced_at":"2026-04-25T01:31:54.346Z","repository":{"id":160117559,"uuid":"634692377","full_name":"Boostibot/game_of_life","owner":"Boostibot","description":null,"archived":false,"fork":false,"pushed_at":"2023-09-15T13:05:57.000Z","size":907,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-18T09:52:22.856Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Boostibot.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-30T23:40:06.000Z","updated_at":"2024-09-02T00:10:09.000Z","dependencies_parsed_at":null,"dependency_job_id":"bf770e6c-672f-473c-b90f-67d87005b44b","html_url":"https://github.com/Boostibot/game_of_life","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/Boostibot%2Fgame_of_life","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Boostibot%2Fgame_of_life/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Boostibot%2Fgame_of_life/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Boostibot%2Fgame_of_life/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Boostibot","download_url":"https://codeload.github.com/Boostibot/game_of_life/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243129323,"owners_count":20240985,"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":[],"created_at":"2024-11-17T14:48:30.813Z","updated_at":"2025-12-26T02:11:16.344Z","avatar_url":"https://github.com/Boostibot.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# game_of_life\n\n *A proof of concept of performant Game of Life implementation.*\n\n We represent cells as single bits and use clever bit shifts to effectlively achieve \n 21 wide parallelism within a single u64 number. This is more or less improvised version of SIMD.\n (in the old days of programming this was more common thing to do).\n We try to operate on as many bits as possible simultanously. How much is that? \n We will answer indirectly. How many bits do we need to represent the entire GOL algorhitm? \n (yes specifically GOL and NOT *any* automata of certain kind). \n \n It seems we need 4. We need to sum all adjecent pixels and then do simple comparison of \n the final value to determin if the cell lives. We need 4 bits because the maximum sum can be 8 (0b1000). \n However if we discard all values higher than 7 as those will result in dead cell anyway we need just 3!\n (we apply some clever masking to achieve this, even if a bit tricky its fairly straigtforward).\n\n Okay so we need 3 bits to do the calculation. Now how does the actual algorhitm work. Lets explain this with a pictures.\n We are trying to determine if the middle cell lives or dies. \n ```\n 0   1   0\n   -----\n 1 | 1 | 1\n   -----\n 0   0   1\n ```\n To do this we first sum along each rows separately: \n ```\n 0 + 1 + 0 = 1\n   -----\n 1 + 1 + 1 = 3\n   -----\n 0 + 0 + 1 = 1\n ```\n This can be achived fairly easily in binary by the following piece of code\n where oct is a pattern of bits spaced 3 appart.\n ```c\n  u64 row = /* bits in a single row of our bitmap chunk*/;\n\tu64 oct = 01111111111111111111111; //..1001001 in binary\n\tu64 sum_every_3_bits = (oct \u0026 (row \u003e\u003e 0));\n\t\t+ (oct \u0026 (row \u003e\u003e 1));\n\t\t+ (oct \u0026 (row \u003e\u003e 2));\n ```\n Now all thats left to do is to sum vertically. Here however we need to be careful since we cannot sum all 3 rows due to overflow \n out of our 3 bits. So instead we only sum the first two and then dermine if the next addition would overflow. \n We then use this to detrmine if the cell is \"overfull\" that is if the sum is a number which kills the cell no matter the circumstance.\n\n We then test if the bit patterns exactly match certain values (this can be done in effect with the following):\n ```c\n  u64 pattern = /* bit pattern of 5 repeating */\n  u64 row = /* bits in a single row of our bitmap chunk*/;\n  u64 xored = pattern ^ row; //if are equl their XOR is everywhere 0\n  u64 are_every_3_bits_not_equal_to_5 = (oct \u0026 (xored \u003e\u003e 0));\n\t\t| (oct \u0026 (xored \u003e\u003e 1));\n\t\t| (oct \u0026 (xored \u003e\u003e 2));\n\n /* now are_every_3_bits_not_equal_to_5 contains a set bit at the lowest adress in each oct (bit triplet) */\n ```\n Then we can test for equality simply like so:\n ```c\n  u64 are_every_3_bits_equal_to_5 = ~are_every_3_bits_not_equal_to_5;\n ```\n Then we simply compose the necessary tests together using bitwise OR, AND and NEG and we recieved every 3rd bit of the output!\n We repeat this exact same procedure except with everything shifted down a bit to recieve every 3rd bit in the second set of the output.\n then finally the thir as well. We or these together and this yields the final value.\n \n This might look daunting (and indeed its painful to debug) but with a bit of patience its not that diffuclt to trial and error into.\n\n This approach is ~200x fatster than naive implementation using serial ifs, and about ~20x faster than branchless version. It can further be sped up about 4x\n by using 256 bit SIMD registers and doing essentially the same thing wider (or the exact same thing on every 1st 4th 8th 12th row simulatneously). \n I was however lazy to implement this as this was fast enough for my need as the current bottle neck is rendering and then hash map lookup.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboostibot%2Fgame_of_life","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fboostibot%2Fgame_of_life","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboostibot%2Fgame_of_life/lists"}