{"id":13643670,"url":"https://github.com/lemire/fastrange","last_synced_at":"2025-04-09T21:22:17.121Z","repository":{"id":66054854,"uuid":"70909136","full_name":"lemire/fastrange","owner":"lemire","description":"A fast alternative to the modulo reduction","archived":false,"fork":false,"pushed_at":"2021-03-22T20:54:09.000Z","size":21,"stargazers_count":309,"open_issues_count":0,"forks_count":16,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-04-02T19:07:49.851Z","etag":null,"topics":["algorithm","interval","modulo-reduction","range"],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lemire.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}},"created_at":"2016-10-14T12:41:38.000Z","updated_at":"2025-03-15T10:03:06.000Z","dependencies_parsed_at":"2023-05-12T19:31:13.730Z","dependency_job_id":null,"html_url":"https://github.com/lemire/fastrange","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/lemire%2Ffastrange","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lemire%2Ffastrange/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lemire%2Ffastrange/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lemire%2Ffastrange/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lemire","download_url":"https://codeload.github.com/lemire/fastrange/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248112720,"owners_count":21049706,"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","interval","modulo-reduction","range"],"created_at":"2024-08-02T01:01:51.090Z","updated_at":"2025-04-09T21:22:17.101Z","avatar_url":"https://github.com/lemire.png","language":"C","readme":"# fastrange: A fast alternative to the modulo reduction\n\nA common operation in software is to take a machine word\nand map it to an integer value in a range [0,p) as fairly as possible.\nThat is, you want that if all values of the machine word are\nequally likely then, as much as possible, all integer values in\n[0,p) are (almost) equally likely. This is common in hashing and probabilistic\nalgorithms.\n\nIn computing, the modulo operation finds the remainder after division of one number by another (called the modulus of the operation). Given two positive numbers, a and n, a modulo n (abbreviated as a mod n) is the remainder of the Euclidean division of a by n, where a is the dividend and n is the divisor.\n\nThe standard approach to this problem is the modulo reduction (``x % p``).\nThough a modulo reduction works fine and has several nice properties,\nit can be slow even on recent processors because it relies on an\ninteger division.\n\nThankfully, there is a faster way: we can replace the modulo by a multiplication\nfollowed by a shift.\n\n[It has accelerated some operations in Google's Tensorflow by 10% to 20%](https://github.com/tensorflow/tensorflow/commit/a47a300185026fe7829990def9113bf3a5109fed).\n\nFurther reading : http://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/\n\n\nSee also:\n\n* Daniel Lemire, [Fast Random Integer Generation in an Interval](https://arxiv.org/abs/1805.10941), ACM Transactions on Modeling and Computer Simulation, January 2019 Article No. 3 https://doi.org/10.1145/3230636\n\n\nThis library provides a single portable header file that you should\nbe able to just drop in your C/C++ projects. The API is simple:\n\n\n```C\n#include \"fastrange\"\n\n// given a value word, produces an integer in [0,p) without division\nuint32_t fastrange32(uint32_t word, uint32_t p);\nuint64_t fastrange64(uint64_t word, uint64_t p);\nsize_t fastrangesize(size_t word, size_t p);\nint fastrangeint(int word, int p);\n```\n## Pre-conditions\n\nFor this code to give the desired result, the provided words should span the whole range (e.g., all 32-bit integers). The C ``rand`` function does not meet this requirement. If you must use the ``rand``  function, wrap it like so:\n\n```\nuint32_t get32rand() {\n    return (rand() ^ (rand() \u003c\u003c 15) ^ (rand() \u003c\u003c 30));\n}\n\nuint64_t get64rand() {\n    return (((uint64_t)get32rand()) \u003c\u003c 32) | get32rand();\n}\n```\n\n\nHowever, the underlying idea is general: we only require that the word values span an interval of the form ``[0,1\u003c\u003cL)``. It suffices then to do `` ( x * range ) \u003e\u003e L `` to get a fair map from ``[0,1\u003c\u003cL)`` to ``[0,range)``. For example, if your word values span the interval [0,65536), then you could simply do ``( x * range ) \u003e\u003e 16``.\n\n\n## Unbiased range functions\n\nTo generate an unbiased random number in a range, you can use an extension of this approach:\n\n```C\nuint32_t random_bounded(uint32_t range) {\n  uint64_t random32bit =  random32(); //32-bit random number \n  multiresult = random32bit * range;\n  leftover = (uint32_t) multiresult;\n  if(leftover \u003c range ) {\n      threshold = -range % range ;\n      while (leftover \u003c threshold) {\n            random32bit =  random32();\n            multiresult = random32bit * range;\n            leftover = (uint32_t) multiresult;\n      }\n   }\n  return multiresult \u003e\u003e 32;\n}\n```\n\nSee http://lemire.me/blog/2016/06/30/fast-random-shuffling/\n","funding_links":[],"categories":["C"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flemire%2Ffastrange","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flemire%2Ffastrange","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flemire%2Ffastrange/lists"}