Пример #1
0
    private static void Main()
    //****************************************************************************80
    //
    //  Purpose:
    //
    //    MAIN is the main program for TOMS743_TEST.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    17 June 2014
    //
    //  Author:
    //
    //    Original FORTRAN77 version by Andrew Barry, S. J. Barry,
    //    Patricia Culligan-Hensley.
    //    C++ version by John Burkardt.
    //
    //  Reference:
    //
    //    Andrew Barry, S. J. Barry, Patricia Culligan-Hensley,
    //    Algorithm 743: WAPR - A Fortran routine for calculating real
    //    values of the W-function,
    //    ACM Transactions on Mathematical Software,
    //    Volume 21, Number 2, June 1995, pages 172-181.
    //
    {
        Console.WriteLine("");
        Console.WriteLine("TOMS743_TEST");
        Console.WriteLine("  Test the TOMS743 library.");

        int nbits = NBITS.nbits_compute();

        Console.WriteLine("");
        Console.WriteLine("  Number of bits in mantissa - 1 = " + nbits + "");

        test01(nbits);

        const double dx = +1.0E-09;
        int          n  = 10;

        test02(nbits, dx, n);

        const double xmin = 0.0;
        const double xmax = 1.0E+20;

        n = 20;
        test03(nbits, xmin, xmax, n);
        Console.WriteLine("");
        Console.WriteLine("TOMS743_TEST");
        Console.WriteLine("  Normal end of execution.");
        Console.WriteLine("");
    }
