< Summary

Line coverage
100%
Covered lines: 242
Uncovered lines: 0
Coverable lines: 242
Total lines: 1143
Line coverage: 100%
Branch coverage
100%
Covered branches: 108
Total branches: 108
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: op_Explicit(...)100%44100%
File 1: op_Explicit(...)100%22100%
File 1: op_Explicit(...)100%11100%
File 1: op_Explicit(...)100%22100%
File 1: op_Explicit(...)100%11100%
File 1: op_Explicit(...)100%11100%
File 1: op_Explicit(...)100%11100%
File 1: op_Explicit(...)100%11100%
File 1: op_Explicit(...)100%11100%
File 1: op_Explicit(...)100%11100%
File 1: ToString()100%11100%
File 1: ToString(...)100%11100%
File 1: ToString(...)100%22100%
File 1: TryFormat(...)100%11100%
File 1: Parse(...)100%11100%
File 1: Parse(...)100%66100%
File 1: ParseRaw(...)100%44100%
File 1: TryParse(...)100%11100%
File 1: TryParse(...)100%66100%
File 1: TryParseRaw(...)100%44100%
File 1: FromRaw(...)100%11100%
File 1: ToInt(...)100%11100%
File 1: FromDouble(...)100%88100%
File 1: FromDecimal(...)100%44100%
File 1: FromFraction(...)100%11100%
File 1: ToDouble(...)100%11100%
File 1: ToFloat(...)100%11100%
File 1: ToDecimal(...)100%11100%
File 2: get_MaxValue()100%11100%
File 2: get_MinValue()100%11100%
File 2: get_One()100%11100%
File 2: get_NegOne()100%11100%
File 2: get_Two()100%11100%
File 2: get_Three()100%11100%
File 2: get_Half()100%11100%
File 2: get_Quarter()100%11100%
File 2: get_Eighth()100%11100%
File 2: get_Zero()100%11100%
File 2: get_Pi()100%11100%
File 2: get_TwoPi()100%11100%
File 2: get_HalfPi()100%11100%
File 2: get_PiOver3()100%11100%
File 2: get_PiOver4()100%11100%
File 2: get_PiOver6()100%11100%
File 2: get_InvertedPi()100%11100%
File 2: get_OneEighty()100%11100%
File 2: get_Deg2Rad()100%11100%
File 2: get_Rad2Deg()100%11100%
File 2: get_Ln2()100%11100%
File 2: get_Log2Max()100%11100%
File 2: get_Log2Min()100%11100%
File 2: get_PadeA1()100%11100%
File 2: get_PadeA2()100%11100%
File 2: get_SinCoeff3()100%11100%
File 2: get_SinCoeff5()100%11100%
File 2: get_SinCoeff7()100%11100%
File 2: get_MinIncrement()100%11100%
File 2: get_Epsilon()100%11100%
File 2: .ctor(...)100%11100%
File 2: .ctor(...)100%11100%
File 2: Offset(...)100%11100%
File 2: ToRawString()100%11100%
File 3: Equals(...)100%22100%
File 3: Equals(...)100%11100%
File 3: Equals(...)100%11100%
File 3: GetHashCode()100%11100%
File 3: GetHashCode(...)100%11100%
File 3: CompareTo(...)100%11100%
File 4: op_Addition(...)100%44100%
File 4: op_Addition(...)100%11100%
File 4: op_Addition(...)100%11100%
File 4: op_Subtraction(...)100%44100%
File 4: op_Subtraction(...)100%11100%
File 4: op_Subtraction(...)100%11100%
File 4: op_Multiply(...)100%1212100%
File 4: AbsToUInt64(...)100%22100%
File 4: Multiply64To128(...)100%11100%
File 4: ShiftRightRoundedToEven(...)100%66100%
File 4: op_Multiply(...)100%11100%
File 4: op_Multiply(...)100%11100%
File 4: op_Division(...)100%2424100%
File 4: op_Division(...)100%11100%
File 4: op_Division(...)100%11100%
File 4: op_Modulus(...)100%44100%
File 4: op_Modulus(...)100%11100%
File 4: op_Modulus(...)100%11100%
File 4: op_UnaryNegation(...)100%22100%
File 4: op_Increment(...)100%11100%
File 4: op_Decrement(...)100%11100%
File 4: op_LeftShift(...)100%11100%
File 4: op_RightShift(...)100%11100%
File 4: op_GreaterThan(...)100%11100%
File 4: op_GreaterThan(...)100%11100%
File 4: op_GreaterThan(...)100%11100%
File 4: op_LessThan(...)100%11100%
File 4: op_LessThan(...)100%11100%
File 4: op_LessThan(...)100%11100%
File 4: op_GreaterThanOrEqual(...)100%11100%
File 4: op_GreaterThanOrEqual(...)100%11100%
File 4: op_GreaterThanOrEqual(...)100%11100%
File 4: op_LessThanOrEqual(...)100%11100%
File 4: op_LessThanOrEqual(...)100%11100%
File 4: op_LessThanOrEqual(...)100%11100%
File 4: op_Equality(...)100%11100%
File 4: op_Equality(...)100%11100%
File 4: op_Equality(...)100%11100%
File 4: op_Inequality(...)100%11100%
File 4: op_Inequality(...)100%11100%
File 4: op_Inequality(...)100%11100%
File 5: CountLeadingZeroes(...)100%44100%
File 5: Sign(...)100%22100%
File 5: IsInteger(...)100%11100%

File(s)

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Numerics/Scalars/Fixed64.Conversions.cs

