// 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)); }
// 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); }
public static Fix64 Asinh(Fix64 x) { throw new NotImplementedException(); }
/// <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(); }