< Summary

Information
Class: FixedMathSharp.Geometry.BoxCylinderEdgeContacts
Assembly: FixedMathSharp
File(s): /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/OrientedBox/BoxCylinderEdgeContacts.cs
Line coverage
100%
Covered lines: 204
Uncovered lines: 0
Coverable lines: 204
Total lines: 351
Line coverage: 100%
Branch coverage
100%
Covered branches: 86
Total branches: 86
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
TryGetContact(...)100%3232100%
TryChart(...)100%3030100%
CreateSelection(...)100%11100%
RestoreValueRoot(...)100%11100%
BuildParameter(...)100%11100%
BuildValues(...)100%11100%
GetNormal(...)100%22100%
WriteDirection(...)100%11100%
GetOffset(...)100%1010100%
SupportSign(...)100%66100%
Component(...)100%44100%
Signed(...)100%22100%
Sign(...)100%11100%
Write(...)100%11100%
Multiply(...)100%11100%
Add(...)100%11100%
.ctor(...)100%11100%
Slice(...)100%11100%

File(s)

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/OrientedBox/BoxCylinderEdgeContacts.cs

#LineLine coverage
 1//=======================================================================
 2// BoxCylinderEdgeContacts.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 System.Runtime.CompilerServices;
 10
 11namespace FixedMathSharp.Geometry;
 12
 13/// <summary>
 14/// Exact box-edge/cylinder-rim support minima. Signed box-coordinate charts
 15/// preserve each edge's normal cone instead of reflecting a projected minimum
 16/// into a different box feature.
 17/// </summary>
 18internal static class BoxCylinderEdgeContacts
 19{
 20    private const int Words = 40;
 21    private const int ValueWords = 56;
 22    private const int ParameterSlots = 28;
 23    private const int ValueCellWords = (16 * (ValueWords * 64 + 11) + 255) / 64;
 24
 25    private struct Selection
 26    {
 27        internal bool HasValue, IsZero, IsRational;
 28        internal int Edge, First, Second, FirstSign, SecondSign, CapSign, ParameterOrdinal;
 29        internal int ValueOrdinal, ValueShift;
 30    }
 31
 32    /// <summary>
 33    /// AnalyticBest already has a nonnegative exact gap. Returns false on a
 34    /// certified separating root. Exact ties retain the earlier analytic or
 35    /// edge candidate. Principal and zero-radial directions belong to the caller.
 36    /// </summary>
 37    internal static bool TryGetContact(in BoxCylinderGeometry geometry,
 38        in ConvexContactCandidate analyticBest, Fixed64 analyticDepth, bool analyticClamped, out bool hasBetter,
 39        out Vector3d normal, out Fixed64 depth, out bool depthIsClamped,
 40        out Vector3d localSupportSigns)
 41    {
 115742        hasBetter = false;
 115743        normal = localSupportSigns = default;
 115744        depth = default;
 115745        depthIsClamped = false;
 115746        Span<ulong> bestValues = stackalloc ulong[5 * ValueWords];
 115747        Span<sbyte> bestSigns = stackalloc sbyte[5];
 115748        Span<ulong> bestCell = stackalloc ulong[ValueCellWords];
 115749        Selection best = default;
 924450        for (int edge = 0; edge < 3; edge++)
 51        {
 693452            int first = (edge + 1) % 3, second = (edge + 2) % 3;
 53            // A cylinder parallel to this edge projects to a circle. Its
 54            // principal radial direction is already an analytic candidate.
 346755            if (Component(geometry.Axis, first).IsZero && Component(geometry.Axis, second).IsZero)
 56                continue;
 57            // A perpendicular cylinder projects to a rectangle, not an
 58            // ellipse. Together with the projected box its support is linear
 59            // between box-face, cap-pole and side-cross normals. A positive
 60            // minimum lies at those boundaries; a negative interior value
 61            // implies a negative boundary value. The analytic owner tests all.
 242762            if (Component(geometry.Axis, edge).IsZero)
 63                continue;
 184464            for (int firstSign = -1; firstSign <= 1; firstSign += 2)
 369265                for (int secondSign = -1; secondSign <= 1; secondSign += 2)
 738866                    for (int cap = -1; cap <= 1; cap += 2)
 67                    {
 246468                        if (BoxCylinderAnalyticFeatures.IsEdgeConeDominated(geometry,
 246469                                edge, first, second, firstSign, secondSign, cap, analyticBest))
 70                            continue;
 1019071                        for (int chart = 0; chart < 2; chart++)
 72                        {
 339873                            int u = chart == 0 ? first : second;
 339874                            int v = chart == 0 ? second : first;
 339875                            int su = chart == 0 ? firstSign : secondSign;
 339876                            int sv = chart == 0 ? secondSign : firstSign;
 339877                            if (!TryChart(geometry, edge, u, v, su, sv, cap, analyticBest,
 339878                                    ((ulong)analyticDepth.m_rawValue << 1) | 1UL, !analyticClamped,
 339879                                    bestValues, bestSigns, bestCell, ref best))
 280                                return false;
 81                        }
 82                    }
 83        }
 115584        if (!best.HasValue)
 112185            return true;
 3486        hasBetter = true;
 3487        normal = GetNormal(geometry, best);
 3488        localSupportSigns = new Vector3d(
 3489            SupportSign(best, 0), SupportSign(best, 1), SupportSign(best, 2));
 3490        if (!best.IsZero)
 91        {
 3092            FiniteAxisValueRoot root = RestoreValueRoot(bestValues, bestSigns, bestCell, best);
 3093            ConvexContactValueRoot.GetRoundedDepth(geometry.RawScale, geometry.ValueShift,
 3094                ref root, out depth, out depthIsClamped);
 95        }
 3496        return true;
 97    }
 98
 99    [MethodImpl(MethodImplOptions.NoInlining)]
 100    private static bool TryChart(in BoxCylinderGeometry geometry, int edge, int first, int second,
 101        int firstSign, int secondSign, int capSign, scoped ConvexContactCandidate analytic,
 102        ulong upperTwiceRaw, bool hasUpperBound,
 103        scoped Span<ulong> bestValues, scoped Span<sbyte> bestSigns, scoped Span<ulong> bestCell,
 104        ref Selection best)
 105    {
 3398106        Signed320 au = Signed(Component(geometry.Axis, first), firstSign);
 3398107        Signed320 av = Signed(Component(geometry.Axis, second), secondSign);
 3398108        if (au.Sign * capSign < 0
 3398109            && WideArithmetic.AddSigned320(au, av).Sign * capSign <= 0)
 1276110            return true;
 111
 2122112        Span<ulong> data = stackalloc ulong[ParameterSlots * Words];
 2122113        Span<sbyte> signs = stackalloc sbyte[ParameterSlots];
 2122114        BuildParameter(geometry, edge, first, second, firstSign, secondSign, capSign, data, signs);
 2122115        Polynomial storage = new(data, signs, Words);
 2122116        Polynomial stationary = storage.Slice(0, 5);
 2122117        Polynomial k = storage.Slice(8, 2);
 4244118        Polynomial l = storage.Slice(10, 3), signedGap = storage.Slice(13, 3);
 4244119        Polynomial numerator = storage.Slice(16, 5), denominator = storage.Slice(21, 5);
 2122120        Polynomial cap = storage.Slice(26, 2);
 2122121        Span<ulong> batchCells = stackalloc ulong[64];
 2122122        Span<int> batchShifts = stackalloc int[8];
 2122123        FiniteAxisValueRoots roots = WideFiniteAxisIntersection.GetFiniteValueRoots(
 2122124            stationary.Values, stationary.Signs, batchCells, batchShifts);
 2122125        Span<ulong> cell = stackalloc ulong[WideFiniteAxisIntersection.GetFiniteValueRootCellWords(
 2122126            stationary.Values, stationary.Signs)];
 2122127        Span<ulong> values = stackalloc ulong[5 * ValueWords];
 2122128        Span<sbyte> valueSigns = stackalloc sbyte[5];
 2122129        Span<ulong> valueCell = stackalloc ulong[ValueCellWords];
 2122130        bool valuesReady = false;
 7664131        for (int ordinal = 0; ordinal < roots.Count; ordinal++)
 132        {
 1712133            scoped FiniteAxisValueRoot root = FiniteAxisValueRoots.GetRoot(
 1712134                roots, ordinal, stationary.Values, stationary.Signs, cell);
 1712135            if (Sign(ref root, cap) < 0)
 136                continue;
 1333137            int kSign = Sign(ref root, k);
 138            // K=0 has the rational direction (p,q), already enumerated by
 139            // the analytic owner. The nonparallel/nonperpendicular dispatch
 140            // above proves this projected ellipse has Q>0 on the whole chart.
 1333141            if (kSign == 0 || Sign(ref root, l) != -kSign)
 142                continue;
 732143            int gapSign = Sign(ref root, signedGap) * kSign;
 732144            if (gapSign < 0)
 2145                return false;
 730146            if (best.IsZero || analytic.GapSign == 0)
 147                continue;
 728148            if (gapSign == 0)
 149            {
 4150                best = CreateSelection(edge, first, second, firstSign, secondSign, capSign, ordinal);
 4151                best.IsZero = true;
 4152                continue;
 153            }
 154            // An unclamped nearest-even depth d bounds the analytic gap by
 155            // d+1/2 raw. A positive edge at or above that bound cannot win;
 156            // ties retain the analytic feature. Admit negative/zero gaps first.
 724157            if (hasUpperBound && ConvexContactValueRoot.CompareSquaredGapToTwiceRaw(ref root,
 724158                    numerator.Values, numerator.Signs, denominator.Values, denominator.Signs, upperTwiceRaw) >= 0)
 159                continue;
 54160            if (!valuesReady)
 161            {
 50162                BuildValues(geometry, edge, first, second, firstSign, secondSign, capSign, values, valueSigns);
 50163                valuesReady = true;
 164            }
 54165            scoped FiniteAxisValueRoot value = ConvexContactValueRoot.MapSquaredValue(
 54166                geometry.RawScale, geometry.ValueShift, ref root, numerator.Values, numerator.Signs,
 54167                denominator.Values, denominator.Signs, values, valueSigns, valueCell);
 54168            int comparison = best.HasValue
 54169                ? WideFiniteAxisIntersection.CompareFiniteValueRoots(value,
 54170                    RestoreValueRoot(bestValues, bestSigns, bestCell, best))
 54171                : ConvexContactValueRoot.CompareRootSquared(geometry.RawScale, geometry.ValueShift, ref value, analytic)
 54172            if (comparison >= 0)
 173                continue;
 33174            values.CopyTo(bestValues);
 33175            valueSigns.CopyTo(bestSigns);
 33176            valueCell.CopyTo(bestCell);
 33177            best = CreateSelection(edge, first, second, firstSign, secondSign, capSign, ordinal);
 33178            best.ValueOrdinal = value.Ordinal;
 33179            best.ValueShift = value.DenominatorShift;
 33180            best.IsRational = value.IsRational;
 181        }
 2120182        return true;
 183    }
 184
 185    private static Selection CreateSelection(int edge, int first, int second,
 37186        int firstSign, int secondSign, int capSign, int ordinal) => new()
 37187    {
 37188        HasValue = true, Edge = edge, First = first, Second = second,
 37189        FirstSign = firstSign, SecondSign = secondSign, CapSign = capSign, ParameterOrdinal = ordinal
 37190    };
 191
 192    private static FiniteAxisValueRoot RestoreValueRoot(ReadOnlySpan<ulong> values,
 34193        ReadOnlySpan<sbyte> signs, Span<ulong> cell, Selection selection) => new()
 34194    {
 34195        Coefficients = values, Signs = signs, LowerNumerator = cell,
 34196        DenominatorShift = selection.ValueShift, Ordinal = selection.ValueOrdinal,
 34197        IsRational = selection.IsRational
 34198    };
 199
 200    /// <summary>
 201    /// W=L²-K²Q, with P=p+qt, Q=A+2Bt+Ct², K=q-pt and
 202    /// L=B+(C-A)t-Bt². At an admitted K!=0 root, sqrt(Q)=-L/K,
 203    /// so the signed gap is (PK-L)/(D K sqrt(1+t²)).
 204    /// </summary>
 205    [MethodImpl(MethodImplOptions.NoInlining)]
 206    private static void BuildParameter(in BoxCylinderGeometry geometry, int edge, int first, int second,
 207        int firstSign, int secondSign, int capSign, Span<ulong> data, Span<sbyte> signs)
 208    {
 209        // |a_i|<2^170, |c_i|<2^237, R<2^235, S<2^170 imply
 210        // U<2^342, |p|,|q|<2^579. Q<2^1157 and W,N<2^2340;
 211        // the denominator coefficients are <2^2190. Forty words (2560 bits)
 212        // include every coefficient-sum carry, before positive normalization.
 4312213        data.Clear(); signs.Clear();
 2156214        Polynomial storage = new(data, signs, Words);
 2156215        Polynomial radial = storage.Slice(5, 3);
 2156216        Polynomial cap = storage.Slice(26, 2);
 2156217        Span<ulong> scratch = stackalloc ulong[24 * Words];
 2156218        Span<sbyte> scratchSigns = stackalloc sbyte[24];
 4312219        scratch.Clear(); scratchSigns.Clear();
 2156220        Polynomial temp = new(scratch, scratchSigns, Words);
 6468221        Polynomial p = temp.Slice(0, 2), u = temp.Slice(2, 1), radius = temp.Slice(3, 1);
 6468222        Polynomial factor = temp.Slice(4, 1), axis = temp.Slice(5, 2), axisSquared = temp.Slice(7, 3);
 4312223        Polynomial one = temp.Slice(10, 3), temporary = temp.Slice(13, 5);
 4312224        Polynomial scalar = temp.Slice(21, 1), scale = temp.Slice(22, 1);
 2156225        Span<ulong> product = scratch.Slice(23 * Words, Words);
 2156226        Signed320 au = Signed(Component(geometry.Axis, first), firstSign);
 2156227        Signed320 av = Signed(Component(geometry.Axis, second), secondSign);
 2156228        WideAxis3 offset = GetOffset(geometry, edge, first, second, firstSign, secondSign, capSign);
 2156229        Write(u, 0, geometry.Axis.SquaredLength);
 2156230        Write(radius, 0, WideArithmetic.MultiplySigned320(geometry.Radius, geometry.Radius));
 2156231        Multiply(factor, radius, u, product);
 2156232        Write(axis, 0, Signed576.ExtendValue(au));
 2156233        Write(axis, 1, Signed576.ExtendValue(av));
 2156234        Add(cap, axis, capSign);
 2156235        one.Values[0] = one.Values[2 * Words] = 1;
 2156236        one.Signs[0] = one.Signs[2] = 1;
 2156237        Multiply(radial, u, one, product);
 2156238        Multiply(axisSquared, axis, axis, product);
 2156239        Add(radial, axisSquared, -1);
 2156240        Multiply(temporary.Slice(0, 3), radial, factor, product);
 2156241        Write(axis, 0, Signed576.ExtendValue(Signed(Component(offset, first), firstSign)));
 2156242        Write(axis, 1, Signed576.ExtendValue(Signed(Component(offset, second), secondSign)));
 2156243        Multiply(p, u, axis, product);
 2156244        Write(scale, 0, Signed576.ExtendValue(Signed320.ExtendValue(geometry.RawScale)));
 2156245        Multiply(scalar, u, scale, product);
 2156246        CylinderEdgeContactPolynomial.Build(p.Values, p.Signs,
 2156247            temporary.Slice(0, 3).Values, temporary.Slice(0, 3).Signs,
 2156248            one.Values, one.Signs, scalar.Values, data[..(26 * Words)], signs[..26]);
 2156249    }
 250
 251    [MethodImpl(MethodImplOptions.NoInlining)]
 252    private static void BuildValues(in BoxCylinderGeometry geometry, int edge, int first, int second,
 253        int firstSign, int secondSign, int capSign, Span<ulong> values, Span<sbyte> signs)
 254    {
 50255        WideAxis3 c = GetOffset(geometry, edge, first, second, firstSign, secondSign, capSign);
 50256        Span<ulong> invariants = stackalloc ulong[8 * ValueWords];
 50257        Span<sbyte> invariantSigns = stackalloc sbyte[8];
 100258        invariants.Clear(); invariantSigns.Clear();
 50259        Polynomial scalars = new(invariants, invariantSigns, ValueWords);
 50260        Write(scalars, 0, geometry.Axis.SquaredLength);
 50261        Write(scalars, 1, Signed576.ExtendValue(Signed320.ExtendValue(Signed192.Signed(1))));
 50262        Write(scalars, 2, Signed576.ExtendValue(Component(geometry.Axis, edge)));
 50263        Write(scalars, 3, c.SquaredLength);
 50264        Write(scalars, 4, WideAxis3.Dot(geometry.Axis, c));
 265        // c's edge coordinate is zero: y=b.c=0, and tau=0.
 50266        Write(scalars, 6, WideArithmetic.MultiplySigned320(geometry.Radius, geometry.Radius));
 50267        CylinderPairSideValuePolynomial.BuildUnshifted(invariants, invariantSigns, ValueWords, values, signs);
 268        // Weighted height after z=2^ValueShift*t is <3310 bits, including
 269        // ValueShift<=480 and |c_i|<2^237. Fifty-six words provide 3584 bits.
 50270        WideFiniteAxisIntersection.ScaleFiniteAxisPolynomialVariable(values, 5, geometry.ValueShift);
 50271        WideFiniteAxisIntersection.NormalizeFiniteAxisPolynomialPowerOfTwo(values, signs);
 50272    }
 273
 274    [MethodImpl(MethodImplOptions.NoInlining)]
 275    private static Vector3d GetNormal(in BoxCylinderGeometry geometry, Selection selection)
 276    {
 34277        Span<ulong> data = stackalloc ulong[ParameterSlots * Words];
 34278        Span<sbyte> signs = stackalloc sbyte[ParameterSlots];
 34279        BuildParameter(geometry, selection.Edge, selection.First, selection.Second,
 34280            selection.FirstSign, selection.SecondSign, selection.CapSign, data, signs);
 34281        Span<ulong> cell = stackalloc ulong[WideFiniteAxisIntersection.GetFiniteValueRootCellWords(
 34282            data[..(5 * Words)], signs[..5])];
 34283        bool found = WideFiniteAxisIntersection.TryGetFiniteValueRoot(data[..(5 * Words)], signs[..5],
 34284            selection.ParameterOrdinal, cell, out FiniteAxisValueRoot root);
 285        System.Diagnostics.Debug.Assert(found);
 286        const int directionWords = 3;
 34287        Span<ulong> direction = stackalloc ulong[6 * directionWords];
 34288        Span<sbyte> directionSigns = stackalloc sbyte[6];
 68289        direction.Clear(); directionSigns.Clear();
 34290        WideAxis3 first = geometry.WorldBasis.GetAxis(selection.First);
 34291        WideAxis3 second = geometry.WorldBasis.GetAxis(selection.Second);
 272292        for (int component = 0; component < 3; component++)
 293        {
 102294            WriteDirection(Component(first, component), selection.FirstSign,
 102295                direction.Slice(component * 2 * directionWords, directionWords), out directionSigns[2 * component]);
 102296            WriteDirection(Component(second, component), selection.SecondSign,
 102297                direction.Slice((component * 2 + 1) * directionWords, directionWords), out directionSigns[2 * component 
 298        }
 34299        return ConvexContactValueRoot.GetNormalizedDirection(ref root, direction, directionSigns, 1);
 300    }
 301
 302    private static void WriteDirection(Signed320 value, int orientation, Span<ulong> magnitude, out sbyte sign)
 303    {
 204304        Signed192 narrow = Signed192.NarrowProven(value);
 204305        WideArithmetic.GetMagnitude(narrow, out magnitude[2], out magnitude[1], out magnitude[0]);
 204306        sign = (sbyte)(value.Sign * orientation);
 204307    }
 308
 309    private static WideAxis3 GetOffset(in BoxCylinderGeometry geometry, int edge, int first, int second,
 310        int firstSign, int secondSign, int capSign)
 311    {
 2206312        int corner = (firstSign > 0 ? 1 << first : 0) | (secondSign > 0 ? 1 << second : 0);
 2206313        WideAxis3 offset = geometry.GetCapVertexOffset(corner, capSign);
 314        // Projection onto the edge-normal plane discards this coordinate.
 2206315        return new WideAxis3(edge == 0 ? default : offset.X,
 2206316            edge == 1 ? default : offset.Y, edge == 2 ? default : offset.Z);
 317    }
 318
 102319    private static Fixed64 SupportSign(Selection selection, int axis) => axis == selection.Edge
 102320        ? Fixed64.Zero : (axis == selection.First ? selection.FirstSign : selection.SecondSign) > 0
 102321            ? Fixed64.One : -Fixed64.One;
 23687322    private static Signed320 Component(in WideAxis3 value, int axis) => axis == 0 ? value.X : axis == 1 ? value.Y : valu
 15420323    private static Signed320 Signed(Signed320 value, int sign) => sign < 0 ? WideArithmetic.Negate(value) : value;
 324    private static int Sign(scoped ref FiniteAxisValueRoot root, scoped Polynomial polynomial) =>
 5108325        WideFiniteAxisIntersection.GetSignAtFiniteValueRootAndRefine(ref root, polynomial.Values, polynomial.Signs);
 326    private static void Write(Polynomial polynomial, int index, Signed576 value)
 327    {
 15392328        Span<ulong> target = polynomial.Values.Slice(index * polynomial.Words, polynomial.Words);
 15392329        target.Clear();
 15392330        WideArithmetic.GetMagnitude(value, target[..9]);
 15392331        polynomial.Signs[index] = (sbyte)value.Sign;
 15392332    }
 333    private static void Multiply(Polynomial result, Polynomial first, Polynomial second, Span<ulong> product) =>
 12936334        WideFiniteAxisIntersection.MultiplyFiniteAxisPolynomials(first.Values, first.Signs,
 12936335            second.Values, second.Signs, result.Values, result.Signs, product);
 336    private static void Add(Polynomial result, Polynomial source, int multiplier) =>
 4312337        WideFiniteAxisIntersection.AddFiniteAxisPolynomial(source.Values, source.Signs,
 4312338            result.Values, result.Signs, multiplier);
 339    private readonly ref struct Polynomial
 340    {
 341        internal readonly Span<ulong> Values;
 342        internal readonly Span<sbyte> Signs;
 343        internal readonly int Words;
 344        internal Polynomial(Span<ulong> values, Span<sbyte> signs, int words)
 345        {
 161034346            Values = values; Signs = signs; Words = words;
 53678347        }
 348        internal Polynomial Slice(int offset, int count) =>
 47194349            new(Values.Slice(offset * Words, count * Words), Signs.Slice(offset, count), Words);
 350    }
 351}

Methods/Properties

TryGetContact(FixedMathSharp.Geometry.BoxCylinderGeometry&,FixedMathSharp.Geometry.ConvexContactCandidate&,FixedMathSharp.Fixed64,System.Boolean,System.Boolean&,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&,System.Boolean&,FixedMathSharp.Vector3d&)
TryChart(FixedMathSharp.Geometry.BoxCylinderGeometry&,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,FixedMathSharp.Geometry.ConvexContactCandidate,System.UInt64,System.Boolean,System.Span`1<System.UInt64>,System.Span`1<System.SByte>,System.Span`1<System.UInt64>,FixedMathSharp.Geometry.BoxCylinderEdgeContacts/Selection&)
CreateSelection(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32)
RestoreValueRoot(System.ReadOnlySpan`1<System.UInt64>,System.ReadOnlySpan`1<System.SByte>,System.Span`1<System.UInt64>,FixedMathSharp.Geometry.BoxCylinderEdgeContacts/Selection)
BuildParameter(FixedMathSharp.Geometry.BoxCylinderGeometry&,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Span`1<System.UInt64>,System.Span`1<System.SByte>)
BuildValues(FixedMathSharp.Geometry.BoxCylinderGeometry&,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Span`1<System.UInt64>,System.Span`1<System.SByte>)
GetNormal(FixedMathSharp.Geometry.BoxCylinderGeometry&,FixedMathSharp.Geometry.BoxCylinderEdgeContacts/Selection)
WriteDirection(FixedMathSharp.Signed320,System.Int32,System.Span`1<System.UInt64>,System.SByte&)
GetOffset(FixedMathSharp.Geometry.BoxCylinderGeometry&,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32)
SupportSign(FixedMathSharp.Geometry.BoxCylinderEdgeContacts/Selection,System.Int32)
Component(FixedMathSharp.Geometry.WideAxis3&,System.Int32)
Signed(FixedMathSharp.Signed320,System.Int32)
Sign(FixedMathSharp.Geometry.FiniteAxisValueRoot&,FixedMathSharp.Geometry.BoxCylinderEdgeContacts/Polynomial)
Write(FixedMathSharp.Geometry.BoxCylinderEdgeContacts/Polynomial,System.Int32,FixedMathSharp.Signed576)
Multiply(FixedMathSharp.Geometry.BoxCylinderEdgeContacts/Polynomial,FixedMathSharp.Geometry.BoxCylinderEdgeContacts/Polynomial,FixedMathSharp.Geometry.BoxCylinderEdgeContacts/Polynomial,System.Span`1<System.UInt64>)
Add(FixedMathSharp.Geometry.BoxCylinderEdgeContacts/Polynomial,FixedMathSharp.Geometry.BoxCylinderEdgeContacts/Polynomial,System.Int32)
.ctor(System.Span`1<System.UInt64>,System.Span`1<System.SByte>,System.Int32)
Slice(System.Int32,System.Int32)