< Summary

Line coverage
99%
Covered lines: 410
Uncovered lines: 1
Coverable lines: 411
Total lines: 1024
Line coverage: 99.7%
Branch coverage
100%
Covered branches: 206
Total branches: 206
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
File 1: .cctor()100%11100%
File 1: CopySign(...)100%22100%
File 1: Clamp01(...)100%44100%
File 1: Clamp(...)100%44100%
File 1: Clamp(...)100%44100%
File 1: ClampOne(...)100%44100%
File 1: Abs(...)100%22100%
File 1: Ceiling(...)100%22100%
File 1: Floor(...)100%11100%
File 1: Max(...)100%22100%
File 1: Min(...)100%22100%
File 1: Round(...)100%1010100%
File 1: RoundToPrecision(...)100%44100%
File 1: Squared(...)100%11100%
File 1: FastAdd(...)100%11100%
File 1: FastSub(...)100%11100%
File 1: FastMul(...)100%11100%
File 1: FastMod(...)100%11100%
File 1: SmoothStep(...)100%11100%
File 1: CubicInterpolate(...)100%11100%
File 1: LinearInterpolate(...)100%44100%
File 1: MoveTowards(...)100%88100%
File 1: AddOverflowHelper(...)100%44100%
File 2: .cctor()100%11100%
File 2: Pow(...)100%88100%
File 2: Pow2(...)100%1616100%
File 2: Log2(...)100%1010100%
File 2: Ln(...)100%22100%
File 2: Sqrt(...)100%1818100%
File 2: RadToDeg(...)100%11100%
File 2: DegToRad(...)100%11100%
File 2: Sin(...)100%2424100%
File 2: Cos(...)100%22100%
File 2: SinToCos(...)100%11100%
File 2: Tan(...)100%161695.65%
File 2: Asin(...)100%1616100%
File 2: Acos(...)100%1212100%
File 2: Atan(...)100%1616100%
File 2: Atan2(...)100%1010100%

File(s)

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Core/FixedMath.cs

