Exemple #1
0
        // This function is not well-tested. It may be wildly inaccurate.
        /// <summary>
        /// Returns the tangent of the specified angle.
        /// </summary>
        /// <param name="x">An angle, measured in radians.</param>
        /// <returns></returns>
        public static Fix64 Tan(Fix64 x)
        {
            var clampedPi = x.RawValue % _PI;
            var flip      = false;

            if (clampedPi < 0)
            {
                clampedPi = -clampedPi;
                flip      = true;
            }
            if (clampedPi > PI_OVER_2)
            {
                flip      = !flip;
                clampedPi = PI_OVER_2 - (clampedPi - PI_OVER_2);
            }

            var clamped = new Fix64(clampedPi);

            // Find the two closest values in the LUT and perform linear interpolation
            var rawIndex     = Fix64.FastMultiply(clamped, LutInterval);
            var roundedIndex = Round(rawIndex);
            var indexError   = Fix64.FastSubtract(rawIndex, roundedIndex);

            var nearestValue       = new Fix64(TanLut[(int)roundedIndex]);
            var secondNearestValue = new Fix64(TanLut[(int)roundedIndex + Sign(indexError)]);

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

            return(new Fix64(finalValue));
        }
Exemple #2
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));
        }