├── .Rbuildignore ├── .github ├── .gitignore └── workflows │ ├── R-CMD-check.yaml │ ├── pkgdown.yaml │ ├── recheck.yml │ └── test-coverage.yaml ├── .gitignore ├── DESCRIPTION ├── NAMESPACE ├── NEWS.md ├── R ├── RANN-package.R ├── nn.R └── zzz.R ├── RANN.Rproj ├── README.md ├── _pkgdown.yml ├── codecov.yml ├── cran-comments-l1.md ├── cran-comments.md ├── inst └── COPYRIGHT ├── man ├── RANN-package.Rd └── nn2.Rd ├── src ├── Makevars ├── Makevars.win ├── NN.cc ├── ann2.cpp ├── init.c └── vendor │ └── ann │ ├── ANN.cpp │ ├── ANN │ ├── ANN.h │ ├── ANNperf.h │ └── ANNx.h │ ├── bd_fix_rad_search.cpp │ ├── bd_pr_search.cpp │ ├── bd_search.cpp │ ├── bd_tree.cpp │ ├── bd_tree.h │ ├── brute.cpp │ ├── kd_dump.cpp │ ├── kd_fix_rad_search.cpp │ ├── kd_fix_rad_search.h │ ├── kd_pr_search.cpp │ ├── kd_pr_search.h │ ├── kd_search.cpp │ ├── kd_search.h │ ├── kd_split.cpp │ ├── kd_split.h │ ├── kd_tree.cpp │ ├── kd_tree.h │ ├── kd_util.cpp │ ├── kd_util.h │ ├── pr_queue.h │ └── pr_queue_k.h └── tests ├── testthat.R └── testthat └── test-nn.R /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^docs$ 2 | ^_pkgdown\.yml$ 3 | .gitignore 4 | .project 5 | .settings 6 | ^test$ 7 | ^.*\.Rproj$ 8 | ^\.Rproj\.user$ 9 | ^cran-comments\.md$ 10 | ^cran-comments-l1\.md$ 11 | ^revdep$ 12 | ^\.github$ 13 | ^pkgdown$ 14 | ^codecov.yml$ 15 | ^CRAN-SUBMISSION$ 16 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: R-CMD-check.yaml 10 | 11 | permissions: read-all 12 | 13 | jobs: 14 | R-CMD-check: 15 | runs-on: ${{ matrix.config.os }} 16 | 17 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 18 | 19 | strategy: 20 | fail-fast: false 21 | matrix: 22 | config: 23 | - {os: macos-latest, r: 'release'} 24 | - {os: windows-latest, r: 'release'} 25 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 26 | - {os: ubuntu-latest, r: 'release'} 27 | - {os: ubuntu-latest, r: 'oldrel-1'} 28 | 29 | env: 30 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 31 | R_KEEP_PKG_SOURCE: yes 32 | 33 | steps: 34 | - uses: actions/checkout@v4 35 | 36 | - uses: r-lib/actions/setup-pandoc@v2 37 | 38 | - uses: r-lib/actions/setup-r@v2 39 | with: 40 | r-version: ${{ matrix.config.r }} 41 | http-user-agent: ${{ matrix.config.http-user-agent }} 42 | use-public-rspm: true 43 | 44 | - uses: r-lib/actions/setup-r-dependencies@v2 45 | with: 46 | extra-packages: any::rcmdcheck 47 | needs: check 48 | 49 | - uses: r-lib/actions/check-r-package@v2 50 | with: 51 | upload-snapshots: true 52 | build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")' 53 | -------------------------------------------------------------------------------- /.github/workflows/pkgdown.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | release: 9 | types: [published] 10 | workflow_dispatch: 11 | 12 | name: pkgdown.yaml 13 | 14 | permissions: read-all 15 | 16 | jobs: 17 | pkgdown: 18 | runs-on: ubuntu-latest 19 | # Only restrict concurrency for non-PR jobs 20 | concurrency: 21 | group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }} 22 | env: 23 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 24 | permissions: 25 | contents: write 26 | steps: 27 | - uses: actions/checkout@v4 28 | 29 | - uses: r-lib/actions/setup-pandoc@v2 30 | 31 | - uses: r-lib/actions/setup-r@v2 32 | with: 33 | use-public-rspm: true 34 | 35 | - uses: r-lib/actions/setup-r-dependencies@v2 36 | with: 37 | extra-packages: any::pkgdown, local::. 38 | needs: website 39 | 40 | - name: Build site 41 | run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) 42 | shell: Rscript {0} 43 | 44 | - name: Deploy to GitHub pages 🚀 45 | if: github.event_name != 'pull_request' 46 | uses: JamesIves/github-pages-deploy-action@v4.5.0 47 | with: 48 | clean: false 49 | branch: gh-pages 50 | folder: docs 51 | -------------------------------------------------------------------------------- /.github/workflows/recheck.yml: -------------------------------------------------------------------------------- 1 | on: 2 | workflow_dispatch: 3 | inputs: 4 | which: 5 | type: choice 6 | description: Which dependents to check 7 | options: 8 | - strong 9 | - most 10 | 11 | name: Reverse dependency check 12 | 13 | jobs: 14 | revdep_check: 15 | name: Reverse check ${{ inputs.which }} dependents 16 | uses: r-devel/recheck/.github/workflows/recheck.yml@v1 17 | with: 18 | which: ${{ inputs.which }} 19 | subdirectory: '' #if your package is in a git subdir 20 | -------------------------------------------------------------------------------- /.github/workflows/test-coverage.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: test-coverage.yaml 10 | 11 | permissions: read-all 12 | 13 | jobs: 14 | test-coverage: 15 | runs-on: ubuntu-latest 16 | env: 17 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 18 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 19 | 20 | steps: 21 | - uses: actions/checkout@v4 22 | 23 | - uses: r-lib/actions/setup-r@v2 24 | with: 25 | use-public-rspm: true 26 | 27 | - uses: r-lib/actions/setup-r-dependencies@v2 28 | with: 29 | extra-packages: any::covr, any::xml2 30 | needs: coverage 31 | 32 | - name: Test coverage 33 | run: | 34 | cov <- covr::package_coverage( 35 | quiet = FALSE, 36 | clean = FALSE, 37 | install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package") 38 | ) 39 | covr::to_cobertura(cov) 40 | shell: Rscript {0} 41 | 42 | - uses: codecov/codecov-action@v4 43 | with: 44 | fail_ci_if_error: ${{ github.event_name != 'pull_request' && true || false }} 45 | file: ./cobertura.xml 46 | plugin: noop 47 | disable_search: true 48 | token: ${{ secrets.CODECOV_TOKEN }} 49 | 50 | - name: Show testthat output 51 | if: always() 52 | run: | 53 | ## -------------------------------------------------------------------- 54 | find '${{ runner.temp }}/package' -name 'testthat.Rout*' -exec cat '{}' \; || true 55 | shell: bash 56 | 57 | - name: Upload test results 58 | if: failure() 59 | uses: actions/upload-artifact@v4 60 | with: 61 | name: coverage-test-failures 62 | path: ${{ runner.temp }}/package 63 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | src/*.o 2 | src/*.so 3 | .Rproj.user 4 | .Rhistory 5 | revdep/ 6 | test/ 7 | docs 8 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: RANN 2 | Title: Fast Nearest Neighbour Search (Wraps ANN Library) Using 3 | L2 Metric 4 | Version: 2.6.2 5 | Authors@R: c( 6 | person("Gregory","Jefferis", email="jefferis@gmail.com", 7 | role = c("aut", "cre"), comment = c(ORCID = "0000-0002-0587-9355")), 8 | person(given = c("Samuel", "E."), family = "Kemp", role = "aut"), 9 | person(given = "Kirill", 10 | family = "M\u00fcller", 11 | role = "ctb", 12 | comment = c(ORCID = "0000-0002-1416-3412")), 13 | person("Sunil","Arya", role=c("aut", "cph"), 14 | comment = c(ORCID = "0000-0003-0939-4192")), 15 | person("David","Mount", role=c("aut", "cph"), 16 | comment = c(ORCID = "0000-0002-3290-8932")), 17 | person("University of Maryland", role="cph", 18 | comment = "ANN library is copyright University of Maryland and Sunil Arya and 19 | David Mount. See file COPYRIGHT for details") 20 | ) 21 | Description: Finds the k nearest neighbours for every point in a 22 | given dataset in O(N log N) time using Arya and Mount's ANN library 23 | (v1.1.3). There is support for approximate as well as exact searches, 24 | fixed radius searches and 'bd' as well as 'kd' trees. The distance is 25 | computed using the L2 (Euclidean) metric. Please see package 'RANN.L1' 26 | for the same functionality using the L1 (Manhattan, taxicab) metric. 27 | License: GPL (>=3) 28 | URL: https://github.com/jefferislab/RANN, https://jefferislab.github.io/RANN/ 29 | BugReports: https://github.com/jefferislab/RANN/issues 30 | Suggests: 31 | testthat 32 | Encoding: UTF-8 33 | RoxygenNote: 7.3.2 34 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(nn2) 4 | useDynLib(RANN) 5 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # RANN 2.6.2 2 | 3 | * define R_NO_REMAP and switch to Rf_* functions at the request of CRAN by 4 | @jefferis in https://github.com/jefferislab/RANN/pull/32 5 | * Use namespacing to isolate ann library and vendor source by @krlmlr in https://github.com/jefferislab/RANN/pull/30 6 | (this could be used to provide the L1 metric in the same package in future) 7 | * switch to github actions by @jefferis in https://github.com/jefferislab/RANN/pull/33 8 | * dev: switch GitHub repo to jefferislab/RANN 9 | 10 | **Full Changelog**: https://github.com/jefferislab/RANN/compare/v2.6.1...v2.6.2 11 | 12 | # RANN 2.6.1 13 | 14 | * Fix Solaris compile error (as requested by BDR, #25) 15 | * Correct usage for compiler vs preprocessor flags (#26) 16 | 17 | # RANN 2.6.0 18 | 19 | * remove register key word from libANN code (at request of CRAN, #23) 20 | 21 | # RANN 2.5.1 22 | 23 | * bug fix wrong result dimensions when query is a vector (#17) 24 | thanks to github user dayey1 25 | * bug fix: check query vs data dimensions 26 | * register native routines (now a NOTE on R 3.4.0) 27 | * fix CRAN URLs in README 28 | 29 | # RANN 2.5.0 30 | 31 | * completely remove defunct nn function 32 | * add note in README about new RANN1 package offering Manhattan (L1) metric as 33 | an alternative to Euclidean (L2) metric. Note that RANN1 is only available on 34 | github at the time of writing). 35 | * dev: use ANN_ROOT macro to unsquare distances 36 | 37 | # RANN 2.4.1 38 | 39 | * fix malformed URL field in DESCRIPTION (K. Hornik) 40 | 41 | # RANN 2.4.0 42 | 43 | * fix crashing bug when receving N x 0 input matrix 44 | (thanks to Rajaraman V for bug report) 45 | * doc: correct documentation of return type and other clarifications. 46 | * dev: switch to testthat for tests 47 | * dev: add Travis CI integration (https://travis-ci.org/jefferis/RANN) 48 | * dev: add rstudio project, retire StatET Eclipse project 49 | 50 | # RANN 2.3.0 51 | 52 | * remove nn() function since underlying get_NN() had memory leaks (noticed by Brian Ripley) 53 | * make nn2() use input data as query when query not specified) 54 | * add Arya and Mount as authors (in accordance with CRAN policies, again BDR) 55 | * add Arya, Mount and University of Maryland in Copyright line 56 | (in accordance with CRAN policies, again BDR) 57 | * add COPYRIGHT file to make it clear exactly which files are from the ANN 58 | library and therefore subject to that library's copyright. 59 | 60 | # RANN 2.2.1 61 | 62 | * fix yet more warnings for CRAN due to presence in ANN of 63 | exit(), std:cout and std:cerr 64 | 65 | # RANN 2.2.0 66 | 67 | * no user-visible changes in theory 68 | * switch to roxygen2 for documentation 69 | * use this to provide a NAMESPACE as requested for CRAN 70 | * and switch from deprecated .First.lib to useDynLib 71 | -------------------------------------------------------------------------------- /R/RANN-package.R: -------------------------------------------------------------------------------- 1 | #' Wrapper for Arya and Mount's Approximate Nearest Neighbours (ANN) C++ library 2 | #' 3 | #' @name RANN-package 4 | #' @aliases RANN 5 | #' @seealso \code{\link{nn2}} 6 | #' @keywords package 7 | "_PACKAGE" 8 | -------------------------------------------------------------------------------- /R/nn.R: -------------------------------------------------------------------------------- 1 | # =============================== 2 | # NEAR NEIGHBOUR FINDER 3 | # =============================== 4 | 5 | 6 | 7 | #'Nearest Neighbour Search 8 | #' 9 | #'Uses a kd-tree to find the p number of near neighbours for each point in an 10 | #'input/output dataset. The advantage of the kd-tree is that it runs in O(M log 11 | #'M) time. 12 | #' 13 | #'The \code{RANN} package utilizes the Approximate Near Neighbor (ANN) C++ 14 | #'library, which can give the exact near neighbours or (as the name suggests) 15 | #'approximate near neighbours to within a specified error bound. For more 16 | #'information on the ANN library please visit 17 | #'\url{https://www.cs.umd.edu/~mount/ANN/}. 18 | #' 19 | #'Search types: \code{priority} visits cells in increasing order of distance 20 | #'from the query point, and hence, should converge more rapidly on the true 21 | #'nearest neighbour, but standard is usually faster for exact searches. 22 | #'\code{radius} only searches for neighbours within a specified radius of the 23 | #'point. If there are no neighbours then nn.idx will contain 0 and nn.dists 24 | #'will contain 1.340781e+154 for that point. 25 | #' 26 | #'@param data An \bold{M} x \bold{d} data.frame or matrix, where each of the 27 | #' \bold{M} rows is a point or a (column) vector (where \bold{d=1}). 28 | #'@param query A set of \bold{N} x \bold{d} points that will be queried against 29 | #' \code{data}. \bold{d}, the number of columns, must be the same as 30 | #' \code{data}. If missing, defaults to \code{data}. 31 | #'@param k The maximum number of nearest neighbours to compute. The default 32 | #' value is set to the smaller of the number of columnns in data 33 | #'@param treetype Character vector specifying the standard \code{'kd'} tree or a 34 | #' \code{'bd'} (box-decomposition, AMNSW98) tree which may perform better for 35 | #' larger point sets 36 | #'@param searchtype See details 37 | #'@param radius Radius of search for searchtype='radius' 38 | #'@param eps Error bound: default of 0.0 implies exact nearest neighbour search 39 | #'@return A \code{list} of length 2 with elements: 40 | #' 41 | #' \item{nn.idx}{A \bold{N} x \bold{k} integer \code{matrix} returning the near 42 | #' neighbour indices.} 43 | #' 44 | #' \item{nn.dists}{A \bold{N} x \bold{k} \code{matrix} returning the near 45 | #' neighbour Euclidean distances.} 46 | #'@author Gregory Jefferis based on earlier code by Samuel E. Kemp (knnFinder 47 | #' package) 48 | #'@references Bentley J. L. (1975), Multidimensional binary search trees used 49 | #' for associative search. Communication ACM, 18:309-517. 50 | #' 51 | #' Arya S. and Mount D. M. (1993), Approximate nearest neighbor searching, 52 | #' Proc. 4th Ann. ACM-SIAM Symposium on Discrete Algorithms (SODA'93), 271-280. 53 | #' 54 | #' Arya S., Mount D. M., Netanyahu N. S., Silverman R. and Wu A. Y (1998), An 55 | #' optimal algorithm for approximate nearest neighbor searching, Journal of the 56 | #' ACM, 45, 891-923. 57 | #'@keywords nonparametric 58 | #'@examples 59 | #' 60 | #'x1 <- runif(100, 0, 2*pi) 61 | #'x2 <- runif(100, 0,3) 62 | #'DATA <- data.frame(x1, x2) 63 | #'nearest <- nn2(DATA,DATA) 64 | #'@export 65 | nn2 <- function(data, query=data, k=min(10,nrow(data)),treetype=c("kd","bd"), 66 | searchtype=c("standard","priority","radius"),radius=0.0,eps=0.0) 67 | { 68 | dimension <- ncol(data) 69 | if(is.null(dimension)) dimension=1L 70 | query_dimension <- ncol(query) 71 | if(is.null(query_dimension)) query_dimension=1L 72 | 73 | ND <- nrow(data) 74 | if(is.null(ND)) ND=length(data) 75 | NQ <- nrow(query) 76 | if(is.null(NQ)) NQ=length(query) 77 | 78 | # Check that both datasets have same dimensionality 79 | if(dimension != query_dimension) 80 | stop("Query and data tables must have same dimensions") 81 | 82 | if(k>ND) 83 | stop("Cannot find more nearest neighbours than there are points") 84 | 85 | searchtypeInt=pmatch(searchtype[1],c("standard","priority","radius")) 86 | if(is.na(searchtypeInt)) stop(paste("Unknown search type",searchtype)) 87 | treetype=match.arg(treetype,c("kd","bd")) 88 | 89 | # Coerce to matrix form 90 | if(is.data.frame(data)) 91 | data <- unlist(data,use.names=FALSE) 92 | 93 | if(!length(data)) stop("no points in data!") 94 | 95 | # Coerce to matrix form 96 | if(!is.matrix(query)) 97 | query <- unlist(query,use.names=FALSE) 98 | 99 | if(!length(query)) stop("no points in query!") 100 | 101 | # void get_NN_2Set(double *data, double *query, int *D, int *ND, int *NQ, int *K, double *EPS, 102 | # int *nn_index, double *distances) 103 | 104 | results <- .C("get_NN_2Set", 105 | as.double(data), 106 | as.double(query), 107 | as.integer(dimension), 108 | as.integer(ND), 109 | as.integer(NQ), 110 | as.integer(k), 111 | as.double(eps), 112 | as.integer(searchtypeInt), 113 | as.integer(treetype=="bd"), 114 | as.double(radius*radius), 115 | nn.idx = integer(k*NQ), 116 | nn = double(k*NQ), PACKAGE="RANN") 117 | 118 | # now put the returned vectors into (nq x k) arrays 119 | nn.indexes=matrix(results$nn.idx,ncol=k,byrow=TRUE) 120 | nn.dist=matrix(results$nn,ncol=k,byrow=TRUE) 121 | 122 | return(list(nn.idx=nn.indexes, nn.dists=nn.dist)) 123 | } 124 | -------------------------------------------------------------------------------- /R/zzz.R: -------------------------------------------------------------------------------- 1 | #' @useDynLib RANN 2 | NULL -------------------------------------------------------------------------------- /RANN.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | 17 | BuildType: Package 18 | PackageUseDevtools: Yes 19 | PackageInstallArgs: --no-multiarch --with-keep.source 20 | PackageRoxygenize: rd,collate,namespace 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RANN 2 | [![Release Version](https://img.shields.io/github/release/jefferislab/RANN.svg)](https://github.com/jefferislab/RANN/releases/latest) 3 | [![CRAN_Status_Badge](https://www.r-pkg.org/badges/version/RANN)](https://CRAN.R-project.org/package=RANN) 4 | [![R-CMD-check](https://github.com/jefferis/RANN/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/jefferislab/RANN/actions/workflows/R-CMD-check.yaml) 5 | [![Codecov test coverage](https://codecov.io/gh/jefferislab/RANN/graph/badge.svg)](https://app.codecov.io/gh/jefferislab/RANN) 6 | [![Downloads](https://cranlogs.r-pkg.org/badges/RANN?color=brightgreen)](https://www.r-pkg.org/pkg/RANN) 7 | 8 | Finds the k nearest neighbours for every point in a given dataset 9 | in O(N log N) time using Arya and Mount's ANN library (v1.1.3). There is 10 | support for approximate as well as exact searches, fixed radius searches 11 | and bd as well as kd trees. 12 | 13 | This package implements nearest neighbors for the Euclidean (L2) metric. 14 | For the Manhattan (L1) metric, install the [RANN1](https://github.com/jefferislab/RANN/tree/master-L1) package. 15 | 16 | For further details on the underlying ANN library, see https://www.cs.umd.edu/~mount/ANN. 17 | 18 | ## Installation 19 | ### Released versions 20 | The recommendation is to install the released version from [CRAN](https://cran.r-project.org/) by doing: 21 | 22 | ```r 23 | install.packages("RANN") 24 | ``` 25 | 26 | ### Bleeding Edge 27 | You can, however, use the **remotes** package to install the development version: 28 | 29 | ```r 30 | # install.packages("remotes") 31 | remotes::install_github("jefferis/RANN") 32 | ``` 33 | 34 | ## Feedback 35 | Please feel free to: 36 | 37 | * submit suggestions and bug-reports at: 38 | * send pull requests after forking: 39 | * e-mail the maintainer: 40 | 41 | ## Copyright and License 42 | see [inst/COPYRIGHT](inst/COPYRIGHT) and [DESCRIPTION](DESCRIPTION) files for copyright and license information. 43 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | url: https://jefferislab.github.io/RANN/ 2 | template: 3 | bootstrap: 5 4 | 5 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | 3 | coverage: 4 | status: 5 | project: 6 | default: 7 | target: auto 8 | threshold: 1% 9 | informational: true 10 | patch: 11 | default: 12 | target: auto 13 | threshold: 1% 14 | informational: true 15 | -------------------------------------------------------------------------------- /cran-comments-l1.md: -------------------------------------------------------------------------------- 1 | - New submission, originally submitted as RANN1 2 | - Difference to existing package RANN: Metric used for computing distances. RANN uses L2, RANN.L1 uses L1. The underlying ANN library requires changing of preprocessor defines to change the metric; using two similar R packages seems to be the simplest solution to provide ANN implementations with different metrics for the R community. 3 | - Checked against R 3.2.0 on Ubuntu, R-devel (r68301) on Debian and R 3.2.0 and R-devel (r68289) on win-builder 4 | - Fixed quoting of 'RANN' in description 5 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## Changes since last release 2 | 3 | The key change is to define R_NO_REMAP and switch to Rf_* functions at the 4 | request of Kurt Hornik and the CRAN team. 5 | 6 | ## Test environments 7 | * local OS X install, R 4.4.1 8 | * win-builder (devel) 9 | * github actions (ubuntu, windows, macosx) 10 | 11 | No checks gave any ERRORs, WARNINGs or NOTEs. 12 | 13 | https://win-builder.r-project.org/I5PnQS3ID3NQ 14 | 15 | Reverse dependency checks did not identify any changes for the worse. 16 | 17 | https://github.com/jefferislab/RANN/actions/runs/10539637944/job/29204049753 18 | -------------------------------------------------------------------------------- /inst/COPYRIGHT: -------------------------------------------------------------------------------- 1 | This R package is copyright Samuel Kemp 2005-9 and and Gregory Jefferis 2 | 2009-2024, with the exception of files from v 1.1.3 of the ANN library, 3 | consisting of all files in src/vendor which are copyright as described below. 4 | 5 | -- 6 | ANN: Approximate Nearest Neighbors 7 | Version: 1.1.3 8 | Release date: Feb 5, 2010 9 | ---------------------------------------------------------------------------- 10 | Copyright (c) 1997-2010 University of Maryland and Sunil Arya and David 11 | Mount All Rights Reserved. 12 | 13 | This program is free software; you can redistribute it and/or modify it 14 | under the terms of the GNU Lesser Public License as published by the 15 | Free Software Foundation; either version 2.1 of the License, or (at your 16 | option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, but 19 | WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 | Lesser Public License for more details. 22 | 23 | A copy of the terms and conditions of the license can be found in 24 | License.txt or online at 25 | 26 | https://www.gnu.org/licenses/lgpl-3.0.html 27 | 28 | To obtain a copy, write to the Free Software Foundation, Inc., 29 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 30 | 31 | Disclaimer 32 | ---------- 33 | The University of Maryland and the authors make no representations about 34 | the suitability or fitness of this software for any purpose. It is 35 | provided "as is" without express or implied warranty. 36 | --------------------------------------------------------------------- 37 | 38 | Authors 39 | ------- 40 | David Mount 41 | Dept of Computer Science 42 | University of Maryland, 43 | College Park, MD 20742 USA 44 | mount@cs.umd.edu 45 | https://www.cs.umd.edu/~mount/ 46 | 47 | Sunil Arya 48 | Dept of Computer Science 49 | Hong University of Science and Technology 50 | Clearwater Bay, HONG KONG 51 | arya@cs.ust.hk 52 | https://cse.hkust.edu.hk/faculty/arya/ 53 | -------------------------------------------------------------------------------- /man/RANN-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/RANN-package.R 3 | \docType{package} 4 | \name{RANN-package} 5 | \alias{RANN-package} 6 | \alias{RANN} 7 | \title{Wrapper for Arya and Mount's Approximate Nearest Neighbours (ANN) C++ library} 8 | \description{ 9 | Finds the k nearest neighbours for every point in a given dataset in O(N log N) time using Arya and Mount's ANN library (v1.1.3). There is support for approximate as well as exact searches, fixed radius searches and 'bd' as well as 'kd' trees. The distance is computed using the L2 (Euclidean) metric. Please see package 'RANN.L1' for the same functionality using the L1 (Manhattan, taxicab) metric. 10 | } 11 | \seealso{ 12 | \code{\link{nn2}} 13 | } 14 | \author{ 15 | \strong{Maintainer}: Gregory Jefferis \email{jefferis@gmail.com} (\href{https://orcid.org/0000-0002-0587-9355}{ORCID}) 16 | 17 | Authors: 18 | \itemize{ 19 | \item Samuel E. Kemp 20 | \item Sunil Arya (\href{https://orcid.org/0000-0003-0939-4192}{ORCID}) [copyright holder] 21 | \item David Mount (\href{https://orcid.org/0000-0002-3290-8932}{ORCID}) [copyright holder] 22 | } 23 | 24 | Other contributors: 25 | \itemize{ 26 | \item Kirill Müller (\href{https://orcid.org/0000-0002-1416-3412}{ORCID}) [contributor] 27 | \item University of Maryland (ANN library is copyright University of Maryland and Sunil Arya and David Mount. See file COPYRIGHT for details) [copyright holder] 28 | } 29 | 30 | } 31 | \keyword{package} 32 | -------------------------------------------------------------------------------- /man/nn2.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/nn.R 3 | \name{nn2} 4 | \alias{nn2} 5 | \title{Nearest Neighbour Search} 6 | \usage{ 7 | nn2( 8 | data, 9 | query = data, 10 | k = min(10, nrow(data)), 11 | treetype = c("kd", "bd"), 12 | searchtype = c("standard", "priority", "radius"), 13 | radius = 0, 14 | eps = 0 15 | ) 16 | } 17 | \arguments{ 18 | \item{data}{An \bold{M} x \bold{d} data.frame or matrix, where each of the 19 | \bold{M} rows is a point or a (column) vector (where \bold{d=1}).} 20 | 21 | \item{query}{A set of \bold{N} x \bold{d} points that will be queried against 22 | \code{data}. \bold{d}, the number of columns, must be the same as 23 | \code{data}. If missing, defaults to \code{data}.} 24 | 25 | \item{k}{The maximum number of nearest neighbours to compute. The default 26 | value is set to the smaller of the number of columnns in data} 27 | 28 | \item{treetype}{Character vector specifying the standard \code{'kd'} tree or a 29 | \code{'bd'} (box-decomposition, AMNSW98) tree which may perform better for 30 | larger point sets} 31 | 32 | \item{searchtype}{See details} 33 | 34 | \item{radius}{Radius of search for searchtype='radius'} 35 | 36 | \item{eps}{Error bound: default of 0.0 implies exact nearest neighbour search} 37 | } 38 | \value{ 39 | A \code{list} of length 2 with elements: 40 | 41 | \item{nn.idx}{A \bold{N} x \bold{k} integer \code{matrix} returning the near 42 | neighbour indices.} 43 | 44 | \item{nn.dists}{A \bold{N} x \bold{k} \code{matrix} returning the near 45 | neighbour Euclidean distances.} 46 | } 47 | \description{ 48 | Uses a kd-tree to find the p number of near neighbours for each point in an 49 | input/output dataset. The advantage of the kd-tree is that it runs in O(M log 50 | M) time. 51 | } 52 | \details{ 53 | The \code{RANN} package utilizes the Approximate Near Neighbor (ANN) C++ 54 | library, which can give the exact near neighbours or (as the name suggests) 55 | approximate near neighbours to within a specified error bound. For more 56 | information on the ANN library please visit 57 | \url{https://www.cs.umd.edu/~mount/ANN/}. 58 | 59 | Search types: \code{priority} visits cells in increasing order of distance 60 | from the query point, and hence, should converge more rapidly on the true 61 | nearest neighbour, but standard is usually faster for exact searches. 62 | \code{radius} only searches for neighbours within a specified radius of the 63 | point. If there are no neighbours then nn.idx will contain 0 and nn.dists 64 | will contain 1.340781e+154 for that point. 65 | } 66 | \examples{ 67 | 68 | x1 <- runif(100, 0, 2*pi) 69 | x2 <- runif(100, 0,3) 70 | DATA <- data.frame(x1, x2) 71 | nearest <- nn2(DATA,DATA) 72 | } 73 | \references{ 74 | Bentley J. L. (1975), Multidimensional binary search trees used 75 | for associative search. Communication ACM, 18:309-517. 76 | 77 | Arya S. and Mount D. M. (1993), Approximate nearest neighbor searching, 78 | Proc. 4th Ann. ACM-SIAM Symposium on Discrete Algorithms (SODA'93), 271-280. 79 | 80 | Arya S., Mount D. M., Netanyahu N. S., Silverman R. and Wu A. Y (1998), An 81 | optimal algorithm for approximate nearest neighbor searching, Journal of the 82 | ACM, 45, 891-923. 83 | } 84 | \author{ 85 | Gregory Jefferis based on earlier code by Samuel E. Kemp (knnFinder 86 | package) 87 | } 88 | \keyword{nonparametric} 89 | -------------------------------------------------------------------------------- /src/Makevars: -------------------------------------------------------------------------------- 1 | PKG_CPPFLAGS=-I. -Ivendor/ann -DRANN 2 | -------------------------------------------------------------------------------- /src/Makevars.win: -------------------------------------------------------------------------------- 1 | PKG_LIBS=-lws2_32 2 | PKG_CXXFLAGS += -O3 3 | PKG_CPPFLAGS += -I. -Ivendor/ann -DWIN32 -DDLL_EXPORTS -DANN_NO_RANDOM -DRANN 4 | -------------------------------------------------------------------------------- /src/NN.cc: -------------------------------------------------------------------------------- 1 | #include // C standard lib defs 2 | #include // I/O manipulators 3 | #include // math includes 4 | #include // I/O streams 5 | #include // C-style strings 6 | 7 | #include // math routines 8 | #define R_NO_REMAP 9 | #include // R header 10 | 11 | namespace ann2 { 12 | 13 | #include "ANN/ANN.h" // ANN library header 14 | 15 | } 16 | 17 | //------------------------------------------------------------------------------------------------ 18 | // Near Neighbours Program 19 | //------------------------------------------------------------------------------------------------ 20 | extern "C" 21 | { 22 | void get_NN_2Set(double *data, double *query, int *D, int *ND, int *NQ, int *K, double *EPS, 23 | int *SEARCHTYPE, int *USEBDTREE, double *SQRAD, int *nn_index, double *distances) 24 | { 25 | using namespace ann2; 26 | 27 | const int d = *D; // Number of Dimensions for points 28 | const int nd = *ND; // Number of Data points 29 | const int nq= *NQ; // Number of Query points 30 | const int k = *K; // Maximum number of Nearest Neighbours 31 | 32 | const int searchtype = *SEARCHTYPE; 33 | const bool usebdtree = *USEBDTREE?true:false; 34 | 35 | const double error_bound = *EPS; // enough said! 36 | const double sqRad = *SQRAD; // Squared Radius for rad search 37 | 38 | ANNkd_tree *the_tree; // Search structure 39 | 40 | ANNpointArray data_pts = annAllocPts(nd,d); // Allocate data points 41 | ANNidxArray nn_idx = new ANNidx[k]; // Allocate near neigh indices 42 | ANNdistArray dists = new ANNdist[k]; // Allocate near neighbor dists 43 | 44 | int *d_ptr = new int[d]; 45 | int ptr = 0; 46 | 47 | // set up column offsets for query point matrix (to convert Row/Col major) 48 | for(int i = 0; i < d; i++) 49 | { 50 | d_ptr[i] = i*nd; 51 | } 52 | 53 | for(int i = 0; i < nd; i++) // now construct the points 54 | { 55 | for(int j = 0; j < d; j++) 56 | { 57 | data_pts[i][j]=data[ d_ptr[j]++ ]; 58 | } 59 | } 60 | 61 | if(usebdtree){ 62 | the_tree = new ANNbd_tree( // Build search structure 63 | data_pts, // The data points 64 | nd, // Number of data points 65 | d); // Dimension of space 66 | } else { 67 | the_tree = new ANNkd_tree( data_pts, nd, d); 68 | } 69 | 70 | // set up offsets for query point matrix (to convert Row / Col major) 71 | for(int i = 0; i < d; i++) 72 | { 73 | d_ptr[i] = i*nq; 74 | } 75 | 76 | ANNpoint pq = annAllocPt(d); 77 | for(int i = 0; i < nq; i++) // Run all query points against tree 78 | { 79 | // read coords of current query point 80 | for(int j = 0; j < d; j++) 81 | { 82 | pq[j]=query[ d_ptr[j]++ ]; 83 | } 84 | 85 | switch(searchtype){ 86 | case 1: 87 | the_tree->annkSearch( // search 88 | pq, // query point 89 | k, // number of near neighbors 90 | nn_idx, // nearest neighbors (returned) 91 | dists, // distance (returned) 92 | error_bound); // error bound 93 | break; 94 | 95 | case 2: // Priority search 96 | the_tree->annkPriSearch(pq, k, nn_idx, dists, error_bound); 97 | break; 98 | 99 | case 3: // Fixed radius search 100 | the_tree->annkFRSearch( pq, sqRad, k, nn_idx, dists,error_bound); 101 | break; 102 | } 103 | 104 | for (int j = 0; j < k; j++) 105 | { 106 | distances[ptr] = ANN_ROOT(dists[j]); // unsquare distance 107 | nn_index[ptr++] = nn_idx[j] + 1; // put indices in returned array 108 | } 109 | } 110 | 111 | // Do a little bit of memory management...... 112 | annDeallocPt(pq); 113 | annDeallocPts(data_pts); 114 | delete [] nn_idx; 115 | delete [] dists; 116 | delete [] d_ptr; 117 | delete the_tree; 118 | } 119 | } 120 | 121 | -------------------------------------------------------------------------------- /src/ann2.cpp: -------------------------------------------------------------------------------- 1 | #include // C standard lib defs 2 | #include // I/O manipulators 3 | #include // math includes 4 | #include // I/O streams 5 | #include // C-style strings 6 | 7 | #ifdef RANN 8 | #define R_NO_REMAP 9 | #include // R headers for error handling 10 | #endif 11 | 12 | 13 | namespace ann2 { 14 | 15 | #include "vendor/ann/ANN.cpp" 16 | #include "vendor/ann/bd_fix_rad_search.cpp" 17 | #include "vendor/ann/bd_pr_search.cpp" 18 | #include "vendor/ann/bd_search.cpp" 19 | #include "vendor/ann/bd_tree.cpp" 20 | #include "vendor/ann/brute.cpp" 21 | #include "vendor/ann/kd_dump.cpp" 22 | #include "vendor/ann/kd_fix_rad_search.cpp" 23 | #include "vendor/ann/kd_pr_search.cpp" 24 | #include "vendor/ann/kd_search.cpp" 25 | #include "vendor/ann/kd_split.cpp" 26 | #include "vendor/ann/kd_tree.cpp" 27 | #include "vendor/ann/kd_util.cpp" 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/init.c: -------------------------------------------------------------------------------- 1 | #include // for NULL 2 | #include 3 | 4 | /* FIXME: 5 | Check these declarations against the C/Fortran source code. 6 | */ 7 | 8 | /* .C calls */ 9 | extern void get_NN_2Set(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *); 10 | 11 | static const R_CMethodDef CEntries[] = { 12 | {"get_NN_2Set", (DL_FUNC) &get_NN_2Set, 12}, 13 | {NULL, NULL, 0} 14 | }; 15 | 16 | void R_init_RANN(DllInfo *dll) 17 | { 18 | R_registerRoutines(dll, CEntries, NULL, NULL, NULL); 19 | R_useDynamicSymbols(dll, FALSE); 20 | } 21 | -------------------------------------------------------------------------------- /src/vendor/ann/ANN.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // File: ANN.cpp 3 | // Programmer: Sunil Arya and David Mount 4 | // Description: Methods for ANN.h and ANNx.h 5 | // Last modified: 01/27/10 (Version 1.1.2) 6 | //---------------------------------------------------------------------- 7 | // Copyright (c) 1997-2010 University of Maryland and Sunil Arya and 8 | // David Mount. All Rights Reserved. 9 | // 10 | // This software and related documentation is part of the Approximate 11 | // Nearest Neighbor Library (ANN). This software is provided under 12 | // the provisions of the Lesser GNU Public License (LGPL). See the 13 | // file ../ReadMe.txt for further information. 14 | // 15 | // The University of Maryland (U.M.) and the authors make no 16 | // representations about the suitability or fitness of this software for 17 | // any purpose. It is provided "as is" without express or implied 18 | // warranty. 19 | //---------------------------------------------------------------------- 20 | // History: 21 | // Revision 0.1 03/04/98 22 | // Initial release 23 | // Revision 1.0 04/01/05 24 | // Added performance counting to annDist() 25 | // Revision 1.1.2 01/27/10 26 | // Fixed minor compilation bugs for new versions of gcc 27 | //---------------------------------------------------------------------- 28 | 29 | #include // C standard lib defs 30 | #include // all ANN includes 31 | #include // ANN performance 32 | #ifdef RANN 33 | #define R_NO_REMAP 34 | #include // R headers for error handling 35 | #endif 36 | 37 | using namespace std; // make std:: accessible 38 | 39 | //---------------------------------------------------------------------- 40 | // Point methods 41 | //---------------------------------------------------------------------- 42 | 43 | //---------------------------------------------------------------------- 44 | // Distance utility. 45 | // (Note: In the nearest neighbor search, most distances are 46 | // computed using partial distance calculations, not this 47 | // procedure.) 48 | //---------------------------------------------------------------------- 49 | 50 | ANNdist annDist( // interpoint squared distance 51 | int dim, 52 | ANNpoint p, 53 | ANNpoint q) 54 | { 55 | int d; 56 | ANNcoord diff; 57 | ANNcoord dist; 58 | 59 | dist = 0; 60 | for (d = 0; d < dim; d++) { 61 | diff = p[d] - q[d]; 62 | dist = ANN_SUM(dist, ANN_POW(diff)); 63 | } 64 | ANN_FLOP(3*dim) // performance counts 65 | ANN_PTS(1) 66 | ANN_COORD(dim) 67 | return dist; 68 | } 69 | 70 | //---------------------------------------------------------------------- 71 | // annPrintPoint() prints a point to a given output stream. 72 | //---------------------------------------------------------------------- 73 | 74 | void annPrintPt( // print a point 75 | ANNpoint pt, // the point 76 | int dim, // the dimension 77 | std::ostream &out) // output stream 78 | { 79 | for (int j = 0; j < dim; j++) { 80 | out << pt[j]; 81 | if (j < dim-1) out << " "; 82 | } 83 | } 84 | 85 | //---------------------------------------------------------------------- 86 | // Point allocation/deallocation: 87 | // 88 | // Because points (somewhat like strings in C) are stored 89 | // as pointers. Consequently, creating and destroying 90 | // copies of points may require storage allocation. These 91 | // procedures do this. 92 | // 93 | // annAllocPt() and annDeallocPt() allocate a deallocate 94 | // storage for a single point, and return a pointer to it. 95 | // 96 | // annAllocPts() allocates an array of points as well a place 97 | // to store their coordinates, and initializes the points to 98 | // point to their respective coordinates. It allocates point 99 | // storage in a contiguous block large enough to store all the 100 | // points. It performs no initialization. 101 | // 102 | // annDeallocPts() should only be used on point arrays allocated 103 | // by annAllocPts since it assumes that points are allocated in 104 | // a block. 105 | // 106 | // annCopyPt() copies a point taking care to allocate storage 107 | // for the new point. 108 | // 109 | // annAssignRect() assigns the coordinates of one rectangle to 110 | // another. The two rectangles must have the same dimension 111 | // (and it is not possible to test this here). 112 | //---------------------------------------------------------------------- 113 | 114 | ANNpoint annAllocPt(int dim, ANNcoord c) // allocate 1 point 115 | { 116 | ANNpoint p = new ANNcoord[dim]; 117 | for (int i = 0; i < dim; i++) p[i] = c; 118 | return p; 119 | } 120 | 121 | ANNpointArray annAllocPts(int n, int dim) // allocate n pts in dim 122 | { 123 | ANNpointArray pa = new ANNpoint[n]; // allocate points 124 | ANNpoint p = new ANNcoord[n*dim]; // allocate space for coords 125 | for (int i = 0; i < n; i++) { 126 | pa[i] = &(p[i*dim]); 127 | } 128 | return pa; 129 | } 130 | 131 | void annDeallocPt(ANNpoint &p) // deallocate 1 point 132 | { 133 | delete [] p; 134 | p = NULL; 135 | } 136 | 137 | void annDeallocPts(ANNpointArray &pa) // deallocate points 138 | { 139 | delete [] pa[0]; // dealloc coordinate storage 140 | delete [] pa; // dealloc points 141 | pa = NULL; 142 | } 143 | 144 | ANNpoint annCopyPt(int dim, ANNpoint source) // copy point 145 | { 146 | ANNpoint p = new ANNcoord[dim]; 147 | for (int i = 0; i < dim; i++) p[i] = source[i]; 148 | return p; 149 | } 150 | 151 | // assign one rect to another 152 | void annAssignRect(int dim, ANNorthRect &dest, const ANNorthRect &source) 153 | { 154 | for (int i = 0; i < dim; i++) { 155 | dest.lo[i] = source.lo[i]; 156 | dest.hi[i] = source.hi[i]; 157 | } 158 | } 159 | 160 | // is point inside rectangle? 161 | ANNbool ANNorthRect::inside(int dim, ANNpoint p) 162 | { 163 | for (int i = 0; i < dim; i++) { 164 | if (p[i] < lo[i] || p[i] > hi[i]) return ANNfalse; 165 | } 166 | return ANNtrue; 167 | } 168 | 169 | //---------------------------------------------------------------------- 170 | // Error handler 171 | //---------------------------------------------------------------------- 172 | 173 | void annError(const char* msg, ANNerr level) 174 | { 175 | if (level == ANNabort) { 176 | #ifdef RANN 177 | Rf_error("RANN: %s",msg); 178 | #else 179 | cerr << "ANN: ERROR------->" << msg << "<-------------ERROR\n"; 180 | exit(1); 181 | #endif 182 | } 183 | else { 184 | #ifdef RANN 185 | Rf_warning("RANN: %s",msg); 186 | #else 187 | cerr << "ANN: WARNING----->" << msg << "<-------------WARNING\n"; 188 | #endif 189 | } 190 | } 191 | 192 | //---------------------------------------------------------------------- 193 | // Limit on number of points visited 194 | // We have an option for terminating the search early if the 195 | // number of points visited exceeds some threshold. If the 196 | // threshold is 0 (its default) this means there is no limit 197 | // and the algorithm applies its normal termination condition. 198 | // This is for applications where there are real time constraints 199 | // on the running time of the algorithm. 200 | //---------------------------------------------------------------------- 201 | 202 | int ANNmaxPtsVisited = 0; // maximum number of pts visited 203 | int ANNptsVisited; // number of pts visited in search 204 | 205 | //---------------------------------------------------------------------- 206 | // Global function declarations 207 | //---------------------------------------------------------------------- 208 | 209 | void annMaxPtsVisit( // set limit on max. pts to visit in search 210 | int maxPts) // the limit 211 | { 212 | ANNmaxPtsVisited = maxPts; 213 | } 214 | -------------------------------------------------------------------------------- /src/vendor/ann/ANN/ANNperf.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // File: ANNperf.h 3 | // Programmer: Sunil Arya and David Mount 4 | // Last modified: 03/04/98 (Release 0.1) 5 | // Description: Include file for ANN performance stats 6 | // 7 | // Some of the code for statistics gathering has been adapted 8 | // from the SmplStat.h package in the g++ library. 9 | //---------------------------------------------------------------------- 10 | // Copyright (c) 1997-2005 University of Maryland and Sunil Arya and 11 | // David Mount. All Rights Reserved. 12 | // 13 | // This software and related documentation is part of the Approximate 14 | // Nearest Neighbor Library (ANN). This software is provided under 15 | // the provisions of the Lesser GNU Public License (LGPL). See the 16 | // file ../ReadMe.txt for further information. 17 | // 18 | // The University of Maryland (U.M.) and the authors make no 19 | // representations about the suitability or fitness of this software for 20 | // any purpose. It is provided "as is" without express or implied 21 | // warranty. 22 | //---------------------------------------------------------------------- 23 | // History: 24 | // Revision 0.1 03/04/98 25 | // Initial release 26 | // Revision 1.0 04/01/05 27 | // Added ANN_ prefix to avoid name conflicts. 28 | //---------------------------------------------------------------------- 29 | 30 | #ifndef ANNperf_H 31 | #define ANNperf_H 32 | 33 | //---------------------------------------------------------------------- 34 | // basic includes 35 | //---------------------------------------------------------------------- 36 | 37 | #include // basic ANN includes 38 | 39 | //---------------------------------------------------------------------- 40 | // kd-tree stats object 41 | // This object is used for collecting information about a kd-tree 42 | // or bd-tree. 43 | //---------------------------------------------------------------------- 44 | 45 | class ANNkdStats { // stats on kd-tree 46 | public: 47 | int dim; // dimension of space 48 | int n_pts; // no. of points 49 | int bkt_size; // bucket size 50 | int n_lf; // no. of leaves (including trivial) 51 | int n_tl; // no. of trivial leaves (no points) 52 | int n_spl; // no. of splitting nodes 53 | int n_shr; // no. of shrinking nodes (for bd-trees) 54 | int depth; // depth of tree 55 | float sum_ar; // sum of leaf aspect ratios 56 | float avg_ar; // average leaf aspect ratio 57 | // 58 | // reset stats 59 | void reset(int d=0, int n=0, int bs=0) 60 | { 61 | dim = d; n_pts = n; bkt_size = bs; 62 | n_lf = n_tl = n_spl = n_shr = depth = 0; 63 | sum_ar = avg_ar = 0.0; 64 | } 65 | 66 | ANNkdStats() // basic constructor 67 | { reset(); } 68 | 69 | void merge(const ANNkdStats &st); // merge stats from child 70 | }; 71 | 72 | //---------------------------------------------------------------------- 73 | // ANNsampStat 74 | // A sample stat collects numeric (double) samples and returns some 75 | // simple statistics. Its main functions are: 76 | // 77 | // reset() Reset to no samples. 78 | // += x Include sample x. 79 | // samples() Return number of samples. 80 | // mean() Return mean of samples. 81 | // stdDev() Return standard deviation 82 | // min() Return minimum of samples. 83 | // max() Return maximum of samples. 84 | //---------------------------------------------------------------------- 85 | class DLL_API ANNsampStat { 86 | int n; // number of samples 87 | double sum; // sum 88 | double sum2; // sum of squares 89 | double minVal, maxVal; // min and max 90 | public : 91 | void reset() // reset everything 92 | { 93 | n = 0; 94 | sum = sum2 = 0; 95 | minVal = ANN_DBL_MAX; 96 | maxVal = -ANN_DBL_MAX; 97 | } 98 | 99 | ANNsampStat() { reset(); } // constructor 100 | 101 | void operator+=(double x) // add sample 102 | { 103 | n++; sum += x; sum2 += x*x; 104 | if (x < minVal) minVal = x; 105 | if (x > maxVal) maxVal = x; 106 | } 107 | 108 | int samples() { return n; } // number of samples 109 | 110 | double mean() { return sum/n; } // mean 111 | 112 | // standard deviation 113 | double stdDev() { return std::sqrt((sum2 - (sum*sum)/n)/(n-1));} 114 | 115 | double min() { return minVal; } // minimum 116 | double max() { return maxVal; } // maximum 117 | }; 118 | 119 | //---------------------------------------------------------------------- 120 | // Operation count updates 121 | //---------------------------------------------------------------------- 122 | 123 | #ifdef ANN_PERF 124 | #define ANN_FLOP(n) {ann_Nfloat_ops += (n);} 125 | #define ANN_LEAF(n) {ann_Nvisit_lfs += (n);} 126 | #define ANN_SPL(n) {ann_Nvisit_spl += (n);} 127 | #define ANN_SHR(n) {ann_Nvisit_shr += (n);} 128 | #define ANN_PTS(n) {ann_Nvisit_pts += (n);} 129 | #define ANN_COORD(n) {ann_Ncoord_hts += (n);} 130 | #else 131 | #define ANN_FLOP(n) 132 | #define ANN_LEAF(n) 133 | #define ANN_SPL(n) 134 | #define ANN_SHR(n) 135 | #define ANN_PTS(n) 136 | #define ANN_COORD(n) 137 | #endif 138 | 139 | //---------------------------------------------------------------------- 140 | // Performance statistics 141 | // The following data and routines are used for computing performance 142 | // statistics for nearest neighbor searching. Because these routines 143 | // can slow the code down, they can be activated and deactiviated by 144 | // defining the ANN_PERF variable, by compiling with the option: 145 | // -DANN_PERF 146 | //---------------------------------------------------------------------- 147 | 148 | //---------------------------------------------------------------------- 149 | // Global counters for performance measurement 150 | // 151 | // visit_lfs The number of leaf nodes visited in the 152 | // tree. 153 | // 154 | // visit_spl The number of splitting nodes visited in the 155 | // tree. 156 | // 157 | // visit_shr The number of shrinking nodes visited in the 158 | // tree. 159 | // 160 | // visit_pts The number of points visited in all the 161 | // leaf nodes visited. Equivalently, this 162 | // is the number of points for which distance 163 | // calculations are performed. 164 | // 165 | // coord_hts The number of times a coordinate of a 166 | // data point is accessed. This is generally 167 | // less than visit_pts*d if partial distance 168 | // calculation is used. This count is low 169 | // in the sense that if a coordinate is hit 170 | // many times in the same routine we may 171 | // count it only once. 172 | // 173 | // float_ops The number of floating point operations. 174 | // This includes all operations in the heap 175 | // as well as distance calculations to boxes. 176 | // 177 | // average_err The average error of each query (the 178 | // error of the reported point to the true 179 | // nearest neighbor). For k nearest neighbors 180 | // the error is computed k times. 181 | // 182 | // rank_err The rank error of each query (the difference 183 | // in the rank of the reported point and its 184 | // true rank). 185 | // 186 | // data_pts The number of data points. This is not 187 | // a counter, but used in stats computation. 188 | //---------------------------------------------------------------------- 189 | 190 | extern int ann_Ndata_pts; // number of data points 191 | extern int ann_Nvisit_lfs; // number of leaf nodes visited 192 | extern int ann_Nvisit_spl; // number of splitting nodes visited 193 | extern int ann_Nvisit_shr; // number of shrinking nodes visited 194 | extern int ann_Nvisit_pts; // visited points for one query 195 | extern int ann_Ncoord_hts; // coordinate hits for one query 196 | extern int ann_Nfloat_ops; // floating ops for one query 197 | extern ANNsampStat ann_visit_lfs; // stats on leaf nodes visits 198 | extern ANNsampStat ann_visit_spl; // stats on splitting nodes visits 199 | extern ANNsampStat ann_visit_shr; // stats on shrinking nodes visits 200 | extern ANNsampStat ann_visit_nds; // stats on total nodes visits 201 | extern ANNsampStat ann_visit_pts; // stats on points visited 202 | extern ANNsampStat ann_coord_hts; // stats on coordinate hits 203 | extern ANNsampStat ann_float_ops; // stats on floating ops 204 | //---------------------------------------------------------------------- 205 | // The following need to be part of the public interface, because 206 | // they are accessed outside the DLL in ann_test.cpp. 207 | //---------------------------------------------------------------------- 208 | DLL_API extern ANNsampStat ann_average_err; // average error 209 | DLL_API extern ANNsampStat ann_rank_err; // rank error 210 | 211 | //---------------------------------------------------------------------- 212 | // Declaration of externally accessible routines for statistics 213 | //---------------------------------------------------------------------- 214 | 215 | DLL_API void annResetStats(int data_size); // reset stats for a set of queries 216 | 217 | DLL_API void annResetCounts(); // reset counts for one queries 218 | 219 | DLL_API void annUpdateStats(); // update stats with current counts 220 | 221 | DLL_API void annPrintStats(ANNbool validate); // print statistics for a run 222 | 223 | #endif 224 | -------------------------------------------------------------------------------- /src/vendor/ann/ANN/ANNx.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // File: ANNx.h 3 | // Programmer: Sunil Arya and David Mount 4 | // Description: Internal include file for ANN 5 | // Last modified: 01/27/10 (Version 1.1.2) 6 | // 7 | // These declarations are of use in manipulating some of 8 | // the internal data objects appearing in ANN, but are not 9 | // needed for applications just using the nearest neighbor 10 | // search. 11 | // 12 | // Typical users of ANN should not need to access this file. 13 | //---------------------------------------------------------------------- 14 | // Copyright (c) 1997-2010 University of Maryland and Sunil Arya and 15 | // David Mount. All Rights Reserved. 16 | // 17 | // This software and related documentation is part of the Approximate 18 | // Nearest Neighbor Library (ANN). This software is provided under 19 | // the provisions of the Lesser GNU Public License (LGPL). See the 20 | // file ../ReadMe.txt for further information. 21 | // 22 | // The University of Maryland (U.M.) and the authors make no 23 | // representations about the suitability or fitness of this software for 24 | // any purpose. It is provided "as is" without express or implied 25 | // warranty. 26 | //---------------------------------------------------------------------- 27 | // History: 28 | // Revision 0.1 03/04/98 29 | // Initial release 30 | // Revision 1.0 04/01/05 31 | // Changed LO, HI, IN, OUT to ANN_LO, ANN_HI, etc. 32 | // Revision 1.1.2 01/27/10 33 | // Fixed minor compilation bugs for new versions of gcc 34 | //---------------------------------------------------------------------- 35 | 36 | #ifndef ANNx_H 37 | #define ANNx_H 38 | 39 | #include // I/O manipulators 40 | #include // ANN includes 41 | 42 | //---------------------------------------------------------------------- 43 | // Global constants and types 44 | //---------------------------------------------------------------------- 45 | enum {ANN_LO=0, ANN_HI=1}; // splitting indices 46 | enum {ANN_IN=0, ANN_OUT=1}; // shrinking indices 47 | // what to do in case of error 48 | enum ANNerr {ANNwarn = 0, ANNabort = 1}; 49 | 50 | //---------------------------------------------------------------------- 51 | // Maximum number of points to visit 52 | // We have an option for terminating the search early if the 53 | // number of points visited exceeds some threshold. If the 54 | // threshold is 0 (its default) this means there is no limit 55 | // and the algorithm applies its normal termination condition. 56 | //---------------------------------------------------------------------- 57 | 58 | extern int ANNmaxPtsVisited; // maximum number of pts visited 59 | extern int ANNptsVisited; // number of pts visited in search 60 | 61 | //---------------------------------------------------------------------- 62 | // Global function declarations 63 | //---------------------------------------------------------------------- 64 | 65 | void annError( // ANN error routine 66 | const char* msg, // error message 67 | ANNerr level); // level of error 68 | 69 | void annPrintPt( // print a point 70 | ANNpoint pt, // the point 71 | int dim, // the dimension 72 | std::ostream &out); // output stream 73 | 74 | //---------------------------------------------------------------------- 75 | // Orthogonal (axis aligned) rectangle 76 | // Orthogonal rectangles are represented by two points, one 77 | // for the lower left corner (min coordinates) and the other 78 | // for the upper right corner (max coordinates). 79 | // 80 | // The constructor initializes from either a pair of coordinates, 81 | // pair of points, or another rectangle. Note that all constructors 82 | // allocate new point storage. The destructor deallocates this 83 | // storage. 84 | // 85 | // BEWARE: Orthogonal rectangles should be passed ONLY BY REFERENCE. 86 | // (C++'s default copy constructor will not allocate new point 87 | // storage, then on return the destructor free's storage, and then 88 | // you get into big trouble in the calling procedure.) 89 | //---------------------------------------------------------------------- 90 | 91 | class ANNorthRect { 92 | public: 93 | ANNpoint lo; // rectangle lower bounds 94 | ANNpoint hi; // rectangle upper bounds 95 | // 96 | ANNorthRect( // basic constructor 97 | int dd, // dimension of space 98 | ANNcoord l=0, // default is empty 99 | ANNcoord h=0) 100 | { lo = annAllocPt(dd, l); hi = annAllocPt(dd, h); } 101 | 102 | ANNorthRect( // (almost a) copy constructor 103 | int dd, // dimension 104 | const ANNorthRect &r) // rectangle to copy 105 | { lo = annCopyPt(dd, r.lo); hi = annCopyPt(dd, r.hi); } 106 | 107 | ANNorthRect( // construct from points 108 | int dd, // dimension 109 | ANNpoint l, // low point 110 | ANNpoint h) // hight point 111 | { lo = annCopyPt(dd, l); hi = annCopyPt(dd, h); } 112 | 113 | ~ANNorthRect() // destructor 114 | { annDeallocPt(lo); annDeallocPt(hi); } 115 | 116 | ANNbool inside(int dim, ANNpoint p);// is point p inside rectangle? 117 | }; 118 | 119 | void annAssignRect( // assign one rect to another 120 | int dim, // dimension (both must be same) 121 | ANNorthRect &dest, // destination (modified) 122 | const ANNorthRect &source); // source 123 | 124 | //---------------------------------------------------------------------- 125 | // Orthogonal (axis aligned) halfspace 126 | // An orthogonal halfspace is represented by an integer cutting 127 | // dimension cd, coordinate cutting value, cv, and side, sd, which is 128 | // either +1 or -1. Our convention is that point q lies in the (closed) 129 | // halfspace if (q[cd] - cv)*sd >= 0. 130 | //---------------------------------------------------------------------- 131 | 132 | class ANNorthHalfSpace { 133 | public: 134 | int cd; // cutting dimension 135 | ANNcoord cv; // cutting value 136 | int sd; // which side 137 | // 138 | ANNorthHalfSpace() // default constructor 139 | { cd = 0; cv = 0; sd = 0; } 140 | 141 | ANNorthHalfSpace( // basic constructor 142 | int cdd, // dimension of space 143 | ANNcoord cvv, // cutting value 144 | int sdd) // side 145 | { cd = cdd; cv = cvv; sd = sdd; } 146 | 147 | ANNbool in(ANNpoint q) const // is q inside halfspace? 148 | { return (ANNbool) ((q[cd] - cv)*sd >= 0); } 149 | 150 | ANNbool out(ANNpoint q) const // is q outside halfspace? 151 | { return (ANNbool) ((q[cd] - cv)*sd < 0); } 152 | 153 | ANNdist dist(ANNpoint q) const // (squared) distance from q 154 | { return (ANNdist) ANN_POW(q[cd] - cv); } 155 | 156 | void setLowerBound(int d, ANNpoint p)// set to lower bound at p[i] 157 | { cd = d; cv = p[d]; sd = +1; } 158 | 159 | void setUpperBound(int d, ANNpoint p)// set to upper bound at p[i] 160 | { cd = d; cv = p[d]; sd = -1; } 161 | 162 | void project(ANNpoint &q) // project q (modified) onto halfspace 163 | { if (out(q)) q[cd] = cv; } 164 | }; 165 | 166 | // array of halfspaces 167 | typedef ANNorthHalfSpace *ANNorthHSArray; 168 | 169 | #endif 170 | -------------------------------------------------------------------------------- /src/vendor/ann/bd_fix_rad_search.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // File: bd_fix_rad_search.cpp 3 | // Programmer: David Mount 4 | // Description: Standard bd-tree search 5 | // Last modified: 05/03/05 (Version 1.1) 6 | //---------------------------------------------------------------------- 7 | // Copyright (c) 1997-2005 University of Maryland and Sunil Arya and 8 | // David Mount. All Rights Reserved. 9 | // 10 | // This software and related documentation is part of the Approximate 11 | // Nearest Neighbor Library (ANN). This software is provided under 12 | // the provisions of the Lesser GNU Public License (LGPL). See the 13 | // file ../ReadMe.txt for further information. 14 | // 15 | // The University of Maryland (U.M.) and the authors make no 16 | // representations about the suitability or fitness of this software for 17 | // any purpose. It is provided "as is" without express or implied 18 | // warranty. 19 | //---------------------------------------------------------------------- 20 | // History: 21 | // Revision 1.1 05/03/05 22 | // Initial release 23 | //---------------------------------------------------------------------- 24 | 25 | #include "bd_tree.h" // bd-tree declarations 26 | #include "kd_fix_rad_search.h" // kd-tree FR search declarations 27 | 28 | //---------------------------------------------------------------------- 29 | // Approximate searching for bd-trees. 30 | // See the file kd_FR_search.cpp for general information on the 31 | // approximate nearest neighbor search algorithm. Here we 32 | // include the extensions for shrinking nodes. 33 | //---------------------------------------------------------------------- 34 | 35 | //---------------------------------------------------------------------- 36 | // bd_shrink::ann_FR_search - search a shrinking node 37 | //---------------------------------------------------------------------- 38 | 39 | void ANNbd_shrink::ann_FR_search(ANNdist box_dist) 40 | { 41 | // check dist calc term cond. 42 | if (ANNmaxPtsVisited != 0 && ANNptsVisited > ANNmaxPtsVisited) return; 43 | 44 | ANNdist inner_dist = 0; // distance to inner box 45 | for (int i = 0; i < n_bnds; i++) { // is query point in the box? 46 | if (bnds[i].out(ANNkdFRQ)) { // outside this bounding side? 47 | // add to inner distance 48 | inner_dist = (ANNdist) ANN_SUM(inner_dist, bnds[i].dist(ANNkdFRQ)); 49 | } 50 | } 51 | if (inner_dist <= box_dist) { // if inner box is closer 52 | child[ANN_IN]->ann_FR_search(inner_dist);// search inner child first 53 | child[ANN_OUT]->ann_FR_search(box_dist);// ...then outer child 54 | } 55 | else { // if outer box is closer 56 | child[ANN_OUT]->ann_FR_search(box_dist);// search outer child first 57 | child[ANN_IN]->ann_FR_search(inner_dist);// ...then outer child 58 | } 59 | ANN_FLOP(3*n_bnds) // increment floating ops 60 | ANN_SHR(1) // one more shrinking node 61 | } 62 | -------------------------------------------------------------------------------- /src/vendor/ann/bd_pr_search.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // File: bd_pr_search.cpp 3 | // Programmer: David Mount 4 | // Description: Priority search for bd-trees 5 | // Last modified: 01/04/05 (Version 1.0) 6 | //---------------------------------------------------------------------- 7 | // Copyright (c) 1997-2005 University of Maryland and Sunil Arya and 8 | // David Mount. All Rights Reserved. 9 | // 10 | // This software and related documentation is part of the Approximate 11 | // Nearest Neighbor Library (ANN). This software is provided under 12 | // the provisions of the Lesser GNU Public License (LGPL). See the 13 | // file ../ReadMe.txt for further information. 14 | // 15 | // The University of Maryland (U.M.) and the authors make no 16 | // representations about the suitability or fitness of this software for 17 | // any purpose. It is provided "as is" without express or implied 18 | // warranty. 19 | //---------------------------------------------------------------------- 20 | //History: 21 | // Revision 0.1 03/04/98 22 | // Initial release 23 | //---------------------------------------------------------------------- 24 | 25 | #include "bd_tree.h" // bd-tree declarations 26 | #include "kd_pr_search.h" // kd priority search declarations 27 | 28 | //---------------------------------------------------------------------- 29 | // Approximate priority searching for bd-trees. 30 | // See the file kd_pr_search.cc for general information on the 31 | // approximate nearest neighbor priority search algorithm. Here 32 | // we include the extensions for shrinking nodes. 33 | //---------------------------------------------------------------------- 34 | 35 | //---------------------------------------------------------------------- 36 | // bd_shrink::ann_search - search a shrinking node 37 | //---------------------------------------------------------------------- 38 | 39 | void ANNbd_shrink::ann_pri_search(ANNdist box_dist) 40 | { 41 | ANNdist inner_dist = 0; // distance to inner box 42 | for (int i = 0; i < n_bnds; i++) { // is query point in the box? 43 | if (bnds[i].out(ANNprQ)) { // outside this bounding side? 44 | // add to inner distance 45 | inner_dist = (ANNdist) ANN_SUM(inner_dist, bnds[i].dist(ANNprQ)); 46 | } 47 | } 48 | if (inner_dist <= box_dist) { // if inner box is closer 49 | if (child[ANN_OUT] != KD_TRIVIAL) // enqueue outer if not trivial 50 | ANNprBoxPQ->insert(box_dist,child[ANN_OUT]); 51 | // continue with inner child 52 | child[ANN_IN]->ann_pri_search(inner_dist); 53 | } 54 | else { // if outer box is closer 55 | if (child[ANN_IN] != KD_TRIVIAL) // enqueue inner if not trivial 56 | ANNprBoxPQ->insert(inner_dist,child[ANN_IN]); 57 | // continue with outer child 58 | child[ANN_OUT]->ann_pri_search(box_dist); 59 | } 60 | ANN_FLOP(3*n_bnds) // increment floating ops 61 | ANN_SHR(1) // one more shrinking node 62 | } 63 | -------------------------------------------------------------------------------- /src/vendor/ann/bd_search.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // File: bd_search.cpp 3 | // Programmer: David Mount 4 | // Description: Standard bd-tree search 5 | // Last modified: 01/04/05 (Version 1.0) 6 | //---------------------------------------------------------------------- 7 | // Copyright (c) 1997-2005 University of Maryland and Sunil Arya and 8 | // David Mount. All Rights Reserved. 9 | // 10 | // This software and related documentation is part of the Approximate 11 | // Nearest Neighbor Library (ANN). This software is provided under 12 | // the provisions of the Lesser GNU Public License (LGPL). See the 13 | // file ../ReadMe.txt for further information. 14 | // 15 | // The University of Maryland (U.M.) and the authors make no 16 | // representations about the suitability or fitness of this software for 17 | // any purpose. It is provided "as is" without express or implied 18 | // warranty. 19 | //---------------------------------------------------------------------- 20 | // History: 21 | // Revision 0.1 03/04/98 22 | // Initial release 23 | //---------------------------------------------------------------------- 24 | 25 | #include "bd_tree.h" // bd-tree declarations 26 | #include "kd_search.h" // kd-tree search declarations 27 | 28 | //---------------------------------------------------------------------- 29 | // Approximate searching for bd-trees. 30 | // See the file kd_search.cpp for general information on the 31 | // approximate nearest neighbor search algorithm. Here we 32 | // include the extensions for shrinking nodes. 33 | //---------------------------------------------------------------------- 34 | 35 | //---------------------------------------------------------------------- 36 | // bd_shrink::ann_search - search a shrinking node 37 | //---------------------------------------------------------------------- 38 | 39 | void ANNbd_shrink::ann_search(ANNdist box_dist) 40 | { 41 | // check dist calc term cond. 42 | if (ANNmaxPtsVisited != 0 && ANNptsVisited > ANNmaxPtsVisited) return; 43 | 44 | ANNdist inner_dist = 0; // distance to inner box 45 | for (int i = 0; i < n_bnds; i++) { // is query point in the box? 46 | if (bnds[i].out(ANNkdQ)) { // outside this bounding side? 47 | // add to inner distance 48 | inner_dist = (ANNdist) ANN_SUM(inner_dist, bnds[i].dist(ANNkdQ)); 49 | } 50 | } 51 | if (inner_dist <= box_dist) { // if inner box is closer 52 | child[ANN_IN]->ann_search(inner_dist); // search inner child first 53 | child[ANN_OUT]->ann_search(box_dist); // ...then outer child 54 | } 55 | else { // if outer box is closer 56 | child[ANN_OUT]->ann_search(box_dist); // search outer child first 57 | child[ANN_IN]->ann_search(inner_dist); // ...then outer child 58 | } 59 | ANN_FLOP(3*n_bnds) // increment floating ops 60 | ANN_SHR(1) // one more shrinking node 61 | } 62 | -------------------------------------------------------------------------------- /src/vendor/ann/bd_tree.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // File: bd_tree.cpp 3 | // Programmer: David Mount 4 | // Description: Basic methods for bd-trees. 5 | // Last modified: 01/04/05 (Version 1.0) 6 | //---------------------------------------------------------------------- 7 | // Copyright (c) 1997-2005 University of Maryland and Sunil Arya and 8 | // David Mount. All Rights Reserved. 9 | // 10 | // This software and related documentation is part of the Approximate 11 | // Nearest Neighbor Library (ANN). This software is provided under 12 | // the provisions of the Lesser GNU Public License (LGPL). See the 13 | // file ../ReadMe.txt for further information. 14 | // 15 | // The University of Maryland (U.M.) and the authors make no 16 | // representations about the suitability or fitness of this software for 17 | // any purpose. It is provided "as is" without express or implied 18 | // warranty. 19 | //---------------------------------------------------------------------- 20 | // History: 21 | // Revision 0.1 03/04/98 22 | // Initial release 23 | // Revision l.0 04/01/05 24 | // Fixed centroid shrink threshold condition to depend on the 25 | // dimension. 26 | // Moved dump routine to kd_dump.cpp. 27 | //---------------------------------------------------------------------- 28 | 29 | #include "bd_tree.h" // bd-tree declarations 30 | #include "kd_util.h" // kd-tree utilities 31 | #include "kd_split.h" // kd-tree splitting rules 32 | 33 | #include // performance evaluation 34 | 35 | //---------------------------------------------------------------------- 36 | // Printing a bd-tree 37 | // These routines print a bd-tree. See the analogous procedure 38 | // in kd_tree.cpp for more information. 39 | //---------------------------------------------------------------------- 40 | 41 | void ANNbd_shrink::print( // print shrinking node 42 | int level, // depth of node in tree 43 | ostream &out) // output stream 44 | { 45 | child[ANN_OUT]->print(level+1, out); // print out-child 46 | 47 | out << " "; 48 | for (int i = 0; i < level; i++) // print indentation 49 | out << ".."; 50 | out << "Shrink"; 51 | for (int j = 0; j < n_bnds; j++) { // print sides, 2 per line 52 | if (j % 2 == 0) { 53 | out << "\n"; // newline and indentation 54 | for (int i = 0; i < level+2; i++) out << " "; 55 | } 56 | out << " ([" << bnds[j].cd << "]" 57 | << (bnds[j].sd > 0 ? ">=" : "< ") 58 | << bnds[j].cv << ")"; 59 | } 60 | out << "\n"; 61 | 62 | child[ANN_IN]->print(level+1, out); // print in-child 63 | } 64 | 65 | //---------------------------------------------------------------------- 66 | // kd_tree statistics utility (for performance evaluation) 67 | // This routine computes various statistics information for 68 | // shrinking nodes. See file kd_tree.cpp for more information. 69 | //---------------------------------------------------------------------- 70 | 71 | void ANNbd_shrink::getStats( // get subtree statistics 72 | int dim, // dimension of space 73 | ANNkdStats &st, // stats (modified) 74 | ANNorthRect &bnd_box) // bounding box 75 | { 76 | ANNkdStats ch_stats; // stats for children 77 | ANNorthRect inner_box(dim); // inner box of shrink 78 | 79 | annBnds2Box(bnd_box, // enclosing box 80 | dim, // dimension 81 | n_bnds, // number of bounds 82 | bnds, // bounds array 83 | inner_box); // inner box (modified) 84 | // get stats for inner child 85 | ch_stats.reset(); // reset 86 | child[ANN_IN]->getStats(dim, ch_stats, inner_box); 87 | st.merge(ch_stats); // merge them 88 | // get stats for outer child 89 | ch_stats.reset(); // reset 90 | child[ANN_OUT]->getStats(dim, ch_stats, bnd_box); 91 | st.merge(ch_stats); // merge them 92 | 93 | st.depth++; // increment depth 94 | st.n_shr++; // increment number of shrinks 95 | } 96 | 97 | //---------------------------------------------------------------------- 98 | // bd-tree constructor 99 | // This is the main constructor for bd-trees given a set of points. 100 | // It first builds a skeleton kd-tree as a basis, then computes the 101 | // bounding box of the data points, and then invokes rbd_tree() to 102 | // actually build the tree, passing it the appropriate splitting 103 | // and shrinking information. 104 | //---------------------------------------------------------------------- 105 | 106 | ANNkd_ptr rbd_tree( // recursive construction of bd-tree 107 | ANNpointArray pa, // point array 108 | ANNidxArray pidx, // point indices to store in subtree 109 | int n, // number of points 110 | int dim, // dimension of space 111 | int bsp, // bucket space 112 | ANNorthRect &bnd_box, // bounding box for current node 113 | ANNkd_splitter splitter, // splitting routine 114 | ANNshrinkRule shrink); // shrinking rule 115 | 116 | ANNbd_tree::ANNbd_tree( // construct from point array 117 | ANNpointArray pa, // point array (with at least n pts) 118 | int n, // number of points 119 | int dd, // dimension 120 | int bs, // bucket size 121 | ANNsplitRule split, // splitting rule 122 | ANNshrinkRule shrink) // shrinking rule 123 | : ANNkd_tree(n, dd, bs) // build skeleton base tree 124 | { 125 | pts = pa; // where the points are 126 | if (n == 0) return; // no points--no sweat 127 | 128 | ANNorthRect bnd_box(dd); // bounding box for points 129 | // construct bounding rectangle 130 | annEnclRect(pa, pidx, n, dd, bnd_box); 131 | // copy to tree structure 132 | bnd_box_lo = annCopyPt(dd, bnd_box.lo); 133 | bnd_box_hi = annCopyPt(dd, bnd_box.hi); 134 | 135 | switch (split) { // build by rule 136 | case ANN_KD_STD: // standard kd-splitting rule 137 | root = rbd_tree(pa, pidx, n, dd, bs, bnd_box, kd_split, shrink); 138 | break; 139 | case ANN_KD_MIDPT: // midpoint split 140 | root = rbd_tree(pa, pidx, n, dd, bs, bnd_box, midpt_split, shrink); 141 | break; 142 | case ANN_KD_SUGGEST: // best (in our opinion) 143 | case ANN_KD_SL_MIDPT: // sliding midpoint split 144 | root = rbd_tree(pa, pidx, n, dd, bs, bnd_box, sl_midpt_split, shrink); 145 | break; 146 | case ANN_KD_FAIR: // fair split 147 | root = rbd_tree(pa, pidx, n, dd, bs, bnd_box, fair_split, shrink); 148 | break; 149 | case ANN_KD_SL_FAIR: // sliding fair split 150 | root = rbd_tree(pa, pidx, n, dd, bs, 151 | bnd_box, sl_fair_split, shrink); 152 | break; 153 | default: 154 | annError("Illegal splitting method", ANNabort); 155 | } 156 | } 157 | 158 | //---------------------------------------------------------------------- 159 | // Shrinking rules 160 | //---------------------------------------------------------------------- 161 | 162 | enum ANNdecomp {SPLIT, SHRINK}; // decomposition methods 163 | 164 | //---------------------------------------------------------------------- 165 | // trySimpleShrink - Attempt a simple shrink 166 | // 167 | // We compute the tight bounding box of the points, and compute 168 | // the 2*dim ``gaps'' between the sides of the tight box and the 169 | // bounding box. If any of the gaps is large enough relative to 170 | // the longest side of the tight bounding box, then we shrink 171 | // all sides whose gaps are large enough. (The reason for 172 | // comparing against the tight bounding box, is that after 173 | // shrinking the longest box size will decrease, and if we use 174 | // the standard bounding box, we may decide to shrink twice in 175 | // a row. Since the tight box is fixed, we cannot shrink twice 176 | // consecutively.) 177 | //---------------------------------------------------------------------- 178 | const float BD_GAP_THRESH = 0.5; // gap threshold (must be < 1) 179 | const int BD_CT_THRESH = 2; // min number of shrink sides 180 | 181 | ANNdecomp trySimpleShrink( // try a simple shrink 182 | ANNpointArray pa, // point array 183 | ANNidxArray pidx, // point indices to store in subtree 184 | int n, // number of points 185 | int dim, // dimension of space 186 | const ANNorthRect &bnd_box, // current bounding box 187 | ANNorthRect &inner_box) // inner box if shrinking (returned) 188 | { 189 | int i; 190 | // compute tight bounding box 191 | annEnclRect(pa, pidx, n, dim, inner_box); 192 | 193 | ANNcoord max_length = 0; // find longest box side 194 | for (i = 0; i < dim; i++) { 195 | ANNcoord length = inner_box.hi[i] - inner_box.lo[i]; 196 | if (length > max_length) { 197 | max_length = length; 198 | } 199 | } 200 | 201 | int shrink_ct = 0; // number of sides we shrunk 202 | for (i = 0; i < dim; i++) { // select which sides to shrink 203 | // gap between boxes 204 | ANNcoord gap_hi = bnd_box.hi[i] - inner_box.hi[i]; 205 | // big enough gap to shrink? 206 | if (gap_hi < max_length*BD_GAP_THRESH) 207 | inner_box.hi[i] = bnd_box.hi[i]; // no - expand 208 | else shrink_ct++; // yes - shrink this side 209 | 210 | // repeat for high side 211 | ANNcoord gap_lo = inner_box.lo[i] - bnd_box.lo[i]; 212 | if (gap_lo < max_length*BD_GAP_THRESH) 213 | inner_box.lo[i] = bnd_box.lo[i]; // no - expand 214 | else shrink_ct++; // yes - shrink this side 215 | } 216 | 217 | if (shrink_ct >= BD_CT_THRESH) // did we shrink enough sides? 218 | return SHRINK; 219 | else return SPLIT; 220 | } 221 | 222 | //---------------------------------------------------------------------- 223 | // tryCentroidShrink - Attempt a centroid shrink 224 | // 225 | // We repeatedly apply the splitting rule, always to the larger subset 226 | // of points, until the number of points decreases by the constant 227 | // fraction BD_FRACTION. If this takes more than dim*BD_MAX_SPLIT_FAC 228 | // splits for this to happen, then we shrink to the final inner box 229 | // Otherwise we split. 230 | //---------------------------------------------------------------------- 231 | 232 | const float BD_MAX_SPLIT_FAC = 0.5; // maximum number of splits allowed 233 | const float BD_FRACTION = 0.5; // ...to reduce points by this fraction 234 | // ...This must be < 1. 235 | 236 | ANNdecomp tryCentroidShrink( // try a centroid shrink 237 | ANNpointArray pa, // point array 238 | ANNidxArray pidx, // point indices to store in subtree 239 | int n, // number of points 240 | int dim, // dimension of space 241 | const ANNorthRect &bnd_box, // current bounding box 242 | ANNkd_splitter splitter, // splitting procedure 243 | ANNorthRect &inner_box) // inner box if shrinking (returned) 244 | { 245 | int n_sub = n; // number of points in subset 246 | int n_goal = (int) (n*BD_FRACTION); // number of point in goal 247 | int n_splits = 0; // number of splits needed 248 | // initialize inner box to bounding box 249 | annAssignRect(dim, inner_box, bnd_box); 250 | 251 | while (n_sub > n_goal) { // keep splitting until goal reached 252 | int cd; // cut dim from splitter (ignored) 253 | ANNcoord cv; // cut value from splitter (ignored) 254 | int n_lo; // number of points on low side 255 | // invoke splitting procedure 256 | (*splitter)(pa, pidx, inner_box, n_sub, dim, cd, cv, n_lo); 257 | n_splits++; // increment split count 258 | 259 | if (n_lo >= n_sub/2) { // most points on low side 260 | inner_box.hi[cd] = cv; // collapse high side 261 | n_sub = n_lo; // recurse on lower points 262 | } 263 | else { // most points on high side 264 | inner_box.lo[cd] = cv; // collapse low side 265 | pidx += n_lo; // recurse on higher points 266 | n_sub -= n_lo; 267 | } 268 | } 269 | if (n_splits > dim*BD_MAX_SPLIT_FAC)// took too many splits 270 | return SHRINK; // shrink to final subset 271 | else 272 | return SPLIT; 273 | } 274 | 275 | //---------------------------------------------------------------------- 276 | // selectDecomp - select which decomposition to use 277 | //---------------------------------------------------------------------- 278 | 279 | ANNdecomp selectDecomp( // select decomposition method 280 | ANNpointArray pa, // point array 281 | ANNidxArray pidx, // point indices to store in subtree 282 | int n, // number of points 283 | int dim, // dimension of space 284 | const ANNorthRect &bnd_box, // current bounding box 285 | ANNkd_splitter splitter, // splitting procedure 286 | ANNshrinkRule shrink, // shrinking rule 287 | ANNorthRect &inner_box) // inner box if shrinking (returned) 288 | { 289 | ANNdecomp decomp = SPLIT; // decomposition 290 | 291 | switch (shrink) { // check shrinking rule 292 | case ANN_BD_NONE: // no shrinking allowed 293 | decomp = SPLIT; 294 | break; 295 | case ANN_BD_SUGGEST: // author's suggestion 296 | case ANN_BD_SIMPLE: // simple shrink 297 | decomp = trySimpleShrink( 298 | pa, pidx, // points and indices 299 | n, dim, // number of points and dimension 300 | bnd_box, // current bounding box 301 | inner_box); // inner box if shrinking (returned) 302 | break; 303 | case ANN_BD_CENTROID: // centroid shrink 304 | decomp = tryCentroidShrink( 305 | pa, pidx, // points and indices 306 | n, dim, // number of points and dimension 307 | bnd_box, // current bounding box 308 | splitter, // splitting procedure 309 | inner_box); // inner box if shrinking (returned) 310 | break; 311 | default: 312 | annError("Illegal shrinking rule", ANNabort); 313 | } 314 | return decomp; 315 | } 316 | 317 | //---------------------------------------------------------------------- 318 | // rbd_tree - recursive procedure to build a bd-tree 319 | // 320 | // This is analogous to rkd_tree, but for bd-trees. See the 321 | // procedure rkd_tree() in kd_split.cpp for more information. 322 | // 323 | // If the number of points falls below the bucket size, then a 324 | // leaf node is created for the points. Otherwise we invoke the 325 | // procedure selectDecomp() which determines whether we are to 326 | // split or shrink. If splitting is chosen, then we essentially 327 | // do exactly as rkd_tree() would, and invoke the specified 328 | // splitting procedure to the points. Otherwise, the selection 329 | // procedure returns a bounding box, from which we extract the 330 | // appropriate shrinking bounds, and create a shrinking node. 331 | // Finally the points are subdivided, and the procedure is 332 | // invoked recursively on the two subsets to form the children. 333 | //---------------------------------------------------------------------- 334 | 335 | ANNkd_ptr rbd_tree( // recursive construction of bd-tree 336 | ANNpointArray pa, // point array 337 | ANNidxArray pidx, // point indices to store in subtree 338 | int n, // number of points 339 | int dim, // dimension of space 340 | int bsp, // bucket space 341 | ANNorthRect &bnd_box, // bounding box for current node 342 | ANNkd_splitter splitter, // splitting routine 343 | ANNshrinkRule shrink) // shrinking rule 344 | { 345 | ANNdecomp decomp; // decomposition method 346 | 347 | ANNorthRect inner_box(dim); // inner box (if shrinking) 348 | 349 | if (n <= bsp) { // n small, make a leaf node 350 | if (n == 0) // empty leaf node 351 | return KD_TRIVIAL; // return (canonical) empty leaf 352 | else // construct the node and return 353 | return new ANNkd_leaf(n, pidx); 354 | } 355 | 356 | decomp = selectDecomp( // select decomposition method 357 | pa, pidx, // points and indices 358 | n, dim, // number of points and dimension 359 | bnd_box, // current bounding box 360 | splitter, shrink, // splitting/shrinking methods 361 | inner_box); // inner box if shrinking (returned) 362 | 363 | if (decomp == SPLIT) { // split selected 364 | int cd; // cutting dimension 365 | ANNcoord cv; // cutting value 366 | int n_lo; // number on low side of cut 367 | // invoke splitting procedure 368 | (*splitter)(pa, pidx, bnd_box, n, dim, cd, cv, n_lo); 369 | 370 | ANNcoord lv = bnd_box.lo[cd]; // save bounds for cutting dimension 371 | ANNcoord hv = bnd_box.hi[cd]; 372 | 373 | bnd_box.hi[cd] = cv; // modify bounds for left subtree 374 | ANNkd_ptr lo = rbd_tree( // build left subtree 375 | pa, pidx, n_lo, // ...from pidx[0..n_lo-1] 376 | dim, bsp, bnd_box, splitter, shrink); 377 | bnd_box.hi[cd] = hv; // restore bounds 378 | 379 | bnd_box.lo[cd] = cv; // modify bounds for right subtree 380 | ANNkd_ptr hi = rbd_tree( // build right subtree 381 | pa, pidx + n_lo, n-n_lo,// ...from pidx[n_lo..n-1] 382 | dim, bsp, bnd_box, splitter, shrink); 383 | bnd_box.lo[cd] = lv; // restore bounds 384 | // create the splitting node 385 | return new ANNkd_split(cd, cv, lv, hv, lo, hi); 386 | } 387 | else { // shrink selected 388 | int n_in; // number of points in box 389 | int n_bnds; // number of bounding sides 390 | 391 | annBoxSplit( // split points around inner box 392 | pa, // points to split 393 | pidx, // point indices 394 | n, // number of points 395 | dim, // dimension 396 | inner_box, // inner box 397 | n_in); // number of points inside (returned) 398 | 399 | ANNkd_ptr in = rbd_tree( // build inner subtree pidx[0..n_in-1] 400 | pa, pidx, n_in, dim, bsp, inner_box, splitter, shrink); 401 | ANNkd_ptr out = rbd_tree( // build outer subtree pidx[n_in..n] 402 | pa, pidx+n_in, n - n_in, dim, bsp, bnd_box, splitter, shrink); 403 | 404 | ANNorthHSArray bnds = NULL; // bounds (alloc in Box2Bnds and 405 | // ...freed in bd_shrink destroyer) 406 | 407 | annBox2Bnds( // convert inner box to bounds 408 | inner_box, // inner box 409 | bnd_box, // enclosing box 410 | dim, // dimension 411 | n_bnds, // number of bounds (returned) 412 | bnds); // bounds array (modified) 413 | 414 | // return shrinking node 415 | return new ANNbd_shrink(n_bnds, bnds, in, out); 416 | } 417 | } 418 | -------------------------------------------------------------------------------- /src/vendor/ann/bd_tree.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // File: bd_tree.h 3 | // Programmer: David Mount 4 | // Description: Declarations for standard bd-tree routines 5 | // Last modified: 01/04/05 (Version 1.0) 6 | //---------------------------------------------------------------------- 7 | // Copyright (c) 1997-2005 University of Maryland and Sunil Arya and 8 | // David Mount. All Rights Reserved. 9 | // 10 | // This software and related documentation is part of the Approximate 11 | // Nearest Neighbor Library (ANN). This software is provided under 12 | // the provisions of the Lesser GNU Public License (LGPL). See the 13 | // file ../ReadMe.txt for further information. 14 | // 15 | // The University of Maryland (U.M.) and the authors make no 16 | // representations about the suitability or fitness of this software for 17 | // any purpose. It is provided "as is" without express or implied 18 | // warranty. 19 | //---------------------------------------------------------------------- 20 | // History: 21 | // Revision 0.1 03/04/98 22 | // Initial release 23 | // Revision 1.0 04/01/05 24 | // Changed IN, OUT to ANN_IN, ANN_OUT 25 | //---------------------------------------------------------------------- 26 | 27 | #ifndef ANN_bd_tree_H 28 | #define ANN_bd_tree_H 29 | 30 | #include // all ANN includes 31 | #include "kd_tree.h" // kd-tree includes 32 | 33 | //---------------------------------------------------------------------- 34 | // bd-tree shrinking node. 35 | // The main addition in the bd-tree is the shrinking node, which 36 | // is declared here. 37 | // 38 | // Shrinking nodes are defined by list of orthogonal halfspaces. 39 | // These halfspaces define a (possibly unbounded) orthogonal 40 | // rectangle. There are two children, in and out. Points that 41 | // lie within this rectangle are stored in the in-child, and the 42 | // other points are stored in the out-child. 43 | // 44 | // We use a list of orthogonal halfspaces rather than an 45 | // orthogonal rectangle object because typically the number of 46 | // sides of the shrinking box will be much smaller than the 47 | // worst case bound of 2*dim. 48 | // 49 | // BEWARE: Note that constructor just copies the pointer to the 50 | // bounding array, but the destructor deallocates it. This is 51 | // rather poor practice, but happens to be convenient. The list 52 | // is allocated in the bd-tree building procedure rbd_tree() just 53 | // prior to construction, and is used for no other purposes. 54 | // 55 | // WARNING: In the near neighbor searching code it is assumed that 56 | // the list of bounding halfspaces is irredundant, meaning that there 57 | // are no two distinct halfspaces in the list with the same outward 58 | // pointing normals. 59 | //---------------------------------------------------------------------- 60 | 61 | class ANNbd_shrink : public ANNkd_node // splitting node of a kd-tree 62 | { 63 | int n_bnds; // number of bounding halfspaces 64 | ANNorthHSArray bnds; // list of bounding halfspaces 65 | ANNkd_ptr child[2]; // in and out children 66 | public: 67 | ANNbd_shrink( // constructor 68 | int nb, // number of bounding halfspaces 69 | ANNorthHSArray bds, // list of bounding halfspaces 70 | ANNkd_ptr ic=NULL, ANNkd_ptr oc=NULL) // children 71 | { 72 | n_bnds = nb; // cutting dimension 73 | bnds = bds; // assign bounds 74 | child[ANN_IN] = ic; // set children 75 | child[ANN_OUT] = oc; 76 | } 77 | 78 | ~ANNbd_shrink() // destructor 79 | { 80 | if (child[ANN_IN]!= NULL && child[ANN_IN]!= KD_TRIVIAL) 81 | delete child[ANN_IN]; 82 | if (child[ANN_OUT]!= NULL&& child[ANN_OUT]!= KD_TRIVIAL) 83 | delete child[ANN_OUT]; 84 | if (bnds != NULL) 85 | delete [] bnds; // delete bounds 86 | } 87 | 88 | virtual void getStats( // get tree statistics 89 | int dim, // dimension of space 90 | ANNkdStats &st, // statistics 91 | ANNorthRect &bnd_box); // bounding box 92 | virtual void print(int level, ostream &out);// print node 93 | virtual void dump(ostream &out); // dump node 94 | 95 | virtual void ann_search(ANNdist); // standard search 96 | virtual void ann_pri_search(ANNdist); // priority search 97 | virtual void ann_FR_search(ANNdist); // fixed-radius search 98 | }; 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /src/vendor/ann/brute.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // File: brute.cpp 3 | // Programmer: Sunil Arya and David Mount 4 | // Description: Brute-force nearest neighbors 5 | // Last modified: 05/03/05 (Version 1.1) 6 | //---------------------------------------------------------------------- 7 | // Copyright (c) 1997-2005 University of Maryland and Sunil Arya and 8 | // David Mount. All Rights Reserved. 9 | // 10 | // This software and related documentation is part of the Approximate 11 | // Nearest Neighbor Library (ANN). This software is provided under 12 | // the provisions of the Lesser GNU Public License (LGPL). See the 13 | // file ../ReadMe.txt for further information. 14 | // 15 | // The University of Maryland (U.M.) and the authors make no 16 | // representations about the suitability or fitness of this software for 17 | // any purpose. It is provided "as is" without express or implied 18 | // warranty. 19 | //---------------------------------------------------------------------- 20 | // History: 21 | // Revision 0.1 03/04/98 22 | // Initial release 23 | // Revision 1.1 05/03/05 24 | // Added fixed-radius kNN search 25 | //---------------------------------------------------------------------- 26 | 27 | #include // all ANN includes 28 | #include "pr_queue_k.h" // k element priority queue 29 | 30 | //---------------------------------------------------------------------- 31 | // Brute-force search simply stores a pointer to the list of 32 | // data points and searches linearly for the nearest neighbor. 33 | // The k nearest neighbors are stored in a k-element priority 34 | // queue (which is implemented in a pretty dumb way as well). 35 | // 36 | // If ANN_ALLOW_SELF_MATCH is ANNfalse then data points at distance 37 | // zero are not considered. 38 | // 39 | // Note that the error bound eps is passed in, but it is ignored. 40 | // These routines compute exact nearest neighbors (which is needed 41 | // for validation purposes in ann_test.cpp). 42 | //---------------------------------------------------------------------- 43 | 44 | ANNbruteForce::ANNbruteForce( // constructor from point array 45 | ANNpointArray pa, // point array 46 | int n, // number of points 47 | int dd) // dimension 48 | { 49 | dim = dd; n_pts = n; pts = pa; 50 | } 51 | 52 | ANNbruteForce::~ANNbruteForce() { } // destructor (empty) 53 | 54 | void ANNbruteForce::annkSearch( // approx k near neighbor search 55 | ANNpoint q, // query point 56 | int k, // number of near neighbors to return 57 | ANNidxArray nn_idx, // nearest neighbor indices (returned) 58 | ANNdistArray dd, // dist to near neighbors (returned) 59 | double eps) // error bound (ignored) 60 | { 61 | ANNmin_k mk(k); // construct a k-limited priority queue 62 | int i; 63 | 64 | if (k > n_pts) { // too many near neighbors? 65 | annError("Requesting more near neighbors than data points", ANNabort); 66 | } 67 | // run every point through queue 68 | for (i = 0; i < n_pts; i++) { 69 | // compute distance to point 70 | ANNdist sqDist = annDist(dim, pts[i], q); 71 | if (ANN_ALLOW_SELF_MATCH || sqDist != 0) 72 | mk.insert(sqDist, i); 73 | } 74 | for (i = 0; i < k; i++) { // extract the k closest points 75 | dd[i] = mk.ith_smallest_key(i); 76 | nn_idx[i] = mk.ith_smallest_info(i); 77 | } 78 | } 79 | 80 | int ANNbruteForce::annkFRSearch( // approx fixed-radius kNN search 81 | ANNpoint q, // query point 82 | ANNdist sqRad, // squared radius 83 | int k, // number of near neighbors to return 84 | ANNidxArray nn_idx, // nearest neighbor array (returned) 85 | ANNdistArray dd, // dist to near neighbors (returned) 86 | double eps) // error bound 87 | { 88 | ANNmin_k mk(k); // construct a k-limited priority queue 89 | int i; 90 | int pts_in_range = 0; // number of points in query range 91 | // run every point through queue 92 | for (i = 0; i < n_pts; i++) { 93 | // compute distance to point 94 | ANNdist sqDist = annDist(dim, pts[i], q); 95 | if (sqDist <= sqRad && // within radius bound 96 | (ANN_ALLOW_SELF_MATCH || sqDist != 0)) { // ...and no self match 97 | mk.insert(sqDist, i); 98 | pts_in_range++; 99 | } 100 | } 101 | for (i = 0; i < k; i++) { // extract the k closest points 102 | if (dd != NULL) 103 | dd[i] = mk.ith_smallest_key(i); 104 | if (nn_idx != NULL) 105 | nn_idx[i] = mk.ith_smallest_info(i); 106 | } 107 | 108 | return pts_in_range; 109 | } 110 | -------------------------------------------------------------------------------- /src/vendor/ann/kd_dump.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // File: kd_dump.cc 3 | // Programmer: David Mount 4 | // Description: Dump and Load for kd- and bd-trees 5 | // Last modified: 01/04/05 (Version 1.0) 6 | //---------------------------------------------------------------------- 7 | // Copyright (c) 1997-2005 University of Maryland and Sunil Arya and 8 | // David Mount. All Rights Reserved. 9 | // 10 | // This software and related documentation is part of the Approximate 11 | // Nearest Neighbor Library (ANN). This software is provided under 12 | // the provisions of the Lesser GNU Public License (LGPL). See the 13 | // file ../ReadMe.txt for further information. 14 | // 15 | // The University of Maryland (U.M.) and the authors make no 16 | // representations about the suitability or fitness of this software for 17 | // any purpose. It is provided "as is" without express or implied 18 | // warranty. 19 | //---------------------------------------------------------------------- 20 | // History: 21 | // Revision 0.1 03/04/98 22 | // Initial release 23 | // Revision 1.0 04/01/05 24 | // Moved dump out of kd_tree.cc into this file. 25 | // Added kd-tree load constructor. 26 | //---------------------------------------------------------------------- 27 | // This file contains routines for dumping kd-trees and bd-trees and 28 | // reloading them. (It is an abuse of policy to include both kd- and 29 | // bd-tree routines in the same file, sorry. There should be no problem 30 | // in deleting the bd- versions of the routines if they are not 31 | // desired.) 32 | //---------------------------------------------------------------------- 33 | 34 | #include "kd_tree.h" // kd-tree declarations 35 | #include "bd_tree.h" // bd-tree declarations 36 | 37 | using namespace std; // make std:: available 38 | 39 | //---------------------------------------------------------------------- 40 | // Constants 41 | //---------------------------------------------------------------------- 42 | 43 | const int STRING_LEN = 500; // maximum string length 44 | //const double EPSILON = 1E-5; // small number for float comparison 45 | 46 | enum ANNtreeType {KD_TREE, BD_TREE}; // tree types (used in loading) 47 | 48 | //---------------------------------------------------------------------- 49 | // Procedure declarations 50 | //---------------------------------------------------------------------- 51 | 52 | static ANNkd_ptr annReadDump( // read dump file 53 | istream &in, // input stream 54 | ANNtreeType tree_type, // type of tree expected 55 | ANNpointArray &the_pts, // new points (if applic) 56 | ANNidxArray &the_pidx, // point indices (returned) 57 | int &the_dim, // dimension (returned) 58 | int &the_n_pts, // number of points (returned) 59 | int &the_bkt_size, // bucket size (returned) 60 | ANNpoint &the_bnd_box_lo, // low bounding point 61 | ANNpoint &the_bnd_box_hi); // high bounding point 62 | 63 | static ANNkd_ptr annReadTree( // read tree-part of dump file 64 | istream &in, // input stream 65 | ANNtreeType tree_type, // type of tree expected 66 | ANNidxArray the_pidx, // point indices (modified) 67 | int &next_idx); // next index (modified) 68 | 69 | //---------------------------------------------------------------------- 70 | // ANN kd- and bd-tree Dump Format 71 | // The dump file begins with a header containing the version of 72 | // ANN, an optional section containing the points, followed by 73 | // a description of the tree. The tree is printed in preorder. 74 | // 75 | // Format: 76 | // #ANN [END_OF_LINE] 77 | // points (point coordinates: this is optional) 78 | // 0 ... (point indices and coordinates) 79 | // 1 ... 80 | // ... 81 | // tree 82 | // ... (lower end of bounding box) 83 | // ... (upper end of bounding box) 84 | // If the tree is null, then a single line "null" is 85 | // output. Otherwise the nodes of the tree are printed 86 | // one per line in preorder. Leaves and splitting nodes 87 | // have the following formats: 88 | // Leaf node: 89 | // leaf ... 90 | // Splitting nodes: 91 | // split 92 | // 93 | // For bd-trees: 94 | // 95 | // Shrinking nodes: 96 | // shrink 97 | // 98 | // 99 | // ... (repeated n_bnds times) 100 | //---------------------------------------------------------------------- 101 | 102 | void ANNkd_tree::Dump( // dump entire tree 103 | ANNbool with_pts, // print points as well? 104 | ostream &out) // output stream 105 | { 106 | out << "#ANN " << ANNversion << "\n"; 107 | out.precision(ANNcoordPrec); // use full precision in dumping 108 | if (with_pts) { // print point coordinates 109 | out << "points " << dim << " " << n_pts << "\n"; 110 | for (int i = 0; i < n_pts; i++) { 111 | out << i << " "; 112 | annPrintPt(pts[i], dim, out); 113 | out << "\n"; 114 | } 115 | } 116 | out << "tree " // print tree elements 117 | << dim << " " 118 | << n_pts << " " 119 | << bkt_size << "\n"; 120 | 121 | annPrintPt(bnd_box_lo, dim, out); // print lower bound 122 | out << "\n"; 123 | annPrintPt(bnd_box_hi, dim, out); // print upper bound 124 | out << "\n"; 125 | 126 | if (root == NULL) // empty tree? 127 | out << "null\n"; 128 | else { 129 | root->dump(out); // invoke printing at root 130 | } 131 | out.precision(0); // restore default precision 132 | } 133 | 134 | void ANNkd_split::dump( // dump a splitting node 135 | ostream &out) // output stream 136 | { 137 | out << "split " << cut_dim << " " << cut_val << " "; 138 | out << cd_bnds[ANN_LO] << " " << cd_bnds[ANN_HI] << "\n"; 139 | 140 | child[ANN_LO]->dump(out); // print low child 141 | child[ANN_HI]->dump(out); // print high child 142 | } 143 | 144 | void ANNkd_leaf::dump( // dump a leaf node 145 | ostream &out) // output stream 146 | { 147 | if (this == KD_TRIVIAL) { // canonical trivial leaf node 148 | out << "leaf 0\n"; // leaf no points 149 | } 150 | else{ 151 | out << "leaf " << n_pts; 152 | for (int j = 0; j < n_pts; j++) { 153 | out << " " << bkt[j]; 154 | } 155 | out << "\n"; 156 | } 157 | } 158 | 159 | void ANNbd_shrink::dump( // dump a shrinking node 160 | ostream &out) // output stream 161 | { 162 | out << "shrink " << n_bnds << "\n"; 163 | for (int j = 0; j < n_bnds; j++) { 164 | out << bnds[j].cd << " " << bnds[j].cv << " " << bnds[j].sd << "\n"; 165 | } 166 | child[ANN_IN]->dump(out); // print in-child 167 | child[ANN_OUT]->dump(out); // print out-child 168 | } 169 | 170 | //---------------------------------------------------------------------- 171 | // Load kd-tree from dump file 172 | // This rebuilds a kd-tree which was dumped to a file. The dump 173 | // file contains all the basic tree information according to a 174 | // preorder traversal. We assume that the dump file also contains 175 | // point data. (This is to guarantee the consistency of the tree.) 176 | // If not, then an error is generated. 177 | // 178 | // Indirectly, this procedure allocates space for points, point 179 | // indices, all nodes in the tree, and the bounding box for the 180 | // tree. When the tree is destroyed, all but the points are 181 | // deallocated. 182 | // 183 | // This routine calls annReadDump to do all the work. 184 | //---------------------------------------------------------------------- 185 | 186 | ANNkd_tree::ANNkd_tree( // build from dump file 187 | istream &in) // input stream for dump file 188 | { 189 | int the_dim; // local dimension 190 | int the_n_pts; // local number of points 191 | int the_bkt_size; // local number of points 192 | ANNpoint the_bnd_box_lo; // low bounding point 193 | ANNpoint the_bnd_box_hi; // high bounding point 194 | ANNpointArray the_pts; // point storage 195 | ANNidxArray the_pidx; // point index storage 196 | ANNkd_ptr the_root; // root of the tree 197 | 198 | the_root = annReadDump( // read the dump file 199 | in, // input stream 200 | KD_TREE, // expecting a kd-tree 201 | the_pts, // point array (returned) 202 | the_pidx, // point indices (returned) 203 | the_dim, the_n_pts, the_bkt_size, // basic tree info (returned) 204 | the_bnd_box_lo, the_bnd_box_hi); // bounding box info (returned) 205 | 206 | // create a skeletal tree 207 | SkeletonTree(the_n_pts, the_dim, the_bkt_size, the_pts, the_pidx); 208 | 209 | bnd_box_lo = the_bnd_box_lo; 210 | bnd_box_hi = the_bnd_box_hi; 211 | 212 | root = the_root; // set the root 213 | } 214 | 215 | ANNbd_tree::ANNbd_tree( // build bd-tree from dump file 216 | istream &in) : ANNkd_tree() // input stream for dump file 217 | { 218 | int the_dim; // local dimension 219 | int the_n_pts; // local number of points 220 | int the_bkt_size; // local number of points 221 | ANNpoint the_bnd_box_lo; // low bounding point 222 | ANNpoint the_bnd_box_hi; // high bounding point 223 | ANNpointArray the_pts; // point storage 224 | ANNidxArray the_pidx; // point index storage 225 | ANNkd_ptr the_root; // root of the tree 226 | 227 | the_root = annReadDump( // read the dump file 228 | in, // input stream 229 | BD_TREE, // expecting a bd-tree 230 | the_pts, // point array (returned) 231 | the_pidx, // point indices (returned) 232 | the_dim, the_n_pts, the_bkt_size, // basic tree info (returned) 233 | the_bnd_box_lo, the_bnd_box_hi); // bounding box info (returned) 234 | 235 | // create a skeletal tree 236 | SkeletonTree(the_n_pts, the_dim, the_bkt_size, the_pts, the_pidx); 237 | bnd_box_lo = the_bnd_box_lo; 238 | bnd_box_hi = the_bnd_box_hi; 239 | 240 | root = the_root; // set the root 241 | } 242 | 243 | //---------------------------------------------------------------------- 244 | // annReadDump - read a dump file 245 | // 246 | // This procedure reads a dump file, constructs a kd-tree 247 | // and returns all the essential information needed to actually 248 | // construct the tree. Because this procedure is used for 249 | // constructing both kd-trees and bd-trees, the second argument 250 | // is used to indicate which type of tree we are expecting. 251 | //---------------------------------------------------------------------- 252 | 253 | static ANNkd_ptr annReadDump( 254 | istream &in, // input stream 255 | ANNtreeType tree_type, // type of tree expected 256 | ANNpointArray &the_pts, // new points (returned) 257 | ANNidxArray &the_pidx, // point indices (returned) 258 | int &the_dim, // dimension (returned) 259 | int &the_n_pts, // number of points (returned) 260 | int &the_bkt_size, // bucket size (returned) 261 | ANNpoint &the_bnd_box_lo, // low bounding point (ret'd) 262 | ANNpoint &the_bnd_box_hi) // high bounding point (ret'd) 263 | { 264 | int j; 265 | char str[STRING_LEN]; // storage for string 266 | char version[STRING_LEN]; // ANN version number 267 | ANNkd_ptr the_root = NULL; 268 | 269 | //------------------------------------------------------------------ 270 | // Input file header 271 | //------------------------------------------------------------------ 272 | in >> str; // input header 273 | if (strcmp(str, "#ANN") != 0) { // incorrect header 274 | annError("Incorrect header for dump file", ANNabort); 275 | } 276 | in.getline(version, STRING_LEN); // get version (ignore) 277 | 278 | //------------------------------------------------------------------ 279 | // Input the points 280 | // An array the_pts is allocated and points are read from 281 | // the dump file. 282 | //------------------------------------------------------------------ 283 | in >> str; // get major heading 284 | if (strcmp(str, "points") == 0) { // points section 285 | in >> the_dim; // input dimension 286 | in >> the_n_pts; // number of points 287 | // allocate point storage 288 | the_pts = annAllocPts(the_n_pts, the_dim); 289 | for (int i = 0; i < the_n_pts; i++) { // input point coordinates 290 | ANNidx idx; // point index 291 | in >> idx; // input point index 292 | if (idx < 0 || idx >= the_n_pts) { 293 | annError("Point index is out of range", ANNabort); 294 | } 295 | for (j = 0; j < the_dim; j++) { 296 | in >> the_pts[idx][j]; // read point coordinates 297 | } 298 | } 299 | in >> str; // get next major heading 300 | } 301 | else { // no points were input 302 | annError("Points must be supplied in the dump file", ANNabort); 303 | } 304 | 305 | //------------------------------------------------------------------ 306 | // Input the tree 307 | // After the basic header information, we invoke annReadTree 308 | // to do all the heavy work. We create our own array of 309 | // point indices (so we can pass them to annReadTree()) 310 | // but we do not deallocate them. They will be deallocated 311 | // when the tree is destroyed. 312 | //------------------------------------------------------------------ 313 | if (strcmp(str, "tree") == 0) { // tree section 314 | in >> the_dim; // read dimension 315 | in >> the_n_pts; // number of points 316 | in >> the_bkt_size; // bucket size 317 | the_bnd_box_lo = annAllocPt(the_dim); // allocate bounding box pts 318 | the_bnd_box_hi = annAllocPt(the_dim); 319 | 320 | for (j = 0; j < the_dim; j++) { // read bounding box low 321 | in >> the_bnd_box_lo[j]; 322 | } 323 | for (j = 0; j < the_dim; j++) { // read bounding box low 324 | in >> the_bnd_box_hi[j]; 325 | } 326 | the_pidx = new ANNidx[the_n_pts]; // allocate point index array 327 | int next_idx = 0; // number of indices filled 328 | // read the tree and indices 329 | the_root = annReadTree(in, tree_type, the_pidx, next_idx); 330 | if (next_idx != the_n_pts) { // didn't see all the points? 331 | annError("Didn't see as many points as expected", ANNwarn); 332 | } 333 | } 334 | else { 335 | annError("Illegal dump format. Expecting section heading", ANNabort); 336 | } 337 | return the_root; 338 | } 339 | 340 | //---------------------------------------------------------------------- 341 | // annReadTree - input tree and return pointer 342 | // 343 | // annReadTree reads in a node of the tree, makes any recursive 344 | // calls as needed to input the children of this node (if internal). 345 | // It returns a pointer to the node that was created. An array 346 | // of point indices is given along with a pointer to the next 347 | // available location in the array. As leaves are read, their 348 | // point indices are stored here, and the point buckets point 349 | // to the first entry in the array. 350 | // 351 | // Recall that these are the formats. The tree is given in 352 | // preorder. 353 | // 354 | // Leaf node: 355 | // leaf ... 356 | // Splitting nodes: 357 | // split 358 | // 359 | // For bd-trees: 360 | // 361 | // Shrinking nodes: 362 | // shrink 363 | // 364 | // 365 | // ... (repeated n_bnds times) 366 | //---------------------------------------------------------------------- 367 | 368 | static ANNkd_ptr annReadTree( 369 | istream &in, // input stream 370 | ANNtreeType tree_type, // type of tree expected 371 | ANNidxArray the_pidx, // point indices (modified) 372 | int &next_idx) // next index (modified) 373 | { 374 | char tag[STRING_LEN]; // tag (leaf, split, shrink) 375 | int n_pts; // number of points in leaf 376 | int cd; // cut dimension 377 | ANNcoord cv; // cut value 378 | ANNcoord lb; // low bound 379 | ANNcoord hb; // high bound 380 | int n_bnds; // number of bounding sides 381 | int sd; // which side 382 | 383 | in >> tag; // input node tag 384 | 385 | if (strcmp(tag, "null") == 0) { // null tree 386 | return NULL; 387 | } 388 | //------------------------------------------------------------------ 389 | // Read a leaf 390 | //------------------------------------------------------------------ 391 | if (strcmp(tag, "leaf") == 0) { // leaf node 392 | 393 | in >> n_pts; // input number of points 394 | int old_idx = next_idx; // save next_idx 395 | if (n_pts == 0) { // trivial leaf 396 | return KD_TRIVIAL; 397 | } 398 | else { 399 | for (int i = 0; i < n_pts; i++) { // input point indices 400 | in >> the_pidx[next_idx++]; // store in array of indices 401 | } 402 | } 403 | return new ANNkd_leaf(n_pts, &the_pidx[old_idx]); 404 | } 405 | //------------------------------------------------------------------ 406 | // Read a splitting node 407 | //------------------------------------------------------------------ 408 | else if (strcmp(tag, "split") == 0) { // splitting node 409 | 410 | in >> cd >> cv >> lb >> hb; 411 | 412 | // read low and high subtrees 413 | ANNkd_ptr lc = annReadTree(in, tree_type, the_pidx, next_idx); 414 | ANNkd_ptr hc = annReadTree(in, tree_type, the_pidx, next_idx); 415 | // create new node and return 416 | return new ANNkd_split(cd, cv, lb, hb, lc, hc); 417 | } 418 | //------------------------------------------------------------------ 419 | // Read a shrinking node (bd-tree only) 420 | //------------------------------------------------------------------ 421 | else if (strcmp(tag, "shrink") == 0) { // shrinking node 422 | if (tree_type != BD_TREE) { 423 | annError("Shrinking node not allowed in kd-tree", ANNabort); 424 | } 425 | 426 | in >> n_bnds; // number of bounding sides 427 | // allocate bounds array 428 | ANNorthHSArray bds = new ANNorthHalfSpace[n_bnds]; 429 | for (int i = 0; i < n_bnds; i++) { 430 | in >> cd >> cv >> sd; // input bounding halfspace 431 | // copy to array 432 | bds[i] = ANNorthHalfSpace(cd, cv, sd); 433 | } 434 | // read inner and outer subtrees 435 | ANNkd_ptr ic = annReadTree(in, tree_type, the_pidx, next_idx); 436 | ANNkd_ptr oc = annReadTree(in, tree_type, the_pidx, next_idx); 437 | // create new node and return 438 | return new ANNbd_shrink(n_bnds, bds, ic, oc); 439 | } 440 | else { 441 | annError("Illegal node type in dump file", ANNabort); 442 | return NULL; // to keep the compiler happy 443 | #ifndef RANN 444 | exit(0); // to keep the compiler happy 445 | #endif 446 | } 447 | } 448 | -------------------------------------------------------------------------------- /src/vendor/ann/kd_fix_rad_search.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // File: kd_fix_rad_search.cpp 3 | // Programmer: Sunil Arya and David Mount 4 | // Description: Standard kd-tree fixed-radius kNN search 5 | // Last modified: 05/03/05 (Version 1.1) 6 | //---------------------------------------------------------------------- 7 | // Copyright (c) 1997-2005 University of Maryland and Sunil Arya and 8 | // David Mount. All Rights Reserved. 9 | // 10 | // This software and related documentation is part of the Approximate 11 | // Nearest Neighbor Library (ANN). This software is provided under 12 | // the provisions of the Lesser GNU Public License (LGPL). See the 13 | // file ../ReadMe.txt for further information. 14 | // 15 | // The University of Maryland (U.M.) and the authors make no 16 | // representations about the suitability or fitness of this software for 17 | // any purpose. It is provided "as is" without express or implied 18 | // warranty. 19 | //---------------------------------------------------------------------- 20 | // History: 21 | // Revision 1.1 05/03/05 22 | // Initial release 23 | //---------------------------------------------------------------------- 24 | 25 | #include "kd_fix_rad_search.h" // kd fixed-radius search decls 26 | 27 | //---------------------------------------------------------------------- 28 | // Approximate fixed-radius k nearest neighbor search 29 | // The squared radius is provided, and this procedure finds the 30 | // k nearest neighbors within the radius, and returns the total 31 | // number of points lying within the radius. 32 | // 33 | // The method used for searching the kd-tree is a variation of the 34 | // nearest neighbor search used in kd_search.cpp, except that the 35 | // radius of the search ball is known. We refer the reader to that 36 | // file for the explanation of the recursive search procedure. 37 | //---------------------------------------------------------------------- 38 | 39 | //---------------------------------------------------------------------- 40 | // To keep argument lists short, a number of global variables 41 | // are maintained which are common to all the recursive calls. 42 | // These are given below. 43 | //---------------------------------------------------------------------- 44 | 45 | int ANNkdFRDim; // dimension of space 46 | ANNpoint ANNkdFRQ; // query point 47 | ANNdist ANNkdFRSqRad; // squared radius search bound 48 | double ANNkdFRMaxErr; // max tolerable squared error 49 | ANNpointArray ANNkdFRPts; // the points 50 | ANNmin_k* ANNkdFRPointMK; // set of k closest points 51 | int ANNkdFRPtsVisited; // total points visited 52 | int ANNkdFRPtsInRange; // number of points in the range 53 | 54 | //---------------------------------------------------------------------- 55 | // annkFRSearch - fixed radius search for k nearest neighbors 56 | //---------------------------------------------------------------------- 57 | 58 | int ANNkd_tree::annkFRSearch( 59 | ANNpoint q, // the query point 60 | ANNdist sqRad, // squared radius search bound 61 | int k, // number of near neighbors to return 62 | ANNidxArray nn_idx, // nearest neighbor indices (returned) 63 | ANNdistArray dd, // the approximate nearest neighbor 64 | double eps) // the error bound 65 | { 66 | ANNkdFRDim = dim; // copy arguments to static equivs 67 | ANNkdFRQ = q; 68 | ANNkdFRSqRad = sqRad; 69 | ANNkdFRPts = pts; 70 | ANNkdFRPtsVisited = 0; // initialize count of points visited 71 | ANNkdFRPtsInRange = 0; // ...and points in the range 72 | 73 | ANNkdFRMaxErr = ANN_POW(1.0 + eps); 74 | ANN_FLOP(2) // increment floating op count 75 | 76 | ANNkdFRPointMK = new ANNmin_k(k); // create set for closest k points 77 | // search starting at the root 78 | root->ann_FR_search(annBoxDistance(q, bnd_box_lo, bnd_box_hi, dim)); 79 | 80 | for (int i = 0; i < k; i++) { // extract the k-th closest points 81 | if (dd != NULL) 82 | dd[i] = ANNkdFRPointMK->ith_smallest_key(i); 83 | if (nn_idx != NULL) 84 | nn_idx[i] = ANNkdFRPointMK->ith_smallest_info(i); 85 | } 86 | 87 | delete ANNkdFRPointMK; // deallocate closest point set 88 | return ANNkdFRPtsInRange; // return final point count 89 | } 90 | 91 | //---------------------------------------------------------------------- 92 | // kd_split::ann_FR_search - search a splitting node 93 | // Note: This routine is similar in structure to the standard kNN 94 | // search. It visits the subtree that is closer to the query point 95 | // first. For fixed-radius search, there is no benefit in visiting 96 | // one subtree before the other, but we maintain the same basic 97 | // code structure for the sake of uniformity. 98 | //---------------------------------------------------------------------- 99 | 100 | void ANNkd_split::ann_FR_search(ANNdist box_dist) 101 | { 102 | // check dist calc term condition 103 | if (ANNmaxPtsVisited != 0 && ANNkdFRPtsVisited > ANNmaxPtsVisited) return; 104 | 105 | // distance to cutting plane 106 | ANNcoord cut_diff = ANNkdFRQ[cut_dim] - cut_val; 107 | 108 | if (cut_diff < 0) { // left of cutting plane 109 | child[ANN_LO]->ann_FR_search(box_dist);// visit closer child first 110 | 111 | ANNcoord box_diff = cd_bnds[ANN_LO] - ANNkdFRQ[cut_dim]; 112 | if (box_diff < 0) // within bounds - ignore 113 | box_diff = 0; 114 | // distance to further box 115 | box_dist = (ANNdist) ANN_SUM(box_dist, 116 | ANN_DIFF(ANN_POW(box_diff), ANN_POW(cut_diff))); 117 | 118 | // visit further child if in range 119 | if (box_dist * ANNkdFRMaxErr <= ANNkdFRSqRad) 120 | child[ANN_HI]->ann_FR_search(box_dist); 121 | 122 | } 123 | else { // right of cutting plane 124 | child[ANN_HI]->ann_FR_search(box_dist);// visit closer child first 125 | 126 | ANNcoord box_diff = ANNkdFRQ[cut_dim] - cd_bnds[ANN_HI]; 127 | if (box_diff < 0) // within bounds - ignore 128 | box_diff = 0; 129 | // distance to further box 130 | box_dist = (ANNdist) ANN_SUM(box_dist, 131 | ANN_DIFF(ANN_POW(box_diff), ANN_POW(cut_diff))); 132 | 133 | // visit further child if close enough 134 | if (box_dist * ANNkdFRMaxErr <= ANNkdFRSqRad) 135 | child[ANN_LO]->ann_FR_search(box_dist); 136 | 137 | } 138 | ANN_FLOP(13) // increment floating ops 139 | ANN_SPL(1) // one more splitting node visited 140 | } 141 | 142 | //---------------------------------------------------------------------- 143 | // kd_leaf::ann_FR_search - search points in a leaf node 144 | // Note: The unreadability of this code is the result of 145 | // some fine tuning to replace indexing by pointer operations. 146 | //---------------------------------------------------------------------- 147 | 148 | void ANNkd_leaf::ann_FR_search(ANNdist box_dist) 149 | { 150 | ANNdist dist; // distance to data point 151 | ANNcoord* pp; // data coordinate pointer 152 | ANNcoord* qq; // query coordinate pointer 153 | ANNcoord t; 154 | int d; 155 | 156 | for (int i = 0; i < n_pts; i++) { // check points in bucket 157 | 158 | pp = ANNkdFRPts[bkt[i]]; // first coord of next data point 159 | qq = ANNkdFRQ; // first coord of query point 160 | dist = 0; 161 | 162 | for(d = 0; d < ANNkdFRDim; d++) { 163 | ANN_COORD(1) // one more coordinate hit 164 | ANN_FLOP(5) // increment floating ops 165 | 166 | t = *(qq++) - *(pp++); // compute length and adv coordinate 167 | // exceeds dist to k-th smallest? 168 | if( (dist = ANN_SUM(dist, ANN_POW(t))) > ANNkdFRSqRad) { 169 | break; 170 | } 171 | } 172 | 173 | if (d >= ANNkdFRDim && // among the k best? 174 | (ANN_ALLOW_SELF_MATCH || dist!=0)) { // and no self-match problem 175 | // add it to the list 176 | ANNkdFRPointMK->insert(dist, bkt[i]); 177 | ANNkdFRPtsInRange++; // increment point count 178 | } 179 | } 180 | ANN_LEAF(1) // one more leaf node visited 181 | ANN_PTS(n_pts) // increment points visited 182 | ANNkdFRPtsVisited += n_pts; // increment number of points visited 183 | } 184 | -------------------------------------------------------------------------------- /src/vendor/ann/kd_fix_rad_search.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // File: kd_fix_rad_search.h 3 | // Programmer: Sunil Arya and David Mount 4 | // Description: Standard kd-tree fixed-radius kNN search 5 | // Last modified: 05/03/05 (Version 1.1) 6 | //---------------------------------------------------------------------- 7 | // Copyright (c) 1997-2005 University of Maryland and Sunil Arya and 8 | // David Mount. All Rights Reserved. 9 | // 10 | // This software and related documentation is part of the Approximate 11 | // Nearest Neighbor Library (ANN). This software is provided under 12 | // the provisions of the Lesser GNU Public License (LGPL). See the 13 | // file ../ReadMe.txt for further information. 14 | // 15 | // The University of Maryland (U.M.) and the authors make no 16 | // representations about the suitability or fitness of this software for 17 | // any purpose. It is provided "as is" without express or implied 18 | // warranty. 19 | //---------------------------------------------------------------------- 20 | // History: 21 | // Revision 1.1 05/03/05 22 | // Initial release 23 | //---------------------------------------------------------------------- 24 | 25 | #ifndef ANN_kd_fix_rad_search_H 26 | #define ANN_kd_fix_rad_search_H 27 | 28 | #include "kd_tree.h" // kd-tree declarations 29 | #include "kd_util.h" // kd-tree utilities 30 | #include "pr_queue_k.h" // k-element priority queue 31 | 32 | #include // performance evaluation 33 | 34 | //---------------------------------------------------------------------- 35 | // Global variables 36 | // These are active for the life of each call to 37 | // annRangeSearch(). They are set to save the number of 38 | // variables that need to be passed among the various search 39 | // procedures. 40 | //---------------------------------------------------------------------- 41 | 42 | extern ANNpoint ANNkdFRQ; // query point (static copy) 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /src/vendor/ann/kd_pr_search.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // File: kd_pr_search.cpp 3 | // Programmer: Sunil Arya and David Mount 4 | // Description: Priority search for kd-trees 5 | // Last modified: 01/04/05 (Version 1.0) 6 | //---------------------------------------------------------------------- 7 | // Copyright (c) 1997-2005 University of Maryland and Sunil Arya and 8 | // David Mount. All Rights Reserved. 9 | // 10 | // This software and related documentation is part of the Approximate 11 | // Nearest Neighbor Library (ANN). This software is provided under 12 | // the provisions of the Lesser GNU Public License (LGPL). See the 13 | // file ../ReadMe.txt for further information. 14 | // 15 | // The University of Maryland (U.M.) and the authors make no 16 | // representations about the suitability or fitness of this software for 17 | // any purpose. It is provided "as is" without express or implied 18 | // warranty. 19 | //---------------------------------------------------------------------- 20 | // History: 21 | // Revision 0.1 03/04/98 22 | // Initial release 23 | //---------------------------------------------------------------------- 24 | 25 | #include "kd_pr_search.h" // kd priority search declarations 26 | 27 | //---------------------------------------------------------------------- 28 | // Approximate nearest neighbor searching by priority search. 29 | // The kd-tree is searched for an approximate nearest neighbor. 30 | // The point is returned through one of the arguments, and the 31 | // distance returned is the SQUARED distance to this point. 32 | // 33 | // The method used for searching the kd-tree is called priority 34 | // search. (It is described in Arya and Mount, ``Algorithms for 35 | // fast vector quantization,'' Proc. of DCC '93: Data Compression 36 | // Conference}, eds. J. A. Storer and M. Cohn, IEEE Press, 1993, 37 | // 381--390.) 38 | // 39 | // The cell of the kd-tree containing the query point is located, 40 | // and cells are visited in increasing order of distance from the 41 | // query point. This is done by placing each subtree which has 42 | // NOT been visited in a priority queue, according to the closest 43 | // distance of the corresponding enclosing rectangle from the 44 | // query point. The search stops when the distance to the nearest 45 | // remaining rectangle exceeds the distance to the nearest point 46 | // seen by a factor of more than 1/(1+eps). (Implying that any 47 | // point found subsequently in the search cannot be closer by more 48 | // than this factor.) 49 | // 50 | // The main entry point is annkPriSearch() which sets things up and 51 | // then call the recursive routine ann_pri_search(). This is a 52 | // recursive routine which performs the processing for one node in 53 | // the kd-tree. There are two versions of this virtual procedure, 54 | // one for splitting nodes and one for leaves. When a splitting node 55 | // is visited, we determine which child to continue the search on 56 | // (the closer one), and insert the other child into the priority 57 | // queue. When a leaf is visited, we compute the distances to the 58 | // points in the buckets, and update information on the closest 59 | // points. 60 | // 61 | // Some trickery is used to incrementally update the distance from 62 | // a kd-tree rectangle to the query point. This comes about from 63 | // the fact that which each successive split, only one component 64 | // (along the dimension that is split) of the squared distance to 65 | // the child rectangle is different from the squared distance to 66 | // the parent rectangle. 67 | //---------------------------------------------------------------------- 68 | 69 | //---------------------------------------------------------------------- 70 | // To keep argument lists short, a number of global variables 71 | // are maintained which are common to all the recursive calls. 72 | // These are given below. 73 | //---------------------------------------------------------------------- 74 | 75 | double ANNprEps; // the error bound 76 | int ANNprDim; // dimension of space 77 | ANNpoint ANNprQ; // query point 78 | double ANNprMaxErr; // max tolerable squared error 79 | ANNpointArray ANNprPts; // the points 80 | ANNpr_queue *ANNprBoxPQ; // priority queue for boxes 81 | ANNmin_k *ANNprPointMK; // set of k closest points 82 | 83 | //---------------------------------------------------------------------- 84 | // annkPriSearch - priority search for k nearest neighbors 85 | //---------------------------------------------------------------------- 86 | 87 | void ANNkd_tree::annkPriSearch( 88 | ANNpoint q, // query point 89 | int k, // number of near neighbors to return 90 | ANNidxArray nn_idx, // nearest neighbor indices (returned) 91 | ANNdistArray dd, // dist to near neighbors (returned) 92 | double eps) // error bound (ignored) 93 | { 94 | // max tolerable squared error 95 | ANNprMaxErr = ANN_POW(1.0 + eps); 96 | ANN_FLOP(2) // increment floating ops 97 | 98 | ANNprDim = dim; // copy arguments to static equivs 99 | ANNprQ = q; 100 | ANNprPts = pts; 101 | ANNptsVisited = 0; // initialize count of points visited 102 | 103 | ANNprPointMK = new ANNmin_k(k); // create set for closest k points 104 | 105 | // distance to root box 106 | ANNdist box_dist = annBoxDistance(q, 107 | bnd_box_lo, bnd_box_hi, dim); 108 | 109 | ANNprBoxPQ = new ANNpr_queue(n_pts);// create priority queue for boxes 110 | ANNprBoxPQ->insert(box_dist, root); // insert root in priority queue 111 | 112 | while (ANNprBoxPQ->non_empty() && 113 | (!(ANNmaxPtsVisited != 0 && ANNptsVisited > ANNmaxPtsVisited))) { 114 | ANNkd_ptr np; // next box from prior queue 115 | 116 | // extract closest box from queue 117 | ANNprBoxPQ->extr_min(box_dist, (void *&) np); 118 | 119 | ANN_FLOP(2) // increment floating ops 120 | if (box_dist*ANNprMaxErr >= ANNprPointMK->max_key()) 121 | break; 122 | 123 | np->ann_pri_search(box_dist); // search this subtree. 124 | } 125 | 126 | for (int i = 0; i < k; i++) { // extract the k-th closest points 127 | dd[i] = ANNprPointMK->ith_smallest_key(i); 128 | nn_idx[i] = ANNprPointMK->ith_smallest_info(i); 129 | } 130 | 131 | delete ANNprPointMK; // deallocate closest point set 132 | delete ANNprBoxPQ; // deallocate priority queue 133 | } 134 | 135 | //---------------------------------------------------------------------- 136 | // kd_split::ann_pri_search - search a splitting node 137 | //---------------------------------------------------------------------- 138 | 139 | void ANNkd_split::ann_pri_search(ANNdist box_dist) 140 | { 141 | ANNdist new_dist; // distance to child visited later 142 | // distance to cutting plane 143 | ANNcoord cut_diff = ANNprQ[cut_dim] - cut_val; 144 | 145 | if (cut_diff < 0) { // left of cutting plane 146 | ANNcoord box_diff = cd_bnds[ANN_LO] - ANNprQ[cut_dim]; 147 | if (box_diff < 0) // within bounds - ignore 148 | box_diff = 0; 149 | // distance to further box 150 | new_dist = (ANNdist) ANN_SUM(box_dist, 151 | ANN_DIFF(ANN_POW(box_diff), ANN_POW(cut_diff))); 152 | 153 | if (child[ANN_HI] != KD_TRIVIAL)// enqueue if not trivial 154 | ANNprBoxPQ->insert(new_dist, child[ANN_HI]); 155 | // continue with closer child 156 | child[ANN_LO]->ann_pri_search(box_dist); 157 | } 158 | else { // right of cutting plane 159 | ANNcoord box_diff = ANNprQ[cut_dim] - cd_bnds[ANN_HI]; 160 | if (box_diff < 0) // within bounds - ignore 161 | box_diff = 0; 162 | // distance to further box 163 | new_dist = (ANNdist) ANN_SUM(box_dist, 164 | ANN_DIFF(ANN_POW(box_diff), ANN_POW(cut_diff))); 165 | 166 | if (child[ANN_LO] != KD_TRIVIAL)// enqueue if not trivial 167 | ANNprBoxPQ->insert(new_dist, child[ANN_LO]); 168 | // continue with closer child 169 | child[ANN_HI]->ann_pri_search(box_dist); 170 | } 171 | ANN_SPL(1) // one more splitting node visited 172 | ANN_FLOP(8) // increment floating ops 173 | } 174 | 175 | //---------------------------------------------------------------------- 176 | // kd_leaf::ann_pri_search - search points in a leaf node 177 | // 178 | // This is virtually identical to the ann_search for standard search. 179 | //---------------------------------------------------------------------- 180 | 181 | void ANNkd_leaf::ann_pri_search(ANNdist box_dist) 182 | { 183 | ANNdist dist; // distance to data point 184 | ANNcoord* pp; // data coordinate pointer 185 | ANNcoord* qq; // query coordinate pointer 186 | ANNdist min_dist; // distance to k-th closest point 187 | ANNcoord t; 188 | int d; 189 | 190 | min_dist = ANNprPointMK->max_key(); // k-th smallest distance so far 191 | 192 | for (int i = 0; i < n_pts; i++) { // check points in bucket 193 | 194 | pp = ANNprPts[bkt[i]]; // first coord of next data point 195 | qq = ANNprQ; // first coord of query point 196 | dist = 0; 197 | 198 | for(d = 0; d < ANNprDim; d++) { 199 | ANN_COORD(1) // one more coordinate hit 200 | ANN_FLOP(4) // increment floating ops 201 | 202 | t = *(qq++) - *(pp++); // compute length and adv coordinate 203 | // exceeds dist to k-th smallest? 204 | if( (dist = ANN_SUM(dist, ANN_POW(t))) > min_dist) { 205 | break; 206 | } 207 | } 208 | 209 | if (d >= ANNprDim && // among the k best? 210 | (ANN_ALLOW_SELF_MATCH || dist!=0)) { // and no self-match problem 211 | // add it to the list 212 | ANNprPointMK->insert(dist, bkt[i]); 213 | min_dist = ANNprPointMK->max_key(); 214 | } 215 | } 216 | ANN_LEAF(1) // one more leaf node visited 217 | ANN_PTS(n_pts) // increment points visited 218 | ANNptsVisited += n_pts; // increment number of points visited 219 | } 220 | -------------------------------------------------------------------------------- /src/vendor/ann/kd_pr_search.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // File: kd_pr_search.h 3 | // Programmer: Sunil Arya and David Mount 4 | // Description: Priority kd-tree search 5 | // Last modified: 01/04/05 (Version 1.0) 6 | //---------------------------------------------------------------------- 7 | // Copyright (c) 1997-2005 University of Maryland and Sunil Arya and 8 | // David Mount. All Rights Reserved. 9 | // 10 | // This software and related documentation is part of the Approximate 11 | // Nearest Neighbor Library (ANN). This software is provided under 12 | // the provisions of the Lesser GNU Public License (LGPL). See the 13 | // file ../ReadMe.txt for further information. 14 | // 15 | // The University of Maryland (U.M.) and the authors make no 16 | // representations about the suitability or fitness of this software for 17 | // any purpose. It is provided "as is" without express or implied 18 | // warranty. 19 | //---------------------------------------------------------------------- 20 | // History: 21 | // Revision 0.1 03/04/98 22 | // Initial release 23 | //---------------------------------------------------------------------- 24 | 25 | #ifndef ANN_kd_pr_search_H 26 | #define ANN_kd_pr_search_H 27 | 28 | #include "kd_tree.h" // kd-tree declarations 29 | #include "kd_util.h" // kd-tree utilities 30 | #include "pr_queue.h" // priority queue declarations 31 | #include "pr_queue_k.h" // k-element priority queue 32 | 33 | #include // performance evaluation 34 | 35 | //---------------------------------------------------------------------- 36 | // Global variables 37 | // Active for the life of each call to Appx_Near_Neigh() or 38 | // Appx_k_Near_Neigh(). 39 | //---------------------------------------------------------------------- 40 | 41 | extern double ANNprEps; // the error bound 42 | extern int ANNprDim; // dimension of space 43 | extern ANNpoint ANNprQ; // query point 44 | extern double ANNprMaxErr; // max tolerable squared error 45 | extern ANNpointArray ANNprPts; // the points 46 | extern ANNpr_queue *ANNprBoxPQ; // priority queue for boxes 47 | extern ANNmin_k *ANNprPointMK; // set of k closest points 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/vendor/ann/kd_search.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // File: kd_search.cpp 3 | // Programmer: Sunil Arya and David Mount 4 | // Description: Standard kd-tree search 5 | // Last modified: 01/04/05 (Version 1.0) 6 | //---------------------------------------------------------------------- 7 | // Copyright (c) 1997-2005 University of Maryland and Sunil Arya and 8 | // David Mount. All Rights Reserved. 9 | // 10 | // This software and related documentation is part of the Approximate 11 | // Nearest Neighbor Library (ANN). This software is provided under 12 | // the provisions of the Lesser GNU Public License (LGPL). See the 13 | // file ../ReadMe.txt for further information. 14 | // 15 | // The University of Maryland (U.M.) and the authors make no 16 | // representations about the suitability or fitness of this software for 17 | // any purpose. It is provided "as is" without express or implied 18 | // warranty. 19 | //---------------------------------------------------------------------- 20 | // History: 21 | // Revision 0.1 03/04/98 22 | // Initial release 23 | // Revision 1.0 04/01/05 24 | // Changed names LO, HI to ANN_LO, ANN_HI 25 | //---------------------------------------------------------------------- 26 | 27 | #include "kd_search.h" // kd-search declarations 28 | 29 | //---------------------------------------------------------------------- 30 | // Approximate nearest neighbor searching by kd-tree search 31 | // The kd-tree is searched for an approximate nearest neighbor. 32 | // The point is returned through one of the arguments, and the 33 | // distance returned is the squared distance to this point. 34 | // 35 | // The method used for searching the kd-tree is an approximate 36 | // adaptation of the search algorithm described by Friedman, 37 | // Bentley, and Finkel, ``An algorithm for finding best matches 38 | // in logarithmic expected time,'' ACM Transactions on Mathematical 39 | // Software, 3(3):209-226, 1977). 40 | // 41 | // The algorithm operates recursively. When first encountering a 42 | // node of the kd-tree we first visit the child which is closest to 43 | // the query point. On return, we decide whether we want to visit 44 | // the other child. If the box containing the other child exceeds 45 | // 1/(1+eps) times the current best distance, then we skip it (since 46 | // any point found in this child cannot be closer to the query point 47 | // by more than this factor.) Otherwise, we visit it recursively. 48 | // The distance between a box and the query point is computed exactly 49 | // (not approximated as is often done in kd-tree), using incremental 50 | // distance updates, as described by Arya and Mount in ``Algorithms 51 | // for fast vector quantization,'' Proc. of DCC '93: Data Compression 52 | // Conference, eds. J. A. Storer and M. Cohn, IEEE Press, 1993, 53 | // 381-390. 54 | // 55 | // The main entry points is annkSearch() which sets things up and 56 | // then call the recursive routine ann_search(). This is a recursive 57 | // routine which performs the processing for one node in the kd-tree. 58 | // There are two versions of this virtual procedure, one for splitting 59 | // nodes and one for leaves. When a splitting node is visited, we 60 | // determine which child to visit first (the closer one), and visit 61 | // the other child on return. When a leaf is visited, we compute 62 | // the distances to the points in the buckets, and update information 63 | // on the closest points. 64 | // 65 | // Some trickery is used to incrementally update the distance from 66 | // a kd-tree rectangle to the query point. This comes about from 67 | // the fact that which each successive split, only one component 68 | // (along the dimension that is split) of the squared distance to 69 | // the child rectangle is different from the squared distance to 70 | // the parent rectangle. 71 | //---------------------------------------------------------------------- 72 | 73 | //---------------------------------------------------------------------- 74 | // To keep argument lists short, a number of global variables 75 | // are maintained which are common to all the recursive calls. 76 | // These are given below. 77 | //---------------------------------------------------------------------- 78 | 79 | int ANNkdDim; // dimension of space 80 | ANNpoint ANNkdQ; // query point 81 | double ANNkdMaxErr; // max tolerable squared error 82 | ANNpointArray ANNkdPts; // the points 83 | ANNmin_k *ANNkdPointMK; // set of k closest points 84 | 85 | //---------------------------------------------------------------------- 86 | // annkSearch - search for the k nearest neighbors 87 | //---------------------------------------------------------------------- 88 | 89 | void ANNkd_tree::annkSearch( 90 | ANNpoint q, // the query point 91 | int k, // number of near neighbors to return 92 | ANNidxArray nn_idx, // nearest neighbor indices (returned) 93 | ANNdistArray dd, // the approximate nearest neighbor 94 | double eps) // the error bound 95 | { 96 | 97 | ANNkdDim = dim; // copy arguments to static equivs 98 | ANNkdQ = q; 99 | ANNkdPts = pts; 100 | ANNptsVisited = 0; // initialize count of points visited 101 | 102 | if (k > n_pts) { // too many near neighbors? 103 | annError("Requesting more near neighbors than data points", ANNabort); 104 | } 105 | 106 | ANNkdMaxErr = ANN_POW(1.0 + eps); 107 | ANN_FLOP(2) // increment floating op count 108 | 109 | ANNkdPointMK = new ANNmin_k(k); // create set for closest k points 110 | // search starting at the root 111 | root->ann_search(annBoxDistance(q, bnd_box_lo, bnd_box_hi, dim)); 112 | 113 | for (int i = 0; i < k; i++) { // extract the k-th closest points 114 | dd[i] = ANNkdPointMK->ith_smallest_key(i); 115 | nn_idx[i] = ANNkdPointMK->ith_smallest_info(i); 116 | } 117 | delete ANNkdPointMK; // deallocate closest point set 118 | } 119 | 120 | //---------------------------------------------------------------------- 121 | // kd_split::ann_search - search a splitting node 122 | //---------------------------------------------------------------------- 123 | 124 | void ANNkd_split::ann_search(ANNdist box_dist) 125 | { 126 | // check dist calc term condition 127 | if (ANNmaxPtsVisited != 0 && ANNptsVisited > ANNmaxPtsVisited) return; 128 | 129 | // distance to cutting plane 130 | ANNcoord cut_diff = ANNkdQ[cut_dim] - cut_val; 131 | 132 | if (cut_diff < 0) { // left of cutting plane 133 | child[ANN_LO]->ann_search(box_dist);// visit closer child first 134 | 135 | ANNcoord box_diff = cd_bnds[ANN_LO] - ANNkdQ[cut_dim]; 136 | if (box_diff < 0) // within bounds - ignore 137 | box_diff = 0; 138 | // distance to further box 139 | box_dist = (ANNdist) ANN_SUM(box_dist, 140 | ANN_DIFF(ANN_POW(box_diff), ANN_POW(cut_diff))); 141 | 142 | // visit further child if close enough 143 | if (box_dist * ANNkdMaxErr < ANNkdPointMK->max_key()) 144 | child[ANN_HI]->ann_search(box_dist); 145 | 146 | } 147 | else { // right of cutting plane 148 | child[ANN_HI]->ann_search(box_dist);// visit closer child first 149 | 150 | ANNcoord box_diff = ANNkdQ[cut_dim] - cd_bnds[ANN_HI]; 151 | if (box_diff < 0) // within bounds - ignore 152 | box_diff = 0; 153 | // distance to further box 154 | box_dist = (ANNdist) ANN_SUM(box_dist, 155 | ANN_DIFF(ANN_POW(box_diff), ANN_POW(cut_diff))); 156 | 157 | // visit further child if close enough 158 | if (box_dist * ANNkdMaxErr < ANNkdPointMK->max_key()) 159 | child[ANN_LO]->ann_search(box_dist); 160 | 161 | } 162 | ANN_FLOP(10) // increment floating ops 163 | ANN_SPL(1) // one more splitting node visited 164 | } 165 | 166 | //---------------------------------------------------------------------- 167 | // kd_leaf::ann_search - search points in a leaf node 168 | // Note: The unreadability of this code is the result of 169 | // some fine tuning to replace indexing by pointer operations. 170 | //---------------------------------------------------------------------- 171 | 172 | void ANNkd_leaf::ann_search(ANNdist box_dist) 173 | { 174 | ANNdist dist; // distance to data point 175 | ANNcoord* pp; // data coordinate pointer 176 | ANNcoord* qq; // query coordinate pointer 177 | ANNdist min_dist; // distance to k-th closest point 178 | ANNcoord t; 179 | int d; 180 | 181 | min_dist = ANNkdPointMK->max_key(); // k-th smallest distance so far 182 | 183 | for (int i = 0; i < n_pts; i++) { // check points in bucket 184 | 185 | pp = ANNkdPts[bkt[i]]; // first coord of next data point 186 | qq = ANNkdQ; // first coord of query point 187 | dist = 0; 188 | 189 | for(d = 0; d < ANNkdDim; d++) { 190 | ANN_COORD(1) // one more coordinate hit 191 | ANN_FLOP(4) // increment floating ops 192 | 193 | t = *(qq++) - *(pp++); // compute length and adv coordinate 194 | // exceeds dist to k-th smallest? 195 | if( (dist = ANN_SUM(dist, ANN_POW(t))) > min_dist) { 196 | break; 197 | } 198 | } 199 | 200 | if (d >= ANNkdDim && // among the k best? 201 | (ANN_ALLOW_SELF_MATCH || dist!=0)) { // and no self-match problem 202 | // add it to the list 203 | ANNkdPointMK->insert(dist, bkt[i]); 204 | min_dist = ANNkdPointMK->max_key(); 205 | } 206 | } 207 | ANN_LEAF(1) // one more leaf node visited 208 | ANN_PTS(n_pts) // increment points visited 209 | ANNptsVisited += n_pts; // increment number of points visited 210 | } 211 | -------------------------------------------------------------------------------- /src/vendor/ann/kd_search.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // File: kd_search.h 3 | // Programmer: Sunil Arya and David Mount 4 | // Description: Standard kd-tree search 5 | // Last modified: 01/04/05 (Version 1.0) 6 | //---------------------------------------------------------------------- 7 | // Copyright (c) 1997-2005 University of Maryland and Sunil Arya and 8 | // David Mount. All Rights Reserved. 9 | // 10 | // This software and related documentation is part of the Approximate 11 | // Nearest Neighbor Library (ANN). This software is provided under 12 | // the provisions of the Lesser GNU Public License (LGPL). See the 13 | // file ../ReadMe.txt for further information. 14 | // 15 | // The University of Maryland (U.M.) and the authors make no 16 | // representations about the suitability or fitness of this software for 17 | // any purpose. It is provided "as is" without express or implied 18 | // warranty. 19 | //---------------------------------------------------------------------- 20 | // History: 21 | // Revision 0.1 03/04/98 22 | // Initial release 23 | //---------------------------------------------------------------------- 24 | 25 | #ifndef ANN_kd_search_H 26 | #define ANN_kd_search_H 27 | 28 | #include "kd_tree.h" // kd-tree declarations 29 | #include "kd_util.h" // kd-tree utilities 30 | #include "pr_queue_k.h" // k-element priority queue 31 | 32 | #include // performance evaluation 33 | 34 | //---------------------------------------------------------------------- 35 | // More global variables 36 | // These are active for the life of each call to annkSearch(). They 37 | // are set to save the number of variables that need to be passed 38 | // among the various search procedures. 39 | //---------------------------------------------------------------------- 40 | 41 | extern int ANNkdDim; // dimension of space (static copy) 42 | extern ANNpoint ANNkdQ; // query point (static copy) 43 | extern double ANNkdMaxErr; // max tolerable squared error 44 | extern ANNpointArray ANNkdPts; // the points (static copy) 45 | extern ANNmin_k *ANNkdPointMK; // set of k closest points 46 | extern int ANNptsVisited; // number of points visited 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /src/vendor/ann/kd_split.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // File: kd_split.h 3 | // Programmer: Sunil Arya and David Mount 4 | // Description: Methods for splitting kd-trees 5 | // Last modified: 01/04/05 (Version 1.0) 6 | //---------------------------------------------------------------------- 7 | // Copyright (c) 1997-2005 University of Maryland and Sunil Arya and 8 | // David Mount. All Rights Reserved. 9 | // 10 | // This software and related documentation is part of the Approximate 11 | // Nearest Neighbor Library (ANN). This software is provided under 12 | // the provisions of the Lesser GNU Public License (LGPL). See the 13 | // file ../ReadMe.txt for further information. 14 | // 15 | // The University of Maryland (U.M.) and the authors make no 16 | // representations about the suitability or fitness of this software for 17 | // any purpose. It is provided "as is" without express or implied 18 | // warranty. 19 | //---------------------------------------------------------------------- 20 | // History: 21 | // Revision 0.1 03/04/98 22 | // Initial release 23 | //---------------------------------------------------------------------- 24 | 25 | #ifndef ANN_KD_SPLIT_H 26 | #define ANN_KD_SPLIT_H 27 | 28 | #include "kd_tree.h" // kd-tree definitions 29 | 30 | //---------------------------------------------------------------------- 31 | // External entry points 32 | // These are all splitting procedures for kd-trees. 33 | //---------------------------------------------------------------------- 34 | 35 | void kd_split( // standard (optimized) kd-splitter 36 | ANNpointArray pa, // point array (unaltered) 37 | ANNidxArray pidx, // point indices (permuted on return) 38 | const ANNorthRect &bnds, // bounding rectangle for cell 39 | int n, // number of points 40 | int dim, // dimension of space 41 | int &cut_dim, // cutting dimension (returned) 42 | ANNcoord &cut_val, // cutting value (returned) 43 | int &n_lo); // num of points on low side (returned) 44 | 45 | void midpt_split( // midpoint kd-splitter 46 | ANNpointArray pa, // point array (unaltered) 47 | ANNidxArray pidx, // point indices (permuted on return) 48 | const ANNorthRect &bnds, // bounding rectangle for cell 49 | int n, // number of points 50 | int dim, // dimension of space 51 | int &cut_dim, // cutting dimension (returned) 52 | ANNcoord &cut_val, // cutting value (returned) 53 | int &n_lo); // num of points on low side (returned) 54 | 55 | void sl_midpt_split( // sliding midpoint kd-splitter 56 | ANNpointArray pa, // point array (unaltered) 57 | ANNidxArray pidx, // point indices (permuted on return) 58 | const ANNorthRect &bnds, // bounding rectangle for cell 59 | int n, // number of points 60 | int dim, // dimension of space 61 | int &cut_dim, // cutting dimension (returned) 62 | ANNcoord &cut_val, // cutting value (returned) 63 | int &n_lo); // num of points on low side (returned) 64 | 65 | void fair_split( // fair-split kd-splitter 66 | ANNpointArray pa, // point array (unaltered) 67 | ANNidxArray pidx, // point indices (permuted on return) 68 | const ANNorthRect &bnds, // bounding rectangle for cell 69 | int n, // number of points 70 | int dim, // dimension of space 71 | int &cut_dim, // cutting dimension (returned) 72 | ANNcoord &cut_val, // cutting value (returned) 73 | int &n_lo); // num of points on low side (returned) 74 | 75 | void sl_fair_split( // sliding fair-split kd-splitter 76 | ANNpointArray pa, // point array (unaltered) 77 | ANNidxArray pidx, // point indices (permuted on return) 78 | const ANNorthRect &bnds, // bounding rectangle for cell 79 | int n, // number of points 80 | int dim, // dimension of space 81 | int &cut_dim, // cutting dimension (returned) 82 | ANNcoord &cut_val, // cutting value (returned) 83 | int &n_lo); // num of points on low side (returned) 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /src/vendor/ann/kd_tree.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // File: kd_tree.cpp 3 | // Programmer: Sunil Arya and David Mount 4 | // Description: Basic methods for kd-trees. 5 | // Last modified: 01/04/05 (Version 1.0) 6 | //---------------------------------------------------------------------- 7 | // Copyright (c) 1997-2005 University of Maryland and Sunil Arya and 8 | // David Mount. All Rights Reserved. 9 | // 10 | // This software and related documentation is part of the Approximate 11 | // Nearest Neighbor Library (ANN). This software is provided under 12 | // the provisions of the Lesser GNU Public License (LGPL). See the 13 | // file ../ReadMe.txt for further information. 14 | // 15 | // The University of Maryland (U.M.) and the authors make no 16 | // representations about the suitability or fitness of this software for 17 | // any purpose. It is provided "as is" without express or implied 18 | // warranty. 19 | //---------------------------------------------------------------------- 20 | // History: 21 | // Revision 0.1 03/04/98 22 | // Initial release 23 | // Revision 1.0 04/01/05 24 | // Increased aspect ratio bound (ANN_AR_TOOBIG) from 100 to 1000. 25 | // Fixed leaf counts to count trivial leaves. 26 | // Added optional pa, pi arguments to Skeleton kd_tree constructor 27 | // for use in load constructor. 28 | // Added annClose() to eliminate KD_TRIVIAL memory leak. 29 | //---------------------------------------------------------------------- 30 | 31 | #include "kd_tree.h" // kd-tree declarations 32 | #include "kd_split.h" // kd-tree splitting rules 33 | #include "kd_util.h" // kd-tree utilities 34 | #include // performance evaluation 35 | 36 | //---------------------------------------------------------------------- 37 | // Global data 38 | // 39 | // For some splitting rules, especially with small bucket sizes, 40 | // it is possible to generate a large number of empty leaf nodes. 41 | // To save storage we allocate a single trivial leaf node which 42 | // contains no points. For messy coding reasons it is convenient 43 | // to have it reference a trivial point index. 44 | // 45 | // KD_TRIVIAL is allocated when the first kd-tree is created. It 46 | // must *never* deallocated (since it may be shared by more than 47 | // one tree). 48 | //---------------------------------------------------------------------- 49 | static int IDX_TRIVIAL[] = {0}; // trivial point index 50 | ANNkd_leaf *KD_TRIVIAL = NULL; // trivial leaf node 51 | 52 | //---------------------------------------------------------------------- 53 | // Printing the kd-tree 54 | // These routines print a kd-tree in reverse inorder (high then 55 | // root then low). (This is so that if you look at the output 56 | // from the right side it appear from left to right in standard 57 | // inorder.) When outputting leaves we output only the point 58 | // indices rather than the point coordinates. There is an option 59 | // to print the point coordinates separately. 60 | // 61 | // The tree printing routine calls the printing routines on the 62 | // individual nodes of the tree, passing in the level or depth 63 | // in the tree. The level in the tree is used to print indentation 64 | // for readability. 65 | //---------------------------------------------------------------------- 66 | 67 | void ANNkd_split::print( // print splitting node 68 | int level, // depth of node in tree 69 | ostream &out) // output stream 70 | { 71 | child[ANN_HI]->print(level+1, out); // print high child 72 | out << " "; 73 | for (int i = 0; i < level; i++) // print indentation 74 | out << ".."; 75 | out << "Split cd=" << cut_dim << " cv=" << cut_val; 76 | out << " lbnd=" << cd_bnds[ANN_LO]; 77 | out << " hbnd=" << cd_bnds[ANN_HI]; 78 | out << "\n"; 79 | child[ANN_LO]->print(level+1, out); // print low child 80 | } 81 | 82 | void ANNkd_leaf::print( // print leaf node 83 | int level, // depth of node in tree 84 | ostream &out) // output stream 85 | { 86 | 87 | out << " "; 88 | for (int i = 0; i < level; i++) // print indentation 89 | out << ".."; 90 | 91 | if (this == KD_TRIVIAL) { // canonical trivial leaf node 92 | out << "Leaf (trivial)\n"; 93 | } 94 | else{ 95 | out << "Leaf n=" << n_pts << " <"; 96 | for (int j = 0; j < n_pts; j++) { 97 | out << bkt[j]; 98 | if (j < n_pts-1) out << ","; 99 | } 100 | out << ">\n"; 101 | } 102 | } 103 | 104 | void ANNkd_tree::Print( // print entire tree 105 | ANNbool with_pts, // print points as well? 106 | ostream &out) // output stream 107 | { 108 | out << "ANN Version " << ANNversion << "\n"; 109 | if (with_pts) { // print point coordinates 110 | out << " Points:\n"; 111 | for (int i = 0; i < n_pts; i++) { 112 | out << "\t" << i << ": "; 113 | annPrintPt(pts[i], dim, out); 114 | out << "\n"; 115 | } 116 | } 117 | if (root == NULL) // empty tree? 118 | out << " Null tree.\n"; 119 | else { 120 | root->print(0, out); // invoke printing at root 121 | } 122 | } 123 | 124 | //---------------------------------------------------------------------- 125 | // kd_tree statistics (for performance evaluation) 126 | // This routine compute various statistics information for 127 | // a kd-tree. It is used by the implementors for performance 128 | // evaluation of the data structure. 129 | //---------------------------------------------------------------------- 130 | 131 | #define MAX(a,b) ((a) > (b) ? (a) : (b)) 132 | 133 | void ANNkdStats::merge(const ANNkdStats &st) // merge stats from child 134 | { 135 | n_lf += st.n_lf; n_tl += st.n_tl; 136 | n_spl += st.n_spl; n_shr += st.n_shr; 137 | depth = MAX(depth, st.depth); 138 | sum_ar += st.sum_ar; 139 | } 140 | 141 | //---------------------------------------------------------------------- 142 | // Update statistics for nodes 143 | //---------------------------------------------------------------------- 144 | 145 | const double ANN_AR_TOOBIG = 1000; // too big an aspect ratio 146 | 147 | void ANNkd_leaf::getStats( // get subtree statistics 148 | int dim, // dimension of space 149 | ANNkdStats &st, // stats (modified) 150 | ANNorthRect &bnd_box) // bounding box 151 | { 152 | st.reset(); 153 | st.n_lf = 1; // count this leaf 154 | if (this == KD_TRIVIAL) st.n_tl = 1; // count trivial leaf 155 | double ar = annAspectRatio(dim, bnd_box); // aspect ratio of leaf 156 | // incr sum (ignore outliers) 157 | st.sum_ar += float(ar < ANN_AR_TOOBIG ? ar : ANN_AR_TOOBIG); 158 | } 159 | 160 | void ANNkd_split::getStats( // get subtree statistics 161 | int dim, // dimension of space 162 | ANNkdStats &st, // stats (modified) 163 | ANNorthRect &bnd_box) // bounding box 164 | { 165 | ANNkdStats ch_stats; // stats for children 166 | // get stats for low child 167 | ANNcoord hv = bnd_box.hi[cut_dim]; // save box bounds 168 | bnd_box.hi[cut_dim] = cut_val; // upper bound for low child 169 | ch_stats.reset(); // reset 170 | child[ANN_LO]->getStats(dim, ch_stats, bnd_box); 171 | st.merge(ch_stats); // merge them 172 | bnd_box.hi[cut_dim] = hv; // restore bound 173 | // get stats for high child 174 | ANNcoord lv = bnd_box.lo[cut_dim]; // save box bounds 175 | bnd_box.lo[cut_dim] = cut_val; // lower bound for high child 176 | ch_stats.reset(); // reset 177 | child[ANN_HI]->getStats(dim, ch_stats, bnd_box); 178 | st.merge(ch_stats); // merge them 179 | bnd_box.lo[cut_dim] = lv; // restore bound 180 | 181 | st.depth++; // increment depth 182 | st.n_spl++; // increment number of splits 183 | } 184 | 185 | //---------------------------------------------------------------------- 186 | // getStats 187 | // Collects a number of statistics related to kd_tree or 188 | // bd_tree. 189 | //---------------------------------------------------------------------- 190 | 191 | void ANNkd_tree::getStats( // get tree statistics 192 | ANNkdStats &st) // stats (modified) 193 | { 194 | st.reset(dim, n_pts, bkt_size); // reset stats 195 | // create bounding box 196 | ANNorthRect bnd_box(dim, bnd_box_lo, bnd_box_hi); 197 | if (root != NULL) { // if nonempty tree 198 | root->getStats(dim, st, bnd_box); // get statistics 199 | st.avg_ar = st.sum_ar / st.n_lf; // average leaf asp ratio 200 | } 201 | } 202 | 203 | //---------------------------------------------------------------------- 204 | // kd_tree destructor 205 | // The destructor just frees the various elements that were 206 | // allocated in the construction process. 207 | //---------------------------------------------------------------------- 208 | 209 | ANNkd_tree::~ANNkd_tree() // tree destructor 210 | { 211 | if (root != NULL) delete root; 212 | if (pidx != NULL) delete [] pidx; 213 | if (bnd_box_lo != NULL) annDeallocPt(bnd_box_lo); 214 | if (bnd_box_hi != NULL) annDeallocPt(bnd_box_hi); 215 | } 216 | 217 | //---------------------------------------------------------------------- 218 | // This is called with all use of ANN is finished. It eliminates the 219 | // minor memory leak caused by the allocation of KD_TRIVIAL. 220 | //---------------------------------------------------------------------- 221 | void annClose() // close use of ANN 222 | { 223 | if (KD_TRIVIAL != NULL) { 224 | delete KD_TRIVIAL; 225 | KD_TRIVIAL = NULL; 226 | } 227 | } 228 | 229 | //---------------------------------------------------------------------- 230 | // kd_tree constructors 231 | // There is a skeleton kd-tree constructor which sets up a 232 | // trivial empty tree. The last optional argument allows 233 | // the routine to be passed a point index array which is 234 | // assumed to be of the proper size (n). Otherwise, one is 235 | // allocated and initialized to the identity. Warning: In 236 | // either case the destructor will deallocate this array. 237 | // 238 | // As a kludge, we need to allocate KD_TRIVIAL if one has not 239 | // already been allocated. (This is because I'm too dumb to 240 | // figure out how to cause a pointer to be allocated at load 241 | // time.) 242 | //---------------------------------------------------------------------- 243 | 244 | void ANNkd_tree::SkeletonTree( // construct skeleton tree 245 | int n, // number of points 246 | int dd, // dimension 247 | int bs, // bucket size 248 | ANNpointArray pa, // point array 249 | ANNidxArray pi) // point indices 250 | { 251 | dim = dd; // initialize basic elements 252 | n_pts = n; 253 | bkt_size = bs; 254 | pts = pa; // initialize points array 255 | 256 | root = NULL; // no associated tree yet 257 | 258 | if (pi == NULL) { // point indices provided? 259 | pidx = new ANNidx[n]; // no, allocate space for point indices 260 | for (int i = 0; i < n; i++) { 261 | pidx[i] = i; // initially identity 262 | } 263 | } 264 | else { 265 | pidx = pi; // yes, use them 266 | } 267 | 268 | bnd_box_lo = bnd_box_hi = NULL; // bounding box is nonexistent 269 | if (KD_TRIVIAL == NULL) // no trivial leaf node yet? 270 | KD_TRIVIAL = new ANNkd_leaf(0, IDX_TRIVIAL); // allocate it 271 | } 272 | 273 | ANNkd_tree::ANNkd_tree( // basic constructor 274 | int n, // number of points 275 | int dd, // dimension 276 | int bs) // bucket size 277 | { SkeletonTree(n, dd, bs); } // construct skeleton tree 278 | 279 | //---------------------------------------------------------------------- 280 | // rkd_tree - recursive procedure to build a kd-tree 281 | // 282 | // Builds a kd-tree for points in pa as indexed through the 283 | // array pidx[0..n-1] (typically a subarray of the array used in 284 | // the top-level call). This routine permutes the array pidx, 285 | // but does not alter pa[]. 286 | // 287 | // The construction is based on a standard algorithm for constructing 288 | // the kd-tree (see Friedman, Bentley, and Finkel, ``An algorithm for 289 | // finding best matches in logarithmic expected time,'' ACM Transactions 290 | // on Mathematical Software, 3(3):209-226, 1977). The procedure 291 | // operates by a simple divide-and-conquer strategy, which determines 292 | // an appropriate orthogonal cutting plane (see below), and splits 293 | // the points. When the number of points falls below the bucket size, 294 | // we simply store the points in a leaf node's bucket. 295 | // 296 | // One of the arguments is a pointer to a splitting routine, 297 | // whose prototype is: 298 | // 299 | // void split( 300 | // ANNpointArray pa, // complete point array 301 | // ANNidxArray pidx, // point array (permuted on return) 302 | // ANNorthRect &bnds, // bounds of current cell 303 | // int n, // number of points 304 | // int dim, // dimension of space 305 | // int &cut_dim, // cutting dimension 306 | // ANNcoord &cut_val, // cutting value 307 | // int &n_lo) // no. of points on low side of cut 308 | // 309 | // This procedure selects a cutting dimension and cutting value, 310 | // partitions pa about these values, and returns the number of 311 | // points on the low side of the cut. 312 | //---------------------------------------------------------------------- 313 | 314 | ANNkd_ptr rkd_tree( // recursive construction of kd-tree 315 | ANNpointArray pa, // point array 316 | ANNidxArray pidx, // point indices to store in subtree 317 | int n, // number of points 318 | int dim, // dimension of space 319 | int bsp, // bucket space 320 | ANNorthRect &bnd_box, // bounding box for current node 321 | ANNkd_splitter splitter) // splitting routine 322 | { 323 | if (n <= bsp) { // n small, make a leaf node 324 | if (n == 0) // empty leaf node 325 | return KD_TRIVIAL; // return (canonical) empty leaf 326 | else // construct the node and return 327 | return new ANNkd_leaf(n, pidx); 328 | } 329 | else { // n large, make a splitting node 330 | int cd; // cutting dimension 331 | ANNcoord cv; // cutting value 332 | int n_lo; // number on low side of cut 333 | ANNkd_node *lo, *hi; // low and high children 334 | 335 | // invoke splitting procedure 336 | (*splitter)(pa, pidx, bnd_box, n, dim, cd, cv, n_lo); 337 | 338 | ANNcoord lv = bnd_box.lo[cd]; // save bounds for cutting dimension 339 | ANNcoord hv = bnd_box.hi[cd]; 340 | 341 | bnd_box.hi[cd] = cv; // modify bounds for left subtree 342 | lo = rkd_tree( // build left subtree 343 | pa, pidx, n_lo, // ...from pidx[0..n_lo-1] 344 | dim, bsp, bnd_box, splitter); 345 | bnd_box.hi[cd] = hv; // restore bounds 346 | 347 | bnd_box.lo[cd] = cv; // modify bounds for right subtree 348 | hi = rkd_tree( // build right subtree 349 | pa, pidx + n_lo, n-n_lo,// ...from pidx[n_lo..n-1] 350 | dim, bsp, bnd_box, splitter); 351 | bnd_box.lo[cd] = lv; // restore bounds 352 | 353 | // create the splitting node 354 | ANNkd_split *ptr = new ANNkd_split(cd, cv, lv, hv, lo, hi); 355 | 356 | return ptr; // return pointer to this node 357 | } 358 | } 359 | 360 | //---------------------------------------------------------------------- 361 | // kd-tree constructor 362 | // This is the main constructor for kd-trees given a set of points. 363 | // It first builds a skeleton tree, then computes the bounding box 364 | // of the data points, and then invokes rkd_tree() to actually 365 | // build the tree, passing it the appropriate splitting routine. 366 | //---------------------------------------------------------------------- 367 | 368 | ANNkd_tree::ANNkd_tree( // construct from point array 369 | ANNpointArray pa, // point array (with at least n pts) 370 | int n, // number of points 371 | int dd, // dimension 372 | int bs, // bucket size 373 | ANNsplitRule split) // splitting method 374 | { 375 | SkeletonTree(n, dd, bs); // set up the basic stuff 376 | pts = pa; // where the points are 377 | if (n == 0) return; // no points--no sweat 378 | 379 | ANNorthRect bnd_box(dd); // bounding box for points 380 | annEnclRect(pa, pidx, n, dd, bnd_box);// construct bounding rectangle 381 | // copy to tree structure 382 | bnd_box_lo = annCopyPt(dd, bnd_box.lo); 383 | bnd_box_hi = annCopyPt(dd, bnd_box.hi); 384 | 385 | switch (split) { // build by rule 386 | case ANN_KD_STD: // standard kd-splitting rule 387 | root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, kd_split); 388 | break; 389 | case ANN_KD_MIDPT: // midpoint split 390 | root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, midpt_split); 391 | break; 392 | case ANN_KD_FAIR: // fair split 393 | root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, fair_split); 394 | break; 395 | case ANN_KD_SUGGEST: // best (in our opinion) 396 | case ANN_KD_SL_MIDPT: // sliding midpoint split 397 | root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, sl_midpt_split); 398 | break; 399 | case ANN_KD_SL_FAIR: // sliding fair split 400 | root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, sl_fair_split); 401 | break; 402 | default: 403 | annError("Illegal splitting method", ANNabort); 404 | } 405 | } 406 | -------------------------------------------------------------------------------- /src/vendor/ann/kd_tree.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // File: kd_tree.h 3 | // Programmer: Sunil Arya and David Mount 4 | // Description: Declarations for standard kd-tree routines 5 | // Last modified: 05/03/05 (Version 1.1) 6 | //---------------------------------------------------------------------- 7 | // Copyright (c) 1997-2005 University of Maryland and Sunil Arya and 8 | // David Mount. All Rights Reserved. 9 | // 10 | // This software and related documentation is part of the Approximate 11 | // Nearest Neighbor Library (ANN). This software is provided under 12 | // the provisions of the Lesser GNU Public License (LGPL). See the 13 | // file ../ReadMe.txt for further information. 14 | // 15 | // The University of Maryland (U.M.) and the authors make no 16 | // representations about the suitability or fitness of this software for 17 | // any purpose. It is provided "as is" without express or implied 18 | // warranty. 19 | //---------------------------------------------------------------------- 20 | // History: 21 | // Revision 0.1 03/04/98 22 | // Initial release 23 | // Revision 1.1 05/03/05 24 | // Added fixed radius kNN search 25 | //---------------------------------------------------------------------- 26 | 27 | #ifndef ANN_kd_tree_H 28 | #define ANN_kd_tree_H 29 | 30 | #include // all ANN includes 31 | 32 | using namespace std; // make std:: available 33 | 34 | //---------------------------------------------------------------------- 35 | // Generic kd-tree node 36 | // 37 | // Nodes in kd-trees are of two types, splitting nodes which contain 38 | // splitting information (a splitting hyperplane orthogonal to one 39 | // of the coordinate axes) and leaf nodes which contain point 40 | // information (an array of points stored in a bucket). This is 41 | // handled by making a generic class kd_node, which is essentially an 42 | // empty shell, and then deriving the leaf and splitting nodes from 43 | // this. 44 | //---------------------------------------------------------------------- 45 | 46 | class ANNkd_node{ // generic kd-tree node (empty shell) 47 | public: 48 | virtual ~ANNkd_node() {} // virtual distroyer 49 | 50 | virtual void ann_search(ANNdist) = 0; // tree search 51 | virtual void ann_pri_search(ANNdist) = 0; // priority search 52 | virtual void ann_FR_search(ANNdist) = 0; // fixed-radius search 53 | 54 | virtual void getStats( // get tree statistics 55 | int dim, // dimension of space 56 | ANNkdStats &st, // statistics 57 | ANNorthRect &bnd_box) = 0; // bounding box 58 | // print node 59 | virtual void print(int level, ostream &out) = 0; 60 | virtual void dump(ostream &out) = 0; // dump node 61 | 62 | friend class ANNkd_tree; // allow kd-tree to access us 63 | }; 64 | 65 | //---------------------------------------------------------------------- 66 | // kd-splitting function: 67 | // kd_splitter is a pointer to a splitting routine for preprocessing. 68 | // Different splitting procedures result in different strategies 69 | // for building the tree. 70 | //---------------------------------------------------------------------- 71 | 72 | typedef void (*ANNkd_splitter)( // splitting routine for kd-trees 73 | ANNpointArray pa, // point array (unaltered) 74 | ANNidxArray pidx, // point indices (permuted on return) 75 | const ANNorthRect &bnds, // bounding rectangle for cell 76 | int n, // number of points 77 | int dim, // dimension of space 78 | int &cut_dim, // cutting dimension (returned) 79 | ANNcoord &cut_val, // cutting value (returned) 80 | int &n_lo); // num of points on low side (returned) 81 | 82 | //---------------------------------------------------------------------- 83 | // Leaf kd-tree node 84 | // Leaf nodes of the kd-tree store the set of points associated 85 | // with this bucket, stored as an array of point indices. These 86 | // are indices in the array points, which resides with the 87 | // root of the kd-tree. We also store the number of points 88 | // that reside in this bucket. 89 | //---------------------------------------------------------------------- 90 | 91 | class ANNkd_leaf: public ANNkd_node // leaf node for kd-tree 92 | { 93 | int n_pts; // no. points in bucket 94 | ANNidxArray bkt; // bucket of points 95 | public: 96 | ANNkd_leaf( // constructor 97 | int n, // number of points 98 | ANNidxArray b) // bucket 99 | { 100 | n_pts = n; // number of points in bucket 101 | bkt = b; // the bucket 102 | } 103 | 104 | ~ANNkd_leaf() { } // destructor (none) 105 | 106 | virtual void getStats( // get tree statistics 107 | int dim, // dimension of space 108 | ANNkdStats &st, // statistics 109 | ANNorthRect &bnd_box); // bounding box 110 | virtual void print(int level, ostream &out);// print node 111 | virtual void dump(ostream &out); // dump node 112 | 113 | virtual void ann_search(ANNdist); // standard search 114 | virtual void ann_pri_search(ANNdist); // priority search 115 | virtual void ann_FR_search(ANNdist); // fixed-radius search 116 | }; 117 | 118 | //---------------------------------------------------------------------- 119 | // KD_TRIVIAL is a special pointer to an empty leaf node. Since 120 | // some splitting rules generate many (more than 50%) trivial 121 | // leaves, we use this one shared node to save space. 122 | // 123 | // The pointer is initialized to NULL, but whenever a kd-tree is 124 | // created, we allocate this node, if it has not already been 125 | // allocated. This node is *never* deallocated, so it produces 126 | // a small memory leak. 127 | //---------------------------------------------------------------------- 128 | 129 | extern ANNkd_leaf *KD_TRIVIAL; // trivial (empty) leaf node 130 | 131 | //---------------------------------------------------------------------- 132 | // kd-tree splitting node. 133 | // Splitting nodes contain a cutting dimension and a cutting value. 134 | // These indicate the axis-parellel plane which subdivide the 135 | // box for this node. The extent of the bounding box along the 136 | // cutting dimension is maintained (this is used to speed up point 137 | // to box distance calculations) [we do not store the entire bounding 138 | // box since this may be wasteful of space in high dimensions]. 139 | // We also store pointers to the 2 children. 140 | //---------------------------------------------------------------------- 141 | 142 | class ANNkd_split : public ANNkd_node // splitting node of a kd-tree 143 | { 144 | int cut_dim; // dim orthogonal to cutting plane 145 | ANNcoord cut_val; // location of cutting plane 146 | ANNcoord cd_bnds[2]; // lower and upper bounds of 147 | // rectangle along cut_dim 148 | ANNkd_ptr child[2]; // left and right children 149 | public: 150 | ANNkd_split( // constructor 151 | int cd, // cutting dimension 152 | ANNcoord cv, // cutting value 153 | ANNcoord lv, ANNcoord hv, // low and high values 154 | ANNkd_ptr lc=NULL, ANNkd_ptr hc=NULL) // children 155 | { 156 | cut_dim = cd; // cutting dimension 157 | cut_val = cv; // cutting value 158 | cd_bnds[ANN_LO] = lv; // lower bound for rectangle 159 | cd_bnds[ANN_HI] = hv; // upper bound for rectangle 160 | child[ANN_LO] = lc; // left child 161 | child[ANN_HI] = hc; // right child 162 | } 163 | 164 | ~ANNkd_split() // destructor 165 | { 166 | if (child[ANN_LO]!= NULL && child[ANN_LO]!= KD_TRIVIAL) 167 | delete child[ANN_LO]; 168 | if (child[ANN_HI]!= NULL && child[ANN_HI]!= KD_TRIVIAL) 169 | delete child[ANN_HI]; 170 | } 171 | 172 | virtual void getStats( // get tree statistics 173 | int dim, // dimension of space 174 | ANNkdStats &st, // statistics 175 | ANNorthRect &bnd_box); // bounding box 176 | virtual void print(int level, ostream &out);// print node 177 | virtual void dump(ostream &out); // dump node 178 | 179 | virtual void ann_search(ANNdist); // standard search 180 | virtual void ann_pri_search(ANNdist); // priority search 181 | virtual void ann_FR_search(ANNdist); // fixed-radius search 182 | }; 183 | 184 | //---------------------------------------------------------------------- 185 | // External entry points 186 | //---------------------------------------------------------------------- 187 | 188 | ANNkd_ptr rkd_tree( // recursive construction of kd-tree 189 | ANNpointArray pa, // point array (unaltered) 190 | ANNidxArray pidx, // point indices to store in subtree 191 | int n, // number of points 192 | int dim, // dimension of space 193 | int bsp, // bucket space 194 | ANNorthRect &bnd_box, // bounding box for current node 195 | ANNkd_splitter splitter); // splitting routine 196 | 197 | #endif 198 | -------------------------------------------------------------------------------- /src/vendor/ann/kd_util.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // File: kd_util.cpp 3 | // Programmer: Sunil Arya and David Mount 4 | // Description: Common utilities for kd-trees 5 | // Last modified: 01/04/05 (Version 1.0) 6 | //---------------------------------------------------------------------- 7 | // Copyright (c) 1997-2005 University of Maryland and Sunil Arya and 8 | // David Mount. All Rights Reserved. 9 | // 10 | // This software and related documentation is part of the Approximate 11 | // Nearest Neighbor Library (ANN). This software is provided under 12 | // the provisions of the Lesser GNU Public License (LGPL). See the 13 | // file ../ReadMe.txt for further information. 14 | // 15 | // The University of Maryland (U.M.) and the authors make no 16 | // representations about the suitability or fitness of this software for 17 | // any purpose. It is provided "as is" without express or implied 18 | // warranty. 19 | //---------------------------------------------------------------------- 20 | // History: 21 | // Revision 0.1 03/04/98 22 | // Initial release 23 | //---------------------------------------------------------------------- 24 | 25 | #include "kd_util.h" // kd-utility declarations 26 | 27 | #include // performance evaluation 28 | 29 | //---------------------------------------------------------------------- 30 | // The following routines are utility functions for manipulating 31 | // points sets, used in determining splitting planes for kd-tree 32 | // construction. 33 | //---------------------------------------------------------------------- 34 | 35 | //---------------------------------------------------------------------- 36 | // NOTE: Virtually all point indexing is done through an index (i.e. 37 | // permutation) array pidx. Consequently, a reference to the d-th 38 | // coordinate of the i-th point is pa[pidx[i]][d]. The macro PA(i,d) 39 | // is a shorthand for this. 40 | //---------------------------------------------------------------------- 41 | // standard 2-d indirect indexing 42 | #define PA(i,d) (pa[pidx[(i)]][(d)]) 43 | // accessing a single point 44 | #define PP(i) (pa[pidx[(i)]]) 45 | 46 | //---------------------------------------------------------------------- 47 | // annAspectRatio 48 | // Compute the aspect ratio (ratio of longest to shortest side) 49 | // of a rectangle. 50 | //---------------------------------------------------------------------- 51 | 52 | double annAspectRatio( 53 | int dim, // dimension 54 | const ANNorthRect &bnd_box) // bounding cube 55 | { 56 | ANNcoord length = bnd_box.hi[0] - bnd_box.lo[0]; 57 | ANNcoord min_length = length; // min side length 58 | ANNcoord max_length = length; // max side length 59 | for (int d = 0; d < dim; d++) { 60 | length = bnd_box.hi[d] - bnd_box.lo[d]; 61 | if (length < min_length) min_length = length; 62 | if (length > max_length) max_length = length; 63 | } 64 | return max_length/min_length; 65 | } 66 | 67 | //---------------------------------------------------------------------- 68 | // annEnclRect, annEnclCube 69 | // These utilities compute the smallest rectangle and cube enclosing 70 | // a set of points, respectively. 71 | //---------------------------------------------------------------------- 72 | 73 | void annEnclRect( 74 | ANNpointArray pa, // point array 75 | ANNidxArray pidx, // point indices 76 | int n, // number of points 77 | int dim, // dimension 78 | ANNorthRect &bnds) // bounding cube (returned) 79 | { 80 | for (int d = 0; d < dim; d++) { // find smallest enclosing rectangle 81 | ANNcoord lo_bnd = PA(0,d); // lower bound on dimension d 82 | ANNcoord hi_bnd = PA(0,d); // upper bound on dimension d 83 | for (int i = 0; i < n; i++) { 84 | if (PA(i,d) < lo_bnd) lo_bnd = PA(i,d); 85 | else if (PA(i,d) > hi_bnd) hi_bnd = PA(i,d); 86 | } 87 | bnds.lo[d] = lo_bnd; 88 | bnds.hi[d] = hi_bnd; 89 | } 90 | } 91 | 92 | void annEnclCube( // compute smallest enclosing cube 93 | ANNpointArray pa, // point array 94 | ANNidxArray pidx, // point indices 95 | int n, // number of points 96 | int dim, // dimension 97 | ANNorthRect &bnds) // bounding cube (returned) 98 | { 99 | int d; 100 | // compute smallest enclosing rect 101 | annEnclRect(pa, pidx, n, dim, bnds); 102 | 103 | ANNcoord max_len = 0; // max length of any side 104 | for (d = 0; d < dim; d++) { // determine max side length 105 | ANNcoord len = bnds.hi[d] - bnds.lo[d]; 106 | if (len > max_len) { // update max_len if longest 107 | max_len = len; 108 | } 109 | } 110 | for (d = 0; d < dim; d++) { // grow sides to match max 111 | ANNcoord len = bnds.hi[d] - bnds.lo[d]; 112 | ANNcoord half_diff = (max_len - len) / 2; 113 | bnds.lo[d] -= half_diff; 114 | bnds.hi[d] += half_diff; 115 | } 116 | } 117 | 118 | //---------------------------------------------------------------------- 119 | // annBoxDistance - utility routine which computes distance from point to 120 | // box (Note: most distances to boxes are computed using incremental 121 | // distance updates, not this function.) 122 | //---------------------------------------------------------------------- 123 | 124 | ANNdist annBoxDistance( // compute distance from point to box 125 | const ANNpoint q, // the point 126 | const ANNpoint lo, // low point of box 127 | const ANNpoint hi, // high point of box 128 | int dim) // dimension of space 129 | { 130 | ANNdist dist = 0.0; // sum of squared distances 131 | ANNdist t; 132 | 133 | for (int d = 0; d < dim; d++) { 134 | if (q[d] < lo[d]) { // q is left of box 135 | t = ANNdist(lo[d]) - ANNdist(q[d]); 136 | dist = ANN_SUM(dist, ANN_POW(t)); 137 | } 138 | else if (q[d] > hi[d]) { // q is right of box 139 | t = ANNdist(q[d]) - ANNdist(hi[d]); 140 | dist = ANN_SUM(dist, ANN_POW(t)); 141 | } 142 | } 143 | ANN_FLOP(4*dim) // increment floating op count 144 | 145 | return dist; 146 | } 147 | 148 | //---------------------------------------------------------------------- 149 | // annSpread - find spread along given dimension 150 | // annMinMax - find min and max coordinates along given dimension 151 | // annMaxSpread - find dimension of max spread 152 | //---------------------------------------------------------------------- 153 | 154 | ANNcoord annSpread( // compute point spread along dimension 155 | ANNpointArray pa, // point array 156 | ANNidxArray pidx, // point indices 157 | int n, // number of points 158 | int d) // dimension to check 159 | { 160 | ANNcoord min = PA(0,d); // compute max and min coords 161 | ANNcoord max = PA(0,d); 162 | for (int i = 1; i < n; i++) { 163 | ANNcoord c = PA(i,d); 164 | if (c < min) min = c; 165 | else if (c > max) max = c; 166 | } 167 | return (max - min); // total spread is difference 168 | } 169 | 170 | void annMinMax( // compute min and max coordinates along dim 171 | ANNpointArray pa, // point array 172 | ANNidxArray pidx, // point indices 173 | int n, // number of points 174 | int d, // dimension to check 175 | ANNcoord &min, // minimum value (returned) 176 | ANNcoord &max) // maximum value (returned) 177 | { 178 | min = PA(0,d); // compute max and min coords 179 | max = PA(0,d); 180 | for (int i = 1; i < n; i++) { 181 | ANNcoord c = PA(i,d); 182 | if (c < min) min = c; 183 | else if (c > max) max = c; 184 | } 185 | } 186 | 187 | int annMaxSpread( // compute dimension of max spread 188 | ANNpointArray pa, // point array 189 | ANNidxArray pidx, // point indices 190 | int n, // number of points 191 | int dim) // dimension of space 192 | { 193 | int max_dim = 0; // dimension of max spread 194 | ANNcoord max_spr = 0; // amount of max spread 195 | 196 | if (n == 0) return max_dim; // no points, who cares? 197 | 198 | for (int d = 0; d < dim; d++) { // compute spread along each dim 199 | ANNcoord spr = annSpread(pa, pidx, n, d); 200 | if (spr > max_spr) { // bigger than current max 201 | max_spr = spr; 202 | max_dim = d; 203 | } 204 | } 205 | return max_dim; 206 | } 207 | 208 | //---------------------------------------------------------------------- 209 | // annMedianSplit - split point array about its median 210 | // Splits a subarray of points pa[0..n] about an element of given 211 | // rank (median: n_lo = n/2) with respect to dimension d. It places 212 | // the element of rank n_lo-1 correctly (because our splitting rule 213 | // takes the mean of these two). On exit, the array is permuted so 214 | // that: 215 | // 216 | // pa[0..n_lo-2][d] <= pa[n_lo-1][d] <= pa[n_lo][d] <= pa[n_lo+1..n-1][d]. 217 | // 218 | // The mean of pa[n_lo-1][d] and pa[n_lo][d] is returned as the 219 | // splitting value. 220 | // 221 | // All indexing is done indirectly through the index array pidx. 222 | // 223 | // This function uses the well known selection algorithm due to 224 | // C.A.R. Hoare. 225 | //---------------------------------------------------------------------- 226 | 227 | // swap two points in pa array 228 | #define PASWAP(a,b) { int tmp = pidx[a]; pidx[a] = pidx[b]; pidx[b] = tmp; } 229 | 230 | void annMedianSplit( 231 | ANNpointArray pa, // points to split 232 | ANNidxArray pidx, // point indices 233 | int n, // number of points 234 | int d, // dimension along which to split 235 | ANNcoord &cv, // cutting value 236 | int n_lo) // split into n_lo and n-n_lo 237 | { 238 | int l = 0; // left end of current subarray 239 | int r = n-1; // right end of current subarray 240 | while (l < r) { 241 | int i = (r+l)/2; // select middle as pivot 242 | int k; 243 | 244 | if (PA(i,d) > PA(r,d)) // make sure last > pivot 245 | PASWAP(i,r) 246 | PASWAP(l,i); // move pivot to first position 247 | 248 | ANNcoord c = PA(l,d); // pivot value 249 | i = l; 250 | k = r; 251 | for(;;) { // pivot about c 252 | while (PA(++i,d) < c) ; 253 | while (PA(--k,d) > c) ; 254 | if (i < k) PASWAP(i,k) else break; 255 | } 256 | PASWAP(l,k); // pivot winds up in location k 257 | 258 | if (k > n_lo) r = k-1; // recurse on proper subarray 259 | else if (k < n_lo) l = k+1; 260 | else break; // got the median exactly 261 | } 262 | if (n_lo > 0) { // search for next smaller item 263 | ANNcoord c = PA(0,d); // candidate for max 264 | int k = 0; // candidate's index 265 | for (int i = 1; i < n_lo; i++) { 266 | if (PA(i,d) > c) { 267 | c = PA(i,d); 268 | k = i; 269 | } 270 | } 271 | PASWAP(n_lo-1, k); // max among pa[0..n_lo-1] to pa[n_lo-1] 272 | } 273 | // cut value is midpoint value 274 | cv = (PA(n_lo-1,d) + PA(n_lo,d))/2.0; 275 | } 276 | 277 | //---------------------------------------------------------------------- 278 | // annPlaneSplit - split point array about a cutting plane 279 | // Split the points in an array about a given plane along a 280 | // given cutting dimension. On exit, br1 and br2 are set so 281 | // that: 282 | // 283 | // pa[ 0 ..br1-1] < cv 284 | // pa[br1..br2-1] == cv 285 | // pa[br2.. n -1] > cv 286 | // 287 | // All indexing is done indirectly through the index array pidx. 288 | // 289 | //---------------------------------------------------------------------- 290 | 291 | void annPlaneSplit( // split points by a plane 292 | ANNpointArray pa, // points to split 293 | ANNidxArray pidx, // point indices 294 | int n, // number of points 295 | int d, // dimension along which to split 296 | ANNcoord cv, // cutting value 297 | int &br1, // first break (values < cv) 298 | int &br2) // second break (values == cv) 299 | { 300 | int l = 0; 301 | int r = n-1; 302 | for(;;) { // partition pa[0..n-1] about cv 303 | while (l < n && PA(l,d) < cv) l++; 304 | while (r >= 0 && PA(r,d) >= cv) r--; 305 | if (l > r) break; 306 | PASWAP(l,r); 307 | l++; r--; 308 | } 309 | br1 = l; // now: pa[0..br1-1] < cv <= pa[br1..n-1] 310 | r = n-1; 311 | for(;;) { // partition pa[br1..n-1] about cv 312 | while (l < n && PA(l,d) <= cv) l++; 313 | while (r >= br1 && PA(r,d) > cv) r--; 314 | if (l > r) break; 315 | PASWAP(l,r); 316 | l++; r--; 317 | } 318 | br2 = l; // now: pa[br1..br2-1] == cv < pa[br2..n-1] 319 | } 320 | 321 | 322 | //---------------------------------------------------------------------- 323 | // annBoxSplit - split point array about a orthogonal rectangle 324 | // Split the points in an array about a given orthogonal 325 | // rectangle. On exit, n_in is set to the number of points 326 | // that are inside (or on the boundary of) the rectangle. 327 | // 328 | // All indexing is done indirectly through the index array pidx. 329 | // 330 | //---------------------------------------------------------------------- 331 | 332 | void annBoxSplit( // split points by a box 333 | ANNpointArray pa, // points to split 334 | ANNidxArray pidx, // point indices 335 | int n, // number of points 336 | int dim, // dimension of space 337 | ANNorthRect &box, // the box 338 | int &n_in) // number of points inside (returned) 339 | { 340 | int l = 0; 341 | int r = n-1; 342 | for(;;) { // partition pa[0..n-1] about box 343 | while (l < n && box.inside(dim, PP(l))) l++; 344 | while (r >= 0 && !box.inside(dim, PP(r))) r--; 345 | if (l > r) break; 346 | PASWAP(l,r); 347 | l++; r--; 348 | } 349 | n_in = l; // now: pa[0..n_in-1] inside and rest outside 350 | } 351 | 352 | //---------------------------------------------------------------------- 353 | // annSplitBalance - compute balance factor for a given plane split 354 | // Balance factor is defined as the number of points lying 355 | // below the splitting value minus n/2 (median). Thus, a 356 | // median split has balance 0, left of this is negative and 357 | // right of this is positive. (The points are unchanged.) 358 | //---------------------------------------------------------------------- 359 | 360 | int annSplitBalance( // determine balance factor of a split 361 | ANNpointArray pa, // points to split 362 | ANNidxArray pidx, // point indices 363 | int n, // number of points 364 | int d, // dimension along which to split 365 | ANNcoord cv) // cutting value 366 | { 367 | int n_lo = 0; 368 | for(int i = 0; i < n; i++) { // count number less than cv 369 | if (PA(i,d) < cv) n_lo++; 370 | } 371 | return n_lo - n/2; 372 | } 373 | 374 | //---------------------------------------------------------------------- 375 | // annBox2Bnds - convert bounding box to list of bounds 376 | // Given two boxes, an inner box enclosed within a bounding 377 | // box, this routine determines all the sides for which the 378 | // inner box is strictly contained with the bounding box, 379 | // and adds an appropriate entry to a list of bounds. Then 380 | // we allocate storage for the final list of bounds, and return 381 | // the resulting list and its size. 382 | //---------------------------------------------------------------------- 383 | 384 | void annBox2Bnds( // convert inner box to bounds 385 | const ANNorthRect &inner_box, // inner box 386 | const ANNorthRect &bnd_box, // enclosing box 387 | int dim, // dimension of space 388 | int &n_bnds, // number of bounds (returned) 389 | ANNorthHSArray &bnds) // bounds array (returned) 390 | { 391 | int i; 392 | n_bnds = 0; // count number of bounds 393 | for (i = 0; i < dim; i++) { 394 | if (inner_box.lo[i] > bnd_box.lo[i]) // low bound is inside 395 | n_bnds++; 396 | if (inner_box.hi[i] < bnd_box.hi[i]) // high bound is inside 397 | n_bnds++; 398 | } 399 | 400 | bnds = new ANNorthHalfSpace[n_bnds]; // allocate appropriate size 401 | 402 | int j = 0; 403 | for (i = 0; i < dim; i++) { // fill the array 404 | if (inner_box.lo[i] > bnd_box.lo[i]) { 405 | bnds[j].cd = i; 406 | bnds[j].cv = inner_box.lo[i]; 407 | bnds[j].sd = +1; 408 | j++; 409 | } 410 | if (inner_box.hi[i] < bnd_box.hi[i]) { 411 | bnds[j].cd = i; 412 | bnds[j].cv = inner_box.hi[i]; 413 | bnds[j].sd = -1; 414 | j++; 415 | } 416 | } 417 | } 418 | 419 | //---------------------------------------------------------------------- 420 | // annBnds2Box - convert list of bounds to bounding box 421 | // Given an enclosing box and a list of bounds, this routine 422 | // computes the corresponding inner box. It is assumed that 423 | // the box points have been allocated already. 424 | //---------------------------------------------------------------------- 425 | 426 | void annBnds2Box( 427 | const ANNorthRect &bnd_box, // enclosing box 428 | int dim, // dimension of space 429 | int n_bnds, // number of bounds 430 | ANNorthHSArray bnds, // bounds array 431 | ANNorthRect &inner_box) // inner box (returned) 432 | { 433 | annAssignRect(dim, inner_box, bnd_box); // copy bounding box to inner 434 | 435 | for (int i = 0; i < n_bnds; i++) { 436 | bnds[i].project(inner_box.lo); // project each endpoint 437 | bnds[i].project(inner_box.hi); 438 | } 439 | } 440 | -------------------------------------------------------------------------------- /src/vendor/ann/kd_util.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // File: kd_util.h 3 | // Programmer: Sunil Arya and David Mount 4 | // Description: Common utilities for kd- trees 5 | // Last modified: 01/04/05 (Version 1.0) 6 | //---------------------------------------------------------------------- 7 | // Copyright (c) 1997-2005 University of Maryland and Sunil Arya and 8 | // David Mount. All Rights Reserved. 9 | // 10 | // This software and related documentation is part of the Approximate 11 | // Nearest Neighbor Library (ANN). This software is provided under 12 | // the provisions of the Lesser GNU Public License (LGPL). See the 13 | // file ../ReadMe.txt for further information. 14 | // 15 | // The University of Maryland (U.M.) and the authors make no 16 | // representations about the suitability or fitness of this software for 17 | // any purpose. It is provided "as is" without express or implied 18 | // warranty. 19 | //---------------------------------------------------------------------- 20 | // History: 21 | // Revision 0.1 03/04/98 22 | // Initial release 23 | //---------------------------------------------------------------------- 24 | 25 | #ifndef ANN_kd_util_H 26 | #define ANN_kd_util_H 27 | 28 | #include "kd_tree.h" // kd-tree declarations 29 | 30 | //---------------------------------------------------------------------- 31 | // externally accessible functions 32 | //---------------------------------------------------------------------- 33 | 34 | double annAspectRatio( // compute aspect ratio of box 35 | int dim, // dimension 36 | const ANNorthRect &bnd_box); // bounding cube 37 | 38 | void annEnclRect( // compute smallest enclosing rectangle 39 | ANNpointArray pa, // point array 40 | ANNidxArray pidx, // point indices 41 | int n, // number of points 42 | int dim, // dimension 43 | ANNorthRect &bnds); // bounding cube (returned) 44 | 45 | void annEnclCube( // compute smallest enclosing cube 46 | ANNpointArray pa, // point array 47 | ANNidxArray pidx, // point indices 48 | int n, // number of points 49 | int dim, // dimension 50 | ANNorthRect &bnds); // bounding cube (returned) 51 | 52 | ANNdist annBoxDistance( // compute distance from point to box 53 | const ANNpoint q, // the point 54 | const ANNpoint lo, // low point of box 55 | const ANNpoint hi, // high point of box 56 | int dim); // dimension of space 57 | 58 | ANNcoord annSpread( // compute point spread along dimension 59 | ANNpointArray pa, // point array 60 | ANNidxArray pidx, // point indices 61 | int n, // number of points 62 | int d); // dimension to check 63 | 64 | void annMinMax( // compute min and max coordinates along dim 65 | ANNpointArray pa, // point array 66 | ANNidxArray pidx, // point indices 67 | int n, // number of points 68 | int d, // dimension to check 69 | ANNcoord& min, // minimum value (returned) 70 | ANNcoord& max); // maximum value (returned) 71 | 72 | int annMaxSpread( // compute dimension of max spread 73 | ANNpointArray pa, // point array 74 | ANNidxArray pidx, // point indices 75 | int n, // number of points 76 | int dim); // dimension of space 77 | 78 | void annMedianSplit( // split points along median value 79 | ANNpointArray pa, // points to split 80 | ANNidxArray pidx, // point indices 81 | int n, // number of points 82 | int d, // dimension along which to split 83 | ANNcoord &cv, // cutting value 84 | int n_lo); // split into n_lo and n-n_lo 85 | 86 | void annPlaneSplit( // split points by a plane 87 | ANNpointArray pa, // points to split 88 | ANNidxArray pidx, // point indices 89 | int n, // number of points 90 | int d, // dimension along which to split 91 | ANNcoord cv, // cutting value 92 | int &br1, // first break (values < cv) 93 | int &br2); // second break (values == cv) 94 | 95 | void annBoxSplit( // split points by a box 96 | ANNpointArray pa, // points to split 97 | ANNidxArray pidx, // point indices 98 | int n, // number of points 99 | int dim, // dimension of space 100 | ANNorthRect &box, // the box 101 | int &n_in); // number of points inside (returned) 102 | 103 | int annSplitBalance( // determine balance factor of a split 104 | ANNpointArray pa, // points to split 105 | ANNidxArray pidx, // point indices 106 | int n, // number of points 107 | int d, // dimension along which to split 108 | ANNcoord cv); // cutting value 109 | 110 | void annBox2Bnds( // convert inner box to bounds 111 | const ANNorthRect &inner_box, // inner box 112 | const ANNorthRect &bnd_box, // enclosing box 113 | int dim, // dimension of space 114 | int &n_bnds, // number of bounds (returned) 115 | ANNorthHSArray &bnds); // bounds array (returned) 116 | 117 | void annBnds2Box( // convert bounds to inner box 118 | const ANNorthRect &bnd_box, // enclosing box 119 | int dim, // dimension of space 120 | int n_bnds, // number of bounds 121 | ANNorthHSArray bnds, // bounds array 122 | ANNorthRect &inner_box); // inner box (returned) 123 | 124 | #endif 125 | -------------------------------------------------------------------------------- /src/vendor/ann/pr_queue.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // File: pr_queue.h 3 | // Programmer: Sunil Arya and David Mount 4 | // Description: Include file for priority queue and related 5 | // structures. 6 | // Last modified: 01/04/05 (Version 1.0) 7 | //---------------------------------------------------------------------- 8 | // Copyright (c) 1997-2005 University of Maryland and Sunil Arya and 9 | // David Mount. All Rights Reserved. 10 | // 11 | // This software and related documentation is part of the Approximate 12 | // Nearest Neighbor Library (ANN). This software is provided under 13 | // the provisions of the Lesser GNU Public License (LGPL). See the 14 | // file ../ReadMe.txt for further information. 15 | // 16 | // The University of Maryland (U.M.) and the authors make no 17 | // representations about the suitability or fitness of this software for 18 | // any purpose. It is provided "as is" without express or implied 19 | // warranty. 20 | //---------------------------------------------------------------------- 21 | // History: 22 | // Revision 0.1 03/04/98 23 | // Initial release 24 | //---------------------------------------------------------------------- 25 | 26 | #ifndef PR_QUEUE_H 27 | #define PR_QUEUE_H 28 | 29 | #include // all ANN includes 30 | #include // performance evaluation 31 | 32 | //---------------------------------------------------------------------- 33 | // Basic types. 34 | //---------------------------------------------------------------------- 35 | typedef void *PQinfo; // info field is generic pointer 36 | typedef ANNdist PQkey; // key field is distance 37 | 38 | //---------------------------------------------------------------------- 39 | // Priority queue 40 | // A priority queue is a list of items, along with associated 41 | // priorities. The basic operations are insert and extract_minimum. 42 | // 43 | // The priority queue is maintained using a standard binary heap. 44 | // (Implementation note: Indexing is performed from [1..max] rather 45 | // than the C standard of [0..max-1]. This simplifies parent/child 46 | // computations.) User information consists of a void pointer, 47 | // and the user is responsible for casting this quantity into whatever 48 | // useful form is desired. 49 | // 50 | // Because the priority queue is so central to the efficiency of 51 | // query processing, all the code is inline. 52 | //---------------------------------------------------------------------- 53 | 54 | class ANNpr_queue { 55 | 56 | struct pq_node { // node in priority queue 57 | PQkey key; // key value 58 | PQinfo info; // info field 59 | }; 60 | int n; // number of items in queue 61 | int max_size; // maximum queue size 62 | pq_node *pq; // the priority queue (array of nodes) 63 | 64 | public: 65 | ANNpr_queue(int max) // constructor (given max size) 66 | { 67 | n = 0; // initially empty 68 | max_size = max; // maximum number of items 69 | pq = new pq_node[max+1]; // queue is array [1..max] of nodes 70 | } 71 | 72 | ~ANNpr_queue() // destructor 73 | { delete [] pq; } 74 | 75 | ANNbool empty() // is queue empty? 76 | { if (n==0) return ANNtrue; else return ANNfalse; } 77 | 78 | ANNbool non_empty() // is queue nonempty? 79 | { if (n==0) return ANNfalse; else return ANNtrue; } 80 | 81 | void reset() // make existing queue empty 82 | { n = 0; } 83 | 84 | inline void insert( // insert item (inlined for speed) 85 | PQkey kv, // key value 86 | PQinfo inf) // item info 87 | { 88 | if (++n > max_size) annError("Priority queue overflow.", ANNabort); 89 | int r = n; 90 | while (r > 1) { // sift up new item 91 | int p = r/2; 92 | ANN_FLOP(1) // increment floating ops 93 | if (pq[p].key <= kv) // in proper order 94 | break; 95 | pq[r] = pq[p]; // else swap with parent 96 | r = p; 97 | } 98 | pq[r].key = kv; // insert new item at final location 99 | pq[r].info = inf; 100 | } 101 | 102 | inline void extr_min( // extract minimum (inlined for speed) 103 | PQkey &kv, // key (returned) 104 | PQinfo &inf) // item info (returned) 105 | { 106 | kv = pq[1].key; // key of min item 107 | inf = pq[1].info; // information of min item 108 | PQkey kn = pq[n--].key;// last item in queue 109 | int p = 1; // p points to item out of position 110 | int r = p<<1; // left child of p 111 | while (r <= n) { // while r is still within the heap 112 | ANN_FLOP(2) // increment floating ops 113 | // set r to smaller child of p 114 | if (r < n && pq[r].key > pq[r+1].key) r++; 115 | if (kn <= pq[r].key) // in proper order 116 | break; 117 | pq[p] = pq[r]; // else swap with child 118 | p = r; // advance pointers 119 | r = p<<1; 120 | } 121 | pq[p] = pq[n+1]; // insert last item in proper place 122 | } 123 | }; 124 | 125 | #endif 126 | -------------------------------------------------------------------------------- /src/vendor/ann/pr_queue_k.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // File: pr_queue_k.h 3 | // Programmer: Sunil Arya and David Mount 4 | // Description: Include file for priority queue with k items. 5 | // Last modified: 01/04/05 (Version 1.0) 6 | //---------------------------------------------------------------------- 7 | // Copyright (c) 1997-2005 University of Maryland and Sunil Arya and 8 | // David Mount. All Rights Reserved. 9 | // 10 | // This software and related documentation is part of the Approximate 11 | // Nearest Neighbor Library (ANN). This software is provided under 12 | // the provisions of the Lesser GNU Public License (LGPL). See the 13 | // file ../ReadMe.txt for further information. 14 | // 15 | // The University of Maryland (U.M.) and the authors make no 16 | // representations about the suitability or fitness of this software for 17 | // any purpose. It is provided "as is" without express or implied 18 | // warranty. 19 | //---------------------------------------------------------------------- 20 | // History: 21 | // Revision 0.1 03/04/98 22 | // Initial release 23 | //---------------------------------------------------------------------- 24 | 25 | #ifndef PR_QUEUE_K_H 26 | #define PR_QUEUE_K_H 27 | 28 | #include // all ANN includes 29 | #include // performance evaluation 30 | 31 | //---------------------------------------------------------------------- 32 | // Basic types 33 | //---------------------------------------------------------------------- 34 | typedef ANNdist PQKkey; // key field is distance 35 | typedef int PQKinfo; // info field is int 36 | 37 | //---------------------------------------------------------------------- 38 | // Constants 39 | // The NULL key value is used to initialize the priority queue, and 40 | // so it should be larger than any valid distance, so that it will 41 | // be replaced as legal distance values are inserted. The NULL 42 | // info value must be a nonvalid array index, we use ANN_NULL_IDX, 43 | // which is guaranteed to be negative. 44 | //---------------------------------------------------------------------- 45 | 46 | const PQKkey PQ_NULL_KEY = ANN_DIST_INF; // nonexistent key value 47 | const PQKinfo PQ_NULL_INFO = ANN_NULL_IDX; // nonexistent info value 48 | 49 | //---------------------------------------------------------------------- 50 | // ANNmin_k 51 | // An ANNmin_k structure is one which maintains the smallest 52 | // k values (of type PQKkey) and associated information (of type 53 | // PQKinfo). The special info and key values PQ_NULL_INFO and 54 | // PQ_NULL_KEY means that thise entry is empty. 55 | // 56 | // It is currently implemented using an array with k items. 57 | // Items are stored in increasing sorted order, and insertions 58 | // are made through standard insertion sort. (This is quite 59 | // inefficient, but current applications call for small values 60 | // of k and relatively few insertions.) 61 | // 62 | // Note that the list contains k+1 entries, but the last entry 63 | // is used as a simple placeholder and is otherwise ignored. 64 | //---------------------------------------------------------------------- 65 | 66 | class ANNmin_k { 67 | struct mk_node { // node in min_k structure 68 | PQKkey key; // key value 69 | PQKinfo info; // info field (user defined) 70 | }; 71 | 72 | int k; // max number of keys to store 73 | int n; // number of keys currently active 74 | mk_node *mk; // the list itself 75 | 76 | public: 77 | ANNmin_k(int max) // constructor (given max size) 78 | { 79 | n = 0; // initially no items 80 | k = max; // maximum number of items 81 | mk = new mk_node[max+1]; // sorted array of keys 82 | } 83 | 84 | ~ANNmin_k() // destructor 85 | { delete [] mk; } 86 | 87 | PQKkey ANNmin_key() // return minimum key 88 | { return (n > 0 ? mk[0].key : PQ_NULL_KEY); } 89 | 90 | PQKkey max_key() // return maximum key 91 | { return (n == k ? mk[k-1].key : PQ_NULL_KEY); } 92 | 93 | PQKkey ith_smallest_key(int i) // ith smallest key (i in [0..n-1]) 94 | { return (i < n ? mk[i].key : PQ_NULL_KEY); } 95 | 96 | PQKinfo ith_smallest_info(int i) // info for ith smallest (i in [0..n-1]) 97 | { return (i < n ? mk[i].info : PQ_NULL_INFO); } 98 | 99 | inline void insert( // insert item (inlined for speed) 100 | PQKkey kv, // key value 101 | PQKinfo inf) // item info 102 | { 103 | int i; 104 | // slide larger values up 105 | for (i = n; i > 0; i--) { 106 | if (mk[i-1].key > kv) 107 | mk[i] = mk[i-1]; 108 | else 109 | break; 110 | } 111 | mk[i].key = kv; // store element here 112 | mk[i].info = inf; 113 | if (n < k) n++; // increment number of items 114 | ANN_FLOP(k-i+1) // increment floating ops 115 | } 116 | }; 117 | 118 | #endif 119 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(RANN) 3 | 4 | test_check("RANN") 5 | -------------------------------------------------------------------------------- /tests/testthat/test-nn.R: -------------------------------------------------------------------------------- 1 | context("nn2") 2 | 3 | test_that("basic use of nn2", { 4 | 5 | res<-structure(list(nn.idx = structure(c(1L, 2L, 2L), 6 | .Dim = c(3L, 1L)), 7 | nn.dists = structure(c(0.01, 1, 2), .Dim = c(3L, 1L))), 8 | .Names = c("nn.idx", "nn.dists")) 9 | 10 | res.func<-nn2(rbind(c(1,0),c(2,0)),rbind(c(1.01,0),c(3,0),c(4.0,0)),k=1) 11 | expect_equal(res,res.func) 12 | 13 | a=structure(c(-0.626453810742332, 0.183643324222082, -0.835628612410047, 14 | 1.59528080213779, 0.329507771815361, -0.820468384118015, 0.487429052428485, 15 | 0.738324705129217, 0.575781351653492, -0.305388387156356, 1.51178116845085, 16 | 0.389843236411431, -0.621240580541804, -2.2146998871775, 1.12493091814311, 17 | -0.0449336090152309, -0.0161902630989461, 0.94383621068530, 0.821221195098089, 18 | 0.593901321217509, 0.918977371608218, 0.782136300731067, 0.0745649833651906, 19 | -1.98935169586337, 0.61982574789471, -0.0561287395290008, -0.155795506705329, 20 | -1.47075238389927, -0.47815005510862, 0.417941560199702), .Dim = c(10L, 21 | 3L)) 22 | 23 | b=structure(c(1.35867955152904, -0.102787727342996, 0.387671611559369, 24 | -0.0538050405829051, -1.37705955682861, -0.41499456329968, -0.394289953710349, 25 | -0.0593133967111857, 1.10002537198388, 0.763175748457544, -0.164523596253587, 26 | -0.253361680136508, 0.696963375404737, 0.556663198673657, -0.68875569454952, 27 | -0.70749515696212, 0.36458196213683, 0.768532924515416, -0.112346212150228, 28 | 0.881107726454215, 0.398105880367068, -0.612026393250771, 0.341119691424425, 29 | -1.12936309608079, 1.43302370170104, 1.98039989850586, -0.367221476466509, 30 | -1.04413462631653, 0.569719627442413, -0.135054603880824), .Dim = c(10L, 31 | 3L)) 32 | 33 | nearest=structure(list( 34 | nn.idx = structure(c(7L, 7L, 5L, 9L, 3L, 2L, 6L, 35 | 9L, 7L, 9L, 2L, 6L, 2L, 8L, 6L, 3L, 10L, 8L, 2L, 5L, 9L, 3L, 36 | 10L, 7L, 10L, 10L, 7L, 7L, 5L, 7L, 5L, 9L, 9L, 6L, 2L, 6L, 9L, 37 | 6L, 9L, 2L, 10L, 10L, 7L, 10L, 1L, 5L, 3L, 10L, 10L, 10L), 38 | .Dim = c(10L, 5L)), 39 | nn.dists = structure(c(1.04301819567468, 0.782785251535478, 40 | 0.514019762075842, 0.943635726058299, 1.46393847125353, 1.73157573316917, 41 | 0.66791447696244, 0.852326186446708, 0.954406845715277, 0.395496580572611, 42 | 1.35481071903339, 0.931412898425681, 0.574844301957827, 0.945472961596115, 43 | 1.71518967014802, 1.95360681279363, 0.822782991518318, 0.921390522381496, 44 | 1.06633538007411, 0.904080753178077, 1.53376883835267, 1.06948509416105, 45 | 0.704879811283639, 1.25256907321914, 1.95552547157996, 2.03639936314308, 46 | 0.983420985126367, 1.30532148465522, 1.45844529983923, 0.938940949941509, 47 | 1.66464626768377, 1.27793083718641, 0.849722423887674, 1.44966319723756, 48 | 2.00569777023645, 2.179643484087, 1.07789743302845, 1.4890400761415, 49 | 1.49813576432115, 1.19098185772077, 1.82885863701822, 1.3489757618116, 50 | 0.874908208472254, 1.56806650285981, 2.38117935086023, 2.40067304459157, 51 | 1.16696237017602, 1.49288843286122, 1.58019302443234, 1.23698083599426), 52 | .Dim = c(10L, 5L))), 53 | .Names = c("nn.idx", "nn.dists")) 54 | 55 | expect_equal(nn2(a, b, k=5), nearest, tol=1e-6) 56 | }) 57 | 58 | # NB this fails with the version of ANN distributed with knnFinder v1.0 59 | test_that("nn2 with identical point", { 60 | res<-structure(list(nn.idx = structure(c(1L, 2L, 2L), .Dim = c(3L, 61 | 1L)), nn.dists = structure(c(0.00, 1, 2), .Dim = c(3L, 1L))), .Names = c("nn.idx", 62 | "nn.dists")) 63 | 64 | res.func<-nn2(rbind(c(1,0),c(2,0)),rbind(c(1.0,0),c(3,0),c(4.0,0)),k=1) 65 | expect_equal(res,res.func) 66 | }) 67 | 68 | 69 | test_that("nn2 with different search / tree types", { 70 | set.seed(1) 71 | a=matrix(rnorm(3000),ncol=3) 72 | b=matrix(rnorm(3000),ncol=3) 73 | n.standard<-nn2(a,b,k=5,searchtype='standard') 74 | n.priority<-nn2(a,b,k=5,searchtype='priority') 75 | n.bd.standard<-nn2(a,b,k=5,searchtype='standard',treetype='bd') 76 | n.bd.priority<-nn2(a,b,k=5,searchtype='priority',treetype='bd') 77 | 78 | expect_equal(n.standard,n.priority) 79 | expect_equal(n.standard,n.bd.standard) 80 | expect_equal(n.standard,n.bd.priority) 81 | }) 82 | 83 | test_that("nn2 fixed radius with large radius", { 84 | set.seed(1) 85 | a=matrix(rnorm(3000),ncol=3) 86 | b=matrix(rnorm(3000),ncol=3) 87 | n.standard<-nn2(a,b,k=5,searchtype='standard') 88 | n.rad<-nn2(a,b,k=5,searchtype='radius',radius=20.0) 89 | n.bd.rad<-nn2(a,b,k=5,searchtype='radius',radius=20.0,treetype='bd') 90 | 91 | expect_equal(n.standard,n.rad) 92 | expect_equal(n.standard,n.bd.rad) 93 | }) 94 | 95 | test_that("matrix with 0 columns", { 96 | d=matrix(ncol=0,nrow=90) 97 | expect_error(nn2(d)) 98 | }) 99 | 100 | test_that("all NA", { 101 | data=matrix(rnorm(10), ncol=2) 102 | query=matrix(rep(NA_real_,10), ncol=2) 103 | expect_error(nn2(data = data, query = query, k=1)) 104 | }) 105 | 106 | test_that("mixture of matrix and vector inputs", { 107 | mat=matrix(rnorm(10), ncol=1) 108 | vec=as.numeric(mat) 109 | expect_is(res<-nn2(data = mat, query = vec, k=1), 'list') 110 | expect_equal(nn2(data = vec, query = mat, k=1), res) 111 | expect_equal(nn2(data = vec, query = vec, k=1), res) 112 | }) 113 | 114 | test_that("vector inputs give outputs of appropriate length", { 115 | expect_is(res<-nn2(data = rnorm(10), query = rnorm(5), k=1), 'list') 116 | expect_equal(length(res$nn.idx), 5L) 117 | }) 118 | 119 | test_that("inputs with different dimensions", { 120 | mat=matrix(rnorm(20), ncol=2) 121 | vec=as.numeric(mat[,1]) 122 | expect_error(nn2(data = mat, query = vec, k=1), 'same dimensions') 123 | }) 124 | --------------------------------------------------------------------------------