< Summary

Information
Class: FixedMathSharp.FixedRange
Assembly: FixedMathSharp
File(s): /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Numerics/FixedRange.cs
Line coverage
100%
Covered lines: 85
Uncovered lines: 0
Coverable lines: 85
Total lines: 292
Line coverage: 100%
Branch coverage
100%
Covered branches: 40
Total branches: 40
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%66100%
get_Length()100%11100%
get_MidPoint()100%11100%
SetMinMax(...)100%11100%
AddInPlace(...)100%11100%
InRange(...)100%66100%
InRange(...)100%66100%
Overlaps(...)100%22100%
GetDirection(...)100%44100%
ComputeOverlapDepth(...)100%1010100%
CheckOverlap(...)100%22100%
op_Addition(...)100%11100%
op_Subtraction(...)100%11100%
op_Equality(...)100%11100%
op_Inequality(...)100%11100%
ToString()100%11100%
Equals(...)100%22100%
Equals(...)100%22100%
GetHashCode()100%11100%

File(s)

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

#LineLine coverage
 1using MemoryPack;
 2using System;
 3using System.Runtime.CompilerServices;
 4using System.Text.Json.Serialization;
 5
 6namespace FixedMathSharp;
 7
 8/// <summary>
 9/// Represents a range of values with fixed precision.
 10/// </summary>
 11[Serializable]
 12[MemoryPackable]
 13public partial struct FixedRange : IEquatable<FixedRange>
 14{
 15    #region Static Readonly Fields
 16
 17    /// <summary>
 18    /// The smallest possible range.
 19    /// </summary>
 20    public static readonly FixedRange MinRange = new FixedRange(Fixed64.MIN_VALUE, Fixed64.MIN_VALUE);
 21
 22    /// <summary>
 23    /// The largest possible range.
 24    /// </summary>
 25    public static readonly FixedRange MaxRange = new FixedRange(Fixed64.MAX_VALUE, Fixed64.MAX_VALUE);
 26
 27    #endregion
 28
 29    #region Fields
 30
 31    /// <summary>
 32    /// Gets the minimum value of the range.
 33    /// </summary>
 34    [JsonInclude]
 35    [MemoryPackOrder(0)]
 36    public Fixed64 Min;
 37
 38    /// <summary>
 39    /// Gets the maximum value of the range.
 40    /// </summary>
 41    [JsonInclude]
 42    [MemoryPackOrder(1)]
 43    public Fixed64 Max;
 44
 45    #endregion
 46
 47    #region Constructors
 48
 49    /// <summary>
 50    /// Initializes a new instance of the FixedRange structure with the specified minimum and maximum values.
 51    /// </summary>
 52    /// <param name="min">The minimum value of the range.</param>
 53    /// <param name="max">The maximum value of the range.</param>
 54    /// <param name="enforceOrder">If true, ensures that Min is less than or equal to Max.</param>
 55    public FixedRange(Fixed64 min, Fixed64 max, bool enforceOrder = true)
 6056    {
 6057        if (enforceOrder)
 5958        {
 5959            Min = min < max ? min : max;
 5960            Max = min < max ? max : min;
 5961        }
 62        else
 163        {
 164            Min = min;
 165            Max = max;
 166        }
 6067    }
 68
 69    #endregion
 70
 71    #region Properties
 72
 73    /// <summary>
 74    /// The length of the range, computed as Max - Min.
 75    /// </summary>
 76    [JsonIgnore]
 77    [MemoryPackIgnore]
 78    public Fixed64 Length
 79    {
 80        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 181        get => Max - Min;
 82    }
 83
 84    /// <summary>
 85    /// The midpoint of the range.
 86    /// </summary>
 87    [JsonIgnore]
 88    [MemoryPackIgnore]
 89    public Fixed64 MidPoint
 90    {
 91        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 192        get => (Min + Max) * Fixed64.Half;
 93    }
 94
 95    #endregion
 96
 97    #region Methods (Instance)
 98
 99    /// <summary>
 100    /// Sets the minimum and maximum values for the range.
 101    /// </summary>
 102    /// <param name="min">The new minimum value.</param>
 103    /// <param name="max">The new maximum value.</param>
 104    public void SetMinMax(Fixed64 min, Fixed64 max)
 1105    {
 1106        Min = min;
 1107        Max = max;
 1108    }
 109
 110    /// <summary>
 111    /// Adds a value to both the minimum and maximum of the range.
 112    /// </summary>
 113    /// <param name="val">The value to add.</param>
 114    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 115    public void AddInPlace(Fixed64 val)
 1116    {
 1117        Min += val;
 1118        Max += val;
 1119    }
 120
 121    /// <summary>
 122    /// Determines whether the specified value is within the range, with an option to include or exclude the upper bound
 123    /// </summary>
 124    /// <param name="x">The value to check.</param>
 125    /// <param name="includeMax">If true, the upper bound (Max) is included in the range check; otherwise, the upper bou
 126    /// <returns>True if the value is within the range; otherwise, false.</returns>
 127    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 128    public bool InRange(Fixed64 x, bool includeMax = false)
 9129    {
 9130        return includeMax ? x >= Min && x <= Max : x >= Min && x < Max;
 9131    }
 132
 133    /// <inheritdoc cref="InRange(Fixed64, bool)" />
 134    public bool InRange(double x, bool includeMax = false)
 6135    {
 6136        long xL = (long)Math.Round((double)x * FixedMath.ONE_L);
 6137        return includeMax ? xL >= Min.m_rawValue && xL <= Max.m_rawValue : xL >= Min.m_rawValue && xL < Max.m_rawValue;
 6138    }
 139
 140    /// <summary>
 141    /// Checks whether this range overlaps with the specified range, ensuring no adjacent edges are considered overlaps.
 142    /// </summary>
 143    /// <param name="other">The range to compare.</param>
 144    /// <returns>True if the ranges overlap; otherwise, false.</returns>
 145    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 146    public bool Overlaps(FixedRange other)
 9147    {
 9148        return Min < other.Max && Max > other.Min;
 9149    }
 150
 151    #endregion
 152
 153    #region Range Operations
 154
 155    /// <summary>
 156    /// Determines the direction from one range to another.
 157    /// If they don't overlap, returns -1 or 1 depending on the relative position.
 158    /// </summary>
 159    /// <param name="range1">The first range.</param>
 160    /// <param name="range2">The second range.</param>
 161    /// <param name="sign">The direction between ranges (-1 or 1).</param>
 162    /// <returns>True if the ranges don't overlap, false if they do.</returns>
 163    public static bool GetDirection(FixedRange range1, FixedRange range2, out Fixed64? sign)
 3164    {
 3165        sign = null;
 3166        if (!range1.Overlaps(range2))
 2167        {
 3168            if (range1.Max < range2.Min) sign = -Fixed64.One;
 1169            else sign = Fixed64.One;
 2170            return true;
 171        }
 1172        return false;
 3173    }
 174
 175    /// <summary>
 176    /// Calculates the overlap depth between two ranges.
 177    /// Assumes the ranges are sorted (min and max are correctly assigned).
 178    /// </summary>
 179    /// <param name="rangeA">The first range.</param>
 180    /// <param name="rangeB">The second range.</param>
 181    /// <returns>The depth of the overlap between the ranges.</returns>
 182    public static Fixed64 ComputeOverlapDepth(FixedRange rangeA, FixedRange rangeB)
 6183    {
 184        // Check if one range is completely within the other
 6185        bool isRangeAInsideB = rangeA.Min >= rangeB.Min && rangeA.Max <= rangeB.Max;
 6186        bool isRangeBInsideA = rangeB.Min >= rangeA.Min && rangeB.Max <= rangeA.Max;
 6187        if (isRangeAInsideB)
 1188            return rangeA.Max - rangeB.Min; // The size of rangeA
 5189        else if (isRangeBInsideA)
 1190            return rangeB.Max - rangeA.Min; // The size of rangeB
 191
 192        // Calculate overlap between the two ranges
 4193        Fixed64 overlapEnd = FixedMath.Min(rangeA.Max, rangeB.Max);
 4194        Fixed64 overlapStart = FixedMath.Max(rangeA.Min, rangeB.Min);
 4195        Fixed64 overlap = overlapEnd - overlapStart;
 196
 4197        return overlap > Fixed64.Zero ? overlap : Fixed64.Zero;
 6198    }
 199
 200    /// <summary>
 201    /// Checks for overlap between two ranges and calculates the vector of overlap depth.
 202    /// </summary>
 203    /// <param name="origin">The origin vector.</param>
 204    /// <param name="range1">The first range.</param>
 205    /// <param name="range2">The second range.</param>
 206    /// <param name="limit">The overlap limit to check.</param>
 207    /// <param name="sign">The direction sign to consider.</param>
 208    /// <param name="output">The overlap vector and depth, if any.</param>
 209    /// <returns>True if overlap occurs and is below the limit, otherwise false.</returns>
 210    public static bool CheckOverlap(Vector3d origin, FixedRange range1, FixedRange range2, Fixed64 limit, Fixed64 sign, 
 2211    {
 2212        output = null;
 2213        Fixed64 overlap = ComputeOverlapDepth(range1, range2);
 214
 215        // If the overlap is smaller than the current minimum, update the minimum
 2216        if (overlap < limit)
 1217        {
 1218            output = (origin * overlap * sign, overlap);
 1219            return true;
 220        }
 1221        return false;
 2222    }
 223
 224    #endregion
 225
 226    #region Operators
 227
 228    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 229    public static FixedRange operator +(FixedRange left, FixedRange right)
 1230    {
 1231        return new FixedRange(left.Min + right.Min, left.Max + right.Max);
 1232    }
 233
 234    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 235    public static FixedRange operator -(FixedRange left, FixedRange right)
 1236    {
 1237        return new FixedRange(left.Min - right.Min, left.Max - right.Max);
 1238    }
 239
 240    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 241    public static bool operator ==(FixedRange left, FixedRange right)
 1242    {
 1243        return left.Equals(right);
 1244    }
 245
 246    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 247    public static bool operator !=(FixedRange left, FixedRange right)
 1248    {
 1249        return !left.Equals(right);
 1250    }
 251
 252    #endregion
 253
 254    #region Conversion
 255
 256    /// <summary>
 257    /// Returns a string that represents the FixedRange instance, formatted as "Min - Max".
 258    /// </summary>
 259    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 260    public override string ToString()
 1261    {
 1262        return $"{Min.ToFormattedDouble()} - {Max.ToFormattedDouble()}";
 1263    }
 264
 265    #endregion
 266
 267    #region Equality and HashCode Overrides
 268
 269    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 270    public override bool Equals(object? obj)
 2271    {
 2272        return obj is FixedRange other && Equals(other);
 2273    }
 274
 275    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 276    public bool Equals(FixedRange other)
 8277    {
 8278        return other.Min == Min && other.Max == Max;
 8279    }
 280
 281    /// <summary>
 282    /// Computes the hash code for the FixedRange instance.
 283    /// </summary>
 284    /// <returns>The hash code of the range.</returns>
 285    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 286    public override int GetHashCode()
 2287    {
 2288        return Min.GetHashCode() ^ Max.GetHashCode();
 2289    }
 290
 291    #endregion
 292}