コード例 #1
0
        public void ShowDoubleRoundingPriest()
        {
            double a          = Math.Pow(2.0, 52.0) + 1.0;
            double b          = 0.5 - Math.Pow(2.0, -54.0);
            double expected53 = a;
            double expected64 = a + 1.0; // Math.Pow(2.0, 52.0) + 2.0;

            Debug.Print(DoubleConverter.ToFloatingPointBinaryString(a));
            Debug.Print(DoubleConverter.ToFloatingPointBinaryString(b));
            Debug.Print(DoubleConverter.ToFloatingPointBinaryString(expected53));
            Debug.Print(DoubleConverter.ToFloatingPointBinaryString(expected64));

            // Set Fpu to 53-bit precision (the default)
            FpuControl.SetState((uint)FpuControl.PrecisionControl.Double53Bits, FpuControl.Mask.PrecisionControl);

            double result53 = a + b;

            Debug.Print(DoubleConverter.ToFloatingPointBinaryString(result53));
            Assert.AreEqual(expected53, result53);

            // Set Fpu to 64-bit precision (extended precision)
            FpuControl.SetState((uint)FpuControl.PrecisionControl.Extended64Bits, FpuControl.Mask.PrecisionControl);
            double result64 = (double)(a + b);

            Debug.Print(DoubleConverter.ToFloatingPointBinaryString(result64));
            Assert.AreEqual(expected64, result64);
        }
コード例 #2
0
        public void ShowDoubleRoundingPriestExplicit()
        {
            double a          = DoubleConverter.FromFloatingPointBinaryString("1" + '0'.Repeat(51) + "1"); // 100....00001 (53-bits wide)
            double b          = DoubleConverter.FromFloatingPointBinaryString("0.0" + '1'.Repeat(53));     //            0.0111...111 (53 1's)
            double expected53 = a;
            double expected64 = a + 1.0;                                                                   // The point is that this is different to expceted53.

            Debug.Print(DoubleConverter.ToFloatingPointBinaryString(a));
            Debug.Print(DoubleConverter.ToFloatingPointBinaryString(b));
            Debug.Print(DoubleConverter.ToFloatingPointBinaryString(expected53));
            Debug.Print(DoubleConverter.ToFloatingPointBinaryString(expected64));

            // Set Fpu to 53-bit precision (the default)
            FpuControl.SetState((uint)FpuControl.PrecisionControl.Double53Bits, FpuControl.Mask.PrecisionControl);

            double result53 = a + b;

            Debug.Print(DoubleConverter.ToFloatingPointBinaryString(result53));
            Assert.AreEqual(expected53, result53);

            // Explicit rounding makes no difference here (since we're in Double53bits precision FPU mode)
            result53 = (double)(a + b);
            Debug.Print(DoubleConverter.ToFloatingPointBinaryString(result53));
            Assert.AreEqual(expected53, result53);

            // Set Fpu to 64-bit precision (extended precision)
            FpuControl.SetState((uint)FpuControl.PrecisionControl.Extended64Bits, FpuControl.Mask.PrecisionControl);
            double result64 = (double)(a + b);

            Debug.Print(DoubleConverter.ToFloatingPointBinaryString(result64));
            Assert.AreEqual(expected64, result64);
        }
コード例 #3
0
        public void ShowDoubleRounding()
        {
            double a          = DoubleConverter.FromFloatingPointBinaryString('1'.Repeat(52) + "0"); // 111....11110
            double b          = DoubleConverter.FromFloatingPointBinaryString("0.100000000001");     // 000....00000.100000000001
            double expected53 = DoubleConverter.FromFloatingPointBinaryString('1'.Repeat(52) + "1"); // 111....11111
            double expected64 = a;

            // Set Fpu to 53-bit precision (the default)
            FpuControl.SetState((uint)FpuControl.PrecisionControl.Double53Bits, FpuControl.Mask.PrecisionControl);

            double result53 = a + b;

            Assert.AreEqual(expected53, result53);

            // Set Fpu to 64-bit precision (extended precision)
            FpuControl.SetState((uint)FpuControl.PrecisionControl.Extended64Bits, FpuControl.Mask.PrecisionControl);
            double result64 = (double)(a + b);

            Assert.AreEqual(expected64, result64);

            double result64_0 = (a + b) - a;

            Assert.AreNotEqual(0.0, result64_0);
            Assert.AreNotEqual(b, result64_0);
            Assert.AreEqual(0.5, result64_0);       // 000....00000.1
        }
コード例 #4
0
        public void TestMethod1()
        {
            double before = TestCalc();

            Assert.AreEqual(0.0, before);

            var  oldState = new FpuControl.State(FpuControl.GetState());
            var  oldPc    = oldState.PrecisionControl;
            uint err      = FpuControl.SetState((uint)FpuControl.PrecisionControl.Extended64Bits, FpuControl.Mask.PrecisionControl);
            var  newState = new FpuControl.State(FpuControl.GetState());
            var  newPc    = newState.PrecisionControl;

            double after = TestCalc();

            Assert.AreEqual(0.5, after);

            double afterSafe = TestCalcSafe();

            Assert.AreEqual(0.0, afterSafe);

            FpuControl.SetState((uint)oldState.PrecisionControl, FpuControl.Mask.PrecisionControl);

            double reset = TestCalc();

            Assert.AreEqual(0.0, reset);
        }
