Esempio n. 1
0
        /**
         *  Convert radians to degrees, with error of less than 0.5 ULP
         *  @param x angle in radians
         *  @return x converted into degrees
         */
        public static double toDegrees(double x)
        {
            if (Double.IsInfinity(x) || x == 0.0)
            { // Matches +/- 0.0; return correct sign
                return(x);
            }

            // These are 180/PI split into high and low order bits
            double facta = 57.2957763671875;
            double factb = 3.145894820876798E-6;

            double xa = BitOps.HighPart(x);
            double xb = x - xa;

            return(xb * factb + xb * facta + xa * factb + xa * facta);
        }
Esempio n. 2
0
        /**
         *  Convert degrees to radians, with error of less than 0.5 ULP
         *  @param x angle in degrees
         *  @return x converted into radians
         */
        public static double ToRadians(double x)
        {
            if (Double.IsInfinity(x) || x == 0.0)
            { // Matches +/- 0.0; return correct sign
                return(x);
            }

            // These are PI/180 split into high and low order bits
            double facta = 0.01745329052209854;
            double factb = 1.997844754509471E-9;

            double xa = BitOps.HighPart(x);
            double xb = x - xa;

            double result = xb * factb + xb * facta + xa * factb + xa * facta;

            if (result == 0)
            {
                result = result * x; // ensure correct sign if calculation underflows
            }
            return(result);
        }
Esempio n. 3
0
        /**
         * Two arguments arctangent function
         * @param y ordinate
         * @param x abscissa
         * @return phase angle of point (x,y) between {@code -PI} and {@code PI}
         */
        public static double Arc(double y, double x)
        {
            if (y == 0)
            {
                double result = x * y;
                double invx   = 1d / x;
                double invy   = 1d / y;

                if (invx == 0)
                { // X is infinite
                    if (x > 0)
                    {
                        return(y); // return +/- 0.0
                    }
                    else
                    {
                        return(BitOps.CopySign(Math.PI, y));
                    }
                }

                if (x < 0 || invx < 0)
                {
                    if (y < 0 || invy < 0)
                    {
                        return(-Math.PI);
                    }
                    else
                    {
                        return(Math.PI);
                    }
                }
                else
                {
                    return(result);
                }
            }

            // y cannot now be zero

            if (y == Double.PositiveInfinity)
            {
                if (x == Double.PositiveInfinity)
                {
                    return(Math.PI * F_1_4);
                }

                if (x == Double.PositiveInfinity)
                {
                    return(Math.PI * F_3_4);
                }

                return(Math.PI * F_1_2);
            }

            if (y == Double.NegativeInfinity)
            {
                if (x == Double.PositiveInfinity)
                {
                    return(-Math.PI * F_1_4);
                }

                if (x == Double.NegativeInfinity)
                {
                    return(-Math.PI * F_3_4);
                }

                return(-Math.PI * F_1_2);
            }

            if (x == Double.PositiveInfinity)
            {
                if (y > 0 || 1 / y > 0)
                {
                    return(0d);
                }

                if (y < 0 || 1 / y < 0)
                {
                    return(-0d);
                }
            }

            if (x == Double.NegativeInfinity)
            {
                if (y > 0.0 || 1 / y > 0.0)
                {
                    return(Math.PI);
                }

                if (y < 0 || 1 / y < 0)
                {
                    return(-Math.PI);
                }
            }

            // Neither y nor x can be infinite or NAN here

            if (x == 0)
            {
                if (y > 0 || 1 / y > 0)
                {
                    return(Math.PI * F_1_2);
                }

                if (y < 0 || 1 / y < 0)
                {
                    return(-Math.PI * F_1_2);
                }
            }

            // Compute ratio r = y/x
            double r = y / x;

            if (Double.IsInfinity(r))
            { // bypass calculations that can create NaN
                return(Arc(r, 0, x < 0));
            }

            double ra = BitOps.HighPart(r);
            double rb = r - ra;

            // Split x
            double xa = BitOps.HighPart(x);
            double xb = x - xa;

            rb += (y - ra * xa - ra * xb - rb * xa - rb * xb) / x;

            double temp = ra + rb;

            rb = -(temp - ra - rb);
            ra = temp;

            if (ra == 0)
            { // Fix up the sign so atan works correctly
                ra = BitOps.CopySign(0d, y);
            }

            // Call atan
            return(Arc(ra, rb, x < 0));
        }
Esempio n. 4
0
        /** Compute the arc cosine of a number.
         * @param x number on which evaluation is done
         * @return arc cosine of x
         */
        public static double Arc(double x)
        {
            if (x > 1.0 || x < -1.0)
            {
                return(Double.NaN);
            }

            if (x == -1.0)
            {
                return(Math.PI);
            }

            if (x == 1.0)
            {
                return(0.0);
            }

            if (x == 0)
            {
                return(Math.PI / 2.0);
            }

            /* Compute acos(x) = atan(sqrt(1-x*x)/x) */

            /* Split x */
            double temp = x * BitOps.HEX_40000000;
            double xa   = x + temp - temp;
            double xb   = x - xa;

            /* Square it */
            double ya = xa * xa;
            double yb = xa * xb * 2.0 + xb * xb;

            /* Subtract from 1 */
            ya = -ya;
            yb = -yb;

            double za = 1.0 + ya;
            double zb = -(za - 1.0 - ya);

            temp = za + yb;
            zb  += -(temp - za - yb);
            za   = temp;

            /* Square root */
            double y = Math.Sqrt(za);

            temp = y * BitOps.HEX_40000000;
            ya   = y + temp - temp;
            yb   = y - ya;

            /* Extend precision of sqrt */
            yb += (za - ya * ya - 2 * ya * yb - yb * yb) / (2.0 * y);

            /* Contribution of zb to sqrt */
            yb += zb / (2.0 * y);
            y   = ya + yb;
            yb  = -(y - ya - yb);

            // Compute ratio r = y/x
            double r = y / x;

            // Did r overflow?
            if (double.IsInfinity(r))
            {                        // x is effectively zero
                return(Math.PI / 2); // so return the appropriate value
            }

            double ra = BitOps.HighPart(r);
            double rb = r - ra;

            rb += (y - ra * xa - ra * xb - rb * xa - rb * xb) / x; // Correct for rounding in division
            rb += yb / x;                                          // Add in effect additional bits of sqrt.

            temp = ra + rb;
            rb   = -(temp - ra - rb);
            ra   = temp;

            return(atan(ra, rb, x < 0));
        }