< Summary

Information
Class: FixedMathSharp.Geometry.TriangleQuadraticSlice
Assembly: FixedMathSharp
File(s): /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Triangles/TriangleQuadraticSlice.cs
Line coverage
100%
Covered lines: 91
Uncovered lines: 0
Coverable lines: 91
Total lines: 157
Line coverage: 100%
Branch coverage
100%
Covered branches: 42
Total branches: 42
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
TryGetWeights(...)100%2626100%
SumWeights(...)100%22100%
SumWeighted(...)100%22100%
RoundTriangleCoordinate(...)100%88100%
Sum(...)100%22100%
Sum(...)100%22100%

File(s)

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Triangles/TriangleQuadraticSlice.cs

#LineLine coverage
 1//=======================================================================
 2// TriangleQuadraticSlice.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024-present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using System;
 9using static FixedMathSharp.Geometry.CylinderContactAlgebra;
 10using static FixedMathSharp.Geometry.ContactQuadratic;
 11
 12namespace FixedMathSharp.Geometry;
 13
 14/// <summary>Exact triangle-feature plane slicing and closed quadratic interval admission.</summary>
 15internal static class TriangleQuadraticSlice
 16{
 17    /// <summary>
 18    /// Slices the selected feature by one exact plane, then admits its free
 19    /// interval coordinate. Quadratic weights retain A+B*sqrt(K) throughout;
 20    /// no intersection parameter or support point rounds before projection.
 21    /// </summary>
 22    internal static bool TryGetWeights(int mask, Span<ulong> distances, Span<int> distanceSigns,
 23        Span<ulong> projections, Span<int> projectionSigns, ContactQuadratic bound, ReadOnlySpan<ulong> root,
 24        Span<ulong> weights, Span<int> weightSigns, out bool centered)
 25    {
 18626        int Words = bound.FieldWords;
 18627        centered = false;
 18628        Span<int> planeSigns = stackalloc int[3];
 18629        Span<ulong> candidates = stackalloc ulong[12 * Words];
 18630        Span<int> candidateSigns = stackalloc int[12];
 37231        candidates.Clear(); candidateSigns.Clear();
 18632        int count = 0;
 148833        for (int vertex = 0; vertex < 3; vertex++)
 34        {
 55835            planeSigns[vertex] = At(distances, distanceSigns, vertex, distances.Length / distanceSigns.Length).Sign(root
 55836            if ((mask & (1 << vertex)) != 0 && planeSigns[vertex] == 0)
 2537                At(candidates, candidateSigns, 3 * count++ + vertex, candidates.Length / candidateSigns.Length).Set(Sign
 38        }
 148839        for (int edge = 0; edge < 3; edge++)
 40        {
 55841            int next = (edge + 1) % 3;
 55842            if ((mask & (1 << edge)) == 0 || (mask & (1 << next)) == 0
 55843                || planeSigns[edge] * planeSigns[next] >= 0)
 44                continue;
 21945            At(distances, distanceSigns, next, distances.Length / distanceSigns.Length).CopyTo(At(candidates, candidateS
 21946            At(distances, distanceSigns, edge, distances.Length / distanceSigns.Length).CopyTo(At(candidates, candidateS
 21947            count++;
 48        }
 49        System.Diagnostics.Debug.Assert(count <= 2);
 18650        Span<ulong> values = stackalloc ulong[12 * Words];
 18651        Span<int> valueSigns = stackalloc int[12];
 37252        ContactQuadratic denominator = At(values, valueSigns, 0, values.Length / valueSigns.Length), limit = At(values, 
 55853        ContactQuadratic comparison = At(values, valueSigns, 2, values.Length / valueSigns.Length), first = At(values, v
 18654        Span<int> endpointSigns = stackalloc int[2];
 52255        for (int index = 0; index < count; index++)
 56        {
 23157            Span<ulong> candidate = candidates.Slice(index * 6 * Words, 6 * Words);
 23158            Span<int> signs = candidateSigns.Slice(index * 6, 6);
 23159            SumWeights(candidate, signs, denominator);
 23160            ContactQuadratic projection = At(values, valueSigns, 4 + index, values.Length / valueSigns.Length);
 23161            SumWeighted(projections, projectionSigns, candidate, signs, root, projection);
 23162            endpointSigns[index] = projection.Sign(root);
 23163            Multiply(denominator, bound, root, limit);
 46264            projection.CopyTo(comparison); comparison.Add(limit, -1);
 23165            if (comparison.Sign(root) > 0)
 66                continue;
 36867            projection.CopyTo(comparison); comparison.Add(limit);
 18468            if (comparison.Sign(root) < 0)
 69                continue;
 31270            candidate.CopyTo(weights); signs.CopyTo(weightSigns);
 15671            return true;
 72        }
 3073        if (count != 2 || endpointSigns[0] * endpointSigns[1] >= 0)
 2374            return false;
 75        // Neither endpoint is admitted, but they straddle the interval. A
 76        // direct blend at coordinate zero keeps one quadratic field and
 77        // avoids nested rounded ratios (or a growing clipping polygon).
 778        centered = true;
 779        ContactQuadratic product = At(values, valueSigns, 3, values.Length / valueSigns.Length);
 5680        for (int vertex = 0; vertex < 3; vertex++)
 81        {
 2182            ContactQuadratic result = At(weights, weightSigns, vertex, weights.Length / weightSigns.Length);
 2183            Multiply(At(candidates, candidateSigns, vertex, candidates.Length / candidateSigns.Length), second, root, re
 2184            result.MultiplySign(endpointSigns[1]);
 2185            Multiply(At(candidates, candidateSigns, vertex + 3, candidates.Length / candidateSigns.Length), first, root,
 2186            result.Add(product, endpointSigns[0]);
 87        }
 788        return true;
 89    }
 90
 91    internal static void SumWeights(Span<ulong> weights, Span<int> signs, ContactQuadratic result)
 92    {
 50093        result.Clear();
 400094        for (int vertex = 0; vertex < 3; vertex++)
 150095            result.Add(At(weights, signs, vertex, weights.Length / signs.Length));
 50096    }
 97
 98    internal static void SumWeighted(Span<ulong> coordinates, Span<int> coordinateSigns,
 99        Span<ulong> weights, Span<int> weightSigns, ReadOnlySpan<ulong> root, ContactQuadratic result)
 100    {
 269101        int Words = result.FieldWords;
 269102        Span<ulong> work = stackalloc ulong[2 * Words];
 269103        Span<int> signs = stackalloc int[2];
 269104        ContactQuadratic product = At(work, signs, 0, work.Length / signs.Length);
 269105        result.Clear();
 2152106        for (int vertex = 0; vertex < 3; vertex++)
 107        {
 807108            Multiply(At(coordinates, coordinateSigns, vertex, coordinates.Length / coordinateSigns.Length), At(weights, 
 807109            result.Add(product);
 110        }
 269111    }
 112    internal static Fixed64 RoundTriangleCoordinate(in TriangleCircularGeometry geometry, FixedTriangle triangle, int co
 113        Span<ulong> weights, Span<int> signs, ContactQuadratic denominator, ReadOnlySpan<ulong> root)
 114    {
 714115        int Words = denominator.FieldWords;
 714116        Span<Signed576> coordinates = stackalloc Signed576[3];
 5712117        for (int vertex = 0; vertex < 3; vertex++)
 2142118            coordinates[vertex] = geometry.WitnessCoordinate(triangle, vertex, component);
 714119        Span<ulong> values = stackalloc ulong[(geometry.IsAffine ? 4 : 2) * Words];
 714120        Span<int> valueSigns = stackalloc int[geometry.IsAffine ? 4 : 2];
 714121        ContactQuadratic numerator = At(values, valueSigns, 0, values.Length / valueSigns.Length);
 714122        Sum(coordinates, weights, signs, numerator);
 1203123        if (!geometry.IsAffine) return RoundRatio(numerator, denominator, root);
 225124        ContactQuadratic scaledDenominator = At(values, valueSigns, 1, values.Length / valueSigns.Length);
 225125        Scale(denominator, Signed576.ExtendValue(geometry.RawScale), scaledDenominator);
 225126        return RoundRatio(numerator, scaledDenominator, root);
 127    }
 128
 129    internal static void Sum(ReadOnlySpan<Signed832> coordinates, Span<ulong> weights, Span<int> signs, ContactQuadratic
 130    {
 545131        int Words = result.FieldWords;
 545132        Span<ulong> values = stackalloc ulong[2 * Words];
 545133        Span<int> productSigns = stackalloc int[2];
 545134        ContactQuadratic product = At(values, productSigns, 0, values.Length / productSigns.Length);
 545135        result.Clear();
 4360136        for (int vertex = 0; vertex < 3; vertex++)
 137        {
 1635138            Scale(At(weights, signs, vertex, weights.Length / signs.Length), coordinates[vertex], product);
 1635139            result.Add(product);
 140        }
 545141    }
 142
 143    internal static void Sum(ReadOnlySpan<Signed576> coordinates, Span<ulong> weights, Span<int> signs, ContactQuadratic
 144    {
 714145        int Words = result.FieldWords;
 714146        Span<ulong> values = stackalloc ulong[2 * Words];
 714147        Span<int> productSigns = stackalloc int[2];
 714148        ContactQuadratic product = At(values, productSigns, 0, values.Length / productSigns.Length);
 714149        result.Clear();
 5712150        for (int vertex = 0; vertex < 3; vertex++)
 151        {
 2142152            Scale(At(weights, signs, vertex, weights.Length / signs.Length), coordinates[vertex], product);
 2142153            result.Add(product);
 154        }
 714155    }
 156
 157}