コード例 #5
0
        public void TestPrecision53()
        {
            double a          = DoubleConverter.FromFloatingPointBinaryString('1'.Repeat(52) + "0"); // 111....11110
            double b          = DoubleConverter.FromFloatingPointBinaryString("0.1");                // 000....00000.1
            double expected53 = a;

            FpuControl.SetState((uint)FpuControl.PrecisionControl.Double53Bits, FpuControl.Mask.PrecisionControl);
            double result53 = (double)(a + b);

            Assert.AreEqual(expected53, result53);

            double result53_0 = (a + b) - a;

            Assert.AreEqual(0.0, result53_0);

            double result53_X = ((double)(a + b)) - a;

            Assert.AreEqual(0.0, result53_X);
        }
コード例 #6
0
        public void TestPrecision64()
        {
            double a          = DoubleConverter.FromFloatingPointBinaryString('1'.Repeat(52) + "0"); // 111....11110
            double b          = DoubleConverter.FromFloatingPointBinaryString("0.1");                // 000....00000.1
            double expected64 = a;

            FpuControl.SetState((uint)FpuControl.PrecisionControl.Extended64Bits, FpuControl.Mask.PrecisionControl);
            double result64 = (double)(a + b);

            Assert.AreEqual(expected64, result64);

            double result64_b = (a + b) - a;

            Assert.AreEqual(b, result64_b);

            double result64_0 = ((double)(a + b)) - a;

            Assert.AreNotEqual(b, result64_0);
            Assert.AreEqual(0.0, result64_0);
        }
