< Summary

Information
Class: FixedMathSharp.Geometry.TriangleCapsuleSlabEndpointWitnesses
Assembly: FixedMathSharp
File(s): /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Triangles/TriangleCapsuleSlabEndpointWitnesses.cs
Line coverage
100%
Covered lines: 98
Uncovered lines: 0
Coverable lines: 98
Total lines: 176
Line coverage: 100%
Branch coverage
100%
Covered branches: 34
Total branches: 34
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
GetCore(...)100%22100%
CreateTerm(...)100%88100%
AdjustAnalytic(...)100%22100%
AdjustAnalyticComponent(...)100%22100%
CompareAnalytic(...)100%11100%
AdjustRoot(...)100%22100%
AdjustRootComponent(...)100%44100%
CompareRoot(...)100%66100%
Threshold(...)100%11100%
Correct(...)100%88100%

File(s)

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Triangles/TriangleCapsuleSlabEndpointWitnesses.cs

#LineLine coverage
 1//=======================================================================
 2// TriangleCapsuleSlabEndpointWitnesses.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 static FixedMathSharp.Geometry.CylinderContactAlgebra;
 10
 11namespace FixedMathSharp.Geometry;
 12
 13/// <summary>Joint radial/core rounding at a selected stadium endpoint.</summary>
 14internal static class TriangleCapsuleSlabEndpointWitnesses
 15{
 16    internal static Vector3d GetCore(Vector2d axis, Fixed64 length, int coreSign,
 17        out FixedPointAnchorTerm3d term)
 18    {
 50719        Fixed64 signedLength = coreSign > 0 ? -length : length;
 50720        Signed576 denominator = Signed576.ExtendValue(Signed320.ExtendValue(FixedPointAnchorTerm3d.Denominator));
 50721        bool representedX = Fixed64.TryGetSignedRawRatio(Signed576.ExtendValue(
 50722            WideArithmetic.MultiplySigned192(Signed192.Raw(axis.X), Signed192.Raw(signedLength))), denominator, out Fixe
 50723        bool representedZ = Fixed64.TryGetSignedRawRatio(Signed576.ExtendValue(
 50724            WideArithmetic.MultiplySigned192(Signed192.Raw(axis.Y), Signed192.Raw(signedLength))), denominator, out Fixe
 25        System.Diagnostics.Debug.Assert(representedX && representedZ);
 50726        var core = new Vector3d(x, Fixed64.Zero, z);
 50727        term = CreateTerm(axis, signedLength, core, 5);
 50728        return core;
 29    }
 30
 31    internal static FixedPointAnchorTerm3d CreateTerm(Vector2d axis, Fixed64 signedLength, Vector3d core, int integralMa
 66732        FixedPointAnchorTerm3d.CreateCenteredAxisSupport(
 66733            new Vector3d((integralMask & 1) != 0 ? axis.X : Fixed64.Zero, Fixed64.Zero,
 66734                (integralMask & 4) != 0 ? axis.Y : Fixed64.Zero), signedLength,
 66735            Vector3d.Zero, Fixed64.Zero,
 66736            new Vector3d((integralMask & 1) != 0 ? core.X : Fixed64.Zero, Fixed64.Zero,
 66737                (integralMask & 4) != 0 ? core.Z : Fixed64.Zero), Vector3d.Zero);
 38
 39    internal static Vector3d AdjustAnalytic(ReadOnlySpan<ulong> direction, ReadOnlySpan<int> signs,
 40        Fixed64 radius, Vector3d core, FixedPointAnchorTerm3d term, Vector3d radial, out int integralMask)
 41    {
 2542        Span<ulong> norm = stackalloc ulong[Words];
 2543        Span<ulong> product = stackalloc ulong[Words];
 2544        WideArithmetic.MultiplyMagnitudes(Slot(direction, 0), Slot(direction, 0), norm);
 2545        WideArithmetic.MultiplyMagnitudes(Slot(direction, 2), Slot(direction, 2), product);
 2546        WideArithmetic.AddMagnitudeInto(product, norm);
 2547        Fixed64 x = AdjustAnalyticComponent(Slot(direction, 0), -signs[0], norm, radius,
 2548            core.X, term.X, radial.X, out bool integralX);
 2549        Fixed64 z = AdjustAnalyticComponent(Slot(direction, 2), -signs[2], norm, radius,
 2550            core.Z, term.Z, radial.Z, out bool integralZ);
 2551        integralMask = (integralX ? 1 : 0) | (integralZ ? 4 : 0);
 2552        return new Vector3d(x, radial.Y, z);
 53    }
 54
 55    private static Fixed64 AdjustAnalyticComponent(ReadOnlySpan<ulong> component, int sign,
 56        ReadOnlySpan<ulong> norm, Fixed64 radius, Fixed64 core, long residual, Fixed64 rounded, out bool integral)
 57    {
 5058        Span<ulong> scaled = stackalloc ulong[Words];
 5059        Span<ulong> factor = stackalloc ulong[Words];
 60        // Compare radial with T/(2D): sign(2DR*n_i - T*sqrt(K)).
 61        // D=2Q, direction<630 bits: the rational term stays below730 bits;
 62        // K<1262 and the existing quadratic sign owner sizes its own squares.
 5063        Signed320 multiplier = WideArithmetic.MultiplySigned192(Signed192.Raw(radius),
 5064            WideArithmetic.AddSigned192(FixedPointAnchorTerm3d.Denominator, FixedPointAnchorTerm3d.Denominator));
 5065        Import(multiplier, factor);
 5066        WideArithmetic.MultiplyMagnitudes(component, factor, scaled);
 5067        integral = CompareAnalytic(scaled, sign, norm, Threshold(rounded, 0, 0)) == 0;
 5068        if (integral)
 3069            return rounded;
 2070        int lower = CompareAnalytic(scaled, sign, norm, Threshold(rounded, -1, residual));
 2071        int upper = CompareAnalytic(scaled, sign, norm, Threshold(rounded, 1, residual));
 2072        return Correct(rounded, core, lower, upper);
 73    }
 74
 75    private static int CompareAnalytic(ReadOnlySpan<ulong> scaled, int sign, ReadOnlySpan<ulong> norm, Signed192 thresho
 76    {
 9077        Span<ulong> magnitude = stackalloc ulong[Words];
 9078        Import(Signed320.ExtendValue(threshold), magnitude);
 9079        return WideConvexPrismRelations.GetConvexContactCandidateQuadraticSign(scaled, sign, magnitude, -threshold.Sign,
 80    }
 81
 82    internal static Vector3d AdjustRoot(ref FiniteAxisValueRoot root, scoped ReadOnlySpan<ulong> gradient,
 83        scoped ReadOnlySpan<sbyte> signs, Fixed64 radius, Vector3d core,
 84        FixedPointAnchorTerm3d term, Vector3d radial, out int integralMask)
 85    {
 10086        int count = signs.Length / 3, words = gradient.Length / signs.Length;
 5087        int squareCount = 2 * count - 1;
 5088        Span<ulong> norm = stackalloc ulong[squareCount * 2 * words];
 5089        Span<sbyte> normSigns = stackalloc sbyte[squareCount];
 5090        ConvexContactValueRoot.BuildSquaredLength(gradient, signs, norm, normSigns);
 5091        Fixed64 x = AdjustRootComponent(ref root, gradient[..(count * words)], signs[..count], norm, normSigns,
 5092            radius, core.X, term.X, radial.X, out bool integralX);
 5093        Fixed64 z = AdjustRootComponent(ref root, gradient[(2 * count * words)..], signs[(2 * count)..], norm, normSigns
 5094            radius, core.Z, term.Z, radial.Z, out bool integralZ);
 5095        integralMask = (integralX ? 1 : 0) | (integralZ ? 4 : 0);
 5096        return new Vector3d(x, radial.Y, z);
 97    }
 98
 99    private static Fixed64 AdjustRootComponent(ref FiniteAxisValueRoot root,
 100        scoped ReadOnlySpan<ulong> component, scoped ReadOnlySpan<sbyte> signs,
 101        scoped ReadOnlySpan<ulong> norm, scoped ReadOnlySpan<sbyte> normSigns,
 102        Fixed64 radius, Fixed64 core, long residual, Fixed64 rounded, out bool integral)
 103    {
 100104        int sign = -WideFiniteAxisIntersection.GetSignAtFiniteValueRootAndRefine(ref root, component, signs);
 200105        int count = normSigns.Length, words = norm.Length / count + 4;
 100106        Span<ulong> squared = stackalloc ulong[count * words];
 100107        Span<sbyte> squaredSigns = stackalloc sbyte[count];
 100108        Span<ulong> product = stackalloc ulong[words];
 100109        WideFiniteAxisIntersection.MultiplyFiniteAxisPolynomials(component, signs, component, signs, squared, squaredSig
 100110        Signed320 multiplier = WideArithmetic.MultiplySigned192(Signed192.Raw(radius),
 100111            WideArithmetic.AddSigned192(FixedPointAnchorTerm3d.Denominator, FixedPointAnchorTerm3d.Denominator));
 100112        Span<ulong> factor = stackalloc ulong[9];
 100113        WideArithmetic.GetMagnitude(WideArithmetic.MultiplySigned320(multiplier, multiplier), factor);
 800114        for (int index = 0; index < count; index++)
 115        {
 300116            Span<ulong> coefficient = squared.Slice(index * words, words);
 300117            WideArithmetic.MultiplyMagnitudes(coefficient, factor, product);
 300118            product.CopyTo(coefficient);
 119        }
 120        // Sign-gated squaring compares (2DR)^2*C(t)^2 with T^2*K(t).
 121        // T<98 bits and the multiplier<98 bits: four additional coefficient
 122        // words cover both products and subtraction, independent of root width.
 100123        integral = CompareRoot(ref root, squared, squaredSigns, norm, normSigns, sign, Threshold(rounded, 0, 0)) == 0;
 100124        if (integral)
 64125            return rounded;
 36126        int lower = CompareRoot(ref root, squared, squaredSigns, norm, normSigns, sign, Threshold(rounded, -1, residual)
 36127        int upper = CompareRoot(ref root, squared, squaredSigns, norm, normSigns, sign, Threshold(rounded, 1, residual))
 36128        return Correct(rounded, core, lower, upper);
 129    }
 130
 131    private static int CompareRoot(ref FiniteAxisValueRoot root, scoped ReadOnlySpan<ulong> squared,
 132        scoped ReadOnlySpan<sbyte> squaredSigns, scoped ReadOnlySpan<ulong> norm,
 133        scoped ReadOnlySpan<sbyte> normSigns, int sign, Signed192 threshold)
 134    {
 172135        if (sign != threshold.Sign)
 8136            return sign.CompareTo(threshold.Sign);
 164137        if (sign == 0)
 1138            return 0;
 489139        int count = normSigns.Length, words = squared.Length / count, normWords = norm.Length / count;
 163140        Span<ulong> query = stackalloc ulong[squared.Length];
 163141        Span<sbyte> querySigns = stackalloc sbyte[count];
 163142        Span<ulong> product = stackalloc ulong[words];
 163143        Span<ulong> factor = stackalloc ulong[5];
 163144        Signed320 square = WideArithmetic.MultiplySigned192(threshold, threshold);
 163145        WideArithmetic.GetMagnitude(square, out factor[4], out factor[3], out factor[2], out factor[1], out factor[0]);
 326146        squared.CopyTo(query); squaredSigns.CopyTo(querySigns);
 1304147        for (int index = 0; index < count; index++)
 148        {
 489149            WideArithmetic.MultiplyMagnitudes(norm.Slice(index * normWords, normWords), factor, product);
 489150            int coefficientSign = querySigns[index];
 489151            Add(product, -normSigns[index], query.Slice(index * words, words), ref coefficientSign);
 489152            querySigns[index] = (sbyte)coefficientSign;
 153        }
 163154        return sign * WideFiniteAxisIntersection.GetSignAtFiniteValueRootAndRefine(ref root, query, querySigns);
 155    }
 156
 157    private static Signed192 Threshold(Fixed64 rounded, int halfStep, long residual)
 158    {
 262159        Signed192 twice = WideArithmetic.AddSigned192(Signed192.Raw(rounded), Signed192.Raw(rounded));
 262160        twice = WideArithmetic.AddSigned192(twice, Signed192.Signed(halfStep));
 262161        Signed192 numerator = Signed192.NarrowValue(WideArithmetic.MultiplySigned192(twice, FixedPointAnchorTerm3d.Denom
 262162        return WideArithmetic.SubtractSigned192(numerator,
 262163            WideArithmetic.AddSigned192(Signed192.Signed(residual), Signed192.Signed(residual)));
 164    }
 165
 166    private static Fixed64 Correct(Fixed64 rounded, Fixed64 core, int lower, int upper)
 167    {
 168        // Core residual is within half a raw unit, so only adjacent rounding
 169        // cells are possible. Parity belongs to the total, not either addend.
 170        // Nonintegral |radial|<R<=Max keeps the corrected displacement scalar
 171        // even when the additive endpoint+radial coordinate exceeds Max.
 56172        bool odd = ((rounded.m_rawValue ^ core.m_rawValue) & 1L) != 0;
 56173        int adjustment = lower < 0 || lower == 0 && odd ? -1 : upper > 0 || upper == 0 && odd ? 1 : 0;
 56174        return Fixed64.FromRaw(rounded.m_rawValue + adjustment);
 175    }
 176}

Methods/Properties

GetCore(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,System.Int32,FixedMathSharp.Geometry.FixedPointAnchorTerm3d&)
CreateTerm(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,System.Int32)
AdjustAnalytic(System.ReadOnlySpan`1<System.UInt64>,System.ReadOnlySpan`1<System.Int32>,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedPointAnchorTerm3d,FixedMathSharp.Vector3d,System.Int32&)
AdjustAnalyticComponent(System.ReadOnlySpan`1<System.UInt64>,System.Int32,System.ReadOnlySpan`1<System.UInt64>,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Int64,FixedMathSharp.Fixed64,System.Boolean&)
CompareAnalytic(System.ReadOnlySpan`1<System.UInt64>,System.Int32,System.ReadOnlySpan`1<System.UInt64>,FixedMathSharp.Signed192)
AdjustRoot(FixedMathSharp.Geometry.FiniteAxisValueRoot&,System.ReadOnlySpan`1<System.UInt64>,System.ReadOnlySpan`1<System.SByte>,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedPointAnchorTerm3d,FixedMathSharp.Vector3d,System.Int32&)
AdjustRootComponent(FixedMathSharp.Geometry.FiniteAxisValueRoot&,System.ReadOnlySpan`1<System.UInt64>,System.ReadOnlySpan`1<System.SByte>,System.ReadOnlySpan`1<System.UInt64>,System.ReadOnlySpan`1<System.SByte>,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Int64,FixedMathSharp.Fixed64,System.Boolean&)
CompareRoot(FixedMathSharp.Geometry.FiniteAxisValueRoot&,System.ReadOnlySpan`1<System.UInt64>,System.ReadOnlySpan`1<System.SByte>,System.ReadOnlySpan`1<System.UInt64>,System.ReadOnlySpan`1<System.SByte>,System.Int32,FixedMathSharp.Signed192)
Threshold(FixedMathSharp.Fixed64,System.Int32,System.Int64)
Correct(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Int32,System.Int32)