< Summary

Information
Class: ArturRios.Util.Math.PrimeUtils
Assembly: ArturRios.Util
File(s): D:\Repositories\dotnet-util\src\Math\PrimeUtils.cs
Line coverage
97%
Covered lines: 168
Uncovered lines: 5
Coverable lines: 173
Total lines: 330
Line coverage: 97.1%
Branch coverage
96%
Covered branches: 79
Total branches: 82
Branch coverage: 96.3%
Method coverage
100%
Covered methods: 11
Fully covered methods: 5
Total methods: 11
Method coverage: 100%
Full method coverage: 45.4%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
IsPrimeNumber(...)100%11100%
IsPrimeNumber(...)100%11100%
IsPrimeNumber(...)100%11100%
IsPrimeNumber(...)100%11100%
IsPrimeNumber(...)100%22100%
IsPrimeNumber(...)100%1010100%
IsPrimeNumber(...)100%1818100%
IsPrimeNumber(...)83.33%191887.5%
IsPrimeNumber(...)100%1010100%
BigIntegerSqrt(...)100%1010100%
CheckSmallPrimesAndDivisors(...)100%1414100%

File(s)

D:\Repositories\dotnet-util\src\Math\PrimeUtils.cs

#LineLine coverage
 1using System.Numerics;
 2
 3namespace ArturRios.Util.Math;
 4
 5/// <summary>
 6/// Static convenience wrapper that shares a single thread-safe generator.
 7/// </summary>
 8public static class PrimeUtils
 9{
 10    /// <summary>
 11    /// Determines whether the specified 8-bit signed integer is prime.
 12    /// </summary>
 13    /// <param name="value">The value to test for primality.</param>
 14    /// <returns>True if <paramref name="value"/> is prime; otherwise false.</returns>
 15    public static bool IsPrimeNumber(sbyte value)
 13216    {
 13217        return IsPrimeNumber((int)value);
 13218    }
 19
 20    /// <summary>
 21    /// Determines whether the specified 8-bit unsigned integer is prime.
 22    /// </summary>
 23    /// <param name="value">The value to test for primality.</param>
 24    /// <returns>True if <paramref name="value"/> is prime; otherwise false.</returns>
 25    public static bool IsPrimeNumber(byte value)
 3226    {
 3227        return IsPrimeNumber((int)value);
 3228    }
 29
 30    /// <summary>
 31    /// Determines whether the specified 16-bit signed integer is prime.
 32    /// </summary>
 33    /// <param name="value">The value to test for primality.</param>
 34    /// <returns>True if <paramref name="value"/> is prime; otherwise false.</returns>
 35    public static bool IsPrimeNumber(short value)
 536    {
 537        return IsPrimeNumber((int)value);
 538    }
 39
 40    /// <summary>
 41    /// Determines whether the specified 16-bit unsigned integer is prime.
 42    /// </summary>
 43    /// <param name="value">The value to test for primality.</param>
 44    /// <returns>True if <paramref name="value"/> is prime; otherwise false.</returns>
 45    public static bool IsPrimeNumber(ushort value)
 446    {
 447        return IsPrimeNumber((int)value);
 448    }
 49
 50    /// <summary>
 51    /// Determines whether the specified 32-bit unsigned integer is prime.
 52    /// </summary>
 53    /// <param name="value">The value to test for primality.</param>
 54    /// <returns>True if <paramref name="value"/> is prime; otherwise false.</returns>
 55    public static bool IsPrimeNumber(uint value)
 556    {
 557        return value <= int.MaxValue ? IsPrimeNumber((int)value) : IsPrimeNumber((ulong)value);
 558    }
 59
 60    /// <summary>
 61    /// Optimized primality check for 32-bit integers using trial division.
 62    /// </summary>
 63    /// <param name="value">The value to test for primality.</param>
 64    /// <returns>True if <paramref name="value"/> is prime; otherwise false.</returns>
 65    public static bool IsPrimeNumber(int value)
 23066    {
 23067        if (value < 2)
 1268        {
 1269            return false;
 70        }
 71
 21872        if (value == 2)
 973        {
 974            return true;
 75        }
 76
 20977        if (value % 2 == 0)
 9578        {
 9579            return false;
 80        }
 81
 11482        var limit = (int)System.Math.Sqrt(value);
 83
 4757684        for (var divisor = 3; divisor <= limit; divisor += 2)
 2372085        {
 2372086            if (value % divisor == 0)
 4687            {
 4688                return false;
 89            }
 2367490        }
 91
 6892        return true;
 23093    }
 94
 95    /// <summary>
 96    /// Optimized primality check for 64-bit integers using deterministic Miller-Rabin for 64-bit range.
 97    /// </summary>
 98    /// <param name="value">The value to test for primality.</param>
 99    /// <returns>True if <paramref name="value"/> is prime; otherwise false.</returns>
 100    public static bool IsPrimeNumber(long value)
 36101    {
 36102        var candidate = (ulong)value;
 36103        var smallPrimeResult = CheckSmallPrimesAndDivisors(candidate);
 104
 36105        if (smallPrimeResult.HasValue)
 24106        {
 24107            return smallPrimeResult.Value;
 108        }
 109
 12110        ulong[] witnesses = [2UL, 325UL, 9375UL, 28178UL, 450775UL, 9780504UL, 1795265022UL];
 111
 12112        var d = candidate - 1UL;
 12113        var s = 0;
 114
 29115        while ((d & 1UL) == 0UL)
 17116        {
 17117            d >>= 1;
 17118            s++;
 17119        }
 120
 12121        var candidateBigInteger = new BigInteger(candidate);
 122
 175123        foreach (var witnessValue in witnesses)
 71124        {
 71125            if (witnessValue % candidate == 0UL)
 2126            {
 2127                return true;
 128            }
 129
 69130            var witnessBigInteger = new BigInteger(witnessValue % candidate);
 69131            var exponentBigInteger = new BigInteger(d);
 69132            var x = BigInteger.ModPow(witnessBigInteger, exponentBigInteger, candidateBigInteger);
 133
 69134            if (x == BigInteger.One || x == candidateBigInteger - BigInteger.One)
 56135            {
 56136                continue;
 137            }
 138
 13139            var roundPassed = false;
 42140            for (var iteration = 1; iteration < s; iteration++)
 20141            {
 20142                x = x * x % candidateBigInteger;
 143
 20144                if (x == candidateBigInteger - BigInteger.One)
 12145                {
 12146                    roundPassed = true;
 147
 12148                    break;
 149                }
 8150            }
 151
 13152            if (!roundPassed)
 1153            {
 1154                return false;
 155            }
 12156        }
 157
 9158        return true;
 36159    }
 160
 161    /// <summary>
 162    /// Determines whether the specified 64-bit unsigned integer is prime.
 163    /// </summary>
 164    /// <param name="value">The value to test for primality.</param>
 165    /// <returns>True if <paramref name="value"/> is prime; otherwise false.</returns>
 166    public static bool IsPrimeNumber(ulong value)
 9167    {
 9168        var smallPrimeResult = CheckSmallPrimesAndDivisors(value);
 9169        if (smallPrimeResult.HasValue)
 6170        {
 6171            return smallPrimeResult.Value;
 172        }
 173
 3174        ulong[] witnesses = [2UL, 325UL, 9375UL, 28178UL, 450775UL, 9780504UL, 1795265022UL];
 175
 3176        var d = value - 1UL;
 3177        var s = 0;
 7178        while ((d & 1UL) == 0UL)
 4179        {
 4180            d >>= 1;
 4181            s++;
 4182        }
 183
 3184        var candidateBigInteger = new BigInteger(value);
 185
 51186        foreach (var witnessValue in witnesses)
 21187        {
 21188            if (witnessValue % value == 0UL)
 0189            {
 0190                return true;
 191            }
 192
 21193            var witnessBigInteger = new BigInteger(witnessValue % value);
 21194            var exponentBigInteger = new BigInteger(d);
 195
 21196            var x = BigInteger.ModPow(witnessBigInteger, exponentBigInteger, candidateBigInteger);
 197
 21198            if (x == BigInteger.One || x == candidateBigInteger - BigInteger.One)
 16199            {
 16200                continue;
 201            }
 202
 5203            var roundPassed = false;
 204
 10205            for (var iteration = 1; iteration < s; iteration++)
 5206            {
 5207                x = (x * x) % candidateBigInteger;
 208
 5209                if (x == candidateBigInteger - BigInteger.One)
 5210                {
 5211                    roundPassed = true;
 5212                    break;
 213                }
 0214            }
 215
 5216            if (!roundPassed)
 0217            {
 0218                return false;
 219            }
 5220        }
 221
 3222        return true;
 9223    }
 224
 225    /// <summary>
 226    /// Determines whether the specified BigInteger is a prime number
 227    /// </summary>
 228    /// <param name="value">The value to test for primality.</param>
 229    /// <returns>True if <paramref name="value"/> is prime; otherwise false.</returns>
 230    public static bool IsPrimeNumber(BigInteger value)
 35231    {
 232        // Numbers less than 2 are not prime
 35233        if (value < 2)
 3234        {
 3235            return false;
 236        }
 237
 32238        if (value == 2)
 2239        {
 2240            return true;
 241        }
 242
 30243        if (value % 2 == 0)
 14244        {
 14245            return false;
 246        }
 247
 16248        var limit = BigIntegerSqrt(value);
 249
 32666250        for (BigInteger divisor = 3; divisor <= limit; divisor += 2)
 16322251        {
 16322252            if (value % divisor == 0)
 5253            {
 5254                return false;
 255            }
 16317256        }
 257
 11258        return true;
 35259    }
 260
 261    /// <summary>
 262    /// Computes the integer square root (floor) of the specified non-negative <see cref="BigInteger"/>.
 263    /// </summary>
 264    /// <param name="n">The non-negative value whose integer square root is to be computed.</param>
 265    /// <returns>The greatest integer less than or equal to the square root of <paramref name="n"/>.</returns>
 266    public static BigInteger BigIntegerSqrt(BigInteger n)
 29267    {
 29268        if (n < 0)
 1269        {
 1270            throw new ArithmeticException("Cannot compute square root of a negative number.");
 271        }
 272
 28273        if (n == 0)
 1274        {
 1275            return 0;
 276        }
 277
 27278        BigInteger low = 1;
 279
 27280        var high = n;
 281
 216282        while (low <= high)
 197283        {
 197284            var mid = (low + high) >> 1; // divide by 2
 197285            var square = mid * mid;
 197286            var compareResult = square.CompareTo(n);
 287
 197288            if (compareResult == 0)
 8289            {
 8290                return mid;
 291            }
 292
 189293            if (compareResult < 0)
 59294            {
 59295                low = mid + 1;
 59296            }
 297            else
 130298            {
 130299                high = mid - 1;
 130300            }
 189301        }
 302
 19303        return high;
 28304    }
 305
 306    /// <summary>
 307    /// Checks if a number is a small prime (2, 3, 5) or divisible by small primes.
 308    /// </summary>
 309    /// <param name="value">The value to test.</param>
 310    /// <returns>True if prime (2, 3, or 5), false if composite (divisible by 2, 3, or 5, or less than 2), null to conti
 311    private static bool? CheckSmallPrimesAndDivisors(ulong value)
 45312    {
 45313        if (value < 2UL)
 3314        {
 3315            return false;
 316        }
 317
 42318        if (value is 2UL or 3UL or 5UL)
 5319        {
 5320            return true;
 321        }
 322
 37323        if ((value & 1UL) == 0UL || value % 3UL == 0UL || value % 5UL == 0UL)
 22324        {
 22325            return false;
 326        }
 327
 15328        return null;
 45329    }
 330}