#LineLine coverage
 1//=======================================================================
 2// Fixed64.Conversions.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024–present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using System;
 9using System.Globalization;
 10using System.Runtime.CompilerServices;
 11
 12namespace FixedMathSharp;
 13
 14public partial struct Fixed64
 15{
 16    #region Explicit and Implicit Conversions
 17
 18    /// <summary>
 19    /// Converts a 64-bit signed integer to a Fixed64 value using explicit casting.
 20    /// </summary>
 21    /// <remarks>
 22    /// The conversion interprets the input value as the integer part of the fixed-point number and saturates
 23    /// to <see cref="MinValue"/> or <see cref="MaxValue"/> when the integer cannot fit in Q32.32 value space.
 24    /// Use <see cref="FromRaw(long)"/> when a raw fixed-point payload is required.
 25    /// </remarks>
 26    /// <param name="value">The 64-bit signed integer to convert to a Fixed64 value.</param>
 27    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 28    public static explicit operator Fixed64(long value)
 29    {
 630        if (value > int.MaxValue)
 231            return MaxValue;
 32
 433        if (value < int.MinValue)
 234            return MinValue;
 35
 236        return FromRaw(value << FixedMath.SHIFT_AMOUNT_I);
 37    }
 38
 39    /// <summary>
 40    /// Converts a Fixed64 value to a 64-bit signed integer by discarding the fractional part.
 41    /// </summary>
 42    /// <remarks>
 43    /// The conversion truncates any fractional component.
 44    /// The result represents the integer portion of the Fixed64 value.</remarks>
 45    /// <param name="value">The Fixed64 value to convert to a long integer.</param>
 46    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 47    public static explicit operator long(Fixed64 value)
 48    {
 649        return value > Zero
 650            ? (long)(FixedMath.Floor(value).m_rawValue >> FixedMath.SHIFT_AMOUNT_I)
 651            : (long)(FixedMath.Ceil(value).m_rawValue >> FixedMath.SHIFT_AMOUNT_I);
 52    }
 53
 54    /// <summary>
 55    /// Defines an explicit conversion from a 32-bit signed integer to a Fixed64 value.
 56    /// </summary>
 57    /// <param name="value">The 32-bit signed integer to convert to a Fixed64 value.</param>
 58    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 59    public static explicit operator Fixed64(int value)
 60    {
 690861        return new Fixed64(value);
 62    }
 63
 64    /// <summary>
 65    /// Converts a Fixed64 value to a 32-bit signed integer by discarding the fractional part.
 66    /// </summary>
 67    /// <remarks>
 68    /// The conversion truncates any fractional component.
 69    /// The result is equivalent to rounding toward zero.
 70    /// </remarks>
 71    /// <param name="value">The Fixed64 value to convert to an integer.</param>
 72    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 73    public static explicit operator int(Fixed64 value)
 74    {
 1875        return value > Zero
 1876            ? (int)(FixedMath.Floor(value).m_rawValue >> FixedMath.SHIFT_AMOUNT_I)
 1877            : (int)(FixedMath.Ceil(value).m_rawValue >> FixedMath.SHIFT_AMOUNT_I);
 78    }
 79
 80    /// <summary>
 81    /// Defines an explicit conversion from a single-precision floating-point value to a Fixed64 instance.
 82    /// </summary>
 83    /// <param name="value">The single-precision floating-point value to convert to Fixed64.</param>
 84    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 85    public static explicit operator Fixed64(float value)
 86    {
 587        return FromDouble(value);
 88    }
 89
 90    /// <summary>
 91    /// Converts a Fixed64 value to its equivalent single-precision floating-point representation.
 92    /// </summary>
 93    /// <remarks>
 94    /// This conversion may result in a loss of precision if the Fixed64 value cannot be exactly  represented as a float
 95    /// </remarks>
 96    /// <param name="value">The Fixed64 value to convert to a float.</param>
 97    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 98    public static explicit operator float(Fixed64 value)
 99    {
 1100        return value.m_rawValue * FixedMath.SCALE_FACTOR_F;
 101    }
 102
 103    /// <summary>
 104    /// Defines an explicit conversion from a double-precision floating-point number to a Fixed64 value.
 105    /// </summary>
 106    /// <remarks>
 107    /// This conversion may result in loss of precision if the double value cannot be exactly represented as a Fixed64.
 108    /// </remarks>
 109    /// <param name="value">The double-precision floating-point number to convert to a Fixed64 value.</param>
 110    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 111    public static explicit operator Fixed64(double value)
 112    {
 3113        return FromDouble(value);
 114    }
 115
 116    /// <summary>
 117    /// Converts a Fixed64 value to its equivalent double-precision floating-point representation.
 118    /// </summary>
 119    /// <remarks>
 120    /// This conversion may result in a loss of precision if the Fixed64 value cannot be exactly represented as a double
 121    /// </remarks>
 122    /// <param name="value">The Fixed64 value to convert to a double.</param>
 123    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 124    public static explicit operator double(Fixed64 value)
 125    {
 3224126        return value.m_rawValue * FixedMath.SCALE_FACTOR_D;
 127    }
 128
 129    /// <summary>
 130    /// Defines an explicit conversion from a decimal value to a Fixed64 instance.
 131    /// </summary>
 132    /// <param name="value">The decimal value to convert to a Fixed64 instance.</param>
 133    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 134    public static explicit operator Fixed64(decimal value)
 135    {
 2136        return FromDecimal(value);
 137    }
 138
 139    /// <summary>
 140    /// Converts a Fixed64 value to its decimal representation.
 141    /// </summary>
 142    /// <remarks>
 143    /// This operator provides an explicit conversion from Fixed64 to decimal, preserving the numeric value as closely a
 144    /// Use this conversion when precise decimal arithmetic is required.
 145    /// </remarks>
 146    /// <param name="value">The Fixed64 value to convert to decimal.</param>
 147    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 148    public static explicit operator decimal(Fixed64 value)
 149    {
 1150        return value.m_rawValue * FixedMath.SCALE_FACTOR_M;
 151    }
 152
 153    #endregion
 154    #region Conversion
 155
 156    /// <summary>
 157    /// Returns the string representation of this Fixed64 instance.
 158    /// </summary>
 159    /// <remarks>
 160    /// Up to 10 decimal places.
 161    /// </remarks>
 162    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 160163    public override string ToString() => ((double)this).ToString(CultureInfo.InvariantCulture);
 164
 165    /// <summary>
 166    /// Converts the numeric value of the current Fixed64 object to its equivalent string representation.
 167    /// </summary>
 168    /// <param name="format">A format specification that governs how the current Fixed64 object is converted.</param>
 169    /// <returns>The string representation of the value of the current Fixed64 object.</returns>
 170    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1171    public string ToString(string? format) => ToString(format, CultureInfo.InvariantCulture);
 172
 173    /// <summary>
 174    /// Converts the numeric value of the current Fixed64 object to its equivalent string representation.
 175    /// </summary>
 176    /// <param name="format">A format specification that governs how the current Fixed64 object is converted.</param>
 177    /// <param name="formatProvider">The provider to use for culture-specific formatting information.</param>
 178    /// <returns>The string representation of the value of the current Fixed64 object.</returns>
 179    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 180    public string ToString(string? format, IFormatProvider? formatProvider) =>
 3181        ((double)this).ToString(format, formatProvider ?? CultureInfo.InvariantCulture);
 182
 183    /// <summary>
 184    /// Formats the value into the provided destination buffer.
 185    /// </summary>
 186    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 187    public bool TryFormat(
 188        Span<char> destination,
 189        out int charsWritten,
 190        ReadOnlySpan<char> format,
 191        IFormatProvider? provider)
 192    {
 229193        return FixedDiagnosticsFormatter.TryFormat(this, destination, out charsWritten, format, provider);
 194    }
 195
 196    /// <summary>
 197    /// Parses a decimal string to create a Fixed64 instance.
 198    /// </summary>
 199    /// <param name="s">The string representation of the Fixed64 value.</param>
 200    /// <returns>The parsed Fixed64 value.</returns>
 6201    public static Fixed64 Parse(string s) => Parse(s, CultureInfo.InvariantCulture);
 202
 203    /// <summary>
 204    /// Parses a decimal string to create a Fixed64 instance.
 205    /// </summary>
 206    /// <param name="s">The string representation of the Fixed64 value.</param>
 207    /// <param name="formatProvider">The provider to use for culture-specific parsing information.</param>
 208    /// <returns>The parsed Fixed64 value.</returns>
 209    public static Fixed64 Parse(string s, IFormatProvider? formatProvider)
 210    {
 9211        if (s is null)
 1212            throw new ArgumentNullException(nameof(s));
 213
 8214        if (!decimal.TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, formatProvider ?? CultureInfo.Invaria
 3215            throw new FormatException($"Invalid format: {s}");
 216
 5217        return FromDecimal(value);
 218    }
 219
 220    /// <summary>
 221    /// Parses a raw Q32.32 payload string to create a Fixed64 instance.
 222    /// </summary>
 223    /// <param name="s">The raw fixed-point payload.</param>
 224    /// <returns>The parsed Fixed64 value.</returns>
 225    public static Fixed64 ParseRaw(string s)
 226    {
 5227        if (s is null)
 1228            throw new ArgumentNullException(nameof(s));
 229
 4230        if (!long.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out long rawValue))
 2231            throw new FormatException($"Invalid format: {s}");
 232
 2233        return FromRaw(rawValue);
 234    }
 235
 236    /// <summary>
 237    /// Tries to parse a decimal string to create a Fixed64 instance.
 238    /// </summary>
 239    /// <param name="s">The string representation of the Fixed64 value.</param>
 240    /// <param name="result">The parsed Fixed64 value.</param>
 241    /// <returns>True if parsing succeeded; otherwise, false.</returns>
 5242    public static bool TryParse(string? s, out Fixed64 result) => TryParse(s, CultureInfo.InvariantCulture, out result);
 243
 244    /// <summary>
 245    /// Tries to parse a decimal string to create a Fixed64 instance.
 246    /// </summary>
 247    /// <param name="s">The string representation of the Fixed64 value.</param>
 248    /// <param name="formatProvider">The provider to use for culture-specific parsing information.</param>
 249    /// <param name="result">The parsed Fixed64 value.</param>
 250    /// <returns>True if parsing succeeded; otherwise, false.</returns>
 251    public static bool TryParse(string? s, IFormatProvider? formatProvider, out Fixed64 result)
 252    {
 7253        result = Zero;
 7254        if (string.IsNullOrEmpty(s))
 1255            return false;
 256
 6257        if (!decimal.TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, formatProvider ?? CultureInfo.Invaria
 2258            return false;
 259
 260        try
 261        {
 4262            result = FromDecimal(value);
 3263            return true;
 264        }
 1265        catch (OverflowException)
 266        {
 1267            return false;
 268        }
 4269    }
 270
 271    /// <summary>
 272    /// Tries to parse a raw Q32.32 payload string to create a Fixed64 instance.
 273    /// </summary>
 274    /// <param name="s">The raw fixed-point payload.</param>
 275    /// <param name="result">The parsed Fixed64 value.</param>
 276    /// <returns>True if parsing succeeded; otherwise, false.</returns>
 277    public static bool TryParseRaw(string? s, out Fixed64 result)
 278    {
 4279        result = Zero;
 4280        if (string.IsNullOrEmpty(s))
 1281            return false;
 282
 3283        if (!long.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out long rawValue))
 1284            return false;
 285
 2286        result = FromRaw(rawValue);
 2287        return true;
 288    }
 289
 290    /// <summary>
 291    /// Creates a Fixed64 from a raw long value.
 292    /// </summary>
 293    /// <remarks>
 294    /// This method interprets <paramref name="rawValue"/> as an already-scaled Q32.32 payload.
 295    /// Use the integer constructors or explicit numeric conversions for user-facing integer values.
 296    /// </remarks>
 297    /// <param name="rawValue">The raw fixed-point payload.</param>
 298    /// <returns>A Fixed64 representing the raw value.</returns>
 299    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 22129300    public static Fixed64 FromRaw(long rawValue) => new(rawValue);
 301
 302
 303    /// <summary>
 304    /// Converts a Fixed64's RawValue (Int64) into an integer by discarding the fractional part.
 305    /// </summary>
 306    /// <param name="value">The Fixed64 value to convert.</param>
 307    /// <returns>The integer representation of the Fixed64 value.</returns>
 308    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1309    public static int ToInt(Fixed64 value) => (int)(value.m_rawValue >> FixedMath.SHIFT_AMOUNT_I);
 310
 311    /// <summary>
 312    /// Constructs a Fixed64 from a double-precision floating-point value.
 313    /// </summary>
 314    /// <remarks>
 315    /// The value is multiplied by the scaling factor (2^SHIFT_AMOUNT) and rounded to the nearest
 316    /// raw integer using midpoint-to-even rounding. Non-finite values throw an
 317    /// <see cref="ArgumentOutOfRangeException"/>. Finite values outside the Q32.32 range throw an
 318    /// <see cref="OverflowException"/>.
 319    /// </remarks>
 320    /// <param name="value">Double value to convert.</param>
 321    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 322    public static Fixed64 FromDouble(double value)
 323    {
 1137324        if (double.IsNaN(value) || double.IsInfinity(value))
 10325            throw new ArgumentOutOfRangeException(nameof(value), value, "Value must be finite.");
 326
 1127327        double rawValue = Math.Round(value * FixedMath.ONE_L, MidpointRounding.ToEven);
 1127328        if (rawValue < FixedMath.MIN_RAW_D || rawValue >= FixedMath.MAX_RAW_EXCLUSIVE_D)
 7329            throw new OverflowException($"{value} is outside the representable range of {nameof(Fixed64)}.");
 330
 1120331        return FromRaw((long)rawValue);
 332    }
 333
 334    /// <summary>
 335    /// Constructs a Fixed64 from a decimal value.
 336    /// </summary>
 337    /// <remarks>
 338    /// The value is multiplied by the scaling factor (2^SHIFT_AMOUNT) and rounded to the nearest
 339    /// raw integer using midpoint-to-even rounding. Values outside the Q32.32 range throw an
 340    /// <see cref="OverflowException"/>.
 341    /// </remarks>
 342    /// <param name="value">Decimal value to convert.</param>
 343    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 344    public static Fixed64 FromDecimal(decimal value)
 345    {
 17346        decimal rawValue = decimal.Round(value * FixedMath.ONE_L, 0, MidpointRounding.ToEven);
 347
 17348        if (rawValue < long.MinValue || rawValue > long.MaxValue)
 4349            throw new OverflowException($"{value} is outside the representable range of {nameof(Fixed64)}.");
 350
 13351        return FromRaw((long)rawValue);
 352    }
 353
 354    /// <summary>
 355    /// Creates a Fixed64 from a fractional number.
 356    /// </summary>
 357    /// <remarks>
 358    /// The quotient is converted through <see cref="FromDouble(double)"/>, so non-finite results
 359    /// throw <see cref="ArgumentOutOfRangeException"/> and finite results outside the Q32.32 range
 360    /// throw <see cref="OverflowException"/>.
 361    /// </remarks>
 362    /// <param name="numerator">The numerator of the fraction.</param>
 363    /// <param name="denominator">The denominator of the fraction.</param>
 364    /// <returns>A Fixed64 representing the fraction.</returns>
 365    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 3366    public static Fixed64 FromFraction(double numerator, double denominator) => FromDouble(numerator / denominator);
 367
 368    /// <summary>
 369    /// Converts a Fixed64s RawValue (Int64) into a double
 370    /// </summary>
 371    /// <param name="f1"></param>
 372    /// <returns></returns>
 1373    public static double ToDouble(long f1) => f1 * FixedMath.SCALE_FACTOR_D;
 374
 375    /// <summary>
 376    /// Converts a Fixed64s RawValue (Int64) into a float
 377    /// </summary>
 378    /// <param name="f1"></param>
 379    /// <returns></returns>
 1380    public static float ToFloat(long f1) => f1 * FixedMath.SCALE_FACTOR_F;
 381
 382    /// <summary>
 383    /// Converts a Fixed64s RawValue (Int64) into a decimal
 384    /// </summary>
 385    /// <param name="f1"></param>
 386    /// <returns></returns>
 1387    public static decimal ToDecimal(long f1) => f1 * FixedMath.SCALE_FACTOR_M;
 388
 389    #endregion
 390}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Numerics/Scalars/Fixed64.cs

