< Summary

Information
Class: FixedMathSharp.Geometry.WideFiniteConeIntersection
Assembly: FixedMathSharp
File(s): /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/FiniteAxis/WideFiniteConeIntersection.cs
Line coverage
100%
Covered lines: 464
Uncovered lines: 0
Coverable lines: 464
Total lines: 860
Line coverage: 100%
Branch coverage
100%
Covered branches: 122
Total branches: 122
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

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

#LineLine coverage
 1//=======================================================================
 2// WideFiniteConeIntersection.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 finite-cone containment and segment reduction.
 12/// </summary>
 13internal static class WideFiniteConeIntersection
 14{
 115    private static readonly Signed192 One = Signed192.Signed(1L);
 116    private static readonly Signed192 Four = Signed192.Signed(4L);
 117    private static readonly Signed192 AxisScaleSquared = new(0UL, 1UL, 0UL);
 18
 19    #region Nested Types
 20
 21    private readonly struct RationalBound
 22    {
 23        internal readonly Signed192 Numerator;
 24        internal readonly Signed192 Denominator;
 25
 26        internal RationalBound(Signed192 numerator, Signed192 denominator)
 27        {
 507428            Numerator = numerator;
 507429            Denominator = denominator;
 507430        }
 31    }
 32
 33    private readonly struct ConeData
 34    {
 35        internal readonly Signed192 StartAxial;
 36        internal readonly Signed192 AxialVelocity;
 37        internal readonly Signed192 MaximumAxial;
 38        internal readonly Signed576 Coefficient;
 39        internal readonly Signed576 Projection;
 40        internal readonly Signed576 Constant;
 41
 42        internal ConeData(
 43            Signed192 startAxial,
 44            Signed192 axialVelocity,
 45            Signed192 maximumAxial,
 46            Signed576 coefficient,
 47            Signed576 projection,
 48            Signed576 constant)
 49        {
 275750            StartAxial = startAxial;
 275751            AxialVelocity = axialVelocity;
 275752            MaximumAxial = maximumAxial;
 275753            Coefficient = coefficient;
 275754            Projection = projection;
 275755            Constant = constant;
 275756        }
 57
 58        internal ConeData NegatedPolynomial() =>
 1359            new(
 1360                StartAxial,
 1361                AxialVelocity,
 1362                MaximumAxial,
 1363                WideArithmetic.SubtractSigned576(default, Coefficient),
 1364                WideArithmetic.SubtractSigned576(default, Projection),
 1365                WideArithmetic.SubtractSigned576(default, Constant));
 66    }
 67
 68    #endregion
 69
 70    internal static bool TryGetApexInterval(
 71        FixedSegment query,
 72        Vector3d apex,
 73        Vector3d apexToBaseDirection,
 74        Fixed64 height,
 75        Fixed64 baseRadius,
 76        out Fixed64 entry,
 77        out Fixed64 exit,
 78        out bool startContained,
 79        out bool endContainedStrict) =>
 4380        TrySolve(
 4381            CreateApexData(query, apex, apexToBaseDirection, height, baseRadius),
 4382            Fixed64.One,
 4383            out entry,
 4384            out exit,
 4385            out startContained,
 4386            out endContainedStrict);
 87
 88    internal static bool TrySolveUnitPolynomial(
 89        Signed576 coefficient,
 90        Signed576 projection,
 91        Signed576 constant,
 92        Fixed64 outputScale,
 93        out Fixed64 entry,
 94        out Fixed64 exit) =>
 186295        TrySolveBoundedPolynomial(
 186296            new ConeData(default, default, default, coefficient, projection, constant),
 186297            new RationalBound(default, One),
 186298            new RationalBound(One, One),
 186299            outputScale,
 1862100            out entry,
 1862101            out exit);
 102
 103    internal static int GetPolynomialSignAtScaledParameter(
 104        Signed576 coefficient,
 105        Signed576 projection,
 106        Signed576 constant,
 107        Fixed64 parameter,
 108        Fixed64 scale) =>
 8109        Evaluate(
 8110            new ConeData(default, default, default, coefficient, projection, constant),
 8111            Signed192.Signed(parameter.m_rawValue),
 8112            Signed192.Signed(scale.m_rawValue)).Sign;
 113
 114    internal static int GetPolynomialSignAtRationalParameter(
 115        Signed576 coefficient,
 116        Signed576 projection,
 117        Signed576 constant,
 118        Signed192 numerator,
 119        Signed192 denominator) =>
 188120        Evaluate(
 188121            new ConeData(default, default, default, coefficient, projection, constant),
 188122            numerator,
 188123            denominator).Sign;
 124
 125    internal static bool TryGetApexDistanceInterval(
 126        FixedSegment query,
 127        Vector3d apex,
 128        Vector3d apexToBaseDirection,
 129        Fixed64 height,
 130        Fixed64 baseRadius,
 131        Fixed64 totalDistance,
 132        out Fixed64 entry,
 133        out Fixed64 exit,
 134        out bool startContained,
 135        out bool endContainedStrict) =>
 99136        TrySolve(
 99137            CreateApexData(query, apex, apexToBaseDirection, height, baseRadius),
 99138            totalDistance,
 99139            out entry,
 99140            out exit,
 99141            out startContained,
 99142            out endContainedStrict);
 143
 144    internal static bool TryGetCenteredInterval(
 145        FixedSegment query,
 146        Vector3d center,
 147        Vector3d baseToApexDirection,
 148        Fixed64 height,
 149        Fixed64 baseRadius,
 150        out Fixed64 entry,
 151        out Fixed64 exit,
 152        out bool startContained,
 153        out bool endContainedStrict) =>
 3154        TrySolve(
 3155            CreateCenteredData(query, center, baseToApexDirection, height, baseRadius),
 3156            Fixed64.One,
 3157            out entry,
 3158            out exit,
 3159            out startContained,
 3160            out endContainedStrict);
 161
 162    internal static bool TryGetCenteredDistanceInterval(
 163        FixedSegment query,
 164        Vector3d center,
 165        Vector3d baseToApexDirection,
 166        Fixed64 height,
 167        Fixed64 baseRadius,
 168        Fixed64 totalDistance,
 169        out Fixed64 entry,
 170        out Fixed64 exit,
 171        out bool startContained,
 172        out bool endContainedStrict) =>
 17173        TrySolve(
 17174            CreateCenteredData(query, center, baseToApexDirection, height, baseRadius),
 17175            totalDistance,
 17176            out entry,
 17177            out exit,
 17178            out startContained,
 17179            out endContainedStrict);
 180
 181    internal static bool ContainsPointInApexCone(
 182        Vector3d point,
 183        Vector3d apex,
 184        Vector3d apexToBaseDirection,
 185        Fixed64 height,
 186        Fixed64 baseRadius,
 187        bool strict)
 188    {
 8189        Signed192 heightRaw = Signed192.Signed(height.m_rawValue);
 8190        Signed192 axisLengthSquared = GetDot(
 8191            apexToBaseDirection,
 8192            Vector3d.Zero,
 8193            apexToBaseDirection,
 8194            Vector3d.Zero);
 8195        bool exactUnitAxis = IsExactUnitAxis(axisLengthSquared);
 8196        Signed192 axisProjection = GetDot(
 8197            point,
 8198            apex,
 8199            apexToBaseDirection,
 8200            Vector3d.Zero);
 8201        Signed192 axial = exactUnitAxis ? axisProjection : GetScaledRaw(axisProjection);
 8202        return ContainsPoint(
 8203            point,
 8204            apex,
 8205            heightRaw,
 8206            axisLengthSquared,
 8207            axisProjection,
 8208            axial,
 8209            exactUnitAxis ? GetScaledRaw(heightRaw) : GetAxisHeightProduct(axisLengthSquared, heightRaw),
 8210            One,
 8211            exactUnitAxis,
 8212            baseRadius,
 8213            strict);
 214    }
 215
 216    internal static bool ContainsPointInCenteredCone(
 217        Vector3d point,
 218        Vector3d center,
 219        Vector3d baseToApexDirection,
 220        Fixed64 height,
 221        Fixed64 baseRadius,
 222        bool strict)
 223    {
 11224        Signed192 heightRaw = Signed192.Signed(height.m_rawValue);
 11225        Signed192 axisLengthSquared = GetDot(
 11226            baseToApexDirection,
 11227            Vector3d.Zero,
 11228            baseToApexDirection,
 11229            Vector3d.Zero);
 11230        bool exactUnitAxis = IsExactUnitAxis(axisLengthSquared);
 11231        Signed192 axisProjection = GetDot(point, center, baseToApexDirection, Vector3d.Zero);
 11232        Signed192 maximumAxial = exactUnitAxis
 11233            ? GetScaledRaw(heightRaw)
 11234            : GetAxisHeightProduct(axisLengthSquared, heightRaw);
 11235        Signed192 axial = exactUnitAxis
 11236            ? WideArithmetic.SubtractSigned192(GetHalfScaledRaw(heightRaw), axisProjection)
 11237            : WideArithmetic.SubtractSigned192(maximumAxial, WideArithmetic.Double(GetScaledRaw(axisProjection)));
 11238        return ContainsPoint(
 11239            point,
 11240            center,
 11241            heightRaw,
 11242            axisLengthSquared,
 11243            axisProjection,
 11244            axial,
 11245            exactUnitAxis ? maximumAxial : WideArithmetic.Double(maximumAxial),
 11246            exactUnitAxis ? One : Four,
 11247            exactUnitAxis,
 11248            baseRadius,
 11249            strict);
 250    }
 251
 252    private static bool ContainsPoint(
 253        Vector3d point,
 254        Vector3d origin,
 255        Signed192 heightRaw,
 256        Signed192 axisLengthSquared,
 257        Signed192 axisProjection,
 258        Signed192 axial,
 259        Signed192 maximumAxial,
 260        Signed192 radialScale,
 261        bool exactUnitAxis,
 262        Fixed64 baseRadius,
 263        bool strict)
 264    {
 19265        Signed192 distanceSquared = GetDot(point, origin, point, origin);
 19266        Signed320 radial = GetRadialTerm(distanceSquared, axisProjection, axisLengthSquared);
 19267        Signed320 heightSquared = WideArithmetic.MultiplySigned192(heightRaw, heightRaw);
 19268        Signed192 radiusRaw = Signed192.Signed(baseRadius.m_rawValue);
 19269        Signed320 radiusSquared = WideArithmetic.MultiplySigned192(radiusRaw, radiusRaw);
 19270        Signed576 polynomial = SubtractConeTerms(
 19271            heightSquared,
 19272            radial,
 19273            axisLengthSquared,
 19274            radialScale,
 19275            exactUnitAxis,
 19276            radiusSquared,
 19277            WideArithmetic.MultiplySigned192(axial, axial));
 19278        return IsContained(axial, polynomial, maximumAxial, strict);
 279    }
 280
 281    private static bool TrySolve(
 282        ConeData data,
 283        Fixed64 outputScale,
 284        out Fixed64 entry,
 285        out Fixed64 exit,
 286        out bool startContained,
 287        out bool endContainedStrict)
 288    {
 162289        startContained = IsContained(
 162290            data.StartAxial,
 162291            data.Constant,
 162292            data.MaximumAxial,
 162293            strict: false);
 162294        Signed192 endAxial = WideArithmetic.AddSigned192(data.StartAxial, data.AxialVelocity);
 162295        endContainedStrict = false;
 296
 162297        if (!TryGetAxialInterval(data, out RationalBound lower, out RationalBound upper))
 298        {
 20299            entry = default;
 20300            exit = default;
 20301            return false;
 302        }
 303
 142304        if (endAxial.Sign > 0
 142305            && WideArithmetic.SubtractSigned192(endAxial, data.MaximumAxial).Sign < 0)
 306        {
 82307            endContainedStrict = Evaluate(data, One, One).Sign < 0;
 308        }
 309
 142310        return TrySolveBoundedPolynomial(data, lower, upper, outputScale, out entry, out exit);
 311    }
 312
 313    private static bool TrySolveBoundedPolynomial(
 314        ConeData data,
 315        RationalBound lower,
 316        RationalBound upper,
 317        Fixed64 outputScale,
 318        out Fixed64 entry,
 319        out Fixed64 exit)
 320    {
 2400321        Signed832 lowerValue = Evaluate(data, lower.Numerator, lower.Denominator);
 2400322        Signed832 upperValue = Evaluate(data, upper.Numerator, upper.Denominator);
 2400323        bool lowerContained = lowerValue.Sign <= 0;
 2400324        bool upperContained = upperValue.Sign <= 0;
 325
 2400326        if (data.Coefficient.IsZero)
 327        {
 251328            if (data.Projection.IsZero)
 329            {
 241330                if (!lowerContained)
 331                {
 166332                    entry = default;
 166333                    exit = default;
 166334                    return false;
 335                }
 336
 75337                entry = Round(lower, outputScale);
 75338                exit = Round(upper, outputScale);
 75339                return true;
 340            }
 341
 10342            if (lowerContained && upperContained)
 343            {
 1344                entry = Round(lower, outputScale);
 1345                exit = Round(upper, outputScale);
 1346                return true;
 347            }
 9348            if (!lowerContained && !upperContained)
 349            {
 7350                entry = default;
 7351                exit = default;
 7352                return false;
 353            }
 354
 2355            Fixed64 root = RoundLinearRoot(data, outputScale);
 2356            entry = lowerContained ? Round(lower, outputScale) : root;
 2357            exit = upperContained ? Round(upper, outputScale) : root;
 2358            return true;
 359        }
 360
 2149361        if (lowerContained && upperContained)
 362        {
 19363            entry = Round(lower, outputScale);
 19364            exit = Round(upper, outputScale);
 19365            return true;
 366        }
 367
 2130368        bool opensUp = data.Coefficient.Sign > 0;
 2130369        if (!opensUp && !lowerContained && !upperContained)
 370        {
 7371            entry = default;
 7372            exit = default;
 7373            return false;
 374        }
 375
 2123376        if (opensUp
 2123377            && ((!lowerContained && EvaluateDerivative(data, lower).Sign >= 0)
 2123378                || (!upperContained && EvaluateDerivative(data, upper).Sign <= 0)))
 379        {
 450380            entry = default;
 450381            exit = default;
 450382            return false;
 383        }
 384
 1673385        ConeData normalized = opensUp ? data : data.NegatedPolynomial();
 1673386        Signed832 discriminant = WideArithmetic.SubtractSigned832(
 1673387            WideArithmetic.MultiplySigned576ToSigned832(normalized.Projection, normalized.Projection),
 1673388            WideArithmetic.MultiplySigned576ToSigned832(normalized.Coefficient, normalized.Constant));
 1673389        if (discriminant.Sign < 0)
 390        {
 523391            entry = default;
 523392            exit = default;
 523393            return false;
 394        }
 395
 1150396        Signed192 outputScaleRaw = Signed192.Signed(outputScale.m_rawValue);
 1150397        Signed192 outputScaleSquared = SquareRaw(outputScale.m_rawValue);
 1150398        Signed576 scaledSquareRoot = WideArithmetic.GetFloorSquareRootOfProduct(
 1150399            discriminant,
 1150400            outputScaleSquared);
 401
 1150402        if (opensUp)
 403        {
 1137404            entry = lowerContained
 1137405                ? Round(lower, outputScale)
 1137406                : RoundLowerRoot(normalized, scaledSquareRoot, outputScaleRaw);
 1137407            exit = upperContained
 1137408                ? Round(upper, outputScale)
 1137409                : RoundUpperRoot(normalized, scaledSquareRoot, outputScaleRaw);
 1137410            return true;
 411        }
 412
 13413        entry = lowerContained
 13414            ? Round(lower, outputScale)
 13415            : RoundUpperRoot(normalized, scaledSquareRoot, outputScaleRaw);
 13416        exit = upperContained
 13417            ? Round(upper, outputScale)
 13418            : RoundLowerRoot(normalized, scaledSquareRoot, outputScaleRaw);
 13419        return true;
 420    }
 421
 422    private static Fixed64 RoundLinearRoot(ConeData data, Fixed64 outputScale)
 423    {
 2424        Signed192 outputScaleRaw = Signed192.Signed(outputScale.m_rawValue);
 2425        Signed576 numerator = WideArithmetic.MultiplySigned576(
 2426            WideArithmetic.SubtractSigned576(default, data.Constant),
 2427            outputScaleRaw);
 2428        Signed576 denominator = WideArithmetic.AddSigned576(data.Projection, data.Projection);
 2429        _ = Fixed64.TryGetSignedRawRatio(numerator, denominator, out Fixed64 root);
 2430        return root;
 431    }
 432
 433    private static Fixed64 RoundLowerRoot(
 434        ConeData normalized,
 435        Signed576 scaledSquareRoot,
 436        Signed192 outputScaleRaw)
 437    {
 1129438        Signed576 negativeScaledProjection = WideArithmetic.SubtractSigned576(
 1129439            default,
 1129440            WideArithmetic.MultiplySigned576(normalized.Projection, outputScaleRaw));
 1129441        Signed576 numerator = WideArithmetic.SubtractSigned576(
 1129442            negativeScaledProjection,
 1129443            scaledSquareRoot);
 1129444        _ = Fixed64.TryGetSignedRawRatio(numerator, normalized.Coefficient, out Fixed64 candidate);
 445
 1129446        long upperRaw = candidate.m_rawValue;
 1129447        Signed192 upper = Signed192.Signed(upperRaw);
 1129448        Signed192 midpoint = WideArithmetic.SubtractSigned192(
 1129449            WideArithmetic.AddSigned192(upper, upper),
 1129450            One);
 1129451        Signed192 doubleScale = WideArithmetic.AddSigned192(outputScaleRaw, outputScaleRaw);
 1129452        Signed832 value = Evaluate(normalized, midpoint, doubleScale);
 1129453        if (value.IsZero)
 1454            return candidate;
 455
 1128456        return Fixed64.FromRaw(value.Sign > 0 ? upperRaw : upperRaw - 1L);
 457    }
 458
 459    private static Fixed64 RoundUpperRoot(
 460        ConeData normalized,
 461        Signed576 scaledSquareRoot,
 462        Signed192 outputScaleRaw)
 463    {
 1123464        Signed576 negativeScaledProjection = WideArithmetic.SubtractSigned576(
 1123465            default,
 1123466            WideArithmetic.MultiplySigned576(normalized.Projection, outputScaleRaw));
 1123467        Signed576 numerator = WideArithmetic.AddSigned576(
 1123468            negativeScaledProjection,
 1123469            scaledSquareRoot);
 1123470        _ = Fixed64.TryGetSignedRawRatio(numerator, normalized.Coefficient, out Fixed64 candidate);
 471
 1123472        long lowerRaw = candidate.m_rawValue;
 1123473        Signed192 lower = Signed192.Signed(lowerRaw);
 1123474        Signed192 midpoint = WideArithmetic.AddSigned192(
 1123475            WideArithmetic.AddSigned192(lower, lower),
 1123476            One);
 1123477        Signed192 doubleScale = WideArithmetic.AddSigned192(outputScaleRaw, outputScaleRaw);
 1123478        Signed832 value = Evaluate(normalized, midpoint, doubleScale);
 1123479        if (value.IsZero)
 1480            return candidate;
 481
 1122482        return Fixed64.FromRaw(value.Sign <= 0 ? lowerRaw + 1L : lowerRaw);
 483    }
 484
 485    private static bool TryGetAxialInterval(
 486        ConeData data,
 487        out RationalBound lower,
 488        out RationalBound upper)
 489    {
 162490        RationalBound zero = new(default, One);
 162491        RationalBound one = new(One, One);
 162492        lower = zero;
 162493        upper = one;
 494
 162495        if (data.AxialVelocity.IsZero)
 496        {
 77497            return data.StartAxial.Sign >= 0
 77498                && WideArithmetic.SubtractSigned192(data.StartAxial, data.MaximumAxial).Sign <= 0;
 499        }
 500
 85501        RationalBound first = Normalize(
 85502            WideArithmetic.SubtractSigned192(default, data.StartAxial),
 85503            data.AxialVelocity);
 85504        RationalBound second = Normalize(
 85505            WideArithmetic.SubtractSigned192(data.MaximumAxial, data.StartAxial),
 85506            data.AxialVelocity);
 85507        if (Compare(first, second) > 0)
 32508            (first, second) = (second, first);
 509
 85510        if (Compare(second, zero) < 0 || Compare(first, one) > 0)
 3511            return false;
 82512        if (Compare(first, zero) > 0)
 41513            lower = first;
 82514        if (Compare(second, one) < 0)
 41515            upper = second;
 82516        return true;
 517    }
 518
 519    private static ConeData CreateApexData(
 520        FixedSegment query,
 521        Vector3d apex,
 522        Vector3d apexToBaseDirection,
 523        Fixed64 height,
 524        Fixed64 baseRadius)
 525    {
 142526        Signed192 heightRaw = Signed192.Signed(height.m_rawValue);
 142527        return CreateData(
 142528            query,
 142529            apex,
 142530            apexToBaseDirection,
 142531            heightRaw,
 142532            centered: false,
 142533            baseRadius);
 534    }
 535
 536    private static ConeData CreateCenteredData(
 537        FixedSegment query,
 538        Vector3d center,
 539        Vector3d baseToApexDirection,
 540        Fixed64 height,
 541        Fixed64 baseRadius)
 542    {
 20543        Signed192 heightRaw = Signed192.Signed(height.m_rawValue);
 20544        return CreateData(
 20545            query,
 20546            center,
 20547            baseToApexDirection,
 20548            heightRaw,
 20549            centered: true,
 20550            baseRadius);
 551    }
 552
 553    private static ConeData CreateData(
 554        FixedSegment query,
 555        Vector3d origin,
 556        Vector3d axisDirection,
 557        Signed192 heightRaw,
 558        bool centered,
 559        Fixed64 baseRadius)
 560    {
 162561        Signed192 startDistanceSquared = GetDot(query.Start, origin, query.Start, origin);
 162562        Signed192 startDirectionProjection = GetDot(query.Start, origin, query.End, query.Start);
 162563        Signed192 directionLengthSquared = GetDot(query.End, query.Start, query.End, query.Start);
 162564        Signed192 axisLengthSquared = GetDot(axisDirection, Vector3d.Zero, axisDirection, Vector3d.Zero);
 162565        bool exactUnitAxis = IsExactUnitAxis(axisLengthSquared);
 162566        Signed192 startAxisProjection = GetDot(query.Start, origin, axisDirection, Vector3d.Zero);
 162567        Signed192 directionAxisProjection = GetDot(query.End, query.Start, axisDirection, Vector3d.Zero);
 162568        Signed192 maximumAxisHeight = exactUnitAxis
 162569            ? GetScaledRaw(heightRaw)
 162570            : GetAxisHeightProduct(axisLengthSquared, heightRaw);
 571        Signed192 startAxial;
 572        Signed192 axialVelocity;
 573        Signed192 maximumAxial;
 574        Signed192 radialScale;
 162575        if (exactUnitAxis)
 576        {
 155577            startAxial = centered
 155578                ? WideArithmetic.SubtractSigned192(GetHalfScaledRaw(heightRaw), startAxisProjection)
 155579                : startAxisProjection;
 155580            axialVelocity = centered
 155581                ? WideArithmetic.SubtractSigned192(default, directionAxisProjection)
 155582                : directionAxisProjection;
 155583            maximumAxial = maximumAxisHeight;
 155584            radialScale = One;
 585        }
 586        else
 587        {
 7588            Signed192 scaledStartAxisProjection = GetScaledRaw(startAxisProjection);
 7589            Signed192 scaledDirectionAxisProjection = GetScaledRaw(directionAxisProjection);
 7590            startAxial = centered
 7591                ? WideArithmetic.SubtractSigned192(maximumAxisHeight, WideArithmetic.Double(scaledStartAxisProjection))
 7592                : scaledStartAxisProjection;
 7593            axialVelocity = centered
 7594                ? WideArithmetic.SubtractSigned192(default, WideArithmetic.Double(scaledDirectionAxisProjection))
 7595                : scaledDirectionAxisProjection;
 7596            maximumAxial = centered
 7597                ? WideArithmetic.Double(maximumAxisHeight)
 7598                : maximumAxisHeight;
 7599            radialScale = centered ? Four : One;
 600        }
 601
 162602        Signed320 radialCoefficient = GetRadialTerm(
 162603            directionLengthSquared,
 162604            directionAxisProjection,
 162605            axisLengthSquared);
 162606        Signed320 radialProjection = GetRadialTerm(
 162607            startDirectionProjection,
 162608            startAxisProjection,
 162609            directionAxisProjection,
 162610            axisLengthSquared);
 162611        Signed320 radialConstant = GetRadialTerm(
 162612            startDistanceSquared,
 162613            startAxisProjection,
 162614            axisLengthSquared);
 162615        Signed320 heightSquared = WideArithmetic.MultiplySigned192(heightRaw, heightRaw);
 162616        Signed192 radiusRaw = Signed192.Signed(baseRadius.m_rawValue);
 162617        Signed320 radiusSquared = WideArithmetic.MultiplySigned192(radiusRaw, radiusRaw);
 162618        Signed320 axialVelocitySquared = WideArithmetic.MultiplySigned192(axialVelocity, axialVelocity);
 162619        Signed320 axialProduct = WideArithmetic.MultiplySigned192(startAxial, axialVelocity);
 162620        Signed320 startAxialSquared = WideArithmetic.MultiplySigned192(startAxial, startAxial);
 621
 162622        return new ConeData(
 162623            startAxial,
 162624            axialVelocity,
 162625            maximumAxial,
 162626            SubtractConeTerms(
 162627                heightSquared, radialCoefficient, axisLengthSquared, radialScale,
 162628                exactUnitAxis,
 162629                radiusSquared, axialVelocitySquared),
 162630            SubtractConeTerms(
 162631                heightSquared, radialProjection, axisLengthSquared, radialScale,
 162632                exactUnitAxis,
 162633                radiusSquared, axialProduct),
 162634            SubtractConeTerms(
 162635                heightSquared, radialConstant, axisLengthSquared, radialScale,
 162636                exactUnitAxis,
 162637                radiusSquared, startAxialSquared));
 638    }
 639
 640    private static Signed320 GetRadialTerm(
 641        Signed192 squaredLength,
 642        Signed192 axisProjection,
 643        Signed192 axisLengthSquared) =>
 343644        WideArithmetic.SubtractSigned320(
 343645            WideArithmetic.MultiplySigned192(squaredLength, axisLengthSquared),
 343646            WideArithmetic.MultiplySigned192(axisProjection, axisProjection));
 647
 648    private static Signed320 GetRadialTerm(
 649        Signed192 dot,
 650        Signed192 startAxisProjection,
 651        Signed192 directionAxisProjection,
 652        Signed192 axisLengthSquared) =>
 162653        WideArithmetic.SubtractSigned320(
 162654            WideArithmetic.MultiplySigned192(dot, axisLengthSquared),
 162655            WideArithmetic.MultiplySigned192(startAxisProjection, directionAxisProjection));
 656
 657    private static Signed576 SubtractConeTerms(
 658        Signed320 heightSquared,
 659        Signed320 radialTerm,
 660        Signed192 axisLengthSquared,
 661        Signed192 radialScale,
 662        bool exactUnitAxis,
 663        Signed320 radiusSquared,
 664        Signed320 axialTerm)
 665    {
 505666        if (exactUnitAxis)
 667        {
 479668            return WideArithmetic.SubtractSigned576(
 479669                WideArithmetic.MultiplySigned320(heightSquared, radialTerm),
 479670                WideArithmetic.MultiplySigned320(radiusSquared, axialTerm));
 671        }
 672
 26673        Signed576 radial = WideArithmetic.MultiplySigned576(
 26674            WideArithmetic.MultiplySigned576(
 26675                WideArithmetic.MultiplySigned320(heightSquared, radialTerm),
 26676                axisLengthSquared),
 26677            radialScale);
 26678        Signed576 axial = WideArithmetic.MultiplySigned320(radiusSquared, axialTerm);
 26679        return WideArithmetic.SubtractSigned576(radial, axial);
 680    }
 681
 682    private static Signed832 Evaluate(ConeData data, Signed192 numerator, Signed192 denominator)
 683    {
 684        // Rigid-frame coefficients have fewer than 390 magnitude bits after
 685        // their common quaternion-denominator factor is removed. Clipped
 686        // rational bounds have at most 132-bit magnitudes, so every homogenized
 687        // term and their sum fit below 656 bits. Signed832 also retains the
 688        // wider legacy conic intermediates without the former eleven-word
 689        // truncation.
 7394690        Signed320 numeratorSquared = WideArithmetic.MultiplySigned192(numerator, numerator);
 7394691        Signed320 numeratorDenominator = WideArithmetic.MultiplySigned192(numerator, denominator);
 7394692        Signed320 denominatorSquared = WideArithmetic.MultiplySigned192(denominator, denominator);
 7394693        Signed832 first = WideArithmetic.MultiplySigned576ToSigned832(data.Coefficient, numeratorSquared);
 7394694        Signed832 second = WideArithmetic.MultiplySigned576ToSigned832(data.Projection, numeratorDenominator);
 7394695        Signed832 third = WideArithmetic.MultiplySigned576ToSigned832(data.Constant, denominatorSquared);
 7394696        return WideArithmetic.AddSigned832(
 7394697            WideArithmetic.AddSigned832(first, WideArithmetic.AddSigned832(second, second)),
 7394698            third);
 699    }
 700
 701    private static Signed832 EvaluateDerivative(ConeData data, RationalBound bound) =>
 3825702        WideArithmetic.AddSigned832(
 3825703            WideArithmetic.MultiplySigned576ToSigned832(
 3825704                data.Coefficient,
 3825705                Signed320.ExtendValue(bound.Numerator)),
 3825706            WideArithmetic.MultiplySigned576ToSigned832(
 3825707                data.Projection,
 3825708                Signed320.ExtendValue(bound.Denominator)));
 709
 710    private static bool IsContained(
 711        Signed192 axial,
 712        Signed576 polynomial,
 713        Signed192 maximumAxial,
 714        bool strict) =>
 181715        IsContained(axial, polynomial.Sign, maximumAxial, strict);
 716
 717    private static bool IsContained(
 718        Signed192 axial,
 719        int polynomialSign,
 720        Signed192 maximumAxial,
 721        bool strict)
 722    {
 181723        int maximumSign = WideArithmetic.SubtractSigned192(axial, maximumAxial).Sign;
 181724        return strict
 181725            ? axial.Sign > 0 && maximumSign < 0 && polynomialSign < 0
 181726            : axial.Sign >= 0 && maximumSign <= 0 && polynomialSign <= 0;
 727    }
 728
 729    private static Signed192 GetScaledRaw(Signed192 value) =>
 215730        new((value.High << FixedMath.SHIFT_AMOUNT_I) | (value.Middle >> FixedMath.SHIFT_AMOUNT_I),
 215731            (value.Middle << FixedMath.SHIFT_AMOUNT_I) | (value.Low >> FixedMath.SHIFT_AMOUNT_I),
 215732            value.Low << FixedMath.SHIFT_AMOUNT_I);
 733
 734    private static Signed192 GetAxisHeightProduct(
 735        Signed192 axisLengthSquared,
 736        Signed192 heightRaw)
 737    {
 12738        Signed320 product = WideArithmetic.MultiplySigned192(axisLengthSquared, heightRaw);
 739        // IsNormalized bounds the positive axis square near 2^64; multiplying
 740        // by a positive Fixed64 raw height therefore occupies fewer than 129 bits.
 12741        return new Signed192(product.Word2, product.Word1, product.Word0);
 742    }
 743
 744    private static Signed192 GetHalfScaledRaw(Signed192 value)
 745    {
 27746        Signed192 scaled = GetScaledRaw(value);
 27747        ulong high = scaled.High;
 27748        ulong middle = scaled.Middle;
 27749        ulong low = scaled.Low;
 27750        WideArithmetic.ShiftRightOne(ref high, ref middle, ref low);
 27751        return new Signed192(high, middle, low);
 752    }
 753
 754    private static bool IsExactUnitAxis(Signed192 axisLengthSquared) =>
 181755        axisLengthSquared.High == AxisScaleSquared.High
 181756        && axisLengthSquared.Middle == AxisScaleSquared.Middle
 181757        && axisLengthSquared.Low == AxisScaleSquared.Low;
 758
 759    private static Signed192 SquareRaw(long raw)
 760    {
 1150761        ulong magnitude = (ulong)raw;
 1150762        Fixed64.Multiply64To128(magnitude, magnitude, out ulong high, out ulong low);
 1150763        return new Signed192(0UL, high, low);
 764    }
 765
 766    private static RationalBound Normalize(Signed192 numerator, Signed192 denominator)
 767    {
 170768        if (denominator.Sign >= 0)
 106769            return new RationalBound(numerator, denominator);
 770
 64771        return new RationalBound(
 64772            WideArithmetic.SubtractSigned192(default, numerator),
 64773            WideArithmetic.SubtractSigned192(default, denominator));
 774    }
 775
 776    private static int Compare(RationalBound left, RationalBound right) =>
 418777        WideArithmetic.MultiplySubtract(
 418778            left.Numerator,
 418779            right.Denominator,
 418780            right.Numerator,
 418781            left.Denominator).Sign;
 782
 783    private static Fixed64 Round(RationalBound value, Fixed64 outputScale)
 784    {
 240785        Signed320 numerator = WideArithmetic.MultiplySigned192(
 240786            value.Numerator,
 240787            Signed192.Signed(outputScale.m_rawValue));
 240788        _ = Fixed64.TryGetSignedRawRatio(
 240789            Signed576.ExtendValue(numerator),
 240790            Signed576.ExtendValue(Signed320.ExtendValue(value.Denominator)),
 240791            out Fixed64 result);
 240792        return result;
 793    }
 794
 795    private static Signed192 GetDot(
 796        Vector3d leftEnd,
 797        Vector3d leftStart,
 798        Vector3d rightEnd,
 799        Vector3d rightStart) =>
 1029800        WideGeometry.GetDifferenceDotProduct3D(
 1029801            leftEnd.X, leftStart.X, leftEnd.Y, leftStart.Y, leftEnd.Z, leftStart.Z,
 1029802            rightEnd.X, rightStart.X, rightEnd.Y, rightStart.Y, rightEnd.Z, rightStart.Z);
 803
 804    internal static int EvaluateBoundedUnitPolynomialSign(
 805            Signed576 coefficient,
 806            Signed576 projection,
 807            Signed576 constant,
 808            Signed192 numerator,
 809            Signed192 denominator) =>
 64810            Evaluate(
 64811                new ConeData(
 64812                    default,
 64813                    default,
 64814                    default,
 64815                    coefficient,
 64816                    projection,
 64817                    constant),
 64818                numerator,
 64819                denominator).Sign;
 820
 821    internal static int EvaluateBoundedUnitPolynomialDerivativeSign(
 822        Signed576 coefficient,
 823        Signed576 projection,
 824        Signed192 numerator,
 825        Signed192 denominator) =>
 64826        EvaluateDerivative(
 64827            new ConeData(
 64828                default,
 64829                default,
 64830                default,
 64831                coefficient,
 64832                projection,
 64833                default),
 64834            new RationalBound(numerator, denominator)).Sign;
 835
 836    internal static bool TrySolveBoundedUnitPolynomial(
 837        Signed576 coefficient,
 838        Signed576 projection,
 839        Signed576 constant,
 840        Signed192 lowerNumerator,
 841        Signed192 lowerDenominator,
 842        Signed192 upperNumerator,
 843        Signed192 upperDenominator,
 844        Fixed64 outputScale,
 845        out Fixed64 entry,
 846        out Fixed64 exit) =>
 396847        TrySolveBoundedPolynomial(
 396848            new ConeData(
 396849                default,
 396850                default,
 396851                default,
 396852                coefficient,
 396853                projection,
 396854                constant),
 396855            new RationalBound(lowerNumerator, lowerDenominator),
 396856            new RationalBound(upperNumerator, upperDenominator),
 396857            outputScale,
 396858            out entry,
 396859            out exit);
 860}

