< Summary

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

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
KeepAll(...)100%1616100%
Keep(...)100%66100%
Dot(...)100%11100%
Component(...)100%11100%
Write(...)100%11100%

File(s)

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

#LineLine coverage
 1//=======================================================================
 2// TriangleConeGeneratorFeatures.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>The exact fixed-latitude generator normal circle and its triangle fan.</summary>
 15internal static class TriangleConeGeneratorFeatures
 16{
 17    internal static void KeepAll(in TriangleCircularGeometry geometry, Fixed64 height, Fixed64 radius,
 18        ref TriangleConeContactSelection selection)
 19    {
 8820        Span<ulong> values = stackalloc ulong[ConvexContactCandidate.Slots * Words];
 8821        Span<int> signs = stackalloc int[ConvexContactCandidate.Slots];
 8822        Span<ulong> work = stackalloc ulong[7 * Words];
 26423        Span<ulong> hSquared = Slot(work, 0), rSquared = Slot(work, 1), length = Slot(work, 2);
 17624        Span<ulong> metric = Slot(work, 3), product = Slot(work, 4);
 17625        Signed192 h = Signed192.Raw(height), r = Signed192.Raw(radius);
 8826        Import(WideArithmetic.MultiplySigned192(h, h), hSquared);
 8827        Import(WideArithmetic.MultiplySigned192(r, r), rSquared);
 8828        WideArithmetic.AddEqualMagnitudes(hSquared, rSquared, length);
 29        // All generator directions share the raw-coordinate scale. Include
 30        // its square once in the length factor used by every gap denominator.
 8831        Import(Signed576.ExtendValue(geometry.RawScale), product);
 8832        WideArithmetic.MultiplyMagnitudes(product, product, Slot(work, 6));
 8833        WideArithmetic.MultiplyMagnitudes(length, Slot(work, 6), product);
 8834        product.CopyTo(length);
 17635        values.Clear(); signs.Clear();
 8836        Write(values, signs, 0, Signed832.ExtendValue(Signed576.ExtendValue(h)));
 8837        Write(values, signs, 1, Signed832.ExtendValue(Signed576.ExtendValue(WideArithmetic.SubtractSigned192(default, r)
 38        // A zero-radial vertex can own the whole constant support circle.
 8839        Keep(geometry, values, signs, length, ref selection);
 69040        for (int vertex = 0; vertex < 3 && !selection.Separated; vertex++)
 41        {
 25742            WideDirection3d p = geometry.Vertex(vertex);
 25743            Signed832 radial = CircularRimContactAlgebra.RadialDot(p, p);
 25744            if (radial.Sign != 0)
 45            {
 49846                values.Clear(); signs.Clear();
 24947                Write(values, signs, 0, Signed832.ExtendValue(WideArithmetic.MultiplySigned576(p.X, h)), -1);
 24948                Write(values, signs, 2, Signed832.ExtendValue(WideArithmetic.MultiplySigned576(p.Z, h)), -1);
 24949                Write(values, signs, 4, Signed832.ExtendValue(Signed576.ExtendValue(r)), -1);
 24950                Import(radial, Slot(values, 6));
 24951                WideArithmetic.MultiplyMagnitudes(Slot(values, 6), length, metric);
 149452                for (int orientation = -1; orientation <= 1; orientation += 2)
 53                {
 49854                    Keep(geometry, values, signs, metric, ref selection);
 99655                    signs[0] = -signs[0]; signs[2] = -signs[2];
 56                }
 57            }
 25758            WideDirection3d e = geometry.Edge(vertex);
 25759            Signed832 eSquared = CircularRimContactAlgebra.RadialDot(e, e);
 25760            if (eSquared.Sign == 0)
 61                continue;
 50662            values.Clear(); signs.Clear();
 25363            Import(eSquared, metric);
 25364            WideArithmetic.MultiplyMagnitudes(metric, hSquared, Slot(values, 6));
 25365            Import(WideArithmetic.MultiplySigned576(e.Y, e.Y), product);
 25366            WideArithmetic.MultiplyMagnitudes(product, rSquared, Slot(work, 5));
 25367            int discriminantSign = 1;
 25368            Add(Slot(work, 5), -1, Slot(values, 6), ref discriminantSign);
 25369            if (discriminantSign < 0)
 70                continue;
 20671            Write(values, signs, 0, WideArithmetic.MultiplySigned832(WideArithmetic.MultiplySigned576(e.Y, e.X), Signed1
 20672            Write(values, signs, 1, WideArithmetic.MultiplySigned832(eSquared, Signed192.Raw(radius)), -1);
 20673            Write(values, signs, 2, WideArithmetic.MultiplySigned832(WideArithmetic.MultiplySigned576(e.Y, e.Z), Signed1
 20674            Write(values, signs, 3, Signed832.ExtendValue(e.Z), -1);
 20675            Write(values, signs, 5, Signed832.ExtendValue(e.X));
 20676            WideArithmetic.MultiplyMagnitudes(metric, metric, product);
 20677            WideArithmetic.MultiplyMagnitudes(product, length, metric);
 20678            Keep(geometry, values, signs, metric, ref selection);
 20679            if (discriminantSign != 0 && !selection.Separated)
 80            {
 81                // Selection preserves the local input: the other quadratic
 82                // branch changes only the two radial radical signs.
 39683                signs[3] = -signs[3]; signs[5] = -signs[5];
 19884                Keep(geometry, values, signs, metric, ref selection);
 85            }
 86        }
 8887    }
 88
 89    internal static void Keep(in TriangleCircularGeometry geometry, scoped Span<ulong> values, scoped Span<int> signs,
 90        scoped ReadOnlySpan<ulong> denominator, ref TriangleConeContactSelection selection)
 91    {
 99592        Span<ulong> work = stackalloc ulong[6 * Words];
 99593        Span<int> workSigns = stackalloc int[6];
 298594        ContactQuadratic maximum = At(work, workSigns, 0), current = At(work, workSigns, 1), difference = At(work, workS
 99595        ReadOnlySpan<ulong> root = Slot(values, 6);
 99596        Dot(geometry.A, values, signs, maximum);
 99597        int mask = 1;
 597098        for (int vertex = 1; vertex < 3; vertex++)
 99        {
 1990100            Dot(geometry.Vertex(vertex), values, signs, current);
 3980101            current.CopyTo(difference); difference.Add(maximum, -1);
 1990102            int comparison = difference.Sign(root);
 3318103            if (comparison > 0) { current.CopyTo(maximum); mask = 1 << vertex; }
 1675104            else if (comparison == 0) mask |= 1 << vertex;
 105        }
 995106        Component(values, signs, 1, current);
 995107        Scale(current, Signed832.ExtendValue(geometry.HalfHeight), difference);
 995108        maximum.Add(difference, -1);
 995109        int gapSign = BuildQuadraticCandidate(maximum, root, denominator, values, signs);
 995110        selection.Keep(values, signs, gapSign, mask, TriangleConeContactSelection.Generator);
 995111    }
 112
 113    internal static void Dot(in WideDirection3d axis, ReadOnlySpan<ulong> normal, ReadOnlySpan<int> signs, ContactQuadra
 114    {
 2985115        CylinderContactAlgebra.Dot(axis, normal[..(3 * Words)], signs[..3], result.Rational, out int rationalSign);
 2985116        CylinderContactAlgebra.Dot(axis, normal.Slice(3 * Words, 3 * Words), signs.Slice(3, 3), result.Radical, out int 
 5970117        result.Signs[0] = rationalSign; result.Signs[1] = radicalSign;
 2985118    }
 119
 120    internal static void Component(ReadOnlySpan<ulong> normal, ReadOnlySpan<int> signs, int component, ContactQuadratic 
 121    {
 3110122        Slot(normal, component).CopyTo(result.Rational); Slot(normal, component + 3).CopyTo(result.Radical);
 3110123        result.Signs[0] = signs[component]; result.Signs[1] = signs[component + 3];
 1555124    }
 125
 126    private static void Write(Span<ulong> values, Span<int> signs, int slot, Signed832 value, int orientation = 1)
 127    {
 3906128        Import(value, Slot(values, slot)); signs[slot] = orientation * value.Sign;
 1953129    }
 130}