{"id":20440249,"url":"https://github.com/strainer/barsort","last_synced_at":"2026-04-18T12:36:02.800Z","repository":{"id":143850428,"uuid":"89157440","full_name":"strainer/barsort","owner":"strainer","description":"An unweildy exercise in fast numeric sorting","archived":false,"fork":false,"pushed_at":"2021-08-02T12:24:29.000Z","size":138,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-08-09T02:23:57.844Z","etag":null,"topics":["exercise","javascript","sort"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/strainer.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":"2017-04-23T16:51:04.000Z","updated_at":"2021-08-06T12:04:05.000Z","dependencies_parsed_at":null,"dependency_job_id":"5b6f3dcf-dbd4-4dcd-9f81-5dbccfb53332","html_url":"https://github.com/strainer/barsort","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/strainer/barsort","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strainer%2Fbarsort","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strainer%2Fbarsort/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strainer%2Fbarsort/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strainer%2Fbarsort/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/strainer","download_url":"https://codeload.github.com/strainer/barsort/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strainer%2Fbarsort/sbom","scorecard":{"id":854614,"data":{"date":"2025-08-11","repo":{"name":"github.com/strainer/barsort","commit":"90f2042a0640958eb328db9c27f69f5880996f44"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: License:0","Info: FSF or OSI recognized license: Apache License 2.0: License:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-23T23:32:16.575Z","repository_id":143850428,"created_at":"2025-08-23T23:32:16.575Z","updated_at":"2025-08-23T23:32:16.575Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31969767,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T00:39:45.007Z","status":"online","status_checked_at":"2026-04-18T02:00:07.018Z","response_time":103,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["exercise","javascript","sort"],"created_at":"2024-11-15T09:23:11.989Z","updated_at":"2026-04-18T12:36:02.778Z","avatar_url":"https://github.com/strainer.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"Barsort\n=======\n\nA speed optimised general purpose and stable numeric sort, specialised to work on numeric input only (integers and reals) and return a clone or sort index.\n\nBarsort utilises a specialised algorithm similar to 'counting sort' originaly made to place array elements into groups of equal size with similar magnitudes. It is combined here with insert and merge sorts, and with edge case processing to create a fast numeric sort.\n\nTesting across a good range of possible input distributions and sizes shows barsort is many times faster than node 2016's native sort and competitive with a proficient javascript implementation of Pythons optimised 'Timsort'. \n\nAlas, the source code is a beastly private exertion beyond redemption. \n\nUsage\n-----\n\n```javascript \n  \n//return a sorted clone of array\nsorted_arr = Barsort.sort( array [,\"descend\"] )      \n\n//return a sorted index to array ([optional params])\nindex_arr = Barsort.sortorder( array [,index_arr][,\"descend\"] )  \n  \n```\t\n\n### Summary of speedtests:\n\nThe following tables are for generating a sort index of arrays. Timsort is considerably faster doing light sorting in place.\n\nPre-sorted input, Lengths: |     100   |    10,000   | 1,000,000\n :-------------- | :-------: | :---------: | :----------\nBarsort sort     |    100 %  |    100 %    |    100 %\nNative sort      |      5 %  |      2 %    |      2 %\nTimsort sort     |    100 %  |    100 %    |    100 %\n\nGaussian distribution |     100   |    10,000   | 1,000,000\n :-------------- | :-------: | :---------: | :----------\nBarsort sort     |    100 %  |    100 %    | 100 %\nNative sort      |      2 %  |      2 %    |   2 %\nTimsort sort     |    100 %  |     60 %    |  60 %\n\nTough distribution |     100   |    10,000   | 1,000,000   \n:-------------- | :-------: | :---------: | :----------\nBarsort sort    |     100 % |    100 %    |    100 %\nNative sort     |      10 % |     10 %    |     10 %\nTimsort sort    |     100 % |     65 %    |     65 %\n\n\n### See also\n\n[Timsort](https://github.com/mziccard/node-timsort) is a popular multipurpose in-place sort. \n\n[LSD Radix Sort](https://duvanenko.tech.blog/2017/06/15/faster-sorting-in-javascript/) is 3x Barsort speed but is limited to unsigned integers and can not arrange an index.\n\n\n### Barsort algorithm basics - a \"counting sort\"\n\nThe input numbers are first tallied into bins as though calculating a histogram (by dividing by a suitable factor and casting to integer to get a bin number). Like this:\n```\n  for(var i=0; i\u003ce; i++) \n  { kysbin[i]=(binperval*(kysval[i]-minv))\u003e\u003e0  } \n```\nThese \"counting bins\" are subsequently indexed by a fewer number of \"placement bins\". The core algorithm was developed to sort data roughly into histogram bars ( without sorting *within* the bars). The \"counting bins\" were subdivisions of the bars to reduce spillage between the bars. So, the cumulative sum of the populations of the placement bins is calculated so that for each placement bin an anchor position in the sorting index (output) is known (for values of bins range).\n\nLike this:\n```\n  for(var bin=0; bin\u003cnbin; bin++){\n    \n    barofbin[bin]=fillbar            //fillbar is the bar to fill currently\n    barsfill[fillbar]+=cntofbin[bin] //here it is being allocated a bins tally \n\n    while(barsfill[fillbar]\u003e=fcap){   //when bar is full... \n      barsfill[fillbar+1]+=barsfill[fillbar]-fcap\n      barsfill[fillbar]=fcap\n      fillbar++                //...fill next bar\n      nxtcap+=kysperbar-fcap   //nxtcap and kysperbar are floats\n      fcap=nxtcap \u003e\u003e\u003e0         //fcap is integer (it differs for each bar)\n    }\n  } \n```\n\nSome multi-indirected lookup and updating is done for each input to use the base placement info to assign inputs their position in the sorting index. Here is that final 'curious' code: \n```\n  var bapos=new Array(nbar); bapos[0]=0 //( before_anchor_pos )\n  for(var i=0;i\u003cnbar-1;i++){ bapos[i+1]=bapos[i]+barsfill[i] }\n\n  for(var i=st; i\u003cov; i++){\n    var binofel=kysbin[i] \n    \n    //(change barofbin if barsfill is empty)\n    while( barsfill[barofbin[binofel]]===0 ){ \n      barofbin[binofel]++ \n    }\n    barsfill[barofbin[binofel]]--          \n    sortix[ bapos[barofbin[binofel]]++ ]=i //sort index gets ordered by bar\n  }\n  // (this is not the unpresentable part...)\n```\n\nThe counting sort is used to get elements quite close to where thay should be but they need to be fine-sorted afterward. The classic \"insertion sort\" is perfect for fine sorting as long it never has to move any elements too far. It can fall back on mergesort to cope with rare problem cases.\n\nVersion History\n---------------\n* 0.5.0 - pre release, in use and testing ...\n* 0.6.0 - repo fixed, pre release in use and testing ...\n* 0.9.0 - much developed and testing ...\n* 0.13.0 - ...much more developed and tested.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstrainer%2Fbarsort","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstrainer%2Fbarsort","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstrainer%2Fbarsort/lists"}