< Summary

Information
Class: FixedMathSharp.Geometry.FixedPointAnchorTerm3d
Assembly: FixedMathSharp
File(s): /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Anchors/FixedPointAnchorTerms.cs
Line coverage
100%
Covered lines: 62
Uncovered lines: 0
Coverable lines: 62
Total lines: 231
Line coverage: 100%
Branch coverage
100%
Covered branches: 8
Total branches: 8
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%11100%
get_IsZero()100%44100%
CreateCenteredAxisSupport(...)100%11100%
CreateRadialSupport(...)100%11100%
LiftPlanarXZ(...)100%11100%
GetResidual(...)100%11100%
get_Denominator()100%11100%
Equals(...)100%44100%
GetHashCode()100%11100%

File(s)

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Anchors/FixedPointAnchorTerms.cs

#LineLine coverage
 1//=======================================================================
 2// FixedPointAnchorTerms.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;
 9
 10namespace FixedMathSharp.Geometry;
 11
 12/// <summary>
 13/// Retains the residual between rounded local feature components and their
 14/// exact centered-axis construction over the shared 2*Q32.32 denominator.
 15/// </summary>
 16internal readonly struct FixedPointAnchorTerm3d : IEquatable<FixedPointAnchorTerm3d>
 17{
 18    internal const long MaximumResidualMagnitude = 1L << 33;
 19
 20    internal readonly long X;
 21    internal readonly long Y;
 22    internal readonly long Z;
 23
 24    private FixedPointAnchorTerm3d(
 25        long x,
 26        long y,
 27        long z)
 28    {
 510029        X = x;
 510030        Y = y;
 510031        Z = z;
 510032    }
 33
 972934    internal bool IsZero => X == 0L && Y == 0L && Z == 0L;
 35
 36    internal static FixedPointAnchorTerm3d CreateCenteredAxisSupport(
 37        Vector3d localAxis,
 38        Fixed64 signedAxisLength,
 39        Vector3d localRadialDirection,
 40        Fixed64 radius,
 41        Vector3d roundedAxialOffset,
 42        Vector3d roundedRadialOffset) =>
 502143        new(
 502144            GetResidual(
 502145                localAxis.X,
 502146                signedAxisLength,
 502147                localRadialDirection.X,
 502148                radius,
 502149                roundedAxialOffset.X,
 502150                roundedRadialOffset.X),
 502151            GetResidual(
 502152                localAxis.Y,
 502153                signedAxisLength,
 502154                localRadialDirection.Y,
 502155                radius,
 502156                roundedAxialOffset.Y,
 502157                roundedRadialOffset.Y),
 502158            GetResidual(
 502159                localAxis.Z,
 502160                signedAxisLength,
 502161                localRadialDirection.Z,
 502162                radius,
 502163                roundedAxialOffset.Z,
 502164                roundedRadialOffset.Z));
 65
 66    internal static FixedPointAnchorTerm3d CreateRadialSupport(
 67        Vector3d localRadialDirection,
 68        Fixed64 radius,
 69        Vector3d roundedRadialOffset) =>
 19170        CreateCenteredAxisSupport(
 19171            Vector3d.Zero,
 19172            Fixed64.Zero,
 19173            localRadialDirection,
 19174            radius,
 19175            Vector3d.Zero,
 19176            roundedRadialOffset);
 77
 78    internal static FixedPointAnchorTerm3d LiftPlanarXZ(
 79        FixedPointAnchorTerm2d planarTerm) =>
 7980        new(planarTerm.X, 0L, planarTerm.Y);
 81
 82    private static long GetResidual(
 83        Fixed64 localAxis,
 84        Fixed64 signedAxisLength,
 85        Fixed64 localRadialDirection,
 86        Fixed64 radius,
 87        Fixed64 roundedAxialOffset,
 88        Fixed64 roundedRadialOffset)
 89    {
 1506390        Signed320 exact = WideArithmetic.AddSigned320(
 1506391            WideArithmetic.MultiplySigned192(
 1506392                Signed192.Raw(localAxis),
 1506393                Signed192.Raw(signedAxisLength)),
 1506394            WideArithmetic.AddSigned320(
 1506395                WideArithmetic.MultiplySigned192(
 1506396                    Signed192.Raw(localRadialDirection),
 1506397                    Signed192.Raw(radius)),
 1506398                WideArithmetic.MultiplySigned192(
 1506399                    Signed192.Raw(localRadialDirection),
 15063100                    Signed192.Raw(radius))));
 15063101        Signed192 rounded = WideArithmetic.AddSigned192(
 15063102            Signed192.Raw(roundedAxialOffset),
 15063103            Signed192.Raw(roundedRadialOffset));
 15063104        Signed320 residual = WideArithmetic.SubtractSigned320(
 15063105            exact,
 15063106            WideArithmetic.MultiplySigned192(
 15063107                rounded,
 15063108                Denominator));
 109        // Each rounded term is within half of its source denominator. The
 110        // axial full-length/2 residual is therefore at most one Q32 scale
 111        // unit, as is the doubled radial product residual. Their sum is
 112        // bounded inclusively by 2*Q32 (2^33), so the exact numerator fits in
 113        // one signed word even at a pair of round-to-even ties.
 15063114        return unchecked((long)residual.Word0);
 115    }
 116
 117    internal static Signed192 Denominator =>
 17281118        Signed192.Signed(Fixed64.Two.m_rawValue);
 119
 120    public bool Equals(FixedPointAnchorTerm3d other) =>
 427121        X == other.X && Y == other.Y && Z == other.Z;
 122
 123    public override int GetHashCode()
 124    {
 125        unchecked
 126        {
 2127            int hash = 17;
 2128            hash = (hash * 31) + X.GetHashCode();
 2129            hash = (hash * 31) + Y.GetHashCode();
 2130            hash = (hash * 31) + Z.GetHashCode();
 2131            return hash;
 132        }
 133    }
 134}
 135
 136/// <summary>
 137/// Two-dimensional counterpart of <see cref="FixedPointAnchorTerm3d"/>.
 138/// </summary>
 139internal readonly struct FixedPointAnchorTerm2d :
 140    IEquatable<FixedPointAnchorTerm2d>
 141{
 142    internal readonly long X;
 143    internal readonly long Y;
 144
 145    private FixedPointAnchorTerm2d(long x, long y)
 146    {
 147        X = x;
 148        Y = y;
 149    }
 150
 151    internal bool IsZero => X == 0L && Y == 0L;
 152
 153    internal static FixedPointAnchorTerm2d CreateCenteredAxisSupport(
 154        Vector2d localAxis,
 155        Fixed64 signedAxisLength,
 156        Vector2d localRadialDirection,
 157        Fixed64 radius,
 158        Vector2d roundedAxialOffset,
 159        Vector2d roundedRadialOffset) =>
 160        new(
 161            GetResidual(
 162                localAxis.X,
 163                signedAxisLength,
 164                localRadialDirection.X,
 165                radius,
 166                roundedAxialOffset.X,
 167                roundedRadialOffset.X),
 168            GetResidual(
 169                localAxis.Y,
 170                signedAxisLength,
 171                localRadialDirection.Y,
 172                radius,
 173                roundedAxialOffset.Y,
 174                roundedRadialOffset.Y));
 175
 176    internal static FixedPointAnchorTerm2d CreateRadialSupport(
 177        Vector2d localRadialDirection,
 178        Fixed64 radius,
 179        Vector2d roundedRadialOffset) =>
 180        CreateCenteredAxisSupport(
 181            Vector2d.Zero,
 182            Fixed64.Zero,
 183            localRadialDirection,
 184            radius,
 185            Vector2d.Zero,
 186            roundedRadialOffset);
 187
 188    private static long GetResidual(
 189        Fixed64 localAxis,
 190        Fixed64 signedAxisLength,
 191        Fixed64 localRadialDirection,
 192        Fixed64 radius,
 193        Fixed64 roundedAxialOffset,
 194        Fixed64 roundedRadialOffset)
 195    {
 196        Signed320 exact = WideArithmetic.AddSigned320(
 197            WideArithmetic.MultiplySigned192(
 198                Signed192.Raw(localAxis),
 199                Signed192.Raw(signedAxisLength)),
 200            WideArithmetic.AddSigned320(
 201                WideArithmetic.MultiplySigned192(
 202                    Signed192.Raw(localRadialDirection),
 203                    Signed192.Raw(radius)),
 204                WideArithmetic.MultiplySigned192(
 205                    Signed192.Raw(localRadialDirection),
 206                    Signed192.Raw(radius))));
 207        Signed192 rounded = WideArithmetic.AddSigned192(
 208            Signed192.Raw(roundedAxialOffset),
 209            Signed192.Raw(roundedRadialOffset));
 210        Signed320 residual = WideArithmetic.SubtractSigned320(
 211            exact,
 212            WideArithmetic.MultiplySigned192(
 213                rounded,
 214                FixedPointAnchorTerm3d.Denominator));
 215        return unchecked((long)residual.Word0);
 216    }
 217
 218    public bool Equals(FixedPointAnchorTerm2d other) =>
 219        X == other.X && Y == other.Y;
 220
 221    public override int GetHashCode()
 222    {
 223        unchecked
 224        {
 225            int hash = 17;
 226            hash = (hash * 31) + X.GetHashCode();
 227            hash = (hash * 31) + Y.GetHashCode();
 228            return hash;
 229        }
 230    }
 231}