< Summary

Information
Class: FixedMathSharp.Geometry.CylinderEdgeContactPolynomial
Assembly: FixedMathSharp
File(s): /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Convex/CylinderEdgeContactPolynomial.cs
Line coverage
100%
Covered lines: 73
Uncovered lines: 0
Coverable lines: 73
Total lines: 133
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
Build(...)100%11100%
BuildStationary(...)100%11100%
CompleteGap(...)100%11100%
Term(...)100%11100%
Multiply(...)100%11100%
Add(...)100%11100%

File(s)

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Convex/CylinderEdgeContactPolynomial.cs

#LineLine coverage
 1//=======================================================================
 2// CylinderEdgeContactPolynomial.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>The shared stationary quartic on a cylinder's edge-normal chart.</summary>
 13internal static class CylinderEdgeContactPolynomial
 14{
 15    internal const int Slots = 26;
 16
 17    /// <summary>
 18    /// For g=(P+sqrt(Q))/(scale*sqrt(M)), writes W=L²-K²Q,
 19    /// Q,K,L,J=PK-L,N=J²,D=scale²K²M into slots 0,5,8,10,13,16,21.
 20    /// K=2P'M-PM' and L=Q'M-QM'. M is a positive quadratic metric.
 21    /// Root admission must retain L=-K sqrt(Q), cap and polytope cones.
 22    /// All buffers are disjoint, and each coefficient must fit its supplied word stride.
 23    /// </summary>
 24    internal static void Build(ReadOnlySpan<ulong> p, ReadOnlySpan<sbyte> ps,
 25        ReadOnlySpan<ulong> q, ReadOnlySpan<sbyte> qs,
 26        ReadOnlySpan<ulong> metric, ReadOnlySpan<sbyte> ms,
 27        ReadOnlySpan<ulong> scale, Span<ulong> data, Span<sbyte> signs)
 28    {
 1516629        BuildStationary(p, ps, q, qs, metric, ms, scale, data, signs);
 1516630        CompleteGap(data, signs);
 1516631    }
 32
 33    /// <summary>
 34    /// Builds W,Q,K,L for root isolation/admission. Slots 13..14 borrow P,
 35    /// 16..18 borrow M, 19 borrows scale, and 21..23 borrow K squared until
 36    /// completion replaces 13..25 by J,N,D. Call CompleteGap at most once.
 37    /// </summary>
 38    internal static void BuildStationary(ReadOnlySpan<ulong> p, ReadOnlySpan<sbyte> ps,
 39        ReadOnlySpan<ulong> q, ReadOnlySpan<sbyte> qs,
 40        ReadOnlySpan<ulong> metric, ReadOnlySpan<sbyte> ms,
 41        ReadOnlySpan<ulong> scale, Span<ulong> data, Span<sbyte> signs)
 42    {
 1611343        int words = data.Length / signs.Length;
 3222644        data.Clear(); signs.Clear();
 3222645        q.CopyTo(data.Slice(5 * words, 3 * words)); qs.CopyTo(signs.Slice(5, 3));
 1611346        Span<ulong> scratch = stackalloc ulong[9 * words];
 1611347        Span<sbyte> scratchSigns = stackalloc sbyte[8];
 3222648        scratch.Clear(); scratchSigns.Clear();
 1611349        Span<ulong> product = scratch.Slice(8 * words, words);
 3222650        Span<ulong> k = data.Slice(8 * words, 2 * words), l = data.Slice(10 * words, 3 * words);
 3222651        Span<sbyte> ks = signs.Slice(8, 2), ls = signs.Slice(10, 3);
 1611352        Term(p, ps, 1, metric, ms, 0, k, ks, 0, 2, product);
 1611353        Term(p, ps, 0, metric, ms, 1, k, ks, 0, -1, product);
 1611354        Term(p, ps, 1, metric, ms, 1, k, ks, 1, 1, product);
 1611355        Term(p, ps, 0, metric, ms, 2, k, ks, 1, -2, product);
 1611356        Term(q, qs, 1, metric, ms, 0, l, ls, 0, 1, product);
 1611357        Term(q, qs, 0, metric, ms, 1, l, ls, 0, -1, product);
 1611358        Term(q, qs, 2, metric, ms, 0, l, ls, 1, 2, product);
 1611359        Term(q, qs, 0, metric, ms, 2, l, ls, 1, -2, product);
 1611360        Term(q, qs, 2, metric, ms, 1, l, ls, 2, 1, product);
 1611361        Term(q, qs, 1, metric, ms, 2, l, ls, 2, -1, product);
 3222662        Span<ulong> kSquared = scratch[..(3 * words)], temporary = scratch.Slice(3 * words, 5 * words);
 3222663        Span<sbyte> kSquaredSigns = scratchSigns[..3], temporarySigns = scratchSigns.Slice(3, 5);
 1611364        Multiply(l, ls, l, ls, data[..(5 * words)], signs[..5], product);
 1611365        Multiply(k, ks, k, ks, kSquared, kSquaredSigns, product);
 1611366        Multiply(kSquared, kSquaredSigns, q, qs, temporary, temporarySigns, product);
 1611367        Add(temporary, temporarySigns, data[..(5 * words)], signs[..5], -1);
 1611368        p.CopyTo(data.Slice(13 * words, 2 * words));
 1611369        ps.CopyTo(signs.Slice(13, 2));
 1611370        metric.CopyTo(data.Slice(16 * words, 3 * words));
 1611371        ms.CopyTo(signs.Slice(16, 3));
 1611372        scale.CopyTo(data.Slice(19 * words, words));
 1611373        kSquared.CopyTo(data.Slice(21 * words, 3 * words));
 1611374        kSquaredSigns.CopyTo(signs.Slice(21, 3));
 1611375        WideFiniteAxisIntersection.NormalizeFiniteAxisPolynomialPowerOfTwo(data[..(5 * words)], signs[..5]);
 1611376    }
 77
 78    /// <summary>
 79    /// Completes J=PK-L, N=J squared and D=scale squared*K squared*M once.
 80    /// Scratch consumes staged P before J overwrites it; D is written before
 81    /// N so staged M/scale can share the future N slots.
 82    /// </summary>
 83    internal static void CompleteGap(Span<ulong> data, Span<sbyte> signs)
 84    {
 1551385        int words = data.Length / signs.Length;
 1551386        Span<ulong> scratch = stackalloc ulong[7 * words];
 1551387        Span<sbyte> scratchSigns = stackalloc sbyte[6];
 3102688        scratch.Clear(); scratchSigns.Clear();
 3102689        Span<ulong> temporary = scratch[..(5 * words)], scaleSquared = scratch.Slice(5 * words, words);
 3102690        Span<sbyte> temporarySigns = scratchSigns[..5], scaleSquaredSigns = scratchSigns.Slice(5, 1);
 1551391        Span<ulong> product = scratch.Slice(6 * words, words);
 1551392        Multiply(data.Slice(13 * words, 2 * words), signs.Slice(13, 2),
 1551393            data.Slice(8 * words, 2 * words), signs.Slice(8, 2),
 1551394            temporary[..(3 * words)], temporarySigns[..3], product);
 1551395        Add(data.Slice(10 * words, 3 * words), signs.Slice(10, 3),
 1551396            temporary[..(3 * words)], temporarySigns[..3], -1);
 1551397        temporary[..(3 * words)].CopyTo(data.Slice(13 * words, 3 * words));
 1551398        temporarySigns[..3].CopyTo(signs.Slice(13, 3));
 99        // Consume staged K squared before D overwrites its slots.
 15513100        Multiply(data.Slice(21 * words, 3 * words), signs.Slice(21, 3),
 15513101            data.Slice(16 * words, 3 * words), signs.Slice(16, 3), temporary, temporarySigns, product);
 15513102        ReadOnlySpan<ulong> scale = data.Slice(19 * words, words);
 15513103        WideArithmetic.MultiplyMagnitudes(scale, scale, scaleSquared);
 15513104        scaleSquaredSigns[0] = 1;
 15513105        Multiply(temporary, temporarySigns, scaleSquared, scaleSquaredSigns,
 15513106            data.Slice(21 * words, 5 * words), signs.Slice(21, 5), product);
 107        // D no longer borrows M/scale; N can overwrite those slots.
 15513108        Multiply(data.Slice(13 * words, 3 * words), signs.Slice(13, 3),
 15513109            data.Slice(13 * words, 3 * words), signs.Slice(13, 3),
 15513110            data.Slice(16 * words, 5 * words), signs.Slice(16, 5), product);
 15513111        WideFiniteAxisIntersection.NormalizeFiniteAxisPolynomialPowerOfTwo(data.Slice(16 * words, 10 * words), signs.Sli
 15513112    }
 113
 114    private static void Term(ReadOnlySpan<ulong> a, ReadOnlySpan<sbyte> aSigns, int ai,
 115        ReadOnlySpan<ulong> b, ReadOnlySpan<sbyte> bSigns, int bi,
 116        Span<ulong> result, Span<sbyte> resultSigns, int ri, int multiplier, Span<ulong> product)
 117    {
 161130118        int words = product.Length;
 161130119        WideArithmetic.MultiplyMagnitudes(a.Slice(ai * words, words), b.Slice(bi * words, words), product);
 161130120        int sign = resultSigns[ri];
 161130121        WideArithmetic.AddShiftedSignedMagnitude(product,
 161130122            aSigns[ai] * bSigns[bi] * Math.Sign(multiplier), Math.Abs(multiplier) == 2 ? 1 : 0,
 161130123            result.Slice(ri * words, words), ref sign);
 161130124        resultSigns[ri] = (sbyte)sign;
 161130125    }
 126    private static void Multiply(ReadOnlySpan<ulong> a, ReadOnlySpan<sbyte> aSigns,
 127        ReadOnlySpan<ulong> b, ReadOnlySpan<sbyte> bSigns, Span<ulong> result,
 128        Span<sbyte> resultSigns, Span<ulong> product) =>
 110391129        WideFiniteAxisIntersection.MultiplyFiniteAxisPolynomials(a, aSigns, b, bSigns, result, resultSigns, product);
 130    private static void Add(ReadOnlySpan<ulong> source, ReadOnlySpan<sbyte> sourceSigns,
 131        Span<ulong> result, Span<sbyte> resultSigns, int multiplier) =>
 31626132        WideFiniteAxisIntersection.AddFiniteAxisPolynomial(source, sourceSigns, result, resultSigns, multiplier);
 133}