예제 #1
0
        /// <summary>
        /// Returns the Inverse Hyperbolic Sine
        /// <para>Asinh(x) = ln(x + Sqrt(x^2 + 1))</para>
        /// </summary>
        /// <param name="x">Asinh argument</param>
        public static double Asinh(double x)
        {
            if (double.IsNaN(x))
            {
                Policies.ReportDomainError("Asinh(x: {0}): NaNs not allowed", x);
                return(double.NaN);
            }
            if (double.IsInfinity(x))
            {
                return(x);
            }

            // odd function
            if (x < 0)
            {
                return(-Math2.Asinh(-x));
            }

            // For |x| < eps^(1/4), use a taylor series
            // Asinh(x) = z - z^3/6 + 3 * z^5/40 ...
            // http://functions.wolfram.com/ElementaryFunctions/ArcSinh/06/01/03/01/
            //
            // otherwise use varying forms of
            // Ln(x + Sqrt(x * x + 1))
            // http://functions.wolfram.com/ElementaryFunctions/ArcSinh/02/


            if (x < 0.75)
            {
                if (x < DoubleLimits.RootMachineEpsilon._4)
                {
                    return(x * (1.0 - x * x / 6));
                }

                // rearrangment of log(x + sqrt(x^2 + 1)) to preserve digits:
                return(Math2.Log1p(x + Math2.Sqrt1pm1(x * x)));
            }

            // for large x, result = Math.Log(2*x), but watch for overflows
            if (x > 1 / DoubleLimits.RootMachineEpsilon._2)
            {
                return(Constants.Ln2 + Math.Log(x));
            }


            return(Math.Log(x + Math.Sqrt(x * x + 1)));
        }