< Summary

Information
Class: FixedMathSharp.WideNormalization
Assembly: FixedMathSharp
File(s): /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Numerics/Wide/WideNormalization.cs
Line coverage
100%
Covered lines: 229
Uncovered lines: 0
Coverable lines: 229
Total lines: 364
Line coverage: 100%
Branch coverage
100%
Covered branches: 42
Total branches: 42
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
GetDirection(...)100%11100%
GetNormalized(...)100%11100%
GetNormalized(...)100%66100%
GetNormalized(...)100%44100%
GetNormalized(...)100%44100%
GetDirection(...)100%11100%
GetNormalized(...)100%11100%
GetNormalized(...)100%66100%
GetNormalized(...)100%66100%
GetNormalized(...)100%66100%
GetNormalized(...)100%44100%
GetNormalized(...)100%22100%
GetPositiveMagnitude(...)100%22100%
GetPositiveMagnitude(...)100%11100%
GetMagnitudeBitLength(...)100%11100%
Max(...)100%22100%

File(s)

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Numerics/Wide/WideNormalization.cs

#LineLine coverage
 1//=======================================================================
 2// WideNormalization.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 FixedMathSharp.Geometry;
 9
 10namespace FixedMathSharp;
 11
 12/// <summary>
 13/// Provides high-precision normalization and direction calculations
 14/// for geometric vectors using wide (extended-precision) arithmetic.
 15/// </summary>
 16internal static class WideNormalization
 17{
 18    /// <summary>
 19    /// Returns the normalized direction between two 2D endpoints without
 20    /// narrowing their component differences.
 21    /// </summary>
 22    internal static Vector2d GetDirection(Vector2d start, Vector2d end)
 23    {
 2924        Signed192 x = WideArithmetic.Difference(end.X, start.X);
 2925        Signed192 y = WideArithmetic.Difference(end.Y, start.Y);
 2926        return GetNormalized(x, y);
 27    }
 28
 29    /// <summary>
 30    /// Returns the nearest representable normalized direction for a nonzero 2D
 31    /// vector using its exact raw components.
 32    /// </summary>
 33    internal static Vector2d GetNormalized(Vector2d value) =>
 21734        GetNormalized(
 21735            Signed192.Signed(value.X.m_rawValue),
 21736            Signed192.Signed(value.Y.m_rawValue));
 37
 38    internal static Vector2d GetNormalized(Signed192 x, Signed192 y)
 39    {
 65040        Signed320 squaredMagnitude = WideGeometry.GetSquaredMagnitude(
 65041            x,
 65042            y,
 65043            default,
 65044            out Signed320 xSquare,
 65045            out Signed320 ySquare,
 65046            out _);
 65047        if (squaredMagnitude.IsZero)
 5048            return Vector2d.Zero;
 49
 60050        if (Max(GetMagnitudeBitLength(x), GetMagnitudeBitLength(y))
 60051            <= FixedMath.SHIFT_AMOUNT_I + 1)
 52        {
 21853            return Vector2d.GetScaleNormalized(new Vector2d(
 21854                Fixed64.FromRaw(unchecked((long)x.Low)),
 21855                Fixed64.FromRaw(unchecked((long)y.Low))));
 56        }
 57
 38258        Signed192 magnitude = WideArithmetic.GetFloorSquareRoot(
 38259            squaredMagnitude,
 38260            out Signed192 remainder);
 38261        Signed192 ceilingMagnitude = remainder.IsZero
 38262            ? magnitude
 38263            : WideArithmetic.AddSigned192(
 38264                magnitude,
 38265                Signed192.Signed(1L));
 38266        return new Vector2d(
 38267            Fixed64.NormalizeWideComponent(
 38268                x,
 38269                xSquare,
 38270                ceilingMagnitude,
 38271                squaredMagnitude),
 38272            Fixed64.NormalizeWideComponent(
 38273                y,
 38274                ySquare,
 38275                ceilingMagnitude,
 38276                squaredMagnitude));
 77    }
 78
 79    /// <summary>
 80    /// Returns the nearest representable normalized direction for exact 2D
 81    /// components wider than the public scalar domain.
 82    /// </summary>
 83    internal static Vector2d GetNormalized(Signed320 x, Signed320 y)
 84    {
 17985        Signed320 largest =
 17986            WideArithmetic.CompareMagnitude(x, y) >= 0 ? x : y;
 17987        if (largest.IsZero)
 2388            return Vector2d.Zero;
 89
 15690        Signed320 scale = GetPositiveMagnitude(largest);
 15691        return Vector2d.GetScaleNormalized(new Vector2d(
 15692            Fixed64.GetSignedRatio(x, scale),
 15693            Fixed64.GetSignedRatio(y, scale)));
 94    }
 95
 96    /// <summary>
 97    /// Returns the nearest representable normalized direction for exact 2D
 98    /// components in the nine-word finite-axis domain.
 99    /// </summary>
 100    internal static Vector2d GetNormalized(Signed576 x, Signed576 y)
 101    {
 772102        Signed576 xMagnitude = GetPositiveMagnitude(x);
 772103        Signed576 yMagnitude = GetPositiveMagnitude(y);
 772104        Signed576 scale =
 772105            WideArithmetic.CompareNonNegative(xMagnitude, yMagnitude) >= 0
 772106                ? xMagnitude
 772107                : yMagnitude;
 772108        if (scale.IsZero)
 12109            return Vector2d.Zero;
 110
 760111        Signed320 fixedScale = Signed320.ExtendValue(
 760112            Signed192.Signed(Fixed64.One.m_rawValue));
 760113        Signed704 denominator = Signed704.ExtendValue(scale);
 760114        _ = Fixed64.TryGetSignedRawRatio(
 760115            WideArithmetic.MultiplySigned576ToSigned704(x, fixedScale),
 760116            denominator,
 760117            out Fixed64 scaledX);
 760118        _ = Fixed64.TryGetSignedRawRatio(
 760119            WideArithmetic.MultiplySigned576ToSigned704(y, fixedScale),
 760120            denominator,
 760121            out Fixed64 scaledY);
 760122        return Vector2d.GetScaleNormalized(new Vector2d(scaledX, scaledY));
 123    }
 124
 125    /// <summary>
 126    /// Returns the normalized direction between two 3D endpoints without
 127    /// narrowing their component differences.
 128    /// </summary>
 129    internal static Vector3d GetDirection(Vector3d start, Vector3d end)
 130    {
 7131        Signed192 x = WideArithmetic.Difference(end.X, start.X);
 7132        Signed192 y = WideArithmetic.Difference(end.Y, start.Y);
 7133        Signed192 z = WideArithmetic.Difference(end.Z, start.Z);
 7134        return GetNormalized(x, y, z);
 135    }
 136
 137    /// <summary>
 138    /// Returns the nearest representable normalized direction for a nonzero 3D
 139    /// vector using its exact raw components.
 140    /// </summary>
 141    internal static Vector3d GetNormalized(Vector3d value) =>
 9194142        GetNormalized(
 9194143            Signed192.Signed(value.X.m_rawValue),
 9194144            Signed192.Signed(value.Y.m_rawValue),
 9194145            Signed192.Signed(value.Z.m_rawValue));
 146
 147    internal static Vector3d GetNormalized(
 148        Signed192 x,
 149        Signed192 y,
 150        Signed192 z)
 151    {
 9218152        Signed320 squaredMagnitude = WideGeometry.GetSquaredMagnitude(
 9218153            x,
 9218154            y,
 9218155            z,
 9218156            out Signed320 xSquare,
 9218157            out Signed320 ySquare,
 9218158            out Signed320 zSquare);
 9218159        if (squaredMagnitude.IsZero)
 3350160            return Vector3d.Zero;
 161
 5868162        if (Max(
 5868163                Max(
 5868164                    GetMagnitudeBitLength(x),
 5868165                    GetMagnitudeBitLength(y)),
 5868166                GetMagnitudeBitLength(z))
 5868167            <= FixedMath.SHIFT_AMOUNT_I + 1)
 168        {
 5847169            return Vector3d.GetScaleNormalized(new Vector3d(
 5847170                Fixed64.FromRaw(unchecked((long)x.Low)),
 5847171                Fixed64.FromRaw(unchecked((long)y.Low)),
 5847172                Fixed64.FromRaw(unchecked((long)z.Low))));
 173        }
 174
 21175        Signed192 magnitude = WideArithmetic.GetFloorSquareRoot(
 21176            squaredMagnitude,
 21177            out Signed192 remainder);
 21178        Signed192 ceilingMagnitude = remainder.IsZero
 21179            ? magnitude
 21180            : WideArithmetic.AddSigned192(
 21181                magnitude,
 21182                Signed192.Signed(1L));
 21183        return new Vector3d(
 21184            Fixed64.NormalizeWideComponent(
 21185                x,
 21186                xSquare,
 21187                ceilingMagnitude,
 21188                squaredMagnitude),
 21189            Fixed64.NormalizeWideComponent(
 21190                y,
 21191                ySquare,
 21192                ceilingMagnitude,
 21193                squaredMagnitude),
 21194            Fixed64.NormalizeWideComponent(
 21195                z,
 21196                zSquare,
 21197                ceilingMagnitude,
 21198                squaredMagnitude));
 199    }
 200
 201    /// <summary>
 202    /// Returns the nearest representable normalized direction for exact 3D
 203    /// components wider than the public scalar domain.
 204    /// </summary>
 205    internal static Vector3d GetNormalized(
 206        Signed320 x,
 207        Signed320 y,
 208        Signed320 z)
 209    {
 113210        Signed320 largest =
 113211            WideArithmetic.CompareMagnitude(x, y) >= 0 ? x : y;
 113212        if (WideArithmetic.CompareMagnitude(z, largest) > 0)
 6213            largest = z;
 113214        if (largest.IsZero)
 21215            return Vector3d.Zero;
 216
 92217        Signed320 scale = GetPositiveMagnitude(largest);
 92218        return Vector3d.GetScaleNormalized(new Vector3d(
 92219            Fixed64.GetSignedRatio(x, scale),
 92220            Fixed64.GetSignedRatio(y, scale),
 92221            Fixed64.GetSignedRatio(z, scale)));
 222    }
 223
 224    /// <summary>
 225    /// Returns the nearest representable normalized direction for exact 3D
 226    /// components in the nine-word finite-axis domain.
 227    /// </summary>
 228    internal static Vector3d GetNormalized(
 229        Signed576 x,
 230        Signed576 y,
 231        Signed576 z)
 232    {
 2496233        Signed576 xMagnitude = GetPositiveMagnitude(x);
 2496234        Signed576 yMagnitude = GetPositiveMagnitude(y);
 2496235        Signed576 zMagnitude = GetPositiveMagnitude(z);
 2496236        Signed576 scale =
 2496237            WideArithmetic.CompareNonNegative(xMagnitude, yMagnitude) >= 0
 2496238                ? xMagnitude
 2496239                : yMagnitude;
 2496240        if (WideArithmetic.CompareNonNegative(zMagnitude, scale) > 0)
 446241            scale = zMagnitude;
 2496242        if (scale.IsZero)
 6243            return Vector3d.Zero;
 244
 2490245        Signed320 fixedScale = Signed320.ExtendValue(
 2490246            Signed192.Signed(Fixed64.One.m_rawValue));
 2490247        Signed704 denominator = Signed704.ExtendValue(scale);
 2490248        _ = Fixed64.TryGetSignedRawRatio(
 2490249            WideArithmetic.MultiplySigned576ToSigned704(x, fixedScale),
 2490250            denominator,
 2490251            out Fixed64 scaledX);
 2490252        _ = Fixed64.TryGetSignedRawRatio(
 2490253            WideArithmetic.MultiplySigned576ToSigned704(y, fixedScale),
 2490254            denominator,
 2490255            out Fixed64 scaledY);
 2490256        _ = Fixed64.TryGetSignedRawRatio(
 2490257            WideArithmetic.MultiplySigned576ToSigned704(z, fixedScale),
 2490258            denominator,
 2490259            out Fixed64 scaledZ);
 2490260        return Vector3d.GetScaleNormalized(
 2490261            new Vector3d(scaledX, scaledY, scaledZ));
 262    }
 263
 264    /// <summary>
 265    /// Returns the nearest representable normalized direction for a nonzero 4D
 266    /// vector using its exact raw components.
 267    /// </summary>
 268    internal static Vector4d GetNormalized(Vector4d value)
 269    {
 15270        Signed192 x = Signed192.Signed(value.X.m_rawValue);
 15271        Signed192 y = Signed192.Signed(value.Y.m_rawValue);
 15272        Signed192 z = Signed192.Signed(value.Z.m_rawValue);
 15273        Signed192 w = Signed192.Signed(value.W.m_rawValue);
 15274        Signed320 squaredMagnitude = WideGeometry.GetSquaredMagnitude(
 15275            x,
 15276            y,
 15277            z,
 15278            out Signed320 xSquare,
 15279            out Signed320 ySquare,
 15280            out Signed320 zSquare);
 15281        Signed320 wSquare = WideArithmetic.MultiplySigned192(w, w);
 15282        squaredMagnitude =
 15283            WideArithmetic.AddSigned320(squaredMagnitude, wSquare);
 15284        if (squaredMagnitude.IsZero)
 2285            return Vector4d.Zero;
 286
 13287        Signed192 magnitude = WideArithmetic.GetFloorSquareRoot(
 13288            squaredMagnitude,
 13289            out Signed192 remainder);
 13290        Signed192 ceilingMagnitude = remainder.IsZero
 13291            ? magnitude
 13292            : WideArithmetic.AddSigned192(
 13293                magnitude,
 13294                Signed192.Signed(1L));
 13295        return new Vector4d(
 13296            Fixed64.NormalizeWideComponent(
 13297                x,
 13298                xSquare,
 13299                ceilingMagnitude,
 13300                squaredMagnitude),
 13301            Fixed64.NormalizeWideComponent(
 13302                y,
 13303                ySquare,
 13304                ceilingMagnitude,
 13305                squaredMagnitude),
 13306            Fixed64.NormalizeWideComponent(
 13307                z,
 13308                zSquare,
 13309                ceilingMagnitude,
 13310                squaredMagnitude),
 13311            Fixed64.NormalizeWideComponent(
 13312                w,
 13313                wSquare,
 13314                ceilingMagnitude,
 13315                squaredMagnitude));
 316    }
 317
 318    /// <summary>
 319    /// Returns the nearest representable unit quaternion for nonzero raw
 320    /// components. The zero quaternion retains its public identity fallback.
 321    /// </summary>
 322    internal static FixedQuaternion GetNormalized(FixedQuaternion value)
 323    {
 9324        Vector4d normalized = GetNormalized(
 9325            new Vector4d(value.X, value.Y, value.Z, value.W));
 9326        return normalized.IsZero
 9327            ? FixedQuaternion.Identity
 9328            : new FixedQuaternion(
 9329                normalized.X,
 9330                normalized.Y,
 9331                normalized.Z,
 9332                normalized.W);
 333    }
 334
 335    private static Signed576 GetPositiveMagnitude(Signed576 value) =>
 9032336        value.Sign < 0
 9032337            ? WideArithmetic.SubtractSigned576(default, value)
 9032338            : value;
 339
 340    private static Signed320 GetPositiveMagnitude(Signed320 value)
 341    {
 248342        WideArithmetic.GetMagnitude(
 248343            value,
 248344            out ulong word4,
 248345            out ulong word3,
 248346            out ulong word2,
 248347            out ulong word1,
 248348            out ulong word0);
 248349        return new Signed320(word4, word3, word2, word1, word0);
 350    }
 351
 352    private static int GetMagnitudeBitLength(Signed192 value)
 353    {
 18804354        WideArithmetic.GetMagnitude(
 18804355            value,
 18804356            out ulong high,
 18804357            out ulong middle,
 18804358            out ulong low);
 18804359        return WideArithmetic.GetBitLength(high, middle, low);
 360    }
 361
 362    private static int Max(int left, int right) =>
 12336363        left >= right ? left : right;
 364}