< Summary

Line coverage
100%
Covered lines: 680
Uncovered lines: 0
Coverable lines: 680
Total lines: 1173
Line coverage: 100%
Branch coverage
100%
Covered branches: 624
Total branches: 624
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: AccumulateCircles(...)100%6868100%
File 1: AccumulateCircleChart(...)100%4242100%
File 1: AccumulateAxialCardinal(...)100%1818100%
File 1: GetCircleLine(...)100%3030100%
File 1: AccumulateCircleParameter(...)100%2626100%
File 1: AccumulateGenerator(...)100%1414100%
File 2: At(...)100%11100%
File 2: Extend(...)100%11100%
File 2: Extend(...)100%11100%
File 2: Integer(...)100%11100%
File 2: Product(...)100%1414100%
File 2: Product(...)100%11100%
File 2: Product(...)100%1414100%
File 2: SetAffinePoint(...)100%1414100%
File 2: Accumulate(...)100%3838100%
File 2: AccumulateEdge(...)100%5050100%
File 2: IsPointInClip(...)100%2020100%
File 3: SetEvent(...)100%11100%
File 3: ReconstructPoint(...)100%11100%
File 3: ReconstructPoint(...)100%44100%
File 3: CompareEventAnchors(...)100%1414100%
File 3: CompareEventAnchors(...)100%22100%
File 3: CompareCoincidentProvenance(...)100%1414100%
File 3: SortVertices(...)100%66100%
File 3: CompareVertex(...)100%44100%
File 4: VisitNativeSegment(...)100%66100%
File 4: ContainsNativeSegmentPoint(...)100%4444100%
File 5: VisitEvents(...)100%11100%
File 5: VisitEvents(...)100%88100%
File 5: IntersectsTriangle(...)100%2020100%
File 5: GetIntrinsicEvents(...)100%7676100%
File 5: GetBoundaryEvents(...)100%1010100%
File 5: TryEvaluateEvent(...)100%1010100%
File 5: TryEvaluateEvent(...)100%1414100%
File 6: AccumulateAxisAndApex(...)100%3030100%
File 6: AccumulateBaseStationary(...)100%1414100%

File(s)

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/ConePlaneRayEvents.Circles.cs

