< Summary

Line coverage
100%
Covered lines: 99
Uncovered lines: 0
Coverable lines: 99
Total lines: 199
Line coverage: 100%
Branch coverage
100%
Covered branches: 64
Total branches: 64
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

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

#LineLine coverage
 1//=======================================================================
 2// FiniteSlabRayFrame.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>One canonical source-plane metric shared by all admitted finite domains.</summary>
 13/// <content>Prepares exact slab charts and dispatches the shared finite-domain active sets.</content>
 14internal readonly partial struct FiniteSlabRayFrame
 15{
 16    internal readonly FiniteSlabSectionFrame Section;
 17    internal readonly CapsulePlaneRayFrame Plane;
 18    internal readonly Vector3d Origin, Center;
 19    internal readonly FixedQuaternion Rotation, SlabRotation;
 20    internal readonly Signed320 Radius, CoreCap;
 21    internal readonly bool HasCore;
 22    internal readonly FixedTriangle SourcePlane;
 23    internal readonly WideDirection3d RayNormal;
 24    internal readonly Signed832 RayNormalSquared;
 25    private readonly bool _wideParameters;
 73026    internal bool UsesWideBanks => Section.RadialFrame.ShapeFrame.HasExactScale || _wideParameters;
 72427    internal int FieldWords => UsesWideBanks ? FiniteSlabPolynomial.AffineWords : FiniteSlabPolynomial.Words;
 228    internal int SelectionStorageWords => FiniteSlabRaySelection.GetStorageWords(FieldWords);
 429    internal FiniteSlabRayFrame WithWideParameters() => UsesWideBanks ? this : new FiniteSlabRayFrame(this);
 330    private FiniteSlabRayFrame(in FiniteSlabRayFrame source) { this = source; _wideParameters = true; }
 31    // HalfThickness retains the supplied extent; FullHeight is zero for authored half-thickness slabs.
 32    internal readonly Fixed64 RadiusValue, HalfThickness, FullHeight;
 33
 34    internal FiniteSlabRayFrame(FixedTriangle sourcePlane, Vector3d origin, FixedQuaternion rotation,
 35        Vector3d center, FixedQuaternion slabRotation, Fixed64 length, Fixed64 radius, Fixed64 halfThickness, bool fullH
 23436        : this(sourcePlane, origin, rotation, center, slabRotation, length, radius, halfThickness, fullHeight, default, 
 23437    { }
 38
 39    internal FiniteSlabRayFrame(FixedTriangle sourcePlane, in ScaledRigidFrame3d sourceFrame,
 40        Vector3d center, FixedQuaternion slabRotation, Fixed64 length, Fixed64 radius, Fixed64 halfThickness, bool fullH
 7441        : this(sourcePlane, sourceFrame.RigidOrigin, sourceFrame.Rotation, center, slabRotation, length, radius,
 7442            halfThickness, fullHeight, sourceFrame, !sourceFrame.IsRigid)
 7443    { }
 44
 45    private FiniteSlabRayFrame(FixedTriangle sourcePlane, Vector3d origin, FixedQuaternion rotation,
 46        Vector3d center, FixedQuaternion slabRotation, Fixed64 length, Fixed64 radius, Fixed64 halfThickness,
 47        bool fullHeight, in ScaledRigidFrame3d sourceFrame, bool exact)
 48    {
 30849        _wideParameters = false;
 30850        Section = exact ? new(sourceFrame, center, slabRotation, length, radius, halfThickness, fullHeight)
 30851            : new(origin, rotation, center, slabRotation, length, radius, halfThickness, fullHeight);
 30852        Plane = exact ? new(sourcePlane, sourceFrame, Section.RadialFrame) : new(sourcePlane, Section.RadialFrame);
 123253        Origin = origin; Rotation = rotation; Center = center; SlabRotation = slabRotation;
 30854        Radius = Signed320.NarrowValue(WideArithmetic.MultiplySigned320(
 30855            Section.RadialFrame.ShapeFrame.CoordinateDenominator, Section.RadialFrame.ShapeFrame.Radius));
 30856        CoreCap = Section.RadialFrame.ShapeFrame.Cap;
 30857        HasCore = length != Fixed64.Zero;
 30858        SourcePlane = sourcePlane;
 92459        RadiusValue = radius; HalfThickness = halfThickness; FullHeight = fullHeight ? halfThickness : Fixed64.Zero;
 60        // Match the established plane-ray variable conditioning: numerator
 61        // coordinates include the rigid frame denominator, so an unscaled
 62        // primitive normal can make ordinary t enormous and u nearly one.
 30863        Signed320 bound = WideArithmetic.AddSigned320(WideArithmetic.AddSigned320(Radius, CoreCap), Section.Cap);
 30864        Span<ulong> magnitude = stackalloc ulong[13];
 30865        WideArithmetic.GetMagnitude(Signed576.ExtendValue(bound), magnitude);
 30866        int boundBits = WideArithmetic.GetMagnitudeBitLength(magnitude);
 30867        WideArithmetic.GetMagnitude(Plane.NormalSquared, magnitude);
 30868        int normalPower = (WideArithmetic.GetMagnitudeBitLength(magnitude) - 1) / 2;
 30869        int shift = Math.Max(0, boundBits + 2 - normalPower);
 70        // The resulting components need at most max(original bits,bound+3),
 71        // below 268 rigid or 352 affine bits; conditioning never adds a
 72        // fixed shift to an already maximal normal.
 30873        RayNormal = exact ? new(ScalePowerOfTwo(Plane.Normal.X, shift), ScalePowerOfTwo(Plane.Normal.Y, shift),
 30874            ScalePowerOfTwo(Plane.Normal.Z, shift))
 30875            : new WideDirection3d(new WideAxis3(ScalePowerOfTwo(Signed320.NarrowValue(Plane.Normal.X), shift),
 30876                ScalePowerOfTwo(Signed320.NarrowValue(Plane.Normal.Y), shift),
 30877                ScalePowerOfTwo(Signed320.NarrowValue(Plane.Normal.Z), shift)));
 30878        RayNormalSquared = RayNormal.SquaredLength;
 30879    }
 80
 81    internal Vector3d GetNormal(int orientation) =>
 182        Plane.GetWorldNormal(Rotation) * (Fixed64)(-orientation);
 83
 84    /// <summary>Compares the positive and negative whole-plane exit depths before materialization.</summary>
 85    /// <remarks>The caller must establish plane/slab intersection before selecting a nonnegative exit.</remarks>
 86    internal int ComparePlaneExitDepths(ReadOnlySpan<Vector2d> offsets)
 87    {
 14488        Signed832 sum = default;
 14489        if (!offsets.IsEmpty)
 90        {
 4891            Signed320 scale = WideArithmetic.AddSigned320(Section.RadialFrame.ShapeFrame.CoordinateDenominator,
 4892                Section.RadialFrame.ShapeFrame.CoordinateDenominator);
 9693            Signed832 low = default, high = default;
 38494            for (int index = 0; index < offsets.Length; index++)
 95            {
 14496                WideAxis3 point = new(Signed320.NarrowValue(WideArithmetic.MultiplySigned320(scale, Signed192.Raw(offset
 14497                    default, Signed320.NarrowValue(WideArithmetic.MultiplySigned320(scale, Signed192.Raw(offsets[index].
 14498                Signed832 value = WideDirection3d.Dot(Plane.Normal, point);
 21699                if (index == 0 || WideArithmetic.SubtractSigned832(value, low).Sign < 0) low = value;
 216100                if (index == 0 || WideArithmetic.SubtractSigned832(value, high).Sign > 0) high = value;
 101            }
 48102            sum = WideArithmetic.AddSigned832(low, high);
 103        }
 104        // Height caps and rounded footprints are symmetric. Affine coordinates
 105        // and normal components are <352 bits; these dot sums fit within 832 bits.
 144106        return WideArithmetic.SubtractSigned832(sum,
 144107            WideArithmetic.AddSigned832(Plane.PlaneConstant, Plane.PlaneConstant)).Sign;
 108    }
 109
 110    /// <summary>Affine dimension of the shape face maximizing the oriented plane functional.</summary>
 111    internal int GetSupportDimension(ReadOnlySpan<Vector2d> prismOffsets, int orientation)
 112    {
 117113        if (orientation != -1 && orientation != 1) throw new ArgumentOutOfRangeException(nameof(orientation));
 114        // A zero normal coefficient leaves that factor of the extrusion free.
 115        // The stadium disk and core share the X/Z plane, whose dimension is at most two.
 115116        int height = Plane.Normal.Y.IsZero && Section.Cap.Sign > 0 ? 1 : 0;
 115117        bool axial = Plane.Normal.X.IsZero && Plane.Normal.Z.IsZero;
 115118        if (prismOffsets.IsEmpty)
 119        {
 71120            int footprint = axial && RadiusValue > Fixed64.Zero ? 2
 71121                : HasCore && Plane.Normal.Z.IsZero ? 1 : 0;
 71122            return height + footprint;
 123        }
 44124        _ = FiniteSlabSectionFrame.GetPrismWinding(prismOffsets);
 46125        if (axial) return height + 2;
 126126        Signed576 maximum = default; Vector2d vertex = default; bool tied = false;
 404127        for (int index = 0; index < prismOffsets.Length; index++)
 128        {
 160129            Vector2d offset = prismOffsets[index];
 160130            Signed576 projection = WideArithmetic.AddSigned576(
 160131                WideArithmetic.MultiplySigned576(Plane.Normal.X, offset.X.m_rawValue),
 160132                WideArithmetic.MultiplySigned576(Plane.Normal.Z, offset.Y.m_rawValue));
 240133            if (orientation < 0) projection = WideArithmetic.SubtractSigned576(default, projection);
 160134            int order = WideArithmetic.SubtractSigned576(projection, maximum).Sign;
 379135            if (index == 0 || order > 0) { maximum = projection; vertex = offset; tied = false; }
 107136            else if (order == 0 && offset != vertex) tied = true;
 137        }
 42138        return height + (tied ? 1 : 0);
 139    }
 140
 141    private static Signed320 ScalePowerOfTwo(Signed320 value, int shift)
 142    {
 1830143        while (shift > 0)
 144        {
 963145            int step = Math.Min(63, shift);
 963146            WideArithmetic.ShiftLeft(value.Word4, value.Word3, value.Word2, value.Word1, value.Word0, step,
 963147                out ulong w4, out ulong w3, out ulong w2, out ulong w1, out ulong w0);
 1926148            value = new(w4, w3, w2, w1, w0); shift -= step;
 149        }
 867150        return value;
 151    }
 152
 153    private static Signed576 ScalePowerOfTwo(Signed576 value, int shift)
 154    {
 333155        while (shift > 0)
 156        {
 222157            int step = Math.Min(62, shift);
 222158            value = WideArithmetic.MultiplySigned576(value, 1L << step);
 222159            shift -= step;
 160        }
 111161        return value;
 162    }
 163}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/FiniteSlabRayFrame.NativePrism.cs

#LineLine coverage
 1//=======================================================================
 2// FiniteSlabRayFrame.NativePrism.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/// <content>Admits exact native affine source charts without rebuilding rounded triangles.</content>
 13internal readonly partial struct FiniteSlabRayFrame
 14{
 15    internal FiniteSlabRayFrame(Fixed64 height, Fixed64 radius, Signed320 coordinateDenominator,
 16        in WideDirection3d normal, Signed832 planeConstant)
 17    {
 1818        this = default;
 1819        Section = new(height, radius, coordinateDenominator);
 1820        Plane = CapsulePlaneRayFrame.ForCapsulePointRay(Fixed64.Zero, radius, coordinateDenominator, normal, planeConsta
 3621        Origin = Center = Vector3d.Zero; Rotation = SlabRotation = FixedQuaternion.Identity;
 1822        Radius = Signed320.NarrowValue(WideArithmetic.MultiplySigned320(coordinateDenominator,
 1823            Signed320.ExtendValue(Section.RadialFrame.ShapeFrame.Radius)));
 3624        RadiusValue = radius; HalfThickness = FullHeight = height;
 1825        Signed320 bound = WideArithmetic.AddSigned320(Radius, Section.Cap);
 1826        Span<ulong> magnitude = stackalloc ulong[13];
 1827        WideArithmetic.GetMagnitude(Signed576.ExtendValue(bound), magnitude);
 1828        int boundBits = WideArithmetic.GetMagnitudeBitLength(magnitude);
 1829        WideArithmetic.GetMagnitude(normal.SquaredLength, magnitude);
 1830        int normalPower = (WideArithmetic.GetMagnitudeBitLength(magnitude) - 1) / 2;
 1831        int shift = Math.Max(0, boundBits + 2 - normalPower);
 1832        RayNormal = new(ScalePowerOfTwo(Signed320.NarrowValue(normal.X), shift),
 1833            ScalePowerOfTwo(Signed320.NarrowValue(normal.Y), shift), ScalePowerOfTwo(Signed320.NarrowValue(normal.Z), sh
 1834        RayNormalSquared = RayNormal.SquaredLength;
 1835    }
 36}