Пример #2
0
    public static double wapr(ref WAPRData data, double x, int nb, ref int nerror, int l)

    //****************************************************************************80
    //
    // WAPR approximates the W function.
    //
    //  Discussion:
    //
    //    The call will fail if the input value X is out of range.
    //    The range requirement for the upper branch is:
    //      -Math.Exp(-1) <= X.
    //    The range requirement for the lower branch is:
    //      -Math.Exp(-1) < X < 0.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    17 June 2014
    //
    //  Author:
    //
    //    Original FORTRAN77 version by Andrew Barry, S. J. Barry,
    //    Patricia Culligan-Hensley.
    //    C++ version by John Burkardt.
    //
    //  Reference:
    //
    //    Andrew Barry, S. J. Barry, Patricia Culligan-Hensley,
    //    Algorithm 743: WAPR - A Fortran routine for calculating real
    //    values of the W-function,
    //    ACM Transactions on Mathematical Software,
    //    Volume 21, Number 2, June 1995, pages 172-181.
    //
    //  Parameters:
    //
    //    Input, double X, the argument.
    //
    //    Input, int NB, indicates the desired branch.
    //    * 0, the upper branch;
    //    * nonzero, the lower branch.
    //
    //    Output, int &NERROR, the error flag.
    //    * 0, successful call.
    //    * 1, failure, the input X is out of range.
    //
    //    Input, int L, indicates the interpretation of X.
    //    * 1, X is actually the offset from -(Math.Exp-1), so compute W(X-Math.Exp(-1)).
    //    * not 1, X is the argument; compute W(X);
    //
    //    Output, double WAPR, the approximate value of W(X).
    //
    {
        double delx;
        int    i;
        double reta;
        double xx;
        double zl;

        double value = 0.0;

        nerror = 0;

        switch (data.init)
        {
        case 0:
        {
            data.init = 1;

            data.nbits = NBITS.nbits_compute();

            data.niter = data.nbits switch
            {
                >= 56 => 2,
                _ => data.niter
            };

            //
            //  Various mathematical constants.
            //
            data.em  = -Math.Exp(-1.0);
            data.em9 = -Math.Exp(-9.0);
            data.c13 = 1.0 / 3.0;
            data.c23 = 2.0 * data.c13;
            data.em2 = 2.0 / data.em;
            data.d12 = -data.em2;
            data.tb  = Math.Pow(0.5, data.nbits);
            data.x0  = Math.Pow(data.tb, 1.0 / 6.0) * 0.5;
            data.x1  = (1.0 - 17.0 * Math.Pow(data.tb, 2.0 / 7.0)) * data.em;
            data.an3 = 8.0 / 3.0;
            data.an4 = 135.0 / 83.0;
            data.an5 = 166.0 / 39.0;
            data.an6 = 3167.0 / 3549.0;
            data.s2  = Math.Sqrt(2.0);
            data.s21 = 2.0 * data.s2 - 3.0;
            data.s22 = 4.0 - 3.0 * data.s2;
            data.s23 = data.s2 - 2.0;
            break;
        }
Пример #3
0
    public static double bisect(ref BisectData data, double xx, int nb, ref int ner, int l)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    BISECT approximates the W function using bisection.
    //
    //  Discussion:
    //
    //    The parameter TOL, which determines the accuracy of the bisection
    //    method, is calculated using NBITS (assuming the final bit is lost
    //    due to rounding error).
    //
    //    N0 is the maximum number of iterations used in the bisection
    //    method.
    //
    //    For XX close to 0 for Wp, the exponential approximation is used.
    //    The approximation is exact to O(XX^8) so, depending on the value
    //    of NBITS, the range of application of this formula varies. Outside
    //    this range, the usual bisection method is used.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    17 June 2014
    //
    //  Author:
    //
    //    Original FORTRAN77 version by Andrew Barry, S. J. Barry,
    //    Patricia Culligan-Hensley.
    //    C++ version by John Burkardt.
    //
    //  Reference:
    //
    //    Andrew Barry, S. J. Barry, Patricia Culligan-Hensley,
    //    Algorithm 743: WAPR - A Fortran routine for calculating real
    //    values of the W-function,
    //    ACM Transactions on Mathematical Software,
    //    Volume 21, Number 2, June 1995, pages 172-181.
    //
    //  Parameters:
    //
    //    Input, double XX, the argument.
    //
    //    Input, int NB, indicates the branch of the W function.
    //    0, the upper branch;
    //    nonzero, the lower branch.
    //
    //    Output, int &NER, the error flag.
    //    0, success;
    //    1, the routine did not converge.  Perhaps reduce NBITS and try again.
    //
    //    Input, int L, the offset indicator.
    //    1, XX represents the offset of the argument from -Math.Exp(-1).
    //    not 1, XX is the actual argument.
    //
    //    Output, double BISECT, the value of W(X), as determined
    //
    {
        double    d;
        double    f;
        double    fd;
        int       i;
        const int n0 = 500;
        double    r;
        double    tol;
        double    u;

        double value = 0.0;

        ner = 0;

        data.nbits = data.nbits switch
        {
            0 => NBITS.nbits_compute(),
            _ => data.nbits
        };

        double x = l switch
        {
            1 => xx - Math.Exp(-1.0),
            _ => xx
        };

        switch (nb)
        {
        case 0:
        {
            double test = 1.0 / Math.Pow(Math.Pow(2.0, data.nbits), 1.0 / 7.0);

            if (Math.Abs(x) < test)
            {
                value = x
                        * Math.Exp(-x
                                   * Math.Exp(-x
                                              * Math.Exp(-x
                                                         * Math.Exp(-x
                                                                    * Math.Exp(-x
                                                                               * Math.Exp(-x))))));

                return(value);
            }

            u   = Crude.crude(ref data.data, x, nb) + 1.0E-03;
            tol = Math.Abs(u) / Math.Pow(2.0, data.nbits);
            d   = Math.Max(u - 2.0E-03, -1.0);

            for (i = 1; i <= n0; i++)
            {
                r     = 0.5 * (u - d);
                value = d + r;
                //
                //  Find root using w*Math.Exp(w)-x to avoid ln(0) error.
                //
                if (x < Math.Exp(1.0))
                {
                    f  = value * Math.Exp(value) - x;
                    fd = d * Math.Exp(d) - x;
                }
                //
                //  Find root using ln(w/x)+w to avoid overflow error.
                //
                else
                {
                    f  = Math.Log(value / x) + value;
                    fd = Math.Log(d / x) + d;
                }

                switch (f)
                {
                case 0.0:
                    return(value);
                }

                if (Math.Abs(r) <= tol)
                {
                    return(value);
                }

                switch (fd * f)
                {
                case > 0.0:
                    d = value;
                    break;

                default:
                    u = value;
                    break;
                }
            }

            break;
        }

        default:
        {
            d   = Crude.crude(ref data.data, x, nb) - 1.0E-03;
            u   = Math.Min(d + 2.0E-03, -1.0);
            tol = Math.Abs(u) / Math.Pow(2.0, data.nbits);

            for (i = 1; i <= n0; i++)
            {
                r     = 0.5 * (u - d);
                value = d + r;
                f     = value * Math.Exp(value) - x;

                switch (f)
                {
                case 0.0:
                    return(value);
                }

                if (Math.Abs(r) <= tol)
                {
                    return(value);
                }

                fd = d * Math.Exp(d) - x;

                switch (fd * f)
                {
                case > 0.0:
                    d = value;
                    break;

                default:
                    u = value;
                    break;
                }
            }

            break;
        }
        }

        //
        //  The iteration did not converge.
        //
        ner = 1;

        return(value);
    }
}