| var bn = require('bn.js'); | 
| var brorand = require('brorand'); | 
|   | 
| function MillerRabin(rand) { | 
|   this.rand = rand || new brorand.Rand(); | 
| } | 
| module.exports = MillerRabin; | 
|   | 
| MillerRabin.create = function create(rand) { | 
|   return new MillerRabin(rand); | 
| }; | 
|   | 
| MillerRabin.prototype._randbelow = function _randbelow(n) { | 
|   var len = n.bitLength(); | 
|   var min_bytes = Math.ceil(len / 8); | 
|   | 
|   // Generage random bytes until a number less than n is found. | 
|   // This ensures that 0..n-1 have an equal probability of being selected. | 
|   do | 
|     var a = new bn(this.rand.generate(min_bytes)); | 
|   while (a.cmp(n) >= 0); | 
|   | 
|   return a; | 
| }; | 
|   | 
| MillerRabin.prototype._randrange = function _randrange(start, stop) { | 
|   // Generate a random number greater than or equal to start and less than stop. | 
|   var size = stop.sub(start); | 
|   return start.add(this._randbelow(size)); | 
| }; | 
|   | 
| MillerRabin.prototype.test = function test(n, k, cb) { | 
|   var len = n.bitLength(); | 
|   var red = bn.mont(n); | 
|   var rone = new bn(1).toRed(red); | 
|   | 
|   if (!k) | 
|     k = Math.max(1, (len / 48) | 0); | 
|   | 
|   // Find d and s, (n - 1) = (2 ^ s) * d; | 
|   var n1 = n.subn(1); | 
|   for (var s = 0; !n1.testn(s); s++) {} | 
|   var d = n.shrn(s); | 
|   | 
|   var rn1 = n1.toRed(red); | 
|   | 
|   var prime = true; | 
|   for (; k > 0; k--) { | 
|     var a = this._randrange(new bn(2), n1); | 
|     if (cb) | 
|       cb(a); | 
|   | 
|     var x = a.toRed(red).redPow(d); | 
|     if (x.cmp(rone) === 0 || x.cmp(rn1) === 0) | 
|       continue; | 
|   | 
|     for (var i = 1; i < s; i++) { | 
|       x = x.redSqr(); | 
|   | 
|       if (x.cmp(rone) === 0) | 
|         return false; | 
|       if (x.cmp(rn1) === 0) | 
|         break; | 
|     } | 
|   | 
|     if (i === s) | 
|       return false; | 
|   } | 
|   | 
|   return prime; | 
| }; | 
|   | 
| MillerRabin.prototype.getDivisor = function getDivisor(n, k) { | 
|   var len = n.bitLength(); | 
|   var red = bn.mont(n); | 
|   var rone = new bn(1).toRed(red); | 
|   | 
|   if (!k) | 
|     k = Math.max(1, (len / 48) | 0); | 
|   | 
|   // Find d and s, (n - 1) = (2 ^ s) * d; | 
|   var n1 = n.subn(1); | 
|   for (var s = 0; !n1.testn(s); s++) {} | 
|   var d = n.shrn(s); | 
|   | 
|   var rn1 = n1.toRed(red); | 
|   | 
|   for (; k > 0; k--) { | 
|     var a = this._randrange(new bn(2), n1); | 
|   | 
|     var g = n.gcd(a); | 
|     if (g.cmpn(1) !== 0) | 
|       return g; | 
|   | 
|     var x = a.toRed(red).redPow(d); | 
|     if (x.cmp(rone) === 0 || x.cmp(rn1) === 0) | 
|       continue; | 
|   | 
|     for (var i = 1; i < s; i++) { | 
|       x = x.redSqr(); | 
|   | 
|       if (x.cmp(rone) === 0) | 
|         return x.fromRed().subn(1).gcd(n); | 
|       if (x.cmp(rn1) === 0) | 
|         break; | 
|     } | 
|   | 
|     if (i === s) { | 
|       x = x.redSqr(); | 
|       return x.fromRed().subn(1).gcd(n); | 
|     } | 
|   } | 
|   | 
|   return false; | 
| }; |