Methods/Properties

.cctor()
.ctor(FixedMathSharp.Signed192,FixedMathSharp.Signed192)
.ctor(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576)
NegatedPolynomial()
TryGetApexInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TrySolveUnitPolynomial(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
GetPolynomialSignAtScaledParameter(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
GetPolynomialSignAtRationalParameter(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
TryGetApexDistanceInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetCenteredInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetCenteredDistanceInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
ContainsPointInApexCone(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean)
ContainsPointInCenteredCone(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean)
ContainsPoint(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,System.Boolean,FixedMathSharp.Fixed64,System.Boolean)
TrySolve(FixedMathSharp.Geometry.WideFiniteConeIntersection/ConeData,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TrySolveBoundedPolynomial(FixedMathSharp.Geometry.WideFiniteConeIntersection/ConeData,FixedMathSharp.Geometry.WideFiniteConeIntersection/RationalBound,FixedMathSharp.Geometry.WideFiniteConeIntersection/RationalBound,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
RoundLinearRoot(FixedMathSharp.Geometry.WideFiniteConeIntersection/ConeData,FixedMathSharp.Fixed64)
RoundLowerRoot(FixedMathSharp.Geometry.WideFiniteConeIntersection/ConeData,FixedMathSharp.Signed576,FixedMathSharp.Signed192)
RoundUpperRoot(FixedMathSharp.Geometry.WideFiniteConeIntersection/ConeData,FixedMathSharp.Signed576,FixedMathSharp.Signed192)
TryGetAxialInterval(FixedMathSharp.Geometry.WideFiniteConeIntersection/ConeData,FixedMathSharp.Geometry.WideFiniteConeIntersection/RationalBound&,FixedMathSharp.Geometry.WideFiniteConeIntersection/RationalBound&)
CreateApexData(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
CreateCenteredData(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
CreateData(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Signed192,System.Boolean,FixedMathSharp.Fixed64)
GetRadialTerm(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
GetRadialTerm(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
SubtractConeTerms(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed192,FixedMathSharp.Signed192,System.Boolean,FixedMathSharp.Signed320,FixedMathSharp.Signed320)
Evaluate(FixedMathSharp.Geometry.WideFiniteConeIntersection/ConeData,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
EvaluateDerivative(FixedMathSharp.Geometry.WideFiniteConeIntersection/ConeData,FixedMathSharp.Geometry.WideFiniteConeIntersection/RationalBound)
IsContained(FixedMathSharp.Signed192,FixedMathSharp.Signed576,FixedMathSharp.Signed192,System.Boolean)
IsContained(FixedMathSharp.Signed192,System.Int32,FixedMathSharp.Signed192,System.Boolean)
GetScaledRaw(FixedMathSharp.Signed192)
GetAxisHeightProduct(FixedMathSharp.Signed192,FixedMathSharp.Signed192)
GetHalfScaledRaw(FixedMathSharp.Signed192)
IsExactUnitAxis(FixedMathSharp.Signed192)
SquareRaw(System.Int64)
Normalize(FixedMathSharp.Signed192,FixedMathSharp.Signed192)
Compare(FixedMathSharp.Geometry.WideFiniteConeIntersection/RationalBound,FixedMathSharp.Geometry.WideFiniteConeIntersection/RationalBound)
Round(FixedMathSharp.Geometry.WideFiniteConeIntersection/RationalBound,FixedMathSharp.Fixed64)
GetDot(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
EvaluateBoundedUnitPolynomialSign(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
EvaluateBoundedUnitPolynomialDerivativeSign(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
TrySolveBoundedUnitPolynomial(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)