{"id":217,"date":"2020-09-10T06:56:51","date_gmt":"2020-09-10T06:56:51","guid":{"rendered":"https:\/\/michaeljohnsteiner.com\/?p=217"},"modified":"2020-09-10T06:56:51","modified_gmt":"2020-09-10T06:56:51","slug":"bigintegerprime-cs","status":"publish","type":"post","link":"https:\/\/michaeljohnsteiner.com\/index.php\/2020\/09\/10\/bigintegerprime-cs\/","title":{"rendered":"BigIntegerPrime.cs"},"content":{"rendered":"\n<p>Generate or Test BigInteger Primes<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">using System;\nusing System.Numerics;\nusing System.Threading;\nusing System.Threading.Tasks;\npublic class BigIntegerPrime\n{\n    private readonly int _bitWidth;\n    private readonly int[] _lowPrimes =\n    {\n        2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,\n        157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313,\n        317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491,\n        499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677,\n        683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881,\n        883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997\n    };\n    private readonly BigIntegerRng _rng;\n    private readonly BigInteger    _twosixtyfour = \"18446744073709551616\".BigIntegerBase10();\n    private readonly uint[]        _w0           = {2};\n    private readonly uint[]        _w1           = {2, 3};\n    private readonly uint[]        _w10          = {2, 3, 5, 7, 11, 13, 17, 19, 23};\n    private readonly uint[]        _w11          = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};\n    private readonly uint[]        _w12          = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41};\n    private readonly uint[]        _w2           = {31, 73};\n    private readonly uint[]        _w3           = {2, 3, 5};\n    private readonly uint[]        _w4           = {2, 3, 5, 7};\n    private readonly uint[]        _w5           = {2, 7, 61};\n    private readonly uint[]        _w6           = {2, 13, 23, 1662803};\n    private readonly uint[]        _w7           = {2, 3, 5, 7, 11};\n    private readonly uint[]        _w8           = {2, 3, 5, 7, 11, 13};\n    private readonly uint[]        _w9           = {2, 3, 5, 7, 11, 13, 17};\n    private          BigInteger    _nextPrime;\n    public BigIntegerPrime(int BitWidthHint)\n    {\n        _rng          = new BigIntegerRng(BitWidthHint);\n        _rng.Unsigned = true;\n        _rng.OddsOnly = true;\n        _bitWidth     = BitWidthHint;\n    }\n    public bool IsPrime(BigInteger candidate)\n    {\n        if (candidate == 1)\n            return false;\n        if (candidate == 2 || candidate == 3 || candidate == 5)\n            return true;\n        if (candidate &lt;= 1000)\n            return CheckLowPrimes(candidate);\n        if (!PrimeCheckM10LD(candidate))\n            return false;\n        if (!PrimeCheckM6(candidate))\n            return false;\n        if (!TrialDivision(candidate))\n            return false;\n        if (candidate &lt; 2047)\n        {\n            if (!MillerRabin(candidate, _w0))\n                return false;\n        }\n        else if (candidate > 2047 &amp;&amp; candidate &lt;= 1373653)\n        {\n            if (!MillerRabin(candidate, _w1))\n                return false;\n        }\n        else if (candidate > 1373653 &amp;&amp; candidate &lt;= 9080191)\n        {\n            if (!MillerRabin(candidate, _w2))\n                return false;\n        }\n        else if (candidate > 9080191 &amp;&amp; candidate &lt;= 25326001)\n        {\n            if (!MillerRabin(candidate, _w3))\n                return false;\n        }\n        else if (candidate > 25326001 &amp;&amp; candidate &lt;= 3215031751)\n        {\n            if (!MillerRabin(candidate, _w4))\n                return false;\n        }\n        else if (candidate > 3215031751 &amp;&amp; candidate &lt;= 4759123141)\n        {\n            if (!MillerRabin(candidate, _w5))\n                return false;\n        }\n        else if (candidate > 4759123141 &amp;&amp; candidate &lt;= 1122004669633)\n        {\n            if (!MillerRabin(candidate, _w6))\n                return false;\n        }\n        else if (candidate > 1122004669633 &amp;&amp; candidate &lt;= 2152302898747)\n        {\n            if (!MillerRabin(candidate, _w7))\n                return false;\n        }\n        else if (candidate > 2152302898747 &amp;&amp; candidate &lt;= 3474749660383)\n        {\n            if (!MillerRabin(candidate, _w8))\n                return false;\n        }\n        else if (candidate > 3474749660383 &amp;&amp; candidate &lt;= 341550071728321)\n        {\n            if (!MillerRabin(candidate, _w9))\n                return false;\n        }\n        else if (candidate > 341550071728321 &amp;&amp; candidate &lt;= 3825123056546413051)\n        {\n            if (!MillerRabin(candidate, _w10))\n                return false;\n        }\n        else if (candidate > 3825123056546413051 &amp;&amp; candidate &lt; _twosixtyfour)\n        {\n            if (!MillerRabin(candidate, _w11))\n                return false;\n        }\n        else if (candidate > _twosixtyfour)\n        {\n            if (!MillerRabin(candidate, _w12))\n                return false;\n        }\n        return true;\n    }\n    private bool MillerRabin(BigInteger candidate, uint[] w)\n    {\n        var s = 0;\n        var d = candidate - BigInteger.One;\n        while ((d &amp; 1) == 0)\n        {\n            d >>= 1;\n            s++;\n        }\n        if (s == 0)\n            return false;\n        var nmo = candidate - BigInteger.One;\n        for (var i = 0; i &lt; w.Length; ++i)\n        {\n            BigInteger a;\n            if (candidate > _twosixtyfour)\n                a = _rng.Next(3, nmo);\n            else\n                a = w[i];\n            var x = BigInteger.ModPow(a, d, candidate);\n            if (x == 1 || x == nmo)\n                continue;\n            for (var r = 1; r &lt; s; ++r)\n            {\n                x = BigInteger.ModPow(x, 2, candidate);\n                if (x == 1)\n                    return false;\n                if (x == nmo)\n                    break;\n            }\n            if (x == nmo)\n                continue;\n            return false;\n        }\n        return true;\n    }\n    private bool TrialDivision(BigInteger candidate)\n    {\n        for (var i = 0; i &lt; _lowPrimes.Length; i++)\n        {\n            var p = _lowPrimes[i];\n            if (i &lt; p)\n            {\n                if (candidate % p != 0)\n                    continue;\n                return false;\n            }\n            break;\n        }\n        return true;\n    }\n    private static bool PrimeCheckM10LD(BigInteger n)\n    {\n        var d1 = (int) (n % 10);\n        return d1 == 1 || d1 == 3 || d1 == 7 || d1 == 9;\n    }\n    private static bool PrimeCheckM6(BigInteger n)\n    {\n        var d1 = (int) (n % 6);\n        return d1 == 1 || d1 == 5;\n    }\n    private bool CheckLowPrimes(BigInteger val)\n    {\n        foreach (var v in _lowPrimes)\n            if (val == v)\n                return true;\n        return false;\n    }\n    private void NextPrime(int t)\n    {\n        if (t > Environment.ProcessorCount - 1)\n            return;\n        var MaxValue = (BigInteger.One &lt;&lt; _bitWidth) - 1;\n        while (true)\n        {\n            if (_nextPrime != 0)\n                return;\n            var n = _rng.NextFast(_bitWidth);\n            if (_nextPrime != 0)\n                return;\n            if (n == 1)\n                continue;\n            if (n > MaxValue)\n                continue;\n            if (!IsPrime(n))\n                continue;\n            _nextPrime = n;\n        }\n    }\n    public BigInteger GetPrime()\n    {\n        void invoke()\n        {\n            Parallel.Invoke(new ParallelOptions {MaxDegreeOfParallelism = Environment.ProcessorCount},\n                () => NextPrime(1),\n                () => NextPrime(2),\n                () => NextPrime(3),\n                () => NextPrime(4),\n                () => NextPrime(5),\n                () => NextPrime(6),\n                () => NextPrime(7),\n                () => NextPrime(8),\n                () => NextPrime(9),\n                () => NextPrime(10),\n                () => NextPrime(11),\n                () => NextPrime(12),\n                () => NextPrime(13),\n                () => NextPrime(14),\n                () => NextPrime(15),\n                () => NextPrime(16)\n            );\n        }\n        _nextPrime = 0;\n        var thread = new Thread(invoke) {Priority = ThreadPriority.Highest};\n        thread.Start();\n        thread.Join();\n        return _nextPrime;\n    }\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Generate or Test BigInteger Primes<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[2],"tags":[14,115,114],"_links":{"self":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/217"}],"collection":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/comments?post=217"}],"version-history":[{"count":1,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/217\/revisions"}],"predecessor-version":[{"id":218,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/217\/revisions\/218"}],"wp:attachment":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/media?parent=217"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/categories?post=217"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/tags?post=217"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}