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); }
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); }
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 }
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); }
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); }
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); }
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); }