Пример #1
0
        //[Fact]
        public void Atan2Benchmark()
        {
            var deltas = new List <decimal>();

            var swf = new Stopwatch();
            var swd = new Stopwatch();

            foreach (var y in m_testCases)
            {
                foreach (var x in m_testCases)
                {
                    for (int k = 0; k < 1000; ++k)
                    {
                        var yf = (Fix64)y;
                        var xf = (Fix64)x;
                        swf.Start();
                        var actualF = MathFix.Atan2(yf, xf);
                        swf.Stop();
                        swd.Start();
                        var expected = Math.Atan2((double)yf, (double)xf);
                        swd.Stop();
                        deltas.Add(Math.Abs((decimal)actualF - (decimal)expected));
                    }
                }
            }
            Console.WriteLine("Max error: {0} ({1} times precision)", deltas.Max(), deltas.Max() / Fix64.Precision);
            Console.WriteLine("Average precision: {0} ({1} times precision)", deltas.Average(), deltas.Average() / Fix64.Precision);
            Console.WriteLine("Fix64.Atan2 time = {0}ms, Math.Atan2 time = {1}ms", swf.ElapsedMilliseconds, swd.ElapsedMilliseconds);
        }
Пример #2
0
        public void Atan()
        {
            var maxDelta = 0.00000001m;
            var deltas   = new List <decimal>();

            Assert.Equal(Fix64.Zero, MathFix.Atan(Fix64.Zero));

            // Precision
            for (var x = -1.0; x < 1.0; x += 0.0001)
            {
                var xf       = (Fix64)x;
                var actual   = (decimal)MathFix.Atan(xf);
                var expected = (decimal)Math.Atan((double)xf);
                var delta    = Math.Abs(actual - expected);
                deltas.Add(delta);
                Assert.True(delta <= maxDelta, string.Format("Precision: Atan({0}): expected {1} but got {2}", xf, expected, actual));
            }

            // Scalability and edge cases
            foreach (var x in m_testCases)
            {
                var xf       = (Fix64)x;
                var actual   = (decimal)MathFix.Atan(xf);
                var expected = (decimal)Math.Atan((double)xf);
                var delta    = Math.Abs(actual - expected);
                deltas.Add(delta);
                Assert.True(delta <= maxDelta, string.Format("Scalability: Atan({0}): expected {1} but got {2}", xf, expected, actual));
            }
            Console.WriteLine("Max error: {0} ({1} times precision)", deltas.Max(), deltas.Max() / Fix64.Precision);
            Console.WriteLine("Average precision: {0} ({1} times precision)", deltas.Average(), deltas.Average() / Fix64.Precision);
        }
Пример #3
0
        public void Pow()
        {
            for (int i = 0; i < m_testCases.Length; ++i)
            {
                var b = Fix64.FromRaw(m_testCases[i]);

                for (int j = 0; j < m_testCases.Length; ++j)
                {
                    var e = Fix64.FromRaw(m_testCases[j]);

                    if (b == Fix64.Zero && e < Fix64.Zero)
                    {
                        Assert.Throws <DivideByZeroException>(() => MathFix.Pow(b, e));
                    }
                    else if (b < Fix64.Zero && e != Fix64.Zero)
                    {
                        Assert.Throws <ArgumentOutOfRangeException>(() => MathFix.Pow(b, e));
                    }
                    else
                    {
                        var expected = e == Fix64.Zero ? 1 : b == Fix64.Zero ? 0 : Math.Min(Math.Pow((double)b, (double)e), (double)Fix64.MaxValue);

                        // Absolute precision deteriorates with large result values, take this into account
                        // Similarly, large exponents reduce precision, even if result is small.
                        double maxDelta = Math.Abs((double)e) > 100000000 ? 0.5 : expected > 100000000 ? 10 : expected > 1000 ? 0.5 : 0.00001;

                        var actual = (double)MathFix.Pow(b, e);
                        var delta  = Math.Abs(expected - actual);

                        Assert.True(delta <= maxDelta, string.Format("Pow({0}, {1}) = expected {2} but got {3}", b, e, expected, actual));
                    }
                }
            }
        }
