Poindexter/npm/poindexter-wasm/PROJECT_README.md

219 lines
No EOL
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Poindexter
[![Go Reference](https://pkg.go.dev/badge/github.com/Snider/Poindexter.svg)](https://pkg.go.dev/github.com/Snider/Poindexter)
[![CI](https://github.com/Snider/Poindexter/actions/workflows/ci.yml/badge.svg)](https://github.com/Snider/Poindexter/actions)
[![Go Report Card](https://goreportcard.com/badge/github.com/Snider/Poindexter)](https://goreportcard.com/report/github.com/Snider/Poindexter)
[![Vulncheck](https://img.shields.io/badge/govulncheck-enabled-brightgreen.svg)](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck)
[![codecov](https://codecov.io/gh/Snider/Poindexter/branch/main/graph/badge.svg)](https://codecov.io/gh/Snider/Poindexter)
[![Release](https://img.shields.io/github/v/release/Snider/Poindexter?display_name=tag)](https://github.com/Snider/Poindexter/releases)
A Go library package providing utility functions including sorting algorithms with custom comparators.
## Features
- 🔢 **Sorting Utilities**: Sort integers, strings, and floats in ascending or descending order
- 🎯 **Custom Sorting**: Sort any type with custom comparison functions or key extractors
- 🔍 **Binary Search**: Fast search on sorted data
- 🧭 **KDTree (NN Search)**: Build a KDTree over points with generic payloads; nearest, k-NN, and radius queries with Euclidean, Manhattan, Chebyshev, and Cosine metrics
- 📦 **Generic Functions**: Type-safe operations using Go generics
-**Well-Tested**: Comprehensive test coverage
- 📖 **Documentation**: Full documentation available at GitHub Pages
## Installation
```bash
go get github.com/Snider/Poindexter
```
## Quick Start
```go
package main
import (
"fmt"
poindexter "github.com/Snider/Poindexter"
)
func main() {
// Basic sorting
numbers := []int{3, 1, 4, 1, 5, 9}
poindexter.SortInts(numbers)
fmt.Println(numbers) // [1 1 3 4 5 9]
// Custom sorting with key function
type Product struct {
Name string
Price float64
}
products := []Product{{"Apple", 1.50}, {"Banana", 0.75}, {"Cherry", 3.00}}
poindexter.SortByKey(products, func(p Product) float64 { return p.Price })
// KDTree quick demo
pts := []poindexter.KDPoint[string]{
{ID: "A", Coords: []float64{0, 0}, Value: "alpha"},
{ID: "B", Coords: []float64{1, 0}, Value: "bravo"},
{ID: "C", Coords: []float64{0, 1}, Value: "charlie"},
}
tree, _ := poindexter.NewKDTree(pts, poindexter.WithMetric(poindexter.EuclideanDistance{}))
nearest, dist, _ := tree.Nearest([]float64{0.9, 0.1})
fmt.Println(nearest.ID, nearest.Value, dist) // B bravo ~0.141...
}
```
## Documentation
Full documentation is available at [https://snider.github.io/Poindexter/](https://snider.github.io/Poindexter/)
Explore runnable examples in the repository:
- examples/dht_ping_1d
- examples/kdtree_2d_ping_hop
- examples/kdtree_3d_ping_hop_geo
- examples/kdtree_4d_ping_hop_geo_score
- examples/wasm-browser (browser demo using the ESM loader)
### KDTree performance and notes
- Dual backend support: Linear (always available) and an optimized KD backend enabled when building with `-tags=gonum`. Linear is the default; with the `gonum` tag, the optimized backend becomes the default.
- Complexity: Linear backend is O(n) per query. Optimized KD backend is typically sub-linear on prunable datasets and dims ≤ ~8, especially as N grows (≥10k100k).
- Insert is O(1) amortized; delete by ID is O(1) via swap-delete; order is not preserved.
- Concurrency: the KDTree type is not safe for concurrent mutation. Protect with a mutex or share immutable snapshots for read-mostly workloads.
- See multi-dimensional examples (ping/hops/geo/score) in docs and `examples/`.
- Performance guide: see docs/Performance for benchmark guidance and tips: [docs/perf.md](docs/perf.md) • Hosted: https://snider.github.io/Poindexter/perf/
### Backend selection
- Default backend is Linear. If you build with `-tags=gonum`, the default becomes the optimized KD backend.
- You can override per tree at construction:
```go
// Force Linear (always available)
kdt1, _ := poindexter.NewKDTree(pts, poindexter.WithBackend(poindexter.BackendLinear))
// Force Gonum (requires build tag)
kdt2, _ := poindexter.NewKDTree(pts, poindexter.WithBackend(poindexter.BackendGonum))
```
- Supported metrics in the optimized backend: Euclidean (L2), Manhattan (L1), Chebyshev (L∞).
- Cosine and Weighted-Cosine currently run on the Linear backend.
- See the Performance guide for measured comparisons and when to choose which backend.
#### Choosing a metric (quick tips)
- Euclidean (L2): smooth trade-offs across axes; solid default for blended preferences.
- Manhattan (L1): emphasizes per-axis absolute differences; good when each unit of ping/hop matters equally.
- Chebyshev (L∞): dominated by the worst axis; useful for strict thresholds (e.g., reject high hop count regardless of ping).
- Cosine: angle-based for vector similarity; pair it with normalized/weighted features when direction matters more than magnitude.
See the multi-dimensional KDTree docs for end-to-end examples and weighting/normalization helpers: [Multi-Dimensional KDTree (DHT)](docs/kdtree-multidimensional.md).
## Maintainer Makefile
The repository includes a maintainer-friendly `Makefile` that mirrors CI tasks and speeds up local workflows.
- help — list available targets
- tidy / tidy-check — run `go mod tidy`, optionally verify no diffs
- fmt — format code (`go fmt ./...`)
- vet — `go vet ./...`
- build — `go build ./...`
- examples — build all programs under `examples/` (if present)
- test — run unit tests
- race — run tests with the race detector
- cover — run tests with race + coverage (writes `coverage.out` and prints summary)
- coverhtml — render HTML coverage report to `coverage.html`
- coverfunc — print per-function coverage (from `coverage.out`)
- cover-kdtree — print coverage details filtered to `kdtree.go`
- fuzz — run Go fuzzing for a configurable time (default 10s) matching CI
- bench — run benchmarks with `-benchmem` (writes `bench.txt`)
- lint — run `golangci-lint` (if installed)
- vuln — run `govulncheck` (if installed)
- ci — CI-parity aggregate: tidy-check, build, vet, cover, examples, bench, lint, vuln
- release — run GoReleaser with the canonical `.goreleaser.yaml` (for tagged releases)
- snapshot — GoReleaser snapshot (no publish)
- docs-serve — serve MkDocs locally on 127.0.0.1:8000
- docs-build — build MkDocs site into `site/`
Quick usage:
- See all targets:
```bash
make help
```
- Fast local cycle:
```bash
make fmt
make vet
make test
```
- CI-parity run (what GitHub Actions does, locally):
```bash
make ci
```
- Coverage summary:
```bash
make cover
```
- Generate HTML coverage report (writes coverage.html):
```bash
make coverhtml
```
- Fuzz for 10 seconds (default):
```bash
make fuzz
```
- Fuzz with a custom time (e.g., 30s):
```bash
make fuzz FUZZTIME=30s
```
- Run benchmarks (writes bench.txt):
```bash
make bench
```
- Build examples (if any under ./examples):
```bash
make examples
```
- Serve docs locally (requires mkdocs-material):
```bash
make docs-serve
```
Configurable variables:
- `FUZZTIME` (default `10s`) — e.g. `make fuzz FUZZTIME=30s`
- `BENCHOUT` (default `bench.txt`), `COVEROUT` (default `coverage.out`), `COVERHTML` (default `coverage.html`)
- Tool commands are overridable via env: `GO`, `GOLANGCI_LINT`, `GORELEASER`, `MKDOCS`
Requirements for optional targets:
- `golangci-lint` for `make lint`
- `golang.org/x/vuln/cmd/govulncheck` for `make vuln`
- `goreleaser` for `make release` / `make snapshot`
- `mkdocs` + `mkdocs-material` for `make docs-serve` / `make docs-build`
See the full Makefile at the repo root for authoritative target definitions.
## License
This project is licensed under the European Union Public Licence v1.2 (EUPL-1.2). See [LICENSE](LICENSE) for details.
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.