#LineLine coverage
 1//=======================================================================
 2// Fixed64.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024–present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using MemoryPack;
 9using System;
 10using System.Collections.Generic;
 11using System.Globalization;
 12using System.Runtime.CompilerServices;
 13using System.Text.Json.Serialization;
 14
 15namespace FixedMathSharp;
 16
 17/// <summary>
 18/// Represents a Q(64-SHIFT_AMOUNT).SHIFT_AMOUNT fixed-point number.
 19/// Provides high precision for fixed-point arithmetic where SHIFT_AMOUNT bits
 20/// are used for the fractional part and (64 - SHIFT_AMOUNT) bits for the integer part.
 21/// The precision is determined by SHIFT_AMOUNT, which defines the resolution of fractional values.
 22/// </summary>
 23[Serializable]
 24[MemoryPackable]
 25public partial struct Fixed64 : IEquatable<Fixed64>, IComparable<Fixed64>, IEqualityComparer<Fixed64>, IFormattable
 26#if NET8_0_OR_GREATER
 27    , ISpanFormattable
 28#endif
 29{
 30    #region Static Fields
 31
 32    /// <inheritdoc cref="FixedMath.MAX_VALUE_L" />
 7033    public static Fixed64 MaxValue => new(FixedMath.MAX_VALUE_L);
 34    /// <inheritdoc cref="FixedMath.MIN_VALUE_L" />
 2635    public static Fixed64 MinValue => new(FixedMath.MIN_VALUE_L);
 36
 37    /// <inheritdoc cref="FixedMath.ONE_L" />
 1402638    public static Fixed64 One => new(FixedMath.ONE_L);
 39    /// <summary>
 40    /// Represents the value -1 shifted left by the number of bits specified by SHIFT_AMOUNT_I.
 41    /// </summary>
 142    public static Fixed64 NegOne => -One;
 43    /// <summary>
 44    /// Represents the value 2 shifted left by the number of bits specified by SHIFT_AMOUNT_I.
 45    /// </summary>
 120246    public static Fixed64 Two => One * 2;
 47    /// <summary>
 48    /// Represents the value 3 shifted left by the number of bits specified by SHIFT_AMOUNT_I.
 49    /// </summary>
 2750    public static Fixed64 Three => One * 3;
 51    /// <summary>
 52    /// Represents the value 0.5 shifted left by the number of bits specified by SHIFT_AMOUNT_I.
 53    /// </summary>
 59354    public static Fixed64 Half => One / 2;
 55    /// <summary>
 56    /// Represents the value 0.25 shifted left by the number of bits specified by SHIFT_AMOUNT_I.
 57    /// </summary>
 158    public static Fixed64 Quarter => One / 4;
 59    /// <summary>
 60    /// Represents the value 0.125 shifted left by the number of bits specified by SHIFT_AMOUNT_I.
 61    /// </summary>
 162    public static Fixed64 Eighth => One / 8;
 63    /// <summary>
 64    /// Represents the value 0 as a fixed-point number.
 65    /// </summary>
 1788766    public static Fixed64 Zero => new(0);
 67
 68    /// <inheritdoc cref="FixedMath.PI_LONG" />
 443869    public static Fixed64 Pi => new(FixedMath.PI_LONG);
 70    /// <summary>
 71    /// Represents the mathematical constant 2Ï€ as a fixed-point value.
 72    /// </summary>
 73    /// <remarks>This value is commonly used to represent a full rotation in radians.</remarks>
 92374    public static Fixed64 TwoPi => Pi * Two;
 75    /// <summary>
 76    /// Represents the mathematical constant Ï€ divided by 2 as a fixed-point value.
 77    /// </summary>
 78    /// <remarks>This value is used where Ï€/2 is required.</remarks>
 144579    public static Fixed64 HalfPi => Pi / new Fixed64(2);
 80    /// <summary>
 81    /// Represents the mathematical constant Ï€ divided by 3 as a fixed-point value.
 82    /// </summary>
 183    public static Fixed64 PiOver3 => Pi / new Fixed64(3);
 84    /// <summary>
 85    /// Represents the mathematical constant Ï€ divided by 4 as a fixed-point value.
 86    /// </summary>
 12987    public static Fixed64 PiOver4 => Pi / new Fixed64(4);
 88    /// <summary>
 89    /// Represents the mathematical constant Ï€ divided by 6 as a fixed-point value.
 90    /// </summary>
 691    public static Fixed64 PiOver6 => Pi / new Fixed64(6);
 92    /// <summary>
 93    /// Represents the multiplicative inverse of the mathematical constant Ï€ (pi) as a fixed-point value.
 94    /// </summary>
 195    public static Fixed64 InvertedPi => One / Pi;
 96    /// <summary>
 97    /// Represents the fixed-point value for 180.
 98    /// </summary>
 16399    public static Fixed64 OneEighty => new(180);
 100    /// <summary>
 101    /// Degrees to radians conversion factor (Ï€ / 180)
 102    /// </summary>
 10103    public static Fixed64 Deg2Rad => Pi / OneEighty;
 104    /// <summary>
 105    /// Radians to degrees conversion factor (180 / Ï€)
 106    /// </summary>
 1107    public static Fixed64 Rad2Deg => OneEighty / Pi;
 108
 109    /// <inheritdoc cref="FixedMath.LN2_LONG" />
 11110    public static Fixed64 Ln2 => new(FixedMath.LN2_LONG);
 111    /// <summary>
 112    /// Represents the maximum value for the base-2 logarithm that can be represented by a Fixed64 instance.
 113    /// </summary>
 114    /// <remarks>
 115    /// This constant is useful when performing logarithmic calculations to ensure results
 116    /// do not exceed the representable range of the Fixed64 type.
 117    /// </remarks>
 2118    public static Fixed64 Log2Max => new(63L * FixedMath.ONE_L);
 119    /// <summary>
 120    /// Represents the minimum base-2 logarithm value supported by the Fixed64 type.
 121    /// </summary>
 122    /// <remarks>
 123    /// This constant can be used as a lower bound when performing logarithmic calculations
 124    /// with Fixed64 values to prevent underflow or invalid results.
 125    /// </remarks>
 1126    public static Fixed64 Log2Min => new(-64L * FixedMath.ONE_L);
 127
 5128    internal static Fixed64 PadeA1 => new(FixedMath.PADE_A1_LONG);
 5129    internal static Fixed64 PadeA2 => new(FixedMath.PADE_A2_LONG);
 130
 296131    internal static Fixed64 SinCoeff3 => new(FixedMath.SIN_COEFF_3_LONG); // 1/3!
 296132    internal static Fixed64 SinCoeff5 => new(FixedMath.SIN_COEFF_5_LONG); // 1/5!
 296133    internal static Fixed64 SinCoeff7 => new(FixedMath.SIN_COEFF_7_LONG); // 1/7!
 134
 135    /// <inheritdoc cref="FixedMath.MIN_INCREMENT_L" />
 22136    public static Fixed64 MinIncrement => new(FixedMath.MIN_INCREMENT_L);
 137    /// <inheritdoc cref="FixedMath.DEFAULT_TOLERANCE_L" />
 2604138    public static Fixed64 Epsilon => new(FixedMath.DEFAULT_TOLERANCE_L);
 139
 140    #endregion
 141    #region Fields
 142
 143    /// <summary>
 144    /// The underlying raw long value representing the fixed-point number.
 145    /// </summary>
 146    [JsonInclude]
 147    [MemoryPackInclude]
 148    public long m_rawValue;
 149
 150    #endregion
 151    #region Constructors
 152
 153    /// <summary>
 154    /// Internal constructor for a Fixed64 from a raw long value.
 155    /// </summary>
 156    /// <param name="m_rawValue">Raw long value representing the fixed-point number.</param>
 157    [JsonConstructor]
 179758158    internal Fixed64(long m_rawValue) => this.m_rawValue = m_rawValue;
 159
 160    /// <summary>
 161    /// Constructs a Fixed64 from an integer, with the fractional part set to zero.
 162    /// </summary>
 163    /// <param name="value">Integer value to convert to </param>
 58704164    public Fixed64(int value) : this((long)value << FixedMath.SHIFT_AMOUNT_I) { }
 165
 166    #endregion
 167    #region Methods (Instance)
 168
 169    /// <summary>
 170    /// Offsets the current Fixed64 by an integer value.
 171    /// </summary>
 172    /// <param name="x">The integer value to add.</param>
 173    /// <remarks>
 174    /// Unlike the <see cref="operator +(Fixed64, int)"/>, this method performs a simple addition of the integer value
 175    /// to the raw fixed-point representation without any overflow checks or saturation behavior.
 176    /// </remarks>
 177    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 178    public Fixed64 Offset(int x)
 179    {
 1180        return new Fixed64(m_rawValue + ((long)x << FixedMath.SHIFT_AMOUNT_I));
 181    }
 182
 183    /// <summary>
 184    /// Returns the raw value as a string.
 185    /// </summary>
 186    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1187    public string ToRawString() => m_rawValue.ToString(CultureInfo.InvariantCulture);
 188
 189    #endregion
 190}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Numerics/Scalars/Fixed64.Equality.cs

