Ejemplo n.º 1
0
        // The relative error is less than 1E-10 for x in [-2PI, 2PI], and less than 1E-7 in the worst case.
        /// <summary>
        /// Returns the sine of the specified angle.
        /// </summary>
        /// <param name="x">An angle, measured in radians.</param>
        /// <returns></returns>
        public static Fix64 Sin(Fix64 x)
        {
            var clampedL = ClampSinValue(x.RawValue, out var flipHorizontal, out var flipVertical);
            var clamped  = new Fix64(clampedL);

            // Find the two closest values in the LUT and perform linear interpolation
            // This is what kills the performance of this function on x86 - x64 is fine though
            var rawIndex     = Fix64.FastMultiply(clamped, LutInterval);
            var roundedIndex = Round(rawIndex);
            var indexError   = Fix64.FastSubtract(rawIndex, roundedIndex);

            var nearestValue = new Fix64(SinLut[flipHorizontal ?
                                                SinLut.Length - 1 - (int)roundedIndex :
                                                (int)roundedIndex]);
            var secondNearestValue = new Fix64(SinLut[flipHorizontal ?
                                                      SinLut.Length - 1 - (int)roundedIndex - Sign(indexError) :
                                                      (int)roundedIndex + Sign(indexError)]);

            var delta             = Fix64.FastMultiply(indexError, FastAbs(Fix64.FastSubtract(nearestValue, secondNearestValue))).RawValue;
            var interpolatedValue = nearestValue.RawValue + (flipHorizontal ? -delta : delta);
            var finalValue        = flipVertical ? -interpolatedValue : interpolatedValue;

            return(new Fix64(finalValue));
        }
Ejemplo n.º 2
0
        // Returns the arctan of of the specified number, calculated using Euler series
        // This function has at least 7 decimals of accuracy.
        /// <summary>
        /// Returns the angle whose tangent is the specified number.
        /// </summary>
        /// <param name="x">A number representing a tangent.</param>
        /// <returns></returns>
        public static Fix64 Atan(Fix64 x)
        {
            if (x.RawValue == 0)
            {
                return(Fix64.Zero);
            }

            // Force positive values for argument
            // Atan(-z) = -Atan(z).
            var neg = x.RawValue < 0;

            if (neg)
            {
                x = -x;
            }

            Fix64 result;
            var   two   = (Fix64)2;
            var   three = (Fix64)3;

            bool invert = x > Fix64.One;

            if (invert)
            {
                x = Fix64.One / x;
            }

            result = Fix64.One;
            var term = Fix64.One;

            var zSq        = x * x;
            var zSq2       = zSq * two;
            var zSqPlusOne = zSq + Fix64.One;
            var zSq12      = zSqPlusOne * two;
            var dividend   = zSq2;
            var divisor    = zSqPlusOne * three;

            for (var i = 2; i < 30; ++i)
            {
                term   *= dividend / divisor;
                result += term;

                dividend += zSq2;
                divisor  += zSq12;

                if (term.RawValue == 0)
                {
                    break;
                }
            }

            result = result * x / zSqPlusOne;

            if (invert)
            {
                result = PIOver2 - result;
            }

            if (neg)
            {
                result = -result;
            }
            return(result);
        }
Ejemplo n.º 3
0
 public static Fix64 Asinh(Fix64 x)
 {
     throw new NotImplementedException();
 }
Ejemplo n.º 4
0
 /// <summary>
 /// Returns the hyperbolic tangent of the specified angle.
 /// </summary>
 /// <param name="value">An angle, measured in radians.</param>
 /// <returns></returns>
 public static Fix64 Tanh(Fix64 value)
 {
     throw new NotImplementedException();
 }