/**
         * Computes (a+b)^2 in two different ways and compares the result.
         * For correct results, a and b should be integers.
         *
         * @param a
         * @param b
         */

        private static void CheckBinomialSquare(double a, double b)
        {
            // binomial square
            var add    = new DD(a);
            var bdd    = new DD(b);
            var aPlusb = add.Add(bdd);
            var abSq   = aPlusb.Multiply(aPlusb);
            //      System.out.println("(a+b)^2 = " + abSq);

            // expansion
            var a2DD = add.Multiply(add);
            var b2DD = bdd.Multiply(bdd);
            var ab   = add.Multiply(bdd);
            var sum  = b2DD.Add(ab).Add(ab);

            //      System.out.println("2ab+b^2 = " + sum);

            var diff = abSq.Subtract(a2DD);
            //      System.out.println("(a+b)^2 - a^2 = " + diff);

            var delta = diff.Subtract(sum);

            Console.WriteLine("\nA = " + a + ", B = " + b);
            Console.WriteLine("[DD]     2ab+b^2 = " + sum
                              + "   (a+b)^2 - a^2 = " + diff
                              + "   delta = " + delta);
            PrintBinomialSquareDouble(a, b);

            var isSame = diff.Equals(sum);

            Assert.IsTrue(isSame);
            var isDeltaZero = delta.IsZero;

            Assert.IsTrue(isDeltaZero);
        }
        /**
         * This routine simply tests for robustness of the toString function.
         *
         * @param xdd
         */
        private static void WriteRepeatedSqrt(DD xdd)
        {
            int count = 0;

            while (xdd.ToDoubleValue() > 1e-300)
            {
                count++;
                //if (count == 100)
                //    count = count;
                double x     = xdd.ToDoubleValue();
                DD     xSqrt = xdd.Sqrt();
                String s     = xSqrt.ToString();
//			System.out.println(count + ": " + s);

                DD     xSqrt2 = DD.Parse(s);
                DD     xx     = xSqrt2.Multiply(xSqrt2);
                double err    = Math.Abs(xx.ToDoubleValue() - x);
                //assertTrue(err < 1e-10);

                xdd = xSqrt;

                // square roots converge on 1 - stop when very close
                DD     distFrom1DD = xSqrt.Subtract(DD.ValueOf(1.0));
                double distFrom1   = distFrom1DD.ToDoubleValue();
                if (Math.Abs(distFrom1) < 1.0e-40)
                {
                    break;
                }
            }
        }
        private static void CheckAddMult2(DD dd)
        {
            DD sum  = dd.Add(dd);
            DD prod = dd.Multiply(new DD(2.0));

            CheckErrorBound("AddMult2", sum, prod, 0.0);
        }
        private static void CheckBinomial2(double a, double b)
        {
            // binomial product
            var add    = new DD(a);
            var bdd    = new DD(b);
            var aPlusb = add.Add(bdd);
            var aSubb  = add.Subtract(bdd);
            var abProd = aPlusb.Multiply(aSubb);
            //      System.out.println("(a+b)^2 = " + abSq);

            // expansion
            var a2DD = add.Multiply(add);
            var b2DD = bdd.Multiply(bdd);

            //      System.out.println("2ab+b^2 = " + sum);

            // this should equal b^2
            var diff = abProd.Subtract(a2DD).Negate();
            //      System.out.println("(a+b)^2 - a^2 = " + diff);

            var delta = diff.Subtract(b2DD);

            Console.WriteLine("\nA = " + a + ", B = " + b);
            Console.WriteLine("[DD] (a+b)(a-b) = " + abProd
                              + "   -((a^2 - b^2) - a^2) = " + diff
                              + "   delta = " + delta);
            //      printBinomialSquareDouble(a,b);

            var isSame = diff.Equals(b2DD);

            Assert.IsTrue(isSame);
            var isDeltaZero = delta.IsZero;

            Assert.IsTrue(isDeltaZero);
        }
        public static bool IsInCircleDD(
            Coordinate a, Coordinate b, Coordinate c,
            Coordinate p)
        {
            var px = new DD(p.X);
            var py = new DD(p.Y);
            var ax = new DD(a.X);
            var ay = new DD(a.Y);
            var bx = new DD(b.X);
            var by = new DD(b.Y);
            var cx = new DD(c.X);
            var cy = new DD(c.Y);

            var aTerm = (ax.Multiply(ax).Add(ay.Multiply(ay)))
                        .Multiply(TriAreaDD(bx, by, cx, cy, px, py));
            var bTerm = (bx.Multiply(bx).Add(by.Multiply(by)))
                        .Multiply(TriAreaDD(ax, ay, cx, cy, px, py));
            var cTerm = (cx.Multiply(cx).Add(cy.Multiply(cy)))
                        .Multiply(TriAreaDD(ax, ay, bx, by, px, py));
            var pTerm = (px.Multiply(px).Add(py.Multiply(py)))
                        .Multiply(TriAreaDD(ax, ay, bx, by, cx, cy));

            var  sum        = aTerm.Subtract(bTerm).Add(cTerm).Subtract(pTerm);
            bool isInCircle = sum.ToDoubleValue() > 0;

            return(isInCircle);
        }
        /// <summary>
        /// Tests if a point is inside the circle defined by
        /// the triangle with vertices a, b, c (oriented counter-clockwise).
        /// </summary>
        /// <remarks>
        /// The computation uses <see cref="DD"/> arithmetic for robustness.
        /// </remarks>
        /// <param name="a">A vertex of the triangle</param>
        /// <param name="b">A vertex of the triangle</param>
        /// <param name="c">A vertex of the triangle</param>
        /// <param name="p">The point to test</param>
        /// <returns>true if this point is inside the circle defined by the points a, b, c</returns>
        public static bool IsInCircleDDSlow(
            Coordinate a, Coordinate b, Coordinate c,
            Coordinate p)
        {
            DD px = DD.ValueOf(p.X);
            DD py = DD.ValueOf(p.Y);
            DD ax = DD.ValueOf(a.X);
            DD ay = DD.ValueOf(a.Y);
            DD bx = DD.ValueOf(b.X);
            DD by = DD.ValueOf(b.Y);
            DD cx = DD.ValueOf(c.X);
            DD cy = DD.ValueOf(c.Y);

            DD aTerm = (ax.Multiply(ax).Add(ay.Multiply(ay)))
                       .Multiply(TriAreaDDSlow(bx, by, cx, cy, px, py));
            DD bTerm = (bx.Multiply(bx).Add(by.Multiply(by)))
                       .Multiply(TriAreaDDSlow(ax, ay, cx, cy, px, py));
            DD cTerm = (cx.Multiply(cx).Add(cy.Multiply(cy)))
                       .Multiply(TriAreaDDSlow(ax, ay, bx, by, px, py));
            DD pTerm = (px.Multiply(px).Add(py.Multiply(py)))
                       .Multiply(TriAreaDDSlow(ax, ay, bx, by, cx, cy));

            DD   sum        = aTerm.Subtract(bTerm).Add(cTerm).Subtract(pTerm);
            bool isInCircle = sum.ToDoubleValue() > 0;

            return(isInCircle);
        }
        private void CheckSqrt(DD x, double errBound)
        {
            DD sqrt = x.Sqrt();
            DD x2   = sqrt.Multiply(sqrt);

            CheckErrorBound("Sqrt", x, x2, errBound);
        }
        /// <summary>
        /// Computes the sign of the determinant of the 2x2 matrix
        /// with the given entries.
        /// </summary>
        /// <param name="x1"></param>
        /// <param name="y1"></param>
        /// <param name="x2"></param>
        /// <param name="y2"></param>
        /// <returns>
        /// <list type="Bullet">
        /// <item>-1 if the determinant is negative,</item>
        /// <item>1 if the determinant is positive,</item>
        /// <item>0 if the determinant is 0.</item>
        /// </list>
        /// </returns>
        public static int SignOfDet2x2(DD x1, DD y1, DD x2, DD y2)
        {
            DD det = x1.Multiply(y2).Subtract(y1.Multiply(x2));
            if (det.IsZero)
                return 0;
            if (det.IsNegative)
                return -1;
            return 1;

        }
        /// <summary>
        /// Computes the sign of the determinant of the 2x2 matrix
        /// with the given entries.
        /// </summary>
        /// <param name="x1"></param>
        /// <param name="y1"></param>
        /// <param name="x2"></param>
        /// <param name="y2"></param>
        /// <returns>
        /// <list type="Bullet">
        /// <item>-1 if the determinant is negative,</item>
        /// <item>1 if the determinant is positive,</item>
        /// <item>0 if the determinant is 0.</item>
        /// </list>
        /// </returns>
        public static int SignOfDet2x2(DD x1, DD y1, DD x2, DD y2)
        {
            DD det = x1.Multiply(y2).Subtract(y1.Multiply(x2));

            if (det.IsZero)
            {
                return(0);
            }
            if (det.IsNegative)
            {
                return(-1);
            }
            return(1);
        }
        private static DD SlowPow(DD x, int exp)
        {
            if (exp == 0)
            {
                return(DD.ValueOf(1.0));
            }

            var n = Math.Abs(exp);
            // MD - could use binary exponentiation for better precision & speed
            var pow = new DD(x);

            for (int i = 1; i < n; i++)
            {
                pow = pow.Multiply(x);
            }
            if (exp < 0)
            {
                return(pow.Reciprocal());
            }
            return(pow);
        }
        public double RunDoubleDouble(int nIter)
        {
            var sw = new Stopwatch();

            sw.Start();
            for (int i = 0; i < nIter; i++)
            {
                var a      = new DD(9.0);
                var factor = new DD(10.0);
                var aMul   = factor.Multiply(a);
                var aDiv   = a.Divide(factor);

                var det = a.Multiply(a)
                          .Subtract(aMul.Multiply(aDiv));
                // Console.WriteLine(aDiv);
                // Console.WriteLine(det);
            }
            sw.Stop();
            Console.WriteLine("DD:              nIter = " + nIter
                              + "   time = " + sw.ElapsedMilliseconds);
            return(sw.ElapsedMilliseconds / (double)nIter);
        }
        public static bool IsInCircleDD(
            Coordinate a, Coordinate b, Coordinate c,
            Coordinate p)
        {
            DD px = new DD(p.X);
            DD py = new DD(p.Y);
            DD ax = new DD(a.X);
            DD ay = new DD(a.Y);
            DD bx = new DD(b.X);
            DD by = new DD(b.Y);
            DD cx = new DD(c.X);
            DD cy = new DD(c.Y);

            DD aTerm = (ax.Multiply(ax).Add(ay.Multiply(ay)))
                .Multiply(TriAreaDD(bx, by, cx, cy, px, py));
            DD bTerm = (bx.Multiply(bx).Add(by.Multiply(by)))
                .Multiply(TriAreaDD(ax, ay, cx, cy, px, py));
            DD cTerm = (cx.Multiply(cx).Add(cy.Multiply(cy)))
                .Multiply(TriAreaDD(ax, ay, bx, by, px, py));
            DD pTerm = (px.Multiply(px).Add(py.Multiply(py)))
                .Multiply(TriAreaDD(ax, ay, bx, by, cx, cy));

            DD sum = aTerm.Subtract(bTerm).Add(cTerm).Subtract(pTerm);
            var isInCircle = sum.ToDoubleValue() > 0;

            return isInCircle;
        }
 private static void CheckAddMult2(DD dd)
 {
     DD sum = dd.Add(dd);
     DD prod = dd.Multiply(new DD(2.0));
     CheckErrorBound("AddMult2", sum, prod, 0.0);
 }
 private static void CheckMultiplyDivide(DD a, DD b, double errBound)
 {
     DD a2 = a.Multiply(b).Divide(b);
     CheckErrorBound("MultiplyDivide", a, a2, errBound);
 }
        private static void CheckMultiplyDivide(DD a, DD b, double errBound)
        {
            DD a2 = a.Multiply(b).Divide(b);

            CheckErrorBound("MultiplyDivide", a, a2, errBound);
        }
        /**
         * Computes (a+b)^2 in two different ways and compares the result.
         * For correct results, a and b should be integers.
         * 
         * @param a
         * @param b
         */

        private static void CheckBinomialSquare(double a, double b)
        {
            // binomial square
            var add = new DD(a);
            var bdd = new DD(b);
            var aPlusb = add.Add(bdd);
            var abSq = aPlusb.Multiply(aPlusb);
            //  	System.out.println("(a+b)^2 = " + abSq);

            // expansion
            var a2DD = add.Multiply(add);
            var b2DD = bdd.Multiply(bdd);
            var ab = add.Multiply(bdd);
            var sum = b2DD.Add(ab).Add(ab);

            //  	System.out.println("2ab+b^2 = " + sum);

            var diff = abSq.Subtract(a2DD);
            //  	System.out.println("(a+b)^2 - a^2 = " + diff);

            var delta = diff.Subtract(sum);

            Console.WriteLine("\nA = " + a + ", B = " + b);
            Console.WriteLine("[DD]     2ab+b^2 = " + sum
                              + "   (a+b)^2 - a^2 = " + diff
                              + "   delta = " + delta);
            PrintBinomialSquareDouble(a, b);

            var isSame = diff.Equals(sum);
            Assert.IsTrue(isSame);
            var isDeltaZero = delta.IsZero;
            Assert.IsTrue(isDeltaZero);
        }
        private static void CheckBinomial2(double a, double b)
        {
            // binomial product
            var add = new DD(a);
            var bdd = new DD(b);
            var aPlusb = add.Add(bdd);
            var aSubb = add.Subtract(bdd);
            var abProd = aPlusb.Multiply(aSubb);
            //  	System.out.println("(a+b)^2 = " + abSq);

            // expansion
            var a2DD = add.Multiply(add);
            var b2DD = bdd.Multiply(bdd);

            //  	System.out.println("2ab+b^2 = " + sum);

            // this should equal b^2
            var diff = abProd.Subtract(a2DD).Negate();
            //  	System.out.println("(a+b)^2 - a^2 = " + diff);

            var delta = diff.Subtract(b2DD);

            Console.WriteLine("\nA = " + a + ", B = " + b);
            Console.WriteLine("[DD] (a+b)(a-b) = " + abProd
                              + "   -((a^2 - b^2) - a^2) = " + diff
                              + "   delta = " + delta);
            //  	printBinomialSquareDouble(a,b);

            var isSame = diff.Equals(b2DD);
            Assert.IsTrue(isSame);
            var isDeltaZero = delta.IsZero;
            Assert.IsTrue(isDeltaZero);
        }
        public double RunDoubleDouble(int nIter)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            for (int i = 0; i < nIter; i++)
            {

                DD a = new DD(9.0);
                DD factor = new DD(10.0);
                DD aMul = factor.Multiply(a);
                DD aDiv = a.Divide(factor);

                DD det = a.Multiply(a)
                    .Subtract(aMul.Multiply(aDiv));
                //      Console.WriteLine(aDiv);
                //      Console.WriteLine(det);
            }
            sw.Stop();
            Console.WriteLine("DD:              nIter = " + nIter
                              + "   time = " + sw.ElapsedMilliseconds);
            return sw.ElapsedMilliseconds/(double) nIter;
        }
        private static DD SlowPow(DD x, int exp)
        {
            if (exp == 0)
                return DD.ValueOf(1.0);

            var n = Math.Abs(exp);
            // MD - could use binary exponentiation for better precision & speed
            var pow = new DD(x);
            for (int i = 1; i < n; i++)
            {
                pow = pow.Multiply(x);
            }
            if (exp < 0)
            {
                return pow.Reciprocal();
            }
            return pow;
        }