Пример #4
0
        public void Tan()
        {
            Assert.True(MathFix.Tan(Fix64.Zero) == Fix64.Zero);
            Assert.True(MathFix.Tan(MathFix.PI) == Fix64.Zero);
            Assert.True(MathFix.Tan(-MathFix.PI) == Fix64.Zero);

            Assert.True(MathFix.Tan(MathFix.PIOver2 - (Fix64)0.001) > Fix64.Zero);
            Assert.True(MathFix.Tan(MathFix.PIOver2 + (Fix64)0.001) < Fix64.Zero);
            Assert.True(MathFix.Tan(-MathFix.PIOver2 - (Fix64)0.001) > Fix64.Zero);
            Assert.True(MathFix.Tan(-MathFix.PIOver2 + (Fix64)0.001) < Fix64.Zero);

            for (double angle = 0; /*-2 * Math.PI;*/ angle <= 2 * Math.PI; angle += 0.0001)
            {
                var f        = (Fix64)angle;
                var actualF  = MathFix.Tan(f);
                var expected = (decimal)Math.Tan(angle);
                Assert.Equal(actualF > Fix64.Zero, expected > 0);
                //TODO figure out a real way to test this function
            }

            //foreach (var val in m_testCases) {
            //    var f = (Fix64)val;
            //    var actualF = Fix64.Tan(f);
            //    var expected = (decimal)Math.Tan((double)f);
            //    var delta = Math.Abs(expected - (decimal)actualF);
            //    Assert.True(delta <= 0.01, string.Format("Tan({0}): expected {1} but got {2}", f, expected, actualF));
            //}
        }
Пример #5
0
        public void Cos()
        {
            Assert.True(MathFix.Cos(Fix64.Zero) == Fix64.One);

            Assert.True(MathFix.Cos(MathFix.PIOver2) == Fix64.Zero);
            Assert.True(MathFix.Cos(MathFix.PI) == -Fix64.One);
            Assert.True(MathFix.Cos(MathFix.PI + MathFix.PIOver2) == Fix64.Zero);
            Assert.True(MathFix.Cos(MathFix.PITimes2) == Fix64.One);

            Assert.True(MathFix.Cos(-MathFix.PIOver2) == -Fix64.Zero);
            Assert.True(MathFix.Cos(-MathFix.PI) == -Fix64.One);
            Assert.True(MathFix.Cos(-MathFix.PI - MathFix.PIOver2) == Fix64.Zero);
            Assert.True(MathFix.Cos(-MathFix.PITimes2) == Fix64.One);


            for (double angle = -2 * Math.PI; angle <= 2 * Math.PI; angle += 0.0001)
            {
                var f        = (Fix64)angle;
                var actualF  = MathFix.Cos(f);
                var expected = (decimal)Math.Cos(angle);
                var delta    = Math.Abs(expected - (decimal)actualF);
                Assert.True(delta <= 3 * Fix64.Precision, string.Format("Cos({0}): expected {1} but got {2}", angle, expected, actualF));
            }

            foreach (var val in m_testCases)
            {
                var f        = Fix64.FromRaw(val);
                var actualF  = MathFix.Cos(f);
                var expected = (decimal)Math.Cos((double)f);
                var delta    = Math.Abs(expected - (decimal)actualF);
                Assert.True(delta <= 0.0000001M, string.Format("Cos({0}): expected {1} but got {2}", f, expected, actualF));
            }
        }
Пример #6
0
        public void Floor()
        {
            var sources   = new[] { -5.1m, -1, 0, 1, 5.1m };
            var expecteds = new[] { -6m, -1, 0, 1, 5m };

            for (int i = 0; i < sources.Length; ++i)
            {
                var actual   = (decimal)MathFix.Floor((Fix64)sources[i]);
                var expected = expecteds[i];
                Assert.Equal(expected, actual);
            }
        }
Пример #7
0
        public void Sign()
        {
            var sources   = new[] { Fix64.MinValue, (Fix64)(-1), Fix64.Zero, Fix64.One, Fix64.MaxValue };
            var expecteds = new[] { -1, -1, 0, 1, 1 };

            for (int i = 0; i < sources.Length; ++i)
            {
                var actual   = MathFix.Sign(sources[i]);
                var expected = expecteds[i];
                Assert.Equal(expected, actual);
            }
        }