#LineLine coverage
 1//=======================================================================
 2// Fixed64.Equality.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024–present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using System.Runtime.CompilerServices;
 9
 10namespace FixedMathSharp;
 11
 12public partial struct Fixed64
 13{
 14    #region Equality, HashCode, Comparable Overrides
 15
 16    /// <summary>
 17    /// Determines whether this instance equals another object.
 18    /// </summary>
 19    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 3820    public override bool Equals(object? obj) => obj is Fixed64 other && Equals(other);
 21
 22    /// <inheritdoc/>
 23    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1255724    public bool Equals(Fixed64 other) => m_rawValue == other.m_rawValue;
 25
 26    /// <inheritdoc/>
 27    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 528    public bool Equals(Fixed64 x, Fixed64 y) => x.Equals(y);
 29
 30    /// <inheritdoc/>
 31    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 16932    public override int GetHashCode() => m_rawValue.GetHashCode();
 33
 34    /// <inheritdoc/>
 35    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 136    public int GetHashCode(Fixed64 obj) => obj.GetHashCode();
 37
 38    /// <summary>
 39    /// Compares this instance to another
 40    /// </summary>
 41    /// <param name="other">The Fixed64 to compare with.</param>
 42    /// <returns>-1 if less than, 0 if equal, 1 if greater than other.</returns>
 4143    public int CompareTo(Fixed64 other) => m_rawValue.CompareTo(other.m_rawValue);
 44
 45    #endregion
 46}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Numerics/Scalars/Fixed64.Operators.cs

