< Summary

Information
Class: FixedMathSharp.Geometry.CurvedPrismCapWitness
Assembly: FixedMathSharp
File(s): /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Convex/CurvedPrismCapWitness.cs
Line coverage
100%
Covered lines: 227
Uncovered lines: 0
Coverable lines: 227
Total lines: 368
Line coverage: 100%
Branch coverage
100%
Covered branches: 142
Total branches: 142
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
TryGetPoint(...)100%4646100%
TryGetInitialPoleRadius(...)100%88100%
TryGetWindowPoint(...)100%3636100%
Project(...)100%22100%
Clamp(...)100%44100%
StrictlyInside(...)100%1010100%
MoveInsideOpenEdge(...)100%2020100%
Contains(...)100%1010100%
WithinDisk(...)100%44100%
IsMinimum(...)100%11100%
SetMagnitude(...)100%11100%
CopyPoint(...)100%22100%

File(s)

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

#LineLine coverage
 1//=======================================================================
 2// CurvedPrismCapWitness.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>Matched rational prism witnesses for an admitted primitive cap pole.</summary>
 14internal static class CurvedPrismCapWitness
 15{
 16    /// <summary>
 17    /// Normal is a nonzero rational local pole, parallel to the primitive axis.
 18    /// Returns a point on its minimum prism feature within the projected cap
 19    /// disk. Caller output fields have denominator.Length words (112 words
 20    /// cover the complete Signed576 pole bound)
 21    /// and are disjoint from the three forty-word input normal fields.
 22    /// </summary>
 23    internal static bool TryGetPoint(in CurvedPrismContactGeometry geometry,
 24        ReadOnlySpan<ulong> normal, ReadOnlySpan<int> normalSigns, int minimumVertex, int capSign,
 25        Span<ulong> point, Span<int> pointSigns, Span<ulong> denominator, bool initialSection = false)
 26    {
 9427        int words = denominator.Length;
 9428        Span<ulong> storage = stackalloc ulong[28 * words];
 9429        Span<int> signs = stackalloc int[28];
 9430        ContactQuadratic metric = ContactQuadratic.At(storage, signs, 3, words);
 9431        ContactQuadratic minimum = ContactQuadratic.At(storage, signs, 4, words);
 9432        ContactQuadratic divisor = ContactQuadratic.At(storage, signs, 8, words);
 9433        ContactQuadratic t = ContactQuadratic.At(storage, signs, 9, words);
 9434        ContactQuadratic tDivisor = ContactQuadratic.At(storage, signs, 10, words);
 9435        ContactQuadratic work = ContactQuadratic.At(storage, signs, 11, words);
 9436        ContactQuadratic term = ContactQuadratic.At(storage, signs, 12, words);
 9437        ContactQuadratic sum = ContactQuadratic.At(storage, signs, 13, words);
 9438        Span<ulong> magnitude = stackalloc ulong[Words];
 18839        SumSquares(normal, magnitude); SetMagnitude(magnitude, 1, metric);
 9440        Dot(geometry.Vertex(minimumVertex), normal, normalSigns, magnitude, out int minimumSign);
 9441        SetMagnitude(magnitude, minimumSign, minimum);
 75242        for (int axis = 0; axis < 3; axis++)
 43        {
 28244            SetMagnitude(Slot(normal, axis), normalSigns[axis], term);
 28245            ContactQuadratic.Multiply(term, minimum, ReadOnlySpan<ulong>.Empty,
 28246                ContactQuadratic.At(storage, signs, axis, words));
 47        }
 9448        Signed832 radiusSquared = initialSection && !(geometry.IsCone && capSign > 0)
 9449            ? Signed832.ExtendValue(WideArithmetic.MultiplySigned320(geometry.Radius, geometry.Radius)) : default;
 9450        Signed576 radiusDenominator = default;
 10651        if (initialSection && !TryGetInitialPoleRadius(geometry, minimumVertex, capSign, ref radiusSquared, out radiusDe
 52        // C=(minP/n²)*n is the disk center in the prism support plane.
 53        // An admitted pole guarantees a finite common slice. If C is outside
 54        // that convex feature, its nearest point is on a real boundary edge.
 8255        if (Contains(geometry, storage[..(6 * words)], signs[..6], metric, words))
 56        {
 5857            CopyPoint(storage, signs, 0, metric, point, pointSigns, denominator, words);
 5858            return true;
 59        }
 2460        if (!initialSection && !(geometry.IsCone && capSign > 0))
 1661            radiusSquared = Signed832.ExtendValue(WideArithmetic.MultiplySigned320(geometry.Radius, geometry.Radius));
 2462        divisor.Set(Signed576.ExtendValue(Signed192.Signed(1)));
 33063        for (int vertex = 0; vertex < geometry.VertexCount; vertex++)
 64        {
 15365            WideDirection3d candidate = geometry.Vertex(vertex);
 15366            if (!IsMinimum(candidate, normal, normalSigns, minimum, work, magnitude)) continue;
 63267            for (int axis = 0; axis < 3; axis++)
 23768                ContactQuadratic.At(storage, signs, 5 + axis, words).Set(Component(candidate, axis));
 7969            if (!WithinDisk(storage, signs, divisor, metric, radiusSquared, words, radiusDenominator)) continue;
 1270            CopyPoint(storage, signs, 5, divisor, point, pointSigns, denominator, words);
 1271            return true;
 72        }
 29873        for (int edge = 0; edge < geometry.EdgeCount; edge++)
 74        {
 14475            geometry.Edge(edge, out int first, out int second);
 28876            WideDirection3d start = geometry.Vertex(first), end = geometry.Vertex(second);
 14477            if (!IsMinimum(start, normal, normalSigns, minimum, work, magnitude)
 14478                || !IsMinimum(end, normal, normalSigns, minimum, work, magnitude)) continue;
 5179            WideDirection3d delta = new(WideArithmetic.SubtractSigned576(end.X, start.X),
 5180                WideArithmetic.SubtractSigned576(end.Y, start.Y), WideArithmetic.SubtractSigned576(end.Z, start.Z));
 5181            if (delta.IsZero) continue;
 4882            t.Clear();
 38483            for (int axis = 0; axis < 3; axis++)
 84            {
 14485                ContactQuadratic.Scale(metric, Signed832.ExtendValue(Component(start, axis)), work);
 28886                ContactQuadratic.At(storage, signs, axis, words).CopyTo(sum); sum.Add(work, -1);
 28887                ContactQuadratic.Scale(sum, Signed832.ExtendValue(Component(delta, axis)), term); t.Add(term);
 88            }
 4889            ContactQuadratic.Scale(metric, delta.SquaredLength, tDivisor);
 90            // Endpoint candidates were already rejected above; only the open
 91            // edge can provide a new nearest point inside the disk.
 4892            if (t.Signs[0] <= 0) continue;
 6893            t.CopyTo(work); work.Add(tDivisor, -1);
 3494            if (work.Signs[0] >= 0) continue;
 16095            for (int axis = 0; axis < 3; axis++)
 96            {
 6097                ContactQuadratic destination = ContactQuadratic.At(storage, signs, 5 + axis, words);
 6098                ContactQuadratic.Scale(tDivisor, Signed832.ExtendValue(Component(start, axis)), destination);
 12099                ContactQuadratic.Scale(t, Signed832.ExtendValue(Component(delta, axis)), term); destination.Add(term);
 100            }
 20101            if (!WithinDisk(storage, signs, tDivisor, metric, radiusSquared, words, radiusDenominator)) continue;
 7102            CopyPoint(storage, signs, 5, tDivisor, point, pointSigns, denominator, words);
 7103            return true;
 104        }
 5105        return false;
 106    }
 107
 108    private static bool TryGetInitialPoleRadius(in CurvedPrismContactGeometry geometry, int minimumVertex,
 109        int capSign, ref Signed832 radiusSquared, out Signed576 radiusDenominator)
 110    {
 54111        radiusDenominator = default;
 112        // Reduced-pole projections need <232 bits. Seek an initial-body
 113        // point before falling back to the larger translated support disk.
 54114        Signed832 axialProjection = WideDirection3d.Dot(new WideDirection3d(geometry.Axis), geometry.Vertex(minimumVerte
 54115        Signed832 half = Signed832.ExtendValue(WideArithmetic.MultiplySigned320(geometry.SquaredAxis, geometry.HalfFacto
 54116        Signed832 height = WideArithmetic.SubtractSigned832(half, axialProjection);
 70117        if (height.Sign < 0 || WideArithmetic.AddSigned832(half, axialProjection).Sign < 0) return false;
 38118        if (geometry.IsCone && capSign < 0)
 119        {
 23120            var h = Signed320.NarrowValue(Signed576.NarrowValue(height));
 23121            radiusSquared = WideArithmetic.MultiplySigned576(Signed576.NarrowValue(radiusSquared), WideArithmetic.Multip
 23122            var t2 = WideArithmetic.MultiplySigned320(Signed320.ExtendValue(geometry.HalfFactor), geometry.HalfFactor);
 23123            radiusDenominator = Signed576.NarrowValue(WideArithmetic.MultiplySigned576(t2,
 23124                WideArithmetic.MultiplySigned320(geometry.SquaredAxis, geometry.SquaredAxis)));
 23125            radiusDenominator = WideArithmetic.AddSigned576(radiusDenominator, radiusDenominator);
 23126            radiusDenominator = WideArithmetic.AddSigned576(radiusDenominator, radiusDenominator);
 127        }
 38128        return true;
 129    }
 130
 131    // A pole's disk is free in two dimensions. Native side rectangles have
 132    // orthogonal edge/up axes even with the exact nonunit scalar-yaw metric.
 133    // Reduce the pole to the authored axis before projecting: its components
 134    // need <65 bits, so clipped rational points and disk tests fit 112 words.
 135    internal static bool TryGetWindowPoint(in CurvedPrismContactGeometry geometry, int minimumVertex, int capSign,
 136        int face, int sourceEdge, in RationalSegmentInterval clip, bool open,
 137        Fixed64 lower, Fixed64 upper, Span<ulong> point, Span<int> pointSigns, Span<ulong> denominator, bool initialSect
 138    {
 44139        int words = denominator.Length;
 88140        Span<ulong> fields = stackalloc ulong[34 * words]; Span<int> signs = stackalloc int[34];
 88141        fields.Clear(); signs.Clear();
 44142        var metric = ContactQuadratic.At(fields, signs, 3, words);
 44143        var candidateD = ContactQuadratic.At(fields, signs, 8, words);
 88144        var n = ContactQuadratic.At(fields, signs, 9, words); var d = ContactQuadratic.At(fields, signs, 10, words);
 88145        var un = ContactQuadratic.At(fields, signs, 11, words); var ud = ContactQuadratic.At(fields, signs, 12, words);
 88146        var work = ContactQuadratic.At(fields, signs, 13, words); var term = ContactQuadratic.At(fields, signs, 14, word
 126147        var axis = new WideDirection3d(geometry.Axis); if (capSign < 0) axis = -axis;
 44148        metric.Set(axis.SquaredLength);
 44149        Signed832 minimum = WideDirection3d.Dot(axis, geometry.Vertex(minimumVertex));
 352150        for (int coordinate = 0; coordinate < 3; coordinate++)
 132151            ContactQuadratic.At(fields, signs, coordinate, words).Set(WideArithmetic.MultiplySigned832(minimum,
 132152                Signed320.NarrowValue(Component(axis, coordinate))));
 44153        int edgeIndex = sourceEdge >= 0 ? sourceEdge : 3 * face;
 44154        geometry.Edge(edgeIndex, out int first, out int last);
 88155        WideDirection3d a = geometry.Vertex(first), e = CurvedPrismContact.Difference(geometry.Vertex(last), a);
 44156        Project(a, e, fields, signs, metric, n, d, words);
 44157        Clamp(n, d, clip.IsClipped ? clip.LowerNumerator : default, clip.IsClipped ? clip.LowerDenominator : Signed320.O
 44158            clip.IsClipped ? clip.UpperNumerator : Signed320.One, clip.IsClipped ? clip.UpperDenominator : Signed320.One
 44159        WideDirection3d up = default;
 44160        if (sourceEdge < 0)
 161        {
 20162            up = CurvedPrismContact.Difference(geometry.Vertex(first + 1), a);
 20163            Project(a, up, fields, signs, metric, un, ud, words);
 20164            Signed320 height = Signed320.ExtendValue(WideArithmetic.AddSigned192(Signed192.Raw(geometry.PrismHalfThickne
 20165            Clamp(un, ud, Signed320.ExtendValue(WideArithmetic.AddSigned192(Signed192.Raw(lower), Signed192.Raw(geometry
 20166                Signed320.ExtendValue(WideArithmetic.AddSigned192(Signed192.Raw(upper), Signed192.Raw(geometry.PrismHalf
 167        }
 48168        else { un.Clear(); ud.Set(Signed576.ExtendValue(Signed192.Signed(1))); }
 44169        ContactQuadratic.Multiply(d, ud, ReadOnlySpan<ulong>.Empty, candidateD);
 352170        for (int coordinate = 0; coordinate < 3; coordinate++)
 171        {
 132172            var value = ContactQuadratic.At(fields, signs, 5 + coordinate, words);
 132173            ContactQuadratic.Scale(candidateD, Component(a, coordinate), value);
 132174            ContactQuadratic.Multiply(n, ud, ReadOnlySpan<ulong>.Empty, work);
 264175            ContactQuadratic.Scale(work, Component(e, coordinate), term); value.Add(term);
 132176            if (!up.IsZero)
 177            {
 60178                ContactQuadratic.Multiply(un, d, ReadOnlySpan<ulong>.Empty, work);
 120179                ContactQuadratic.Scale(work, Component(up, coordinate), term); value.Add(term);
 180            }
 181        }
 44182        Signed832 radiusSquared = geometry.IsCone && capSign > 0 ? default
 44183            : Signed832.ExtendValue(WideArithmetic.MultiplySigned320(geometry.Radius, geometry.Radius));
 44184        Signed576 radiusDenominator = default;
 48185        if (initialSection && !TryGetInitialPoleRadius(geometry, minimumVertex, capSign, ref radiusSquared, out radiusDe
 42186        if (!WithinDisk(fields, signs, candidateD, metric, radiusSquared, words, radiusDenominator)) return false;
 38187        if (open && !StrictlyInside(n, d, clip, work, term))
 188        {
 28189            if (!MoveInsideOpenEdge(a, e, clip, fields, signs, metric, radiusSquared, radiusDenominator, candidateD, wor
 190        }
 64191        CopyPoint(fields, signs, 5, candidateD, point, pointSigns, denominator, words); return true;
 192    }
 193
 194    private static void Project(in WideDirection3d a, in WideDirection3d edge, Span<ulong> fields, Span<int> signs,
 195        ContactQuadratic metric, ContactQuadratic n, ContactQuadratic d, int words)
 196    {
 128197        var work = ContactQuadratic.At(fields, signs, 15, words); var term = ContactQuadratic.At(fields, signs, 16, word
 64198        n.Clear();
 512199        for (int axis = 0; axis < 3; axis++)
 200        {
 192201            ContactQuadratic.Scale(metric, Component(a, axis), work);
 384202            work.MultiplySign(-1); work.Add(ContactQuadratic.At(fields, signs, axis, words));
 384203            ContactQuadratic.Scale(work, Component(edge, axis), term); n.Add(term);
 204        }
 64205        ContactQuadratic.Scale(metric, edge.SquaredLength, d);
 64206    }
 207
 208    private static void Clamp(ContactQuadratic n, ContactQuadratic d, Signed320 ln, Signed320 ld, Signed320 un, Signed32
 209        ContactQuadratic work, ContactQuadratic term)
 210    {
 192211        ContactQuadratic.Scale(n, Signed576.ExtendValue(ld), work); ContactQuadratic.Scale(d, Signed576.ExtendValue(ln),
 104212        if (work.Signs[0] < 0) { n.Set(Signed576.ExtendValue(ln)); d.Set(Signed576.ExtendValue(ld)); }
 192213        ContactQuadratic.Scale(n, Signed576.ExtendValue(ud), work); ContactQuadratic.Scale(d, Signed576.ExtendValue(un),
 88214        if (work.Signs[0] > 0) { n.Set(Signed576.ExtendValue(un)); d.Set(Signed576.ExtendValue(ud)); }
 64215    }
 216
 217    private static bool StrictlyInside(ContactQuadratic n, ContactQuadratic d, in RationalSegmentInterval clip,
 218        ContactQuadratic work, ContactQuadratic term)
 219    {
 24220        ContactQuadratic.Scale(n, Signed576.ExtendValue(clip.IsClipped ? clip.LowerDenominator : Signed320.One), work);
 48221        ContactQuadratic.Scale(d, Signed576.ExtendValue(clip.IsClipped ? clip.LowerNumerator : default), term); work.Add
 42222        if (work.Signs[0] <= 0) return false;
 6223        ContactQuadratic.Scale(n, Signed576.ExtendValue(clip.IsClipped ? clip.UpperDenominator : Signed320.One), work);
 12224        ContactQuadratic.Scale(d, Signed576.ExtendValue(clip.IsClipped ? clip.UpperNumerator : Signed320.One), term); wo
 6225        return work.Signs[0] < 0;
 226    }
 227
 228    private static bool MoveInsideOpenEdge(in WideDirection3d a, in WideDirection3d edge, in RationalSegmentInterval cli
 229        Span<ulong> fields, Span<int> signs, ContactQuadratic metric, Signed832 radiusSquared, Signed576 radiusDenominat
 230    {
 231        // Q is the true nearest closed-window point. With positive disk slack,
 232        // blend toward the interval mediant F by t=g/(g+2|d.v|+v*v). Then
 233        // 0<t<=1 and the whole exact point remains strictly inside the disk.
 44234        Span<ulong> scratch = stackalloc ulong[30 * words]; Span<int> scratchSigns = stackalloc int[30];
 44235        var fd = ContactQuadratic.At(scratch, scratchSigns, 0, words); var fn = ContactQuadratic.At(scratch, scratchSign
 44236        var g = ContactQuadratic.At(scratch, scratchSigns, 2, words); var k = ContactQuadratic.At(scratch, scratchSigns,
 44237        var work = ContactQuadratic.At(scratch, scratchSigns, 4, words); var term = ContactQuadratic.At(scratch, scratch
 44238        var deltaD = ContactQuadratic.At(scratch, scratchSigns, 6, words); var qd = ContactQuadratic.At(scratch, scratch
 22239        fn.Set(Signed576.ExtendValue(WideArithmetic.AddSigned320(clip.IsClipped ? clip.LowerNumerator : default, clip.Is
 22240        fd.Set(Signed576.ExtendValue(WideArithmetic.AddSigned320(clip.IsClipped ? clip.LowerDenominator : Signed320.One,
 22241        ContactQuadratic.Multiply(denominator, fd, ReadOnlySpan<ulong>.Empty, deltaD);
 22242        ContactQuadratic.Multiply(deltaD, metric, ReadOnlySpan<ulong>.Empty, qd);
 66243        ContactQuadratic.Multiply(qd, qd, ReadOnlySpan<ulong>.Empty, work); ContactQuadratic.Scale(work, radiusSquared, 
 176244        for (int axis = 0; axis < 3; axis++)
 245        {
 132246            var q = ContactQuadratic.At(scratch, scratchSigns, 8 + axis, words); var v = ContactQuadratic.At(scratch, sc
 198247            ContactQuadratic.Scale(fd, Component(a, axis), work); ContactQuadratic.Scale(fn, Component(edge, axis), term
 66248            ContactQuadratic.Multiply(work, denominator, ReadOnlySpan<ulong>.Empty, v);
 66249            ContactQuadratic.Multiply(ContactQuadratic.At(fields, signs, 5 + axis, words), fd, ReadOnlySpan<ulong>.Empty
 198250            v.Add(q, -1); q.CopyTo(work); ContactQuadratic.Multiply(work, metric, ReadOnlySpan<ulong>.Empty, q);
 132251            ContactQuadratic.Multiply(ContactQuadratic.At(fields, signs, axis, words), deltaD, ReadOnlySpan<ulong>.Empty
 132252            v.CopyTo(work); ContactQuadratic.Multiply(work, metric, ReadOnlySpan<ulong>.Empty, v);
 66253            ContactQuadratic.Multiply(q, q, ReadOnlySpan<ulong>.Empty, work);
 84254            if (radiusDenominator.IsZero) g.Add(work, -1);
 96255            else { ContactQuadratic.Scale(work, radiusDenominator, term); g.Add(term, -1); }
 256        }
 28257        if (g.Signs[0] <= 0) return false; // Tangency at an excluded endpoint admits no open point.
 32258        var dot = ContactQuadratic.At(scratch, scratchSigns, 14, words); dot.Clear();
 128259        for (int axis = 0; axis < 3; axis++)
 260        {
 96261            var q = ContactQuadratic.At(scratch, scratchSigns, 8 + axis, words); var v = ContactQuadratic.At(scratch, sc
 96262            ContactQuadratic.Multiply(q, v, ReadOnlySpan<ulong>.Empty, work); dot.Add(work);
 96263            ContactQuadratic.Multiply(v, v, ReadOnlySpan<ulong>.Empty, work); k.Add(work);
 264        }
 265        // Q is the exact projection onto the same interval containing F,
 266        // so (Q-C).(F-Q)>=0; no absolute-value branch is needed.
 267        System.Diagnostics.Debug.Assert(dot.Signs[0] >= 0);
 32268        k.Add(dot); k.Add(dot);
 36269        if (!radiusDenominator.IsZero) { ContactQuadratic.Scale(k, radiusDenominator, work); work.CopyTo(k); }
 16270        k.Add(g);
 128271        for (int axis = 0; axis < 3; axis++)
 272        {
 48273            var value = ContactQuadratic.At(fields, signs, 5 + axis, words);
 48274            ContactQuadratic.Multiply(value, fd, ReadOnlySpan<ulong>.Empty, work);
 48275            ContactQuadratic.Multiply(work, k, ReadOnlySpan<ulong>.Empty, ContactQuadratic.At(scratch, scratchSigns, 8 +
 276            // v includes metric; divide it out by multiplying the other terms.
 48277            ContactQuadratic.Multiply(ContactQuadratic.At(scratch, scratchSigns, 8 + axis, words), metric, ReadOnlySpan<
 144278            ContactQuadratic.Multiply(ContactQuadratic.At(scratch, scratchSigns, 11 + axis, words), g, ReadOnlySpan<ulon
 279        }
 16280        ContactQuadratic.Multiply(deltaD, k, ReadOnlySpan<ulong>.Empty, work);
 32281        ContactQuadratic.Multiply(work, metric, ReadOnlySpan<ulong>.Empty, denominator); return true;
 282    }
 283
 284    private static bool Contains(in CurvedPrismContactGeometry geometry,
 285        Span<ulong> point, Span<int> pointSigns, ContactQuadratic denominator, int words)
 286    {
 82287        Span<ulong> storage = stackalloc ulong[6 * words];
 82288        Span<int> signs = stackalloc int[6];
 82289        ContactQuadratic sum = ContactQuadratic.At(storage, signs, 0, words);
 82290        ContactQuadratic term = ContactQuadratic.At(storage, signs, 1, words);
 82291        ContactQuadratic bound = ContactQuadratic.At(storage, signs, 2, words);
 1048292        for (int plane = 0; plane < geometry.PlaneCount; plane++)
 293        {
 466294            WideDirection3d normal = geometry.Plane(plane);
 466295            if (normal.IsZero) continue;
 2684296            for (int orientation = 0; orientation < 2; orientation++)
 297            {
 906298                bound.Set(geometry.ProjectionMinimum(normal));
 906299                ContactQuadratic.Multiply(bound, denominator, ReadOnlySpan<ulong>.Empty, sum);
 906300                sum.MultiplySign(-1);
 7248301                for (int axis = 0; axis < 3; axis++)
 302                {
 2718303                    ContactQuadratic.Scale(ContactQuadratic.At(point, pointSigns, axis, words),
 5436304                        Signed832.ExtendValue(Component(normal, axis)), term); sum.Add(term);
 305                }
 930306                if (sum.Signs[0] < 0) return false;
 882307                normal = -normal;
 308            }
 309        }
 58310        return true;
 311    }
 312
 313    private static bool WithinDisk(Span<ulong> values, Span<int> valueSigns,
 314        ContactQuadratic denominator, ContactQuadratic metric, Signed832 radiusSquared, int words, Signed576 radiusDenom
 315    {
 316        // Coordinates <165 bits and pole components <576 bits give metric
 317        // <1154, center numerators <1320 and edge point numerators <1656 bits.
 318        // Complete squared-distance products are <5700 bits, within the
 319        // caller's 112-word banks, including every signed-sum carry.
 139320        Span<ulong> storage = stackalloc ulong[10 * words];
 139321        Span<int> signs = stackalloc int[10];
 139322        ContactQuadratic difference = ContactQuadratic.At(storage, signs, 0, words);
 139323        ContactQuadratic product = ContactQuadratic.At(storage, signs, 1, words);
 139324        ContactQuadratic sum = ContactQuadratic.At(storage, signs, 2, words);
 139325        ContactQuadratic divisor = ContactQuadratic.At(storage, signs, 3, words);
 139326        ContactQuadratic limit = ContactQuadratic.At(storage, signs, 4, words);
 139327        sum.Clear();
 1112328        for (int axis = 0; axis < 3; axis++)
 329        {
 417330            ContactQuadratic.Multiply(ContactQuadratic.At(values, valueSigns, 5 + axis, words),
 417331                metric, ReadOnlySpan<ulong>.Empty, difference);
 417332            ContactQuadratic.Multiply(ContactQuadratic.At(values, valueSigns, axis, words),
 834333                denominator, ReadOnlySpan<ulong>.Empty, product); difference.Add(product, -1);
 834334            ContactQuadratic.Multiply(difference, difference, ReadOnlySpan<ulong>.Empty, product); sum.Add(product);
 335        }
 139336        if (!radiusDenominator.IsZero)
 56337        { ContactQuadratic.Scale(sum, radiusDenominator, product); product.CopyTo(sum); }
 139338        ContactQuadratic.Multiply(denominator, metric, ReadOnlySpan<ulong>.Empty, divisor);
 139339        ContactQuadratic.Multiply(divisor, divisor, ReadOnlySpan<ulong>.Empty, product);
 278340        ContactQuadratic.Scale(product, radiusSquared, limit); sum.Add(limit, -1);
 139341        return sum.Signs[0] <= 0;
 342    }
 343
 344    private static bool IsMinimum(in WideDirection3d point, ReadOnlySpan<ulong> normal,
 345        ReadOnlySpan<int> normalSigns, ContactQuadratic minimum, ContactQuadratic work, Span<ulong> magnitude)
 346    {
 375347        Dot(point, normal, normalSigns, magnitude, out int sign);
 750348        SetMagnitude(magnitude, sign, work); work.Add(minimum, -1);
 375349        return work.Signs[0] == 0;
 350    }
 351
 352    private static void SetMagnitude(ReadOnlySpan<ulong> magnitude, int sign, ContactQuadratic result)
 353    {
 2535354        magnitude.CopyTo(result.Rational); result.Rational[magnitude.Length..].Clear(); result.Radical.Clear();
 1690355        result.Signs[0] = sign; result.Signs[1] = 0;
 845356    }
 357
 358    private static void CopyPoint(Span<ulong> values, Span<int> signs, int first,
 359        ContactQuadratic divisor, Span<ulong> point, Span<int> pointSigns, Span<ulong> denominator, int words)
 360    {
 872361        for (int axis = 0; axis < 3; axis++)
 362        {
 327363            ContactQuadratic coordinate = ContactQuadratic.At(values, signs, first + axis, words);
 654364            coordinate.Rational.CopyTo(point.Slice(axis * words, words)); pointSigns[axis] = coordinate.Signs[0];
 365        }
 109366        divisor.Rational.CopyTo(denominator);
 109367    }
 368}

Methods/Properties

TryGetPoint(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,System.ReadOnlySpan`1<System.UInt64>,System.ReadOnlySpan`1<System.Int32>,System.Int32,System.Int32,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,System.Span`1<System.UInt64>,System.Boolean)
TryGetInitialPoleRadius(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,System.Int32,System.Int32,FixedMathSharp.Signed832&,FixedMathSharp.Signed576&)
TryGetWindowPoint(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,System.Int32,System.Int32,System.Int32,System.Int32,FixedMathSharp.Geometry.RationalSegmentInterval&,System.Boolean,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,System.Span`1<System.UInt64>,System.Boolean)
Project(FixedMathSharp.Geometry.WideDirection3d&,FixedMathSharp.Geometry.WideDirection3d&,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,System.Int32)
Clamp(FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic)
StrictlyInside(FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.RationalSegmentInterval&,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic)
MoveInsideOpenEdge(FixedMathSharp.Geometry.WideDirection3d&,FixedMathSharp.Geometry.WideDirection3d&,FixedMathSharp.Geometry.RationalSegmentInterval&,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Signed832,FixedMathSharp.Signed576,FixedMathSharp.Geometry.ContactQuadratic,System.Int32)
Contains(FixedMathSharp.Geometry.CurvedPrismContactGeometry&,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,FixedMathSharp.Geometry.ContactQuadratic,System.Int32)
WithinDisk(System.Span`1<System.UInt64>,System.Span`1<System.Int32>,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Signed832,System.Int32,FixedMathSharp.Signed576)
IsMinimum(FixedMathSharp.Geometry.WideDirection3d&,System.ReadOnlySpan`1<System.UInt64>,System.ReadOnlySpan`1<System.Int32>,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,System.Span`1<System.UInt64>)
SetMagnitude(System.ReadOnlySpan`1<System.UInt64>,System.Int32,FixedMathSharp.Geometry.ContactQuadratic)
CopyPoint(System.Span`1<System.UInt64>,System.Span`1<System.Int32>,System.Int32,FixedMathSharp.Geometry.ContactQuadratic,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,System.Span`1<System.UInt64>,System.Int32)