Пример #8
0
        public void Round()
        {
            var sources   = new[] { -5.5m, -5.1m, -4.5m, -4.4m, -1, 0, 1, 4.5m, 4.6m, 5.4m, 5.5m };
            var expecteds = new[] { -6m, -5m, -4m, -4m, -1, 0, 1, 4m, 5m, 5m, 6m };

            for (int i = 0; i < sources.Length; ++i)
            {
                var actual   = (decimal)MathFix.Round((Fix64)sources[i]);
                var expected = expecteds[i];
                Assert.Equal(expected, actual);
            }
            Assert.Equal(Fix64.MaxValue, MathFix.Round(Fix64.MaxValue));
        }
Пример #9
0
        public void FastAbs()
        {
            Assert.Equal(Fix64.MinValue, MathFix.FastAbs(Fix64.MinValue));
            var sources   = new[] { -1, 0, 1, int.MaxValue };
            var expecteds = new[] { 1, 0, 1, int.MaxValue };

            for (int i = 0; i < sources.Length; ++i)
            {
                var actual   = MathFix.FastAbs((Fix64)sources[i]);
                var expected = (Fix64)expecteds[i];
                Assert.Equal(expected, actual);
            }
        }
Пример #10
0
        public void Ceiling()
        {
            var sources   = new[] { -5.1m, -1, 0, 1, 5.1m };
            var expecteds = new[] { -5m, -1, 0, 1, 6m };

            for (int i = 0; i < sources.Length; ++i)
            {
                var actual   = (decimal)MathFix.Ceiling((Fix64)sources[i]);
                var expected = expecteds[i];
                Assert.Equal(expected, actual);
            }

            Assert.Equal(Fix64.MaxValue, MathFix.Ceiling(Fix64.MaxValue));
        }
Пример #11
0
        public void Pow2()
        {
            double maxDelta = 0.0000001;

            for (int i = 0; i < m_testCases.Length; ++i)
            {
                var e = Fix64.FromRaw(m_testCases[i]);

                var expected = Math.Min(Math.Pow(2, (double)e), (double)Fix64.MaxValue);
                var actual   = (double)MathFix.Pow2(e);
                var delta    = Math.Abs(expected - actual);

                Assert.True(delta <= maxDelta, string.Format("Pow2({0}) = expected {1} but got {2}", e, expected, actual));
            }
        }
Пример #12
0
 public void Sqrt()
 {
     for (int i = 0; i < m_testCases.Length; ++i)
     {
         var f = Fix64.FromRaw(m_testCases[i]);
         if (MathFix.Sign(f) < 0)
         {
             Assert.Throws <ArgumentOutOfRangeException>(() => MathFix.Sqrt(f));
         }
         else
         {
             var expected = Math.Sqrt((double)f);
             var actual   = (double)MathFix.Sqrt(f);
             var delta    = (decimal)Math.Abs(expected - actual);
             Assert.True(delta <= Fix64.Precision);
         }
     }
 }
Пример #13
0
        public void Atan2()
        {
            var deltas = new List <decimal>();

            // Identities
            Assert.Equal(MathFix.Atan2(Fix64.Zero, -Fix64.One), MathFix.PI);
            Assert.Equal(MathFix.Atan2(Fix64.Zero, Fix64.Zero), Fix64.Zero);
            Assert.Equal(MathFix.Atan2(Fix64.Zero, Fix64.One), Fix64.Zero);
            Assert.Equal(MathFix.Atan2(Fix64.One, Fix64.Zero), MathFix.PIOver2);
            Assert.Equal(MathFix.Atan2(-Fix64.One, Fix64.Zero), -MathFix.PIOver2);

            // Precision
            for (var y = -1.0; y < 1.0; y += 0.01)
            {
                for (var x = -1.0; x < 1.0; x += 0.01)
                {
                    var yf       = (Fix64)y;
                    var xf       = (Fix64)x;
                    var actual   = MathFix.Atan2(yf, xf);
                    var expected = (decimal)Math.Atan2((double)yf, (double)xf);
                    var delta    = Math.Abs((decimal)actual - expected);
                    deltas.Add(delta);
                    Assert.True(delta <= 0.005M, string.Format("Precision: Atan2({0}, {1}): expected {2} but got {3}", yf, xf, expected, actual));
                }
            }

            // Scalability and edge cases
            foreach (var y in m_testCases)
            {
                foreach (var x in m_testCases)
                {
                    var yf       = (Fix64)y;
                    var xf       = (Fix64)x;
                    var actual   = (decimal)MathFix.Atan2(yf, xf);
                    var expected = (decimal)Math.Atan2((double)yf, (double)xf);
                    var delta    = Math.Abs(actual - expected);
                    deltas.Add(delta);
                    Assert.True(delta <= 0.005M, string.Format("Scalability: Atan2({0}, {1}): expected {2} but got {3}", yf, xf, expected, actual));
                }
            }
            Console.WriteLine("Max error: {0} ({1} times precision)", deltas.Max(), deltas.Max() / Fix64.Precision);
            Console.WriteLine("Average precision: {0} ({1} times precision)", deltas.Average(), deltas.Average() / Fix64.Precision);
        }
