< Summary

Line coverage
100%
Covered lines: 716
Uncovered lines: 0
Coverable lines: 716
Total lines: 1280
Line coverage: 100%
Branch coverage
100%
Covered branches: 480
Total branches: 480
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: IntersectsBoundaryLine(...)100%11100%
File 1: GetNativeBoundarySegment(...)100%44100%
File 1: IntersectsRealEdge(...)100%11100%
File 1: NormalizeNativeSegment(...)100%11100%
File 1: IntersectsNativeSegment(...)100%22100%
File 1: InterpolateNativeSource(...)100%11100%
File 1: DoubledBoundaryPoint(...)100%11100%
File 2: TryGetContact(...)100%2020100%
File 2: KeepAnalytic(...)100%3434100%
File 2: HasPoleMinimumCertificate(...)100%2020100%
File 2: IsBasisDirection(...)100%88100%
File 2: KeepAxis(...)100%1414100%
File 2: ReduceEdgeDirection(...)100%11100%
File 2: Difference(...)100%11100%
File 3: TryGetCylinderBoundaryContact(...)100%2020100%
File 4: TryGetContact(...)100%3636100%
File 4: TryAdmitAnalyticCandidate(...)100%4242100%
File 4: GetDomainWindow(...)100%11100%
File 4: IsFaceDirection(...)100%66100%
File 4: DirectionDotSign(...)100%1616100%
File 4: DirectionDotQuadraticSign(...)100%66100%
File 4: ClipRealEdgeWindow(...)100%2020100%
File 4: IsInsideRealEdgeWindow(...)100%1010100%
File 5: TryGetFaceSupportContact(...)100%1212100%
File 5: GetFacePlane(...)100%88100%
File 5: .ctor(...)100%11100%
File 5: .ctor(...)100%11100%
File 5: ClipFaceWindow(...)100%66100%
File 5: GetFaceWindowHalfplanes(...)100%2222100%
File 5: ScaleAxis(...)100%11100%
File 5: SumProducts(...)100%11100%
File 5: ClipFaceHalfplane(...)100%11100%
File 5: ClipBound(...)100%88100%
File 5: GetCurvedImplicit(...)100%1212100%
File 6: GetAnalyticWitnesses(...)100%11100%
File 6: TryGetAnalyticWitnesses(...)100%6262100%
File 6: GetPoleSupport(...)100%1818100%
File 6: ClipSegment(...)100%4444100%
File 6: ClipOriginalBody(...)100%1818100%
File 6: Blend(...)100%22100%
File 6: CreateQuadraticAnchor(...)100%66100%
File 6: DotQuadratic(...)100%22100%
File 6: DotQuadraticNormal(...)100%22100%
File 6: WAt(...)100%11100%
File 6: Integer(...)100%11100%

File(s)

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Convex/CurvedPrismContact.BoundaryLines.cs

