From eb2f7e75256ea21d4a58d3658940fe3ff0a5a7e7 Mon Sep 17 00:00:00 2001 From: <> Date: Sun, 4 Jan 2026 20:04:41 +0000 Subject: [PATCH] Deployed 91146b2 with MkDocs version: 1.6.1 --- .nojekyll | 0 404.html | 755 ++ api/index.html | 2218 ++++++ assets/images/favicon.png | Bin 0 -> 1870 bytes assets/javascripts/bundle.79ae519e.min.js | 16 + assets/javascripts/bundle.79ae519e.min.js.map | 7 + assets/javascripts/lunr/min/lunr.ar.min.js | 1 + assets/javascripts/lunr/min/lunr.da.min.js | 18 + assets/javascripts/lunr/min/lunr.de.min.js | 18 + assets/javascripts/lunr/min/lunr.du.min.js | 18 + assets/javascripts/lunr/min/lunr.el.min.js | 1 + assets/javascripts/lunr/min/lunr.es.min.js | 18 + assets/javascripts/lunr/min/lunr.fi.min.js | 18 + assets/javascripts/lunr/min/lunr.fr.min.js | 18 + assets/javascripts/lunr/min/lunr.he.min.js | 1 + assets/javascripts/lunr/min/lunr.hi.min.js | 1 + assets/javascripts/lunr/min/lunr.hu.min.js | 18 + assets/javascripts/lunr/min/lunr.hy.min.js | 1 + assets/javascripts/lunr/min/lunr.it.min.js | 18 + assets/javascripts/lunr/min/lunr.ja.min.js | 1 + assets/javascripts/lunr/min/lunr.jp.min.js | 1 + assets/javascripts/lunr/min/lunr.kn.min.js | 1 + assets/javascripts/lunr/min/lunr.ko.min.js | 1 + assets/javascripts/lunr/min/lunr.multi.min.js | 1 + assets/javascripts/lunr/min/lunr.nl.min.js | 18 + assets/javascripts/lunr/min/lunr.no.min.js | 18 + assets/javascripts/lunr/min/lunr.pt.min.js | 18 + assets/javascripts/lunr/min/lunr.ro.min.js | 18 + assets/javascripts/lunr/min/lunr.ru.min.js | 18 + assets/javascripts/lunr/min/lunr.sa.min.js | 1 + .../lunr/min/lunr.stemmer.support.min.js | 1 + assets/javascripts/lunr/min/lunr.sv.min.js | 18 + assets/javascripts/lunr/min/lunr.ta.min.js | 1 + assets/javascripts/lunr/min/lunr.te.min.js | 1 + assets/javascripts/lunr/min/lunr.th.min.js | 1 + assets/javascripts/lunr/min/lunr.tr.min.js | 18 + assets/javascripts/lunr/min/lunr.vi.min.js | 1 + assets/javascripts/lunr/min/lunr.zh.min.js | 1 + assets/javascripts/lunr/tinyseg.js | 206 + assets/javascripts/lunr/wordcut.js | 6708 +++++++++++++++++ .../workers/search.2c215733.min.js | 42 + .../workers/search.2c215733.min.js.map | 7 + assets/stylesheets/main.484c7ddc.min.css | 1 + assets/stylesheets/main.484c7ddc.min.css.map | 1 + assets/stylesheets/palette.ab4e12ef.min.css | 1 + .../stylesheets/palette.ab4e12ef.min.css.map | 1 + dht-best-ping/index.html | 1057 +++ getting-started/index.html | 1165 +++ index.html | 1037 +++ kdtree-multidimensional/index.html | 1266 ++++ license/index.html | 973 +++ perf/index.html | 1036 +++ search/search_index.json | 1 + sitemap.xml | 3 + sitemap.xml.gz | Bin 0 -> 127 bytes wasm/index.html | 1160 +++ 56 files changed, 17948 insertions(+) create mode 100644 .nojekyll create mode 100644 404.html create mode 100644 api/index.html create mode 100644 assets/images/favicon.png create mode 100644 assets/javascripts/bundle.79ae519e.min.js create mode 100644 assets/javascripts/bundle.79ae519e.min.js.map create mode 100644 assets/javascripts/lunr/min/lunr.ar.min.js create mode 100644 assets/javascripts/lunr/min/lunr.da.min.js create mode 100644 assets/javascripts/lunr/min/lunr.de.min.js create mode 100644 assets/javascripts/lunr/min/lunr.du.min.js create mode 100644 assets/javascripts/lunr/min/lunr.el.min.js create mode 100644 assets/javascripts/lunr/min/lunr.es.min.js create mode 100644 assets/javascripts/lunr/min/lunr.fi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.fr.min.js create mode 100644 assets/javascripts/lunr/min/lunr.he.min.js create mode 100644 assets/javascripts/lunr/min/lunr.hi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.hu.min.js create mode 100644 assets/javascripts/lunr/min/lunr.hy.min.js create mode 100644 assets/javascripts/lunr/min/lunr.it.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ja.min.js create mode 100644 assets/javascripts/lunr/min/lunr.jp.min.js create mode 100644 assets/javascripts/lunr/min/lunr.kn.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ko.min.js create mode 100644 assets/javascripts/lunr/min/lunr.multi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.nl.min.js create mode 100644 assets/javascripts/lunr/min/lunr.no.min.js create mode 100644 assets/javascripts/lunr/min/lunr.pt.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ro.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ru.min.js create mode 100644 assets/javascripts/lunr/min/lunr.sa.min.js create mode 100644 assets/javascripts/lunr/min/lunr.stemmer.support.min.js create mode 100644 assets/javascripts/lunr/min/lunr.sv.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ta.min.js create mode 100644 assets/javascripts/lunr/min/lunr.te.min.js create mode 100644 assets/javascripts/lunr/min/lunr.th.min.js create mode 100644 assets/javascripts/lunr/min/lunr.tr.min.js create mode 100644 assets/javascripts/lunr/min/lunr.vi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.zh.min.js create mode 100644 assets/javascripts/lunr/tinyseg.js create mode 100644 assets/javascripts/lunr/wordcut.js create mode 100644 assets/javascripts/workers/search.2c215733.min.js create mode 100644 assets/javascripts/workers/search.2c215733.min.js.map create mode 100644 assets/stylesheets/main.484c7ddc.min.css create mode 100644 assets/stylesheets/main.484c7ddc.min.css.map create mode 100644 assets/stylesheets/palette.ab4e12ef.min.css create mode 100644 assets/stylesheets/palette.ab4e12ef.min.css.map create mode 100644 dht-best-ping/index.html create mode 100644 getting-started/index.html create mode 100644 index.html create mode 100644 kdtree-multidimensional/index.html create mode 100644 license/index.html create mode 100644 perf/index.html create mode 100644 search/search_index.json create mode 100644 sitemap.xml create mode 100644 sitemap.xml.gz create mode 100644 wasm/index.html diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/404.html b/404.html new file mode 100644 index 0000000..85898ba --- /dev/null +++ b/404.html @@ -0,0 +1,755 @@ + + + +
+ + + + + + + + + + + + + + + + + + + + + +Complete API documentation for the Poindexter library.
+Returns the current version of the library.
+Returns:
+- string: The version string (e.g., "0.3.0")
Example:
+ +Returns a greeting message.
+Parameters:
+- name (string): The name to greet. If empty, defaults to "World"
Returns:
+- string: A greeting message
Examples:
+// Greet the world
+message := poindexter.Hello("")
+fmt.Println(message) // Output: Hello, World!
+
+// Greet a specific person
+message = poindexter.Hello("Alice")
+fmt.Println(message) // Output: Hello, Alice!
+Sorts a slice of integers in ascending order in place.
+Example:
+numbers := []int{3, 1, 4, 1, 5, 9}
+poindexter.SortInts(numbers)
+fmt.Println(numbers) // Output: [1 1 3 4 5 9]
+Sorts a slice of integers in descending order in place.
+Example:
+numbers := []int{3, 1, 4, 1, 5, 9}
+poindexter.SortIntsDescending(numbers)
+fmt.Println(numbers) // Output: [9 5 4 3 1 1]
+Sorts a slice of strings in ascending order in place.
+Example:
+words := []string{"banana", "apple", "cherry"}
+poindexter.SortStrings(words)
+fmt.Println(words) // Output: [apple banana cherry]
+Sorts a slice of strings in descending order in place.
+Sorts a slice of float64 values in ascending order in place.
+Sorts a slice of float64 values in descending order in place.
+Sorts a slice using a custom comparison function.
+Parameters:
+- data: The slice to sort
+- less: A function that returns true if data[i] should come before data[j]
Example:
+type Person struct {
+ Name string
+ Age int
+}
+
+people := []Person{
+ {"Alice", 30},
+ {"Bob", 25},
+ {"Charlie", 35},
+}
+
+// Sort by age
+poindexter.SortBy(people, func(i, j int) bool {
+ return people[i].Age < people[j].Age
+})
+// Result: [Bob(25) Alice(30) Charlie(35)]
+Sorts a slice by extracting a comparable key from each element in ascending order.
+Parameters:
+- data: The slice to sort
+- key: A function that extracts a sortable key from each element
Example:
+type Product struct {
+ Name string
+ Price float64
+}
+
+products := []Product{
+ {"Apple", 1.50},
+ {"Banana", 0.75},
+ {"Cherry", 3.00},
+}
+
+// Sort by price
+poindexter.SortByKey(products, func(p Product) float64 {
+ return p.Price
+})
+// Result: [Banana(0.75) Apple(1.50) Cherry(3.00)]
+Sorts a slice by extracting a comparable key from each element in descending order.
+Example:
+type Student struct {
+ Name string
+ Score int
+}
+
+students := []Student{
+ {"Alice", 85},
+ {"Bob", 92},
+ {"Charlie", 78},
+}
+
+// Sort by score descending
+poindexter.SortByKeyDescending(students, func(s Student) int {
+ return s.Score
+})
+// Result: [Bob(92) Alice(85) Charlie(78)]
+Checks if a slice of integers is sorted in ascending order.
+Checks if a slice of strings is sorted in ascending order.
+Checks if a slice of float64 values is sorted in ascending order.
+Performs a binary search on a sorted slice of integers.
+Parameters:
+- data: A sorted slice of integers
+- target: The value to search for
Returns:
+- int: The index where target is found, or -1 if not found
Example:
+numbers := []int{1, 3, 5, 7, 9, 11}
+index := poindexter.BinarySearch(numbers, 7)
+fmt.Println(index) // Output: 3
+Performs a binary search on a sorted slice of strings.
+Parameters:
+- data: A sorted slice of strings
+- target: The value to search for
Returns:
+- int: The index where target is found, or -1 if not found
Poindexter provides helpers to build normalized, weighted KD points from your own records. These functions min–max normalize each axis over your dataset, optionally invert axes where higher is better (to turn them into “lower cost”), and apply per‑axis weights.
+func Build2D[T any](
+ items []T,
+ id func(T) string,
+ f1, f2 func(T) float64,
+ weights [2]float64,
+ invert [2]bool,
+) ([]KDPoint[T], error)
+
+func Build3D[T any](
+ items []T,
+ id func(T) string,
+ f1, f2, f3 func(T) float64,
+ weights [3]float64,
+ invert [3]bool,
+) ([]KDPoint[T], error)
+
+func Build4D[T any](
+ items []T,
+ id func(T) string,
+ f1, f2, f3, f4 func(T) float64,
+ weights [4]float64,
+ invert [4]bool,
+) ([]KDPoint[T], error)
+Example (4D over ping, hops, geo, score):
+// weights and inversion: flip score so higher is better → lower cost
+weights := [4]float64{1.0, 0.7, 0.2, 1.2}
+invert := [4]bool{false, false, false, true}
+
+pts, err := poindexter.Build4D(
+ peers,
+ func(p Peer) string { return p.ID },
+ func(p Peer) float64 { return p.PingMS },
+ func(p Peer) float64 { return p.Hops },
+ func(p Peer) float64 { return p.GeoKM },
+ func(p Peer) float64 { return p.Score },
+ weights, invert,
+)
+if err != nil { panic(err) }
+
+kdt, _ := poindexter.NewKDTree(pts, poindexter.WithMetric(poindexter.EuclideanDistance{}))
+best, dist, _ := kdt.Nearest([]float64{0, 0, 0, 0})
+Notes:
+- Keep and reuse your normalization parameters (min/max) if you need consistency across updates; otherwise rebuild points when the candidate set changes.
+- Use invert to turn “higher is better” features (like scores) into lower costs for distance calculations.
Build a KDTree from the provided points. All points must have the same dimensionality (> 0) and IDs (if provided) must be unique.
+Possible errors:
+- ErrEmptyPoints: no points provided
+- ErrZeroDim: dimension must be at least 1
+- ErrDimMismatch: inconsistent dimensionality among points
+- ErrDuplicateID: duplicate point ID encountered
Construct an empty KDTree with the given dimension, then populate later via Insert.
Nearest, KNearest, Radius). Inserts are O(1) amortized. Deletes by ID are O(1) using swap-delete (order not preserved).See runnable examples in the repository examples/ and the docs pages for 1D DHT and multi-dimensional KDTree usage.
To keep normalization consistent across dynamic updates, compute per‑axis min/max once and reuse it to build points later. This avoids drift when the candidate set changes.
+// AxisStats holds the min/max observed for a single axis.
+type AxisStats struct {
+ Min float64
+ Max float64
+}
+
+// NormStats holds per‑axis normalisation stats; for D dims, Stats has length D.
+type NormStats struct {
+ Stats []AxisStats
+}
+func ComputeNormStats2D[T any](items []T, f1, f2 func(T) float64) NormStats
+func ComputeNormStats3D[T any](items []T, f1, f2, f3 func(T) float64) NormStats
+func ComputeNormStats4D[T any](items []T, f1, f2, f3, f4 func(T) float64) NormStats
+func Build2DWithStats[T any](
+ items []T,
+ id func(T) string,
+ f1, f2 func(T) float64,
+ weights [2]float64,
+ invert [2]bool,
+ stats NormStats,
+) ([]KDPoint[T], error)
+
+func Build3DWithStats[T any](
+ items []T,
+ id func(T) string,
+ f1, f2, f3 func(T) float64,
+ weights [3]float64,
+ invert [3]bool,
+ stats NormStats,
+) ([]KDPoint[T], error)
+
+func Build4DWithStats[T any](
+ items []T,
+ id func(T) string,
+ f1, f2, f3, f4 func(T) float64,
+ weights [4]float64,
+ invert [4]bool,
+ stats NormStats,
+) ([]KDPoint[T], error)
+// Compute stats once over your baseline set
+stats := poindexter.ComputeNormStats2D(peers,
+ func(p Peer) float64 { return p.PingMS },
+ func(p Peer) float64 { return p.Hops },
+)
+
+// Build points using those stats (now or later)
+pts, _ := poindexter.Build2DWithStats(
+ peers,
+ func(p Peer) string { return p.ID },
+ func(p Peer) float64 { return p.PingMS },
+ func(p Peer) float64 { return p.Hops },
+ [2]float64{1,1}, [2]bool{false,false}, stats,
+)
+Notes:
+- If min==max for an axis, normalized value is 0 for that axis.
+- invert[i] flips the normalized axis as 1 - n before applying weights[i].
+- These helpers mirror Build2D/3D/4D, but use your provided NormStats instead of recomputing from the items slice.
Poindexter includes helpers to build KD points from arbitrary dimensions.
+func BuildND[T any](
+ items []T,
+ id func(T) string,
+ features []func(T) float64,
+ weights []float64,
+ invert []bool,
+) ([]KDPoint[T], error)
+
+// Like BuildND but never returns an error. It performs no validation beyond
+// basic length checks and propagates NaN/Inf values from feature extractors.
+func BuildNDNoErr[T any](
+ items []T,
+ id func(T) string,
+ features []func(T) float64,
+ weights []float64,
+ invert []bool,
+) []KDPoint[T]
+features: extract raw values per axis.weights: per-axis weights, same length as features.invert: if true for an axis, uses 1 - normalized before weighting (turns “higher is better” into lower cost).ComputeNormStatsND + BuildNDWithStats to reuse normalization between updates.Example:
+pts := poindexter.BuildNDNoErr(records,
+ func(r Rec) string { return r.ID },
+ []func(Rec) float64{
+ func(r Rec) float64 { return r.PingMS },
+ func(r Rec) float64 { return r.Hops },
+ func(r Rec) float64 { return r.GeoKM },
+ func(r Rec) float64 { return r.Score },
+ },
+ []float64{1.0, 0.7, 0.2, 1.2},
+ []bool{false, false, false, true},
+)
+Poindexter provides two internal backends for KDTree queries:
+linear: always available; performs O(n) scans for Nearest, KNearest, and Radius.gonum: optimized KD backend compiled when you build with the gonum build tag; typically sub-linear on prunable datasets and modest dimensions.// KDBackend selects the internal engine used by KDTree.
+type KDBackend string
+
+const (
+ BackendLinear KDBackend = "linear"
+ BackendGonum KDBackend = "gonum"
+)
+
+// WithBackend selects the internal KDTree backend ("linear" or "gonum").
+// If the requested backend is unavailable (e.g., missing build tag), the constructor
+// falls back to the linear backend.
+func WithBackend(b KDBackend) KDOption
+linear.-tags=gonum, the default becomes gonum.// Default metric is Euclidean; you can override with WithMetric.
+pts := []poindexter.KDPoint[string]{
+ {ID: "A", Coords: []float64{0, 0}},
+ {ID: "B", Coords: []float64{1, 0}},
+}
+
+// Force Linear (always available)
+lin, _ := poindexter.NewKDTree(pts, poindexter.WithBackend(poindexter.BackendLinear))
+_, _, _ = lin.Nearest([]float64{0.9, 0.1})
+
+// Force Gonum (requires building with: go build -tags=gonum)
+gon, _ := poindexter.NewKDTree(pts, poindexter.WithBackend(poindexter.BackendGonum))
+_, _, _ = gon.Nearest([]float64{0.9, 0.1})
+See also the Performance guide for measured comparisons and guidance: docs/perf.md.
0&&i[i.length-1])&&(p[0]===6||p[0]===2)){r=0;continue}if(p[0]===3&&(!i||p[1]>i[0]&&p[1]=e.length&&(e=void 0),{value:e&&e[o++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function K(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var o=r.call(e),n,i=[],s;try{for(;(t===void 0||t-- >0)&&!(n=o.next()).done;)i.push(n.value)}catch(a){s={error:a}}finally{try{n&&!n.done&&(r=o.return)&&r.call(o)}finally{if(s)throw s.error}}return i}function B(e,t,r){if(r||arguments.length===2)for(var o=0,n=t.length,i;o