Пример #14
0
        public void FastCos()
        {
            for (double angle = -2 * Math.PI; angle <= 2 * Math.PI; angle += 0.0001)
            {
                var f        = (Fix64)angle;
                var actualF  = MathFix.FastCos(f);
                var expected = (decimal)Math.Cos(angle);
                var delta    = Math.Abs(expected - (decimal)actualF);
                Assert.True(delta <= 50000 * Fix64.Precision, string.Format("Cos({0}): expected {1} but got {2}", angle, expected, actualF));
            }

            foreach (var val in m_testCases)
            {
                var f        = Fix64.FromRaw(val);
                var actualF  = MathFix.FastCos(f);
                var expected = (decimal)Math.Cos((double)f);
                var delta    = Math.Abs(expected - (decimal)actualF);
                Assert.True(delta <= 0.01M, string.Format("Cos({0}): expected {1} but got {2}", f, expected, actualF));
            }
        }
Пример #15
0
        public void Acos()
        {
            var maxDelta = 0.00000001m;
            var deltas   = new List <decimal>();

            Assert.Equal(Fix64.Zero, MathFix.Acos(Fix64.One));
            Assert.Equal(MathFix.PIOver2, MathFix.Acos(Fix64.Zero));
            Assert.Equal(MathFix.PI, MathFix.Acos(-Fix64.One));

            // Precision
            for (var x = -1.0; x < 1.0; x += 0.001)
            {
                var xf       = (Fix64)x;
                var actual   = (decimal)MathFix.Acos(xf);
                var expected = (decimal)Math.Acos((double)xf);
                var delta    = Math.Abs(actual - expected);
                deltas.Add(delta);
                Assert.True(delta <= maxDelta, string.Format("Precision: Acos({0}): expected {1} but got {2}", xf, expected, actual));
            }

            for (int i = 0; i < m_testCases.Length; ++i)
            {
                var b = Fix64.FromRaw(m_testCases[i]);

                if (b < -Fix64.One || b > Fix64.One)
                {
                    Assert.Throws <ArgumentOutOfRangeException>(() => MathFix.Acos(b));
                }
                else
                {
                    var expected = (decimal)Math.Acos((double)b);
                    var actual   = (decimal)MathFix.Acos(b);
                    var delta    = Math.Abs(expected - actual);
                    deltas.Add(delta);
                    Assert.True(delta <= maxDelta, string.Format("Acos({0}) = expected {1} but got {2}", b, expected, actual));
                }
            }
            Console.WriteLine("Max error: {0} ({1} times precision)", deltas.Max(), deltas.Max() / Fix64.Precision);
            Console.WriteLine("Average precision: {0} ({1} times precision)", deltas.Average(), deltas.Average() / Fix64.Precision);
        }
Пример #16
0
        public void Ln()
        {
            double maxDelta = 0.00000001;

            for (int j = 0; j < m_testCases.Length; ++j)
            {
                var b = Fix64.FromRaw(m_testCases[j]);

                if (b <= Fix64.Zero)
                {
                    Assert.Throws <ArgumentOutOfRangeException>(() => MathFix.Log(b));
                }
                else
                {
                    var expected = Math.Log((double)b);
                    var actual   = (double)MathFix.Log(b);
                    var delta    = Math.Abs(expected - actual);

                    Assert.True(delta <= maxDelta, string.Format("Ln({0}) = expected {1} but got {2}", b, expected, actual));
                }
            }
        }