コード例 #1
0
    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);
    }
コード例 #2
0
    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);
    }
コード例 #3
0
    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);
    }