#LineLine coverage
 1//=======================================================================
 2// Fixed64.Operators.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024–present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using System;
 9using System.Runtime.CompilerServices;
 10
 11namespace FixedMathSharp;
 12
 13public partial struct Fixed64
 14{
 15    #region Arithmetic Operators
 16
 17    /// <summary>
 18    /// Adds two Fixed64 numbers, with saturating behavior in case of overflow.
 19    /// </summary>
 20    public static Fixed64 operator +(Fixed64 x, Fixed64 y)
 21    {
 2344322        long xl = x.m_rawValue;
 2344323        long yl = y.m_rawValue;
 2344324        long sum = xl + yl;
 25        // Check for overflow, if signs of operands are equal and signs of sum and x are different
 2344326        if (((~(xl ^ yl) & (xl ^ sum)) & FixedMath.MIN_VALUE_L) != 0)
 227            sum = xl > 0 ? FixedMath.MAX_VALUE_L : FixedMath.MIN_VALUE_L;
 2344328        return new Fixed64(sum);
 29    }
 30
 31    /// <summary>
 32    /// Adds an int to a Fixed64, with saturating behavior in case of overflow.
 33    /// </summary>
 34    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 2435    public static Fixed64 operator +(Fixed64 x, int y) => x + new Fixed64((long)y << FixedMath.SHIFT_AMOUNT_I);
 36
 37    /// <inheritdoc cref="operator +(Fixed64, int)" />
 38    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 139    public static Fixed64 operator +(int x, Fixed64 y) => y + x;
 40
 41    /// <summary>
 42    /// Subtracts one Fixed64 number from another, with saturating behavior in case of overflow.
 43    /// </summary>
 44    public static Fixed64 operator -(Fixed64 x, Fixed64 y)
 45    {
 1593746        long xl = x.m_rawValue;
 1593747        long yl = y.m_rawValue;
 1593748        long diff = xl - yl;
 49        // Check for overflow, if signs of operands are different and signs of sum and x are different
 1593750        if ((((xl ^ yl) & (xl ^ diff)) & FixedMath.MIN_VALUE_L) != 0)
 251            diff = xl < 0 ? FixedMath.MIN_VALUE_L : FixedMath.MAX_VALUE_L;
 1593752        return new Fixed64(diff);
 53    }
 54
 55    /// <summary>
 56    /// Subtracts an int from a Fixed64, with saturating behavior in case of overflow.
 57    /// </summary>
 58    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 59    public static Fixed64 operator -(Fixed64 x, int y) =>
 1060        x - new Fixed64((long)y << FixedMath.SHIFT_AMOUNT_I);
 61
 62    /// <summary>
 63    /// Subtracts a Fixed64 from an int, with saturating behavior in case of overflow.
 64    /// </summary>
 65    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 66    public static Fixed64 operator -(int x, Fixed64 y) =>
 1067         new Fixed64((long)x << FixedMath.SHIFT_AMOUNT_I) - y;
 68
 69    /// <summary>
 70    /// Multiplies two Fixed64 numbers, handling overflow and rounding.
 71    /// </summary>
 72    /// <summary>
 73    /// Multiplies two Fixed64 numbers using full-width 128-bit intermediate precision
 74    /// and round-half-to-even semantics on the discarded fractional bits.
 75    /// </summary>
 76    public static Fixed64 operator *(Fixed64 x, Fixed64 y)
 77    {
 5442778        long xl = x.m_rawValue;
 5442779        long yl = y.m_rawValue;
 80
 5442781        int shift = FixedMath.SHIFT_AMOUNT_I;
 82
 83        // Determine sign of the final result.
 5442784        bool negative = ((xl ^ yl) < 0);
 85
 86        // Convert to unsigned magnitudes safely, including long.MinValue.
 5442787        ulong ax = AbsToUInt64(xl);
 5442788        ulong ay = AbsToUInt64(yl);
 89
 90        // Compute exact 128-bit unsigned product: (hi << 64) | lo
 5442791        Multiply64To128(ax, ay, out ulong hi, out ulong lo);
 92
 93        // Shift-right with round-half-to-even using the FULL discarded remainder.
 5442794        ulong magnitude = ShiftRightRoundedToEven(hi, lo, shift, out bool roundedOverflow);
 95
 96        // If rounding overflowed the shifted magnitude, carry it into saturation handling.
 5442797        if (!negative)
 98        {
 4073799            if (roundedOverflow || magnitude > long.MaxValue)
 5100                return new Fixed64(FixedMath.MAX_VALUE_L);
 101
 40732102            return new Fixed64((long)magnitude);
 103        }
 104        else
 105        {
 106            // For negative results, magnitude may be exactly 2^63, which maps to long.MinValue.
 107            const ulong minValueMagnitude = 0x8000000000000000UL;
 108
 13690109            if (roundedOverflow || magnitude > minValueMagnitude)
 2110                return new Fixed64(FixedMath.MIN_VALUE_L);
 111
 13688112            if (magnitude == minValueMagnitude)
 1113                return new Fixed64(FixedMath.MIN_VALUE_L);
 114
 13687115            return new Fixed64(-(long)magnitude);
 116        }
 117    }
 118
 119    /// <summary>
 120    /// Returns the absolute value of a signed 64-bit integer as an unsigned 64-bit magnitude,
 121    /// safely handling long.MinValue.
 122    /// </summary>
 123    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 124    private static ulong AbsToUInt64(long value)
 125    {
 108854126        return value < 0
 108854127            ? unchecked((ulong)(~value + 1))
 108854128            : (ulong)value;
 129    }
 130
 131    /// <summary>
 132    /// Computes the exact unsigned 128-bit product of two 64-bit unsigned integers.
 133    /// The result is returned as hi:lo, where product = (hi &lt;&lt; 64) | lo.
 134    /// </summary>
 135    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 136    private static void Multiply64To128(ulong a, ulong b, out ulong hi, out ulong lo)
 137    {
 54427138        ulong aLo = (uint)a;
 54427139        ulong aHi = a >> 32;
 54427140        ulong bLo = (uint)b;
 54427141        ulong bHi = b >> 32;
 142
 54427143        ulong p0 = aLo * bLo;
 54427144        ulong p1 = aLo * bHi;
 54427145        ulong p2 = aHi * bLo;
 54427146        ulong p3 = aHi * bHi;
 147
 54427148        ulong middle = (p0 >> 32) + (uint)p1 + (uint)p2;
 149
 54427150        lo = (p0 & 0xFFFFFFFFUL) | (middle << 32);
 54427151        hi = p3 + (p1 >> 32) + (p2 >> 32) + (middle >> 32);
 54427152    }
 153
 154    /// <summary>
 155    /// Shifts the unsigned 128-bit value (hi:lo) right by <paramref name="shift"/> bits,
 156    /// applying round-half-to-even to the discarded bits.
 157    /// </summary>
 158    /// <param name="hi">Upper 64 bits of the 128-bit value.</param>
 159    /// <param name="lo">Lower 64 bits of the 128-bit value.</param>
 160    /// <param name="shift">Number of bits to shift right. Must be in the range 1..63.</param>
 161    /// <param name="overflowed">
 162    /// True if the shifted or rounded result exceeded 64 bits.
 163    /// </param>
 164    /// <returns>
 165    /// The rounded 64-bit result of ((hi:lo) >> shift).
 166    /// </returns>
 167    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 168    private static ulong ShiftRightRoundedToEven(ulong hi, ulong lo, int shift, out bool overflowed)
 169    {
 170        // Preconditions: 1 <= shift <= 63
 171
 172        // Bits above the low 64 result bits must be preserved as saturation state
 173        // before the lower projection can wrap back into range.
 54427174        overflowed = (hi >> shift) != 0UL;
 175
 176        // Integer part after shifting right by 'shift':
 177        // result = ((hi << (64 - shift)) | (lo >> shift))
 54427178        ulong result = (hi << (64 - shift)) | (lo >> shift);
 179
 180        // Discarded remainder bits are the low 'shift' bits of lo.
 54427181        ulong remainderMask = (1UL << shift) - 1UL;
 54427182        ulong remainder = lo & remainderMask;
 183
 184        // Halfway value among the discarded bits.
 54427185        ulong half = 1UL << (shift - 1);
 186
 187        // Round-half-to-even:
 188        // - round up if remainder > half
 189        // - if exactly half, round so final result is even
 54427190        bool shouldRoundUp =
 54427191            remainder > half ||
 54427192            (remainder == half && (result & 1UL) != 0);
 193
 54427194        if (shouldRoundUp)
 195        {
 2686196            ulong incremented = result + 1UL;
 2686197            overflowed |= incremented < result;
 2686198            result = incremented;
 199        }
 200
 54427201        return result;
 202    }
 203
 204    /// <summary>
 205    /// Multiplies a Fixed64 by an integer, with overflow handling.
 206    /// </summary>
 207    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 208    public static Fixed64 operator *(Fixed64 x, int y) =>
 1528209        x * new Fixed64((long)y << FixedMath.SHIFT_AMOUNT_I);
 210
 211    /// <inheritdoc cref="operator *(Fixed64, int)" />
 212    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 56213    public static Fixed64 operator *(int x, Fixed64 y) => y * x;
 214
 215    /// <summary>
 216    /// Divides one Fixed64 number by another, handling division by zero and overflow.
 217    /// </summary>
 218    public static Fixed64 operator /(Fixed64 x, Fixed64 y)
 219    {
 5542220        long xl = x.m_rawValue;
 5542221        long yl = y.m_rawValue;
 222
 5542223        if (yl == 0)
 3224            throw new DivideByZeroException($"Attempted to divide {x} by zero.");
 225
 5539226        ulong remainder = (ulong)(xl < 0 ? -xl : xl);
 5539227        ulong divider = (ulong)(yl < 0 ? -yl : yl);
 5539228        ulong quotient = 0UL;
 5539229        int bitPos = FixedMath.SHIFT_AMOUNT_I + 1;
 230
 231        // If the divider is divisible by 2^n, take advantage of it.
 45346232        while ((divider & 0xF) == 0 && bitPos >= 4)
 233        {
 39807234            divider >>= 4;
 39807235            bitPos -= 4;
 236        }
 237
 10863238        while (remainder != 0 && bitPos >= 0)
 239        {
 5326240            int shift = CountLeadingZeroes(remainder);
 5326241            if (shift > bitPos)
 4880242                shift = bitPos;
 243
 5326244            remainder <<= shift;
 5326245            bitPos -= shift;
 246
 5326247            ulong div = remainder / divider;
 5326248            remainder %= divider;
 5326249            quotient += div << bitPos;
 250
 251            // Detect overflow
 5326252            if ((div & ~(0xFFFFFFFFFFFFFFFF >> bitPos)) != 0)
 2253                return ((xl ^ yl) & FixedMath.MIN_VALUE_L) == 0
 2254                    ? new Fixed64(FixedMath.MAX_VALUE_L)
 2255                    : new Fixed64(FixedMath.MIN_VALUE_L);
 256
 5324257            remainder <<= 1;
 5324258            --bitPos;
 259        }
 260
 261        // Rounding logic: "Round half to even" or "Banker's rounding"
 5537262        if ((quotient & 0x1) != 0)
 390263            quotient += 1;
 264
 5537265        long result = (long)(quotient >> 1);
 5537266        if (((xl ^ yl) & FixedMath.MIN_VALUE_L) != 0)
 677267            result = -result;
 268
 5537269        return new Fixed64(result);
 270    }
 271
 272    /// <summary>
 273    /// Divides a Fixed64 by an integer, handling division by zero and overflow.
 274    /// </summary>
 275    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 276    public static Fixed64 operator /(Fixed64 x, int y) =>
 811277         x / new Fixed64((long)y << FixedMath.SHIFT_AMOUNT_I);
 278
 279    /// <summary>
 280    /// Divides an integer by a Fixed64, handling division by zero and overflow.
 281    /// </summary>
 282    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 283    public static Fixed64 operator /(int y, Fixed64 x) =>
 1284         new Fixed64((long)y << FixedMath.SHIFT_AMOUNT_I) / x;
 285
 286    /// <summary>
 287    /// Computes the remainder of division of one Fixed64 number by another.
 288    /// </summary>
 289    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 290    public static Fixed64 operator %(Fixed64 x, Fixed64 y)
 291    {
 284292        if (x.m_rawValue == FixedMath.MIN_VALUE_L && y.m_rawValue == -1)
 1293            return Zero;
 283294        return new Fixed64(x.m_rawValue % y.m_rawValue);
 295    }
 296
 297    /// <summary>
 298    /// Computes the remainder of division of a Fixed64 by an int.
 299    /// </summary>
 300    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1301    public static Fixed64 operator %(Fixed64 x, int y) => x % new Fixed64((long)y << FixedMath.SHIFT_AMOUNT_I);
 302
 303    /// <summary>
 304    /// Computes the remainder of division of an int by a Fixed64.
 305    /// </summary>
 306    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1307    public static Fixed64 operator %(int x, Fixed64 y) => new Fixed64((long)x << FixedMath.SHIFT_AMOUNT_I) % y;
 308
 309    /// <summary>
 310    /// Unary negation operator.
 311    /// </summary>
 312    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 313    public static Fixed64 operator -(Fixed64 x) =>
 4036314        x.m_rawValue == FixedMath.MIN_VALUE_L
 4036315            ? new Fixed64(FixedMath.MAX_VALUE_L)
 4036316            : new Fixed64(-x.m_rawValue);
 317
 318    /// <summary>
 319    /// Increments a Fixed64 number by one, with saturating behavior in case of overflow.
 320    /// </summary>
 321    /// <param name="a">The Fixed64 number to increment.</param>
 322    /// <returns>The incremented Fixed64 number.</returns>
 323    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 2324    public static Fixed64 operator ++(Fixed64 a) => a + One;
 325
 326    /// <summary>
 327    /// Decrements a Fixed64 number by one, with saturating behavior in case of overflow.
 328    /// </summary>
 329    /// <param name="a">The Fixed64 number to decrement.</param>
 330    /// <returns>The decremented Fixed64 number.</returns>
 331    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 2332    public static Fixed64 operator --(Fixed64 a) => a - One;
 333
 334    /// <summary>
 335    /// Bitwise left shift operator.
 336    /// </summary>
 337    /// <param name="a">Operand to shift.</param>
 338    /// <param name="shift">Number of bits to shift.</param>
 339    /// <returns>The shifted value.</returns>
 340    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1341    public static Fixed64 operator <<(Fixed64 a, int shift) => new(a.m_rawValue << shift);
 342
 343    /// <summary>
 344    /// Bitwise right shift operator.
 345    /// </summary>
 346    /// <param name="a">Operand to shift.</param>
 347    /// <param name="shift">Number of bits to shift.</param>
 348    /// <returns>The shifted value.</returns>
 349    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1350    public static Fixed64 operator >>(Fixed64 a, int shift) => new(a.m_rawValue >> shift);
 351
 352    #endregion
 353    #region Comparison Operators
 354
 355    /// <summary>
 356    /// Determines whether one Fixed64 is greater than another.
 357    /// </summary>
 358    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 7156359    public static bool operator >(Fixed64 x, Fixed64 y) => x.m_rawValue > y.m_rawValue;
 360
 361    /// <summary>
 362    /// Determines whether a Fixed64 is greater than an integer.
 363    /// </summary>
 364    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1365    public static bool operator >(Fixed64 x, int y) => x.m_rawValue > (long)y << FixedMath.SHIFT_AMOUNT_I;
 366
 367    /// <summary>
 368    /// Determines whether an integer is greater than a Fixed64.
 369    /// </summary>
 370    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1371    public static bool operator >(int y, Fixed64 x) => (long)y << FixedMath.SHIFT_AMOUNT_I > x.m_rawValue;
 372
 373    /// <summary>
 374    /// Determines whether one Fixed64 is less than another.
 375    /// </summary>
 376    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 18969377    public static bool operator <(Fixed64 x, Fixed64 y) => x.m_rawValue < y.m_rawValue;
 378
 379    /// <summary>
 380    /// Determines whether one Fixed64 is less than an integer.
 381    /// </summary>
 382    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1383    public static bool operator <(Fixed64 x, int y) => x.m_rawValue < (long)y << FixedMath.SHIFT_AMOUNT_I;
 384
 385    /// <summary>
 386    /// Determines whether an integer is less than a Fixed64.
 387    /// </summary>
 388    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1389    public static bool operator <(int y, Fixed64 x) => (long)y << FixedMath.SHIFT_AMOUNT_I < x.m_rawValue;
 390
 391    /// <summary>
 392    /// Determines whether one Fixed64 is greater than or equal to another.
 393    /// </summary>
 394    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 15142395    public static bool operator >=(Fixed64 x, Fixed64 y) => x.m_rawValue >= y.m_rawValue;
 396
 397    /// <summary>
 398    /// Determines whether Fixed64 is greater than or equal to an integer.
 399    /// </summary>
 400    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1401    public static bool operator >=(Fixed64 x, int y) => x.m_rawValue >= (long)y << FixedMath.SHIFT_AMOUNT_I;
 402
 403    /// <summary>
 404    /// Determines whether an integer is greater than or equal to a Fixed64.
 405    /// </summary>
 406    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1407    public static bool operator >=(int y, Fixed64 x) => (long)y << FixedMath.SHIFT_AMOUNT_I >= x.m_rawValue;
 408
 409    /// <summary>
 410    /// Determines whether one Fixed64 is less than or equal to another.
 411    /// </summary>
 412    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 7783413    public static bool operator <=(Fixed64 x, Fixed64 y) => x.m_rawValue <= y.m_rawValue;
 414
 415    /// <summary>
 416    /// Determines whether a Fixed64 is less than or equal to an integer.
 417    /// </summary>
 418    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1419    public static bool operator <=(Fixed64 x, int y) => x.m_rawValue <= (long)y << FixedMath.SHIFT_AMOUNT_I;
 420
 421    /// <summary>
 422    /// Determines whether an integer is less than or equal to a Fixed64.
 423    /// </summary>
 424    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1425    public static bool operator <=(int y, Fixed64 x) => (long)y << FixedMath.SHIFT_AMOUNT_I <= x.m_rawValue;
 426
 427    /// <summary>
 428    /// Determines whether two Fixed64 instances are equal.
 429    /// </summary>
 430    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 9207431    public static bool operator ==(Fixed64 left, Fixed64 right) => left.Equals(right);
 432
 433    /// <summary>
 434    /// Determines whether a Fixed64 instance is equal to an integer.
 435    /// </summary>
 436    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1437    public static bool operator ==(Fixed64 left, int right) => left.m_rawValue == (long)right << FixedMath.SHIFT_AMOUNT_
 438
 439    /// <summary>
 440    /// Determines whether an integer is equal to a Fixed64 instance.
 441    /// </summary>
 442    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1443    public static bool operator ==(int left, Fixed64 right) => (long)left << FixedMath.SHIFT_AMOUNT_I == right.m_rawValu
 444
 445    /// <summary>
 446    /// Determines whether two Fixed64 instances are not equal.
 447    /// </summary>
 448    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 426449    public static bool operator !=(Fixed64 left, Fixed64 right) => !left.Equals(right);
 450
 451    /// <summary>
 452    /// Determines whether a Fixed64 instance is not equal to an integer.
 453    /// </summary>
 454    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1455    public static bool operator !=(Fixed64 left, int right) => left.m_rawValue != (long)right << FixedMath.SHIFT_AMOUNT_
 456
 457    /// <summary>
 458    /// Determines whether an integer is equal to a Fixed64 instance.
 459    /// </summary>
 460    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1461    public static bool operator !=(int left, Fixed64 right) => (long)left << FixedMath.SHIFT_AMOUNT_I != right.m_rawValu
 462
 463    #endregion
 464}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Numerics/Scalars/Fixed64.Statics.cs

