< Summary

Information
Class: FixedMathSharp.Geometry.WideFiniteAxisIntersection
Assembly: FixedMathSharp
File(s): File 1: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredAxes.cs
File 2: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredAxes.Solver.cs
File 3: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredAxisTriangle.cs
File 4: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredAxisTriangle.Materialization.cs
File 5: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredCapsule.cs
File 6: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredCapsuleAnchor.cs
File 7: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredCapsuleDistance.cs
File 8: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredCapsuleSweep2d.cs
File 9: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredConeSurfaceAnchors.cs
File 10: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredSurfaceAnchors.cs
File 11: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredSurfaces.cs
File 12: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredSurfaceTriangle.cs
File 13: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.Containment.cs
File 14: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.cs
File 15: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.Distance.cs
File 16: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.DistanceSolver.cs
File 17: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.NarrowSolver.cs
File 18: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.Ray.cs
File 19: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.RigidPointRelation.cs
File 20: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.RootSolver.cs
File 21: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.RoundedBox.cs
File 22: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.RoundedCylinder.cs
File 23: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.RoundedCylinderInteger.cs
File 24: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.RoundedCylinderRootSolver.cs
File 25: /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.Witness.cs
Line coverage
100%
Covered lines: 7888
Uncovered lines: 0
Coverable lines: 7888
Total lines: 12577
Line coverage: 100%
Branch coverage
100%
Covered branches: 1008
Total branches: 1008
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
File 1: .ctor(...)100%11100%
File 1: .ctor(...)100%11100%
File 1: TryGetDistanceToCenteredAxis(...)100%11100%
File 1: TryGetDistanceToCenteredAxis(...)100%11100%
File 1: TryGetDistanceBetweenCenteredAxes(...)100%11100%
File 1: TryGetDistanceBetweenCenteredAxes(...)100%11100%
File 1: DoCenteredCapsulesOverlap(...)100%11100%
File 1: DoCenteredCapsulesOverlap(...)100%11100%
File 1: TryGetCenteredCapsulesContact(...)100%44100%
File 1: TryGetCenteredCapsulesContact(...)100%22100%
File 1: TryGetClosestPointsBetweenCenteredAxes(...)100%22100%
File 1: TryGetClosestPointsBetweenCenteredAxes(...)100%22100%
File 1: TryGetClosestOffsetsBetweenCenteredAxes(...)100%11100%
File 1: GetClosestDirectionBetweenCenteredAxes(...)100%11100%
File 2: GetClosestCenteredAxisParameters(...)100%1212100%
File 2: GetCenteredAxesSquaredDistance(...)100%11100%
File 2: GetCenteredAxesCandidate(...)100%11100%
File 2: GetCenteredAxesSquaredDistance(...)100%11100%
File 2: GetCenteredAxesCandidate(...)100%11100%
File 2: IsWithinCombinedRadius(...)100%11100%
File 2: ProjectSecondFromCenteredAxisCap(...)100%11100%
File 2: ProjectFirstFromCenteredAxisCap(...)100%11100%
File 2: ClampCenteredAxisParameter(...)100%44100%
File 2: SetCenteredAxisCap(...)100%22100%
File 2: TryRoundCenteredAxesDistance(...)100%44100%
File 2: GetHalfToEvenIncrement(...)100%11100%
File 2: TryGetCenteredAxisPointCoordinate(...)100%11100%
File 2: GetCenteredAxisPointNumerator(...)100%11100%
File 2: GetCenteredAxisLocalOffset(...)100%11100%
File 2: GetLocalRadialFeature(...)100%11100%
File 2: TryGetCenteredCapsulesDepth(...)100%11100%
File 2: GetCenteredRadiusDepth(...)100%88100%
File 2: CompareSquaredDistanceToCenteredDepthThreshold(...)100%22100%
File 3: .ctor(...)100%11100%
File 3: TryGetClosestPointsToCenteredAxis(...)100%11100%
File 3: DoesCenteredCapsuleTriangleOverlap(...)100%11100%
File 3: TryGetCenteredCapsuleTriangleContact(...)100%88100%
File 3: TryGetCenteredCapsuleTriangleLocalContact(...)100%44100%
File 3: GetClosestCenteredAxisTriangleCandidate(...)100%11100%
File 3: TryGetCenteredAxisTriangleFaceCandidate(...)100%88100%
File 3: KeepCenteredAxisTriangleEdgeCandidate(...)100%44100%
File 3: GetClosestCenteredAxisSegmentParameters(...)100%1414100%
File 3: ClampUnitParameter(...)100%44100%
File 3: ProjectEdgeFromCenteredCap(...)100%11100%
File 3: ProjectAxisFromEdgeCap(...)100%11100%
File 3: SetUnitCapAtCenteredDenominator(...)100%22100%
File 3: GetRationalPoint(...)100%11100%
File 3: GetRationalSegmentPoint(...)100%11100%
File 3: GetRationalCoordinate(...)100%11100%
File 3: CreateAxisTriangleCandidate(...)100%11100%
File 3: GetCenteredCapsuleTriangleDepth(...)100%11100%
File 4: ContainsTriangleProjection(...)100%44100%
File 4: IsInsideTriangleEdge(...)100%11100%
File 4: SubtractVertex(...)100%11100%
File 4: SubtractVertex(...)100%11100%
File 4: GetWideDot(...)100%11100%
File 4: GetTriangleNormal(...)100%11100%
File 4: TryMaterialize(...)100%22100%
File 4: TryOffsetPoint(...)100%22100%
File 4: TryGetRelativeCoordinate(...)100%11100%
File 5: TryGetSurfacePointOnCenteredCapsule(...)100%44100%
File 5: TryGetSurfaceOffsetOnCenteredCapsule(...)100%22100%
File 5: TryGetSurfaceOffsetOnCenteredCapsule(...)100%22100%
File 5: TryGetSurfacePointOnCenteredCapsule(...)100%66100%
File 5: ContainsPointInCenteredCapsule(...)100%11100%
File 5: ContainsPointInCenteredCapsule(...)100%11100%
File 5: GetDirectionFromCenteredAxis(...)100%22100%
File 5: GetDirectionFromCenteredAxis(...)100%22100%
File 5: TryGetCapsuleInterval(...)100%22100%
File 5: TryGetCapsuleInterval(...)100%22100%
File 5: IsCenteredCapsulePointContained(...)100%66100%
File 5: IsCenteredCapsulePointContained(...)100%66100%
File 5: GetCenteredCap(...)100%22100%
File 5: MergeCenteredCapInterval(...)100%11100%
File 5: MergeCenteredCapInterval(...)100%11100%
File 5: GetCenteredCapPolynomial(...)100%11100%
File 5: GetCenteredCapPolynomial(...)100%11100%
File 5: GetCenteredCapConstant(...)100%11100%
File 5: GetCenteredCapConstant(...)100%11100%
File 5: GetCenteredCapOffset(...)100%22100%
File 5: GetRadialComponent(...)100%11100%
File 5: GetClosestCenteredAxisRatio(...)100%44100%
File 5: GetClosestCenteredAxisRatio(...)100%44100%
File 5: TryGetCenteredCapsuleSurfaceCoordinate(...)100%11100%
File 5: MultiplyThreeToSigned320(...)100%11100%
File 5: GetCenteredAxisOffsetComponent(...)100%11100%
File 5: GetComponentDifference(...)100%11100%
File 5: GetScaledDifference(...)100%11100%
File 5: ScaleByCenteredAxis(...)100%11100%
File 5: TrySolveUnitQuadratic(...)100%11100%
File 6: GetSurfaceAnchorOnCenteredCapsule(...)100%11100%
File 6: GetSurfaceAnchorOnCenteredCapsule(...)100%11100%
File 6: GetSurfaceAnchorOnCenteredCapsule(...)100%11100%
File 7: TryGetDistanceToCenteredCapsule(...)100%11100%
File 7: TryGetDistanceToCenteredCapsule(...)100%11100%
File 7: TryGetDistanceToCenteredCapsule(...)100%1010100%
File 8: .ctor(...)100%11100%
File 8: TryGetSweptCenteredCapsuleSegmentFirstDistance(...)100%11100%
File 8: TryGetSweptCenteredCapsuleOriginOffsetSegmentFirstDistance(...)100%11100%
File 8: TryGetSweptOriginOffsetSegmentsFirstDistance(...)100%11100%
File 8: TryGetSweptCenteredCapsulesFirstDistance(...)100%11100%
File 8: TryGetSweptAxesFirstDistance(...)100%66100%
File 8: TryKeepEndpointAxisSweep(...)100%1010100%
File 8: GetAxisSweepFallbackNormal(...)100%44100%
File 8: TryKeepCircleSweep(...)100%11100%
File 8: TryKeepSideSweep(...)100%1010100%
File 8: IsWithinAxisAtDistance(...)100%22100%
File 8: KeepFirstSweepRoot(...)100%66100%
File 8: GetEndpointAxisNormal(...)100%44100%
File 8: GetPointAtDistance(...)100%11100%
File 8: AxesIntersect(...)100%1818100%
File 8: Orientation(...)100%11100%
File 8: IsWithinBounds(...)100%22100%
File 8: IsBetween(...)100%44100%
File 8: GetSweepVelocity(...)100%11100%
File 8: GetCenteredAxisEndpoints(...)100%11100%
File 8: GetAuthoredAxisEndpoints(...)100%11100%
File 8: GetRotatedOriginOffsetAxisEndpoints(...)100%11100%
File 8: GetRotatedOriginOffsetCoordinate(...)100%11100%
File 8: GetCenteredEndpointNumerator(...)100%22100%
File 8: ScaleAuthoredCoordinate(...)100%11100%
File 9: TryGetClosestCenteredFiniteConeSurfaceAnchor(...)100%22100%
File 9: GetClosestCenteredFiniteConeSurfaceAnchor(...)100%22100%
File 9: GetRigidCenteredConeMeridian(...)100%22100%
File 9: GetClosestCenteredConeSideCoordinates(...)100%44100%
File 9: GetCenteredConeSideApproximation(...)100%22100%
File 9: RoundBoundedCenteredConeCoordinate(...)100%1010100%
File 9: CompareCenteredConeCoordinateToRaw(...)100%11100%
File 9: GetCenteredConeHeightRelation(...)100%11100%
File 9: IsPointContainedInRigidCenteredCone(...)100%22100%
File 9: IsCenteredConeSideNearest(...)100%44100%
File 9: GetCenteredConeSideParameterNumerator(...)100%11100%
File 9: CompareCenteredConeSideParameterToEndpoint(...)100%22100%
File 9: CompareCenteredConeApexToBaseDistance(...)100%44100%
File 9: CompareCenteredConeInteriorSideToBaseDistance(...)100%44100%
File 10: TryGetClosestCenteredCapsuleSurfaceAnchor(...)100%22100%
File 10: GetClosestCenteredCapsuleSurfaceAnchor(...)100%11100%
File 10: GetLocalCapsuleSurfaceDirection(...)100%22100%
File 10: GetLocalCapsuleCapDelta(...)100%11100%
File 10: TryGetClosestCenteredFiniteCylinderSurfaceAnchor(...)100%22100%
File 10: GetClosestCenteredFiniteCylinderSurfaceAnchor(...)100%2222100%
File 10: TryGetSignedSurfaceDistance(...)100%66100%
File 10: CreateCenteredCylinderSideAnchor(...)100%44100%
File 10: CreateCenteredCapsuleAnchors(...)100%44100%
File 10: GetClosestCenteredRigidAxisDistance(...)100%44100%
File 10: CreateCenteredSurfaceAnchor(...)100%11100%
File 10: TryGetCenteredRadialDistance(...)100%66100%
File 10: GetNonNegativeComparisonIncrement(...)100%11100%
File 10: GetLocalRadialDirection(...)100%22100%
File 10: GetProjection(...)100%11100%
File 10: GetCenteredCap(...)100%22100%
File 10: GetCenteredRadialBound(...)100%11100%
File 10: GetLocalRadialComponents(...)100%11100%
File 10: GetLocalRadialComponent(...)100%11100%
File 10: CompareSigned576(...)100%11100%
File 10: CompareMagnitudeSigned576(...)100%22100%
File 11: DoesCenteredFiniteConeOverlapSphere(...)100%44100%
File 11: TryGetClosestPointOnCenteredFiniteConeSurface(...)100%44100%
File 11: TryGetClosestCenteredFiniteConeSurfaceOffset(...)100%44100%
File 11: TryGetClosestPointOnCenteredFiniteCylinderSurface(...)100%44100%
File 11: TryGetClosestCenteredFiniteCylinderSurfaceOffset(...)100%44100%
File 11: GetCenteredConeSideNormal(...)100%11100%
File 12: TryGetTriangleSupportPointContact(...)100%11100%
File 12: TryGetTriangleSupportContactOffsets(...)100%1010100%
File 12: GetSupportDifference(...)100%11100%
File 12: GetProjectedCoordinateNumerator(...)100%11100%
File 12: GetAbsoluteCoordinateNumerator(...)100%11100%
File 12: TryGetTriangleOriginOffsetCoordinate(...)100%11100%
File 13: ContainsPointInCenteredFiniteCylinder(...)100%11100%
File 13: ContainsPointInCenteredFiniteCylinder(...)100%11100%
File 13: IsCapsulePointContained(...)100%66100%
File 13: IsFiniteCylinderPointContained(...)100%1010100%
File 13: IsCenteredFiniteCylinderPointContained(...)100%1010100%
File 13: IsWithinRadius(...)100%22100%
File 13: GetRadialConstant(...)100%11100%
File 14: .cctor()100%11100%
File 14: .ctor(...)100%11100%
File 14: .ctor(...)100%11100%
File 14: TryGetCapsuleInterval(...)100%22100%
File 14: TryGetCapsuleInterval(...)100%22100%
File 14: TryGetFiniteCylinderInterval(...)100%11100%
File 14: TryGetFiniteCylinderInterval(...)100%22100%
File 14: TryGetFiniteAxisInterval(...)100%11100%
File 14: TryGetFiniteAxisInterval(...)100%3232100%
File 14: TryGetAxialInterval(...)100%1414100%
File 14: TryGetCenteredAxialInterval(...)100%1414100%
File 14: GetCenteredAxialExtent(...)100%11100%
File 14: GetCenteredAxialExtent(...)100%11100%
File 14: Normalize(...)100%22100%
File 14: Normalize(...)100%22100%
File 14: Compare(...)100%11100%
File 14: Compare(...)100%11100%
File 14: GetMaximumBound(...)100%11100%
File 14: GetMaximumBound320(...)100%11100%
File 14: Round(...)100%11100%
File 14: Round(...)100%11100%
File 14: TryGetCircleInterval(...)100%11100%
File 14: TryGetSphereInterval(...)100%11100%
File 14: GetExpandedRadius(...)100%11100%
File 14: GetSquaredRadius(...)100%11100%
File 14: GetDot(...)100%11100%
File 14: GetDot(...)100%11100%
File 14: Merge(...)100%88100%
File 14: TrySolveBoundedQuadratic(...)100%3030100%
File 15: TryGetCircleDirectionDistanceInterval(...)100%11100%
File 15: TryGetSphereDirectionDistanceInterval(...)100%11100%
File 15: TryGetCircleDistanceInterval(...)100%11100%
File 15: TryGetSphereDistanceInterval(...)100%11100%
File 15: TryGetCapsuleDistanceInterval(...)100%22100%
File 15: TryGetCapsuleDistanceInterval(...)100%22100%
File 15: TryGetCapsuleDistanceInterval(...)100%22100%
File 15: TryGetCapsuleDistanceInterval(...)100%22100%
File 15: TryGetFiniteCylinderDistanceInterval(...)100%11100%
File 15: TryGetFiniteCylinderDistanceInterval(...)100%11100%
File 15: TryGetFiniteCylinderDistanceInterval(...)100%22100%
File 15: TryGetFiniteAxisDistanceInterval(...)100%22100%
File 15: TryGetFiniteAxisDistanceInterval(...)100%11100%
File 15: TryGetCircleDistanceInterval(...)100%11100%
File 15: TryGetSphereDistanceInterval(...)100%11100%
File 15: MergeCenteredCapDistanceInterval(...)100%11100%
File 15: MergeCenteredCapDistanceInterval(...)100%11100%
File 16: TrySolveUnitQuadraticAtDistance(...)100%11100%
File 16: TrySolveBoundedQuadraticAtDistance(...)100%2222100%
File 16: RoundLowerRootAtDistance(...)100%66100%
File 16: RoundUpperRootAtDistance(...)100%66100%
File 16: RoundAtDistance(...)100%11100%
File 16: SquareRaw(...)100%11100%
File 17: TryGetNarrowRadialCoefficients(...)100%44100%
File 17: GetMagnitudeBitLength(...)100%22100%
File 17: GetTrailingZeroCount(...)100%66100%
File 17: CountTrailingZeroes(...)100%11100%
File 17: ShiftRightExact(...)100%11100%
File 17: GetShiftedWord(...)100%22100%
File 17: GetSignedWord(...)100%88100%
File 18: TryGetCapsuleInterval(...)100%44100%
File 18: TryGetCapsuleInterval(...)100%44100%
File 18: TryGetCapsuleInterval(...)100%22100%
File 18: TryGetCapsuleInterval(...)100%22100%
File 18: TryGetFiniteCylinderInterval(...)100%11100%
File 18: TryGetFiniteCylinderInterval(...)100%22100%
File 18: IsCapsuleContainedAtParameter(...)100%66100%
File 18: IsCapsuleContainedAtParameter(...)100%66100%
File 18: IsFiniteCylinderContainedAtParameter(...)100%44100%
File 18: IsCenteredFiniteCylinderContainedAtParameter(...)100%44100%
File 18: IsCenteredCapsuleContainedAtParameter(...)100%22100%
File 18: IsCenteredCapsuleContainedAtParameter(...)100%22100%
File 18: GetCenteredCap(...)100%22100%
File 18: MergeCenteredCapInterval(...)100%11100%
File 18: MergeCenteredCapInterval(...)100%11100%
File 18: GetCenteredCapPolynomial(...)100%11100%
File 18: GetCenteredCapPolynomial(...)100%11100%
File 18: EvaluateLinear(...)100%11100%
File 18: GetRadialPolynomial(...)100%11100%
File 18: IsQuadraticContained(...)100%11100%
File 18: IsQuadraticContained(...)100%11100%
File 18: TryGetCircleInterval(...)100%11100%
File 18: TryGetSphereInterval(...)100%11100%
File 18: GetDirectionDot(...)100%11100%
File 18: GetDirectionDot(...)100%11100%
File 18: GetDirectionDot(...)100%11100%
File 18: GetDirectionDot(...)100%11100%
File 19: .ctor(...)100%11100%
File 19: GetRigidLocalPointRelation(...)100%11100%
File 20: RoundLowerRoot(...)100%66100%
File 20: RoundUpperRoot(...)100%66100%
File 20: ShiftLeftByFixed64FractionalBits(...)100%11100%
File 20: EvaluatePolynomial(...)100%11100%
File 20: EvaluateDerivative(...)100%11100%
File 20: EvaluatePolynomial(...)100%11100%
File 20: EvaluateDerivative(...)100%11100%
File 21: .ctor(...)100%11100%
File 21: TryGetSphericallyExpandedBoxFirstDistance(...)100%1414100%
File 21: TryGetSphericallyExpandedProjectedBoxFirstDistance(...)100%1818100%
File 21: AddAxisBreakpoints(...)100%1616100%
File 21: AddProjectedAxisBreakpoints(...)100%1616100%
File 21: AddBreakpoint(...)100%44100%
File 21: AddProjectedBreakpoint(...)100%44100%
File 21: SortBreakpoints(...)100%66100%
File 21: GetBoxDistancePolynomial(...)100%11100%
File 21: GetProjectedBoxDistancePolynomial(...)100%11100%
File 21: AddBoxAxisPolynomial(...)100%44100%
File 21: AddProjectedBoxAxisPolynomial(...)100%44100%
File 21: IsWithinProjectedRoundedBox(...)100%11100%
File 21: GetProjectedBoxAxisOffset(...)100%44100%
File 22: .ctor(...)100%11100%
File 22: .ctor(...)100%11100%
File 22: .cctor()100%11100%
File 22: .ctor(...)100%11100%
File 22: DoesCenteredFiniteCylinderOverlapSphere(...)100%11100%
File 22: TryGetSphericallyExpandedFiniteCylinderDistanceInterval(...)100%11100%
File 22: TryGetSphericallyExpandedFiniteCylinderFirstDistance(...)100%11100%
File 22: TryGetSphericallyExpandedFiniteCylinderFirstDistanceFromHalfAxisLength(...)100%11100%
File 22: TryGetSphericallyExpandedFiniteCylinderDirectionFirstDistanceFromHalfAxisLength(...)100%22100%
File 22: TryGetSphericallyExpandedFiniteCylinderDistanceIntervalWithFullAxisLength(...)100%44100%
File 22: TryGetSphericallyExpandedFiniteCylinderDistanceInterval(...)100%22100%
File 22: MergeSphericallyExpandedFiniteCylinderRoundedIntervals(...)100%44100%
File 22: TryGetRoundedCylinderCapCoreDistanceInterval(...)100%2020100%
File 22: RoundedCylinderRimBoundsIntersect(...)100%11100%
File 22: CreateRoundedCylinderQuadraticBound(...)100%66100%
File 22: MergeRoundedCylinderRimInterval(...)100%11100%
File 22: IsPointInRoundedCylinderRimTube(...)100%1414100%
File 22: TryGetFiniteCylinderDirectionFirstDistance(...)100%22100%
File 22: CreateRoundedCylinderBaseData(...)100%11100%
File 22: CreateRoundedCylinderBaseData(...)100%11100%
File 22: CreateRoundedCylinderBaseData(...)100%11100%
File 22: CreateRoundedCylinderTorusPolynomial(...)100%22100%
File 22: MultiplyToSigned320(...)100%11100%
File 22: MultiplyToSigned320(...)100%11100%
File 22: Twice(...)100%11100%
File 22: Four(...)100%11100%
File 22: Twice(...)100%11100%
File 22: AddFive(...)100%11100%
File 23: ImportRoundedCylinderCoefficient(...)100%11100%
File 23: ImportRoundedCylinderCoefficient(...)100%11100%
File 23: GetRoundedCylinderCoefficient(...)100%11100%
File 23: GetRoundedCylinderCoefficientIndex(...)100%11100%
File 23: AddRoundedCylinderSigned(...)100%66100%
File 23: SubtractRoundedCylinderSigned(...)100%1818100%
File 23: MultiplyRoundedCylinderWide(...)100%44100%
File 23: MultiplyRoundedCylinderWideByWord(...)100%44100%
File 23: AddRoundedCylinderWord(...)100%22100%
File 23: MultiplyRoundedCylinderSigns(...)100%44100%
File 23: GetRoundedCylinderWideLength(...)100%44100%
File 23: CopyRoundedCylinderWide(...)100%11100%
File 23: CountRoundedCylinderTrailingZeroes(...)100%44100%
File 23: ShiftRoundedCylinderWideRight(...)100%66100%
File 24: CountProjectionDomainQuarticRoots(...)100%66100%
File 24: GetRoundedCylinderInfinityVariations(...)100%1010100%
File 24: TryGetRoundedCylinderRimDistanceInterval(...)100%1818100%
File 24: FindRoundedCylinderRoot(...)100%2222100%
File 24: FindRoundedCylinderSignChangingRoot(...)100%1010100%
File 24: HomogenizeRoundedCylinderSturmSequence(...)100%66100%
File 24: IsRoundedCylinderEntryBeforeOrEqualToExit(...)100%1212100%
File 24: GetRoundedCylinderRadicalSquare(...)100%11100%
File 24: ImportRoundedCylinderWide(...)100%11100%
File 24: ImportRoundedCylinderWide(...)100%11100%
File 24: GetRoundedCylinderSignVariations(...)100%88100%
File 24: EvaluateRoundedCylinderPolynomialSign(...)100%44100%
File 24: EvaluateRoundedCylinderPolynomialSignAtInteger(...)100%22100%
File 24: BuildRoundedCylinderSturmSequence(...)100%66100%
File 24: BuildRoundedCylinderQuarticSturmSequence(...)100%1616100%
File 24: SetRoundedCylinderProduct(...)100%11100%
File 24: SetRoundedCylinderScaledProduct(...)100%11100%
File 24: SetRoundedCylinderTripleProduct(...)100%11100%
File 24: BuildRoundedCylinderNegativeRemainder(...)100%1818100%
File 24: RemoveRoundedCylinderCommonPowerOfTwo(...)100%88100%
File 24: TrimRoundedCylinderPolynomial(...)100%44100%
File 25: .cctor()100%11100%
File 25: TryGetCenteredAxisEndpoint(...)100%11100%
File 25: TryGetCenteredAxisEndpoint(...)100%11100%
File 25: TryGetCenteredCapsuleSupport(...)100%22100%
File 25: GetCenteredCapsuleSupportAnchor(...)100%88100%
File 25: TryGetCenteredCapsuleSupport(...)100%22100%
File 25: TryGetCenteredFiniteCylinderSupport(...)100%11100%
File 25: TryGetCenteredFiniteConeSupport(...)100%1010100%
File 25: TryGetCenteredSupport(...)100%22100%
File 25: TryGetCenteredSupport(...)100%22100%
File 25: TryGetSupportCoordinate(...)100%2222100%
File 25: CompareSupportCoordinateToMidpoint(...)100%66100%
File 25: IsCenteredFiniteConeApexSupport(...)100%11100%
File 25: IsCenteredFiniteConeApexSupportCore(...)100%66100%
File 25: GetDirection(...)100%11100%
File 25: GetDirection(...)100%11100%
File 25: GetPlaneDirection(...)100%11100%
File 25: GetMinimumMidpoint()100%11100%
File 25: GetMaximumMidpoint()100%11100%

File(s)

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredAxes.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.CenteredAxes.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
 8namespace FixedMathSharp.Geometry;
 9
 10/// <content>
 11/// Contains logic for computing closest-point intersections between finite axes
 12/// defined relative to centered (origin-relative) coordinate frames, using
 13/// wide-precision (Signed320/576/832) arithmetic for numerical stability.
 14/// </content>
 15internal static partial class WideFiniteAxisIntersection
 16{
 17    #region NestedTypes
 18
 19    private readonly struct CenteredAxesCandidate
 20    {
 21        internal readonly Signed576 FirstX;
 22        internal readonly Signed576 FirstY;
 23        internal readonly Signed576 FirstZ;
 24        internal readonly Signed576 SecondX;
 25        internal readonly Signed576 SecondY;
 26        internal readonly Signed576 SecondZ;
 27        internal readonly Signed320 FirstParameterNumerator;
 28        internal readonly Signed320 SecondParameterNumerator;
 29        internal readonly Signed320 ParameterDenominator;
 30        internal readonly Signed832 SquaredDistanceNumerator;
 31
 32        internal CenteredAxesCandidate(
 33            Signed576 firstX,
 34            Signed576 firstY,
 35            Signed576 firstZ,
 36            Signed576 secondX,
 37            Signed576 secondY,
 38            Signed576 secondZ,
 39            Signed320 firstParameterNumerator,
 40            Signed320 secondParameterNumerator,
 41            Signed320 parameterDenominator,
 42            Signed832 squaredDistanceNumerator)
 43        {
 54144            FirstX = firstX;
 54145            FirstY = firstY;
 54146            FirstZ = firstZ;
 54147            SecondX = secondX;
 54148            SecondY = secondY;
 54149            SecondZ = secondZ;
 54150            FirstParameterNumerator = firstParameterNumerator;
 54151            SecondParameterNumerator = secondParameterNumerator;
 54152            ParameterDenominator = parameterDenominator;
 54153            SquaredDistanceNumerator = squaredDistanceNumerator;
 54154        }
 55    }
 56
 57    private readonly struct CenteredAxesCandidate2d
 58    {
 59        internal readonly Signed576 FirstX;
 60        internal readonly Signed576 FirstY;
 61        internal readonly Signed576 SecondX;
 62        internal readonly Signed576 SecondY;
 63        internal readonly Signed320 ParameterDenominator;
 64        internal readonly Signed832 SquaredDistanceNumerator;
 65
 66        internal CenteredAxesCandidate2d(
 67            Signed576 firstX,
 68            Signed576 firstY,
 69            Signed576 secondX,
 70            Signed576 secondY,
 71            Signed320 parameterDenominator,
 72            Signed832 squaredDistanceNumerator)
 73        {
 923074            FirstX = firstX;
 923075            FirstY = firstY;
 923076            SecondX = secondX;
 923077            SecondY = secondY;
 923078            ParameterDenominator = parameterDenominator;
 923079            SquaredDistanceNumerator = squaredDistanceNumerator;
 923080        }
 81    }
 82
 83    #endregion
 84
 85    internal static bool TryGetDistanceToCenteredAxis(
 86        Vector2d point,
 87        Vector2d center,
 88        Vector2d axis,
 89        Fixed64 axisLength,
 90        out Fixed64 distance) =>
 291        TryGetDistanceToCenteredCapsule(
 292            point,
 293            center,
 294            axis,
 295            axisLength,
 296            Fixed64.Zero,
 297            out distance);
 98
 99    internal static bool TryGetDistanceToCenteredAxis(
 100        Vector3d point,
 101        Vector3d center,
 102        Vector3d axis,
 103        Fixed64 axisLength,
 104        out Fixed64 distance) =>
 3105        TryGetDistanceToCenteredCapsule(
 3106            point,
 3107            center,
 3108            axis,
 3109            axisLength,
 3110            Fixed64.Zero,
 3111            out distance);
 112
 113    internal static bool TryGetDistanceBetweenCenteredAxes(
 114        Vector2d firstCenter,
 115        Vector2d firstAxis,
 116        Fixed64 firstLength,
 117        Vector2d secondCenter,
 118        Vector2d secondAxis,
 119        Fixed64 secondLength,
 120        out Fixed64 distance)
 121    {
 4610122        GetCenteredAxesSquaredDistance(
 4610123            firstCenter,
 4610124            firstAxis,
 4610125            firstLength,
 4610126            secondCenter,
 4610127            secondAxis,
 4610128            secondLength,
 4610129            out Signed832 squaredNumerator,
 4610130            out Signed320 denominator);
 4610131        return TryRoundCenteredAxesDistance(
 4610132            squaredNumerator,
 4610133            denominator,
 4610134            out distance);
 135    }
 136
 137    internal static bool TryGetDistanceBetweenCenteredAxes(
 138        Vector3d firstCenter,
 139        Vector3d firstAxis,
 140        Fixed64 firstLength,
 141        Vector3d secondCenter,
 142        Vector3d secondAxis,
 143        Fixed64 secondLength,
 144        out Fixed64 distance)
 145    {
 263146        GetCenteredAxesSquaredDistance(
 263147            firstCenter,
 263148            firstAxis,
 263149            firstLength,
 263150            secondCenter,
 263151            secondAxis,
 263152            secondLength,
 263153            out Signed832 squaredNumerator,
 263154            out Signed320 denominator);
 263155        return TryRoundCenteredAxesDistance(
 263156            squaredNumerator,
 263157            denominator,
 263158            out distance);
 159    }
 160
 161    internal static bool DoCenteredCapsulesOverlap(
 162        Vector2d firstCenter,
 163        Vector2d firstAxis,
 164        Fixed64 firstLength,
 165        Fixed64 firstRadius,
 166        Vector2d secondCenter,
 167        Vector2d secondAxis,
 168        Fixed64 secondLength,
 169        Fixed64 secondRadius)
 170    {
 4612171        GetCenteredAxesSquaredDistance(
 4612172            firstCenter,
 4612173            firstAxis,
 4612174            firstLength,
 4612175            secondCenter,
 4612176            secondAxis,
 4612177            secondLength,
 4612178            out Signed832 squaredNumerator,
 4612179            out Signed320 denominator);
 4612180        return IsWithinCombinedRadius(
 4612181            squaredNumerator,
 4612182            denominator,
 4612183            firstRadius,
 4612184            secondRadius);
 185    }
 186
 187    internal static bool DoCenteredCapsulesOverlap(
 188        Vector3d firstCenter,
 189        Vector3d firstAxis,
 190        Fixed64 firstLength,
 191        Fixed64 firstRadius,
 192        Vector3d secondCenter,
 193        Vector3d secondAxis,
 194        Fixed64 secondLength,
 195        Fixed64 secondRadius)
 196    {
 257197        GetCenteredAxesSquaredDistance(
 257198            firstCenter,
 257199            firstAxis,
 257200            firstLength,
 257201            secondCenter,
 257202            secondAxis,
 257203            secondLength,
 257204            out Signed832 squaredNumerator,
 257205            out Signed320 denominator);
 257206        return IsWithinCombinedRadius(
 257207            squaredNumerator,
 257208            denominator,
 257209            firstRadius,
 257210            secondRadius);
 211    }
 212
 213    internal static bool TryGetCenteredCapsulesContact(
 214        Vector2d firstCenter,
 215        Fixed64 firstAnchorRotation,
 216        Vector2d firstAxis,
 217        Fixed64 firstLength,
 218        Fixed64 firstRadius,
 219        Vector2d secondCenter,
 220        Fixed64 secondAnchorRotation,
 221        Vector2d secondAxis,
 222        Fixed64 secondLength,
 223        Fixed64 secondRadius,
 224        Vector2d fallbackNormal,
 225        out FixedContactAnchors2d contact)
 226    {
 8227        GetCenteredAxesCandidate(
 8228            firstCenter,
 8229            firstAxis,
 8230            firstLength,
 8231            secondCenter,
 8232            secondAxis,
 8233            secondLength,
 8234            out CenteredAxesCandidate2d candidate);
 8235        if (!IsWithinCombinedRadius(
 8236                candidate.SquaredDistanceNumerator,
 8237                candidate.ParameterDenominator,
 8238                firstRadius,
 8239                secondRadius))
 240        {
 1241            contact = default;
 1242            return false;
 243        }
 244
 7245        Vector2d normal = WideNormalization.GetNormalized(
 7246            WideArithmetic.SubtractSigned576(candidate.SecondX, candidate.FirstX),
 7247            WideArithmetic.SubtractSigned576(candidate.SecondY, candidate.FirstY));
 7248        if (normal == Vector2d.Zero)
 4249            normal = fallbackNormal;
 250
 7251        GetLocalRadialFeature(
 7252            normal,
 7253            firstRadius,
 7254            firstAnchorRotation,
 7255            out Vector2d firstLocalRadialDirection,
 7256            out Vector2d firstRadialOffset);
 7257        GetLocalRadialFeature(
 7258            -normal,
 7259            secondRadius,
 7260            secondAnchorRotation,
 7261            out Vector2d secondLocalRadialDirection,
 7262            out Vector2d secondRadialOffset);
 7263        Vector2d firstAxisOffset = GetCenteredAxisLocalOffset(
 7264            candidate.FirstX,
 7265            candidate.FirstY,
 7266            firstCenter,
 7267            candidate.ParameterDenominator,
 7268            firstAnchorRotation);
 7269        Vector2d secondAxisOffset = GetCenteredAxisLocalOffset(
 7270            candidate.SecondX,
 7271            candidate.SecondY,
 7272            secondCenter,
 7273            candidate.ParameterDenominator,
 7274            secondAnchorRotation);
 7275        _ = TryGetCenteredCapsulesDepth(
 7276            candidate.SquaredDistanceNumerator,
 7277            candidate.ParameterDenominator,
 7278            firstRadius,
 7279            secondRadius,
 7280            out Fixed64 depth,
 7281            out bool depthIsClamped);
 7282        contact = new FixedContactAnchors2d(
 7283            new FixedPointAnchor2d(
 7284                firstCenter,
 7285                firstAnchorRotation,
 7286                firstAxisOffset,
 7287                firstRadialOffset,
 7288                FixedPointAnchorTerm2d.CreateRadialSupport(
 7289                    firstLocalRadialDirection,
 7290                    firstRadius,
 7291                    firstRadialOffset)),
 7292            new FixedPointAnchor2d(
 7293                secondCenter,
 7294                secondAnchorRotation,
 7295                secondAxisOffset,
 7296                secondRadialOffset,
 7297                FixedPointAnchorTerm2d.CreateRadialSupport(
 7298                    secondLocalRadialDirection,
 7299                    secondRadius,
 7300                    secondRadialOffset)),
 7301            normal,
 7302            depth,
 7303            depthIsClamped);
 7304        return true;
 305    }
 306
 307    internal static bool TryGetCenteredCapsulesContact(
 308        Vector3d firstCenter,
 309        FixedQuaternion firstRotation,
 310        Vector3d firstLocalAxis,
 311        Vector3d firstAxis,
 312        Fixed64 firstLength,
 313        Fixed64 firstRadius,
 314        Vector3d secondCenter,
 315        FixedQuaternion secondRotation,
 316        Vector3d secondLocalAxis,
 317        Vector3d secondAxis,
 318        Fixed64 secondLength,
 319        Fixed64 secondRadius,
 320        Vector3d fallbackNormal,
 321        out FixedContactAnchors contact)
 322    {
 20323        GetCenteredAxesCandidate(
 20324            firstCenter,
 20325            firstAxis,
 20326            firstLength,
 20327            secondCenter,
 20328            secondAxis,
 20329            secondLength,
 20330            out CenteredAxesCandidate candidate);
 20331        Signed576 differenceX = WideArithmetic.SubtractSigned576(
 20332            candidate.SecondX,
 20333            candidate.FirstX);
 20334        Signed576 differenceY = WideArithmetic.SubtractSigned576(
 20335            candidate.SecondY,
 20336            candidate.FirstY);
 20337        Signed576 differenceZ = WideArithmetic.SubtractSigned576(
 20338            candidate.SecondZ,
 20339            candidate.FirstZ);
 20340        Vector3d normal = WideNormalization.GetNormalized(
 20341            differenceX,
 20342            differenceY,
 20343            differenceZ);
 20344        if (normal.IsZero)
 4345            normal = fallbackNormal;
 346
 20347        _ = TryGetCenteredAxisPointCoordinate(
 20348            Fixed64.Zero,
 20349            firstLocalAxis.X,
 20350            candidate.FirstParameterNumerator,
 20351            candidate.ParameterDenominator,
 20352            out Fixed64 firstX);
 20353        _ = TryGetCenteredAxisPointCoordinate(
 20354            Fixed64.Zero,
 20355            firstLocalAxis.Y,
 20356            candidate.FirstParameterNumerator,
 20357            candidate.ParameterDenominator,
 20358            out Fixed64 firstY);
 20359        _ = TryGetCenteredAxisPointCoordinate(
 20360            Fixed64.Zero,
 20361            firstLocalAxis.Z,
 20362            candidate.FirstParameterNumerator,
 20363            candidate.ParameterDenominator,
 20364            out Fixed64 firstZ);
 20365        _ = TryGetCenteredAxisPointCoordinate(
 20366            Fixed64.Zero,
 20367            secondLocalAxis.X,
 20368            candidate.SecondParameterNumerator,
 20369            candidate.ParameterDenominator,
 20370            out Fixed64 secondX);
 20371        _ = TryGetCenteredAxisPointCoordinate(
 20372            Fixed64.Zero,
 20373            secondLocalAxis.Y,
 20374            candidate.SecondParameterNumerator,
 20375            candidate.ParameterDenominator,
 20376            out Fixed64 secondY);
 20377        _ = TryGetCenteredAxisPointCoordinate(
 20378            Fixed64.Zero,
 20379            secondLocalAxis.Z,
 20380            candidate.SecondParameterNumerator,
 20381            candidate.ParameterDenominator,
 20382            out Fixed64 secondZ);
 20383        _ = TryGetCenteredCapsulesDepth(
 20384            candidate.SquaredDistanceNumerator,
 20385            candidate.ParameterDenominator,
 20386            firstRadius,
 20387            secondRadius,
 20388            out Fixed64 depth,
 20389            out bool depthIsClamped);
 20390        depth = FixedMath.Max(depth, Fixed64.Zero);
 20391        Vector3d firstLocalRadialDirection = WideNormalization.GetNormalized(
 20392            firstRotation.Inverse().Rotate(normal));
 20393        Vector3d secondLocalRadialDirection = WideNormalization.GetNormalized(
 20394            secondRotation.Inverse().Rotate(-normal));
 20395        Vector3d firstRadialOffset =
 20396            firstLocalRadialDirection * firstRadius;
 20397        Vector3d secondRadialOffset =
 20398            secondLocalRadialDirection * secondRadius;
 20399        contact = new FixedContactAnchors(
 20400            new FixedPointAnchor(
 20401                firstCenter,
 20402                firstRotation,
 20403                new Vector3d(firstX, firstY, firstZ),
 20404                firstRadialOffset,
 20405                FixedPointAnchorTerm3d.CreateRadialSupport(
 20406                    firstLocalRadialDirection,
 20407                    firstRadius,
 20408                    firstRadialOffset)),
 20409            new FixedPointAnchor(
 20410                secondCenter,
 20411                secondRotation,
 20412                new Vector3d(secondX, secondY, secondZ),
 20413                secondRadialOffset,
 20414                FixedPointAnchorTerm3d.CreateRadialSupport(
 20415                    secondLocalRadialDirection,
 20416                    secondRadius,
 20417                    secondRadialOffset)),
 20418            normal,
 20419            depth,
 20420            depthIsClamped);
 20421        return true;
 422    }
 423
 424    internal static bool TryGetClosestPointsBetweenCenteredAxes(
 425        Vector2d firstCenter,
 426        Vector2d firstAxis,
 427        Fixed64 firstLength,
 428        Vector2d secondCenter,
 429        Vector2d secondAxis,
 430        Fixed64 secondLength,
 431        out Vector2d firstPoint,
 432        out Vector2d secondPoint)
 433    {
 4434        GetClosestCenteredAxisParameters(
 4435            GetDot(firstAxis, Vector2d.Zero, firstAxis, Vector2d.Zero),
 4436            GetDot(firstAxis, Vector2d.Zero, secondAxis, Vector2d.Zero),
 4437            GetDot(secondAxis, Vector2d.Zero, secondAxis, Vector2d.Zero),
 4438            GetDot(firstCenter, secondCenter, firstAxis, Vector2d.Zero),
 4439            GetDot(firstCenter, secondCenter, secondAxis, Vector2d.Zero),
 4440            firstLength,
 4441            secondLength,
 4442            out Signed320 firstNumerator,
 4443            out Signed320 secondNumerator,
 4444            out Signed320 denominator);
 445
 4446        bool representable = TryGetCenteredAxisPointCoordinate(
 4447            firstCenter.X, firstAxis.X, firstNumerator, denominator, out Fixed64 firstX);
 4448        representable &= TryGetCenteredAxisPointCoordinate(
 4449            firstCenter.Y, firstAxis.Y, firstNumerator, denominator, out Fixed64 firstY);
 4450        representable &= TryGetCenteredAxisPointCoordinate(
 4451            secondCenter.X, secondAxis.X, secondNumerator, denominator, out Fixed64 secondX);
 4452        representable &= TryGetCenteredAxisPointCoordinate(
 4453            secondCenter.Y, secondAxis.Y, secondNumerator, denominator, out Fixed64 secondY);
 4454        if (!representable)
 455        {
 3456            firstPoint = default;
 3457            secondPoint = default;
 3458            return false;
 459        }
 460
 1461        firstPoint = new Vector2d(firstX, firstY);
 1462        secondPoint = new Vector2d(secondX, secondY);
 1463        return true;
 464    }
 465
 466    internal static bool TryGetClosestPointsBetweenCenteredAxes(
 467        Vector3d firstCenter,
 468        Vector3d firstAxis,
 469        Fixed64 firstLength,
 470        Vector3d secondCenter,
 471        Vector3d secondAxis,
 472        Fixed64 secondLength,
 473        out Vector3d firstPoint,
 474        out Vector3d secondPoint)
 475    {
 137476        GetClosestCenteredAxisParameters(
 137477            GetDot(firstAxis, Vector3d.Zero, firstAxis, Vector3d.Zero),
 137478            GetDot(firstAxis, Vector3d.Zero, secondAxis, Vector3d.Zero),
 137479            GetDot(secondAxis, Vector3d.Zero, secondAxis, Vector3d.Zero),
 137480            GetDot(firstCenter, secondCenter, firstAxis, Vector3d.Zero),
 137481            GetDot(firstCenter, secondCenter, secondAxis, Vector3d.Zero),
 137482            firstLength,
 137483            secondLength,
 137484            out Signed320 firstNumerator,
 137485            out Signed320 secondNumerator,
 137486            out Signed320 denominator);
 487
 137488        bool representable = TryGetCenteredAxisPointCoordinate(
 137489            firstCenter.X, firstAxis.X, firstNumerator, denominator, out Fixed64 firstX);
 137490        representable &= TryGetCenteredAxisPointCoordinate(
 137491            firstCenter.Y, firstAxis.Y, firstNumerator, denominator, out Fixed64 firstY);
 137492        representable &= TryGetCenteredAxisPointCoordinate(
 137493            firstCenter.Z, firstAxis.Z, firstNumerator, denominator, out Fixed64 firstZ);
 137494        representable &= TryGetCenteredAxisPointCoordinate(
 137495            secondCenter.X, secondAxis.X, secondNumerator, denominator, out Fixed64 secondX);
 137496        representable &= TryGetCenteredAxisPointCoordinate(
 137497            secondCenter.Y, secondAxis.Y, secondNumerator, denominator, out Fixed64 secondY);
 137498        representable &= TryGetCenteredAxisPointCoordinate(
 137499            secondCenter.Z, secondAxis.Z, secondNumerator, denominator, out Fixed64 secondZ);
 137500        if (!representable)
 501        {
 2502            firstPoint = default;
 2503            secondPoint = default;
 2504            return false;
 505        }
 506
 135507        firstPoint = new Vector3d(firstX, firstY, firstZ);
 135508        secondPoint = new Vector3d(secondX, secondY, secondZ);
 135509        return true;
 510    }
 511
 512    internal static bool TryGetClosestOffsetsBetweenCenteredAxes(
 513        Vector3d firstCenter,
 514        Vector3d firstAxis,
 515        Fixed64 firstLength,
 516        Vector3d secondCenter,
 517        Vector3d secondAxis,
 518        Fixed64 secondLength,
 519        out Vector3d firstCenterOffset,
 520        out Vector3d secondCenterOffset)
 521    {
 1522        GetClosestCenteredAxisParameters(
 1523            GetDot(firstAxis, Vector3d.Zero, firstAxis, Vector3d.Zero),
 1524            GetDot(firstAxis, Vector3d.Zero, secondAxis, Vector3d.Zero),
 1525            GetDot(secondAxis, Vector3d.Zero, secondAxis, Vector3d.Zero),
 1526            GetDot(firstCenter, secondCenter, firstAxis, Vector3d.Zero),
 1527            GetDot(firstCenter, secondCenter, secondAxis, Vector3d.Zero),
 1528            firstLength,
 1529            secondLength,
 1530            out Signed320 firstNumerator,
 1531            out Signed320 secondNumerator,
 1532            out Signed320 denominator);
 533
 534        // A centered-axis offset cannot exceed half of its representable full
 535        // length, so valid normalized axes always narrow successfully here.
 1536        _ = TryGetCenteredAxisPointCoordinate(
 1537            Fixed64.Zero, firstAxis.X, firstNumerator, denominator, out Fixed64 firstX);
 1538        _ = TryGetCenteredAxisPointCoordinate(
 1539            Fixed64.Zero, firstAxis.Y, firstNumerator, denominator, out Fixed64 firstY);
 1540        _ = TryGetCenteredAxisPointCoordinate(
 1541            Fixed64.Zero, firstAxis.Z, firstNumerator, denominator, out Fixed64 firstZ);
 1542        _ = TryGetCenteredAxisPointCoordinate(
 1543            Fixed64.Zero, secondAxis.X, secondNumerator, denominator, out Fixed64 secondX);
 1544        _ = TryGetCenteredAxisPointCoordinate(
 1545            Fixed64.Zero, secondAxis.Y, secondNumerator, denominator, out Fixed64 secondY);
 1546        _ = TryGetCenteredAxisPointCoordinate(
 1547            Fixed64.Zero, secondAxis.Z, secondNumerator, denominator, out Fixed64 secondZ);
 548
 1549        firstCenterOffset = new Vector3d(firstX, firstY, firstZ);
 1550        secondCenterOffset = new Vector3d(secondX, secondY, secondZ);
 1551        return true;
 552    }
 553
 554    internal static Vector3d GetClosestDirectionBetweenCenteredAxes(
 555        Vector3d firstCenter,
 556        Vector3d firstAxis,
 557        Fixed64 firstLength,
 558        Vector3d secondCenter,
 559        Vector3d secondAxis,
 560        Fixed64 secondLength)
 561    {
 1562        GetCenteredAxesCandidate(
 1563            firstCenter,
 1564            firstAxis,
 1565            firstLength,
 1566            secondCenter,
 1567            secondAxis,
 1568            secondLength,
 1569            out CenteredAxesCandidate candidate);
 1570        return WideNormalization.GetNormalized(
 1571            WideArithmetic.SubtractSigned576(candidate.SecondX, candidate.FirstX),
 1572            WideArithmetic.SubtractSigned576(candidate.SecondY, candidate.FirstY),
 1573            WideArithmetic.SubtractSigned576(candidate.SecondZ, candidate.FirstZ));
 574    }
 575}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredAxes.Solver.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.CenteredAxes.Solver.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
 8namespace FixedMathSharp.Geometry;
 9
 10/// <content>
 11/// Solver logic for finding the closest points between two finite axes
 12/// defined relative to their centers, using high-precision wide arithmetic.
 13/// </content>
 14internal static partial class WideFiniteAxisIntersection
 15{
 16    private static void GetClosestCenteredAxisParameters(
 17        Signed192 firstLengthSquared,
 18        Signed192 directionsDot,
 19        Signed192 secondLengthSquared,
 20        Signed192 firstDirectionDotDifference,
 21        Signed192 secondDirectionDotDifference,
 22        Fixed64 firstLength,
 23        Fixed64 secondLength,
 24        out Signed320 firstNumerator,
 25        out Signed320 secondNumerator,
 26        out Signed320 denominator)
 27    {
 991328        Signed320 determinant = WideArithmetic.MultiplySubtract(
 991329            firstLengthSquared,
 991330            secondLengthSquared,
 991331            directionsDot,
 991332            directionsDot);
 991333        if (determinant.Sign > 0)
 34        {
 744535            firstNumerator = WideArithmetic.MultiplySubtract(
 744536                directionsDot,
 744537                secondDirectionDotDifference,
 744538                secondLengthSquared,
 744539                firstDirectionDotDifference);
 744540            secondNumerator = WideArithmetic.MultiplySubtract(
 744541                firstLengthSquared,
 744542                secondDirectionDotDifference,
 744543                directionsDot,
 744544                firstDirectionDotDifference);
 744545            denominator = determinant;
 744546            if (!ClampCenteredAxisParameter(
 744547                    ref firstNumerator,
 744548                    ref denominator,
 744549                    firstLength))
 50            {
 283151                if (!ClampCenteredAxisParameter(
 283152                        ref secondNumerator,
 283153                        ref denominator,
 283154                        secondLength))
 55                {
 224956                    return;
 57                }
 58
 58259                ProjectFirstFromCenteredAxisCap(
 58260                    secondNumerator,
 58261                    firstLengthSquared,
 58262                    directionsDot,
 58263                    firstDirectionDotDifference,
 58264                    out firstNumerator,
 58265                    out denominator);
 58266                if (!ClampCenteredAxisParameter(
 58267                        ref firstNumerator,
 58268                        ref denominator,
 58269                        firstLength))
 70                {
 39071                    secondNumerator = WideArithmetic.MultiplySigned192(
 39072                        new Signed192(
 39073                            secondNumerator.Word2,
 39074                            secondNumerator.Word1,
 39075                            secondNumerator.Word0),
 39076                        firstLengthSquared);
 39077                    return;
 78                }
 79
 19280                SetCenteredAxisCap(ref secondNumerator, ref denominator, secondLength);
 19281                return;
 82            }
 83        }
 84        else
 85        {
 246886            firstNumerator = Signed320.ExtendValue(
 246887                Signed192.Signed(-firstLength.m_rawValue));
 246888            denominator = Signed320.ExtendValue(DoubleParameterScale);
 89        }
 90
 708291        ProjectSecondFromCenteredAxisCap(
 708292            firstNumerator,
 708293            directionsDot,
 708294            secondLengthSquared,
 708295            secondDirectionDotDifference,
 708296            out secondNumerator,
 708297            out denominator);
 708298        if (!ClampCenteredAxisParameter(
 708299                ref secondNumerator,
 7082100                ref denominator,
 7082101                secondLength))
 102        {
 1594103            firstNumerator = WideArithmetic.MultiplySigned192(
 1594104                new Signed192(
 1594105                    firstNumerator.Word2,
 1594106                    firstNumerator.Word1,
 1594107                    firstNumerator.Word0),
 1594108                secondLengthSquared);
 1594109            return;
 110        }
 111
 5488112        ProjectFirstFromCenteredAxisCap(
 5488113            secondNumerator,
 5488114            firstLengthSquared,
 5488115            directionsDot,
 5488116            firstDirectionDotDifference,
 5488117            out firstNumerator,
 5488118            out denominator);
 5488119        if (!ClampCenteredAxisParameter(
 5488120                ref firstNumerator,
 5488121                ref denominator,
 5488122                firstLength))
 123        {
 835124            secondNumerator = WideArithmetic.MultiplySigned192(
 835125                new Signed192(
 835126                    secondNumerator.Word2,
 835127                    secondNumerator.Word1,
 835128                    secondNumerator.Word0),
 835129                firstLengthSquared);
 835130            return;
 131        }
 132
 4653133        SetCenteredAxisCap(ref secondNumerator, ref denominator, secondLength);
 4653134    }
 135
 136    private static void GetCenteredAxesSquaredDistance(
 137        Vector2d firstCenter,
 138        Vector2d firstAxis,
 139        Fixed64 firstLength,
 140        Vector2d secondCenter,
 141        Vector2d secondAxis,
 142        Fixed64 secondLength,
 143        out Signed832 squaredNumerator,
 144        out Signed320 denominator)
 145    {
 9222146        GetCenteredAxesCandidate(
 9222147            firstCenter,
 9222148            firstAxis,
 9222149            firstLength,
 9222150            secondCenter,
 9222151            secondAxis,
 9222152            secondLength,
 9222153            out CenteredAxesCandidate2d candidate);
 9222154        squaredNumerator = candidate.SquaredDistanceNumerator;
 9222155        denominator = candidate.ParameterDenominator;
 9222156    }
 157
 158    private static void GetCenteredAxesCandidate(
 159        Vector2d firstCenter,
 160        Vector2d firstAxis,
 161        Fixed64 firstLength,
 162        Vector2d secondCenter,
 163        Vector2d secondAxis,
 164        Fixed64 secondLength,
 165        out CenteredAxesCandidate2d candidate)
 166    {
 9230167        GetClosestCenteredAxisParameters(
 9230168            GetDot(firstAxis, Vector2d.Zero, firstAxis, Vector2d.Zero),
 9230169            GetDot(firstAxis, Vector2d.Zero, secondAxis, Vector2d.Zero),
 9230170            GetDot(secondAxis, Vector2d.Zero, secondAxis, Vector2d.Zero),
 9230171            GetDot(firstCenter, secondCenter, firstAxis, Vector2d.Zero),
 9230172            GetDot(firstCenter, secondCenter, secondAxis, Vector2d.Zero),
 9230173            firstLength,
 9230174            secondLength,
 9230175            out Signed320 firstNumerator,
 9230176            out Signed320 secondNumerator,
 9230177            out Signed320 denominator);
 9230178        Signed576 firstX = GetCenteredAxisPointNumerator(
 9230179            firstCenter.X,
 9230180            firstAxis.X,
 9230181            firstNumerator,
 9230182            denominator);
 9230183        Signed576 firstY = GetCenteredAxisPointNumerator(
 9230184            firstCenter.Y,
 9230185            firstAxis.Y,
 9230186            firstNumerator,
 9230187            denominator);
 9230188        Signed576 secondX = GetCenteredAxisPointNumerator(
 9230189            secondCenter.X,
 9230190            secondAxis.X,
 9230191            secondNumerator,
 9230192            denominator);
 9230193        Signed576 secondY = GetCenteredAxisPointNumerator(
 9230194            secondCenter.Y,
 9230195            secondAxis.Y,
 9230196            secondNumerator,
 9230197            denominator);
 9230198        Signed576 differenceX = WideArithmetic.SubtractSigned576(firstX, secondX);
 9230199        Signed576 differenceY = WideArithmetic.SubtractSigned576(firstY, secondY);
 9230200        candidate = new CenteredAxesCandidate2d(
 9230201            firstX,
 9230202            firstY,
 9230203            secondX,
 9230204            secondY,
 9230205            denominator,
 9230206            WideArithmetic.AddSigned832(
 9230207                WideArithmetic.MultiplySigned576ToSigned832(differenceX, differenceX),
 9230208                WideArithmetic.MultiplySigned576ToSigned832(differenceY, differenceY)));
 9230209    }
 210
 211    private static void GetCenteredAxesSquaredDistance(
 212        Vector3d firstCenter,
 213        Vector3d firstAxis,
 214        Fixed64 firstLength,
 215        Vector3d secondCenter,
 216        Vector3d secondAxis,
 217        Fixed64 secondLength,
 218        out Signed832 squaredNumerator,
 219        out Signed320 denominator)
 220    {
 520221        GetCenteredAxesCandidate(
 520222            firstCenter,
 520223            firstAxis,
 520224            firstLength,
 520225            secondCenter,
 520226            secondAxis,
 520227            secondLength,
 520228            out CenteredAxesCandidate candidate);
 520229        squaredNumerator = candidate.SquaredDistanceNumerator;
 520230        denominator = candidate.ParameterDenominator;
 520231    }
 232
 233    private static void GetCenteredAxesCandidate(
 234        Vector3d firstCenter,
 235        Vector3d firstAxis,
 236        Fixed64 firstLength,
 237        Vector3d secondCenter,
 238        Vector3d secondAxis,
 239        Fixed64 secondLength,
 240        out CenteredAxesCandidate candidate)
 241    {
 541242        GetClosestCenteredAxisParameters(
 541243            GetDot(firstAxis, Vector3d.Zero, firstAxis, Vector3d.Zero),
 541244            GetDot(firstAxis, Vector3d.Zero, secondAxis, Vector3d.Zero),
 541245            GetDot(secondAxis, Vector3d.Zero, secondAxis, Vector3d.Zero),
 541246            GetDot(firstCenter, secondCenter, firstAxis, Vector3d.Zero),
 541247            GetDot(firstCenter, secondCenter, secondAxis, Vector3d.Zero),
 541248            firstLength,
 541249            secondLength,
 541250            out Signed320 firstNumerator,
 541251            out Signed320 secondNumerator,
 541252            out Signed320 denominator);
 541253        Signed576 firstX = GetCenteredAxisPointNumerator(
 541254            firstCenter.X,
 541255            firstAxis.X,
 541256            firstNumerator,
 541257            denominator);
 541258        Signed576 firstY = GetCenteredAxisPointNumerator(
 541259            firstCenter.Y,
 541260            firstAxis.Y,
 541261            firstNumerator,
 541262            denominator);
 541263        Signed576 firstZ = GetCenteredAxisPointNumerator(
 541264            firstCenter.Z,
 541265            firstAxis.Z,
 541266            firstNumerator,
 541267            denominator);
 541268        Signed576 secondX = GetCenteredAxisPointNumerator(
 541269            secondCenter.X,
 541270            secondAxis.X,
 541271            secondNumerator,
 541272            denominator);
 541273        Signed576 secondY = GetCenteredAxisPointNumerator(
 541274            secondCenter.Y,
 541275            secondAxis.Y,
 541276            secondNumerator,
 541277            denominator);
 541278        Signed576 secondZ = GetCenteredAxisPointNumerator(
 541279            secondCenter.Z,
 541280            secondAxis.Z,
 541281            secondNumerator,
 541282            denominator);
 541283        Signed576 differenceX = WideArithmetic.SubtractSigned576(firstX, secondX);
 541284        Signed576 differenceY = WideArithmetic.SubtractSigned576(firstY, secondY);
 541285        Signed576 differenceZ = WideArithmetic.SubtractSigned576(firstZ, secondZ);
 541286        Signed832 squaredDistance = WideArithmetic.AddSigned832(
 541287            WideArithmetic.AddSigned832(
 541288                WideArithmetic.MultiplySigned576ToSigned832(differenceX, differenceX),
 541289                WideArithmetic.MultiplySigned576ToSigned832(differenceY, differenceY)),
 541290            WideArithmetic.MultiplySigned576ToSigned832(differenceZ, differenceZ));
 541291        candidate = new CenteredAxesCandidate(
 541292            firstX,
 541293            firstY,
 541294            firstZ,
 541295            secondX,
 541296            secondY,
 541297            secondZ,
 541298            firstNumerator,
 541299            secondNumerator,
 541300            denominator,
 541301            squaredDistance);
 541302    }
 303
 304    private static bool IsWithinCombinedRadius(
 305        Signed832 squaredDistanceNumerator,
 306        Signed320 distanceDenominator,
 307        Fixed64 firstRadius,
 308        Fixed64 secondRadius)
 309    {
 4877310        Signed192 combinedRadius = WideArithmetic.AddSigned192(
 4877311            Signed192.Signed(firstRadius.m_rawValue),
 4877312            Signed192.Signed(secondRadius.m_rawValue));
 4877313        Signed576 radiusNumerator = WideArithmetic.MultiplySigned320(
 4877314            distanceDenominator,
 4877315            Signed320.ExtendValue(combinedRadius));
 4877316        return WideArithmetic.SubtractSigned832(
 4877317            squaredDistanceNumerator,
 4877318            WideArithmetic.MultiplySigned576ToSigned832(
 4877319                radiusNumerator,
 4877320                radiusNumerator)).Sign <= 0;
 321    }
 322
 323    private static void ProjectSecondFromCenteredAxisCap(
 324        Signed320 firstCapNumerator,
 325        Signed192 directionsDot,
 326        Signed192 secondLengthSquared,
 327        Signed192 secondDirectionDotDifference,
 328        out Signed320 secondNumerator,
 329        out Signed320 denominator)
 330    {
 7082331        Signed192 capNumerator = new(
 7082332            firstCapNumerator.Word2,
 7082333            firstCapNumerator.Word1,
 7082334            firstCapNumerator.Word0);
 7082335        secondNumerator = WideArithmetic.AddSigned320(
 7082336            WideArithmetic.MultiplySigned192(
 7082337                DoubleParameterScale,
 7082338                secondDirectionDotDifference),
 7082339            WideArithmetic.MultiplySigned192(capNumerator, directionsDot));
 7082340        denominator = WideArithmetic.MultiplySigned192(
 7082341            DoubleParameterScale,
 7082342            secondLengthSquared);
 7082343    }
 344
 345    private static void ProjectFirstFromCenteredAxisCap(
 346        Signed320 secondCapNumerator,
 347        Signed192 firstLengthSquared,
 348        Signed192 directionsDot,
 349        Signed192 firstDirectionDotDifference,
 350        out Signed320 firstNumerator,
 351        out Signed320 denominator)
 352    {
 6070353        Signed192 capNumerator = new(
 6070354            secondCapNumerator.Word2,
 6070355            secondCapNumerator.Word1,
 6070356            secondCapNumerator.Word0);
 6070357        firstNumerator = WideArithmetic.SubtractSigned320(
 6070358            WideArithmetic.MultiplySigned192(capNumerator, directionsDot),
 6070359            WideArithmetic.MultiplySigned192(
 6070360                DoubleParameterScale,
 6070361                firstDirectionDotDifference));
 6070362        denominator = WideArithmetic.MultiplySigned192(
 6070363            DoubleParameterScale,
 6070364            firstLengthSquared);
 6070365    }
 366
 367    private static bool ClampCenteredAxisParameter(
 368        ref Signed320 numerator,
 369        ref Signed320 denominator,
 370        Fixed64 axisLength)
 371    {
 23489372        Signed576 scaledNumerator = WideArithmetic.MultiplySigned320(
 23489373            numerator,
 23489374            Signed320.ExtendValue(DoubleParameterScale));
 23489375        Signed576 limit = WideArithmetic.MultiplySigned320(
 23489376            denominator,
 23489377            Signed320.ExtendValue(
 23489378                Signed192.Signed(axisLength.m_rawValue)));
 23489379        if (WideArithmetic.SubtractSigned576(
 23489380                scaledNumerator,
 23489381                WideArithmetic.SubtractSigned576(default, limit)).Sign < 0)
 382        {
 8007383            numerator = Signed320.ExtendValue(
 8007384                Signed192.Signed(-axisLength.m_rawValue));
 8007385            denominator = Signed320.ExtendValue(DoubleParameterScale);
 8007386            return true;
 387        }
 15482388        if (WideArithmetic.SubtractSigned576(scaledNumerator, limit).Sign > 0)
 389        {
 7551390            numerator = Signed320.ExtendValue(
 7551391                Signed192.Signed(axisLength.m_rawValue));
 7551392            denominator = Signed320.ExtendValue(DoubleParameterScale);
 7551393            return true;
 394        }
 395
 7931396        return false;
 397    }
 398
 399    private static void SetCenteredAxisCap(
 400        ref Signed320 numerator,
 401        ref Signed320 denominator,
 402        Fixed64 axisLength)
 403    {
 4845404        bool positive = numerator.Sign > 0;
 4845405        numerator = Signed320.ExtendValue(
 4845406            Signed192.Signed(
 4845407                positive ? axisLength.m_rawValue : -axisLength.m_rawValue));
 4845408        denominator = Signed320.ExtendValue(DoubleParameterScale);
 4845409    }
 410
 411    private static bool TryRoundCenteredAxesDistance(
 412        Signed832 squaredNumerator,
 413        Signed320 denominator,
 414        out Fixed64 distance)
 415    {
 4873416        Signed576 root = WideArithmetic.GetFloorSquareRootOfProduct(
 4873417            squaredNumerator,
 4873418            Scale);
 4873419        Signed576 wideDenominator = Signed576.ExtendValue(denominator);
 4873420        distance = Fixed64.GetNonNegativeRawRatioFloor(
 4873421            Signed704.ExtendValue(root),
 4873422            Signed704.ExtendValue(wideDenominator));
 423
 4873424        Signed192 doubledMidpoint = new(
 4873425            0UL,
 4873426            unchecked((ulong)distance.m_rawValue) >> 63,
 4873427            (unchecked((ulong)distance.m_rawValue) << 1) | 1UL);
 4873428        Signed576 midpointNumerator = WideArithmetic.MultiplySigned320(
 4873429            denominator,
 4873430            Signed320.ExtendValue(doubledMidpoint));
 4873431        Signed832 fourSquaredNumerator = WideArithmetic.AddSigned832(
 4873432            WideArithmetic.AddSigned832(squaredNumerator, squaredNumerator),
 4873433            WideArithmetic.AddSigned832(squaredNumerator, squaredNumerator));
 4873434        int midpointComparison = WideArithmetic.SubtractSigned832(
 4873435            fourSquaredNumerator,
 4873436            WideArithmetic.MultiplySigned576ToSigned832(
 4873437                midpointNumerator,
 4873438                midpointNumerator)).Sign;
 4873439        long increment =
 4873440            GetHalfToEvenIncrement(midpointComparison, distance.m_rawValue);
 4873441        if (distance == Fixed64.MaxValue && increment != 0L)
 2442            return false;
 443
 4871444        distance = Fixed64.FromRaw(distance.m_rawValue + increment);
 4871445        return true;
 446    }
 447
 448    private static long GetHalfToEvenIncrement(
 449        int midpointComparison,
 450        long lowerRaw)
 451    {
 4946452        int negative = (int)((uint)midpointComparison >> 31);
 4946453        int nonzero = (int)(
 4946454            (uint)(midpointComparison | -midpointComparison) >> 31);
 4946455        int positive = nonzero & (negative ^ 1);
 4946456        int zero = nonzero ^ 1;
 4946457        return (long)positive | ((long)zero & (lowerRaw & 1L));
 458    }
 459
 460    private static bool TryGetCenteredAxisPointCoordinate(
 461        Fixed64 center,
 462        Fixed64 axis,
 463        Signed320 parameterNumerator,
 464        Signed320 parameterDenominator,
 465        out Fixed64 coordinate)
 466    {
 964467        Signed576 numerator = GetCenteredAxisPointNumerator(
 964468            center,
 964469            axis,
 964470            parameterNumerator,
 964471            parameterDenominator);
 964472        return Fixed64.TryGetSignedRawRatio(
 964473            numerator,
 964474            Signed576.ExtendValue(parameterDenominator),
 964475            out coordinate);
 476    }
 477
 478    private static Signed576 GetCenteredAxisPointNumerator(
 479        Fixed64 center,
 480        Fixed64 axis,
 481        Signed320 parameterNumerator,
 482        Signed320 parameterDenominator) =>
 41130483        WideArithmetic.AddSigned576(
 41130484            WideArithmetic.MultiplySigned320(
 41130485                parameterDenominator,
 41130486                Signed320.ExtendValue(
 41130487                    Signed192.Signed(center.m_rawValue))),
 41130488            WideArithmetic.MultiplySigned320(
 41130489                parameterNumerator,
 41130490                Signed320.ExtendValue(
 41130491                    Signed192.Signed(axis.m_rawValue))));
 492
 493    private static Vector2d GetCenteredAxisLocalOffset(
 494        Signed576 axisPointX,
 495        Signed576 axisPointY,
 496        Vector2d center,
 497        Signed320 axisPointDenominator,
 498        Fixed64 frameRotation)
 499    {
 14500        Signed576 centerX = WideArithmetic.MultiplySigned320(
 14501            axisPointDenominator,
 14502            Signed320.ExtendValue(
 14503                Signed192.Signed(center.X.m_rawValue)));
 14504        Signed576 centerY = WideArithmetic.MultiplySigned320(
 14505            axisPointDenominator,
 14506            Signed320.ExtendValue(
 14507                Signed192.Signed(center.Y.m_rawValue)));
 14508        Signed576 deltaX =
 14509            WideArithmetic.SubtractSigned576(axisPointX, centerX);
 14510        Signed576 deltaY =
 14511            WideArithmetic.SubtractSigned576(axisPointY, centerY);
 14512        Fixed64 cosine = FixedMath.Cos(frameRotation);
 14513        Fixed64 sine = FixedMath.Sin(frameRotation);
 14514        Signed192 cosineRaw =
 14515            Signed192.Signed(cosine.m_rawValue);
 14516        Signed192 sineRaw =
 14517            Signed192.Signed(sine.m_rawValue);
 14518        Signed576 xNumerator = WideArithmetic.AddSigned576(
 14519            WideArithmetic.MultiplySigned576(deltaX, cosineRaw),
 14520            WideArithmetic.MultiplySigned576(deltaY, sineRaw));
 14521        Signed576 yNumerator = WideArithmetic.SubtractSigned576(
 14522            WideArithmetic.MultiplySigned576(deltaY, cosineRaw),
 14523            WideArithmetic.MultiplySigned576(deltaX, sineRaw));
 14524        Signed192 fixedScale =
 14525            Signed192.Signed(Fixed64.One.m_rawValue);
 14526        xNumerator = WideArithmetic.MultiplySigned576(
 14527            xNumerator,
 14528            fixedScale);
 14529        yNumerator = WideArithmetic.MultiplySigned576(
 14530            yNumerator,
 14531            fixedScale);
 14532        Signed320 rotationDenominator = WideArithmetic.AddSigned320(
 14533            WideArithmetic.MultiplySigned192(cosineRaw, cosineRaw),
 14534            WideArithmetic.MultiplySigned192(sineRaw, sineRaw));
 14535        Signed576 denominator = WideArithmetic.MultiplySigned320(
 14536            axisPointDenominator,
 14537            rotationDenominator);
 14538        _ = Fixed64.TryGetSignedRawRatio(
 14539            xNumerator,
 14540            denominator,
 14541            out Fixed64 x);
 14542        _ = Fixed64.TryGetSignedRawRatio(
 14543            yNumerator,
 14544            denominator,
 14545            out Fixed64 y);
 14546        return new Vector2d(x, y);
 547    }
 548
 549    private static void GetLocalRadialFeature(
 550        Vector2d worldDirection,
 551        Fixed64 radius,
 552        Fixed64 frameRotation,
 553        out Vector2d localDirection,
 554        out Vector2d roundedLocalOffset)
 555    {
 14556        _ = Vector2d.TryRotate(
 14557            worldDirection,
 14558            -frameRotation,
 14559            out localDirection);
 14560        localDirection = WideNormalization.GetNormalized(localDirection);
 14561        roundedLocalOffset = localDirection * radius;
 14562    }
 563
 564    private static bool TryGetCenteredCapsulesDepth(
 565        Signed832 squaredDistanceNumerator,
 566        Signed320 distanceDenominator,
 567        Fixed64 firstRadius,
 568        Fixed64 secondRadius,
 569        out Fixed64 depth,
 570        out bool depthIsClamped)
 571    {
 27572        Signed192 combinedRadius = WideArithmetic.AddSigned192(
 27573            Signed192.Signed(firstRadius.m_rawValue),
 27574            Signed192.Signed(secondRadius.m_rawValue));
 27575        GetCenteredRadiusDepth(
 27576            squaredDistanceNumerator,
 27577            Signed576.ExtendValue(distanceDenominator),
 27578            combinedRadius,
 27579            out depth,
 27580            out depthIsClamped);
 27581        return true;
 582    }
 583
 584    private static void GetCenteredRadiusDepth(
 585        Signed832 squaredDistanceNumerator,
 586        Signed576 distanceDenominator,
 587        Signed192 radius,
 588        out Fixed64 depth,
 589        out bool depthIsClamped)
 590    {
 32591        Signed192 maximumThreshold = WideArithmetic.SubtractSigned192(
 32592            radius,
 32593            Signed192.Signed(Fixed64.MaxValue.m_rawValue));
 32594        if (maximumThreshold.Sign > 0
 32595            && CompareSquaredDistanceToCenteredDepthThreshold(
 32596                squaredDistanceNumerator,
 32597                distanceDenominator,
 32598                maximumThreshold) < 0)
 599        {
 3600            depth = Fixed64.MaxValue;
 3601            depthIsClamped = true;
 3602            return;
 603        }
 604
 29605        Signed576 root = WideArithmetic.GetFloorSquareRootOfProduct(
 29606            squaredDistanceNumerator,
 29607            Scale);
 29608        Signed576 radiusNumerator = WideArithmetic.MultiplySigned576(
 29609            distanceDenominator,
 29610            radius);
 29611        Signed576 approximateDepthNumerator =
 29612            WideArithmetic.SubtractSigned576(radiusNumerator, root);
 29613        depth = Fixed64.GetNonNegativeRawRatioFloor(
 29614            Signed704.ExtendValue(approximateDepthNumerator),
 29615            Signed704.ExtendValue(distanceDenominator));
 616
 29617        Signed192 floorThreshold = WideArithmetic.SubtractSigned192(
 29618            radius,
 29619            Signed192.Signed(depth.m_rawValue));
 29620        if (CompareSquaredDistanceToCenteredDepthThreshold(
 29621                squaredDistanceNumerator,
 29622                distanceDenominator,
 29623                floorThreshold) > 0)
 624        {
 1625            depth = Fixed64.FromRaw(depth.m_rawValue - 1L);
 626        }
 627
 29628        Signed192 doubledRadius = WideArithmetic.AddSigned192(
 29629            radius,
 29630            radius);
 29631        Signed192 doubledMidpoint = WideArithmetic.AddSigned192(
 29632            WideArithmetic.AddSigned192(
 29633                Signed192.Signed(depth.m_rawValue),
 29634                Signed192.Signed(depth.m_rawValue)),
 29635            Scale);
 29636        Signed192 distanceThreshold = WideArithmetic.SubtractSigned192(
 29637            doubledRadius,
 29638            doubledMidpoint);
 29639        if (distanceThreshold.Sign <= 0)
 640        {
 6641            depthIsClamped = false;
 6642            return;
 643        }
 644
 23645        int comparison = CompareSquaredDistanceToCenteredDepthThreshold(
 23646            squaredDistanceNumerator,
 23647            distanceDenominator,
 23648            distanceThreshold,
 23649            quadrupleDistance: true);
 23650        depth = Fixed64.FromRaw(
 23651            depth.m_rawValue
 23652            + GetHalfToEvenIncrement(-comparison, depth.m_rawValue));
 653
 23654        depthIsClamped = false;
 23655    }
 656
 657    private static int CompareSquaredDistanceToCenteredDepthThreshold(
 658        Signed832 squaredDistanceNumerator,
 659        Signed576 distanceDenominator,
 660        Signed192 distanceThreshold,
 661        bool quadrupleDistance = false)
 662    {
 56663        Signed576 thresholdNumerator = WideArithmetic.MultiplySigned576(
 56664            distanceDenominator,
 56665            distanceThreshold);
 56666        Signed832 left = squaredDistanceNumerator;
 56667        if (quadrupleDistance)
 668        {
 23669            left = WideArithmetic.AddSigned832(
 23670                WideArithmetic.AddSigned832(left, left),
 23671                WideArithmetic.AddSigned832(left, left));
 672        }
 56673        return WideArithmetic.SubtractSigned832(
 56674            left,
 56675            WideArithmetic.MultiplySigned576ToSigned832(
 56676                thresholdNumerator,
 56677                thresholdNumerator)).Sign;
 678    }
 679}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredAxisTriangle.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.CenteredAxisTriangle.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
 8namespace FixedMathSharp.Geometry;
 9
 10/// <content>
 11/// Provides high-precision closest-point and overlap tests between a
 12/// <see cref="FixedTriangle"/> and a centered, finite-length axis segment
 13/// (e.g. a capsule's core axis), using wide fixed-point arithmetic.
 14/// </content>
 15internal static partial class WideFiniteAxisIntersection
 16{
 17    #region Nested Types
 18
 19    private readonly struct AxisTriangleCandidate
 20    {
 21        internal readonly Signed576 TriangleX;
 22        internal readonly Signed576 TriangleY;
 23        internal readonly Signed576 TriangleZ;
 24        internal readonly Signed576 AxisX;
 25        internal readonly Signed576 AxisY;
 26        internal readonly Signed576 AxisZ;
 27        internal readonly Signed576 Denominator;
 28        internal readonly Signed832 SquaredDistanceNumerator;
 29
 30        internal AxisTriangleCandidate(
 31            Signed576 triangleX,
 32            Signed576 triangleY,
 33            Signed576 triangleZ,
 34            Signed576 axisX,
 35            Signed576 axisY,
 36            Signed576 axisZ,
 37            Signed576 denominator,
 38            Signed832 squaredDistanceNumerator)
 39        {
 5440            TriangleX = triangleX;
 5441            TriangleY = triangleY;
 5442            TriangleZ = triangleZ;
 5443            AxisX = axisX;
 5444            AxisY = axisY;
 5445            AxisZ = axisZ;
 5446            Denominator = denominator;
 5447            SquaredDistanceNumerator = squaredDistanceNumerator;
 5448        }
 49    }
 50
 51    #endregion
 52
 53    internal static bool TryGetClosestPointsToCenteredAxis(
 54        FixedTriangle triangle,
 55        Vector3d center,
 56        Vector3d axisDirection,
 57        Fixed64 axisLength,
 58        out Vector3d pointOnTriangle,
 59        out Vector3d pointOnAxis)
 60    {
 761        GetClosestCenteredAxisTriangleCandidate(
 762            triangle,
 763            center,
 764            axisDirection,
 765            axisLength,
 766            out AxisTriangleCandidate candidate);
 767        return TryMaterialize(
 768            candidate,
 769            out pointOnTriangle,
 770            out pointOnAxis);
 71    }
 72
 73    internal static bool DoesCenteredCapsuleTriangleOverlap(
 74        FixedTriangle triangle,
 75        Vector3d center,
 76        Vector3d axisDirection,
 77        Fixed64 axisLength,
 78        Fixed64 radius)
 79    {
 180        GetClosestCenteredAxisTriangleCandidate(
 181            triangle,
 182            center,
 183            axisDirection,
 184            axisLength,
 185            out AxisTriangleCandidate candidate);
 186        Signed576 radiusNumerator = WideArithmetic.MultiplySigned576(
 187            candidate.Denominator,
 188            Signed192.Signed(radius.m_rawValue));
 189        return WideArithmetic.SubtractSigned832(
 190            candidate.SquaredDistanceNumerator,
 191            WideArithmetic.MultiplySigned576ToSigned832(
 192                radiusNumerator,
 193                radiusNumerator)).Sign <= 0;
 94    }
 95
 96    internal static bool TryGetCenteredCapsuleTriangleContact(
 97        FixedTriangle triangle,
 98        Vector3d center,
 99        Vector3d axisDirection,
 100        Fixed64 axisLength,
 101        Fixed64 radius,
 102        Vector3d fallbackNormal,
 103        out Vector3d pointOnTriangle,
 104        out Vector3d pointOnCapsule,
 105        out Vector3d normal,
 106        out Fixed64 depth)
 107    {
 4108        GetClosestCenteredAxisTriangleCandidate(
 4109            triangle,
 4110            center,
 4111            axisDirection,
 4112            axisLength,
 4113            out AxisTriangleCandidate candidate);
 4114        Signed576 radiusNumerator = WideArithmetic.MultiplySigned576(
 4115            candidate.Denominator,
 4116            Signed192.Signed(radius.m_rawValue));
 4117        if (WideArithmetic.SubtractSigned832(
 4118                candidate.SquaredDistanceNumerator,
 4119                WideArithmetic.MultiplySigned576ToSigned832(
 4120                    radiusNumerator,
 4121                    radiusNumerator)).Sign > 0
 4122            || !TryMaterialize(candidate, out pointOnTriangle, out Vector3d pointOnAxis))
 123        {
 1124            pointOnTriangle = default;
 1125            pointOnCapsule = default;
 1126            normal = default;
 1127            depth = default;
 1128            return false;
 129        }
 130
 3131        normal = WideNormalization.GetDirection(pointOnTriangle, pointOnAxis);
 3132        if (normal.IsZero)
 1133            normal = fallbackNormal;
 3134        if (!TryOffsetPoint(pointOnAxis, -normal, radius, out pointOnCapsule))
 135        {
 1136            pointOnTriangle = default;
 1137            pointOnCapsule = default;
 1138            normal = default;
 1139            depth = default;
 1140            return false;
 141        }
 2142        GetCenteredCapsuleTriangleDepth(candidate, radius, out depth, out _);
 143
 2144        return true;
 145    }
 146
 147    internal static bool TryGetCenteredCapsuleTriangleLocalContact(
 148        FixedTriangle triangle,
 149        Vector3d center,
 150        Vector3d axisDirection,
 151        Fixed64 axisLength,
 152        Fixed64 radius,
 153        Vector3d fallbackNormal,
 154        out Vector3d pointOnTriangle,
 155        out Fixed64 axisParameter,
 156        out Vector3d normal,
 157        out Fixed64 depth,
 158        out bool depthIsClamped)
 159    {
 4160        GetClosestCenteredAxisTriangleCandidate(
 4161            triangle,
 4162            center,
 4163            axisDirection,
 4164            axisLength,
 4165            out AxisTriangleCandidate candidate);
 4166        Signed576 radiusNumerator = WideArithmetic.MultiplySigned576(
 4167            candidate.Denominator,
 4168            Signed192.Signed(radius.m_rawValue));
 4169        if (WideArithmetic.SubtractSigned832(
 4170                candidate.SquaredDistanceNumerator,
 4171                WideArithmetic.MultiplySigned576ToSigned832(
 4172                    radiusNumerator,
 4173                    radiusNumerator)).Sign > 0)
 174        {
 1175            pointOnTriangle = default;
 1176            axisParameter = default;
 1177            normal = default;
 1178            depth = default;
 1179            depthIsClamped = default;
 1180            return false;
 181        }
 182
 3183        Signed576 differenceX = WideArithmetic.SubtractSigned576(
 3184            candidate.AxisX,
 3185            candidate.TriangleX);
 3186        Signed576 differenceY = WideArithmetic.SubtractSigned576(
 3187            candidate.AxisY,
 3188            candidate.TriangleY);
 3189        Signed576 differenceZ = WideArithmetic.SubtractSigned576(
 3190            candidate.AxisZ,
 3191            candidate.TriangleZ);
 3192        normal = WideNormalization.GetNormalized(
 3193            differenceX,
 3194            differenceY,
 3195            differenceZ);
 3196        if (normal.IsZero)
 1197            normal = fallbackNormal;
 198
 199        // Both witnesses are convex points on representable local features:
 200        // the triangle point stays within its vertex component intervals and
 201        // the axis offset stays within the representable half length.
 3202        _ = TryGetRelativeCoordinate(
 3203            candidate.TriangleX,
 3204            Fixed64.Zero,
 3205            candidate.Denominator,
 3206            out Fixed64 triangleX);
 3207        _ = TryGetRelativeCoordinate(
 3208            candidate.TriangleY,
 3209            Fixed64.Zero,
 3210            candidate.Denominator,
 3211            out Fixed64 triangleY);
 3212        _ = TryGetRelativeCoordinate(
 3213            candidate.TriangleZ,
 3214            Fixed64.Zero,
 3215            candidate.Denominator,
 3216            out Fixed64 triangleZ);
 3217        _ = TryGetRelativeCoordinate(
 3218            candidate.AxisX,
 3219            center.X,
 3220            candidate.Denominator,
 3221            out Fixed64 axisX);
 3222        _ = TryGetRelativeCoordinate(
 3223            candidate.AxisY,
 3224            center.Y,
 3225            candidate.Denominator,
 3226            out Fixed64 axisY);
 3227        _ = TryGetRelativeCoordinate(
 3228            candidate.AxisZ,
 3229            center.Z,
 3230            candidate.Denominator,
 3231            out Fixed64 axisZ);
 3232        GetCenteredCapsuleTriangleDepth(
 3233            candidate,
 3234            radius,
 3235            out depth,
 3236            out depthIsClamped);
 237
 3238        pointOnTriangle = new Vector3d(
 3239            triangleX,
 3240            triangleY,
 3241            triangleZ);
 3242        axisParameter = Vector3d.Dot(
 3243            new Vector3d(axisX, axisY, axisZ),
 3244            axisDirection);
 3245        return true;
 246    }
 247
 248    private static void GetClosestCenteredAxisTriangleCandidate(
 249        FixedTriangle triangle,
 250        Vector3d center,
 251        Vector3d axisDirection,
 252        Fixed64 axisLength,
 253        out AxisTriangleCandidate best)
 254    {
 16255        bool found = TryGetCenteredAxisTriangleFaceCandidate(
 16256            triangle,
 16257            center,
 16258            axisDirection,
 16259            axisLength,
 16260            out best);
 16261        KeepCenteredAxisTriangleEdgeCandidate(
 16262            triangle.A,
 16263            triangle.B,
 16264            center,
 16265            axisDirection,
 16266            axisLength,
 16267            ref found,
 16268            ref best);
 16269        KeepCenteredAxisTriangleEdgeCandidate(
 16270            triangle.B,
 16271            triangle.C,
 16272            center,
 16273            axisDirection,
 16274            axisLength,
 16275            ref found,
 16276            ref best);
 16277        KeepCenteredAxisTriangleEdgeCandidate(
 16278            triangle.C,
 16279            triangle.A,
 16280            center,
 16281            axisDirection,
 16282            axisLength,
 16283            ref found,
 16284            ref best);
 16285    }
 286
 287    private static bool TryGetCenteredAxisTriangleFaceCandidate(
 288        FixedTriangle triangle,
 289        Vector3d center,
 290        Vector3d axisDirection,
 291        Fixed64 axisLength,
 292        out AxisTriangleCandidate candidate)
 293    {
 16294        GetTriangleNormal(
 16295            triangle,
 16296            out Signed192 normalX,
 16297            out Signed192 normalY,
 16298            out Signed192 normalZ);
 16299        Signed320 normalSquared = WideGeometry.GetSquaredMagnitude(
 16300            normalX,
 16301            normalY,
 16302            normalZ,
 16303            out _,
 16304            out _,
 16305            out _);
 16306        if (normalSquared.IsZero)
 307        {
 4308            candidate = default;
 4309            return false;
 310        }
 311
 12312        Signed320 planeProjection = GetWideDot(
 12313            normalX,
 12314            normalY,
 12315            normalZ,
 12316            center,
 12317            triangle.A);
 12318        Signed320 axisProjection = GetWideDot(
 12319            normalX,
 12320            normalY,
 12321            normalZ,
 12322            axisDirection,
 12323            Vector3d.Zero);
 12324        if (axisProjection.IsZero)
 325        {
 3326            candidate = default;
 3327            return false;
 328        }
 329
 9330        Signed320 parameterNumerator =
 9331            WideArithmetic.SubtractSigned320(default, planeProjection);
 9332        Signed320 parameterDenominator = axisProjection;
 9333        if (parameterDenominator.Sign < 0)
 334        {
 7335            parameterNumerator =
 7336                WideArithmetic.SubtractSigned320(default, parameterNumerator);
 7337            parameterDenominator =
 7338                WideArithmetic.SubtractSigned320(default, parameterDenominator);
 339        }
 9340        ClampCenteredAxisParameter(
 9341            ref parameterNumerator,
 9342            ref parameterDenominator,
 9343            axisLength);
 344
 9345        GetRationalPoint(
 9346            center,
 9347            axisDirection,
 9348            parameterNumerator,
 9349            parameterDenominator,
 9350            out Signed576 axisX,
 9351            out Signed576 axisY,
 9352            out Signed576 axisZ);
 9353        Signed576 wideParameterDenominator =
 9354            Signed576.ExtendValue(parameterDenominator);
 9355        if (!ContainsTriangleProjection(
 9356                triangle,
 9357                normalX,
 9358                normalY,
 9359                normalZ,
 9360                axisX,
 9361                axisY,
 9362                axisZ,
 9363                wideParameterDenominator))
 364        {
 3365            candidate = default;
 3366            return false;
 367        }
 368
 6369        Signed576 planeDistanceNumerator = WideArithmetic.AddSigned576(
 6370            WideArithmetic.AddSigned576(
 6371                WideArithmetic.MultiplySigned576(
 6372                    SubtractVertex(axisX, triangle.A.X, parameterDenominator),
 6373                    normalX),
 6374                WideArithmetic.MultiplySigned576(
 6375                    SubtractVertex(axisY, triangle.A.Y, parameterDenominator),
 6376                    normalY)),
 6377            WideArithmetic.MultiplySigned576(
 6378                SubtractVertex(axisZ, triangle.A.Z, parameterDenominator),
 6379                normalZ));
 380        // A full-domain center scaled by the face parameter denominator plus
 381        // one normalized-axis parameter product needs fewer than 320 signed bits.
 6382        Signed320 narrowAxisX = new(
 6383            axisX.Word4,
 6384            axisX.Word3,
 6385            axisX.Word2,
 6386            axisX.Word1,
 6387            axisX.Word0);
 6388        Signed320 narrowAxisY = new(
 6389            axisY.Word4,
 6390            axisY.Word3,
 6391            axisY.Word2,
 6392            axisY.Word1,
 6393            axisY.Word0);
 6394        Signed320 narrowAxisZ = new(
 6395            axisZ.Word4,
 6396            axisZ.Word3,
 6397            axisZ.Word2,
 6398            axisZ.Word1,
 6399            axisZ.Word0);
 6400        Signed576 denominator = WideArithmetic.MultiplySigned320(
 6401            parameterDenominator,
 6402            normalSquared);
 6403        Signed576 scaledAxisX = WideArithmetic.MultiplySigned320(
 6404            narrowAxisX,
 6405            normalSquared);
 6406        Signed576 scaledAxisY = WideArithmetic.MultiplySigned320(
 6407            narrowAxisY,
 6408            normalSquared);
 6409        Signed576 scaledAxisZ = WideArithmetic.MultiplySigned320(
 6410            narrowAxisZ,
 6411            normalSquared);
 6412        Signed576 triangleX = WideArithmetic.SubtractSigned576(
 6413            scaledAxisX,
 6414            WideArithmetic.MultiplySigned576(planeDistanceNumerator, normalX));
 6415        Signed576 triangleY = WideArithmetic.SubtractSigned576(
 6416            scaledAxisY,
 6417            WideArithmetic.MultiplySigned576(planeDistanceNumerator, normalY));
 6418        Signed576 triangleZ = WideArithmetic.SubtractSigned576(
 6419            scaledAxisZ,
 6420            WideArithmetic.MultiplySigned576(planeDistanceNumerator, normalZ));
 6421        candidate = CreateAxisTriangleCandidate(
 6422            triangleX,
 6423            triangleY,
 6424            triangleZ,
 6425            scaledAxisX,
 6426            scaledAxisY,
 6427            scaledAxisZ,
 6428            denominator);
 6429        return true;
 430    }
 431
 432    private static void KeepCenteredAxisTriangleEdgeCandidate(
 433        Vector3d edgeStart,
 434        Vector3d edgeEnd,
 435        Vector3d center,
 436        Vector3d axisDirection,
 437        Fixed64 axisLength,
 438        ref bool found,
 439        ref AxisTriangleCandidate best)
 440    {
 48441        GetClosestCenteredAxisSegmentParameters(
 48442            center,
 48443            axisDirection,
 48444            axisLength,
 48445            edgeStart,
 48446            edgeEnd,
 48447            out Signed320 axisNumerator,
 48448            out Signed320 edgeNumerator,
 48449            out Signed320 denominator);
 48450        GetRationalPoint(
 48451            center,
 48452            axisDirection,
 48453            axisNumerator,
 48454            denominator,
 48455            out Signed576 axisX,
 48456            out Signed576 axisY,
 48457            out Signed576 axisZ);
 48458        GetRationalSegmentPoint(
 48459            edgeStart,
 48460            edgeEnd,
 48461            edgeNumerator,
 48462            denominator,
 48463            out Signed576 edgeX,
 48464            out Signed576 edgeY,
 48465            out Signed576 edgeZ);
 48466        AxisTriangleCandidate candidate = CreateAxisTriangleCandidate(
 48467            edgeX,
 48468            edgeY,
 48469            edgeZ,
 48470            axisX,
 48471            axisY,
 48472            axisZ,
 48473            Signed576.ExtendValue(denominator));
 48474        if (found
 48475            && WideArithmetic.CompareNonNegativeSquaredRatios(
 48476                candidate.SquaredDistanceNumerator,
 48477                candidate.Denominator,
 48478                best.SquaredDistanceNumerator,
 48479                best.Denominator) >= 0)
 480        {
 36481            return;
 482        }
 483
 12484        found = true;
 12485        best = candidate;
 12486    }
 487
 488    private static void GetClosestCenteredAxisSegmentParameters(
 489        Vector3d center,
 490        Vector3d axis,
 491        Fixed64 axisLength,
 492        Vector3d edgeStart,
 493        Vector3d edgeEnd,
 494        out Signed320 axisNumerator,
 495        out Signed320 edgeNumerator,
 496        out Signed320 denominator)
 497    {
 48498        Signed192 axisSquared = GetDot(axis, Vector3d.Zero, axis, Vector3d.Zero);
 48499        Signed192 directionsDot = GetDot(axis, Vector3d.Zero, edgeEnd, edgeStart);
 48500        Signed192 edgeSquared = GetDot(edgeEnd, edgeStart, edgeEnd, edgeStart);
 48501        Signed192 axisDotDifference = GetDot(center, edgeStart, axis, Vector3d.Zero);
 48502        Signed192 edgeDotDifference = GetDot(center, edgeStart, edgeEnd, edgeStart);
 48503        if (edgeSquared.IsZero)
 504        {
 12505            axisNumerator = Signed320.ExtendValue(
 12506                WideArithmetic.SubtractSigned192(default, axisDotDifference));
 12507            denominator = Signed320.ExtendValue(axisSquared);
 12508            ClampCenteredAxisParameter(
 12509                ref axisNumerator,
 12510                ref denominator,
 12511                axisLength);
 12512            edgeNumerator = default;
 12513            return;
 514        }
 515
 36516        Signed320 determinant = WideArithmetic.MultiplySubtract(
 36517            axisSquared,
 36518            edgeSquared,
 36519            directionsDot,
 36520            directionsDot);
 36521        if (determinant.Sign > 0)
 522        {
 33523            axisNumerator = WideArithmetic.MultiplySubtract(
 33524                directionsDot,
 33525                edgeDotDifference,
 33526                edgeSquared,
 33527                axisDotDifference);
 33528            edgeNumerator = WideArithmetic.MultiplySubtract(
 33529                axisSquared,
 33530                edgeDotDifference,
 33531                directionsDot,
 33532                axisDotDifference);
 33533            denominator = determinant;
 33534            if (!ClampCenteredAxisParameter(
 33535                    ref axisNumerator,
 33536                    ref denominator,
 33537                    axisLength))
 538            {
 18539                if (!ClampUnitParameter(ref edgeNumerator, ref denominator))
 15540                    return;
 541
 3542                ProjectAxisFromEdgeCap(
 3543                    edgeNumerator,
 3544                    axisSquared,
 3545                    directionsDot,
 3546                    axisDotDifference,
 3547                    out axisNumerator,
 3548                    out denominator);
 3549                if (!ClampCenteredAxisParameter(
 3550                        ref axisNumerator,
 3551                        ref denominator,
 3552                        axisLength))
 553                {
 2554                    edgeNumerator = WideArithmetic.MultiplySigned192(
 2555                        new Signed192(
 2556                            edgeNumerator.Word2,
 2557                            edgeNumerator.Word1,
 2558                            edgeNumerator.Word0),
 2559                        axisSquared);
 2560                    return;
 561                }
 562
 1563                SetUnitCapAtCenteredDenominator(
 1564                    ref edgeNumerator,
 1565                    ref denominator);
 1566                return;
 567            }
 568        }
 569        else
 570        {
 3571            axisNumerator = Signed320.ExtendValue(
 3572                Signed192.Signed(-axisLength.m_rawValue));
 3573            denominator = Signed320.ExtendValue(DoubleParameterScale);
 574        }
 575
 18576        ProjectEdgeFromCenteredCap(
 18577            axisNumerator,
 18578            directionsDot,
 18579            edgeSquared,
 18580            edgeDotDifference,
 18581            out edgeNumerator,
 18582            out denominator);
 18583        if (!ClampUnitParameter(ref edgeNumerator, ref denominator))
 584        {
 14585            axisNumerator = WideArithmetic.MultiplySigned192(
 14586                new Signed192(
 14587                    axisNumerator.Word2,
 14588                    axisNumerator.Word1,
 14589                    axisNumerator.Word0),
 14590                edgeSquared);
 14591            return;
 592        }
 593
 4594        ProjectAxisFromEdgeCap(
 4595            edgeNumerator,
 4596            axisSquared,
 4597            directionsDot,
 4598            axisDotDifference,
 4599            out axisNumerator,
 4600            out denominator);
 4601        if (!ClampCenteredAxisParameter(
 4602                ref axisNumerator,
 4603                ref denominator,
 4604                axisLength))
 605        {
 1606            edgeNumerator = WideArithmetic.MultiplySigned192(
 1607                new Signed192(
 1608                    edgeNumerator.Word2,
 1609                    edgeNumerator.Word1,
 1610                    edgeNumerator.Word0),
 1611                axisSquared);
 1612            return;
 613        }
 614
 3615        SetUnitCapAtCenteredDenominator(
 3616            ref edgeNumerator,
 3617            ref denominator);
 3618    }
 619
 620    private static bool ClampUnitParameter(
 621        ref Signed320 numerator,
 622        ref Signed320 denominator)
 623    {
 36624        if (numerator.Sign < 0)
 625        {
 4626            numerator = default;
 4627            denominator = Signed320.ExtendValue(ParameterScale);
 4628            return true;
 629        }
 32630        if (WideArithmetic.SubtractSigned320(numerator, denominator).Sign > 0)
 631        {
 3632            numerator = Signed320.ExtendValue(ParameterScale);
 3633            denominator = Signed320.ExtendValue(ParameterScale);
 3634            return true;
 635        }
 636
 29637        return false;
 638    }
 639
 640    private static void ProjectEdgeFromCenteredCap(
 641        Signed320 axisCapNumerator,
 642        Signed192 directionsDot,
 643        Signed192 edgeSquared,
 644        Signed192 edgeDotDifference,
 645        out Signed320 edgeNumerator,
 646        out Signed320 denominator)
 647    {
 18648        Signed192 capNumerator = new(
 18649            axisCapNumerator.Word2,
 18650            axisCapNumerator.Word1,
 18651            axisCapNumerator.Word0);
 18652        edgeNumerator = WideArithmetic.AddSigned320(
 18653            WideArithmetic.MultiplySigned192(
 18654                DoubleParameterScale,
 18655                edgeDotDifference),
 18656            WideArithmetic.MultiplySigned192(
 18657                capNumerator,
 18658                directionsDot));
 18659        denominator = WideArithmetic.MultiplySigned192(
 18660            DoubleParameterScale,
 18661            edgeSquared);
 18662    }
 663
 664    private static void ProjectAxisFromEdgeCap(
 665        Signed320 edgeCapNumerator,
 666        Signed192 axisSquared,
 667        Signed192 directionsDot,
 668        Signed192 axisDotDifference,
 669        out Signed320 axisNumerator,
 670        out Signed320 denominator)
 671    {
 7672        Signed192 capNumerator = new(
 7673            edgeCapNumerator.Word2,
 7674            edgeCapNumerator.Word1,
 7675            edgeCapNumerator.Word0);
 7676        axisNumerator = WideArithmetic.SubtractSigned320(
 7677            WideArithmetic.MultiplySigned192(
 7678                capNumerator,
 7679                directionsDot),
 7680            WideArithmetic.MultiplySigned192(
 7681                ParameterScale,
 7682                axisDotDifference));
 7683        denominator = WideArithmetic.MultiplySigned192(
 7684            ParameterScale,
 7685            axisSquared);
 7686    }
 687
 688    private static void SetUnitCapAtCenteredDenominator(
 689        ref Signed320 numerator,
 690        ref Signed320 denominator)
 691    {
 4692        bool positive = numerator.Sign > 0;
 4693        numerator = positive
 4694            ? Signed320.ExtendValue(DoubleParameterScale)
 4695            : default;
 4696        denominator = Signed320.ExtendValue(DoubleParameterScale);
 4697    }
 698
 699    private static void GetRationalPoint(
 700        Vector3d center,
 701        Vector3d direction,
 702        Signed320 parameterNumerator,
 703        Signed320 denominator,
 704        out Signed576 x,
 705        out Signed576 y,
 706        out Signed576 z)
 707    {
 57708        x = GetRationalCoordinate(
 57709            center.X,
 57710            Signed192.Signed(direction.X.m_rawValue),
 57711            parameterNumerator,
 57712            denominator);
 57713        y = GetRationalCoordinate(
 57714            center.Y,
 57715            Signed192.Signed(direction.Y.m_rawValue),
 57716            parameterNumerator,
 57717            denominator);
 57718        z = GetRationalCoordinate(
 57719            center.Z,
 57720            Signed192.Signed(direction.Z.m_rawValue),
 57721            parameterNumerator,
 57722            denominator);
 57723    }
 724
 725    private static void GetRationalSegmentPoint(
 726        Vector3d start,
 727        Vector3d end,
 728        Signed320 parameterNumerator,
 729        Signed320 denominator,
 730        out Signed576 x,
 731        out Signed576 y,
 732        out Signed576 z)
 733    {
 48734        x = GetRationalCoordinate(
 48735            start.X,
 48736            GetComponentDifference(end.X, start.X),
 48737            parameterNumerator,
 48738            denominator);
 48739        y = GetRationalCoordinate(
 48740            start.Y,
 48741            GetComponentDifference(end.Y, start.Y),
 48742            parameterNumerator,
 48743            denominator);
 48744        z = GetRationalCoordinate(
 48745            start.Z,
 48746            GetComponentDifference(end.Z, start.Z),
 48747            parameterNumerator,
 48748            denominator);
 48749    }
 750
 751    private static Signed576 GetRationalCoordinate(
 752        Fixed64 origin,
 753        Signed192 direction,
 754        Signed320 parameterNumerator,
 755        Signed320 denominator) =>
 315756        WideArithmetic.AddSigned576(
 315757            WideArithmetic.MultiplySigned320(
 315758                Signed320.ExtendValue(
 315759                    Signed192.Signed(origin.m_rawValue)),
 315760                denominator),
 315761            WideArithmetic.MultiplySigned320(
 315762                Signed320.ExtendValue(direction),
 315763                parameterNumerator));
 764
 765    private static AxisTriangleCandidate CreateAxisTriangleCandidate(
 766        Signed576 triangleX,
 767        Signed576 triangleY,
 768        Signed576 triangleZ,
 769        Signed576 axisX,
 770        Signed576 axisY,
 771        Signed576 axisZ,
 772        Signed576 denominator)
 773    {
 54774        Signed576 differenceX =
 54775            WideArithmetic.SubtractSigned576(axisX, triangleX);
 54776        Signed576 differenceY =
 54777            WideArithmetic.SubtractSigned576(axisY, triangleY);
 54778        Signed576 differenceZ =
 54779            WideArithmetic.SubtractSigned576(axisZ, triangleZ);
 54780        Signed832 squaredDistance = WideArithmetic.AddSigned832(
 54781            WideArithmetic.AddSigned832(
 54782                WideArithmetic.MultiplySigned576ToSigned832(
 54783                    differenceX,
 54784                    differenceX),
 54785                WideArithmetic.MultiplySigned576ToSigned832(
 54786                    differenceY,
 54787                    differenceY)),
 54788            WideArithmetic.MultiplySigned576ToSigned832(
 54789                differenceZ,
 54790                differenceZ));
 54791        return new AxisTriangleCandidate(
 54792            triangleX,
 54793            triangleY,
 54794            triangleZ,
 54795            axisX,
 54796            axisY,
 54797            axisZ,
 54798            denominator,
 54799            squaredDistance);
 800    }
 801
 802
 803    private static void GetCenteredCapsuleTriangleDepth(
 804        AxisTriangleCandidate candidate,
 805        Fixed64 radius,
 806        out Fixed64 depth,
 807        out bool depthIsClamped)
 808    {
 5809        GetCenteredRadiusDepth(
 5810            candidate.SquaredDistanceNumerator,
 5811            candidate.Denominator,
 5812            Signed192.Signed(radius.m_rawValue),
 5813            out depth,
 5814            out depthIsClamped);
 5815    }
 816}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredAxisTriangle.Materialization.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.CenteredAxisTriangle.Materialization.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
 8namespace FixedMathSharp.Geometry;
 9
 10/// <content>
 11/// Helpers for materializing wide-precision axis/triangle intersection
 12/// candidates back into <see cref="Fixed64"/>/<see cref="Vector3d"/> results,
 13/// including triangle containment tests and normal/edge computations.
 14/// </content>
 15internal static partial class WideFiniteAxisIntersection
 16{
 17    private static bool ContainsTriangleProjection(
 18        FixedTriangle triangle,
 19        Signed192 normalX,
 20        Signed192 normalY,
 21        Signed192 normalZ,
 22        Signed576 pointX,
 23        Signed576 pointY,
 24        Signed576 pointZ,
 25        Signed576 denominator) =>
 1626        IsInsideTriangleEdge(
 1627            triangle.A,
 1628            triangle.B,
 1629            normalX,
 1630            normalY,
 1631            normalZ,
 1632            pointX,
 1633            pointY,
 1634            pointZ,
 1635            denominator)
 1636        && IsInsideTriangleEdge(
 1637            triangle.B,
 1638            triangle.C,
 1639            normalX,
 1640            normalY,
 1641            normalZ,
 1642            pointX,
 1643            pointY,
 1644            pointZ,
 1645            denominator)
 1646        && IsInsideTriangleEdge(
 1647            triangle.C,
 1648            triangle.A,
 1649            normalX,
 1650            normalY,
 1651            normalZ,
 1652            pointX,
 1653            pointY,
 1654            pointZ,
 1655            denominator);
 56
 57    private static bool IsInsideTriangleEdge(
 58        Vector3d start,
 59        Vector3d end,
 60        Signed192 normalX,
 61        Signed192 normalY,
 62        Signed192 normalZ,
 63        Signed576 pointX,
 64        Signed576 pointY,
 65        Signed576 pointZ,
 66        Signed576 denominator)
 67    {
 4568        Signed192 edgeX = GetComponentDifference(end.X, start.X);
 4569        Signed192 edgeY = GetComponentDifference(end.Y, start.Y);
 4570        Signed192 edgeZ = GetComponentDifference(end.Z, start.Z);
 4571        Signed320 inwardX = WideArithmetic.MultiplySubtract(
 4572            normalY,
 4573            edgeZ,
 4574            normalZ,
 4575            edgeY);
 4576        Signed320 inwardY = WideArithmetic.MultiplySubtract(
 4577            normalZ,
 4578            edgeX,
 4579            normalX,
 4580            edgeZ);
 4581        Signed320 inwardZ = WideArithmetic.MultiplySubtract(
 4582            normalX,
 4583            edgeY,
 4584            normalY,
 4585            edgeX);
 4586        Signed704 side = WideArithmetic.AddSigned704(
 4587            WideArithmetic.AddSigned704(
 4588                WideArithmetic.MultiplySigned576ToSigned704(
 4589                    SubtractVertex(pointX, start.X, denominator),
 4590                    inwardX),
 4591                WideArithmetic.MultiplySigned576ToSigned704(
 4592                    SubtractVertex(pointY, start.Y, denominator),
 4593                    inwardY)),
 4594            WideArithmetic.MultiplySigned576ToSigned704(
 4595                SubtractVertex(pointZ, start.Z, denominator),
 4596                inwardZ));
 4597        return side.Sign >= 0;
 98    }
 99
 100    private static Signed576 SubtractVertex(
 101        Signed576 point,
 102        Fixed64 vertex,
 103        Signed320 denominator) =>
 18104        WideArithmetic.SubtractSigned576(
 18105            point,
 18106            WideArithmetic.MultiplySigned320(
 18107                Signed320.ExtendValue(
 18108                    Signed192.Signed(vertex.m_rawValue)),
 18109                denominator));
 110
 111    private static Signed576 SubtractVertex(
 112        Signed576 point,
 113        Fixed64 vertex,
 114        Signed576 denominator) =>
 135115        WideArithmetic.SubtractSigned576(
 135116            point,
 135117            WideArithmetic.MultiplySigned576(
 135118                denominator,
 135119                Signed192.Signed(vertex.m_rawValue)));
 120
 121    private static Signed320 GetWideDot(
 122        Signed192 x,
 123        Signed192 y,
 124        Signed192 z,
 125        Vector3d end,
 126        Vector3d start) =>
 24127        WideArithmetic.AddSigned320(
 24128            WideArithmetic.AddSigned320(
 24129                WideArithmetic.MultiplySigned192(
 24130                    x,
 24131                    GetComponentDifference(end.X, start.X)),
 24132                WideArithmetic.MultiplySigned192(
 24133                    y,
 24134                    GetComponentDifference(end.Y, start.Y))),
 24135            WideArithmetic.MultiplySigned192(
 24136                z,
 24137                GetComponentDifference(end.Z, start.Z)));
 138
 139    private static void GetTriangleNormal(
 140        FixedTriangle triangle,
 141        out Signed192 x,
 142        out Signed192 y,
 143        out Signed192 z) =>
 25144        WideGeometry.GetDifferenceCrossProduct3D(
 25145            triangle.B.X,
 25146            triangle.A.X,
 25147            triangle.B.Y,
 25148            triangle.A.Y,
 25149            triangle.B.Z,
 25150            triangle.A.Z,
 25151            triangle.C.X,
 25152            triangle.A.X,
 25153            triangle.C.Y,
 25154            triangle.A.Y,
 25155            triangle.C.Z,
 25156            triangle.A.Z,
 25157            out x,
 25158            out y,
 25159            out z);
 160
 161    private static bool TryMaterialize(
 162        AxisTriangleCandidate candidate,
 163        out Vector3d pointOnTriangle,
 164        out Vector3d pointOnAxis)
 165    {
 166        // A selected triangle candidate is a convex combination of authored
 167        // vertices, so its coordinates remain representable.
 10168        _ = Fixed64.TryGetSignedRawRatio(
 10169            candidate.TriangleX,
 10170            candidate.Denominator,
 10171            out Fixed64 triangleX);
 10172        _ = Fixed64.TryGetSignedRawRatio(
 10173            candidate.TriangleY,
 10174            candidate.Denominator,
 10175            out Fixed64 triangleY);
 10176        _ = Fixed64.TryGetSignedRawRatio(
 10177            candidate.TriangleZ,
 10178            candidate.Denominator,
 10179            out Fixed64 triangleZ);
 10180        bool representable = Fixed64.TryGetSignedRawRatio(
 10181            candidate.AxisX,
 10182            candidate.Denominator,
 10183            out Fixed64 axisX);
 10184        representable &= Fixed64.TryGetSignedRawRatio(
 10185            candidate.AxisY,
 10186            candidate.Denominator,
 10187            out Fixed64 axisY);
 10188        representable &= Fixed64.TryGetSignedRawRatio(
 10189            candidate.AxisZ,
 10190            candidate.Denominator,
 10191            out Fixed64 axisZ);
 10192        if (!representable)
 193        {
 1194            pointOnTriangle = default;
 1195            pointOnAxis = default;
 1196            return false;
 197        }
 198
 9199        pointOnTriangle = new Vector3d(triangleX, triangleY, triangleZ);
 9200        pointOnAxis = new Vector3d(axisX, axisY, axisZ);
 9201        return true;
 202    }
 203
 204    private static bool TryOffsetPoint(
 205        Vector3d point,
 206        Vector3d direction,
 207        Fixed64 distance,
 208        out Vector3d result)
 209    {
 3210        bool representable =
 3211            Fixed64.TryMultiplyAdd(direction.X, distance, point.X, out Fixed64 x)
 3212            & Fixed64.TryMultiplyAdd(direction.Y, distance, point.Y, out Fixed64 y)
 3213            & Fixed64.TryMultiplyAdd(direction.Z, distance, point.Z, out Fixed64 z);
 3214        result = representable ? new Vector3d(x, y, z) : default;
 3215        return representable;
 216    }
 217
 218    private static bool TryGetRelativeCoordinate(
 219        Signed576 pointNumerator,
 220        Fixed64 origin,
 221        Signed576 denominator,
 222        out Fixed64 coordinate)
 223    {
 18224        Signed576 originNumerator = WideArithmetic.MultiplySigned576(
 18225            denominator,
 18226            Signed192.Signed(origin.m_rawValue));
 18227        return Fixed64.TryGetSignedRawRatio(
 18228            WideArithmetic.SubtractSigned576(
 18229                pointNumerator,
 18230                originNumerator),
 18231            denominator,
 18232            out coordinate);
 233    }
 234
 235}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredCapsule.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.CenteredCapsule.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
 8namespace FixedMathSharp.Geometry;
 9
 10/// <content>
 11/// Provides high-precision surface point and offset calculations for capsules
 12/// centered at the origin (or a given center), using a fixed axis and radius.
 13/// </content>
 14internal static partial class WideFiniteAxisIntersection
 15{
 16    internal static bool TryGetSurfacePointOnCenteredCapsule(
 17        Vector2d point,
 18        Vector2d center,
 19        Vector2d axisDirection,
 20        Fixed64 axisLength,
 21        Fixed64 radius,
 22        Vector2d normal,
 23        out Vector2d surfacePoint)
 24    {
 825        GetClosestCenteredAxisRatio(
 826            point,
 827            center,
 828            axisDirection,
 829            axisLength,
 830            out Signed192 numerator,
 831            out Signed192 denominator);
 832        if (!TryGetCenteredCapsuleSurfaceCoordinate(
 833                center.X, axisDirection.X, numerator, denominator, normal.X, radius, out Fixed64 x)
 834            || !TryGetCenteredCapsuleSurfaceCoordinate(
 835                center.Y, axisDirection.Y, numerator, denominator, normal.Y, radius, out Fixed64 y))
 36        {
 337            surfacePoint = default;
 338            return false;
 39        }
 40
 541        surfacePoint = new Vector2d(x, y);
 542        return true;
 43    }
 44
 45    internal static bool TryGetSurfaceOffsetOnCenteredCapsule(
 46        Vector2d point,
 47        Vector2d center,
 48        Vector2d axisDirection,
 49        Fixed64 axisLength,
 50        Fixed64 radius,
 51        Vector2d normal,
 52        out Vector2d surfaceOffset)
 53    {
 454        GetClosestCenteredAxisRatio(
 455            point,
 456            center,
 457            axisDirection,
 458            axisLength,
 459            out Signed192 numerator,
 460            out Signed192 denominator);
 461        bool representable =
 462            TryGetCenteredCapsuleSurfaceCoordinate(
 463                Fixed64.Zero,
 464                axisDirection.X,
 465                numerator,
 466                denominator,
 467                normal.X,
 468                radius,
 469                out Fixed64 x)
 470            & TryGetCenteredCapsuleSurfaceCoordinate(
 471                Fixed64.Zero,
 472                axisDirection.Y,
 473                numerator,
 474                denominator,
 475                normal.Y,
 476                radius,
 477                out Fixed64 y);
 478        surfaceOffset = representable ? new Vector2d(x, y) : default;
 479        return representable;
 80    }
 81
 82    internal static bool TryGetSurfaceOffsetOnCenteredCapsule(
 83        Vector3d point,
 84        Vector3d center,
 85        Vector3d axisDirection,
 86        Fixed64 axisLength,
 87        Fixed64 radius,
 88        Vector3d normal,
 89        out Vector3d surfaceOffset)
 90    {
 391        GetClosestCenteredAxisRatio(
 392            point,
 393            center,
 394            axisDirection,
 395            axisLength,
 396            out Signed192 numerator,
 397            out Signed192 denominator);
 398        bool representable =
 399            TryGetCenteredCapsuleSurfaceCoordinate(
 3100                Fixed64.Zero, axisDirection.X, numerator, denominator, normal.X, radius, out Fixed64 x)
 3101            & TryGetCenteredCapsuleSurfaceCoordinate(
 3102                Fixed64.Zero, axisDirection.Y, numerator, denominator, normal.Y, radius, out Fixed64 y)
 3103            & TryGetCenteredCapsuleSurfaceCoordinate(
 3104                Fixed64.Zero, axisDirection.Z, numerator, denominator, normal.Z, radius, out Fixed64 z);
 3105        surfaceOffset = representable ? new Vector3d(x, y, z) : default;
 3106        return representable;
 107    }
 108
 109    internal static bool TryGetSurfacePointOnCenteredCapsule(
 110        Vector3d point,
 111        Vector3d center,
 112        Vector3d axisDirection,
 113        Fixed64 axisLength,
 114        Fixed64 radius,
 115        Vector3d normal,
 116        out Vector3d surfacePoint)
 117    {
 6118        GetClosestCenteredAxisRatio(
 6119            point,
 6120            center,
 6121            axisDirection,
 6122            axisLength,
 6123            out Signed192 numerator,
 6124            out Signed192 denominator);
 6125        if (!TryGetCenteredCapsuleSurfaceCoordinate(
 6126                center.X, axisDirection.X, numerator, denominator, normal.X, radius, out Fixed64 x)
 6127            || !TryGetCenteredCapsuleSurfaceCoordinate(
 6128                center.Y, axisDirection.Y, numerator, denominator, normal.Y, radius, out Fixed64 y)
 6129            || !TryGetCenteredCapsuleSurfaceCoordinate(
 6130                center.Z, axisDirection.Z, numerator, denominator, normal.Z, radius, out Fixed64 z))
 131        {
 4132            surfacePoint = default;
 4133            return false;
 134        }
 135
 2136        surfacePoint = new Vector3d(x, y, z);
 2137        return true;
 138    }
 139
 140    internal static bool ContainsPointInCenteredCapsule(
 141        Vector2d point,
 142        Vector2d center,
 143        Vector2d axisDirection,
 144        Fixed64 axisLength,
 145        Fixed64 radius,
 146        Fixed64 radiusExpansion,
 147        bool strict)
 148    {
 18149        Signed192 expandedRadius = GetExpandedRadius(radius, radiusExpansion);
 18150        Signed192 axisLengthSquared = GetDot(axisDirection, Vector2d.Zero, axisDirection, Vector2d.Zero);
 18151        Signed192 axisProjection = GetDot(point, center, axisDirection, Vector2d.Zero);
 18152        return IsCenteredCapsulePointContained(
 18153            point,
 18154            center,
 18155            axisDirection,
 18156            axisLength,
 18157            GetDot(point, center, point, center),
 18158            axisProjection,
 18159            axisLengthSquared,
 18160            GetSquaredRadius(expandedRadius),
 18161            expandedRadius,
 18162            GetCenteredAxialExtent(axisLengthSquared, axisLength, Fixed64.Zero),
 18163            strict);
 164    }
 165
 166    internal static bool ContainsPointInCenteredCapsule(
 167        Vector3d point,
 168        Vector3d center,
 169        Vector3d axisDirection,
 170        Fixed64 axisLength,
 171        Fixed64 radius,
 172        Fixed64 radiusExpansion,
 173        bool strict)
 174    {
 10175        Signed192 expandedRadius = GetExpandedRadius(radius, radiusExpansion);
 10176        Signed192 axisLengthSquared = GetDot(axisDirection, Vector3d.Zero, axisDirection, Vector3d.Zero);
 10177        Signed192 axisProjection = GetDot(point, center, axisDirection, Vector3d.Zero);
 10178        return IsCenteredCapsulePointContained(
 10179            point,
 10180            center,
 10181            axisDirection,
 10182            axisLength,
 10183            GetDot(point, center, point, center),
 10184            axisProjection,
 10185            axisLengthSquared,
 10186            GetSquaredRadius(expandedRadius),
 10187            expandedRadius,
 10188            GetCenteredAxialExtent(axisLengthSquared, axisLength, Fixed64.Zero),
 10189            strict);
 190    }
 191
 192    internal static Vector2d GetDirectionFromCenteredAxis(
 193        Vector2d point,
 194        Vector2d center,
 195        Vector2d axisDirection,
 196        Fixed64 axisLength)
 197    {
 6198        Signed192 differenceX = GetComponentDifference(point.X, center.X);
 6199        Signed192 differenceY = GetComponentDifference(point.Y, center.Y);
 6200        Signed192 axisLengthSquared = GetDot(axisDirection, Vector2d.Zero, axisDirection, Vector2d.Zero);
 6201        Signed192 axisProjection = GetDot(point, center, axisDirection, Vector2d.Zero);
 6202        int cap = GetCenteredCap(
 6203            axisProjection,
 6204            GetCenteredAxialExtent(axisLengthSquared, axisLength, Fixed64.Zero));
 6205        if (cap != 0)
 206        {
 1207            return WideNormalization.GetNormalized(
 1208                GetCenteredCapOffset(point.X, center.X, axisDirection.X, axisLength, cap > 0),
 1209                GetCenteredCapOffset(point.Y, center.Y, axisDirection.Y, axisLength, cap > 0));
 210        }
 211
 5212        Signed192 axisX = Signed192.Signed(axisDirection.X.m_rawValue);
 5213        Signed192 axisY = Signed192.Signed(axisDirection.Y.m_rawValue);
 5214        return WideNormalization.GetNormalized(
 5215            GetRadialComponent(axisLengthSquared, differenceX, axisX, axisProjection),
 5216            GetRadialComponent(axisLengthSquared, differenceY, axisY, axisProjection));
 217    }
 218
 219    internal static Vector3d GetDirectionFromCenteredAxis(
 220        Vector3d point,
 221        Vector3d center,
 222        Vector3d axisDirection,
 223        Fixed64 axisLength)
 224    {
 4225        Signed192 differenceX = GetComponentDifference(point.X, center.X);
 4226        Signed192 differenceY = GetComponentDifference(point.Y, center.Y);
 4227        Signed192 differenceZ = GetComponentDifference(point.Z, center.Z);
 4228        Signed192 axisLengthSquared = GetDot(axisDirection, Vector3d.Zero, axisDirection, Vector3d.Zero);
 4229        Signed192 axisProjection = GetDot(point, center, axisDirection, Vector3d.Zero);
 4230        int cap = GetCenteredCap(
 4231            axisProjection,
 4232            GetCenteredAxialExtent(axisLengthSquared, axisLength, Fixed64.Zero));
 4233        if (cap != 0)
 234        {
 1235            return WideNormalization.GetNormalized(
 1236                GetCenteredCapOffset(point.X, center.X, axisDirection.X, axisLength, cap > 0),
 1237                GetCenteredCapOffset(point.Y, center.Y, axisDirection.Y, axisLength, cap > 0),
 1238                GetCenteredCapOffset(point.Z, center.Z, axisDirection.Z, axisLength, cap > 0));
 239        }
 240
 3241        Signed192 axisX = Signed192.Signed(axisDirection.X.m_rawValue);
 3242        Signed192 axisY = Signed192.Signed(axisDirection.Y.m_rawValue);
 3243        Signed192 axisZ = Signed192.Signed(axisDirection.Z.m_rawValue);
 3244        return WideNormalization.GetNormalized(
 3245            GetRadialComponent(axisLengthSquared, differenceX, axisX, axisProjection),
 3246            GetRadialComponent(axisLengthSquared, differenceY, axisY, axisProjection),
 3247            GetRadialComponent(axisLengthSquared, differenceZ, axisZ, axisProjection));
 248    }
 249
 250    internal static bool TryGetCapsuleInterval(
 251        FixedSegment2d query,
 252        Vector2d center,
 253        Vector2d axisDirection,
 254        Fixed64 axisLength,
 255        Fixed64 radius,
 256        Fixed64 radiusExpansion,
 257        out Fixed64 entry,
 258        out Fixed64 exit,
 259        out bool startContained,
 260        out bool endContainedStrict)
 261    {
 143262        Signed192 expandedRadius = GetExpandedRadius(radius, radiusExpansion);
 143263        Signed192 squaredRadius = GetSquaredRadius(expandedRadius);
 143264        Signed192 axisLengthSquared = GetDot(axisDirection, Vector2d.Zero, axisDirection, Vector2d.Zero);
 143265        Signed192 queryLengthSquared = GetDot(query.End, query.Start, query.End, query.Start);
 143266        Signed192 startDistanceSquared = GetDot(query.Start, center, query.Start, center);
 143267        Signed192 directionsDot = GetDot(query.End, query.Start, axisDirection, Vector2d.Zero);
 143268        Signed192 startAxisProjection = GetDot(query.Start, center, axisDirection, Vector2d.Zero);
 143269        Signed192 endAxisProjection = GetDot(query.End, center, axisDirection, Vector2d.Zero);
 143270        Signed192 startDirectionProjection = GetDot(query.Start, center, query.End, query.Start);
 143271        Signed320 axialExtent = GetCenteredAxialExtent(
 143272            axisLengthSquared,
 143273            axisLength,
 143274            Fixed64.Zero);
 275
 143276        startContained = IsCenteredCapsulePointContained(
 143277            query.Start,
 143278            center,
 143279            axisDirection,
 143280            axisLength,
 143281            startDistanceSquared,
 143282            startAxisProjection,
 143283            axisLengthSquared,
 143284            squaredRadius,
 143285            expandedRadius,
 143286            axialExtent,
 143287            strict: false);
 143288        endContainedStrict = IsCenteredCapsulePointContained(
 143289            query.End,
 143290            center,
 143291            axisDirection,
 143292            axisLength,
 143293            GetDot(query.End, center, query.End, center),
 143294            endAxisProjection,
 143295            axisLengthSquared,
 143296            squaredRadius,
 143297            expandedRadius,
 143298            axialExtent,
 143299            strict: true);
 300
 143301        bool found = false;
 143302        entry = default;
 143303        exit = default;
 143304        if (TryGetCenteredAxialInterval(
 143305                startAxisProjection,
 143306                directionsDot,
 143307                axialExtent,
 143308                Fixed64.One,
 143309                out RationalBound320 lower,
 143310                out RationalBound320 upper))
 311        {
 139312            found = TryGetFiniteAxisInterval(
 139313                queryLengthSquared,
 139314                axisLengthSquared,
 139315                startDistanceSquared,
 139316                directionsDot,
 139317                startAxisProjection,
 139318                startDirectionProjection,
 139319                expandedRadius,
 139320                lower,
 139321                upper,
 139322                Fixed64.One,
 139323                out entry,
 139324                out exit);
 325        }
 326
 143327        MergeCenteredCapInterval(
 143328            query,
 143329            center,
 143330            axisDirection,
 143331            axisLength,
 143332            expandedRadius,
 143333            positiveCap: false,
 143334            ref found,
 143335            ref entry,
 143336            ref exit);
 143337        MergeCenteredCapInterval(
 143338            query,
 143339            center,
 143340            axisDirection,
 143341            axisLength,
 143342            expandedRadius,
 143343            positiveCap: true,
 143344            ref found,
 143345            ref entry,
 143346            ref exit);
 143347        return found;
 348    }
 349
 350    internal static bool TryGetCapsuleInterval(
 351        FixedSegment query,
 352        Vector3d center,
 353        Vector3d axisDirection,
 354        Fixed64 axisLength,
 355        Fixed64 radius,
 356        Fixed64 radiusExpansion,
 357        out Fixed64 entry,
 358        out Fixed64 exit,
 359        out bool startContained,
 360        out bool endContainedStrict)
 361    {
 6362        Signed192 expandedRadius = GetExpandedRadius(radius, radiusExpansion);
 6363        Signed192 squaredRadius = GetSquaredRadius(expandedRadius);
 6364        Signed192 axisLengthSquared = GetDot(axisDirection, Vector3d.Zero, axisDirection, Vector3d.Zero);
 6365        Signed192 queryLengthSquared = GetDot(query.End, query.Start, query.End, query.Start);
 6366        Signed192 startDistanceSquared = GetDot(query.Start, center, query.Start, center);
 6367        Signed192 directionsDot = GetDot(query.End, query.Start, axisDirection, Vector3d.Zero);
 6368        Signed192 startAxisProjection = GetDot(query.Start, center, axisDirection, Vector3d.Zero);
 6369        Signed192 endAxisProjection = GetDot(query.End, center, axisDirection, Vector3d.Zero);
 6370        Signed192 startDirectionProjection = GetDot(query.Start, center, query.End, query.Start);
 6371        Signed320 axialExtent = GetCenteredAxialExtent(
 6372            axisLengthSquared,
 6373            axisLength,
 6374            Fixed64.Zero);
 375
 6376        startContained = IsCenteredCapsulePointContained(
 6377            query.Start,
 6378            center,
 6379            axisDirection,
 6380            axisLength,
 6381            startDistanceSquared,
 6382            startAxisProjection,
 6383            axisLengthSquared,
 6384            squaredRadius,
 6385            expandedRadius,
 6386            axialExtent,
 6387            strict: false);
 6388        endContainedStrict = IsCenteredCapsulePointContained(
 6389            query.End,
 6390            center,
 6391            axisDirection,
 6392            axisLength,
 6393            GetDot(query.End, center, query.End, center),
 6394            endAxisProjection,
 6395            axisLengthSquared,
 6396            squaredRadius,
 6397            expandedRadius,
 6398            axialExtent,
 6399            strict: true);
 400
 6401        bool found = false;
 6402        entry = default;
 6403        exit = default;
 6404        if (TryGetCenteredAxialInterval(
 6405                startAxisProjection,
 6406                directionsDot,
 6407                axialExtent,
 6408                Fixed64.One,
 6409                out RationalBound320 lower,
 6410                out RationalBound320 upper))
 411        {
 4412            found = TryGetFiniteAxisInterval(
 4413                queryLengthSquared,
 4414                axisLengthSquared,
 4415                startDistanceSquared,
 4416                directionsDot,
 4417                startAxisProjection,
 4418                startDirectionProjection,
 4419                expandedRadius,
 4420                lower,
 4421                upper,
 4422                Fixed64.One,
 4423                out entry,
 4424                out exit);
 425        }
 426
 6427        MergeCenteredCapInterval(
 6428            query,
 6429            center,
 6430            axisDirection,
 6431            axisLength,
 6432            expandedRadius,
 6433            positiveCap: false,
 6434            ref found,
 6435            ref entry,
 6436            ref exit);
 6437        MergeCenteredCapInterval(
 6438            query,
 6439            center,
 6440            axisDirection,
 6441            axisLength,
 6442            expandedRadius,
 6443            positiveCap: true,
 6444            ref found,
 6445            ref entry,
 6446            ref exit);
 6447        return found;
 448    }
 449
 450    private static bool IsCenteredCapsulePointContained(
 451        Vector2d point,
 452        Vector2d center,
 453        Vector2d axisDirection,
 454        Fixed64 axisLength,
 455        Signed192 distanceSquared,
 456        Signed192 axisProjection,
 457        Signed192 axisLengthSquared,
 458        Signed192 squaredRadius,
 459        Signed192 expandedRadius,
 460        Signed320 axialExtent,
 461        bool strict)
 462    {
 318463        int cap = GetCenteredCap(axisProjection, axialExtent);
 318464        if (cap == 0)
 465        {
 292466            int radialSign = GetRadialConstant(
 292467                distanceSquared,
 292468                axisProjection,
 292469                axisLengthSquared,
 292470                squaredRadius).Sign;
 292471            return strict ? radialSign < 0 : radialSign <= 0;
 472        }
 473
 26474        int capSign = GetCenteredCapConstant(
 26475            point,
 26476            center,
 26477            axisDirection,
 26478            axisLength,
 26479            expandedRadius,
 26480            positiveCap: cap > 0).Sign;
 26481        return strict ? capSign < 0 : capSign <= 0;
 482    }
 483
 484    private static bool IsCenteredCapsulePointContained(
 485        Vector3d point,
 486        Vector3d center,
 487        Vector3d axisDirection,
 488        Fixed64 axisLength,
 489        Signed192 distanceSquared,
 490        Signed192 axisProjection,
 491        Signed192 axisLengthSquared,
 492        Signed192 squaredRadius,
 493        Signed192 expandedRadius,
 494        Signed320 axialExtent,
 495        bool strict)
 496    {
 59497        int cap = GetCenteredCap(axisProjection, axialExtent);
 59498        if (cap == 0)
 499        {
 19500            int radialSign = GetRadialConstant(
 19501                distanceSquared,
 19502                axisProjection,
 19503                axisLengthSquared,
 19504                squaredRadius).Sign;
 19505            return strict ? radialSign < 0 : radialSign <= 0;
 506        }
 507
 40508        int capSign = GetCenteredCapConstant(
 40509            point,
 40510            center,
 40511            axisDirection,
 40512            axisLength,
 40513            expandedRadius,
 40514            positiveCap: cap > 0).Sign;
 40515        return strict ? capSign < 0 : capSign <= 0;
 516    }
 517
 518    private static int GetCenteredCap(Signed192 axisProjection, Signed320 axialExtent)
 519    {
 431520        Signed320 scaledProjection = WideArithmetic.MultiplySigned192(DoubleParameterScale, axisProjection);
 431521        if (WideArithmetic.AddSigned320(scaledProjection, axialExtent).Sign <= 0)
 38522            return -1;
 393523        return WideArithmetic.SubtractSigned320(scaledProjection, axialExtent).Sign >= 0
 393524            ? 1
 393525            : 0;
 526    }
 527
 528    private static void MergeCenteredCapInterval(
 529        FixedSegment2d query,
 530        Vector2d center,
 531        Vector2d axisDirection,
 532        Fixed64 axisLength,
 533        Signed192 expandedRadius,
 534        bool positiveCap,
 535        ref bool found,
 536        ref Fixed64 entry,
 537        ref Fixed64 exit)
 538    {
 286539        GetCenteredCapPolynomial(
 286540            query,
 286541            center,
 286542            axisDirection,
 286543            axisLength,
 286544            expandedRadius,
 286545            positiveCap,
 286546            out Signed320 coefficient,
 286547            out Signed320 projection,
 286548            out Signed320 constant);
 286549        Merge(
 286550            TrySolveUnitQuadratic(coefficient, projection, constant, out Fixed64 capEntry, out Fixed64 capExit),
 286551            capEntry,
 286552            capExit,
 286553            ref found,
 286554            ref entry,
 286555            ref exit);
 286556    }
 557
 558    private static void MergeCenteredCapInterval(
 559        FixedSegment query,
 560        Vector3d center,
 561        Vector3d axisDirection,
 562        Fixed64 axisLength,
 563        Signed192 expandedRadius,
 564        bool positiveCap,
 565        ref bool found,
 566        ref Fixed64 entry,
 567        ref Fixed64 exit)
 568    {
 12569        GetCenteredCapPolynomial(
 12570            query,
 12571            center,
 12572            axisDirection,
 12573            axisLength,
 12574            expandedRadius,
 12575            positiveCap,
 12576            out Signed320 coefficient,
 12577            out Signed320 projection,
 12578            out Signed320 constant);
 12579        Merge(
 12580            TrySolveUnitQuadratic(coefficient, projection, constant, out Fixed64 capEntry, out Fixed64 capExit),
 12581            capEntry,
 12582            capExit,
 12583            ref found,
 12584            ref entry,
 12585            ref exit);
 12586    }
 587
 588    private static void GetCenteredCapPolynomial(
 589        FixedSegment2d query,
 590        Vector2d center,
 591        Vector2d axisDirection,
 592        Fixed64 axisLength,
 593        Signed192 expandedRadius,
 594        bool positiveCap,
 595        out Signed320 coefficient,
 596        out Signed320 projection,
 597        out Signed320 constant)
 598    {
 296599        Signed192 x = GetCenteredCapOffset(
 296600            query.Start.X,
 296601            center.X,
 296602            axisDirection.X,
 296603            axisLength,
 296604            positiveCap);
 296605        Signed192 y = GetCenteredCapOffset(
 296606            query.Start.Y,
 296607            center.Y,
 296608            axisDirection.Y,
 296609            axisLength,
 296610            positiveCap);
 296611        Signed192 velocityX = GetScaledDifference(query.End.X, query.Start.X);
 296612        Signed192 velocityY = GetScaledDifference(query.End.Y, query.Start.Y);
 296613        Signed192 scaledRadius = ScaleByCenteredAxis(expandedRadius);
 614
 296615        coefficient = WideArithmetic.AddProducts(velocityX, velocityX, velocityY, velocityY);
 296616        projection = WideArithmetic.AddProducts(x, velocityX, y, velocityY);
 296617        constant = WideArithmetic.SubtractSigned320(
 296618            WideArithmetic.AddProducts(x, x, y, y),
 296619            WideArithmetic.MultiplySigned192(scaledRadius, scaledRadius));
 296620    }
 621
 622    private static void GetCenteredCapPolynomial(
 623        FixedSegment query,
 624        Vector3d center,
 625        Vector3d axisDirection,
 626        Fixed64 axisLength,
 627        Signed192 expandedRadius,
 628        bool positiveCap,
 629        out Signed320 coefficient,
 630        out Signed320 projection,
 631        out Signed320 constant)
 632    {
 44633        Signed192 x = GetCenteredCapOffset(
 44634            query.Start.X,
 44635            center.X,
 44636            axisDirection.X,
 44637            axisLength,
 44638            positiveCap);
 44639        Signed192 y = GetCenteredCapOffset(
 44640            query.Start.Y,
 44641            center.Y,
 44642            axisDirection.Y,
 44643            axisLength,
 44644            positiveCap);
 44645        Signed192 z = GetCenteredCapOffset(
 44646            query.Start.Z,
 44647            center.Z,
 44648            axisDirection.Z,
 44649            axisLength,
 44650            positiveCap);
 44651        Signed192 velocityX = GetScaledDifference(query.End.X, query.Start.X);
 44652        Signed192 velocityY = GetScaledDifference(query.End.Y, query.Start.Y);
 44653        Signed192 velocityZ = GetScaledDifference(query.End.Z, query.Start.Z);
 44654        Signed192 scaledRadius = ScaleByCenteredAxis(expandedRadius);
 655
 44656        coefficient = WideArithmetic.AddProducts(velocityX, velocityX, velocityY, velocityY, velocityZ, velocityZ);
 44657        projection = WideArithmetic.AddProducts(x, velocityX, y, velocityY, z, velocityZ);
 44658        constant = WideArithmetic.SubtractSigned320(
 44659            WideArithmetic.AddProducts(x, x, y, y, z, z),
 44660            WideArithmetic.MultiplySigned192(scaledRadius, scaledRadius));
 44661    }
 662
 663    private static Signed320 GetCenteredCapConstant(
 664        Vector2d point,
 665        Vector2d center,
 666        Vector2d axisDirection,
 667        Fixed64 axisLength,
 668        Signed192 expandedRadius,
 669        bool positiveCap)
 670    {
 26671        Signed192 x = GetCenteredCapOffset(
 26672            point.X,
 26673            center.X,
 26674            axisDirection.X,
 26675            axisLength,
 26676            positiveCap);
 26677        Signed192 y = GetCenteredCapOffset(
 26678            point.Y,
 26679            center.Y,
 26680            axisDirection.Y,
 26681            axisLength,
 26682            positiveCap);
 26683        Signed192 scaledRadius = ScaleByCenteredAxis(expandedRadius);
 26684        return WideArithmetic.SubtractSigned320(
 26685            WideArithmetic.AddProducts(x, x, y, y),
 26686            WideArithmetic.MultiplySigned192(scaledRadius, scaledRadius));
 687    }
 688
 689    private static Signed320 GetCenteredCapConstant(
 690        Vector3d point,
 691        Vector3d center,
 692        Vector3d axisDirection,
 693        Fixed64 axisLength,
 694        Signed192 expandedRadius,
 695        bool positiveCap)
 696    {
 40697        Signed192 x = GetCenteredCapOffset(
 40698            point.X,
 40699            center.X,
 40700            axisDirection.X,
 40701            axisLength,
 40702            positiveCap);
 40703        Signed192 y = GetCenteredCapOffset(
 40704            point.Y,
 40705            center.Y,
 40706            axisDirection.Y,
 40707            axisLength,
 40708            positiveCap);
 40709        Signed192 z = GetCenteredCapOffset(
 40710            point.Z,
 40711            center.Z,
 40712            axisDirection.Z,
 40713            axisLength,
 40714            positiveCap);
 40715        Signed192 scaledRadius = ScaleByCenteredAxis(expandedRadius);
 40716        return WideArithmetic.SubtractSigned320(
 40717            WideArithmetic.AddProducts(x, x, y, y, z, z),
 40718            WideArithmetic.MultiplySigned192(scaledRadius, scaledRadius));
 719    }
 720
 721    private static Signed192 GetCenteredCapOffset(
 722        Fixed64 point,
 723        Fixed64 center,
 724        Fixed64 axisDirection,
 725        Fixed64 axisLength,
 726        bool positiveCap)
 727    {
 962728        Signed192 difference = WideArithmetic.SubtractSigned192(
 962729            Signed192.Signed(point.m_rawValue),
 962730            Signed192.Signed(center.m_rawValue));
 962731        Signed320 scaledDifference = WideArithmetic.MultiplySigned192(difference, DoubleParameterScale);
 962732        Signed320 directionalOffset = WideArithmetic.MultiplySigned192(
 962733            Signed192.Signed(axisDirection.m_rawValue),
 962734            Signed192.Signed(axisLength.m_rawValue));
 962735        return Signed192.NarrowValue(positiveCap
 962736            ? WideArithmetic.SubtractSigned320(scaledDifference, directionalOffset)
 962737            : WideArithmetic.AddSigned320(scaledDifference, directionalOffset));
 738    }
 739
 740    private static Signed320 GetRadialComponent(
 741        Signed192 axisLengthSquared,
 742        Signed192 difference,
 743        Signed192 axisComponent,
 744        Signed192 axisProjection) =>
 19745        WideArithmetic.SubtractSigned320(
 19746            WideArithmetic.MultiplySigned192(axisLengthSquared, difference),
 19747            WideArithmetic.MultiplySigned192(axisComponent, axisProjection));
 748
 749    private static void GetClosestCenteredAxisRatio(
 750        Vector2d point,
 751        Vector2d center,
 752        Vector2d axisDirection,
 753        Fixed64 axisLength,
 754        out Signed192 numerator,
 755        out Signed192 denominator)
 756    {
 27757        Signed192 axisLengthSquared = GetDot(axisDirection, Vector2d.Zero, axisDirection, Vector2d.Zero);
 27758        Signed192 axisProjection = GetDot(point, center, axisDirection, Vector2d.Zero);
 27759        int cap = GetCenteredCap(
 27760            axisProjection,
 27761            GetCenteredAxialExtent(axisLengthSquared, axisLength, Fixed64.Zero));
 27762        if (cap == 0)
 763        {
 18764            numerator = axisProjection;
 18765            denominator = axisLengthSquared;
 18766            return;
 767        }
 768
 9769        numerator = Signed192.Signed(
 9770            cap < 0 ? -axisLength.m_rawValue : axisLength.m_rawValue);
 9771        denominator = DoubleParameterScale;
 9772    }
 773
 774    private static void GetClosestCenteredAxisRatio(
 775        Vector3d point,
 776        Vector3d center,
 777        Vector3d axisDirection,
 778        Fixed64 axisLength,
 779        out Signed192 numerator,
 780        out Signed192 denominator)
 781    {
 17782        Signed192 axisLengthSquared = GetDot(axisDirection, Vector3d.Zero, axisDirection, Vector3d.Zero);
 17783        Signed192 axisProjection = GetDot(point, center, axisDirection, Vector3d.Zero);
 17784        int cap = GetCenteredCap(
 17785            axisProjection,
 17786            GetCenteredAxialExtent(axisLengthSquared, axisLength, Fixed64.Zero));
 17787        if (cap == 0)
 788        {
 9789            numerator = axisProjection;
 9790            denominator = axisLengthSquared;
 9791            return;
 792        }
 793
 8794        numerator = Signed192.Signed(
 8795            cap < 0 ? -axisLength.m_rawValue : axisLength.m_rawValue);
 8796        denominator = DoubleParameterScale;
 8797    }
 798
 799    private static bool TryGetCenteredCapsuleSurfaceCoordinate(
 800        Fixed64 center,
 801        Fixed64 axisDirection,
 802        Signed192 axisNumerator,
 803        Signed192 axisDenominator,
 804        Fixed64 normal,
 805        Fixed64 radius,
 806        out Fixed64 coordinate)
 807    {
 50808        Signed320 centerTerm = MultiplyThreeToSigned320(
 50809            Signed192.Signed(center.m_rawValue),
 50810            axisDenominator,
 50811            ParameterScale);
 50812        Signed320 axisTerm = MultiplyThreeToSigned320(
 50813            Signed192.Signed(axisDirection.m_rawValue),
 50814            axisNumerator,
 50815            ParameterScale);
 50816        Signed320 radialTerm = MultiplyThreeToSigned320(
 50817            Signed192.Signed(normal.m_rawValue),
 50818            Signed192.Signed(radius.m_rawValue),
 50819            axisDenominator);
 50820        Signed320 denominator = MultiplyThreeToSigned320(
 50821            axisDenominator,
 50822            ParameterScale,
 50823            ParameterScale);
 50824        Signed320 numerator = WideArithmetic.AddSigned320(
 50825            WideArithmetic.AddSigned320(centerTerm, axisTerm),
 50826            radialTerm);
 50827        return Fixed64.TryGetSignedRatio(numerator, denominator, out coordinate);
 828    }
 829
 830    private static Signed320 MultiplyThreeToSigned320(
 831        Signed192 first,
 832        Signed192 second,
 833        Signed192 third) =>
 834        // Centered-capsule surface terms use at most 194 signed bits. The upper
 835        // four words are therefore sign extension before this mechanical narrow.
 355836        Signed320.NarrowValue(WideArithmetic.MultiplySigned320(
 355837            WideArithmetic.MultiplySigned192(first, second),
 355838            Signed320.ExtendValue(third)));
 839
 840    private static Signed320 GetCenteredAxisOffsetComponent(
 841        Fixed64 point,
 842        Fixed64 center,
 843        Fixed64 axisDirection,
 844        Signed192 axisNumerator,
 845        Signed192 axisDenominator) =>
 45846        WideArithmetic.MultiplySubtract(
 45847            GetComponentDifference(point, center),
 45848            axisDenominator,
 45849            Signed192.Signed(axisDirection.m_rawValue),
 45850            axisNumerator);
 851
 852    private static Signed192 GetComponentDifference(Fixed64 point, Fixed64 center) =>
 465853        WideArithmetic.SubtractSigned192(
 465854            Signed192.Signed(point.m_rawValue),
 465855            Signed192.Signed(center.m_rawValue));
 856
 857    private static Signed192 GetScaledDifference(Fixed64 end, Fixed64 start) =>
 724858        ScaleByCenteredAxis(WideArithmetic.SubtractSigned192(
 724859            Signed192.Signed(end.m_rawValue),
 724860            Signed192.Signed(start.m_rawValue)));
 861
 862    private static Signed192 ScaleByCenteredAxis(Signed192 value) =>
 863        // A doubled full-domain coordinate difference plus one normalized-axis
 864        // component times a nonnegative Fixed64 full length uses at most 98 signed
 865        // bits. The upper two words are therefore sign extension.
 1215866        Signed192.NarrowValue(WideArithmetic.MultiplySigned192(value, DoubleParameterScale));
 867
 868    private static bool TrySolveUnitQuadratic(
 869        Signed320 coefficient,
 870        Signed320 projection,
 871        Signed320 constant,
 872        out Fixed64 entry,
 873        out Fixed64 exit)
 874    {
 298875        Signed320 one = Scale320;
 298876        return TrySolveBoundedQuadratic(
 298877            coefficient,
 298878            projection,
 298879            constant,
 298880            new RationalBound320(default, one),
 298881            new RationalBound320(one, one),
 298882            Fixed64.One,
 298883            out entry,
 298884            out exit);
 885    }
 886
 887}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredCapsuleAnchor.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.CenteredCapsuleAnchor.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
 8namespace FixedMathSharp.Geometry;
 9
 10/// <content>
 11/// Provides methods for computing surface anchors on capsules centered at a given point,
 12/// supporting both 2D and 3D representations with rotation and axis-aligned variants.
 13/// </content>
 14internal static partial class WideFiniteAxisIntersection
 15{
 16    internal static FixedPointAnchor2d GetSurfaceAnchorOnCenteredCapsule(
 17        Vector2d point,
 18        Vector2d center,
 19        Fixed64 frameRotation,
 20        Vector2d localAxisDirection,
 21        Fixed64 axisLength,
 22        Fixed64 radius,
 23        Vector2d localNormal)
 24    {
 325        _ = Vector2d.TryRotate(
 326            localAxisDirection,
 327            frameRotation,
 328            out Vector2d axisDirection);
 329        GetClosestCenteredAxisRatio(
 330            point,
 331            center,
 332            axisDirection,
 333            axisLength,
 334            out Signed192 numerator,
 335            out Signed192 denominator);
 336        _ = TryGetCenteredCapsuleSurfaceCoordinate(
 337            Fixed64.Zero,
 338            Fixed64.One,
 339            numerator,
 340            denominator,
 341            Fixed64.Zero,
 342            Fixed64.Zero,
 343            out Fixed64 axialDistance);
 344        Vector2d roundedRadialOffset = localNormal * radius;
 345        return new FixedPointAnchor2d(
 346            center,
 347            frameRotation,
 348            localAxisDirection * axialDistance,
 349            roundedRadialOffset,
 350            FixedPointAnchorTerm2d.CreateRadialSupport(
 351                localNormal,
 352                radius,
 353                roundedRadialOffset));
 54    }
 55
 56    internal static FixedPointAnchor GetSurfaceAnchorOnCenteredCapsule(
 57        Vector3d point,
 58        Vector3d center,
 59        FixedQuaternion frameRotation,
 60        Vector3d localAxisDirection,
 61        Fixed64 axisLength,
 62        Fixed64 radius,
 63        Vector3d localNormal)
 64    {
 8965        GetRigidLocalPointRelation(
 8966            point,
 8967            center,
 8968            frameRotation,
 8969            localAxisDirection,
 8970            out RigidLocalPointRelation relation);
 8971        int cap = GetCenteredCap(relation, axisLength);
 8972        Fixed64 axialDistance = GetClosestCenteredRigidAxisDistance(
 8973            relation,
 8974            axisLength,
 8975            cap);
 8976        Vector3d roundedRadialOffset = localNormal * radius;
 8977        return new FixedPointAnchor(
 8978            center,
 8979            frameRotation,
 8980            localAxisDirection * axialDistance,
 8981            roundedRadialOffset,
 8982            FixedPointAnchorTerm3d.CreateRadialSupport(
 8983                localNormal,
 8984                radius,
 8985                roundedRadialOffset));
 86    }
 87
 88    internal static FixedPointAnchor GetSurfaceAnchorOnCenteredCapsule(
 89        Vector3d point,
 90        Vector3d center,
 91        Vector3d axisDirection,
 92        Fixed64 axisLength,
 93        Fixed64 radius,
 94        Vector3d surfaceDirection)
 95    {
 196        GetClosestCenteredAxisRatio(
 197            point,
 198            center,
 199            axisDirection,
 1100            axisLength,
 1101            out Signed192 numerator,
 1102            out Signed192 denominator);
 1103        _ = TryGetCenteredCapsuleSurfaceCoordinate(
 1104            Fixed64.Zero,
 1105            axisDirection.X,
 1106            numerator,
 1107            denominator,
 1108            Fixed64.Zero,
 1109            Fixed64.Zero,
 1110            out Fixed64 axialX);
 1111        _ = TryGetCenteredCapsuleSurfaceCoordinate(
 1112            Fixed64.Zero,
 1113            axisDirection.Y,
 1114            numerator,
 1115            denominator,
 1116            Fixed64.Zero,
 1117            Fixed64.Zero,
 1118            out Fixed64 axialY);
 1119        _ = TryGetCenteredCapsuleSurfaceCoordinate(
 1120            Fixed64.Zero,
 1121            axisDirection.Z,
 1122            numerator,
 1123            denominator,
 1124            Fixed64.Zero,
 1125            Fixed64.Zero,
 1126            out Fixed64 axialZ);
 1127        Vector3d roundedRadialOffset = surfaceDirection * radius;
 1128        return new FixedPointAnchor(
 1129            center,
 1130            FixedQuaternion.Identity,
 1131            new Vector3d(axialX, axialY, axialZ),
 1132            roundedRadialOffset,
 1133            FixedPointAnchorTerm3d.CreateRadialSupport(
 1134                surfaceDirection,
 1135                radius,
 1136                roundedRadialOffset));
 137    }
 138}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredCapsuleDistance.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.CenteredCapsuleDistance.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
 8namespace FixedMathSharp.Geometry;
 9
 10/// <content>
 11/// High-precision distance computations between a point and a centered capsule
 12/// (a finite axis segment with a radius), using wide integer arithmetic to
 13/// avoid overflow and rounding error in intermediate squared-distance terms.
 14/// </content>
 15internal static partial class WideFiniteAxisIntersection
 16{
 17    internal static bool TryGetDistanceToCenteredCapsule(
 18        Vector2d point,
 19        Vector2d center,
 20        Vector2d axisDirection,
 21        Fixed64 axisLength,
 22        Fixed64 radius,
 23        out Fixed64 distance)
 24    {
 1225        GetClosestCenteredAxisRatio(
 1226            point, center, axisDirection, axisLength, out Signed192 numerator, out Signed192 denominator);
 1227        Signed320 x = GetCenteredAxisOffsetComponent(
 1228            point.X, center.X, axisDirection.X, numerator, denominator);
 1229        Signed320 y = GetCenteredAxisOffsetComponent(
 1230            point.Y, center.Y, axisDirection.Y, numerator, denominator);
 1231        return TryGetDistanceToCenteredCapsule(
 1232            WideArithmetic.AddSigned576(
 1233                WideArithmetic.MultiplySigned320(x, x),
 1234                WideArithmetic.MultiplySigned320(y, y)),
 1235            denominator,
 1236            radius,
 1237            out distance);
 38    }
 39
 40    internal static bool TryGetDistanceToCenteredCapsule(
 41        Vector3d point,
 42        Vector3d center,
 43        Vector3d axisDirection,
 44        Fixed64 axisLength,
 45        Fixed64 radius,
 46        out Fixed64 distance)
 47    {
 748        GetClosestCenteredAxisRatio(
 749            point, center, axisDirection, axisLength, out Signed192 numerator, out Signed192 denominator);
 750        Signed320 x = GetCenteredAxisOffsetComponent(
 751            point.X, center.X, axisDirection.X, numerator, denominator);
 752        Signed320 y = GetCenteredAxisOffsetComponent(
 753            point.Y, center.Y, axisDirection.Y, numerator, denominator);
 754        Signed320 z = GetCenteredAxisOffsetComponent(
 755            point.Z, center.Z, axisDirection.Z, numerator, denominator);
 756        return TryGetDistanceToCenteredCapsule(
 757            WideArithmetic.AddSigned576(
 758                WideArithmetic.AddSigned576(
 759                    WideArithmetic.MultiplySigned320(x, x),
 760                    WideArithmetic.MultiplySigned320(y, y)),
 761                WideArithmetic.MultiplySigned320(z, z)),
 762            denominator,
 763            radius,
 764            out distance);
 65    }
 66
 67    internal static bool TryGetDistanceToCenteredCapsule(
 68        Signed576 squaredAxisDistanceNumerator,
 69        Signed192 axisDenominator,
 70        Fixed64 radius,
 71        out Fixed64 distance)
 72    {
 3273        Signed320 radiusAxis = WideArithmetic.MultiplySigned192(
 3274            Signed192.Signed(radius.m_rawValue),
 3275            axisDenominator);
 3276        Signed576 radiusAxisSquared = WideArithmetic.MultiplySigned320(radiusAxis, radiusAxis);
 3277        if (WideArithmetic.CompareNonNegative(
 3278                squaredAxisDistanceNumerator,
 3279                radiusAxisSquared) <= 0)
 80        {
 281            distance = Fixed64.Zero;
 282            return true;
 83        }
 84
 3085        Signed320 scaledAxisDistance = WideArithmetic.GetFloorSquareRootScaledByFixed64(
 3086            squaredAxisDistanceNumerator);
 3087        Signed320 radiusDistance = MultiplyThreeToSigned320(
 3088            Signed192.Signed(radius.m_rawValue),
 3089            axisDenominator,
 3090            ParameterScale);
 3091        Signed320 approximateSurfaceDistance = WideArithmetic.SubtractSigned320(
 3092            scaledAxisDistance,
 3093            radiusDistance);
 3094        if (approximateSurfaceDistance.Sign <= 0)
 95        {
 196            distance = Fixed64.Zero;
 197            return true;
 98        }
 99
 29100        Signed320 scale = MultiplyThreeToSigned320(axisDenominator, ParameterScale, ParameterScale);
 29101        if (!Fixed64.TryGetSignedRatio(approximateSurfaceDistance, scale, out distance))
 102        {
 7103            distance = Fixed64.MaxValue;
 7104            return false;
 105        }
 106
 107        // A MaxValue candidate cannot require correction: every exact
 108        // half-raw midpoint maps to an integer restoring-root numerator. If
 109        // the floored numerator is below that midpoint, the exact root is not
 110        // above it; at or above it, TryGetSignedRatio already rejects the
 111        // positive overflow tie.
 22112        if (distance == Fixed64.MaxValue)
 2113            return true;
 114
 115        // The restoring root is floor(sqrt(N) * S), so the approximate gap is
 116        // below the exact gap by less than one/(axisDenominator * S) raw unit.
 117        // Its half-even result can therefore only remain unchanged or advance
 118        // by one. Compare the exact squared distance with the midpoint above
 119        // the candidate; importantly, radius participates before the parity
 120        // decision because subtracting an odd raw radius reverses tie parity.
 20121        ulong axisDistanceCandidateRaw = unchecked((ulong)radius.m_rawValue)
 20122            + unchecked((ulong)distance.m_rawValue);
 20123        Signed192 doubledMidpoint = new(
 20124            0UL,
 20125            axisDistanceCandidateRaw >> 63,
 20126            (axisDistanceCandidateRaw << 1) | 1UL);
 20127        Signed320 midpointNumerator = WideArithmetic.MultiplySigned192(
 20128            axisDenominator,
 20129            doubledMidpoint);
 20130        Signed576 midpointSquared = WideArithmetic.MultiplySigned320(
 20131            midpointNumerator,
 20132            midpointNumerator);
 20133        Signed576 fourSquaredDistance = WideArithmetic.AddSigned576(
 20134            WideArithmetic.AddSigned576(
 20135                squaredAxisDistanceNumerator,
 20136                squaredAxisDistanceNumerator),
 20137            WideArithmetic.AddSigned576(
 20138                squaredAxisDistanceNumerator,
 20139                squaredAxisDistanceNumerator));
 20140        int midpointComparison = WideArithmetic.CompareNonNegative(
 20141            fourSquaredDistance,
 20142            midpointSquared);
 20143        if (midpointComparison <= 0)
 19144            return true;
 145
 1146        distance = Fixed64.FromRaw(distance.m_rawValue + 1L);
 1147        return true;
 148    }
 149}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredCapsuleSweep2d.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.CenteredCapsuleSweep2d.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
 8namespace FixedMathSharp.Geometry;
 9
 10/// <content>
 11/// Provides 2D swept intersection tests between a center-defined capsule (axis + radius)
 12/// moving along a direction and a target segment-based capsule, using wide (Signed192) precision.
 13/// </content>
 14internal static partial class WideFiniteAxisIntersection
 15{
 16    #region Nested Types
 17
 18    private readonly struct WideAxis2d
 19    {
 20        internal readonly Signed192 StartX;
 21        internal readonly Signed192 StartY;
 22        internal readonly Signed192 EndX;
 23        internal readonly Signed192 EndY;
 24
 25        internal WideAxis2d(Signed192 startX, Signed192 startY, Signed192 endX, Signed192 endY)
 26        {
 27427            StartX = startX;
 27428            StartY = startY;
 27429            EndX = endX;
 27430            EndY = endY;
 27431        }
 32    }
 33
 34    #endregion
 35
 36    internal static bool TryGetSweptCenteredCapsuleSegmentFirstDistance(
 37        Vector2d center,
 38        Vector2d axis,
 39        Fixed64 axisLength,
 40        Fixed64 radius,
 41        Vector2d direction,
 42        Fixed64 maximumDistance,
 43        FixedSegment2d targetAxis,
 44        Fixed64 targetRadius,
 45        out Fixed64 distance,
 46        out Vector2d normal)
 47    {
 648        GetCenteredAxisEndpoints(center, axis, axisLength, out WideAxis2d mover);
 649        GetAuthoredAxisEndpoints(targetAxis, out WideAxis2d target);
 650        return TryGetSweptAxesFirstDistance(
 651            mover,
 652            radius,
 653            direction,
 654            maximumDistance,
 655            target,
 656            targetRadius,
 657            axis,
 658            out distance,
 659            out normal);
 60    }
 61
 62    internal static bool TryGetSweptCenteredCapsuleOriginOffsetSegmentFirstDistance(
 63        Vector2d center,
 64        Vector2d axis,
 65        Fixed64 axisLength,
 66        Fixed64 radius,
 67        Vector2d direction,
 68        Fixed64 maximumDistance,
 69        Vector2d targetOrigin,
 70        Fixed64 targetRotation,
 71        Vector2d targetStartOffset,
 72        Vector2d targetEndOffset,
 73        Fixed64 targetRadius,
 74        out Fixed64 distance,
 75        out Vector2d normal)
 76    {
 5677        GetCenteredAxisEndpoints(center, axis, axisLength, out WideAxis2d mover);
 5678        GetRotatedOriginOffsetAxisEndpoints(
 5679            targetOrigin,
 5680            targetRotation,
 5681            targetStartOffset,
 5682            targetEndOffset,
 5683            out WideAxis2d target);
 5684        return TryGetSweptAxesFirstDistance(
 5685            mover,
 5686            radius,
 5687            direction,
 5688            maximumDistance,
 5689            target,
 5690            targetRadius,
 5691            axis,
 5692            out distance,
 5693            out normal);
 94    }
 95
 96    internal static bool TryGetSweptOriginOffsetSegmentsFirstDistance(
 97        Vector2d moverOrigin,
 98        Fixed64 moverRotation,
 99        Vector2d moverStartOffset,
 100        Vector2d moverEndOffset,
 101        Fixed64 moverRadius,
 102        Vector2d direction,
 103        Fixed64 maximumDistance,
 104        Vector2d targetOrigin,
 105        Fixed64 targetRotation,
 106        Vector2d targetStartOffset,
 107        Vector2d targetEndOffset,
 108        Fixed64 targetRadius,
 109        out Fixed64 distance,
 110        out Vector2d normal)
 111    {
 64112        GetRotatedOriginOffsetAxisEndpoints(
 64113            moverOrigin,
 64114            moverRotation,
 64115            moverStartOffset,
 64116            moverEndOffset,
 64117            out WideAxis2d mover);
 64118        GetRotatedOriginOffsetAxisEndpoints(
 64119            targetOrigin,
 64120            targetRotation,
 64121            targetStartOffset,
 64122            targetEndOffset,
 64123            out WideAxis2d target);
 64124        return TryGetSweptAxesFirstDistance(
 64125            mover,
 64126            moverRadius,
 64127            direction,
 64128            maximumDistance,
 64129            target,
 64130            targetRadius,
 64131            WideConvex2dRelations.GetTransformedEdgeDirection(
 64132                moverRotation,
 64133                moverStartOffset,
 64134                moverEndOffset),
 64135            out distance,
 64136            out normal);
 137    }
 138
 139    internal static bool TryGetSweptCenteredCapsulesFirstDistance(
 140        Vector2d center,
 141        Vector2d axis,
 142        Fixed64 axisLength,
 143        Fixed64 radius,
 144        Vector2d direction,
 145        Fixed64 maximumDistance,
 146        Vector2d targetCenter,
 147        Vector2d targetAxis,
 148        Fixed64 targetAxisLength,
 149        Fixed64 targetRadius,
 150        out Fixed64 distance,
 151        out Vector2d normal)
 152    {
 11153        GetCenteredAxisEndpoints(center, axis, axisLength, out WideAxis2d mover);
 11154        GetCenteredAxisEndpoints(targetCenter, targetAxis, targetAxisLength, out WideAxis2d target);
 11155        return TryGetSweptAxesFirstDistance(
 11156            mover,
 11157            radius,
 11158            direction,
 11159            maximumDistance,
 11160            target,
 11161            targetRadius,
 11162            axis,
 11163            out distance,
 11164            out normal);
 165    }
 166
 167    private static bool TryGetSweptAxesFirstDistance(
 168        WideAxis2d mover,
 169        Fixed64 moverRadius,
 170        Vector2d direction,
 171        Fixed64 maximumDistance,
 172        WideAxis2d target,
 173        Fixed64 targetRadius,
 174        Vector2d moverAxis,
 175        out Fixed64 distance,
 176        out Vector2d normal)
 177    {
 137178        Signed192 radius = WideArithmetic.AddSigned192(
 137179            Signed192.Signed(moverRadius.m_rawValue),
 137180            Signed192.Signed(targetRadius.m_rawValue));
 137181        Signed192 scaledRadius = Signed192.NarrowValue(
 137182            WideArithmetic.MultiplySigned192(radius, DoubleParameterScale));
 137183        GetSweepVelocity(
 137184            direction,
 137185            maximumDistance,
 137186            out Signed192 displacementPerRawX,
 137187            out Signed192 displacementPerRawY,
 137188            out Signed192 velocityX,
 137189            out Signed192 velocityY);
 190
 137191        bool found = false;
 137192        distance = default;
 137193        normal = default;
 137194        TryKeepEndpointAxisSweep(
 137195            mover.StartX, mover.StartY,
 137196            displacementPerRawX, displacementPerRawY,
 137197            velocityX, velocityY,
 137198            target, scaledRadius, maximumDistance, reverseNormal: false,
 137199            ref found, ref distance, ref normal);
 137200        TryKeepEndpointAxisSweep(
 137201            mover.EndX, mover.EndY,
 137202            displacementPerRawX, displacementPerRawY,
 137203            velocityX, velocityY,
 137204            target, scaledRadius, maximumDistance, reverseNormal: false,
 137205            ref found, ref distance, ref normal);
 137206        TryKeepEndpointAxisSweep(
 137207            target.StartX, target.StartY,
 137208            WideArithmetic.SubtractSigned192(default, displacementPerRawX),
 137209            WideArithmetic.SubtractSigned192(default, displacementPerRawY),
 137210            WideArithmetic.SubtractSigned192(default, velocityX),
 137211            WideArithmetic.SubtractSigned192(default, velocityY),
 137212            mover, scaledRadius, maximumDistance, reverseNormal: true,
 137213            ref found, ref distance, ref normal);
 137214        TryKeepEndpointAxisSweep(
 137215            target.EndX, target.EndY,
 137216            WideArithmetic.SubtractSigned192(default, displacementPerRawX),
 137217            WideArithmetic.SubtractSigned192(default, displacementPerRawY),
 137218            WideArithmetic.SubtractSigned192(default, velocityX),
 137219            WideArithmetic.SubtractSigned192(default, velocityY),
 137220            mover, scaledRadius, maximumDistance, reverseNormal: true,
 137221            ref found, ref distance, ref normal);
 222
 137223        if (AxesIntersect(mover, target) && (!found || distance > Fixed64.Zero))
 224        {
 1225            distance = Fixed64.Zero;
 1226            normal = new Vector2d(-moverAxis.Y, moverAxis.X);
 1227            return true;
 228        }
 229
 136230        return found;
 231    }
 232
 233    private static void TryKeepEndpointAxisSweep(
 234        Signed192 startX,
 235        Signed192 startY,
 236        Signed192 displacementPerRawX,
 237        Signed192 displacementPerRawY,
 238        Signed192 velocityX,
 239        Signed192 velocityY,
 240        WideAxis2d target,
 241        Signed192 scaledRadius,
 242        Fixed64 maximumDistance,
 243        bool reverseNormal,
 244        ref bool found,
 245        ref Fixed64 bestDistance,
 246        ref Vector2d bestNormal)
 247    {
 548248        bool candidateFound = false;
 548249        Fixed64 candidateDistance = default;
 548250        TryKeepCircleSweep(
 548251            startX, startY, velocityX, velocityY,
 548252            target.StartX, target.StartY, scaledRadius, maximumDistance,
 548253            ref candidateFound, ref candidateDistance);
 548254        TryKeepCircleSweep(
 548255            startX, startY, velocityX, velocityY,
 548256            target.EndX, target.EndY, scaledRadius, maximumDistance,
 548257            ref candidateFound, ref candidateDistance);
 548258        TryKeepSideSweep(
 548259            startX, startY,
 548260            displacementPerRawX, displacementPerRawY,
 548261            velocityX, velocityY,
 548262            target, scaledRadius, maximumDistance,
 548263            ref candidateFound, ref candidateDistance);
 548264        if (!candidateFound || (found && candidateDistance >= bestDistance))
 463265            return;
 266
 85267        found = true;
 85268        bestDistance = candidateDistance;
 85269        bestNormal = GetEndpointAxisNormal(
 85270            startX,
 85271            startY,
 85272            displacementPerRawX,
 85273            displacementPerRawY,
 85274            candidateDistance,
 85275            target);
 85276        if (bestNormal == Vector2d.Zero)
 277        {
 54278            bestNormal = GetAxisSweepFallbackNormal(
 54279                target,
 54280                velocityX,
 54281                velocityY);
 282        }
 85283        if (reverseNormal)
 4284            bestNormal = -bestNormal;
 85285    }
 286
 287    private static Vector2d GetAxisSweepFallbackNormal(
 288        WideAxis2d target,
 289        Signed192 velocityX,
 290        Signed192 velocityY)
 291    {
 54292        Vector2d edgeDirection = WideNormalization.GetNormalized(
 54293            WideArithmetic.SubtractSigned192(target.EndX, target.StartX),
 54294            WideArithmetic.SubtractSigned192(target.EndY, target.StartY));
 54295        Vector2d normal = edgeDirection.RightHandNormal;
 54296        if (normal == Vector2d.Zero)
 1297            normal = WideNormalization.GetNormalized(velocityX, velocityY);
 298
 54299        Signed320 velocityProjection = WideArithmetic.AddProducts(
 54300            Signed192.Signed(normal.X.m_rawValue),
 54301            velocityX,
 54302            Signed192.Signed(normal.Y.m_rawValue),
 54303            velocityY);
 54304        return velocityProjection.Sign < 0 ? -normal : normal;
 305    }
 306
 307    private static void TryKeepCircleSweep(
 308        Signed192 startX,
 309        Signed192 startY,
 310        Signed192 velocityX,
 311        Signed192 velocityY,
 312        Signed192 circleX,
 313        Signed192 circleY,
 314        Signed192 scaledRadius,
 315        Fixed64 maximumDistance,
 316        ref bool found,
 317        ref Fixed64 distance)
 318    {
 1096319        Signed192 x = WideArithmetic.SubtractSigned192(startX, circleX);
 1096320        Signed192 y = WideArithmetic.SubtractSigned192(startY, circleY);
 1096321        Signed320 coefficient = WideArithmetic.AddProducts(velocityX, velocityX, velocityY, velocityY);
 1096322        Signed320 projection = WideArithmetic.AddProducts(x, velocityX, y, velocityY);
 1096323        Signed320 constant = WideArithmetic.SubtractSigned320(
 1096324            WideArithmetic.AddProducts(x, x, y, y),
 1096325            WideArithmetic.MultiplySigned192(scaledRadius, scaledRadius));
 1096326        KeepFirstSweepRoot(
 1096327            Signed576.ExtendValue(coefficient),
 1096328            Signed576.ExtendValue(projection),
 1096329            Signed576.ExtendValue(constant),
 1096330            maximumDistance,
 1096331            ref found,
 1096332            ref distance);
 1096333    }
 334
 335    private static void TryKeepSideSweep(
 336        Signed192 startX,
 337        Signed192 startY,
 338        Signed192 displacementPerRawX,
 339        Signed192 displacementPerRawY,
 340        Signed192 velocityX,
 341        Signed192 velocityY,
 342        WideAxis2d target,
 343        Signed192 scaledRadius,
 344        Fixed64 maximumDistance,
 345        ref bool found,
 346        ref Fixed64 distance)
 347    {
 548348        Signed192 deltaX = WideArithmetic.SubtractSigned192(target.EndX, target.StartX);
 548349        Signed192 deltaY = WideArithmetic.SubtractSigned192(target.EndY, target.StartY);
 548350        Signed192 offsetX = WideArithmetic.SubtractSigned192(startX, target.StartX);
 548351        Signed192 offsetY = WideArithmetic.SubtractSigned192(startY, target.StartY);
 548352        Signed320 startCross = WideArithmetic.MultiplySubtract(
 548353            offsetX, deltaY, offsetY, deltaX);
 548354        Signed320 velocityCross = WideArithmetic.MultiplySubtract(
 548355            velocityX, deltaY, velocityY, deltaX);
 548356        Signed320 deltaSquared = WideArithmetic.AddProducts(deltaX, deltaX, deltaY, deltaY);
 548357        if (deltaSquared.IsZero)
 62358            return;
 359
 486360        Signed576 coefficient = WideArithmetic.MultiplySigned320(velocityCross, velocityCross);
 486361        Signed576 projection = WideArithmetic.MultiplySigned320(startCross, velocityCross);
 486362        Signed576 constant = WideArithmetic.SubtractSigned576(
 486363            WideArithmetic.MultiplySigned320(startCross, startCross),
 486364            WideArithmetic.MultiplySigned320(
 486365                WideArithmetic.MultiplySigned192(scaledRadius, scaledRadius),
 486366                deltaSquared));
 486367        bool sideFound = WideFiniteConeIntersection.TrySolveUnitPolynomial(
 486368            coefficient,
 486369            projection,
 486370            constant,
 486371            maximumDistance,
 486372            out Fixed64 entry,
 486373            out _);
 486374        if (!sideFound
 486375            || !IsWithinAxisAtDistance(
 486376                startX,
 486377                startY,
 486378                displacementPerRawX,
 486379                displacementPerRawY,
 486380                entry,
 486381                target,
 486382                deltaX,
 486383                deltaY,
 486384                deltaSquared)
 486385            || (found && entry >= distance))
 386        {
 424387            return;
 388        }
 389
 62390        found = true;
 62391        distance = entry;
 62392    }
 393
 394    private static bool IsWithinAxisAtDistance(
 395        Signed192 startX,
 396        Signed192 startY,
 397        Signed192 displacementPerRawX,
 398        Signed192 displacementPerRawY,
 399        Fixed64 distance,
 400        WideAxis2d target,
 401        Signed192 deltaX,
 402        Signed192 deltaY,
 403        Signed320 deltaSquared)
 404    {
 250405        GetPointAtDistance(
 250406            startX,
 250407            startY,
 250408            displacementPerRawX,
 250409            displacementPerRawY,
 250410            distance,
 250411            out Signed192 pointX,
 250412            out Signed192 pointY);
 250413        Signed320 projection = WideArithmetic.AddProducts(
 250414            WideArithmetic.SubtractSigned192(pointX, target.StartX),
 250415            deltaX,
 250416            WideArithmetic.SubtractSigned192(pointY, target.StartY),
 250417            deltaY);
 250418        return projection.Sign >= 0
 250419            && WideArithmetic.SubtractSigned320(projection, deltaSquared).Sign <= 0;
 420    }
 421
 422    private static void KeepFirstSweepRoot(
 423        Signed576 coefficient,
 424        Signed576 projection,
 425        Signed576 constant,
 426        Fixed64 maximumDistance,
 427        ref bool found,
 428        ref Fixed64 distance)
 429    {
 1096430        if (!WideFiniteConeIntersection.TrySolveUnitPolynomial(
 1096431                coefficient,
 1096432                projection,
 1096433                constant,
 1096434                maximumDistance,
 1096435                out Fixed64 entry,
 1096436                out _)
 1096437            || (found && entry >= distance))
 438        {
 899439            return;
 440        }
 441
 197442        found = true;
 197443        distance = entry;
 197444    }
 445
 446    private static Vector2d GetEndpointAxisNormal(
 447        Signed192 startX,
 448        Signed192 startY,
 449        Signed192 displacementPerRawX,
 450        Signed192 displacementPerRawY,
 451        Fixed64 distance,
 452        WideAxis2d target)
 453    {
 85454        GetPointAtDistance(
 85455            startX,
 85456            startY,
 85457            displacementPerRawX,
 85458            displacementPerRawY,
 85459            distance,
 85460            out Signed192 pointX,
 85461            out Signed192 pointY);
 85462        Signed192 deltaX = WideArithmetic.SubtractSigned192(target.EndX, target.StartX);
 85463        Signed192 deltaY = WideArithmetic.SubtractSigned192(target.EndY, target.StartY);
 85464        Signed320 deltaSquared = WideArithmetic.AddProducts(deltaX, deltaX, deltaY, deltaY);
 85465        Signed320 projection = WideArithmetic.AddProducts(
 85466            WideArithmetic.SubtractSigned192(pointX, target.StartX),
 85467            deltaX,
 85468            WideArithmetic.SubtractSigned192(pointY, target.StartY),
 85469            deltaY);
 85470        if (projection.Sign <= 0)
 471        {
 28472            return WideNormalization.GetNormalized(
 28473                WideArithmetic.SubtractSigned192(target.StartX, pointX),
 28474                WideArithmetic.SubtractSigned192(target.StartY, pointY));
 475        }
 57476        if (WideArithmetic.SubtractSigned320(projection, deltaSquared).Sign >= 0)
 477        {
 22478            return WideNormalization.GetNormalized(
 22479                WideArithmetic.SubtractSigned192(target.EndX, pointX),
 22480                WideArithmetic.SubtractSigned192(target.EndY, pointY));
 481        }
 482
 35483        Signed320 closestX = Signed320.NarrowValue(WideArithmetic.SubtractSigned576(
 35484            WideArithmetic.AddSigned576(
 35485                WideArithmetic.MultiplySigned320(
 35486                    Signed320.ExtendValue(target.StartX),
 35487                    deltaSquared),
 35488                WideArithmetic.MultiplySigned320(
 35489                    Signed320.ExtendValue(deltaX),
 35490                    projection)),
 35491            WideArithmetic.MultiplySigned320(
 35492                Signed320.ExtendValue(pointX),
 35493                deltaSquared)));
 35494        Signed320 closestY = Signed320.NarrowValue(WideArithmetic.SubtractSigned576(
 35495            WideArithmetic.AddSigned576(
 35496                WideArithmetic.MultiplySigned320(
 35497                    Signed320.ExtendValue(target.StartY),
 35498                    deltaSquared),
 35499                WideArithmetic.MultiplySigned320(
 35500                    Signed320.ExtendValue(deltaY),
 35501                    projection)),
 35502            WideArithmetic.MultiplySigned320(
 35503                Signed320.ExtendValue(pointY),
 35504                deltaSquared)));
 35505        return WideNormalization.GetNormalized(closestX, closestY);
 506    }
 507
 508    private static void GetPointAtDistance(
 509        Signed192 startX,
 510        Signed192 startY,
 511        Signed192 displacementPerRawX,
 512        Signed192 displacementPerRawY,
 513        Fixed64 distance,
 514        out Signed192 pointX,
 515        out Signed192 pointY)
 516    {
 335517        Signed192 rawDistance = Signed192.Signed(distance.m_rawValue);
 335518        pointX = Signed192.NarrowValue(WideArithmetic.AddSigned320(
 335519            Signed320.ExtendValue(startX),
 335520            WideArithmetic.MultiplySigned192(displacementPerRawX, rawDistance)));
 335521        pointY = Signed192.NarrowValue(WideArithmetic.AddSigned320(
 335522            Signed320.ExtendValue(startY),
 335523            WideArithmetic.MultiplySigned192(displacementPerRawY, rawDistance)));
 335524    }
 525
 526    private static bool AxesIntersect(WideAxis2d first, WideAxis2d second)
 527    {
 137528        int firstStart = Orientation(first.StartX, first.StartY, first.EndX, first.EndY, second.StartX, second.StartY);
 137529        int firstEnd = Orientation(first.StartX, first.StartY, first.EndX, first.EndY, second.EndX, second.EndY);
 137530        int secondStart = Orientation(second.StartX, second.StartY, second.EndX, second.EndY, first.StartX, first.StartY
 137531        int secondEnd = Orientation(second.StartX, second.StartY, second.EndX, second.EndY, first.EndX, first.EndY);
 137532        return (firstStart == 0 && IsWithinBounds(first, second.StartX, second.StartY))
 137533            || (firstEnd == 0 && IsWithinBounds(first, second.EndX, second.EndY))
 137534            || (secondStart == 0 && IsWithinBounds(second, first.StartX, first.StartY))
 137535            || (secondEnd == 0 && IsWithinBounds(second, first.EndX, first.EndY))
 137536            || (firstStart != firstEnd && secondStart != secondEnd);
 537    }
 538
 539    private static int Orientation(
 540        Signed192 startX,
 541        Signed192 startY,
 542        Signed192 endX,
 543        Signed192 endY,
 544        Signed192 pointX,
 545        Signed192 pointY) =>
 548546        WideArithmetic.MultiplySubtract(
 548547            WideArithmetic.SubtractSigned192(endX, startX),
 548548            WideArithmetic.SubtractSigned192(pointY, startY),
 548549            WideArithmetic.SubtractSigned192(endY, startY),
 548550            WideArithmetic.SubtractSigned192(pointX, startX)).Sign;
 551
 552    private static bool IsWithinBounds(WideAxis2d axis, Signed192 x, Signed192 y) =>
 120553        IsBetween(x, axis.StartX, axis.EndX)
 120554        && IsBetween(y, axis.StartY, axis.EndY);
 555
 556    private static bool IsBetween(Signed192 value, Signed192 first, Signed192 second)
 557    {
 128558        if (WideArithmetic.SubtractSigned192(first, second).Sign > 0)
 33559            (first, second) = (second, first);
 128560        return WideArithmetic.SubtractSigned192(value, first).Sign >= 0
 128561            && WideArithmetic.SubtractSigned192(value, second).Sign <= 0;
 562    }
 563
 564    private static void GetSweepVelocity(
 565        Vector2d direction,
 566        Fixed64 maximumDistance,
 567        out Signed192 displacementPerRawX,
 568        out Signed192 displacementPerRawY,
 569        out Signed192 x,
 570        out Signed192 y)
 571    {
 137572        Signed192 rawX = Signed192.Signed(direction.X.m_rawValue);
 137573        Signed192 rawY = Signed192.Signed(direction.Y.m_rawValue);
 137574        displacementPerRawX = WideArithmetic.AddSigned192(rawX, rawX);
 137575        displacementPerRawY = WideArithmetic.AddSigned192(rawY, rawY);
 137576        Signed192 distance = Signed192.Signed(maximumDistance.m_rawValue);
 137577        x = Signed192.NarrowValue(WideArithmetic.MultiplySigned192(displacementPerRawX, distance));
 137578        y = Signed192.NarrowValue(WideArithmetic.MultiplySigned192(displacementPerRawY, distance));
 137579    }
 580
 581    private static void GetCenteredAxisEndpoints(
 582        Vector2d center,
 583        Vector2d axis,
 584        Fixed64 axisLength,
 585        out WideAxis2d endpoints)
 586    {
 84587        Signed192 startX = GetCenteredEndpointNumerator(center.X, axis.X, axisLength, positive: false);
 84588        Signed192 startY = GetCenteredEndpointNumerator(center.Y, axis.Y, axisLength, positive: false);
 84589        Signed192 endX = GetCenteredEndpointNumerator(center.X, axis.X, axisLength, positive: true);
 84590        Signed192 endY = GetCenteredEndpointNumerator(center.Y, axis.Y, axisLength, positive: true);
 84591        endpoints = new WideAxis2d(startX, startY, endX, endY);
 84592    }
 593
 594    private static void GetAuthoredAxisEndpoints(FixedSegment2d axis, out WideAxis2d endpoints) =>
 6595        endpoints = new WideAxis2d(
 6596            ScaleAuthoredCoordinate(axis.Start.X),
 6597            ScaleAuthoredCoordinate(axis.Start.Y),
 6598            ScaleAuthoredCoordinate(axis.End.X),
 6599            ScaleAuthoredCoordinate(axis.End.Y));
 600
 601    private static void GetRotatedOriginOffsetAxisEndpoints(
 602        Vector2d origin,
 603        Fixed64 rotation,
 604        Vector2d startOffset,
 605        Vector2d endOffset,
 606        out WideAxis2d endpoints)
 607    {
 184608        GetRotatedOriginOffsetCoordinate(
 184609            origin,
 184610            rotation,
 184611            startOffset,
 184612            out Signed192 startX,
 184613            out Signed192 startY);
 184614        GetRotatedOriginOffsetCoordinate(
 184615            origin,
 184616            rotation,
 184617            endOffset,
 184618            out Signed192 endX,
 184619            out Signed192 endY);
 184620        endpoints = new WideAxis2d(startX, startY, endX, endY);
 184621    }
 622
 623    private static void GetRotatedOriginOffsetCoordinate(
 624        Vector2d origin,
 625        Fixed64 rotation,
 626        Vector2d offset,
 627        out Signed192 x,
 628        out Signed192 y)
 629    {
 368630        Signed192 cosine =
 368631            Signed192.Signed(
 368632                FixedMath.Cos(rotation).m_rawValue);
 368633        Signed192 sine =
 368634            Signed192.Signed(
 368635                FixedMath.Sin(rotation).m_rawValue);
 368636        Signed320 rotatedX = WideArithmetic.SubtractSigned320(
 368637            WideArithmetic.MultiplySigned192(
 368638                Signed192.Signed(offset.X.m_rawValue),
 368639                cosine),
 368640            WideArithmetic.MultiplySigned192(
 368641                Signed192.Signed(offset.Y.m_rawValue),
 368642                sine));
 368643        Signed320 rotatedY = WideArithmetic.AddSigned320(
 368644            WideArithmetic.MultiplySigned192(
 368645                Signed192.Signed(offset.X.m_rawValue),
 368646                sine),
 368647            WideArithmetic.MultiplySigned192(
 368648                Signed192.Signed(offset.Y.m_rawValue),
 368649                cosine));
 368650        Signed320 originX = WideArithmetic.MultiplySigned192(
 368651            Signed192.Signed(origin.X.m_rawValue),
 368652            DoubleParameterScale);
 368653        Signed320 originY = WideArithmetic.MultiplySigned192(
 368654            Signed192.Signed(origin.Y.m_rawValue),
 368655            DoubleParameterScale);
 368656        x = Signed192.NarrowValue(
 368657            WideArithmetic.AddSigned320(
 368658                originX,
 368659                WideArithmetic.AddSigned320(rotatedX, rotatedX)));
 368660        y = Signed192.NarrowValue(
 368661            WideArithmetic.AddSigned320(
 368662                originY,
 368663                WideArithmetic.AddSigned320(rotatedY, rotatedY)));
 368664    }
 665
 666    private static Signed192 GetCenteredEndpointNumerator(
 667        Fixed64 center,
 668        Fixed64 axis,
 669        Fixed64 axisLength,
 670        bool positive)
 671    {
 336672        Signed320 centerTerm = WideArithmetic.MultiplySigned192(
 336673            Signed192.Signed(center.m_rawValue),
 336674            DoubleParameterScale);
 336675        Signed320 axisTerm = WideArithmetic.MultiplySigned192(
 336676            Signed192.Signed(axis.m_rawValue),
 336677            Signed192.Signed(axisLength.m_rawValue));
 336678        return Signed192.NarrowValue(positive
 336679            ? WideArithmetic.AddSigned320(centerTerm, axisTerm)
 336680            : WideArithmetic.SubtractSigned320(centerTerm, axisTerm));
 681    }
 682
 683    private static Signed192 ScaleAuthoredCoordinate(Fixed64 value) =>
 24684        Signed192.NarrowValue(WideArithmetic.MultiplySigned192(
 24685            Signed192.Signed(value.m_rawValue),
 24686            DoubleParameterScale));
 687}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredConeSurfaceAnchors.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.CenteredConeSurfaceAnchors.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
 8namespace FixedMathSharp.Geometry;
 9
 10/// <content>
 11/// Provides helpers for computing the closest surface anchor, outward normal,
 12/// and signed distance from a point to a centered finite cone's lateral surface.
 13/// </content>
 14internal static partial class WideFiniteAxisIntersection
 15{
 16    internal static bool TryGetClosestCenteredFiniteConeSurfaceAnchor(
 17        Vector3d point,
 18        Vector3d center,
 19        FixedQuaternion frameRotation,
 20        Vector3d localAxisDirection,
 21        Fixed64 height,
 22        Fixed64 radius,
 23        Vector3d localFallbackRadialDirection,
 24        out FixedPointAnchor surfaceAnchor,
 25        out Vector3d outwardNormal,
 26        out Fixed64 signedDistance)
 27    {
 2728        surfaceAnchor =
 2729            GetClosestCenteredFiniteConeSurfaceAnchor(
 2730                point,
 2731                center,
 2732                frameRotation,
 2733                localAxisDirection,
 2734                height,
 2735                radius,
 2736                localFallbackRadialDirection,
 2737                out outwardNormal,
 2738                out bool contained);
 2739        if (TryGetSignedSurfaceDistance(
 2740                point,
 2741                surfaceAnchor,
 2742                contained,
 2743                out signedDistance))
 44        {
 2045            return true;
 46        }
 47
 748        surfaceAnchor = default;
 749        outwardNormal = default;
 750        signedDistance = default;
 751        return false;
 52    }
 53
 54    internal static FixedPointAnchor
 55        GetClosestCenteredFiniteConeSurfaceAnchor(
 56            Vector3d point,
 57            Vector3d center,
 58            FixedQuaternion frameRotation,
 59            Vector3d localAxisDirection,
 60            Fixed64 height,
 61            Fixed64 radius,
 62            Vector3d localFallbackRadialDirection,
 63            out Vector3d outwardNormal,
 64            out bool contained)
 65    {
 2866        GetRigidLocalPointRelation(
 2867            point,
 2868            center,
 2869            frameRotation,
 2870            localAxisDirection,
 2871            out RigidLocalPointRelation relation);
 2872        Vector3d localRadialDirection = GetLocalRadialDirection(
 2873            relation,
 2874            localAxisDirection,
 2875            localFallbackRadialDirection);
 2876        GetRigidCenteredConeMeridian(
 2877            relation,
 2878            height,
 2879            radius,
 2880            out Fixed64 surfaceRadius,
 2881            out Fixed64 signedAxisLength,
 2882            out bool side,
 2883            out contained);
 84
 2885        FixedPointAnchor surfaceAnchor = CreateCenteredSurfaceAnchor(
 2886            center,
 2887            frameRotation,
 2888            localAxisDirection,
 2889            signedAxisLength,
 2890            localRadialDirection,
 2891            surfaceRadius);
 2892        Vector3d localNormal = side
 2893            ? GetCenteredConeSideNormal(
 2894                localRadialDirection,
 2895                localAxisDirection,
 2896                height,
 2897                radius)
 2898            : -localAxisDirection;
 2899        _ = frameRotation.TryRotate(
 28100            localNormal,
 28101            out Vector3d rotatedNormal);
 28102        outwardNormal = WideNormalization.GetNormalized(rotatedNormal);
 28103        return surfaceAnchor;
 104    }
 105
 106    private static void GetRigidCenteredConeMeridian(
 107        RigidLocalPointRelation relation,
 108        Fixed64 height,
 109        Fixed64 radius,
 110        out Fixed64 surfaceRadius,
 111        out Fixed64 signedAxisLength,
 112        out bool side,
 113        out bool contained)
 114    {
 28115        GetCenteredConeHeightRelation(
 28116            relation,
 28117            height,
 28118            out Signed576 heightFromBaseNumerator,
 28119            out Signed320 heightFromBaseDenominator);
 28120        Signed192 radiusRaw = Signed192.Signed(
 28121            radius.m_rawValue);
 28122        int radialToRadius = WideArithmetic
 28123            .CompareNonNegativeRadicalToRatio(
 28124                relation.RadialNumerator,
 28125                relation.RadialDenominator,
 28126                Signed320.ExtendValue(radiusRaw),
 28127                Scale320);
 28128        side = IsCenteredConeSideNearest(
 28129            relation,
 28130            height,
 28131            radius,
 28132            heightFromBaseNumerator,
 28133            heightFromBaseDenominator);
 28134        if (side)
 135        {
 22136            GetClosestCenteredConeSideCoordinates(
 22137                relation,
 22138                height,
 22139                radius,
 22140                heightFromBaseNumerator,
 22141                heightFromBaseDenominator,
 22142                out surfaceRadius,
 22143                out signedAxisLength);
 144        }
 145        else
 146        {
 147            // A base selection proves the radial projection lies inside the
 148            // disk; otherwise the shared rim is also the nearest side feature.
 6149            _ = TryGetCenteredRadialDistance(
 6150                relation,
 6151                out surfaceRadius);
 6152            signedAxisLength = -height;
 153        }
 28154        contained = IsPointContainedInRigidCenteredCone(
 28155            relation,
 28156            height,
 28157            radius);
 28158    }
 159
 160    private static void GetClosestCenteredConeSideCoordinates(
 161        RigidLocalPointRelation relation,
 162        Fixed64 height,
 163        Fixed64 radius,
 164        Signed576 heightFromBaseNumerator,
 165        Signed320 heightFromBaseDenominator,
 166        out Fixed64 surfaceRadius,
 167        out Fixed64 signedAxisLength)
 168    {
 22169        Signed192 heightRaw = Signed192.Signed(
 22170            height.m_rawValue);
 22171        Signed192 radiusRaw = Signed192.Signed(
 22172            radius.m_rawValue);
 22173        Signed192 sideSquared = WideArithmetic.AddSigned192(
 22174            GetSquaredRadius(heightRaw),
 22175            GetSquaredRadius(radiusRaw));
 22176        Signed576 parameterNumerator =
 22177            GetCenteredConeSideParameterNumerator(
 22178                heightFromBaseNumerator,
 22179                heightFromBaseDenominator,
 22180                heightRaw,
 22181                radiusRaw,
 22182                GetSquaredRadius(radiusRaw));
 22183        int startComparison = CompareCenteredConeSideParameterToEndpoint(
 22184            relation,
 22185            parameterNumerator,
 22186            heightFromBaseDenominator,
 22187            radiusRaw,
 22188            sideSquared,
 22189            endpoint: 0);
 22190        if (startComparison <= 0)
 191        {
 5192            surfaceRadius = radius;
 5193            signedAxisLength = -height;
 5194            return;
 195        }
 196
 17197        int endComparison = CompareCenteredConeSideParameterToEndpoint(
 17198            relation,
 17199            parameterNumerator,
 17200            heightFromBaseDenominator,
 17201            radiusRaw,
 17202            sideSquared,
 17203            endpoint: 1);
 17204        if (endComparison >= 0)
 205        {
 7206            surfaceRadius = Fixed64.Zero;
 7207            signedAxisLength = height;
 7208            return;
 209        }
 210
 10211        Signed576 denominator = WideArithmetic.MultiplySigned320(
 10212            heightFromBaseDenominator,
 10213            Signed320.ExtendValue(sideSquared));
 10214        Signed576 radicalCoefficient = WideArithmetic.MultiplySigned320(
 10215            heightFromBaseDenominator,
 10216            Signed320.ExtendValue(
 10217                WideArithmetic.SubtractSigned192(default, radiusRaw)));
 10218        GetCenteredConeSideApproximation(
 10219            relation,
 10220            height,
 10221            radius,
 10222            heightFromBaseNumerator,
 10223            heightFromBaseDenominator,
 10224            out Fixed64 approximateRadius,
 10225            out Fixed64 approximateAxisLength);
 226
 10227        surfaceRadius = RoundBoundedCenteredConeCoordinate(
 10228            WideArithmetic.MultiplySigned576(
 10229                WideArithmetic.SubtractSigned576(
 10230                    denominator,
 10231                    parameterNumerator),
 10232                radiusRaw),
 10233            WideArithmetic.MultiplySigned576(
 10234                radicalCoefficient,
 10235                WideArithmetic.SubtractSigned192(default, radiusRaw)),
 10236            relation,
 10237            denominator,
 10238            Fixed64.Zero,
 10239            radius,
 10240            approximateRadius);
 241
 10242        Signed576 heightAndParameter = WideArithmetic.MultiplySigned576(
 10243            parameterNumerator,
 10244            heightRaw);
 10245        Signed576 heightAndDenominator = WideArithmetic.MultiplySigned576(
 10246            denominator,
 10247            heightRaw);
 10248        Signed576 heightAndRadical = WideArithmetic.MultiplySigned576(
 10249            radicalCoefficient,
 10250            heightRaw);
 10251        signedAxisLength = RoundBoundedCenteredConeCoordinate(
 10252            WideArithmetic.SubtractSigned576(
 10253                WideArithmetic.AddSigned576(
 10254                    heightAndParameter,
 10255                    heightAndParameter),
 10256                heightAndDenominator),
 10257            WideArithmetic.AddSigned576(
 10258                heightAndRadical,
 10259                heightAndRadical),
 10260            relation,
 10261            denominator,
 10262            -height,
 10263            height,
 10264            approximateAxisLength);
 10265    }
 266
 267    private static void GetCenteredConeSideApproximation(
 268        RigidLocalPointRelation relation,
 269        Fixed64 height,
 270        Fixed64 radius,
 271        Signed576 heightFromBaseNumerator,
 272        Signed320 heightFromBaseDenominator,
 273        out Fixed64 surfaceRadius,
 274        out Fixed64 signedAxisLength)
 275    {
 10276        bool representable = TryGetCenteredRadialDistance(
 10277            relation,
 10278            out Fixed64 radialDistance);
 10279        representable &= Fixed64.TryGetSignedRawRatio(
 10280            heightFromBaseNumerator,
 10281            Signed576.ExtendValue(
 10282                heightFromBaseDenominator),
 10283            out Fixed64 heightFromBase);
 10284        if (!representable)
 285        {
 2286            surfaceRadius = radius / Fixed64.Two;
 2287            signedAxisLength = Fixed64.Zero;
 2288            return;
 289        }
 290
 8291        Vector2d start = new(radius, Fixed64.Zero);
 8292        Vector2d end = new(Fixed64.Zero, height);
 8293        Signed192 denominator = WideGeometry.GetDifferenceDotProduct2D(
 8294            end.X, start.X, end.Y, start.Y,
 8295            end.X, start.X, end.Y, start.Y);
 8296        Signed192 numerator = WideGeometry.GetDifferenceDotProduct2D(
 8297            radialDistance, start.X, heightFromBase, start.Y,
 8298            end.X, start.X, end.Y, start.Y);
 8299        Signed192 remaining = WideArithmetic.SubtractSigned192(
 8300            denominator,
 8301            numerator);
 8302        _ = Fixed64.TryGetSignedRawRatio(
 8303            Signed576.ExtendValue(
 8304                WideArithmetic.MultiplySigned192(
 8305                    Signed192.Signed(radius.m_rawValue),
 8306                    remaining)),
 8307            Signed576.ExtendValue(
 8308                Signed320.ExtendValue(denominator)),
 8309            out surfaceRadius);
 8310        _ = Fixed64.TryGetSignedRawRatio(
 8311            Signed576.ExtendValue(
 8312                WideArithmetic.MultiplySigned192(
 8313                    Signed192.Signed(height.m_rawValue),
 8314                    numerator)),
 8315            Signed576.ExtendValue(
 8316                Signed320.ExtendValue(denominator)),
 8317            out Fixed64 sideHeight);
 8318        _ = Fixed64.TrySubtractProducts(
 8319            Fixed64.Two,
 8320            sideHeight,
 8321            height,
 8322            Fixed64.One,
 8323            out signedAxisLength);
 8324    }
 325
 326    private static Fixed64 RoundBoundedCenteredConeCoordinate(
 327        Signed576 rational,
 328        Signed576 radicalCoefficient,
 329        RigidLocalPointRelation relation,
 330        Signed576 denominator,
 331        Fixed64 minimum,
 332        Fixed64 maximum,
 333        Fixed64 approximation)
 334    {
 20335        long low = minimum.m_rawValue;
 20336        long high = maximum.m_rawValue;
 20337        long candidate = approximation.Clamp(minimum, maximum).m_rawValue;
 20338        int candidateComparison = CompareCenteredConeCoordinateToRaw(
 20339            rational,
 20340            radicalCoefficient,
 20341            relation,
 20342            denominator,
 20343            candidate);
 20344        if (candidateComparison >= 0)
 345        {
 13346            ulong distanceToHigh = unchecked((ulong)high - (ulong)candidate);
 13347            long nextCandidate = unchecked(
 13348                candidate + (long)((distanceToHigh | (0UL - distanceToHigh)) >> 63));
 13349            if (CompareCenteredConeCoordinateToRaw(
 13350                    rational,
 13351                    radicalCoefficient,
 13352                    relation,
 13353                    denominator,
 13354                    nextCandidate) < 0)
 355            {
 10356                low = candidate;
 357            }
 358            else
 359            {
 3360                low = nextCandidate;
 361            }
 362        }
 363        else
 364        {
 7365            high = candidate - 1L;
 7366            if (CompareCenteredConeCoordinateToRaw(
 7367                    rational,
 7368                    radicalCoefficient,
 7369                    relation,
 7370                    denominator,
 7371                    high) >= 0)
 372            {
 5373                low = high;
 374            }
 375        }
 376
 502377        while (low < high)
 378        {
 482379            ulong span = unchecked((ulong)high - (ulong)low);
 482380            long midpoint = unchecked(
 482381                (long)((ulong)low + ((span + 1UL) >> 1)));
 482382            if (CompareCenteredConeCoordinateToRaw(
 482383                    rational,
 482384                    radicalCoefficient,
 482385                    relation,
 482386                    denominator,
 482387                    midpoint) >= 0)
 388            {
 62389                low = midpoint;
 390            }
 391            else
 392            {
 420393                high = midpoint - 1L;
 394            }
 395        }
 396
 20397        Signed192 doubledMidpoint = WideArithmetic.AddSigned192(
 20398            WideArithmetic.AddSigned192(
 20399                Signed192.Signed(low),
 20400                Signed192.Signed(low)),
 20401            Scale);
 20402        Signed576 midpointRational = WideArithmetic.SubtractSigned576(
 20403            WideArithmetic.AddSigned576(rational, rational),
 20404            WideArithmetic.MultiplySigned576(
 20405                denominator,
 20406                doubledMidpoint));
 20407        int midpointComparison =
 20408            WideArithmetic.CompareSignedLinearRadicalToZero(
 20409                Signed832.ExtendValue(midpointRational),
 20410                Signed704.ExtendValue(
 20411                    WideArithmetic.AddSigned576(
 20412                        radicalCoefficient,
 20413                        radicalCoefficient)),
 20414                relation.RadialNumerator,
 20415                relation.RadialDenominator);
 20416        return Fixed64.FromRaw(
 20417            low + GetHalfToEvenIncrement(midpointComparison, low));
 418    }
 419
 420    private static int CompareCenteredConeCoordinateToRaw(
 421        Signed576 rational,
 422        Signed576 radicalCoefficient,
 423        RigidLocalPointRelation relation,
 424        Signed576 denominator,
 425        long raw)
 426    {
 522427        Signed832 candidate = WideArithmetic.MultiplySigned576ToSigned832(
 522428            denominator,
 522429            Signed320.ExtendValue(
 522430                Signed192.Signed(raw)));
 522431        return WideArithmetic.CompareSignedLinearRadicalToZero(
 522432            WideArithmetic.SubtractSigned832(
 522433                Signed832.ExtendValue(rational),
 522434                candidate),
 522435            Signed704.ExtendValue(radicalCoefficient),
 522436            relation.RadialNumerator,
 522437            relation.RadialDenominator);
 438    }
 439
 440    private static void GetCenteredConeHeightRelation(
 441        RigidLocalPointRelation relation,
 442        Fixed64 height,
 443        out Signed576 numerator,
 444        out Signed320 denominator)
 445    {
 28446        Signed320 denominatorAndAxis = WideArithmetic.MultiplySigned192(
 28447            relation.Denominator,
 28448            relation.AxisSquared);
 28449        Signed576 heightTerm = WideArithmetic.MultiplySigned320(
 28450            denominatorAndAxis,
 28451            Signed320.ExtendValue(
 28452                Signed192.Signed(
 28453                    height.m_rawValue)));
 28454        Signed576 projectionTerm = WideArithmetic.MultiplySigned320(
 28455            relation.Projection,
 28456            Signed320.ExtendValue(
 28457                Signed192.Signed(
 28458                    Fixed64.One.m_rawValue)));
 28459        numerator = WideArithmetic.AddSigned576(
 28460            heightTerm,
 28461            WideArithmetic.AddSigned576(
 28462                projectionTerm,
 28463                projectionTerm));
 28464        denominator = WideArithmetic.AddSigned320(
 28465            denominatorAndAxis,
 28466            denominatorAndAxis);
 28467    }
 468
 469    private static bool IsPointContainedInRigidCenteredCone(
 470        RigidLocalPointRelation relation,
 471        Fixed64 height,
 472        Fixed64 radius)
 473    {
 28474        if (GetCenteredCap(relation, height) != 0)
 13475            return false;
 476
 15477        Signed320 denominatorAndAxis = WideArithmetic.MultiplySigned192(
 15478            relation.Denominator,
 15479            relation.AxisSquared);
 15480        Signed576 remaining = WideArithmetic.SubtractSigned576(
 15481            WideArithmetic.MultiplySigned320(
 15482                denominatorAndAxis,
 15483                Signed320.ExtendValue(
 15484                    Signed192.Signed(
 15485                        height.m_rawValue))),
 15486            WideArithmetic.AddSigned576(
 15487                WideArithmetic.MultiplySigned320(
 15488                    relation.Projection,
 15489                    Signed320.ExtendValue(
 15490                        Signed192.Signed(
 15491                            Fixed64.One.m_rawValue))),
 15492                WideArithmetic.MultiplySigned320(
 15493                    relation.Projection,
 15494                    Signed320.ExtendValue(
 15495                        Signed192.Signed(
 15496                            Fixed64.One.m_rawValue)))));
 15497        _ = Signed320.TryNarrowSigned(
 15498            remaining,
 15499            out Signed320 narrowRemaining);
 15500        Signed192 heightSquared = GetSquaredRadius(
 15501            Signed192.Signed(
 15502                height.m_rawValue));
 15503        Signed320 axisAndHeightSquared =
 15504            WideArithmetic.MultiplySigned192(
 15505                relation.AxisSquared,
 15506                heightSquared);
 15507        Signed704 left = WideArithmetic.MultiplySigned576ToSigned704(
 15508            relation.RadialNumerator,
 15509            axisAndHeightSquared);
 15510        left = WideArithmetic.AddSigned704(left, left);
 15511        left = WideArithmetic.AddSigned704(left, left);
 512
 15513        Signed576 remainingSquared = WideArithmetic.MultiplySigned320(
 15514            narrowRemaining,
 15515            narrowRemaining);
 15516        Signed192 radiusSquared = GetSquaredRadius(
 15517            Signed192.Signed(
 15518                radius.m_rawValue));
 15519        Signed704 right = Signed704.ExtendValue(
 15520            WideArithmetic.MultiplySigned576(
 15521                remainingSquared,
 15522                radiusSquared));
 15523        return WideArithmetic.CompareNonNegative(left, right) <= 0;
 524    }
 525
 526    private static bool IsCenteredConeSideNearest(
 527        RigidLocalPointRelation relation,
 528        Fixed64 height,
 529        Fixed64 radius,
 530        Signed576 heightFromBaseNumerator,
 531        Signed320 heightFromBaseDenominator)
 532    {
 28533        Signed192 heightRaw = Signed192.Signed(
 28534            height.m_rawValue);
 28535        Signed192 radiusRaw = Signed192.Signed(
 28536            radius.m_rawValue);
 28537        Signed192 heightSquared = GetSquaredRadius(heightRaw);
 28538        Signed192 radiusSquared = GetSquaredRadius(radiusRaw);
 28539        Signed192 sideSquared = WideArithmetic.AddSigned192(
 28540            heightSquared,
 28541            radiusSquared);
 28542        Signed576 sideParameterNumerator =
 28543            GetCenteredConeSideParameterNumerator(
 28544                heightFromBaseNumerator,
 28545                heightFromBaseDenominator,
 28546                heightRaw,
 28547                radiusRaw,
 28548                radiusSquared);
 28549        int startComparison = CompareCenteredConeSideParameterToEndpoint(
 28550            relation,
 28551            sideParameterNumerator,
 28552            heightFromBaseDenominator,
 28553            radiusRaw,
 28554            sideSquared,
 28555            endpoint: 0);
 28556        int radialToRadius = WideArithmetic
 28557            .CompareNonNegativeRadicalToRatio(
 28558                relation.RadialNumerator,
 28559                relation.RadialDenominator,
 28560                Signed320.ExtendValue(radiusRaw),
 28561                Scale320);
 28562        if (startComparison <= 0)
 9563            return radialToRadius >= 0;
 564
 19565        int endComparison = CompareCenteredConeSideParameterToEndpoint(
 19566            relation,
 19567            sideParameterNumerator,
 19568            heightFromBaseDenominator,
 19569            radiusRaw,
 19570            sideSquared,
 19571            endpoint: 1);
 19572        bool baseInterior = radialToRadius <= 0;
 19573        if (endComparison >= 0)
 574        {
 7575            return CompareCenteredConeApexToBaseDistance(
 7576                relation,
 7577                heightFromBaseNumerator,
 7578                heightFromBaseDenominator,
 7579                heightRaw,
 7580                radiusRaw,
 7581                heightSquared,
 7582                radiusSquared,
 7583                baseInterior) <= 0;
 584        }
 585
 12586        return CompareCenteredConeInteriorSideToBaseDistance(
 12587            relation,
 12588            heightFromBaseNumerator,
 12589            heightFromBaseDenominator,
 12590            heightRaw,
 12591            radiusRaw,
 12592            heightSquared,
 12593            radiusSquared,
 12594            sideSquared,
 12595            baseInterior) <= 0;
 596    }
 597
 598    private static Signed576 GetCenteredConeSideParameterNumerator(
 599        Signed576 heightFromBaseNumerator,
 600        Signed320 heightFromBaseDenominator,
 601        Signed192 height,
 602        Signed192 radius,
 603        Signed192 radiusSquared) =>
 50604        WideArithmetic.AddSigned576(
 50605            WideArithmetic.MultiplySigned320(
 50606                heightFromBaseDenominator,
 50607                Signed320.ExtendValue(radiusSquared)),
 50608            WideArithmetic.MultiplySigned576(
 50609                heightFromBaseNumerator,
 50610                height));
 611
 612    private static int CompareCenteredConeSideParameterToEndpoint(
 613        RigidLocalPointRelation relation,
 614        Signed576 sideParameterNumerator,
 615        Signed320 heightFromBaseDenominator,
 616        Signed192 radius,
 617        Signed192 sideSquared,
 618        int endpoint)
 619    {
 86620        Signed576 rational = sideParameterNumerator;
 86621        if (endpoint != 0)
 622        {
 36623            rational = WideArithmetic.SubtractSigned576(
 36624                rational,
 36625                WideArithmetic.MultiplySigned320(
 36626                    heightFromBaseDenominator,
 36627                    Signed320.ExtendValue(
 36628                        sideSquared)));
 629        }
 86630        Signed576 radialCoefficient = WideArithmetic.MultiplySigned320(
 86631            heightFromBaseDenominator,
 86632            Signed320.ExtendValue(
 86633                WideArithmetic.SubtractSigned192(
 86634                    default,
 86635                    radius)));
 86636        return WideArithmetic.CompareSignedLinearRadicalToZero(
 86637            Signed832.ExtendValue(rational),
 86638            Signed704.ExtendValue(radialCoefficient),
 86639            relation.RadialNumerator,
 86640            relation.RadialDenominator);
 641    }
 642
 643    private static int CompareCenteredConeApexToBaseDistance(
 644        RigidLocalPointRelation relation,
 645        Signed576 heightFromBaseNumerator,
 646        Signed320 heightFromBaseDenominator,
 647        Signed192 height,
 648        Signed192 radius,
 649        Signed192 heightSquared,
 650        Signed192 radiusSquared,
 651        bool baseInterior)
 652    {
 7653        Signed576 twiceHeightAndY = WideArithmetic.AddSigned576(
 7654            WideArithmetic.MultiplySigned576(
 7655                heightFromBaseNumerator,
 7656                height),
 7657            WideArithmetic.MultiplySigned576(
 7658                heightFromBaseNumerator,
 7659                height));
 7660        Signed576 rational = WideArithmetic.SubtractSigned576(
 7661            WideArithmetic.MultiplySigned320(
 7662                heightFromBaseDenominator,
 7663                Signed320.ExtendValue(
 7664                    baseInterior
 7665                        ? heightSquared
 7666                        : WideArithmetic.SubtractSigned192(
 7667                            heightSquared,
 7668                            radiusSquared))),
 7669            twiceHeightAndY);
 7670        if (baseInterior)
 671        {
 3672            Signed704 result = WideArithmetic.AddSigned704(
 3673                WideArithmetic.MultiplySigned576ToSigned704(
 3674                    relation.RadialNumerator,
 3675                    heightFromBaseDenominator),
 3676                WideArithmetic.MultiplySigned576ToSigned704(
 3677                    rational,
 3678                    relation.RadialDenominator));
 3679            return result.Sign;
 680        }
 681
 4682        Signed576 radialCoefficient = WideArithmetic.MultiplySigned320(
 4683            heightFromBaseDenominator,
 4684            Signed320.ExtendValue(
 4685                WideArithmetic.AddSigned192(
 4686                    radius,
 4687                    radius)));
 4688        return WideArithmetic.CompareSignedLinearRadicalToZero(
 4689            Signed832.ExtendValue(rational),
 4690            Signed704.ExtendValue(radialCoefficient),
 4691            relation.RadialNumerator,
 4692            relation.RadialDenominator);
 693    }
 694
 695    private static int CompareCenteredConeInteriorSideToBaseDistance(
 696        RigidLocalPointRelation relation,
 697        Signed576 heightFromBaseNumerator,
 698        Signed320 heightFromBaseDenominator,
 699        Signed192 height,
 700        Signed192 radius,
 701        Signed192 heightSquared,
 702        Signed192 radiusSquared,
 703        Signed192 sideSquared,
 704        bool baseInterior)
 705    {
 12706        Signed576 denominatorSquared = WideArithmetic.MultiplySigned320(
 12707            heightFromBaseDenominator,
 12708            heightFromBaseDenominator);
 12709        _ = Signed320.TryNarrowSigned(
 12710            denominatorSquared,
 12711            out Signed320 narrowDenominatorSquared);
 12712        Signed576 radialAndHeightSquared =
 12713            WideArithmetic.MultiplySigned576(
 12714                relation.RadialNumerator,
 12715                heightSquared);
 12716        Signed832 rational = WideArithmetic.MultiplySigned576ToSigned832(
 12717            radialAndHeightSquared,
 12718            denominatorSquared);
 719
 12720        Signed576 heightRadius = Signed576.ExtendValue(
 12721            WideArithmetic.MultiplySigned192(
 12722                height,
 12723                radius));
 724        // The normalized rigid-frame and local-axis denominators are both
 725        // Q32.32 squared magnitudes, so their product remains Signed192-wide.
 12726        _ = Signed192.TryNarrowSigned(
 12727            Signed576.ExtendValue(
 12728                heightFromBaseDenominator),
 12729            out Signed192 narrowHeightDenominator);
 12730        Signed576 meridianOffset = WideArithmetic.SubtractSigned576(
 12731            WideArithmetic.MultiplySigned576(
 12732                heightFromBaseNumerator,
 12733                radius),
 12734            WideArithmetic.MultiplySigned576(
 12735                heightRadius,
 12736                narrowHeightDenominator));
 12737        _ = Signed320.TryNarrowSigned(
 12738            meridianOffset,
 12739            out Signed320 narrowMeridianOffset);
 12740        Signed576 meridianOffsetSquared =
 12741            WideArithmetic.MultiplySigned320(
 12742                narrowMeridianOffset,
 12743                narrowMeridianOffset);
 12744        rational = WideArithmetic.AddSigned832(
 12745            rational,
 12746            Signed832.ExtendValue(
 12747                WideArithmetic.MultiplySigned576ToSigned704(
 12748                    meridianOffsetSquared,
 12749                    relation.RadialDenominator)));
 750
 12751        Signed576 heightNumeratorSquared =
 12752            WideArithmetic.MultiplySigned320(
 12753                Signed320.NarrowValue(heightFromBaseNumerator),
 12754                Signed320.NarrowValue(heightFromBaseNumerator));
 12755        Signed576 denominatorAndSide = WideArithmetic.MultiplySigned320(
 12756            relation.RadialDenominator,
 12757            Signed320.ExtendValue(sideSquared));
 12758        rational = WideArithmetic.SubtractSigned832(
 12759            rational,
 12760            WideArithmetic.MultiplySigned576ToSigned832(
 12761                heightNumeratorSquared,
 12762                denominatorAndSide));
 763
 12764        if (!baseInterior)
 765        {
 4766            Signed576 radialAndSideSquared =
 4767                WideArithmetic.MultiplySigned576(
 4768                    relation.RadialNumerator,
 4769                    sideSquared);
 4770            rational = WideArithmetic.SubtractSigned832(
 4771                rational,
 4772                WideArithmetic.MultiplySigned576ToSigned832(
 4773                    radialAndSideSquared,
 4774                    denominatorSquared));
 4775            Signed320 radiusAndSideSquared =
 4776                WideArithmetic.MultiplySigned192(
 4777                    radiusSquared,
 4778                    sideSquared);
 4779            rational = WideArithmetic.SubtractSigned832(
 4780                rational,
 4781                Signed832.ExtendValue(
 4782                    WideArithmetic.MultiplySigned320(
 4783                        radiusAndSideSquared,
 4784                        narrowDenominatorSquared,
 4785                        relation.RadialDenominator)));
 786        }
 787
 12788        Signed576 heightAndDenominator =
 12789            WideArithmetic.MultiplySigned320(
 12790                heightFromBaseDenominator,
 12791                Signed320.ExtendValue(height));
 12792        _ = Signed320.TryNarrowSigned(
 12793            heightAndDenominator,
 12794            out Signed320 narrowHeightAndDenominator);
 12795        Signed704 radicalCoefficient =
 12796            WideArithmetic.MultiplySigned320(
 12797                narrowHeightAndDenominator,
 12798                narrowMeridianOffset,
 12799                relation.RadialDenominator);
 12800        radicalCoefficient = WideArithmetic.AddSigned704(
 12801            radicalCoefficient,
 12802            radicalCoefficient);
 12803        if (!baseInterior)
 804        {
 4805            Signed320 radiusAndSide = WideArithmetic.MultiplySigned192(
 4806                radius,
 4807                sideSquared);
 4808            Signed704 baseCoefficient = WideArithmetic.MultiplySigned320(
 4809                radiusAndSide,
 4810                narrowDenominatorSquared,
 4811                relation.RadialDenominator);
 4812            baseCoefficient = WideArithmetic.AddSigned704(
 4813                baseCoefficient,
 4814                baseCoefficient);
 4815            radicalCoefficient = WideArithmetic.AddSigned704(
 4816                radicalCoefficient,
 4817                baseCoefficient);
 818        }
 819
 12820        return WideArithmetic.CompareSignedLinearRadicalToZero(
 12821            rational,
 12822            radicalCoefficient,
 12823            relation.RadialNumerator,
 12824            relation.RadialDenominator);
 825    }
 826
 827}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredSurfaceAnchors.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.CenteredSurfaceAnchors.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
 8namespace FixedMathSharp.Geometry;
 9
 10/// <content>
 11/// Provides methods for computing the closest surface anchor points on centered,
 12/// finite-axis shapes (e.g. capsules) relative to a given world-space point.
 13/// </content>
 14internal static partial class WideFiniteAxisIntersection
 15{
 16    internal static bool TryGetClosestCenteredCapsuleSurfaceAnchor(
 17        Vector3d point,
 18        Vector3d center,
 19        FixedQuaternion frameRotation,
 20        Vector3d localAxisDirection,
 21        Fixed64 axisLength,
 22        Fixed64 radius,
 23        Vector3d localFallbackRadialDirection,
 24        out FixedPointAnchor surfaceAnchor,
 25        out Vector3d outwardNormal,
 26        out Fixed64 signedDistance)
 27    {
 528        surfaceAnchor = GetClosestCenteredCapsuleSurfaceAnchor(
 529            point,
 530            center,
 531            frameRotation,
 532            localAxisDirection,
 533            axisLength,
 534            radius,
 535            localFallbackRadialDirection,
 536            out outwardNormal,
 537            out bool contained);
 538        if (TryGetSignedSurfaceDistance(
 539                point,
 540                surfaceAnchor,
 541                contained,
 542                out signedDistance))
 43        {
 344            return true;
 45        }
 46
 247        surfaceAnchor = default;
 248        outwardNormal = default;
 249        signedDistance = default;
 250        return false;
 51    }
 52
 53    internal static FixedPointAnchor GetClosestCenteredCapsuleSurfaceAnchor(
 54        Vector3d point,
 55        Vector3d center,
 56        FixedQuaternion frameRotation,
 57        Vector3d localAxisDirection,
 58        Fixed64 axisLength,
 59        Fixed64 radius,
 60        Vector3d localFallbackRadialDirection,
 61        out Vector3d outwardNormal,
 62        out bool contained)
 63    {
 664        GetRigidLocalPointRelation(
 665            point,
 666            center,
 667            frameRotation,
 668            localAxisDirection,
 669            out RigidLocalPointRelation relation);
 670        int cap = GetCenteredCap(relation, axisLength);
 671        Vector3d localSurfaceDirection = GetLocalCapsuleSurfaceDirection(
 672            relation,
 673            localAxisDirection,
 674            axisLength,
 675            cap,
 676            localFallbackRadialDirection);
 677        CreateCenteredCapsuleAnchors(
 678            center,
 679            frameRotation,
 680            localAxisDirection,
 681            axisLength,
 682            radius,
 683            localSurfaceDirection,
 684            cap,
 685            relation,
 686            out FixedPointAnchor axisAnchor,
 687            out FixedPointAnchor surfaceAnchor);
 88
 689        var pointAnchor = new FixedPointAnchor(
 690            point,
 691            FixedQuaternion.Identity,
 692            Vector3d.Zero);
 693        contained = axisAnchor.CompareSquaredDistance(
 694            pointAnchor,
 695            surfaceAnchor) <= 0;
 696        _ = frameRotation.TryRotate(
 697            localSurfaceDirection,
 698            out Vector3d rotatedNormal);
 699        outwardNormal = WideNormalization.GetNormalized(rotatedNormal);
 6100        return surfaceAnchor;
 101    }
 102
 103    private static Vector3d GetLocalCapsuleSurfaceDirection(
 104        RigidLocalPointRelation relation,
 105        Vector3d localAxisDirection,
 106        Fixed64 axisLength,
 107        int cap,
 108        Vector3d localFallbackDirection)
 109    {
 6110        if (cap == 0)
 111        {
 3112            return GetLocalRadialDirection(
 3113                relation,
 3114                localAxisDirection,
 3115                localFallbackDirection);
 116        }
 117
 3118        Signed192 axisLengthRaw = Signed192.Signed(
 3119            axisLength.m_rawValue);
 3120        Signed192 axisX = Signed192.Signed(
 3121            localAxisDirection.X.m_rawValue);
 3122        Signed192 axisY = Signed192.Signed(
 3123            localAxisDirection.Y.m_rawValue);
 3124        Signed192 axisZ = Signed192.Signed(
 3125            localAxisDirection.Z.m_rawValue);
 3126        Signed192 sign = Signed192.Signed(cap);
 3127        Signed192 pointScale = Signed192.Signed(
 3128            Fixed64.Two.m_rawValue);
 3129        Signed320 x = GetLocalCapsuleCapDelta(
 3130            relation.X,
 3131            relation.Denominator,
 3132            pointScale,
 3133            axisX,
 3134            axisLengthRaw,
 3135            sign);
 3136        Signed320 y = GetLocalCapsuleCapDelta(
 3137            relation.Y,
 3138            relation.Denominator,
 3139            pointScale,
 3140            axisY,
 3141            axisLengthRaw,
 3142            sign);
 3143        Signed320 z = GetLocalCapsuleCapDelta(
 3144            relation.Z,
 3145            relation.Denominator,
 3146            pointScale,
 3147            axisZ,
 3148            axisLengthRaw,
 3149            sign);
 3150        return WideNormalization.GetNormalized(x, y, z);
 151    }
 152
 153    private static Signed320 GetLocalCapsuleCapDelta(
 154        Signed192 pointNumerator,
 155        Signed192 denominator,
 156        Signed192 pointScale,
 157        Signed192 axisComponent,
 158        Signed192 axisLength,
 159        Signed192 sign)
 160    {
 9161        Signed320 scaledPoint = WideArithmetic.MultiplySigned192(
 9162            pointNumerator,
 9163            pointScale);
 9164        _ = Signed192.TryNarrowSigned(
 9165            WideArithmetic.MultiplySigned192(
 9166                axisComponent,
 9167                sign),
 9168            out Signed192 signedAxisComponent);
 9169        Signed320 axisAndLength = WideArithmetic.MultiplySigned192(
 9170            signedAxisComponent,
 9171            axisLength);
 9172        _ = Signed192.TryNarrowSigned(
 9173            axisAndLength,
 9174            out Signed192 narrowAxisAndLength);
 9175        Signed320 endpoint = WideArithmetic.MultiplySigned192(
 9176            denominator,
 9177            narrowAxisAndLength);
 9178        return WideArithmetic.SubtractSigned320(
 9179            scaledPoint,
 9180            endpoint);
 181    }
 182
 183    internal static bool TryGetClosestCenteredFiniteCylinderSurfaceAnchor(
 184        Vector3d point,
 185        Vector3d center,
 186        FixedQuaternion frameRotation,
 187        Vector3d localAxisDirection,
 188        Fixed64 axisLength,
 189        Fixed64 radius,
 190        Vector3d localFallbackRadialDirection,
 191        out FixedPointAnchor surfaceAnchor,
 192        out Vector3d outwardNormal,
 193        out Fixed64 signedDistance)
 194    {
 27195        surfaceAnchor =
 27196            GetClosestCenteredFiniteCylinderSurfaceAnchor(
 27197                point,
 27198                center,
 27199                frameRotation,
 27200                localAxisDirection,
 27201                axisLength,
 27202                radius,
 27203                localFallbackRadialDirection,
 27204                out outwardNormal,
 27205                out bool contained);
 27206        if (TryGetSignedSurfaceDistance(
 27207                point,
 27208                surfaceAnchor,
 27209                contained,
 27210                out signedDistance))
 211        {
 23212            return true;
 213        }
 214
 4215        surfaceAnchor = default;
 4216        outwardNormal = default;
 4217        signedDistance = default;
 4218        return false;
 219    }
 220
 221    internal static FixedPointAnchor
 222        GetClosestCenteredFiniteCylinderSurfaceAnchor(
 223            Vector3d point,
 224            Vector3d center,
 225            FixedQuaternion frameRotation,
 226            Vector3d localAxisDirection,
 227            Fixed64 axisLength,
 228            Fixed64 radius,
 229            Vector3d localFallbackRadialDirection,
 230            out Vector3d outwardNormal,
 231            out bool contained)
 232    {
 28233        GetRigidLocalPointRelation(
 28234            point,
 28235            center,
 28236            frameRotation,
 28237            localAxisDirection,
 28238            out RigidLocalPointRelation relation);
 28239        int cap = GetCenteredCap(relation, axisLength);
 28240        Signed576 radialBound = GetCenteredRadialBound(
 28241            relation,
 28242            radius);
 28243        bool radialOutside = CompareSigned576(
 28244            relation.RadialNumerator,
 28245            radialBound) > 0;
 28246        contained =
 28247            cap == 0
 28248            && CompareSigned576(
 28249                relation.RadialNumerator,
 28250                radialBound) <= 0;
 28251        Vector3d localRadialDirection = GetLocalRadialDirection(
 28252            relation,
 28253            localAxisDirection,
 28254            localFallbackRadialDirection);
 28255        FixedPointAnchor sideAnchor = CreateCenteredCylinderSideAnchor(
 28256            center,
 28257            frameRotation,
 28258            localAxisDirection,
 28259            axisLength,
 28260            radius,
 28261            localRadialDirection,
 28262            cap,
 28263            relation);
 264
 28265        bool side = radialOutside || cap == 0;
 28266        FixedPointAnchor capAnchor = default;
 28267        if (!side || contained)
 268        {
 14269            _ = TryGetCenteredRadialDistance(
 14270                relation,
 14271                out Fixed64 radialDistance);
 14272            capAnchor = CreateCenteredSurfaceAnchor(
 14273                center,
 14274                frameRotation,
 14275                localAxisDirection,
 14276                relation.Projection.Sign >= 0
 14277                    ? axisLength
 14278                    : -axisLength,
 14279                localRadialDirection,
 14280                radialDistance);
 281        }
 28282        if (contained)
 283        {
 11284            var pointAnchor = new FixedPointAnchor(
 11285                point,
 11286                FixedQuaternion.Identity,
 11287                Vector3d.Zero);
 11288            side = pointAnchor.CompareSquaredDistance(
 11289                sideAnchor,
 11290                capAnchor) <= 0;
 291        }
 28292        FixedPointAnchor surfaceAnchor =
 28293            side ? sideAnchor : capAnchor;
 294
 28295        var reference = new FixedPointAnchor(
 28296            point,
 28297            FixedQuaternion.Identity,
 28298            Vector3d.Zero);
 28299        if (side && cap != 0 && radialOutside)
 300        {
 7301            outwardNormal = WidePointAnchor3d.GetDirection(
 7302                reference,
 7303                surfaceAnchor);
 304        }
 305        else
 306        {
 21307            Vector3d localNormal = side
 21308                ? localRadialDirection
 21309                : (cap > 0 || relation.Projection.Sign >= 0
 21310                    ? localAxisDirection
 21311                    : -localAxisDirection);
 21312            _ = frameRotation.TryRotate(
 21313                localNormal,
 21314                out Vector3d rotatedNormal);
 21315            outwardNormal = WideNormalization.GetNormalized(rotatedNormal);
 316        }
 28317        return surfaceAnchor;
 318    }
 319
 320    private static bool TryGetSignedSurfaceDistance(
 321        Vector3d point,
 322        in FixedPointAnchor surfaceAnchor,
 323        bool contained,
 324        out Fixed64 signedDistance)
 325    {
 59326        var reference = new FixedPointAnchor(
 59327            point,
 59328            FixedQuaternion.Identity,
 59329            Vector3d.Zero);
 59330        if (!reference.TryGetOffsetFrom(
 59331                surfaceAnchor,
 59332                out Vector3d surfaceToPoint)
 59333            || !Vector3d.TryGetMagnitude(
 59334                surfaceToPoint,
 59335                out Fixed64 distance))
 336        {
 13337            signedDistance = default;
 13338            return false;
 339        }
 340
 46341        signedDistance = contained ? -distance : distance;
 46342        return true;
 343    }
 344
 345    private static FixedPointAnchor CreateCenteredCylinderSideAnchor(
 346        Vector3d center,
 347        FixedQuaternion frameRotation,
 348        Vector3d localAxisDirection,
 349        Fixed64 axisLength,
 350        Fixed64 radius,
 351        Vector3d localRadialDirection,
 352        int cap,
 353        RigidLocalPointRelation relation)
 354    {
 28355        if (cap != 0)
 356        {
 10357            return CreateCenteredSurfaceAnchor(
 10358                center,
 10359                frameRotation,
 10360                localAxisDirection,
 10361                cap > 0 ? axisLength : -axisLength,
 10362                localRadialDirection,
 10363                radius);
 364        }
 365
 18366        Fixed64 axialDistance =
 18367            GetClosestCenteredRigidAxisDistance(
 18368                relation,
 18369                axisLength,
 18370                cap);
 18371        Vector3d roundedRadialOffset = localRadialDirection * radius;
 18372        return new FixedPointAnchor(
 18373            center,
 18374            frameRotation,
 18375            localAxisDirection * axialDistance,
 18376            roundedRadialOffset,
 18377            FixedPointAnchorTerm3d.CreateRadialSupport(
 18378                localRadialDirection,
 18379                radius,
 18380                roundedRadialOffset));
 381    }
 382
 383    private static void CreateCenteredCapsuleAnchors(
 384        Vector3d center,
 385        FixedQuaternion frameRotation,
 386        Vector3d localAxisDirection,
 387        Fixed64 axisLength,
 388        Fixed64 radius,
 389        Vector3d localRadialDirection,
 390        int cap,
 391        RigidLocalPointRelation relation,
 392        out FixedPointAnchor axisAnchor,
 393        out FixedPointAnchor surfaceAnchor)
 394    {
 6395        if (cap != 0)
 396        {
 3397            Fixed64 signedLength = cap > 0
 3398                ? axisLength
 3399                : -axisLength;
 3400            axisAnchor = CreateCenteredSurfaceAnchor(
 3401                center,
 3402                frameRotation,
 3403                localAxisDirection,
 3404                signedLength,
 3405                localRadialDirection,
 3406                Fixed64.Zero);
 3407            surfaceAnchor = CreateCenteredSurfaceAnchor(
 3408                center,
 3409                frameRotation,
 3410                localAxisDirection,
 3411                signedLength,
 3412                localRadialDirection,
 3413                radius);
 3414            return;
 415        }
 416
 3417        Fixed64 axialDistance =
 3418            GetClosestCenteredRigidAxisDistance(
 3419                relation,
 3420                axisLength,
 3421                cap);
 3422        Vector3d localAxisOffset =
 3423            localAxisDirection * axialDistance;
 3424        axisAnchor = new FixedPointAnchor(
 3425            center,
 3426            frameRotation,
 3427            localAxisOffset);
 3428        Vector3d roundedRadialOffset =
 3429            localRadialDirection * radius;
 3430        surfaceAnchor = new FixedPointAnchor(
 3431            center,
 3432            frameRotation,
 3433            localAxisOffset,
 3434            roundedRadialOffset,
 3435            FixedPointAnchorTerm3d.CreateRadialSupport(
 3436                localRadialDirection,
 3437                radius,
 3438                roundedRadialOffset));
 3439    }
 440
 441    private static Fixed64 GetClosestCenteredRigidAxisDistance(
 442        RigidLocalPointRelation relation,
 443        Fixed64 axisLength,
 444        int cap)
 445    {
 110446        if (cap != 0)
 447        {
 6448            return cap > 0
 6449                ? axisLength / Fixed64.Two
 6450                : -(axisLength / Fixed64.Two);
 451        }
 452
 104453        Signed576 numerator = WideArithmetic.MultiplySigned320(
 104454            relation.Projection,
 104455            Signed320.ExtendValue(
 104456                Signed192.Signed(
 104457                    Fixed64.One.m_rawValue)));
 104458        Signed320 denominator = WideArithmetic.MultiplySigned192(
 104459            relation.Denominator,
 104460            relation.AxisSquared);
 461        // Interior classification proves the ratio lies within the centered
 462        // axis's representable half-length.
 104463        _ = Fixed64.TryGetSignedRawRatio(
 104464            numerator,
 104465            Signed576.ExtendValue(denominator),
 104466            out Fixed64 axialDistance);
 104467        return axialDistance;
 468    }
 469
 470    private static FixedPointAnchor CreateCenteredSurfaceAnchor(
 471        Vector3d center,
 472        FixedQuaternion frameRotation,
 473        Vector3d localAxisDirection,
 474        Fixed64 signedAxisLength,
 475        Vector3d localRadialDirection,
 476        Fixed64 radialDistance)
 477    {
 58478        Vector3d roundedAxialOffset =
 58479            localAxisDirection * (signedAxisLength / Fixed64.Two);
 58480        Vector3d roundedRadialOffset =
 58481            localRadialDirection * radialDistance;
 58482        return new FixedPointAnchor(
 58483            center,
 58484            frameRotation,
 58485            roundedAxialOffset,
 58486            roundedRadialOffset,
 58487            FixedPointAnchorTerm3d.CreateCenteredAxisSupport(
 58488                localAxisDirection,
 58489                signedAxisLength,
 58490                localRadialDirection,
 58491                radialDistance,
 58492                roundedAxialOffset,
 58493                roundedRadialOffset));
 494    }
 495
 496    private static bool TryGetCenteredRadialDistance(
 497        RigidLocalPointRelation relation,
 498        out Fixed64 radialDistance)
 499    {
 30500        Signed576 numeratorRoot = WideArithmetic.GetFloorSquareRoot(
 30501            Signed704.ExtendValue(
 30502                relation.RadialNumerator));
 30503        Signed576 denominatorRootWide =
 30504            WideArithmetic.GetFloorSquareRoot(
 30505                Signed704.ExtendValue(
 30506                    Signed576.ExtendValue(
 30507                        relation.RadialDenominator)));
 30508        Fixed64 candidate = Fixed64.GetNonNegativeRawRatioFloor(
 30509            Signed704.ExtendValue(numeratorRoot),
 30510            Signed704.ExtendValue(denominatorRootWide));
 511
 30512        Signed320 one = Signed320.ExtendValue(
 30513            Signed192.Signed(1L));
 30514        Signed320 candidateRaw = Signed320.ExtendValue(
 30515            Signed192.Signed(candidate.m_rawValue));
 30516        int candidateComparison =
 30517            WideArithmetic.CompareNonNegativeRadicalToRatio(
 30518                relation.RadialNumerator,
 30519                relation.RadialDenominator,
 30520                candidateRaw,
 30521                one);
 30522        candidate = Fixed64.FromRaw(
 30523            candidate.m_rawValue + (candidateComparison >> 31));
 30524        if (candidate != Fixed64.MaxValue)
 525        {
 28526            Signed320 next = Signed320.ExtendValue(
 28527                Signed192.Signed(candidate.m_rawValue + 1L));
 28528            int nextComparison =
 28529                WideArithmetic.CompareNonNegativeRadicalToRatio(
 28530                    relation.RadialNumerator,
 28531                    relation.RadialDenominator,
 28532                    next,
 28533                    one);
 28534            candidate = Fixed64.FromRaw(
 28535                candidate.m_rawValue
 28536                + GetNonNegativeComparisonIncrement(nextComparison));
 537        }
 538
 30539        Signed192 doubledMidpoint = WideArithmetic.AddSigned192(
 30540            WideArithmetic.AddSigned192(
 30541                Signed192.Signed(candidate.m_rawValue),
 30542                Signed192.Signed(candidate.m_rawValue)),
 30543            Signed192.Signed(1L));
 30544        int midpointComparison =
 30545            WideArithmetic.CompareNonNegativeRadicalToRatio(
 30546                relation.RadialNumerator,
 30547                relation.RadialDenominator,
 30548                Signed320.ExtendValue(doubledMidpoint),
 30549                    Signed320.ExtendValue(
 30550                        Signed192.Signed(2L)));
 30551        long increment =
 30552            GetHalfToEvenIncrement(midpointComparison, candidate.m_rawValue);
 30553        if (candidate == Fixed64.MaxValue && increment != 0L)
 554        {
 2555            radialDistance = default;
 2556            return false;
 557        }
 558
 28559        radialDistance =
 28560            Fixed64.FromRaw(candidate.m_rawValue + increment);
 28561        return true;
 562    }
 563
 564    private static long GetNonNegativeComparisonIncrement(int comparison) =>
 28565        1L ^ ((uint)comparison >> 31);
 566
 567    private static Vector3d GetLocalRadialDirection(
 568        RigidLocalPointRelation relation,
 569        Vector3d localAxisDirection,
 570        Vector3d localFallbackRadialDirection)
 571    {
 59572        GetLocalRadialComponents(
 59573            relation.X,
 59574            relation.Y,
 59575            relation.Z,
 59576            relation.Projection,
 59577            relation.AxisSquared,
 59578            localAxisDirection,
 59579            out Signed320 radialX,
 59580            out Signed320 radialY,
 59581            out Signed320 radialZ);
 59582        Vector3d radial = WideNormalization.GetNormalized(
 59583            radialX,
 59584            radialY,
 59585            radialZ);
 59586        if (!radial.IsZero)
 39587            return radial;
 588
 20589        Signed192 fallbackX = Signed192.Signed(
 20590            localFallbackRadialDirection.X.m_rawValue);
 20591        Signed192 fallbackY = Signed192.Signed(
 20592            localFallbackRadialDirection.Y.m_rawValue);
 20593        Signed192 fallbackZ = Signed192.Signed(
 20594            localFallbackRadialDirection.Z.m_rawValue);
 20595        Signed320 fallbackProjection = GetProjection(
 20596            fallbackX,
 20597            fallbackY,
 20598            fallbackZ,
 20599            localAxisDirection);
 20600        GetLocalRadialComponents(
 20601            fallbackX,
 20602            fallbackY,
 20603            fallbackZ,
 20604            fallbackProjection,
 20605            relation.AxisSquared,
 20606            localAxisDirection,
 20607            out radialX,
 20608            out radialY,
 20609            out radialZ);
 20610        return WideNormalization.GetNormalized(radialX, radialY, radialZ);
 611    }
 612
 613    private static Signed320 GetProjection(
 614        Signed192 x,
 615        Signed192 y,
 616        Signed192 z,
 617        Vector3d localAxisDirection) =>
 171618        WideArithmetic.AddSigned320(
 171619            WideArithmetic.AddSigned320(
 171620                WideArithmetic.MultiplySigned192(
 171621                    x,
 171622                    Signed192.Signed(
 171623                        localAxisDirection.X.m_rawValue)),
 171624                WideArithmetic.MultiplySigned192(
 171625                    y,
 171626                    Signed192.Signed(
 171627                        localAxisDirection.Y.m_rawValue))),
 171628            WideArithmetic.MultiplySigned192(
 171629                z,
 171630                Signed192.Signed(
 171631                    localAxisDirection.Z.m_rawValue)));
 632
 633    private static int GetCenteredCap(
 634        RigidLocalPointRelation relation,
 635        Fixed64 axisLength)
 636    {
 151637        Signed576 scaledProjection = WideArithmetic.MultiplySigned320(
 151638            relation.Projection,
 151639            Signed320.ExtendValue(
 151640                Signed192.Signed(
 151641                    Fixed64.One.m_rawValue)));
 151642        scaledProjection = WideArithmetic.AddSigned576(
 151643            scaledProjection,
 151644            scaledProjection);
 151645        Signed320 denominatorAndAxis = WideArithmetic.MultiplySigned192(
 151646            relation.Denominator,
 151647            relation.AxisSquared);
 151648        Signed576 axialExtent = WideArithmetic.MultiplySigned320(
 151649            denominatorAndAxis,
 151650            Signed320.ExtendValue(
 151651                Signed192.Signed(
 151652                    axisLength.m_rawValue)));
 151653        return CompareMagnitudeSigned576(
 151654            scaledProjection,
 151655            axialExtent) > 0
 151656            ? relation.Projection.Sign
 151657            : 0;
 658    }
 659
 660    private static Signed576 GetCenteredRadialBound(
 661        RigidLocalPointRelation relation,
 662        Fixed64 radius)
 663    {
 28664        Signed192 squaredRadius = GetSquaredRadius(
 28665            Signed192.Signed(radius.m_rawValue));
 28666        return WideArithmetic.MultiplySigned320(
 28667            relation.RadialDenominator,
 28668            Signed320.ExtendValue(squaredRadius));
 669    }
 670
 671    private static void GetLocalRadialComponents(
 672        Signed192 x,
 673        Signed192 y,
 674        Signed192 z,
 675        Signed320 projection,
 676        Signed192 axisSquared,
 677        Vector3d localAxisDirection,
 678        out Signed320 radialX,
 679        out Signed320 radialY,
 680        out Signed320 radialZ)
 681    {
 79682        radialX = GetLocalRadialComponent(
 79683            x,
 79684            projection,
 79685            axisSquared,
 79686            localAxisDirection.X);
 79687        radialY = GetLocalRadialComponent(
 79688            y,
 79689            projection,
 79690            axisSquared,
 79691            localAxisDirection.Y);
 79692        radialZ = GetLocalRadialComponent(
 79693            z,
 79694            projection,
 79695            axisSquared,
 79696            localAxisDirection.Z);
 79697    }
 698
 699    private static Signed320 GetLocalRadialComponent(
 700        Signed192 pointComponent,
 701        Signed320 projection,
 702        Signed192 axisSquared,
 703        Fixed64 axisComponent)
 704    {
 237705        Signed576 projectedAxis = WideArithmetic.MultiplySigned320(
 237706            projection,
 237707            Signed320.ExtendValue(
 237708                Signed192.Signed(
 237709                    axisComponent.m_rawValue)));
 237710        _ = Signed320.TryNarrowSigned(
 237711            projectedAxis,
 237712            out Signed320 narrowProjectedAxis);
 237713        return WideArithmetic.SubtractSigned320(
 237714            WideArithmetic.MultiplySigned192(
 237715                pointComponent,
 237716                axisSquared),
 237717            narrowProjectedAxis);
 718    }
 719
 720    private static int CompareSigned576(
 721        Signed576 left,
 722        Signed576 right) =>
 46723        WideArithmetic.SubtractSigned576(left, right).Sign;
 724
 725    private static int CompareMagnitudeSigned576(
 726        Signed576 left,
 727        Signed576 right)
 728    {
 151729        if (left.Sign < 0)
 20730            left = WideArithmetic.SubtractSigned576(default, left);
 151731        return WideArithmetic.CompareNonNegative(left, right);
 732    }
 733
 734}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredSurfaces.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.CenteredSurfaces.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
 8namespace FixedMathSharp.Geometry;
 9
 10/// <content>
 11/// Provides overlap and closest-surface-point queries for axis-aligned (origin-centered)
 12/// finite cones and cylinders, including surface anchors, normals, and signed distances.
 13/// </content>
 14internal static partial class WideFiniteAxisIntersection
 15{
 16    internal static bool DoesCenteredFiniteConeOverlapSphere(
 17        Vector3d coneCenter,
 18        Vector3d axisDirection,
 19        Fixed64 height,
 20        Fixed64 radius,
 21        Vector3d sphereCenter,
 22        Fixed64 sphereRadius)
 23    {
 524        if (WideFiniteConeIntersection.ContainsPointInCenteredCone(
 525                sphereCenter,
 526                coneCenter,
 527                axisDirection,
 528                height,
 529                radius,
 530                strict: false))
 31        {
 132            return true;
 33        }
 34
 435        return TryGetClosestCenteredFiniteConeSurfaceAnchor(
 436                sphereCenter,
 437                coneCenter,
 438                FixedQuaternion.Identity,
 439                axisDirection,
 440                height,
 441                radius,
 442                Vector3d.Zero,
 443                out _,
 444                out _,
 445                out Fixed64 distance)
 446            && distance <= sphereRadius;
 47    }
 48
 49    internal static bool TryGetClosestPointOnCenteredFiniteConeSurface(
 50        Vector3d point,
 51        Vector3d center,
 52        Vector3d axisDirection,
 53        Fixed64 height,
 54        Fixed64 radius,
 55        Vector3d fallbackRadialDirection,
 56        out Vector3d surfacePoint,
 57        out Vector3d outwardNormal,
 58        out Fixed64 signedDistance)
 59    {
 1160        if (!TryGetClosestCenteredFiniteConeSurfaceOffset(
 1161                point,
 1162                center,
 1163                axisDirection,
 1164                height,
 1165                radius,
 1166                fallbackRadialDirection,
 1167                out Vector3d surfaceOffset,
 1168                out outwardNormal,
 1169                out signedDistance)
 1170            || !Vector3d.TryAdd(center, surfaceOffset, out surfacePoint))
 71        {
 572            surfacePoint = default;
 573            outwardNormal = default;
 574            signedDistance = default;
 575            return false;
 76        }
 77
 678        return true;
 79    }
 80
 81    internal static bool TryGetClosestCenteredFiniteConeSurfaceOffset(
 82        Vector3d point,
 83        Vector3d center,
 84        Vector3d axisDirection,
 85        Fixed64 height,
 86        Fixed64 radius,
 87        Vector3d fallbackRadialDirection,
 88        out Vector3d surfaceOffset,
 89        out Vector3d outwardNormal,
 90        out Fixed64 signedDistance)
 91    {
 1492        if (!TryGetClosestCenteredFiniteConeSurfaceAnchor(
 1493                point,
 1494                center,
 1495                FixedQuaternion.Identity,
 1496                axisDirection,
 1497                height,
 1498                radius,
 1499                fallbackRadialDirection,
 14100                out FixedPointAnchor anchor,
 14101                out outwardNormal,
 14102                out signedDistance)
 14103            || !anchor.TryGetLocalPointIn(
 14104                center,
 14105                FixedQuaternion.Identity,
 14106                out surfaceOffset))
 107        {
 5108            surfaceOffset = default;
 5109            outwardNormal = default;
 5110            signedDistance = default;
 5111            return false;
 112        }
 9113        return true;
 114    }
 115
 116    internal static bool TryGetClosestPointOnCenteredFiniteCylinderSurface(
 117        Vector3d point,
 118        Vector3d center,
 119        Vector3d axisDirection,
 120        Fixed64 axisLength,
 121        Fixed64 radius,
 122        Vector3d fallbackRadialDirection,
 123        out Vector3d surfacePoint,
 124        out Vector3d outwardNormal,
 125        out Fixed64 signedDistance)
 126    {
 13127        if (!TryGetClosestCenteredFiniteCylinderSurfaceOffset(
 13128                point,
 13129                center,
 13130                axisDirection,
 13131                axisLength,
 13132                radius,
 13133                fallbackRadialDirection,
 13134                out Vector3d surfaceOffset,
 13135                out outwardNormal,
 13136                out signedDistance)
 13137            || !Vector3d.TryAdd(center, surfaceOffset, out surfacePoint))
 138        {
 3139            surfacePoint = default;
 3140            outwardNormal = default;
 3141            signedDistance = default;
 3142            return false;
 143        }
 144
 10145        return true;
 146    }
 147
 148    internal static bool TryGetClosestCenteredFiniteCylinderSurfaceOffset(
 149        Vector3d point,
 150        Vector3d center,
 151        Vector3d axisDirection,
 152        Fixed64 axisLength,
 153        Fixed64 radius,
 154        Vector3d fallbackRadialDirection,
 155        out Vector3d surfaceOffset,
 156        out Vector3d outwardNormal,
 157        out Fixed64 signedDistance)
 158    {
 16159        if (TryGetClosestCenteredFiniteCylinderSurfaceAnchor(
 16160                point,
 16161                center,
 16162                FixedQuaternion.Identity,
 16163                axisDirection,
 16164                axisLength,
 16165                radius,
 16166                fallbackRadialDirection,
 16167                out FixedPointAnchor anchor,
 16168                out outwardNormal,
 16169                out signedDistance)
 16170            && anchor.TryGetLocalPointIn(
 16171                center,
 16172                FixedQuaternion.Identity,
 16173                out surfaceOffset))
 174        {
 14175            return true;
 176        }
 177
 2178        surfaceOffset = default;
 2179        outwardNormal = default;
 2180        signedDistance = default;
 2181        return false;
 182    }
 183
 184    private static Vector3d GetCenteredConeSideNormal(
 185        Vector3d radialNormal,
 186        Vector3d axisDirection,
 187        Fixed64 height,
 188        Fixed64 radius)
 189    {
 22190        Signed320 x = WideArithmetic.AddSigned320(
 22191            WideArithmetic.MultiplySigned192(
 22192                Signed192.Signed(radialNormal.X.m_rawValue),
 22193                Signed192.Signed(height.m_rawValue)),
 22194            WideArithmetic.MultiplySigned192(
 22195                Signed192.Signed(axisDirection.X.m_rawValue),
 22196                Signed192.Signed(radius.m_rawValue)));
 22197        Signed320 y = WideArithmetic.AddSigned320(
 22198            WideArithmetic.MultiplySigned192(
 22199                Signed192.Signed(radialNormal.Y.m_rawValue),
 22200                Signed192.Signed(height.m_rawValue)),
 22201            WideArithmetic.MultiplySigned192(
 22202                Signed192.Signed(axisDirection.Y.m_rawValue),
 22203                Signed192.Signed(radius.m_rawValue)));
 22204        Signed320 z = WideArithmetic.AddSigned320(
 22205            WideArithmetic.MultiplySigned192(
 22206                Signed192.Signed(radialNormal.Z.m_rawValue),
 22207                Signed192.Signed(height.m_rawValue)),
 22208            WideArithmetic.MultiplySigned192(
 22209                Signed192.Signed(axisDirection.Z.m_rawValue),
 22210                Signed192.Signed(radius.m_rawValue)));
 22211        return WideNormalization.GetNormalized(x, y, z);
 212    }
 213}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.CenteredSurfaceTriangle.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.CenteredSurfaceTriangle.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
 8namespace FixedMathSharp.Geometry;
 9
 10/// <content>
 11/// Computes wide-precision contact points and penetration depth between a
 12/// support point along an axis normal and a triangle surface, using centered
 13/// (relative) coordinates to preserve precision.
 14/// </content>
 15internal static partial class WideFiniteAxisIntersection
 16{
 17    internal static bool TryGetTriangleSupportPointContact(
 18        FixedTriangle triangle,
 19        Vector3d supportPoint,
 20        Vector3d normal,
 21        out Vector3d pointOnTriangle,
 22        out Fixed64 depth,
 23        out bool depthIsClamped) =>
 1024        TryGetTriangleSupportContactOffsets(
 1025            triangle,
 1026            Vector3d.Zero,
 1027            supportPoint,
 1028            Vector3d.Zero,
 1029            normal,
 1030            out pointOnTriangle,
 1031            out depth,
 1032            out depthIsClamped);
 33
 34    private static bool TryGetTriangleSupportContactOffsets(
 35        FixedTriangle triangle,
 36        Vector3d triangleOrigin,
 37        Vector3d center,
 38        Vector3d centerOffset,
 39        Vector3d normal,
 40        out Vector3d triangleOriginOffset,
 41        out Fixed64 depth,
 42        out bool depthIsClamped)
 43    {
 1044        Signed192 relativeX = GetSupportDifference(
 1045            center.X,
 1046            triangle.A.X,
 1047            centerOffset.X);
 1048        Signed192 relativeY = GetSupportDifference(
 1049            center.Y,
 1050            triangle.A.Y,
 1051            centerOffset.Y);
 1052        Signed192 relativeZ = GetSupportDifference(
 1053            center.Z,
 1054            triangle.A.Z,
 1055            centerOffset.Z);
 1056        Signed192 normalX = Signed192.Signed(normal.X.m_rawValue);
 1057        Signed192 normalY = Signed192.Signed(normal.Y.m_rawValue);
 1058        Signed192 normalZ = Signed192.Signed(normal.Z.m_rawValue);
 1059        Signed320 normalSquared = WideGeometry.GetSquaredMagnitude(
 1060            normalX,
 1061            normalY,
 1062            normalZ,
 1063            out _,
 1064            out _,
 1065            out _);
 1066        Signed320 signedDistanceNumerator = WideArithmetic.AddSigned320(
 1067            WideArithmetic.AddSigned320(
 1068                WideArithmetic.MultiplySigned192(relativeX, normalX),
 1069                WideArithmetic.MultiplySigned192(relativeY, normalY)),
 1070            WideArithmetic.MultiplySigned192(relativeZ, normalZ));
 1071        if (signedDistanceNumerator.Sign > 0
 1072            && WideArithmetic.GetRoundedNonNegativeNormalizedDepth(
 1073                Signed576.ExtendValue(signedDistanceNumerator),
 1074                Signed576.ExtendValue(normalSquared),
 1075                Scale320,
 1076                out _) > Fixed64.Epsilon)
 77        {
 178            triangleOriginOffset = default;
 179            depth = default;
 180            depthIsClamped = default;
 181            return false;
 82        }
 83
 984        Signed320 projectionDenominator = normalSquared;
 985        Signed576 projectedX = GetProjectedCoordinateNumerator(
 986            relativeX,
 987            normalX,
 988            signedDistanceNumerator,
 989            projectionDenominator);
 990        Signed576 projectedY = GetProjectedCoordinateNumerator(
 991            relativeY,
 992            normalY,
 993            signedDistanceNumerator,
 994            projectionDenominator);
 995        Signed576 projectedZ = GetProjectedCoordinateNumerator(
 996            relativeZ,
 997            normalZ,
 998            signedDistanceNumerator,
 999            projectionDenominator);
 9100        Signed576 wideProjectionDenominator =
 9101            Signed576.ExtendValue(projectionDenominator);
 9102        GetTriangleNormal(
 9103            triangle,
 9104            out Signed192 triangleNormalX,
 9105            out Signed192 triangleNormalY,
 9106            out Signed192 triangleNormalZ);
 9107        if (WideGeometry.GetSquaredMagnitude(
 9108                triangleNormalX,
 9109                triangleNormalY,
 9110                triangleNormalZ,
 9111                out _,
 9112                out _,
 9113                out _).IsZero)
 114        {
 2115            triangleOriginOffset = default;
 2116            depth = default;
 2117            depthIsClamped = default;
 2118            return false;
 119        }
 7120        if (!ContainsTriangleProjection(
 7121                triangle,
 7122                triangleNormalX,
 7123                triangleNormalY,
 7124                triangleNormalZ,
 7125                GetAbsoluteCoordinateNumerator(
 7126                    projectedX,
 7127                    triangle.A.X,
 7128                    wideProjectionDenominator),
 7129                GetAbsoluteCoordinateNumerator(
 7130                    projectedY,
 7131                    triangle.A.Y,
 7132                    wideProjectionDenominator),
 7133                GetAbsoluteCoordinateNumerator(
 7134                    projectedZ,
 7135                    triangle.A.Z,
 7136                    wideProjectionDenominator),
 7137                wideProjectionDenominator))
 138        {
 2139            triangleOriginOffset = default;
 2140            depth = default;
 2141            depthIsClamped = default;
 2142            return false;
 143        }
 144
 145        // A point contained by a triangle of representable local vertices is
 146        // representable in the same local chart.
 5147        _ = TryGetTriangleOriginOffsetCoordinate(
 5148            projectedX,
 5149            triangle.A.X,
 5150            triangleOrigin.X,
 5151            wideProjectionDenominator,
 5152            out Fixed64 triangleX);
 5153        _ = TryGetTriangleOriginOffsetCoordinate(
 5154            projectedY,
 5155            triangle.A.Y,
 5156            triangleOrigin.Y,
 5157            wideProjectionDenominator,
 5158            out Fixed64 triangleY);
 5159        _ = TryGetTriangleOriginOffsetCoordinate(
 5160            projectedZ,
 5161            triangle.A.Z,
 5162            triangleOrigin.Z,
 5163            wideProjectionDenominator,
 5164            out Fixed64 triangleZ);
 165
 5166        triangleOriginOffset = new Vector3d(triangleX, triangleY, triangleZ);
 5167        if (signedDistanceNumerator.Sign >= 0)
 168        {
 2169            depth = Fixed64.Zero;
 2170            depthIsClamped = false;
 2171            return true;
 172        }
 173
 3174        depth = WideArithmetic.GetRoundedNonNegativeNormalizedDepth(
 3175            Signed576.ExtendValue(
 3176                WideArithmetic.SubtractSigned320(
 3177                    default,
 3178                    signedDistanceNumerator)),
 3179            Signed576.ExtendValue(normalSquared),
 3180            Scale320,
 3181            out depthIsClamped);
 3182        return true;
 183    }
 184
 185    private static Signed192 GetSupportDifference(
 186        Fixed64 center,
 187        Fixed64 trianglePoint,
 188        Fixed64 centerOffset) =>
 30189        WideArithmetic.AddSigned192(
 30190            GetComponentDifference(center, trianglePoint),
 30191            Signed192.Signed(centerOffset.m_rawValue));
 192
 193    private static Signed576 GetProjectedCoordinateNumerator(
 194        Signed192 relative,
 195        Signed192 normal,
 196        Signed320 signedDistanceNumerator,
 197        Signed320 projectionDenominator) =>
 27198        WideArithmetic.SubtractSigned576(
 27199            WideArithmetic.MultiplySigned320(
 27200                Signed320.ExtendValue(relative),
 27201                projectionDenominator),
 27202            WideArithmetic.MultiplySigned320(
 27203                Signed320.ExtendValue(normal),
 27204                signedDistanceNumerator));
 205
 206    private static Signed576 GetAbsoluteCoordinateNumerator(
 207        Signed576 relativeToTriangleA,
 208        Fixed64 triangleA,
 209        Signed576 denominator) =>
 21210        WideArithmetic.AddSigned576(
 21211            relativeToTriangleA,
 21212            WideArithmetic.MultiplySigned576(
 21213                denominator,
 21214                Signed192.Signed(triangleA.m_rawValue)));
 215
 216    private static bool TryGetTriangleOriginOffsetCoordinate(
 217        Signed576 relativeToTriangleA,
 218        Fixed64 triangleA,
 219        Fixed64 triangleOrigin,
 220        Signed576 denominator,
 221        out Fixed64 coordinate)
 222    {
 15223        Signed192 originDifference =
 15224            GetComponentDifference(triangleA, triangleOrigin);
 15225        Signed576 numerator = WideArithmetic.AddSigned576(
 15226            relativeToTriangleA,
 15227            WideArithmetic.MultiplySigned576(denominator, originDifference));
 15228        return Fixed64.TryGetSignedRawRatio(
 15229            numerator,
 15230            denominator,
 15231            out coordinate);
 232    }
 233}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.Containment.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.Containment.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
 8namespace FixedMathSharp.Geometry;
 9
 10/// <content>
 11/// Provides high-precision containment tests for points against finite cylinder
 12/// and capsule shapes, using wide (multi-word) arithmetic to avoid overflow
 13/// and precision loss when checking axial and radial bounds.
 14/// </content>
 15internal static partial class WideFiniteAxisIntersection
 16{
 17    internal static bool ContainsPointInCenteredFiniteCylinder(
 18        Vector3d point,
 19        Vector3d center,
 20        Vector3d axisDirection,
 21        Fixed64 axisLength,
 22        Fixed64 radius,
 23        bool strict)
 24    {
 1025        Signed192 axisLengthSquared = GetDot(
 1026            axisDirection,
 1027            Vector3d.Zero,
 1028            axisDirection,
 1029            Vector3d.Zero);
 1030        Signed192 distanceSquared = GetDot(point, center, point, center);
 1031        Signed192 axisProjection = GetDot(
 1032            point,
 1033            center,
 1034            axisDirection,
 1035            Vector3d.Zero);
 1036        Signed192 rawRadius = Signed192.Signed(radius.m_rawValue);
 1037        return IsCenteredFiniteCylinderPointContained(
 1038            distanceSquared,
 1039            axisProjection,
 1040            axisLengthSquared,
 1041            GetSquaredRadius(rawRadius),
 1042            GetCenteredAxialExtent(axisLengthSquared, axisLength, Fixed64.Zero),
 1043            strict);
 44    }
 45
 46    internal static bool ContainsPointInCenteredFiniteCylinder(
 47        Vector3d point,
 48        Vector3d center,
 49        Vector3d axisDirection,
 50        Fixed64 axisLength,
 51        Fixed64 radius,
 52        Fixed64 axialTolerance,
 53        Fixed64 radialTolerance,
 54        bool strict)
 55    {
 356        Signed192 axisLengthSquared = GetDot(
 357            axisDirection,
 358            Vector3d.Zero,
 359            axisDirection,
 360            Vector3d.Zero);
 361        Signed192 distanceSquared = GetDot(point, center, point, center);
 362        Signed192 axisProjection = GetDot(
 363            point,
 364            center,
 365            axisDirection,
 366            Vector3d.Zero);
 367        Signed192 expandedRadius = GetExpandedRadius(radius, radialTolerance);
 368        return IsCenteredFiniteCylinderPointContained(
 369            distanceSquared,
 370            axisProjection,
 371            axisLengthSquared,
 372            GetSquaredRadius(expandedRadius),
 373            GetCenteredAxialExtent(axisLengthSquared, axisLength, axialTolerance),
 374            strict);
 75    }
 76
 77    private static bool IsCapsulePointContained(
 78        Signed192 startDistanceSquared,
 79        Signed192 endDistanceSquared,
 80        Signed192 axisProjection,
 81        Signed192 axisLengthSquared,
 82        Signed192 squaredRadius,
 83        bool strict)
 84    {
 3485        if (axisProjection.Sign <= 0)
 1286            return IsWithinRadius(startDistanceSquared, squaredRadius, strict);
 2287        if (WideArithmetic.SubtractSigned192(axisProjection, axisLengthSquared).Sign >= 0)
 388            return IsWithinRadius(endDistanceSquared, squaredRadius, strict);
 89
 1990        int radialSign = GetRadialConstant(
 1991            startDistanceSquared,
 1992            axisProjection,
 1993            axisLengthSquared,
 1994            squaredRadius).Sign;
 1995        return strict ? radialSign < 0 : radialSign <= 0;
 96    }
 97
 98    private static bool IsFiniteCylinderPointContained(
 99        Signed192 distanceSquared,
 100        Signed192 axisProjection,
 101        Signed192 axisLengthSquared,
 102        Signed192 squaredRadius,
 103        bool strict)
 104    {
 119105        int maximumProjectionSign = WideArithmetic.SubtractSigned192(
 119106            axisProjection,
 119107            axisLengthSquared).Sign;
 119108        if (strict
 119109                ? axisProjection.Sign <= 0 || maximumProjectionSign >= 0
 119110                : axisProjection.Sign < 0 || maximumProjectionSign > 0)
 111        {
 24112            return false;
 113        }
 114
 95115        int radialSign = GetRadialConstant(
 95116            distanceSquared,
 95117            axisProjection,
 95118            axisLengthSquared,
 95119            squaredRadius).Sign;
 95120        return strict ? radialSign < 0 : radialSign <= 0;
 121    }
 122
 123    private static bool IsCenteredFiniteCylinderPointContained(
 124        Signed192 distanceSquared,
 125        Signed192 axisProjection,
 126        Signed192 axisLengthSquared,
 127        Signed192 squaredRadius,
 128        Signed320 axialExtent,
 129        bool strict)
 130    {
 169131        Signed320 scaledProjection = WideArithmetic.MultiplySigned192(DoubleParameterScale, axisProjection);
 169132        Signed320 minimumProjection = WideArithmetic.SubtractSigned320(default, axialExtent);
 169133        int minimumSign = WideArithmetic.SubtractSigned320(scaledProjection, minimumProjection).Sign;
 169134        int maximumSign = WideArithmetic.SubtractSigned320(scaledProjection, axialExtent).Sign;
 169135        if (strict
 169136                ? minimumSign <= 0 || maximumSign >= 0
 169137                : minimumSign < 0 || maximumSign > 0)
 138        {
 102139            return false;
 140        }
 141
 67142        int radialSign = GetRadialConstant(
 67143            distanceSquared,
 67144            axisProjection,
 67145            axisLengthSquared,
 67146            squaredRadius).Sign;
 67147        return strict ? radialSign < 0 : radialSign <= 0;
 148    }
 149
 150    private static bool IsWithinRadius(
 151        Signed192 distanceSquared,
 152        Signed192 squaredRadius,
 153        bool strict)
 154    {
 39586155        int differenceSign = WideArithmetic.SubtractSigned192(distanceSquared, squaredRadius).Sign;
 39586156        return strict ? differenceSign < 0 : differenceSign <= 0;
 157    }
 158
 159    private static Signed320 GetRadialConstant(
 160        Signed192 distanceSquared,
 161        Signed192 axisProjection,
 162        Signed192 axisLengthSquared,
 163        Signed192 squaredRadius) =>
 794164        WideArithmetic.SubtractSigned320(
 794165            WideArithmetic.MultiplySubtract(
 794166                distanceSquared,
 794167                axisLengthSquared,
 794168                axisProjection,
 794169                axisProjection),
 794170            WideArithmetic.MultiplySigned192(squaredRadius, axisLengthSquared));
 171}

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

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.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
 8namespace FixedMathSharp.Geometry;
 9
 10/// <summary>
 11/// Owns exact full-domain query-segment intersections with finite radial axes.
 12/// </summary>
 13internal static partial class WideFiniteAxisIntersection
 14{
 115    private static readonly Signed192 Scale = Signed192.Signed(1L);
 116    private static readonly Signed320 Scale320 = Signed320.ExtendValue(Scale);
 117    private static readonly Signed192 ParameterScale = Signed192.Signed(FixedMath.ONE_L);
 118    private static readonly Signed192 DoubleParameterScale = Signed192.Signed(FixedMath.ONE_L * 2L);
 19
 20    #region Nested Types
 21
 22    private readonly struct RationalBound
 23    {
 24        internal readonly Signed192 Numerator;
 25        internal readonly Signed192 Denominator;
 26
 27        internal RationalBound(Signed192 numerator, Signed192 denominator)
 28        {
 22229            Numerator = numerator;
 22230            Denominator = denominator;
 22231        }
 32    }
 33
 34    private readonly struct RationalBound320
 35    {
 36        internal readonly Signed320 Numerator;
 37        internal readonly Signed320 Denominator;
 38
 39        internal RationalBound320(Signed320 numerator, Signed320 denominator)
 40        {
 4244641            Numerator = numerator;
 4244642            Denominator = denominator;
 4244643        }
 44    }
 45
 46    #endregion
 47
 48    internal static bool TryGetCapsuleInterval(
 49        FixedSegment2d query,
 50        FixedSegment2d axis,
 51        Fixed64 radius,
 52        Fixed64 radiusExpansion,
 53        out Fixed64 entry,
 54        out Fixed64 exit,
 55        out bool startContained,
 56        out bool endContainedStrict)
 57    {
 758        Signed192 expandedRadius = GetExpandedRadius(radius, radiusExpansion);
 759        Signed192 squaredRadius = GetSquaredRadius(expandedRadius);
 760        Signed192 axisLengthSquared = GetDot(axis.End, axis.Start, axis.End, axis.Start);
 761        Signed192 queryLengthSquared = GetDot(query.End, query.Start, query.End, query.Start);
 762        Signed192 startDistanceSquared = GetDot(query.Start, axis.Start, query.Start, axis.Start);
 763        Signed192 endDistanceSquared = GetDot(query.End, axis.Start, query.End, axis.Start);
 764        Signed192 directionsDot = GetDot(query.End, query.Start, axis.End, axis.Start);
 765        Signed192 startAxisProjection = GetDot(query.Start, axis.Start, axis.End, axis.Start);
 766        Signed192 endAxisProjection = GetDot(query.End, axis.Start, axis.End, axis.Start);
 767        Signed192 startDirectionProjection = GetDot(query.Start, axis.Start, query.End, query.Start);
 68
 769        if (axisLengthSquared.IsZero)
 70        {
 271            startContained = IsWithinRadius(startDistanceSquared, squaredRadius, strict: false);
 272            endContainedStrict = IsWithinRadius(endDistanceSquared, squaredRadius, strict: true);
 273            return TryGetCircleInterval(
 274                query.Start,
 275                query.End,
 276                axis.Start,
 277                expandedRadius,
 278                out entry,
 279                out exit);
 80        }
 81
 582        startContained = IsCapsulePointContained(
 583            startDistanceSquared,
 584            GetDot(query.Start, axis.End, query.Start, axis.End),
 585            startAxisProjection,
 586            axisLengthSquared,
 587            squaredRadius,
 588            strict: false);
 589        endContainedStrict = IsCapsulePointContained(
 590            endDistanceSquared,
 591            GetDot(query.End, axis.End, query.End, axis.End),
 592            endAxisProjection,
 593            axisLengthSquared,
 594            squaredRadius,
 595            strict: true);
 596        bool found = TryGetFiniteAxisInterval(
 597            queryLengthSquared,
 598            axisLengthSquared,
 599            startDistanceSquared,
 5100            directionsDot,
 5101            startAxisProjection,
 5102            startDirectionProjection,
 5103            expandedRadius,
 5104            Fixed64.One,
 5105            out entry,
 5106            out exit);
 5107        Merge(
 5108            TryGetCircleInterval(query.Start, query.End, axis.Start, expandedRadius, out Fixed64 startEntry, out Fixed64
 5109            startEntry,
 5110            startExit,
 5111            ref found,
 5112            ref entry,
 5113            ref exit);
 5114        Merge(
 5115            TryGetCircleInterval(query.Start, query.End, axis.End, expandedRadius, out Fixed64 endEntry, out Fixed64 end
 5116            endEntry,
 5117            endExit,
 5118            ref found,
 5119            ref entry,
 5120            ref exit);
 5121        return found;
 122    }
 123
 124    internal static bool TryGetCapsuleInterval(
 125        FixedSegment query,
 126        FixedSegment axis,
 127        Fixed64 radius,
 128        Fixed64 radiusExpansion,
 129        out Fixed64 entry,
 130        out Fixed64 exit,
 131        out bool startContained,
 132        out bool endContainedStrict)
 133    {
 9134        Signed192 expandedRadius = GetExpandedRadius(radius, radiusExpansion);
 9135        Signed192 squaredRadius = GetSquaredRadius(expandedRadius);
 9136        Signed192 axisLengthSquared = GetDot(axis.End, axis.Start, axis.End, axis.Start);
 9137        Signed192 queryLengthSquared = GetDot(query.End, query.Start, query.End, query.Start);
 9138        Signed192 startDistanceSquared = GetDot(query.Start, axis.Start, query.Start, axis.Start);
 9139        Signed192 endDistanceSquared = GetDot(query.End, axis.Start, query.End, axis.Start);
 9140        Signed192 directionsDot = GetDot(query.End, query.Start, axis.End, axis.Start);
 9141        Signed192 startAxisProjection = GetDot(query.Start, axis.Start, axis.End, axis.Start);
 9142        Signed192 endAxisProjection = GetDot(query.End, axis.Start, axis.End, axis.Start);
 9143        Signed192 startDirectionProjection = GetDot(query.Start, axis.Start, query.End, query.Start);
 144
 9145        if (axisLengthSquared.IsZero)
 146        {
 3147            startContained = IsWithinRadius(startDistanceSquared, squaredRadius, strict: false);
 3148            endContainedStrict = IsWithinRadius(endDistanceSquared, squaredRadius, strict: true);
 3149            return TryGetSphereInterval(
 3150                query.Start,
 3151                query.End,
 3152                axis.Start,
 3153                expandedRadius,
 3154                out entry,
 3155                out exit);
 156        }
 157
 6158        startContained = IsCapsulePointContained(
 6159            startDistanceSquared,
 6160            GetDot(query.Start, axis.End, query.Start, axis.End),
 6161            startAxisProjection,
 6162            axisLengthSquared,
 6163            squaredRadius,
 6164            strict: false);
 6165        endContainedStrict = IsCapsulePointContained(
 6166            endDistanceSquared,
 6167            GetDot(query.End, axis.End, query.End, axis.End),
 6168            endAxisProjection,
 6169            axisLengthSquared,
 6170            squaredRadius,
 6171            strict: true);
 6172        bool found = TryGetFiniteAxisInterval(
 6173            queryLengthSquared,
 6174            axisLengthSquared,
 6175            startDistanceSquared,
 6176            directionsDot,
 6177            startAxisProjection,
 6178            startDirectionProjection,
 6179            expandedRadius,
 6180            Fixed64.One,
 6181            out entry,
 6182            out exit);
 6183        Merge(
 6184            TryGetSphereInterval(query.Start, query.End, axis.Start, expandedRadius, out Fixed64 startEntry, out Fixed64
 6185            startEntry,
 6186            startExit,
 6187            ref found,
 6188            ref entry,
 6189            ref exit);
 6190        Merge(
 6191            TryGetSphereInterval(query.Start, query.End, axis.End, expandedRadius, out Fixed64 endEntry, out Fixed64 end
 6192            endEntry,
 6193            endExit,
 6194            ref found,
 6195            ref entry,
 6196            ref exit);
 6197        return found;
 198    }
 199
 200    internal static bool TryGetFiniteCylinderInterval(
 201        FixedSegment query,
 202        FixedSegment axis,
 203        Fixed64 radius,
 204        Fixed64 radiusExpansion,
 205        out Fixed64 entry,
 206        out Fixed64 exit,
 207        out bool startContained,
 208        out bool endContainedStrict)
 209    {
 55210        Signed192 expandedRadius = GetExpandedRadius(radius, radiusExpansion);
 55211        Signed192 squaredRadius = GetSquaredRadius(expandedRadius);
 55212        Signed192 axisLengthSquared = GetDot(axis.End, axis.Start, axis.End, axis.Start);
 55213        Signed192 queryLengthSquared = GetDot(query.End, query.Start, query.End, query.Start);
 55214        Signed192 startDistanceSquared = GetDot(query.Start, axis.Start, query.Start, axis.Start);
 55215        Signed192 endDistanceSquared = GetDot(query.End, axis.Start, query.End, axis.Start);
 55216        Signed192 directionsDot = GetDot(query.End, query.Start, axis.End, axis.Start);
 55217        Signed192 startAxisProjection = GetDot(query.Start, axis.Start, axis.End, axis.Start);
 55218        Signed192 endAxisProjection = GetDot(query.End, axis.Start, axis.End, axis.Start);
 55219        Signed192 startDirectionProjection = GetDot(query.Start, axis.Start, query.End, query.Start);
 55220        startContained = IsFiniteCylinderPointContained(
 55221            startDistanceSquared,
 55222            startAxisProjection,
 55223            axisLengthSquared,
 55224            squaredRadius,
 55225            strict: false);
 55226        endContainedStrict = IsFiniteCylinderPointContained(
 55227            endDistanceSquared,
 55228            endAxisProjection,
 55229            axisLengthSquared,
 55230            squaredRadius,
 55231            strict: true);
 55232        return TryGetFiniteAxisInterval(
 55233            queryLengthSquared,
 55234            axisLengthSquared,
 55235            startDistanceSquared,
 55236            directionsDot,
 55237            startAxisProjection,
 55238            startDirectionProjection,
 55239            expandedRadius,
 55240            Fixed64.One,
 55241            out entry,
 55242            out exit);
 243    }
 244
 245    internal static bool TryGetFiniteCylinderInterval(
 246        FixedSegment query,
 247        Vector3d center,
 248        Vector3d axisDirection,
 249        Fixed64 axisLength,
 250        Fixed64 radius,
 251        Fixed64 radiusExpansion,
 252        Fixed64 axialExpansion,
 253        out Fixed64 entry,
 254        out Fixed64 exit,
 255        out bool startContained,
 256        out bool endContainedStrict)
 257    {
 24258        Signed192 queryLengthSquared = GetDot(query.End, query.Start, query.End, query.Start);
 24259        Signed192 axisLengthSquared = GetDot(axisDirection, Vector3d.Zero, axisDirection, Vector3d.Zero);
 24260        Signed192 startDistanceSquared = GetDot(query.Start, center, query.Start, center);
 24261        Signed192 endDistanceSquared = GetDot(query.End, center, query.End, center);
 24262        Signed192 directionsDot = GetDot(query.End, query.Start, axisDirection, Vector3d.Zero);
 24263        Signed192 startAxisProjection = GetDot(query.Start, center, axisDirection, Vector3d.Zero);
 24264        Signed192 endAxisProjection = GetDot(query.End, center, axisDirection, Vector3d.Zero);
 24265        Signed192 startDirectionProjection = GetDot(query.Start, center, query.End, query.Start);
 24266        Signed192 expandedRadius = GetExpandedRadius(radius, radiusExpansion);
 24267        Signed192 squaredRadius = GetSquaredRadius(expandedRadius);
 24268        Signed320 axialExtent = GetCenteredAxialExtent(
 24269            axisLengthSquared,
 24270            axisLength,
 24271            axialExpansion);
 272
 24273        startContained = IsCenteredFiniteCylinderPointContained(
 24274            startDistanceSquared,
 24275            startAxisProjection,
 24276            axisLengthSquared,
 24277            squaredRadius,
 24278            axialExtent,
 24279            strict: false);
 24280        endContainedStrict = IsCenteredFiniteCylinderPointContained(
 24281            endDistanceSquared,
 24282            endAxisProjection,
 24283            axisLengthSquared,
 24284            squaredRadius,
 24285            axialExtent,
 24286            strict: true);
 287
 24288        if (!TryGetCenteredAxialInterval(
 24289                startAxisProjection,
 24290                directionsDot,
 24291                axialExtent,
 24292                Fixed64.One,
 24293                out RationalBound320 lower,
 24294                out RationalBound320 upper))
 295        {
 6296            entry = default;
 6297            exit = default;
 6298            return false;
 299        }
 300
 18301        return TryGetFiniteAxisInterval(
 18302            queryLengthSquared,
 18303            axisLengthSquared,
 18304            startDistanceSquared,
 18305            directionsDot,
 18306            startAxisProjection,
 18307            startDirectionProjection,
 18308            expandedRadius,
 18309            lower,
 18310            upper,
 18311            Fixed64.One,
 18312            out entry,
 18313            out exit);
 314    }
 315
 316    private static bool TryGetFiniteAxisInterval(
 317        Signed192 queryLengthSquared,
 318        Signed192 axisLengthSquared,
 319        Signed192 startDistanceSquared,
 320        Signed192 directionsDot,
 321        Signed192 startAxisProjection,
 322        Signed192 startDirectionProjection,
 323        Signed192 radius,
 324        RationalBound320 lower,
 325        RationalBound320 upper,
 326        Fixed64 maxParameter,
 327        out Fixed64 entry,
 328        out Fixed64 exit)
 329    {
 171330        entry = default;
 171331        exit = default;
 332
 171333        Signed320 radialCoefficient = WideArithmetic.MultiplySubtract(
 171334            queryLengthSquared,
 171335            axisLengthSquared,
 171336            directionsDot,
 171337            directionsDot);
 171338        Signed320 radialProjection = WideArithmetic.MultiplySubtract(
 171339            startDirectionProjection,
 171340            axisLengthSquared,
 171341            startAxisProjection,
 171342            directionsDot);
 171343        Signed320 radialConstant = GetRadialConstant(
 171344            startDistanceSquared,
 171345            startAxisProjection,
 171346            axisLengthSquared,
 171347            GetSquaredRadius(radius));
 171348        return TrySolveBoundedQuadratic(
 171349            radialCoefficient,
 171350            radialProjection,
 171351            radialConstant,
 171352            lower,
 171353            upper,
 171354            maxParameter,
 171355            out entry,
 171356            out exit);
 357    }
 358
 359    private static bool TryGetFiniteAxisInterval(
 360        Signed192 queryLengthSquared,
 361        Signed192 axisLengthSquared,
 362        Signed192 startDistanceSquared,
 363        Signed192 directionsDot,
 364        Signed192 startAxisProjection,
 365        Signed192 startDirectionProjection,
 366        Signed192 radius,
 367        Fixed64 maxParameter,
 368        out Fixed64 entry,
 369        out Fixed64 exit)
 370    {
 77371        entry = default;
 77372        exit = default;
 373
 77374        if (!TryGetAxialInterval(
 77375                startAxisProjection,
 77376                directionsDot,
 77377                axisLengthSquared,
 77378                maxParameter,
 77379                out RationalBound lower,
 77380                out RationalBound upper))
 381        {
 9382            return false;
 383        }
 384
 68385        Signed320 radialCoefficient = WideArithmetic.MultiplySubtract(
 68386            queryLengthSquared,
 68387            axisLengthSquared,
 68388            directionsDot,
 68389            directionsDot);
 68390        Signed320 radialProjection = WideArithmetic.MultiplySubtract(
 68391            startDirectionProjection,
 68392            axisLengthSquared,
 68393            startAxisProjection,
 68394            directionsDot);
 68395        Signed320 radialConstant = GetRadialConstant(
 68396            startDistanceSquared,
 68397            startAxisProjection,
 68398            axisLengthSquared,
 68399            GetSquaredRadius(radius));
 400
 68401        if (radialCoefficient.IsZero)
 402        {
 14403            if (radialConstant.Sign > 0)
 2404                return false;
 405
 12406            entry = Round(lower);
 12407            exit = Round(upper);
 12408            return true;
 409        }
 410
 54411        Signed576 lowerValue = EvaluatePolynomial(
 54412            radialCoefficient,
 54413            radialProjection,
 54414            radialConstant,
 54415            lower.Numerator,
 54416            lower.Denominator);
 54417        Signed576 upperValue = EvaluatePolynomial(
 54418            radialCoefficient,
 54419            radialProjection,
 54420            radialConstant,
 54421            upper.Numerator,
 54422            upper.Denominator);
 54423        int lowerDerivative = EvaluateDerivative(
 54424            radialCoefficient,
 54425            radialProjection,
 54426            lower.Numerator,
 54427            lower.Denominator).Sign;
 54428        int upperDerivative = EvaluateDerivative(
 54429            radialCoefficient,
 54430            radialProjection,
 54431            upper.Numerator,
 54432            upper.Denominator).Sign;
 433
 54434        if ((lowerValue.Sign > 0 && lowerDerivative >= 0)
 54435            || (upperValue.Sign > 0 && upperDerivative <= 0))
 436        {
 2437            return false;
 438        }
 439
 52440        if (lowerValue.Sign <= 0 && upperValue.Sign <= 0)
 441        {
 2442            entry = Round(lower);
 2443            exit = Round(upper);
 2444            return true;
 445        }
 446
 50447        if (TryGetNarrowRadialCoefficients(
 50448                radialCoefficient,
 50449                radialProjection,
 50450                radialConstant,
 50451                out Signed192 narrowCoefficient,
 50452                out Signed192 narrowProjection,
 50453                out Signed192 narrowConstant))
 454        {
 30455            if (!WideRayIntersection.TrySolveInterval(
 30456                    narrowCoefficient,
 30457                    narrowProjection,
 30458                    narrowConstant,
 30459                    maxParameter,
 30460                    out Fixed64 radialEntry,
 30461                    out Fixed64 radialExit))
 462            {
 1463                return false;
 464            }
 465
 29466            entry = lowerValue.Sign <= 0 ? Round(lower) : radialEntry;
 29467            exit = upperValue.Sign <= 0 ? Round(upper) : radialExit;
 29468            return true;
 469        }
 470
 20471        Signed576 discriminant = WideArithmetic.SubtractSigned576(
 20472            WideArithmetic.MultiplySigned320(radialProjection, radialProjection),
 20473            WideArithmetic.MultiplySigned320(radialCoefficient, radialConstant));
 20474        if (discriminant.Sign < 0)
 1475            return false;
 476
 19477        Signed320 scaledSquareRoot = WideArithmetic.GetFloorSquareRootScaledByFixed64(discriminant);
 478
 19479        entry = lowerValue.Sign <= 0
 19480            ? Round(lower)
 19481            : RoundLowerRoot(radialCoefficient, radialProjection, radialConstant, scaledSquareRoot);
 19482        exit = upperValue.Sign <= 0
 19483            ? Round(upper)
 19484            : RoundUpperRoot(radialCoefficient, radialProjection, radialConstant, scaledSquareRoot, maxParameter);
 19485        return true;
 486    }
 487
 488    private static bool TryGetAxialInterval(
 489        Signed192 projection,
 490        Signed192 velocity,
 491        Signed192 axisLengthSquared,
 492        Fixed64 maxParameter,
 493        out RationalBound lower,
 494        out RationalBound upper)
 495    {
 82496        RationalBound maximum = GetMaximumBound(maxParameter);
 82497        lower = new RationalBound(default, Scale);
 82498        upper = maximum;
 499
 82500        if (velocity.IsZero)
 501        {
 53502            return projection.Sign >= 0
 53503                && WideArithmetic.SubtractSigned192(projection, axisLengthSquared).Sign <= 0;
 504        }
 505
 29506        RationalBound first = Normalize(
 29507            WideArithmetic.SubtractSigned192(default, projection),
 29508            velocity);
 29509        RationalBound second = Normalize(
 29510            WideArithmetic.SubtractSigned192(axisLengthSquared, projection),
 29511            velocity);
 29512        if (Compare(first, second) > 0)
 4513            (first, second) = (second, first);
 514
 29515        if (second.Numerator.Sign < 0 || Compare(first, maximum) > 0)
 6516            return false;
 517
 23518        if (first.Numerator.Sign > 0)
 14519            lower = first;
 23520        if (Compare(second, maximum) < 0)
 11521            upper = second;
 23522        return true;
 523    }
 524
 525    private static bool TryGetCenteredAxialInterval(
 526        Signed192 projection,
 527        Signed192 velocity,
 528        Signed320 axialExtent,
 529        Fixed64 maxParameter,
 530        out RationalBound320 lower,
 531        out RationalBound320 upper)
 532    {
 261533        Signed320 scaledProjection = WideArithmetic.MultiplySigned192(DoubleParameterScale, projection);
 261534        Signed320 scaledVelocity = WideArithmetic.MultiplySigned192(DoubleParameterScale, velocity);
 261535        Signed320 minimumProjection = WideArithmetic.SubtractSigned320(default, axialExtent);
 261536        RationalBound320 maximum = GetMaximumBound320(maxParameter);
 261537        lower = new RationalBound320(default, Signed320.ExtendValue(Scale));
 261538        upper = maximum;
 539
 261540        if (scaledVelocity.IsZero)
 541        {
 76542            return WideArithmetic.SubtractSigned320(scaledProjection, minimumProjection).Sign >= 0
 76543                && WideArithmetic.SubtractSigned320(scaledProjection, axialExtent).Sign <= 0;
 544        }
 545
 185546        RationalBound320 first = Normalize(
 185547            WideArithmetic.SubtractSigned320(minimumProjection, scaledProjection),
 185548            scaledVelocity);
 185549        RationalBound320 second = Normalize(
 185550            WideArithmetic.SubtractSigned320(axialExtent, scaledProjection),
 185551            scaledVelocity);
 185552        if (Compare(first, second) > 0)
 19553            (first, second) = (second, first);
 554
 185555        if (second.Numerator.Sign < 0 || Compare(first, maximum) > 0)
 9556            return false;
 557
 176558        if (first.Numerator.Sign > 0)
 36559            lower = first;
 176560        if (Compare(second, maximum) < 0)
 30561            upper = second;
 176562        return true;
 563    }
 564
 565    private static Signed320 GetCenteredAxialExtent(
 566        Signed192 axisLengthSquared,
 567        Fixed64 axisLength,
 568        Fixed64 axialExpansion) =>
 303569        GetCenteredAxialExtent(
 303570            axisLengthSquared,
 303571            Signed192.Signed(axisLength.m_rawValue),
 303572            axialExpansion);
 573
 574    private static Signed320 GetCenteredAxialExtent(
 575        Signed192 axisLengthSquared,
 576        Signed192 axisLength,
 577        Fixed64 axialExpansion) =>
 356578        WideArithmetic.AddSigned320(
 356579            WideArithmetic.MultiplySigned192(
 356580                axisLength,
 356581                axisLengthSquared),
 356582            WideArithmetic.MultiplySigned192(
 356583                WideArithmetic.AddSigned192(
 356584                    Signed192.Signed(axialExpansion.m_rawValue),
 356585                    Signed192.Signed(axialExpansion.m_rawValue)),
 356586                axisLengthSquared));
 587
 588    private static RationalBound Normalize(Signed192 numerator, Signed192 denominator)
 589    {
 58590        if (denominator.Sign >= 0)
 50591            return new RationalBound(numerator, denominator);
 592
 8593        return new RationalBound(
 8594            WideArithmetic.SubtractSigned192(default, numerator),
 8595            WideArithmetic.SubtractSigned192(default, denominator));
 596    }
 597
 598    private static RationalBound320 Normalize(Signed320 numerator, Signed320 denominator)
 599    {
 650600        if (denominator.Sign >= 0)
 360601            return new RationalBound320(numerator, denominator);
 602
 290603        return new RationalBound320(
 290604            WideArithmetic.SubtractSigned320(default, numerator),
 290605            WideArithmetic.SubtractSigned320(default, denominator));
 606    }
 607
 608    private static int Compare(RationalBound left, RationalBound right) =>
 80609        WideArithmetic.MultiplySubtract(
 80610            left.Numerator,
 80611            right.Denominator,
 80612            right.Numerator,
 80613            left.Denominator).Sign;
 614
 615    private static int Compare(RationalBound320 left, RationalBound320 right) =>
 820616        WideArithmetic.SubtractSigned576(
 820617            WideArithmetic.MultiplySigned320(left.Numerator, right.Denominator),
 820618            WideArithmetic.MultiplySigned320(right.Numerator, left.Denominator)).Sign;
 619
 620    private static RationalBound GetMaximumBound(Fixed64 maxParameter) =>
 82621        new(Signed192.Signed(maxParameter.m_rawValue), ParameterScale);
 622
 623    private static RationalBound320 GetMaximumBound320(Fixed64 maxParameter) =>
 279624        new(
 279625            Signed320.ExtendValue(
 279626                Signed192.Signed(maxParameter.m_rawValue)),
 279627            Signed320.ExtendValue(ParameterScale));
 628
 629    private static Fixed64 Round(RationalBound value) =>
 45630        Fixed64.GetSignedRatio(value.Numerator, value.Denominator);
 631
 632    private static Fixed64 Round(RationalBound320 value) =>
 33633        Fixed64.GetSignedRatio(value.Numerator, value.Denominator);
 634
 635    private static bool TryGetCircleInterval(
 636        Vector2d start,
 637        Vector2d end,
 638        Vector2d center,
 639        Signed192 radius,
 640        out Fixed64 entry,
 641        out Fixed64 exit)
 642    {
 12643        Signed192 directionLengthSquared = GetDot(end, start, end, start);
 12644        Signed192 projection = GetDot(start, center, end, start);
 12645        Signed192 distanceSquared = GetDot(start, center, start, center);
 12646        return WideRayIntersection.TrySolveInterval(
 12647            directionLengthSquared,
 12648            projection,
 12649            WideArithmetic.SubtractSigned192(distanceSquared, GetSquaredRadius(radius)),
 12650            Fixed64.One,
 12651            out entry,
 12652            out exit);
 653    }
 654
 655    private static bool TryGetSphereInterval(
 656        Vector3d start,
 657        Vector3d end,
 658        Vector3d center,
 659        Signed192 radius,
 660        out Fixed64 entry,
 661        out Fixed64 exit)
 662    {
 15663        Signed192 directionLengthSquared = GetDot(end, start, end, start);
 15664        Signed192 projection = GetDot(start, center, end, start);
 15665        Signed192 distanceSquared = GetDot(start, center, start, center);
 15666        return WideRayIntersection.TrySolveInterval(
 15667            directionLengthSquared,
 15668            projection,
 15669            WideArithmetic.SubtractSigned192(distanceSquared, GetSquaredRadius(radius)),
 15670            Fixed64.One,
 15671            out entry,
 15672            out exit);
 673    }
 674
 675    private static Signed192 GetExpandedRadius(Fixed64 radius, Fixed64 radiusExpansion) =>
 20167676        WideArithmetic.AddSigned192(
 20167677            Signed192.Signed(radius.m_rawValue),
 20167678            Signed192.Signed(radiusExpansion.m_rawValue));
 679
 680    private static Signed192 GetSquaredRadius(Signed192 radius)
 681    {
 40503682        WideArithmetic.GetMagnitude(radius, out _, out _, out ulong rawRadius);
 40503683        Fixed64.Multiply64To128(rawRadius, rawRadius, out ulong middle, out ulong low);
 40503684        return new Signed192(0UL, middle, low);
 685    }
 686
 687    private static Signed192 GetDot(
 688        Vector2d leftEnd,
 689        Vector2d leftStart,
 690        Vector2d rightEnd,
 691        Vector2d rightStart) =>
 245591692        WideGeometry.GetDifferenceDotProduct2D(
 245591693            leftEnd.X,
 245591694            leftStart.X,
 245591695            leftEnd.Y,
 245591696            leftStart.Y,
 245591697            rightEnd.X,
 245591698            rightStart.X,
 245591699            rightEnd.Y,
 245591700            rightStart.Y);
 701
 702    private static Signed192 GetDot(
 703        Vector3d leftEnd,
 704        Vector3d leftStart,
 705        Vector3d rightEnd,
 706        Vector3d rightStart) =>
 19617707        WideGeometry.GetDifferenceDotProduct3D(
 19617708            leftEnd.X,
 19617709            leftStart.X,
 19617710            leftEnd.Y,
 19617711            leftStart.Y,
 19617712            leftEnd.Z,
 19617713            leftStart.Z,
 19617714            rightEnd.X,
 19617715            rightStart.X,
 19617716            rightEnd.Y,
 19617717            rightStart.Y,
 19617718            rightEnd.Z,
 19617719            rightStart.Z);
 720
 721    private static void Merge(
 722        bool candidateFound,
 723        Fixed64 candidateEntry,
 724        Fixed64 candidateExit,
 725        ref bool found,
 726        ref Fixed64 entry,
 727        ref Fixed64 exit)
 728    {
 538729        if (!candidateFound)
 380730            return;
 731
 158732        if (!found)
 733        {
 18734            found = true;
 18735            entry = candidateEntry;
 18736            exit = candidateExit;
 18737            return;
 738        }
 739
 140740        if (candidateEntry < entry)
 22741            entry = candidateEntry;
 140742        if (candidateExit > exit)
 13743            exit = candidateExit;
 140744    }
 745
 746    private static bool TrySolveBoundedQuadratic(
 747        Signed320 coefficient,
 748        Signed320 projection,
 749        Signed320 constant,
 750        RationalBound320 lower,
 751        RationalBound320 upper,
 752        Fixed64 maxParameter,
 753        out Fixed64 entry,
 754        out Fixed64 exit)
 755    {
 487756        entry = default;
 487757        exit = default;
 758
 487759        if (coefficient.IsZero)
 760        {
 20761            if (constant.Sign > 0)
 9762                return false;
 763
 11764            entry = Round(lower);
 11765            exit = Round(upper);
 11766            return true;
 767        }
 768
 467769        Signed704 lowerValue = EvaluatePolynomial(
 467770            coefficient,
 467771            projection,
 467772            constant,
 467773            lower.Numerator,
 467774            lower.Denominator);
 467775        Signed704 upperValue = EvaluatePolynomial(
 467776            coefficient,
 467777            projection,
 467778            constant,
 467779            upper.Numerator,
 467780            upper.Denominator);
 467781        int lowerDerivative = EvaluateDerivative(
 467782            coefficient,
 467783            projection,
 467784            lower.Numerator,
 467785            lower.Denominator).Sign;
 467786        int upperDerivative = EvaluateDerivative(
 467787            coefficient,
 467788            projection,
 467789            upper.Numerator,
 467790            upper.Denominator).Sign;
 791
 467792        if ((lowerValue.Sign > 0 && lowerDerivative >= 0)
 467793            || (upperValue.Sign > 0 && upperDerivative <= 0))
 794        {
 16795            return false;
 796        }
 797
 451798        if (lowerValue.Sign <= 0 && upperValue.Sign <= 0)
 799        {
 2800            entry = Round(lower);
 2801            exit = Round(upper);
 2802            return true;
 803        }
 804
 449805        if (TryGetNarrowRadialCoefficients(
 449806                coefficient,
 449807                projection,
 449808                constant,
 449809                out Signed192 narrowCoefficient,
 449810                out Signed192 narrowProjection,
 449811                out Signed192 narrowConstant))
 812        {
 316813            if (!WideRayIntersection.TrySolveInterval(
 316814                    narrowCoefficient,
 316815                    narrowProjection,
 316816                    narrowConstant,
 316817                    maxParameter,
 316818                    out Fixed64 radialEntry,
 316819                    out Fixed64 radialExit))
 820            {
 272821                return false;
 822            }
 823
 44824            entry = lowerValue.Sign <= 0 ? Round(lower) : radialEntry;
 44825            exit = upperValue.Sign <= 0 ? Round(upper) : radialExit;
 44826            return true;
 827        }
 828
 133829        Signed576 discriminant = WideArithmetic.SubtractSigned576(
 133830            WideArithmetic.MultiplySigned320(projection, projection),
 133831            WideArithmetic.MultiplySigned320(coefficient, constant));
 133832        if (discriminant.Sign < 0)
 1833            return false;
 834
 132835        Signed320 scaledSquareRoot = WideArithmetic.GetFloorSquareRootScaledByFixed64(discriminant);
 132836        entry = lowerValue.Sign <= 0
 132837            ? Round(lower)
 132838            : RoundLowerRoot(coefficient, projection, constant, scaledSquareRoot);
 132839        exit = upperValue.Sign <= 0
 132840            ? Round(upper)
 132841            : RoundUpperRoot(coefficient, projection, constant, scaledSquareRoot, maxParameter);
 132842        return true;
 843    }
 844}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.Distance.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.Distance.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
 8namespace FixedMathSharp.Geometry;
 9
 10/// <content>
 11/// Physical-distance intervals for radial and finite-axis intersection tests.
 12/// </content>
 13internal static partial class WideFiniteAxisIntersection
 14{
 15    internal static bool TryGetCircleDirectionDistanceInterval(
 16        Vector2d position,
 17        Vector2d direction,
 18        FixedBoundCircle circle,
 19        Fixed64 radiusExpansion,
 20        Fixed64 totalDistance,
 21        out Fixed64 entryDistance,
 22        out Fixed64 exitDistance)
 23    {
 224        Signed192 expandedRadius = GetExpandedRadius(circle.Radius, radiusExpansion);
 225        return TrySolveUnitQuadraticAtDistance(
 226            Signed320.ExtendValue(GetDirectionDot(direction, direction)),
 227            Signed320.ExtendValue(GetDirectionDot(direction, position, circle.Center)),
 228            Signed320.ExtendValue(WideArithmetic.SubtractSigned192(
 229                GetDot(position, circle.Center, position, circle.Center),
 230                GetSquaredRadius(expandedRadius))),
 231            totalDistance,
 232            out entryDistance,
 233            out exitDistance);
 34    }
 35
 36    internal static bool TryGetSphereDirectionDistanceInterval(
 37        Vector3d position,
 38        Vector3d direction,
 39        FixedBoundSphere sphere,
 40        Fixed64 radiusExpansion,
 41        Fixed64 totalDistance,
 42        out Fixed64 entryDistance,
 43        out Fixed64 exitDistance)
 44    {
 245        Signed192 expandedRadius = GetExpandedRadius(sphere.Radius, radiusExpansion);
 246        return TrySolveUnitQuadraticAtDistance(
 247            Signed320.ExtendValue(GetDirectionDot(direction, direction)),
 248            Signed320.ExtendValue(GetDirectionDot(direction, position, sphere.Center)),
 249            Signed320.ExtendValue(WideArithmetic.SubtractSigned192(
 250                GetDot(position, sphere.Center, position, sphere.Center),
 251                GetSquaredRadius(expandedRadius))),
 252            totalDistance,
 253            out entryDistance,
 254            out exitDistance);
 55    }
 56
 57    internal static bool TryGetCircleDistanceInterval(
 58        FixedSegment2d query,
 59        FixedBoundCircle circle,
 60        Fixed64 radiusExpansion,
 61        Fixed64 segmentLength,
 62        out Fixed64 entry,
 63        out Fixed64 exit,
 64        out bool startContained,
 65        out bool endContainedStrict)
 66    {
 667        Signed192 expandedRadius = GetExpandedRadius(circle.Radius, radiusExpansion);
 668        Signed192 squaredRadius = GetSquaredRadius(expandedRadius);
 669        startContained = IsWithinRadius(
 670            GetDot(query.Start, circle.Center, query.Start, circle.Center),
 671            squaredRadius,
 672            strict: false);
 673        endContainedStrict = IsWithinRadius(
 674            GetDot(query.End, circle.Center, query.End, circle.Center),
 675            squaredRadius,
 676            strict: true);
 677        return TryGetCircleDistanceInterval(
 678            query.Start,
 679            query.End,
 680            circle.Center,
 681            expandedRadius,
 682            segmentLength,
 683            out entry,
 684            out exit);
 85    }
 86
 87    internal static bool TryGetSphereDistanceInterval(
 88        FixedSegment query,
 89        FixedBoundSphere sphere,
 90        Fixed64 radiusExpansion,
 91        Fixed64 segmentLength,
 92        out Fixed64 entry,
 93        out Fixed64 exit,
 94        out bool startContained,
 95        out bool endContainedStrict)
 96    {
 697        Signed192 expandedRadius = GetExpandedRadius(sphere.Radius, radiusExpansion);
 698        Signed192 squaredRadius = GetSquaredRadius(expandedRadius);
 699        startContained = IsWithinRadius(
 6100            GetDot(query.Start, sphere.Center, query.Start, sphere.Center),
 6101            squaredRadius,
 6102            strict: false);
 6103        endContainedStrict = IsWithinRadius(
 6104            GetDot(query.End, sphere.Center, query.End, sphere.Center),
 6105            squaredRadius,
 6106            strict: true);
 6107        return TryGetSphereDistanceInterval(
 6108            query.Start,
 6109            query.End,
 6110            sphere.Center,
 6111            expandedRadius,
 6112            segmentLength,
 6113            out entry,
 6114            out exit);
 115    }
 116
 117    internal static bool TryGetCapsuleDistanceInterval(
 118        FixedSegment2d query,
 119        FixedSegment2d axis,
 120        Fixed64 radius,
 121        Fixed64 radiusExpansion,
 122        Fixed64 segmentLength,
 123        out Fixed64 entry,
 124        out Fixed64 exit,
 125        out bool startContained,
 126        out bool endContainedStrict)
 127    {
 19765128        Signed192 expandedRadius = GetExpandedRadius(radius, radiusExpansion);
 19765129        Signed192 squaredRadius = GetSquaredRadius(expandedRadius);
 19765130        Signed192 axisLengthSquared = GetDot(axis.End, axis.Start, axis.End, axis.Start);
 19765131        Signed192 queryLengthSquared = GetDot(query.End, query.Start, query.End, query.Start);
 19765132        Signed192 startDistanceSquared = GetDot(query.Start, axis.Start, query.Start, axis.Start);
 19765133        Signed192 endDistanceSquared = GetDot(query.End, axis.Start, query.End, axis.Start);
 19765134        Signed192 directionsDot = GetDot(query.End, query.Start, axis.End, axis.Start);
 19765135        Signed192 startAxisProjection = GetDot(query.Start, axis.Start, axis.End, axis.Start);
 19765136        Signed192 startDirectionProjection = GetDot(query.Start, axis.Start, query.End, query.Start);
 137
 19765138        if (axisLengthSquared.IsZero)
 139        {
 19764140            startContained = IsWithinRadius(startDistanceSquared, squaredRadius, strict: false);
 19764141            endContainedStrict = IsWithinRadius(endDistanceSquared, squaredRadius, strict: true);
 19764142            return TryGetCircleDistanceInterval(
 19764143                query.Start,
 19764144                query.End,
 19764145                axis.Start,
 19764146                expandedRadius,
 19764147                segmentLength,
 19764148                out entry,
 19764149                out exit);
 150        }
 151
 1152        startContained = IsCapsulePointContained(
 1153            startDistanceSquared,
 1154            GetDot(query.Start, axis.End, query.Start, axis.End),
 1155            startAxisProjection,
 1156            axisLengthSquared,
 1157            squaredRadius,
 1158            strict: false);
 1159        endContainedStrict = IsCapsulePointContained(
 1160            endDistanceSquared,
 1161            GetDot(query.End, axis.End, query.End, axis.End),
 1162            GetDot(query.End, axis.Start, axis.End, axis.Start),
 1163            axisLengthSquared,
 1164            squaredRadius,
 1165            strict: true);
 1166        bool found = TryGetFiniteAxisDistanceInterval(
 1167            queryLengthSquared,
 1168            axisLengthSquared,
 1169            startDistanceSquared,
 1170            directionsDot,
 1171            startAxisProjection,
 1172            startDirectionProjection,
 1173            expandedRadius,
 1174            segmentLength,
 1175            out entry,
 1176            out exit);
 1177        Merge(
 1178            TryGetCircleDistanceInterval(query.Start, query.End, axis.Start, expandedRadius, segmentLength, out Fixed64 
 1179            startEntry,
 1180            startExit,
 1181            ref found,
 1182            ref entry,
 1183            ref exit);
 1184        Merge(
 1185            TryGetCircleDistanceInterval(query.Start, query.End, axis.End, expandedRadius, segmentLength, out Fixed64 en
 1186            endEntry,
 1187            endExit,
 1188            ref found,
 1189            ref entry,
 1190            ref exit);
 1191        return found;
 192    }
 193
 194    internal static bool TryGetCapsuleDistanceInterval(
 195        FixedSegment query,
 196        FixedSegment axis,
 197        Fixed64 radius,
 198        Fixed64 radiusExpansion,
 199        Fixed64 segmentLength,
 200        out Fixed64 entry,
 201        out Fixed64 exit,
 202        out bool startContained,
 203        out bool endContainedStrict)
 204    {
 2205        Signed192 expandedRadius = GetExpandedRadius(radius, radiusExpansion);
 2206        Signed192 squaredRadius = GetSquaredRadius(expandedRadius);
 2207        Signed192 axisLengthSquared = GetDot(axis.End, axis.Start, axis.End, axis.Start);
 2208        Signed192 queryLengthSquared = GetDot(query.End, query.Start, query.End, query.Start);
 2209        Signed192 startDistanceSquared = GetDot(query.Start, axis.Start, query.Start, axis.Start);
 2210        Signed192 endDistanceSquared = GetDot(query.End, axis.Start, query.End, axis.Start);
 2211        Signed192 directionsDot = GetDot(query.End, query.Start, axis.End, axis.Start);
 2212        Signed192 startAxisProjection = GetDot(query.Start, axis.Start, axis.End, axis.Start);
 2213        Signed192 startDirectionProjection = GetDot(query.Start, axis.Start, query.End, query.Start);
 214
 2215        if (axisLengthSquared.IsZero)
 216        {
 1217            startContained = IsWithinRadius(startDistanceSquared, squaredRadius, strict: false);
 1218            endContainedStrict = IsWithinRadius(endDistanceSquared, squaredRadius, strict: true);
 1219            return TryGetSphereDistanceInterval(
 1220                query.Start,
 1221                query.End,
 1222                axis.Start,
 1223                expandedRadius,
 1224                segmentLength,
 1225                out entry,
 1226                out exit);
 227        }
 228
 1229        startContained = IsCapsulePointContained(
 1230            startDistanceSquared,
 1231            GetDot(query.Start, axis.End, query.Start, axis.End),
 1232            startAxisProjection,
 1233            axisLengthSquared,
 1234            squaredRadius,
 1235            strict: false);
 1236        endContainedStrict = IsCapsulePointContained(
 1237            endDistanceSquared,
 1238            GetDot(query.End, axis.End, query.End, axis.End),
 1239            GetDot(query.End, axis.Start, axis.End, axis.Start),
 1240            axisLengthSquared,
 1241            squaredRadius,
 1242            strict: true);
 1243        bool found = TryGetFiniteAxisDistanceInterval(
 1244            queryLengthSquared,
 1245            axisLengthSquared,
 1246            startDistanceSquared,
 1247            directionsDot,
 1248            startAxisProjection,
 1249            startDirectionProjection,
 1250            expandedRadius,
 1251            segmentLength,
 1252            out entry,
 1253            out exit);
 1254        Merge(
 1255            TryGetSphereDistanceInterval(query.Start, query.End, axis.Start, expandedRadius, segmentLength, out Fixed64 
 1256            startEntry,
 1257            startExit,
 1258            ref found,
 1259            ref entry,
 1260            ref exit);
 1261        Merge(
 1262            TryGetSphereDistanceInterval(query.Start, query.End, axis.End, expandedRadius, segmentLength, out Fixed64 en
 1263            endEntry,
 1264            endExit,
 1265            ref found,
 1266            ref entry,
 1267            ref exit);
 1268        return found;
 269    }
 270
 271    internal static bool TryGetCapsuleDistanceInterval(
 272        FixedSegment2d query,
 273        Vector2d center,
 274        Vector2d axisDirection,
 275        Fixed64 axisLength,
 276        Fixed64 radius,
 277        Fixed64 radiusExpansion,
 278        Fixed64 segmentLength,
 279        out Fixed64 entry,
 280        out Fixed64 exit,
 281        out bool startContained,
 282        out bool endContainedStrict)
 283    {
 5284        Signed192 expandedRadius = GetExpandedRadius(radius, radiusExpansion);
 5285        Signed192 squaredRadius = GetSquaredRadius(expandedRadius);
 5286        Signed192 axisLengthSquared = GetDot(axisDirection, Vector2d.Zero, axisDirection, Vector2d.Zero);
 5287        Signed192 queryLengthSquared = GetDot(query.End, query.Start, query.End, query.Start);
 5288        Signed192 startDistanceSquared = GetDot(query.Start, center, query.Start, center);
 5289        Signed192 directionsDot = GetDot(query.End, query.Start, axisDirection, Vector2d.Zero);
 5290        Signed192 startAxisProjection = GetDot(query.Start, center, axisDirection, Vector2d.Zero);
 5291        Signed192 endAxisProjection = GetDot(query.End, center, axisDirection, Vector2d.Zero);
 5292        Signed192 startDirectionProjection = GetDot(query.Start, center, query.End, query.Start);
 5293        Signed320 axialExtent = GetCenteredAxialExtent(axisLengthSquared, axisLength, Fixed64.Zero);
 294
 5295        startContained = IsCenteredCapsulePointContained(
 5296            query.Start, center, axisDirection, axisLength,
 5297            startDistanceSquared, startAxisProjection, axisLengthSquared,
 5298            squaredRadius, expandedRadius, axialExtent, strict: false);
 5299        endContainedStrict = IsCenteredCapsulePointContained(
 5300            query.End, center, axisDirection, axisLength,
 5301            GetDot(query.End, center, query.End, center), endAxisProjection,
 5302            axisLengthSquared, squaredRadius, expandedRadius, axialExtent, strict: true);
 303
 5304        bool found = false;
 5305        entry = default;
 5306        exit = default;
 5307        if (TryGetCenteredAxialInterval(
 5308                startAxisProjection,
 5309                directionsDot,
 5310                axialExtent,
 5311                Fixed64.One,
 5312                out RationalBound320 lower,
 5313                out RationalBound320 upper))
 314        {
 4315            found = TryGetFiniteAxisDistanceInterval(
 4316                queryLengthSquared, axisLengthSquared, startDistanceSquared,
 4317                directionsDot, startAxisProjection, startDirectionProjection,
 4318                expandedRadius, lower, upper, segmentLength, out entry, out exit);
 319        }
 320
 5321        MergeCenteredCapDistanceInterval(query, center, axisDirection, axisLength, expandedRadius, segmentLength, false,
 5322        MergeCenteredCapDistanceInterval(query, center, axisDirection, axisLength, expandedRadius, segmentLength, true, 
 5323        return found;
 324    }
 325
 326    internal static bool TryGetCapsuleDistanceInterval(
 327        FixedSegment query,
 328        Vector3d center,
 329        Vector3d axisDirection,
 330        Fixed64 axisLength,
 331        Fixed64 radius,
 332        Fixed64 radiusExpansion,
 333        Fixed64 segmentLength,
 334        out Fixed64 entry,
 335        out Fixed64 exit,
 336        out bool startContained,
 337        out bool endContainedStrict)
 338    {
 16339        Signed192 expandedRadius = GetExpandedRadius(radius, radiusExpansion);
 16340        Signed192 squaredRadius = GetSquaredRadius(expandedRadius);
 16341        Signed192 axisLengthSquared = GetDot(axisDirection, Vector3d.Zero, axisDirection, Vector3d.Zero);
 16342        Signed192 queryLengthSquared = GetDot(query.End, query.Start, query.End, query.Start);
 16343        Signed192 startDistanceSquared = GetDot(query.Start, center, query.Start, center);
 16344        Signed192 directionsDot = GetDot(query.End, query.Start, axisDirection, Vector3d.Zero);
 16345        Signed192 startAxisProjection = GetDot(query.Start, center, axisDirection, Vector3d.Zero);
 16346        Signed192 endAxisProjection = GetDot(query.End, center, axisDirection, Vector3d.Zero);
 16347        Signed192 startDirectionProjection = GetDot(query.Start, center, query.End, query.Start);
 16348        Signed320 axialExtent = GetCenteredAxialExtent(axisLengthSquared, axisLength, Fixed64.Zero);
 349
 16350        startContained = IsCenteredCapsulePointContained(
 16351            query.Start, center, axisDirection, axisLength,
 16352            startDistanceSquared, startAxisProjection, axisLengthSquared,
 16353            squaredRadius, expandedRadius, axialExtent, strict: false);
 16354        endContainedStrict = IsCenteredCapsulePointContained(
 16355            query.End, center, axisDirection, axisLength,
 16356            GetDot(query.End, center, query.End, center), endAxisProjection,
 16357            axisLengthSquared, squaredRadius, expandedRadius, axialExtent, strict: true);
 358
 16359        bool found = false;
 16360        entry = default;
 16361        exit = default;
 16362        if (TryGetCenteredAxialInterval(
 16363                startAxisProjection,
 16364                directionsDot,
 16365                axialExtent,
 16366                Fixed64.One,
 16367                out RationalBound320 lower,
 16368                out RationalBound320 upper))
 369        {
 15370            found = TryGetFiniteAxisDistanceInterval(
 15371                queryLengthSquared, axisLengthSquared, startDistanceSquared,
 15372                directionsDot, startAxisProjection, startDirectionProjection,
 15373                expandedRadius, lower, upper, segmentLength, out entry, out exit);
 374        }
 375
 16376        MergeCenteredCapDistanceInterval(query, center, axisDirection, axisLength, expandedRadius, segmentLength, false,
 16377        MergeCenteredCapDistanceInterval(query, center, axisDirection, axisLength, expandedRadius, segmentLength, true, 
 16378        return found;
 379    }
 380
 381    internal static bool TryGetFiniteCylinderDistanceInterval(
 382        FixedSegment query,
 383        FixedSegment axis,
 384        Fixed64 radius,
 385        Fixed64 radiusExpansion,
 386        Fixed64 segmentLength,
 387        out Fixed64 entry,
 388        out Fixed64 exit,
 389        out bool startContained,
 390        out bool endContainedStrict)
 391    {
 3392        Signed192 expandedRadius = GetExpandedRadius(radius, radiusExpansion);
 3393        Signed192 squaredRadius = GetSquaredRadius(expandedRadius);
 3394        Signed192 axisLengthSquared = GetDot(axis.End, axis.Start, axis.End, axis.Start);
 3395        Signed192 queryLengthSquared = GetDot(query.End, query.Start, query.End, query.Start);
 3396        Signed192 startDistanceSquared = GetDot(query.Start, axis.Start, query.Start, axis.Start);
 3397        Signed192 endDistanceSquared = GetDot(query.End, axis.Start, query.End, axis.Start);
 3398        Signed192 directionsDot = GetDot(query.End, query.Start, axis.End, axis.Start);
 3399        Signed192 startAxisProjection = GetDot(query.Start, axis.Start, axis.End, axis.Start);
 3400        Signed192 startDirectionProjection = GetDot(query.Start, axis.Start, query.End, query.Start);
 3401        startContained = IsFiniteCylinderPointContained(
 3402            startDistanceSquared, startAxisProjection, axisLengthSquared, squaredRadius, strict: false);
 3403        endContainedStrict = IsFiniteCylinderPointContained(
 3404            endDistanceSquared,
 3405            GetDot(query.End, axis.Start, axis.End, axis.Start),
 3406            axisLengthSquared,
 3407            squaredRadius,
 3408            strict: true);
 3409        return TryGetFiniteAxisDistanceInterval(
 3410            queryLengthSquared, axisLengthSquared, startDistanceSquared,
 3411            directionsDot, startAxisProjection, startDirectionProjection,
 3412            expandedRadius, segmentLength, out entry, out exit);
 413    }
 414
 415    internal static bool TryGetFiniteCylinderDistanceInterval(
 416        FixedSegment query,
 417        Vector3d center,
 418        Vector3d axisDirection,
 419        Fixed64 axisLength,
 420        Fixed64 radius,
 421        Fixed64 radiusExpansion,
 422        Fixed64 axialExpansion,
 423        Fixed64 segmentLength,
 424        out Fixed64 entry,
 425        out Fixed64 exit,
 426        out bool startContained,
 427        out bool endContainedStrict) =>
 6428        TryGetFiniteCylinderDistanceInterval(
 6429            query,
 6430            center,
 6431            axisDirection,
 6432            Signed192.Signed(axisLength.m_rawValue),
 6433            radius,
 6434            radiusExpansion,
 6435            axialExpansion,
 6436            segmentLength,
 6437            out entry,
 6438            out exit,
 6439            out startContained,
 6440            out endContainedStrict);
 441
 442    internal static bool TryGetFiniteCylinderDistanceInterval(
 443        FixedSegment query,
 444        Vector3d center,
 445        Vector3d axisDirection,
 446        Signed192 axisLength,
 447        Fixed64 radius,
 448        Fixed64 radiusExpansion,
 449        Fixed64 axialExpansion,
 450        Fixed64 segmentLength,
 451        out Fixed64 entry,
 452        out Fixed64 exit,
 453        out bool startContained,
 454        out bool endContainedStrict)
 455    {
 50456        Signed192 queryLengthSquared = GetDot(query.End, query.Start, query.End, query.Start);
 50457        Signed192 axisLengthSquared = GetDot(axisDirection, Vector3d.Zero, axisDirection, Vector3d.Zero);
 50458        Signed192 startDistanceSquared = GetDot(query.Start, center, query.Start, center);
 50459        Signed192 endDistanceSquared = GetDot(query.End, center, query.End, center);
 50460        Signed192 directionsDot = GetDot(query.End, query.Start, axisDirection, Vector3d.Zero);
 50461        Signed192 startAxisProjection = GetDot(query.Start, center, axisDirection, Vector3d.Zero);
 50462        Signed192 startDirectionProjection = GetDot(query.Start, center, query.End, query.Start);
 50463        Signed192 expandedRadius = GetExpandedRadius(radius, radiusExpansion);
 50464        Signed192 squaredRadius = GetSquaredRadius(expandedRadius);
 50465        Signed320 axialExtent = GetCenteredAxialExtent(axisLengthSquared, axisLength, axialExpansion);
 50466        startContained = IsCenteredFiniteCylinderPointContained(
 50467            startDistanceSquared, startAxisProjection, axisLengthSquared,
 50468            squaredRadius, axialExtent, strict: false);
 50469        endContainedStrict = IsCenteredFiniteCylinderPointContained(
 50470            endDistanceSquared,
 50471            GetDot(query.End, center, axisDirection, Vector3d.Zero),
 50472            axisLengthSquared,
 50473            squaredRadius,
 50474            axialExtent,
 50475            strict: true);
 476
 50477        if (!TryGetCenteredAxialInterval(
 50478                startAxisProjection, directionsDot, axialExtent, Fixed64.One,
 50479                out RationalBound320 lower, out RationalBound320 upper))
 480        {
 19481            entry = default;
 19482            exit = default;
 19483            return false;
 484        }
 485
 31486        return TryGetFiniteAxisDistanceInterval(
 31487            queryLengthSquared, axisLengthSquared, startDistanceSquared,
 31488            directionsDot, startAxisProjection, startDirectionProjection,
 31489            expandedRadius, lower, upper, segmentLength, out entry, out exit);
 490    }
 491
 492    private static bool TryGetFiniteAxisDistanceInterval(
 493        Signed192 queryLengthSquared,
 494        Signed192 axisLengthSquared,
 495        Signed192 startDistanceSquared,
 496        Signed192 directionsDot,
 497        Signed192 startAxisProjection,
 498        Signed192 startDirectionProjection,
 499        Signed192 radius,
 500        Fixed64 segmentLength,
 501        out Fixed64 entry,
 502        out Fixed64 exit)
 503    {
 5504        if (!TryGetAxialInterval(
 5505                startAxisProjection,
 5506                directionsDot,
 5507                axisLengthSquared,
 5508                Fixed64.One,
 5509                out RationalBound lower,
 5510                out RationalBound upper))
 511        {
 1512            entry = default;
 1513            exit = default;
 1514            return false;
 515        }
 516
 4517        return TryGetFiniteAxisDistanceInterval(
 4518            queryLengthSquared,
 4519            axisLengthSquared,
 4520            startDistanceSquared,
 4521            directionsDot,
 4522            startAxisProjection,
 4523            startDirectionProjection,
 4524            radius,
 4525            new RationalBound320(
 4526                Signed320.ExtendValue(lower.Numerator),
 4527                Signed320.ExtendValue(lower.Denominator)),
 4528            new RationalBound320(
 4529                Signed320.ExtendValue(upper.Numerator),
 4530                Signed320.ExtendValue(upper.Denominator)),
 4531            segmentLength,
 4532            out entry,
 4533            out exit);
 534    }
 535
 536    private static bool TryGetFiniteAxisDistanceInterval(
 537        Signed192 queryLengthSquared,
 538        Signed192 axisLengthSquared,
 539        Signed192 startDistanceSquared,
 540        Signed192 directionsDot,
 541        Signed192 startAxisProjection,
 542        Signed192 startDirectionProjection,
 543        Signed192 radius,
 544        RationalBound320 lower,
 545        RationalBound320 upper,
 546        Fixed64 segmentLength,
 547        out Fixed64 entry,
 548        out Fixed64 exit)
 549    {
 56550        Signed320 radialCoefficient = WideArithmetic.MultiplySubtract(
 56551            queryLengthSquared, axisLengthSquared, directionsDot, directionsDot);
 56552        Signed320 radialProjection = WideArithmetic.MultiplySubtract(
 56553            startDirectionProjection, axisLengthSquared, startAxisProjection, directionsDot);
 56554        Signed320 radialConstant = GetRadialConstant(
 56555            startDistanceSquared,
 56556            startAxisProjection,
 56557            axisLengthSquared,
 56558            GetSquaredRadius(radius));
 56559        return TrySolveBoundedQuadraticAtDistance(
 56560            radialCoefficient,
 56561            radialProjection,
 56562            radialConstant,
 56563            lower,
 56564            upper,
 56565            segmentLength,
 56566            out entry,
 56567            out exit);
 568    }
 569
 570    private static bool TryGetCircleDistanceInterval(
 571        Vector2d start,
 572        Vector2d end,
 573        Vector2d center,
 574        Signed192 radius,
 575        Fixed64 segmentLength,
 576        out Fixed64 entry,
 577        out Fixed64 exit) =>
 19772578        TrySolveUnitQuadraticAtDistance(
 19772579            Signed320.ExtendValue(GetDot(end, start, end, start)),
 19772580            Signed320.ExtendValue(GetDot(start, center, end, start)),
 19772581            Signed320.ExtendValue(WideArithmetic.SubtractSigned192(
 19772582                GetDot(start, center, start, center),
 19772583                GetSquaredRadius(radius))),
 19772584            segmentLength,
 19772585            out entry,
 19772586            out exit);
 587
 588    private static bool TryGetSphereDistanceInterval(
 589        Vector3d start,
 590        Vector3d end,
 591        Vector3d center,
 592        Signed192 radius,
 593        Fixed64 segmentLength,
 594        out Fixed64 entry,
 595        out Fixed64 exit) =>
 9596        TrySolveUnitQuadraticAtDistance(
 9597            Signed320.ExtendValue(GetDot(end, start, end, start)),
 9598            Signed320.ExtendValue(GetDot(start, center, end, start)),
 9599            Signed320.ExtendValue(WideArithmetic.SubtractSigned192(
 9600                GetDot(start, center, start, center),
 9601                GetSquaredRadius(radius))),
 9602            segmentLength,
 9603            out entry,
 9604            out exit);
 605
 606    private static void MergeCenteredCapDistanceInterval(
 607        FixedSegment2d query,
 608        Vector2d center,
 609        Vector2d axisDirection,
 610        Fixed64 axisLength,
 611        Signed192 expandedRadius,
 612        Fixed64 segmentLength,
 613        bool positiveCap,
 614        ref bool found,
 615        ref Fixed64 entry,
 616        ref Fixed64 exit)
 617    {
 10618        GetCenteredCapPolynomial(
 10619            query, center, axisDirection, axisLength, expandedRadius, positiveCap,
 10620            out Signed320 coefficient, out Signed320 projection, out Signed320 constant);
 10621        Merge(
 10622            TrySolveUnitQuadraticAtDistance(
 10623                coefficient, projection, constant, segmentLength,
 10624                out Fixed64 capEntry, out Fixed64 capExit),
 10625            capEntry, capExit, ref found, ref entry, ref exit);
 10626    }
 627
 628    private static void MergeCenteredCapDistanceInterval(
 629        FixedSegment query,
 630        Vector3d center,
 631        Vector3d axisDirection,
 632        Fixed64 axisLength,
 633        Signed192 expandedRadius,
 634        Fixed64 segmentLength,
 635        bool positiveCap,
 636        ref bool found,
 637        ref Fixed64 entry,
 638        ref Fixed64 exit)
 639    {
 32640        GetCenteredCapPolynomial(
 32641            query, center, axisDirection, axisLength, expandedRadius, positiveCap,
 32642            out Signed320 coefficient, out Signed320 projection, out Signed320 constant);
 32643        Merge(
 32644            TrySolveUnitQuadraticAtDistance(
 32645                coefficient, projection, constant, segmentLength,
 32646                out Fixed64 capEntry, out Fixed64 capExit),
 32647            capEntry, capExit, ref found, ref entry, ref exit);
 32648    }
 649}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.DistanceSolver.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.DistanceSolver.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
 8namespace FixedMathSharp.Geometry;
 9
 10/// <content>
 11/// Solves bounded quadratic intersection problems and converts the resulting
 12/// parametric roots into actual distances along a segment of a given length.
 13/// </content>
 14internal static partial class WideFiniteAxisIntersection
 15{
 16    private static bool TrySolveUnitQuadraticAtDistance(
 17        Signed320 coefficient,
 18        Signed320 projection,
 19        Signed320 constant,
 20        Fixed64 segmentLength,
 21        out Fixed64 entryDistance,
 22        out Fixed64 exitDistance)
 23    {
 2014724        Signed320 one = Scale320;
 2014725        return TrySolveBoundedQuadraticAtDistance(
 2014726            coefficient,
 2014727            projection,
 2014728            constant,
 2014729            new RationalBound320(default, one),
 2014730            new RationalBound320(one, one),
 2014731            segmentLength,
 2014732            out entryDistance,
 2014733            out exitDistance);
 34    }
 35
 36    private static bool TrySolveBoundedQuadraticAtDistance(
 37        Signed320 coefficient,
 38        Signed320 projection,
 39        Signed320 constant,
 40        RationalBound320 lower,
 41        RationalBound320 upper,
 42        Fixed64 segmentLength,
 43        out Fixed64 entryDistance,
 44        out Fixed64 exitDistance)
 45    {
 2026546        entryDistance = default;
 2026547        exitDistance = default;
 48
 2026549        if (coefficient.IsZero)
 50        {
 16151            if (constant.Sign > 0)
 6552                return false;
 53
 9654            entryDistance = RoundAtDistance(lower, segmentLength);
 9655            exitDistance = RoundAtDistance(upper, segmentLength);
 9656            return true;
 57        }
 58
 2010459        Signed704 lowerValue = EvaluatePolynomial(
 2010460            coefficient,
 2010461            projection,
 2010462            constant,
 2010463            lower.Numerator,
 2010464            lower.Denominator);
 2010465        Signed704 upperValue = EvaluatePolynomial(
 2010466            coefficient,
 2010467            projection,
 2010468            constant,
 2010469            upper.Numerator,
 2010470            upper.Denominator);
 2010471        int lowerDerivative = EvaluateDerivative(
 2010472            coefficient,
 2010473            projection,
 2010474            lower.Numerator,
 2010475            lower.Denominator).Sign;
 2010476        int upperDerivative = EvaluateDerivative(
 2010477            coefficient,
 2010478            projection,
 2010479            upper.Numerator,
 2010480            upper.Denominator).Sign;
 81
 2010482        if ((lowerValue.Sign > 0 && lowerDerivative >= 0)
 2010483            || (upperValue.Sign > 0 && upperDerivative <= 0))
 84        {
 5285            return false;
 86        }
 87
 2005288        if (lowerValue.Sign <= 0 && upperValue.Sign <= 0)
 89        {
 1390            entryDistance = RoundAtDistance(lower, segmentLength);
 1391            exitDistance = RoundAtDistance(upper, segmentLength);
 1392            return true;
 93        }
 94
 2003995        Signed576 discriminant = WideArithmetic.SubtractSigned576(
 2003996            WideArithmetic.MultiplySigned320(projection, projection),
 2003997            WideArithmetic.MultiplySigned320(coefficient, constant));
 2003998        if (discriminant.Sign < 0)
 1199            return false;
 100
 20028101        Signed192 lengthSquared = SquareRaw(segmentLength.m_rawValue);
 20028102        Signed576 scaledSquareRoot = WideArithmetic.GetFloorSquareRoot(
 20028103            WideArithmetic.MultiplyNonNegative(discriminant, lengthSquared));
 20028104        entryDistance = lowerValue.Sign <= 0
 20028105            ? RoundAtDistance(lower, segmentLength)
 20028106            : RoundLowerRootAtDistance(
 20028107                coefficient,
 20028108                projection,
 20028109                constant,
 20028110                scaledSquareRoot,
 20028111                segmentLength);
 20028112        exitDistance = upperValue.Sign <= 0
 20028113            ? RoundAtDistance(upper, segmentLength)
 20028114            : RoundUpperRootAtDistance(
 20028115                coefficient,
 20028116                projection,
 20028117                constant,
 20028118                scaledSquareRoot,
 20028119                segmentLength);
 20028120        return true;
 121    }
 122
 123    private static Fixed64 RoundLowerRootAtDistance(
 124        Signed320 coefficient,
 125        Signed320 projection,
 126        Signed320 constant,
 127        Signed576 scaledSquareRoot,
 128        Fixed64 segmentLength)
 129    {
 10122130        Signed320 lengthRaw = Signed320.ExtendValue(
 10122131            Signed192.Signed(segmentLength.m_rawValue));
 10122132        Signed576 negativeScaledProjection = WideArithmetic.SubtractSigned576(
 10122133            default,
 10122134            WideArithmetic.MultiplySigned320(projection, lengthRaw));
 10122135        Signed576 numerator = WideArithmetic.SubtractSigned576(
 10122136            negativeScaledProjection,
 10122137            scaledSquareRoot);
 10122138        Fixed64.TryGetSignedRawRatio(
 10122139            numerator,
 10122140            Signed576.ExtendValue(coefficient),
 10122141            out Fixed64 candidate);
 142
 10122143        long upperRaw = candidate.m_rawValue;
 10122144        if (upperRaw == 0L)
 110145            return Fixed64.Zero;
 146
 10012147        Signed320 upper = Signed320.ExtendValue(
 10012148            Signed192.Signed(upperRaw));
 10012149        Signed320 midpoint = WideArithmetic.SubtractSigned320(
 10012150            WideArithmetic.AddSigned320(upper, upper),
 10012151            Scale320);
 10012152        Signed320 doubleLength = WideArithmetic.AddSigned320(lengthRaw, lengthRaw);
 10012153        Signed704 value = EvaluatePolynomial(
 10012154            coefficient,
 10012155            projection,
 10012156            constant,
 10012157            midpoint,
 10012158            doubleLength);
 10012159        if (value.IsZero)
 277160            return candidate;
 161
 9735162        return Fixed64.FromRaw(value.Sign > 0
 9735163            ? upperRaw
 9735164            : upperRaw - 1L);
 165    }
 166
 167    private static Fixed64 RoundUpperRootAtDistance(
 168        Signed320 coefficient,
 169        Signed320 projection,
 170        Signed320 constant,
 171        Signed576 scaledSquareRoot,
 172        Fixed64 segmentLength)
 173    {
 10029174        Signed320 lengthRaw = Signed320.ExtendValue(
 10029175            Signed192.Signed(segmentLength.m_rawValue));
 10029176        Signed576 negativeScaledProjection = WideArithmetic.SubtractSigned576(
 10029177            default,
 10029178            WideArithmetic.MultiplySigned320(projection, lengthRaw));
 10029179        Signed576 numerator = WideArithmetic.AddSigned576(
 10029180            negativeScaledProjection,
 10029181            scaledSquareRoot);
 10029182        Fixed64.TryGetSignedRawRatio(
 10029183            numerator,
 10029184            Signed576.ExtendValue(coefficient),
 10029185            out Fixed64 candidate);
 186
 10029187        long lowerRaw = candidate.m_rawValue;
 10029188        if (lowerRaw == segmentLength.m_rawValue)
 87189            return segmentLength;
 190
 9942191        Signed320 lower = Signed320.ExtendValue(
 9942192            Signed192.Signed(lowerRaw));
 9942193        Signed320 midpoint = WideArithmetic.AddSigned320(
 9942194            WideArithmetic.AddSigned320(lower, lower),
 9942195            Scale320);
 9942196        Signed320 doubleLength = WideArithmetic.AddSigned320(lengthRaw, lengthRaw);
 9942197        Signed704 value = EvaluatePolynomial(
 9942198            coefficient,
 9942199            projection,
 9942200            constant,
 9942201            midpoint,
 9942202            doubleLength);
 9942203        if (value.IsZero)
 266204            return candidate;
 205
 9676206        return Fixed64.FromRaw(value.Sign <= 0
 9676207            ? lowerRaw + 1L
 9676208            : lowerRaw);
 209    }
 210
 211    private static Fixed64 RoundAtDistance(RationalBound320 value, Fixed64 segmentLength)
 212    {
 20123213        Signed320 lengthRaw = Signed320.ExtendValue(
 20123214            Signed192.Signed(segmentLength.m_rawValue));
 20123215        Fixed64.TryGetSignedRawRatio(
 20123216            WideArithmetic.MultiplySigned320(value.Numerator, lengthRaw),
 20123217            Signed576.ExtendValue(value.Denominator),
 20123218            out Fixed64 distance);
 20123219        return distance;
 220    }
 221
 222    private static Signed192 SquareRaw(long raw)
 223    {
 20028224        ulong magnitude = (ulong)raw;
 20028225        Fixed64.Multiply64To128(magnitude, magnitude, out ulong high, out ulong low);
 20028226        return new Signed192(0UL, high, low);
 227    }
 228}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.NarrowSolver.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.NarrowSolver.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>
 13/// Narrowing helpers that reduce wide 320-bit radial coefficients down to
 14/// 192-bit values when their magnitude and common shift allow it, enabling
 15/// cheaper downstream arithmetic in the narrow intersection solver.
 16/// </content>
 17internal static partial class WideFiniteAxisIntersection
 18{
 19    // Squaring two values below 2^159 and subtracting their products stays
 20    // inside the signed 320-bit discriminant used by WideRayIntersection.
 21    private const int NarrowRadialCoefficientBits = 159;
 22
 23    private static bool TryGetNarrowRadialCoefficients(
 24        Signed320 coefficient,
 25        Signed320 projection,
 26        Signed320 constant,
 27        out Signed192 narrowCoefficient,
 28        out Signed192 narrowProjection,
 29        out Signed192 narrowConstant)
 30    {
 49931        int commonShift = Math.Min(
 49932            GetTrailingZeroCount(coefficient),
 49933            Math.Min(GetTrailingZeroCount(projection), GetTrailingZeroCount(constant)));
 49934        if (commonShift > 0)
 35        {
 34636            coefficient = ShiftRightExact(coefficient, commonShift);
 34637            projection = ShiftRightExact(projection, commonShift);
 34638            constant = ShiftRightExact(constant, commonShift);
 39        }
 40
 49941        int maximumBits = Math.Max(
 49942            GetMagnitudeBitLength(coefficient),
 49943            Math.Max(GetMagnitudeBitLength(projection), GetMagnitudeBitLength(constant)));
 49944        if (maximumBits > NarrowRadialCoefficientBits)
 45        {
 15346            narrowCoefficient = default;
 15347            narrowProjection = default;
 15348            narrowConstant = default;
 15349            return false;
 50        }
 51
 34652        bool coefficientFits = Signed192.TryNarrowSigned(coefficient, out narrowCoefficient);
 34653        bool projectionFits = Signed192.TryNarrowSigned(projection, out narrowProjection);
 34654        bool constantFits = Signed192.TryNarrowSigned(constant, out narrowConstant);
 34655        return coefficientFits && projectionFits && constantFits;
 56    }
 57
 58    private static int GetMagnitudeBitLength(Signed320 value)
 59    {
 149760        if (value.IsZero)
 561            return 0;
 62
 149263        WideArithmetic.GetMagnitude(
 149264            value,
 149265            out ulong word4,
 149266            out ulong word3,
 149267            out ulong word2,
 149268            out ulong word1,
 149269            out ulong word0);
 149270        return WideArithmetic.GetBitLength(word4, word3, word2, word1, word0);
 71    }
 72
 73    private static int GetTrailingZeroCount(Signed320 value)
 74    {
 149775        if (value.Word0 != 0UL)
 46376            return CountTrailingZeroes(value.Word0);
 103477        if (value.Word1 != 0UL)
 85278            return 64 + CountTrailingZeroes(value.Word1);
 18279        if (value.Word2 != 0UL)
 17780            return 128 + CountTrailingZeroes(value.Word2);
 581        return 192;
 82    }
 83
 84    private static int CountTrailingZeroes(ulong value) =>
 149285        63 - Fixed64.CountLeadingZeroes(value & unchecked(0UL - value));
 86
 87    private static Signed320 ShiftRightExact(Signed320 value, int bits)
 88    {
 121889        int wordShift = bits >> 6;
 121890        int bitShift = bits & 63;
 121891        return new Signed320(
 121892            GetShiftedWord(value, 4, wordShift, bitShift),
 121893            GetShiftedWord(value, 3, wordShift, bitShift),
 121894            GetShiftedWord(value, 2, wordShift, bitShift),
 121895            GetShiftedWord(value, 1, wordShift, bitShift),
 121896            GetShiftedWord(value, 0, wordShift, bitShift));
 97    }
 98
 99    private static ulong GetShiftedWord(Signed320 value, int index, int wordShift, int bitShift)
 100    {
 6090101        int sourceIndex = index + wordShift;
 6090102        ulong lower = GetSignedWord(value, sourceIndex);
 6090103        if (bitShift == 0)
 315104            return lower;
 105
 5775106        ulong upper = GetSignedWord(value, sourceIndex + 1);
 5775107        return (lower >> bitShift) | (upper << (64 - bitShift));
 108    }
 109
 11865110    private static ulong GetSignedWord(Signed320 value, int index) => index switch
 11865111    {
 198112        0 => value.Word0,
 1260113        1 => value.Word1,
 2265114        2 => value.Word2,
 2373115        3 => value.Word3,
 2373116        4 => value.Word4,
 3396117        _ => value.Sign < 0 ? ulong.MaxValue : 0UL,
 11865118    };
 119}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.Ray.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.Ray.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
 8namespace FixedMathSharp.Geometry;
 9
 10/// <content>
 11/// Provides ray/segment-based intersection helpers for finite-axis shapes,
 12/// including capsule interval computation against a <see cref="FixedRay2d"/>.
 13/// </content>
 14internal static partial class WideFiniteAxisIntersection
 15{
 16    internal static bool TryGetCapsuleInterval(
 17        FixedRay2d query,
 18        Fixed64 maxParameter,
 19        FixedSegment2d axis,
 20        Fixed64 radius,
 21        Fixed64 radiusExpansion,
 22        out Fixed64 entry,
 23        out Fixed64 exit,
 24        out bool originContained,
 25        out bool maximumContainedStrict)
 26    {
 1027        Signed192 expandedRadius = GetExpandedRadius(radius, radiusExpansion);
 1028        Signed192 squaredRadius = GetSquaredRadius(expandedRadius);
 1029        Signed192 axisLengthSquared = GetDot(axis.End, axis.Start, axis.End, axis.Start);
 1030        Signed192 queryLengthSquared = GetDirectionDot(query.Direction, query.Direction);
 1031        Signed192 startDistanceSquared = GetDot(query.Position, axis.Start, query.Position, axis.Start);
 1032        Signed192 directionsDot = GetDirectionDot(query.Direction, axis.End, axis.Start);
 1033        Signed192 startAxisProjection = GetDot(query.Position, axis.Start, axis.End, axis.Start);
 1034        Signed192 startDirectionProjection = GetDirectionDot(query.Direction, query.Position, axis.Start);
 35
 1036        originContained = axisLengthSquared.IsZero
 1037            ? IsWithinRadius(startDistanceSquared, squaredRadius, strict: false)
 1038            : IsCapsulePointContained(
 1039                startDistanceSquared,
 1040                GetDot(query.Position, axis.End, query.Position, axis.End),
 1041                startAxisProjection,
 1042                axisLengthSquared,
 1043                squaredRadius,
 1044                strict: false);
 1045        maximumContainedStrict = IsCapsuleContainedAtParameter(
 1046            query,
 1047            maxParameter,
 1048            axis,
 1049            expandedRadius,
 1050            queryLengthSquared,
 1051            axisLengthSquared,
 1052            startDistanceSquared,
 1053            directionsDot,
 1054            startAxisProjection,
 1055            startDirectionProjection);
 56
 1057        if (axisLengthSquared.IsZero)
 58        {
 559            return TryGetCircleInterval(
 560                query.Position,
 561                query.Direction,
 562                axis.Start,
 563                expandedRadius,
 564                maxParameter,
 565                out entry,
 566                out exit);
 67        }
 68
 569        bool found = TryGetFiniteAxisInterval(
 570            queryLengthSquared,
 571            axisLengthSquared,
 572            startDistanceSquared,
 573            directionsDot,
 574            startAxisProjection,
 575            startDirectionProjection,
 576            expandedRadius,
 577            maxParameter,
 578            out entry,
 579            out exit);
 580        Merge(
 581            TryGetCircleInterval(
 582                query.Position, query.Direction, axis.Start, expandedRadius, maxParameter,
 583                out Fixed64 startEntry, out Fixed64 startExit),
 584            startEntry, startExit, ref found, ref entry, ref exit);
 585        Merge(
 586            TryGetCircleInterval(
 587                query.Position, query.Direction, axis.End, expandedRadius, maxParameter,
 588                out Fixed64 endEntry, out Fixed64 endExit),
 589            endEntry, endExit, ref found, ref entry, ref exit);
 590        return found;
 91    }
 92
 93    internal static bool TryGetCapsuleInterval(
 94        FixedRay query,
 95        Fixed64 maxParameter,
 96        FixedSegment axis,
 97        Fixed64 radius,
 98        Fixed64 radiusExpansion,
 99        out Fixed64 entry,
 100        out Fixed64 exit,
 101        out bool originContained,
 102        out bool maximumContainedStrict)
 103    {
 5104        Signed192 expandedRadius = GetExpandedRadius(radius, radiusExpansion);
 5105        Signed192 squaredRadius = GetSquaredRadius(expandedRadius);
 5106        Signed192 axisLengthSquared = GetDot(axis.End, axis.Start, axis.End, axis.Start);
 5107        Signed192 queryLengthSquared = GetDirectionDot(query.Direction, query.Direction);
 5108        Signed192 startDistanceSquared = GetDot(query.Position, axis.Start, query.Position, axis.Start);
 5109        Signed192 directionsDot = GetDirectionDot(query.Direction, axis.End, axis.Start);
 5110        Signed192 startAxisProjection = GetDot(query.Position, axis.Start, axis.End, axis.Start);
 5111        Signed192 startDirectionProjection = GetDirectionDot(query.Direction, query.Position, axis.Start);
 112
 5113        originContained = axisLengthSquared.IsZero
 5114            ? IsWithinRadius(startDistanceSquared, squaredRadius, strict: false)
 5115            : IsCapsulePointContained(
 5116                startDistanceSquared,
 5117                GetDot(query.Position, axis.End, query.Position, axis.End),
 5118                startAxisProjection,
 5119                axisLengthSquared,
 5120                squaredRadius,
 5121                strict: false);
 5122        maximumContainedStrict = IsCapsuleContainedAtParameter(
 5123            query,
 5124            maxParameter,
 5125            axis,
 5126            expandedRadius,
 5127            queryLengthSquared,
 5128            axisLengthSquared,
 5129            startDistanceSquared,
 5130            directionsDot,
 5131            startAxisProjection,
 5132            startDirectionProjection);
 133
 5134        if (axisLengthSquared.IsZero)
 135        {
 2136            return TryGetSphereInterval(
 2137                query.Position,
 2138                query.Direction,
 2139                axis.Start,
 2140                expandedRadius,
 2141                maxParameter,
 2142                out entry,
 2143                out exit);
 144        }
 145
 3146        bool found = TryGetFiniteAxisInterval(
 3147            queryLengthSquared,
 3148            axisLengthSquared,
 3149            startDistanceSquared,
 3150            directionsDot,
 3151            startAxisProjection,
 3152            startDirectionProjection,
 3153            expandedRadius,
 3154            maxParameter,
 3155            out entry,
 3156            out exit);
 3157        Merge(
 3158            TryGetSphereInterval(
 3159                query.Position, query.Direction, axis.Start, expandedRadius, maxParameter,
 3160                out Fixed64 startEntry, out Fixed64 startExit),
 3161            startEntry, startExit, ref found, ref entry, ref exit);
 3162        Merge(
 3163            TryGetSphereInterval(
 3164                query.Position, query.Direction, axis.End, expandedRadius, maxParameter,
 3165                out Fixed64 endEntry, out Fixed64 endExit),
 3166            endEntry, endExit, ref found, ref entry, ref exit);
 3167        return found;
 168    }
 169
 170    internal static bool TryGetCapsuleInterval(
 171        FixedRay2d query,
 172        Fixed64 maxParameter,
 173        Vector2d center,
 174        Vector2d axisDirection,
 175        Fixed64 axisLength,
 176        Fixed64 radius,
 177        Fixed64 radiusExpansion,
 178        out Fixed64 entry,
 179        out Fixed64 exit,
 180        out bool originContained,
 181        out bool maximumContainedStrict)
 182    {
 4183        Signed192 expandedRadius = GetExpandedRadius(radius, radiusExpansion);
 4184        Signed192 squaredRadius = GetSquaredRadius(expandedRadius);
 4185        Signed192 axisLengthSquared = GetDot(axisDirection, Vector2d.Zero, axisDirection, Vector2d.Zero);
 4186        Signed192 queryLengthSquared = GetDirectionDot(query.Direction, query.Direction);
 4187        Signed192 startDistanceSquared = GetDot(query.Position, center, query.Position, center);
 4188        Signed192 directionsDot = GetDirectionDot(query.Direction, axisDirection);
 4189        Signed192 startAxisProjection = GetDot(query.Position, center, axisDirection, Vector2d.Zero);
 4190        Signed192 startDirectionProjection = GetDirectionDot(query.Direction, query.Position, center);
 4191        Signed320 axialExtent = GetCenteredAxialExtent(
 4192            axisLengthSquared,
 4193            axisLength,
 4194            Fixed64.Zero);
 195
 4196        originContained = IsCenteredCapsulePointContained(
 4197            query.Position, center, axisDirection, axisLength,
 4198            startDistanceSquared, startAxisProjection, axisLengthSquared,
 4199            squaredRadius, expandedRadius, axialExtent, strict: false);
 4200        maximumContainedStrict = IsCenteredCapsuleContainedAtParameter(
 4201            query,
 4202            maxParameter,
 4203            center,
 4204            axisDirection,
 4205            axisLength,
 4206            expandedRadius,
 4207            queryLengthSquared,
 4208            axisLengthSquared,
 4209            startDistanceSquared,
 4210            directionsDot,
 4211            startAxisProjection,
 4212            startDirectionProjection,
 4213            axialExtent);
 214
 4215        bool found = false;
 4216        entry = default;
 4217        exit = default;
 4218        if (TryGetCenteredAxialInterval(
 4219                startAxisProjection,
 4220                directionsDot,
 4221                axialExtent,
 4222                maxParameter,
 4223                out RationalBound320 lower,
 4224                out RationalBound320 upper))
 225        {
 3226            found = TryGetFiniteAxisInterval(
 3227                queryLengthSquared,
 3228                axisLengthSquared,
 3229                startDistanceSquared,
 3230                directionsDot,
 3231                startAxisProjection,
 3232                startDirectionProjection,
 3233                expandedRadius,
 3234                lower,
 3235                upper,
 3236                maxParameter,
 3237                out entry,
 3238                out exit);
 239        }
 240
 4241        MergeCenteredCapInterval(
 4242            query, maxParameter, center, axisDirection, axisLength,
 4243            expandedRadius, positiveCap: false, ref found, ref entry, ref exit);
 4244        MergeCenteredCapInterval(
 4245            query, maxParameter, center, axisDirection, axisLength,
 4246            expandedRadius, positiveCap: true, ref found, ref entry, ref exit);
 4247        return found;
 248    }
 249
 250    internal static bool TryGetCapsuleInterval(
 251        FixedRay query,
 252        Fixed64 maxParameter,
 253        Vector3d center,
 254        Vector3d axisDirection,
 255        Fixed64 axisLength,
 256        Fixed64 radius,
 257        Fixed64 radiusExpansion,
 258        out Fixed64 entry,
 259        out Fixed64 exit,
 260        out bool originContained,
 261        out bool maximumContainedStrict)
 262    {
 5263        Signed192 expandedRadius = GetExpandedRadius(radius, radiusExpansion);
 5264        Signed192 squaredRadius = GetSquaredRadius(expandedRadius);
 5265        Signed192 axisLengthSquared = GetDot(axisDirection, Vector3d.Zero, axisDirection, Vector3d.Zero);
 5266        Signed192 queryLengthSquared = GetDirectionDot(query.Direction, query.Direction);
 5267        Signed192 startDistanceSquared = GetDot(query.Position, center, query.Position, center);
 5268        Signed192 directionsDot = GetDirectionDot(query.Direction, axisDirection);
 5269        Signed192 startAxisProjection = GetDot(query.Position, center, axisDirection, Vector3d.Zero);
 5270        Signed192 startDirectionProjection = GetDirectionDot(query.Direction, query.Position, center);
 5271        Signed320 axialExtent = GetCenteredAxialExtent(
 5272            axisLengthSquared,
 5273            axisLength,
 5274            Fixed64.Zero);
 275
 5276        originContained = IsCenteredCapsulePointContained(
 5277            query.Position, center, axisDirection, axisLength,
 5278            startDistanceSquared, startAxisProjection, axisLengthSquared,
 5279            squaredRadius, expandedRadius, axialExtent, strict: false);
 5280        maximumContainedStrict = IsCenteredCapsuleContainedAtParameter(
 5281            query,
 5282            maxParameter,
 5283            center,
 5284            axisDirection,
 5285            axisLength,
 5286            expandedRadius,
 5287            queryLengthSquared,
 5288            axisLengthSquared,
 5289            startDistanceSquared,
 5290            directionsDot,
 5291            startAxisProjection,
 5292            startDirectionProjection,
 5293            axialExtent);
 294
 5295        bool found = false;
 5296        entry = default;
 5297        exit = default;
 5298        if (TryGetCenteredAxialInterval(
 5299                startAxisProjection,
 5300                directionsDot,
 5301                axialExtent,
 5302                maxParameter,
 5303                out RationalBound320 lower,
 5304                out RationalBound320 upper))
 305        {
 4306            found = TryGetFiniteAxisInterval(
 4307                queryLengthSquared,
 4308                axisLengthSquared,
 4309                startDistanceSquared,
 4310                directionsDot,
 4311                startAxisProjection,
 4312                startDirectionProjection,
 4313                expandedRadius,
 4314                lower,
 4315                upper,
 4316                maxParameter,
 4317                out entry,
 4318                out exit);
 319        }
 320
 5321        MergeCenteredCapInterval(
 5322            query, maxParameter, center, axisDirection, axisLength,
 5323            expandedRadius, positiveCap: false, ref found, ref entry, ref exit);
 5324        MergeCenteredCapInterval(
 5325            query, maxParameter, center, axisDirection, axisLength,
 5326            expandedRadius, positiveCap: true, ref found, ref entry, ref exit);
 5327        return found;
 328    }
 329
 330    internal static bool TryGetFiniteCylinderInterval(
 331        FixedRay query,
 332        Fixed64 maxParameter,
 333        FixedSegment axis,
 334        Fixed64 radius,
 335        Fixed64 radiusExpansion,
 336        out Fixed64 entry,
 337        out Fixed64 exit,
 338        out bool originContained,
 339        out bool maximumContainedStrict)
 340    {
 3341        Signed192 expandedRadius = GetExpandedRadius(radius, radiusExpansion);
 3342        Signed192 squaredRadius = GetSquaredRadius(expandedRadius);
 3343        Signed192 axisLengthSquared = GetDot(axis.End, axis.Start, axis.End, axis.Start);
 3344        Signed192 queryLengthSquared = GetDirectionDot(query.Direction, query.Direction);
 3345        Signed192 startDistanceSquared = GetDot(query.Position, axis.Start, query.Position, axis.Start);
 3346        Signed192 directionsDot = GetDirectionDot(query.Direction, axis.End, axis.Start);
 3347        Signed192 startAxisProjection = GetDot(query.Position, axis.Start, axis.End, axis.Start);
 3348        Signed192 startDirectionProjection = GetDirectionDot(query.Direction, query.Position, axis.Start);
 349
 3350        originContained = IsFiniteCylinderPointContained(
 3351            startDistanceSquared, startAxisProjection, axisLengthSquared, squaredRadius, strict: false);
 3352        maximumContainedStrict = IsFiniteCylinderContainedAtParameter(
 3353            maxParameter,
 3354            expandedRadius,
 3355            queryLengthSquared,
 3356            axisLengthSquared,
 3357            startDistanceSquared,
 3358            directionsDot,
 3359            startAxisProjection,
 3360            startDirectionProjection);
 3361        return TryGetFiniteAxisInterval(
 3362            queryLengthSquared,
 3363            axisLengthSquared,
 3364            startDistanceSquared,
 3365            directionsDot,
 3366            startAxisProjection,
 3367            startDirectionProjection,
 3368            expandedRadius,
 3369            maxParameter,
 3370            out entry,
 3371            out exit);
 372    }
 373
 374    internal static bool TryGetFiniteCylinderInterval(
 375        FixedRay query,
 376        Fixed64 maxParameter,
 377        Vector3d center,
 378        Vector3d axisDirection,
 379        Fixed64 axisLength,
 380        Fixed64 radius,
 381        Fixed64 radiusExpansion,
 382        Fixed64 axialExpansion,
 383        out Fixed64 entry,
 384        out Fixed64 exit,
 385        out bool originContained,
 386        out bool maximumContainedStrict)
 387    {
 5388        Signed192 queryLengthSquared = GetDirectionDot(query.Direction, query.Direction);
 5389        Signed192 axisLengthSquared = GetDot(axisDirection, Vector3d.Zero, axisDirection, Vector3d.Zero);
 5390        Signed192 startDistanceSquared = GetDot(query.Position, center, query.Position, center);
 5391        Signed192 directionsDot = GetDirectionDot(query.Direction, axisDirection);
 5392        Signed192 startAxisProjection = GetDot(query.Position, center, axisDirection, Vector3d.Zero);
 5393        Signed192 startDirectionProjection = GetDirectionDot(query.Direction, query.Position, center);
 5394        Signed192 expandedRadius = GetExpandedRadius(radius, radiusExpansion);
 5395        Signed192 squaredRadius = GetSquaredRadius(expandedRadius);
 5396        Signed320 axialExtent = GetCenteredAxialExtent(
 5397            axisLengthSquared,
 5398            axisLength,
 5399            axialExpansion);
 400
 5401        originContained = IsCenteredFiniteCylinderPointContained(
 5402            startDistanceSquared, startAxisProjection, axisLengthSquared,
 5403            squaredRadius, axialExtent, strict: false);
 5404        maximumContainedStrict = IsCenteredFiniteCylinderContainedAtParameter(
 5405            maxParameter,
 5406            expandedRadius,
 5407            queryLengthSquared,
 5408            axisLengthSquared,
 5409            startDistanceSquared,
 5410            directionsDot,
 5411            startAxisProjection,
 5412            startDirectionProjection,
 5413            axialExtent);
 414
 5415        if (!TryGetCenteredAxialInterval(
 5416                startAxisProjection,
 5417                directionsDot,
 5418                axialExtent,
 5419                maxParameter,
 5420                out RationalBound320 lower,
 5421                out RationalBound320 upper))
 422        {
 2423            entry = default;
 2424            exit = default;
 2425            return false;
 426        }
 427
 3428        return TryGetFiniteAxisInterval(
 3429            queryLengthSquared,
 3430            axisLengthSquared,
 3431            startDistanceSquared,
 3432            directionsDot,
 3433            startAxisProjection,
 3434            startDirectionProjection,
 3435            expandedRadius,
 3436            lower,
 3437            upper,
 3438            maxParameter,
 3439            out entry,
 3440            out exit);
 441    }
 442
 443    private static bool IsCapsuleContainedAtParameter(
 444        FixedRay2d query,
 445        Fixed64 parameter,
 446        FixedSegment2d axis,
 447        Signed192 radius,
 448        Signed192 queryLengthSquared,
 449        Signed192 axisLengthSquared,
 450        Signed192 startDistanceSquared,
 451        Signed192 directionsDot,
 452        Signed192 startAxisProjection,
 453        Signed192 startDirectionProjection)
 454    {
 10455        if (axisLengthSquared.IsZero)
 456        {
 5457            return IsQuadraticContained(
 5458                queryLengthSquared,
 5459                startDirectionProjection,
 5460                WideArithmetic.SubtractSigned192(startDistanceSquared, GetSquaredRadius(radius)),
 5461                parameter);
 462        }
 463
 5464        Signed320 projection = EvaluateLinear(startAxisProjection, directionsDot, parameter);
 5465        if (projection.Sign <= 0)
 466        {
 3467            return IsQuadraticContained(
 3468                queryLengthSquared,
 3469                startDirectionProjection,
 3470                WideArithmetic.SubtractSigned192(startDistanceSquared, GetSquaredRadius(radius)),
 3471                parameter);
 472        }
 473
 2474        Signed320 maximumProjection = WideArithmetic.MultiplySigned192(axisLengthSquared, ParameterScale);
 2475        if (WideArithmetic.SubtractSigned320(projection, maximumProjection).Sign >= 0)
 476        {
 1477            Signed192 endDistanceSquared = GetDot(query.Position, axis.End, query.Position, axis.End);
 1478            Signed192 endDirectionProjection = GetDirectionDot(query.Direction, query.Position, axis.End);
 1479            return IsQuadraticContained(
 1480                queryLengthSquared,
 1481                endDirectionProjection,
 1482                WideArithmetic.SubtractSigned192(endDistanceSquared, GetSquaredRadius(radius)),
 1483                parameter);
 484        }
 485
 1486        GetRadialPolynomial(
 1487            queryLengthSquared, axisLengthSquared, startDistanceSquared,
 1488            directionsDot, startAxisProjection, startDirectionProjection, radius,
 1489            out Signed320 coefficient, out Signed320 radialProjection, out Signed320 constant);
 1490        return IsQuadraticContained(coefficient, radialProjection, constant, parameter);
 491    }
 492
 493    private static bool IsCapsuleContainedAtParameter(
 494        FixedRay query,
 495        Fixed64 parameter,
 496        FixedSegment axis,
 497        Signed192 radius,
 498        Signed192 queryLengthSquared,
 499        Signed192 axisLengthSquared,
 500        Signed192 startDistanceSquared,
 501        Signed192 directionsDot,
 502        Signed192 startAxisProjection,
 503        Signed192 startDirectionProjection)
 504    {
 5505        if (axisLengthSquared.IsZero)
 506        {
 2507            return IsQuadraticContained(
 2508                queryLengthSquared,
 2509                startDirectionProjection,
 2510                WideArithmetic.SubtractSigned192(startDistanceSquared, GetSquaredRadius(radius)),
 2511                parameter);
 512        }
 513
 3514        Signed320 projection = EvaluateLinear(startAxisProjection, directionsDot, parameter);
 3515        if (projection.Sign <= 0)
 516        {
 1517            return IsQuadraticContained(
 1518                queryLengthSquared,
 1519                startDirectionProjection,
 1520                WideArithmetic.SubtractSigned192(startDistanceSquared, GetSquaredRadius(radius)),
 1521                parameter);
 522        }
 523
 2524        Signed320 maximumProjection = WideArithmetic.MultiplySigned192(axisLengthSquared, ParameterScale);
 2525        if (WideArithmetic.SubtractSigned320(projection, maximumProjection).Sign >= 0)
 526        {
 1527            Signed192 endDistanceSquared = GetDot(query.Position, axis.End, query.Position, axis.End);
 1528            Signed192 endDirectionProjection = GetDirectionDot(query.Direction, query.Position, axis.End);
 1529            return IsQuadraticContained(
 1530                queryLengthSquared,
 1531                endDirectionProjection,
 1532                WideArithmetic.SubtractSigned192(endDistanceSquared, GetSquaredRadius(radius)),
 1533                parameter);
 534        }
 535
 1536        GetRadialPolynomial(
 1537            queryLengthSquared, axisLengthSquared, startDistanceSquared,
 1538            directionsDot, startAxisProjection, startDirectionProjection, radius,
 1539            out Signed320 coefficient, out Signed320 radialProjection, out Signed320 constant);
 1540        return IsQuadraticContained(coefficient, radialProjection, constant, parameter);
 541    }
 542
 543    private static bool IsFiniteCylinderContainedAtParameter(
 544        Fixed64 parameter,
 545        Signed192 radius,
 546        Signed192 queryLengthSquared,
 547        Signed192 axisLengthSquared,
 548        Signed192 startDistanceSquared,
 549        Signed192 directionsDot,
 550        Signed192 startAxisProjection,
 551        Signed192 startDirectionProjection)
 552    {
 3553        Signed320 projection = EvaluateLinear(startAxisProjection, directionsDot, parameter);
 3554        Signed320 maximumProjection = WideArithmetic.MultiplySigned192(axisLengthSquared, ParameterScale);
 3555        int minimumSign = projection.Sign;
 3556        int maximumSign = WideArithmetic.SubtractSigned320(projection, maximumProjection).Sign;
 3557        if (minimumSign <= 0 || maximumSign >= 0)
 558        {
 2559            return false;
 560        }
 561
 1562        GetRadialPolynomial(
 1563            queryLengthSquared, axisLengthSquared, startDistanceSquared,
 1564            directionsDot, startAxisProjection, startDirectionProjection, radius,
 1565            out Signed320 coefficient, out Signed320 radialProjection, out Signed320 constant);
 1566        return IsQuadraticContained(coefficient, radialProjection, constant, parameter);
 567    }
 568
 569    private static bool IsCenteredFiniteCylinderContainedAtParameter(
 570        Fixed64 parameter,
 571        Signed192 radius,
 572        Signed192 queryLengthSquared,
 573        Signed192 axisLengthSquared,
 574        Signed192 startDistanceSquared,
 575        Signed192 directionsDot,
 576        Signed192 startAxisProjection,
 577        Signed192 startDirectionProjection,
 578        Signed320 axialExtent)
 579    {
 5580        Signed320 projection = EvaluateLinear(startAxisProjection, directionsDot, parameter);
 5581        projection = WideArithmetic.AddSigned320(projection, projection);
 5582        Signed320 minimumProjection = WideArithmetic.SubtractSigned320(default, axialExtent);
 5583        int minimumSign = WideArithmetic.SubtractSigned320(projection, minimumProjection).Sign;
 5584        int maximumSign = WideArithmetic.SubtractSigned320(projection, axialExtent).Sign;
 5585        if (minimumSign <= 0 || maximumSign >= 0)
 586        {
 4587            return false;
 588        }
 589
 1590        GetRadialPolynomial(
 1591            queryLengthSquared, axisLengthSquared, startDistanceSquared,
 1592            directionsDot, startAxisProjection, startDirectionProjection, radius,
 1593            out Signed320 coefficient, out Signed320 radialProjection, out Signed320 constant);
 1594        return IsQuadraticContained(coefficient, radialProjection, constant, parameter);
 595    }
 596
 597    private static bool IsCenteredCapsuleContainedAtParameter(
 598        FixedRay2d query,
 599        Fixed64 parameter,
 600        Vector2d center,
 601        Vector2d axisDirection,
 602        Fixed64 axisLength,
 603        Signed192 radius,
 604        Signed192 queryLengthSquared,
 605        Signed192 axisLengthSquared,
 606        Signed192 startDistanceSquared,
 607        Signed192 directionsDot,
 608        Signed192 startAxisProjection,
 609        Signed192 startDirectionProjection,
 610        Signed320 axialExtent)
 611    {
 4612        Signed320 projection = EvaluateLinear(startAxisProjection, directionsDot, parameter);
 4613        projection = WideArithmetic.AddSigned320(projection, projection);
 4614        int cap = GetCenteredCap(projection, axialExtent);
 4615        if (cap != 0)
 616        {
 3617            GetCenteredCapPolynomial(
 3618                query, center, axisDirection, axisLength, radius, cap > 0,
 3619                out Signed320 coefficient, out Signed320 capProjection, out Signed320 constant);
 3620            return IsQuadraticContained(coefficient, capProjection, constant, parameter);
 621        }
 622
 1623        GetRadialPolynomial(
 1624            queryLengthSquared, axisLengthSquared, startDistanceSquared,
 1625            directionsDot, startAxisProjection, startDirectionProjection, radius,
 1626            out Signed320 radialCoefficient, out Signed320 radialProjection, out Signed320 radialConstant);
 1627        return IsQuadraticContained(radialCoefficient, radialProjection, radialConstant, parameter);
 628    }
 629
 630    private static bool IsCenteredCapsuleContainedAtParameter(
 631        FixedRay query,
 632        Fixed64 parameter,
 633        Vector3d center,
 634        Vector3d axisDirection,
 635        Fixed64 axisLength,
 636        Signed192 radius,
 637        Signed192 queryLengthSquared,
 638        Signed192 axisLengthSquared,
 639        Signed192 startDistanceSquared,
 640        Signed192 directionsDot,
 641        Signed192 startAxisProjection,
 642        Signed192 startDirectionProjection,
 643        Signed320 axialExtent)
 644    {
 5645        Signed320 projection = EvaluateLinear(startAxisProjection, directionsDot, parameter);
 5646        projection = WideArithmetic.AddSigned320(projection, projection);
 5647        int cap = GetCenteredCap(projection, axialExtent);
 5648        if (cap != 0)
 649        {
 3650            GetCenteredCapPolynomial(
 3651                query, center, axisDirection, axisLength, radius, cap > 0,
 3652                out Signed320 coefficient, out Signed320 capProjection, out Signed320 constant);
 3653            return IsQuadraticContained(coefficient, capProjection, constant, parameter);
 654        }
 655
 2656        GetRadialPolynomial(
 2657            queryLengthSquared, axisLengthSquared, startDistanceSquared,
 2658            directionsDot, startAxisProjection, startDirectionProjection, radius,
 2659            out Signed320 radialCoefficient, out Signed320 radialProjection, out Signed320 radialConstant);
 2660        return IsQuadraticContained(radialCoefficient, radialProjection, radialConstant, parameter);
 661    }
 662
 663    private static int GetCenteredCap(Signed320 scaledProjection, Signed320 axialExtent)
 664    {
 9665        if (WideArithmetic.AddSigned320(scaledProjection, axialExtent).Sign <= 0)
 4666            return -1;
 5667        return WideArithmetic.SubtractSigned320(scaledProjection, axialExtent).Sign >= 0
 5668            ? 1
 5669            : 0;
 670    }
 671
 672    private static void MergeCenteredCapInterval(
 673        FixedRay2d query,
 674        Fixed64 maxParameter,
 675        Vector2d center,
 676        Vector2d axisDirection,
 677        Fixed64 axisLength,
 678        Signed192 radius,
 679        bool positiveCap,
 680        ref bool found,
 681        ref Fixed64 entry,
 682        ref Fixed64 exit)
 683    {
 8684        GetCenteredCapPolynomial(
 8685            query, center, axisDirection, axisLength, radius, positiveCap,
 8686            out Signed320 coefficient, out Signed320 projection, out Signed320 constant);
 8687        RationalBound320 maximum = GetMaximumBound320(maxParameter);
 8688        Signed320 one = Scale320;
 8689        Merge(
 8690            TrySolveBoundedQuadratic(
 8691                coefficient, projection, constant,
 8692                new RationalBound320(default, one), maximum, maxParameter,
 8693                out Fixed64 capEntry, out Fixed64 capExit),
 8694            capEntry, capExit, ref found, ref entry, ref exit);
 8695    }
 696
 697    private static void MergeCenteredCapInterval(
 698        FixedRay query,
 699        Fixed64 maxParameter,
 700        Vector3d center,
 701        Vector3d axisDirection,
 702        Fixed64 axisLength,
 703        Signed192 radius,
 704        bool positiveCap,
 705        ref bool found,
 706        ref Fixed64 entry,
 707        ref Fixed64 exit)
 708    {
 10709        GetCenteredCapPolynomial(
 10710            query, center, axisDirection, axisLength, radius, positiveCap,
 10711            out Signed320 coefficient, out Signed320 projection, out Signed320 constant);
 10712        RationalBound320 maximum = GetMaximumBound320(maxParameter);
 10713        Signed320 one = Scale320;
 10714        Merge(
 10715            TrySolveBoundedQuadratic(
 10716                coefficient, projection, constant,
 10717                new RationalBound320(default, one), maximum, maxParameter,
 10718                out Fixed64 capEntry, out Fixed64 capExit),
 10719            capEntry, capExit, ref found, ref entry, ref exit);
 10720    }
 721
 722    private static void GetCenteredCapPolynomial(
 723        FixedRay2d query,
 724        Vector2d center,
 725        Vector2d axisDirection,
 726        Fixed64 axisLength,
 727        Signed192 radius,
 728        bool positiveCap,
 729        out Signed320 coefficient,
 730        out Signed320 projection,
 731        out Signed320 constant)
 732    {
 11733        Signed192 x = GetCenteredCapOffset(
 11734            query.Position.X, center.X, axisDirection.X, axisLength, positiveCap);
 11735        Signed192 y = GetCenteredCapOffset(
 11736            query.Position.Y, center.Y, axisDirection.Y, axisLength, positiveCap);
 11737        Signed192 velocityX = ScaleByCenteredAxis(
 11738            Signed192.Signed(query.Direction.X.m_rawValue));
 11739        Signed192 velocityY = ScaleByCenteredAxis(
 11740            Signed192.Signed(query.Direction.Y.m_rawValue));
 11741        Signed192 scaledRadius = ScaleByCenteredAxis(radius);
 11742        coefficient = WideArithmetic.AddProducts(velocityX, velocityX, velocityY, velocityY);
 11743        projection = WideArithmetic.AddProducts(x, velocityX, y, velocityY);
 11744        constant = WideArithmetic.SubtractSigned320(
 11745            WideArithmetic.AddProducts(x, x, y, y),
 11746            WideArithmetic.MultiplySigned192(scaledRadius, scaledRadius));
 11747    }
 748
 749    private static void GetCenteredCapPolynomial(
 750        FixedRay query,
 751        Vector3d center,
 752        Vector3d axisDirection,
 753        Fixed64 axisLength,
 754        Signed192 radius,
 755        bool positiveCap,
 756        out Signed320 coefficient,
 757        out Signed320 projection,
 758        out Signed320 constant)
 759    {
 13760        Signed192 x = GetCenteredCapOffset(
 13761            query.Position.X, center.X, axisDirection.X, axisLength, positiveCap);
 13762        Signed192 y = GetCenteredCapOffset(
 13763            query.Position.Y, center.Y, axisDirection.Y, axisLength, positiveCap);
 13764        Signed192 z = GetCenteredCapOffset(
 13765            query.Position.Z, center.Z, axisDirection.Z, axisLength, positiveCap);
 13766        Signed192 velocityX = ScaleByCenteredAxis(
 13767            Signed192.Signed(query.Direction.X.m_rawValue));
 13768        Signed192 velocityY = ScaleByCenteredAxis(
 13769            Signed192.Signed(query.Direction.Y.m_rawValue));
 13770        Signed192 velocityZ = ScaleByCenteredAxis(
 13771            Signed192.Signed(query.Direction.Z.m_rawValue));
 13772        Signed192 scaledRadius = ScaleByCenteredAxis(radius);
 13773        coefficient = WideArithmetic.AddProducts(
 13774            velocityX, velocityX, velocityY, velocityY, velocityZ, velocityZ);
 13775        projection = WideArithmetic.AddProducts(x, velocityX, y, velocityY, z, velocityZ);
 13776        constant = WideArithmetic.SubtractSigned320(
 13777            WideArithmetic.AddProducts(x, x, y, y, z, z),
 13778            WideArithmetic.MultiplySigned192(scaledRadius, scaledRadius));
 13779    }
 780
 781    private static Signed320 EvaluateLinear(
 782        Signed192 constant,
 783        Signed192 velocity,
 784        Fixed64 parameter) =>
 25785        WideArithmetic.AddSigned320(
 25786            WideArithmetic.MultiplySigned192(constant, ParameterScale),
 25787            WideArithmetic.MultiplySigned192(
 25788                velocity,
 25789                Signed192.Signed(parameter.m_rawValue)));
 790
 791    private static void GetRadialPolynomial(
 792        Signed192 queryLengthSquared,
 793        Signed192 axisLengthSquared,
 794        Signed192 startDistanceSquared,
 795        Signed192 directionsDot,
 796        Signed192 startAxisProjection,
 797        Signed192 startDirectionProjection,
 798        Signed192 radius,
 799        out Signed320 coefficient,
 800        out Signed320 projection,
 801        out Signed320 constant)
 802    {
 7803        coefficient = WideArithmetic.MultiplySubtract(
 7804            queryLengthSquared, axisLengthSquared, directionsDot, directionsDot);
 7805        projection = WideArithmetic.MultiplySubtract(
 7806            startDirectionProjection, axisLengthSquared, startAxisProjection, directionsDot);
 7807        constant = GetRadialConstant(
 7808            startDistanceSquared,
 7809            startAxisProjection,
 7810            axisLengthSquared,
 7811            GetSquaredRadius(radius));
 7812    }
 813
 814    private static bool IsQuadraticContained(
 815        Signed192 coefficient,
 816        Signed192 projection,
 817        Signed192 constant,
 818        Fixed64 parameter) =>
 13819        IsQuadraticContained(
 13820            Signed320.ExtendValue(coefficient),
 13821            Signed320.ExtendValue(projection),
 13822            Signed320.ExtendValue(constant),
 13823            parameter);
 824
 825    private static bool IsQuadraticContained(
 826        Signed320 coefficient,
 827        Signed320 projection,
 828        Signed320 constant,
 829        Fixed64 parameter)
 830    {
 26831        Signed320 numerator = Signed320.ExtendValue(
 26832            Signed192.Signed(parameter.m_rawValue));
 26833        Signed320 denominator = Signed320.ExtendValue(ParameterScale);
 26834        int sign = EvaluatePolynomial(
 26835            coefficient,
 26836            projection,
 26837            constant,
 26838            numerator,
 26839            denominator).Sign;
 26840        return sign < 0;
 841    }
 842
 843    private static bool TryGetCircleInterval(
 844        Vector2d position,
 845        Vector2d direction,
 846        Vector2d center,
 847        Signed192 radius,
 848        Fixed64 maxParameter,
 849        out Fixed64 entry,
 850        out Fixed64 exit) =>
 15851        WideRayIntersection.TrySolveInterval(
 15852            GetDirectionDot(direction, direction),
 15853            GetDirectionDot(direction, position, center),
 15854            WideArithmetic.SubtractSigned192(
 15855                GetDot(position, center, position, center),
 15856                GetSquaredRadius(radius)),
 15857            maxParameter,
 15858            out entry,
 15859            out exit);
 860
 861    private static bool TryGetSphereInterval(
 862        Vector3d position,
 863        Vector3d direction,
 864        Vector3d center,
 865        Signed192 radius,
 866        Fixed64 maxParameter,
 867        out Fixed64 entry,
 868        out Fixed64 exit) =>
 8869        WideRayIntersection.TrySolveInterval(
 8870            GetDirectionDot(direction, direction),
 8871            GetDirectionDot(direction, position, center),
 8872            WideArithmetic.SubtractSigned192(
 8873                GetDot(position, center, position, center),
 8874                GetSquaredRadius(radius)),
 8875            maxParameter,
 8876            out entry,
 8877            out exit);
 878
 879    private static Signed192 GetDirectionDot(Vector2d left, Vector2d right) =>
 35880        GetDot(left, Vector2d.Zero, right, Vector2d.Zero);
 881
 882    private static Signed192 GetDirectionDot(
 883        Vector2d direction,
 884        Vector2d point,
 885        Vector2d origin) =>
 42886        GetDot(direction, Vector2d.Zero, point, origin);
 887
 888    private static Signed192 GetDirectionDot(Vector3d left, Vector3d right) =>
 48889        GetDot(left, Vector3d.Zero, right, Vector3d.Zero);
 890
 891    private static Signed192 GetDirectionDot(
 892        Vector3d direction,
 893        Vector3d point,
 894        Vector3d origin) =>
 42895        GetDot(direction, Vector3d.Zero, point, origin);
 896}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.RigidPointRelation.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.RigidPointRelation.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
 8namespace FixedMathSharp.Geometry;
 9
 10/// <content>
 11/// Computes high-precision point-to-axis relations (projection, radial distance, and
 12/// associated denominators) for a point expressed in the local space of a rotated rigid frame.
 13/// </content>
 14internal static partial class WideFiniteAxisIntersection
 15{
 16    #region Nested Types
 17
 18    private readonly struct RigidLocalPointRelation
 19    {
 20        internal readonly Signed192 X;
 21        internal readonly Signed192 Y;
 22        internal readonly Signed192 Z;
 23        internal readonly Signed192 Denominator;
 24        internal readonly Signed192 AxisSquared;
 25        internal readonly Signed320 Projection;
 26        internal readonly Signed576 RadialNumerator;
 27        internal readonly Signed320 RadialDenominator;
 28
 29        internal RigidLocalPointRelation(
 30            Signed192 x,
 31            Signed192 y,
 32            Signed192 z,
 33            Signed192 denominator,
 34            Signed192 axisSquared,
 35            Signed320 projection,
 36            Signed576 radialNumerator,
 37            Signed320 radialDenominator)
 38        {
 15139            X = x;
 15140            Y = y;
 15141            Z = z;
 15142            Denominator = denominator;
 15143            AxisSquared = axisSquared;
 15144            Projection = projection;
 15145            RadialNumerator = radialNumerator;
 15146            RadialDenominator = radialDenominator;
 15147        }
 48    }
 49
 50    #endregion
 51
 52    private static void GetRigidLocalPointRelation(
 53        Vector3d point,
 54        Vector3d center,
 55        FixedQuaternion frameRotation,
 56        Vector3d localAxisDirection,
 57        out RigidLocalPointRelation relation)
 58    {
 15159        WideOrientedBox.GetRelativeLocalPointNumerators(
 15160            point,
 15161            center,
 15162            frameRotation,
 15163            out Signed192 x,
 15164            out Signed192 y,
 15165            out Signed192 z,
 15166            out Signed192 denominator);
 15167        Signed192 axisSquared = GetDot(
 15168            localAxisDirection,
 15169            Vector3d.Zero,
 15170            localAxisDirection,
 15171            Vector3d.Zero);
 15172        Signed320 projection = GetProjection(
 15173            x,
 15174            y,
 15175            z,
 15176            localAxisDirection);
 15177        Signed320 squaredDistance = WideArithmetic.AddSigned320(
 15178            WideArithmetic.AddSigned320(
 15179                WideArithmetic.MultiplySigned192(x, x),
 15180                WideArithmetic.MultiplySigned192(y, y)),
 15181            WideArithmetic.MultiplySigned192(z, z));
 15182        Signed576 radialNumerator = WideArithmetic.SubtractSigned576(
 15183            WideArithmetic.MultiplySigned320(
 15184                squaredDistance,
 15185                Signed320.ExtendValue(axisSquared)),
 15186            WideArithmetic.MultiplySigned320(
 15187                projection,
 15188                projection));
 15189        Signed320 denominatorSquared = WideArithmetic.MultiplySigned192(
 15190            denominator,
 15191            denominator);
 15192        Signed576 wideRadialDenominator = WideArithmetic.MultiplySigned320(
 15193            denominatorSquared,
 15194            Signed320.ExtendValue(axisSquared));
 15195        _ = Signed320.TryNarrowSigned(
 15196            wideRadialDenominator,
 15197            out Signed320 radialDenominator);
 15198        relation = new RigidLocalPointRelation(
 15199            x,
 151100            y,
 151101            z,
 151102            denominator,
 151103            axisSquared,
 151104            projection,
 151105            radialNumerator,
 151106            radialDenominator);
 151107    }
 108}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.RootSolver.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.RootSolver.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
 8namespace FixedMathSharp.Geometry;
 9
 10/// <content>
 11/// Root-solving helpers for the finite-axis intersection quadratic:
 12/// rounds candidate roots to exact fixed-point precision and evaluates
 13/// the polynomial/derivative using wide integer arithmetic to determine
 14/// correct rounding direction near the roots.
 15/// </content>
 16internal static partial class WideFiniteAxisIntersection
 17{
 18    private static Fixed64 RoundLowerRoot(
 19        Signed320 radialCoefficient,
 20        Signed320 radialProjection,
 21        Signed320 radialConstant,
 22        Signed320 scaledSquareRoot)
 23    {
 14824        Signed320 scaledCoefficient = ShiftLeftByFixed64FractionalBits(radialCoefficient);
 14825        Signed320 negativeScaledProjection = WideArithmetic.SubtractSigned320(
 14826            default,
 14827            ShiftLeftByFixed64FractionalBits(radialProjection));
 14828        Signed320 numerator = WideArithmetic.SubtractSigned320(
 14829            negativeScaledProjection,
 14830            scaledSquareRoot);
 14831        Fixed64 candidate = Fixed64.GetSignedRatio(numerator, scaledCoefficient);
 32
 14833        long upperRaw = candidate.m_rawValue;
 14834        if (upperRaw == 0L)
 235            return Fixed64.Zero;
 36
 14637        long lowerRaw = upperRaw - 1L;
 14638        Signed192 midpoint = Signed192.Signed((upperRaw * 2L) - 1L);
 14639        Signed576 value = EvaluatePolynomial(
 14640            radialCoefficient,
 14641            radialProjection,
 14642            radialConstant,
 14643            midpoint,
 14644            DoubleParameterScale);
 14645        if (value.IsZero)
 146            return candidate;
 47
 48        // The upward-biased lower seed differs from the exact root by less than
 49        // 1 / A, so this midpoint cannot cross the vertex before correction.
 14550        return Fixed64.FromRaw(value.Sign > 0
 14551            ? upperRaw
 14552            : lowerRaw);
 53    }
 54
 55    private static Fixed64 RoundUpperRoot(
 56        Signed320 radialCoefficient,
 57        Signed320 radialProjection,
 58        Signed320 radialConstant,
 59        Signed320 scaledSquareRoot,
 60        Fixed64 maxParameter)
 61    {
 14862        Signed320 scaledCoefficient = ShiftLeftByFixed64FractionalBits(radialCoefficient);
 14863        Signed320 negativeScaledProjection = WideArithmetic.SubtractSigned320(
 14864            default,
 14865            ShiftLeftByFixed64FractionalBits(radialProjection));
 14866        Signed320 numerator = WideArithmetic.AddSigned320(
 14867            negativeScaledProjection,
 14868            scaledSquareRoot);
 14869        Fixed64 candidate = Fixed64.GetSignedRatio(numerator, scaledCoefficient);
 70
 14871        long lowerRaw = candidate.m_rawValue;
 14872        if (lowerRaw == maxParameter.m_rawValue)
 273            return maxParameter;
 74
 14675        long upperRaw = lowerRaw + 1L;
 14676        Signed192 midpoint = Signed192.Signed((lowerRaw * 2L) + 1L);
 14677        Signed576 value = EvaluatePolynomial(
 14678            radialCoefficient,
 14679            radialProjection,
 14680            radialConstant,
 14681            midpoint,
 14682            DoubleParameterScale);
 14683        if (value.IsZero)
 184            return candidate;
 85
 86        // The downward-biased upper seed differs from the exact root by less
 87        // than 1 / A, so this midpoint cannot cross the vertex before correction.
 14588        return Fixed64.FromRaw(value.Sign <= 0
 14589            ? upperRaw
 14590            : lowerRaw);
 91    }
 92
 93    private static Signed320 ShiftLeftByFixed64FractionalBits(Signed320 value) =>
 59294        new(
 59295            (value.Word4 << FixedMath.SHIFT_AMOUNT_I) | (value.Word3 >> FixedMath.SHIFT_AMOUNT_I),
 59296            (value.Word3 << FixedMath.SHIFT_AMOUNT_I) | (value.Word2 >> FixedMath.SHIFT_AMOUNT_I),
 59297            (value.Word2 << FixedMath.SHIFT_AMOUNT_I) | (value.Word1 >> FixedMath.SHIFT_AMOUNT_I),
 59298            (value.Word1 << FixedMath.SHIFT_AMOUNT_I) | (value.Word0 >> FixedMath.SHIFT_AMOUNT_I),
 59299            value.Word0 << FixedMath.SHIFT_AMOUNT_I);
 100
 101    private static Signed576 EvaluatePolynomial(
 102        Signed320 radialCoefficient,
 103        Signed320 radialProjection,
 104        Signed320 radialConstant,
 105        Signed192 numerator,
 106        Signed192 denominator)
 107    {
 400108        Signed320 numeratorSquared = WideArithmetic.MultiplySigned192(numerator, numerator);
 400109        Signed320 numeratorDenominator = WideArithmetic.MultiplySigned192(numerator, denominator);
 400110        Signed320 denominatorSquared = WideArithmetic.MultiplySigned192(denominator, denominator);
 400111        Signed576 first = WideArithmetic.MultiplySigned320(radialCoefficient, numeratorSquared);
 400112        Signed576 second = WideArithmetic.MultiplySigned320(radialProjection, numeratorDenominator);
 400113        Signed576 third = WideArithmetic.MultiplySigned320(radialConstant, denominatorSquared);
 400114        return WideArithmetic.AddSigned576(
 400115            WideArithmetic.AddSigned576(
 400116                first,
 400117                WideArithmetic.AddSigned576(second, second)),
 400118            third);
 119    }
 120
 121    private static Signed576 EvaluateDerivative(
 122        Signed320 radialCoefficient,
 123        Signed320 radialProjection,
 124        Signed192 numerator,
 125        Signed192 denominator) =>
 108126        WideArithmetic.AddSigned576(
 108127            WideArithmetic.MultiplySigned320(
 108128                radialCoefficient,
 108129                Signed320.ExtendValue(numerator)),
 108130            WideArithmetic.MultiplySigned320(
 108131                radialProjection,
 108132                Signed320.ExtendValue(denominator)));
 133
 134    private static Signed704 EvaluatePolynomial(
 135        Signed320 radialCoefficient,
 136        Signed320 radialProjection,
 137        Signed320 radialConstant,
 138        Signed320 numerator,
 139        Signed320 denominator)
 140    {
 61122141        Signed704 first = WideArithmetic.MultiplySigned320(radialCoefficient, numerator, numerator);
 61122142        Signed704 second = WideArithmetic.MultiplySigned320(radialProjection, numerator, denominator);
 61122143        Signed704 third = WideArithmetic.MultiplySigned320(radialConstant, denominator, denominator);
 61122144        return WideArithmetic.AddSigned704(
 61122145            WideArithmetic.AddSigned704(
 61122146                first,
 61122147                WideArithmetic.AddSigned704(second, second)),
 61122148            third);
 149    }
 150
 151    private static Signed576 EvaluateDerivative(
 152        Signed320 radialCoefficient,
 153        Signed320 radialProjection,
 154        Signed320 numerator,
 155        Signed320 denominator) =>
 41142156        WideArithmetic.AddSigned576(
 41142157            WideArithmetic.MultiplySigned320(radialCoefficient, numerator),
 41142158            WideArithmetic.MultiplySigned320(radialProjection, denominator));
 159}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.RoundedBox.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.RoundedBox.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>
 13/// Provides segment-vs-rounded-box intersection tests by computing the first distance
 14/// at which a spherically expanded query segment reaches an axis-aligned bounding box,
 15/// using per-axis breakpoints to evaluate closest-feature distance across intervals.
 16/// </content>
 17internal static partial class WideFiniteAxisIntersection
 18{
 19    private const int BoxAxisCount = 3;
 20    private const int MaximumBoxBreakpointCount = BoxAxisCount * 2;
 21
 22    #region Nested Types
 23
 24    private readonly struct BoxBreakpoint
 25    {
 26        internal readonly RationalBound320 Parameter;
 27        internal readonly byte Axis;
 28        internal readonly sbyte StateAfter;
 29
 30        internal BoxBreakpoint(RationalBound320 parameter, byte axis, sbyte stateAfter)
 31        {
 9432            Parameter = parameter;
 9433            Axis = axis;
 9434            StateAfter = stateAfter;
 9435        }
 36    }
 37
 38    #endregion
 39
 40    internal static bool TryGetSphericallyExpandedBoxFirstDistance(
 41        FixedSegment query,
 42        FixedBoundBox box,
 43        Fixed64 sphericalExpansion,
 44        Fixed64 segmentLength,
 45        out Fixed64 distance)
 46    {
 1447        distance = default;
 1448        if (box.Intersects(new FixedBoundSphere(query.Start, sphericalExpansion)))
 149            return true;
 1350        if (query.Start == query.End)
 151            return false;
 52
 53        // The closest box feature is fixed between coordinate-boundary
 54        // crossings, so squared distance is one quadratic per interval.
 1255        Span<BoxBreakpoint> breakpoints = stackalloc BoxBreakpoint[MaximumBoxBreakpointCount];
 1256        int breakpointCount = 0;
 1257        Span<sbyte> axisStates = stackalloc sbyte[BoxAxisCount];
 1258        AddAxisBreakpoints(
 1259            query.Start.X, query.End.X, box.Min.X, box.Max.X, 0,
 1260            breakpoints, ref breakpointCount, out axisStates[0]);
 1261        AddAxisBreakpoints(
 1262            query.Start.Y, query.End.Y, box.Min.Y, box.Max.Y, 1,
 1263            breakpoints, ref breakpointCount, out axisStates[1]);
 1264        AddAxisBreakpoints(
 1265            query.Start.Z, query.End.Z, box.Min.Z, box.Max.Z, 2,
 1266            breakpoints, ref breakpointCount, out axisStates[2]);
 1267        SortBreakpoints(breakpoints, breakpointCount);
 68
 1269        Signed320 unit = Scale320;
 1270        RationalBound320 lower = new(default, unit);
 1271        RationalBound320 maximum = new(unit, unit);
 1272        int breakpointIndex = 0;
 273        while (true)
 74        {
 1475            RationalBound320 upper = breakpointIndex < breakpointCount
 1476                ? breakpoints[breakpointIndex].Parameter
 1477                : maximum;
 1478            GetBoxDistancePolynomial(
 1479                query,
 1480                box,
 1481                axisStates,
 1482                sphericalExpansion,
 1483                out Signed320 coefficient,
 1484                out Signed320 projection,
 1485                out Signed320 constant);
 1486            if (TrySolveBoundedQuadraticAtDistance(
 1487                    coefficient,
 1488                    projection,
 1489                    constant,
 1490                    lower,
 1491                    upper,
 1492                    segmentLength,
 1493                    out distance,
 1494                    out _))
 95            {
 1096                return true;
 97            }
 98
 499            if (breakpointIndex == breakpointCount)
 2100                return false;
 101
 102            do
 103            {
 2104                BoxBreakpoint breakpoint = breakpoints[breakpointIndex++];
 2105                axisStates[breakpoint.Axis] = breakpoint.StateAfter;
 106            }
 2107            while (breakpointIndex < breakpointCount
 2108                && Compare(breakpoints[breakpointIndex].Parameter, upper) == 0);
 2109            lower = upper;
 110        }
 111    }
 112
 113    internal static bool TryGetSphericallyExpandedProjectedBoxFirstDistance(
 114        Signed192 startX,
 115        Signed192 startY,
 116        Signed192 startZ,
 117        Signed192 endX,
 118        Signed192 endY,
 119        Signed192 endZ,
 120        Signed192 extentX,
 121        Signed192 extentY,
 122        Signed192 extentZ,
 123        Signed192 projectionDenominator,
 124        Fixed64 sphericalExpansion,
 125        Fixed64 segmentLength,
 126        out Fixed64 distance)
 127    {
 47128        distance = default;
 129        // A nonnegative Fixed64 radius scaled by a normalized quaternion-basis
 130        // denominator uses at most 127 signed bits.
 47131        Signed192 radiusNumerator = Signed192.NarrowValue(
 47132            WideArithmetic.MultiplySigned192(
 47133                Signed192.Signed(sphericalExpansion.m_rawValue),
 47134                projectionDenominator));
 47135        if (IsWithinProjectedRoundedBox(
 47136                startX,
 47137                startY,
 47138                startZ,
 47139                extentX,
 47140                extentY,
 47141                extentZ,
 47142                radiusNumerator))
 143        {
 1144            return true;
 145        }
 146
 46147        if (WideArithmetic.SubtractSigned192(endX, startX).IsZero
 46148            && WideArithmetic.SubtractSigned192(endY, startY).IsZero
 46149            && WideArithmetic.SubtractSigned192(endZ, startZ).IsZero)
 1150            return false;
 151
 45152        Span<BoxBreakpoint> breakpoints = stackalloc BoxBreakpoint[MaximumBoxBreakpointCount];
 45153        int breakpointCount = 0;
 45154        Span<sbyte> axisStates = stackalloc sbyte[BoxAxisCount];
 45155        AddProjectedAxisBreakpoints(
 45156            startX, endX, extentX, 0,
 45157            breakpoints, ref breakpointCount, out axisStates[0]);
 45158        AddProjectedAxisBreakpoints(
 45159            startY, endY, extentY, 1,
 45160            breakpoints, ref breakpointCount, out axisStates[1]);
 45161        AddProjectedAxisBreakpoints(
 45162            startZ, endZ, extentZ, 2,
 45163            breakpoints, ref breakpointCount, out axisStates[2]);
 45164        SortBreakpoints(breakpoints, breakpointCount);
 165
 45166        Signed320 unit = Scale320;
 45167        RationalBound320 lower = new(default, unit);
 45168        RationalBound320 maximum = new(unit, unit);
 45169        int breakpointIndex = 0;
 3170        while (true)
 171        {
 48172            RationalBound320 upper = breakpointIndex < breakpointCount
 48173                ? breakpoints[breakpointIndex].Parameter
 48174                : maximum;
 48175            GetProjectedBoxDistancePolynomial(
 48176                startX,
 48177                startY,
 48178                startZ,
 48179                endX,
 48180                endY,
 48181                endZ,
 48182                extentX,
 48183                extentY,
 48184                extentZ,
 48185                axisStates,
 48186                radiusNumerator,
 48187                out Signed320 coefficient,
 48188                out Signed320 projection,
 48189                out Signed320 constant);
 48190            if (TrySolveBoundedQuadraticAtDistance(
 48191                    coefficient,
 48192                    projection,
 48193                    constant,
 48194                    lower,
 48195                    upper,
 48196                    segmentLength,
 48197                    out distance,
 48198                    out _))
 199            {
 40200                return true;
 201            }
 202
 8203            if (breakpointIndex == breakpointCount)
 5204                return false;
 205
 206            do
 207            {
 3208                BoxBreakpoint breakpoint = breakpoints[breakpointIndex++];
 3209                axisStates[breakpoint.Axis] = breakpoint.StateAfter;
 210            }
 3211            while (breakpointIndex < breakpointCount
 3212                && Compare(breakpoints[breakpointIndex].Parameter, upper) == 0);
 3213            lower = upper;
 214        }
 215    }
 216
 217    private static void AddAxisBreakpoints(
 218        Fixed64 start,
 219        Fixed64 end,
 220        Fixed64 minimum,
 221        Fixed64 maximum,
 222        byte axis,
 223        Span<BoxBreakpoint> breakpoints,
 224        ref int count,
 225        out sbyte initialState)
 226    {
 36227        Signed192 direction = WideArithmetic.Difference(end, start);
 36228        initialState = start < minimum || (start == minimum && direction.Sign < 0)
 36229            ? (sbyte)-1
 36230            : start > maximum || (start == maximum && direction.Sign > 0)
 36231                ? (sbyte)1
 36232                : (sbyte)0;
 36233        if (direction.Sign > 0)
 234        {
 2235            AddBreakpoint(start, minimum, direction, axis, 0, breakpoints, ref count);
 2236            AddBreakpoint(start, maximum, direction, axis, 1, breakpoints, ref count);
 237        }
 34238        else if (direction.Sign < 0)
 239        {
 13240            AddBreakpoint(start, maximum, direction, axis, 0, breakpoints, ref count);
 13241            AddBreakpoint(start, minimum, direction, axis, -1, breakpoints, ref count);
 242        }
 34243    }
 244
 245    private static void AddProjectedAxisBreakpoints(
 246        Signed192 start,
 247        Signed192 end,
 248        Signed192 extent,
 249        byte axis,
 250        Span<BoxBreakpoint> breakpoints,
 251        ref int count,
 252        out sbyte initialState)
 253    {
 135254        Signed192 minimum = WideArithmetic.SubtractSigned192(default, extent);
 135255        Signed192 direction = WideArithmetic.SubtractSigned192(end, start);
 135256        int minimumComparison = WideArithmetic.SubtractSigned192(start, minimum).Sign;
 135257        int maximumComparison = WideArithmetic.SubtractSigned192(start, extent).Sign;
 135258        initialState = minimumComparison < 0
 135259            || (minimumComparison == 0 && direction.Sign < 0)
 135260                ? (sbyte)-1
 135261                : maximumComparison > 0
 135262                    || (maximumComparison == 0 && direction.Sign > 0)
 135263                        ? (sbyte)1
 135264                        : (sbyte)0;
 135265        if (direction.Sign > 0)
 266        {
 12267            AddProjectedBreakpoint(
 12268                start, minimum, direction, axis, 0, breakpoints, ref count);
 12269            AddProjectedBreakpoint(
 12270                start, extent, direction, axis, 1, breakpoints, ref count);
 271        }
 123272        else if (direction.Sign < 0)
 273        {
 113274            AddProjectedBreakpoint(
 113275                start, extent, direction, axis, 0, breakpoints, ref count);
 113276            AddProjectedBreakpoint(
 113277                start, minimum, direction, axis, -1, breakpoints, ref count);
 278        }
 123279    }
 280
 281    private static void AddBreakpoint(
 282        Fixed64 start,
 283        Fixed64 boundary,
 284        Signed192 direction,
 285        byte axis,
 286        sbyte stateAfter,
 287        Span<BoxBreakpoint> breakpoints,
 288        ref int count)
 289    {
 30290        RationalBound320 parameter = Normalize(
 30291            Signed320.ExtendValue(WideArithmetic.Difference(boundary, start)),
 30292            Signed320.ExtendValue(direction));
 30293        Signed320 unit = Scale320;
 30294        if (parameter.Numerator.Sign <= 0
 30295            || Compare(parameter, new RationalBound320(unit, unit)) >= 0)
 296        {
 19297            return;
 298        }
 299
 11300        breakpoints[count++] = new BoxBreakpoint(parameter, axis, stateAfter);
 11301    }
 302
 303    private static void AddProjectedBreakpoint(
 304        Signed192 start,
 305        Signed192 boundary,
 306        Signed192 direction,
 307        byte axis,
 308        sbyte stateAfter,
 309        Span<BoxBreakpoint> breakpoints,
 310        ref int count)
 311    {
 250312        RationalBound320 parameter = Normalize(
 250313            Signed320.ExtendValue(
 250314                WideArithmetic.SubtractSigned192(boundary, start)),
 250315            Signed320.ExtendValue(direction));
 250316        Signed320 unit = Scale320;
 250317        if (parameter.Numerator.Sign <= 0
 250318            || Compare(parameter, new RationalBound320(unit, unit)) >= 0)
 319        {
 167320            return;
 321        }
 322
 83323        breakpoints[count++] = new BoxBreakpoint(parameter, axis, stateAfter);
 83324    }
 325
 326    private static void SortBreakpoints(Span<BoxBreakpoint> breakpoints, int count)
 327    {
 204328        for (int index = 1; index < count; index++)
 329        {
 45330            BoxBreakpoint current = breakpoints[index];
 45331            int insertion = index;
 85332            while (insertion > 0
 85333                && Compare(breakpoints[insertion - 1].Parameter, current.Parameter) > 0)
 334            {
 40335                breakpoints[insertion] = breakpoints[insertion - 1];
 40336                insertion--;
 337            }
 338
 45339            breakpoints[insertion] = current;
 340        }
 57341    }
 342
 343    private static void GetBoxDistancePolynomial(
 344        FixedSegment query,
 345        FixedBoundBox box,
 346        Span<sbyte> axisStates,
 347        Fixed64 sphericalExpansion,
 348        out Signed320 coefficient,
 349        out Signed320 projection,
 350        out Signed320 constant)
 351    {
 14352        coefficient = default;
 14353        projection = default;
 14354        Signed192 radius = Signed192.Signed(sphericalExpansion.m_rawValue);
 14355        constant = WideArithmetic.SubtractSigned320(
 14356            default,
 14357            WideArithmetic.MultiplySigned192(radius, radius));
 358
 14359        AddBoxAxisPolynomial(
 14360            query.Start.X, query.End.X, box.Min.X, box.Max.X, axisStates[0],
 14361            ref coefficient, ref projection, ref constant);
 14362        AddBoxAxisPolynomial(
 14363            query.Start.Y, query.End.Y, box.Min.Y, box.Max.Y, axisStates[1],
 14364            ref coefficient, ref projection, ref constant);
 14365        AddBoxAxisPolynomial(
 14366            query.Start.Z, query.End.Z, box.Min.Z, box.Max.Z, axisStates[2],
 14367            ref coefficient, ref projection, ref constant);
 14368    }
 369
 370    private static void GetProjectedBoxDistancePolynomial(
 371        Signed192 startX,
 372        Signed192 startY,
 373        Signed192 startZ,
 374        Signed192 endX,
 375        Signed192 endY,
 376        Signed192 endZ,
 377        Signed192 extentX,
 378        Signed192 extentY,
 379        Signed192 extentZ,
 380        Span<sbyte> axisStates,
 381        Signed192 radiusNumerator,
 382        out Signed320 coefficient,
 383        out Signed320 projection,
 384        out Signed320 constant)
 385    {
 48386        coefficient = default;
 48387        projection = default;
 48388        constant = WideArithmetic.SubtractSigned320(
 48389            default,
 48390            WideArithmetic.MultiplySigned192(radiusNumerator, radiusNumerator));
 391
 48392        AddProjectedBoxAxisPolynomial(
 48393            startX, endX, extentX, axisStates[0],
 48394            ref coefficient, ref projection, ref constant);
 48395        AddProjectedBoxAxisPolynomial(
 48396            startY, endY, extentY, axisStates[1],
 48397            ref coefficient, ref projection, ref constant);
 48398        AddProjectedBoxAxisPolynomial(
 48399            startZ, endZ, extentZ, axisStates[2],
 48400            ref coefficient, ref projection, ref constant);
 48401    }
 402
 403    private static void AddBoxAxisPolynomial(
 404        Fixed64 start,
 405        Fixed64 end,
 406        Fixed64 minimum,
 407        Fixed64 maximum,
 408        sbyte state,
 409        ref Signed320 coefficient,
 410        ref Signed320 projection,
 411        ref Signed320 constant)
 412    {
 42413        if (state == 0)
 18414            return;
 415
 24416        Signed192 direction = WideArithmetic.Difference(end, start);
 24417        Signed192 offset = WideArithmetic.Difference(start, state < 0 ? minimum : maximum);
 24418        coefficient = WideArithmetic.AddSigned320(
 24419            coefficient,
 24420            WideArithmetic.MultiplySigned192(direction, direction));
 24421        projection = WideArithmetic.AddSigned320(
 24422            projection,
 24423            WideArithmetic.MultiplySigned192(offset, direction));
 24424        constant = WideArithmetic.AddSigned320(
 24425            constant,
 24426            WideArithmetic.MultiplySigned192(offset, offset));
 24427    }
 428
 429    private static void AddProjectedBoxAxisPolynomial(
 430        Signed192 start,
 431        Signed192 end,
 432        Signed192 extent,
 433        sbyte state,
 434        ref Signed320 coefficient,
 435        ref Signed320 projection,
 436        ref Signed320 constant)
 437    {
 144438        if (state == 0)
 51439            return;
 440
 93441        Signed192 direction = WideArithmetic.SubtractSigned192(end, start);
 93442        Signed192 boundary = state < 0
 93443            ? WideArithmetic.SubtractSigned192(default, extent)
 93444            : extent;
 93445        Signed192 offset = WideArithmetic.SubtractSigned192(start, boundary);
 93446        coefficient = WideArithmetic.AddSigned320(
 93447            coefficient,
 93448            WideArithmetic.MultiplySigned192(direction, direction));
 93449        projection = WideArithmetic.AddSigned320(
 93450            projection,
 93451            WideArithmetic.MultiplySigned192(offset, direction));
 93452        constant = WideArithmetic.AddSigned320(
 93453            constant,
 93454            WideArithmetic.MultiplySigned192(offset, offset));
 93455    }
 456
 457    private static bool IsWithinProjectedRoundedBox(
 458        Signed192 x,
 459        Signed192 y,
 460        Signed192 z,
 461        Signed192 extentX,
 462        Signed192 extentY,
 463        Signed192 extentZ,
 464        Signed192 radiusNumerator)
 465    {
 47466        Signed192 offsetX = GetProjectedBoxAxisOffset(x, extentX);
 47467        Signed192 offsetY = GetProjectedBoxAxisOffset(y, extentY);
 47468        Signed192 offsetZ = GetProjectedBoxAxisOffset(z, extentZ);
 47469        Signed320 squaredDistance = WideArithmetic.AddSigned320(
 47470            WideArithmetic.AddSigned320(
 47471                WideArithmetic.MultiplySigned192(offsetX, offsetX),
 47472                WideArithmetic.MultiplySigned192(offsetY, offsetY)),
 47473            WideArithmetic.MultiplySigned192(offsetZ, offsetZ));
 47474        Signed320 squaredRadius = WideArithmetic.MultiplySigned192(
 47475            radiusNumerator,
 47476            radiusNumerator);
 47477        return WideArithmetic.SubtractSigned320(
 47478            squaredDistance,
 47479            squaredRadius).Sign <= 0;
 480    }
 481
 482    private static Signed192 GetProjectedBoxAxisOffset(
 483        Signed192 coordinate,
 484        Signed192 extent)
 485    {
 141486        Signed192 minimum = WideArithmetic.SubtractSigned192(default, extent);
 141487        if (WideArithmetic.SubtractSigned192(coordinate, minimum).Sign < 0)
 4488            return WideArithmetic.SubtractSigned192(coordinate, minimum);
 137489        if (WideArithmetic.SubtractSigned192(coordinate, extent).Sign > 0)
 84490            return WideArithmetic.SubtractSigned192(coordinate, extent);
 53491        return default;
 492    }
 493}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.RoundedCylinder.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.RoundedCylinder.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
 8namespace FixedMathSharp.Geometry;
 9
 10/// <content>
 11/// Rounded-cylinder (capsule-swept torus/cylinder) intersection tests for wide, high-precision
 12/// finite-axis geometry, using extended-width fixed-point arithmetic for numerical robustness.
 13/// </content>
 14internal static partial class WideFiniteAxisIntersection
 15{
 16    #region Nested Types
 17
 18    private readonly struct RoundedCylinderBaseData
 19    {
 20        internal readonly Signed192 AxisLengthSquared;
 21        internal readonly Signed192 G0;
 22        internal readonly Signed192 G1;
 23        internal readonly Signed192 G2;
 24        internal readonly Signed192 StartAxisProjection;
 25        internal readonly Signed192 DirectionAxisProjection;
 26        internal readonly Signed320 Q0;
 27        internal readonly Signed320 Q1;
 28        internal readonly Signed320 Q2;
 29        internal readonly Signed192 Radius;
 30        internal readonly Signed192 Expansion;
 31
 32        internal RoundedCylinderBaseData(
 33            Signed192 axisLengthSquared,
 34            Signed192 g0,
 35            Signed192 g1,
 36            Signed192 g2,
 37            Signed192 startAxisProjection,
 38            Signed192 directionAxisProjection,
 39            Signed320 q0,
 40            Signed320 q1,
 41            Signed320 q2,
 42            Signed192 radius,
 43            Signed192 expansion)
 44        {
 4545            AxisLengthSquared = axisLengthSquared;
 4546            G0 = g0;
 4547            G1 = g1;
 4548            G2 = g2;
 4549            StartAxisProjection = startAxisProjection;
 4550            DirectionAxisProjection = directionAxisProjection;
 4551            Q0 = q0;
 4552            Q1 = q1;
 4553            Q2 = q2;
 4554            Radius = radius;
 4555            Expansion = expansion;
 4556        }
 57    }
 58
 59    private readonly struct RoundedCylinderTorusPolynomial
 60    {
 61        internal readonly Signed320 N0;
 62        internal readonly Signed320 N1;
 63        internal readonly Signed320 N2;
 64        internal readonly Signed576 H0;
 65        internal readonly Signed576 H1;
 66        internal readonly Signed576 H2;
 67        internal readonly Signed576 H3;
 68        internal readonly Signed576 H4;
 69
 70        internal RoundedCylinderTorusPolynomial(
 71            Signed320 n0,
 72            Signed320 n1,
 73            Signed320 n2,
 74            Signed576 h0,
 75            Signed576 h1,
 76            Signed576 h2,
 77            Signed576 h3,
 78            Signed576 h4)
 79        {
 4880            N0 = n0;
 4881            N1 = n1;
 4882            N2 = n2;
 4883            H0 = h0;
 4884            H1 = h1;
 4885            H2 = h2;
 4886            H3 = h3;
 4887            H4 = h4;
 4888        }
 89    }
 90
 91    private readonly struct RoundedCylinderQuadraticBound
 92    {
 193        internal static readonly RoundedCylinderQuadraticBound Zero = new(
 194            default,
 195            Scale320,
 196            default,
 197            0);
 198        internal static readonly RoundedCylinderQuadraticBound One = new(
 199            Scale320,
 1100            Scale320,
 1101            default,
 1102            0);
 103
 104        internal readonly Signed320 Numerator;
 105        internal readonly Signed320 Denominator;
 106        internal readonly Signed576 Discriminant;
 107        internal readonly int RadicalSign;
 108
 109        internal RoundedCylinderQuadraticBound(
 110            Signed320 numerator,
 111            Signed320 denominator,
 112            Signed576 discriminant,
 113            int radicalSign)
 114        {
 18115            Numerator = numerator;
 18116            Denominator = denominator;
 18117            Discriminant = discriminant;
 18118            RadicalSign = radicalSign;
 18119        }
 120    }
 121
 122    #endregion
 123
 124    internal static bool DoesCenteredFiniteCylinderOverlapSphere(
 125        Vector3d cylinderCenter,
 126        Vector3d cylinderAxisDirection,
 127        Fixed64 cylinderAxisLength,
 128        Fixed64 cylinderRadius,
 129        Vector3d sphereCenter,
 130        Fixed64 sphereRadius)
 131    {
 2132        _ = TryGetSphericallyExpandedFiniteCylinderDistanceIntervalWithFullAxisLength(
 2133            new FixedSegment(sphereCenter, sphereCenter),
 2134            cylinderCenter,
 2135            cylinderAxisDirection,
 2136            cylinderAxisLength,
 2137            cylinderRadius,
 2138            sphereRadius,
 2139            Fixed64.Zero,
 2140            calculateExit: false,
 2141            out _,
 2142            out _,
 2143            out bool contained,
 2144            out _);
 2145        return contained;
 146    }
 147
 148    internal static bool TryGetSphericallyExpandedFiniteCylinderDistanceInterval(
 149        FixedSegment query,
 150        Vector3d center,
 151        Vector3d axisDirection,
 152        Fixed64 axisLength,
 153        Fixed64 radius,
 154        Fixed64 sphericalExpansion,
 155        Fixed64 segmentLength,
 156        out Fixed64 entry,
 157        out Fixed64 exit,
 158        out bool startContained,
 159        out bool endContainedStrict) =>
 35160        TryGetSphericallyExpandedFiniteCylinderDistanceIntervalWithFullAxisLength(
 35161            query,
 35162            center,
 35163            axisDirection,
 35164            axisLength,
 35165            radius,
 35166            sphericalExpansion,
 35167            segmentLength,
 35168            calculateExit: true,
 35169            out entry,
 35170            out exit,
 35171            out startContained,
 35172            out endContainedStrict);
 173
 174    internal static bool TryGetSphericallyExpandedFiniteCylinderFirstDistance(
 175        FixedSegment query,
 176        Vector3d center,
 177        Vector3d axisDirection,
 178        Fixed64 axisLength,
 179        Fixed64 radius,
 180        Fixed64 sphericalExpansion,
 181        Fixed64 segmentLength,
 182        out Fixed64 distance) =>
 5183        TryGetSphericallyExpandedFiniteCylinderDistanceIntervalWithFullAxisLength(
 5184            query,
 5185            center,
 5186            axisDirection,
 5187            axisLength,
 5188            radius,
 5189            sphericalExpansion,
 5190            segmentLength,
 5191            calculateExit: false,
 5192            out distance,
 5193            out _,
 5194            out _,
 5195            out _);
 196
 197    internal static bool TryGetSphericallyExpandedFiniteCylinderFirstDistanceFromHalfAxisLength(
 198        FixedSegment query,
 199        Vector3d center,
 200        Vector3d axisDirection,
 201        Fixed64 halfAxisLength,
 202        Fixed64 radius,
 203        Fixed64 sphericalExpansion,
 204        Fixed64 segmentLength,
 205        out Fixed64 distance)
 206    {
 5207        Signed192 halfAxisLengthRaw =
 5208            Signed192.Signed(halfAxisLength.m_rawValue);
 5209        Signed192 fullAxisLength = WideArithmetic.AddSigned192(
 5210            halfAxisLengthRaw,
 5211            halfAxisLengthRaw);
 5212        return TryGetSphericallyExpandedFiniteCylinderDistanceInterval(
 5213            query,
 5214            center,
 5215            axisDirection,
 5216            fullAxisLength,
 5217            radius,
 5218            sphericalExpansion,
 5219            segmentLength,
 5220            calculateExit: false,
 5221            out distance,
 5222            out _,
 5223            out _,
 5224            out _);
 225    }
 226
 227    internal static bool TryGetSphericallyExpandedFiniteCylinderDirectionFirstDistanceFromHalfAxisLength(
 228        Vector3d position,
 229        Vector3d direction,
 230        Vector3d center,
 231        Vector3d axisDirection,
 232        Fixed64 halfAxisLength,
 233        Fixed64 radius,
 234        Fixed64 sphericalExpansion,
 235        Fixed64 totalDistance,
 236        out Fixed64 distance)
 237    {
 3238        Signed192 halfAxisLengthRaw =
 3239            Signed192.Signed(halfAxisLength.m_rawValue);
 3240        Signed192 fullAxisLength = WideArithmetic.AddSigned192(
 3241            halfAxisLengthRaw,
 3242            halfAxisLengthRaw);
 243
 3244        if (sphericalExpansion == Fixed64.Zero)
 245        {
 1246            return TryGetFiniteCylinderDirectionFirstDistance(
 1247                position,
 1248                direction,
 1249                center,
 1250                axisDirection,
 1251                fullAxisLength,
 1252                radius,
 1253                Fixed64.Zero,
 1254                Fixed64.Zero,
 1255                totalDistance,
 1256                out distance,
 1257                out _);
 258        }
 259
 2260        bool found = TryGetFiniteCylinderDirectionFirstDistance(
 2261            position,
 2262            direction,
 2263            center,
 2264            axisDirection,
 2265            fullAxisLength,
 2266            radius,
 2267            sphericalExpansion,
 2268            Fixed64.Zero,
 2269            totalDistance,
 2270            out distance,
 2271            out bool sideStartContained);
 2272        RoundedCylinderBaseData baseData = CreateRoundedCylinderBaseData(
 2273            position,
 2274            direction,
 2275            center,
 2276            axisDirection,
 2277            radius,
 2278            sphericalExpansion);
 2279        Fixed64 exit = default;
 2280        return MergeSphericallyExpandedFiniteCylinderRoundedIntervals(
 2281            baseData,
 2282            fullAxisLength,
 2283            totalDistance,
 2284            calculateExit: false,
 2285            ref found,
 2286            ref distance,
 2287            ref exit,
 2288            sideStartContained,
 2289            false,
 2290            out _,
 2291            out _);
 292    }
 293
 294    private static bool TryGetSphericallyExpandedFiniteCylinderDistanceIntervalWithFullAxisLength(
 295        FixedSegment query,
 296        Vector3d center,
 297        Vector3d axisDirection,
 298        Fixed64 axisLength,
 299        Fixed64 radius,
 300        Fixed64 sphericalExpansion,
 301        Fixed64 segmentLength,
 302        bool calculateExit,
 303        out Fixed64 entry,
 304        out Fixed64 exit,
 305        out bool startContained,
 306        out bool endContainedStrict)
 307    {
 42308        if (sphericalExpansion == Fixed64.Zero)
 309        {
 2310            return TryGetFiniteCylinderDistanceInterval(
 2311                query,
 2312                center,
 2313                axisDirection,
 2314                axisLength,
 2315                radius,
 2316                Fixed64.Zero,
 2317                Fixed64.Zero,
 2318                segmentLength,
 2319                out entry,
 2320                out exit,
 2321                out startContained,
 2322                out endContainedStrict);
 323        }
 324
 40325        if (radius == Fixed64.Zero)
 326        {
 1327            return TryGetCapsuleDistanceInterval(
 1328                query,
 1329                center,
 1330                axisDirection,
 1331                axisLength,
 1332                Fixed64.Zero,
 1333                sphericalExpansion,
 1334                segmentLength,
 1335                out entry,
 1336                out exit,
 1337                out startContained,
 1338                out endContainedStrict);
 339        }
 340
 39341        return TryGetSphericallyExpandedFiniteCylinderDistanceInterval(
 39342            query,
 39343            center,
 39344            axisDirection,
 39345            Signed192.Signed(axisLength.m_rawValue),
 39346            radius,
 39347            sphericalExpansion,
 39348            segmentLength,
 39349            calculateExit,
 39350            out entry,
 39351            out exit,
 39352            out startContained,
 39353            out endContainedStrict);
 354    }
 355
 356    private static bool TryGetSphericallyExpandedFiniteCylinderDistanceInterval(
 357        FixedSegment query,
 358        Vector3d center,
 359        Vector3d axisDirection,
 360        Signed192 axisLength,
 361        Fixed64 radius,
 362        Fixed64 sphericalExpansion,
 363        Fixed64 segmentLength,
 364        bool calculateExit,
 365        out Fixed64 entry,
 366        out Fixed64 exit,
 367        out bool startContained,
 368        out bool endContainedStrict)
 369    {
 44370        if (sphericalExpansion == Fixed64.Zero)
 371        {
 1372            return TryGetFiniteCylinderDistanceInterval(
 1373                query,
 1374                center,
 1375                axisDirection,
 1376                axisLength,
 1377                radius,
 1378                Fixed64.Zero,
 1379                Fixed64.Zero,
 1380                segmentLength,
 1381                out entry,
 1382                out exit,
 1383                out startContained,
 1384                out endContainedStrict);
 385        }
 386
 43387        bool found = TryGetFiniteCylinderDistanceInterval(
 43388            query,
 43389            center,
 43390            axisDirection,
 43391            axisLength,
 43392            radius,
 43393            sphericalExpansion,
 43394            Fixed64.Zero,
 43395            segmentLength,
 43396            out entry,
 43397            out exit,
 43398            out bool sideStartContained,
 43399            out bool sideEndContainedStrict);
 400
 43401        RoundedCylinderBaseData baseData = CreateRoundedCylinderBaseData(
 43402            query,
 43403            center,
 43404            axisDirection,
 43405            radius,
 43406            sphericalExpansion);
 43407        return MergeSphericallyExpandedFiniteCylinderRoundedIntervals(
 43408            baseData,
 43409            axisLength,
 43410            segmentLength,
 43411            calculateExit,
 43412            ref found,
 43413            ref entry,
 43414            ref exit,
 43415            sideStartContained,
 43416            sideEndContainedStrict,
 43417            out startContained,
 43418            out endContainedStrict);
 419    }
 420
 421    private static bool MergeSphericallyExpandedFiniteCylinderRoundedIntervals(
 422        RoundedCylinderBaseData baseData,
 423        Signed192 axisLength,
 424        Fixed64 segmentLength,
 425        bool calculateExit,
 426        ref bool found,
 427        ref Fixed64 entry,
 428        ref Fixed64 exit,
 429        bool sideStartContained,
 430        bool sideEndContainedStrict,
 431        out bool startContained,
 432        out bool endContainedStrict)
 433    {
 45434        Merge(
 45435            TryGetRoundedCylinderCapCoreDistanceInterval(
 45436                baseData,
 45437                axisLength,
 45438                baseData.Radius,
 45439                segmentLength,
 45440                positiveCap: false,
 45441                out Fixed64 capEntry,
 45442                out Fixed64 capExit,
 45443                out bool negativeCapStartContained,
 45444                out bool negativeCapEndContainedStrict),
 45445            capEntry,
 45446            capExit,
 45447            ref found,
 45448            ref entry,
 45449            ref exit);
 45450        Merge(
 45451            TryGetRoundedCylinderCapCoreDistanceInterval(
 45452                baseData,
 45453                axisLength,
 45454                baseData.Radius,
 45455                segmentLength,
 45456                positiveCap: true,
 45457                out capEntry,
 45458                out capExit,
 45459                out bool positiveCapStartContained,
 45460                out bool positiveCapEndContainedStrict),
 45461            capEntry,
 45462            capExit,
 45463            ref found,
 45464            ref entry,
 45465            ref exit);
 45466        bool negativeStartContained = false;
 45467        bool negativeEndContainedStrict = false;
 45468        if (RoundedCylinderRimBoundsIntersect(
 45469                baseData,
 45470                axisLength,
 45471                segmentLength,
 45472                positiveCap: false))
 473        {
 12474            MergeRoundedCylinderRimInterval(
 12475                CreateRoundedCylinderTorusPolynomial(baseData, axisLength, positiveCap: false),
 12476                segmentLength,
 12477                ref found,
 12478                ref entry,
 12479                ref exit,
 12480                calculateExit,
 12481                out negativeStartContained,
 12482                out negativeEndContainedStrict);
 483        }
 484
 45485        bool positiveStartContained = false;
 45486        bool positiveEndContainedStrict = false;
 45487        if (RoundedCylinderRimBoundsIntersect(
 45488                baseData,
 45489                axisLength,
 45490                segmentLength,
 45491                positiveCap: true))
 492        {
 36493            MergeRoundedCylinderRimInterval(
 36494                CreateRoundedCylinderTorusPolynomial(baseData, axisLength, positiveCap: true),
 36495                segmentLength,
 36496                ref found,
 36497                ref entry,
 36498                ref exit,
 36499                calculateExit,
 36500                out positiveStartContained,
 36501                out positiveEndContainedStrict);
 502        }
 503
 45504        startContained = sideStartContained
 45505            || negativeCapStartContained
 45506            || positiveCapStartContained
 45507            || negativeStartContained
 45508            || positiveStartContained;
 45509        endContainedStrict = sideEndContainedStrict
 45510            || negativeCapEndContainedStrict
 45511            || positiveCapEndContainedStrict
 45512            || negativeEndContainedStrict
 45513            || positiveEndContainedStrict;
 45514        return found;
 515    }
 516
 517    private static bool TryGetRoundedCylinderCapCoreDistanceInterval(
 518        RoundedCylinderBaseData data,
 519        Signed192 axisLength,
 520        Signed192 radialRadius,
 521        Fixed64 segmentLength,
 522        bool positiveCap,
 523        out Fixed64 entry,
 524        out Fixed64 exit,
 525        out bool startContained,
 526        out bool endContainedStrict)
 527    {
 180528        Signed320 radiusSquared = WideArithmetic.MultiplySigned192(radialRadius, radialRadius);
 180529        Signed320 radialLimit = MultiplyToSigned320(radiusSquared, data.AxisLengthSquared);
 180530        Signed320 radial0 = WideArithmetic.SubtractSigned320(data.Q0, radialLimit);
 180531        Signed320 radialProjection = ShiftRightExact(data.Q1, 1);
 180532        Signed320 radial2 = data.Q2;
 533
 180534        Signed320 scaledStartProjection = WideArithmetic.MultiplySigned192(
 180535            DoubleParameterScale,
 180536            data.StartAxisProjection);
 180537        Signed320 scaledDirectionProjection = WideArithmetic.MultiplySigned192(
 180538            DoubleParameterScale,
 180539            data.DirectionAxisProjection);
 180540        Signed320 capProjection = WideArithmetic.MultiplySigned192(
 180541            axisLength,
 180542            data.AxisLengthSquared);
 180543        Signed320 z0 = positiveCap
 180544            ? WideArithmetic.SubtractSigned320(scaledStartProjection, capProjection)
 180545            : WideArithmetic.AddSigned320(scaledStartProjection, capProjection);
 180546        Signed320 z1 = scaledDirectionProjection;
 180547        Signed320 expansionSquared = WideArithmetic.MultiplySigned192(data.Expansion, data.Expansion);
 180548        Signed320 scaleSquared = WideArithmetic.MultiplySigned192(
 180549            DoubleParameterScale,
 180550            DoubleParameterScale);
 180551        Signed320 axialLimit = MultiplyToSigned320(
 180552            MultiplyToSigned320(expansionSquared, scaleSquared),
 180553            data.AxisLengthSquared);
 180554        Signed320 axial0 = WideArithmetic.SubtractSigned320(
 180555            MultiplyToSigned320(z0, z0),
 180556            axialLimit);
 180557        Signed320 axial1 = MultiplyToSigned320(z0, z1);
 180558        Signed320 axial2 = MultiplyToSigned320(z1, z1);
 559
 180560        int startRadialSign = radial0.Sign;
 180561        int startAxialSign = axial0.Sign;
 180562        int endRadialSign = WideArithmetic.AddSigned320(
 180563            WideArithmetic.AddSigned320(radial0, data.Q1),
 180564            radial2).Sign;
 180565        int endAxialSign = WideArithmetic.AddSigned320(
 180566            WideArithmetic.AddSigned320(axial0, axial1),
 180567            WideArithmetic.AddSigned320(axial1, axial2)).Sign;
 180568        startContained = startRadialSign <= 0 && startAxialSign <= 0;
 180569        endContainedStrict = endRadialSign < 0 && endAxialSign < 0;
 180570        bool endRadialContained = endRadialSign <= 0;
 180571        bool endAxialContained = endAxialSign <= 0;
 572
 180573        if (!TrySolveUnitQuadraticAtDistance(
 180574                radial2,
 180575                radialProjection,
 180576                radial0,
 180577                segmentLength,
 180578                out Fixed64 radialEntry,
 180579                out Fixed64 radialExit)
 180580            || !TrySolveUnitQuadraticAtDistance(
 180581                axial2,
 180582                axial1,
 180583                axial0,
 180584                segmentLength,
 180585                out Fixed64 axialEntry,
 180586                out Fixed64 axialExit))
 587        {
 100588            entry = default;
 100589            exit = default;
 100590            return false;
 591        }
 592
 80593        entry = radialEntry >= axialEntry ? radialEntry : axialEntry;
 80594        exit = radialExit <= axialExit ? radialExit : axialExit;
 80595        if (entry < exit)
 63596            return true;
 17597        if (entry > exit)
 4598            return false;
 599
 13600        RoundedCylinderQuadraticBound radialEntryBound = CreateRoundedCylinderQuadraticBound(
 13601            radial2,
 13602            radialProjection,
 13603            radial0,
 13604            startRadialSign <= 0,
 13605            endRadialContained,
 13606            entryBound: true);
 13607        RoundedCylinderQuadraticBound radialExitBound = CreateRoundedCylinderQuadraticBound(
 13608            radial2,
 13609            radialProjection,
 13610            radial0,
 13611            startRadialSign <= 0,
 13612            endRadialContained,
 13613            entryBound: false);
 13614        RoundedCylinderQuadraticBound axialEntryBound = CreateRoundedCylinderQuadraticBound(
 13615            axial2,
 13616            axial1,
 13617            axial0,
 13618            startAxialSign <= 0,
 13619            endAxialContained,
 13620            entryBound: true);
 13621        RoundedCylinderQuadraticBound axialExitBound = CreateRoundedCylinderQuadraticBound(
 13622            axial2,
 13623            axial1,
 13624            axial0,
 13625            startAxialSign <= 0,
 13626            endAxialContained,
 13627            entryBound: false);
 13628        return IsRoundedCylinderEntryBeforeOrEqualToExit(radialEntryBound, axialExitBound)
 13629            && IsRoundedCylinderEntryBeforeOrEqualToExit(axialEntryBound, radialExitBound);
 630    }
 631
 632    private static bool RoundedCylinderRimBoundsIntersect(
 633        RoundedCylinderBaseData data,
 634        Signed192 axisLength,
 635        Fixed64 segmentLength,
 636        bool positiveCap) =>
 90637        TryGetRoundedCylinderCapCoreDistanceInterval(
 90638            data,
 90639            axisLength,
 90640            WideArithmetic.AddSigned192(data.Radius, data.Expansion),
 90641            segmentLength,
 90642            positiveCap,
 90643            out _,
 90644            out _,
 90645            out _,
 90646            out _);
 647
 648    private static RoundedCylinderQuadraticBound CreateRoundedCylinderQuadraticBound(
 649        Signed320 coefficient,
 650        Signed320 projection,
 651        Signed320 constant,
 652        bool startContained,
 653        bool endContained,
 654        bool entryBound)
 655    {
 52656        if (entryBound && startContained)
 19657            return RoundedCylinderQuadraticBound.Zero;
 33658        if (!entryBound && endContained)
 17659            return RoundedCylinderQuadraticBound.One;
 660
 16661        Signed576 discriminant = WideArithmetic.SubtractSigned576(
 16662            WideArithmetic.MultiplySigned320(projection, projection),
 16663            WideArithmetic.MultiplySigned320(coefficient, constant));
 16664        return new RoundedCylinderQuadraticBound(
 16665            WideArithmetic.SubtractSigned320(default, projection),
 16666            coefficient,
 16667            discriminant,
 16668            entryBound ? -1 : 1);
 669    }
 670
 671    private static void MergeRoundedCylinderRimInterval(
 672        RoundedCylinderTorusPolynomial polynomial,
 673        Fixed64 segmentLength,
 674        ref bool found,
 675        ref Fixed64 entry,
 676        ref Fixed64 exit,
 677        bool calculateExit,
 678        out bool startContained,
 679        out bool endContainedStrict)
 680    {
 48681        startContained = IsPointInRoundedCylinderRimTube(polynomial, atEnd: false, strict: false);
 48682        endContainedStrict = IsPointInRoundedCylinderRimTube(polynomial, atEnd: true, strict: true);
 48683        bool rimFound = TryGetRoundedCylinderRimDistanceInterval(
 48684            polynomial,
 48685            segmentLength,
 48686            startContained,
 48687            IsPointInRoundedCylinderRimTube(polynomial, atEnd: true, strict: false),
 48688            calculateExit,
 48689            out Fixed64 rimEntry,
 48690            out Fixed64 rimExit);
 48691        Merge(rimFound, rimEntry, rimExit, ref found, ref entry, ref exit);
 48692    }
 693
 694    private static bool IsPointInRoundedCylinderRimTube(
 695        RoundedCylinderTorusPolynomial polynomial,
 696        bool atEnd,
 697        bool strict)
 698    {
 144699        Signed320 n = atEnd
 144700            ? WideArithmetic.AddSigned320(
 144701                WideArithmetic.AddSigned320(polynomial.N0, polynomial.N1),
 144702                polynomial.N2)
 144703            : polynomial.N0;
 144704        if (!strict && n.Sign <= 0)
 5705            return true;
 139706        if (strict && n.Sign < 0)
 4707            return true;
 708
 135709        Signed576 h = atEnd
 135710            ? AddFive(
 135711                polynomial.H0,
 135712                polynomial.H1,
 135713                polynomial.H2,
 135714                polynomial.H3,
 135715                polynomial.H4)
 135716            : polynomial.H0;
 135717        return strict ? h.Sign < 0 : h.Sign <= 0;
 718    }
 719
 720    private static bool TryGetFiniteCylinderDirectionFirstDistance(
 721        Vector3d position,
 722        Vector3d direction,
 723        Vector3d center,
 724        Vector3d axisDirection,
 725        Signed192 axisLength,
 726        Fixed64 radius,
 727        Fixed64 radiusExpansion,
 728        Fixed64 axialExpansion,
 729        Fixed64 totalDistance,
 730        out Fixed64 distance,
 731        out bool startContained)
 732    {
 3733        Signed192 queryLengthSquared = GetDirectionDot(direction, direction);
 3734        Signed192 axisLengthSquared = GetDot(
 3735            axisDirection, Vector3d.Zero, axisDirection, Vector3d.Zero);
 3736        Signed192 startDistanceSquared = GetDot(position, center, position, center);
 3737        Signed192 directionsDot = GetDirectionDot(direction, axisDirection);
 3738        Signed192 startAxisProjection = GetDot(
 3739            position, center, axisDirection, Vector3d.Zero);
 3740        Signed192 startDirectionProjection = GetDirectionDot(direction, position, center);
 3741        Signed192 expandedRadius = GetExpandedRadius(radius, radiusExpansion);
 3742        Signed192 squaredRadius = GetSquaredRadius(expandedRadius);
 3743        Signed320 axialExtent = GetCenteredAxialExtent(
 3744            axisLengthSquared, axisLength, axialExpansion);
 3745        startContained = IsCenteredFiniteCylinderPointContained(
 3746            startDistanceSquared, startAxisProjection, axisLengthSquared,
 3747            squaredRadius, axialExtent, strict: false);
 748
 3749        if (!TryGetCenteredAxialInterval(
 3750                startAxisProjection, directionsDot, axialExtent, Fixed64.One,
 3751                out RationalBound320 lower, out RationalBound320 upper))
 752        {
 1753            distance = default;
 1754            return false;
 755        }
 756
 2757        return TryGetFiniteAxisDistanceInterval(
 2758            queryLengthSquared, axisLengthSquared, startDistanceSquared,
 2759            directionsDot, startAxisProjection, startDirectionProjection,
 2760            expandedRadius, lower, upper, totalDistance, out distance, out _);
 761    }
 762
 763    private static RoundedCylinderBaseData CreateRoundedCylinderBaseData(
 764        FixedSegment query,
 765        Vector3d center,
 766        Vector3d axisDirection,
 767        Fixed64 radius,
 768        Fixed64 sphericalExpansion)
 769    {
 43770        Signed192 axisLengthSquared = GetDot(
 43771            axisDirection,
 43772            Vector3d.Zero,
 43773            axisDirection,
 43774            Vector3d.Zero);
 43775        Signed192 startDistanceSquared = GetDot(query.Start, center, query.Start, center);
 43776        Signed192 directionLengthSquared = GetDot(query.End, query.Start, query.End, query.Start);
 43777        Signed192 startDirectionProjection = GetDot(query.Start, center, query.End, query.Start);
 43778        Signed192 startAxisProjection = GetDot(query.Start, center, axisDirection, Vector3d.Zero);
 43779        Signed192 directionAxisProjection = GetDot(query.End, query.Start, axisDirection, Vector3d.Zero);
 780
 43781        return CreateRoundedCylinderBaseData(
 43782            axisLengthSquared,
 43783            startDistanceSquared,
 43784            directionLengthSquared,
 43785            startDirectionProjection,
 43786            startAxisProjection,
 43787            directionAxisProjection,
 43788            radius,
 43789            sphericalExpansion);
 790    }
 791
 792    private static RoundedCylinderBaseData CreateRoundedCylinderBaseData(
 793        Vector3d position,
 794        Vector3d direction,
 795        Vector3d center,
 796        Vector3d axisDirection,
 797        Fixed64 radius,
 798        Fixed64 sphericalExpansion)
 799    {
 2800        Signed192 axisLengthSquared = GetDot(
 2801            axisDirection, Vector3d.Zero, axisDirection, Vector3d.Zero);
 2802        Signed192 startDistanceSquared = GetDot(position, center, position, center);
 2803        Signed192 directionLengthSquared = GetDirectionDot(direction, direction);
 2804        Signed192 startDirectionProjection = GetDirectionDot(direction, position, center);
 2805        Signed192 startAxisProjection = GetDot(position, center, axisDirection, Vector3d.Zero);
 2806        Signed192 directionAxisProjection = GetDirectionDot(direction, axisDirection);
 2807        return CreateRoundedCylinderBaseData(
 2808            axisLengthSquared,
 2809            startDistanceSquared,
 2810            directionLengthSquared,
 2811            startDirectionProjection,
 2812            startAxisProjection,
 2813            directionAxisProjection,
 2814            radius,
 2815            sphericalExpansion);
 816    }
 817
 818    private static RoundedCylinderBaseData CreateRoundedCylinderBaseData(
 819        Signed192 axisLengthSquared,
 820        Signed192 startDistanceSquared,
 821        Signed192 directionLengthSquared,
 822        Signed192 startDirectionProjection,
 823        Signed192 startAxisProjection,
 824        Signed192 directionAxisProjection,
 825        Fixed64 radius,
 826        Fixed64 sphericalExpansion)
 827    {
 45828        Signed320 q0 = WideArithmetic.MultiplySubtract(
 45829            startDistanceSquared,
 45830            axisLengthSquared,
 45831            startAxisProjection,
 45832            startAxisProjection);
 45833        Signed320 q1 = Twice(WideArithmetic.MultiplySubtract(
 45834            startDirectionProjection,
 45835            axisLengthSquared,
 45836            startAxisProjection,
 45837            directionAxisProjection));
 45838        Signed320 q2 = WideArithmetic.MultiplySubtract(
 45839            directionLengthSquared,
 45840            axisLengthSquared,
 45841            directionAxisProjection,
 45842            directionAxisProjection);
 843
 45844        return new RoundedCylinderBaseData(
 45845            axisLengthSquared,
 45846            startDistanceSquared,
 45847            startDirectionProjection,
 45848            directionLengthSquared,
 45849            startAxisProjection,
 45850            directionAxisProjection,
 45851            q0,
 45852            q1,
 45853            q2,
 45854            Signed192.Signed(radius.m_rawValue),
 45855            Signed192.Signed(sphericalExpansion.m_rawValue));
 856    }
 857
 858    private static RoundedCylinderTorusPolynomial CreateRoundedCylinderTorusPolynomial(
 859        RoundedCylinderBaseData data,
 860        Signed192 axisLength,
 861        bool positiveCap)
 862    {
 48863        Signed320 scaleSquared = WideArithmetic.MultiplySigned192(
 48864            DoubleParameterScale,
 48865            DoubleParameterScale);
 48866        Signed320 heightSquared = WideArithmetic.MultiplySigned192(axisLength, axisLength);
 48867        Signed320 radiusSquared = WideArithmetic.MultiplySigned192(data.Radius, data.Radius);
 48868        Signed320 expansionSquared = WideArithmetic.MultiplySigned192(data.Expansion, data.Expansion);
 48869        Signed320 radiusDifference = WideArithmetic.SubtractSigned320(radiusSquared, expansionSquared);
 48870        Signed320 constant = WideArithmetic.AddSigned320(
 48871            MultiplyToSigned320(heightSquared, data.AxisLengthSquared),
 48872            MultiplyToSigned320(radiusDifference, scaleSquared));
 873
 48874        Signed320 axial0 = MultiplyThreeToSigned320(
 48875            DoubleParameterScale,
 48876            axisLength,
 48877            data.StartAxisProjection);
 48878        Signed320 axial1 = MultiplyThreeToSigned320(
 48879            DoubleParameterScale,
 48880            axisLength,
 48881            data.DirectionAxisProjection);
 48882        if (positiveCap)
 883        {
 36884            axial0 = WideArithmetic.SubtractSigned320(default, axial0);
 36885            axial1 = WideArithmetic.SubtractSigned320(default, axial1);
 886        }
 887
 48888        Signed320 n0 = WideArithmetic.AddSigned320(
 48889            WideArithmetic.AddSigned320(
 48890                MultiplyToSigned320(scaleSquared, data.G0),
 48891                Twice(axial0)),
 48892            constant);
 48893        Signed320 n1 = WideArithmetic.AddSigned320(
 48894            Twice(MultiplyToSigned320(scaleSquared, data.G1)),
 48895            Twice(axial1));
 48896        Signed320 n2 = MultiplyToSigned320(scaleSquared, data.G2);
 897
 48898        Signed320 rimScale = Four(MultiplyToSigned320(
 48899            MultiplyToSigned320(radiusSquared, scaleSquared),
 48900            scaleSquared));
 48901        Signed576 h0 = WideArithmetic.SubtractSigned576(
 48902            WideArithmetic.MultiplySigned576(
 48903                WideArithmetic.MultiplySigned320(n0, n0),
 48904                data.AxisLengthSquared),
 48905            WideArithmetic.MultiplySigned320(rimScale, data.Q0));
 48906        Signed576 h1 = WideArithmetic.SubtractSigned576(
 48907            Twice(WideArithmetic.MultiplySigned576(
 48908                WideArithmetic.MultiplySigned320(n0, n1),
 48909                data.AxisLengthSquared)),
 48910            WideArithmetic.MultiplySigned320(rimScale, data.Q1));
 48911        Signed576 h2 = WideArithmetic.SubtractSigned576(
 48912            WideArithmetic.MultiplySigned576(
 48913                WideArithmetic.AddSigned576(
 48914                    WideArithmetic.MultiplySigned320(n1, n1),
 48915                    Twice(WideArithmetic.MultiplySigned320(n0, n2))),
 48916                data.AxisLengthSquared),
 48917            WideArithmetic.MultiplySigned320(rimScale, data.Q2));
 48918        Signed576 h3 = Twice(WideArithmetic.MultiplySigned576(
 48919            WideArithmetic.MultiplySigned320(n1, n2),
 48920            data.AxisLengthSquared));
 48921        Signed576 h4 = WideArithmetic.MultiplySigned576(
 48922            WideArithmetic.MultiplySigned320(n2, n2),
 48923            data.AxisLengthSquared);
 48924        return new RoundedCylinderTorusPolynomial(n0, n1, n2, h0, h1, h2, h3, h4);
 925    }
 926
 927    private static Signed320 MultiplyToSigned320(Signed320 left, Signed192 right) =>
 552928        Signed320.NarrowValue(WideArithmetic.MultiplySigned576(Signed576.ExtendValue(left), right));
 929
 930    private static Signed320 MultiplyToSigned320(Signed320 left, Signed320 right) =>
 864931        Signed320.NarrowValue(WideArithmetic.MultiplySigned320(left, right));
 932
 285933    private static Signed320 Twice(Signed320 value) => WideArithmetic.AddSigned320(value, value);
 934
 48935    private static Signed320 Four(Signed320 value) => Twice(Twice(value));
 936
 144937    private static Signed576 Twice(Signed576 value) => WideArithmetic.AddSigned576(value, value);
 938
 939    private static Signed576 AddFive(
 940        Signed576 first,
 941        Signed576 second,
 942        Signed576 third,
 943        Signed576 fourth,
 944        Signed576 fifth) =>
 88945        WideArithmetic.AddSigned576(
 88946            WideArithmetic.AddSigned576(
 88947                WideArithmetic.AddSigned576(first, second),
 88948                WideArithmetic.AddSigned576(third, fourth)),
 88949            fifth);
 950
 951}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.RoundedCylinderInteger.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.RoundedCylinderInteger.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>
 13/// Signed wide-integer arithmetic helpers (add, subtract, multiply, shift, compare)
 14/// used to evaluate rounded-cylinder intersection polynomial coefficients.
 15/// </content>
 16internal static partial class WideFiniteAxisIntersection
 17{
 18    private static void ImportRoundedCylinderCoefficient(
 19        Signed576 value,
 20        Span<ulong> coefficients,
 21        Span<sbyte> signs,
 22        int polynomialIndex,
 23        int coefficientIndex)
 24    {
 22525        Span<ulong> destination = GetRoundedCylinderCoefficient(
 22526            coefficients,
 22527            polynomialIndex,
 22528            coefficientIndex);
 22529        WideArithmetic.GetMagnitude(value, destination[..9]);
 22530        signs[GetRoundedCylinderCoefficientIndex(polynomialIndex, coefficientIndex)] = (sbyte)value.Sign;
 22531    }
 32
 33    private static void ImportRoundedCylinderCoefficient(
 34        Signed832 value,
 35        Span<ulong> coefficients,
 36        Span<sbyte> signs,
 37        int polynomialIndex,
 38        int coefficientIndex)
 39    {
 56540        Span<ulong> destination = GetRoundedCylinderCoefficient(
 56541            coefficients,
 56542            polynomialIndex,
 56543            coefficientIndex);
 56544        WideArithmetic.GetMagnitude(value, destination[..13]);
 56545        signs[GetRoundedCylinderCoefficientIndex(polynomialIndex, coefficientIndex)] =
 56546            (sbyte)value.Sign;
 56547    }
 48
 49    private static Span<ulong> GetRoundedCylinderCoefficient(
 50        Span<ulong> coefficients,
 51        int polynomialIndex,
 52        int coefficientIndex)
 53    {
 2476854        int index = GetRoundedCylinderCoefficientIndex(polynomialIndex, coefficientIndex);
 2476855        return coefficients.Slice(
 2476856            index * RoundedCylinderWideLimbCount,
 2476857            RoundedCylinderWideLimbCount);
 58    }
 59
 60    private static int GetRoundedCylinderCoefficientIndex(int polynomialIndex, int coefficientIndex) =>
 5128861        polynomialIndex * RoundedCylinderCoefficientCount + coefficientIndex;
 62
 63    private static void AddRoundedCylinderSigned(
 64        ReadOnlySpan<ulong> left,
 65        sbyte leftSign,
 66        ReadOnlySpan<ulong> right,
 67        sbyte rightSign,
 68        Span<ulong> destination,
 69        out sbyte destinationSign)
 70    {
 1572171        if (leftSign == 0)
 72        {
 3473            CopyRoundedCylinderWide(right, destination);
 3474            destinationSign = rightSign;
 3475            return;
 76        }
 1568777        if (rightSign == 0)
 78        {
 28679            CopyRoundedCylinderWide(left, destination);
 28680            destinationSign = leftSign;
 28681            return;
 82        }
 1540183        if (leftSign != rightSign)
 84        {
 1479085            SubtractRoundedCylinderSigned(
 1479086                left,
 1479087                leftSign,
 1479088                right,
 1479089                (sbyte)-rightSign,
 1479090                destination,
 1479091                out destinationSign);
 1479092            return;
 93        }
 94
 61195        WideArithmetic.AddEqualMagnitudes(left, right, destination);
 61196        destinationSign = leftSign;
 61197    }
 98
 99    private static void SubtractRoundedCylinderSigned(
 100        ReadOnlySpan<ulong> left,
 101        sbyte leftSign,
 102        ReadOnlySpan<ulong> right,
 103        sbyte rightSign,
 104        Span<ulong> destination,
 105        out sbyte destinationSign)
 106    {
 16382107        if (leftSign == 0 || rightSign == 0)
 108        {
 439109            bool useRight = leftSign == 0;
 439110            CopyRoundedCylinderWide(useRight ? right : left, destination);
 439111            destinationSign = useRight ? (sbyte)-rightSign : leftSign;
 439112            return;
 113        }
 15943114        if (leftSign != rightSign)
 115        {
 215116            AddRoundedCylinderSigned(
 215117                left,
 215118                leftSign,
 215119                right,
 215120                (sbyte)-rightSign,
 215121                destination,
 215122                out destinationSign);
 215123            return;
 124        }
 125
 15728126        int comparison = WideArithmetic.CompareMagnitudeEqualLength(left, right);
 15728127        if (comparison == 0)
 128        {
 186129            destination.Clear();
 186130            destinationSign = 0;
 186131            return;
 132        }
 133
 15542134        ReadOnlySpan<ulong> larger = comparison > 0 ? left : right;
 15542135        ReadOnlySpan<ulong> smaller = comparison > 0 ? right : left;
 15542136        WideArithmetic.SubtractEqualMagnitudes(larger, smaller, destination);
 15542137        destinationSign = comparison > 0 ? leftSign : (sbyte)-leftSign;
 15542138    }
 139
 140    private static void MultiplyRoundedCylinderWide(
 141        ReadOnlySpan<ulong> left,
 142        ReadOnlySpan<ulong> right,
 143        Span<ulong> destination)
 144    {
 4602145        destination.Clear();
 4602146        int leftLength = GetRoundedCylinderWideLength(left);
 4602147        int rightLength = GetRoundedCylinderWideLength(right);
 54368148        for (int leftIndex = 0; leftIndex < leftLength; leftIndex++)
 149        {
 326156150            for (int rightIndex = 0; rightIndex < rightLength; rightIndex++)
 151            {
 140496152                Fixed64.Multiply64To128(
 140496153                    left[leftIndex],
 140496154                    right[rightIndex],
 140496155                    out ulong high,
 140496156                    out ulong low);
 140496157                AddRoundedCylinderWord(destination, leftIndex + rightIndex, low);
 140496158                AddRoundedCylinderWord(destination, leftIndex + rightIndex + 1, high);
 159            }
 160        }
 4602161    }
 162
 163    private static void MultiplyRoundedCylinderWideByWord(
 164        ReadOnlySpan<ulong> value,
 165        ulong multiplier,
 166        Span<ulong> destination)
 167    {
 19124168        destination.Clear();
 19124169        if (multiplier == 0UL)
 555170            return;
 18569171        int length = GetRoundedCylinderWideLength(value);
 264180172        for (int index = 0; index < length; index++)
 173        {
 113521174            Fixed64.Multiply64To128(value[index], multiplier, out ulong high, out ulong low);
 113521175            AddRoundedCylinderWord(destination, index, low);
 113521176            AddRoundedCylinderWord(destination, index + 1, high);
 177        }
 18569178    }
 179
 180    private static void AddRoundedCylinderWord(Span<ulong> value, int index, ulong word)
 181    {
 747129182        while (word != 0UL)
 183        {
 239095184            ulong sum = unchecked(value[index] + word);
 239095185            word = sum < value[index] ? 1UL : 0UL;
 239095186            value[index] = sum;
 239095187            index++;
 188        }
 508034189    }
 190
 191    private static sbyte MultiplyRoundedCylinderSigns(sbyte left, sbyte right) =>
 4215192        left == 0 || right == 0 ? (sbyte)0 : (sbyte)(left * right);
 193
 194    private static int GetRoundedCylinderWideLength(ReadOnlySpan<ulong> value)
 195    {
 27789196        int length = value.Length;
 1095959197        while (length > 0 && value[length - 1] == 0UL)
 1068170198            length--;
 27789199        return length;
 200    }
 201
 202    private static void CopyRoundedCylinderWide(
 203        ReadOnlySpan<ulong> source,
 204        Span<ulong> destination) =>
 22177205        source.CopyTo(destination);
 206
 207    private static int CountRoundedCylinderTrailingZeroes(ReadOnlySpan<ulong> value)
 208    {
 605209        int wordIndex = 0;
 2762210        while (value[wordIndex] == 0UL)
 2157211            wordIndex++;
 605212        ulong word = value[wordIndex];
 605213        int bits = 0;
 14199214        while ((word & 1UL) == 0UL)
 215        {
 13594216            word >>= 1;
 13594217            bits++;
 218        }
 605219        return wordIndex * 64 + bits;
 220    }
 221
 222    private static void ShiftRoundedCylinderWideRight(Span<ulong> value, int bits)
 223    {
 887224        int wordShift = bits >> 6;
 887225        int bitShift = bits & 63;
 79830226        for (int destinationIndex = 0; destinationIndex < value.Length; destinationIndex++)
 227        {
 39028228            int sourceIndex = destinationIndex + wordShift;
 39028229            ulong lower = sourceIndex < value.Length ? value[sourceIndex] : 0UL;
 39028230            ulong upper = sourceIndex + 1 < value.Length ? value[sourceIndex + 1] : 0UL;
 39028231            uint nonzero = ((uint)bitShift | (0U - (uint)bitShift)) >> 31;
 39028232            ulong upperMask = 0UL - nonzero;
 39028233            value[destinationIndex] = (lower >> bitShift)
 39028234                | ((upper << ((64 - bitShift) & 63)) & upperMask);
 235        }
 887236    }
 237}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.RoundedCylinderRootSolver.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.RoundedCylinderRootSolver.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>
 13/// Implements a wide-precision root solver for rounded-cylinder (capsule-like) torus
 14/// intersection tests, using a Sturm sequence built over arbitrary-precision integer
 15/// coefficients to isolate and count roots within a bounded segment length.
 16/// </content>
 17internal static partial class WideFiniteAxisIntersection
 18{
 19    private const int RoundedCylinderPolynomialCount = 5;
 20    private const int RoundedCylinderCoefficientCount = 5;
 21    // The largest factorized quartic subresultant transient is below 2,772 bits.
 22    private const int RoundedCylinderWideLimbCount = 44;
 23
 24    /// <summary>
 25    /// Counts real roots for quartics whose coefficient growth is bounded by
 26    /// the finite-axis and planar-projection derivations in this assembly.
 27    /// </summary>
 28    internal static int CountProjectionDomainQuarticRoots(
 29        Signed832 constant,
 30        Signed832 linear,
 31        Signed832 quadratic,
 32        Signed832 cubic,
 33        Signed832 quartic)
 34    {
 11435        int leadingSign = quartic.Sign;
 11436        if (leadingSign == 0)
 137            throw new ArgumentOutOfRangeException(nameof(quartic));
 38
 11339        if (leadingSign < 0)
 40        {
 441            constant = WideArithmetic.SubtractSigned832(default, constant);
 442            linear = WideArithmetic.SubtractSigned832(default, linear);
 443            quadratic = WideArithmetic.SubtractSigned832(default, quadratic);
 444            cubic = WideArithmetic.SubtractSigned832(default, cubic);
 445            quartic = WideArithmetic.SubtractSigned832(default, quartic);
 46        }
 47
 11348        Span<ulong> coefficients = stackalloc ulong[
 11349            RoundedCylinderPolynomialCount
 11350            * RoundedCylinderCoefficientCount
 11351            * RoundedCylinderWideLimbCount];
 11352        Span<sbyte> signs = stackalloc sbyte[
 11353            RoundedCylinderPolynomialCount * RoundedCylinderCoefficientCount];
 11354        Span<int> degrees = stackalloc int[RoundedCylinderPolynomialCount];
 11355        coefficients.Clear();
 11356        signs.Clear();
 11357        degrees.Clear();
 11358        ImportRoundedCylinderCoefficient(constant, coefficients, signs, 0, 0);
 11359        ImportRoundedCylinderCoefficient(linear, coefficients, signs, 0, 1);
 11360        ImportRoundedCylinderCoefficient(quadratic, coefficients, signs, 0, 2);
 11361        ImportRoundedCylinderCoefficient(cubic, coefficients, signs, 0, 3);
 11362        ImportRoundedCylinderCoefficient(quartic, coefficients, signs, 0, 4);
 11363        degrees[0] = 4;
 113064        for (int coefficientIndex = 1; coefficientIndex <= 4; coefficientIndex++)
 65        {
 45266            int destinationIndex = coefficientIndex - 1;
 45267            MultiplyRoundedCylinderWideByWord(
 45268                GetRoundedCylinderCoefficient(
 45269                    coefficients,
 45270                    0,
 45271                    coefficientIndex),
 45272                (ulong)coefficientIndex,
 45273                GetRoundedCylinderCoefficient(
 45274                    coefficients,
 45275                    1,
 45276                    destinationIndex));
 45277            signs[GetRoundedCylinderCoefficientIndex(1, destinationIndex)] =
 45278                signs[GetRoundedCylinderCoefficientIndex(
 45279                    0,
 45280                    coefficientIndex)];
 81        }
 11382        degrees[1] = 3;
 83
 11384        int sequenceCount = BuildRoundedCylinderQuarticSturmSequence(
 11385            coefficients,
 11386            signs,
 11387            degrees);
 11388        return GetRoundedCylinderInfinityVariations(
 11389                   signs,
 11390                   degrees,
 11391                   sequenceCount,
 11392                   negative: true)
 11393               - GetRoundedCylinderInfinityVariations(
 11394                   signs,
 11395                   degrees,
 11396                   sequenceCount,
 11397                   negative: false);
 98    }
 99
 100    private static int GetRoundedCylinderInfinityVariations(
 101        ReadOnlySpan<sbyte> signs,
 102        ReadOnlySpan<int> degrees,
 103        int sequenceCount,
 104        bool negative)
 105    {
 226106        int variations = 0;
 226107        int previousSign = 0;
 226108        for (int polynomialIndex = 0;
 1320109             polynomialIndex < sequenceCount;
 1094110             polynomialIndex++)
 111        {
 1094112            int degree = degrees[polynomialIndex];
 1094113            int sign = signs[
 1094114                GetRoundedCylinderCoefficientIndex(
 1094115                    polynomialIndex,
 1094116                    degree)];
 1094117            if (negative && (degree & 1) != 0)
 221118                sign = -sign;
 1094119            if (previousSign != 0 && sign != previousSign)
 434120                variations++;
 1094121            previousSign = sign;
 122        }
 123
 226124        return variations;
 125    }
 126
 127    private static bool TryGetRoundedCylinderRimDistanceInterval(
 128        RoundedCylinderTorusPolynomial polynomial,
 129        Fixed64 segmentLength,
 130        bool startContained,
 131        bool endContained,
 132        bool calculateExit,
 133        out Fixed64 entry,
 134        out Fixed64 exit)
 135    {
 48136        entry = default;
 48137        exit = default;
 48138        if (segmentLength == Fixed64.Zero)
 3139            return startContained;
 140
 45141        Span<ulong> coefficients = stackalloc ulong[
 45142            RoundedCylinderPolynomialCount
 45143            * RoundedCylinderCoefficientCount
 45144            * RoundedCylinderWideLimbCount];
 45145        Span<sbyte> signs = stackalloc sbyte[
 45146            RoundedCylinderPolynomialCount * RoundedCylinderCoefficientCount];
 45147        Span<int> degrees = stackalloc int[RoundedCylinderPolynomialCount];
 45148        coefficients.Clear();
 45149        signs.Clear();
 45150        degrees.Clear();
 151
 45152        ulong maximum = unchecked((ulong)segmentLength.m_rawValue);
 45153        int sequenceCount = BuildRoundedCylinderSturmSequence(
 45154            polynomial,
 45155            coefficients,
 45156            signs,
 45157            degrees);
 45158        if (sequenceCount == 0)
 159        {
 1160            exit = segmentLength;
 1161            return true;
 162        }
 44163        HomogenizeRoundedCylinderSturmSequence(
 44164            coefficients,
 44165            degrees,
 44166            sequenceCount,
 44167            maximum);
 168
 44169        int lowerVariations = GetRoundedCylinderSignVariations(
 44170            coefficients,
 44171            signs,
 44172            degrees,
 44173            sequenceCount,
 44174            0UL,
 44175            1UL);
 44176        int upperVariations = GetRoundedCylinderSignVariations(
 44177            coefficients,
 44178            signs,
 44179            degrees,
 44180            sequenceCount,
 44181            maximum,
 44182            1UL);
 44183        int rootCount = lowerVariations - upperVariations;
 44184        bool rootAtStart = polynomial.H0.IsZero;
 44185        if (rootCount == 0)
 186        {
 7187            if (!startContained && !rootAtStart)
 4188                return false;
 189
 3190            entry = Fixed64.Zero;
 3191            exit = endContained ? segmentLength : Fixed64.Zero;
 3192            return true;
 193        }
 194
 37195        entry = startContained || rootAtStart
 37196            ? Fixed64.Zero
 37197            : FindRoundedCylinderRoot(
 37198                coefficients,
 37199                signs,
 37200                degrees,
 37201                sequenceCount,
 37202                maximum,
 37203                lowerVariations,
 37204                upperVariations,
 37205                rootCount,
 37206                findFirst: true);
 37207        if (!calculateExit)
 208        {
 8209            exit = entry;
 8210            return true;
 211        }
 29212        exit = endContained
 29213            ? segmentLength
 29214            : FindRoundedCylinderRoot(
 29215                coefficients,
 29216                signs,
 29217                degrees,
 29218                sequenceCount,
 29219                maximum,
 29220                lowerVariations,
 29221                upperVariations,
 29222                rootCount,
 29223                findFirst: false);
 29224        return true;
 225    }
 226
 227    private static Fixed64 FindRoundedCylinderRoot(
 228        Span<ulong> coefficients,
 229        Span<sbyte> signs,
 230        Span<int> degrees,
 231        int sequenceCount,
 232        ulong maximum,
 233        int lowerVariations,
 234        int upperVariations,
 235        int totalRootCount,
 236        bool findFirst)
 237    {
 52238        ulong lower = 0UL;
 52239        ulong upper = maximum;
 52240        int intervalRootCount = totalRootCount;
 742241        while (upper - lower > 1UL)
 242        {
 721243            if (intervalRootCount == 1)
 244            {
 593245                int lowerSign = EvaluateRoundedCylinderPolynomialSign(
 593246                    coefficients,
 593247                    signs,
 593248                    degrees[0],
 593249                    0,
 593250                    lower,
 593251                    1UL);
 252                // The global start root is handled before isolation; midpoint
 253                // roots remain on the upper boundary of the retained interval.
 593254                int upperSign = EvaluateRoundedCylinderPolynomialSign(
 593255                    coefficients,
 593256                    signs,
 593257                    degrees[0],
 593258                    0,
 593259                    upper,
 593260                    1UL);
 593261                if (upperSign == 0)
 4262                    return Fixed64.FromRaw((long)upper);
 263
 589264                if (lowerSign != upperSign)
 265                {
 27266                    return FindRoundedCylinderSignChangingRoot(
 27267                        coefficients,
 27268                        signs,
 27269                        degrees[0],
 27270                        maximum,
 27271                        lower,
 27272                        upper,
 27273                        lowerSign);
 274                }
 275            }
 276
 690277            ulong midpoint = lower + ((upper - lower) >> 1);
 690278            int midpointVariations = GetRoundedCylinderSignVariations(
 690279                coefficients,
 690280                signs,
 690281                degrees,
 690282                sequenceCount,
 690283                midpoint,
 690284                1UL);
 690285            int leftRootCount = lowerVariations - midpointVariations;
 690286            if (findFirst ? leftRootCount > 0 : leftRootCount == intervalRootCount)
 287            {
 341288                upper = midpoint;
 341289                upperVariations = midpointVariations;
 341290                intervalRootCount = leftRootCount;
 291            }
 292            else
 293            {
 349294                lower = midpoint;
 349295                lowerVariations = midpointVariations;
 349296                intervalRootCount -= leftRootCount;
 297            }
 298        }
 299
 21300        ulong midpointNumerator = (lower << 1) | 1UL;
 21301        int halfVariations = GetRoundedCylinderSignVariations(
 21302            coefficients,
 21303            signs,
 21304            degrees,
 21305            sequenceCount,
 21306            midpointNumerator,
 21307            2UL);
 21308        int leftHalfRootCount = lowerVariations - halfVariations;
 21309        int midpointSign = EvaluateRoundedCylinderPolynomialSign(
 21310            coefficients,
 21311            signs,
 21312            degrees[0],
 21313            0,
 21314            midpointNumerator,
 21315            2UL);
 316
 317        ulong rounded;
 21318        if (findFirst)
 319        {
 14320            rounded = leftHalfRootCount > 0 ? lower : upper;
 14321            if ((midpointSign == 0) & (leftHalfRootCount == 1))
 1322                rounded = lower + (lower & 1UL);
 323        }
 324        else
 325        {
 7326            int rightHalfRootCount = intervalRootCount - leftHalfRootCount;
 7327            rounded = rightHalfRootCount > 0 ? upper : lower;
 7328            if ((midpointSign == 0) & (rightHalfRootCount == 0))
 1329                rounded = lower + (lower & 1UL);
 330        }
 331
 21332        return Fixed64.FromRaw((long)rounded);
 333    }
 334
 335    private static Fixed64 FindRoundedCylinderSignChangingRoot(
 336        Span<ulong> coefficients,
 337        Span<sbyte> signs,
 338        int degree,
 339        ulong maximum,
 340        ulong lower,
 341        ulong upper,
 342        int lowerSign)
 343    {
 869344        while (upper - lower > 1UL)
 345        {
 847346            ulong midpoint = lower + ((upper - lower) >> 1);
 847347            int midpointSign = EvaluateRoundedCylinderPolynomialSign(
 847348                coefficients,
 847349                signs,
 847350                degree,
 847351                0,
 847352                midpoint,
 847353                1UL);
 847354            if (midpointSign == 0)
 5355                return Fixed64.FromRaw((long)midpoint);
 842356            if (midpointSign == lowerSign)
 445357                lower = midpoint;
 358            else
 397359                upper = midpoint;
 360        }
 361
 22362        ulong midpointNumerator = (lower << 1) | 1UL;
 22363        int halfSign = EvaluateRoundedCylinderPolynomialSign(
 22364            coefficients,
 22365            signs,
 22366            degree,
 22367            0,
 22368            midpointNumerator,
 22369            2UL);
 22370        if (halfSign == 0)
 2371            return Fixed64.FromRaw((long)(lower + (lower & 1UL)));
 20372        return Fixed64.FromRaw((long)(halfSign == lowerSign ? upper : lower));
 373    }
 374
 375    private static void HomogenizeRoundedCylinderSturmSequence(
 376        Span<ulong> coefficients,
 377        Span<int> degrees,
 378        int sequenceCount,
 379        ulong segmentLengthRaw)
 380    {
 44381        Span<ulong> product = stackalloc ulong[RoundedCylinderWideLimbCount];
 420382        for (int polynomialIndex = 0; polynomialIndex < sequenceCount; polynomialIndex++)
 383        {
 166384            int degree = degrees[polynomialIndex];
 1098385            for (int coefficientIndex = 0; coefficientIndex < degree; coefficientIndex++)
 386            {
 383387                Span<ulong> coefficient = GetRoundedCylinderCoefficient(
 383388                    coefficients,
 383389                    polynomialIndex,
 383390                    coefficientIndex);
 383391                int power = degree - coefficientIndex;
 2350392                for (int factor = 0; factor < power; factor++)
 393                {
 792394                    MultiplyRoundedCylinderWideByWord(coefficient, segmentLengthRaw, product);
 792395                    CopyRoundedCylinderWide(product, coefficient);
 396                }
 397            }
 398        }
 44399    }
 400
 401    private static bool IsRoundedCylinderEntryBeforeOrEqualToExit(
 402        RoundedCylinderQuadraticBound entry,
 403        RoundedCylinderQuadraticBound exit)
 404    {
 25405        Signed576 cross = WideArithmetic.SubtractSigned576(
 25406            WideArithmetic.MultiplySigned320(entry.Numerator, exit.Denominator),
 25407            WideArithmetic.MultiplySigned320(exit.Numerator, entry.Denominator));
 25408        bool hasEntryRadical = entry.RadicalSign < 0;
 25409        bool hasExitRadical = exit.RadicalSign > 0;
 25410        if (!hasEntryRadical && !hasExitRadical)
 12411            return cross.Sign <= 0;
 13412        if (cross.Sign <= 0)
 5413            return true;
 414
 8415        Span<ulong> crossMagnitude = stackalloc ulong[RoundedCylinderWideLimbCount];
 8416        Span<ulong> entryTerm = stackalloc ulong[RoundedCylinderWideLimbCount];
 8417        Span<ulong> exitTerm = stackalloc ulong[RoundedCylinderWideLimbCount];
 8418        Span<ulong> crossSquared = stackalloc ulong[RoundedCylinderWideLimbCount];
 8419        Span<ulong> termSum = stackalloc ulong[RoundedCylinderWideLimbCount];
 8420        Span<ulong> difference = stackalloc ulong[RoundedCylinderWideLimbCount];
 8421        Span<ulong> differenceSquared = stackalloc ulong[RoundedCylinderWideLimbCount];
 8422        Span<ulong> termProduct = stackalloc ulong[RoundedCylinderWideLimbCount];
 8423        Span<ulong> right = stackalloc ulong[RoundedCylinderWideLimbCount];
 8424        Span<ulong> first = stackalloc ulong[RoundedCylinderWideLimbCount];
 8425        Span<ulong> second = stackalloc ulong[RoundedCylinderWideLimbCount];
 8426        crossMagnitude.Clear();
 8427        entryTerm.Clear();
 8428        exitTerm.Clear();
 8429        ImportRoundedCylinderWide(cross, crossMagnitude);
 8430        if (hasEntryRadical)
 431        {
 5432            GetRoundedCylinderRadicalSquare(
 5433                exit.Denominator,
 5434                entry.Discriminant,
 5435                entryTerm,
 5436                first,
 5437                second);
 438        }
 8439        if (hasExitRadical)
 440        {
 6441            GetRoundedCylinderRadicalSquare(
 6442                entry.Denominator,
 6443                exit.Discriminant,
 6444                exitTerm,
 6445                first,
 6446                second);
 447        }
 448
 8449        MultiplyRoundedCylinderWide(crossMagnitude, crossMagnitude, crossSquared);
 8450        AddRoundedCylinderSigned(
 8451            entryTerm,
 8452            GetRoundedCylinderWideLength(entryTerm) == 0 ? (sbyte)0 : (sbyte)1,
 8453            exitTerm,
 8454            GetRoundedCylinderWideLength(exitTerm) == 0 ? (sbyte)0 : (sbyte)1,
 8455            termSum,
 8456            out _);
 8457        SubtractRoundedCylinderSigned(
 8458            crossSquared,
 8459            1,
 8460            termSum,
 8461            1,
 8462            difference,
 8463            out sbyte differenceSign);
 8464        if (differenceSign <= 0)
 7465            return true;
 466
 1467        MultiplyRoundedCylinderWide(difference, difference, differenceSquared);
 1468        MultiplyRoundedCylinderWide(entryTerm, exitTerm, termProduct);
 1469        MultiplyRoundedCylinderWideByWord(termProduct, 4UL, right);
 1470        return WideArithmetic.CompareMagnitudeEqualLength(differenceSquared, right) <= 0;
 471    }
 472
 473    private static void GetRoundedCylinderRadicalSquare(
 474        Signed320 coefficient,
 475        Signed576 discriminant,
 476        Span<ulong> destination,
 477        Span<ulong> first,
 478        Span<ulong> second)
 479    {
 11480        ImportRoundedCylinderWide(coefficient, first);
 11481        MultiplyRoundedCylinderWide(first, first, second);
 11482        ImportRoundedCylinderWide(discriminant, first);
 11483        MultiplyRoundedCylinderWide(second, first, destination);
 11484    }
 485
 486    private static void ImportRoundedCylinderWide(Signed320 value, Span<ulong> destination)
 487    {
 11488        destination.Clear();
 11489        WideArithmetic.GetMagnitude(
 11490            value,
 11491            out destination[4],
 11492            out destination[3],
 11493            out destination[2],
 11494            out destination[1],
 11495            out destination[0]);
 11496    }
 497
 498    private static void ImportRoundedCylinderWide(Signed576 value, Span<ulong> destination)
 499    {
 19500        destination.Clear();
 19501        WideArithmetic.GetMagnitude(value, destination[..9]);
 19502    }
 503
 504    private static int GetRoundedCylinderSignVariations(
 505        Span<ulong> coefficients,
 506        Span<sbyte> signs,
 507        Span<int> degrees,
 508        int sequenceCount,
 509        ulong numerator,
 510        ulong denominator)
 511    {
 799512        int variations = 0;
 799513        int previousSign = 0;
 6344514        for (int polynomialIndex = 0; polynomialIndex < sequenceCount; polynomialIndex++)
 515        {
 2373516            int sign = EvaluateRoundedCylinderPolynomialSign(
 2373517                coefficients,
 2373518                signs,
 2373519                degrees[polynomialIndex],
 2373520                polynomialIndex,
 2373521                numerator,
 2373522                denominator);
 2373523            if (sign == 0)
 524                continue;
 2289525            if (previousSign != 0 && sign != previousSign)
 930526                variations++;
 2289527            previousSign = sign;
 528        }
 529
 799530        return variations;
 531    }
 532
 533    private static int EvaluateRoundedCylinderPolynomialSign(
 534        Span<ulong> coefficients,
 535        Span<sbyte> signs,
 536        int degree,
 537        int polynomialIndex,
 538        ulong numerator,
 539        ulong denominator)
 540    {
 4449541        if (denominator == 1UL)
 542        {
 4341543            return EvaluateRoundedCylinderPolynomialSignAtInteger(
 4341544                coefficients,
 4341545                signs,
 4341546                degree,
 4341547                polynomialIndex,
 4341548                numerator);
 549        }
 550
 108551        Span<ulong> result = stackalloc ulong[RoundedCylinderWideLimbCount];
 108552        Span<ulong> scale = stackalloc ulong[RoundedCylinderWideLimbCount];
 108553        Span<ulong> first = stackalloc ulong[RoundedCylinderWideLimbCount];
 108554        Span<ulong> second = stackalloc ulong[RoundedCylinderWideLimbCount];
 108555        Span<ulong> sum = stackalloc ulong[RoundedCylinderWideLimbCount];
 108556        result.Clear();
 108557        scale.Clear();
 108558        CopyRoundedCylinderWide(
 108559            GetRoundedCylinderCoefficient(coefficients, polynomialIndex, degree),
 108560            result);
 108561        sbyte resultSign = signs[GetRoundedCylinderCoefficientIndex(polynomialIndex, degree)];
 108562        scale[0] = denominator;
 563
 926564        for (int coefficientIndex = degree - 1; coefficientIndex >= 0; coefficientIndex--)
 565        {
 355566            MultiplyRoundedCylinderWideByWord(result, numerator, first);
 355567            sbyte firstSign = resultSign;
 355568            MultiplyRoundedCylinderWide(
 355569                GetRoundedCylinderCoefficient(coefficients, polynomialIndex, coefficientIndex),
 355570                scale,
 355571                second);
 355572            sbyte secondSign = signs[GetRoundedCylinderCoefficientIndex(polynomialIndex, coefficientIndex)];
 355573            AddRoundedCylinderSigned(
 355574                first,
 355575                firstSign,
 355576                second,
 355577                secondSign,
 355578                sum,
 355579                out resultSign);
 355580            CopyRoundedCylinderWide(sum, result);
 355581            MultiplyRoundedCylinderWideByWord(scale, denominator, first);
 355582            CopyRoundedCylinderWide(first, scale);
 583        }
 584
 108585        return resultSign;
 586    }
 587
 588    private static int EvaluateRoundedCylinderPolynomialSignAtInteger(
 589        Span<ulong> coefficients,
 590        Span<sbyte> signs,
 591        int degree,
 592        int polynomialIndex,
 593        ulong parameter)
 594    {
 4341595        Span<ulong> result = stackalloc ulong[RoundedCylinderWideLimbCount];
 4341596        Span<ulong> product = stackalloc ulong[RoundedCylinderWideLimbCount];
 4341597        Span<ulong> sum = stackalloc ulong[RoundedCylinderWideLimbCount];
 4341598        result.Clear();
 4341599        CopyRoundedCylinderWide(
 4341600            GetRoundedCylinderCoefficient(coefficients, polynomialIndex, degree),
 4341601            result);
 4341602        sbyte resultSign = signs[GetRoundedCylinderCoefficientIndex(polynomialIndex, degree)];
 603
 37894604        for (int coefficientIndex = degree - 1; coefficientIndex >= 0; coefficientIndex--)
 605        {
 14606606            MultiplyRoundedCylinderWideByWord(result, parameter, product);
 14606607            AddRoundedCylinderSigned(
 14606608                product,
 14606609                resultSign,
 14606610                GetRoundedCylinderCoefficient(coefficients, polynomialIndex, coefficientIndex),
 14606611                signs[GetRoundedCylinderCoefficientIndex(polynomialIndex, coefficientIndex)],
 14606612                sum,
 14606613                out resultSign);
 14606614            CopyRoundedCylinderWide(sum, result);
 615        }
 616
 4341617        return resultSign;
 618    }
 619
 620    private static int BuildRoundedCylinderSturmSequence(
 621        RoundedCylinderTorusPolynomial polynomial,
 622        Span<ulong> coefficients,
 623        Span<sbyte> signs,
 624        Span<int> degrees)
 625    {
 45626        ImportRoundedCylinderCoefficient(polynomial.H0, coefficients, signs, 0, 0);
 45627        ImportRoundedCylinderCoefficient(polynomial.H1, coefficients, signs, 0, 1);
 45628        ImportRoundedCylinderCoefficient(polynomial.H2, coefficients, signs, 0, 2);
 45629        ImportRoundedCylinderCoefficient(polynomial.H3, coefficients, signs, 0, 3);
 45630        ImportRoundedCylinderCoefficient(polynomial.H4, coefficients, signs, 0, 4);
 45631        degrees[0] = TrimRoundedCylinderPolynomial(signs, 0, 4);
 45632        if (degrees[0] < 0)
 1633            return 0;
 44634        if (degrees[0] == 0)
 2635            return 1;
 636
 420637        for (int coefficientIndex = 1; coefficientIndex <= degrees[0]; coefficientIndex++)
 638        {
 168639            int destinationIndex = coefficientIndex - 1;
 168640            MultiplyRoundedCylinderWideByWord(
 168641                GetRoundedCylinderCoefficient(coefficients, 0, coefficientIndex),
 168642                (ulong)coefficientIndex,
 168643                GetRoundedCylinderCoefficient(coefficients, 1, destinationIndex));
 168644            signs[GetRoundedCylinderCoefficientIndex(1, destinationIndex)] =
 168645                signs[GetRoundedCylinderCoefficientIndex(0, coefficientIndex)];
 646        }
 42647        degrees[1] = degrees[0] - 1;
 648
 649        // A nonstationary authored chord makes H4 strictly positive. A
 650        // stationary chord was already reduced to the constant cases above.
 42651        return BuildRoundedCylinderQuarticSturmSequence(coefficients, signs, degrees);
 652    }
 653
 654    private static int BuildRoundedCylinderQuarticSturmSequence(
 655        Span<ulong> coefficients,
 656        Span<sbyte> signs,
 657        Span<int> degrees)
 658    {
 155659        Span<ulong> first = stackalloc ulong[RoundedCylinderWideLimbCount];
 155660        Span<ulong> second = stackalloc ulong[RoundedCylinderWideLimbCount];
 155661        Span<ulong> scratch = stackalloc ulong[RoundedCylinderWideLimbCount];
 155662        Span<ulong> result = stackalloc ulong[RoundedCylinderWideLimbCount];
 663
 155664        ReadOnlySpan<ulong> a = GetRoundedCylinderCoefficient(coefficients, 0, 4);
 155665        ReadOnlySpan<ulong> b = GetRoundedCylinderCoefficient(coefficients, 0, 3);
 155666        ReadOnlySpan<ulong> c = GetRoundedCylinderCoefficient(coefficients, 0, 2);
 155667        ReadOnlySpan<ulong> d = GetRoundedCylinderCoefficient(coefficients, 0, 1);
 155668        ReadOnlySpan<ulong> e = GetRoundedCylinderCoefficient(coefficients, 0, 0);
 155669        sbyte aSign = signs[GetRoundedCylinderCoefficientIndex(0, 4)];
 155670        sbyte bSign = signs[GetRoundedCylinderCoefficientIndex(0, 3)];
 155671        sbyte cSign = signs[GetRoundedCylinderCoefficientIndex(0, 2)];
 155672        sbyte dSign = signs[GetRoundedCylinderCoefficientIndex(0, 1)];
 155673        sbyte eSign = signs[GetRoundedCylinderCoefficientIndex(0, 0)];
 674
 675        // Positive-scaled negative remainder of the quartic and its derivative.
 155676        SetRoundedCylinderScaledProduct(b, bSign, b, bSign, 3UL, first, out sbyte firstSign, scratch);
 155677        SetRoundedCylinderScaledProduct(a, aSign, c, cSign, 8UL, second, out sbyte secondSign, scratch);
 155678        Span<ulong> u = GetRoundedCylinderCoefficient(coefficients, 2, 2);
 155679        SubtractRoundedCylinderSigned(first, firstSign, second, secondSign, u, out sbyte uSign);
 155680        signs[GetRoundedCylinderCoefficientIndex(2, 2)] = uSign;
 681
 155682        SetRoundedCylinderProduct(b, bSign, c, cSign, first, out firstSign);
 155683        SetRoundedCylinderScaledProduct(a, aSign, d, dSign, 6UL, second, out secondSign, scratch);
 155684        SubtractRoundedCylinderSigned(first, firstSign, second, secondSign, result, out sbyte resultSign);
 155685        Span<ulong> v = GetRoundedCylinderCoefficient(coefficients, 2, 1);
 155686        MultiplyRoundedCylinderWideByWord(result, 2UL, v);
 155687        sbyte vSign = resultSign;
 155688        signs[GetRoundedCylinderCoefficientIndex(2, 1)] = vSign;
 689
 155690        SetRoundedCylinderProduct(b, bSign, d, dSign, first, out firstSign);
 155691        SetRoundedCylinderScaledProduct(a, aSign, e, eSign, 16UL, second, out secondSign, scratch);
 155692        Span<ulong> w = GetRoundedCylinderCoefficient(coefficients, 2, 0);
 155693        SubtractRoundedCylinderSigned(first, firstSign, second, secondSign, w, out sbyte wSign);
 155694        signs[GetRoundedCylinderCoefficientIndex(2, 0)] = wSign;
 155695        degrees[2] = TrimRoundedCylinderPolynomial(signs, 2, 2);
 155696        if (degrees[2] < 0)
 6697            return 2;
 149698        if (degrees[2] == 0)
 699        {
 5700            RemoveRoundedCylinderCommonPowerOfTwo(coefficients, signs, 2, 0);
 5701            return 3;
 702        }
 144703        if (degrees[2] == 1)
 704        {
 3705            RemoveRoundedCylinderCommonPowerOfTwo(coefficients, signs, 2, 1);
 3706            int finalDegree = BuildRoundedCylinderNegativeRemainder(
 3707                coefficients,
 3708                signs,
 3709                1,
 3710                3,
 3711                2,
 3712                1,
 3713                3);
 3714            if (finalDegree < 0)
 1715                return 3;
 716
 2717            degrees[3] = finalDegree;
 2718            return 4;
 719        }
 141720        Span<ulong> l = GetRoundedCylinderCoefficient(coefficients, 3, 1);
 141721        Span<ulong> m = GetRoundedCylinderCoefficient(coefficients, 3, 0);
 722
 723        // This factorization divides the ordinary third Sturm polynomial by
 724        // positive 16a. Both two-bit shifts are algebraically exact.
 141725        SetRoundedCylinderScaledProduct(c, cSign, c, cSign, 4UL, first, out firstSign, scratch);
 141726        AddRoundedCylinderSigned(w, wSign, first, firstSign, result, out resultSign);
 141727        SetRoundedCylinderScaledProduct(b, bSign, d, dSign, 9UL, first, out firstSign, scratch);
 141728        SubtractRoundedCylinderSigned(result, resultSign, first, firstSign, l, out sbyte xSign);
 729
 141730        SetRoundedCylinderProduct(c, cSign, d, dSign, first, out firstSign);
 141731        SetRoundedCylinderScaledProduct(b, bSign, e, eSign, 6UL, second, out secondSign, scratch);
 141732        SubtractRoundedCylinderSigned(first, firstSign, second, secondSign, m, out sbyte ySign);
 733
 141734        SetRoundedCylinderProduct(u, uSign, l, xSign, first, out firstSign);
 141735        SetRoundedCylinderProduct(v, vSign, v, vSign, second, out secondSign);
 141736        SubtractRoundedCylinderSigned(first, firstSign, second, secondSign, result, out resultSign);
 141737        ShiftRoundedCylinderWideRight(result, 2);
 141738        CopyRoundedCylinderWide(result, l);
 141739        sbyte lSign = resultSign;
 141740        signs[GetRoundedCylinderCoefficientIndex(3, 1)] = lSign;
 741
 141742        SetRoundedCylinderProduct(u, uSign, m, ySign, first, out firstSign);
 141743        MultiplyRoundedCylinderWideByWord(first, 2UL, second);
 141744        secondSign = firstSign;
 141745        SetRoundedCylinderProduct(v, vSign, w, wSign, first, out firstSign);
 141746        SubtractRoundedCylinderSigned(second, secondSign, first, firstSign, result, out resultSign);
 141747        ShiftRoundedCylinderWideRight(result, 2);
 141748        CopyRoundedCylinderWide(result, m);
 141749        sbyte mSign = resultSign;
 141750        signs[GetRoundedCylinderCoefficientIndex(3, 0)] = mSign;
 751
 141752        RemoveRoundedCylinderCommonPowerOfTwo(coefficients, signs, 2, 2);
 141753        uSign = signs[GetRoundedCylinderCoefficientIndex(2, 2)];
 141754        vSign = signs[GetRoundedCylinderCoefficientIndex(2, 1)];
 141755        wSign = signs[GetRoundedCylinderCoefficientIndex(2, 0)];
 141756        degrees[3] = TrimRoundedCylinderPolynomial(signs, 3, 1);
 141757        if (degrees[3] < 0)
 7758            return 3;
 134759        RemoveRoundedCylinderCommonPowerOfTwo(coefficients, signs, 3, degrees[3]);
 134760        if (degrees[3] == 0)
 2761            return 4;
 762
 132763        Span<ulong> k = GetRoundedCylinderCoefficient(coefficients, 4, 0);
 764        // The last remainder has the quartic discriminant's sign when u != 0.
 765        // Factorized invariants avoid materializing its much wider magnitude.
 132766        SetRoundedCylinderProduct(c, cSign, c, cSign, first, out firstSign);
 132767        SetRoundedCylinderScaledProduct(b, bSign, d, dSign, 3UL, second, out secondSign, scratch);
 132768        SubtractRoundedCylinderSigned(first, firstSign, second, secondSign, result, out resultSign);
 132769        SetRoundedCylinderScaledProduct(a, aSign, e, eSign, 12UL, first, out firstSign, scratch);
 132770        AddRoundedCylinderSigned(result, resultSign, first, firstSign, k, out sbyte delta0Sign);
 771
 132772        SetRoundedCylinderTripleProduct(c, cSign, c, cSign, c, cSign, first, out firstSign, scratch);
 132773        MultiplyRoundedCylinderWideByWord(first, 2UL, second);
 132774        secondSign = firstSign;
 132775        SetRoundedCylinderTripleProduct(b, bSign, c, cSign, d, dSign, first, out firstSign, scratch);
 132776        MultiplyRoundedCylinderWideByWord(first, 9UL, result);
 132777        SubtractRoundedCylinderSigned(second, secondSign, result, firstSign, scratch, out secondSign);
 132778        CopyRoundedCylinderWide(scratch, second);
 132779        SetRoundedCylinderTripleProduct(b, bSign, b, bSign, e, eSign, first, out firstSign, scratch);
 132780        MultiplyRoundedCylinderWideByWord(first, 27UL, result);
 132781        AddRoundedCylinderSigned(second, secondSign, result, firstSign, scratch, out secondSign);
 132782        CopyRoundedCylinderWide(scratch, second);
 132783        SetRoundedCylinderTripleProduct(a, aSign, d, dSign, d, dSign, first, out firstSign, scratch);
 132784        MultiplyRoundedCylinderWideByWord(first, 27UL, result);
 132785        AddRoundedCylinderSigned(second, secondSign, result, firstSign, scratch, out secondSign);
 132786        CopyRoundedCylinderWide(scratch, second);
 132787        SetRoundedCylinderTripleProduct(a, aSign, c, cSign, e, eSign, first, out firstSign, scratch);
 132788        MultiplyRoundedCylinderWideByWord(first, 72UL, result);
 132789        SubtractRoundedCylinderSigned(second, secondSign, result, firstSign, scratch, out secondSign);
 132790        CopyRoundedCylinderWide(scratch, second);
 791
 132792        SetRoundedCylinderTripleProduct(k, delta0Sign, k, delta0Sign, k, delta0Sign, first, out firstSign, scratch);
 132793        MultiplyRoundedCylinderWideByWord(first, 4UL, result);
 132794        SetRoundedCylinderProduct(second, secondSign, second, secondSign, scratch, out sbyte delta1SquaredSign);
 132795        SubtractRoundedCylinderSigned(result, firstSign, scratch, delta1SquaredSign, first, out sbyte kSign);
 132796        k.Clear();
 132797        if (kSign != 0)
 116798            k[0] = 1UL;
 132799        signs[GetRoundedCylinderCoefficientIndex(4, 0)] = kSign;
 132800        if (kSign == 0)
 16801            return 4;
 116802        degrees[4] = 0;
 116803        return 5;
 804    }
 805
 806    private static void SetRoundedCylinderProduct(
 807        ReadOnlySpan<ulong> left,
 808        sbyte leftSign,
 809        ReadOnlySpan<ulong> right,
 810        sbyte rightSign,
 811        Span<ulong> destination,
 812        out sbyte destinationSign)
 813    {
 1279814        MultiplyRoundedCylinderWide(left, right, destination);
 1279815        destinationSign = MultiplyRoundedCylinderSigns(leftSign, rightSign);
 1279816    }
 817
 818    private static void SetRoundedCylinderScaledProduct(
 819        ReadOnlySpan<ulong> left,
 820        sbyte leftSign,
 821        ReadOnlySpan<ulong> right,
 822        sbyte rightSign,
 823        ulong scale,
 824        Span<ulong> destination,
 825        out sbyte destinationSign,
 826        Span<ulong> scratch)
 827    {
 1307828        MultiplyRoundedCylinderWide(left, right, scratch);
 1307829        MultiplyRoundedCylinderWideByWord(scratch, scale, destination);
 1307830        destinationSign = MultiplyRoundedCylinderSigns(leftSign, rightSign);
 1307831    }
 832
 833    private static void SetRoundedCylinderTripleProduct(
 834        ReadOnlySpan<ulong> first,
 835        sbyte firstSign,
 836        ReadOnlySpan<ulong> second,
 837        sbyte secondSign,
 838        ReadOnlySpan<ulong> third,
 839        sbyte thirdSign,
 840        Span<ulong> destination,
 841        out sbyte destinationSign,
 842        Span<ulong> scratch)
 843    {
 792844        MultiplyRoundedCylinderWide(first, second, scratch);
 792845        MultiplyRoundedCylinderWide(scratch, third, destination);
 792846        destinationSign = MultiplyRoundedCylinderSigns(
 792847            MultiplyRoundedCylinderSigns(firstSign, secondSign),
 792848            thirdSign);
 792849    }
 850
 851    private static int BuildRoundedCylinderNegativeRemainder(
 852        Span<ulong> coefficients,
 853        Span<sbyte> signs,
 854        int dividendIndex,
 855        int dividendDegree,
 856        int divisorIndex,
 857        int divisorDegree,
 858        int destinationIndex)
 859    {
 30860        for (int coefficientIndex = 0; coefficientIndex <= dividendDegree; coefficientIndex++)
 861        {
 12862            CopyRoundedCylinderWide(
 12863                GetRoundedCylinderCoefficient(coefficients, dividendIndex, coefficientIndex),
 12864                GetRoundedCylinderCoefficient(coefficients, destinationIndex, coefficientIndex));
 12865            signs[GetRoundedCylinderCoefficientIndex(destinationIndex, coefficientIndex)] =
 12866                signs[GetRoundedCylinderCoefficientIndex(dividendIndex, coefficientIndex)];
 867        }
 868
 3869        Span<ulong> leadingRemainder = stackalloc ulong[RoundedCylinderWideLimbCount];
 3870        Span<ulong> leadingDivisor = stackalloc ulong[RoundedCylinderWideLimbCount];
 3871        Span<ulong> first = stackalloc ulong[RoundedCylinderWideLimbCount];
 3872        Span<ulong> second = stackalloc ulong[RoundedCylinderWideLimbCount];
 3873        Span<ulong> difference = stackalloc ulong[RoundedCylinderWideLimbCount];
 3874        CopyRoundedCylinderWide(
 3875            GetRoundedCylinderCoefficient(coefficients, divisorIndex, divisorDegree),
 3876            leadingDivisor);
 3877        sbyte leadingDivisorSign = signs[GetRoundedCylinderCoefficientIndex(divisorIndex, divisorDegree)];
 3878        int remainderDegree = dividendDegree;
 3879        int multiplicationCount = 0;
 11880        while (remainderDegree >= divisorDegree)
 881        {
 9882            CopyRoundedCylinderWide(
 9883                GetRoundedCylinderCoefficient(coefficients, destinationIndex, remainderDegree),
 9884                leadingRemainder);
 9885            sbyte leadingRemainderSign = signs[
 9886                GetRoundedCylinderCoefficientIndex(destinationIndex, remainderDegree)];
 9887            int offset = remainderDegree - divisorDegree;
 888
 72889            for (int coefficientIndex = 0; coefficientIndex <= remainderDegree; coefficientIndex++)
 890            {
 27891                Span<ulong> remainderCoefficient = GetRoundedCylinderCoefficient(
 27892                    coefficients,
 27893                    destinationIndex,
 27894                    coefficientIndex);
 27895                MultiplyRoundedCylinderWide(
 27896                    leadingDivisor,
 27897                    remainderCoefficient,
 27898                    first);
 27899                sbyte firstSign = MultiplyRoundedCylinderSigns(
 27900                    leadingDivisorSign,
 27901                    signs[GetRoundedCylinderCoefficientIndex(destinationIndex, coefficientIndex)]);
 902
 27903                int divisorCoefficientIndex = coefficientIndex - offset;
 904                sbyte secondSign;
 27905                if (divisorCoefficientIndex >= 0 && divisorCoefficientIndex <= divisorDegree)
 906                {
 18907                    MultiplyRoundedCylinderWide(
 18908                        leadingRemainder,
 18909                        GetRoundedCylinderCoefficient(coefficients, divisorIndex, divisorCoefficientIndex),
 18910                        second);
 18911                    secondSign = MultiplyRoundedCylinderSigns(
 18912                        leadingRemainderSign,
 18913                        signs[GetRoundedCylinderCoefficientIndex(divisorIndex, divisorCoefficientIndex)]);
 914                }
 915                else
 916                {
 9917                    second.Clear();
 9918                    secondSign = 0;
 919                }
 920
 27921                SubtractRoundedCylinderSigned(
 27922                    first,
 27923                    firstSign,
 27924                    second,
 27925                    secondSign,
 27926                    difference,
 27927                    out sbyte differenceSign);
 27928                CopyRoundedCylinderWide(difference, remainderCoefficient);
 27929                signs[GetRoundedCylinderCoefficientIndex(destinationIndex, coefficientIndex)] = differenceSign;
 930            }
 931
 9932            multiplicationCount++;
 9933            remainderDegree = TrimRoundedCylinderPolynomial(
 9934                signs,
 9935                destinationIndex,
 9936                remainderDegree - 1);
 9937            if (remainderDegree < 0)
 1938                return -1;
 939        }
 940
 2941        bool pseudoScaleIsPositive = leadingDivisorSign > 0 || (multiplicationCount & 1) == 0;
 2942        if (pseudoScaleIsPositive)
 943        {
 4944            for (int coefficientIndex = 0; coefficientIndex <= remainderDegree; coefficientIndex++)
 945            {
 1946                int signIndex = GetRoundedCylinderCoefficientIndex(destinationIndex, coefficientIndex);
 1947                signs[signIndex] = (sbyte)-signs[signIndex];
 948            }
 949        }
 950
 2951        RemoveRoundedCylinderCommonPowerOfTwo(
 2952            coefficients,
 2953            signs,
 2954            destinationIndex,
 2955            remainderDegree);
 2956        return remainderDegree;
 957    }
 958
 959    private static void RemoveRoundedCylinderCommonPowerOfTwo(
 960        Span<ulong> coefficients,
 961        Span<sbyte> signs,
 962        int polynomialIndex,
 963        int degree)
 964    {
 285965        int commonShift = int.MaxValue;
 1974966        for (int coefficientIndex = 0; coefficientIndex <= degree; coefficientIndex++)
 967        {
 702968            if (signs[GetRoundedCylinderCoefficientIndex(polynomialIndex, coefficientIndex)] == 0)
 969                continue;
 605970            commonShift = Math.Min(
 605971                commonShift,
 605972                CountRoundedCylinderTrailingZeroes(
 605973                    GetRoundedCylinderCoefficient(coefficients, polynomialIndex, coefficientIndex)));
 974        }
 975
 1974976        for (int coefficientIndex = 0; coefficientIndex <= degree; coefficientIndex++)
 977        {
 702978            if (signs[GetRoundedCylinderCoefficientIndex(polynomialIndex, coefficientIndex)] != 0)
 979            {
 605980                ShiftRoundedCylinderWideRight(
 605981                    GetRoundedCylinderCoefficient(coefficients, polynomialIndex, coefficientIndex),
 605982                    commonShift);
 983            }
 984        }
 285985    }
 986
 987    private static int TrimRoundedCylinderPolynomial(
 988        Span<sbyte> signs,
 989        int polynomialIndex,
 990        int degree)
 991    {
 411992        while (degree >= 0
 411993            && signs[GetRoundedCylinderCoefficientIndex(polynomialIndex, degree)] == 0)
 994        {
 61995            degree--;
 996        }
 350997        return degree;
 998    }
 999
 1000}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteAxisIntersection.Witness.cs

#LineLine coverage
 1//=======================================================================
 2// WideFiniteAxisIntersection.Witness.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
 8namespace FixedMathSharp.Geometry;
 9
 10/// <content>
 11/// Provides witness/support point computation for finite axis and capsule
 12/// intersection queries, including centered axis endpoints and capsule supports.
 13/// </content>
 14internal static partial class WideFiniteAxisIntersection
 15{
 116    private static readonly Signed192 DirectionRootScale = new(0UL, 1UL, 0UL);
 17
 18    internal static bool TryGetCenteredAxisEndpoint(
 19        Vector2d center,
 20        Vector2d axis,
 21        Fixed64 axisLength,
 22        bool positive,
 23        out Vector2d endpoint) =>
 224        TryGetCenteredSupport(
 225            center,
 226            axis,
 227            axisLength,
 228            Fixed64.Zero,
 229            default,
 230            default,
 231            default,
 232            positive,
 233            out endpoint);
 34
 35    internal static bool TryGetCenteredAxisEndpoint(
 36        Vector3d center,
 37        Vector3d axis,
 38        Fixed64 axisLength,
 39        bool positive,
 40        out Vector3d endpoint) =>
 13841        TryGetCenteredSupport(
 13842            center,
 13843            axis,
 13844            axisLength,
 13845            Fixed64.Zero,
 13846            default,
 13847            default,
 13848            default,
 13849            default,
 13850            positive,
 13851            out endpoint);
 52
 53    internal static bool TryGetCenteredCapsuleSupport(
 54        Vector2d center,
 55        Vector2d axis,
 56        Fixed64 axisLength,
 57        Fixed64 radius,
 58        Vector2d direction,
 59        out Vector2d support)
 60    {
 461        GetDirection(direction, out Signed192 radialX, out Signed192 radialY, out Signed320 radialSquared);
 462        int axialSign = GetDot(axis, Vector2d.Zero, direction, Vector2d.Zero).Sign;
 463        return TryGetCenteredSupport(
 464            center,
 465            axis,
 466            axialSign == 0 ? Fixed64.Zero : axisLength,
 467            radius,
 468            radialX,
 469            radialY,
 470            radialSquared,
 471            axialSign > 0,
 472            out support);
 73    }
 74
 75    internal static FixedPointAnchor2d GetCenteredCapsuleSupportAnchor(
 76        Vector2d center,
 77        Fixed64 frameRotation,
 78        Vector2d localAxis,
 79        Fixed64 axisLength,
 80        Fixed64 radius,
 81        Vector2d localDirection)
 82    {
 18383        int axialSign =
 18384            GetDot(
 18385                localAxis,
 18386                Vector2d.Zero,
 18387                localDirection,
 18388                Vector2d.Zero).Sign;
 18389        Fixed64 halfLength = axialSign == 0
 18390            ? Fixed64.Zero
 18391            : axisLength / Fixed64.Two;
 18392        Vector2d axialOffset =
 18393            localAxis * (axialSign > 0 ? halfLength : -halfLength);
 18394        Vector2d radialDirection =
 18395            WideNormalization.GetNormalized(localDirection);
 18396        Vector2d radialOffset = radialDirection * radius;
 18397        FixedPointAnchorTerm2d exactLocalTerm =
 18398            FixedPointAnchorTerm2d.CreateCenteredAxisSupport(
 18399                localAxis,
 183100                axialSign == 0
 183101                    ? Fixed64.Zero
 183102                    : axialSign > 0
 183103                        ? axisLength
 183104                        : -axisLength,
 183105                radialDirection,
 183106                radius,
 183107                axialOffset,
 183108                radialOffset);
 183109        return new FixedPointAnchor2d(
 183110            center,
 183111            frameRotation,
 183112            axialOffset,
 183113            radialOffset,
 183114            exactLocalTerm);
 115    }
 116
 117    internal static bool TryGetCenteredCapsuleSupport(
 118        Vector3d center,
 119        Vector3d axis,
 120        Fixed64 axisLength,
 121        Fixed64 radius,
 122        Vector3d direction,
 123        out Vector3d support)
 124    {
 141125        GetDirection(
 141126            direction,
 141127            out Signed192 radialX,
 141128            out Signed192 radialY,
 141129            out Signed192 radialZ,
 141130            out Signed320 radialSquared);
 141131        int axialSign = GetDot(axis, Vector3d.Zero, direction, Vector3d.Zero).Sign;
 141132        return TryGetCenteredSupport(
 141133            center,
 141134            axis,
 141135            axialSign == 0 ? Fixed64.Zero : axisLength,
 141136            radius,
 141137            radialX,
 141138            radialY,
 141139            radialZ,
 141140            radialSquared,
 141141            axialSign > 0,
 141142            out support);
 143    }
 144
 145    internal static bool TryGetCenteredFiniteCylinderSupport(
 146        Vector3d center,
 147        Vector3d axis,
 148        Fixed64 axisLength,
 149        Fixed64 radius,
 150        Vector3d direction,
 151        out Vector3d support)
 152    {
 137153        GetPlaneDirection(
 137154            direction,
 137155            axis,
 137156            out Signed192 radialX,
 137157            out Signed192 radialY,
 137158            out Signed192 radialZ,
 137159            out Signed320 radialSquared);
 137160        return TryGetCenteredSupport(
 137161            center,
 137162            axis,
 137163            axisLength,
 137164            radius,
 137165            radialX,
 137166            radialY,
 137167            radialZ,
 137168            radialSquared,
 137169            GetDot(axis, Vector3d.Zero, direction, Vector3d.Zero).Sign > 0,
 137170            out support);
 171    }
 172
 173    internal static bool TryGetCenteredFiniteConeSupport(
 174        Vector3d center,
 175        Vector3d axis,
 176        Fixed64 height,
 177        Fixed64 radius,
 178        Vector3d direction,
 179        out Vector3d support)
 180    {
 136181        GetPlaneDirection(
 136182            direction,
 136183            axis,
 136184            out Signed192 radialX,
 136185            out Signed192 radialY,
 136186            out Signed192 radialZ,
 136187            out Signed320 radialSquared);
 136188        bool apex = IsCenteredFiniteConeApexSupportCore(
 136189            axis,
 136190            height,
 136191            radius,
 136192            direction,
 136193            radialX,
 136194            radialY,
 136195            radialZ,
 136196            radialSquared);
 136197        return TryGetCenteredSupport(
 136198            center,
 136199            axis,
 136200            height,
 136201            apex ? Fixed64.Zero : radius,
 136202            apex ? default : radialX,
 136203            apex ? default : radialY,
 136204            apex ? default : radialZ,
 136205            apex ? default : radialSquared,
 136206            apex,
 136207            out support);
 208    }
 209
 210    private static bool TryGetCenteredSupport(
 211        Vector2d center,
 212        Vector2d axis,
 213        Fixed64 axisLength,
 214        Fixed64 radius,
 215        Signed192 radialX,
 216        Signed192 radialY,
 217        Signed320 radialSquared,
 218        bool positive,
 219        out Vector2d support)
 220    {
 6221        bool representable = TryGetSupportCoordinate(
 6222                center.X, axis.X, axisLength, radius, radialX, radialSquared, positive, out Fixed64 x)
 6223            & TryGetSupportCoordinate(
 6224                center.Y, axis.Y, axisLength, radius, radialY, radialSquared, positive, out Fixed64 y);
 6225        if (!representable)
 226        {
 2227            support = default;
 2228            return false;
 229        }
 230
 4231        support = new Vector2d(x, y);
 4232        return true;
 233    }
 234
 235    private static bool TryGetCenteredSupport(
 236        Vector3d center,
 237        Vector3d axis,
 238        Fixed64 axisLength,
 239        Fixed64 radius,
 240        Signed192 radialX,
 241        Signed192 radialY,
 242        Signed192 radialZ,
 243        Signed320 radialSquared,
 244        bool positive,
 245        out Vector3d support)
 246    {
 552247        bool representable = TryGetSupportCoordinate(
 552248                center.X, axis.X, axisLength, radius, radialX, radialSquared, positive, out Fixed64 x)
 552249            & TryGetSupportCoordinate(
 552250                center.Y, axis.Y, axisLength, radius, radialY, radialSquared, positive, out Fixed64 y)
 552251            & TryGetSupportCoordinate(
 552252                center.Z, axis.Z, axisLength, radius, radialZ, radialSquared, positive, out Fixed64 z);
 552253        if (!representable)
 254        {
 10255            support = default;
 10256            return false;
 257        }
 258
 542259        support = new Vector3d(x, y, z);
 542260        return true;
 261    }
 262
 263    private static bool TryGetSupportCoordinate(
 264        Fixed64 center,
 265        Fixed64 axis,
 266        Fixed64 axisLength,
 267        Fixed64 radius,
 268        Signed192 radial,
 269        Signed320 radialSquared,
 270        bool positive,
 271        out Fixed64 coordinate)
 272    {
 1668273        Signed192 signedLength = Signed192.Signed(axisLength.m_rawValue);
 1668274        if (!positive)
 1251275            signedLength = WideArithmetic.SubtractSigned192(default, signedLength);
 1668276        Signed320 baseNumerator = WideArithmetic.AddSigned320(
 1668277            WideArithmetic.MultiplySigned192(
 1668278                Signed192.Signed(center.m_rawValue),
 1668279                DoubleParameterScale),
 1668280            WideArithmetic.MultiplySigned192(
 1668281                Signed192.Signed(axis.m_rawValue),
 1668282                signedLength));
 1668283        if (radius == Fixed64.Zero || radialSquared.IsZero)
 284        {
 436285            return Fixed64.TryGetSignedRawRatio(
 436286                Signed576.ExtendValue(baseNumerator),
 436287                Signed576.ExtendValue(
 436288                    Signed320.ExtendValue(DoubleParameterScale)),
 436289                out coordinate);
 290        }
 291
 1232292        Signed320 radialFactor = WideArithmetic.MultiplySigned192(
 1232293            Signed192.Signed(radius.m_rawValue),
 1232294            radial);
 1232295        if (CompareSupportCoordinateToMidpoint(
 1232296                baseNumerator,
 1232297                radialFactor,
 1232298                radialSquared,
 1232299                GetMinimumMidpoint()) < 0
 1232300            || CompareSupportCoordinateToMidpoint(
 1232301                baseNumerator,
 1232302                radialFactor,
 1232303                radialSquared,
 1232304                GetMaximumMidpoint()) >= 0)
 305        {
 8306            coordinate = default;
 8307            return false;
 308        }
 309
 310        // The square-root helper contributes one Q32.32 scale. Pre-scaling
 311        // the radicand by another scale yields floor(sqrt(q) * 2^64), keeping
 312        // the candidate within a sub-raw-unit interval before exact correction.
 1224313        Signed576 scaledSquared = WideArithmetic.MultiplySigned576(
 1224314            Signed576.ExtendValue(radialSquared),
 1224315            DirectionRootScale);
 1224316        Signed320 scaledRoot = WideArithmetic.GetFloorSquareRootScaledByFixed64(scaledSquared);
 1224317        Signed576 numerator = WideArithmetic.AddSigned576(
 1224318            WideArithmetic.MultiplySigned320(baseNumerator, scaledRoot),
 1224319            WideArithmetic.MultiplySigned576(
 1224320                WideArithmetic.MultiplySigned576(
 1224321                    Signed576.ExtendValue(radialFactor),
 1224322                    DirectionRootScale),
 1224323                DoubleParameterScale));
 1224324        Signed576 denominator = WideArithmetic.MultiplySigned320(
 1224325            scaledRoot,
 1224326            Signed320.ExtendValue(DoubleParameterScale));
 1224327        if (!Fixed64.TryGetSignedRawRatio(numerator, denominator, out coordinate))
 328        {
 2329            coordinate = numerator.Sign < 0 ? Fixed64.MinValue : Fixed64.MaxValue;
 330        }
 331
 1224332        long raw = coordinate.m_rawValue;
 333        // A nonzero nonsquare radical cannot equal a rational half-step; when
 334        // the radical is rational, scaledRoot is exact and already rounds ties
 335        // to even. Only a strict midpoint crossing can need correction.
 1224336        if (raw > long.MinValue)
 337        {
 1223338            Signed192 lowerMidpoint = WideArithmetic.SubtractSigned192(
 1223339                WideArithmetic.AddSigned192(
 1223340                    Signed192.Signed(raw),
 1223341                    Signed192.Signed(raw)),
 1223342                Scale);
 1223343            int lowerComparison = CompareSupportCoordinateToMidpoint(
 1223344                baseNumerator,
 1223345                radialFactor,
 1223346                radialSquared,
 1223347                lowerMidpoint);
 1223348            if (lowerComparison < 0)
 349            {
 3350                coordinate = Fixed64.FromRaw(raw - 1L);
 3351                return true;
 352            }
 353        }
 354
 1221355        if (raw < long.MaxValue)
 356        {
 1220357            Signed192 upperMidpoint = WideArithmetic.AddSigned192(
 1220358                WideArithmetic.AddSigned192(
 1220359                    Signed192.Signed(raw),
 1220360                    Signed192.Signed(raw)),
 1220361                Scale);
 1220362            int upperComparison = CompareSupportCoordinateToMidpoint(
 1220363                baseNumerator,
 1220364                radialFactor,
 1220365                radialSquared,
 1220366                upperMidpoint);
 1220367            if (upperComparison > 0)
 3368                coordinate = Fixed64.FromRaw(raw + 1L);
 369        }
 370
 1221371        return true;
 372    }
 373
 374    private static int CompareSupportCoordinateToMidpoint(
 375        Signed320 baseNumerator,
 376        Signed320 radialFactor,
 377        Signed320 radialSquared,
 378        Signed192 midpointTwice)
 379    {
 4906380        Signed320 rational = WideArithmetic.SubtractSigned320(
 4906381            WideArithmetic.AddSigned320(baseNumerator, baseNumerator),
 4906382            WideArithmetic.MultiplySigned192(midpointTwice, DoubleParameterScale));
 4906383        int rationalSign = rational.Sign;
 4906384        int radialSign = radialFactor.Sign;
 4906385        if (rationalSign == 0)
 1386            return radialSign;
 4905387        if (radialSign == 0 || rationalSign == radialSign)
 3672388            return rationalSign;
 389
 1233390        Signed832 rationalSquared = WideArithmetic.MultiplySigned576ToSigned832(
 1233391            WideArithmetic.MultiplySigned320(rational, rational),
 1233392            Signed576.ExtendValue(radialSquared));
 1233393        Signed192 doubleDenominator = WideArithmetic.AddSigned192(
 1233394            DoubleParameterScale,
 1233395            DoubleParameterScale);
 1233396        Signed832 radialSquaredValue = WideArithmetic.MultiplySigned576ToSigned832(
 1233397            WideArithmetic.MultiplySigned320(radialFactor, radialFactor),
 1233398            Signed576.ExtendValue(
 1233399                WideArithmetic.MultiplySigned192(doubleDenominator, doubleDenominator)));
 1233400        int magnitudeComparison = WideArithmetic.SubtractSigned832(
 1233401            rationalSquared,
 1233402            radialSquaredValue).Sign;
 1233403        return rationalSign * magnitudeComparison;
 404    }
 405
 406    internal static bool IsCenteredFiniteConeApexSupport(
 407        Vector3d axis,
 408        Fixed64 height,
 409        Fixed64 radius,
 410        Vector3d direction)
 411    {
 4304412        GetPlaneDirection(
 4304413            direction,
 4304414            axis,
 4304415            out Signed192 radialX,
 4304416            out Signed192 radialY,
 4304417            out Signed192 radialZ,
 4304418            out Signed320 radialSquared);
 4304419        return IsCenteredFiniteConeApexSupportCore(
 4304420            axis,
 4304421            height,
 4304422            radius,
 4304423            direction,
 4304424            radialX,
 4304425            radialY,
 4304426            radialZ,
 4304427            radialSquared);
 428    }
 429
 430    private static bool IsCenteredFiniteConeApexSupportCore(
 431        Vector3d axis,
 432        Fixed64 height,
 433        Fixed64 radius,
 434        Vector3d direction,
 435        Signed192 radialX,
 436        Signed192 radialY,
 437        Signed192 radialZ,
 438        Signed320 radialSquared)
 439    {
 4440440        Signed320 axisTerm = WideArithmetic.MultiplySigned192(
 4440441            GetDot(axis, Vector3d.Zero, direction, Vector3d.Zero),
 4440442            Signed192.Signed(height.m_rawValue));
 4440443        if (axisTerm.Sign <= 0)
 4029444            return false;
 411445        if (radius == Fixed64.Zero || radialSquared.IsZero)
 127446            return true;
 447
 284448        Signed320 radialProjection = WideArithmetic.AddSigned320(
 284449            WideArithmetic.AddSigned320(
 284450                WideArithmetic.MultiplySigned192(
 284451                    radialX,
 284452                    Signed192.Signed(direction.X.m_rawValue)),
 284453                WideArithmetic.MultiplySigned192(
 284454                    radialY,
 284455                    Signed192.Signed(direction.Y.m_rawValue))),
 284456            WideArithmetic.MultiplySigned192(
 284457                radialZ,
 284458                Signed192.Signed(direction.Z.m_rawValue)));
 284459        Signed576 radialTerm = WideArithmetic.MultiplySigned576(
 284460            WideArithmetic.MultiplySigned320(
 284461                radialProjection,
 284462                Signed320.ExtendValue(
 284463                    Signed192.Signed(radius.m_rawValue))),
 284464            ParameterScale);
 284465        Signed832 axisSquared = WideArithmetic.MultiplySigned576ToSigned832(
 284466            WideArithmetic.MultiplySigned320(axisTerm, axisTerm),
 284467            Signed576.ExtendValue(radialSquared));
 284468        Signed832 radialTermSquared = WideArithmetic.MultiplySigned576ToSigned832(
 284469            radialTerm,
 284470            radialTerm);
 284471        return WideArithmetic.SubtractSigned832(axisSquared, radialTermSquared).Sign > 0;
 472    }
 473
 474    private static void GetDirection(
 475        Vector2d direction,
 476        out Signed192 x,
 477        out Signed192 y,
 478        out Signed320 squared)
 479    {
 4480        x = Signed192.Signed(direction.X.m_rawValue);
 4481        y = Signed192.Signed(direction.Y.m_rawValue);
 4482        squared = WideArithmetic.AddSigned320(
 4483            WideArithmetic.MultiplySigned192(x, x),
 4484            WideArithmetic.MultiplySigned192(y, y));
 4485    }
 486
 487    private static void GetDirection(
 488        Vector3d direction,
 489        out Signed192 x,
 490        out Signed192 y,
 491        out Signed192 z,
 492        out Signed320 squared)
 493    {
 141494        x = Signed192.Signed(direction.X.m_rawValue);
 141495        y = Signed192.Signed(direction.Y.m_rawValue);
 141496        z = Signed192.Signed(direction.Z.m_rawValue);
 141497        squared = WideArithmetic.AddSigned320(
 141498            WideArithmetic.AddSigned320(
 141499                WideArithmetic.MultiplySigned192(x, x),
 141500                WideArithmetic.MultiplySigned192(y, y)),
 141501            WideArithmetic.MultiplySigned192(z, z));
 141502    }
 503
 504    private static void GetPlaneDirection(
 505        Vector3d direction,
 506        Vector3d axis,
 507        out Signed192 x,
 508        out Signed192 y,
 509        out Signed192 z,
 510        out Signed320 squared)
 511    {
 4577512        Signed192 axisSquared = GetDot(axis, Vector3d.Zero, axis, Vector3d.Zero);
 4577513        Signed192 projection = GetDot(axis, Vector3d.Zero, direction, Vector3d.Zero);
 4577514        x = Signed192.NarrowValue(WideArithmetic.MultiplySubtract(
 4577515            axisSquared,
 4577516            Signed192.Signed(direction.X.m_rawValue),
 4577517            Signed192.Signed(axis.X.m_rawValue),
 4577518            projection));
 4577519        y = Signed192.NarrowValue(WideArithmetic.MultiplySubtract(
 4577520            axisSquared,
 4577521            Signed192.Signed(direction.Y.m_rawValue),
 4577522            Signed192.Signed(axis.Y.m_rawValue),
 4577523            projection));
 4577524        z = Signed192.NarrowValue(WideArithmetic.MultiplySubtract(
 4577525            axisSquared,
 4577526            Signed192.Signed(direction.Z.m_rawValue),
 4577527            Signed192.Signed(axis.Z.m_rawValue),
 4577528            projection));
 4577529        squared = WideArithmetic.AddSigned320(
 4577530            WideArithmetic.AddSigned320(
 4577531                WideArithmetic.MultiplySigned192(x, x),
 4577532                WideArithmetic.MultiplySigned192(y, y)),
 4577533            WideArithmetic.MultiplySigned192(z, z));
 4577534    }
 535
 536    private static Signed192 GetMinimumMidpoint() =>
 1232537        WideArithmetic.SubtractSigned192(
 1232538            WideArithmetic.AddSigned192(
 1232539                Signed192.Signed(long.MinValue),
 1232540                Signed192.Signed(long.MinValue)),
 1232541            Scale);
 542
 543    private static Signed192 GetMaximumMidpoint() =>
 1231544        WideArithmetic.AddSigned192(
 1231545            WideArithmetic.AddSigned192(
 1231546                Signed192.Signed(long.MaxValue),
 1231547                Signed192.Signed(long.MaxValue)),
 1231548            Scale);
 549}

Methods/Properties

.ctor(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed832)
.ctor(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed320,FixedMathSharp.Signed832)
TryGetDistanceToCenteredAxis(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
TryGetDistanceToCenteredAxis(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
TryGetDistanceBetweenCenteredAxes(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
TryGetDistanceBetweenCenteredAxes(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
DoCenteredCapsulesOverlap(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
DoCenteredCapsulesOverlap(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
TryGetCenteredCapsulesContact(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Geometry.FixedContactAnchors2d&)
TryGetCenteredCapsulesContact(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedContactAnchors&)
TryGetClosestPointsBetweenCenteredAxes(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d&,FixedMathSharp.Vector2d&)
TryGetClosestPointsBetweenCenteredAxes(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&)
TryGetClosestOffsetsBetweenCenteredAxes(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&)
GetClosestDirectionBetweenCenteredAxes(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64)
GetClosestCenteredAxisParameters(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&)
GetCenteredAxesSquaredDistance(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Signed832&,FixedMathSharp.Signed320&)
GetCenteredAxesCandidate(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.WideFiniteAxisIntersection/CenteredAxesCandidate2d&)
GetCenteredAxesSquaredDistance(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Signed832&,FixedMathSharp.Signed320&)
GetCenteredAxesCandidate(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.WideFiniteAxisIntersection/CenteredAxesCandidate&)
IsWithinCombinedRadius(FixedMathSharp.Signed832,FixedMathSharp.Signed320,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
ProjectSecondFromCenteredAxisCap(FixedMathSharp.Signed320,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&)
ProjectFirstFromCenteredAxisCap(FixedMathSharp.Signed320,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&)
ClampCenteredAxisParameter(FixedMathSharp.Signed320&,FixedMathSharp.Signed320&,FixedMathSharp.Fixed64)
SetCenteredAxisCap(FixedMathSharp.Signed320&,FixedMathSharp.Signed320&,FixedMathSharp.Fixed64)
TryRoundCenteredAxesDistance(FixedMathSharp.Signed832,FixedMathSharp.Signed320,FixedMathSharp.Fixed64&)
GetHalfToEvenIncrement(System.Int32,System.Int64)
TryGetCenteredAxisPointCoordinate(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Fixed64&)
GetCenteredAxisPointNumerator(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Signed320,FixedMathSharp.Signed320)
GetCenteredAxisLocalOffset(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Vector2d,FixedMathSharp.Signed320,FixedMathSharp.Fixed64)
GetLocalRadialFeature(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d&,FixedMathSharp.Vector2d&)
TryGetCenteredCapsulesDepth(FixedMathSharp.Signed832,FixedMathSharp.Signed320,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,System.Boolean&)
GetCenteredRadiusDepth(FixedMathSharp.Signed832,FixedMathSharp.Signed576,FixedMathSharp.Signed192,FixedMathSharp.Fixed64&,System.Boolean&)
CompareSquaredDistanceToCenteredDepthThreshold(FixedMathSharp.Signed832,FixedMathSharp.Signed576,FixedMathSharp.Signed192,System.Boolean)
.ctor(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed832)
TryGetClosestPointsToCenteredAxis(FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&)
DoesCenteredCapsuleTriangleOverlap(FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
TryGetCenteredCapsuleTriangleContact(FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&)
TryGetCenteredCapsuleTriangleLocalContact(FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&,System.Boolean&)
GetClosestCenteredAxisTriangleCandidate(FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.WideFiniteAxisIntersection/AxisTriangleCandidate&)
TryGetCenteredAxisTriangleFaceCandidate(FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.WideFiniteAxisIntersection/AxisTriangleCandidate&)
KeepCenteredAxisTriangleEdgeCandidate(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,System.Boolean&,FixedMathSharp.Geometry.WideFiniteAxisIntersection/AxisTriangleCandidate&)
GetClosestCenteredAxisSegmentParameters(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&)
ClampUnitParameter(FixedMathSharp.Signed320&,FixedMathSharp.Signed320&)
ProjectEdgeFromCenteredCap(FixedMathSharp.Signed320,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&)
ProjectAxisFromEdgeCap(FixedMathSharp.Signed320,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&)
SetUnitCapAtCenteredDenominator(FixedMathSharp.Signed320&,FixedMathSharp.Signed320&)
GetRationalPoint(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&)
GetRationalSegmentPoint(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&)
GetRationalCoordinate(FixedMathSharp.Fixed64,FixedMathSharp.Signed192,FixedMathSharp.Signed320,FixedMathSharp.Signed320)
CreateAxisTriangleCandidate(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576)
GetCenteredCapsuleTriangleDepth(FixedMathSharp.Geometry.WideFiniteAxisIntersection/AxisTriangleCandidate,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,System.Boolean&)
ContainsTriangleProjection(FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576)
IsInsideTriangleEdge(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576)
SubtractVertex(FixedMathSharp.Signed576,FixedMathSharp.Fixed64,FixedMathSharp.Signed320)
SubtractVertex(FixedMathSharp.Signed576,FixedMathSharp.Fixed64,FixedMathSharp.Signed576)
GetWideDot(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
GetTriangleNormal(FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Signed192&,FixedMathSharp.Signed192&,FixedMathSharp.Signed192&)
TryMaterialize(FixedMathSharp.Geometry.WideFiniteAxisIntersection/AxisTriangleCandidate,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&)
TryOffsetPoint(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d&)
TryGetRelativeCoordinate(FixedMathSharp.Signed576,FixedMathSharp.Fixed64,FixedMathSharp.Signed576,FixedMathSharp.Fixed64&)
TryGetSurfacePointOnCenteredCapsule(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d&)
TryGetSurfaceOffsetOnCenteredCapsule(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d&)
TryGetSurfaceOffsetOnCenteredCapsule(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&)
TryGetSurfacePointOnCenteredCapsule(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&)
ContainsPointInCenteredCapsule(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean)
ContainsPointInCenteredCapsule(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean)
GetDirectionFromCenteredAxis(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64)
GetDirectionFromCenteredAxis(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64)
TryGetCapsuleInterval(FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetCapsuleInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
IsCenteredCapsulePointContained(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320,System.Boolean)
IsCenteredCapsulePointContained(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320,System.Boolean)
GetCenteredCap(FixedMathSharp.Signed192,FixedMathSharp.Signed320)
MergeCenteredCapInterval(FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,System.Boolean,System.Boolean&,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
MergeCenteredCapInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,System.Boolean,System.Boolean&,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
GetCenteredCapPolynomial(FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,System.Boolean,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&)
GetCenteredCapPolynomial(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,System.Boolean,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&)
GetCenteredCapConstant(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,System.Boolean)
GetCenteredCapConstant(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,System.Boolean)
GetCenteredCapOffset(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean)
GetRadialComponent(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
GetClosestCenteredAxisRatio(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Signed192&,FixedMathSharp.Signed192&)
GetClosestCenteredAxisRatio(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Signed192&,FixedMathSharp.Signed192&)
TryGetCenteredCapsuleSurfaceCoordinate(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
MultiplyThreeToSigned320(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
GetCenteredAxisOffsetComponent(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
GetComponentDifference(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
GetScaledDifference(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
ScaleByCenteredAxis(FixedMathSharp.Signed192)
TrySolveUnitQuadratic(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
GetSurfaceAnchorOnCenteredCapsule(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d)
GetSurfaceAnchorOnCenteredCapsule(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d)
GetSurfaceAnchorOnCenteredCapsule(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d)
TryGetDistanceToCenteredCapsule(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
TryGetDistanceToCenteredCapsule(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
TryGetDistanceToCenteredCapsule(FixedMathSharp.Signed576,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
.ctor(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
TryGetSweptCenteredCapsuleSegmentFirstDistance(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Vector2d&)
TryGetSweptCenteredCapsuleOriginOffsetSegmentFirstDistance(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Vector2d&)
TryGetSweptOriginOffsetSegmentsFirstDistance(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Vector2d&)
TryGetSweptCenteredCapsulesFirstDistance(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Vector2d&)
TryGetSweptAxesFirstDistance(FixedMathSharp.Geometry.WideFiniteAxisIntersection/WideAxis2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.WideFiniteAxisIntersection/WideAxis2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64&,FixedMathSharp.Vector2d&)
TryKeepEndpointAxisSweep(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Geometry.WideFiniteAxisIntersection/WideAxis2d,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,System.Boolean,System.Boolean&,FixedMathSharp.Fixed64&,FixedMathSharp.Vector2d&)
GetAxisSweepFallbackNormal(FixedMathSharp.Geometry.WideFiniteAxisIntersection/WideAxis2d,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
TryKeepCircleSweep(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,System.Boolean&,FixedMathSharp.Fixed64&)
TryKeepSideSweep(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Geometry.WideFiniteAxisIntersection/WideAxis2d,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,System.Boolean&,FixedMathSharp.Fixed64&)
IsWithinAxisAtDistance(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.WideFiniteAxisIntersection/WideAxis2d,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320)
KeepFirstSweepRoot(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Fixed64,System.Boolean&,FixedMathSharp.Fixed64&)
GetEndpointAxisNormal(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.WideFiniteAxisIntersection/WideAxis2d)
GetPointAtDistance(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Signed192&,FixedMathSharp.Signed192&)
AxesIntersect(FixedMathSharp.Geometry.WideFiniteAxisIntersection/WideAxis2d,FixedMathSharp.Geometry.WideFiniteAxisIntersection/WideAxis2d)
Orientation(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
IsWithinBounds(FixedMathSharp.Geometry.WideFiniteAxisIntersection/WideAxis2d,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
IsBetween(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
GetSweepVelocity(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Signed192&,FixedMathSharp.Signed192&,FixedMathSharp.Signed192&,FixedMathSharp.Signed192&)
GetCenteredAxisEndpoints(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.WideFiniteAxisIntersection/WideAxis2d&)
GetAuthoredAxisEndpoints(FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Geometry.WideFiniteAxisIntersection/WideAxis2d&)
GetRotatedOriginOffsetAxisEndpoints(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Geometry.WideFiniteAxisIntersection/WideAxis2d&)
GetRotatedOriginOffsetCoordinate(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Signed192&,FixedMathSharp.Signed192&)
GetCenteredEndpointNumerator(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean)
ScaleAuthoredCoordinate(FixedMathSharp.Fixed64)
TryGetClosestCenteredFiniteConeSurfaceAnchor(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&)
GetClosestCenteredFiniteConeSurfaceAnchor(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&,System.Boolean&)
GetRigidCenteredConeMeridian(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RigidLocalPointRelation,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
GetClosestCenteredConeSideCoordinates(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RigidLocalPointRelation,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Signed576,FixedMathSharp.Signed320,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
GetCenteredConeSideApproximation(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RigidLocalPointRelation,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Signed576,FixedMathSharp.Signed320,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
RoundBoundedCenteredConeCoordinate(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Geometry.WideFiniteAxisIntersection/RigidLocalPointRelation,FixedMathSharp.Signed576,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
CompareCenteredConeCoordinateToRaw(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Geometry.WideFiniteAxisIntersection/RigidLocalPointRelation,FixedMathSharp.Signed576,System.Int64)
GetCenteredConeHeightRelation(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RigidLocalPointRelation,FixedMathSharp.Fixed64,FixedMathSharp.Signed576&,FixedMathSharp.Signed320&)
IsPointContainedInRigidCenteredCone(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RigidLocalPointRelation,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
IsCenteredConeSideNearest(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RigidLocalPointRelation,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Signed576,FixedMathSharp.Signed320)
GetCenteredConeSideParameterNumerator(FixedMathSharp.Signed576,FixedMathSharp.Signed320,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
CompareCenteredConeSideParameterToEndpoint(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RigidLocalPointRelation,FixedMathSharp.Signed576,FixedMathSharp.Signed320,FixedMathSharp.Signed192,FixedMathSharp.Signed192,System.Int32)
CompareCenteredConeApexToBaseDistance(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RigidLocalPointRelation,FixedMathSharp.Signed576,FixedMathSharp.Signed320,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,System.Boolean)
CompareCenteredConeInteriorSideToBaseDistance(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RigidLocalPointRelation,FixedMathSharp.Signed576,FixedMathSharp.Signed320,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,System.Boolean)
TryGetClosestCenteredCapsuleSurfaceAnchor(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&)
GetClosestCenteredCapsuleSurfaceAnchor(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&,System.Boolean&)
GetLocalCapsuleSurfaceDirection(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RigidLocalPointRelation,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,System.Int32,FixedMathSharp.Vector3d)
GetLocalCapsuleCapDelta(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
TryGetClosestCenteredFiniteCylinderSurfaceAnchor(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&)
GetClosestCenteredFiniteCylinderSurfaceAnchor(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&,System.Boolean&)
TryGetSignedSurfaceDistance(FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedPointAnchor&,System.Boolean,FixedMathSharp.Fixed64&)
CreateCenteredCylinderSideAnchor(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,System.Int32,FixedMathSharp.Geometry.WideFiniteAxisIntersection/RigidLocalPointRelation)
CreateCenteredCapsuleAnchors(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,System.Int32,FixedMathSharp.Geometry.WideFiniteAxisIntersection/RigidLocalPointRelation,FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Geometry.FixedPointAnchor&)
GetClosestCenteredRigidAxisDistance(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RigidLocalPointRelation,FixedMathSharp.Fixed64,System.Int32)
CreateCenteredSurfaceAnchor(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64)
TryGetCenteredRadialDistance(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RigidLocalPointRelation,FixedMathSharp.Fixed64&)
GetNonNegativeComparisonIncrement(System.Int32)
GetLocalRadialDirection(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RigidLocalPointRelation,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
GetProjection(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Vector3d)
GetCenteredCap(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RigidLocalPointRelation,FixedMathSharp.Fixed64)
GetCenteredRadialBound(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RigidLocalPointRelation,FixedMathSharp.Fixed64)
GetLocalRadialComponents(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320,FixedMathSharp.Signed192,FixedMathSharp.Vector3d,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&)
GetLocalRadialComponent(FixedMathSharp.Signed192,FixedMathSharp.Signed320,FixedMathSharp.Signed192,FixedMathSharp.Fixed64)
CompareSigned576(FixedMathSharp.Signed576,FixedMathSharp.Signed576)
CompareMagnitudeSigned576(FixedMathSharp.Signed576,FixedMathSharp.Signed576)
DoesCenteredFiniteConeOverlapSphere(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64)
TryGetClosestPointOnCenteredFiniteConeSurface(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&)
TryGetClosestCenteredFiniteConeSurfaceOffset(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&)
TryGetClosestPointOnCenteredFiniteCylinderSurface(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&)
TryGetClosestCenteredFiniteCylinderSurfaceOffset(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&)
GetCenteredConeSideNormal(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
TryGetTriangleSupportPointContact(FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&,System.Boolean&)
TryGetTriangleSupportContactOffsets(FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&,System.Boolean&)
GetSupportDifference(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
GetProjectedCoordinateNumerator(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320,FixedMathSharp.Signed320)
GetAbsoluteCoordinateNumerator(FixedMathSharp.Signed576,FixedMathSharp.Fixed64,FixedMathSharp.Signed576)
TryGetTriangleOriginOffsetCoordinate(FixedMathSharp.Signed576,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Signed576,FixedMathSharp.Fixed64&)
ContainsPointInCenteredFiniteCylinder(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean)
ContainsPointInCenteredFiniteCylinder(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean)
IsCapsulePointContained(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,System.Boolean)
IsFiniteCylinderPointContained(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,System.Boolean)
IsCenteredFiniteCylinderPointContained(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320,System.Boolean)
IsWithinRadius(FixedMathSharp.Signed192,FixedMathSharp.Signed192,System.Boolean)
GetRadialConstant(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
.cctor()
.ctor(FixedMathSharp.Signed192,FixedMathSharp.Signed192)
.ctor(FixedMathSharp.Signed320,FixedMathSharp.Signed320)
TryGetCapsuleInterval(FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetCapsuleInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetFiniteCylinderInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetFiniteCylinderInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetFiniteAxisInterval(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Geometry.WideFiniteAxisIntersection/RationalBound320,FixedMathSharp.Geometry.WideFiniteAxisIntersection/RationalBound320,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetFiniteAxisInterval(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetAxialInterval(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.WideFiniteAxisIntersection/RationalBound&,FixedMathSharp.Geometry.WideFiniteAxisIntersection/RationalBound&)
TryGetCenteredAxialInterval(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.WideFiniteAxisIntersection/RationalBound320&,FixedMathSharp.Geometry.WideFiniteAxisIntersection/RationalBound320&)
GetCenteredAxialExtent(FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
GetCenteredAxialExtent(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64)
Normalize(FixedMathSharp.Signed192,FixedMathSharp.Signed192)
Normalize(FixedMathSharp.Signed320,FixedMathSharp.Signed320)
Compare(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RationalBound,FixedMathSharp.Geometry.WideFiniteAxisIntersection/RationalBound)
Compare(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RationalBound320,FixedMathSharp.Geometry.WideFiniteAxisIntersection/RationalBound320)
GetMaximumBound(FixedMathSharp.Fixed64)
GetMaximumBound320(FixedMathSharp.Fixed64)
Round(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RationalBound)
Round(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RationalBound320)
TryGetCircleInterval(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Signed192,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetSphereInterval(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Signed192,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
GetExpandedRadius(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
GetSquaredRadius(FixedMathSharp.Signed192)
GetDot(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d)
GetDot(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
Merge(System.Boolean,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean&,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TrySolveBoundedQuadratic(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Geometry.WideFiniteAxisIntersection/RationalBound320,FixedMathSharp.Geometry.WideFiniteAxisIntersection/RationalBound320,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetCircleDirectionDistanceInterval(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Geometry.FixedBoundCircle,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetSphereDirectionDistanceInterval(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedBoundSphere,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetCircleDistanceInterval(FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Geometry.FixedBoundCircle,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetSphereDistanceInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Geometry.FixedBoundSphere,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetCapsuleDistanceInterval(FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetCapsuleDistanceInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetCapsuleDistanceInterval(FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetCapsuleDistanceInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetFiniteCylinderDistanceInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetFiniteCylinderDistanceInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetFiniteCylinderDistanceInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetFiniteAxisDistanceInterval(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetFiniteAxisDistanceInterval(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Geometry.WideFiniteAxisIntersection/RationalBound320,FixedMathSharp.Geometry.WideFiniteAxisIntersection/RationalBound320,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetCircleDistanceInterval(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetSphereDistanceInterval(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
MergeCenteredCapDistanceInterval(FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,System.Boolean,System.Boolean&,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
MergeCenteredCapDistanceInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,System.Boolean,System.Boolean&,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TrySolveUnitQuadraticAtDistance(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TrySolveBoundedQuadraticAtDistance(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Geometry.WideFiniteAxisIntersection/RationalBound320,FixedMathSharp.Geometry.WideFiniteAxisIntersection/RationalBound320,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
RoundLowerRootAtDistance(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed576,FixedMathSharp.Fixed64)
RoundUpperRootAtDistance(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed576,FixedMathSharp.Fixed64)
RoundAtDistance(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RationalBound320,FixedMathSharp.Fixed64)
SquareRaw(System.Int64)
TryGetNarrowRadialCoefficients(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed192&,FixedMathSharp.Signed192&,FixedMathSharp.Signed192&)
GetMagnitudeBitLength(FixedMathSharp.Signed320)
GetTrailingZeroCount(FixedMathSharp.Signed320)
CountTrailingZeroes(System.UInt64)
ShiftRightExact(FixedMathSharp.Signed320,System.Int32)
GetShiftedWord(FixedMathSharp.Signed320,System.Int32,System.Int32,System.Int32)
GetSignedWord(FixedMathSharp.Signed320,System.Int32)
TryGetCapsuleInterval(FixedMathSharp.Geometry.FixedRay2d,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetCapsuleInterval(FixedMathSharp.Geometry.FixedRay,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetCapsuleInterval(FixedMathSharp.Geometry.FixedRay2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetCapsuleInterval(FixedMathSharp.Geometry.FixedRay,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetFiniteCylinderInterval(FixedMathSharp.Geometry.FixedRay,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetFiniteCylinderInterval(FixedMathSharp.Geometry.FixedRay,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
IsCapsuleContainedAtParameter(FixedMathSharp.Geometry.FixedRay2d,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
IsCapsuleContainedAtParameter(FixedMathSharp.Geometry.FixedRay,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
IsFiniteCylinderContainedAtParameter(FixedMathSharp.Fixed64,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
IsCenteredFiniteCylinderContainedAtParameter(FixedMathSharp.Fixed64,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320)
IsCenteredCapsuleContainedAtParameter(FixedMathSharp.Geometry.FixedRay2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320)
IsCenteredCapsuleContainedAtParameter(FixedMathSharp.Geometry.FixedRay,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320)
GetCenteredCap(FixedMathSharp.Signed320,FixedMathSharp.Signed320)
MergeCenteredCapInterval(FixedMathSharp.Geometry.FixedRay2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,System.Boolean,System.Boolean&,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
MergeCenteredCapInterval(FixedMathSharp.Geometry.FixedRay,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,System.Boolean,System.Boolean&,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
GetCenteredCapPolynomial(FixedMathSharp.Geometry.FixedRay2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,System.Boolean,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&)
GetCenteredCapPolynomial(FixedMathSharp.Geometry.FixedRay,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,System.Boolean,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&)
EvaluateLinear(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64)
GetRadialPolynomial(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&)
IsQuadraticContained(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64)
IsQuadraticContained(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Fixed64)
TryGetCircleInterval(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetSphereInterval(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
GetDirectionDot(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d)
GetDirectionDot(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d)
GetDirectionDot(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
GetDirectionDot(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
.ctor(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320,FixedMathSharp.Signed576,FixedMathSharp.Signed320)
GetRigidLocalPointRelation(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.WideFiniteAxisIntersection/RigidLocalPointRelation&)
RoundLowerRoot(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320)
RoundUpperRoot(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Fixed64)
ShiftLeftByFixed64FractionalBits(FixedMathSharp.Signed320)
EvaluatePolynomial(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
EvaluateDerivative(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
EvaluatePolynomial(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320)
EvaluateDerivative(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320)
.ctor(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RationalBound320,System.Byte,System.SByte)
TryGetSphericallyExpandedBoxFirstDistance(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Geometry.FixedBoundBox,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
TryGetSphericallyExpandedProjectedBoxFirstDistance(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
AddAxisBreakpoints(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Byte,System.Span`1<FixedMathSharp.Geometry.WideFiniteAxisIntersection/BoxBreakpoint>,System.Int32&,System.SByte&)
AddProjectedAxisBreakpoints(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,System.Byte,System.Span`1<FixedMathSharp.Geometry.WideFiniteAxisIntersection/BoxBreakpoint>,System.Int32&,System.SByte&)
AddBreakpoint(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,System.Byte,System.SByte,System.Span`1<FixedMathSharp.Geometry.WideFiniteAxisIntersection/BoxBreakpoint>,System.Int32&)
AddProjectedBreakpoint(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,System.Byte,System.SByte,System.Span`1<FixedMathSharp.Geometry.WideFiniteAxisIntersection/BoxBreakpoint>,System.Int32&)
SortBreakpoints(System.Span`1<FixedMathSharp.Geometry.WideFiniteAxisIntersection/BoxBreakpoint>,System.Int32)
GetBoxDistancePolynomial(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Geometry.FixedBoundBox,System.Span`1<System.SByte>,FixedMathSharp.Fixed64,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&)
GetProjectedBoxDistancePolynomial(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,System.Span`1<System.SByte>,FixedMathSharp.Signed192,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&)
AddBoxAxisPolynomial(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.SByte,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&)
AddProjectedBoxAxisPolynomial(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,System.SByte,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&)
IsWithinProjectedRoundedBox(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
GetProjectedBoxAxisOffset(FixedMathSharp.Signed192,FixedMathSharp.Signed192)
.ctor(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
.ctor(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576)
.cctor()
.ctor(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed576,System.Int32)
DoesCenteredFiniteCylinderOverlapSphere(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64)
TryGetSphericallyExpandedFiniteCylinderDistanceInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetSphericallyExpandedFiniteCylinderFirstDistance(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
TryGetSphericallyExpandedFiniteCylinderFirstDistanceFromHalfAxisLength(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
TryGetSphericallyExpandedFiniteCylinderDirectionFirstDistanceFromHalfAxisLength(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
TryGetSphericallyExpandedFiniteCylinderDistanceIntervalWithFullAxisLength(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetSphericallyExpandedFiniteCylinderDistanceInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
MergeSphericallyExpandedFiniteCylinderRoundedIntervals(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RoundedCylinderBaseData,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,System.Boolean,System.Boolean&,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean,System.Boolean,System.Boolean&,System.Boolean&)
TryGetRoundedCylinderCapCoreDistanceInterval(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RoundedCylinderBaseData,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,System.Boolean,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
RoundedCylinderRimBoundsIntersect(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RoundedCylinderBaseData,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,System.Boolean)
CreateRoundedCylinderQuadraticBound(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,System.Boolean,System.Boolean,System.Boolean)
MergeRoundedCylinderRimInterval(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RoundedCylinderTorusPolynomial,FixedMathSharp.Fixed64,System.Boolean&,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean,System.Boolean&,System.Boolean&)
IsPointInRoundedCylinderRimTube(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RoundedCylinderTorusPolynomial,System.Boolean,System.Boolean)
TryGetFiniteCylinderDirectionFirstDistance(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,System.Boolean&)
CreateRoundedCylinderBaseData(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
CreateRoundedCylinderBaseData(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
CreateRoundedCylinderBaseData(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
CreateRoundedCylinderTorusPolynomial(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RoundedCylinderBaseData,FixedMathSharp.Signed192,System.Boolean)
MultiplyToSigned320(FixedMathSharp.Signed320,FixedMathSharp.Signed192)
MultiplyToSigned320(FixedMathSharp.Signed320,FixedMathSharp.Signed320)
Twice(FixedMathSharp.Signed320)
Four(FixedMathSharp.Signed320)
Twice(FixedMathSharp.Signed576)
AddFive(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576)
ImportRoundedCylinderCoefficient(FixedMathSharp.Signed576,System.Span`1<System.UInt64>,System.Span`1<System.SByte>,System.Int32,System.Int32)
ImportRoundedCylinderCoefficient(FixedMathSharp.Signed832,System.Span`1<System.UInt64>,System.Span`1<System.SByte>,System.Int32,System.Int32)
GetRoundedCylinderCoefficient(System.Span`1<System.UInt64>,System.Int32,System.Int32)
GetRoundedCylinderCoefficientIndex(System.Int32,System.Int32)
AddRoundedCylinderSigned(System.ReadOnlySpan`1<System.UInt64>,System.SByte,System.ReadOnlySpan`1<System.UInt64>,System.SByte,System.Span`1<System.UInt64>,System.SByte&)
SubtractRoundedCylinderSigned(System.ReadOnlySpan`1<System.UInt64>,System.SByte,System.ReadOnlySpan`1<System.UInt64>,System.SByte,System.Span`1<System.UInt64>,System.SByte&)
MultiplyRoundedCylinderWide(System.ReadOnlySpan`1<System.UInt64>,System.ReadOnlySpan`1<System.UInt64>,System.Span`1<System.UInt64>)
MultiplyRoundedCylinderWideByWord(System.ReadOnlySpan`1<System.UInt64>,System.UInt64,System.Span`1<System.UInt64>)
AddRoundedCylinderWord(System.Span`1<System.UInt64>,System.Int32,System.UInt64)
MultiplyRoundedCylinderSigns(System.SByte,System.SByte)
GetRoundedCylinderWideLength(System.ReadOnlySpan`1<System.UInt64>)
CopyRoundedCylinderWide(System.ReadOnlySpan`1<System.UInt64>,System.Span`1<System.UInt64>)
CountRoundedCylinderTrailingZeroes(System.ReadOnlySpan`1<System.UInt64>)
ShiftRoundedCylinderWideRight(System.Span`1<System.UInt64>,System.Int32)
CountProjectionDomainQuarticRoots(FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Signed832)
GetRoundedCylinderInfinityVariations(System.ReadOnlySpan`1<System.SByte>,System.ReadOnlySpan`1<System.Int32>,System.Int32,System.Boolean)
TryGetRoundedCylinderRimDistanceInterval(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RoundedCylinderTorusPolynomial,FixedMathSharp.Fixed64,System.Boolean,System.Boolean,System.Boolean,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
FindRoundedCylinderRoot(System.Span`1<System.UInt64>,System.Span`1<System.SByte>,System.Span`1<System.Int32>,System.Int32,System.UInt64,System.Int32,System.Int32,System.Int32,System.Boolean)
FindRoundedCylinderSignChangingRoot(System.Span`1<System.UInt64>,System.Span`1<System.SByte>,System.Int32,System.UInt64,System.UInt64,System.UInt64,System.Int32)
HomogenizeRoundedCylinderSturmSequence(System.Span`1<System.UInt64>,System.Span`1<System.Int32>,System.Int32,System.UInt64)
IsRoundedCylinderEntryBeforeOrEqualToExit(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RoundedCylinderQuadraticBound,FixedMathSharp.Geometry.WideFiniteAxisIntersection/RoundedCylinderQuadraticBound)
GetRoundedCylinderRadicalSquare(FixedMathSharp.Signed320,FixedMathSharp.Signed576,System.Span`1<System.UInt64>,System.Span`1<System.UInt64>,System.Span`1<System.UInt64>)
ImportRoundedCylinderWide(FixedMathSharp.Signed320,System.Span`1<System.UInt64>)
ImportRoundedCylinderWide(FixedMathSharp.Signed576,System.Span`1<System.UInt64>)
GetRoundedCylinderSignVariations(System.Span`1<System.UInt64>,System.Span`1<System.SByte>,System.Span`1<System.Int32>,System.Int32,System.UInt64,System.UInt64)
EvaluateRoundedCylinderPolynomialSign(System.Span`1<System.UInt64>,System.Span`1<System.SByte>,System.Int32,System.Int32,System.UInt64,System.UInt64)
EvaluateRoundedCylinderPolynomialSignAtInteger(System.Span`1<System.UInt64>,System.Span`1<System.SByte>,System.Int32,System.Int32,System.UInt64)
BuildRoundedCylinderSturmSequence(FixedMathSharp.Geometry.WideFiniteAxisIntersection/RoundedCylinderTorusPolynomial,System.Span`1<System.UInt64>,System.Span`1<System.SByte>,System.Span`1<System.Int32>)
BuildRoundedCylinderQuarticSturmSequence(System.Span`1<System.UInt64>,System.Span`1<System.SByte>,System.Span`1<System.Int32>)
SetRoundedCylinderProduct(System.ReadOnlySpan`1<System.UInt64>,System.SByte,System.ReadOnlySpan`1<System.UInt64>,System.SByte,System.Span`1<System.UInt64>,System.SByte&)
SetRoundedCylinderScaledProduct(System.ReadOnlySpan`1<System.UInt64>,System.SByte,System.ReadOnlySpan`1<System.UInt64>,System.SByte,System.UInt64,System.Span`1<System.UInt64>,System.SByte&,System.Span`1<System.UInt64>)
SetRoundedCylinderTripleProduct(System.ReadOnlySpan`1<System.UInt64>,System.SByte,System.ReadOnlySpan`1<System.UInt64>,System.SByte,System.ReadOnlySpan`1<System.UInt64>,System.SByte,System.Span`1<System.UInt64>,System.SByte&,System.Span`1<System.UInt64>)
BuildRoundedCylinderNegativeRemainder(System.Span`1<System.UInt64>,System.Span`1<System.SByte>,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32)
RemoveRoundedCylinderCommonPowerOfTwo(System.Span`1<System.UInt64>,System.Span`1<System.SByte>,System.Int32,System.Int32)
TrimRoundedCylinderPolynomial(System.Span`1<System.SByte>,System.Int32,System.Int32)
.cctor()
TryGetCenteredAxisEndpoint(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,System.Boolean,FixedMathSharp.Vector2d&)
TryGetCenteredAxisEndpoint(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,System.Boolean,FixedMathSharp.Vector3d&)
TryGetCenteredCapsuleSupport(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d&)
GetCenteredCapsuleSupportAnchor(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d)
TryGetCenteredCapsuleSupport(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&)
TryGetCenteredFiniteCylinderSupport(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&)
TryGetCenteredFiniteConeSupport(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&)
TryGetCenteredSupport(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320,System.Boolean,FixedMathSharp.Vector2d&)
TryGetCenteredSupport(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320,System.Boolean,FixedMathSharp.Vector3d&)
TryGetSupportCoordinate(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,FixedMathSharp.Signed320,System.Boolean,FixedMathSharp.Fixed64&)
CompareSupportCoordinateToMidpoint(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed192)
IsCenteredFiniteConeApexSupport(FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d)
IsCenteredFiniteConeApexSupportCore(FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320)
GetDirection(FixedMathSharp.Vector2d,FixedMathSharp.Signed192&,FixedMathSharp.Signed192&,FixedMathSharp.Signed320&)
GetDirection(FixedMathSharp.Vector3d,FixedMathSharp.Signed192&,FixedMathSharp.Signed192&,FixedMathSharp.Signed192&,FixedMathSharp.Signed320&)
GetPlaneDirection(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Signed192&,FixedMathSharp.Signed192&,FixedMathSharp.Signed192&,FixedMathSharp.Signed320&)
GetMinimumMidpoint()
GetMaximumMidpoint()