コード例 #7
0
        public void InPlane_ProblemCase()
        {
            /*
             *      CAUTION: (From a comment to http://digestingduck.blogspot.com/2010/12/computational-geometry-sucks.html)
             *
             *          "Shewchuk predicates are not completely stable, at least I wasn't able to make it stable on new HW:
             *
             *          double pointA[3] = {0.12539999f, 0.0016452915f, -0.019413333f};
             *          double pointB[3] = {0.12539999f, 0.0017933375f, -0.019214222f};
             *          double pointC[3] = {0.12539999f, 0.0017933375f, -0.017919999f};
             *          double pointD[3] = {0.11700000f, 0.0017933375f, -0.018710587f};
             *          double pointE[3] = {0.12539999f, 0.0017933375f, -0.019413333f};
             *
             *          std::cout << "On plane: A, C, B, E: " << onPlane(pointA, pointC, pointB, pointE) << std::endl;
             *          std::cout << "On plane: B, C, D, E: " << onPlane(pointB, pointC, pointD, pointE) << std::endl;
             *          std::cout << "On plane: B, C, D, A: " << onPlane(pointB, pointC, pointD, pointA) << std::endl;
             *
             *          This three tests ultimately fail telling you that first 2 tests are true and the last one is false,
             *      which is logically impossible and therefore predicates are not working correctly on modern HW at least."
             *
             *
             *  HOWEVER: This is not really a problem of instability with the Shewchuk predicates. The points A, B, C and E
             *  above are collinear. This makes the first onPlane test meaningless.
             *  (It did keep me busy for a while, though.)
             *
             */

            var oldState = new FpuControl.State(FpuControl.GetState());
            var oldPc    = oldState.PrecisionControl;

            double[] pA = new double[] { 0.12539999f, 0.0017933375f, -0.019214222f };
            double[] pB = new double[] { 0.12539999f, 0.0017933375f, -0.017919999f };
            double[] pC = new double[] { 0.12539999f, 0.0016452915f, -0.019413333f };
            double[] pD = new double[] { 0.11700000f, 0.0017933375f, -0.018710587f };
            double[] pE = new double[] { 0.12539999f, 0.0017933375f, -0.019413333f };

            double d1 = Orient3DExact_ScaledChecked(pA, pB, pC, pD, 1.0);
            double d2 = Orient3DExact_ScaledChecked(pA, pB, pC, pE, 1.0);
            double d3 = Orient3DExact_ScaledChecked(pB, pC, pE, pD, 1.0);

            var l1 = GP.Orient2D(pA, pB, pC);
            var l2 = GP.Orient2D(pB, pC, pD);
            var l3 = GP.Orient2D(pB, pC, pE);
            var l4 = GP.Orient2D(pA, pC, pE);

            var le1 = GP.Orient2DExact(pA, pB, pC);
            var le2 = GP.Orient2DExact(pB, pC, pD);
            var le3 = GP.Orient2DExact(pB, pC, pE);
            var le4 = GP.Orient2DExact(pA, pC, pE);

            double scale = System.Math.Pow(2.0, 32);

            double[] psA = pA.Select(d => d * scale).ToArray();
            double[] psB = pB.Select(d => d * scale).ToArray();
            double[] psC = pC.Select(d => d * scale).ToArray();
            double[] psD = pD.Select(d => d * scale).ToArray();
            double[] psE = pE.Select(d => d * scale).ToArray();

            double s1 = Orient3DExact_ScaledChecked(psA, psB, psC, psD, scale);
            double s2 = Orient3DExact_ScaledChecked(psA, psB, psC, psE, scale);
            double s3 = Orient3DExact_ScaledChecked(psB, psC, psE, psD, scale);

            BigInteger[] plA = psA.Select(d => (BigInteger)d).ToArray();
            BigInteger[] plB = psB.Select(d => (BigInteger)d).ToArray();
            BigInteger[] plC = psC.Select(d => (BigInteger)d).ToArray();
            BigInteger[] plD = psD.Select(d => (BigInteger)d).ToArray();
            BigInteger[] plE = psE.Select(d => (BigInteger)d).ToArray();

            var bl1 = Orient2DBigInteger(plA, plB, plC);
            var bl2 = Orient2DBigInteger(plB, plC, plE);

            BigInteger b1 = Orient3DInt64(plA, plB, plC, plD);
            BigInteger b2 = Orient3DInt64(plA, plB, plC, plE);
            BigInteger b3 = Orient3DInt64(plB, plC, plE, plD);

            Assert.AreEqual(s1, (double)b1);

            //double d1m = Orient3DExact_Checked2(pA, pC, pB, pD);

            //Assert.AreEqual(d1, -d1m);
            //double[] pE = new double[]{0.12539999f, 0.0017933375f, -0.019413333f};

            //// Not zero !? - Already res4 and res5 differ, and res4 and resF4 differ.
            //double res4 = Orient3DExact_Checked(pA, pB, pC, pD, true);


            //double res5b = Orient3DExact_Checked2(pB, pC, pD, pA);

            //double res5c = Orient3DExact_Checked2(pA, pC, pB, pD);


            //double resF4 = GP.Orient3DFast(pA, pB, pC, pD);

            //double res6 = Orient3DExact_Checked2(pA, pC, pD, pB);
            //double res7 = Orient3DExact_Checked2(pA, pB, pD, pC);

            //double res1 = Orient3DExact_Checked(pA, pC, pB, pE);
            //double res12 = Orient3DExact_Checked(pC, pB, pE, pA);
            //double res13 = Orient3DExact_Checked(pA, pB, pC, pE);
            //double res14 = Orient3DExact_Checked(pA, pE, pC, pB);
            //double res2 = Orient3DExact_Checked(pB, pC, pD, pE);
            //double res3 = Orient3DExact_Checked2(pB, pC, pD, pA);
            //double resF1 = GP.Orient3DFast(pA, pC, pB, pE);
            //double resF2 = GP.Orient3DFast(pB, pC, pD, pE);
            //double resF3 = GP.Orient3DFast(pB, pC, pD, pA);


            //double scale = 2.0;
            //double[] psA = pA.Select(d => d * scale).ToArray();
            //double[] psB = pA.Select(d => d * scale).ToArray();
            //double[] psC = pA.Select(d => d * scale).ToArray();
            //double[] psD = pA.Select(d => d * scale).ToArray();
            //double[] psE = pA.Select(d => d * scale).ToArray();



            //double rss4 = Orient3DExact_Checked2(psA, psB, psC, psD);
            //double rss5 = Orient3DExact_Checked2(psB, psC, psA, psD);
            //double rssF4 = GP.Orient3DFast(psA, psB, psC, psD);

            //double rss6 = Orient3DExact_Checked2(psA, psC, psD, psB);
            //double rss7 = Orient3DExact_Checked2(psA, psB, psD, psC);

            //double rss1 = Orient3DExact_Checked(psA, psC, psB, psE);
            //double rss12 = Orient3DExact_Checked(psC, psB, psE, psA);
            //double rss13 = Orient3DExact_Checked(psA, psB, psC, psE);
            //double rss14 = Orient3DExact_Checked(psA, psE, psC, psB);
            //double rss2 = Orient3DExact_Checked(psB, psC, psD, psE);
            //double rss3 = Orient3DExact_Checked2(psB, psC, psD, psA);
            //double rssF1 = GP.Orient3DFast(psA, psC, psB, psE);
            //double rssF2 = GP.Orient3DFast(psB, psC, psD, psE);
            //double rssF3 = GP.Orient3DFast(psB, psC, psD, psA);


            //Assert.AreEqual(res1, res2);
            //Assert.AreEqual(res1, res4);
            //Assert.AreEqual(res1, res5);
            //Assert.AreEqual(res1, res6);
            //Assert.AreEqual(res1, res7);
            //Assert.AreEqual(res1, res3);
            //Assert.AreEqual(res1, res12);
            //Assert.AreEqual(res1, res13);
        }