< Summary

Line coverage
100%
Covered lines: 598
Uncovered lines: 0
Coverable lines: 598
Total lines: 1118
Line coverage: 100%
Branch coverage
100%
Covered branches: 222
Total branches: 222
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: TrySolveBoundedUnitPolynomial(...)100%2424100%
File 1: GetBorrowedPolynomialSignAtRationalParameter(...)100%11100%
File 2: .cctor()100%11100%
File 2: .ctor(...)100%11100%
File 2: .ctor(...)100%11100%
File 2: NegatedPolynomial()100%11100%
File 2: TryGetApexInterval(...)100%11100%
File 2: TrySolveUnitPolynomial(...)100%11100%
File 2: TryGetApexDistanceInterval(...)100%11100%
File 2: TryGetCenteredInterval(...)100%11100%
File 2: TryGetCenteredDistanceInterval(...)100%11100%
File 2: ContainsPointInApexCone(...)100%44100%
File 2: ContainsPointInCenteredCone(...)100%88100%
File 2: ContainsPoint(...)100%11100%
File 2: TrySolve(...)100%66100%
File 2: TrySolveBoundedPolynomial(...)100%11100%
File 2: TrySolveBoundedUnitPolynomial(...)100%7070100%
File 2: TryGetCompactPolynomial(...)100%1414100%
File 2: NarrowCoefficient(...)100%11100%
File 2: GetMagnitudeBitLength(...)100%11100%
File 2: GetMagnitudeBitLength(...)100%11100%
File 2: GetPolynomialSignAtRationalParameter(...)100%11100%
File 2: GetPolynomialSignAtRationalParameter(...)100%11100%
File 2: GetDerivativeSign(...)100%11100%
File 2: EvaluateWidePolynomialSign(...)100%11100%
File 2: EvaluateWidePolynomialSign(...)100%2626100%
File 2: RoundRoot(...)100%1414100%
File 2: RoundLinearRoot(...)100%11100%
File 2: Round(...)100%11100%
File 2: RoundLinearRoot(...)100%11100%
File 2: RoundLowerRoot(...)100%44100%
File 2: RoundUpperRoot(...)100%44100%
File 2: TryGetAxialInterval(...)100%1414100%
File 2: CreateApexData(...)100%11100%
File 2: CreateCenteredData(...)100%11100%
File 2: CreateData(...)100%1616100%
File 2: GetRadialTerm(...)100%11100%
File 2: GetRadialTerm(...)100%11100%
File 2: SubtractConeTerms(...)100%22100%
File 2: Evaluate(...)100%11100%
File 2: EvaluateDerivative(...)100%11100%
File 2: IsContained(...)100%11100%
File 2: IsContained(...)100%1010100%
File 2: GetScaledRaw(...)100%11100%
File 2: GetAxisHeightProduct(...)100%11100%
File 2: GetHalfScaledRaw(...)100%11100%
File 2: IsExactUnitAxis(...)100%44100%
File 2: SquareRaw(...)100%11100%
File 2: Normalize(...)100%22100%
File 2: Compare(...)100%11100%
File 2: GetDot(...)100%11100%
File 2: EvaluateBoundedUnitPolynomialSign(...)100%11100%
File 2: EvaluateBoundedUnitPolynomialDerivativeSign(...)100%11100%
File 2: TrySolveBoundedUnitPolynomial(...)100%11100%

File(s)

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteConeIntersection.BorrowedPolynomial.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteConeIntersection.BorrowedPolynomial.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>Retains affine-query polynomial coefficients through the existing exact quadratic root owner.</content>
 13internal static partial class WideFiniteConeIntersection
 14{
 15    internal static bool TrySolveBoundedUnitPolynomial(scoped ContactQuadratic a, scoped ContactQuadratic b,
 16        scoped ContactQuadratic c, Signed832 lowerN, Signed832 lowerD, Signed832 upperN, Signed832 upperD,
 17        Fixed64 outputScale, out Fixed64 entry, out Fixed64 exit)
 18    {
 8219        entry = exit = default;
 8220        int words = Math.Max(a.FieldWords, Math.Max(b.FieldWords,c.FieldWords)) + 14;
 16421        Span<ulong> storage=stackalloc ulong[20*words]; Span<int> signs=stackalloc int[20];
 16422        var loN=ContactQuadratic.At(storage,signs,0,words);var loD=ContactQuadratic.At(storage,signs,1,words);
 16423        var hiN=ContactQuadratic.At(storage,signs,2,words);var hiD=ContactQuadratic.At(storage,signs,3,words);
 16424        var n=ContactQuadratic.At(storage,signs,4,words);var d=ContactQuadratic.At(storage,signs,5,words);
 16425        var lower=ContactQuadratic.At(storage,signs,6,words);var lowerDivisor=ContactQuadratic.At(storage,signs,7,words)
 16426        var upper=ContactQuadratic.At(storage,signs,8,words);var upperDivisor=ContactQuadratic.At(storage,signs,9,words)
 32827        lower.Set(lowerN);lowerDivisor.Set(lowerD);upper.Set(upperN);upperDivisor.Set(upperD);
 8228        bool found=false;
 8229        if(GetBorrowedPolynomialSignAtRationalParameter(a,b,c,lowerN,lowerD)<=0)
 5530        {lower.CopyTo(loN);lowerDivisor.CopyTo(loD);lower.CopyTo(hiN);lowerDivisor.CopyTo(hiD);found=true;}
 8231        if(GetBorrowedPolynomialSignAtRationalParameter(a,b,c,upperN,upperD)<=0)
 12632        {if(!found){upper.CopyTo(loN);upperDivisor.CopyTo(loD);}upper.CopyTo(hiN);upperDivisor.CopyTo(hiD);found=true;}
 8233        Span<ulong> root=stackalloc ulong[2*words];
 34        // Every retained root uses this same discriminant; rational endpoints
 35        // have a zero radical coefficient and therefore share its field.
 49236        for(int branch=-1;branch<=1;branch+=2)
 37        {
 16438            if(!ContactQuadratic.TryGetParameter(a,b,c,branch,root,n,d)) continue;
 9539            if(ContactQuadratic.CompareRatios(n,d,root,lower,lowerDivisor,root)<0
 9540                ||ContactQuadratic.CompareRatios(n,d,root,upper,upperDivisor,root)>0)continue;
 11341            if(!found||ContactQuadratic.CompareRatios(n,d,root,loN,loD,root)<0){n.CopyTo(loN);d.CopyTo(loD);}
 11542            if(!found||ContactQuadratic.CompareRatios(n,d,root,hiN,hiD,root)>0){n.CopyTo(hiN);d.CopyTo(hiD);}
 5143            found=true;
 44        }
 12245        if(!found)return false;
 4246        ContactQuadratic.Scale(loN,Signed576.ExtendValue(Signed192.Raw(outputScale)),n);
 4247        entry=ContactQuadratic.RoundRatio(n,loD,root,0,outputScale.m_rawValue);
 4248        ContactQuadratic.Scale(hiN,Signed576.ExtendValue(Signed192.Raw(outputScale)),n);
 4249        exit=ContactQuadratic.RoundRatio(n,hiD,root,0,outputScale.m_rawValue);
 4250        return true;
 51    }
 52
 53    internal static int GetBorrowedPolynomialSignAtRationalParameter(scoped ContactQuadratic a,
 54        scoped ContactQuadratic b, scoped ContactQuadratic c, Signed832 n, Signed832 d)
 55    {
 543256        int words=Math.Max(a.FieldWords,Math.Max(b.FieldWords,c.FieldWords))+26;
 1086457        Span<ulong> storage=stackalloc ulong[6*words];Span<int> signs=stackalloc int[6];
 1086458        var value=ContactQuadratic.At(storage,signs,0,words);var term=ContactQuadratic.At(storage,signs,1,words);
 543259        var work=ContactQuadratic.At(storage,signs,2,words);
 1086460        ContactQuadratic.Scale(a,n,work);ContactQuadratic.Scale(work,n,value);
 2172861        ContactQuadratic.Scale(b,n,work);ContactQuadratic.Scale(work,d,term);value.Add(term);value.Add(term);
 1629662        ContactQuadratic.Scale(c,d,work);ContactQuadratic.Scale(work,d,term);value.Add(term);
 543263        return value.Signs[0];
 64    }
 65}

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

