< Summary

Information
Class: FixedMathSharp.Geometry.ConePlaneRayCharts
Assembly: FixedMathSharp
File(s): /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/ConePlaneRayCharts.cs
Line coverage
100%
Covered lines: 10
Uncovered lines: 0
Coverable lines: 10
Total lines: 90
Line coverage: 100%
Branch coverage
100%
Covered branches: 6
Total branches: 6
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
IsUnitParameter(...)100%66100%

File(s)

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

#LineLine coverage
 1//=======================================================================
 2// ConePlaneRayCharts.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>Borrowed quadratic parameters for finite cone plane-section event charts.</summary>
 13internal static class ConePlaneRayCharts
 14{
 15    internal const int Words = 64;
 16    internal const int RootWords = 40;
 17
 18    // Apex coordinates use F(p)=H²(px²+pz²)-R²py² and plane N.p=c.
 19    // For one normal orientation, F(p+tN)=A*t²+2B(p)*t+C(p).
 20    //
 21    // Candidate completeness is a boundary-stratum argument. A maximum
 22    // strictly inside the admitted section projects a global support face.
 23    // Otherwise p is on a triangle edge, the lower cone side, or lower base.
 24    // A switch between upper side and upper base is on the projected upper
 25    // rim; every remaining boundary is an endpoint of one of these strata.
 26    //
 27    // On the LOWER side C(p)=0. Its nonzero side root is -2B(p)/A;
 28    // admission of that root additionally requires B(p)<=0 (the derivative
 29    // at the upper root is -2B(p)). Choosing the other crossing would leave
 30    // the finite cone immediately and later enter the opposite nappe.
 31    // With g=(Rcos(theta),H,Rsin(theta)), D=N.g and p=c*g/D,
 32    // E=N^T M g=H²D-H(H²+R²)Ny. The side depth is -2cE/(AD).
 33    // Its derivative vanishes at D'=0 or is constant. Triangle, axial,
 34    // and switch boundaries are lines on this generator circle. c=0 and
 35    // D=0 retain finite generator intervals rather than dividing by zero.
 36    //
 37    // On the UPPER rim q=g, t=(N.q-c)/|N|² and p=q-tN. Triangle walls W
 38    // have W.N=0, so W.p=W.q. Lower-cone admission factors as
 39    // F(p)=t*(A*t-2B(q)); t>0 makes the remaining circle predicate linear.
 40    // t=0 is admitted separately before that division. Interior stationary
 41    // rim values are exactly global rim supports; clipping endpoints and
 42    // rim/apex tangencies supply the remaining extrema.
 43    //
 44    // The four signed quadrant charts use u in [0,1]:
 45    // cos=sx*(1-u²)/(1+u²), sin=sz*2u/(1+u²).
 46    // Every admitted circle line is therefore a quadratic in u. On a
 47    // clipped straight edge G(s,t)=a*s²+2(b+m*t)*s+c+2n*t+A*t²;
 48    // eliminating stationary s gives a*(c+2n*t+A*t²)-(b+m*t)²=0.
 49    // Axial endpoints are rational. Lower-side edge roots need only the
 50    // original quadratic followed by t=-2B/A. No nested radical is needed.
 51    //
 52    // Full-domain ledger for the shared unreduced exact rigid frame:
 53    // point/edge/apex differences <198 bits, N <260, |N|² <522, c <460;
 54    // raw H/R squares <126, scaled base H/R <193. Authored normal-cross-
 55    // edge walls transformed without narrowing are <326; wall offsets
 56    // <526. Lower-circle triangle lines <990 and projected-rim lower-cone
 57    // lines <1118. Edge stationary polynomial coefficients <1184. Thus
 58    // face-stratum defining coefficients <1248 and discriminants <2498 bits.
 59    // Rational axis/generator point rays additionally have A<1302, B<1241,
 60    // C<1181; their discriminants remain <2485 bits.
 61    // Forty words retain the complete discriminant; sixty-four words retain
 62    // the unreduced evaluated depth numerator/denominator (<4096 bits).
 63    // Admission products and depth comparisons use larger transient storage;
 64    // these bounds do not authorize materializing those products in a field.
 65
 66    // Affine near-field ingress retains scaled local coordinates below 110
 67    // bits. Exact relative coordinates are <306, normals <351, normal² <704,
 68    // plane constants <659, wall coefficients <463 and wall offsets <771.
 69    // Independently retained cross-frame clips can use 832-bit parameters
 70    // instead of rigid 319-bit parameters. Every independent input bound is
 71    // therefore below three times the rigid ledger above; these same fixed-
 72    // degree polynomials fit three times its retained/transient capacities.
 73    // Only affine frames select those banks.
 74
 75    /// <summary>Tests a positive-denominator parameter against the closed or open unit interval.</summary>
 76    internal static bool IsUnitParameter(ContactQuadratic numerator, ContactQuadratic denominator,
 77        ReadOnlySpan<ulong> root, bool includeEndpoints = true)
 78    {
 1842979        int sign = numerator.Sign(root);
 1842980        if (includeEndpoints ? sign < 0 : sign <= 0)
 865981            return false;
 977082        int words = numerator.FieldWords;
 977083        Span<ulong> work = stackalloc ulong[2 * words];
 977084        Span<int> signs = stackalloc int[2];
 977085        ContactQuadratic difference = ContactQuadratic.At(work, signs, 0, words);
 1954086        numerator.CopyTo(difference); difference.Add(denominator, -1);
 977087        sign = difference.Sign(root);
 977088        return includeEndpoints ? sign <= 0 : sign < 0;
 89    }
 90}