{"id":17142928,"url":"https://github.com/js-choi/proposal-popcount","last_synced_at":"2025-07-10T12:33:45.801Z","repository":{"id":44360469,"uuid":"512235872","full_name":"js-choi/proposal-popcount","owner":"js-choi","description":"Draft specification for bit popcount in JavaScript.","archived":false,"fork":false,"pushed_at":"2022-07-15T18:43:08.000Z","size":88,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-06-05T10:04:27.371Z","etag":null,"topics":["binary","bitwise","hamming-code","hamt","javascript","math","popcnt","popcount","succinct-data-structure","tc39"],"latest_commit_sha":null,"homepage":"","language":"HTML","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/js-choi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-07-09T16:39:50.000Z","updated_at":"2023-03-04T04:05:30.000Z","dependencies_parsed_at":"2022-07-19T04:33:05.030Z","dependency_job_id":null,"html_url":"https://github.com/js-choi/proposal-popcount","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/js-choi/proposal-popcount","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/js-choi%2Fproposal-popcount","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/js-choi%2Fproposal-popcount/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/js-choi%2Fproposal-popcount/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/js-choi%2Fproposal-popcount/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/js-choi","download_url":"https://codeload.github.com/js-choi/proposal-popcount/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/js-choi%2Fproposal-popcount/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264578896,"owners_count":23631555,"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":["binary","bitwise","hamming-code","hamt","javascript","math","popcnt","popcount","succinct-data-structure","tc39"],"created_at":"2024-10-14T20:33:13.509Z","updated_at":"2025-07-10T12:33:45.785Z","avatar_url":"https://github.com/js-choi.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Bitwise population count in JavaScript\nECMAScript Proposal. J. S. Choi, 2021. Stage 0.\n\n## Rationale\n\nBitwise population count (aka “popcount”, “popcnt”, and “bit count”) is a numeric operation that\ncounts the number of 1-bits in an integer’s binary representation. This is a\nuseful and versatile operation in numerics, scientific applications, binary parsing, and many other context—such that it is included as a\nbuilt-in instruction in many today CPUs; it’s also an instruction in\nWebAssembly. It is also present in many programming languages’ standard\nlibraries.\n\nSome known use cases are detailed in an [article by Vaibhav Sagar][]. These\ninclude:\n\n* [Succinct data structures][] such as [Roaring Bitmaps][] and other\n  [rank–select bitmaps][] for [suffix trees][], [binary trees, and multisets][RRR].\n* [Hash-array-mapped tries (HAMTs)][HAMTs].\n* [Error-correcting codes for strings using their Hamming distance][Hamming].\n* [Molecular fingerprinting][] in chemistry applications.\n* [Calculating piece mobility][] of [bitboards][] in [chess programming][].\n* Graph analysis when represented by bitmaps, e.g., [calculating adjacency matrices][].\n\n[article by Vaibhav Sagar]: https://vaibhavsagar.com/blog/2019/09/08/popcount/\n[succinct data structures]: https://en.wikipedia.org/wiki/Succinct_data_structure\n[rank–select bitmaps]: http://www.cs.cmu.edu/~./dga/papers/zhou-sea2013.pdf\n[Roaring bitmaps]: https://roaringbitmap.org\n[RRR]: https://archive.org/details/proceedingsofthi2002acms/page/233\n[suffix trees]: https://web.archive.org/web/20110929230740/http://www.dmi.unisa.it/people/cerulli/www/WSPages/WSFiles/Abs/S3/S33_abs_Grossi.pdf\n[HAMTs]: https://vaibhavsagar.com/blog/2018/07/29/hamts-from-scratch/\n[Hamming]: https://en.wikipedia.org/wiki/Hamming_distance#Error_detection_and_error_correction\n[molecular fingerprinting]: http://www.dalkescientific.com/writings/diary/archive/2008/06/26/fingerprint_background.html\n[chess programming]: https://www.chessprogramming.org/Population_Count\n[bitboards]: https://www.chessprogramming.org/Bitboards\n[calculating piece mobility]: https://www.chessprogramming.org/Mobility#Mobility_with_Bitboards\n[calculating adjacency matrices]: https://news.ycombinator.com/item?id=20915187\n\nPopcount is so pervasive in programs that both [GCC][] and [Clang][] will try\nto detect popcount implementations and replace them with the built-in CPU\ninstruction. See also [LLVM’s detection algorithm][]. (Note that [SIMD-using\napproaches may often be faster than using dedicated CPU instructions][SIMD];\nLLVM/Clang has adopted the former for this reason.)\n\n[GCC]: https://godbolt.org/z/JUzmD8\n[Clang]: https://godbolt.org/z/AVqMGl\n[LLVM’s detection algorithm]: https://github.com/llvm-mirror/llvm/blob/f36485f7ac2a8d72ad0e0f2134c17fd365272285/lib/Transforms/Scalar/LoopIdiomRecognize.cpp#L960\n[SIMD]: https://arxiv.org/pdf/1611.07612.pdf\n\nPopcount is annoying and inefficient to write in JavaScript. We therefore\npropose exploring the addition of a popcount API to the JavaScript language.\n\nIf this proposal is approved for Stage 1, then we would explore various\ndirections for the API’s design. We would also assemble as many real-world use\ncases as possible and shape our design to fulfill them.\n\n## Description\nWe would probably add a static function to the Math constructor that would look\nlike one the following:\n\n\n| Precedent             | Form                                        | Size                      | Signed?  | Negative-int behavior                     |\n| ----------------------| ------------------------------------------- | --------------------------| -------- | ----------------------------------------- |\n|**[Python][]**         |`i.bit_count()`                              | Bignum                    | Signed   | Input treated as absolute value           |\n|**[Wolfram][]**        |`DigitCount[i, 2, 1]`                        | Bignum                    | Signed   | Input treated as absolute value           |\n|**[Common Lisp][]**    |`(logcount i)`                               | Bignum†                   | Signed   | Two’s complement; counts zeroes†          |\n|**[Scheme (R7RS)][]**\\*|`(bit-count i)`                              | Bignum†                   | Signed   | Two’s complement; counts zeroes†          |\n|**[Scheme (R6RS)][]**  |`(bitwise-bit-count i)`                      | Bignum†                   | Signed   | Two’s complement; counts zeroes then NOTs†|\n|**[GMP][]**            |`mp_bitcnt_t(i)`                             | Bignum‡                   | Signed   | Special behavior‡                         |\n|**[C++][]**            |`std::popcnt(i)`                             | 8/16/32/64-bit            | Unsigned | Forbidden by static typing                |\n|**[Go][]**             |`bits.OnesCount(i)`, `bits.OnesCount8(i)`, … | 8/16/32/64-bit            | Unsigned | Forbidden by static typing                |\n|**[Java][]**           |`Integer.bitCount(i)`, `Long.bitCount(i)`, … | 16/32-bit; bignum         | Signed   | Two’s complement (type dependent)         |\n|**[Haskell][]**        |`popCount i`                                 | 8/16/≥29/32/64-bit; bignum| Signed   | Two’s complement (type dependent)         |\n|**[Rust][]**           |`i.count_ones()`                             | 8/16/32/64/128-bit        | Signed   | Two’s complement (type dependent)         |\n|**[WebAssembly][]**    |`i32.popcnt`, `i64.popcnt`                   | 32/64-bit                 | Signed   | Two’s complement (type dependent)         |\n|**[MySQL][]**          |`BIT_COUNT(i)`                               | 64-bit                    | Signed   | Two’s complement (64-bit)                 |\n|**[Swift][]**          |`i.nonzeroBitCount`§                         | 32/64-bit¶                | Signed   | Two’s complement¶                         |\n\n\u003cdetails\u003e\n\n\u003csummary\u003eTable footnotes\u003c/summary\u003e\n\n\\* [Scheme (R7RS)][] here refers to SRFI 151, which is implemented in several\nR7RS implementations, such as [in Chicken Scheme][].\n\n† When R7RS’s `bit-count` or Common Lisp’s `logcount` receives a\nnegative integer, it returns its number of zeroes instead. For example, both\n`(bit-count 255)` and `(bit-count -256)` are 8, and both `(logcount 256)` and\n`(logcount -257)` are 1.\n\nR6RS’s `bitwise-bit-count` additionally applies bitwise NOT (i.e., one’s\ncomplement – i.e., two’s complement minus one) to the number of zeroes. For\nexample, `(bitwise-bit-count -256)` is -9, and `(bitwise-bit-count -257)` is -2.\n\n‡ [GMP][]’s documentation about `mp_bitcnt_t` says, “If [the argument is\nnegative], the number of 1s is infinite, and the return value is the largest\npossible `mp_bitcnt_t`.”\n\n§ [Swift][]’s `nonzeroBitCount` property forms a trio with its\n`leadingZeroBitCount` and `trailingZeroBitCount` properties.\n\n¶ Whether Swift’s int type is either 32- or 64-bit depends on its compiler.\n\n\u003c/details\u003e\n\n[C++]: https://en.cppreference.com/w/cpp/numeric/popcount\n[Common Lisp]: http://www.lispworks.com/documentation/HyperSpec/Body/f_logcou.htm\n[GMP]: https://gmplib.org/manual/Integer-Logic-and-Bit-Fiddling#index-mpz_005fpopcount\n[Go]: https://pkg.go.dev/math/bits#OnesCount\n[Haskell]: https://downloads.haskell.org/~ghc/9.2.3/docs/html/libraries/base-4.16.2.0/Data-Bits.html#v:popCount\n[in Chicken Scheme]: https://wiki.call-cc.org/supported-standards\n[Java]: https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/lang/Integer.html#bitCount(int)\n[MySQL]: https://dev.mysql.com/doc/refman/5.7/en/bit-functions.html#function_bit-count\n[Python]: https://docs.python.org/3/library/stdtypes.html#int.bit_count\n[Rust]: https://doc.rust-lang.org/std/?search=count_ones\n[Scheme (R6RS)]: http://www.r6rs.org/final/html/r6rs-lib/r6rs-lib-Z-H-12.html\n[Scheme (R7RS)]: https://srfi.schemers.org/srfi-151/srfi-151.html\n[Swift]: https://developer.apple.com/documentation/swift/int/nonzerobitcount\n[WebAssembly]: https://developer.mozilla.org/en-US/docs/webassembly/reference/numeric/population_count\n[Wolfram]: https://reference.wolfram.com/language/ref/DigitCount.html\n\nWe could restrict the function to safe integers; it is uncertain how it should\nbehave on non-safe integers, negative integers, or non-integer numbers.\n\nIt is also uncertain whether we should limit it to 32- and/or 64-bit integers\nand, if not, whether we should split it up by size (e.g., `Math.popcnt(i)`\nversus `Math.popcnt32(i)` and `Math.popcnt64(i)`). A related cross-cutting\nconcern is how its API would fit with the [BigInt Math proposal][].\n\n[BigInt Math proposal]: https://github.com/tc39/proposal-bigint-math\n\n(Lastly, an alternative to adding a popcount function that acts on integers\nwould be to add a bit-array data type with a popcount method. This would\nprobably be considerably more complicated.)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjs-choi%2Fproposal-popcount","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjs-choi%2Fproposal-popcount","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjs-choi%2Fproposal-popcount/lists"}