#LineLine coverage
 1using System;
 2using System.Runtime.CompilerServices;
 3
 4namespace FixedMathSharp
 5{
 6    /// <summary>
 7    /// A static class that provides a variety of fixed-point math functions.
 8    /// Fixed-point numbers are represented as <see cref="Fixed64"/>.
 9    /// </summary>
 10    public static partial class FixedMath
 11    {
 12        #region Fields and Constants
 13
 14        /// <summary>
 15        /// Represents the number of bits to shift for fixed-point representation.
 16        /// </summary>
 17        public const int SHIFT_AMOUNT_I = 32;
 18        /// <summary>
 19        /// Represents the maximum value that can be produced by left-shifting 1 by SHIFT_AMOUNT_I bits and subtracting 
 20        /// </summary>
 21        /// <remarks>
 22        /// This constant is typically used as a bitmask to extract or limit values to the range
 23        /// defined by SHIFT_AMOUNT_I.
 24        /// The value is always non-negative and fits within a 32-bit unsigned
 25        /// integer.
 26        /// </remarks>
 27        public const uint MAX_SHIFTED_AMOUNT_UI = (uint)((1L << SHIFT_AMOUNT_I) - 1);
 28        /// <summary>
 29        /// Represents a bitmask with all bits set except for the lowest SHIFT_AMOUNT_I bits.
 30        /// </summary>
 31        /// <remarks>
 32        /// This constant is typically used to isolate or clear the lower SHIFT_AMOUNT_I bits of
 33        /// an unsigned 64-bit value.
 34        /// The value of SHIFT_AMOUNT_I determines how many least significant bits are masked out.
 35        /// </remarks>
 36        public const ulong MASK_UL = (ulong)(ulong.MaxValue << SHIFT_AMOUNT_I);
 37
 38        /// <summary>
 39        /// Represents the largest possible value for a 64-bit fixed-point number.
 40        /// </summary>
 41        /// <remarks>
 42        /// Use this constant to perform comparisons or to initialize variables that require the
 43        /// maximum representable value for a 64-bit fixed-point type.
 44        /// </remarks>
 45        public const long MAX_VALUE_L = long.MaxValue;
 46        /// <summary>
 47        /// Represents the smallest possible value for a 64-bit fixed-point number.
 48        /// </summary>
 49        /// <remarks>
 50        /// Use this constant to check for underflow conditions or to initialize variables that
 51        /// require the minimum representable value for a 64-bit fixed-point type.
 52        /// </remarks>
 53        public const long MIN_VALUE_L = long.MinValue;
 54
 55        /// <summary>
 56        /// Represents the value 1 shifted left by the number of bits specified by SHIFT_AMOUNT_I.
 57        /// </summary>
 58        public const long ONE_L = 1L << SHIFT_AMOUNT_I;
 59
 60        // Precomputed scale factors only for performance-critical scenarios to avoid division at runtime
 61
 62        /// <summary>
 63        /// Represents the precomputed scale factor used for floating-point calculations.
 64        /// </summary>
 65        /// <remarks>
 66        /// This constant is intended only for converting fixed-point values to floating-point representations in perfor
 67        /// </remarks>
 68        public const float SCALE_FACTOR_F = 1.0f / ONE_L;
 69        /// <summary>
 70        /// Represents the precomputed scale factor used for double-precision calculations.
 71        /// </summary>
 72        /// <remarks>
 73        /// This constant is intended only for converting fixed-point values to double-precision representations in perf
 74        /// </remarks>
 75        public const double SCALE_FACTOR_D = 1.0 / ONE_L;
 76        /// <summary>
 77        /// Represents the precomputed scale factor used for decimal calculations.
 78        /// </summary>
 79        /// <remarks>
 80        /// This constant is intended only for converting fixed-point values to decimal representations in performance-c
 81        /// </remarks>
 182        public const decimal SCALE_FACTOR_M = 1.0m / ONE_L;
 83
 84        /// <summary>
 85        /// The smallest non-zero raw increment representable by Fixed64.
 86        /// </summary>
 87        public const long MIN_INCREMENT_L = 1L;
 88
 89        /// <summary>
 90        /// Default tolerance for fuzzy comparisons.
 91        /// Approximately 2^-24 (~5.96e-8) in value space.
 92        /// </summary>
 93        public const long DEFAULT_TOLERANCE_L = 1L << (SHIFT_AMOUNT_I - 24);
 94
 95
 96        #endregion
 97
 98        #region FixedMath Operations
 99
 100        /// <summary>
 101        /// Produces a value with the magnitude of the first argument and the sign of the second argument.
 102        /// </summary>
 103        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 104        public static Fixed64 CopySign(Fixed64 x, Fixed64 y)
 4105        {
 4106            return y >= Fixed64.Zero ? x.Abs() : -x.Abs();
 4107        }
 108
 109        /// <summary>
 110        /// Clamps value between 0 and 1 and returns value.
 111        /// </summary>
 112        /// <param name="value"></param>
 113        /// <returns></returns>
 114        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 115        public static Fixed64 Clamp01(Fixed64 value)
 16116        {
 16117            return value < Fixed64.Zero ? Fixed64.Zero : value > Fixed64.One ? Fixed64.One : value;
 16118        }
 119
 120        /// <summary>
 121        /// Clamps a fixed-point value between the given minimum and maximum values.
 122        /// </summary>
 123        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 124        public static Fixed64 Clamp(Fixed64 f1, Fixed64 min, Fixed64 max)
 160125        {
 160126            return f1 < min ? min : f1 > max ? max : f1;
 160127        }
 128
 129        /// <summary>
 130        /// Clamps a value to the inclusive range [min, max].
 131        /// </summary>
 132        /// <typeparam name="T">The type of the value, must implement IComparable&lt;T&gt;.</typeparam>
 133        /// <param name="value">The value to clamp.</param>
 134        /// <param name="min">The minimum allowed value.</param>
 135        /// <param name="max">The maximum allowed value.</param>
 136        /// <returns>The clamped value.</returns>
 137        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 138        public static T Clamp<T>(T value, T min, T max) where T : IComparable<T>
 3139        {
 4140            if (value.CompareTo(max) > 0) return max;
 3141            if (value.CompareTo(min) < 0) return min;
 1142            return value;
 3143        }
 144
 145        /// <summary>
 146        /// Clamps the value between -1 and 1 inclusive.
 147        /// </summary>
 148        /// <param name="f1">The Fixed64 value to clamp.</param>
 149        /// <returns>Returns a value clamped between -1 and 1.</returns>
 150        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 151        public static Fixed64 ClampOne(Fixed64 f1)
 14152        {
 14153            return f1 > Fixed64.One ? Fixed64.One : f1 < -Fixed64.One ? -Fixed64.One : f1;
 14154        }
 155
 156        /// <summary>
 157        /// Returns the absolute value of a Fixed64 number.
 158        /// </summary>
 159        public static Fixed64 Abs(Fixed64 value)
 3858160        {
 161            // For the minimum value, return the max to avoid overflow
 3858162            if (value.m_rawValue == MIN_VALUE_L)
 1163                return new Fixed64(MAX_VALUE_L);
 164
 165            // Use branchless absolute value calculation
 3857166            long mask = value.m_rawValue >> 63; // If negative, mask will be all 1s; if positive, all 0s
 3857167            return Fixed64.FromRaw((value.m_rawValue + mask) ^ mask);
 3858168        }
 169
 170        /// <summary>
 171        /// Returns the smallest integral value that is greater than or equal to the specified number.
 172        /// </summary>
 173        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 174        public static Fixed64 Ceiling(Fixed64 value)
 6175        {
 6176            bool hasFractionalPart = (value.m_rawValue & MAX_SHIFTED_AMOUNT_UI) != 0;
 6177            return hasFractionalPart ? value.Floor() + Fixed64.One : value;
 6178        }
 179
 180        /// <summary>
 181        /// Returns the largest integer less than or equal to the specified number (floor function).
 182        /// </summary>
 183        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 184        public static Fixed64 Floor(Fixed64 value)
 36185        {
 186            // Efficiently zeroes out the fractional part
 36187            return Fixed64.FromRaw((long)((ulong)value.m_rawValue & FixedMath.MASK_UL));
 36188        }
 189
 190        /// <summary>
 191        /// Returns the larger of two fixed-point values.
 192        /// </summary>
 193        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 194        public static Fixed64 Max(Fixed64 f1, Fixed64 f2)
 13195        {
 13196            return f1 >= f2 ? f1 : f2;
 13197        }
 198
 199        /// <summary>
 200        /// Returns the smaller of two fixed-point values.
 201        /// </summary>
 202        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 203        public static Fixed64 Min(Fixed64 a, Fixed64 b)
 46204        {
 46205            return (a < b) ? a : b;
 46206        }
 207
 208        /// <summary>
 209        /// Rounds a fixed-point number to the nearest integral value, based on the specified rounding mode.
 210        /// </summary>
 211        public static Fixed64 Round(Fixed64 value, MidpointRounding mode = MidpointRounding.ToEven)
 25212        {
 25213            long fractionalPart = value.m_rawValue & MAX_SHIFTED_AMOUNT_UI;
 25214            Fixed64 integralPart = value.Floor();
 25215            if (fractionalPart < Fixed64.Half.m_rawValue)
 3216                return integralPart;
 217
 22218            if (fractionalPart > Fixed64.Half.m_rawValue)
 10219                return integralPart + Fixed64.One;
 220
 221            // When value is exactly Fixed64.Halfway between two numbers
 12222            return mode switch
 12223            {
 3224                MidpointRounding.AwayFromZero => value.m_rawValue > 0 ? integralPart + Fixed64.One : integralPart,// For
 9225                _ => (integralPart.m_rawValue & ONE_L) == 0 ? integralPart : integralPart + Fixed64.One,// Rounds to the
 12226            };
 25227        }
 228
 229        /// <summary>
 230        /// Rounds a fixed-point number to a specific number of decimal places.
 231        /// </summary>
 232        public static Fixed64 RoundToPrecision(Fixed64 value, int decimalPlaces, MidpointRounding mode = MidpointRoundin
 7233        {
 7234            if (decimalPlaces < 0 || decimalPlaces >= Pow10Lookup.Length)
 2235                throw new ArgumentOutOfRangeException(nameof(decimalPlaces), "Decimal places out of range.");
 236
 5237            int factor = Pow10Lookup[decimalPlaces];
 5238            Fixed64 scaled = value * factor;
 5239            long rounded = Round(scaled, mode).m_rawValue;
 5240            return new Fixed64(rounded + (factor / 2)) / factor;
 5241        }
 242
 243        /// <summary>
 244        /// Squares the Fixed64 value.
 245        /// </summary>
 246        /// <param name="value">The Fixed64 value to square.</param>
 247        /// <returns>The squared value.</returns>
 248        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 249        public static Fixed64 Squared(Fixed64 value)
 2250        {
 2251            return value * value;
 2252        }
 253
 254        /// <summary>
 255        /// Adds two fixed-point numbers without performing overflow checking.
 256        /// </summary>
 257        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 258        public static Fixed64 FastAdd(Fixed64 x, Fixed64 y)
 5259        {
 5260            return Fixed64.FromRaw(x.m_rawValue + y.m_rawValue);
 5261        }
 262
 263        /// <summary>
 264        /// Subtracts two fixed-point numbers without performing overflow checking.
 265        /// </summary>
 266        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 267        public static Fixed64 FastSub(Fixed64 x, Fixed64 y)
 5268        {
 5269            return Fixed64.FromRaw(x.m_rawValue - y.m_rawValue);
 5270        }
 271
 272        /// <summary>
 273        /// Multiplies two fixed-point numbers without overflow checking for performance-critical scenarios.
 274        /// </summary>
 275        public static Fixed64 FastMul(Fixed64 x, Fixed64 y)
 188276        {
 188277            long xl = x.m_rawValue;
 188278            long yl = y.m_rawValue;
 279
 280            // Split values into high and low bits for long multiplication
 188281            ulong xlo = (ulong)(xl & MAX_SHIFTED_AMOUNT_UI);
 188282            long xhi = xl >> SHIFT_AMOUNT_I;
 188283            ulong ylo = (ulong)(yl & MAX_SHIFTED_AMOUNT_UI);
 188284            long yhi = yl >> SHIFT_AMOUNT_I;
 285
 286            // Perform partial products
 188287            ulong lolo = xlo * ylo;
 188288            long lohi = (long)xlo * yhi;
 188289            long hilo = xhi * (long)ylo;
 188290            long hihi = xhi * yhi;
 291
 292            // Combine the results
 188293            ulong loResult = lolo >> SHIFT_AMOUNT_I;
 188294            long midResult1 = lohi;
 188295            long midResult2 = hilo;
 188296            long hiResult = hihi << SHIFT_AMOUNT_I;
 297
 188298            long sum = (long)loResult + midResult1 + midResult2 + hiResult;
 188299            return Fixed64.FromRaw(sum);
 188300        }
 301
 302        /// <summary>
 303        /// Fast modulus without the checks performed by the '%' operator.
 304        /// </summary>
 305        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 306        public static Fixed64 FastMod(Fixed64 x, Fixed64 y)
 5307        {
 5308            return Fixed64.FromRaw(x.m_rawValue % y.m_rawValue);
 4309        }
 310
 311        /// <summary>
 312        /// Performs a smooth step interpolation between two values.
 313        /// </summary>
 314        /// <remarks>
 315        /// The interpolation follows a cubic Hermite curve where the function starts at `a`,
 316        /// accelerates, and then decelerates towards `b`, ensuring smooth transitions.
 317        /// </remarks>
 318        /// <param name="a">The starting value.</param>
 319        /// <param name="b">The ending value.</param>
 320        /// <param name="t">A value between 0 and 1 that represents the interpolation factor.</param>
 321        /// <returns>The interpolated value between `a` and `b`.</returns>
 322        public static Fixed64 SmoothStep(Fixed64 a, Fixed64 b, Fixed64 t)
 4323        {
 4324            t = t * t * (Fixed64.Three - Fixed64.Two * t);
 4325            return LinearInterpolate(a, b, t);
 4326        }
 327
 328        /// <summary>
 329        /// Performs a cubic Hermite interpolation between two points, using specified tangents.
 330        /// </summary>
 331        /// <remarks>
 332        /// This method interpolates smoothly between `p0` and `p1` while considering the tangents `m0` and `m1`.
 333        /// It is useful for animation curves and smooth motion transitions.
 334        /// </remarks>
 335        /// <param name="p0">The first point.</param>
 336        /// <param name="p1">The second point.</param>
 337        /// <param name="m0">The tangent (slope) at `p0`.</param>
 338        /// <param name="m1">The tangent (slope) at `p1`.</param>
 339        /// <param name="t">A value between 0 and 1 that represents the interpolation factor.</param>
 340        /// <returns>The interpolated value between `p0` and `p1`.</returns>
 341        public static Fixed64 CubicInterpolate(Fixed64 p0, Fixed64 p1, Fixed64 m0, Fixed64 m1, Fixed64 t)
 4342        {
 4343            Fixed64 t2 = t * t;
 4344            Fixed64 t3 = t2 * t;
 4345            return (Fixed64.Two * p0 - Fixed64.Two * p1 + m0 + m1) * t3
 4346                 + (-Fixed64.Three * p0 + Fixed64.Three * p1 - Fixed64.Two * m0 - m1) * t2
 4347                 + m0 * t + p0;
 4348        }
 349
 350        /// <summary>
 351        /// Performs linear interpolation between two fixed-point values based on the interpolant t (0 greater or equal 
 352        /// </summary>
 353        public static Fixed64 LinearInterpolate(Fixed64 from, Fixed64 to, Fixed64 t)
 35354        {
 35355            if (t.m_rawValue >= ONE_L)
 2356                return to;
 33357            if (t.m_rawValue <= 0)
 3358                return from;
 359
 30360            return (to * t) + (from * (Fixed64.One - t));
 35361        }
 362
 363        /// <summary>
 364        /// Moves a value from 'from' to 'to' by a maximum step of 'maxAmount'.
 365        /// Ensures the value does not exceed 'to'.
 366        /// </summary>
 367        public static Fixed64 MoveTowards(Fixed64 from, Fixed64 to, Fixed64 maxAmount)
 4368        {
 4369            if (from < to)
 2370            {
 2371                from += maxAmount;
 2372                if (from > to)
 1373                    from = to;
 2374            }
 2375            else if (from > to)
 2376            {
 2377                from -= maxAmount;
 2378                if (from < to)
 1379                    from = to;
 2380            }
 381
 4382            return Fixed64.FromRaw(from.m_rawValue);
 4383        }
 384
 385        /// <summary>
 386        /// Adds two <see cref="long"/> values and checks for overflow.
 387        /// If an overflow occurs during addition, the <paramref name="overflow"/> parameter is set to true.
 388        /// </summary>
 389        /// <param name="x">The first operand to add.</param>
 390        /// <param name="y">The second operand to add.</param>
 391        /// <param name="overflow">
 392        /// A reference parameter that is set to true if an overflow is detected during the addition.
 393        /// The existing value of <paramref name="overflow"/> is preserved if already true.
 394        /// </param>
 395        /// <returns>The sum of <paramref name="x"/> and <paramref name="y"/>.</returns>
 396        /// <remarks>
 397        /// Overflow is detected by checking for a change in the sign bit that indicates a wrap-around.
 398        /// Additionally, a special check is performed for adding <see cref="Fixed64.MIN_VALUE"/> and -1,
 399        /// as this is a known edge case for overflow.
 400        /// </remarks>
 401        public static long AddOverflowHelper(long x, long y, ref bool overflow)
 3402        {
 3403            long sum = x + y;
 404            // Check for overflow using sign bit changes
 3405            overflow |= ((x ^ y ^ sum) & MIN_VALUE_L) != 0;
 406            // Special check for the case when x is long.Fixed64.MinValue and y is negative
 3407            if (x == long.MinValue && y == -1)
 1408                overflow = true;
 3409            return sum;
 3410        }
 411
 412        #endregion
 413    }
 414}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Core/FixedTrigonometry.cs

#LineLine coverage
 1using System;
 2using System.Runtime.CompilerServices;
 3
 4namespace FixedMathSharp
 5{
 6    public static partial class FixedMath
 7    {
 8        #region Fields and Constants
 9
 10        /// <summary>
 11        /// Provides a lookup table of integer powers of 10 from 10^0 to 10^9.
 12        /// </summary>
 13        /// <remarks>
 14        /// This array can be used to efficiently retrieve the value of 10 raised to an integer
 15        /// exponent within the supported range, avoiding repeated calculations.
 16        /// The index corresponds to the exponent.
 17        /// </remarks>
 118        public static readonly int[] Pow10Lookup = {
 119            1,           // 10^0 = 1
 120            10,          // 10^1 = 10
 121            100,         // 10^2 = 100
 122            1000,        // 10^3 = 1000
 123            10000,       // 10^4 = 10000
 124            100000,      // 10^5 = 100000
 125            1000000,     // 10^6 = 1000000
 126            10000000,    // 10^7 = 1000000
 127            100000000,   // 10^8 = 1000000
 128            1000000000,  // 10^9 = 1000000
 129        };
 30
 31        // Trigonometric and logarithmic constants
 32
 33        /// <summary>
 34        /// Represents the mathematical constant π (pi).
 35        /// </summary>
 36        /// <remarks>The value is approximately 3.14159265358979323846.</remarks>
 137        public static readonly Fixed64 PI = (Fixed64)3.14159265358979323846;
 38
 39        /// <summary>
 40        /// Represents the mathematical constant 2π as a fixed-point value.
 41        /// </summary>
 42        /// <remarks>This value is commonly used to represent a full rotation in radians.</remarks>
 143        public static readonly Fixed64 TwoPI = PI * Fixed64.Two;
 44        /// <summary>
 45        /// Represents the mathematical constant π divided by 2 as a fixed-point value.
 46        /// </summary>
 47        /// <remarks>This value is used where π/2 is required.</remarks>
 148        public static readonly Fixed64 PiOver2 = PI / new Fixed64(2);
 49        /// <summary>
 50        /// Represents the mathematical constant π divided by 3 as a fixed-point value.
 51        /// </summary>
 152        public static readonly Fixed64 PiOver3 = PI / new Fixed64(3);
 53        /// <summary>
 54        /// Represents the mathematical constant π divided by 4 as a fixed-point value.
 55        /// </summary>
 156        public static readonly Fixed64 PiOver4 = PI / new Fixed64(4);
 57        /// <summary>
 58        /// Represents the mathematical constant π divided by 6 as a fixed-point value.
 59        /// </summary>
 160        public static readonly Fixed64 PiOver6 = PI / new Fixed64(6);
 61        /// <summary>
 62        /// Represents the multiplicative inverse of the mathematical constant π (pi) as a fixed-point value.
 63        /// </summary>
 164        public static readonly Fixed64 InvertedPI = Fixed64.One / PI;
 65
 66        /// <summary>
 67        /// Represents the fixed-point value for 180.
 68        /// </summary>
 169        public static readonly Fixed64 OneEighty = new(180);
 70
 71        /// <summary>
 72        /// Degrees to radians conversion factor (π / 180)
 73        /// </summary>
 174        public static readonly Fixed64 Deg2Rad = PI / OneEighty;
 75        /// <summary>
 76        /// Radians to degrees conversion factor (180 / π)
 77        /// </summary>
 178        public static readonly Fixed64 Rad2Deg = OneEighty / PI;
 79
 80        /// <summary>
 81        /// Represents the natural logarithm of 2 as a fixed-point value.
 82        /// </summary>
 183        public static readonly Fixed64 Ln2 = new(0.6931471805599453);
 84        /// <summary>
 85        /// Represents the maximum value for the base-2 logarithm that can be represented by a Fixed64 instance.
 86        /// </summary>
 87        /// <remarks>
 88        /// This constant is useful when performing logarithmic calculations to ensure results
 89        /// do not exceed the representable range of the Fixed64 type.
 90        /// </remarks>
 191        public static readonly Fixed64 LOG_2_MAX = new(63L * ONE_L);
 92        /// <summary>
 93        /// Represents the minimum base-2 logarithm value supported by the Fixed64 type.
 94        /// </summary>
 95        /// <remarks>
 96        /// This constant can be used as a lower bound when performing logarithmic calculations
 97        /// with Fixed64 values to prevent underflow or invalid results.
 98        /// </remarks>
 199        public static readonly Fixed64 LOG_2_MIN = new(-64L * ONE_L);
 100
 101        // Asin Padé approximations
 1102        private static readonly Fixed64 PADE_A1 = (Fixed64)0.183320102;
 1103        private static readonly Fixed64 PADE_A2 = (Fixed64)0.0218804099;
 104
 105        // Carefully optimized polynomial coefficients for sin(x), ensuring maximum precision in Fixed64 math.
 1106        private static readonly Fixed64 SIN_COEFF_3 = (Fixed64)0.16666667605750262737274169921875d; // 1/3!
 1107        private static readonly Fixed64 SIN_COEFF_5 = (Fixed64)0.0083328341133892536163330078125d; // 1/5!
 1108        private static readonly Fixed64 SIN_COEFF_7 = (Fixed64)0.00019588856957852840423583984375d; // 1/7!
 109
 110        #endregion
 111
 112        #region FixedTrigonometry Operations
 113
 114        /// <summary>
 115        /// Raises the base number b to the power of exp.
 116        /// Uses logarithms to compute power efficiently for fixed-point values.
 117        /// </summary>
 118        /// <exception cref="DivideByZeroException">
 119        /// The base was Fixed64.Zero, with a negative expFixed64.Onent
 120        /// </exception>
 121        /// <exception cref="ArgumentOutOfRangeException">
 122        /// The base was negative, with a non-Fixed64.Zero expFixed64.Onent
 123        /// </exception>
 124        public static Fixed64 Pow(Fixed64 b, Fixed64 exp)
 6125        {
 6126            if (b == Fixed64.One)
 1127                return Fixed64.One;
 128
 5129            if (exp.m_rawValue == 0)
 1130                return Fixed64.One;
 131
 4132            if (b.m_rawValue == 0)
 2133            {
 2134                if (exp.m_rawValue < 0)
 1135                    throw new DivideByZeroException("Cannot raise 0 to a negative power.");
 136
 1137                return Fixed64.Zero;
 138            }
 139
 2140            Fixed64 log2 = Log2(b);  // Calculate logarithm base 2
 2141            return Pow2(exp * log2);  // Raise 2 to the power of log2 result
 5142        }
 143
 144        /// <summary>
 145        /// Raises 2 to the power of x.
 146        /// Provides high accuracy for small values of x.
 147        /// </summary>
 148        public static Fixed64 Pow2(Fixed64 x)
 8149        {
 8150            if (x.m_rawValue == 0)
 1151                return Fixed64.One;
 152
 153            // Handle negative expFixed64.Onents by using the reciprocal
 7154            bool neg = x.m_rawValue < 0;
 7155            if (neg)
 4156                x = -x;
 157
 7158            if (x == Fixed64.One)
 3159                return neg ? Fixed64.One / Fixed64.Two : Fixed64.Two;
 160
 4161            if (x >= LOG_2_MAX)
 2162                return neg ? Fixed64.One / new Fixed64(MAX_VALUE_L) : new Fixed64(MAX_VALUE_L);
 163
 164            /*
 165             * Taylor series expansion for exp(x)
 166             * From term n, we get term n+1 by multiplying with x/n.
 167             * When the sum term drops to Fixed64.Zero, we can stop summing.
 168             */
 2169            int integerPart = (int)x.Floor();
 2170            x = Fixed64.FromRaw(x.m_rawValue & MAX_SHIFTED_AMOUNT_UI);  // Fractional part
 171
 2172            var result = Fixed64.One;
 2173            var term = Fixed64.One;
 2174            int i = 1;
 13175            while (term.m_rawValue != 0)
 11176            {
 11177                term = FastMul(FastMul(x, term), Ln2) / (Fixed64)i;
 11178                result += term;
 11179                i++;
 11180            }
 181
 2182            result = Fixed64.FromRaw(result.m_rawValue << integerPart);
 2183            if (neg)
 1184                result = Fixed64.One / result;
 185
 2186            return result;
 8187        }
 188
 189        /// <summary>
 190        /// Returns the base-2 logarithm of a specified number.
 191        /// Provides at least 9 decimals of accuracy.
 192        /// </summary>
 193        /// <remarks>
 194        /// This implementation is based on Clay. S. Turner's fast binary logarithm algorithm
 195        /// (C. S. Turner,  "A Fast Binary Logarithm Algorithm", IEEE Signal Processing Mag., pp. 124,140, Sep. 2010.)
 196        /// </remarks>
 197        public static Fixed64 Log2(Fixed64 x)
 6198        {
 6199            if (x.m_rawValue <= 0)
 1200                throw new ArgumentOutOfRangeException(nameof(x), "Cannot compute logarithm of non-positive number.");
 201
 5202            long b = 1U << (SHIFT_AMOUNT_I - 1);  // Initial value for binary logarithm
 5203            long y = 0;  // Result accumulator
 5204            long rawX = x.m_rawValue;
 205
 206            // Adjust rawX to the correct range [1, 2)
 6207            while (rawX < ONE_L)
 1208            {
 1209                rawX <<= 1;
 1210                y -= ONE_L;
 1211            }
 212
 11213            while (rawX >= (ONE_L << 1))
 6214            {
 6215                rawX >>= 1;
 6216                y += ONE_L;
 6217            }
 218
 5219            Fixed64 z = Fixed64.FromRaw(rawX);  // Remaining fraction
 220
 330221            for (int i = 0; i < SHIFT_AMOUNT_I; i++)
 160222            {
 160223                z = FastMul(z, z);
 160224                if (z.m_rawValue >= (ONE_L << 1))
 15225                {
 15226                    z = Fixed64.FromRaw(z.m_rawValue >> 1);
 15227                    y += b;
 15228                }
 160229                b >>= 1;
 160230            }
 231
 5232            return Fixed64.FromRaw(y);
 5233        }
 234
 235        /// <summary>
 236        /// Returns the natural logarithm of a specified fixed-point number.
 237        /// Provides at least 7 decimals of accuracy.
 238        /// </summary>
 239        public static Fixed64 Ln(Fixed64 x)
 2240        {
 2241            if (x.m_rawValue <= 0)
 1242                throw new ArgumentOutOfRangeException(nameof(x), "Cannot compute logarithm of non-positive number.");
 243
 1244            return FastMul(Log2(x), Ln2).Round();
 1245        }
 246
 247        /// <summary>
 248        /// Returns the square root of a specified fixed-point number.
 249        /// </summary>
 250        public static Fixed64 Sqrt(Fixed64 x)
 807251        {
 807252            if (x.m_rawValue < 0)
 1253                throw new ArgumentOutOfRangeException(nameof(x), "Cannot compute square root of a negative number.");
 254
 806255            ulong num = (ulong)x.m_rawValue;
 806256            ulong result = 0UL;
 806257            ulong bit = 1UL << (sizeof(long) * 8) - 2; // second-to-top bit of a 64-bit integer
 258
 259            // Adjust the bit position to a suitable starting point
 11694260            while (bit > num)
 10888261                bit >>= 2;
 262
 263            // Perform the square root calculation using bitwise shifts
 4836264            for (int i = 0; i < 2; ++i)
 1612265            {
 266                // Calculate the top bits of the square root result
 29412267                while (bit != 0)
 27800268                {
 27800269                    if (num >= result + bit)
 10339270                    {
 10339271                        num -= result + bit;
 10339272                        result = (result >> 1) + bit;
 10339273                    }
 274                    else
 17461275                    {
 17461276                        result >>= 1;
 17461277                    }
 278
 27800279                    bit >>= 2;
 27800280                }
 281
 1612282                if (i == 0)
 806283                {
 284                    // Process it again to get the remaining bits
 806285                    if (num > ((1UL << SHIFT_AMOUNT_I) - 1))
 1286                    {
 287                        // Handle large remainders by adjusting the result
 1288                        num -= result;
 1289                        num = (num << SHIFT_AMOUNT_I) - (ulong)Fixed64.Half.m_rawValue;
 1290                        result = (result << SHIFT_AMOUNT_I) + (ulong)Fixed64.Half.m_rawValue;
 1291                    }
 292                    else
 805293                    {
 805294                        num <<= SHIFT_AMOUNT_I;
 805295                        result <<= SHIFT_AMOUNT_I;
 805296                    }
 297
 806298                    bit = 1UL << (SHIFT_AMOUNT_I - 2);
 806299                }
 1612300            }
 301
 302            // Rounding: round up if necessary
 806303            if (num > result && (num - result) > (result >> 1))
 131304                ++result;
 305
 806306            return Fixed64.FromRaw((long)result);
 806307        }
 308
 309        /// <summary>
 310        /// Converts a value in radians to degrees.
 311        /// </summary>
 312        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 313        public static Fixed64 RadToDeg(Fixed64 rad)
 20314        {
 20315            return (rad * OneEighty) / PI;
 20316        }
 317
 318        /// <summary>
 319        /// Converts a value in degrees to radians.
 320        /// </summary>
 321        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 322        public static Fixed64 DegToRad(Fixed64 deg)
 95323        {
 95324            return (deg * PI) / OneEighty;
 95325        }
 326
 327        /// <summary>
 328        /// Computes the sine of a given angle in radians using an optimized
 329        /// minimax polynomial approximation.
 330        /// </summary>
 331        /// <param name="x">The angle in radians.</param>
 332        /// <returns>The sine of the given angle, in fixed-point format.</returns>
 333        /// <remarks>
 334        /// - This function uses a Chebyshev-polynomial-based approximation to ensure high accuracy
 335        ///   while maintaining performance in fixed-point arithmetic.
 336        /// - The coefficients have been carefully tuned to minimize fixed-point truncation errors.
 337        /// - The error is less than 1 ULP (unit in the last place) at key reference points,
 338        ///   ensuring <c>Sin(π/4) = 0.707106781192124</c> exactly within Fixed64 precision.
 339        /// - The function automatically normalizes input values to the range [-π, π] for stability.
 340        /// </remarks>
 341        public static Fixed64 Sin(Fixed64 x)
 355342        {
 343            // Check for special cases
 413344            if (x == Fixed64.Zero) return Fixed64.Zero;   // sin(0) = 0
 379345            if (x == PiOver2) return Fixed64.One;         // sin(π/2) = 1
 217346            if (x == -PiOver2) return -Fixed64.One;       // sin(-π/2) = -1
 214347            if (x == PI) return Fixed64.Zero;             // sin(π) = 0
 236348            if (x == -PI) return Fixed64.Zero;            // sin(-π) = 0
 190349            if (x == TwoPI || x == -TwoPI) return Fixed64.Zero;  // sin(2π) = 0
 350
 351            // Normalize x to [-π, π]
 186352            x %= TwoPI;
 186353            if (x < -PI)
 89354                x += TwoPI;
 97355            else if (x > PI)
 1356                x -= TwoPI;
 357
 186358            bool flip = false;
 186359            if (x < Fixed64.Zero)
 4360            {
 4361                x = -x;
 4362                flip = true;
 4363            }
 364
 186365            if (x > PiOver2)
 90366                x = PI - x;
 367
 368            // Precompute x^2
 186369            Fixed64 x2 = x * x;
 370
 371            // Optimized Chebyshev Polynomial for Sin(x)
 186372            Fixed64 result = x * (Fixed64.One
 186373                - x2 * SIN_COEFF_3
 186374                + (x2 * x2) * SIN_COEFF_5
 186375                - (x2 * x2 * x2) * SIN_COEFF_7);
 376
 186377            return flip ? -result : result;
 355378        }
 379
 380        /// <summary>
 381        /// Computes the cosine of a given angle in radians using a sine-based identity transformation.
 382        /// </summary>
 383        /// <param name="x">The angle in radians.</param>
 384        /// <returns>The cosine of the given angle, in fixed-point format.</returns>
 385        /// <remarks>
 386        /// - Instead of directly approximating cosine, this function derives <c>cos(x)</c> using
 387        ///   the identity <c>cos(x) = sin(x + π/2)</c>. This ensures maximum accuracy.
 388        /// - The underlying sine function is computed using a highly optimized minimax polynomial approximation.
 389        /// - By leveraging this transformation, cosine achieves the same precision guarantees
 390        ///   as sine, including <c>Cos(π/4) = 0.707106781192124</c> exactly within Fixed64 precision.
 391        /// - The function automatically normalizes input values to the range [-π, π] for stability.
 392        /// </remarks>
 393        public static Fixed64 Cos(Fixed64 x)
 174394        {
 174395            long xl = x.m_rawValue;
 174396            long rawAngle = xl + (xl > 0 ? -PI.m_rawValue - PiOver2.m_rawValue : PiOver2.m_rawValue);
 174397            return Sin(Fixed64.FromRaw(rawAngle));
 174398        }
 399
 400        /// <summary>
 401        /// Calculates the cosine value corresponding to a given sine value, assuming the angle is in the first or
 402        /// second quadrant.
 403        /// </summary>
 404        /// <remarks>
 405        /// This method returns the principal (non-negative) value of the cosine.
 406        /// If the input is outside the valid range for sine values, the result may not be meaningful.
 407        /// </remarks>
 408        /// <param name="sin">The sine of the angle. Must be in the range [-1, 1].</param>
 409        /// <returns>The cosine of the angle, computed as the positive square root of (1 - sin²).</returns>
 410        public static Fixed64 SinToCos(Fixed64 sin)
 1411        {
 1412            return Sqrt(Fixed64.One - sin * sin);
 1413        }
 414
 415        /// <summary>
 416        /// Returns the tangent of x.
 417        /// </summary>
 418        /// <remarks>
 419        /// This function is not well-tested. It may be wildly inaccurate.
 420        /// </remarks>
 421        public static Fixed64 Tan(Fixed64 x)
 12422        {
 423            // Check for special cases
 13424            if (x == Fixed64.Zero) return Fixed64.Zero;
 15425            if (x == PiOver4) return Fixed64.One;
 8426            if (x == -PiOver4) return -Fixed64.One;
 427
 428            // Normalize x to [-π/2, π/2]
 6429            x %= PI;
 6430            if (x < -PiOver2)
 1431                x += PI;
 5432            else if (x > PiOver2)
 1433                x -= PI;
 434
 435            // Use continued fraction to approximate tan(x)
 6436            Fixed64 x2 = x * x;
 6437            Fixed64 numerator = x;
 6438            Fixed64 denominator = Fixed64.One;
 439
 440            // Iterate over the continued fraction terms
 6441            Fixed64 prevDenominator = denominator;
 6442            int start = x.Abs() > PiOver6 ? 19 : 13;
 114443            for (int i = start; i >= 1; i -= 2)
 51444            {
 51445                denominator = (Fixed64)i - (x2 / denominator);
 51446                if ((denominator - prevDenominator).Abs() < Fixed64.Epsilon)
 0447                    break;
 51448                prevDenominator = denominator;
 51449            }
 450
 6451            return numerator / denominator;
 12452        }
 453
 454        /// <summary>
 455        /// Returns the arc-sine of a fixed-point number x, which is the angle in radians
 456        /// whose sine is x, using a combination of a Taylor series expansion and trigonometric identities.
 457        ///
 458        /// For values of x near ±1, the identity asin(x) = π/2 - acos(x) is used for stability.
 459        /// For values of x near 0, a Taylor series expansion is used.
 460        /// </summary>
 461        /// <param name="x">The input value (sine) whose arcsine is to be computed. Should be in the range [-1, 1].</par
 462        /// <returns>The arc-sine of x in radians.</returns>
 463        /// <exception cref="ArithmeticException">Thrown if x is outside the domain [-1, 1].</exception>
 464        public static Fixed64 Asin(Fixed64 x)
 11465        {
 466            // Ensure x is within the domain [-1, 1]
 11467            if (x < -Fixed64.One || x > Fixed64.One)
 2468                throw new ArithmeticException("Input out of domain for Asin: " + x);
 469
 470            // Handle boundary cases for -1 and 1
 10471            if (x == Fixed64.One) return PiOver2;  // asin(1) = π/2
 9472            if (x == -Fixed64.One) return -PiOver2;  // asin(-1) = -π/2
 473
 474            // Special case handling for asin(0.5) -> π/6 and asin(-0.5) -> -π/6
 8475            if (x == Fixed64.Half) return PiOver6;
 7476            if (x == -Fixed64.Half) return -PiOver6;
 477
 478            // For values close to 0, use a Padé approximation for better precision
 5479            if (x.Abs() < Fixed64.Half)
 3480            {
 481                // Padé approximation of asin(x) for |x| < 0.5
 3482                Fixed64 xSquared = x * x;
 3483                Fixed64 numerator = x * (Fixed64.One + (xSquared * (PADE_A1 + (xSquared * PADE_A2))));
 3484                return numerator;
 485            }
 486
 487            // For values closer to ±1, use the identity: asin(x) = π/2 - acos(x) for stability
 2488            return x > Fixed64.Zero
 2489                ? PiOver2 - Acos(x)
 2490                : -PiOver2 + Acos(-x);
 9491        }
 492
 493        /// <summary>
 494        /// Returns the arccosine of the specified number x, calculated using a combination of the atan and sqrt functio
 495        /// </summary>
 496        /// <param name="x">The input value whose arccosine is to be computed. Should be in the range [-1, 1].</param>
 497        /// <returns>The arccosine of x in radians.</returns>
 498        /// <exception cref="ArgumentOutOfRangeException">Thrown if x is outside the domain [-1, 1].</exception>
 499        public static Fixed64 Acos(Fixed64 x)
 20500        {
 20501            if (x < -Fixed64.One || x > Fixed64.One)
 2502                throw new ArgumentOutOfRangeException(nameof(x), "Input out of domain for Acos: " + x);
 503
 504            // For values near 1 or -1, the result is directly known.
 20505            if (x == Fixed64.One) return Fixed64.Zero;      // acos(1) = 0
 17506            if (x == -Fixed64.One) return PI;       // acos(-1) = π
 21507            if (x == Fixed64.Zero) return PiOver2;  // acos(0) = π/2
 508
 509            // Compute using the relationship acos(x) = atan(sqrt(1 - x^2) / x) + π/2 when x is negative
 9510            var sqrtTerm = Sqrt(Fixed64.One - x * x);   // sqrt(1 - x^2)
 9511            var atanTerm = Atan(sqrtTerm / x);
 512
 9513            return x < Fixed64.Zero
 9514                    ? atanTerm + PI   // acos(-x) = atan(...) + π
 9515                    : atanTerm;               // Otherwise, return just atan(sqrt(...))
 18516        }
 517
 518        /// <summary>
 519        /// Returns the arctangent of the specified number, using a more accurate approximation for larger values.
 520        /// This function has at least 7 decimals of accuracy.
 521        /// </summary>
 522        public static Fixed64 Atan(Fixed64 z)
 78523        {
 85524            if (z == Fixed64.Zero) return Fixed64.Zero;
 85525            if (z == Fixed64.One) return PiOver4;
 63526            if (z == -Fixed64.One) return -PiOver4;
 527
 51528            bool neg = z < Fixed64.Zero;
 67529            if (neg) z = -z;
 530
 531            // Adjust series for z > 0.5 using the identity.
 532            Fixed64 adjustedResult;
 51533            if (z > Fixed64.Half)
 24534            {
 535                // Apply the identity: atan(z) = π/4 - atan((1 - z) / (1 + z))
 24536                Fixed64 transformedZ = (Fixed64.One - z) / (Fixed64.One + z);
 24537                adjustedResult = PiOver4 - Atan(transformedZ);
 24538            }
 539            else
 27540            {
 541                // Use extended Taylor series directly for better precision on small z.
 27542                Fixed64 zSq = z * z;
 543
 27544                Fixed64 result = z;
 27545                Fixed64 term = z;
 27546                int sign = -1;
 547
 184548                for (int i = 3; i < 15; i += 2)
 85549                {
 85550                    term *= zSq;
 85551                    Fixed64 nextTerm = term / i;
 85552                    if (nextTerm.Abs() < Fixed64.Epsilon)
 20553                        break;
 554
 65555                    result += nextTerm * sign;
 65556                    sign = -sign;
 65557                }
 558
 27559                adjustedResult = result;
 27560            }
 561
 51562            return neg ? -adjustedResult : adjustedResult;
 78563        }
 564
 565        /// <summary>
 566        /// Computes the angle whose tangent is the quotient of two specified numbers.
 567        /// </summary>
 568        /// <remarks>
 569        /// Uses a fixed-point arithmetic approximation for the arc tangent function, which is more efficient than using
 570        /// especially on systems where floating-point operations are expensive.
 571        /// </remarks>
 572        /// <param name="y">The y-coordinate of the point to which the angle is measured.</param>
 573        /// <param name="x">The x-coordinate of the point to which the angle is measured.</param>
 574        /// <returns>An angle, θ, measured in radians, such that -π ≤ θ ≤ π, and tan(θ) = y / x,
 575        /// taking into account the quadrants of the inputs to determine the sign of the result.</returns>
 576        public static Fixed64 Atan2(Fixed64 y, Fixed64 x)
 27577        {
 27578            if (x == Fixed64.Zero)
 3579            {
 3580                if (y > Fixed64.Zero)
 1581                    return PiOver2;
 2582                if (y == Fixed64.Zero)
 1583                    return Fixed64.Zero;
 1584                return -PiOver2;
 585            }
 586
 24587            Fixed64 atan = Atan(y / x);
 588
 589            // Adjust based on the quadrant
 24590            if (x < Fixed64.Zero)
 8591            {
 8592                if (y >= Fixed64.Zero)
 4593                {
 594                    // Second quadrant
 4595                    return atan + PI;
 596                }
 597                else
 4598                {
 599                    // Third quadrant
 4600                    return atan - PI;
 601                }
 602            }
 603
 604            // First or fourth quadrant
 16605            return atan;
 27606        }
 607
 608        #endregion
 609    }
 610}

Methods/Properties

.cctor()
CopySign(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
Clamp01(FixedMathSharp.Fixed64)
Clamp(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
Clamp(T,T,T)
ClampOne(FixedMathSharp.Fixed64)
Abs(FixedMathSharp.Fixed64)
Ceiling(FixedMathSharp.Fixed64)
Floor(FixedMathSharp.Fixed64)
Max(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
Min(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
Round(FixedMathSharp.Fixed64,System.MidpointRounding)
RoundToPrecision(FixedMathSharp.Fixed64,System.Int32,System.MidpointRounding)
Squared(FixedMathSharp.Fixed64)
FastAdd(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
FastSub(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
FastMul(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
FastMod(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
SmoothStep(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
CubicInterpolate(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
LinearInterpolate(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
MoveTowards(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
AddOverflowHelper(System.Int64,System.Int64,System.Boolean&)
.cctor()
Pow(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
Pow2(FixedMathSharp.Fixed64)
Log2(FixedMathSharp.Fixed64)
Ln(FixedMathSharp.Fixed64)
Sqrt(FixedMathSharp.Fixed64)
RadToDeg(FixedMathSharp.Fixed64)
DegToRad(FixedMathSharp.Fixed64)
Sin(FixedMathSharp.Fixed64)
Cos(FixedMathSharp.Fixed64)
SinToCos(FixedMathSharp.Fixed64)
Tan(FixedMathSharp.Fixed64)
Asin(FixedMathSharp.Fixed64)
Acos(FixedMathSharp.Fixed64)
Atan(FixedMathSharp.Fixed64)
Atan2(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)