public static double[] r8vec_uniform_unit_new(int m, ref r8vecNormalData data, ref int seed) //****************************************************************************80 // // Purpose: // // R8VEC_UNIFORM_UNIT_NEW generates a random unit vector. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 04 October 2012 // // Author: // // John Burkardt // // Parameters: // // Input, int M, the dimension of the space. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double R8VEC_UNIFORM_UNIT_NEW[M], a random direction vector, // with unit norm. // { int i; // // Take M random samples from the normal distribution. // double[] a = r8vec_normal_01_new(m, ref data, ref seed); // // Compute the norm. // double norm = 0.0; for (i = 0; i < m; i++) { norm += a[i] * a[i]; } norm = Math.Sqrt(norm); // // Normalize. // for (i = 0; i < m; i++) { a[i] /= norm; } return(a); }
public static double[] r8mat_normal_01_new(int m, int n, ref r8vecNormalData data, ref int seed) //****************************************************************************80 // // Purpose: // // R8MAT_NORMAL_01_NEW returns a unit pseudonormal R8MAT. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 09 April 2012 // // Author: // // John Burkardt // // Reference: // // Paul Bratley, Bennett Fox, Linus Schrage, // A Guide to Simulation, // Springer Verlag, pages 201-202, 1983. // // Bennett Fox, // Algorithm 647: // Implementation and Relative Efficiency of Quasirandom // Sequence Generators, // ACM Transactions on Mathematical Software, // Volume 12, Number 4, pages 362-376, 1986. // // Peter Lewis, Allen Goodman, James Miller, // A Pseudo-Random Number Generator for the System/360, // IBM Systems Journal, // Volume 8, pages 136-143, 1969. // // Parameters: // // Input, int M, N, the number of rows and columns in the array. // // Input/output, int &SEED, the "seed" value, which should NOT be 0. // On output, SEED has been updated. // // Output, double R8MAT_NORMAL_01_NEW[M*N], the array of pseudonormal values. // { double[] r = r8vec_normal_01_new(m * n, ref data, ref seed); return(r); }
public static double[] r8vec_normal_01_new(int n, ref r8vecNormalData data, ref int seed) //****************************************************************************80 // // Purpose: // // R8VEC_NORMAL_01_NEW returns a unit pseudonormal R8VEC. // // Discussion: // // An R8VEC is a vector of R8's. // // The standard normal probability distribution function (PDF) has // mean 0 and standard deviation 1. // // This routine can generate a vector of values on one call. It // has the feature that it should provide the same results // in the same order no matter how we break up the task. // // Before calling this routine, the user may call RANDOM_SEED // in order to set the seed of the random number generator. // // The Box-Muller method is used, which is efficient, but // generates an even number of values each time. On any call // to this routine, an even number of new values are generated. // Depending on the situation, one value may be left over. // In that case, it is saved for the next call. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 February 2005 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of values desired. If N is negative, // then the code will flush its internal memory; in particular, // if there is a saved value to be used on the next call, it is // instead discarded. This is useful if the user has reset the // random number seed, for instance. // // Input/output, int &SEED, a seed for the random number generator. // // Output, double R8VEC_NORMAL_01_NEW[N], a sample of the standard normal PDF. // // Local parameters: // // Local, int MADE, records the number of values that have // been computed. On input with negative N, this value overwrites // the return value of N, so the user can get an accounting of // how much work has been done. // // Local, double R[N+1], is used to store some uniform random values. // Its dimension is N+1, but really it is only needed to be the // smallest even number greater than or equal to N. // // Local, int SAVED, is 0 or 1 depending on whether there is a // single saved value left over from the previous call. // // Local, int X_LO, X_HI, records the range of entries of // X that we need to compute. This starts off as 1:N, but is adjusted // if we have a saved value that can be immediately stored in X(1), // and so on. // // Local, double Y, the value saved from the previous call, if // SAVED is 1. // { double[] r; switch (n) { // // I'd like to allow the user to reset the internal data. // But this won't work properly if we have a saved value Y. // I'm making a crock option that allows the user to signal // explicitly that any internal memory should be flushed, // by passing in a negative value for N. // case < 0: data.made = 0; data.saved = 0; data.y = 0.0; return(null); case 0: return(null); } double[] x = new double[n]; // // Record the range of X we need to fill in. // int x_lo = 1; int x_hi = n; switch (data.saved) { // // Use up the old value, if we have it. // case 1: x[0] = data.y; data.saved = 0; x_lo = 2; break; } switch (x_hi - x_lo + 1) { // // Maybe we don't need any more values. // case 0: break; // // If we need just one new value, do that here to avoid null arrays. // case 1: r = UniformRNG.r8vec_uniform_01_new(2, ref seed); x[x_hi - 1] = Math.Sqrt(-2.0 * Math.Log(r[0])) * Math.Cos(2.0 * Math.PI * r[1]); data.y = Math.Sqrt(-2.0 * Math.Log(r[0])) * Math.Sin(2.0 * Math.PI * r[1]); data.saved = 1; data.made += 2; break; // default: { int i; int m; switch ((x_hi - x_lo + 1) % 2) { case 0: { m = (x_hi - x_lo + 1) / 2; r = UniformRNG.r8vec_uniform_01_new(2 * m, ref seed); for (i = 0; i <= 2 * m - 2; i += 2) { x[x_lo + i - 1] = Math.Sqrt(-2.0 * Math.Log(r[i])) * Math.Cos(2.0 * Math.PI * r[i + 1]); x[x_lo + i] = Math.Sqrt(-2.0 * Math.Log(r[i])) * Math.Sin(2.0 * Math.PI * r[i + 1]); } data.made = data.made + x_hi - x_lo + 1; break; } // default: { x_hi -= 1; m = (x_hi - x_lo + 1) / 2 + 1; r = UniformRNG.r8vec_uniform_01_new(2 * m, ref seed); for (i = 0; i <= 2 * m - 4; i += 2) { x[x_lo + i - 1] = Math.Sqrt(-2.0 * Math.Log(r[i])) * Math.Cos(2.0 * Math.PI * r[i + 1]); x[x_lo + i] = Math.Sqrt(-2.0 * Math.Log(r[i])) * Math.Sin(2.0 * Math.PI * r[i + 1]); } i = 2 * m - 2; x[x_lo + i - 1] = Math.Sqrt(-2.0 * Math.Log(r[i])) * Math.Cos(2.0 * Math.PI * r[i + 1]); data.y = Math.Sqrt(-2.0 * Math.Log(r[i])) * Math.Sin(2.0 * Math.PI * r[i + 1]); data.saved = 1; data.made = data.made + x_hi - x_lo + 2; break; } } break; } } return(x); }