diff options
Diffstat (limited to 'src/js/entropy.js')
-rw-r--r-- | src/js/entropy.js | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/src/js/entropy.js b/src/js/entropy.js index c28620a..5900346 100644 --- a/src/js/entropy.js +++ b/src/js/entropy.js | |||
@@ -117,6 +117,40 @@ window.Entropy = new (function() { | |||
117 | while (entropyBin.length < expectedBits) { | 117 | while (entropyBin.length < expectedBits) { |
118 | entropyBin = "0" + entropyBin; | 118 | entropyBin = "0" + entropyBin; |
119 | } | 119 | } |
120 | // Assume cards are NOT replaced. | ||
121 | // Additional entropy decreases as more cards are used. This means | ||
122 | // entropy is measured using n!, not base^n. | ||
123 | // eg the second last card can be only one of two, not one of fifty two | ||
124 | // so the added entropy for that card is only one bit at most | ||
125 | if (base.asInt == 52) { | ||
126 | // Get the maximum value without replacement | ||
127 | var totalDecks = Math.ceil(base.parts.length / 52); | ||
128 | var totalCards = totalDecks * 52; | ||
129 | var totalCombos = factorial(52).pow(totalDecks); | ||
130 | var totalRemainingCards = totalCards - base.parts.length; | ||
131 | var remainingDecks = Math.floor(totalRemainingCards / 52); | ||
132 | var remainingCards = totalRemainingCards % 52; | ||
133 | var remainingCombos = factorial(52).pow(remainingDecks).multiply(factorial(remainingCards)); | ||
134 | var currentCombos = totalCombos.divide(remainingCombos); | ||
135 | var numberOfBits = Math.log2(currentCombos); | ||
136 | var maxWithoutReplace = BigInteger.pow(2, numberOfBits); | ||
137 | // aggresive flooring of numberOfBits by BigInteger.pow means a | ||
138 | // more accurate result can be had for small numbers using the | ||
139 | // built-in Math.pow function. | ||
140 | if (numberOfBits < 32) { | ||
141 | maxWithoutReplace = BigInteger(Math.round(Math.pow(2, numberOfBits))); | ||
142 | } | ||
143 | // Get the maximum value with replacement | ||
144 | var maxWithReplace = BigInteger.pow(52, base.parts.length); | ||
145 | // Calculate the new value by scaling the original value down | ||
146 | var withoutReplace = entropyInt.multiply(maxWithoutReplace).divide(maxWithReplace); | ||
147 | // Left pad with zeros based on number of bits | ||
148 | var entropyBin = withoutReplace.toString(2); | ||
149 | var numberOfBitsInt = Math.floor(numberOfBits); | ||
150 | while (entropyBin.length < numberOfBitsInt) { | ||
151 | entropyBin = "0" + entropyBin; | ||
152 | } | ||
153 | } | ||
120 | // Supply a 'filtered' entropy string for display purposes | 154 | // Supply a 'filtered' entropy string for display purposes |
121 | var entropyClean = base.parts.join(""); | 155 | var entropyClean = base.parts.join(""); |
122 | var entropyHtml = base.parts.join(""); | 156 | var entropyHtml = base.parts.join(""); |
@@ -221,4 +255,16 @@ window.Entropy = new (function() { | |||
221 | return BigInteger.log(x) / BigInteger.log(2); | 255 | return BigInteger.log(x) / BigInteger.log(2); |
222 | }; | 256 | }; |
223 | 257 | ||
258 | // Depends on BigInteger | ||
259 | function factorial(n) { | ||
260 | if (n == 0) { | ||
261 | return 1; | ||
262 | } | ||
263 | f = BigInteger.ONE; | ||
264 | for (var i=1; i<=n; i++) { | ||
265 | f = f.multiply(new BigInteger(i)); | ||
266 | } | ||
267 | return f; | ||
268 | } | ||
269 | |||
224 | })(); | 270 | })(); |