#LineLine coverage
 1//=======================================================================
 2// Fixed64.Statics.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024–present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using System.Runtime.CompilerServices;
 9
 10namespace FixedMathSharp;
 11
 12public partial struct Fixed64
 13{
 14    #region Static Operations
 15
 16    /// <summary>
 17    /// Counts the leading zeros in a 64-bit unsigned integer.
 18    /// </summary>
 19    /// <param name="x">The number to count leading zeros for.</param>
 20    /// <returns>The number of leading zeros.</returns>
 21    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 22    internal static int CountLeadingZeroes(ulong x)
 23    {
 566724        int result = 0;
 12632425        while ((x & 0xF000000000000000) == 0) { result += 4; x <<= 4; }
 4128326        while ((x & 0x8000000000000000) == 0) { result += 1; x <<= 1; }
 566727        return result;
 28    }
 29
 30    /// <summary>
 31    /// Returns a number indicating the sign of a Fix64 number.
 32    /// Returns 1 if the value is positive, 0 if is 0, and -1 if it is negative.
 33    /// </summary>
 34    /// <remarks>
 35    /// Optimized for branchless comparison.
 36    /// </remarks>
 37    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 38    public static int Sign(Fixed64 value) =>
 1839        value.m_rawValue < 0
 1840                ? -1
 1841                : (value.m_rawValue > 0 ? 1 : 0);
 42
 43    /// <summary>
 44    /// Returns true if the number has no decimal part (i.e., if the number is equivalent to an integer) and False other
 45    /// </summary>
 46    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 47    public static bool IsInteger(Fixed64 value)
 48    {
 749        return ((ulong)value.m_rawValue & FixedMath.MAX_SHIFTED_AMOUNT_UI) == 0;
 50    }
 51
 52    #endregion
 53}

Methods/Properties

op_Explicit(System.Int64)
op_Explicit(FixedMathSharp.Fixed64)
op_Explicit(System.Int32)
op_Explicit(FixedMathSharp.Fixed64)
op_Explicit(System.Single)
op_Explicit(FixedMathSharp.Fixed64)
op_Explicit(System.Double)
op_Explicit(FixedMathSharp.Fixed64)
op_Explicit(System.Decimal)
op_Explicit(FixedMathSharp.Fixed64)
ToString()
ToString(System.String)
ToString(System.String,System.IFormatProvider)
TryFormat(System.Span`1<System.Char>,System.Int32&,System.ReadOnlySpan`1<System.Char>,System.IFormatProvider)
Parse(System.String)
Parse(System.String,System.IFormatProvider)
ParseRaw(System.String)
TryParse(System.String,FixedMathSharp.Fixed64&)
TryParse(System.String,System.IFormatProvider,FixedMathSharp.Fixed64&)
TryParseRaw(System.String,FixedMathSharp.Fixed64&)
FromRaw(System.Int64)
ToInt(FixedMathSharp.Fixed64)
FromDouble(System.Double)
FromDecimal(System.Decimal)
FromFraction(System.Double,System.Double)
ToDouble(System.Int64)
ToFloat(System.Int64)
ToDecimal(System.Int64)
get_MaxValue()
get_MinValue()
get_One()
get_NegOne()
get_Two()
get_Three()
get_Half()
get_Quarter()
get_Eighth()
get_Zero()
get_Pi()
get_TwoPi()
get_HalfPi()
get_PiOver3()
get_PiOver4()
get_PiOver6()
get_InvertedPi()
get_OneEighty()
get_Deg2Rad()
get_Rad2Deg()
get_Ln2()
get_Log2Max()
get_Log2Min()
get_PadeA1()
get_PadeA2()
get_SinCoeff3()
get_SinCoeff5()
get_SinCoeff7()
get_MinIncrement()
get_Epsilon()
.ctor(System.Int64)
.ctor(System.Int32)
Offset(System.Int32)
ToRawString()
Equals(System.Object)
Equals(FixedMathSharp.Fixed64)
Equals(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
GetHashCode()
GetHashCode(FixedMathSharp.Fixed64)
CompareTo(FixedMathSharp.Fixed64)
op_Addition(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
op_Addition(FixedMathSharp.Fixed64,System.Int32)
op_Addition(System.Int32,FixedMathSharp.Fixed64)
op_Subtraction(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
op_Subtraction(FixedMathSharp.Fixed64,System.Int32)
op_Subtraction(System.Int32,FixedMathSharp.Fixed64)
op_Multiply(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
AbsToUInt64(System.Int64)
Multiply64To128(System.UInt64,System.UInt64,System.UInt64&,System.UInt64&)
ShiftRightRoundedToEven(System.UInt64,System.UInt64,System.Int32,System.Boolean&)
op_Multiply(FixedMathSharp.Fixed64,System.Int32)
op_Multiply(System.Int32,FixedMathSharp.Fixed64)
op_Division(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
op_Division(FixedMathSharp.Fixed64,System.Int32)
op_Division(System.Int32,FixedMathSharp.Fixed64)
op_Modulus(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
op_Modulus(FixedMathSharp.Fixed64,System.Int32)
op_Modulus(System.Int32,FixedMathSharp.Fixed64)
op_UnaryNegation(FixedMathSharp.Fixed64)
op_Increment(FixedMathSharp.Fixed64)
op_Decrement(FixedMathSharp.Fixed64)
op_LeftShift(FixedMathSharp.Fixed64,System.Int32)
op_RightShift(FixedMathSharp.Fixed64,System.Int32)
op_GreaterThan(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
op_GreaterThan(FixedMathSharp.Fixed64,System.Int32)
op_GreaterThan(System.Int32,FixedMathSharp.Fixed64)
op_LessThan(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
op_LessThan(FixedMathSharp.Fixed64,System.Int32)
op_LessThan(System.Int32,FixedMathSharp.Fixed64)
op_GreaterThanOrEqual(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
op_GreaterThanOrEqual(FixedMathSharp.Fixed64,System.Int32)
op_GreaterThanOrEqual(System.Int32,FixedMathSharp.Fixed64)
op_LessThanOrEqual(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
op_LessThanOrEqual(FixedMathSharp.Fixed64,System.Int32)
op_LessThanOrEqual(System.Int32,FixedMathSharp.Fixed64)
op_Equality(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
op_Equality(FixedMathSharp.Fixed64,System.Int32)
op_Equality(System.Int32,FixedMathSharp.Fixed64)
op_Inequality(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
op_Inequality(FixedMathSharp.Fixed64,System.Int32)
op_Inequality(System.Int32,FixedMathSharp.Fixed64)
CountLeadingZeroes(System.UInt64)
Sign(FixedMathSharp.Fixed64)
IsInteger(FixedMathSharp.Fixed64)