#LineLine coverage
 1//=======================================================================
 2// CurvedPrismContact.BoundaryLines.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/// <content>Certifies actual finite-body intersection at retained native boundary junctions.</content>
 13internal static partial class CurvedPrismContact
 14{
 15    // Horizontal sources retain their original edge parameter. Vertical sources
 16    // have a singleton tangent cut and retain the original lower/upper heights.
 17    internal static bool IntersectsBoundaryLine(in CurvedPrismContactGeometry geometry, int edge,
 18        in RationalSegmentInterval clip, Fixed64 lower, Fixed64 upper)
 19    {
 2420        GetNativeBoundarySegment(geometry, edge, clip, lower, upper, out var a, out var b, out var coordinateD, out var 
 2421        return IntersectsNativeSegment(geometry, a, b, coordinateD, retained);
 22    }
 23
 24    /// <summary>Gets doubled centered primitive coordinates in one exact original line chart.</summary>
 25    internal static void GetNativeBoundarySegment(in CurvedPrismContactGeometry geometry, int edge,
 26        in RationalSegmentInterval clip, Fixed64 lower, Fixed64 upper,
 27        out WideAxis3 start, out WideAxis3 end, out Signed320 coordinateD, out RationalSegmentInterval retained)
 28    {
 10829        Vector2d first = geometry.FootprintVertex(edge), last = geometry.FootprintVertex((edge + 1) % (geometry.VertexCo
 5430        WideDirection3d a = geometry.GetNativeSourcePoint(new(first.X, lower, first.Y));
 5431        WideDirection3d b = geometry.GetNativeSourcePoint(new(last.X, lower, last.Y));
 5432        Signed576 denominator = Signed576.ExtendValue(geometry.NativeRawScale);
 5433        bool vertical = lower != upper;
 5434        if (vertical)
 35        {
 1936            var c = geometry.GetNativeSourcePoint(new(first.X, upper, first.Y));
 1937            var d = geometry.GetNativeSourcePoint(new(last.X, upper, last.Y));
 3838            Signed320 n = clip.LowerNumerator, div = clip.LowerDenominator;
 3839            a = InterpolateNativeSource(a, b, n, div); b = InterpolateNativeSource(c, d, n, div);
 1940            denominator = WideArithmetic.MultiplySigned320(div, geometry.NativeRawScale);
 41        }
 5442        NormalizeNativeSegment(a, b, denominator, out start, out end, out coordinateD);
 5443        retained = vertical ? default : clip;
 5444    }
 45
 46    // Source feasibility is independent of support direction. Discarding a
 47    // disjoint real-edge window avoids replaying large witness fields for it.
 48    internal static bool IntersectsRealEdge(in CurvedPrismContactGeometry geometry, int edge,
 49        in RationalSegmentInterval clip)
 50    {
 1051        geometry.Edge(edge, out int first, out int last);
 1052        NormalizeNativeSegment(geometry.Vertex(first), geometry.Vertex(last), Signed576.ExtendValue(geometry.RawScale),
 1053            out var a, out var b, out var coordinateD);
 1054        return IntersectsNativeSegment(geometry, a, b, coordinateD, clip);
 55    }
 56
 57    private static void NormalizeNativeSegment(in WideDirection3d a, in WideDirection3d b, Signed576 denominator,
 58        out WideAxis3 start, out WideAxis3 end, out Signed320 coordinateD)
 59    {
 6460        Span<Signed576> shared = stackalloc Signed576[7] { a.X, a.Y, a.Z, b.X, b.Y, b.Z, denominator };
 6461        WideArithmetic.ReduceCommonScale(shared);
 6462        coordinateD = Signed320.NarrowValue(shared[6]);
 63        // Native near-field coordinates need <147 bits, singleton cuts <162.
 64        // After one common scale, doubled points stay <311 bits. The existing
 65        // identity frame selects wide quadratics when D exceeds Signed192:
 66        // cone coefficients <716 bits, cylinder coefficients <624, within832.
 6467        start = DoubledBoundaryPoint(shared[0], shared[1], shared[2]);
 6468        end = DoubledBoundaryPoint(shared[3], shared[4], shared[5]);
 6469    }
 70
 71    private static bool IntersectsNativeSegment(in CurvedPrismContactGeometry geometry,
 72        WideAxis3 start, WideAxis3 end, Signed320 coordinateD, in RationalSegmentInterval retained)
 73    {
 3474        if (!geometry.IsCone)
 1775            return new FiniteSlabSectionFrame(geometry.HeightValue, geometry.RadiusValue, coordinateD)
 1776                .IntersectsTransformedSegment(start, end, retained);
 1777        var cone = new ConeFiniteSectionFrame(geometry.HeightValue, geometry.RadiusValue, coordinateD);
 78        // The cone owner measures height down from the apex; native P is centered.
 1779        start = new(start.X, WideArithmetic.SubtractSigned320(cone.ShapeFrame.Cap, start.Y), start.Z);
 1780        end = new(end.X, WideArithmetic.SubtractSigned320(cone.ShapeFrame.Cap, end.Y), end.Z);
 1781        return cone.IntersectsTransformedSegment(start, end, retained);
 82    }
 83
 84    private static WideDirection3d InterpolateNativeSource(in WideDirection3d a, in WideDirection3d b,
 85        Signed320 n, Signed320 d)
 86    {
 3887        Signed320 other = WideArithmetic.SubtractSigned320(d, n);
 3888        return new(Signed576.NarrowValue(WideArithmetic.AddSigned832(WideArithmetic.MultiplySigned576ToSigned832(a.X, ot
 3889            Signed576.NarrowValue(WideArithmetic.AddSigned832(WideArithmetic.MultiplySigned576ToSigned832(a.Y, other), W
 3890            Signed576.NarrowValue(WideArithmetic.AddSigned832(WideArithmetic.MultiplySigned576ToSigned832(a.Z, other), W
 91    }
 92
 12893    private static WideAxis3 DoubledBoundaryPoint(Signed576 x, Signed576 y, Signed576 z) => new(
 12894        Signed320.NarrowValue(WideArithmetic.AddSigned576(x, x)), Signed320.NarrowValue(WideArithmetic.AddSigned576(y, y
 12895        Signed320.NarrowValue(WideArithmetic.AddSigned576(z, z)));
 96}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Convex/CurvedPrismContact.cs

#LineLine coverage
 1//=======================================================================
 2// CurvedPrismContact.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>Complete native-yaw prism support-fan selection for finite cones and cylinders.</summary>
 14/// <content>Selects exact analytic, generator and rim contacts against native convex prisms.</content>
 15internal static partial class CurvedPrismContact
 16{
 17    internal static bool TryGetContact(Vector3d center, FixedQuaternion rotation, Vector3d localAxis,
 18        Fixed64 length, Fixed64 radius, Vector3d prismOrigin, Fixed64 yaw,
 19        ReadOnlySpan<Vector2d> offsets, Fixed64 halfThickness, bool cone, out FixedContactAnchors contact)
 20    {
 90821        contact = default;
 90822        Span<WideDirection3d> vertices = stackalloc WideDirection3d[32];
 90823        var geometry = new CurvedPrismContactGeometry(center, rotation, localAxis, length, radius,
 90824            prismOrigin, yaw, offsets, halfThickness, cone && radius != Fixed64.Zero, vertices);
 90825        Span<ulong> values = stackalloc ulong[ConvexContactCandidate.Slots * Words];
 90826        Span<int> signs = stackalloc int[ConvexContactCandidate.Slots];
 90827        var selection = new CurvedPrismContactSelection(values, signs);
 90828        Span<ulong> direction = stackalloc ulong[3 * Words];
 90829        Span<int> directionSigns = stackalloc int[3];
 90830        KeepAxis(geometry, new WideDirection3d(geometry.Axis), direction, directionSigns, ref selection);
 90831        bool minimumCertified = selection.GapSign >= 0 && HasPoleMinimumCertificate(geometry, selection);
 179232        if (!minimumCertified) KeepAxis(geometry, geometry.Plane(1), direction, directionSigns, ref selection);
 96333        if (selection.GapSign < 0) return false;
 34        // Zero meridional curvature excludes positive open vertex/rim minima,
 35        // but not negative separating ones. Keep complete closed admission
 36        // independent of the positive minimum-translation support inventory.
 85337        if (!minimumCertified && !WideConvexPrismRelations.IntersectsCurvedPrism(cone, center, rotation, localAxis,
 85338                length, radius, prismOrigin, yaw, offsets, halfThickness))
 60839            return false;
 40        // Complete admission bounds every gap below by zero; an exact initial
 41        // zero is already the earliest global minimum, including its witnesses.
 24542        minimumCertified |= selection.GapSign == 0;
 45943        if (!minimumCertified) KeepAnalytic(geometry, ref selection);
 24544        WideConvexPrismRelations.GetRoundedConvexContactCandidateDepth(selection.Candidate,
 24545            Fixed64.Zero, out Fixed64 depth, out bool clamped);
 24546        CurvedPrismRimContacts.Selection rim = default;
 47        // Complete admission bounds every support gap below by zero. An exact
 48        // analytic zero already meets that bound, so no rim can improve it.
 24549        if (!minimumCertified && selection.GapSign != 0)
 16650            CurvedPrismRimContacts.GetContact(geometry, selection.Candidate, depth, clamped,
 16651                out rim, out depth, out clamped);
 52        Vector3d normal;
 53        FixedPointAnchor shapeAnchor, prismAnchor;
 24554        if (rim.HasValue)
 3955            CurvedPrismRimContacts.GetMaterials(geometry, rim, center, rotation, prismOrigin,
 3956                out normal, out shapeAnchor, out prismAnchor);
 57        else
 20658            GetAnalyticWitnesses(geometry, selection, center, rotation, prismOrigin,
 20659                out normal, out shapeAnchor, out prismAnchor);
 24560        contact = new FixedContactAnchors(shapeAnchor, prismAnchor, normal, depth, clamped);
 24561        return true;
 62    }
 63
 64    private static void KeepAnalytic(in CurvedPrismContactGeometry geometry,
 65        ref CurvedPrismContactSelection selection)
 66    {
 26167        Span<ulong> direction = stackalloc ulong[3 * Words];
 26168        Span<int> signs = stackalloc int[3];
 26169        var axis = new WideDirection3d(geometry.Axis);
 26170        WideDirection3d up = geometry.Plane(1);
 654871        for (int index = 0; index < geometry.EdgeCount; index++)
 72        {
 304773            geometry.Edge(index, out int start, out int end);
 304774            WideDirection3d edge = Difference(geometry.Vertex(end), geometry.Vertex(start));
 304775            if (edge.IsZero) continue;
 512676            if (!selection.Domain.Enabled) edge = ReduceEdgeDirection(edge);
 284577            if (index % 3 == 0)
 92878                KeepAxis(geometry, WideDirection3d.Cross(edge, up), direction, signs, ref selection);
 79            // These rational arc endpoints also cover K=0 stationary roots,
 80            // which the quartic owner deliberately leaves to the analytic fan.
 81            // Only supporting real edges bound those arcs; face directions
 82            // above and vertex extrema below remain unrestricted.
 284583            CircularRimContactAlgebra.GetBasis(edge, out WideDirection3d first, out WideDirection3d second);
 284584            KeepAxis(geometry, first, direction, signs, ref selection, start);
 284585            KeepAxis(geometry, second, direction, signs, ref selection, start);
 284586            KeepAxis(geometry, WideDirection3d.ProjectPerpendicular(edge, axis), direction, signs, ref selection, start)
 1707087            for (int cap = -1; cap <= 1; cap += 2)
 88            {
 569089                if (geometry.IsCone && cap > 0) continue;
 452290                WideDirection3d offset = Difference(cap < 0 ? -geometry.Half : geometry.Half, geometry.Vertex(start));
 452291                KeepAxis(geometry, WideDirection3d.ProjectPerpendicular(edge, offset), direction, signs, ref selection, 
 92            }
 284593            WideDirection3d cross = WideDirection3d.Cross(axis, edge);
 284594            if (!IsBasisDirection(edge, cross))
 22495                KeepAxis(geometry, cross, direction, signs, ref selection, start);
 287996            if (selection.HasValue && selection.GapSign == 0) return;
 97        }
 22798        if (geometry.IsCone)
 10099            CurvedPrismGeneratorFeatures.KeepAll(geometry, ref selection);
 100        else
 2378101            for (int index = 0; index < geometry.VertexCount && (!selection.HasValue || selection.GapSign != 0); index++
 102            {
 103                // Open side minima use the positive vertex projection; real-edge
 104                // boundaries were visited before this final ordinary family.
 1062105                KeepAxis(geometry, WideDirection3d.ProjectPerpendicular(axis, geometry.Vertex(index)), direction, signs,
 1062106                    orientations: selection.HasValue && !selection.Domain.Enabled ? 1 : 2);
 107            }
 127108    }
 109
 110    private static bool HasPoleMinimumCertificate(in CurvedPrismContactGeometry geometry,
 111        scoped CurvedPrismContactSelection selection)
 112    {
 1204113        if (geometry.IsCone && selection.Feature > 0) return false;
 512114        var axis = new WideDirection3d(geometry.Axis);
 512115        WideDirection3d normal = selection.Feature < 0 ? -axis : axis;
 512116        Signed320 minimum = Signed320.NarrowValue(Signed576.NarrowValue(geometry.ProjectionMinimum(normal)));
 714117        if (minimum.Sign < 0) return false;
 310118        Signed320 half = Signed320.NarrowValue(Signed576.NarrowValue(WideDirection3d.Dot(geometry.Half, axis)));
 310119        Signed320 gap = WideArithmetic.SubtractSigned320(half, minimum);
 310120        Signed576 gapSquared = WideArithmetic.MultiplySigned320(gap, gap);
 310121        Signed576 radiusSquared = WideArithmetic.MultiplySigned320(geometry.Radius, geometry.Radius);
 310122        Signed832 radial = WideArithmetic.MultiplySigned576ToSigned832(radiusSquared, geometry.SquaredAxis);
 310123        bool insideBall = geometry.IsCone
 310124            ? WideArithmetic.SubtractSigned832(WideArithmetic.MultiplySigned832(radial, minimum),
 310125                WideArithmetic.MultiplySigned576ToSigned832(gapSquared, half)).Sign >= 0
 310126            : WideArithmetic.SubtractSigned832(radial, Signed832.ExtendValue(gapSquared)).Sign >= 0;
 317127        if (!insideBall) return false;
 128        // At a cap pole, C=(minimum/q)*normal is the disk center in the
 129        // opposing prism plane. If C belongs to the prism and ball(C,depth)
 130        // belongs to the primitive, their Minkowski difference contains that
 131        // ball. The pole's upper bound is therefore the global minimum.
 132        // Cylinder: depth<=half-height and depth<=R. Cone base: the exact
 133        // side-distance test reduces to R²*q*minimum >= half*gap².
 134        // All vectors here are the raw authored axis: scalars <202 bits,
 135        // plane dots <401 and complete products <610, within Signed832.
 1512136        for (int plane = 0; plane < geometry.PlaneCount; plane++)
 137        {
 732138            WideDirection3d face = geometry.Plane(plane);
 732139            if (face.IsZero) continue;
 4923140            for (int orientation = 0; orientation < 2; orientation++, face = -face)
 141            {
 1436142                Signed320 projection = Signed320.NarrowValue(Signed576.NarrowValue(WideDirection3d.Dot(face, normal)));
 1436143                Signed576 left = WideArithmetic.MultiplySigned320(minimum, projection);
 1436144                Signed832 right = WideArithmetic.MultiplySigned832(geometry.ProjectionMinimum(face), geometry.SquaredAxi
 1715145                if (WideArithmetic.SubtractSigned832(Signed832.ExtendValue(left), right).Sign < 0) return false;
 146            }
 147        }
 24148        return true;
 149    }
 150
 151    // The direction is perpendicular to edge. Each selected line was already
 152    // visited in both orientations with the same required vertex.
 153    private static bool IsBasisDirection(in WideDirection3d edge, in WideDirection3d direction) =>
 2845154        edge.X.IsZero
 2845155            ? direction.X.IsZero || direction.Y.IsZero && direction.Z.IsZero
 2845156            : direction.Y.IsZero || direction.Z.IsZero;
 157
 158    private static void KeepAxis(in CurvedPrismContactGeometry geometry, in WideDirection3d axis,
 159        scoped Span<ulong> direction, scoped Span<int> directionSigns, ref CurvedPrismContactSelection selection,
 160        int requiredVertex = -1, int orientations = 2)
 161    {
 17710162        if (selection.HasValue && selection.GapSign < 0 || axis.IsZero) return;
 163        // Rational normals need<504 bits; full candidate fields need<1475.
 164        // Twenty-four words retain them; domain witnesses keep their original stride.
 16686165        int words = selection.Domain.Enabled ? Words : 24;
 16686166        Span<ulong> values = stackalloc ulong[ConvexContactCandidate.Slots * words];
 16686167        Span<int> signs = stackalloc int[ConvexContactCandidate.Slots];
 16686168        direction = direction[..(3 * words)];
 98384169        for (int orientation = 0; orientation < orientations; orientation++)
 170        {
 32506171            WideDirection3d normal = orientation == 0 ? axis : -axis;
 32506172            if (geometry.TryBuildCandidate(normal, direction, directionSigns, values, signs, requiredVertex,
 32506173                    out int gap, out int vertex, out int feature))
 17232174                selection.Keep(geometry, values, signs, gap, vertex, feature, words);
 175        }
 16686176    }
 177
 178    internal static WideDirection3d ReduceEdgeDirection(in WideDirection3d edge)
 179    {
 180        // A positive content preserves analytic normal rays (linear crosses,
 181        // quadratic projections) and rim t/ordinals; rim N/D share its eighth power.
 182        // Real edge components fit192 bits. Domain mediants retain unreduced rays.
 7017183        Signed192 x = Signed192.NarrowValue(edge.X), y = Signed192.NarrowValue(edge.Y), z = Signed192.NarrowValue(edge.Z
 2339184        Signed192 divisor = WideArithmetic.GetGreatestCommonDivisor(
 2339185            WideArithmetic.GetGreatestCommonDivisor(x, y), z);
 2339186        return new WideDirection3d(
 2339187            Signed576.ExtendValue(WideArithmetic.DivideExactSigned192(x, divisor)),
 2339188            Signed576.ExtendValue(WideArithmetic.DivideExactSigned192(y, divisor)),
 2339189            Signed576.ExtendValue(WideArithmetic.DivideExactSigned192(z, divisor)));
 190    }
 191
 21731192    internal static WideDirection3d Difference(in WideDirection3d first, in WideDirection3d second) => new(
 21731193        WideArithmetic.SubtractSigned576(first.X, second.X), WideArithmetic.SubtractSigned576(first.Y, second.Y),
 21731194        WideArithmetic.SubtractSigned576(first.Z, second.Z));
 195}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Convex/CurvedPrismContact.CylinderBoundary.cs

#LineLine coverage
 1//=======================================================================
 2// CurvedPrismContact.CylinderBoundary.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/// <content>Reuses finite-slab active sets on one exact native boundary line.</content>
 13internal static partial class CurvedPrismContact
 14{
 15    // Native callers admit positive-radius/height cylinders with local axis Up.
 16    // The line chart is A+lambda*E; mu=0 reuses the existing affine LP owner.
 17    internal static bool TryGetCylinderBoundaryContact(in CurvedPrismContactGeometry geometry, int face,
 18        in RationalSegmentInterval clip, Fixed64 lower, Fixed64 upper,
 19        Vector3d center, FixedQuaternion rotation, Vector3d prismOrigin,
 20        out FixedContactAnchors contact, int boundaryEdge = -1, scoped CurvedPrismContactValue native = default,
 21        PrismCurvedBoundaryContactVisitor? visitor = null, int ordinal = 0)
 22    {
 1823        contact = default;
 1824        GetFacePlane(geometry, face, out WideDirection3d normal, out _, out _);
 25        System.Diagnostics.Debug.Assert(!normal.IsZero);
 1826        Span<Signed576> direction = stackalloc Signed576[3] { normal.X, normal.Y, normal.Z };
 3627        WideArithmetic.ReduceCommonScale(direction); normal = new(direction[0], direction[1], direction[2]);
 2428        if (face < 0) lower = upper = face == -1 ? -geometry.PrismHalfThickness : geometry.PrismHalfThickness;
 1829        GetNativeBoundarySegment(geometry, face >= 0 ? face : boundaryEdge, clip, lower, upper,
 1830            out WideAxis3 a, out WideAxis3 b, out Signed320 coordinateD, out var retained);
 1831        WideAxis3 e = new(WideArithmetic.SubtractSigned320(b.X, a.X), WideArithmetic.SubtractSigned320(b.Y, a.Y), WideAr
 1832        var frame = new FiniteSlabRayFrame(geometry.HeightValue, geometry.RadiusValue, coordinateD, normal, WideDirectio
 1933        if (!frame.Section.IntersectsTransformedSegment(a, b, retained)) return false;
 34        // mu=0 makes the affine LP one-dimensional: nonzero minors need
 35        // that row. Retained coefficients stay <2300 bits, discriminants
 36        // <2600 and replayed CQ points <2250. Rescaling and final frame
 37        // materialization stay <2450 bits, so 64-word banks suffice.
 1738        Span<Signed832> rows = stackalloc Signed832[16];
 1739        rows.Clear();
 1740        Signed832 one = Signed832.ExtendValue(Signed192.Signed(1));
 1741        rows[0] = retained.IsClipped ? retained.WideLowerDenominator : one;
 1742        rows[3] = retained.IsClipped ? WideArithmetic.SubtractSigned832(default, retained.WideLowerNumerator) : default;
 1743        rows[4] = retained.IsClipped ? WideArithmetic.SubtractSigned832(default, retained.WideUpperDenominator) : WideAr
 1744        rows[7] = retained.IsClipped ? retained.WideUpperNumerator : one;
 3445        rows[9] = one; rows[13] = WideArithmetic.SubtractSigned832(default, one);
 1746        Span<ulong> selectionValues = stackalloc ulong[FiniteSlabRaySelection.StorageWords];
 1747        Span<sbyte> selectionSigns = stackalloc sbyte[FiniteSlabRaySelection.SignCount];
 1748        var maximum = new FiniteSlabRaySelection(selectionValues, selectionSigns);
 49        // Initial line admission used the existing finite-section owner.
 50        // Clearance retains points that enter the cylinder during translation.
 1751        FiniteSlabRayExtrema.AccumulateNativeLine(frame, a, e, rows, ref maximum);
 52        // The admitted finite line and positive cylinder have a compact,
 53        // nonempty ray envelope, so the complete active sets retain a maximum.
 1754        maximum.GetDepth(frame, out Fixed64 depth, out bool clamped);
 55        const int words = FiniteSlabPolynomial.Words;
 3456        Span<ulong> source = stackalloc ulong[6 * words], exit = stackalloc ulong[6 * words];
 3457        Span<int> sourceSigns = stackalloc int[6], exitSigns = stackalloc int[6];
 3458        Span<ulong> fields = stackalloc ulong[4 * words], root = stackalloc ulong[2 * words + 1];
 1759        Span<int> fieldSigns = stackalloc int[4];
 1760        var denominator = ContactQuadratic.At(fields, fieldSigns, 0, words);
 1761        var term = ContactQuadratic.At(fields, fieldSigns, 1, words);
 1762        maximum.GetNativeLinePointFields(frame, a, e, source, sourceSigns, exit, exitSigns, denominator, root);
 13663        for (int axis = 0; axis < 3; axis++)
 64        {
 15365            var point = WAt(source, sourceSigns, axis); ContactQuadratic.Scale(point, Signed576.ExtendValue(geometry.Raw
 15366            point = WAt(exit, exitSigns, axis); ContactQuadratic.Scale(point, Signed576.ExtendValue(geometry.RawScale), 
 67        }
 3468        ContactQuadratic.Scale(denominator, Signed576.ExtendValue(WideArithmetic.AddSigned320(coordinateD, coordinateD))
 1769        FixedPointAnchor shapeAnchor = CreateQuadraticAnchor(geometry, center, rotation, center, exit, exitSigns, denomi
 1770        FixedPointAnchor sourceAnchor = CreateQuadraticAnchor(geometry, center, rotation, prismOrigin, source, sourceSig
 1771        contact = new(shapeAnchor, sourceAnchor, normal.Transform(geometry.WorldBasis).GetNormal(false), depth, clamped)
 2772        if (visitor != null) visitor(ordinal, contact, maximum.CompareNativeDepth(geometry, frame, native));
 1773        return true;
 74    }
 75}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Convex/CurvedPrismContact.Domain.cs

#LineLine coverage
 1//=======================================================================
 2// CurvedPrismContact.Domain.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;
 10using static FixedMathSharp.Geometry.CylinderContactAlgebra;
 11using static FixedMathSharp.Geometry.ContactQuadratic;
 12
 13namespace FixedMathSharp.Geometry;
 14
 15/// <content>Admits retained source support families before native curved minimum selection.</content>
 16internal static partial class CurvedPrismContact
 17{
 18    /// <remarks>The caller independently certifies physical source-prism overlap.
 19    /// A borrowed coplanar support supplier need not overlap; a far-boundary
 20    /// pass can also inspect a disjoint source. Restricting response supports
 21    /// never substitutes for the separate closed-solid overlap oracle.</remarks>
 22    internal static bool TryGetContact(in CurvedPrismContactGeometry geometry, PrismCurvedContactDomain domain,
 23        Vector3d center, FixedQuaternion rotation, Vector3d prismOrigin,
 24        out FixedContactAnchors contact, out int face, out bool physical, out int certificate,
 25        ReadOnlySpan<PrismCurvedBoundaryLine> boundaryLines = default,
 26        PrismCurvedBoundaryContactVisitor? boundaryVisitor = null, ConePrismBoundaryContacts? coneBoundary = null)
 27    {
 25628        contact = default; face = -3; physical = false; certificate = -1;
 6429        Span<ulong> values = stackalloc ulong[ConvexContactCandidate.Slots * Words];
 6430        Span<int> signs = stackalloc int[ConvexContactCandidate.Slots];
 6431        var selection = new CurvedPrismContactSelection(values, signs, domain);
 12832        Span<ulong> direction = stackalloc ulong[3 * Words]; Span<int> directionSigns = stackalloc int[3];
 33        // A same-plane full-support certificate supplies a cheap exact bound
 34        // before any large witness matching or quartic chart construction.
 20935        foreach (var proof in domain.Certificates)
 36        {
 4137            if (!proof.Physical && !domain.IncludeFarBoundary) continue;
 4038            GetFacePlane(geometry, proof.Face, out WideDirection3d plane, out _, out _);
 4039            KeepAxis(geometry, plane, direction, directionSigns, ref selection);
 40            System.Diagnostics.Debug.Assert(selection.HasValue);
 4041            if (selection.GapSign == 0) break;
 42        }
 6443        if (!domain.Edges.IsEmpty)
 44        {
 4845            KeepAxis(geometry, new WideDirection3d(geometry.Axis), direction, directionSigns, ref selection);
 9546            if (!selection.HasValue || selection.GapSign != 0) KeepAxis(geometry, geometry.Plane(1), direction, directio
 9547            if (!selection.HasValue || selection.GapSign != 0) KeepAnalytic(geometry, ref selection);
 48        }
 12849        Fixed64 depth = Fixed64.Zero; bool clamped = false;
 9550        if (selection.HasValue) WideConvexPrismRelations.GetRoundedConvexContactCandidateDepth(selection.Candidate,
 3151            Fixed64.Zero, out depth, out clamped);
 6452        CurvedPrismRimContacts.Selection rim = default;
 6453        if (!domain.Edges.IsEmpty && (!selection.HasValue || selection.GapSign != 0))
 4754            CurvedPrismRimContacts.GetContact(geometry, selection.Candidate, depth, clamped, out rim, out depth, out cla
 4755                domain, selection.HasValue);
 6456        var native = new CurvedPrismContactValue(selection.Candidate, selection.HasValue, rim);
 15657        for (int index = 0; index < boundaryLines.Length; index++)
 58        {
 1459            var line = boundaryLines[index];
 60            // The producer qualifies independent source domains. Numeric
 61            // line competition does not change this native minimum or infer
 62            // ownership from a coincident face or a preferred support point.
 1463            if (geometry.IsCone)
 64            {
 65                System.Diagnostics.Debug.Assert(coneBoundary != null);
 466                coneBoundary!.TryGetContact(geometry, line.Face, line.Clip, line.Lower, line.Upper,
 467                    center, rotation, prismOrigin, out _, line.BoundaryEdge, native, boundaryVisitor, index);
 68            }
 1069            else TryGetCylinderBoundaryContact(geometry, line.Face, line.Clip, line.Lower, line.Upper,
 1070                center, rotation, prismOrigin, out _, line.BoundaryEdge, native, boundaryVisitor, index);
 71        }
 6472        if (rim.HasValue)
 73        {
 1174            CurvedPrismRimContacts.GetMaterials(geometry, rim, center, rotation, prismOrigin, out Vector3d normal,
 1175                out FixedPointAnchor shapeAnchor, out FixedPointAnchor prismAnchor);
 3376            contact = new(shapeAnchor, prismAnchor, normal, depth, clamped); physical = rim.Physical; return true;
 77        }
 7578        if (!selection.HasValue) return false;
 3179        if (selection.Certificate >= 0)
 80        {
 3281            certificate = selection.Certificate; var proof = domain.Certificates[certificate];
 4882            var supplied = proof.Contact; face = proof.Face; physical = proof.Physical;
 3283            contact = new(supplied.FirstAnchor, supplied.SecondAnchor, supplied.Normal, depth, clamped); return true;
 84        }
 1585        var window = GetDomainWindow(domain, selection.Window);
 86        // Keep admitted this unchanged candidate/window with the same exact
 87        // matcher. Only final normal/anchor materialization is added here.
 1588        bool matched = TryGetAnalyticWitnesses(geometry, selection, center, rotation, prismOrigin,
 1589            out Vector3d analyticNormal, out FixedPointAnchor shape, out FixedPointAnchor target, out physical, window);
 90        System.Diagnostics.Debug.Assert(matched);
 3091        contact = new(shape, target, analyticNormal, depth, clamped); return true;
 92    }
 93
 94    internal static bool TryAdmitAnalyticCandidate(in CurvedPrismContactGeometry geometry,
 95        PrismCurvedContactDomain domain, ReadOnlySpan<ulong> values, ReadOnlySpan<int> signs,
 96        int gap, int vertex, int feature, out int window, out int certificate)
 97    {
 431098        window = 0; certificate = -1; bool physical;
 225799        if (gap < 0) return false;
 4382100        for (int index = 0; index < domain.Certificates.Length; index++)
 101        {
 162102            var proof = domain.Certificates[index];
 162103            if (!proof.Physical && !domain.IncludeFarBoundary) continue;
 162104            GetFacePlane(geometry, proof.Face, out WideDirection3d axis, out _, out _);
 162105            if (IsFaceDirection(values, signs, axis))
 48106            { certificate = index; return true; }
 107        }
 108        System.Diagnostics.Debug.Assert(!domain.Edges.IsEmpty);
 109        // Face directions belong exclusively to the complete full-support
 110        // certificate inventory. Do not rediscover an absent face proof by
 111        // matching the same closed family through its edge endpoints.
 21104112        for (int face = -2; face < geometry.VertexCount / 2; face++)
 113        {
 9615114            GetFacePlane(geometry, face, out WideDirection3d axis, out _, out _);
 10707115            if (IsFaceDirection(values, signs, axis)) return false;
 116        }
 937117        Span<ulong> copy = stackalloc ulong[ConvexContactCandidate.Slots * Words];
 937118        Span<int> copySigns = stackalloc int[ConvexContactCandidate.Slots];
 1874119        values.CopyTo(copy); signs.CopyTo(copySigns);
 937120        var candidate = new CurvedPrismContactSelection(copy, copySigns)
 937121            { HasValue = true, GapSign = gap, Vertex = vertex, Feature = feature };
 3918122        for (int index = 0; index < domain.Edges.Length; index++)
 123        {
 1037124            var edge = domain.Edges[index];
 1037125            if (edge.ReferenceVertex != vertex && DirectionDotSign(values, signs, Difference(geometry.Vertex(edge.Refere
 126            // A non-endpoint support on a real edge requires the whole edge
 127            // to tie. Reject incompatible directions before matching witnesses.
 188128            var interval = edge.Interval;
 188129            bool endpoint = edge.Point && (!interval.IsClipped || interval.LowerNumerator.IsZero
 188130                || interval.LowerNumerator.Equals(interval.LowerDenominator));
 188131            if (!endpoint)
 132            {
 161133                geometry.Edge(edge.Edge, out int first, out int last);
 161134                if (DirectionDotSign(values, signs, Difference(geometry.Vertex(last), geometry.Vertex(first))) != 0) con
 135            }
 100136            bool admits = true;
 233137            foreach (var covector in domain.FanCovectors.Slice(edge.FanStart, edge.FanCount))
 49138                if (DirectionDotSign(values, signs, covector) < 0) { admits = false; break; }
 100139            if (!admits) continue;
 87140            if (TryGetAnalyticWitnesses(geometry, candidate, default, FixedQuaternion.Identity, default,
 87141                out _, out _, out _, out physical, new FaceWindow(edge), materialize: false)
 117142                && (physical || domain.IncludeFarBoundary)) { window = -index - 1; return true; }
 143        }
 922144        return false;
 145    }
 146
 147    private static FaceWindow GetDomainWindow(PrismCurvedContactDomain domain, int window)
 15148        => new(domain.Edges[-window - 1]);
 149
 150    private static bool IsFaceDirection(ReadOnlySpan<ulong> values, ReadOnlySpan<int> signs, in WideDirection3d axis)
 9777151        => DirectionDotSign(values, signs, axis) > 0
 9777152        && DirectionDotSign(values, signs, new(default, axis.Z, WideArithmetic.Negate(axis.Y))) == 0
 9777153        && DirectionDotSign(values, signs, new(WideArithmetic.Negate(axis.Z), default, axis.X)) == 0
 9777154        && DirectionDotSign(values, signs, new(axis.Y, WideArithmetic.Negate(axis.X), default)) == 0;
 155
 156    private static int DirectionDotSign(ReadOnlySpan<ulong> direction, ReadOnlySpan<int> directionSigns, in WideDirectio
 157    {
 18487158        if (delta.IsZero) return 0;
 17491159        if ((directionSigns[3] | directionSigns[4] | directionSigns[5]) == 0
 17491160            && WideArithmetic.GetMagnitudeBitLength(Slot(direction, 0)) < 576
 17491161            && WideArithmetic.GetMagnitudeBitLength(Slot(direction, 1)) < 576
 17491162            && WideArithmetic.GetMagnitudeBitLength(Slot(direction, 2)) < 576)
 163        {
 164            // Native rational directions and fan covectors need <576/<234
 165            // bits. Their complete dot fits Signed832 without CQ scratch.
 15881166            var normal = new WideDirection3d(
 15881167                directionSigns[0] == 0 ? default : CurvedPrismContactGeometry.ReadDirectionComponent(Slot(direction, 0),
 15881168                directionSigns[1] == 0 ? default : CurvedPrismContactGeometry.ReadDirectionComponent(Slot(direction, 1),
 15881169                directionSigns[2] == 0 ? default : CurvedPrismContactGeometry.ReadDirectionComponent(Slot(direction, 2),
 15881170            return WideDirection3d.Dot(normal, delta).Sign;
 171        }
 1610172        return DirectionDotQuadraticSign(direction, directionSigns, delta);
 173    }
 174
 175    // Keep the large CQ stack frame out of rational fan checks.
 176    [MethodImpl(MethodImplOptions.NoInlining)]
 177    private static int DirectionDotQuadraticSign(ReadOnlySpan<ulong> direction, ReadOnlySpan<int> directionSigns, in Wid
 178    {
 3220179        Span<ulong> fields = stackalloc ulong[8 * Words]; Span<int> signs = stackalloc int[8];
 4830180        var value = At(fields, signs, 0); var component = At(fields, signs, 1); var term = At(fields, signs, 2);
 1610181        value.Clear();
 12880182        for (int axis = 0; axis < 3; axis++)
 183        {
 9660184            Slot(direction, axis).CopyTo(component.Rational); Slot(direction, axis + 3).CopyTo(component.Radical);
 9660185            component.Signs[0] = directionSigns[axis]; component.Signs[1] = directionSigns[axis + 3];
 9660186            Scale(component, axis == 0 ? delta.X : axis == 1 ? delta.Y : delta.Z, term); value.Add(term);
 187        }
 1610188        return value.Sign(Slot(direction, 6));
 189    }
 190
 191    private static bool ClipRealEdgeWindow(in CurvedPrismContactGeometry geometry, in FaceWindow window,
 192        Span<ulong> start, Span<int> startSigns, Span<ulong> delta, Span<int> deltaSigns,
 193        ContactQuadratic denominator, ReadOnlySpan<ulong> root, ContactQuadratic lower,
 194        ContactQuadratic lowerDen, ContactQuadratic upper, ContactQuadratic upperDen)
 195    {
 76196        geometry.Edge(window.SourceEdge, out int first, out int last);
 152197        int vertex = window.SourceEdge / 3, kind = window.SourceEdge % 3;
 152198        WideDirection3d a = geometry.Vertex(first), edge = Difference(geometry.Vertex(last), a);
 76199        WideDirection3d firstPlane = kind == 2 ? geometry.Plane(3 + (vertex == 0 ? geometry.VertexCount / 2 - 1 : vertex
 76200        WideDirection3d secondPlane = geometry.Plane(3 + vertex);
 76201        Span<WideDirection3d> planes = stackalloc WideDirection3d[2] { firstPlane, secondPlane };
 432202        foreach (var plane in planes)
 203        {
 144204            Signed832 c = WideDirection3d.Dot(plane, a);
 144205            if (!ClipFaceHalfplane(plane, c, start, startSigns, delta, deltaSigns, denominator, root, lower, lowerDen, u
 144206                || !ClipFaceHalfplane(-plane, WideArithmetic.SubtractSigned832(default, c), start, startSigns, delta, de
 152207                    denominator, root, lower, lowerDen, upper, upperDen)) return false;
 208        }
 136209        Signed832 dot = WideDirection3d.Dot(edge, a), squared = edge.SquaredLength;
 68210        var clip = window.Tangent;
 136211        Signed320 ln = clip.IsClipped ? clip.LowerNumerator : default, ld = clip.IsClipped ? clip.LowerDenominator : Sig
 136212        Signed320 un = clip.IsClipped ? clip.UpperNumerator : Signed320.One, ud = clip.IsClipped ? clip.UpperDenominator
 68213        return ClipFaceHalfplane(ScaleAxis(edge, ld), SumProducts(dot, ld, squared, ln), start, startSigns, delta, delta
 68214            denominator, root, lower, lowerDen, upper, upperDen)
 68215            && ClipFaceHalfplane(-ScaleAxis(edge, ud), WideArithmetic.SubtractSigned832(default, SumProducts(dot, ud, sq
 68216                start, startSigns, delta, deltaSigns, denominator, root, lower, lowerDen, upper, upperDen);
 217    }
 218
 219    private static bool IsInsideRealEdgeWindow(in CurvedPrismContactGeometry geometry, in FaceWindow window,
 220        Span<ulong> point, Span<int> pointSigns, ContactQuadratic denominator, ReadOnlySpan<ulong> root)
 221    {
 82222        geometry.Edge(window.SourceEdge, out int first, out int last);
 164223        var a = geometry.Vertex(first); var edge = Difference(geometry.Vertex(last), a);
 82224        int words = denominator.FieldWords;
 164225        Span<ulong> fields = stackalloc ulong[8 * words]; Span<int> signs = stackalloc int[8];
 246226        var n = WAt(fields, signs, 0); var d = WAt(fields, signs, 1); var work = WAt(fields, signs, 2);
 246227        DotQuadratic(edge, point, pointSigns, n); Scale(denominator, WideDirection3d.Dot(edge, a), work); n.Add(work, -1
 82228        Scale(denominator, edge.SquaredLength, d);
 82229        var clip = window.Tangent;
 82230        Scale(n, Signed576.ExtendValue(clip.IsClipped ? clip.LowerDenominator : Signed320.One), work);
 164231        Scale(d, Signed576.ExtendValue(clip.IsClipped ? clip.LowerNumerator : default), n); work.Add(n, -1);
 105232        if (work.Sign(root) <= 0) return false;
 177233        DotQuadratic(edge, point, pointSigns, n); Scale(denominator, WideDirection3d.Dot(edge, a), work); n.Add(work, -1
 59234        Scale(n, Signed576.ExtendValue(clip.IsClipped ? clip.UpperDenominator : Signed320.One), work);
 118235        Scale(d, Signed576.ExtendValue(clip.IsClipped ? clip.UpperNumerator : Signed320.One), n); work.Add(n, -1);
 59236        return work.Sign(root) < 0;
 237    }
 238}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Convex/CurvedPrismContact.Faces.cs

#LineLine coverage
 1//=======================================================================
 2// CurvedPrismContact.Faces.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;
 10using static FixedMathSharp.Geometry.ContactQuadratic;
 11
 12namespace FixedMathSharp.Geometry;
 13
 14/// <content>Matches complete curved supports against retained native prism face windows.</content>
 15internal static partial class CurvedPrismContact
 16{
 17    // Side faces use their footprint edge index; -1/-2 identify bottom/top.
 18    // This is a full-support certificate, not an arbitrary finite-face maximum:
 19    // a cut that removes that support still needs the finite boundary events.
 20    internal static bool TryGetFaceSupportContact(in CurvedPrismContactGeometry geometry, int face,
 21        in RationalSegmentInterval tangentClip, Fixed64 lowerY, Fixed64 upperY,
 22        Vector3d center, FixedQuaternion rotation, Vector3d prismOrigin, bool includeRecovery,
 23        out FixedContactAnchors contact, out bool physical)
 24    {
 20225        contact = default; physical = false;
 10126        GetFacePlane(geometry, face, out WideDirection3d axis, out Signed832 minimum, out int vertex);
 27        System.Diagnostics.Debug.Assert(!axis.IsZero);
 20228        Span<ulong> direction = stackalloc ulong[3 * Words]; Span<int> directionSigns = stackalloc int[3];
 10129        Span<ulong> values = stackalloc ulong[ConvexContactCandidate.Slots * Words];
 10130        Span<int> signs = stackalloc int[ConvexContactCandidate.Slots];
 10131        WriteDirection(-axis, direction, directionSigns);
 10132        int other = geometry.BuildPlaneCandidate(direction, directionSigns, -axis,
 10133            WideArithmetic.SubtractSigned832(default, minimum), values, signs, out _);
 34        // An outside source plane cannot supply an initial-section physical row.
 10935        if (!includeRecovery && other < 0) return false;
 9336        WriteDirection(axis, direction, directionSigns);
 9337        int gap = geometry.BuildPlaneCandidate(direction, directionSigns, axis, minimum, values, signs, out int feature)
 9738        if (gap < 0) return false;
 8939        var selection = new CurvedPrismContactSelection(values, signs)
 8940            { HasValue = true, GapSign = gap, Vertex = vertex, Feature = feature };
 8941        if (!TryGetAnalyticWitnesses(geometry, selection, center, rotation, prismOrigin,
 8942                out Vector3d normal, out FixedPointAnchor shape, out FixedPointAnchor target, out physical,
 11843                new FaceWindow(face, tangentClip, lowerY, upperY)) || !includeRecovery && !physical) return false;
 6044        WideConvexPrismRelations.GetRoundedConvexContactCandidateDepth(selection.Candidate,
 6045            Fixed64.Zero, out Fixed64 depth, out bool clamped);
 12046        contact = new(shape, target, normal, depth, clamped); return true;
 47    }
 48
 49    internal static void GetFacePlane(in CurvedPrismContactGeometry geometry, int face,
 50        out WideDirection3d axis, out Signed832 minimum, out int vertex)
 51    {
 994752        axis = face < 0 ? geometry.Plane(1) : geometry.Plane(3 + face);
 1211953        if (face == -2) axis = -axis;
 994754        vertex = face < 0 ? (face == -1 ? 0 : 1) : 2 * face;
 994755        minimum = WideDirection3d.Dot(axis, geometry.Vertex(vertex));
 994756        if (WideArithmetic.SubtractSigned832(geometry.ProjectionMinimum(axis), minimum).Sign != 0)
 257        { axis = -axis; minimum = WideArithmetic.SubtractSigned832(default, minimum); }
 994758    }
 59
 60    private readonly struct FaceWindow
 61    {
 62        internal readonly bool Enabled;
 63        internal readonly int Face, SourceEdge;
 64        internal readonly bool Open;
 65        internal readonly RationalSegmentInterval Tangent;
 66        internal readonly Fixed64 Lower, Upper;
 67        internal FaceWindow(int face, RationalSegmentInterval tangent, Fixed64 lower, Fixed64 upper)
 71268        { Enabled = true; Face = face; SourceEdge = -1; Open = false; Tangent = tangent; Lower = lower; Upper = upper; }
 69        internal FaceWindow(in PrismCurvedEdgeWindow edge)
 40870        { Enabled = true; Face = -1; SourceEdge = edge.Edge; Open = !edge.Point;
 30671          Tangent = edge.Interval; Lower = Upper = default; }
 72    }
 73
 74    private static bool ClipFaceWindow(in CurvedPrismContactGeometry geometry, in FaceWindow window,
 75        Span<ulong> start, Span<int> startSigns, Span<ulong> delta, Span<int> deltaSigns,
 76        ContactQuadratic denominator, ReadOnlySpan<ulong> root, ContactQuadratic lower,
 77        ContactQuadratic lowerDen, ContactQuadratic upper, ContactQuadratic upperDen)
 78    {
 21779        if (window.SourceEdge >= 0) return ClipRealEdgeWindow(geometry, window, start, startSigns, delta, deltaSigns,
 7680            denominator, root, lower, lowerDen, upper, upperDen);
 6581        Span<WideDirection3d> normals = stackalloc WideDirection3d[4];
 6582        Span<Signed832> constants = stackalloc Signed832[4];
 6583        int count = GetFaceWindowHalfplanes(geometry, window.Face, window.Tangent, window.Lower, window.Upper, normals, 
 25084        for (int index = 0; index < count; index++)
 6485            if (!ClipFaceHalfplane(normals[index], constants[index], start, startSigns, delta, deltaSigns,
 6886                denominator, root, lower, lowerDen, upper, upperDen)) return false;
 6187        return true;
 88    }
 89
 90    private static int GetFaceWindowHalfplanes(in CurvedPrismContactGeometry geometry, int face,
 91        in RationalSegmentInterval tangent, Fixed64 lowerY, Fixed64 upperY,
 92        Span<WideDirection3d> normals, Span<Signed832> constants)
 93    {
 9294        if (face < 0) return 0; // The complete cap footprint is already clipped by the prism.
 3895        geometry.Edge(3 * face, out int first, out int last);
 7696        WideDirection3d a = geometry.Vertex(first), edge = Difference(geometry.Vertex(last), a);
 7697        Signed832 dot = WideDirection3d.Dot(edge, a), squared = edge.SquaredLength;
 3898        Signed320 ln = tangent.IsClipped ? tangent.LowerNumerator : default;
 3899        Signed320 ld = tangent.IsClipped ? tangent.LowerDenominator : Signed320.One;
 38100        Signed320 un = tangent.IsClipped ? tangent.UpperNumerator : Signed320.One;
 38101        Signed320 ud = tangent.IsClipped ? tangent.UpperDenominator : Signed320.One;
 38102        int count = 0;
 78103        if (!ln.IsZero) { normals[count] = ScaleAxis(edge, ld); constants[count++] = SumProducts(dot, ld, squared, ln); 
 38104        if (!un.Equals(ud))
 36105        { normals[count] = -ScaleAxis(edge, ud); constants[count++] = WideArithmetic.SubtractSigned832(default, SumProdu
 38106        Fixed64 half = geometry.PrismHalfThickness;
 38107        if (lowerY > -half || upperY < half)
 108        {
 19109            WideDirection3d up = geometry.Plane(1);
 19110            Signed832 bottom = WideDirection3d.Dot(up, geometry.Vertex(0));
 19111            Signed832 height = WideArithmetic.SubtractSigned832(WideDirection3d.Dot(up, geometry.Vertex(1)), bottom);
 19112            Signed320 whole = Signed320.ExtendValue(WideArithmetic.AddSigned192(Signed192.Raw(half), Signed192.Raw(half)
 19113            if (lowerY > -half)
 34114            { normals[count] = ScaleAxis(up, whole); constants[count++] = SumProducts(bottom, whole, height,
 17115                Signed320.ExtendValue(WideArithmetic.AddSigned192(Signed192.Raw(lowerY), Signed192.Raw(half)))); }
 19116            if (upperY < half)
 34117            { normals[count] = -ScaleAxis(up, whole); constants[count++] = WideArithmetic.SubtractSigned832(default, Sum
 17118                Signed320.ExtendValue(WideArithmetic.AddSigned192(Signed192.Raw(upperY), Signed192.Raw(half))))); }
 119        }
 38120        return count;
 121    }
 122
 123    // Native retained cut ratios fit Signed320. Their scaled edge normals stay
 124    // below 486 bits and plane constants below 652; the witness banks remain sufficient.
 207125    private static WideDirection3d ScaleAxis(in WideDirection3d axis, Signed320 scale) => new(
 207126        Signed576.NarrowValue(WideArithmetic.MultiplySigned576ToSigned832(axis.X, scale)),
 207127        Signed576.NarrowValue(WideArithmetic.MultiplySigned576ToSigned832(axis.Y, scale)),
 207128        Signed576.NarrowValue(WideArithmetic.MultiplySigned576ToSigned832(axis.Z, scale)));
 129
 130    private static Signed832 SumProducts(Signed832 first, Signed320 firstScale, Signed832 second, Signed320 secondScale)
 207131        WideArithmetic.AddSigned832(WideArithmetic.MultiplySigned832(first, firstScale),
 207132            WideArithmetic.MultiplySigned832(second, secondScale));
 133
 134    private static bool ClipFaceHalfplane(in WideDirection3d normal, Signed832 constant,
 135        Span<ulong> start, Span<int> startSigns, Span<ulong> delta, Span<int> deltaSigns,
 136        ContactQuadratic denominator, ReadOnlySpan<ulong> root, ContactQuadratic lower,
 137        ContactQuadratic lowerDen, ContactQuadratic upper, ContactQuadratic upperDen)
 138    {
 707139        int words = denominator.FieldWords;
 1414140        Span<ulong> values = stackalloc ulong[6 * words]; Span<int> signs = stackalloc int[6];
 1414141        var a = WAt(values, signs, 0); var b = WAt(values, signs, 1);
 707142        var term = WAt(values, signs, 2);
 2121143        DotQuadratic(normal, start, startSigns, a); Scale(denominator, constant, term); a.Add(term, -1);
 707144        DotQuadratic(normal, delta, deltaSigns, b);
 707145        return ClipBound(a, b, root, lower, lowerDen, upper, upperDen);
 146    }
 147
 148    private static bool ClipBound(ContactQuadratic a, ContactQuadratic b, ReadOnlySpan<ulong> root,
 149        ContactQuadratic lower, ContactQuadratic lowerDen, ContactQuadratic upper, ContactQuadratic upperDen)
 150    {
 807151        int words = Math.Max(a.FieldWords, b.FieldWords);
 1614152        Span<ulong> values = stackalloc ulong[4 * words]; Span<int> signs = stackalloc int[4];
 1614153        var comparison = WAt(values, signs, 0); var term = WAt(values, signs, 1);
 807154        int slope = b.Sign(root);
 1418155        if (slope == 0) return a.Sign(root) >= 0;
 392156        a.MultiplySign(-slope); b.MultiplySign(slope);
 392157        var bound = slope > 0 ? lower : upper; var boundDen = slope > 0 ? lowerDen : upperDen;
 588158        Multiply(a, boundDen, root, comparison); Multiply(bound, b, root, term); comparison.Add(term, -1);
 338159        if (comparison.Sign(root) * slope > 0) { a.CopyTo(bound); b.CopyTo(boundDen); }
 196160        return true;
 161    }
 162
 163    private static void GetCurvedImplicit(in CurvedPrismContactGeometry geometry,
 164        Span<ulong> point, Span<int> pointSigns, ContactQuadratic denominator, ReadOnlySpan<ulong> root, ContactQuadrati
 165    {
 166        // This runs before support-parameter blending. The squared point and
 167        // root products add at most twenty limbs for all retained axis/radius
 168        // factors; size by active coefficients rather than padded witnesses.
 200169        int active = ContactQuadratic.ActiveWords(denominator);
 2200170        for (int axis = 0; axis < 3; axis++) active = Math.Max(active, ContactQuadratic.ActiveWords(WAt(point, pointSign
 200171        int words = 2 * active + WideArithmetic.GetActiveMagnitudeLength(root) + 20;
 400172        Span<ulong> values = stackalloc ulong[16 * words]; Span<int> signs = stackalloc int[16];
 400173        var axial = At(values, signs, 0, words); var maximum = At(values, signs, 1, words);
 400174        var work = At(values, signs, 2, words); var product = At(values, signs, 3, words);
 400175        var radial = At(values, signs, 4, words); var component = At(values, signs, 5, words);
 400176        var d = At(values, signs, 6, words); var limit = At(values, signs, 7, words);
 600177        denominator.CopyTo(d); axial.Clear(); radial.Clear();
 1600178        for (int axis = 0; axis < 3; axis++)
 179        {
 600180            WAt(point, pointSigns, axis).CopyTo(component);
 600181            Scale(component, Signed576.ExtendValue(axis == 0 ? geometry.Axis.X : axis == 1 ? geometry.Axis.Y : geometry.
 1800182            axial.Add(work); Multiply(component, component, root, work); radial.Add(work);
 183        }
 200184        Scale(d, WideArithmetic.MultiplySigned320(geometry.SquaredAxis, geometry.HalfFactor), maximum);
 200185        Scale(radial, Signed576.ExtendValue(geometry.SquaredAxis), work);
 600186        Multiply(axial, axial, root, product); work.Add(product, -1); work.CopyTo(radial);
 200187        Signed576 radiusSquared = WideArithmetic.MultiplySigned320(geometry.Radius, geometry.Radius);
 200188        if (geometry.IsCone && !geometry.HalfFactor.IsZero)
 189        {
 130190            Signed576 factor = Signed576.ExtendValue(WideArithmetic.MultiplySigned192(geometry.HalfFactor, geometry.Half
 130191            factor = Signed576.NarrowValue(WideArithmetic.MultiplySigned576ToSigned832(factor, geometry.SquaredAxis));
 260192            factor = WideArithmetic.AddSigned576(factor, factor); factor = WideArithmetic.AddSigned576(factor, factor);
 390193            Scale(radial, factor, work); maximum.CopyTo(component); component.Add(axial, -1);
 260194            Multiply(component, component, root, product); Scale(product, radiusSquared, limit);
 195        }
 196        else
 197        {
 210198            radial.CopyTo(work); Multiply(d, d, root, product); Scale(product, radiusSquared, component);
 70199            Scale(component, Signed576.ExtendValue(geometry.SquaredAxis), limit);
 200        }
 400201        work.Add(limit, -1); work.CopyTo(result);
 200202    }
 203
 204}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Convex/CurvedPrismContact.Witnesses.cs

#LineLine coverage
 1//=======================================================================
 2// CurvedPrismContact.Witnesses.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;
 10using static FixedMathSharp.Geometry.ContactQuadratic;
 11
 12namespace FixedMathSharp.Geometry;
 13
 14/// <content>Matches the retained analytic feature before any physical point rounds.</content>
 15internal static partial class CurvedPrismContact
 16{
 17    // Generator normals have effective height <600 bits, their squared norm
 18    // <1202, and the common support denominator <832. Translated segment
 19    // numerators are <2200 bits; plane bounds <2440; cross-bound comparisons
 20    // <4880 and final coordinates (including frame scales) <4820. Pole
 21    // matching's squared disk test is <5700; its displacement is identically
 22    // zero, so clipping never multiplies two pole interval bounds. Keep all
 23    // products in 7168-bit banks; candidate ranking still uses forty.
 24    private const int WitnessWords = 112;
 25
 26    private static void GetAnalyticWitnesses(in CurvedPrismContactGeometry geometry,
 27        scoped CurvedPrismContactSelection selection, Vector3d center, FixedQuaternion rotation,
 28        Vector3d prismOrigin, out Vector3d normal, out FixedPointAnchor shapeAnchor, out FixedPointAnchor prismAnchor)
 29    {
 20630        bool matched = TryGetAnalyticWitnesses(geometry, selection, center, rotation, prismOrigin,
 20631            out normal, out shapeAnchor, out prismAnchor, out _, default);
 32        System.Diagnostics.Debug.Assert(matched);
 20633    }
 34
 35    private static bool TryGetAnalyticWitnesses(in CurvedPrismContactGeometry geometry,
 36        scoped CurvedPrismContactSelection selection, Vector3d center, FixedQuaternion rotation,
 37        Vector3d prismOrigin, out Vector3d normal, out FixedPointAnchor shapeAnchor, out FixedPointAnchor prismAnchor,
 38        out bool physical, in FaceWindow window, bool materialize = true)
 39    {
 40        // Only a clipped algebraic cone-generator family can grow its physical
 41        // parameter beyond the ordinary bound. Rational native face normals,
 42        // pole disks and unique witnesses retain the existing smaller banks.
 39743        int words = window.Enabled && window.SourceEdge >= 0 && geometry.IsCone
 39744            && selection.Feature == CurvedPrismContactSelection.Free ? 192 : WitnessWords;
 79445        shapeAnchor = prismAnchor = default; physical = false;
 39746        normal = default;
 39747        if (materialize)
 48        {
 31049            Span<ulong> world = stackalloc ulong[7 * Words];
 31050            Span<int> worldSigns = stackalloc int[7];
 62051            world.Clear(); worldSigns.Clear();
 31052            WriteWorldDirection(geometry.WorldBasis, selection.Values[..(3 * Words)], selection.Signs[..3],
 31053                world[..(3 * Words)], worldSigns[..3]);
 31054            WriteWorldDirection(geometry.WorldBasis, selection.Values.Slice(3 * Words, 3 * Words), selection.Signs.Slice
 31055                world.Slice(3 * Words, 3 * Words), worldSigns.Slice(3, 3));
 31056            Slot(selection.Values, 6).CopyTo(Slot(world, 6));
 31057            normal = WideConvexPrismRelations.GetConvexContactCandidateNormal(new ConvexContactCandidate(world, worldSig
 58        }
 59
 39760        Span<ulong> root = stackalloc ulong[words];
 79461        root.Clear(); Slot(selection.Values, 6).CopyTo(root);
 39762        Span<ulong> work = stackalloc ulong[24 * words];
 39763        Span<int> signs = stackalloc int[24];
 79464        ContactQuadratic metric = WAt(work, signs, 0), axial = WAt(work, signs, 1);
 79465        ContactQuadratic minimum = WAt(work, signs, 2), supportDenominator = WAt(work, signs, 3);
 79466        ContactQuadratic temporary = WAt(work, signs, 4), product = WAt(work, signs, 5);
 79467        ContactQuadratic gap = WAt(work, signs, 6), q = WAt(work, signs, 7);
 39768        Span<ulong> n = stackalloc ulong[6 * words];
 39769        Span<int> nSigns = stackalloc int[6];
 317670        for (int axis = 0; axis < 3; axis++)
 71        {
 119172            ContactQuadratic component = WAt(n, nSigns, axis);
 119173            component.Clear();
 119174            Slot(selection.Values, axis).CopyTo(component.Rational);
 119175            Slot(selection.Values, axis + 3).CopyTo(component.Radical);
 238276            component.Signs[0] = selection.Signs[axis]; component.Signs[1] = selection.Signs[axis + 3];
 77        }
 39778        metric.Clear();
 317679        for (int axis = 0; axis < 3; axis++)
 80        {
 119181            Multiply(WAt(n, nSigns, axis), WAt(n, nSigns, axis), root, temporary);
 119182            metric.Add(temporary);
 83        }
 39784        DotQuadratic(new WideDirection3d(geometry.Axis), n, nSigns, axial);
 85        // Selection retained an exact minimum vertex for this same normal.
 39786        DotQuadratic(geometry.Vertex(selection.Vertex), n, nSigns, minimum);
 39787        q.Set(Signed576.ExtendValue(geometry.SquaredAxis));
 88
 39789        Span<ulong> support = stackalloc ulong[6 * words];
 39790        Span<int> supportSigns = stackalloc int[6];
 39791        Span<ulong> displacement = stackalloc ulong[6 * words];
 39792        Span<int> displacementSigns = stackalloc int[6];
 79493        displacement.Clear(); displacementSigns.Clear();
 39794        Multiply(metric, q, root, temporary);
 79495        Multiply(axial, axial, root, product); temporary.Add(product, -1);
 39796        bool pole = temporary.Sign(root) == 0;
 39797        if (pole)
 98        {
 99            // The pole's support disk is free in two dimensions. Select a
 100            // finite prism point inside that disk before translating it back.
 112101            if (!GetPoleSupport(geometry, selection, n, nSigns, metric, minimum,
 115102                support, supportSigns, supportDenominator, window)) return false;
 103        }
 285104        else if (geometry.IsCone && selection.Feature == CurvedPrismContactSelection.Free)
 105        {
 106            // On the generator seam sqrt(q*(q*n²-h²))=2*q*H.n/R.
 107            // Rationalizing with that exact equality keeps one quadratic field.
 64108            DotQuadratic(geometry.Half, n, nSigns, supportDenominator);
 64109            Scale(supportDenominator, Signed576.ExtendValue(geometry.SquaredAxis), temporary);
 128110            temporary.CopyTo(supportDenominator); supportDenominator.Add(temporary);
 64111            Signed576 radiusSquared = WideArithmetic.MultiplySigned320(geometry.Radius, geometry.Radius);
 512112            for (int axis = 0; axis < 3; axis++)
 113            {
 192114                ContactQuadratic start = WAt(support, supportSigns, axis);
 192115                ContactQuadratic delta = WAt(displacement, displacementSigns, axis);
 192116                Scale(supportDenominator, Component(geometry.Half, axis), start);
 384117                start.CopyTo(delta, -1); delta.Add(delta);
 192118                Scale(WAt(n, nSigns, axis), Signed576.ExtendValue(geometry.SquaredAxis), temporary);
 192119                Scale(axial, Signed576.ExtendValue(Component(geometry.Axis, axis)), product);
 192120                temporary.Add(product, -1);
 384121                Scale(temporary, radiusSquared, product); delta.Add(product);
 122            }
 123        }
 221124        else if (!geometry.IsCone && selection.Feature == CurvedPrismContactSelection.Free)
 125        {
 126            // Side support is a finite axial segment. Its radial term uses
 127            // sqrt(n²); the exact local normal itself is rational here.
 99128            metric.Rational.CopyTo(root);
 99129            metric.CopyTo(supportDenominator);
 792130            for (int axis = 0; axis < 3; axis++)
 131            {
 297132                ContactQuadratic start = WAt(support, supportSigns, axis);
 297133                Scale(metric, Component(geometry.Half, axis), start);
 297134                ContactQuadratic delta = WAt(displacement, displacementSigns, axis);
 594135                start.CopyTo(delta); delta.Add(delta);
 297136                start.MultiplySign(-1);
 297137                Scale(WAt(n, nSigns, axis), Signed576.ExtendValue(geometry.Radius), temporary);
 594138                MultiplyRoot(temporary, root, product); start.Add(product);
 139            }
 140        }
 122141        else if (geometry.IsCone && selection.Feature == CurvedPrismContactSelection.Top)
 142        {
 5143            supportDenominator.Set(Integer(1));
 40144            for (int axis = 0; axis < 3; axis++)
 15145                WAt(support, supportSigns, axis).Set(Component(geometry.Half, axis));
 146        }
 147        else
 148        {
 149            // Smooth rim point R*(q*n-h*A)/sqrt(q*(q*n²-h²)).
 150            // Store its rationalized quadratic coordinates, rather than feed
 151            // a rounded public normal back into support selection.
 117152            Multiply(temporary, q, root, supportDenominator);
 117153            supportDenominator.Rational.CopyTo(root);
 117154            int cap = selection.Feature;
 936155            for (int axis = 0; axis < 3; axis++)
 156            {
 351157                ContactQuadratic point = WAt(support, supportSigns, axis);
 351158                Scale(supportDenominator, Component(geometry.Half, axis), point);
 351159                point.MultiplySign(cap);
 351160                Scale(WAt(n, nSigns, axis), Signed576.ExtendValue(geometry.SquaredAxis), temporary);
 351161                Scale(axial, Signed576.ExtendValue(Component(geometry.Axis, axis)), product);
 351162                temporary.Add(product, -1);
 351163                Scale(temporary, Signed576.ExtendValue(geometry.Radius), product);
 702164                MultiplyRoot(product, root, temporary); point.Add(temporary);
 165            }
 166        }
 167
 394168        Span<ulong> translated = stackalloc ulong[6 * words];
 394169        Span<int> translatedSigns = stackalloc int[6];
 394170        Span<ulong> translatedDelta = stackalloc ulong[6 * words];
 394171        Span<int> translatedDeltaSigns = stackalloc int[6];
 394172        ContactQuadratic translatedDenominator = WAt(work, signs, 8);
 394173        if (!window.Enabled && !pole && !geometry.IsCone && selection.Feature == CurvedPrismContactSelection.Free)
 174        {
 175            // The side branch has H.n=0 and support=-H*M+R*n*sqrt(M).
 176            // Translation cancels the radical and one positive common M:
 177            // point=-H*M+minimum*n, delta=2H*M, denominator=M.
 66178            metric.CopyTo(translatedDenominator);
 132179            displacement.CopyTo(translatedDelta); displacementSigns.CopyTo(translatedDeltaSigns);
 528180            for (int axis = 0; axis < 3; axis++)
 181            {
 198182                ContactQuadratic point = WAt(translated, translatedSigns, axis);
 198183                Scale(metric, WideArithmetic.Negate(Component(geometry.Half, axis)), point);
 396184                Multiply(minimum, WAt(n, nSigns, axis), root, product); point.Add(product);
 185            }
 186        }
 187        else
 188        {
 328189            DotQuadraticNormal(support, supportSigns, n, nSigns, root, gap);
 656190            Multiply(minimum, supportDenominator, root, product); gap.Add(product, -1);
 328191            Multiply(supportDenominator, metric, root, translatedDenominator);
 2624192            for (int axis = 0; axis < 3; axis++)
 193            {
 984194                ContactQuadratic point = WAt(translated, translatedSigns, axis);
 984195                Multiply(WAt(support, supportSigns, axis), metric, root, point);
 1968196                Multiply(gap, WAt(n, nSigns, axis), root, product); point.Add(product, -1);
 984197                Multiply(WAt(displacement, displacementSigns, axis), metric, root,
 984198                    WAt(translatedDelta, translatedDeltaSigns, axis));
 199            }
 200        }
 788201        ContactQuadratic parameterNumerator = WAt(work, signs, 9), parameterDenominator = WAt(work, signs, 10);
 394202        if (!ClipSegment(geometry, translated, translatedSigns, translatedDelta, translatedDeltaSigns,
 466203            translatedDenominator, root, parameterNumerator, parameterDenominator, window, out physical)) return false;
 322204        ContactQuadratic finalDenominator = WAt(work, signs, 11);
 322205        Blend(support, supportSigns, displacement, displacementSigns,
 322206            parameterNumerator, parameterDenominator, root);
 322207        Multiply(supportDenominator, parameterDenominator, root, finalDenominator);
 604208        if (materialize) shapeAnchor = CreateQuadraticAnchor(geometry, center, rotation, center,
 282209            support, supportSigns, finalDenominator, root);
 322210        Blend(translated, translatedSigns, translatedDelta, translatedDeltaSigns,
 322211            parameterNumerator, parameterDenominator, root);
 322212        Multiply(translatedDenominator, parameterDenominator, root, finalDenominator);
 336213        if (window.SourceEdge >= 0 && window.Open && !IsInsideRealEdgeWindow(geometry, window, translated, translatedSig
 590214        if (materialize) prismAnchor = CreateQuadraticAnchor(geometry, center, rotation, prismOrigin,
 282215            translated, translatedSigns, finalDenominator, root);
 308216        return true;
 217    }
 218
 219    private static bool GetPoleSupport(in CurvedPrismContactGeometry geometry,
 220        scoped CurvedPrismContactSelection selection, Span<ulong> normal, Span<int> normalSigns,
 221        ContactQuadratic metric, ContactQuadratic minimum, Span<ulong> support, Span<int> supportSigns,
 222        ContactQuadratic denominator, in FaceWindow window)
 223    {
 112224        int words = denominator.FieldWords;
 224225        Span<ulong> point = stackalloc ulong[3 * words], pointDenominator = stackalloc ulong[words];
 112226        Span<int> pointSigns = stackalloc int[3];
 227        bool found;
 112228        if (window.Enabled && (window.SourceEdge >= 0 || window.Face >= 0))
 229        {
 32230            found = CurvedPrismCapWitness.TryGetWindowPoint(geometry, selection.Vertex, selection.Feature,
 32231                window.Face, window.SourceEdge, window.Tangent, window.Open, window.Lower, window.Upper,
 32232                point, pointSigns, pointDenominator, initialSection: true);
 44233            if (!found) found = CurvedPrismCapWitness.TryGetWindowPoint(geometry, selection.Vertex, selection.Feature,
 12234                window.Face, window.SourceEdge, window.Tangent, window.Open, window.Lower, window.Upper,
 12235                point, pointSigns, pointDenominator);
 236        }
 80237        else if (window.Enabled)
 238        {
 44239            Span<ulong> pole = stackalloc ulong[3 * Words]; Span<int> poleSigns = stackalloc int[3];
 57240            var axis = new WideDirection3d(geometry.Axis); if (selection.Feature < 0) axis = -axis;
 22241            WriteDirection(axis, pole, poleSigns);
 22242            found = CurvedPrismCapWitness.TryGetPoint(geometry, pole, poleSigns, selection.Vertex, selection.Feature,
 22243                point, pointSigns, pointDenominator, initialSection: true);
 35244            if (!found) found = CurvedPrismCapWitness.TryGetPoint(geometry, pole, poleSigns, selection.Vertex, selection
 13245                point, pointSigns, pointDenominator);
 246        }
 58247        else found = CurvedPrismCapWitness.TryGetPoint(geometry, selection.Values[..(3 * Words)], selection.Signs[..3],
 58248            selection.Vertex, selection.Feature, point, pointSigns, pointDenominator);
 115249        if (!found) return false;
 109250        Span<ulong> work = stackalloc ulong[6 * words];
 109251        Span<int> signs = stackalloc int[6];
 327252        ContactQuadratic pDen = WAt(work, signs, 0), component = WAt(work, signs, 1), temporary = WAt(work, signs, 2);
 327253        pDen.Clear(); pointDenominator.CopyTo(pDen.Rational); pDen.Signs[0] = 1;
 109254        Multiply(pDen, metric, default, denominator);
 872255        for (int axis = 0; axis < 3; axis++)
 256        {
 981257            component.Clear(); Slot(point, axis, words).CopyTo(component.Rational); component.Signs[0] = pointSigns[axis
 327258            ContactQuadratic result = WAt(support, supportSigns, axis);
 327259            Multiply(component, metric, default, result);
 654260            Scale(denominator, Component(geometry.Half, axis), component); component.MultiplySign(selection.Feature);
 327261            result.Add(component);
 327262            Multiply(minimum, WAt(normal, normalSigns, axis), default, component);
 654263            Multiply(component, pDen, default, temporary); result.Add(temporary, -1);
 264        }
 109265        return true;
 266    }
 267
 268    private static bool ClipSegment(in CurvedPrismContactGeometry geometry, Span<ulong> start, Span<int> startSigns,
 269        Span<ulong> delta, Span<int> deltaSigns, ContactQuadratic denominator, ReadOnlySpan<ulong> root,
 270        ContactQuadratic parameterNumerator, ContactQuadratic parameterDenominator, in FaceWindow window, out bool physi
 271    {
 788272        int words = denominator.FieldWords; physical = false;
 273#if !DEBUG
 394274        if (!window.Enabled)
 275        {
 206276            int displacementSign = 0;
 4120277            foreach (int sign in deltaSigns) displacementSign |= sign;
 206278            if (displacementSign == 0)
 279            {
 280                // A fixed ordinary point keeps the original interval [0,1].
 281                // Debug builds retain the complete membership assertions below.
 208282                parameterNumerator.Clear(); parameterDenominator.Set(Integer(1));
 104283                return true;
 284            }
 285        }
 286#endif
 290287        Span<ulong> work = stackalloc ulong[16 * words];
 290288        Span<int> signs = stackalloc int[16];
 580289        ContactQuadratic lower = WAt(work, signs, 0), lowerDen = WAt(work, signs, 1);
 580290        ContactQuadratic upper = WAt(work, signs, 2), upperDen = WAt(work, signs, 3);
 580291        ContactQuadratic a = WAt(work, signs, 4), b = WAt(work, signs, 5);
 580292        ContactQuadratic product = WAt(work, signs, 6), comparison = WAt(work, signs, 7);
 1160293        lower.Clear(); lowerDen.Set(Integer(1)); upper.Set(Integer(1)); upperDen.Set(Integer(1));
 4172294        for (int plane = 0; plane < geometry.PlaneCount; plane++)
 295        {
 296            // Coordinate planes are nonzero; duplicate-side rejection also removes zero edges.
 1843297            if (plane >= 3 && geometry.IsCoordinateSidePlane(plane)) continue;
 1008298            WideDirection3d normal = geometry.Plane(plane);
 7923299            for (int orientation = 0; orientation < 2; orientation++, normal = -normal)
 300            {
 2016301                DotQuadratic(normal, start, startSigns, a);
 4032302                Scale(denominator, geometry.ProjectionMinimum(normal), product); a.Add(product, -1);
 2016303                DotQuadratic(normal, delta, deltaSigns, b);
 2016304                int slope = b.Sign(root);
 2016305                if (slope == 0)
 306                {
 1540307                    if (window.Enabled)
 308                    {
 1325309                        if (a.Sign(root) < 0) return false;
 310                    }
 311#if DEBUG
 312                    else System.Diagnostics.Debug.Assert(a.Sign(root) >= 0);
 313#endif
 314                    continue;
 315                }
 316                // a+t*b>=0. Retain exact quadratic endpoints and compare
 317                // cross-products; no clipped parameter ever rounds.
 952318                a.MultiplySign(-slope); b.MultiplySign(slope);
 476319                ContactQuadratic bound = slope > 0 ? lower : upper;
 476320                ContactQuadratic boundDen = slope > 0 ? lowerDen : upperDen;
 476321                Multiply(a, boundDen, root, comparison);
 952322                Multiply(bound, b, root, product); comparison.Add(product, -1);
 812323                if (comparison.Sign(root) * slope > 0) { a.CopyTo(bound); b.CopyTo(boundDen); }
 324            }
 325        }
 243326        if (window.Enabled && !ClipFaceWindow(geometry, window, start, startSigns, delta, deltaSigns,
 258327            denominator, root, lower, lowerDen, upper, upperDen)) return false;
 228328        if (window.Enabled)
 329        {
 126330            Multiply(lower, upperDen, root, comparison);
 252331            Multiply(upper, lowerDen, root, product); comparison.Add(product, -1);
 136332            if (comparison.Sign(root) > 0) return false;
 333        }
 334#if DEBUG
 335        else
 336        {
 337            Multiply(lower, upperDen, root, comparison);
 338            Multiply(upper, lowerDen, root, product); comparison.Add(product, -1);
 339            System.Diagnostics.Debug.Assert(comparison.Sign(root) <= 0);
 340        }
 341#endif
 218342        if (window.Enabled)
 343        {
 116344            physical = ClipOriginalBody(geometry, start, startSigns, delta, deltaSigns, denominator, root, lower, lowerD
 348345            Multiply(lower, upperDen, root, comparison); Multiply(upper, lowerDen, root, product); comparison.Add(produc
 346        }
 347        // A fixed endpoint is deterministic and avoids multiplying two
 348        // independent interval denominators just to choose their midpoint.
 436349        lower.CopyTo(parameterNumerator); lowerDen.CopyTo(parameterDenominator);
 218350        if (window.Enabled && window.SourceEdge >= 0 && window.Open && comparison.Sign(root) < 0)
 351        {
 352            // The mediant lies strictly between ordered ratios with positive
 353            // denominators, including quadratic fields, without cross products.
 74354            parameterNumerator.Add(upper); parameterDenominator.Add(upperDen);
 355        }
 218356        return true;
 357    }
 358
 359    private static bool ClipOriginalBody(in CurvedPrismContactGeometry geometry,
 360        Span<ulong> point, Span<int> pointSigns, Span<ulong> delta, Span<int> deltaSigns,
 361        ContactQuadratic denominator, ReadOnlySpan<ulong> root, ContactQuadratic lower,
 362        ContactQuadratic lowerDen, ContactQuadratic upper, ContactQuadratic upperDen, in FaceWindow window)
 363    {
 116364        int words = denominator.FieldWords;
 232365        Span<ulong> values = stackalloc ulong[16 * words]; Span<int> signs = stackalloc int[16];
 232366        var l = WAt(values, signs, 0); var ld = WAt(values, signs, 1);
 232367        var u = WAt(values, signs, 2); var ud = WAt(values, signs, 3);
 232368        var a = WAt(values, signs, 4); var b = WAt(values, signs, 5);
 232369        var comparison = WAt(values, signs, 6); var work = WAt(values, signs, 7);
 464370        lower.CopyTo(l); lowerDen.CopyTo(ld); upper.CopyTo(u); upperDen.CopyTo(ud);
 116371        var axis = new WideDirection3d(geometry.Axis);
 116372        Signed832 bound = Signed832.ExtendValue(WideArithmetic.Negate(WideArithmetic.MultiplySigned320(geometry.SquaredA
 116373        if (!ClipFaceHalfplane(axis, bound, point, pointSigns, delta, deltaSigns, denominator, root, l, ld, u, ud)
 132374            || !ClipFaceHalfplane(-axis, bound, point, pointSigns, delta, deltaSigns, denominator, root, l, ld, u, ud)) 
 100375        GetCurvedImplicit(geometry, point, pointSigns, denominator, root, a);
 200376        Span<ulong> end = stackalloc ulong[6 * words]; Span<int> endSigns = stackalloc int[6];
 800377        for (int coordinate = 0; coordinate < 3; coordinate++)
 600378        { WAt(point, pointSigns, coordinate).CopyTo(WAt(end, endSigns, coordinate)); WAt(end, endSigns, coordinate).Add(
 200379        GetCurvedImplicit(geometry, end, endSigns, denominator, root, b); b.Add(a, -1);
 380        // Every free analytic family is a cone generator or cylinder axis;
 381        // both are null directions of their radial quadratic form. Its
 382        // restriction is therefore LINEAR in t, with no new root field.
 200383        a.MultiplySign(-1); b.MultiplySign(-1);
 120384        if (!ClipBound(a, b, root, l, ld, u, ud)) return false;
 240385        Multiply(l, ud, root, comparison); Multiply(u, ld, root, work); comparison.Add(work, -1);
 95386        if (comparison.Sign(root) > 0) return false;
 65387        if (window.SourceEdge >= 0 && window.Open)
 388        {
 62389            var n = a; var d = b;
 62390            l.CopyTo(n); ld.CopyTo(d);
 75391            if (comparison.Sign(root) < 0) { n.Add(u); d.Add(ud); }
 62392            Span<ulong> trial = stackalloc ulong[6 * words]; Span<int> trialSigns = stackalloc int[6];
 62393            point.CopyTo(trial); pointSigns.CopyTo(trialSigns);
 62394            Blend(trial, trialSigns, delta, deltaSigns, n, d, root); Multiply(denominator, d, root, a);
 395            // A body-only endpoint excluded by this open source stratum must
 396            // not suppress the separately admissible far-boundary family.
 40397            if (!IsInsideRealEdgeWindow(geometry, window, trial, trialSigns, a, root)) return false;
 398        }
 280399        l.CopyTo(lower); ld.CopyTo(lowerDen); u.CopyTo(upper); ud.CopyTo(upperDen); return true;
 400    }
 401
 402    private static void Blend(Span<ulong> start, Span<int> startSigns, Span<ulong> delta, Span<int> deltaSigns,
 403        ContactQuadratic numerator, ContactQuadratic denominator, ReadOnlySpan<ulong> root)
 404    {
 675405        int words = start.Length / startSigns.Length;
 675406        Span<ulong> work = stackalloc ulong[4 * words];
 675407        Span<int> signs = stackalloc int[4];
 1350408        ContactQuadratic first = WAt(work, signs, 0), second = WAt(work, signs, 1);
 5400409        for (int axis = 0; axis < 3; axis++)
 410        {
 2025411            ContactQuadratic point = WAt(start, startSigns, axis);
 2025412            Multiply(point, denominator, root, first);
 2025413            Multiply(WAt(delta, deltaSigns, axis), numerator, root, second);
 4050414            first.Add(second); first.CopyTo(point);
 415        }
 675416    }
 417
 418    internal static FixedPointAnchor CreateQuadraticAnchor(in CurvedPrismContactGeometry geometry,
 419        Vector3d center, FixedQuaternion rotation, Vector3d origin, Span<ulong> point, Span<int> pointSigns,
 420        ContactQuadratic denominator, ReadOnlySpan<ulong> root)
 421    {
 598422        int words = point.Length / pointSigns.Length;
 598423        WideOrientedBox.GetRelativeLocalPointNumerators(center, origin, geometry.WorldBasis,
 598424            out Signed192 dx, out Signed192 dy, out Signed192 dz);
 598425        Span<ulong> work = stackalloc ulong[8 * words];
 598426        Span<int> signs = stackalloc int[8];
 1196427        ContactQuadratic rawDen = WAt(work, signs, 0), finalDen = WAt(work, signs, 1);
 1196428        ContactQuadratic numerator = WAt(work, signs, 2), product = WAt(work, signs, 3);
 598429        Scale(denominator, Signed576.ExtendValue(geometry.RawScale), rawDen);
 598430        Scale(rawDen, Signed576.ExtendValue(geometry.WorldBasis.Denominator), finalDen);
 598431        int orientation = finalDen.Sign(root);
 598432        finalDen.MultiplySign(orientation);
 1196433        Vector3d first = default, second = default;
 4784434        for (int axis = 0; axis < 3; axis++)
 435        {
 1794436            Scale(WAt(point, pointSigns, axis), Signed576.ExtendValue(geometry.WorldBasis.Denominator), numerator);
 1794437            Scale(rawDen, Signed576.ExtendValue(axis == 0 ? dx : axis == 1 ? dy : dz), product);
 3588438            numerator.Add(product); numerator.MultiplySign(orientation);
 1794439            SplitRound(numerator, finalDen, root, out Fixed64 a, out Fixed64 b);
 3588440            first[axis] = a; second[axis] = b;
 441        }
 598442        return new FixedPointAnchor(origin, rotation, first, second);
 443    }
 444
 445    private static void DotQuadratic(in WideDirection3d vector, Span<ulong> values, Span<int> signs, ContactQuadratic re
 446    {
 6445447        Span<ulong> work = stackalloc ulong[2 * result.FieldWords];
 6445448        Span<int> workSigns = stackalloc int[2];
 6445449        ContactQuadratic product = WAt(work, workSigns, 0);
 6445450        result.Clear();
 51560451        for (int axis = 0; axis < 3; axis++)
 452        {
 38670453            Scale(WAt(values, signs, axis), Component(vector, axis), product); result.Add(product);
 454        }
 6445455    }
 456
 457    private static void DotQuadraticNormal(Span<ulong> first, Span<int> firstSigns, Span<ulong> second,
 458        Span<int> secondSigns, ReadOnlySpan<ulong> root, ContactQuadratic result)
 459    {
 328460        Span<ulong> work = stackalloc ulong[2 * result.FieldWords];
 328461        Span<int> signs = stackalloc int[2];
 328462        ContactQuadratic product = WAt(work, signs, 0);
 328463        result.Clear();
 2624464        for (int axis = 0; axis < 3; axis++)
 465        {
 1968466            Multiply(WAt(first, firstSigns, axis), WAt(second, secondSigns, axis), root, product); result.Add(product);
 467        }
 328468    }
 469
 64127470    private static ContactQuadratic WAt(Span<ulong> values, Span<int> signs, int index) => At(values, signs, index, valu
 979471    private static Signed576 Integer(long value) => Signed576.ExtendValue(Signed192.Signed(value));
 472}

Methods/Properties

IntersectsBoundaryLine(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,System.Int32,FixedMathSharp.Geometry.RationalSegmentInterval&,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
GetNativeBoundarySegment(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,System.Int32,FixedMathSharp.Geometry.RationalSegmentInterval&,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.WideAxis3&,FixedMathSharp.Geometry.WideAxis3&,FixedMathSharp.Signed320&,FixedMathSharp.Geometry.RationalSegmentInterval&)
IntersectsRealEdge(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,System.Int32,FixedMathSharp.Geometry.RationalSegmentInterval&)
NormalizeNativeSegment(FixedMathSharp.Geometry.WideDirection3d&,FixedMathSharp.Geometry.WideDirection3d&,FixedMathSharp.Signed576,FixedMathSharp.Geometry.WideAxis3&,FixedMathSharp.Geometry.WideAxis3&,FixedMathSharp.Signed320&)
IntersectsNativeSegment(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,FixedMathSharp.Geometry.WideAxis3,FixedMathSharp.Geometry.WideAxis3,FixedMathSharp.Signed320,FixedMathSharp.Geometry.RationalSegmentInterval&)
InterpolateNativeSource(FixedMathSharp.Geometry.WideDirection3d&,FixedMathSharp.Geometry.WideDirection3d&,FixedMathSharp.Signed320,FixedMathSharp.Signed320)
DoubledBoundaryPoint(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576)
TryGetContact(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,System.ReadOnlySpan`1<FixedMathSharp.Vector2d>,FixedMathSharp.Fixed64,System.Boolean,FixedMathSharp.Geometry.FixedContactAnchors&)
KeepAnalytic(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,FixedMathSharp.Geometry.CurvedPrismContactSelection&)
HasPoleMinimumCertificate(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,FixedMathSharp.Geometry.CurvedPrismContactSelection)
IsBasisDirection(FixedMathSharp.Geometry.WideDirection3d&,FixedMathSharp.Geometry.WideDirection3d&)
KeepAxis(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,FixedMathSharp.Geometry.WideDirection3d&,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,FixedMathSharp.Geometry.CurvedPrismContactSelection&,System.Int32,System.Int32)
ReduceEdgeDirection(FixedMathSharp.Geometry.WideDirection3d&)
Difference(FixedMathSharp.Geometry.WideDirection3d&,FixedMathSharp.Geometry.WideDirection3d&)
TryGetCylinderBoundaryContact(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,System.Int32,FixedMathSharp.Geometry.RationalSegmentInterval&,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedContactAnchors&,System.Int32,FixedMathSharp.Geometry.CurvedPrismContactValue,FixedMathSharp.Geometry.PrismCurvedBoundaryContactVisitor,System.Int32)
TryGetContact(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,FixedMathSharp.Geometry.PrismCurvedContactDomain,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedContactAnchors&,System.Int32&,System.Boolean&,System.Int32&,System.ReadOnlySpan`1<FixedMathSharp.Geometry.PrismCurvedBoundaryLine>,FixedMathSharp.Geometry.PrismCurvedBoundaryContactVisitor,FixedMathSharp.Geometry.ConePrismBoundaryContacts)
TryAdmitAnalyticCandidate(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,FixedMathSharp.Geometry.PrismCurvedContactDomain,System.ReadOnlySpan`1<System.UInt64>,System.ReadOnlySpan`1<System.Int32>,System.Int32,System.Int32,System.Int32,System.Int32&,System.Int32&)
GetDomainWindow(FixedMathSharp.Geometry.PrismCurvedContactDomain,System.Int32)
IsFaceDirection(System.ReadOnlySpan`1<System.UInt64>,System.ReadOnlySpan`1<System.Int32>,FixedMathSharp.Geometry.WideDirection3d&)
DirectionDotSign(System.ReadOnlySpan`1<System.UInt64>,System.ReadOnlySpan`1<System.Int32>,FixedMathSharp.Geometry.WideDirection3d&)
DirectionDotQuadraticSign(System.ReadOnlySpan`1<System.UInt64>,System.ReadOnlySpan`1<System.Int32>,FixedMathSharp.Geometry.WideDirection3d&)
ClipRealEdgeWindow(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,FixedMathSharp.Geometry.CurvedPrismContact/FaceWindow&,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,FixedMathSharp.Geometry.ContactQuadratic,System.ReadOnlySpan`1<System.UInt64>,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic)
IsInsideRealEdgeWindow(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,FixedMathSharp.Geometry.CurvedPrismContact/FaceWindow&,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,FixedMathSharp.Geometry.ContactQuadratic,System.ReadOnlySpan`1<System.UInt64>)
TryGetFaceSupportContact(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,System.Int32,FixedMathSharp.Geometry.RationalSegmentInterval&,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,System.Boolean,FixedMathSharp.Geometry.FixedContactAnchors&,System.Boolean&)
GetFacePlane(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,System.Int32,FixedMathSharp.Geometry.WideDirection3d&,FixedMathSharp.Signed832&,System.Int32&)
.ctor(System.Int32,FixedMathSharp.Geometry.RationalSegmentInterval,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
.ctor(FixedMathSharp.Geometry.PrismCurvedEdgeWindow&)
ClipFaceWindow(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,FixedMathSharp.Geometry.CurvedPrismContact/FaceWindow&,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,FixedMathSharp.Geometry.ContactQuadratic,System.ReadOnlySpan`1<System.UInt64>,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic)
GetFaceWindowHalfplanes(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,System.Int32,FixedMathSharp.Geometry.RationalSegmentInterval&,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Span`1<FixedMathSharp.Geometry.WideDirection3d>,System.Span`1<FixedMathSharp.Signed832>)
ScaleAxis(FixedMathSharp.Geometry.WideDirection3d&,FixedMathSharp.Signed320)
SumProducts(FixedMathSharp.Signed832,FixedMathSharp.Signed320,FixedMathSharp.Signed832,FixedMathSharp.Signed320)
ClipFaceHalfplane(FixedMathSharp.Geometry.WideDirection3d&,FixedMathSharp.Signed832,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,FixedMathSharp.Geometry.ContactQuadratic,System.ReadOnlySpan`1<System.UInt64>,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic)
ClipBound(FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,System.ReadOnlySpan`1<System.UInt64>,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic)
GetCurvedImplicit(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,FixedMathSharp.Geometry.ContactQuadratic,System.ReadOnlySpan`1<System.UInt64>,FixedMathSharp.Geometry.ContactQuadratic)
GetAnalyticWitnesses(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,FixedMathSharp.Geometry.CurvedPrismContactSelection,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&,FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Geometry.FixedPointAnchor&)
TryGetAnalyticWitnesses(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,FixedMathSharp.Geometry.CurvedPrismContactSelection,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&,FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Geometry.FixedPointAnchor&,System.Boolean&,FixedMathSharp.Geometry.CurvedPrismContact/FaceWindow&,System.Boolean)
GetPoleSupport(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,FixedMathSharp.Geometry.CurvedPrismContactSelection,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.CurvedPrismContact/FaceWindow&)
ClipSegment(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,FixedMathSharp.Geometry.ContactQuadratic,System.ReadOnlySpan`1<System.UInt64>,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.CurvedPrismContact/FaceWindow&,System.Boolean&)
ClipOriginalBody(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,FixedMathSharp.Geometry.ContactQuadratic,System.ReadOnlySpan`1<System.UInt64>,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.CurvedPrismContact/FaceWindow&)
Blend(System.Span`1<System.UInt64>,System.Span`1<System.Int32>,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,System.ReadOnlySpan`1<System.UInt64>)
CreateQuadraticAnchor(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,FixedMathSharp.Geometry.ContactQuadratic,System.ReadOnlySpan`1<System.UInt64>)
DotQuadratic(FixedMathSharp.Geometry.WideDirection3d&,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,FixedMathSharp.Geometry.ContactQuadratic)
DotQuadraticNormal(System.Span`1<System.UInt64>,System.Span`1<System.Int32>,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,System.ReadOnlySpan`1<System.UInt64>,FixedMathSharp.Geometry.ContactQuadratic)
WAt(System.Span`1<System.UInt64>,System.Span`1<System.Int32>,System.Int32)
Integer(System.Int64)