{"id":29902916,"url":"https://github.com/downflux/go-kd","last_synced_at":"2025-08-01T16:17:39.286Z","repository":{"id":46027908,"uuid":"423755222","full_name":"downflux/go-kd","owner":"downflux","description":"Golang k-D tree implementation with duplicate coordinate support","archived":false,"fork":false,"pushed_at":"2022-12-16T18:53:38.000Z","size":169,"stargazers_count":51,"open_issues_count":3,"forks_count":7,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-06-19T00:31:32.756Z","etag":null,"topics":["golang","kdtree"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/downflux/go-kd","language":"Go","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/downflux.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}},"created_at":"2021-11-02T08:04:44.000Z","updated_at":"2024-04-16T16:38:01.000Z","dependencies_parsed_at":"2023-01-29T15:45:40.867Z","dependency_job_id":null,"html_url":"https://github.com/downflux/go-kd","commit_stats":null,"previous_names":[],"tags_count":30,"template":false,"template_full_name":null,"purl":"pkg:github/downflux/go-kd","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/downflux%2Fgo-kd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/downflux%2Fgo-kd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/downflux%2Fgo-kd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/downflux%2Fgo-kd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/downflux","download_url":"https://codeload.github.com/downflux/go-kd/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/downflux%2Fgo-kd/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268257513,"owners_count":24221062,"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","status":"online","status_checked_at":"2025-08-01T02:00:08.611Z","response_time":67,"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":["golang","kdtree"],"created_at":"2025-08-01T16:17:29.586Z","updated_at":"2025-08-01T16:17:39.258Z","avatar_url":"https://github.com/downflux.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# go-kd\n\nGolang K-D tree implementation with duplicate coordinate support\n\nSee [Wikipedia](https://en.wikipedia.org/wiki/K-d_tree) for more information.\n\n## Testing\n\n```bash\ngo test github.com/downflux/go-kd/...\ngo test github.com/downflux/go-kd/internal/perf \\\n  -bench . \\\n  -benchmem \\\n  -timeout=60m \\\n  -args -performance_test_size=large\n```\n\n## Example\n\n```golang\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/downflux/go-geometry/nd/hyperrectangle\"\n\t\"github.com/downflux/go-geometry/nd/vector\"\n\t\"github.com/downflux/go-kd/point\"\n\n\t\"github.com/downflux/go-kd/kd\"\n)\n\n// P implements the point.P interface, which needs to provide a coordinate\n// vector function P().\nvar _ point.P = \u0026P{}\n\ntype P struct {\n\tp   vector.V\n\ttag string\n}\n\nfunc (p *P) P() vector.V     { return p.p }\nfunc (p *P) Equal(q *P) bool { return vector.Within(p.P(), q.P()) \u0026\u0026 p.tag == q.tag }\n\nfunc main() {\n\tdata := []*P{\n\t\t\u0026P{p: vector.V{1, 2}, tag: \"A\"},\n\t\t\u0026P{p: vector.V{2, 100}, tag: \"B\"},\n\t}\n\n\t// Data is copy-constructed and may be read from outside the k-D tree.\n\tt := kd.New[*P](kd.O[*P]{\n\t\tData: data,\n\t\tK:    2,\n\t\tN:    1,\n\t})\n\n\tfmt.Println(\"KNN search\")\n\tfor _, p := range kd.KNN(\n\t\tt,\n\t\t/* v = */ vector.V{0, 0},\n\t\t/* k = */ 2,\n\t\tfunc(p *P) bool { return true }) {\n\t\tfmt.Println(p)\n\t}\n\n\t// Remove deletes the first data point at the given input coordinate and\n\t// matches the input check function.\n\tp, ok := t.Remove(data[0].P(), data[0].Equal)\n\tfmt.Printf(\"removed %v (found = %v)\\n\", p, ok)\n\n\t// RangeSearch returns all points within the k-D bounds and matches the\n\t// input filter function.\n\tfmt.Println(\"range search\")\n\tfor _, p := range kd.RangeSearch(\n\t\tt,\n\t\t*hyperrectangle.New(\n\t\t\t/* min = */ vector.V{0, 0},\n\t\t\t/* max = */ vector.V{100, 100},\n\t\t),\n\t\tfunc(p *P) bool { return true },\n\t) {\n\t\tfmt.Println(p)\n\t}\n}\n```\n\n## Performance (@v1.0.0)\n\nThis k-D tree implementation was compared against a brute force method, as well\nas with the leading Golang k-D tree implementation\n(http://github.com/kyroy/kdtree). Overall, we have found that\n\n* tree construction is about 10x faster for large N.\n\n  ```\n  BenchmarkNew/kyroy/K=16/N=1000-8               758980 ns/op  146777 B/op\n  BenchmarkNew/Real/K=16/N=1000/LeafSize=16-8    200749 ns/op   32637 B/op\n\n  BenchmarkNew/kyroy/K=16/N=1000000-8                7407144200 ns/op  184813784 B/op\n  BenchmarkNew/Real/K=16/N=1000000/LeafSize=256-8     588456300 ns/op   12462912 B/op\n  ```\n\n* KNN is significantly faster; for small N, we have found our implementation is\n  ~10x faster than the reference implementation and ~20x faster than brute\n  force. For large N, we have found up to ~15x faster than brute force, and a\n  staggering _~1500x_ speedup when compared to the reference implementation.\n\n  ```\n  BenchmarkKNN/BruteForce/K=16/N=1000-8                   1563019 ns/op  2220712 B/op\n  BenchmarkKNN/kyroy/K=16/N=1000/KNN=0.05-8                791415 ns/op    21960 B/op\n  BenchmarkKNN/Real/K=16/N=1000/LeafSize=16/KNN=0.05-8      69537 ns/op    12024 B/op\n\n  BenchmarkKNN/BruteForce/K=16/N=1000000-8                       5030811400 ns/op  5347687464 B/op\n  BenchmarkKNN/kyroy/K=16/N=1000000/KNN=0.05-8                 529703585200 ns/op    23755688 B/op\n  BenchmarkKNN/Real/K=16/N=1000000/LeafSize=256/KNN=0.05-8        335845533 ns/op     6044016 B/op\n  ```\n\n* RangeSearch is slower for small N -- we are approximately at parity for brute\n  force, and ~10x slower than the reference implementation. However, at large N,\n  we are ~300x faster than brute force, and ~100x faster than the reference\n  implementation.\n\n  ```\n  BenchmarkRangeSearch/BruteForce/K=16/N=1000-8                        154712 ns/op   25208 B/op\n  BenchmarkRangeSearch/kyroy/K=16/N=1000/Coverage=0.05-8                13373 ns/op     496 B/op\n  BenchmarkRangeSearch/Real/K=16/N=1000/LeafSize=16/Coverage=0.05-8    193276 ns/op  101603 B/op\n\n  BenchmarkRangeSearch/BruteForce/K=16/N=1000000-8                         173427000 ns/op  41678072 B/op\n  BenchmarkRangeSearch/kyroy/K=16/N=1000000/Coverage=0.05-8                 56820240 ns/op       496 B/op\n  BenchmarkRangeSearch/Real/K=16/N=1000000/LeafSize=256/Coverage=0.05-8       530937 ns/op    212134 B/op\n  ```\n\nRaw data on these results may be found [here](/internal/perf/results/v0.5.5.txt).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdownflux%2Fgo-kd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdownflux%2Fgo-kd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdownflux%2Fgo-kd/lists"}