📄 rand.cpp
字号:
//----------------------------------------------------------------------// File: rand.cpp// Programmer: Sunil Arya and David Mount// Description: Routines for random point generation// Last modified: 08/04/06 (Version 1.1.1)//----------------------------------------------------------------------// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and// David Mount. All Rights Reserved.// // This software and related documentation is part of the Approximate// Nearest Neighbor Library (ANN). This software is provided under// the provisions of the Lesser GNU Public License (LGPL). See the// file ../ReadMe.txt for further information.// // The University of Maryland (U.M.) and the authors make no// representations about the suitability or fitness of this software for// any purpose. It is provided "as is" without express or implied// warranty.//----------------------------------------------------------------------// History:// Revision 0.1 03/04/98// Initial release// Revision 0.2 03/26/98// Changed random/srandom declarations for SGI's.// Revision 1.0 04/01/05// annClusGauss centers distributed over [-1,1] rather than [0,1]// Added annClusOrthFlats distribution// Changed procedure names to avoid namespace conflicts// Added annClusFlats distribution// Added rand/srand option and fixed annRan0() initialization.// Revision 1.1.1 08/04/06// Added planted distribution//----------------------------------------------------------------------#include "rand.h" // random generator declarationsusing namespace std; // make std:: accessible//----------------------------------------------------------------------// Globals//----------------------------------------------------------------------int annIdum = 0; // used for random number generation//------------------------------------------------------------------------// annRan0 - (safer) uniform random number generator//// The code given here is taken from "Numerical Recipes in C" by// William Press, Brian Flannery, Saul Teukolsky, and William// Vetterling. The task of the code is to do an additional randomizing// shuffle on the system-supplied random number generator to make it// safer to use. //// Returns a uniform deviate between 0.0 and 1.0 using the// system-supplied routine random() or rand(). Set the global// annIdum to any negative value to initialise or reinitialise// the sequence.//------------------------------------------------------------------------double annRan0(){ const int TAB_SIZE = 97; // table size: any large number int j; static double y, v[TAB_SIZE]; static int iff = 0; const double RAN_DIVISOR = double(ANN_RAND_MAX + 1UL); if (RAN_DIVISOR < 0) { cout << "RAN_DIVISOR " << RAN_DIVISOR << endl; exit(0); } //-------------------------------------------------------------------- // As a precaution against misuse, we will always initialize on the // first call, even if "annIdum" is not set negative. Determine // "maxran", the next integer after the largest representable value // of type int. We assume this is a factor of 2 smaller than the // corresponding value of type unsigned int. //-------------------------------------------------------------------- if (annIdum < 0 || iff == 0) { // initialize iff = 1; ANN_SRAND(annIdum); // (re)seed the generator annIdum = 1; for (j = 0; j < TAB_SIZE; j++) // exercise the system routine ANN_RAND(); // (values intentionally ignored) for (j = 0; j < TAB_SIZE; j++) // then save TAB_SIZE-1 values v[j] = ANN_RAND(); y = ANN_RAND(); // generate starting value } //-------------------------------------------------------------------- // This is where we start if not initializing. Use the previously // saved random number y to get an index j between 1 and TAB_SIZE-1. // Then use the corresponding v[j] for both the next j and as the // output number. //-------------------------------------------------------------------- j = int(TAB_SIZE * (y / RAN_DIVISOR)); y = v[j]; v[j] = ANN_RAND(); // refill the table entry return y / RAN_DIVISOR;}//------------------------------------------------------------------------// annRanInt - generate a random integer from {0,1,...,n-1}//// If n == 0, then -1 is returned.//------------------------------------------------------------------------static int annRanInt( int n){ int r = (int) (annRan0()*n); if (r == n) r--; // (in case annRan0() == 1 or n == 0) return r;}//------------------------------------------------------------------------// annRanUnif - generate a random uniform in [lo,hi]//------------------------------------------------------------------------static double annRanUnif( double lo, double hi){ return annRan0()*(hi-lo) + lo;}//------------------------------------------------------------------------// annRanGauss - Gaussian random number generator// Returns a normally distributed deviate with zero mean and unit// variance, using annRan0() as the source of uniform deviates.//------------------------------------------------------------------------static double annRanGauss(){ static int iset=0; static double gset; if (iset == 0) { // we don't have a deviate handy double v1, v2; double r = 2.0; while (r >= 1.0) { //------------------------------------------------------------ // Pick two uniform numbers in the square extending from -1 to // +1 in each direction, see if they are in the circle of radius // 1. If not, try again //------------------------------------------------------------ v1 = annRanUnif(-1, 1); v2 = annRanUnif(-1, 1); r = v1 * v1 + v2 * v2; } double fac = sqrt(-2.0 * log(r) / r); //----------------------------------------------------------------- // Now make the Box-Muller transformation to get two normal // deviates. Return one and save the other for next time. //----------------------------------------------------------------- gset = v1 * fac; iset = 1; // set flag return v2 * fac; } else { // we have an extra deviate handy iset = 0; // so unset the flag return gset; // and return it }}//------------------------------------------------------------------------// annRanLaplace - Laplacian random number generator// Returns a Laplacian distributed deviate with zero mean and// unit variance, using annRan0() as the source of uniform deviates. //// prob(x) = b/2 * exp(-b * |x|).//// b is chosen to be sqrt(2.0) so that the variance of the Laplacian// distribution [2/(b^2)] becomes 1. //------------------------------------------------------------------------static double annRanLaplace() { const double b = 1.4142136; double laprand = -log(annRan0()) / b; double sign = annRan0(); if (sign < 0.5) laprand = -laprand; return(laprand);}//----------------------------------------------------------------------// annUniformPts - Generate uniformly distributed points// A uniform distribution over [-1,1].//----------------------------------------------------------------------void annUniformPts( // uniform distribution ANNpointArray pa, // point array (modified) int n, // number of points int dim) // dimension{ for (int i = 0; i < n; i++) { for (int d = 0; d < dim; d++) { pa[i][d] = (ANNcoord) (annRanUnif(-1,1)); } }}//----------------------------------------------------------------------// annGaussPts - Generate Gaussian distributed points// A Gaussian distribution with zero mean and the given standard// deviation.//----------------------------------------------------------------------void annGaussPts( // Gaussian distribution ANNpointArray pa, // point array (modified) int n, // number of points int dim, // dimension double std_dev) // standard deviation{ for (int i = 0; i < n; i++) { for (int d = 0; d < dim; d++) { pa[i][d] = (ANNcoord) (annRanGauss() * std_dev); } }}//----------------------------------------------------------------------// annLaplacePts - Generate Laplacian distributed points// Generates a Laplacian distribution (zero mean and unit variance).//----------------------------------------------------------------------void annLaplacePts( // Laplacian distribution ANNpointArray pa, // point array (modified) int n, // number of points int dim) // dimension{ for (int i = 0; i < n; i++) { for (int d = 0; d < dim; d++) { pa[i][d] = (ANNcoord) annRanLaplace(); } }}//----------------------------------------------------------------------// annCoGaussPts - Generate correlated Gaussian distributed points// Generates a Gauss-Markov distribution of zero mean and unit// variance.//----------------------------------------------------------------------void annCoGaussPts( // correlated-Gaussian distribution ANNpointArray pa, // point array (modified) int n, // number of points int dim, // dimension double correlation) // correlation{ double std_dev_w = sqrt(1.0 - correlation * correlation); for (int i = 0; i < n; i++) { double previous = annRanGauss(); pa[i][0] = (ANNcoord) previous; for (int d = 1; d < dim; d++) { previous = correlation*previous + std_dev_w*annRanGauss(); pa[i][d] = (ANNcoord) previous; } }}//----------------------------------------------------------------------// annCoLaplacePts - Generate correlated Laplacian distributed points// Generates a Laplacian-Markov distribution of zero mean and unit// variance.//----------------------------------------------------------------------void annCoLaplacePts( // correlated-Laplacian distribution ANNpointArray pa, // point array (modified) int n, // number of points int dim, // dimension double correlation) // correlation{ double wn; double corr_sq = correlation * correlation; for (int i = 0; i < n; i++) { double previous = annRanLaplace(); pa[i][0] = (ANNcoord) previous; for (int d = 1; d < dim; d++) { double temp = annRan0(); if (temp < corr_sq) wn = 0.0; else wn = annRanLaplace(); previous = correlation * previous + wn; pa[i][d] = (ANNcoord) previous; } }}//----------------------------------------------------------------------// annClusGaussPts - Generate clusters of Gaussian distributed points
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -