< Summary

Information
Class: FixedMathSharp.Fixed64
Assembly: FixedMathSharp
File(s): /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Numerics/Fixed64.cs
Line coverage
99%
Covered lines: 293
Uncovered lines: 2
Coverable lines: 295
Total lines: 779
Line coverage: 99.3%
Branch coverage
92%
Covered branches: 87
Total branches: 94
Branch coverage: 92.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
.ctor(...)100%11100%
.ctor(...)100%11100%
Offset(...)100%11100%
RawToString()100%11100%
Fraction(...)100%11100%
PostIncrement(...)100%11100%
PostDecrement(...)100%11100%
CountLeadingZeroes(...)100%44100%
Sign(...)100%44100%
IsInteger(...)100%11100%
op_Explicit(...)100%11100%
op_Explicit(...)100%11100%
op_Explicit(...)100%11100%
op_Explicit(...)100%11100%
op_Explicit(...)100%11100%
op_Explicit(...)100%11100%
op_Explicit(...)100%11100%
op_Explicit(...)100%11100%
op_Explicit(...)100%11100%
op_Explicit(...)100%11100%
op_Addition(...)75%44100%
op_Addition(...)100%11100%
op_Addition(...)100%11100%
op_Addition(...)100%11100%
op_Addition(...)100%11100%
op_Subtraction(...)75%44100%
op_Subtraction(...)100%11100%
op_Subtraction(...)100%11100%
op_Subtraction(...)100%11100%
op_Subtraction(...)100%11100%
op_Multiply(...)86.66%303095.12%
op_Multiply(...)100%11100%
op_Multiply(...)100%11100%
op_Division(...)100%2424100%
op_Division(...)100%11100%
op_Modulus(...)100%44100%
op_UnaryNegation(...)100%22100%
op_Increment(...)100%11100%
op_Decrement(...)100%11100%
op_LeftShift(...)100%11100%
op_RightShift(...)100%11100%
op_GreaterThan(...)100%11100%
op_LessThan(...)100%11100%
op_GreaterThanOrEqual(...)100%11100%
op_LessThanOrEqual(...)100%11100%
op_Equality(...)100%11100%
op_Inequality(...)100%11100%
ToString()100%11100%
ToString(...)100%11100%
Parse(...)100%88100%
TryParse(...)100%88100%
FromRaw(...)100%11100%
ToDouble(...)100%11100%
ToFloat(...)100%11100%
ToDecimal(...)100%11100%
Equals(...)50%22100%
Equals(...)100%11100%
Equals(...)100%11100%
GetHashCode()100%11100%
GetHashCode(...)100%11100%
CompareTo(...)100%11100%

File(s)

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