#LineLine coverage
 1//=======================================================================
 2// WideFiniteConeIntersection.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>
 13/// Owns exact full-domain finite-cone containment and segment reduction.
 14/// </summary>
 15internal static partial class WideFiniteConeIntersection
 16{
 117    private static readonly Signed192 One = Signed192.Signed(1L);
 118    private static readonly Signed192 Four = Signed192.Signed(4L);
 119    private static readonly Signed192 AxisScaleSquared = new(0UL, 1UL, 0UL);
 20
 21    #region Nested Types
 22
 23    private readonly struct RationalBound
 24    {
 25        internal readonly Signed192 Numerator;
 26        internal readonly Signed192 Denominator;
 27
 28        internal RationalBound(Signed192 numerator, Signed192 denominator)
 29        {
 13170330            Numerator = numerator;
 13170331            Denominator = denominator;
 13170332        }
 33    }
 34
 35    private readonly struct ConeData
 36    {
 37        internal readonly Signed192 StartAxial;
 38        internal readonly Signed192 AxialVelocity;
 39        internal readonly Signed192 MaximumAxial;
 40        internal readonly Signed576 Coefficient;
 41        internal readonly Signed576 Projection;
 42        internal readonly Signed576 Constant;
 43
 44        internal ConeData(
 45            Signed192 startAxial,
 46            Signed192 axialVelocity,
 47            Signed192 maximumAxial,
 48            Signed576 coefficient,
 49            Signed576 projection,
 50            Signed576 constant)
 51        {
 7086752            StartAxial = startAxial;
 7086753            AxialVelocity = axialVelocity;
 7086754            MaximumAxial = maximumAxial;
 7086755            Coefficient = coefficient;
 7086756            Projection = projection;
 7086757            Constant = constant;
 7086758        }
 59
 60        internal ConeData NegatedPolynomial() =>
 6461            new(
 6462                StartAxial,
 6463                AxialVelocity,
 6464                MaximumAxial,
 6465                WideArithmetic.SubtractSigned576(default, Coefficient),
 6466                WideArithmetic.SubtractSigned576(default, Projection),
 6467                WideArithmetic.SubtractSigned576(default, Constant));
 68    }
 69
 70    #endregion
 71
 72    internal static bool TryGetApexInterval(
 73        FixedSegment query,
 74        Vector3d apex,
 75        Vector3d apexToBaseDirection,
 76        Fixed64 height,
 77        Fixed64 baseRadius,
 78        out Fixed64 entry,
 79        out Fixed64 exit,
 80        out bool startContained,
 81        out bool endContainedStrict) =>
 4382        TrySolve(
 4383            CreateApexData(query, apex, apexToBaseDirection, height, baseRadius),
 4384            Fixed64.One,
 4385            out entry,
 4386            out exit,
 4387            out startContained,
 4388            out endContainedStrict);
 89
 90    internal static bool TrySolveUnitPolynomial(
 91        Signed576 coefficient,
 92        Signed576 projection,
 93        Signed576 constant,
 94        Fixed64 outputScale,
 95        out Fixed64 entry,
 96        out Fixed64 exit) =>
 3448297        TrySolveBoundedPolynomial(
 3448298            new ConeData(default, default, default, coefficient, projection, constant),
 3448299            new RationalBound(default, One),
 34482100            new RationalBound(One, One),
 34482101            outputScale,
 34482102            out entry,
 34482103            out exit);
 104
 105    internal static bool TryGetApexDistanceInterval(
 106        FixedSegment query,
 107        Vector3d apex,
 108        Vector3d apexToBaseDirection,
 109        Fixed64 height,
 110        Fixed64 baseRadius,
 111        Fixed64 totalDistance,
 112        out Fixed64 entry,
 113        out Fixed64 exit,
 114        out bool startContained,
 115        out bool endContainedStrict) =>
 363116        TrySolve(
 363117            CreateApexData(query, apex, apexToBaseDirection, height, baseRadius),
 363118            totalDistance,
 363119            out entry,
 363120            out exit,
 363121            out startContained,
 363122            out endContainedStrict);
 123
 124    internal static bool TryGetCenteredInterval(
 125        FixedSegment query,
 126        Vector3d center,
 127        Vector3d baseToApexDirection,
 128        Fixed64 height,
 129        Fixed64 baseRadius,
 130        out Fixed64 entry,
 131        out Fixed64 exit,
 132        out bool startContained,
 133        out bool endContainedStrict) =>
 3134        TrySolve(
 3135            CreateCenteredData(query, center, baseToApexDirection, height, baseRadius),
 3136            Fixed64.One,
 3137            out entry,
 3138            out exit,
 3139            out startContained,
 3140            out endContainedStrict);
 141
 142    internal static bool TryGetCenteredDistanceInterval(
 143        FixedSegment query,
 144        Vector3d center,
 145        Vector3d baseToApexDirection,
 146        Fixed64 height,
 147        Fixed64 baseRadius,
 148        Fixed64 totalDistance,
 149        out Fixed64 entry,
 150        out Fixed64 exit,
 151        out bool startContained,
 152        out bool endContainedStrict) =>
 17153        TrySolve(
 17154            CreateCenteredData(query, center, baseToApexDirection, height, baseRadius),
 17155            totalDistance,
 17156            out entry,
 17157            out exit,
 17158            out startContained,
 17159            out endContainedStrict);
 160
 161    internal static bool ContainsPointInApexCone(
 162        Vector3d point,
 163        Vector3d apex,
 164        Vector3d apexToBaseDirection,
 165        Fixed64 height,
 166        Fixed64 baseRadius,
 167        bool strict)
 168    {
 8169        Signed192 heightRaw = Signed192.Signed(height.m_rawValue);
 8170        Signed192 axisLengthSquared = GetDot(
 8171            apexToBaseDirection,
 8172            Vector3d.Zero,
 8173            apexToBaseDirection,
 8174            Vector3d.Zero);
 8175        bool exactUnitAxis = IsExactUnitAxis(axisLengthSquared);
 8176        Signed192 axisProjection = GetDot(
 8177            point,
 8178            apex,
 8179            apexToBaseDirection,
 8180            Vector3d.Zero);
 8181        Signed192 axial = exactUnitAxis ? axisProjection : GetScaledRaw(axisProjection);
 8182        return ContainsPoint(
 8183            point,
 8184            apex,
 8185            heightRaw,
 8186            axisLengthSquared,
 8187            axisProjection,
 8188            axial,
 8189            exactUnitAxis ? GetScaledRaw(heightRaw) : GetAxisHeightProduct(axisLengthSquared, heightRaw),
 8190            One,
 8191            exactUnitAxis,
 8192            baseRadius,
 8193            strict);
 194    }
 195
 196    internal static bool ContainsPointInCenteredCone(
 197        Vector3d point,
 198        Vector3d center,
 199        Vector3d baseToApexDirection,
 200        Fixed64 height,
 201        Fixed64 baseRadius,
 202        bool strict)
 203    {
 11204        Signed192 heightRaw = Signed192.Signed(height.m_rawValue);
 11205        Signed192 axisLengthSquared = GetDot(
 11206            baseToApexDirection,
 11207            Vector3d.Zero,
 11208            baseToApexDirection,
 11209            Vector3d.Zero);
 11210        bool exactUnitAxis = IsExactUnitAxis(axisLengthSquared);
 11211        Signed192 axisProjection = GetDot(point, center, baseToApexDirection, Vector3d.Zero);
 11212        Signed192 maximumAxial = exactUnitAxis
 11213            ? GetScaledRaw(heightRaw)
 11214            : GetAxisHeightProduct(axisLengthSquared, heightRaw);
 11215        Signed192 axial = exactUnitAxis
 11216            ? WideArithmetic.SubtractSigned192(GetHalfScaledRaw(heightRaw), axisProjection)
 11217            : WideArithmetic.SubtractSigned192(maximumAxial, WideArithmetic.Double(GetScaledRaw(axisProjection)));
 11218        return ContainsPoint(
 11219            point,
 11220            center,
 11221            heightRaw,
 11222            axisLengthSquared,
 11223            axisProjection,
 11224            axial,
 11225            exactUnitAxis ? maximumAxial : WideArithmetic.Double(maximumAxial),
 11226            exactUnitAxis ? One : Four,
 11227            exactUnitAxis,
 11228            baseRadius,
 11229            strict);
 230    }
 231
 232    private static bool ContainsPoint(
 233        Vector3d point,
 234        Vector3d origin,
 235        Signed192 heightRaw,
 236        Signed192 axisLengthSquared,
 237        Signed192 axisProjection,
 238        Signed192 axial,
 239        Signed192 maximumAxial,
 240        Signed192 radialScale,
 241        bool exactUnitAxis,
 242        Fixed64 baseRadius,
 243        bool strict)
 244    {
 19245        Signed192 distanceSquared = GetDot(point, origin, point, origin);
 19246        Signed320 radial = GetRadialTerm(distanceSquared, axisProjection, axisLengthSquared);
 19247        Signed320 heightSquared = WideArithmetic.MultiplySigned192(heightRaw, heightRaw);
 19248        Signed192 radiusRaw = Signed192.Signed(baseRadius.m_rawValue);
 19249        Signed320 radiusSquared = WideArithmetic.MultiplySigned192(radiusRaw, radiusRaw);
 19250        Signed576 polynomial = SubtractConeTerms(
 19251            heightSquared,
 19252            radial,
 19253            axisLengthSquared,
 19254            radialScale,
 19255            exactUnitAxis,
 19256            radiusSquared,
 19257            WideArithmetic.MultiplySigned192(axial, axial));
 19258        return IsContained(axial, polynomial, maximumAxial, strict);
 259    }
 260
 261    private static bool TrySolve(
 262        ConeData data,
 263        Fixed64 outputScale,
 264        out Fixed64 entry,
 265        out Fixed64 exit,
 266        out bool startContained,
 267        out bool endContainedStrict)
 268    {
 426269        startContained = IsContained(
 426270            data.StartAxial,
 426271            data.Constant,
 426272            data.MaximumAxial,
 426273            strict: false);
 426274        Signed192 endAxial = WideArithmetic.AddSigned192(data.StartAxial, data.AxialVelocity);
 426275        endContainedStrict = false;
 276
 426277        if (!TryGetAxialInterval(data, out RationalBound lower, out RationalBound upper))
 278        {
 70279            entry = default;
 70280            exit = default;
 70281            return false;
 282        }
 283
 356284        if (endAxial.Sign > 0
 356285            && WideArithmetic.SubtractSigned192(endAxial, data.MaximumAxial).Sign < 0)
 286        {
 201287            endContainedStrict = Evaluate(data, One, One).Sign < 0;
 288        }
 289
 356290        return TrySolveBoundedPolynomial(data, lower, upper, outputScale, out entry, out exit);
 291    }
 292
 293    private static bool TrySolveBoundedPolynomial(
 294        ConeData data,
 295        RationalBound lower,
 296        RationalBound upper,
 297        Fixed64 outputScale,
 298        out Fixed64 entry,
 299        out Fixed64 exit) =>
 35234300        TrySolveBoundedUnitPolynomial(
 35234301            Signed832.ExtendValue(data.Coefficient),
 35234302            Signed832.ExtendValue(data.Projection),
 35234303            Signed832.ExtendValue(data.Constant),
 35234304            Signed320.ExtendValue(lower.Numerator),
 35234305            Signed320.ExtendValue(lower.Denominator),
 35234306            Signed320.ExtendValue(upper.Numerator),
 35234307            Signed320.ExtendValue(upper.Denominator),
 35234308            outputScale,
 35234309            out entry,
 35234310            out exit);
 311
 312    /// <summary>
 313    /// Reduces an axially clipped conic on [0, 1]. Rigid triangle coefficients
 314    /// have fewer than 660 magnitude bits and clip ratios at most 200; midpoint
 315    /// root evaluations fit Signed832, while clipped evaluations use fixed
 316    /// transient magnitude storage. The admitted cone interval is connected.
 317    /// </summary>
 318    internal static bool TrySolveBoundedUnitPolynomial(
 319        Signed832 coefficient,
 320        Signed832 projection,
 321        Signed832 constant,
 322        Signed320 lowerNumerator,
 323        Signed320 lowerDenominator,
 324        Signed320 upperNumerator,
 325        Signed320 upperDenominator,
 326        Fixed64 outputScale,
 327        out Fixed64 entry,
 328        out Fixed64 exit)
 329    {
 35419330        bool compact = TryGetCompactPolynomial(
 35419331            coefficient, projection, constant,
 35419332            lowerNumerator, lowerDenominator, upperNumerator, upperDenominator,
 35419333            out ConeData data);
 35419334        bool lowerContained = (compact
 35419335            ? Evaluate(data, Signed192.NarrowValue(lowerNumerator), Signed192.NarrowValue(lowerDenominator)).Sign
 35419336            : GetPolynomialSignAtRationalParameter(coefficient, projection, constant, lowerNumerator, lowerDenominator))
 35419337        bool upperContained = (compact
 35419338            ? Evaluate(data, Signed192.NarrowValue(upperNumerator), Signed192.NarrowValue(upperDenominator)).Sign
 35419339            : GetPolynomialSignAtRationalParameter(coefficient, projection, constant, upperNumerator, upperDenominator))
 340
 35419341        if (lowerContained && upperContained)
 342        {
 805343            entry = Round(lowerNumerator, lowerDenominator, outputScale);
 805344            exit = Round(upperNumerator, upperDenominator, outputScale);
 805345            return true;
 346        }
 347
 34614348        if (coefficient.IsZero)
 349        {
 3485350            if (!lowerContained && !upperContained)
 351            {
 3478352                entry = default;
 3478353                exit = default;
 3478354                return false;
 355            }
 356
 7357            Fixed64 root = compact
 7358                ? RoundLinearRoot(data, outputScale)
 7359                : RoundLinearRoot(projection, constant, outputScale);
 7360            entry = lowerContained ? Round(lowerNumerator, lowerDenominator, outputScale) : root;
 7361            exit = upperContained ? Round(upperNumerator, upperDenominator, outputScale) : root;
 7362            return true;
 363        }
 364
 31129365        bool opensUp = coefficient.Sign > 0;
 31129366        if (!opensUp && !lowerContained && !upperContained)
 367        {
 33368            entry = default;
 33369            exit = default;
 33370            return false;
 371        }
 372
 31096373        if (opensUp
 31096374            && ((!lowerContained && (compact
 31096375                    ? EvaluateDerivative(data, new RationalBound(Signed192.NarrowValue(lowerNumerator), Signed192.Narrow
 31096376                    : GetDerivativeSign(coefficient, projection, lowerNumerator, lowerDenominator)) >= 0)
 31096377                || (!upperContained && (compact
 31096378                    ? EvaluateDerivative(data, new RationalBound(Signed192.NarrowValue(upperNumerator), Signed192.Narrow
 31096379                    : GetDerivativeSign(coefficient, projection, upperNumerator, upperDenominator)) <= 0)))
 380        {
 1246381            entry = default;
 1246382            exit = default;
 1246383            return false;
 384        }
 385
 29850386        if (!opensUp)
 387        {
 64388            coefficient = WideArithmetic.SubtractSigned832(default, coefficient);
 64389            projection = WideArithmetic.SubtractSigned832(default, projection);
 64390            constant = WideArithmetic.SubtractSigned832(default, constant);
 391        }
 29850392        ConeData normalized = opensUp ? data : data.NegatedPolynomial();
 29850393        Signed832 discriminant = compact
 29850394            ? WideArithmetic.SubtractSigned832(
 29850395                WideArithmetic.MultiplySigned576ToSigned832(normalized.Projection, normalized.Projection),
 29850396                WideArithmetic.MultiplySigned576ToSigned832(normalized.Coefficient, normalized.Constant))
 29850397            : default;
 29850398        int discriminantSign = compact ? discriminant.Sign
 29850399            : constant.Sign < 0 ? 1
 29850400            : WideArithmetic.CompareNonNegativeProducts(projection, projection, coefficient, constant);
 29850401        if (discriminantSign < 0)
 402        {
 18621403            entry = default;
 18621404            exit = default;
 18621405            return false;
 406        }
 407
 11229408        Signed192 outputScaleRaw = Signed192.Signed(outputScale.m_rawValue);
 11229409        Signed192 outputScaleSquared = SquareRaw(outputScale.m_rawValue);
 11229410        Signed576 scaledSquareRoot = compact
 11229411            ? WideArithmetic.GetFloorSquareRootOfProduct(discriminant, outputScaleSquared)
 11229412            : default;
 413
 11229414        if (opensUp)
 415        {
 11165416            entry = lowerContained
 11165417                ? Round(lowerNumerator, lowerDenominator, outputScale)
 11165418                : compact ? RoundLowerRoot(normalized, scaledSquareRoot, outputScaleRaw)
 11165419                : RoundRoot(coefficient, projection, constant, outputScale, upperRoot: false);
 11165420            exit = upperContained
 11165421                ? Round(upperNumerator, upperDenominator, outputScale)
 11165422                : compact ? RoundUpperRoot(normalized, scaledSquareRoot, outputScaleRaw)
 11165423                : RoundRoot(coefficient, projection, constant, outputScale, upperRoot: true);
 11165424            return true;
 425        }
 426
 64427        entry = lowerContained
 64428            ? Round(lowerNumerator, lowerDenominator, outputScale)
 64429            : compact ? RoundUpperRoot(normalized, scaledSquareRoot, outputScaleRaw)
 64430            : RoundRoot(coefficient, projection, constant, outputScale, upperRoot: true);
 64431        exit = upperContained
 64432            ? Round(upperNumerator, upperDenominator, outputScale)
 64433            : compact ? RoundLowerRoot(normalized, scaledSquareRoot, outputScaleRaw)
 64434            : RoundRoot(coefficient, projection, constant, outputScale, upperRoot: false);
 64435        return true;
 436    }
 437
 438    private static bool TryGetCompactPolynomial(
 439        Signed832 coefficient,
 440        Signed832 projection,
 441        Signed832 constant,
 442        Signed320 lowerNumerator,
 443        Signed320 lowerDenominator,
 444        Signed320 upperNumerator,
 445        Signed320 upperDenominator,
 446        out ConeData data)
 447    {
 35419448        int coefficientBits = GetMagnitudeBitLength(coefficient);
 35419449        int projectionBits = GetMagnitudeBitLength(projection);
 35419450        int constantBits = GetMagnitudeBitLength(constant);
 35419451        int coefficientMaximum = Math.Max(coefficientBits, Math.Max(projectionBits, constantBits));
 35419452        int boundMaximum = Math.Max(
 35419453            Math.Max(GetMagnitudeBitLength(lowerNumerator), GetMagnitudeBitLength(lowerDenominator)),
 35419454            Math.Max(GetMagnitudeBitLength(upperNumerator), GetMagnitudeBitLength(upperDenominator)));
 455        // Rational squares fit Signed320, evaluated sums and the discriminant
 456        // fit Signed832, and the linear numerator retains its 63-bit scale.
 457        // The discriminant proof also bounds the scaled quadratic-root
 458        // numerator below 480 bits, inside the existing Signed576 owner.
 35419459        if (coefficientMaximum > 575 || boundMaximum > 159
 35419460            || coefficientMaximum + 2 * boundMaximum > 828
 35419461            || 2 * projectionBits > 830 || coefficientBits + constantBits > 830
 35419462            || (coefficient.IsZero && constantBits > 512))
 463        {
 48464            data = default;
 48465            return false;
 466        }
 467
 35371468        data = new ConeData(default, default, default,
 35371469            NarrowCoefficient(coefficient), NarrowCoefficient(projection), NarrowCoefficient(constant));
 35371470        return true;
 471    }
 472
 473    private static Signed576 NarrowCoefficient(Signed832 value) =>
 106113474        new(value.Word8, value.Word7, value.Word6, value.Word5, value.Word4,
 106113475            value.Word3, value.Word2, value.Word1, value.Word0);
 476
 477    private static int GetMagnitudeBitLength(Signed832 value)
 478    {
 106257479        Span<ulong> magnitude = stackalloc ulong[13];
 106257480        WideArithmetic.GetMagnitude(value, magnitude);
 106257481        return WideArithmetic.GetMagnitudeBitLength(magnitude);
 482    }
 483
 484    private static int GetMagnitudeBitLength(Signed320 value)
 485    {
 141676486        Span<ulong> magnitude = stackalloc ulong[5];
 141676487        WideArithmetic.GetMagnitude(value, out magnitude[4], out magnitude[3],
 141676488            out magnitude[2], out magnitude[1], out magnitude[0]);
 141676489        return WideArithmetic.GetMagnitudeBitLength(magnitude);
 490    }
 491
 492    /// <summary>
 493    /// Returns the exact sign of A*n*n + 2*B*n*d + C*d*d without narrowing
 494    /// rigid-frame clip ratios or their homogenized products.
 495    /// </summary>
 496    internal static int GetPolynomialSignAtRationalParameter(
 497        Signed832 coefficient,
 498        Signed832 projection,
 499        Signed832 constant,
 500        Signed320 numerator,
 501        Signed320 denominator) =>
 20722502        EvaluateWidePolynomialSign(coefficient, projection, constant, numerator, denominator, derivative: false);
 503
 504    internal static int GetPolynomialSignAtRationalParameter(Signed832 coefficient, Signed832 projection,
 505        Signed832 constant, Signed832 numerator, Signed832 denominator)
 506    {
 506507        Span<ulong> n = stackalloc ulong[13], d = stackalloc ulong[13];
 506508        WideArithmetic.GetMagnitude(numerator, n); WideArithmetic.GetMagnitude(denominator, d);
 253509        return EvaluateWidePolynomialSign(coefficient, projection, constant,
 253510            n, numerator.Sign, d, denominator.Sign, derivative: false);
 511    }
 512
 513    private static int GetDerivativeSign(
 514        Signed832 coefficient,
 515        Signed832 projection,
 516        Signed320 numerator,
 517        Signed320 denominator) =>
 40518        EvaluateWidePolynomialSign(coefficient, projection, default, numerator, denominator, derivative: true);
 519
 520    private static int EvaluateWidePolynomialSign(
 521        Signed832 coefficient,
 522        Signed832 projection,
 523        Signed832 constant,
 524        Signed320 numerator,
 525        Signed320 denominator,
 526        bool derivative)
 527    {
 528        // Even the full carrier products occupy fewer than 1,474 bits including
 529        // the doubled middle term and addition carries; 24 words retain them.
 530        // Current rigid query bounds are smaller: 660 + 2*200 + 2 < 1,063 bits.
 20762531        Span<ulong> n = stackalloc ulong[5];
 20762532        Span<ulong> d = stackalloc ulong[5];
 20762533        WideArithmetic.GetMagnitude(numerator, out n[4], out n[3], out n[2], out n[1], out n[0]);
 20762534        WideArithmetic.GetMagnitude(denominator, out d[4], out d[3], out d[2], out d[1], out d[0]);
 20762535        return EvaluateWidePolynomialSign(coefficient, projection, constant,
 20762536            n, numerator.Sign, d, denominator.Sign, derivative);
 537    }
 538
 539    private static int EvaluateWidePolynomialSign(Signed832 coefficient, Signed832 projection, Signed832 constant,
 540        ReadOnlySpan<ulong> n, int numeratorSign, ReadOnlySpan<ulong> d, int denominatorSign, bool derivative)
 541    {
 21015542        int factorWords = n.Length + d.Length;
 543        // Full coefficient and two complete parameter magnitudes plus one
 544        // limb retain the doubled middle term and both addition carries.
 21015545        int words = 14 + factorWords;
 42030546        Span<ulong> factor = stackalloc ulong[factorWords], coefficientMagnitude = stackalloc ulong[13],
 42030547            product = stackalloc ulong[words], sum = stackalloc ulong[words];
 21015548        sum.Clear();
 21015549        int sign = 0;
 168040550        for (int term = 0; term < (derivative ? 2 : 3); term++)
 551        {
 63005552            Signed832 value = term == 0 ? coefficient : term == 1 ? projection : constant;
 63005553            WideArithmetic.GetMagnitude(value, coefficientMagnitude);
 554            int factorSign;
 63005555            if (derivative)
 556            {
 80557                factor.Clear();
 80558                (term == 0 ? n : d).CopyTo(factor);
 80559                factorSign = term == 0 ? numeratorSign : denominatorSign;
 560            }
 561            else
 562            {
 62925563                WideArithmetic.MultiplyMagnitudes(term == 2 ? d : n, term == 0 ? n : d, factor);
 62925564                factorSign = term == 0 ? numeratorSign * numeratorSign
 62925565                    : term == 1 ? numeratorSign * denominatorSign : denominatorSign * denominatorSign;
 566            }
 63005567            WideArithmetic.MultiplyMagnitudes(coefficientMagnitude, factor, product);
 63005568            WideArithmetic.AddShiftedSignedMagnitude(product, value.Sign * factorSign,
 63005569                !derivative && term == 1 ? 1 : 0, sum, ref sign);
 570        }
 21015571        return sign;
 572    }
 573
 574    private static Fixed64 RoundRoot(
 575        Signed832 coefficient,
 576        Signed832 projection,
 577        Signed832 constant,
 578        Fixed64 outputScale,
 579        bool upperRoot)
 580    {
 24581        ulong low = 0UL;
 24582        ulong high = (ulong)outputScale.m_rawValue;
 24583        Signed192 denominator = new(0UL, 0UL, high << 1);
 1003584        while (low < high)
 585        {
 979586            ulong candidate = low + ((high - low) >> 1);
 979587            Signed192 numerator = new(0UL, 0UL, (candidate << 1) | 1UL);
 979588            Signed832 first = WideArithmetic.MultiplySigned832(coefficient, numerator);
 979589            Signed832 second = WideArithmetic.MultiplySigned832(projection, denominator);
 979590            int derivativeSign = WideArithmetic.AddSigned832(first, second).Sign;
 979591            Signed832 mixed = WideArithmetic.MultiplySigned832(second, numerator);
 979592            int polynomialSign = WideArithmetic.AddSigned832(
 979593                WideArithmetic.AddSigned832(
 979594                    WideArithmetic.MultiplySigned832(first, numerator),
 979595                    WideArithmetic.AddSigned832(mixed, mixed)),
 979596                WideArithmetic.MultiplySigned832(
 979597                    WideArithmetic.MultiplySigned832(constant, denominator), denominator)).Sign;
 979598            bool exactRoot = polynomialSign == 0 && (upperRoot ? derivativeSign >= 0 : derivativeSign <= 0);
 979599            bool precedes = exactRoot ? (candidate & 1UL) != 0UL
 979600                : upperRoot ? derivativeSign < 0 || polynomialSign < 0
 979601                : derivativeSign < 0 && polynomialSign > 0;
 979602            if (precedes)
 427603                low = candidate + 1UL;
 604            else
 552605                high = candidate;
 606        }
 24607        return Fixed64.FromRaw((long)low);
 608    }
 609
 610    private static Fixed64 RoundLinearRoot(Signed832 projection, Signed832 constant, Fixed64 outputScale)
 611    {
 2612        Signed832 numerator = WideArithmetic.MultiplySigned832(
 2613            WideArithmetic.SubtractSigned832(default, constant), Signed192.Raw(outputScale));
 2614        Signed832 denominator = WideArithmetic.AddSigned832(projection, projection);
 2615        _ = Fixed64.TryGetSignedRawRatio(numerator, denominator, 0, out Fixed64 root);
 2616        return root;
 617    }
 618
 619    private static Fixed64 Round(Signed320 numerator, Signed320 denominator, Fixed64 outputScale)
 620    {
 2426621        _ = Fixed64.TryGetSignedRawRatio(
 2426622            WideArithmetic.MultiplySigned320(numerator, Signed192.Raw(outputScale)),
 2426623            Signed576.ExtendValue(denominator), out Fixed64 result);
 2426624        return result;
 625    }
 626
 627    private static Fixed64 RoundLinearRoot(ConeData data, Fixed64 outputScale)
 628    {
 5629        Signed192 outputScaleRaw = Signed192.Signed(outputScale.m_rawValue);
 5630        Signed576 numerator = WideArithmetic.MultiplySigned576(
 5631            WideArithmetic.SubtractSigned576(default, data.Constant),
 5632            outputScaleRaw);
 5633        Signed576 denominator = WideArithmetic.AddSigned576(data.Projection, data.Projection);
 5634        _ = Fixed64.TryGetSignedRawRatio(numerator, denominator, out Fixed64 root);
 5635        return root;
 636    }
 637
 638    private static Fixed64 RoundLowerRoot(
 639        ConeData normalized,
 640        Signed576 scaledSquareRoot,
 641        Signed192 outputScaleRaw)
 642    {
 11082643        Signed576 negativeScaledProjection = WideArithmetic.SubtractSigned576(
 11082644            default,
 11082645            WideArithmetic.MultiplySigned576(normalized.Projection, outputScaleRaw));
 11082646        Signed576 numerator = WideArithmetic.SubtractSigned576(
 11082647            negativeScaledProjection,
 11082648            scaledSquareRoot);
 11082649        _ = Fixed64.TryGetSignedRawRatio(numerator, normalized.Coefficient, out Fixed64 candidate);
 650
 11082651        long upperRaw = candidate.m_rawValue;
 11082652        Signed192 upper = Signed192.Signed(upperRaw);
 11082653        Signed192 midpoint = WideArithmetic.SubtractSigned192(
 11082654            WideArithmetic.AddSigned192(upper, upper),
 11082655            One);
 11082656        Signed192 doubleScale = WideArithmetic.AddSigned192(outputScaleRaw, outputScaleRaw);
 11082657        Signed832 value = Evaluate(normalized, midpoint, doubleScale);
 11082658        if (value.IsZero)
 22659            return candidate;
 660
 11060661        return Fixed64.FromRaw(value.Sign > 0 ? upperRaw : upperRaw - 1L);
 662    }
 663
 664    private static Fixed64 RoundUpperRoot(
 665        ConeData normalized,
 666        Signed576 scaledSquareRoot,
 667        Signed192 outputScaleRaw)
 668    {
 10543669        Signed576 negativeScaledProjection = WideArithmetic.SubtractSigned576(
 10543670            default,
 10543671            WideArithmetic.MultiplySigned576(normalized.Projection, outputScaleRaw));
 10543672        Signed576 numerator = WideArithmetic.AddSigned576(
 10543673            negativeScaledProjection,
 10543674            scaledSquareRoot);
 10543675        _ = Fixed64.TryGetSignedRawRatio(numerator, normalized.Coefficient, out Fixed64 candidate);
 676
 10543677        long lowerRaw = candidate.m_rawValue;
 10543678        Signed192 lower = Signed192.Signed(lowerRaw);
 10543679        Signed192 midpoint = WideArithmetic.AddSigned192(
 10543680            WideArithmetic.AddSigned192(lower, lower),
 10543681            One);
 10543682        Signed192 doubleScale = WideArithmetic.AddSigned192(outputScaleRaw, outputScaleRaw);
 10543683        Signed832 value = Evaluate(normalized, midpoint, doubleScale);
 10543684        if (value.IsZero)
 26685            return candidate;
 686
 10517687        return Fixed64.FromRaw(value.Sign <= 0 ? lowerRaw + 1L : lowerRaw);
 688    }
 689
 690    private static bool TryGetAxialInterval(
 691        ConeData data,
 692        out RationalBound lower,
 693        out RationalBound upper)
 694    {
 426695        RationalBound zero = new(default, One);
 426696        RationalBound one = new(One, One);
 426697        lower = zero;
 426698        upper = one;
 699
 426700        if (data.AxialVelocity.IsZero)
 701        {
 135702            return data.StartAxial.Sign >= 0
 135703                && WideArithmetic.SubtractSigned192(data.StartAxial, data.MaximumAxial).Sign <= 0;
 704        }
 705
 291706        RationalBound first = Normalize(
 291707            WideArithmetic.SubtractSigned192(default, data.StartAxial),
 291708            data.AxialVelocity);
 291709        RationalBound second = Normalize(
 291710            WideArithmetic.SubtractSigned192(data.MaximumAxial, data.StartAxial),
 291711            data.AxialVelocity);
 291712        if (Compare(first, second) > 0)
 138713            (first, second) = (second, first);
 714
 291715        if (Compare(second, zero) < 0 || Compare(first, one) > 0)
 30716            return false;
 261717        if (Compare(first, zero) > 0)
 110718            lower = first;
 261719        if (Compare(second, one) < 0)
 110720            upper = second;
 261721        return true;
 722    }
 723
 724    private static ConeData CreateApexData(
 725        FixedSegment query,
 726        Vector3d apex,
 727        Vector3d apexToBaseDirection,
 728        Fixed64 height,
 729        Fixed64 baseRadius)
 730    {
 406731        Signed192 heightRaw = Signed192.Signed(height.m_rawValue);
 406732        return CreateData(
 406733            query,
 406734            apex,
 406735            apexToBaseDirection,
 406736            heightRaw,
 406737            centered: false,
 406738            baseRadius);
 739    }
 740
 741    private static ConeData CreateCenteredData(
 742        FixedSegment query,
 743        Vector3d center,
 744        Vector3d baseToApexDirection,
 745        Fixed64 height,
 746        Fixed64 baseRadius)
 747    {
 20748        Signed192 heightRaw = Signed192.Signed(height.m_rawValue);
 20749        return CreateData(
 20750            query,
 20751            center,
 20752            baseToApexDirection,
 20753            heightRaw,
 20754            centered: true,
 20755            baseRadius);
 756    }
 757
 758    private static ConeData CreateData(
 759        FixedSegment query,
 760        Vector3d origin,
 761        Vector3d axisDirection,
 762        Signed192 heightRaw,
 763        bool centered,
 764        Fixed64 baseRadius)
 765    {
 426766        Signed192 startDistanceSquared = GetDot(query.Start, origin, query.Start, origin);
 426767        Signed192 startDirectionProjection = GetDot(query.Start, origin, query.End, query.Start);
 426768        Signed192 directionLengthSquared = GetDot(query.End, query.Start, query.End, query.Start);
 426769        Signed192 axisLengthSquared = GetDot(axisDirection, Vector3d.Zero, axisDirection, Vector3d.Zero);
 426770        bool exactUnitAxis = IsExactUnitAxis(axisLengthSquared);
 426771        Signed192 startAxisProjection = GetDot(query.Start, origin, axisDirection, Vector3d.Zero);
 426772        Signed192 directionAxisProjection = GetDot(query.End, query.Start, axisDirection, Vector3d.Zero);
 426773        Signed192 maximumAxisHeight = exactUnitAxis
 426774            ? GetScaledRaw(heightRaw)
 426775            : GetAxisHeightProduct(axisLengthSquared, heightRaw);
 776        Signed192 startAxial;
 777        Signed192 axialVelocity;
 778        Signed192 maximumAxial;
 779        Signed192 radialScale;
 426780        if (exactUnitAxis)
 781        {
 386782            startAxial = centered
 386783                ? WideArithmetic.SubtractSigned192(GetHalfScaledRaw(heightRaw), startAxisProjection)
 386784                : startAxisProjection;
 386785            axialVelocity = centered
 386786                ? WideArithmetic.SubtractSigned192(default, directionAxisProjection)
 386787                : directionAxisProjection;
 386788            maximumAxial = maximumAxisHeight;
 386789            radialScale = One;
 790        }
 791        else
 792        {
 40793            Signed192 scaledStartAxisProjection = GetScaledRaw(startAxisProjection);
 40794            Signed192 scaledDirectionAxisProjection = GetScaledRaw(directionAxisProjection);
 40795            startAxial = centered
 40796                ? WideArithmetic.SubtractSigned192(maximumAxisHeight, WideArithmetic.Double(scaledStartAxisProjection))
 40797                : scaledStartAxisProjection;
 40798            axialVelocity = centered
 40799                ? WideArithmetic.SubtractSigned192(default, WideArithmetic.Double(scaledDirectionAxisProjection))
 40800                : scaledDirectionAxisProjection;
 40801            maximumAxial = centered
 40802                ? WideArithmetic.Double(maximumAxisHeight)
 40803                : maximumAxisHeight;
 40804            radialScale = centered ? Four : One;
 805        }
 806
 426807        Signed320 radialCoefficient = GetRadialTerm(
 426808            directionLengthSquared,
 426809            directionAxisProjection,
 426810            axisLengthSquared);
 426811        Signed320 radialProjection = GetRadialTerm(
 426812            startDirectionProjection,
 426813            startAxisProjection,
 426814            directionAxisProjection,
 426815            axisLengthSquared);
 426816        Signed320 radialConstant = GetRadialTerm(
 426817            startDistanceSquared,
 426818            startAxisProjection,
 426819            axisLengthSquared);
 426820        Signed320 heightSquared = WideArithmetic.MultiplySigned192(heightRaw, heightRaw);
 426821        Signed192 radiusRaw = Signed192.Signed(baseRadius.m_rawValue);
 426822        Signed320 radiusSquared = WideArithmetic.MultiplySigned192(radiusRaw, radiusRaw);
 426823        Signed320 axialVelocitySquared = WideArithmetic.MultiplySigned192(axialVelocity, axialVelocity);
 426824        Signed320 axialProduct = WideArithmetic.MultiplySigned192(startAxial, axialVelocity);
 426825        Signed320 startAxialSquared = WideArithmetic.MultiplySigned192(startAxial, startAxial);
 826
 426827        return new ConeData(
 426828            startAxial,
 426829            axialVelocity,
 426830            maximumAxial,
 426831            SubtractConeTerms(
 426832                heightSquared, radialCoefficient, axisLengthSquared, radialScale,
 426833                exactUnitAxis,
 426834                radiusSquared, axialVelocitySquared),
 426835            SubtractConeTerms(
 426836                heightSquared, radialProjection, axisLengthSquared, radialScale,
 426837                exactUnitAxis,
 426838                radiusSquared, axialProduct),
 426839            SubtractConeTerms(
 426840                heightSquared, radialConstant, axisLengthSquared, radialScale,
 426841                exactUnitAxis,
 426842                radiusSquared, startAxialSquared));
 843    }
 844
 845    private static Signed320 GetRadialTerm(
 846        Signed192 squaredLength,
 847        Signed192 axisProjection,
 848        Signed192 axisLengthSquared) =>
 871849        WideArithmetic.SubtractSigned320(
 871850            WideArithmetic.MultiplySigned192(squaredLength, axisLengthSquared),
 871851            WideArithmetic.MultiplySigned192(axisProjection, axisProjection));
 852
 853    private static Signed320 GetRadialTerm(
 854        Signed192 dot,
 855        Signed192 startAxisProjection,
 856        Signed192 directionAxisProjection,
 857        Signed192 axisLengthSquared) =>
 426858        WideArithmetic.SubtractSigned320(
 426859            WideArithmetic.MultiplySigned192(dot, axisLengthSquared),
 426860            WideArithmetic.MultiplySigned192(startAxisProjection, directionAxisProjection));
 861
 862    private static Signed576 SubtractConeTerms(
 863        Signed320 heightSquared,
 864        Signed320 radialTerm,
 865        Signed192 axisLengthSquared,
 866        Signed192 radialScale,
 867        bool exactUnitAxis,
 868        Signed320 radiusSquared,
 869        Signed320 axialTerm)
 870    {
 1297871        if (exactUnitAxis)
 872        {
 1172873            return WideArithmetic.SubtractSigned576(
 1172874                WideArithmetic.MultiplySigned320(heightSquared, radialTerm),
 1172875                WideArithmetic.MultiplySigned320(radiusSquared, axialTerm));
 876        }
 877
 125878        Signed576 radial = WideArithmetic.MultiplySigned576(
 125879            WideArithmetic.MultiplySigned576(
 125880                WideArithmetic.MultiplySigned320(heightSquared, radialTerm),
 125881                axisLengthSquared),
 125882            radialScale);
 125883        Signed576 axial = WideArithmetic.MultiplySigned320(radiusSquared, axialTerm);
 125884        return WideArithmetic.SubtractSigned576(radial, axial);
 885    }
 886
 887    private static Signed832 Evaluate(ConeData data, Signed192 numerator, Signed192 denominator)
 888    {
 889        // Rigid-frame coefficients have fewer than 390 magnitude bits after
 890        // their common quaternion-denominator factor is removed. Clipped
 891        // rational bounds have at most 132-bit magnitudes, so every homogenized
 892        // term and their sum fit below 656 bits. Signed832 also retains the
 893        // wider legacy conic intermediates without the former eleven-word
 894        // truncation.
 92632895        Signed320 numeratorSquared = WideArithmetic.MultiplySigned192(numerator, numerator);
 92632896        Signed320 numeratorDenominator = WideArithmetic.MultiplySigned192(numerator, denominator);
 92632897        Signed320 denominatorSquared = WideArithmetic.MultiplySigned192(denominator, denominator);
 92632898        Signed832 first = WideArithmetic.MultiplySigned576ToSigned832(data.Coefficient, numeratorSquared);
 92632899        Signed832 second = WideArithmetic.MultiplySigned576ToSigned832(data.Projection, numeratorDenominator);
 92632900        Signed832 third = WideArithmetic.MultiplySigned576ToSigned832(data.Constant, denominatorSquared);
 92632901        return WideArithmetic.AddSigned832(
 92632902            WideArithmetic.AddSigned832(first, WideArithmetic.AddSigned832(second, second)),
 92632903            third);
 904    }
 905
 906    private static Signed832 EvaluateDerivative(ConeData data, RationalBound bound) =>
 60513907        WideArithmetic.AddSigned832(
 60513908            WideArithmetic.MultiplySigned576ToSigned832(
 60513909                data.Coefficient,
 60513910                Signed320.ExtendValue(bound.Numerator)),
 60513911            WideArithmetic.MultiplySigned576ToSigned832(
 60513912                data.Projection,
 60513913                Signed320.ExtendValue(bound.Denominator)));
 914
 915    private static bool IsContained(
 916        Signed192 axial,
 917        Signed576 polynomial,
 918        Signed192 maximumAxial,
 919        bool strict) =>
 445920        IsContained(axial, polynomial.Sign, maximumAxial, strict);
 921
 922    private static bool IsContained(
 923        Signed192 axial,
 924        int polynomialSign,
 925        Signed192 maximumAxial,
 926        bool strict)
 927    {
 445928        int maximumSign = WideArithmetic.SubtractSigned192(axial, maximumAxial).Sign;
 445929        return strict
 445930            ? axial.Sign > 0 && maximumSign < 0 && polynomialSign < 0
 445931            : axial.Sign >= 0 && maximumSign <= 0 && polynomialSign <= 0;
 932    }
 933
 934    private static Signed192 GetScaledRaw(Signed192 value) =>
 512935        new((value.High << FixedMath.SHIFT_AMOUNT_I) | (value.Middle >> FixedMath.SHIFT_AMOUNT_I),
 512936            (value.Middle << FixedMath.SHIFT_AMOUNT_I) | (value.Low >> FixedMath.SHIFT_AMOUNT_I),
 512937            value.Low << FixedMath.SHIFT_AMOUNT_I);
 938
 939    private static Signed192 GetAxisHeightProduct(
 940        Signed192 axisLengthSquared,
 941        Signed192 heightRaw)
 942    {
 45943        Signed320 product = WideArithmetic.MultiplySigned192(axisLengthSquared, heightRaw);
 944        // IsNormalized bounds the positive axis square near 2^64; multiplying
 945        // by a positive Fixed64 raw height therefore occupies fewer than 129 bits.
 45946        return new Signed192(product.Word2, product.Word1, product.Word0);
 947    }
 948
 949    private static Signed192 GetHalfScaledRaw(Signed192 value)
 950    {
 27951        Signed192 scaled = GetScaledRaw(value);
 27952        ulong high = scaled.High;
 27953        ulong middle = scaled.Middle;
 27954        ulong low = scaled.Low;
 27955        WideArithmetic.ShiftRightOne(ref high, ref middle, ref low);
 27956        return new Signed192(high, middle, low);
 957    }
 958
 959    private static bool IsExactUnitAxis(Signed192 axisLengthSquared) =>
 445960        axisLengthSquared.High == AxisScaleSquared.High
 445961        && axisLengthSquared.Middle == AxisScaleSquared.Middle
 445962        && axisLengthSquared.Low == AxisScaleSquared.Low;
 963
 964    private static Signed192 SquareRaw(long raw)
 965    {
 11229966        ulong magnitude = (ulong)raw;
 11229967        Fixed64.Multiply64To128(magnitude, magnitude, out ulong high, out ulong low);
 11229968        return new Signed192(0UL, high, low);
 969    }
 970
 971    private static RationalBound Normalize(Signed192 numerator, Signed192 denominator)
 972    {
 582973        if (denominator.Sign >= 0)
 306974            return new RationalBound(numerator, denominator);
 975
 276976        return new RationalBound(
 276977            WideArithmetic.SubtractSigned192(default, numerator),
 276978            WideArithmetic.SubtractSigned192(default, denominator));
 979    }
 980
 981    private static int Compare(RationalBound left, RationalBound right) =>
 1380982        WideArithmetic.MultiplySubtract(
 1380983            left.Numerator,
 1380984            right.Denominator,
 1380985            right.Numerator,
 1380986            left.Denominator).Sign;
 987
 988    private static Signed192 GetDot(
 989        Vector3d leftEnd,
 990        Vector3d leftStart,
 991        Vector3d rightEnd,
 992        Vector3d rightStart) =>
 2613993        WideGeometry.GetDifferenceDotProduct3D(
 2613994            leftEnd.X, leftStart.X, leftEnd.Y, leftStart.Y, leftEnd.Z, leftStart.Z,
 2613995            rightEnd.X, rightStart.X, rightEnd.Y, rightStart.Y, rightEnd.Z, rightStart.Z);
 996
 997    internal static int EvaluateBoundedUnitPolynomialSign(
 998            Signed576 coefficient,
 999            Signed576 projection,
 1000            Signed576 constant,
 1001            Signed192 numerator,
 1002            Signed192 denominator) =>
 641003            Evaluate(
 641004                new ConeData(
 641005                    default,
 641006                    default,
 641007                    default,
 641008                    coefficient,
 641009                    projection,
 641010                    constant),
 641011                numerator,
 641012                denominator).Sign;
 1013
 1014    internal static int EvaluateBoundedUnitPolynomialDerivativeSign(
 1015        Signed576 coefficient,
 1016        Signed576 projection,
 1017        Signed192 numerator,
 1018        Signed192 denominator) =>
 641019        EvaluateDerivative(
 641020            new ConeData(
 641021                default,
 641022                default,
 641023                default,
 641024                coefficient,
 641025                projection,
 641026                default),
 641027            new RationalBound(numerator, denominator)).Sign;
 1028
 1029    internal static bool TrySolveBoundedUnitPolynomial(
 1030        Signed576 coefficient,
 1031        Signed576 projection,
 1032        Signed576 constant,
 1033        Signed192 lowerNumerator,
 1034        Signed192 lowerDenominator,
 1035        Signed192 upperNumerator,
 1036        Signed192 upperDenominator,
 1037        Fixed64 outputScale,
 1038        out Fixed64 entry,
 1039        out Fixed64 exit) =>
 3961040        TrySolveBoundedPolynomial(
 3961041            new ConeData(
 3961042                default,
 3961043                default,
 3961044                default,
 3961045                coefficient,
 3961046                projection,
 3961047                constant),
 3961048            new RationalBound(lowerNumerator, lowerDenominator),
 3961049            new RationalBound(upperNumerator, upperDenominator),
 3961050            outputScale,
 3961051            out entry,
 3961052            out exit);
 1053}

Methods/Properties

TrySolveBoundedUnitPolynomial(FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
GetBorrowedPolynomialSignAtRationalParameter(FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Signed832,FixedMathSharp.Signed832)
.cctor()
.ctor(FixedMathSharp.Signed192,FixedMathSharp.Signed192)
.ctor(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576)
NegatedPolynomial()
TryGetApexInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TrySolveUnitPolynomial(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetApexDistanceInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetCenteredInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetCenteredDistanceInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
ContainsPointInApexCone(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean)
ContainsPointInCenteredCone(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean)
ContainsPoint(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,System.Boolean,FixedMathSharp.Fixed64,System.Boolean)
TrySolve(FixedMathSharp.Geometry.WideFiniteConeIntersection/ConeData,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TrySolveBoundedPolynomial(FixedMathSharp.Geometry.WideFiniteConeIntersection/ConeData,FixedMathSharp.Geometry.WideFiniteConeIntersection/RationalBound,FixedMathSharp.Geometry.WideFiniteConeIntersection/RationalBound,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TrySolveBoundedUnitPolynomial(FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetCompactPolynomial(FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Geometry.WideFiniteConeIntersection/ConeData&)
NarrowCoefficient(FixedMathSharp.Signed832)
GetMagnitudeBitLength(FixedMathSharp.Signed832)
GetMagnitudeBitLength(FixedMathSharp.Signed320)
GetPolynomialSignAtRationalParameter(FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Signed320,FixedMathSharp.Signed320)
GetPolynomialSignAtRationalParameter(FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Signed832)
GetDerivativeSign(FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Signed320,FixedMathSharp.Signed320)
EvaluateWidePolynomialSign(FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Signed320,FixedMathSharp.Signed320,System.Boolean)
EvaluateWidePolynomialSign(FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Signed832,System.ReadOnlySpan`1<System.UInt64>,System.Int32,System.ReadOnlySpan`1<System.UInt64>,System.Int32,System.Boolean)
RoundRoot(FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Fixed64,System.Boolean)
RoundLinearRoot(FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Fixed64)
Round(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Fixed64)
RoundLinearRoot(FixedMathSharp.Geometry.WideFiniteConeIntersection/ConeData,FixedMathSharp.Fixed64)
RoundLowerRoot(FixedMathSharp.Geometry.WideFiniteConeIntersection/ConeData,FixedMathSharp.Signed576,FixedMathSharp.Signed192)
RoundUpperRoot(FixedMathSharp.Geometry.WideFiniteConeIntersection/ConeData,FixedMathSharp.Signed576,FixedMathSharp.Signed192)
TryGetAxialInterval(FixedMathSharp.Geometry.WideFiniteConeIntersection/ConeData,FixedMathSharp.Geometry.WideFiniteConeIntersection/RationalBound&,FixedMathSharp.Geometry.WideFiniteConeIntersection/RationalBound&)
CreateApexData(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
CreateCenteredData(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
CreateData(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Signed192,System.Boolean,FixedMathSharp.Fixed64)
GetRadialTerm(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
GetRadialTerm(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
SubtractConeTerms(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed192,FixedMathSharp.Signed192,System.Boolean,FixedMathSharp.Signed320,FixedMathSharp.Signed320)
Evaluate(FixedMathSharp.Geometry.WideFiniteConeIntersection/ConeData,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
EvaluateDerivative(FixedMathSharp.Geometry.WideFiniteConeIntersection/ConeData,FixedMathSharp.Geometry.WideFiniteConeIntersection/RationalBound)
IsContained(FixedMathSharp.Signed192,FixedMathSharp.Signed576,FixedMathSharp.Signed192,System.Boolean)
IsContained(FixedMathSharp.Signed192,System.Int32,FixedMathSharp.Signed192,System.Boolean)
GetScaledRaw(FixedMathSharp.Signed192)
GetAxisHeightProduct(FixedMathSharp.Signed192,FixedMathSharp.Signed192)
GetHalfScaledRaw(FixedMathSharp.Signed192)
IsExactUnitAxis(FixedMathSharp.Signed192)
SquareRaw(System.Int64)
Normalize(FixedMathSharp.Signed192,FixedMathSharp.Signed192)
Compare(FixedMathSharp.Geometry.WideFiniteConeIntersection/RationalBound,FixedMathSharp.Geometry.WideFiniteConeIntersection/RationalBound)
GetDot(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
EvaluateBoundedUnitPolynomialSign(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
EvaluateBoundedUnitPolynomialDerivativeSign(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
TrySolveBoundedUnitPolynomial(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)