{"id":19149220,"url":"https://github.com/hoshimin/ranger","last_synced_at":"2025-04-14T17:07:17.035Z","repository":{"id":189601383,"uuid":"680940851","full_name":"HoShiMin/Ranger","owner":"HoShiMin","description":"Fast sparsed range intersection","archived":false,"fork":false,"pushed_at":"2023-08-21T22:09:51.000Z","size":23,"stargazers_count":2,"open_issues_count":0,"forks_count":2,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-14T17:07:07.509Z","etag":null,"topics":["algorithm","algorithms","header-only","intersect","intersection","range","sparse"],"latest_commit_sha":null,"homepage":"","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/HoShiMin.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-08-20T22:25:51.000Z","updated_at":"2024-12-27T13:07:41.000Z","dependencies_parsed_at":"2025-01-03T17:50:33.452Z","dependency_job_id":null,"html_url":"https://github.com/HoShiMin/Ranger","commit_stats":null,"previous_names":["hoshimin/ranger"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HoShiMin%2FRanger","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HoShiMin%2FRanger/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HoShiMin%2FRanger/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HoShiMin%2FRanger/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/HoShiMin","download_url":"https://codeload.github.com/HoShiMin/Ranger/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248923765,"owners_count":21183953,"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":["algorithm","algorithms","header-only","intersect","intersection","range","sparse"],"created_at":"2024-11-09T08:07:15.016Z","updated_at":"2025-04-14T17:07:17.011Z","avatar_url":"https://github.com/HoShiMin.png","language":"C++","readme":"# 📐 Ranger\n## The sparsed range intersector.\nA sparsed range is a bitmap that describes several ranges using two values: `Base` and `Mask`.  \n`Base` is a set of ones and zeroes, and `Mask` is a bitmap of meaningful bits in the base.  \nIf a bit in the mask is 0 - the corresponding bit at the same position is treated as \"any bit\", and if the bit is 1, it means the the corresponding bit must be the same as in the base at the same position.\n\nExample:\n```\n0110'0100 Base\n0111'1100 Mask\n--------------\n?110'01?? Range\n\n'?' may be any bit.\n```\n\n### One shot check.\nWe can check whether an arbitrary value intersects the range using this function:\n```cpp\nbool intersects(auto base, auto mask, auto value)\n{\n    return (value \u0026 mask) == (base \u0026 mask);\n}\n```\n\nThe function above ensures that all meaningful bits of the range are the same in the given value:\n```\n?110'01?? Range\n^      ^^\nMay be either 0 or 1 in any combination.\n\nSample values:\n1110'0100 Matches\n0110'0111 Matches too\n^      ^^\nThese bits are ignored.\n\n0010'0111 Doesn't match!\n ^\n This bit must be 1 as it's a meaningful bit\n and must be the same as in the range.\n```\n\n### Range check.\nLet's complicate the task. Now we need to check not a single value, but a range of values `[Begin..End]`, and we must check this in a performant manner.\n\nThis project presents the following algorithm:\n\n0. Suppose we have these initial conditions:\n    ```\n    0010'0000 Base\n    1010'0100 Mask\n    --------------\n    0?1?'?0?? Range\n\n    1000'1101 Begin\n    1010'0001 End\n\n    Whether any value in the [Begin..End] belongs to the given range?\n    ```\n1. Determine the volatile bits of the `[Begin..End]`:\n    ```\n    1000'1101 Begin\n    1010'0001 End\n    10xx'xxxx\n      -------\n       Volatile bits\n    ```\n2. Drop the volatile bits and check the constant part only:\n    ```\n    ?0|1?'?0??\n    10|xx'xxxx The constant part from the previous step\n    ^^\n    Check the constant part only.\n    ```\n    If the constant part doesn't match, the whole range is apriory mismatched and there is no point in continuing.  \n    Otherwise go to the next step.\n3. Trim the constant part as it was already checked and we don't need to check it anymore:\n    ```\n    00|1?'?0?? Range\n    00|00'1101 Begin\n    00|10'0001 End\n    ^^\n    Reset the constant part.\n    ```\n4. So, we have these ranges:\n   ```\n   1?'?0?? Range\n\n   00'1101 Begin\n   10'0001 End\n   ```\n   In the next steps we will work with the range only.  \n   We should find such combination of bits instead of \"?\" so that the resulting value falls into the `[Begin..End]` if possible.  \n   \n   We will use the following strategy:\n\n   1. Select the highest \"any-bit\" (marked as \"?\") and set it to 1 and reset all lower any-bits:\n        ```\n        1?'?0?? -\u003e 11'0000\n         ^ ^ ^^\n         1 0 00\n        ```\n        We've got the probe value.\n   2. We need to understand where the probe value is in relation to the range.  \n        It can be in three places:  \n        - To the left of the `Begin`. In this case we can increase the value more by setting lower \"any-bits\" to ones. Fix the highest \"any-bit\" as one and repeat all these steps for the next \"any-bit\".\n        - To the right of the `End`. In this case we can't lower the probe value by the lower \"any-bits\" as they're already zeroes. It means that the only case is to reset the highest \"any-bit\" to zero, set the lower \"any-bits\" to ones and try again:\n            ```\n            1?'?0?? -\u003e 10'1011\n             ^ ^ ^^\n             0 1 11\n            ```\n            Repeat comparation with this probe value. If it will be lower than the `Begin` - it is impossible to increase it more and it means that ranges don't intersect. Otherwise fix the highest \"any-bit\" as zero and repeat allthese steps for the next \"any-bit\".\n        - Inside the `[Begin..End]` - in this case we can end our search as at least one value from the `[Begin..End]`falls withing the sparsed range.\n      \n\n      \n\nAll these steps are implemented in this library.\n\n### Usage:\nJust include the `include/Ranger/Ranger.hpp` and you're good to go!\n```cpp\n#include \u003cRanger/Ranger.hpp\u003e\n#include \u003ccassert\u003e\n\nint main()\n{\n    // Create the sparsed range:\n    auto range = Ranger::BitRange\u003cuint8_t\u003e::make(\"011?'??10\");\n    assert(range.intersects(0b01101010));\n    assert(range.intersects(0b01110110));\n\n    //\n    // [0010'0000..1000'0000]\n    //    Begin       End\n    //\n    assert(range.intersects(0b00100000, 0b10000000));\n    \n    // Set the base and the mask manually:\n    range.setBase(0b0110'1000);\n    range.setMask(0b0111'1100);\n\n    // Format the sparsed range to the string:\n    char formattedRange[sizeof(\"xxxxxxxx\")]{};\n    range.format(formattedRange);\n    assert(strcmp(formattedRange, \"?11010??\") == 0);\n\n    return 0;\n}\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoshimin%2Franger","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhoshimin%2Franger","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoshimin%2Franger/lists"}