#LineLine coverage
 1using MemoryPack;
 2using System;
 3using System.Collections.Generic;
 4using System.Globalization;
 5using System.Runtime.CompilerServices;
 6using System.Text.Json.Serialization;
 7
 8namespace FixedMathSharp;
 9
 10/// <summary>
 11/// Represents a Q(64-SHIFT_AMOUNT).SHIFT_AMOUNT fixed-point number.
 12/// Provides high precision for fixed-point arithmetic where SHIFT_AMOUNT bits
 13/// are used for the fractional part and (64 - SHIFT_AMOUNT) bits for the integer part.
 14/// The precision is determined by SHIFT_AMOUNT, which defines the resolution of fractional values.
 15/// </summary>
 16[Serializable]
 17[MemoryPackable]
 18public partial struct Fixed64 : IEquatable<Fixed64>, IComparable<Fixed64>, IEqualityComparer<Fixed64>
 19{
 20    #region Static Readonly Fields
 21
 22    public static readonly Fixed64 MAX_VALUE = new Fixed64(FixedMath.MAX_VALUE_L);
 23    public static readonly Fixed64 MIN_VALUE = new Fixed64(FixedMath.MIN_VALUE_L);
 24
 25    public static readonly Fixed64 One = new Fixed64(FixedMath.ONE_L);
 26    public static readonly Fixed64 Two = One * 2;
 27    public static readonly Fixed64 Three = One * 3;
 28    public static readonly Fixed64 Half = One / 2;
 29    public static readonly Fixed64 Quarter = One / 4;
 30    public static readonly Fixed64 Eighth = One / 8;
 31    public static readonly Fixed64 Zero = new Fixed64(0);
 32
 33    /// <inheritdoc cref="FixedMath.EPSILON_L" />
 34    public static readonly Fixed64 Epsilon = new Fixed64(FixedMath.EPSILON_L);
 35    /// <inheritdoc cref="FixedMath.PRECISION_L" />
 36    public static readonly Fixed64 Precision = new Fixed64(FixedMath.PRECISION_L);
 37
 38    #endregion
 39
 40    #region Fields
 41
 42    /// <summary>
 43    /// The underlying raw long value representing the fixed-point number.
 44    /// </summary>
 45    [JsonInclude]
 46    [MemoryPackInclude]
 47    public long m_rawValue;
 48
 49    #endregion
 50
 51    #region Constructors
 52
 53    /// <summary>
 54    /// Internal constructor for a Fixed64 from a raw long value.
 55    /// </summary>
 56    /// <param name="rawValue">Raw long value representing the fixed-point number.</param>
 3526357    internal Fixed64(long rawValue) => m_rawValue = rawValue;
 58
 59    /// <summary>
 60    /// Constructs a Fixed64 from an integer, with the fractional part set to zero.
 61    /// </summary>
 62    /// <param name="value">Integer value to convert to </param>
 917463    public Fixed64(int value) : this((long)value << FixedMath.SHIFT_AMOUNT_I) { }
 64
 65    /// <summary>
 66    /// Constructs a Fixed64 from a double-precision floating-point value.
 67    /// </summary>
 68    /// <param name="value">Double value to convert to </param>
 278169    public Fixed64(double value) : this((long)Math.Round((double)value * FixedMath.ONE_L)) { }
 70
 71    #endregion
 72
 73    #region Methods (Instance)
 74
 75    /// <summary>
 76    /// Offsets the current Fixed64 by an integer value.
 77    /// </summary>
 78    /// <param name="x">The integer value to add.</param>
 79    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 80    public void Offset(int x)
 181    {
 182        m_rawValue += (long)x << FixedMath.SHIFT_AMOUNT_I;
 183    }
 84
 85    /// <summary>
 86    /// Returns the raw value as a string.
 87    /// </summary>
 88    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 89    public string RawToString()
 190    {
 191        return m_rawValue.ToString();
 192    }
 93
 94    #endregion
 95
 96    #region Fixed64 Operations
 97
 98    /// <summary>
 99    /// Creates a Fixed64 from a fractional number.
 100    /// </summary>
 101    /// <param name="numerator">The numerator of the fraction.</param>
 102    /// <param name="denominator">The denominator of the fraction.</param>
 103    /// <returns>A Fixed64 representing the fraction.</returns>
 104    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 105    public static Fixed64 Fraction(double numerator, double denominator)
 1106    {
 1107        return new Fixed64(numerator / denominator);
 1108    }
 109
 110    /// <summary>
 111    /// x++ (post-increment)
 112    /// </summary>
 113    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 114    public static Fixed64 PostIncrement(ref Fixed64 a)
 1115    {
 1116        Fixed64 originalValue = a;
 1117        a.m_rawValue += One.m_rawValue;
 1118        return originalValue;
 1119    }
 120
 121    /// <summary>
 122    /// x-- (post-decrement)
 123    /// </summary>
 124    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 125    public static Fixed64 PostDecrement(ref Fixed64 a)
 1126    {
 1127        Fixed64 originalValue = a;
 1128        a.m_rawValue -= One.m_rawValue;
 1129        return originalValue;
 1130    }
 131
 132    /// <summary>
 133    /// Counts the leading zeros in a 64-bit unsigned integer.
 134    /// </summary>
 135    /// <param name="x">The number to count leading zeros for.</param>
 136    /// <returns>The number of leading zeros.</returns>
 137    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 138    internal static int CountLeadingZeroes(ulong x)
 633139    {
 633140        int result = 0;
 24003141        while ((x & 0xF000000000000000) == 0) { result += 4; x <<= 4; }
 6028142        while ((x & 0x8000000000000000) == 0) { result += 1; x <<= 1; }
 633143        return result;
 633144    }
 145
 146    /// <summary>
 147    /// Returns a number indicating the sign of a Fix64 number.
 148    /// Returns 1 if the value is positive, 0 if is 0, and -1 if it is negative.
 149    /// </summary>
 150    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 151    public static int Sign(Fixed64 value)
 10152    {
 153        // Return the sign of the value, optimizing for branchless comparison
 10154        return value.m_rawValue < 0 ? -1 : (value.m_rawValue > 0 ? 1 : 0);
 10155    }
 156
 157    /// <summary>
 158    /// Returns true if the number has no decimal part (i.e., if the number is equivalent to an integer) and False other
 159    /// </summary>
 160    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 161    public static bool IsInteger(Fixed64 value)
 7162    {
 7163        return ((ulong)value.m_rawValue & FixedMath.MAX_SHIFTED_AMOUNT_UI) == 0;
 7164    }
 165
 166    #endregion
 167
 168    #region Explicit and Implicit Conversions
 169
 170    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 171    public static explicit operator Fixed64(long value)
 1172    {
 1173        return FromRaw(value << FixedMath.SHIFT_AMOUNT_I);
 1174    }
 175
 176    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 177    public static explicit operator long(Fixed64 value)
 1178    {
 1179        return value.m_rawValue >> FixedMath.SHIFT_AMOUNT_I;
 1180    }
 181
 182    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 183    public static explicit operator Fixed64(int value)
 2191184    {
 2191185        return new Fixed64(value);
 2191186    }
 187
 188    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 189    public static explicit operator int(Fixed64 value)
 14190    {
 14191        return (int)(value.m_rawValue >> FixedMath.SHIFT_AMOUNT_I);
 14192    }
 193
 194    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 195    public static explicit operator Fixed64(float value)
 3196    {
 3197        return new Fixed64((double)value);
 3198    }
 199
 200    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 201    public static explicit operator float(Fixed64 value)
 1202    {
 1203        return value.m_rawValue * FixedMath.SCALE_FACTOR_F;
 1204    }
 205
 206    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 207    public static explicit operator Fixed64(double value)
 95208    {
 95209        return new Fixed64(value);
 95210    }
 211
 212    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 213    public static explicit operator double(Fixed64 value)
 1494214    {
 1494215        return value.m_rawValue * FixedMath.SCALE_FACTOR_D;
 1494216    }
 217
 218    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 219    public static explicit operator Fixed64(decimal value)
 1220    {
 1221        return new Fixed64((double)value);
 1222    }
 223
 224    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 225    public static explicit operator decimal(Fixed64 value)
 1226    {
 1227        return value.m_rawValue * FixedMath.SCALE_FACTOR_M;
 1228    }
 229
 230    #endregion
 231
 232    #region Arithmetic Operators
 233
 234    /// <summary>
 235    /// Adds two Fixed64 numbers, with saturating behavior in case of overflow.
 236    /// </summary>
 237    public static Fixed64 operator +(Fixed64 x, Fixed64 y)
 3879238    {
 3879239        long xl = x.m_rawValue;
 3879240        long yl = y.m_rawValue;
 3879241        long sum = xl + yl;
 242        // Check for overflow, if signs of operands are equal and signs of sum and x are different
 3879243        if (((~(xl ^ yl) & (xl ^ sum)) & FixedMath.MIN_VALUE_L) != 0)
 1244            sum = xl > 0 ? FixedMath.MAX_VALUE_L : FixedMath.MIN_VALUE_L;
 3879245        return new Fixed64(sum);
 3879246    }
 247
 248    /// <summary>
 249    /// Adds an int to x
 250    /// </summary>
 251    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 252    public static Fixed64 operator +(Fixed64 x, int y)
 12253    {
 12254        return new Fixed64((x.m_rawValue * FixedMath.SCALE_FACTOR_D) + y);
 12255    }
 256
 257    /// <summary>
 258    /// Adds an Fixed64 to x
 259    /// </summary>
 260    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 261    public static Fixed64 operator +(int x, Fixed64 y)
 1262    {
 1263        return y + x;
 1264    }
 265
 266    /// <summary>
 267    /// Adds a float to x
 268    /// </summary>
 269    public static Fixed64 operator +(Fixed64 x, float y)
 12270    {
 12271        return new Fixed64((x.m_rawValue * FixedMath.SCALE_FACTOR_D) + y);
 12272    }
 273
 274    /// <summary>
 275    /// Adds a Fixed64 to x
 276    /// </summary>
 277    public static Fixed64 operator +(float x, Fixed64 y)
 1278    {
 1279        return y + x;
 1280    }
 281
 282    /// <summary>
 283    /// Subtracts one Fixed64 number from another, with saturating behavior in case of overflow.
 284    /// </summary>
 285    public static Fixed64 operator -(Fixed64 x, Fixed64 y)
 2478286    {
 2478287        long xl = x.m_rawValue;
 2478288        long yl = y.m_rawValue;
 2478289        long diff = xl - yl;
 290        // Check for overflow, if signs of operands are different and signs of sum and x are different
 2478291        if ((((xl ^ yl) & (xl ^ diff)) & FixedMath.MIN_VALUE_L) != 0)
 1292            diff = xl < 0 ? FixedMath.MIN_VALUE_L : FixedMath.MAX_VALUE_L;
 2478293        return new Fixed64(diff);
 2478294    }
 295
 296    /// <summary>
 297    /// Subtracts an int from x
 298    /// </summary>
 299    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 300    public static Fixed64 operator -(Fixed64 x, int y)
 6301    {
 6302        return new Fixed64((x.m_rawValue * FixedMath.SCALE_FACTOR_D) - y);
 6303    }
 304
 305    /// <summary>
 306    /// Subtracts a Fixed64 from x
 307    /// </summary>
 308    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 309    public static Fixed64 operator -(int x, Fixed64 y)
 6310    {
 6311        return new Fixed64(x - (y.m_rawValue * FixedMath.SCALE_FACTOR_D));
 6312    }
 313
 314    /// <summary>
 315    /// Subtracts a float from x
 316    /// </summary>
 317    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 318    public static Fixed64 operator -(Fixed64 x, float y)
 6319    {
 6320        return new Fixed64((x.m_rawValue * FixedMath.SCALE_FACTOR_D) - y);
 6321    }
 322
 323    /// <summary>
 324    /// Subtracts a Fixed64 from x
 325    /// </summary>
 326    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 327    public static Fixed64 operator -(float x, Fixed64 y)
 6328    {
 6329        return new Fixed64(x - (y.m_rawValue * FixedMath.SCALE_FACTOR_D));
 6330    }
 331
 332    /// <summary>
 333    /// Multiplies two Fixed64 numbers, handling overflow and rounding.
 334    /// </summary>
 335    public static Fixed64 operator *(Fixed64 x, Fixed64 y)
 8301336    {
 8301337        long xl = x.m_rawValue;
 8301338        long yl = y.m_rawValue;
 339
 340        // Split both numbers into high and low parts
 8301341        ulong xlo = (ulong)(xl & FixedMath.MAX_SHIFTED_AMOUNT_UI);
 8301342        long xhi = xl >> FixedMath.SHIFT_AMOUNT_I;
 8301343        ulong ylo = (ulong)(yl & FixedMath.MAX_SHIFTED_AMOUNT_UI);
 8301344        long yhi = yl >> FixedMath.SHIFT_AMOUNT_I;
 345
 346        // Perform partial products
 8301347        ulong lolo = xlo * ylo;          // low bits * low bits
 8301348        long lohi = (long)xlo * yhi;     // low bits * high bits
 8301349        long hilo = xhi * (long)ylo;     // high bits * low bits
 8301350        long hihi = xhi * yhi;           // high bits * high bits
 351
 352        // Combine results, starting with the low part
 8301353        ulong loResult = lolo >> FixedMath.SHIFT_AMOUNT_I;
 8301354        long hiResult = hihi << FixedMath.SHIFT_AMOUNT_I;
 355
 356        // Adjust rounding for the fractional part of the lolo term
 8301357        if ((lolo & (1UL << (FixedMath.SHIFT_AMOUNT_I - 1))) != 0)
 951358            loResult++; // Apply rounding up if the dropped bit is 1 (round half-up)
 359
 8301360        bool overflow = false;
 8301361        long sum = FixedMath.AddOverflowHelper((long)loResult, lohi, ref overflow);
 8301362        sum = FixedMath.AddOverflowHelper(sum, hilo, ref overflow);
 8301363        sum = FixedMath.AddOverflowHelper(sum, hiResult, ref overflow);
 364
 365        // Overflow handling
 8301366        bool opSignsEqual = ((xl ^ yl) & FixedMath.MIN_VALUE_L) == 0;
 367
 368        // Positive overflow check
 8301369        if (opSignsEqual)
 7844370        {
 7844371            if (sum < 0 || (overflow && xl > 0))
 1372                return MAX_VALUE;
 7843373        }
 374        else
 457375        {
 457376            if (sum > 0)
 1377                return MIN_VALUE;
 456378        }
 379
 380        // Final overflow check: if the high 32 bits are non-zero or non-sign-extended, it's an overflow
 8299381        long topCarry = hihi >> FixedMath.SHIFT_AMOUNT_I;
 8299382        if (topCarry != 0 && topCarry != -1)
 0383            return opSignsEqual ? MAX_VALUE : MIN_VALUE;
 384
 385        // Negative overflow check
 8299386        if (!opSignsEqual)
 456387        {
 456388            long posOp = xl > yl ? xl : yl;
 456389            long negOp = xl < yl ? xl : yl;
 390
 456391            if (sum > negOp && negOp < -FixedMath.ONE_L && posOp > FixedMath.ONE_L)
 0392                return MIN_VALUE;
 456393        }
 394
 8299395        return new Fixed64(sum);
 8301396    }
 397
 398    /// <summary>
 399    /// Multiplies a Fixed64 by an integer.
 400    /// </summary>
 401    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 402    public static Fixed64 operator *(Fixed64 x, int y)
 157403    {
 157404        return new Fixed64((x.m_rawValue * FixedMath.SCALE_FACTOR_D) * y);
 157405    }
 406
 407    /// <summary>
 408    /// Multiplies an integer by a
 409    /// </summary>
 410    public static Fixed64 operator *(int x, Fixed64 y)
 29411    {
 29412        return y * x;
 29413    }
 414
 415    /// <summary>
 416    /// Divides one Fixed64 number by another, handling division by zero and overflow.
 417    /// </summary>
 418    public static Fixed64 operator /(Fixed64 x, Fixed64 y)
 868419    {
 868420        long xl = x.m_rawValue;
 868421        long yl = y.m_rawValue;
 422
 868423        if (yl == 0)
 1424            throw new DivideByZeroException($"Attempted to divide {x} by zero.");
 425
 867426        ulong remainder = (ulong)(xl < 0 ? -xl : xl);
 867427        ulong divider = (ulong)(yl < 0 ? -yl : yl);
 867428        ulong quotient = 0UL;
 867429        int bitPos = FixedMath.SHIFT_AMOUNT_I + 1;
 430
 431        // If the divider is divisible by 2^n, take advantage of it.
 6297432        while ((divider & 0xF) == 0 && bitPos >= 4)
 5430433        {
 5430434            divider >>= 4;
 5430435            bitPos -= 4;
 5430436        }
 437
 1496438        while (remainder != 0 && bitPos >= 0)
 631439        {
 631440            int shift = CountLeadingZeroes(remainder);
 631441            if (shift > bitPos)
 509442                shift = bitPos;
 443
 631444            remainder <<= shift;
 631445            bitPos -= shift;
 446
 631447            ulong div = remainder / divider;
 631448            remainder %= divider;
 631449            quotient += div << bitPos;
 450
 451            // Detect overflow
 631452            if ((div & ~(0xFFFFFFFFFFFFFFFF >> bitPos)) != 0)
 2453                return ((xl ^ yl) & FixedMath.MIN_VALUE_L) == 0 ? MAX_VALUE : MIN_VALUE;
 454
 629455            remainder <<= 1;
 629456            --bitPos;
 629457        }
 458
 459        // Rounding logic: "Round half to even" or "Banker's rounding"
 865460        if ((quotient & 0x1) != 0)
 143461            quotient += 1;
 462
 865463        long result = (long)(quotient >> 1);
 865464        if (((xl ^ yl) & FixedMath.MIN_VALUE_L) != 0)
 41465            result = -result;
 466
 865467        return new Fixed64(result);
 867468    }
 469
 470    /// <summary>
 471    /// Divides a Fixed64 by an integer.
 472    /// </summary>
 473    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 474    public static Fixed64 operator /(Fixed64 x, int y)
 124475    {
 124476        return new Fixed64((x.m_rawValue * FixedMath.SCALE_FACTOR_D) / y);
 124477    }
 478
 479    /// <summary>
 480    /// Computes the remainder of division of one Fixed64 number by another.
 481    /// </summary>
 482    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 483    public static Fixed64 operator %(Fixed64 x, Fixed64 y)
 172484    {
 172485        if (x.m_rawValue == FixedMath.MIN_VALUE_L && y.m_rawValue == -1)
 1486            return Zero;
 171487        return new Fixed64(x.m_rawValue % y.m_rawValue);
 172488    }
 489
 490    /// <summary>
 491    /// Unary negation operator.
 492    /// </summary>
 493    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 494    public static Fixed64 operator -(Fixed64 x)
 1199495    {
 1199496        return x.m_rawValue == FixedMath.MIN_VALUE_L ? MAX_VALUE : new Fixed64(-x.m_rawValue);
 1199497    }
 498
 499    /// <summary>
 500    /// Pre-increment operator (++x).
 501    /// </summary>
 502    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 503    public static Fixed64 operator ++(Fixed64 a)
 1504    {
 1505        a.m_rawValue += One.m_rawValue;
 1506        return a;
 1507    }
 508
 509    /// <summary>
 510    /// Pre-decrement operator (--x).
 511    /// </summary>
 512    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 513    public static Fixed64 operator --(Fixed64 a)
 1514    {
 1515        a.m_rawValue -= One.m_rawValue;
 1516        return a;
 1517    }
 518
 519    /// <summary>
 520    /// Bitwise left shift operator.
 521    /// </summary>
 522    /// <param name="a">Operand to shift.</param>
 523    /// <param name="shift">Number of bits to shift.</param>
 524    /// <returns>The shifted value.</returns>
 525    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 526    public static Fixed64 operator <<(Fixed64 a, int shift)
 1527    {
 1528        return new Fixed64(a.m_rawValue << shift);
 1529    }
 530
 531    /// <summary>
 532    /// Bitwise right shift operator.
 533    /// </summary>
 534    /// <param name="a">Operand to shift.</param>
 535    /// <param name="shift">Number of bits to shift.</param>
 536    /// <returns>The shifted value.</returns>
 537    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 538    public static Fixed64 operator >>(Fixed64 a, int shift)
 1539    {
 1540        return new Fixed64(a.m_rawValue >> shift);
 1541    }
 542
 543    #endregion
 544
 545    #region Comparison Operators
 546
 547    /// <summary>
 548    /// Determines whether one Fixed64 is greater than another.
 549    /// </summary>
 550    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 551    public static bool operator >(Fixed64 x, Fixed64 y)
 1365552    {
 1365553        return x.m_rawValue > y.m_rawValue;
 1365554    }
 555
 556    /// <summary>
 557    /// Determines whether one Fixed64 is less than another.
 558    /// </summary>
 559    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 560    public static bool operator <(Fixed64 x, Fixed64 y)
 11572561    {
 11572562        return x.m_rawValue < y.m_rawValue;
 11572563    }
 564
 565    /// <summary>
 566    /// Determines whether one Fixed64 is greater than or equal to another.
 567    /// </summary>
 568    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 569    public static bool operator >=(Fixed64 x, Fixed64 y)
 14538570    {
 14538571        return x.m_rawValue >= y.m_rawValue;
 14538572    }
 573
 574    /// <summary>
 575    /// Determines whether one Fixed64 is less than or equal to another.
 576    /// </summary>
 577    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 578    public static bool operator <=(Fixed64 x, Fixed64 y)
 4970579    {
 4970580        return x.m_rawValue <= y.m_rawValue;
 4970581    }
 582
 583    /// <summary>
 584    /// Determines whether two Fixed64 instances are equal.
 585    /// </summary>
 586    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 587    public static bool operator ==(Fixed64 left, Fixed64 right)
 4389588    {
 4389589        return left.Equals(right);
 4389590    }
 591
 592    /// <summary>
 593    /// Determines whether two Fixed64 instances are not equal.
 594    /// </summary>
 595    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 596    public static bool operator !=(Fixed64 left, Fixed64 right)
 383597    {
 383598        return !left.Equals(right);
 383599    }
 600
 601    #endregion
 602
 603    #region Conversion
 604
 605    /// <summary>
 606    /// Returns the string representation of this Fixed64 instance.
 607    /// </summary>
 608    /// <remarks>
 609    /// Up to 10 decimal places.
 610    /// </remarks>
 611    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 612    public override string ToString()
 1007613    {
 1007614        return ((double)this).ToString(CultureInfo.InvariantCulture);
 1007615    }
 616
 617    /// <summary>
 618    /// Converts the numeric value of the current Fixed64 object to its equivalent string representation.
 619    /// </summary>
 620    /// <param name="format">A format specification that governs how the current Fixed64 object is converted.</param>
 621    /// <returns>The string representation of the value of the current Fixed64 object.</returns>
 622    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 623    public string ToString(string format)
 1624    {
 1625        return ((double)this).ToString(format, CultureInfo.InvariantCulture);
 1626    }
 627
 628    /// <summary>
 629    /// Parses a string to create a Fixed64 instance.
 630    /// </summary>
 631    /// <param name="s">The string representation of the </param>
 632    /// <returns>The parsed Fixed64 value.</returns>
 633    public static Fixed64 Parse(string s)
 5634    {
 7635        if (string.IsNullOrEmpty(s)) throw new ArgumentNullException(nameof(s));
 636
 637        // Check if the value is negative
 3638        bool isNegative = false;
 3639        if (s[0] == '-')
 1640        {
 1641            isNegative = true;
 1642            s = s.Substring(1);
 1643        }
 644
 3645        if (!long.TryParse(s, out long rawValue))
 1646            throw new FormatException($"Invalid format: {s}");
 647
 648        // If the value was negative, negate the result
 2649        if (isNegative)
 1650            rawValue = -rawValue;
 651
 2652        return FromRaw(rawValue);
 2653    }
 654
 655    /// <summary>
 656    /// Tries to parse a string to create a Fixed64 instance.
 657    /// </summary>
 658    /// <param name="s">The string representation of the </param>
 659    /// <param name="result">The parsed Fixed64 value.</param>
 660    /// <returns>True if parsing succeeded; otherwise, false.</returns>
 661    public static bool TryParse(string s, out Fixed64 result)
 4662    {
 4663        result = Zero;
 5664        if (string.IsNullOrEmpty(s)) return false;
 665
 666        // Check if the value is negative
 3667        bool isNegative = false;
 3668        if (s[0] == '-')
 1669        {
 1670            isNegative = true;
 1671            s = s.Substring(1);
 1672        }
 673
 4674        if (!long.TryParse(s, out long rawValue)) return false;
 675
 676        // If the value was negative, negate the result
 2677        if (isNegative)
 1678            rawValue = -rawValue;
 679
 2680        result = FromRaw(rawValue);
 2681        return true;
 4682    }
 683
 684    /// <summary>
 685    /// Creates a Fixed64 from a raw long value.
 686    /// </summary>
 687    /// <param name="rawValue">The raw long value.</param>
 688    /// <returns>A Fixed64 representing the raw value.</returns>
 689    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 690    public static Fixed64 FromRaw(long rawValue)
 14374691    {
 14374692        return new Fixed64(rawValue);
 14374693    }
 694
 695    /// <summary>
 696    /// Converts a Fixed64s RawValue (Int64) into a double
 697    /// </summary>
 698    /// <param name="f1"></param>
 699    /// <returns></returns>
 700    public static double ToDouble(long f1)
 1701    {
 1702        return f1 * FixedMath.SCALE_FACTOR_D;
 1703    }
 704
 705    /// <summary>
 706    /// Converts a Fixed64s RawValue (Int64) into a float
 707    /// </summary>
 708    /// <param name="f1"></param>
 709    /// <returns></returns>
 710    public static float ToFloat(long f1)
 1711    {
 1712        return f1 * FixedMath.SCALE_FACTOR_F;
 1713    }
 714
 715    /// <summary>
 716    /// Converts a Fixed64s RawValue (Int64) into a decimal
 717    /// </summary>
 718    /// <param name="f1"></param>
 719    /// <returns></returns>
 720    public static decimal ToDecimal(long f1)
 1721    {
 1722        return f1 * FixedMath.SCALE_FACTOR_M;
 1723    }
 724
 725    #endregion
 726
 727    #region Equality, HashCode, Comparable Overrides
 728
 729    /// <summary>
 730    /// Determines whether this instance equals another object.
 731    /// </summary>
 732    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 733    public override bool Equals(object? obj)
 6734    {
 6735        return obj is Fixed64 other && Equals(other);
 6736    }
 737
 738    /// <summary>
 739    /// Determines whether this instance equals another
 740    /// </summary>
 741    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 742    public bool Equals(Fixed64 other)
 7211743    {
 7211744        return m_rawValue == other.m_rawValue;
 7211745    }
 746
 747    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 748    public bool Equals(Fixed64 x, Fixed64 y)
 5749    {
 5750        return x.Equals(y);
 5751    }
 752
 753    /// <summary>
 754    /// Returns the hash code for this Fixed64 instance.
 755    /// </summary>
 756    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 757    public override int GetHashCode()
 131758    {
 131759        return m_rawValue.GetHashCode();
 131760    }
 761
 762    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 763    public int GetHashCode(Fixed64 obj)
 1764    {
 1765        return obj.GetHashCode();
 1766    }
 767
 768    /// <summary>
 769    /// Compares this instance to another
 770    /// </summary>
 771    /// <param name="other">The Fixed64 to compare with.</param>
 772    /// <returns>-1 if less than, 0 if equal, 1 if greater than other.</returns>
 773    public int CompareTo(Fixed64 other)
 36774    {
 36775        return m_rawValue.CompareTo(other.m_rawValue);
 36776    }
 777
 778    #endregion
 779}