#LineLine coverage
 1//=======================================================================
 2// ConePlaneRayEvents.Circles.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>Generator-circle and projected upper-rim boundary events.</content>
 13internal static partial class ConePlaneRayEvents
 14{
 15    // Circle coefficients <1248 bits; chart sums and doubled linear
 16    // denominators <1250 bits fit this 1280-bit bank. Full generator,
 17    // discriminant and exit fields retain their independently larger banks.
 18
 19    private static bool AccumulateCircles(in ConePlaneRayEventSource source, in ConePlaneRayFrame frame,
 20        scoped ref ConePlaneRaySelection positive, scoped ref ConePlaneRaySelection negative,
 21        scoped ref ConePlaneRayEventSink sink)
 22    {
 4577123        if (!sink.IsStreaming)
 4571624            return AccumulateCircleChart(source, frame, sink.Target.Kind == ConePlaneRayEventKind.UpperRim,
 4571625                sink.Target.Feature, sink.Target.Quadrant, sink.Target.Branch, sink.Target.Branch, Span<ulong>.Empty, Sp
 5526        bool axial = frame.Normal.X.IsZero && frame.Normal.Z.IsZero && !frame.Normal.Y.IsZero;
 27        // A defining line is independent of quadrant. Keep one borrowed bank
 28        // for the current lower/upper cohort; quadrant zero fills every used
 29        // entry before the remaining quadrants read it. Axial plane cohorts have no
 30        // nonseam lines. One allocation outside the loop bounds stack usage.
 5531        int lineFields = source.IsSegment ? 6 : axial ? 0 : 48;
 5532        Span<ulong> lines = stackalloc ulong[lineFields * frame.CircleWords];
 5533        Span<int> lineSigns = stackalloc int[lineFields];
 5534        bool found = false;
 35        // Match the compact inventories exactly, including seam ownership and
 36        // axial pruning. Each chart reuses its defining line for both roots;
 37        // generator endpoints reuse that same admitted circle parameter.
 26838        for (int upper = source.IsSegment ? 1 : 0; upper < 2; upper++)
 79039        for (int quadrant = 0; quadrant < 4; quadrant++)
 40        {
 31641            if (source.Scope == ConePlaneRayEventScope.Plane)
 115242                for (int endpoint = 0; endpoint < 2; endpoint++)
 43                {
 38444                    if (endpoint == 0 ? (quadrant & 2) != 0 : (quadrant & 1) != 0) continue;
 19245                    if (!axial || upper == 0 && frame.Radius != Fixed64.Zero && !frame.PlaneConstant.IsZero)
 16046                        found |= AccumulateCircleChart(source, frame, upper != 0, 8, quadrant, endpoint, endpoint, lines
 47                }
 31648            if (axial && source.Scope == ConePlaneRayEventScope.Plane) continue;
 26849            int lineCount = source.IsSegment ? 1 : upper == 0 ? 6 : 8;
 280050            for (int line = 0; line < lineCount; line++)
 51            {
 113252                if (source.Scope == ConePlaneRayEventScope.Plane)
 53                {
 54                    // The azimuth line has only cardinal seam roots when one
 55                    // radial normal component is zero; seam cohorts own them.
 100856                    if (line == (upper == 0 ? 5 : 7)
 100857                        && (frame.Normal.X.IsZero || frame.Normal.Z.IsZero)) continue;
 58                    // Lower line 0 imposes N.g=0 and can retain a generator
 59                    // only when c=0. Radial upper lines 4/5 are respectively
 60                    // a positive constant and the zero polynomial. Neither
 61                    // yields an isolated root. For c!=0, lower line 1 already
 62                    // supplies upper line 3's base points and both exits. For
 63                    // Ny=0, line 6 projects by reflection onto that same base
 64                    // intersection (line 3 when c=0). Lower/cardinal provenance
 65                    // wins those ties. Target replay retains every descriptor.
 89666                    if (upper == 0 ? line >= 2 && line <= 4 || line == 0 && !frame.PlaneConstant.IsZero
 89667                        : line < 3 || line == 3 && !frame.PlaneConstant.IsZero
 89668                            || frame.Normal.Y.IsZero && line >= 4 && line <= 6) continue;
 69                }
 38870                found |= AccumulateCircleChart(source, frame, upper != 0, line, quadrant, -1, 1, lines, lineSigns, ref p
 71            }
 72        }
 5573        return found;
 74    }
 75
 76    private static bool AccumulateCircleChart(in ConePlaneRayEventSource source, in ConePlaneRayFrame frame,
 77        bool upper, int line, int quadrant, int firstBranch, int lastBranch,
 78        scoped Span<ulong> lines, scoped Span<int> lineSigns, scoped ref ConePlaneRaySelection positive, scoped ref Cone
 79        scoped ref ConePlaneRayEventSink sink)
 80    {
 4626681        if (source.IsSegment && (!upper || line != 0)) return false;
 4626282        if (!upper && line == 8 && frame.Normal.X.IsZero && frame.Normal.Z.IsZero && !frame.Normal.Y.IsZero)
 36983            return AccumulateAxialCardinal(source, frame, quadrant, firstBranch, ref positive, ref negative, ref sink);
 9178684        Span<ulong> values = stackalloc ulong[16 * frame.CircleWords], root = stackalloc ulong[frame.RootWords];
 4589385        Span<int> signs = stackalloc int[16];
 13767986        ContactQuadratic x = ContactQuadratic.At(values, signs, 0, frame.CircleWords), z = ContactQuadratic.At(values, s
 13767987        ContactQuadratic a = ContactQuadratic.At(values, signs, 3, frame.CircleWords), b = ContactQuadratic.At(values, s
 9178688        ContactQuadratic n = ContactQuadratic.At(values, signs, 6, frame.CircleWords), d = ContactQuadratic.At(values, s
 9178689        int sx = (quadrant & 1) == 0 ? 1 : -1, sz = (quadrant & 2) == 0 ? 1 : -1;
 4589390        ConePlaneRayEventKind kind = upper ? ConePlaneRayEventKind.UpperRim : ConePlaneRayEventKind.LowerCircle;
 4589391        if (line == 8)
 92        {
 93            // The cohort enumerator owns each cardinal seam exactly once.
 2058094            root.Clear(); n.Set(Integer(firstBranch)); d.Set(Integer(1));
 686095            var seam = new ConePlaneRayEvent(kind, line, quadrant, firstBranch, firstBranch);
 686096            return AccumulateCircleParameter(source, frame, upper, sx, sz, n, d, root, true,
 686097                seam, default, default, default, 0, ref positive, ref negative, ref sink);
 98        }
 3903399        if (sink.IsStreaming)
 100        {
 388101            ContactQuadratic lx = ContactQuadratic.At(lines, lineSigns, 3 * line, frame.CircleWords);
 388102            ContactQuadratic lz = ContactQuadratic.At(lines, lineSigns, 3 * line + 1, frame.CircleWords);
 388103            ContactQuadratic lc = ContactQuadratic.At(lines, lineSigns, 3 * line + 2, frame.CircleWords);
 485104            if (quadrant == 0) GetCircleLine(source, frame, upper, line, lx, lz, lc, ref sink);
 1164105            lx.CopyTo(x); lz.CopyTo(z); lc.CopyTo(constant);
 106        }
 38645107        else GetCircleLine(source, frame, upper, line, x, z, constant, ref sink);
 195165108        constant.CopyTo(a); a.Add(x, -sx); z.CopyTo(b, sz); constant.CopyTo(c); c.Add(x, sx);
 78066109        bool found = false, conjugate = false;
 156908110        for (int branch = firstBranch; branch <= lastBranch; branch += 2)
 111        {
 112            // A successful negative quadratic branch shares its rational
 113            // numerator, positive denominator and discriminant with the next
 114            // branch. Only the radical sign changes; linear/repeated cases
 115            // still use the shared chart owner's positive-branch handling.
 116            bool parameter;
 39829117            if (conjugate) { n.Signs[1] = 1; parameter = true; }
 118            else
 119            {
 39217120                parameter = ContactQuadratic.TryGetParameter(a, b, c, branch, root, n, d);
 39217121                conjugate = parameter && branch == -1;
 122            }
 123            // Cardinal cohorts own the endpoints; test the open chart once.
 39421124            if (!parameter || !ConePlaneRayCharts.IsUnitParameter(n, d, root, includeEndpoints: false)) continue;
 3297125            var descriptor = new ConePlaneRayEvent(kind, line, quadrant, branch);
 3297126            found |= AccumulateCircleParameter(source, frame, upper, sx, sz, n, d, root, line == 0,
 3297127                descriptor, x, z, constant, branch == -1 || branch == 1 ? a.Signs[0] * branch * sx * sz : 0,
 3297128                ref positive, ref negative, ref sink);
 129        }
 39033130        return found;
 131    }
 132
 133    private static bool AccumulateAxialCardinal(in ConePlaneRayEventSource source, in ConePlaneRayFrame frame,
 134        int quadrant, int branch, scoped ref ConePlaneRaySelection positive, scoped ref ConePlaneRaySelection negative,
 135        scoped ref ConePlaneRayEventSink sink)
 136    {
 369137        Signed832 sectionHeight = frame.Normal.Y.Sign < 0
 369138            ? WideArithmetic.SubtractSigned832(default, frame.PlaneConstant) : frame.PlaneConstant;
 369139        if (sectionHeight.Sign < 0 || WideArithmetic.SubtractSigned832(sectionHeight,
 369140                Signed832.ExtendValue(Extend(frame.Finite.FullHeight))).Sign > 0)
 82141            return false;
 287142        Span<ulong> pointValues = stackalloc ulong[frame.PointStorageWords];
 287143        Span<int> pointSigns = stackalloc int[ConePlaneRayPoint.SignCount];
 574144        var point = new ConePlaneRayPoint(pointValues, pointSigns, frame.FieldWords); point.Set(default(WideAxis3));
 574145        Span<ulong> values = stackalloc ulong[2 * frame.FieldWords]; Span<int> signs = stackalloc int[2];
 287146        ContactQuadratic height = At(values, signs, 0);
 147        // A primitive axial normal has Ny=+/-1, hence s=c*sign(Ny).
 148        // With positive homogeneous denominator Hraw, a cardinal generator
 149        // section is (X,Y,Z)=(+/-s*Rraw,s*Hraw,0), or its Z counterpart.
 150        // s<198 bits and raw dimensions<63 keep products below261 bits.
 151        // Plane scope and the primitive axial normal are established by the
 152        // chart dispatcher. These coordinates satisfy the plane and zero cone
 153        // polynomial exactly; the closed s range proves remaining admission.
 154        // Radius zero or s=0 remains an axis point for the shared exit owner.
 287155        height.Set(sectionHeight);
 287156        Signed576 rawHeight = Extend(Signed320.ExtendValue(Signed192.Raw(frame.Height)));
 287157        ContactQuadratic.Scale(height, rawHeight, point.Y);
 287158        ContactQuadratic radial = branch == 0 ? point.X : point.Z;
 287159        ContactQuadratic.Scale(height, Extend(Signed320.ExtendValue(Signed192.Raw(frame.Radius))), radial);
 287160        radial.MultiplySign((quadrant & (branch == 0 ? 1 : 2)) == 0 ? 1 : -1);
 287161        point.Denominator.Set(rawHeight);
 287162        var descriptor = new ConePlaneRayEvent(ConePlaneRayEventKind.LowerCircle, 8, quadrant, branch, branch);
 287163        SetEvent(source, descriptor, ref positive, ref negative);
 287164        if (!sink.PointOnly)
 165        {
 265166            if (sink.RequestedOrientation >= 0)
 167            {
 243168                bool found = ConePlaneRayPointExits.TryAccumulateAxialOrientation(point, frame,
 243169                    ReadOnlySpan<ulong>.Empty, 1, sidePoint: true, ref positive);
 170                System.Diagnostics.Debug.Assert(found);
 171            }
 265172            if (sink.RequestedOrientation <= 0)
 173            {
 243174                bool found = ConePlaneRayPointExits.TryAccumulateAxialOrientation(point, frame,
 243175                    ReadOnlySpan<ulong>.Empty, -1, sidePoint: true, ref negative);
 176                System.Diagnostics.Debug.Assert(found);
 177            }
 178        }
 287179        sink.Keep(descriptor, point, ReadOnlySpan<ulong>.Empty, positive, negative);
 287180        return true;
 181    }
 182
 183    // Returns x*cos(theta)+z*sin(theta)+constant. Scaling the symbolic line
 184    // before chart substitution keeps its defining coefficients below1248bits.
 185    private static void GetCircleLine(in ConePlaneRayEventSource source, in ConePlaneRayFrame frame,
 186        bool upper, int line, scoped ContactQuadratic x, scoped ContactQuadratic z, scoped ContactQuadratic constant, sc
 187    {
 38742188        Span<ulong> values = stackalloc ulong[14 * frame.CircleWords];
 38742189        Span<int> signs = stackalloc int[14];
 116226190        ContactQuadratic lx = ContactQuadratic.At(values, signs, 0, frame.CircleWords), ly = ContactQuadratic.At(values,
 77484191        ContactQuadratic offset = ContactQuadratic.At(values, signs, 3, frame.CircleWords), A = ContactQuadratic.At(valu
 77484192        ContactQuadratic term = ContactQuadratic.At(values, signs, 5, frame.CircleWords), scalar = ContactQuadratic.At(v
 154968193        lx.Clear(); ly.Clear(); lz.Clear(); offset.Clear();
 38742194        if (source.IsSegment)
 195        {
 196            Signed576 wx, wy, wz; Signed832 w;
 9207197            if (sink.NativeSegment.IsEmpty)
 9195198                frame.GetEdgeLine(new FixedSegment(source.A, source.B), out wx, out wy, out wz, out w);
 199            else
 200            {
 12201                sink.GetSegment(source, frame, out WideAxis3 a, out WideAxis3 b);
 12202                WideDirection3d edge = CurvedPrismContact.Difference(new WideDirection3d(b), new WideDirection3d(a));
 12203                WideDirection3d wall = WideDirection3d.Cross(frame.Normal, edge);
 36204                wx = wall.X; wy = wall.Y; wz = wall.Z;
 12205                w = WideDirection3d.Dot(wall, a);
 206            }
 27621207            lx.Set(wx); ly.Set(wy); lz.Set(wz);
 9207208            offset.Set(WideArithmetic.SubtractSigned832(default, w));
 209        }
 29535210        else if (line == (upper ? 7 : 5))
 211        {
 13128212            lx.Set(Extend(frame.Normal.Z)); lz.Set(Extend(WideArithmetic.SubtractSigned576(default, frame.Normal.X)));
 213        }
 22971214        else if (upper && (line == 4 || line == 5))
 215        {
 6432216            scalar.Set(Extend(frame.Normal.Y));
 12864217            ContactQuadratic.Scale(scalar, Extend(frame.Normal.X), lx); lx.MultiplySign(-1);
 12864218            ContactQuadratic.Scale(scalar, Extend(frame.Normal.Y), ly); ly.MultiplySign(-1);
 12864219            ContactQuadratic.Scale(scalar, Extend(frame.Normal.Z), lz); lz.MultiplySign(-1);
 6432220            ContactQuadratic.Scale(scalar, frame.PlaneConstant, offset);
 6432221            if (line == 4)
 222            {
 3212223                scalar.Set(frame.NormalSquared);
 6424224                ContactQuadratic.Scale(scalar, Extend(frame.Finite.FullHeight), term); offset.Add(term);
 225            }
 226        }
 16539227        else if (upper && line == 6 && frame.Normal.Y.IsZero)
 228        {
 229            // For a radial plane A=H²*|N|². Cancel that strictly positive
 230            // common factor from the line before chart substitution; its
 231            // roots, branch labels and projected witnesses are unchanged.
 101232            lx.Set(Extend(WideArithmetic.SubtractSigned576(default, frame.Normal.X)));
 101233            lz.Set(Extend(WideArithmetic.SubtractSigned576(default, frame.Normal.Z)));
 101234            offset.Set(WideArithmetic.SubtractSigned832(default, frame.PlaneConstant));
 235        }
 16438236        else if (upper && line == 6)
 237        {
 2552238            Product(frame.Normal, frame.Normal, frame, A);
 2552239            Signed576 h2 = Extend(WideArithmetic.MultiplySigned192(Signed192.Raw(frame.Height), Signed192.Raw(frame.Heig
 2552240            Signed576 r2 = Extend(WideArithmetic.MultiplySigned192(Signed192.Raw(frame.Radius), Signed192.Raw(frame.Radi
 2552241            scalar.Set(frame.NormalSquared);
 5104242            ContactQuadratic.Scale(scalar, h2, term); term.Add(term);
 7656243            A.CopyTo(lx); lx.Add(term, -1); lx.CopyTo(lz);
 5104244            ContactQuadratic.Scale(scalar, r2, term); term.Add(term);
 5104245            A.CopyTo(ly); ly.Add(term);
 5104246            ContactQuadratic.Scale(lx, Extend(frame.Normal.X), term); term.CopyTo(lx);
 5104247            ContactQuadratic.Scale(ly, Extend(frame.Normal.Y), term); term.CopyTo(ly);
 5104248            ContactQuadratic.Scale(lz, Extend(frame.Normal.Z), term); term.CopyTo(lz);
 5104249            ContactQuadratic.Scale(A, frame.PlaneConstant, offset); offset.MultiplySign(-1);
 250        }
 251        else
 252        {
 41658253            lx.Set(Extend(frame.Normal.X)); ly.Set(Extend(frame.Normal.Y)); lz.Set(Extend(frame.Normal.Z));
 13886254            if (upper || line == 1)
 3864255                offset.Set(WideArithmetic.SubtractSigned832(default, frame.PlaneConstant));
 256        }
 38742257        Signed320 radius = Signed320.NarrowValue(WideArithmetic.MultiplySigned320(
 38742258            frame.Finite.ShapeFrame.CoordinateDenominator, frame.Finite.ShapeFrame.Radius));
 38742259        ContactQuadratic.Scale(lx, Extend(radius), x);
 38742260        ContactQuadratic.Scale(lz, Extend(radius), z);
 77484261        ContactQuadratic.Scale(ly, Extend(frame.Finite.FullHeight), constant); constant.Add(offset);
 38742262    }
 263
 264    private static bool AccumulateCircleParameter(in ConePlaneRayEventSource source, in ConePlaneRayFrame frame,
 265        bool upper, int sx, int sz, scoped ContactQuadratic n, scoped ContactQuadratic d, scoped ReadOnlySpan<ulong> roo
 266        ConePlaneRayEvent descriptor, scoped ContactQuadratic lineX, scoped ContactQuadratic lineZ,
 267        scoped ContactQuadratic lineConstant, int circleRootSign,
 268        scoped ref ConePlaneRaySelection positive, scoped ref ConePlaneRaySelection negative, scoped ref ConePlaneRayEve
 269    {
 10157270        Span<ulong> values = stackalloc ulong[20 * frame.FieldWords];
 10157271        Span<int> signs = stackalloc int[20];
 10157272        Span<ulong> pointValues = stackalloc ulong[frame.PointStorageWords];
 10157273        Span<int> pointSigns = stackalloc int[8];
 10157274        var point = new ConePlaneRayPoint(pointValues, pointSigns, frame.FieldWords);
 30471275        ContactQuadratic nn = At(values, signs, 0), dd = At(values, signs, 1), gx = At(values, signs, 2);
 30471276        ContactQuadratic gy = At(values, signs, 3), gz = At(values, signs, 4), gd = At(values, signs, 5);
 20314277        ContactQuadratic dot = At(values, signs, 6), term = At(values, signs, 7);
 20314278        ContactQuadratic t = At(values, signs, 8), td = At(values, signs, 9);
 10157279        Signed320 radius = Signed320.NarrowValue(WideArithmetic.MultiplySigned320(
 10157280            frame.Finite.ShapeFrame.CoordinateDenominator, frame.Finite.ShapeFrame.Radius));
 10157281        if (circleRootSign != 0)
 282        {
 283            // x*cos+z*sin+c=0 gives (cos,sin)=(-c*x+e*z*sqrt(D),
 284            // -c*z-e*x*sqrt(D))/(x*x+z*z), D=x*x+z*z-c*c.
 285            // The existing quadrant root has this same D and e=sign(a)*
 286            // branch*sx*sz. Linear charts retain their rational parameter
 287            // because their root bank is zero. Defining-line coefficients <1118
 288            // bits keep projected homogeneous fields <2960 bits in the existing bank.
 3223289            ContactQuadratic.Multiply(lineX, lineX, root, gd);
 6446290            ContactQuadratic.Multiply(lineZ, lineZ, root, term); gd.Add(term);
 6446291            ContactQuadratic.Multiply(lineConstant, lineX, root, gx); gx.MultiplySign(-1);
 6446292            ContactQuadratic.MultiplyRoot(lineZ, root, term); gx.Add(term, circleRootSign);
 6446293            ContactQuadratic.Multiply(lineConstant, lineZ, root, gz); gz.MultiplySign(-1);
 6446294            ContactQuadratic.MultiplyRoot(lineX, root, term); gz.Add(term, -circleRootSign);
 295        }
 296        else
 297        {
 13868298            ContactQuadratic.Multiply(n, n, root, nn); ContactQuadratic.Multiply(d, d, root, dd);
 13868299            dd.CopyTo(gd); gd.Add(nn);
 20802300            dd.CopyTo(gx); gx.Add(nn, -1); gx.MultiplySign(sx);
 20802301            ContactQuadratic.Multiply(n, d, root, gz); gz.Add(gz); gz.MultiplySign(sz);
 302        }
 20314303        ContactQuadratic.Scale(gx, Extend(radius), term); term.CopyTo(gx);
 10157304        ContactQuadratic.Scale(gd, Extend(frame.Finite.FullHeight), gy);
 20314305        ContactQuadratic.Scale(gz, Extend(radius), term); term.CopyTo(gz);
 10157306        ContactQuadratic.Scale(gx, Extend(frame.Normal.X), dot);
 20314307        ContactQuadratic.Scale(gy, Extend(frame.Normal.Y), term); dot.Add(term);
 20314308        ContactQuadratic.Scale(gz, Extend(frame.Normal.Z), term); dot.Add(term);
 10157309        if (!upper)
 310        {
 6847311            int divisorSign = dot.Sign(root);
 6847312            if (divisorSign == 0)
 997313                return retainGenerator && frame.PlaneConstant.IsZero && AccumulateGenerator(source, frame, gx, gy, gz, g
 997314                    descriptor, ref positive, ref negative, ref sink);
 8970315            if (!sink.Wants(descriptor)) return false;
 5460316            ContactQuadratic.Scale(gx, frame.PlaneConstant, point.X); point.X.MultiplySign(divisorSign);
 5460317            ContactQuadratic.Scale(gy, frame.PlaneConstant, point.Y); point.Y.MultiplySign(divisorSign);
 5460318            ContactQuadratic.Scale(gz, frame.PlaneConstant, point.Z); point.Z.MultiplySign(divisorSign);
 2730319            dot.CopyTo(point.Denominator, divisorSign);
 2730320            SetEvent(source, descriptor, ref positive, ref negative);
 2730321            bool admitted = ConePlaneRayPointExits.AccumulateSidePoint(source, frame, point, root, ref positive, ref neg
 4873322            if (admitted) sink.Keep(descriptor, point, root, positive, negative);
 2730323            return admitted;
 324        }
 9930325        dot.CopyTo(t); ContactQuadratic.Scale(gd, frame.PlaneConstant, term); t.Add(term, -1);
 3310326        ContactQuadratic.Scale(gd, frame.NormalSquared, td);
 3310327        ContactQuadratic.Scale(gx, frame.NormalSquared, point.X);
 6620328        ContactQuadratic.Scale(t, Extend(frame.Normal.X), term); point.X.Add(term, -1);
 3310329        ContactQuadratic.Scale(gy, frame.NormalSquared, point.Y);
 6620330        ContactQuadratic.Scale(t, Extend(frame.Normal.Y), term); point.Y.Add(term, -1);
 3310331        ContactQuadratic.Scale(gz, frame.NormalSquared, point.Z);
 6620332        ContactQuadratic.Scale(t, Extend(frame.Normal.Z), term); point.Z.Add(term, -1);
 3310333        td.CopyTo(point.Denominator);
 3310334        int orientation = t.Sign(root);
 3310335        descriptor = new ConePlaneRayEvent(descriptor.Kind, descriptor.Feature, descriptor.Quadrant,
 3310336            descriptor.Branch, descriptor.Endpoint, orientation);
 3310337        SetEvent(source, descriptor, ref positive, ref negative);
 3310338        if (orientation == 0)
 339        {
 527340            bool sideAdmitted = ConePlaneRayPointExits.AccumulateSidePoint(source, frame, point, root, ref positive, ref
 1052341            if (sideAdmitted) sink.Keep(descriptor, point, root, positive, negative);
 527342            return sideAdmitted;
 343        }
 2783344        t.MultiplySign(orientation);
 345        // For projected rim line 6, F(P)=T*(A*T-2*|N|²*B(G)). A valid
 346        // chart root makes the second factor zero. Other projections and
 347        // malformed targeted branches retain full solid admission.
 2783348        bool sideCertificate = source.Scope == ConePlaneRayEventScope.Plane && descriptor.Feature == 6
 2783349            && (descriptor.Branch == -1 || descriptor.Branch == 1);
 2783350        bool certified = ConePlaneRayPointExits.AccumulateCertifiedExit(source, frame, point, root, t, td,
 2783351            orientation, ref positive, ref negative, sink.PointOnly, sideCertificate);
 4080352        if (certified) sink.Keep(descriptor, point, root, positive, negative);
 2783353        return certified;
 354    }
 355
 356    private static bool AccumulateGenerator(in ConePlaneRayEventSource source, in ConePlaneRayFrame frame,
 357        scoped ContactQuadratic gx, scoped ContactQuadratic gy, scoped ContactQuadratic gz, scoped ContactQuadratic gd,
 358        scoped ReadOnlySpan<ulong> root, ConePlaneRayEvent generator,
 359        scoped ref ConePlaneRaySelection positive, scoped ref ConePlaneRaySelection negative,
 360        scoped ref ConePlaneRayEventSink sink)
 361    {
 278362        if (!sink.Wants(ConePlaneRayEventKind.Generator) || !sink.IsStreaming && (uint)sink.Target.Endpoint > 1) return 
 154363        Span<ulong> pointValues = stackalloc ulong[frame.PointStorageWords];
 154364        Span<int> pointSigns = stackalloc int[ConePlaneRayPoint.SignCount];
 154365        var point = new ConePlaneRayPoint(pointValues, pointSigns, frame.FieldWords);
 366        // Only the cone's generator endpoints are intrinsic. Its intersection
 367        // with a finite boundary is already that segment's side root/endpoint.
 644368        for (int endpoint = sink.IsStreaming ? 0 : sink.Target.Endpoint; endpoint <= (sink.IsStreaming ? 1 : sink.Target
 369        {
 252370            if (endpoint == 0) point.Set(default(WideAxis3));
 336371            else { gx.CopyTo(point.X); gy.CopyTo(point.Y); gz.CopyTo(point.Z); gd.CopyTo(point.Denominator); }
 168372            var descriptor = new ConePlaneRayEvent(ConePlaneRayEventKind.Generator, generator.Feature,
 168373                generator.Quadrant, generator.Branch, endpoint);
 168374            SetEvent(source, descriptor, ref positive, ref negative);
 168375            bool admitted = ConePlaneRayPointExits.AccumulateSidePoint(source, frame, point, root, ref positive, ref neg
 376            // D=N.g=0 and c=0 already certify this intrinsic generator's plane.
 377            // Its apex has denominator 1; its base-rim endpoint has denominator
 378            // d*d+n*n>0 and satisfies the finite cone exactly, including R=0.
 379            System.Diagnostics.Debug.Assert(admitted);
 168380            sink.Keep(descriptor, point, root, positive, negative);
 381        }
 154382        return true;
 383    }
 384}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/ConePlaneRayEvents.cs

#LineLine coverage
 1//=======================================================================
 2// ConePlaneRayEvents.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024-present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using System;
 9
 10namespace FixedMathSharp.Geometry;
 11
 12/// <summary>Exact critical events for a finite cone with a shared plane, finite segment.</summary>
 13/// <content>Scoped event dispatch and authored-edge endpoint, side and stationary candidates.</content>
 14internal static partial class ConePlaneRayEvents
 15{
 16    private static ContactQuadratic At(Span<ulong> values, Span<int> signs, int index) =>
 31951717        ContactQuadratic.At(values, signs, index, values.Length / signs.Length);
 35663018    private static Signed576 Extend(Signed320 value) => Signed576.ExtendValue(value);
 13318919    private static Signed576 Extend(Signed576 value) => value;
 1377220    private static Signed576 Integer(long value) => Extend(Signed320.ExtendValue(Signed192.Signed(value)));
 21
 22    // The fixed-width frame product is sufficient for two authored points,
 23    // but not for the larger canonical normal. Keep normal products in the
 24    // existing quadratic owner instead of narrowing their exact coefficients.
 25    private static void Product(in WideAxis3 left, in WideAxis3 right,
 26        in ConePlaneRayFrame frame, ContactQuadratic result)
 27    {
 1388728        Span<ulong> values = stackalloc ulong[8 * frame.FieldWords];
 1388729        Span<int> signs = stackalloc int[8];
 2777430        ContactQuadratic x = At(values, signs, 0), y = At(values, signs, 1);
 2777431        ContactQuadratic term = At(values, signs, 2), scaled = At(values, signs, 3);
 1388732        result.Clear();
 11109633        for (int axis = 0; axis < 3; axis++)
 34        {
 4166135            x.Set(Extend(axis == 0 ? left.X : axis == 1 ? left.Y : left.Z));
 4166136            y.Set(Extend(axis == 0 ? right.X : axis == 1 ? right.Y : right.Z));
 4166137            ContactQuadratic.Multiply(x, y, ReadOnlySpan<ulong>.Empty, term);
 4166138            Signed192 raw = Signed192.Raw(axis == 1 ? frame.Radius : frame.Height);
 4166139            ContactQuadratic.Scale(term, Extend(WideArithmetic.MultiplySigned192(raw, raw)), scaled);
 4166140            result.Add(scaled, axis == 1 ? -1 : 1);
 41        }
 1388742    }
 43
 44    private static void Product(in WideAxis3 left, in WideDirection3d right,
 460845        in ConePlaneRayFrame frame, ContactQuadratic result) => Product(new WideDirection3d(left), right, frame, result)
 46
 47    private static void Product(in WideDirection3d left, in WideDirection3d right,
 48        in ConePlaneRayFrame frame, ContactQuadratic result)
 49    {
 1013050        Span<ulong> values = stackalloc ulong[8 * frame.FieldWords];
 1013051        Span<int> signs = stackalloc int[8];
 2026052        ContactQuadratic x = At(values, signs, 0), y = At(values, signs, 1);
 2026053        ContactQuadratic term = At(values, signs, 2), scaled = At(values, signs, 3);
 1013054        result.Clear();
 8104055        for (int axis = 0; axis < 3; axis++)
 56        {
 3039057            x.Set(axis == 0 ? left.X : axis == 1 ? left.Y : left.Z);
 3039058            y.Set(axis == 0 ? right.X : axis == 1 ? right.Y : right.Z);
 3039059            ContactQuadratic.Multiply(x, y, ReadOnlySpan<ulong>.Empty, term);
 3039060            Signed192 raw = Signed192.Raw(axis == 1 ? frame.Radius : frame.Height);
 3039061            ContactQuadratic.Scale(term, Extend(WideArithmetic.MultiplySigned192(raw, raw)), scaled);
 3039062            result.Add(scaled, axis == 1 ? -1 : 1);
 63        }
 1013064    }
 65
 66    private static void SetAffinePoint(ConePlaneRayPoint point, in WideAxis3 start, in WideAxis3 delta,
 67        ContactQuadratic numerator, ContactQuadratic denominator)
 68    {
 446669        Span<ulong> values = stackalloc ulong[2 * point.BankWords];
 446670        Span<int> signs = stackalloc int[2];
 446671        ContactQuadratic term = At(values, signs, 0);
 3572872        for (int axis = 0; axis < 3; axis++)
 73        {
 1339874            ContactQuadratic target = axis == 0 ? point.X : axis == 1 ? point.Y : point.Z;
 1339875            ContactQuadratic.Scale(denominator, Extend(axis == 0 ? start.X : axis == 1 ? start.Y : start.Z), target);
 1339876            ContactQuadratic.Scale(numerator, Extend(axis == 0 ? delta.X : axis == 1 ? delta.Y : delta.Z), term);
 1339877            target.Add(term);
 78        }
 446679        denominator.CopyTo(point.Denominator);
 446680    }
 81
 82    private static bool Accumulate(in ConePlaneRayEventSource source, in ConePlaneRayFrame frame,
 83        scoped ref ConePlaneRaySelection positive, scoped ref ConePlaneRaySelection negative,
 84        scoped ref ConePlaneRayEventSink sink)
 85    {
 5574286        sink.HasPoint = false;
 5574287        if (frame.NormalSquared.IsZero)
 55388            return false;
 5518989        bool found = false;
 5518990        if (source.IsSegment && sink.Target.Feature == 0
 5518991            && (sink.Wants(ConePlaneRayEventKind.EdgeEndpoint) || sink.Wants(ConePlaneRayEventKind.EdgeSide)
 5518992                || sink.Wants(ConePlaneRayEventKind.EdgeStationary)))
 701693            found |= AccumulateEdge(source, frame, ref positive, ref negative, ref sink);
 5518994        if (!sink.IsStreaming && !source.IsSegment
 5518995            && (sink.Wants(ConePlaneRayEventKind.Axis) || sink.Wants(ConePlaneRayEventKind.Apex)))
 175196            found |= AccumulateAxisAndApex(source, frame, ref positive, ref negative, ref sink);
 5518997        if (sink.Wants(ConePlaneRayEventKind.LowerCircle) || sink.Wants(ConePlaneRayEventKind.UpperRim)
 5518998            || sink.Wants(ConePlaneRayEventKind.Generator))
 4577199            found |= AccumulateCircles(source, frame, ref positive, ref negative, ref sink);
 55189100        if (sink.IsStreaming && !source.IsSegment)
 24101            found |= AccumulateAxisAndApex(source, frame, ref positive, ref negative, ref sink);
 102        // Radial base-stationary points/exits already belong to upper line 7
 103        // or its cardinal seams, with earlier canonical provenance.
 55189104        if (!source.IsSegment && sink.Wants(ConePlaneRayEventKind.BaseStationary)
 55189105            && (!sink.IsStreaming || !frame.Normal.Y.IsZero))
 686106            found |= AccumulateBaseStationary(source, frame, ref positive, ref negative, ref sink);
 55189107        return found;
 108    }
 109
 110    private static bool AccumulateEdge(in ConePlaneRayEventSource source, in ConePlaneRayFrame frame,
 111        scoped ref ConePlaneRaySelection positive, scoped ref ConePlaneRaySelection negative,
 112        scoped ref ConePlaneRayEventSink sink)
 113    {
 7016114        sink.GetSegment(source, frame, out WideAxis3 p, out WideAxis3 end);
 7016115        WideAxis3 e = new(WideArithmetic.SubtractSigned320(end.X, p.X),
 7016116            WideArithmetic.SubtractSigned320(end.Y, p.Y), WideArithmetic.SubtractSigned320(end.Z, p.Z));
 7016117        if (!frame.Finite.TryGetAxialInterval(p.Y, e.Y, out Signed320 ln, out Signed320 ld,
 7016118            out Signed320 un, out Signed320 ud))
 48119            return false;
 6968120        Signed832 lowerN = Signed832.ExtendValue(Signed576.ExtendValue(ln)),
 6968121            lowerD = Signed832.ExtendValue(Signed576.ExtendValue(ld)),
 6968122            upperN = Signed832.ExtendValue(Signed576.ExtendValue(un)),
 6968123            upperD = Signed832.ExtendValue(Signed576.ExtendValue(ud));
 6968124        if (!sink.Clip.IsEmpty)
 125        {
 38126            ref readonly RationalSegmentInterval clip = ref sink.Clip[0];
 38127            if (RationalSegmentInterval.CompareParameters(clip.WideLowerNumerator, clip.WideLowerDenominator, lowerN, lo
 64128            { lowerN = clip.WideLowerNumerator; lowerD = clip.WideLowerDenominator; }
 38129            if (RationalSegmentInterval.CompareParameters(clip.WideUpperNumerator, clip.WideUpperDenominator, upperN, up
 68130            { upperN = clip.WideUpperNumerator; upperD = clip.WideUpperDenominator; }
 41131            if (RationalSegmentInterval.CompareParameters(lowerN, lowerD, upperN, upperD) > 0) return false;
 132        }
 6965133        Span<ulong> values = stackalloc ulong[30 * frame.FieldWords];
 6965134        Span<int> signs = stackalloc int[30];
 6965135        Span<ulong> root = stackalloc ulong[frame.RootWords];
 6965136        Span<ulong> pointValues = stackalloc ulong[frame.PointStorageWords];
 6965137        Span<int> pointSigns = stackalloc int[8];
 6965138        var point = new ConePlaneRayPoint(pointValues, pointSigns, frame.FieldWords);
 20895139        ContactQuadratic a = At(values, signs, 0), b = At(values, signs, 1), c = At(values, signs, 2);
 20895140        ContactQuadratic m = At(values, signs, 3), n = At(values, signs, 4), A = At(values, signs, 5);
 20895141        ContactQuadratic qa = At(values, signs, 6), qb = At(values, signs, 7), qc = At(values, signs, 8);
 20895142        ContactQuadratic t = At(values, signs, 9), d = At(values, signs, 10), s = At(values, signs, 11);
 20895143        ContactQuadratic sd = At(values, signs, 12), work = At(values, signs, 13), term = At(values, signs, 14);
 6965144        bool found = false;
 41790145        for (int endpoint = 0; endpoint < 2; endpoint++)
 146        {
 13930147            var descriptor = new ConePlaneRayEvent(ConePlaneRayEventKind.EdgeEndpoint, endpoint: endpoint);
 13930148            if (!sink.Wants(descriptor)) continue;
 4792149            s.Set(endpoint == 0 ? lowerN : upperN); sd.Set(endpoint == 0 ? lowerD : upperD);
 2396150            SetAffinePoint(point, p, e, s, sd);
 2396151            SetEvent(source, descriptor, ref positive, ref negative);
 2396152            bool admitted = ConePlaneRayPointExits.AccumulateRationalPoint(source, frame, point, ref positive, ref negat
 2548153            if (admitted) sink.Keep(descriptor, point, ReadOnlySpan<ulong>.Empty, positive, negative);
 2396154            found |= admitted;
 155        }
 6965156        if (!sink.Wants(ConePlaneRayEventKind.EdgeSide) && !sink.Wants(ConePlaneRayEventKind.EdgeStationary))
 2336157            return found;
 13887158        Product(e, e, frame, a); Product(p, e, frame, b); Product(p, p, frame, c);
 159        // Construct the stationary polynomial once, then emit side/stationary
 160        // events in each branch's inventory order. Targeted side replay avoids
 161        // these products entirely; streaming does not retain extra wide fields.
 4629162        bool stationary = a.Signs[0] != 0 && sink.Wants(ConePlaneRayEventKind.EdgeStationary);
 4629163        if (stationary)
 164        {
 4608165            Product(e, frame.Normal, frame, m); Product(p, frame.Normal, frame, n);
 2304166            Product(frame.Normal, frame.Normal, frame, A);
 2304167            ContactQuadratic.Multiply(a, A, ReadOnlySpan<ulong>.Empty, qa);
 4608168            ContactQuadratic.Multiply(m, m, ReadOnlySpan<ulong>.Empty, term); qa.Add(term, -1);
 2304169            ContactQuadratic.Multiply(a, n, ReadOnlySpan<ulong>.Empty, qb);
 4608170            ContactQuadratic.Multiply(b, m, ReadOnlySpan<ulong>.Empty, term); qb.Add(term, -1);
 2304171            ContactQuadratic.Multiply(a, c, ReadOnlySpan<ulong>.Empty, qc);
 4608172            ContactQuadratic.Multiply(b, b, ReadOnlySpan<ulong>.Empty, term); qc.Add(term, -1);
 173        }
 174        // a=0 has no isolated interior stationary point, or has a constant
 175        // interval already represented by its clipped endpoints and side/rim.
 27774176        for (int branch = -1; branch <= 1; branch += 2)
 177        {
 9258178            var descriptor = new ConePlaneRayEvent(ConePlaneRayEventKind.EdgeSide, branch: branch);
 9258179            if (sink.Wants(descriptor)
 9258180                && ContactQuadratic.TryGetParameter(a, b, c, branch, root, s, sd)
 9258181                && ConePlaneRayCharts.IsUnitParameter(s, sd, root))
 182            {
 558183                SetAffinePoint(point, p, e, s, sd);
 558184                SetEvent(source, descriptor, ref positive, ref negative);
 558185                bool admitted = ConePlaneRayPointExits.AccumulateSidePoint(source, frame, point, root, ref positive, ref
 698186                if (admitted) sink.Keep(descriptor, point, root, positive, negative);
 558187                found |= admitted;
 188            }
 9258189            descriptor = new ConePlaneRayEvent(ConePlaneRayEventKind.EdgeStationary, branch: branch);
 9258190            if (!stationary || !sink.Wants(descriptor)
 9258191                || !ContactQuadratic.TryGetParameter(qa, qb, qc, branch, root, t, d))
 192                continue;
 2197193            ContactQuadratic.Multiply(b, d, root, s);
 6591194            ContactQuadratic.Multiply(m, t, root, term); s.Add(term); s.MultiplySign(-a.Signs[0]);
 4394195            ContactQuadratic.Multiply(a, d, root, sd); sd.MultiplySign(a.Signs[0]);
 2197196            if (!ConePlaneRayCharts.IsUnitParameter(s, sd, root))
 197                continue;
 1512198            SetAffinePoint(point, p, e, s, sd);
 1512199            int orientation = t.Sign(root) < 0 ? -1 : 1;
 1512200            descriptor = new ConePlaneRayEvent(descriptor.Kind, branch: branch, orientation: orientation);
 1512201            t.CopyTo(work, orientation);
 1512202            SetEvent(source, descriptor, ref positive, ref negative);
 1512203            bool stationaryAdmitted = ConePlaneRayPointExits.AccumulateStationarySideExit(source, frame, point, root,
 1512204                work, d, orientation, ref positive, ref negative, sink.PointOnly);
 1608205            if (stationaryAdmitted) sink.Keep(descriptor, point, root, positive, negative);
 1512206            found |= stationaryAdmitted;
 207        }
 4629208        return found;
 209    }
 210
 211    internal static bool IsPointInClip(in ConePlaneRayEventSource source, in ConePlaneRayFrame frame,
 212        scoped ConePlaneRayPoint point, scoped ReadOnlySpan<ulong> root, in RationalSegmentInterval clip)
 213    {
 106214        WideAxis3 start = frame.Transform(source.A), end = frame.Transform(source.B);
 53215        Signed320 dx = WideArithmetic.SubtractSigned320(end.X, start.X);
 53216        Signed320 dy = WideArithmetic.SubtractSigned320(end.Y, start.Y);
 53217        Signed320 dz = WideArithmetic.SubtractSigned320(end.Z, start.Z);
 53218        int axis = !dx.IsZero ? 0 : !dy.IsZero ? 1 : 2;
 53219        Signed320 delta = axis == 0 ? dx : axis == 1 ? dy : dz;
 57220        if (delta.IsZero) return true;
 49221        ContactQuadratic coordinate = axis == 0 ? point.X : axis == 1 ? point.Y : point.Z;
 222        // Transformed authored endpoints/differences are <199 bits. Preserve
 223        // the complete point fields plus four limbs before interval products.
 49224        int words = Math.Max(ContactQuadratic.ActiveWords(coordinate), ContactQuadratic.ActiveWords(point.Denominator)) 
 98225        Span<ulong> values = stackalloc ulong[4 * words]; Span<int> signs = stackalloc int[4];
 98226        ContactQuadratic numerator = ContactQuadratic.At(values, signs, 0, words), denominator = ContactQuadratic.At(val
 49227        ContactQuadratic.Scale(point.Denominator, Extend(axis == 0 ? start.X : axis == 1 ? start.Y : start.Z), numerator
 98228        numerator.MultiplySign(-1); numerator.Add(coordinate);
 49229        ContactQuadratic.Scale(point.Denominator, Extend(delta), denominator);
 61230        if (denominator.Sign(root) < 0) { numerator.MultiplySign(-1); denominator.MultiplySign(-1); }
 49231        return clip.Contains(numerator, denominator, root);
 232    }
 233}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/ConePlaneRayEvents.Descriptors.cs

#LineLine coverage
 1//=======================================================================
 2// ConePlaneRayEvents.Descriptors.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
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24/// <content>Compact candidate provenance and direct event reconstruction.</content>
 25internal static partial class ConePlaneRayEvents
 26{
 27    private static void SetEvent(in ConePlaneRayEventSource source, in ConePlaneRayEvent descriptor,
 28        scoped ref ConePlaneRaySelection positive, scoped ref ConePlaneRaySelection negative)
 29    {
 1253430        positive.HasValue = negative.HasValue = false;
 2506831        positive.CurrentEvent = descriptor; negative.CurrentEvent = descriptor;
 2506832        positive.CurrentSource = source; negative.CurrentSource = source;
 1253433    }
 34
 35    private static bool ReconstructPoint(in ConePlaneRayEventSource source, in ConePlaneRayFrame frame,
 36        ConePlaneRayEvent descriptor, scoped ConePlaneRayPoint point, scoped Span<ulong> root)
 37    {
 38        // Point-only routes never read selection storage or solve exits.
 68239        scoped ConePlaneRaySelection positive = default, negative = default;
 34140        var sink = new ConePlaneRayEventSink(descriptor, point, root, pointOnly: true);
 34141        Accumulate(source, frame, ref positive, ref negative, ref sink);
 34142        return sink.HasPoint;
 43    }
 44
 45    /// <summary>Reconstructs only a clipped event's admitted point, without solving unused exits.</summary>
 46    internal static bool ReconstructPoint(in ConePlaneRayEventSource source, in ConePlaneRayFrame frame,
 47        ConePlaneRayEvent descriptor, in RationalSegmentInterval clip, scoped ConePlaneRayPoint point, scoped Span<ulong
 48    {
 949        if (!clip.IsClipped) return ReconstructPoint(source, frame, descriptor, point, root);
 750        if (source.Scope != ConePlaneRayEventScope.Segment)
 151            throw new ArgumentException("Only authored segment sources can be replayed with a clipped interval.", nameof
 1252        scoped ConePlaneRaySelection positive = default, negative = default;
 653        Span<RationalSegmentInterval> clips = stackalloc RationalSegmentInterval[1] { clip };
 654        var sink = new ConePlaneRayEventSink(descriptor, point, root, pointOnly: true,
 655            source: source, frame: frame, clip: clips);
 656        Accumulate(source, frame, ref positive, ref negative, ref sink);
 657        return sink.HasPoint;
 58    }
 59
 60    internal static int CompareEventAnchors(in ConePlaneRayEventSource firstSource, ConePlaneRayEvent first,
 61        in ConePlaneRayEventSource secondSource, ConePlaneRayEvent second, in ConePlaneRayFrame frame,
 62        bool includeCoincidentProvenance = true)
 63    {
 2364        if (first.Matches(second) && firstSource.Scope == secondSource.Scope && firstSource.A == secondSource.A
 2365            && firstSource.B == secondSource.B)
 266            return 0;
 2167        Span<ulong> av = stackalloc ulong[frame.PointStorageWords];
 2168        Span<int> sa = stackalloc int[ConePlaneRayPoint.SignCount];
 2169        Span<ulong> ar = stackalloc ulong[frame.RootWords];
 2170        var a = new ConePlaneRayPoint(av, sa, frame.FieldWords);
 2171        if (!ReconstructPoint(firstSource, frame, first, a, ar))
 372            throw new InvalidOperationException("An admitted finite event could not be reconstructed.");
 1873        int comparison = CompareEventAnchors(a, ar, secondSource, second, frame);
 2374        if (comparison != 0) return comparison;
 1175        return includeCoincidentProvenance
 1176            ? CompareCoincidentProvenance(firstSource, first, secondSource, second) : 0;
 77    }
 78
 79    /// <summary>Compares an admitted point with a reconstructed event by exact coordinates.</summary>
 80    /// <remarks>The borrowed first point and root already belong to the supplied frame; provenance does not participate
 81    internal static int CompareEventAnchors(scoped ConePlaneRayPoint first, scoped ReadOnlySpan<ulong> firstRoot,
 82        in ConePlaneRayEventSource secondSource, ConePlaneRayEvent second, in ConePlaneRayFrame frame)
 83    {
 21484        Span<ulong> values = stackalloc ulong[frame.PointStorageWords], root = stackalloc ulong[frame.RootWords];
 10785        Span<int> signs = stackalloc int[ConePlaneRayPoint.SignCount];
 10786        var point = new ConePlaneRayPoint(values, signs, frame.FieldWords);
 10787        if (!ReconstructPoint(secondSource, frame, second, point, root))
 188            throw new InvalidOperationException("An admitted finite event could not be reconstructed.");
 10689        return first.CompareTo(point, firstRoot, root);
 90    }
 91
 92    internal static int CompareCoincidentProvenance(in ConePlaneRayEventSource firstSource, ConePlaneRayEvent first,
 93        in ConePlaneRayEventSource secondSource, ConePlaneRayEvent second)
 94    {
 44395        int scopeOrder = ((byte)firstSource.Scope).CompareTo((byte)secondSource.Scope);
 45496        if (scopeOrder != 0) return scopeOrder;
 43297        Span<Vector3d> a = stackalloc Vector3d[2] { firstSource.A, firstSource.B };
 43298        Span<Vector3d> b = stackalloc Vector3d[2] { secondSource.A, secondSource.B };
 86499        SortVertices(a); SortVertices(b);
 2568100        for (int i = 0; i < 2; i++)
 101        {
 859102            int comparison = CompareVertex(a[i], b[i]);
 866103            if (comparison != 0) return comparison;
 104        }
 425105        int order = ((int)first.Kind).CompareTo((int)second.Kind);
 601106        if (order == 0) order = first.Feature.CompareTo(second.Feature);
 520107        if (order == 0) order = first.Quadrant.CompareTo(second.Quadrant);
 472108        if (order == 0) order = first.Branch.CompareTo(second.Branch);
 425109        return order == 0 ? first.Endpoint.CompareTo(second.Endpoint) : order;
 110    }
 111
 112    private static void SortVertices(Span<Vector3d> vertices)
 113    {
 3456114        for (int i = 1; i < 2; i++)
 1766115            for (int j = i; j > 0 && CompareVertex(vertices[j], vertices[j - 1]) < 0; j--)
 19116                (vertices[j], vertices[j - 1]) = (vertices[j - 1], vertices[j]);
 864117    }
 118
 119    private static int CompareVertex(Vector3d a, Vector3d b)
 120    {
 1723121        int order = a.X.m_rawValue.CompareTo(b.X.m_rawValue);
 3432122        if (order == 0) order = a.Y.m_rawValue.CompareTo(b.Y.m_rawValue);
 1723123        return order == 0 ? a.Z.m_rawValue.CompareTo(b.Z.m_rawValue) : order;
 124    }
 125}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/ConePlaneRayEvents.Native.cs

#LineLine coverage
 1//=======================================================================
 2// ConePlaneRayEvents.Native.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>Streams exact native boundary segments without rounded source descriptors.</content>
 13internal static partial class ConePlaneRayEvents
 14{
 15    internal static bool VisitNativeSegment(in ConePlaneRayFrame frame, in WideAxis3 start, in WideAxis3 end,
 16        in RationalSegmentInterval clip, ConePlaneRayEventVisitor visitor)
 17    {
 1318        if (clip.HasWideBounds && !frame.UsesWideBanks)
 119            return VisitNativeSegment(frame.WithWideParameters(), start, end, clip, visitor);
 2420        Span<ulong> pv = stackalloc ulong[frame.SelectionStorageWords], nv = stackalloc ulong[frame.SelectionStorageWord
 2421        Span<int> ps = stackalloc int[ConePlaneRaySelection.SignCount], ns = stackalloc int[ConePlaneRaySelection.SignCo
 1222        var positive = new ConePlaneRaySelection(pv, ps, frame.FieldWords, frame.RootWords);
 1223        var negative = new ConePlaneRaySelection(nv, ns, frame.FieldWords, frame.RootWords);
 1224        Span<WideAxis3> segment = stackalloc WideAxis3[2] { start, end };
 1225        Span<RationalSegmentInterval> clips = stackalloc RationalSegmentInterval[clip.IsClipped ? 1 : 0];
 2026        if (!clips.IsEmpty) clips[0] = clip;
 1227        var source = ConePlaneRayEventSource.NativeSegment;
 1228        var sink = new ConePlaneRayEventSink(source, frame, visitor, clips, segment);
 1229        Accumulate(source, frame, ref positive, ref negative, ref sink);
 1230        return sink.HasPoint;
 31    }
 32
 33    internal static bool ContainsNativeSegmentPoint(in WideAxis3 start, in WideAxis3 end,
 34        scoped ConePlaneRayPoint point, scoped ReadOnlySpan<ulong> root, in RationalSegmentInterval clip)
 35    {
 10836        WideAxis3 delta = new(WideArithmetic.SubtractSigned320(end.X, start.X),
 10837            WideArithmetic.SubtractSigned320(end.Y, start.Y), WideArithmetic.SubtractSigned320(end.Z, start.Z));
 10838        int pivot = !delta.X.IsZero ? 0 : !delta.Y.IsZero ? 1 : 2;
 10839        Signed576 step = Signed576.ExtendValue(pivot == 0 ? delta.X : pivot == 1 ? delta.Y : delta.Z);
 10840        int words = point.BankWords + 6;
 21641        Span<ulong> values = stackalloc ulong[10 * words]; Span<int> signs = stackalloc int[10];
 10842        var numerator = ContactQuadratic.At(values, signs, 0, words);
 10843        var denominator = ContactQuadratic.At(values, signs, 1, words);
 10844        var coordinate = ContactQuadratic.At(values, signs, 2, words);
 10845        var first = ContactQuadratic.At(values, signs, 3, words);
 10846        var second = ContactQuadratic.At(values, signs, 4, words);
 10847        ContactQuadratic.Scale(point.Denominator, Signed576.ExtendValue(pivot == 0 ? start.X : pivot == 1 ? start.Y : st
 21648        numerator.MultiplySign(-1); numerator.Add(pivot == 0 ? point.X : pivot == 1 ? point.Y : point.Z);
 83649        for (int axis = 0; axis < 3; axis++)
 50        {
 31751            ContactQuadratic.Scale(point.Denominator, Signed576.ExtendValue(axis == 0 ? start.X : axis == 1 ? start.Y : 
 63452            coordinate.MultiplySign(-1); coordinate.Add(axis == 0 ? point.X : axis == 1 ? point.Y : point.Z);
 31753            if (step.IsZero)
 54            {
 655                if (coordinate.Sign(root) != 0) return false;
 56            }
 57            else
 58            {
 31259                ContactQuadratic.Scale(coordinate, step, first);
 31260                ContactQuadratic.Scale(numerator, Signed576.ExtendValue(axis == 0 ? delta.X : axis == 1 ? delta.Y : delt
 63061                first.Add(second, -1); if (first.Sign(root) != 0) return false;
 62            }
 63        }
 10264        if (step.IsZero) return true;
 10065        ContactQuadratic.Scale(point.Denominator, step, denominator);
 18866        if (denominator.Sign(root) < 0) { numerator.MultiplySign(-1); denominator.MultiplySign(-1); }
 15767        if (clip.IsClipped) return clip.Contains(numerator, denominator, root);
 8668        numerator.CopyTo(first); first.Add(denominator, -1);
 4369        return numerator.Sign(root) >= 0 && first.Sign(root) <= 0;
 70    }
 71}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/ConePlaneRayEvents.Scopes.cs

#LineLine coverage
 1//=======================================================================
 2// ConePlaneRayEvents.Scopes.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>Shared-plane and finite-boundary construction cohorts, evaluated independently of mesh regions.</content>
 13internal static partial class ConePlaneRayEvents
 14{
 15    // Possible constructions, not admitted roots: circles 72, generator
 16    // endpoints 24, axis 3, apex 1, base stationary 2. A boundary needs its
 17    // six edge events and eight projected upper-rim wall chart branches.
 18    internal const int IntrinsicCapacity = 102;
 19    internal const int BoundaryCapacity = 14;
 20
 21    /// <summary>Constructs the scoped inventory once and synchronously visits its admitted exact events.</summary>
 22    internal static bool VisitEvents(in ConePlaneRayEventSource source, in ConePlaneRayFrame frame, ConePlaneRayEventVis
 23    {
 6424        Span<ulong> positiveValues = stackalloc ulong[frame.SelectionStorageWords], negativeValues = stackalloc ulong[fr
 6425        Span<int> positiveSigns = stackalloc int[ConePlaneRaySelection.SignCount], negativeSigns = stackalloc int[ConePl
 3226        var positive = new ConePlaneRaySelection(positiveValues, positiveSigns, frame.FieldWords, frame.RootWords);
 3227        var negative = new ConePlaneRaySelection(negativeValues, negativeSigns, frame.FieldWords, frame.RootWords);
 3228        scoped ConePlaneRayEventSink sink = new(source, frame, visitor);
 3229        return Accumulate(source, frame, ref positive, ref negative, ref sink);
 30    }
 31
 32    /// <summary>Creates exact cut-endpoint events and admits every cohort against the original segment parameter.</summ
 33    internal static bool VisitEvents(in ConePlaneRayEventSource source, in ConePlaneRayFrame frame,
 34        in RationalSegmentInterval clip, ConePlaneRayEventVisitor visitor)
 35    {
 1736        if (!clip.IsClipped) return VisitEvents(source, frame, visitor);
 1537        if (clip.HasWideBounds && !frame.UsesWideBanks)
 238            return VisitEvents(source, frame.WithWideParameters(), clip, visitor);
 1339        if (source.Scope != ConePlaneRayEventScope.Segment)
 140            throw new ArgumentException("Only finite segment sources can have a clipped interval.", nameof(source));
 2441        Span<ulong> positiveValues = stackalloc ulong[frame.SelectionStorageWords], negativeValues = stackalloc ulong[fr
 2442        Span<int> positiveSigns = stackalloc int[ConePlaneRaySelection.SignCount], negativeSigns = stackalloc int[ConePl
 1243        var positive = new ConePlaneRaySelection(positiveValues, positiveSigns, frame.FieldWords, frame.RootWords);
 1244        var negative = new ConePlaneRaySelection(negativeValues, negativeSigns, frame.FieldWords, frame.RootWords);
 45        // Borrow the clip without enlarging ordinary event or source records.
 1246        Span<RationalSegmentInterval> clips = stackalloc RationalSegmentInterval[1] { clip };
 1247        scoped ConePlaneRayEventSink sink = new(source, frame, visitor, clips);
 1248        Accumulate(source, frame, ref positive, ref negative, ref sink);
 1249        return sink.HasPoint;
 50    }
 51
 52    /// <summary>Tests closed finite triangle admission without reconstructing exits or rounding witnesses.</summary>
 53    /// <remarks>The triangle belongs to the frame's exact authored plane.</remarks>
 54    internal static bool IntersectsTriangle(in ConePlaneRayFrame frame, FixedTriangle triangle)
 55    {
 3756        if (frame.NormalSquared.IsZero) return false;
 3357        if (frame.Finite.ShapeFrame.HasExactScale)
 58        {
 59            // The caller's retained plane owns physical scale; an authored
 60            // epsilon-area test can discard a perfectly large scaled face.
 861            triangle.GetExactNormal(out _, out _, out _, out Signed320 squared);
 962            if (squared.IsZero) return false;
 63        }
 2664        else if (triangle.IsDegenerate) return false;
 23665        for (int edge = 0; edge < 3; edge++)
 9366            if (frame.IntersectsSegment(triangle.GetEdge(edge))) return true;
 2867        Span<ulong> words = stackalloc ulong[frame.PointStorageWords];
 2868        Span<int> signs = stackalloc int[ConePlaneRayPoint.SignCount];
 2869        Span<ulong> root = stackalloc ulong[frame.RootWords];
 2870        var point = new ConePlaneRayPoint(words, signs, frame.FieldWords);
 2871        var axis = new ConePlaneRayEvent(ConePlaneRayEventKind.Axis, endpoint: frame.Normal.Y.IsZero ? 0 : -1);
 2872        if (ReconstructPoint(ConePlaneRayEventSource.Plane, frame, axis, point, root))
 1873            return ConePlaneRayPointExits.ContainsTrianglePoint(triangle, frame, point, root);
 1074        Span<ConePlaneRayEvent> events = stackalloc ConePlaneRayEvent[IntrinsicCapacity];
 1075        int count = GetIntrinsicEvents(frame, events);
 38476        foreach (ConePlaneRayEvent descriptor in events[..count])
 18477            if (ReconstructPoint(ConePlaneRayEventSource.Plane, frame, descriptor, point, root))
 78                // A finite cone section is compact and connected, including a
 79                // tangent point/generator or radius-zero segment. With all
 80                // closed triangle edges disjoint, an intersecting section lies
 81                // wholly inside the triangle. Any certified section point then
 82                // decides admission; no extremum or materialized point is needed.
 483                return ConePlaneRayPointExits.ContainsTrianglePoint(triangle, frame, point, root);
 684        return false;
 85    }
 86
 87    internal static int GetIntrinsicEvents(in ConePlaneRayFrame frame, Span<ConePlaneRayEvent> events)
 88    {
 43589        if (events.Length < IntrinsicCapacity) throw new ArgumentException("Intrinsic event storage is too small.", name
 90        // An axial section needs its axis and four lower-circle cardinals.
 91        // Other circle restrictions have no roots; projected upper-rim points
 92        // fail cone admission except at the base, where they duplicate these
 93        // cardinals. Apex and extra axes add no point or larger first exit.
 94        // Radius zero or an axial plane through the apex collapses the entire
 95        // section to the axis alone; its four cardinals add identical points.
 43396        bool axial = frame.Normal.X.IsZero && frame.Normal.Z.IsZero && !frame.Normal.Y.IsZero;
 43397        int count = 0;
 43398        if (axial)
 99        {
 36100            if (frame.Radius != Fixed64.Zero && !frame.PlaneConstant.IsZero)
 240101                for (int quadrant = 0; quadrant < 4; quadrant++)
 576102                    for (int endpoint = 0; endpoint < 2; endpoint++)
 192103                        if (endpoint == 0 ? (quadrant & 2) == 0 : (quadrant & 1) == 0)
 96104                            events[count++] = new ConePlaneRayEvent(ConePlaneRayEventKind.LowerCircle, 8, quadrant, endp
 36105            events[count++] = new ConePlaneRayEvent(ConePlaneRayEventKind.Axis, endpoint: -1);
 36106            return count;
 107        }
 2382108        for (int upper = 0; upper < 2; upper++)
 7940109        for (int quadrant = 0; quadrant < 4; quadrant++)
 110        {
 3176111            ConePlaneRayEventKind kind = upper == 0 ? ConePlaneRayEventKind.LowerCircle : ConePlaneRayEventKind.UpperRim
 19056112            for (int endpoint = 0; endpoint < 2; endpoint++)
 113            {
 6352114                if (endpoint == 0 && (quadrant & 2) != 0 || endpoint == 1 && (quadrant & 1) != 0) continue;
 3176115                events[count++] = new ConePlaneRayEvent(kind, 8, quadrant, endpoint, endpoint);
 3176116                if (upper == 0)
 9528117                    for (int bound = 0; bound < 2; bound++)
 3176118                        events[count++] = new ConePlaneRayEvent(ConePlaneRayEventKind.Generator, 8, quadrant, endpoint, 
 119            }
 50816120            for (int line = 0; line < (upper == 0 ? 6 : 8); line++)
 121            {
 122                // Keep canonical base intersections once. A nonzero plane
 123                // constant admits lower line 1's identical upper-line-3 point;
 124                // radial line 6 reflects onto those same base intersections.
 125                // Degenerate frames retain the general diagnostic inventory.
 22232126                if (upper == 0 ? line >= 2 && line <= 4 : line < 3
 22232127                    || line == 3 && !frame.PlaneConstant.IsZero
 22232128                    || line == 6 && frame.Normal.Y.IsZero && !frame.NormalSquared.IsZero) continue;
 65856129                for (int branch = -1; branch <= 1; branch += 2)
 130                {
 21952131                    events[count++] = new ConePlaneRayEvent(kind, line, quadrant, branch);
 21952132                    if (upper == 0 && line == 0)
 19056133                        for (int bound = 0; bound < 2; bound++)
 6352134                            events[count++] = new ConePlaneRayEvent(ConePlaneRayEventKind.Generator, line, quadrant, bra
 135                }
 136            }
 137        }
 3176138        for (int endpoint = -1; endpoint < 2; endpoint++)
 1191139            events[count++] = new ConePlaneRayEvent(ConePlaneRayEventKind.Axis, endpoint: endpoint);
 397140        events[count++] = new ConePlaneRayEvent(ConePlaneRayEventKind.Apex);
 141        // On radial planes the upper parallel-rim cohort already owns the
 142        // base stationary point and both exits, including cardinal seams.
 397143        if (!frame.Normal.Y.IsZero || frame.NormalSquared.IsZero)
 1890144            for (int branch = -1; branch <= 1; branch += 2)
 630145                events[count++] = new ConePlaneRayEvent(ConePlaneRayEventKind.BaseStationary, branch: branch);
 397146        return count;
 147    }
 148
 149    internal static int GetBoundaryEvents(Span<ConePlaneRayEvent> events)
 150    {
 1140151        if (events.Length < BoundaryCapacity) throw new ArgumentException("Boundary event storage is too small.", nameof
 1138152        int count = 0;
 6828153        for (int endpoint = 0; endpoint < 2; endpoint++)
 2276154            events[count++] = new ConePlaneRayEvent(ConePlaneRayEventKind.EdgeEndpoint, endpoint: endpoint);
 6828155        for (int branch = -1; branch <= 1; branch += 2)
 156        {
 2276157            events[count++] = new ConePlaneRayEvent(ConePlaneRayEventKind.EdgeSide, branch: branch);
 2276158            events[count++] = new ConePlaneRayEvent(ConePlaneRayEventKind.EdgeStationary, branch: branch);
 159        }
 11380160        for (int quadrant = 0; quadrant < 4; quadrant++)
 27312161        for (int branch = -1; branch <= 1; branch += 2)
 9104162            events[count++] = new ConePlaneRayEvent(ConePlaneRayEventKind.UpperRim, quadrant: quadrant, branch: branch);
 163        // Lower-circle wall, generator-wall and finite-axis intersections are
 164        // already the segment's side roots, or endpoints when F is identically
 165        // zero on that segment. Only the upper-rim projection adds the switch
 166        // between its side and cap exits; no artificial triangle is required.
 1138167        return count;
 168    }
 169
 170    /// <summary>Reconstructs an admitted point, optionally omitting the unused opposite rational or side exit.</summary
 171    /// <remarks>Zero requests both directions. Admission and directional availability are independent.</remarks>
 172    internal static bool TryEvaluateEvent(in ConePlaneRayEventSource source, in ConePlaneRayFrame frame,
 173        ConePlaneRayEvent descriptor, scoped ConePlaneRayPoint point, scoped Span<ulong> root,
 174        scoped ref ConePlaneRaySelection positive, scoped ref ConePlaneRaySelection negative, int requestedOrientation =
 175    {
 55329176        if (requestedOrientation < -1 || requestedOrientation > 1)
 2177            throw new ArgumentOutOfRangeException(nameof(requestedOrientation));
 55327178        positive.HasValue = negative.HasValue = false;
 55327179        root.Clear();
 180        // Reborrow coefficient storage locally: the sink borrows this call's
 181        // output point/root, and no such reference may enter caller metadata.
 55327182        scoped ConePlaneRaySelection evaluatedPositive = new(positive.Values, positive.Signs, frame.FieldWords, frame.Ro
 55327183        scoped ConePlaneRaySelection evaluatedNegative = new(negative.Values, negative.Signs, frame.FieldWords, frame.Ro
 55327184        var sink = new ConePlaneRayEventSink(descriptor, point, root, requestedOrientation: requestedOrientation);
 55327185        Accumulate(source, frame, ref evaluatedPositive, ref evaluatedNegative, ref sink);
 105611186        if (!sink.HasPoint) return false;
 5043187        if (evaluatedPositive.HasValue)
 4140188            positive.Restore(frame, evaluatedPositive.MaximumSource, evaluatedPositive.MaximumEvent);
 5043189        if (evaluatedNegative.HasValue)
 4124190            negative.Restore(frame, evaluatedNegative.MaximumSource, evaluatedNegative.MaximumEvent);
 5043191        return true;
 192    }
 193
 194    /// <summary>Replays a clipped boundary descriptor with the same original-parameter interval used to create it.</sum
 195    internal static bool TryEvaluateEvent(in ConePlaneRayEventSource source, in ConePlaneRayFrame frame,
 196        ConePlaneRayEvent descriptor, in RationalSegmentInterval clip, scoped ConePlaneRayPoint point, scoped Span<ulong
 197        scoped ref ConePlaneRaySelection positive, scoped ref ConePlaneRaySelection negative, int requestedOrientation =
 198    {
 21199        if (!clip.IsClipped) return TryEvaluateEvent(source, frame, descriptor, point, root, ref positive, ref negative,
 15200        if (source.Scope != ConePlaneRayEventScope.Segment)
 1201            throw new ArgumentException("Only finite segment sources can have a clipped interval.", nameof(source));
 14202        if (requestedOrientation < -1 || requestedOrientation > 1)
 2203            throw new ArgumentOutOfRangeException(nameof(requestedOrientation));
 24204        positive.HasValue = negative.HasValue = false; root.Clear();
 12205        scoped ConePlaneRaySelection evaluatedPositive = new(positive.Values, positive.Signs, frame.FieldWords, frame.Ro
 12206        scoped ConePlaneRaySelection evaluatedNegative = new(negative.Values, negative.Signs, frame.FieldWords, frame.Ro
 12207        Span<RationalSegmentInterval> clips = stackalloc RationalSegmentInterval[1] { clip };
 12208        var sink = new ConePlaneRayEventSink(descriptor, point, root, requestedOrientation: requestedOrientation,
 12209            source: source, frame: frame, clip: clips);
 12210        Accumulate(source, frame, ref evaluatedPositive, ref evaluatedNegative, ref sink);
 13211        if (!sink.HasPoint) return false;
 20212        if (evaluatedPositive.HasValue) positive.Restore(frame, evaluatedPositive.MaximumSource, evaluatedPositive.Maxim
 20213        if (evaluatedNegative.HasValue) negative.Restore(frame, evaluatedNegative.MaximumSource, evaluatedNegative.Maxim
 11214        return true;
 215    }
 216}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/ConePlaneRayEvents.Special.cs

#LineLine coverage
 1//=======================================================================
 2// ConePlaneRayEvents.Special.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>Apex, axial support continua, and the lower base-line stationary stratum.</content>
 13internal static partial class ConePlaneRayEvents
 14{
 15    private static bool AccumulateAxisAndApex(in ConePlaneRayEventSource source, in ConePlaneRayFrame frame,
 16        scoped ref ConePlaneRaySelection positive, scoped ref ConePlaneRaySelection negative,
 17        scoped ref ConePlaneRayEventSink sink)
 18    {
 177519        Span<ulong> values = stackalloc ulong[6 * frame.FieldWords];
 177520        Span<int> signs = stackalloc int[6];
 177521        Span<ulong> pointValues = stackalloc ulong[frame.PointStorageWords];
 177522        Span<int> pointSigns = stackalloc int[8];
 177523        var point = new ConePlaneRayPoint(pointValues, pointSigns, frame.FieldWords);
 532524        ContactQuadratic n = At(values, signs, 0), d = At(values, signs, 1), term = At(values, signs, 2);
 355025        point.X.Clear(); point.Z.Clear();
 177526        bool found = false;
 177527        if (sink.Wants(ConePlaneRayEventKind.Axis))
 28        {
 29            ConePlaneRayEvent descriptor;
 137330            if (!frame.Normal.Y.IsZero)
 31            {
 114732                descriptor = new ConePlaneRayEvent(ConePlaneRayEventKind.Axis);
 180233                if (!sink.Wants(descriptor)) return false;
 98434                point.Y.Set(frame.PlaneConstant); point.Y.MultiplySign(frame.Normal.Y.Sign);
 98435                point.Denominator.Set(Extend(frame.Normal.Y)); point.Denominator.MultiplySign(frame.Normal.Y.Sign);
 49236                SetEvent(source, descriptor, ref positive, ref negative);
 49237                bool admitted = ConePlaneRayPointExits.AccumulateRationalPoint(source, frame, point, ref positive, ref n
 93438                if (admitted) sink.Keep(descriptor, point, ReadOnlySpan<ulong>.Empty, positive, negative);
 49239                found |= admitted;
 40            }
 41            else
 42            {
 22643                if (frame.PlaneConstant.IsZero && (sink.IsStreaming || (uint)sink.Target.Endpoint <= 1))
 19444                    for (int endpoint = sink.IsStreaming ? 0 : sink.Target.Endpoint; endpoint <= (sink.IsStreaming ? 1 :
 45                    {
 5246                        descriptor = new ConePlaneRayEvent(ConePlaneRayEventKind.Axis, endpoint: endpoint);
 5247                        point.Y.Set(endpoint == 0 ? default : Extend(frame.Finite.FullHeight));
 5248                        point.Denominator.Set(Integer(1));
 5249                        SetEvent(source, descriptor, ref positive, ref negative);
 5250                        bool admitted = ConePlaneRayPointExits.AccumulateRationalPoint(source, frame, point, ref positiv
 51                        // Ny=0 and c=0 contain the whole axis. Its two
 52                        // finite endpoints satisfy this plane and solid cone
 53                        // exactly, including radius zero; admission cannot fail.
 54                        System.Diagnostics.Debug.Assert(admitted);
 5255                        sink.Keep(descriptor, point, ReadOnlySpan<ulong>.Empty, positive, negative);
 5256                        found = true;
 57                    }
 58            }
 141259            if (!sink.IsStreaming) return found;
 60        }
 43261        if (!sink.Wants(ConePlaneRayEventKind.Apex)) return found;
 62        // Project the apex onto the shared plane. Zero depth is represented by
 63        // the axis event; a nonzero certified exit retains its orientation.
 84064        n.Set(frame.PlaneConstant); d.Set(frame.NormalSquared);
 42065        ContactQuadratic.Scale(n, Extend(frame.Normal.X), point.X);
 42066        ContactQuadratic.Scale(n, Extend(frame.Normal.Y), point.Y);
 42067        ContactQuadratic.Scale(n, Extend(frame.Normal.Z), point.Z);
 42068        d.CopyTo(point.Denominator);
 42069        int orientation = -frame.PlaneConstant.Sign;
 42070        if (orientation != 0)
 71        {
 37472            var descriptor = new ConePlaneRayEvent(ConePlaneRayEventKind.Apex, orientation: orientation);
 37473            n.CopyTo(term, -orientation);
 37474            SetEvent(source, descriptor, ref positive, ref negative);
 37475            bool admitted = ConePlaneRayPointExits.AccumulateCertifiedExit(source, frame, point,
 37476                ReadOnlySpan<ulong>.Empty, term, d, orientation, ref positive, ref negative, sink.PointOnly);
 44677            if (admitted) sink.Keep(descriptor, point, ReadOnlySpan<ulong>.Empty, positive, negative);
 37478            return found | admitted;
 79        }
 4680        return found;
 81    }
 82
 83    private static bool AccumulateBaseStationary(in ConePlaneRayEventSource source, in ConePlaneRayFrame frame,
 84        scoped ref ConePlaneRaySelection positive, scoped ref ConePlaneRaySelection negative,
 85        scoped ref ConePlaneRayEventSink sink)
 86    {
 68687        Signed832 radialSquared = WideArithmetic.AddSigned832(
 68688            WideArithmetic.MultiplySigned576ToSigned832(frame.Normal.X, frame.Normal.X),
 68689            WideArithmetic.MultiplySigned576ToSigned832(frame.Normal.Z, frame.Normal.Z));
 68690        if (radialSquared.IsZero)
 2091            return false;
 66692        Span<ulong> values = stackalloc ulong[22 * frame.FieldWords];
 66693        Span<int> signs = stackalloc int[22];
 66694        Span<ulong> root = stackalloc ulong[frame.RootWords];
 66695        Span<ulong> pointValues = stackalloc ulong[frame.PointStorageWords];
 66696        Span<int> pointSigns = stackalloc int[8];
 66697        var point = new ConePlaneRayPoint(pointValues, pointSigns, frame.FieldWords);
 199898        ContactQuadratic k = At(values, signs, 0), L = At(values, signs, 1), A = At(values, signs, 2);
 199899        ContactQuadratic a = At(values, signs, 3), b = At(values, signs, 4), c = At(values, signs, 5);
 1998100        ContactQuadratic term = At(values, signs, 6), work = At(values, signs, 7), t = At(values, signs, 8);
 1332101        ContactQuadratic d = At(values, signs, 9), depth = At(values, signs, 10);
 666102        Signed576 h2 = Extend(WideArithmetic.MultiplySigned192(Signed192.Raw(frame.Height), Signed192.Raw(frame.Height))
 666103        Signed576 r2 = Extend(WideArithmetic.MultiplySigned192(Signed192.Raw(frame.Radius), Signed192.Raw(frame.Radius))
 666104        k.Set(frame.PlaneConstant);
 666105        term.Set(Extend(frame.Normal.Y));
 1332106        ContactQuadratic.Scale(term, Extend(frame.Finite.FullHeight), work); k.Add(work, -1);
 666107        L.Set(radialSquared);
 666108        ContactQuadratic.Scale(k, Extend(frame.Normal.X), point.X);
 666109        ContactQuadratic.Scale(L, Extend(frame.Finite.FullHeight), point.Y);
 666110        ContactQuadratic.Scale(k, Extend(frame.Normal.Z), point.Z);
 666111        L.CopyTo(point.Denominator);
 112        // On the lower-base line, the stationary upper-side endpoint has
 113        // radial q parallel to N's radial projection. Thus its lower endpoint
 114        // is the line's closest point to the axis, k*Nrad/L. Substitution gives
 115        // h²(k+tL)²-r²L(H+tNy)²=0 without expanding a rational discriminant.
 116        // The defining coefficients remain <1184bits, root <2370bits.
 666117        Product(frame.Normal, frame.Normal, frame, A);
 666118        ContactQuadratic.Multiply(L, A, ReadOnlySpan<ulong>.Empty, a);
 666119        ContactQuadratic.Scale(k, h2, b);
 666120        term.Set(Extend(frame.Finite.FullHeight));
 666121        ContactQuadratic.Scale(term, Extend(frame.Normal.Y), work);
 1332122        ContactQuadratic.Scale(work, r2, term); b.Add(term, -1);
 1332123        ContactQuadratic.Multiply(b, L, ReadOnlySpan<ulong>.Empty, work); work.CopyTo(b);
 666124        ContactQuadratic.Multiply(k, k, ReadOnlySpan<ulong>.Empty, work);
 666125        ContactQuadratic.Scale(work, h2, c);
 666126        ContactQuadratic.Scale(L, Extend(frame.Finite.FullHeight), term);
 666127        ContactQuadratic.Scale(term, Extend(frame.Finite.FullHeight), work);
 1332128        ContactQuadratic.Scale(work, r2, term); c.Add(term, -1);
 666129        bool found = false;
 2680130        for (int branch = sink.IsStreaming ? -1 : sink.Target.Branch; branch <= (sink.IsStreaming ? 1 : sink.Target.Bran
 131        {
 674132            if (!ContactQuadratic.TryGetParameter(a, b, c, branch, root, t, d)) continue;
 655133            int orientation = t.Sign(root) < 0 ? -1 : 1;
 655134            var descriptor = new ConePlaneRayEvent(ConePlaneRayEventKind.BaseStationary, branch: branch, orientation: or
 655135            t.CopyTo(depth, orientation);
 655136            SetEvent(source, descriptor, ref positive, ref negative);
 655137            bool admitted = ConePlaneRayPointExits.AccumulateStationarySideExit(source, frame, point, root,
 655138                depth, d, orientation, ref positive, ref negative, sink.PointOnly);
 846139            if (admitted) sink.Keep(descriptor, point, root, positive, negative);
 655140            found |= admitted;
 141        }
 666142        return found;
 143    }
 144}

Methods/Properties

AccumulateCircles(FixedMathSharp.Geometry.ConePlaneRayEventSource&,FixedMathSharp.Geometry.ConePlaneRayFrame&,FixedMathSharp.Geometry.ConePlaneRaySelection&,FixedMathSharp.Geometry.ConePlaneRaySelection&,FixedMathSharp.Geometry.ConePlaneRayEventSink&)
AccumulateCircleChart(FixedMathSharp.Geometry.ConePlaneRayEventSource&,FixedMathSharp.Geometry.ConePlaneRayFrame&,System.Boolean,System.Int32,System.Int32,System.Int32,System.Int32,System.Span`1<System.UInt64>,System.Span`1<System.Int32>,FixedMathSharp.Geometry.ConePlaneRaySelection&,FixedMathSharp.Geometry.ConePlaneRaySelection&,FixedMathSharp.Geometry.ConePlaneRayEventSink&)
AccumulateAxialCardinal(FixedMathSharp.Geometry.ConePlaneRayEventSource&,FixedMathSharp.Geometry.ConePlaneRayFrame&,System.Int32,System.Int32,FixedMathSharp.Geometry.ConePlaneRaySelection&,FixedMathSharp.Geometry.ConePlaneRaySelection&,FixedMathSharp.Geometry.ConePlaneRayEventSink&)
GetCircleLine(FixedMathSharp.Geometry.ConePlaneRayEventSource&,FixedMathSharp.Geometry.ConePlaneRayFrame&,System.Boolean,System.Int32,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ConePlaneRayEventSink&)
AccumulateCircleParameter(FixedMathSharp.Geometry.ConePlaneRayEventSource&,FixedMathSharp.Geometry.ConePlaneRayFrame&,System.Boolean,System.Int32,System.Int32,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,System.ReadOnlySpan`1<System.UInt64>,System.Boolean,FixedMathSharp.Geometry.ConePlaneRayEvent,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,System.Int32,FixedMathSharp.Geometry.ConePlaneRaySelection&,FixedMathSharp.Geometry.ConePlaneRaySelection&,FixedMathSharp.Geometry.ConePlaneRayEventSink&)
AccumulateGenerator(FixedMathSharp.Geometry.ConePlaneRayEventSource&,FixedMathSharp.Geometry.ConePlaneRayFrame&,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,System.ReadOnlySpan`1<System.UInt64>,FixedMathSharp.Geometry.ConePlaneRayEvent,FixedMathSharp.Geometry.ConePlaneRaySelection&,FixedMathSharp.Geometry.ConePlaneRaySelection&,FixedMathSharp.Geometry.ConePlaneRayEventSink&)
At(System.Span`1<System.UInt64>,System.Span`1<System.Int32>,System.Int32)
Extend(FixedMathSharp.Signed320)
Extend(FixedMathSharp.Signed576)
Integer(System.Int64)
Product(FixedMathSharp.Geometry.WideAxis3&,FixedMathSharp.Geometry.WideAxis3&,FixedMathSharp.Geometry.ConePlaneRayFrame&,FixedMathSharp.Geometry.ContactQuadratic)
Product(FixedMathSharp.Geometry.WideAxis3&,FixedMathSharp.Geometry.WideDirection3d&,FixedMathSharp.Geometry.ConePlaneRayFrame&,FixedMathSharp.Geometry.ContactQuadratic)
Product(FixedMathSharp.Geometry.WideDirection3d&,FixedMathSharp.Geometry.WideDirection3d&,FixedMathSharp.Geometry.ConePlaneRayFrame&,FixedMathSharp.Geometry.ContactQuadratic)
SetAffinePoint(FixedMathSharp.Geometry.ConePlaneRayPoint,FixedMathSharp.Geometry.WideAxis3&,FixedMathSharp.Geometry.WideAxis3&,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic)
Accumulate(FixedMathSharp.Geometry.ConePlaneRayEventSource&,FixedMathSharp.Geometry.ConePlaneRayFrame&,FixedMathSharp.Geometry.ConePlaneRaySelection&,FixedMathSharp.Geometry.ConePlaneRaySelection&,FixedMathSharp.Geometry.ConePlaneRayEventSink&)
AccumulateEdge(FixedMathSharp.Geometry.ConePlaneRayEventSource&,FixedMathSharp.Geometry.ConePlaneRayFrame&,FixedMathSharp.Geometry.ConePlaneRaySelection&,FixedMathSharp.Geometry.ConePlaneRaySelection&,FixedMathSharp.Geometry.ConePlaneRayEventSink&)
IsPointInClip(FixedMathSharp.Geometry.ConePlaneRayEventSource&,FixedMathSharp.Geometry.ConePlaneRayFrame&,FixedMathSharp.Geometry.ConePlaneRayPoint,System.ReadOnlySpan`1<System.UInt64>,FixedMathSharp.Geometry.RationalSegmentInterval&)
SetEvent(FixedMathSharp.Geometry.ConePlaneRayEventSource&,FixedMathSharp.Geometry.ConePlaneRayEvent&,FixedMathSharp.Geometry.ConePlaneRaySelection&,FixedMathSharp.Geometry.ConePlaneRaySelection&)
ReconstructPoint(FixedMathSharp.Geometry.ConePlaneRayEventSource&,FixedMathSharp.Geometry.ConePlaneRayFrame&,FixedMathSharp.Geometry.ConePlaneRayEvent,FixedMathSharp.Geometry.ConePlaneRayPoint,System.Span`1<System.UInt64>)
ReconstructPoint(FixedMathSharp.Geometry.ConePlaneRayEventSource&,FixedMathSharp.Geometry.ConePlaneRayFrame&,FixedMathSharp.Geometry.ConePlaneRayEvent,FixedMathSharp.Geometry.RationalSegmentInterval&,FixedMathSharp.Geometry.ConePlaneRayPoint,System.Span`1<System.UInt64>)
CompareEventAnchors(FixedMathSharp.Geometry.ConePlaneRayEventSource&,FixedMathSharp.Geometry.ConePlaneRayEvent,FixedMathSharp.Geometry.ConePlaneRayEventSource&,FixedMathSharp.Geometry.ConePlaneRayEvent,FixedMathSharp.Geometry.ConePlaneRayFrame&,System.Boolean)
CompareEventAnchors(FixedMathSharp.Geometry.ConePlaneRayPoint,System.ReadOnlySpan`1<System.UInt64>,FixedMathSharp.Geometry.ConePlaneRayEventSource&,FixedMathSharp.Geometry.ConePlaneRayEvent,FixedMathSharp.Geometry.ConePlaneRayFrame&)
CompareCoincidentProvenance(FixedMathSharp.Geometry.ConePlaneRayEventSource&,FixedMathSharp.Geometry.ConePlaneRayEvent,FixedMathSharp.Geometry.ConePlaneRayEventSource&,FixedMathSharp.Geometry.ConePlaneRayEvent)
SortVertices(System.Span`1<FixedMathSharp.Vector3d>)
CompareVertex(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
VisitNativeSegment(FixedMathSharp.Geometry.ConePlaneRayFrame&,FixedMathSharp.Geometry.WideAxis3&,FixedMathSharp.Geometry.WideAxis3&,FixedMathSharp.Geometry.RationalSegmentInterval&,FixedMathSharp.Geometry.ConePlaneRayEventVisitor)
ContainsNativeSegmentPoint(FixedMathSharp.Geometry.WideAxis3&,FixedMathSharp.Geometry.WideAxis3&,FixedMathSharp.Geometry.ConePlaneRayPoint,System.ReadOnlySpan`1<System.UInt64>,FixedMathSharp.Geometry.RationalSegmentInterval&)
VisitEvents(FixedMathSharp.Geometry.ConePlaneRayEventSource&,FixedMathSharp.Geometry.ConePlaneRayFrame&,FixedMathSharp.Geometry.ConePlaneRayEventVisitor)
VisitEvents(FixedMathSharp.Geometry.ConePlaneRayEventSource&,FixedMathSharp.Geometry.ConePlaneRayFrame&,FixedMathSharp.Geometry.RationalSegmentInterval&,FixedMathSharp.Geometry.ConePlaneRayEventVisitor)
IntersectsTriangle(FixedMathSharp.Geometry.ConePlaneRayFrame&,FixedMathSharp.Geometry.FixedTriangle)
GetIntrinsicEvents(FixedMathSharp.Geometry.ConePlaneRayFrame&,System.Span`1<FixedMathSharp.Geometry.ConePlaneRayEvent>)
GetBoundaryEvents(System.Span`1<FixedMathSharp.Geometry.ConePlaneRayEvent>)
TryEvaluateEvent(FixedMathSharp.Geometry.ConePlaneRayEventSource&,FixedMathSharp.Geometry.ConePlaneRayFrame&,FixedMathSharp.Geometry.ConePlaneRayEvent,FixedMathSharp.Geometry.ConePlaneRayPoint,System.Span`1<System.UInt64>,FixedMathSharp.Geometry.ConePlaneRaySelection&,FixedMathSharp.Geometry.ConePlaneRaySelection&,System.Int32)
TryEvaluateEvent(FixedMathSharp.Geometry.ConePlaneRayEventSource&,FixedMathSharp.Geometry.ConePlaneRayFrame&,FixedMathSharp.Geometry.ConePlaneRayEvent,FixedMathSharp.Geometry.RationalSegmentInterval&,FixedMathSharp.Geometry.ConePlaneRayPoint,System.Span`1<System.UInt64>,FixedMathSharp.Geometry.ConePlaneRaySelection&,FixedMathSharp.Geometry.ConePlaneRaySelection&,System.Int32)
AccumulateAxisAndApex(FixedMathSharp.Geometry.ConePlaneRayEventSource&,FixedMathSharp.Geometry.ConePlaneRayFrame&,FixedMathSharp.Geometry.ConePlaneRaySelection&,FixedMathSharp.Geometry.ConePlaneRaySelection&,FixedMathSharp.Geometry.ConePlaneRayEventSink&)
AccumulateBaseStationary(FixedMathSharp.Geometry.ConePlaneRayEventSource&,FixedMathSharp.Geometry.ConePlaneRayFrame&,FixedMathSharp.Geometry.ConePlaneRaySelection&,FixedMathSharp.Geometry.ConePlaneRaySelection&,FixedMathSharp.Geometry.ConePlaneRayEventSink&)