< Summary

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

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_Root()100%11100%
Coordinate(...)100%11100%
get_Denominator()100%11100%
.ctor(...)100%11100%
TryGetFirstSegmentPoint(...)100%44100%
SetSegmentPoint(...)100%22100%
TryGetSegmentParameter(...)100%1414100%
CompareLexicographic(...)100%44100%
ComparePositions(...)100%44100%
CopyTo(...)100%22100%
TryGetFirstSegmentPoint(...)100%44100%
TryGetFirstSegmentPoint(...)100%11100%
TryGetFirstSegmentPoint(...)100%44100%

File(s)

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

#LineLine coverage
 1//=======================================================================
 2// FiniteSectionPoint.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 exact homogeneous coordinates and shared radicand of a finite section point.</summary>
 13internal readonly ref struct FiniteSectionPoint
 14{
 15    internal const int Words = 10, RootWords = 17, StorageWords = 8 * Words + RootWords;
 16    internal const int AffineWords = 13, AffineRootWords = 23;
 17    internal const int SignCount = 8;
 18    internal readonly Span<ulong> Values;
 19    internal readonly Span<int> Signs;
 20    private readonly int _fieldWords;
 17021    internal Span<ulong> Root => Values[(8 * _fieldWords)..];
 32122    internal ContactQuadratic Coordinate(int axis) => ContactQuadratic.At(Values, Signs, axis, _fieldWords);
 17923    internal ContactQuadratic Denominator => ContactQuadratic.At(Values, Signs, 3, _fieldWords);
 24
 25    internal FiniteSectionPoint(Span<ulong> values, Span<int> signs,
 26        int fieldWords = Words, int rootWords = RootWords)
 27    {
 9828        Values = values[..(8 * fieldWords + rootWords)]; Signs = signs[..SignCount];
 4929        _fieldWords = fieldWords;
 4930    }
 31
 32    /// <summary>Retains the lexicographically first point of a closed segment/cone section.</summary>
 33    internal static bool TryGetFirstSegmentPoint(FixedSegment segment,
 34        in ConeFiniteSectionFrame frame, FiniteSectionPoint result)
 35    {
 3636        result.Values.Clear(); result.Signs.Clear();
 1837        if (ComparePositions(segment.Start, segment.End) > 0)
 338            segment = new FixedSegment(segment.End, segment.Start);
 1839        int words = result._fieldWords;
 1840        Span<ulong> work = stackalloc ulong[4 * words];
 1841        Span<int> signs = stackalloc int[4];
 1842        ContactQuadratic parameter = ContactQuadratic.At(work, signs, 0, words);
 1843        ContactQuadratic term = ContactQuadratic.At(work, signs, 1, words);
 1844        ContactQuadratic denominator = result.Denominator;
 1845        if (!TryGetSegmentParameter(segment, frame, false, parameter, denominator, result.Root))
 146            return false;
 1747        SetSegmentPoint(segment, parameter, denominator, term, result);
 1748        return true;
 49    }
 50
 51    private static void SetSegmentPoint(FixedSegment segment, ContactQuadratic parameter,
 52        ContactQuadratic denominator, ContactQuadratic term, FiniteSectionPoint result)
 53    {
 54        // The cone frame bounds A/B/C below 528 bits, so a parameter
 55        // numerator/denominator fits 529 bits and its discriminant 1057 bits.
 56        // Authored raw endpoint differences are below 65 bits; the complete
 57        // point coefficients fit 595 bits (ten limbs), root fits seventeen.
 24058        for (int axis = 0; axis < 3; axis++)
 59        {
 9060            Signed192 first = Signed192.Raw(segment.Start[axis]);
 9061            Signed192 difference = WideArithmetic.SubtractSigned192(Signed192.Raw(segment.End[axis]), first);
 9062            ContactQuadratic coordinate = result.Coordinate(axis);
 9063            ContactQuadratic.Scale(denominator, Signed576.ExtendValue(Signed320.ExtendValue(first)), coordinate);
 9064            ContactQuadratic.Scale(parameter, Signed576.ExtendValue(Signed320.ExtendValue(difference)), term);
 9065            coordinate.Add(term);
 66        }
 3067    }
 68
 69    /// <summary>Retains a closed cone-section endpoint in the input segment's exact parameter order.</summary>
 70    /// <remarks>
 71    /// Numerator/denominator coefficients need 529 bits and root needs 1057
 72    /// bits. A non-dyadic or irrational endpoint remains admitted without ever
 73    /// materializing t; callers may form paired coordinates in this same field.
 74    /// </remarks>
 75    internal static bool TryGetSegmentParameter(FixedSegment segment, in ConeFiniteSectionFrame frame,
 76        bool upper, ContactQuadratic numerator, ContactQuadratic denominator, Span<ulong> root)
 77    {
 1234278        numerator.Clear(); denominator.Clear(); root.Clear();
 822879        WideAxis3 start = frame.Transform(segment.Start), end = frame.Transform(segment.End);
 411780        if (!frame.IntersectsTransformedSegment(start, end)) return false;
 411181        WideAxis3 delta = new(WideArithmetic.SubtractSigned320(end.X, start.X),
 411182            WideArithmetic.SubtractSigned320(end.Y, start.Y), WideArithmetic.SubtractSigned320(end.Z, start.Z));
 411183        bool axial = frame.TryGetAxialInterval(start.Y, delta.Y, out Signed320 lowerN, out Signed320 lowerD,
 411184            out Signed320 upperN, out Signed320 upperD);
 85        System.Diagnostics.Debug.Assert(axial);
 822286        Signed320 clipN = upper ? upperN : lowerN, clipD = upper ? upperD : lowerD;
 822287        Signed832 a = frame.QuadraticProductWide(delta, delta), b = frame.QuadraticProductWide(start, delta),
 411188            c = frame.QuadraticProductWide(start, start);
 411189        if (WideFiniteConeIntersection.GetPolynomialSignAtRationalParameter(a, b, c, clipN, clipD) <= 0)
 90        {
 781691            numerator.Set(Signed576.ExtendValue(clipN)); denominator.Set(Signed576.ExtendValue(clipD));
 390892            return true;
 93        }
 20394        int words = numerator.FieldWords;
 20395        Span<ulong> work = stackalloc ulong[6 * words];
 20396        Span<int> signs = stackalloc int[6];
 40697        ContactQuadratic qa = ContactQuadratic.At(work, signs, 0, words), qb = ContactQuadratic.At(work, signs, 1, words
 20398        ContactQuadratic qc = ContactQuadratic.At(work, signs, 2, words);
 60999        qa.Set(a); qb.Set(b); qc.Set(c);
 100        // For A>0 the admitted interval is between the roots; for A<0 it
 101        // lies outside them. Finite axial clipping excludes the opposite
 102        // nappe. The linear and repeated-root chart has only branch +1.
 203103        int branch = a.Sign == 0 ? 1 : (upper ? 1 : -1) * a.Sign;
 203104        bool found = ContactQuadratic.TryGetParameter(qa, qb, qc, branch, root, numerator, denominator);
 203105        if (!found)
 19106            found = ContactQuadratic.TryGetParameter(qa, qb, qc, 1, root, numerator, denominator);
 107        System.Diagnostics.Debug.Assert(found);
 203108        return true;
 109    }
 110
 111    internal static int CompareLexicographic(FiniteSectionPoint first, FiniteSectionPoint second)
 112    {
 94113        for (int axis = 0; axis < 3; axis++)
 114        {
 37115            int comparison = ContactQuadratic.CompareRatios(first.Coordinate(axis), first.Denominator, first.Root,
 37116                second.Coordinate(axis), second.Denominator, second.Root);
 37117            if (comparison != 0)
 4118                return comparison;
 119        }
 10120        return 0;
 121    }
 122
 123    private static int ComparePositions(Vector3d first, Vector3d second)
 124    {
 38125        int comparison = first.X.CompareTo(second.X);
 65126        if (comparison != 0) return comparison;
 11127        comparison = first.Y.CompareTo(second.Y);
 11128        return comparison != 0 ? comparison : first.Z.CompareTo(second.Z);
 129    }
 130
 131    internal void CopyTo(FiniteSectionPoint destination)
 132    {
 133        // The caller proves the complete active fields fit. Different packed
 134        // layouts must not overlap; equal-layout self-copy remains valid.
 50135        for (int coordinate = 0; coordinate < 4; coordinate++)
 20136            Coordinate(coordinate).CopyTo(destination.Coordinate(coordinate));
 5137        int activeRoot = WideArithmetic.GetActiveMagnitudeLength(Root);
 5138        Root[..activeRoot].CopyTo(destination.Root);
 5139        destination.Root[activeRoot..].Clear();
 5140    }
 141
 142    internal static bool TryGetFirstSegmentPoint(FixedSegment segment,
 143        in CapsuleFiniteSectionFrame frame, FiniteSectionPoint result)
 144    {
 32145        result.Values.Clear(); result.Signs.Clear();
 16146        if (ComparePositions(segment.Start, segment.End) > 0)
 3147            segment = new FixedSegment(segment.End, segment.Start);
 16148        int words = result._fieldWords;
 16149        Span<ulong> work = stackalloc ulong[4 * words];
 16150        Span<int> signs = stackalloc int[4];
 16151        ContactQuadratic parameter = ContactQuadratic.At(work, signs, 0, words);
 16152        ContactQuadratic term = ContactQuadratic.At(work, signs, 1, words);
 22153        if (!frame.TryGetFirstSegmentParameter(segment, parameter, result.Denominator, result.Root)) return false;
 154        // Capsule coefficients <400 bits need <466 bits after authored
 155        // endpoint multiplication, within the existing cone-sized bank.
 10156        SetSegmentPoint(segment, parameter, result.Denominator, term, result);
 10157        return true;
 158    }
 159
 160    internal static bool TryGetFirstSegmentPoint(FixedSegment segment,
 161        in FiniteSlabSectionFrame frame, FiniteSectionPoint result)
 4162        => TryGetFirstSegmentPoint(segment, frame, ReadOnlySpan<Vector2d>.Empty, result);
 163
 164    internal static bool TryGetFirstSegmentPoint(FixedSegment segment,
 165        in FiniteSlabSectionFrame frame, ReadOnlySpan<Vector2d> prismOffsets, FiniteSectionPoint result)
 166    {
 8167        result.Values.Clear(); result.Signs.Clear();
 4168        if (ComparePositions(segment.Start, segment.End) > 0)
 1169            segment = new FixedSegment(segment.End, segment.Start);
 4170        int words = result._fieldWords;
 8171        Span<ulong> work = stackalloc ulong[4 * words]; Span<int> signs = stackalloc int[4];
 4172        ContactQuadratic parameter = ContactQuadratic.At(work, signs, 0, words);
 4173        ContactQuadratic term = ContactQuadratic.At(work, signs, 1, words);
 5174        if (!frame.TryGetFirstSegmentParameter(segment, prismOffsets, parameter, result.Denominator, result.Root)) retur
 3175        SetSegmentPoint(segment, parameter, result.Denominator, term, result);
 3176        return true;
 177    }
 178}

Methods/Properties

get_Root()
Coordinate(System.Int32)
get_Denominator()
.ctor(System.Span`1<System.UInt64>,System.Span`1<System.Int32>,System.Int32,System.Int32)
TryGetFirstSegmentPoint(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Geometry.ConeFiniteSectionFrame&,FixedMathSharp.Geometry.FiniteSectionPoint)
SetSegmentPoint(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.FiniteSectionPoint)
TryGetSegmentParameter(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Geometry.ConeFiniteSectionFrame&,System.Boolean,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,System.Span`1<System.UInt64>)
CompareLexicographic(FixedMathSharp.Geometry.FiniteSectionPoint,FixedMathSharp.Geometry.FiniteSectionPoint)
ComparePositions(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
CopyTo(FixedMathSharp.Geometry.FiniteSectionPoint)
TryGetFirstSegmentPoint(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Geometry.CapsuleFiniteSectionFrame&,FixedMathSharp.Geometry.FiniteSectionPoint)
TryGetFirstSegmentPoint(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Geometry.FiniteSlabSectionFrame&,FixedMathSharp.Geometry.FiniteSectionPoint)
TryGetFirstSegmentPoint(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Geometry.FiniteSlabSectionFrame&,System.ReadOnlySpan`1<FixedMathSharp.Vector2d>,FixedMathSharp.Geometry.FiniteSectionPoint)