Methods/Properties

.ctor(System.Int64)
.ctor(System.Int32)
.ctor(System.Double)
Offset(System.Int32)
RawToString()
Fraction(System.Double,System.Double)
PostIncrement(FixedMathSharp.Fixed64&)
PostDecrement(FixedMathSharp.Fixed64&)
CountLeadingZeroes(System.UInt64)
Sign(FixedMathSharp.Fixed64)
IsInteger(FixedMathSharp.Fixed64)
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)
op_Addition(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
op_Addition(FixedMathSharp.Fixed64,System.Int32)
op_Addition(System.Int32,FixedMathSharp.Fixed64)
op_Addition(FixedMathSharp.Fixed64,System.Single)
op_Addition(System.Single,FixedMathSharp.Fixed64)
op_Subtraction(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
op_Subtraction(FixedMathSharp.Fixed64,System.Int32)
op_Subtraction(System.Int32,FixedMathSharp.Fixed64)
op_Subtraction(FixedMathSharp.Fixed64,System.Single)
op_Subtraction(System.Single,FixedMathSharp.Fixed64)
op_Multiply(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
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_Modulus(FixedMathSharp.Fixed64,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_LessThan(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
op_GreaterThanOrEqual(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
op_LessThanOrEqual(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
op_Equality(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
op_Inequality(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
ToString()
ToString(System.String)
Parse(System.String)
TryParse(System.String,FixedMathSharp.Fixed64&)
FromRaw(System.Int64)
ToDouble(System.Int64)
ToFloat(System.Int64)
ToDecimal(System.Int64)
Equals(System.Object)
Equals(FixedMathSharp.Fixed64)
Equals(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
GetHashCode()
GetHashCode(FixedMathSharp.Fixed64)
CompareTo(FixedMathSharp.Fixed64)